效果圖:兩個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