iOS省市二級聯(lián)動的數(shù)據(jù)組織PHP版
之所以要發(fā)表這篇博客,還源于最近的開發(fā)工作所實現(xiàn)的一個小的Demo, 當(dāng)然這個Demo不會涉及工作中App的一些內(nèi)容,下方要實現(xiàn)的Demo是通用的。因為項目需求的迭代,要求在銀行卡綁定中添加支行所在的省市信息。在iOS中選擇這種省市信息的一個比較不錯的方式當(dāng)時是使用UIPickerView進行顯示了。當(dāng)然在PickerView上的省市信息是聯(lián)動顯示的,我們在此因為需求定的是讓用戶選擇省市信息,所以我們進行二級聯(lián)動,當(dāng)然多級聯(lián)動的原理也是一樣的。由于之前的老項目是使用Objective-C寫的,雖然現(xiàn)在是Swift與OC混編,不過要在OC實現(xiàn)VC上添加新的功能還得用OC來實現(xiàn)呢,所以今天的博客的Demo咱就不用Swift來實現(xiàn)了,不過原理上是一樣的。
下方的的截圖就是我們今天博客中要介紹的Demo的運行效果,我們今天的博客就是生成PickerView所需的數(shù)據(jù),以及對下方這個PickerView進行封裝。從下方的動畫中我們不難看出,在第一列選擇省后,第二列會自動的顯示該省下的所有地級市。點擊完成后,會在上方相應(yīng)的Label中顯示出你所有選擇的省市以及該省市所對應(yīng)的編號。具體的請看下方這個粗劣的動畫。
一、數(shù)據(jù)源的生成(從Excel到Plist)
1.組織數(shù)據(jù)的前奏
在封裝上述PickerView控件之前,我們得有數(shù)據(jù)不是,也就是我們得有省市的名稱,各個省市所對應(yīng)的編碼,以及省與市的對應(yīng)關(guān)系。當(dāng)然這些數(shù)據(jù)在網(wǎng)上一抓一大把,權(quán)威的數(shù)據(jù)要看"國家統(tǒng)計局"所提供的數(shù)據(jù)了。下方這兩個截圖是一個Excel表格中的兩個Sheet,是我們服務(wù)端的一個程序媛給的,算是客戶端與服務(wù)端的一個標(biāo)準(zhǔn)吧,估計也是從網(wǎng)上下載的。下方的省市信息以及編碼當(dāng)然與國家統(tǒng)計局提供的一致了,這個毋庸置疑。
我拿到這個Excel表格怎么用呢?我就想通過OC或者Swift來直接解析excel表格來讀取數(shù)據(jù),然后處理成我想要的格式。不過經(jīng)過一番了解后,感覺該解決方案頗為復(fù)雜,于是乎就另尋他路。又于是乎,想起了之前用過的PHPExcel這個框架,因為之前做PHP開發(fā)的時候使用過PHPExcel來讀取Excel文件。這個PHPExcel使用起來還是蠻順手的,用起來也不復(fù)雜,于是乎我就決定使用PHPExcel來讀取下方這兩個Sheet中的數(shù)據(jù)。
使用PHPExcel讀取數(shù)據(jù)后,重新將數(shù)據(jù)進行關(guān)聯(lián)組織并生成json提供給iOS這邊使用。iOS這邊獲取到Json后,將其進行解析后存儲到plist文件中,這樣我們就可以從plist文件中來獲取“省市”相關(guān)數(shù)據(jù)了,然后我們就可以封裝我們的PickerView了。今天博客就一步一步的來完成這個東西。當(dāng)然你也可以使用SQLite數(shù)據(jù)庫來存儲下方Excel中的數(shù)據(jù),create兩張表,一張放省,一張放市,使用外鍵進行一對多的關(guān)聯(lián)即可。使用SQLite數(shù)據(jù)庫是另一種解決方案,在此我們使用的是plist文件,因為相對簡單嗎,因為數(shù)據(jù)少,plist文件度過了就可以在我們的pickerView上使用了,如果你想使用SQLite也是相當(dāng)OK的,此篇博客值提供plist文件這種解決方案。
2.使用PHPExecl讀取省市Excel數(shù)據(jù)
在上面的Excel數(shù)據(jù)中第一個Sheet中存儲的是每個省以及每個省所對應(yīng)的編碼,而第二個Sheet中是存儲的每個市和市的編碼,并給出了每個市所在的省。接下來我們要使用PHPExcel這個第三方框架對上述Excel的數(shù)據(jù)進行讀取,關(guān)于PHPExcel的東西請看其官方文檔,地址為:https://phpexcel.codeplex.com/。下方代碼就是我們使用PHPExcel讀取上述Excel文件的代碼了,并且將上述數(shù)據(jù)進行處理,將處理后的數(shù)據(jù)進行json編碼。下方我們將介紹相關(guān)的PHP代碼。
(1)加載PHPExcel框架以及省市excel文件--province.xls
下方的PHP代碼片段就是加載PHPExcel框架,以及通過PHPExcel_IOFactory來創(chuàng)建文件讀取器對象$objReader, 并公告$objReader對象來加載我們的province.xls文件。打開后會返回一個操作Excel文件的一個文件句柄對象$objPHPExcel,我們可以通過$objPHPExcel來操作已經(jīng)打開的Excel文件。具體代碼如下所示。
(2)通過上述$objPHPExcel對象來讀取Excel文件內(nèi)容
接下來我們要通過$objPHPExcel這個操作文件的對象來獲取province.xml中的數(shù)據(jù)。下方對主要的代碼添加的注釋,應(yīng)該還算是清晰。在下方代碼片段中$dataArray數(shù)組我們用來存儲province.xml中所有Sheet的數(shù)據(jù)。我們循環(huán)了兩次來打開該Excel中的兩個Sheet,通過$objPHPExcel對象的setActiveSheetIndex()方法通過索引來選擇相應(yīng)Sheet(從左到右,從0到n),并通過該對象的getActiveSheet()方法來獲取當(dāng)前選擇的Sheet,選擇后返回一個$objWorksheet對象,我們可以通過$objWorksheet對象來讀取當(dāng)前Sheet中每行每列的數(shù)據(jù)。
我們通過foreach來迭代當(dāng)前Sheet中的每行數(shù)據(jù),同樣適用foreach來迭代一行中每列的數(shù)據(jù)。我們將每列的數(shù)據(jù)存入$tempRowArray數(shù)組中,然后在將每行的數(shù)據(jù)即$tempRowArray存入到Sheet數(shù)據(jù)的$tempSheetArray中。最后將當(dāng)前的Sheet的數(shù)據(jù)$tempSheetArray存入到$dataArray中。具體實現(xiàn)如下:
3.數(shù)據(jù)的驗證
通過上述步驟,我們就可以將Excel中的每個Sheet中的數(shù)據(jù)存入到我們的數(shù)組中。其中的數(shù)據(jù)結(jié)果是這樣的: $dataArray中存儲的是每個Sheet($tempSheetArray)的數(shù)據(jù),Sheet($tempSheetArray)中又有多行($tempRowArray),每行($tempRowArray)中又有多列。所以dataArray就對應(yīng)著整個Excel表格。我們也就獲取了所有的Excel數(shù)據(jù)。經(jīng)過上述代碼,$dataArray中就存儲了Excel的數(shù)據(jù)。為了保險起見我們將$dataArray中的數(shù)據(jù)進行打印,下方是我們的測試代碼。
還有在我們寫程序時呢,為了減少bug量,以及減少調(diào)試bug的難度,我們一定要養(yǎng)成一邊寫代碼一遍調(diào)試的好習(xí)慣。這樣會及時發(fā)現(xiàn)bug并修正,寫好一個小的功能模塊我們就對其進行測試,如果出了問題就很容易定位bug的所在之處。下方代碼就是對上述代碼的測試:
上述代碼對$dataArray中存儲的數(shù)據(jù)進行了一個打印,可以幫助我們查看我們$dataArray中所存儲的數(shù)據(jù)是否符合我們的預(yù)期。下方的輸出結(jié)果就是我們上述的測試用例所輸出的結(jié)果,上面紅框中是第一個Sheet中的數(shù)據(jù),下方的是第二個Sheet中的數(shù)據(jù),我們大體上一看符合我們的預(yù)期,就說明我們之前的代碼沒有什么問題,我們就可以對$data中的數(shù)據(jù)進行關(guān)聯(lián)并生成JSON數(shù)據(jù)了。
4.省市數(shù)據(jù)進行關(guān)聯(lián)
上面我們已經(jīng)將數(shù)據(jù)從Excel中讀取出來了,并且將量Sheet中的數(shù)據(jù)存入了不同的數(shù)組,接下來我們將要對數(shù)據(jù)進行處理。該部分就是將省市的數(shù)據(jù)進行關(guān)聯(lián),也就是將兩個Sheet中的數(shù)據(jù)合并成一個數(shù)據(jù)塊。下方就是我們要存儲數(shù)據(jù)的一個結(jié)構(gòu)圖。整個是一個數(shù)組,數(shù)組中是一個字典,每個字典就代表一個省。每個省的字典又省編碼Code、省名Name、所有市Citys組成。Citys中存儲的又是一個數(shù)組。該數(shù)組中的每一項又是一個字典,此處的每個字典代表著一個市,每個市的字典中有包括市名Name和市編碼Code。數(shù)據(jù)結(jié)構(gòu)如下所示。
參考上圖,我們要對讀取的數(shù)據(jù)進行處理,將數(shù)據(jù)重新組織成上述結(jié)構(gòu)。下方代碼段就是對讀取的Excel表格中的數(shù)據(jù)進行重組。經(jīng)過下方代碼的處理我們就可以得到上述結(jié)構(gòu)的數(shù)據(jù)了。下面的$allDataArray就存儲的是所有的數(shù)據(jù)信息,$provinceTempData中暫存著每次省的所有信息,$currentProvinceCitys中存儲的就是當(dāng)前省中所有市的信息。第二個循環(huán)中的if語句則負責(zé)管理省市間的關(guān)系了,具體代碼以及代碼注釋如下所示。
經(jīng)過上面的代碼我們所有的數(shù)據(jù)就會存入到$allDataArray中,上面對$allDataArray進行了Json編碼并輸出,下方就是處理后輸出的Josn數(shù)據(jù)。在此我們以河北省為例。下圖中的結(jié)構(gòu)是與上面我們數(shù)據(jù)結(jié)構(gòu)圖一一對應(yīng)的,這正是我們想要的數(shù)據(jù)。到此我們數(shù)據(jù)處理的任務(wù)就完成一大半了,因為我們得到了我們想要的JSON。
5. 將上述JSON數(shù)據(jù)進行解析并存入Plist文件
經(jīng)過上述步驟,PHP的工作算是告一段落。接下來我們就是要使用iOS客戶端來訪問上述地址,獲取上述生成的JSON數(shù)據(jù)。獲取到JSON數(shù)據(jù)后,我們將JSON數(shù)據(jù)進行解析,并存儲到沙盒中的plist文件。這樣我們就可以從plist文件中來加載我們的省市數(shù)據(jù)了。
下方代碼段是我們的iOS客戶端的代碼,該代碼通過NSURLSessionDataTask來請求上述PHP代碼所在的文件獲取省市的JSON數(shù)據(jù)。請求到JSON數(shù)據(jù)后對數(shù)據(jù)進行解析,將JSON數(shù)據(jù)解析成數(shù)組后在通過NSFileManager存儲到沙盒中的PList文件中。如果你要在外部使用,只需要找到模擬器中的沙盒路徑拷貝出plist文件即可。下方代碼就是網(wǎng)絡(luò)請求+JSON解析+Plist文件存儲的的代碼。
經(jīng)過上述代碼的執(zhí)行,你會在你的模擬器中上述App的沙盒中發(fā)現(xiàn)一個叫province.plist的文件,該文件中存儲的就是我們要使用的省市數(shù)據(jù)。該plist文件的數(shù)據(jù)存儲結(jié)構(gòu)是我們上面的介紹過的數(shù)據(jù)結(jié)構(gòu),下方就是該plist文件中數(shù)據(jù)的部分截圖。至此我們就獲得了一個按我們的預(yù)期存有省市數(shù)據(jù)plist文件了。
二、封裝選擇省市的PickerView的使用方式
封裝當(dāng)然不是簡單的將PickerView的簡單使用,在封裝代碼時我們要考慮到用戶的易用性和可擴展性。在此我只對PickerView做了一個簡單的封裝,不過干貨還是有的,主要是思想呢。經(jīng)過上面一大模塊的數(shù)據(jù)組織呢,我們就可以將之前服務(wù)端所給的Excel文檔中的數(shù)據(jù)組織成我們想要的plist數(shù)據(jù)。本部分所做的主題就是讀取plist文件中的數(shù)據(jù),將該數(shù)據(jù)顯示在二級聯(lián)動的PickerView上供用戶選擇。用戶選擇完成后返回用戶選擇的省市名以及省市所對應(yīng)的編碼。開始我們控件的封裝。
1.所封裝控件的目錄結(jié)構(gòu)
首先我們先整體的看一下我們所封裝控件的目錄結(jié)構(gòu)是怎樣的,先整體的了解一下我們這個封裝的控件。下方截圖中就是我們所封裝控件的目錄結(jié)構(gòu)了,因為我們是對顯示省市信息的UIPikcerView進行的封裝,所以在此我們稱其為ProvincePickerView,ProvincePickerView就是我們所封裝的組件了。用戶只需要對其進行實例化并添加到其視圖上就可以進行使用了。下方的province.plist數(shù)據(jù)就是我們上面所生成的存有省市信息是數(shù)據(jù),我們ProvincePickerView中的數(shù)據(jù)源就是province.plist文件。
ProvinceModel就存儲著當(dāng)前選中的省市的名稱以及編碼,下面第二張截圖就是ProvinceModel中的內(nèi)容了。provinceCode存儲的是當(dāng)前選中的省的編碼,provinceName存儲的就是當(dāng)前所選省的名稱,cityCode存儲的是所選市的編碼,cityName存儲的是所選市的名稱。具體代碼如下所示。
2. 所封裝控件的初始化以及調(diào)用方式
接下來我們看一下我們封裝的這個ProvincePickerView的使用方式,使用起來還算簡單。下方代碼段就是ProvincePickerView初始化方式,將ProvincePickerView進行初始化然后添加到所要顯示ProvincePickerView的視圖上,然后設(shè)置ProvincePickerView對象的Block回調(diào)。該回調(diào)會在用戶點擊ProvincePickerView上的完成按鈕時執(zhí)行,并返回當(dāng)前用戶選中的省市信息的Model數(shù)據(jù)。
上面是初始化ProvincePickerView,并且設(shè)置數(shù)據(jù)回調(diào)Block。下方的代碼段就是用來顯示ProvincePickerView的,調(diào)用showPickerView方法就會在下方彈出ProvincePickerView,因為ProvincePickerView本身就有取消按鈕,取消后就會自動收回ProvincePickerView,所以我們不需要為用戶提供收回ProvincePickerView的方法,所以使用起來還是比較簡單的。
三、代碼分享
由于博客篇幅有限,至于ProvincePickerView中封裝的代碼在此就不一一的往上粘貼了。說白了最核心就是對UIPickerViewDelegate和UIPickerViewDataSource兩個代理中的相應(yīng)的方法的封裝。還有就是如何顯示和隱藏PickerView,換一句話說,就是講PickerView放在什么地方進行顯示。有感興趣的小伙伴可以從下方的github中分享的代碼來自行分析呢。事無巨細,所以在此就不做過多的贅述了。
下方的代碼截圖就是在github上分享的部分代碼,可以說是添加了詳細的注釋,有感興趣的小伙伴可以進行自行閱讀。代碼中如有偏頗之處,還望指出。
上述所有的代碼都是使用截圖的方式呈現(xiàn)的,這無關(guān)緊要,在博客的結(jié)尾會給出所有相關(guān)的代碼,當(dāng)然也包括上述的PHP代碼,以及PickerView的具體實現(xiàn)呢。好了,由于博客篇幅有限,今天就先到這兒吧。下方就是本篇博客相關(guān)代碼的分享鏈接。
github分享地址:https://github.com/lizelu/ProvincePickerDemo
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
- 詳解iOS開發(fā)中UIPickerView控件的使用方法
- 實例講解iOS應(yīng)用開發(fā)中UIPickerView滾動選擇欄的用法
- iOS App中UIPickerView選擇欄控件的使用實例解析
- 詳解iOS App中UIPickerView滾動選擇欄的添加方法
- IOS實現(xiàn)選擇城市后跳轉(zhuǎn)Tabbar效果
- jQuery select表單提交省市區(qū)城市三級聯(lián)動核心代碼
- js實現(xiàn)全國省份城市級聯(lián)下拉菜單效果代碼
- C#省份城市下拉框聯(lián)動簡單實現(xiàn)方法
- JS簡單實現(xiàn)城市二級聯(lián)動選擇插件的方法
- iOS開發(fā)之UIPickerView實現(xiàn)城市選擇器的步驟詳解
相關(guān)文章
iOS UICollectionView實現(xiàn)橫向滑動
這篇文章主要為大家詳細介紹了iOS UICollectionView實現(xiàn)橫向滑動,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2020-03-03IOS微信端confirm以及alert去掉網(wǎng)址的實例代碼
下面小編就為大家分享一篇IOS微信端confirm以及alert去掉網(wǎng)址的實例代碼,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-01-01Objective-C實現(xiàn)自定義的半透明導(dǎo)航
這篇文章主要為大家詳細介紹了Objective-C實現(xiàn)自定義的半透明導(dǎo)航的相關(guān)資料,需要的朋友可以參考下2016-05-05iOS App開發(fā)中Core Data框架基本的數(shù)據(jù)管理功能小結(jié)
除了使用SQL關(guān)系型數(shù)據(jù)庫,我們還可以使用Xcode中提供的Core Data來進行表結(jié)構(gòu)數(shù)據(jù)處理,這里我們就來初步整理iOS App開發(fā)中Core Data框架基本的數(shù)據(jù)管理功能小結(jié):2016-06-06IOS 打包出現(xiàn)Missing Push Notification Entitlement 問題解決方案
這篇文章主要介紹了IOS 打包出現(xiàn)Missing Push Notification Entitlement 問題解決方案的相關(guān)資料,需要的朋友可以參考下2016-12-12IOS設(shè)備上給body綁定click事件不生效的原因及解決辦法
最近在做移動端的項目,在ios上對body綁定click事件實現(xiàn)事件代理冒泡至某些元素上不生效,怎么回事,如何解決呢?今天小編給大家?guī)砹薎OS設(shè)備上給body綁定click事件不生效的原因及解決辦法,一起看看吧2016-09-09