效果图:两个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
时间: 2024-08-03 15:52:15