iOS开发之"省市"二级联动的数据组织(PHP版)以及PickerView的实现与封装
之所以要发表这篇博客,还源于最近的开发工作所实现的一个小的Demo, 当然这个Demo不会涉及工作中App的一些内容,下方要实现的Demo是通用的。因为项目需求的迭代,要求在银行卡绑定中添加支行所在的省市信息。在iOS中选择这种省市信息的一个比较不错的方式当时是使用UIPickerView进行显示了。当然在PickerView上的省市信息是联动显示的,我们在此因为需求定的是让用户选择省市信息,所以我们进行二级联动,当然多级联动的原理也是一样的。由于之前的老项目是使用Objective-C写的,虽然现在是Swift与OC混编,不过要在OC实现VC上添加新的功能还得用OC来实现呢,所以今天的博客的Demo咱就不用Swift来实现了,不过原理上是一样的。
下方的的截图就是我们今天博客中要介绍的Demo的运行效果,我们今天的博客就是生成PickerView所需的数据,以及对下方这个PickerView进行封装。从下方的动画中我们不难看出,在第一列选择省后,第二列会自动的显示该省下的所有地级市。点击完成后,会在上方相应的Label中显示出你所有选择的省市以及该省市所对应的编号。具体的请看下方这个粗劣的动画。
一、数据源的生成(从Excel到Plist)
1.组织数据的前奏
在封装上述PickerView控件之前,我们得有数据不是,也就是我们得有省市的名称,各个省市所对应的编码,以及省与市的对应关系。当然这些数据在网上一抓一大把,权威的数据要看"国家统计局"所提供的数据了。下方这两个截图是一个Excel表格中的两个Sheet,是我们服务端的一个程序媛给的,算是客户端与服务端的一个标准吧,估计也是从网上下载的。下方的省市信息以及编码当然与国家统计局提供的一致了,这个毋庸置疑。
我拿到这个Excel表格怎么用呢?我就想通过OC或者Swift来直接解析excel表格来读取数据,然后处理成我想要的格式。不过经过一番了解后,感觉该解决方案颇为复杂,于是乎就另寻他路。又于是乎,想起了之前用过的PHPExcel这个框架,因为之前做PHP开发的时候使用过PHPExcel来读取Excel文件。这个PHPExcel使用起来还是蛮顺手的,用起来也不复杂,于是乎我就决定使用PHPExcel来读取下方这两个Sheet中的数据。
使用PHPExcel读取数据后,重新将数据进行关联组织并生成json提供给iOS这边使用。iOS这边获取到Json后,将其进行解析后存储到plist文件中,这样我们就可以从plist文件中来获取“省市”相关数据了,然后我们就可以封装我们的PickerView了。今天博客就一步一步的来完成这个东西。当然你也可以使用SQLite数据库来存储下方Excel中的数据,create两张表,一张放省,一张放市,使用外键进行一对多的关联即可。使用SQLite数据库是另一种解决方案,在此我们使用的是plist文件,因为相对简单吗,因为数据少,plist文件度过了就可以在我们的pickerView上使用了,如果你想使用SQLite也是相当OK的,此篇博客值提供plist文件这种解决方案。
2.使用PHPExecl读取省市Excel数据
在上面的Excel数据中第一个Sheet中存储的是每个省以及每个省所对应的编码,而第二个Sheet中是存储的每个市和市的编码,并给出了每个市所在的省。接下来我们要使用PHPExcel这个第三方框架对上述Excel的数据进行读取,关于PHPExcel的东西请看其官方文档,地址为:https://phpexcel.codeplex.com/。下方代码就是我们使用PHPExcel读取上述Excel文件的代码了,并且将上述数据进行处理,将处理后的数据进行json编码。下方我们将介绍相关的PHP代码。
(1)加载PHPExcel框架以及省市excel文件--province.xls
下方的PHP代码片段就是加载PHPExcel框架,以及通过PHPExcel_IOFactory来创建文件读取器对象$objReader, 并公告$objReader对象来加载我们的province.xls文件。打开后会返回一个操作Excel文件的一个文件句柄对象$objPHPExcel,我们可以通过$objPHPExcel来操作已经打开的Excel文件。具体代码如下所示。
(2)通过上述$objPHPExcel对象来读取Excel文件内容
接下来我们要通过$objPHPExcel这个操作文件的对象来获取province.xml中的数据。下方对主要的代码添加的注释,应该还算是清晰。在下方代码片段中$dataArray数组我们用来存储province.xml中所有Sheet的数据。我们循环了两次来打开该Excel中的两个Sheet,通过$objPHPExcel对象的setActiveSheetIndex()方法通过索引来选择相应Sheet(从左到右,从0到n),并通过该对象的getActiveSheet()方法来获取当前选择的Sheet,选择后返回一个$objWorksheet对象,我们可以通过$objWorksheet对象来读取当前Sheet中每行每列的数据。
我们通过foreach来迭代当前Sheet中的每行数据,同样适用foreach来迭代一行中每列的数据。我们将每列的数据存入$tempRowArray数组中,然后在将每行的数据即$tempRowArray存入到Sheet数据的$tempSheetArray中。最后将当前的Sheet的数据$tempSheetArray存入到$dataArray中。具体实现如下:
3.数据的验证
通过上述步骤,我们就可以将Excel中的每个Sheet中的数据存入到我们的数组中。其中的数据结果是这样的: $dataArray中存储的是每个Sheet($tempSheetArray)的数据,Sheet($tempSheetArray)中又有多行($tempRowArray),每行($tempRowArray)中又有多列。所以dataArray就对应着整个Excel表格。我们也就获取了所有的Excel数据。经过上述代码,$dataArray中就存储了Excel的数据。为了保险起见我们将$dataArray中的数据进行打印,下方是我们的测试代码。
还有在我们写程序时呢,为了减少bug量,以及减少调试bug的难度,我们一定要养成一边写代码一遍调试的好习惯。这样会及时发现bug并修正,写好一个小的功能模块我们就对其进行测试,如果出了问题就很容易定位bug的所在之处。下方代码就是对上述代码的测试:
上述代码对$dataArray中存储的数据进行了一个打印,可以帮助我们查看我们$dataArray中所存储的数据是否符合我们的预期。下方的输出结果就是我们上述的测试用例所输出的结果,上面红框中是第一个Sheet中的数据,下方的是第二个Sheet中的数据,我们大体上一看符合我们的预期,就说明我们之前的代码没有什么问题,我们就可以对$data中的数据进行关联并生成JSON数据了。
4.省市数据进行关联
上面我们已经将数据从Excel中读取出来了,并且将量Sheet中的数据存入了不同的数组,接下来我们将要对数据进行处理。该部分就是将省市的数据进行关联,也就是将两个Sheet中的数据合并成一个数据块。下方就是我们要存储数据的一个结构图。整个是一个数组,数组中是一个字典,每个字典就代表一个省。每个省的字典又省编码Code、省名Name、所有市Citys组成。Citys中存储的又是一个数组。该数组中的每一项又是一个字典,此处的每个字典代表着一个市,每个市的字典中有包括市名Name和市编码Code。数据结构如下所示。
参考上图,我们要对读取的数据进行处理,将数据重新组织成上述结构。下方代码段就是对读取的Excel表格中的数据进行重组。经过下方代码的处理我们就可以得到上述结构的数据了。下面的$allDataArray就存储的是所有的数据信息,$provinceTempData中暂存着每次省的所有信息,$currentProvinceCitys中存储的就是当前省中所有市的信息。第二个循环中的if语句则负责管理省市间的关系了,具体代码以及代码注释如下所示。
经过上面的代码我们所有的数据就会存入到$allDataArray中,上面对$allDataArray进行了Json编码并输出,下方就是处理后输出的Josn数据。在此我们以河北省为例。下图中的结构是与上面我们数据结构图一一对应的,这正是我们想要的数据。到此我们数据处理的任务就完成一大半了,因为我们得到了我们想要的JSON。
5. 将上述JSON数据进行解析并存入Plist文件
经过上述步骤,PHP的工作算是告一段落。接下来我们就是要使用iOS客户端来访问上述地址,获取上述生成的JSON数据。获取到JSON数据后,我们将JSON数据进行解析,并存储到沙盒中的plist文件。这样我们就可以从plist文件中来加载我们的省市数据了。
下方代码段是我们的iOS客户端的代码,该代码通过NSURLSessionDataTask来请求上述PHP代码所在的文件获取省市的JSON数据。请求到JSON数据后对数据进行解析,将JSON数据解析成数组后在通过NSFileManager存储到沙盒中的PList文件中。如果你要在外部使用,只需要找到模拟器中的沙盒路径拷贝出plist文件即可。下方代码就是网络请求+JSON解析+Plist文件存储的的代码。
经过上述代码的执行,你会在你的模拟器中上述App的沙盒中发现一个叫province.plist的文件,该文件中存储的就是我们要使用的省市数据。该plist文件的数据存储结构是我们上面的介绍过的数据结构,下方就是该plist文件中数据的部分截图。至此我们就获得了一个按我们的预期存有省市数据plist文件了。
二、封装选择省市的PickerView的使用方式
封装当然不是简单的将PickerView的简单使用,在封装代码时我们要考虑到用户的易用性和可扩展性。在此我只对PickerView做了一个简单的封装,不过干货还是有的,主要是思想呢。经过上面一大模块的数据组织呢,我们就可以将之前服务端所给的Excel文档中的数据组织成我们想要的plist数据。本部分所做的主题就是读取plist文件中的数据,将该数据显示在二级联动的PickerView上供用户选择。用户选择完成后返回用户选择的省市名以及省市所对应的编码。开始我们控件的封装。
1.所封装控件的目录结构
首先我们先整体的看一下我们所封装控件的目录结构是怎样的,先整体的了解一下我们这个封装的控件。下方截图中就是我们所封装控件的目录结构了,因为我们是对显示省市信息的UIPikcerView进行的封装,所以在此我们称其为ProvincePickerView,ProvincePickerView就是我们所封装的组件了。用户只需要对其进行实例化并添加到其视图上就可以进行使用了。下方的province.plist数据就是我们上面所生成的存有省市信息是数据,我们ProvincePickerView中的数据源就是province.plist文件。
ProvinceModel就存储着当前选中的省市的名称以及编码,下面第二张截图就是ProvinceModel中的内容了。provinceCode存储的是当前选中的省的编码,provinceName存储的就是当前所选省的名称,cityCode存储的是所选市的编码,cityName存储的是所选市的名称。具体代码如下所示。
2. 所封装控件的初始化以及调用方式
接下来我们看一下我们封装的这个ProvincePickerView的使用方式,使用起来还算简单。下方代码段就是ProvincePickerView初始化方式,将ProvincePickerView进行初始化然后添加到所要显示ProvincePickerView的视图上,然后设置ProvincePickerView对象的Block回调。该回调会在用户点击ProvincePickerView上的完成按钮时执行,并返回当前用户选中的省市信息的Model数据。
上面是初始化ProvincePickerView,并且设置数据回调Block。下方的代码段就是用来显示ProvincePickerView的,调用showPickerView方法就会在下方弹出ProvincePickerView,因为ProvincePickerView本身就有取消按钮,取消后就会自动收回ProvincePickerView,所以我们不需要为用户提供收回ProvincePickerView的方法,所以使用起来还是比较简单的。
三、代码分享
由于博客篇幅有限,至于ProvincePickerView中封装的代码在此就不一一的往上粘贴了。说白了最核心就是对UIPickerViewDelegate和UIPickerViewDataSource两个代理中的相应的方法的封装。还有就是如何显示和隐藏PickerView,换一句话说,就是讲PickerView放在什么地方进行显示。有感兴趣的小伙伴可以从下方的github中分享的代码来自行分析呢。事无巨细,所以在此就不做过多的赘述了。
下方的代码截图就是在github上分享的部分代码,可以说是添加了详细的注释,有感兴趣的小伙伴可以进行自行阅读。代码中如有偏颇之处,还望指出。
上述所有的代码都是使用截图的方式呈现的,这无关紧要,在博客的结尾会给出所有相关的代码,当然也包括上述的PHP代码,以及PickerView的具体实现呢。好了,由于博客篇幅有限,今天就先到这儿吧。下方就是本篇博客相关代码的分享链接。
github分享地址:https://github.com/lizelu/ProvincePickerDemo
iOS开发之"省市"二级联动的数据组织(PHP版)以及PickerView的实现与封装的更多相关文章
- 省市二级联动(原生JS)
代码如下: <html> <head> <meta charset="UTF-8"> <title>省市二级联动</title ...
- 省市二级联动--使用app-jquery-cityselect.js插件
只有省市二级联动,三级联动还没处理好,会尽快完善. 嵌入id: <div class="form-group"> <label>地址</label&g ...
- 微信小程序picker组件 - 省市二级联动
picker 从底部弹起的滚动选择器,现支持五种选择器,通过mode来区分,分别是普通选择器,多列选择器,时间选择器,日期选择器,省市区选择器,默认是普通选择器. picker官方文档链接 由于项目需 ...
- JavaScript 实现省市二级联动
JavaScript 实现省市二级联动 版权声明:未经授权,严禁转载! 案例代码 <style> .hide { display: none; } </style> <s ...
- jQuery_完成省市二级联动
当填表的时候会让你设计某省某市怎么设计,应该明白,如果你选择了一个确定的省,那么在第二个下拉框内则不会有除了你选择的省的市之外的名称.而这功能用js来实现很麻烦,但是用jq确很容易实现. 原表结构: ...
- js省市二级联动实例
//动态创建省市二级联动<!DOCTYPE html><html lang="en"><head> <meta charset=" ...
- iOS开发之静态库(五)—— 图片、界面xib等资源文件封装到静态框架framework
编译环境:Macbook Air + OS X 10.9.2 + XCode5.1 + iPhone5s(iOS7.0.3) 一.首先将资源文件打包成bundle 由于bundle是静态的,所以可以将 ...
- jquery ajax实现省市二级联动
今天给大家带来使用jQuery ajax实现的省市联动效果.我们直奔主题,先说下实现思路: 准备数据 这里数据库我使用的是mysql,先看下表格: provience表 city表 这里使用provi ...
- 用jquery+Asp.Net实现省市二级联动
页面html: <%@ Page Language="C#" AutoEventWireup="true" CodeFile="ddlAjax. ...
随机推荐
- 说说Makefile那些事儿
说说Makefile那些事儿 |扬说|透过现象看本质 工作至今,一直对Makefile半知半解.突然某天幡然醒悟,觉得此举极为不妥,只得洗心革面从头学来,以前许多不明觉厉之处顿时茅塞顿开,想想好记性不 ...
- MIP 官方发布 v1稳定版本
近期,MIP官方发布了MIP系列文件的全新v1版本,我们建议大家尽快完成升级. 一. 我是开发者,如何升级版本? 对于MIP页面开发者来说,只需替换线上引用的MIP文件为v1版本,就可以完成升级.所有 ...
- ABP文档 - 通知系统
文档目录 本节内容: 简介 发送模式 通知类型 通知数据 通知重要性 关于通知持久化 订阅通知 发布通知 用户通知管理器 实时通知 客户端 通知存储 通知定义 简介 通知用来告知用户系统里特定的事件发 ...
- 渗透测试工具BurpSuite做网站的安全测试(基础版)
渗透测试工具BurpSuite做网站的安全测试(基础版) 版权声明:本文为博主原创文章,未经博主允许不得转载. 学习网址: https://t0data.gitbooks.io/burpsuite/c ...
- 03.LoT.UI 前后台通用框架分解系列之——多样的表格
LOT.UI分解系列汇总:http://www.cnblogs.com/dunitian/p/4822808.html#lotui LoT.UI开源地址如下:https://github.com/du ...
- 不懂CSS的后端难道就不是好程序猿?
由于H5在移动端的发展如日中天,现在大部分公司对高级前端需求也是到处挖墙角,前端薪资也随之水涨船高,那公司没有配备专用的前端怎么办呢? 作为老板眼中的“程序猿” 前端都不会是非常无能的表现,那作为后端 ...
- MSYS2环境下编译X265
HEVC(High Efficiency Video Coding),是一种新的视频压缩标准.可以替代H.264/ AVC编码,使得保持相同质量的情况下,体积减少40%左右.目前有多种实现版本,x26 ...
- EC笔记:第4部分:20、传递引用代替传值
考虑以下场景: #include <iostream> #include <string> using namespace std; struct Person { strin ...
- PHP设计模式(四)单例模式(Singleton For PHP)
今天讲单例设计模式,这种设计模式和工厂模式一样,用的非常非常多,同时单例模式比较容易的一种设计模式. 一.什么是单例设计模式 单例模式,也叫单子模式,是一种常用的软件设计模式.在应用这个模式时,单例对 ...
- nginx服务器安装及配置文件详解
nginx在工作中已经有好几个环境在使用了,每次都是重新去网上扒博客,各种编译配置,今天自己也整理一份安装文档和nginx.conf配置选项的说明,留作以后参考.像负载均衡配置(包括健康检查).缓存( ...