效果图:两个label、两个textField、两个button(背景是图片);点击时间对应的按钮,创建选择日期的DatePicker(并移除选择地点的PickerView),选择日期,将结果传到相应textField内,点击地点对应的按钮,创建选择地点的PickerView(并移除选择地点的DatePicker),选择地点,将结果传到相应的textField内,选择地点时,同时滑动省和城市这两列,不会崩溃
直接上代码吧,里面有注释;界面使用storyBoard搭建的,
首先是viewController.m中的代码:
1 #import "ViewController.h"
2 #import "DataModel.h"
3
4 @interface ViewController ()<UIPickerViewDataSource, UIPickerViewDelegate>
5 ///日期输入框
6 @property (weak, nonatomic) IBOutlet UITextField *dateField; 7 ///地点输入框
8 @property (weak, nonatomic) IBOutlet UITextField *placeField; 9
10 @property (nonatomic, strong) UIPickerView *myPickerView; 11 @property (nonatomic, strong) UIDatePicker *datePicker; 12 //当省列表和城市列表同时滑动时,刷新不及时,造成数组越界,程序崩溃,该变量用于记录当前省份在provinceArray中的角标,防止崩溃
13 @property (nonatomic, assign) NSInteger provinceIndex; 14
15 ///加载plist文件数据所需属性
16 @property (nonatomic, strong) NSMutableArray *provinceArray; 17
18 @end
19
20 @implementation ViewController 21 //懒加载读取plist文件中的数据
22 - (NSMutableArray *)provinceArray { 23 if (_provinceArray == nil) { 24 _provinceArray = [NSMutableArray array]; 25 NSString *pathString = [[NSBundle mainBundle] pathForResource:@"provinces.plist" ofType:nil]; 26 NSArray *arry = [NSArray arrayWithContentsOfFile:pathString]; 27 for (NSDictionary *dict in arry) { 28 DataModel *model = [[DataModel alloc] init]; 29 [model setValuesForKeysWithDictionary:dict]; 30 [_provinceArray addObject:model]; 31 } 32
33 } 34 return _provinceArray; 35 } 36
37 - (void)viewDidLoad { 38 [super viewDidLoad]; 39 // Do any additional setup after loading the view, typically from a nib.
40
41 } 42
43 #pragma mark - 日期选择按钮的响应方法
44 - (IBAction)dateAction:(UIButton *)sender { 45 [self.myPickerView removeFromSuperview]; 46 if (self.datePicker == nil) { 47
48 //设置UIDatePicker;只创建一次,防止多次点击按钮,创建多个对象,占用过多内存
49 self.datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 200)]; 50 } 51 //设置本地时间为中国
52 self.datePicker.locale = [NSLocale localeWithLocaleIdentifier:@"ch"]; 53 //日期显示格式
54 self.datePicker.datePickerMode = UIDatePickerModeDate; 55 [self.view addSubview:self.datePicker]; 56 [self changeValue:self.datePicker]; 57 //添加监听,当滑动选择的时候触发changeValue:方法
58 [self.datePicker addTarget:self action:@selector(changeValue:) forControlEvents:UIControlEventValueChanged]; 59
60 } 61 //监听触发方法的实现,将self.datePicker显示的日期转换成字符串显示在self.dateField上
62 - (void)changeValue:(UIDatePicker *)datePicker { 63 NSDateFormatter *format = [[NSDateFormatter alloc] init]; 64 format.dateFormat = @"yyyy-MM-dd"; 65 NSString *dateString = [format stringFromDate:datePicker.date]; 66 self.dateField.text = dateString; 67 } 68 #pragma mark - 地点选择按钮的响应方法
69 - (IBAction)placeAction:(UIButton *)sender { 70 //先将self.datePicker从父视图移除,再添加self.myPickerView
71 [self.datePicker removeFromSuperview]; 72 //设置UIPickerView
73 if (self.myPickerView == nil) {//只创建一次,防止多次点击按钮,创建多个对象,占用过多内存
74 self.myPickerView = [[UIPickerView alloc] initWithFrame:CGRectMake(0, 300, self.view.frame.size.width, 200)]; 75 } 76 [self.view addSubview:self.myPickerView]; 77 //设置代理
78 self.myPickerView.dataSource = self; 79 self.myPickerView.delegate = self; 80 [self pickerView:self.myPickerView didSelectRow:0 inComponent:0];//给placeField赋初始值
81
82 } 83 //设置列数
84 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { 85 return 2; 86 } 87 //设置每列的行数
88 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { 89 if (component == 0) { 90 return self.provinceArray.count;//第一列显示各个省份
91 }else { 92 DataModel *model = self.provinceArray[self.provinceIndex]; 93 return model.cities.count;//第二列根据第一列选中的省份,显示该省的城市,
94 } 95 } 96 //设置每行显示的内容,若不设置,默认显示的都是?
97 - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { 98 if (component == 0) { 99 DataModel *model = self.provinceArray[row]; 100 return model.name; 101 }else { 102 // NSInteger *index = [self.myPickerView selectedRowInComponent:0] 103 //DataModel *model = self.provinceArray[index];//之所以不用该句,是因为该句获取的是当前省份的城市,当省列表和城市列表同时滑动时,刷新不及时(UI刷新之后row的范围才能改变,例如UI刷新之前row的范围是1-10,省列表和城市列表同时滑动时,使用上面两句代码,当前省份随着滚动而改变,若某个省份的城市数量小于10,后面代码“return model.cities[row];”就会数组越界,程序崩溃),造成数组越界,程序崩溃,所以在开始的时候声明一个记录当前省份的变量provinceIndex。
104 DataModel *model = self.provinceArray[self.provinceIndex]; 105 return model.cities[row]; 106 } 107 } 108 //滚动的时候,触发的方法
109 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { 110 if (component == 0) { 111 //记录当前选中的省份
112 self.provinceIndex = [self.myPickerView selectedRowInComponent:0]; 113 [self.myPickerView reloadComponent:1]; 114 } 115 DataModel *model = self.provinceArray[self.provinceIndex]; 116 NSInteger index = [self.myPickerView selectedRowInComponent:1]; 117 NSString *string = [model.name stringByAppendingString:model.cities[index]];//注意:这里model.cities[index],要获取当前列选中的行数,不能使用model.cities[row],否则会造成数组越界
118 self.placeField.text = string; 119 } 120
121 @end
然后是DataModel.h中的代码:该部分是取出plist文件中的数据时创建的模型:
1 #import <Foundation/Foundation.h>
2
3 @interface DataModel : NSObject 4 ///存放城市
5 @property (nonatomic, strong) NSArray *cities; 6 ///省的名称
7 @property (nonatomic, strong) NSString *name; 8
9 @end
最后是DataModel.m中的代码
1 #import "DataModel.h"
2
3 @implementation DataModel 4 //使用KVC赋值,防止程序崩溃
5 - (void)setValue:(id)value forUndefinedKey:(NSString *)key { 6
7 } 8
9 @end