iOS-UIDatePicker以及UIPickerView--日期選擇和地址選擇實(shí)現(xiàn)(省市縣三級聯(lián)動)

金陵子弟來相送,欲行不行各盡觴!<地幔巖>

簡單說幾句:

UIDatePicker:
1: 直接繼承 UIControl (那么就可以有 addTarget ........的方法使用 可以添加相應(yīng)的觸發(fā)事件)
2: 可以用來選擇作為時間選擇器, 通過 datePickerMode 選擇樣式效果
3: 使用比較多的屬性可以點(diǎn)進(jìn)去看下一般就是 date(當(dāng)前的表示日期 NSDate 類型) locale( 選擇語言 zh 中文 en 英文)
UIPickerView:
1: 直接繼承與 UIView 在使用上與 tabelView 有很多類似之處
2: 完美的使用要依賴代理實(shí)現(xiàn)兩個協(xié)議<UIPickerViewDelegate, UIPickerViewDataSource>
3: 其他的搜集到了再補(bǔ)充


看一下 UI 的外觀展示


UIDatePicker的樣子
UIPickerView

下面我們簡單實(shí)現(xiàn)一下一個選擇日期和選擇地址的效果

這里我用兩個 textFile 作為輸入框接收我們?nèi)掌诤偷刂沸Ч麍D如下, 在一些注冊和購物選址地方會出現(xiàn)使用
效果圖如下:

日期和地址輸入展示.gif

解析思路難點(diǎn):
1: 兩個 textFile 點(diǎn)擊后的彈出的默認(rèn)鍵盤 分別替換成 UIDatePicker 和 UIPickerView 作為輸入
2: 通過鍵盤的代理方法來控制鍵盤的輸入問題
3: 地址的處理容易三級聯(lián)動過程中容易出現(xiàn)數(shù)組越界問題, 我這里解決不知道完美不, 有更好的方法還請簡友多幫助我.

上代碼:

需要的屬性:

@interface ViewController ()<UITextFieldDelegate, UIPickerViewDelegate, UIPickerViewDataSource>

@property (weak, nonatomic) IBOutlet UITextField *timeField;// 時間輸入
@property (weak, nonatomic) IBOutlet UITextField *addressFiled;// 地址輸入
@property (strong, nonatomic) UIDatePicker *dateKB;// 日期鍵盤
@property (strong, nonatomic) UIPickerView *addressKB;// 地址鍵盤
@property (strong, nonatomic) NSMutableArray<province_Model *> *allProvinceArray;// 存放所有的數(shù)據(jù)

# 下面幾個數(shù)據(jù)為了防止同時滑動多個列的時候  某個列數(shù)據(jù)獲取時候數(shù)組越界導(dǎo)致崩潰
@property (assign, nonatomic) NSInteger provinceCurrentIndex;// 用來記錄''當(dāng)前''的省份下標(biāo)(地址鍵盤第 0 列選中 row))
@property (assign, nonatomic) NSInteger cityCurrentIndex; // 用來記錄''當(dāng)前''的城市的下標(biāo)(地址鍵盤第 1 列選中的 row)
@property (assign, nonatomic) NSInteger countyCurrenIndex; // 記錄縣
@end

我這里使用了兩個 Model 類

# province_Model
@property (copy, nonatomic) NSString *provinceName;
@property (strong, nonatomic) NSMutableArray<city_Model *> *cityArray;
# city_Model
@property (copy, nonatomic) NSString *cityName;
@property (strong, nonatomic) NSMutableArray *countyArray;

在 viewDidLoad 中設(shè)置一些基本的參數(shù):
 // 設(shè)置代理
    self.timeField.delegate = self;
    self.addressFiled.delegate = self;
    
  // 初始化日期鍵盤
    self.dateKB = [UIDatePicker new];
    _dateKB.datePickerMode = UIDatePickerModeDate; // 設(shè)置模式 這里是 年月日 沒有上下午
    _dateKB.locale = [NSLocale localeWithLocaleIdentifier:@"zh"]; // 設(shè)置地區(qū) 這里是
    self.timeField.inputView = _dateKB; // 用 UIDatePicker 替換 timeField 的鍵盤
    
    // 當(dāng)值改變的時候會觸發(fā)的方法  我們滑動日期鍵盤的時候  執(zhí)行方法 rollAction:
    [_dateKB addTarget:self action:@selector(rollAction:) forControlEvents:(UIControlEventValueChanged)];
    
    // 初始化地址鍵盤
    self.addressKB = [UIPickerView new];
    self.addressKB.delegate = self;
    self.addressKB.dataSource = self;
    self.addressFiled.inputView = self.addressKB; // 用 UIPickerView 替換 addressFiled輸入鍵盤
    
    // 解析數(shù)據(jù)
    self.allProvinceArray = [NSMutableArray array];  // 存放所有的省份
// 調(diào)用 自定義的 從 plist 析數(shù)據(jù)方法
    [self getDataForPlist];

數(shù)據(jù)的結(jié)構(gòu)如圖: 感謝網(wǎng)友的分享的 plist 的文件有需要的可以下載使用鏈接: 密碼: 2pdf

文件.png

#pragma mark ------>> 解析數(shù)據(jù) <<------
- (void)getDataForPlist
{
    NSString *pathDataStr =  [[NSBundle mainBundle] pathForResource:@"China" ofType:@"plist"];
    NSDictionary *dic = [NSDictionary dictionaryWithContentsOfFile:pathDataStr];
    // 取出省份
    // 先取到每個省最外層的 key
   for (NSString *item in [dic allKeys])
    {
        //NSLog(@"①--itme--->%@", item);
        // 遍歷取到 省份名
        for (NSString *provinceName in dic[item])
        {
            // 創(chuàng)建 省份 的實(shí)體 Model
            province_Model *modelP = [province_Model new];
            modelP.provinceName = provinceName;
            for (NSString *itemCity in dic[item][provinceName])
            {
                  // 遍歷取到 對應(yīng)省份的  城市
                for (NSString *cityName in dic[item][provinceName][itemCity])
                {
                    city_Model *modelC = [city_Model new];
                    modelC.cityName = cityName;
                    // 依次找到 城市 對應(yīng)的縣城
                    modelC.countyArray = dic[item][provinceName][itemCity][cityName];
                    // 把對應(yīng)的城市 Model 添加到  省的城市數(shù)組中
                    [modelP.cityArray addObject:modelC];
                }
            }
            [self.allProvinceArray addObject:modelP];
        }
    }    
}

先來實(shí)現(xiàn) 日期的輸入

#pragma mark ------>> 使用鍵盤的代理方法對輸入進(jìn)行控制 監(jiān)聽的效果 <<------
// 這里返回 NO 就是不讓鍵盤輸入  而是按照我們需要的作為 textFile 的 text
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
     NSLog(@"方法名--->%s", __func__);
           return NO;
}
#pragma mark 開始編輯的時候就把默認(rèn)的 日期 和地址 顯示上  可以直接調(diào)用方法
- (void)textFieldDidBeginEditing:(UITextField *)textField
{
     NSLog(@"方法名--->%s", __func__);
    if (textField == self.addressFiled)
    {// 調(diào)用 PickView 的選中方法 給地址 textFile 賦值 (這個方法在后面有)
        [self  pickerView:self.addressKB didSelectRow:0 inComponent:0];
    }else
    {// 調(diào)用監(jiān)聽的方法 給時間的 textFile 賦值
        [self rollAction:_dateKB];
    }
}

#pragma mark ------>> 監(jiān)聽滾動的方法   滾動日期鍵盤時候走的方法<<------
- (void)rollAction:(UIDatePicker *)sender
{
    // 格式化日期格式
    NSDateFormatter *formatter = [NSDateFormatter new];
   // 設(shè)置顯示的格式     這里的格式 2016 / 08 / 08
    [formatter setDateFormat:@"YYYY / MM / dd"];
   // UIDatePicker 滾動也就是日期改變 我們就改變對應(yīng)的 textFile 的 text
    self.timeField.text = [formatter stringFromDate:sender.date];

}

下面是實(shí)現(xiàn) 地址的輸入一些方法 先把 UIPickerView 的代理方法完成

#pragma mark ------>> UIPickView 的協(xié)議方法  編輯鍵盤 <<------
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
     NSLog(@"返回列數(shù)!");
    return 3;
}

#pragma mark ------>> 每個組件的 row 數(shù)量 <<------
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
// 先找到選中的省份
    NSInteger indexP = self.provinceCurrentIndex;
    province_Model *modelP = self.allProvinceArray[indexP];
    
    switch (component) {
        case 0:
           return self.allProvinceArray.count;
            break;
        case 1:
        {// 根據(jù)第 0 列選中省 得到對應(yīng)的城市數(shù)組
           return modelP.cityArray.count;
        }
            break;
        case 2:
        {// 根據(jù)第 1 列選中城市  找到縣級的數(shù)組
            city_Model *modelC = modelP.cityArray[_cityCurrentIndex];
           return  modelC.countyArray.count;
        }
            break;
            
        default:
            return 0;
            break;
    }
    

}
#pragma mark ------>> 當(dāng)我們滑動列選中某一個 row 的時候  要更新視圖 讓與之相關(guān)的列更新 <<------
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
    NSLog(@"滾動了第 %ld 列 ",component);
    switch (component) {
        case 0:
      // 滑動了第 0 列 更新后兩列
            self.provinceCurrentIndex = [pickerView selectedRowInComponent:0];
            [pickerView reloadComponent:1];
            [pickerView selectRow:0 inComponent:1 animated:YES];
            self.cityCurrentIndex = 0;
            [pickerView reloadComponent:2];
            [pickerView selectRow:0 inComponent:2 animated:YES];
         break;
        
        case 1:
      // 滑動了第 1 列 更新最后一列
            self.cityCurrentIndex = [pickerView selectedRowInComponent:1];
            [pickerView reloadComponent:2];
            [pickerView selectRow:0 inComponent:2 animated:YES];
            self.countyCurrenIndex = 0;
            break;
        
        case 2:
            self.countyCurrenIndex = [pickerView selectedRowInComponent:2];
            break;
  
        default:
            break;
    }


    // 當(dāng)前選中的 省份
    province_Model *modelP = self.allProvinceArray[_provinceCurrentIndex];
    // 當(dāng)前的選中的 城市
    city_Model *modelC = modelP.cityArray[_cityCurrentIndex];
    // 當(dāng)前選中 縣城
    NSString *countyStr = [NSString new];
    if (_countyCurrenIndex >= modelC.countyArray.count)
    {
        countyStr = modelC.countyArray[0];
        [pickerView selectRow:0 inComponent:2 animated:YES];
    }else
    {
       countyStr = modelC.countyArray[_countyCurrenIndex];
    }
    // 給 addressFiled 賦值
    self.addressFiled.text = [NSString stringWithFormat:@"%@  %@  %@",modelP.provinceName, modelC.cityName, countyStr];
}
#pragma mark ------>> PickerView 顯示的內(nèi)容 <<------
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    // 獲取第 0 列選中的省份  那么后面的城市就是這個省份的城市數(shù)組里面的
    NSInteger indexP = self.provinceCurrentIndex;
    province_Model *modelP = self.allProvinceArray[indexP];
   
    // 創(chuàng)建 UILabel 用于顯示每一個 row 上面的內(nèi)容
    UILabel *label = [UILabel new];
    label.adjustsFontSizeToFitWidth = YES;
    
    switch (component) {
        case 0:
        {// 第 0 列 顯示省份
            label.text =  [self.allProvinceArray[row] provinceName];
        }
            break;
        case 1:
        {// 根據(jù)第 0 選中的省份 來確定第 1 列顯示城市
            label.text =  [modelP.cityArray[row] cityName];
        }
            break;
        case 2:
        {// 根據(jù)第 1 列選中城市  找到縣級的數(shù)組 返回對應(yīng)的下標(biāo)的縣名
       //     NSInteger indexCity = [pickerView selectedRowInComponent:1];
            
            label.text =  [modelP.cityArray[_cityCurrentIndex] countyArray][row];
        }
            break;
            
        default:
            label.text = @"其他";
            break;
    }
    return label;
}```







最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 選擇器,我想大家都不陌生,當(dāng)需要用戶去選擇某些范圍值內(nèi)的一個固定值時,我們會采用選擇器的方式。選擇器可以直觀的提示...
    若錦閱讀 16,231評論 49 90
  • 《午后》是一篇小說。算是吧,沒怎么寫過。 寫這篇小說很費(fèi)勁,從2006年開始構(gòu)思,后來開始落筆,寫了一年多...
    靜石閱讀 389評論 0 1
  • 格瑞斯是一個不?;丶业闹魅?,32歲,獨(dú)居,家里有畫室,烘焙區(qū),衣帽間里最多的是包包,房子坐落在一座古樸的公寓里,房...
    夕子故事鋪閱讀 808評論 0 0
  • 西藏,在我心中一直是一個特別神秘的地方。據(jù)說每一個藏族人都很向往。 今年總算是有時間,去到那個地方。我的內(nèi)心是激動...
    聽聞你在漠北孤城閱讀 193評論 0 1
  • 不管怎么說,這部最新的《金剛》電影還是比我預(yù)想中的好看,在越南取的景確實(shí)很美,至少比之前的新鮮,大金剛也足夠兇猛,...
    年少影追閱讀 513評論 0 0

友情鏈接更多精彩內(nèi)容