一个简单的plist 解析过程,借助UIPickerView 实现了手选全国的 省市区 方法,
源码中有详细注释;长句自己可以拆开看,最好的方法是,拆开,并打印,查看每一步打印的结果,结合Plist文件,解读文件读取过程
基本原理是通过字典 、数组、逐层剥壳
源码:
.h
1 // 2 // ViewController.h 3 // AreaAnalysis 4 // 5 // Created by Ibokan on 15/8/28. 6 // Copyright (c) 2015年 Crazy凡. All rights reserved. 7 // 8 9 #import <UIKit/UIKit.h> 10 11 @interface ViewController : UIViewController <UIPickerViewDelegate, UIPickerViewDataSource>//遵守协议 12 13 14 @end
.m
1 // 2 // ViewController.m 3 // AreaAnalysis 4 // 5 // Created by Ibokan on 15/8/28. 6 // Copyright (c) 2015年 Crazy凡. All rights reserved. 7 // 8 9 #import "ViewController.h" 10 11 @interface ViewController () 12 @property (weak, nonatomic) IBOutlet UIPickerView *pickerView; 13 @property (weak, nonatomic) IBOutlet UILabel *infoLabel; 14 @property (nonatomic,strong) NSArray *province; 15 @property (nonatomic,strong) NSMutableArray *tempdata;//装载当前省的全部数据 16 @property (nonatomic, strong) NSMutableArray *pickerProvincesData;//当所有省的名称数据 17 @property (nonatomic, strong) NSMutableArray *pickerCitiesData;//当前的省下面的市名称数据 18 @property (nonatomic, strong) NSMutableArray *pickerDistrictData;//当前的市下面的区的名称数据 19 @property int ia,ib; 20 @end 21 @implementation ViewController 22 23 - (void)viewDidLoad { 24 [super viewDidLoad]; 25 // Do any additional setup after loading the view. 26 self.province = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"area2.plist" ofType:nil]]; 27 self.pickerProvincesData = [[NSMutableArray alloc]init]; 28 self.pickerCitiesData = [[NSMutableArray alloc]init]; 29 self.pickerDistrictData = [[NSMutableArray alloc]init]; 30 self.tempdata = [[NSMutableArray alloc]init]; 31 for(int i = 0 ; i < self.province.count ; [self.pickerProvincesData addObjectsFromArray:[self.province[i++] allKeys]]);//取出所有的keys(省)仅有名称,数据部分是根据省动态获取的 32 self.ia = self.ib = 0; 33 [self getPickerCitiesData];//获取初始化市 34 [self getPickerDistrictData];//获取初始化区 35 self.pickerView.dataSource = self; 36 self.pickerView.delegate = self; 37 [self.infoLabel setText:[NSString stringWithFormat:@"%@;%@;%@",self.pickerProvincesData[[self.pickerView selectedRowInComponent:0]],self.pickerCitiesData[[self.pickerView selectedRowInComponent:1]],self.pickerDistrictData[[self.pickerView selectedRowInComponent:2]]]];//让label 显示选中的内容(初始化后显示) 38 } 39 - (void)getPickerCitiesData//装载市 40 { 41 [self.pickerCitiesData removeAllObjects];//清除数据 42 [self.tempdata removeAllObjects];//清除数据 43 [self.tempdata addObjectsFromArray:[[NSArray alloc]initWithArray:[self.province[self.ia] valueForKey:self.pickerProvincesData[self.ia]]]];//将当前省的所有数据保存在一个数组中,避免反复读取 44 for(NSDictionary *dir in self.tempdata) { [self.pickerCitiesData addObjectsFromArray:[dir allKeys]]; }//将市的名称取出 45 } 46 - (void)getPickerDistrictData//装载区 47 { 48 [self.pickerDistrictData removeAllObjects]; 49 [self.pickerDistrictData addObjectsFromArray:[self.tempdata [self.ib]valueForKey:self.pickerCitiesData[self.ib]]];//填充区的名称 50 } 51 #pragma mark 实现协议UIPickerViewDataSource方法 52 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {return 3; }//设定有几列 53 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 54 switch (component) {//设定每一列有多少行 55 case 0: return self.pickerProvincesData.count; break; 56 case 1: return self.pickerCitiesData.count; break; 57 case 2: return self.pickerDistrictData.count; break; 58 default: break; 59 } 60 return 0; 61 } 62 #pragma mark 实现协议UIPickerViewDelegate方法 63 -(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {//设定行内容 64 switch (component) { 65 case 0: return [self.pickerProvincesData objectAtIndex:row]; break; 66 case 1: return [self.pickerCitiesData objectAtIndex:row]; break; 67 case 2: return [self.pickerDistrictData objectAtIndex:row]; break; 68 default: break; 69 } 70 return 0; 71 }//设定行内容结束 72 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 73 switch (component) {//检测滑动事件(row 是行 component 是代表滚动的列) 74 case 0: 75 self.ia = (int) row; 76 self.ib = 0; 77 [self getPickerCitiesData];//重新装载城市数据 78 [self getPickerDistrictData];//重新装载区数据 79 [self.pickerView reloadComponent:1];//重新填充城市列表 80 [self.pickerView reloadComponent:2];//重新填充城市列表 81 break; 82 case 1: 83 self.ib = (int) row; 84 [self getPickerDistrictData]; 85 [self.pickerView reloadComponent:2]; 86 break; 87 default: break; 88 } 89 [self.infoLabel setText:[NSString stringWithFormat:@"%@;%@;%@",self.pickerProvincesData[[self.pickerView selectedRowInComponent:0]],self.pickerCitiesData[[self.pickerView selectedRowInComponent:1]],self.pickerDistrictData[[self.pickerView selectedRowInComponent:2]]]];//刷新 label 显示的内容 (每次滚动后刷新) 90 } 91 - (void)didReceiveMemoryWarning { 92 [super didReceiveMemoryWarning]; 93 // Dispose of any resources that can be recreated. 94 } 95 @end
知识点:
先说一下 UIPickerView吧,我只是让你会用,理解的话,自己看文档 command + 鼠标左键 别告诉我不认识英文,我也不认识!
废话不多说:
首先是遵守协议:
<UIPickerViewDelegate, UIPickerViewDataSource>//遵守协议
其次 是实现方法;也就是下面很长这一块;代码中有注释,我再摘出来单独说一下
#pragma mark 实现协议UIPickerViewDataSource方法
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {return 3; }//设定有几列(return N 就有N列)
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
switch (component) {//设定每一列有多少行 看参数 component 代表当前在为第几列设定行数,return N 就会为第几列设定多少行
case 0: return self.pickerProvincesData.count; break;
case 1: return self.pickerCitiesData.count; break;
case 2: return self.pickerDistrictData.count; break;
default: break;
}
return 0;
}
#pragma mark 实现协议UIPickerViewDelegate方法
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {//设定行内容
switch (component) {//设定行的内容,Component 是列 row 是列中的行, 也就是 给 第几行几列设定值(返回值就是 设定的值)
case 0: return [self.pickerProvincesData objectAtIndex:row]; break;
case 1: return [self.pickerCitiesData objectAtIndex:row]; break;
case 2: return [self.pickerDistrictData objectAtIndex:row]; break;
default: break;
}
return 0;//这里是写代码的失误吧,换成nil 更好 为了保证和上面贴的源码一致,就不改了,下面下载的文件中改过来,大家见谅,
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
switch (component) {//检测滑动事件(row 是行 component 是代表滚动的列) 判断滑动的是第几列 然后 刷新数据
case 0:
self.ia = (int) row;
self.ib = 0;
[self getPickerCitiesData];//重新装载城市数据
[self getPickerDistrictData];//重新装载区数据
[self.pickerView reloadComponent:1];//重新填充城市列表
[self.pickerView reloadComponent:2];//重新填充城市列表
break;
case 1:
self.ib = (int) row;
[self getPickerDistrictData];
[self.pickerView reloadComponent:2];
break;
default: break;
}
[self.infoLabel setText:[NSString stringWithFormat:@"%@;%@;%@",self.pickerProvincesData[[self.pickerView selectedRowInComponent:0]],self.pickerCitiesData[[self.pickerView selectedRowInComponent:1]],self.pickerDistrictData[[self.pickerView selectedRowInComponent:2]]]];//刷新 label 显示的内容 (每次滚动后刷新)这句下面有解析,我就不重复了
}
1、
self.province = [[NSArray alloc]initWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"area2.plist" ofType:nil]];
不多解释,Plist文件读取,很多次了,
2、
self.pickerProvincesData = [[NSMutableArray alloc]init];
可变数组初始化,记得使用之前一定要初始化,一定要初始化,一定要初始化,重要的事情说三遍!!很小的问题,但是(自己)会经常忘掉,然后找半天错……都是空、都是泪、
3、
for(int i = 0 ; i < self.province.count ; [self.pickerProvincesData addObjectsFromArray:[self.province[i++] allKeys]]);
字典数组怎么取出所有字典的key值,addObjectsFromArray 和 allKeys 的完美搭配
4、
[self.pickerCitiesData removeAllObjects];//清除数据
重新使用可变数组记得清空!!!
5、
[self.infoLabel setText:[NSString stringWithFormat:@"%@;%@;%@",self.pickerProvincesData[[self.pickerView selectedRowInComponent:0]],self.pickerCitiesData[[self.pickerView selectedRowInComponent:1]],self.pickerDistrictData[[self.pickerView selectedRowInComponent:2]]]];
好吧,这句话好长,但是很简单
可以拆为stringWithFormat 和 self.pickerView selectedRowInComponent:0 前一句 应该都懂了,后面一句是取出当前选中的是第几行