UIPickerView和UIDatePicker的簡單應用(雙級聯動防止崩潰)


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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM