UI--UIPickerView和UIDatePicker的总结

UIPickerView的主要方法和城市选择器的修正

UIPickerView只有两个数据源方法.要想完整地显示出PickerView,需要结合使用代理方法 数据源方法:

// 一共有多少组(列)

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView



// 每列有多少行,传入的参数component是对应的列

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component

UIPickerView的代理方法:

// 告诉系统每一行显示什么数据  通常可以结合switch case使用的

- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component; 



// 监听pickerView的点击事件

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;

一些其他的常用方法

// pickerView的对象方法,选择指定列的指定行

- (void)selectRow:(NSInteger)row inComponent:(NSInteger)component animated:(BOOL)animated



// 对象方法,获取指定列的当前选择的行的行号,如果没有选中任何行 就会返回-1

- (NSInteger)selectedRowInComponent:(NSInteger)component;

城市选择程序中同时修改省份和城市的时候,会造成程序崩溃的原因和修改方案:

在 这个项目中最容易出问题的地方是:每次选择器在变化的过程中,注意是变化的过程中,会不断地调用下面两个方法
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
在这两个方法中,若是用这个方法以下方法获取当前被选中的项
- (NSInteger)selectedRowInComponent:
这个方法返回的的值是变化的,因此若根据这个值计算com1的选中项的索引,很容易造成数组越界。 因此我的解决方案是用成员变量这个值。每次didSelected时,也就是已经确定值之后,改变这个固定的值。

1.首先增加类的成员属性selectedRowOfComp1

2.在计算第二列也就是"城市"列的列数的时候按照成员属性存储的选择的第一行进行计算。在pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component

if (component == 0) {

    return self.provinces.count;

}

MKProvince *p = self.provinces[self.selectedRowOfComp1];

return p.cities.count;

由此每行需要显示数据的方法中也做了改动:
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{

    if (component == 0) {

        MKProvince *p = self.provinces[row];

        return p.name;

    } else {

        MKProvince *p = self.provinces[self.selectedRowOfComp1];

        return p.cities[row];

    }

}

3.当省份部分的数据选定之后,要修改成员属性,并且刷新城市部分的数据。在label中要显示的城市和省份也是根据成员属性值来计算的:

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{

    if (component == 0) {

        MKProvince *p = self.provinces[row];

        // 改变lbl的显示

        self.lblProvince.text = p.name;

        

        // 改变城市组的显示

        self.selectedRowOfComp1 = row;

        [pickerView reloadComponent:1]; // 这句话一定要在self.selectedRowOfComp1 = row;之后。  reloadComponent:1重新加载component1但是不会改变已经选中的行号,因此可能会造成已经选中的是第二行,对于省份变成重庆这样的只有一个市的省份可能会引起bug,但是不会的,因为像这样的情况reload会将城市的数据显示为第一行

        // 更新lblCity的数据

        NSInteger cityIndex = [pickerView selectedRowInComponent:1];

        self.lblCity.text = p.cities[cityIndex];// 上一句使得component1更新,这句保证了lbl和component1数据一致

    } else {

        MKProvince *p = self.provinces[self.selectedRowOfComp1];

        // 改变lbl的显示

        self.lblCity.text = p.cities[row];

    }

}

UIDatePicker的使用,并抽取为工具类

创建一个UIDatePicker

// 先创建dataPicker

CGFloat width = [UIScreen mainScreen].bounds.size.width;

UIDatePicker *datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, width, 180)];

datePicker.locale = [NSLocale localeWithLocaleIdentifier:@"zh-Hans"]; // 设置默认的地区

datePicker.datePickerMode = UIDatePickerModeDate; // 设置输入的模式是日期

self.datePicker = datePicker; // 设置为控制器的属性

self.txtTime.inputView = self.datePicker; // 将datePicker设置为textField控件的输入器



// DatePicker输入器的附属view

UIToolbar *toolbar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, width, 44)];

UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"上一个" style:UIBarButtonItemStylePlain target:self action:@selector(previous)];

UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"下一个" style:UIBarButtonItemStylePlain target:self action:@selector(next)];

UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

UIBarButtonItem *item4 = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStyleDone target:self action:@selector(done)]; // 设置完成的监听事件



toolbar.items = @[item1, item2, item3, item4]; 



self.txtTime.inputAccessoryView = toolbar; // 将toolbar设置为textField的输入器附属view

处理输入完成后done按钮的点击事件

- (void)done{

    [self.view endEditing:YES];

    // 将选择的日期格式化

    NSDate *date = self.datePicker.date;

    NSDateFormatter *fmt = [[NSDateFormatter alloc]init];

    fmt.dateFormat = @"yyyy年MM月dd日";

    NSString *dateStr = [fmt stringFromDate:date];

    // 将格式化后的字符串赋值给textField

    self.txtTime.text = dateStr; 

}

抽取为工具类

创建工具类MKToolDatePicker,在MKToolDatePicker.h中

#import "MKTool.h"



@class UITextField;





@protocol MKToolDatePickerDelegate;

/**

 *  创建后需要强引用这个类

 */

@interface MKToolDatePicker : MKTool

/**

 *  指定要设置的UITextField控件

 */

@property (nonatomic, weak) id delegate;

- (void)datePickerOnTextField:(UITextField *)textField;

@end



@protocol MKToolDatePickerDelegate 

/**

 *  当点击了时间选择器的"完成"按钮,并且代理类(一般为控制器)已经实现了该方法的时候调用,用于处理选择的NSDate

 *

 *  @param toolDatePicker 工具类对象本本身

 *  @param textField      指定的textField

 *  @param date           点击"完成"之前选择的date

 */

- (void)toolDatePicker:(MKToolDatePicker *)toolDatePicker onView:(UITextField *)textField didClickedDoneWithDate:(NSDate *)date;

@end

在MKToolDatePicker.m中

#import "MKToolDatePicker.h"

#import <UIKit/UIDatePicker.h>

#import <UIKit/UIScreen.h>

#import <UIKit/UIToolbar.h>



@interface MKToolDatePicker ()

@property (nonatomic, strong) UIDatePicker *datePicker;

@property (nonatomic, strong) UIToolbar *toolBar;

@property (nonatomic, weak) UITextField *textField;

@end

@implementation MKToolDatePicker



- (UIDatePicker *)datePicker{

    if (!_datePicker) {

        

        // 先创建dataPicker

        CGFloat width = [UIScreen mainScreen].bounds.size.width;

        _datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake(0, 0, width, 180)];

        _datePicker.locale = [NSLocale localeWithLocaleIdentifier:@"zh-Hans"];

        _datePicker.datePickerMode = UIDatePickerModeDate;

    }

    return _datePicker;

}

- (UIToolbar *)toolBar{

    if (!_toolBar) {

        // 输入的附属view

        _toolBar = [[UIToolbar alloc]initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 44)];

        UIBarButtonItem *item1 = [[UIBarButtonItem alloc] initWithTitle:@"上一个" style:UIBarButtonItemStylePlain target:self action:@selector(previous)];

        UIBarButtonItem *item2 = [[UIBarButtonItem alloc] initWithTitle:@"下一个" style:UIBarButtonItemStylePlain target:self action:@selector(next)];

        UIBarButtonItem *item3 = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil];

        UIBarButtonItem *item4 = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStyleDone target:self action:@selector(done)];

        _toolBar.items = @[item1, item2, item3, item4];

    }

    return _toolBar;

}

- (void)datePickerOnTextField:(UITextField *)textField{

    self.textField = textField;

    textField.inputView = self.datePicker;

    

    textField.inputAccessoryView = self.toolBar;

}

- (void)done{

    [self.textField endEditing:YES];

    if ([self.delegate respondsToSelector:@selector(toolDatePicker:onView:didClickedDoneWithDate:)]) {

        [self.delegate toolDatePicker:self onView:self.textField didClickedDoneWithDate:self.datePicker.date];

    }    

}

在控制器中使用时间选择器工具类

#import "ViewController.h"

#import "MKToolDatePicker.h"

@interface ViewController () 

@property (weak, nonatomic) IBOutlet UITextField *txtTime;

// 强引用时间选择器工具

@property (nonatomic, strong) MKToolDatePicker *toolDatePicker;

@end



@implementation ViewController



- (void)viewDidLoad {

    [super viewDidLoad];

    

    MKToolDatePicker *tool = [[MKToolDatePicker alloc]init];

    self.toolDatePicker = tool;

    tool.delegate = self; // 设置代理

    [tool datePickerOnTextField:self.txtTime]; // 指定UITextView

}

// 根据onView的不同分别处理

- (void)toolDatePicker:(MKToolDatePicker *)toolDatePicker onView:(UITextField *)textField didClickedDoneWithDate:(NSDate *)date{

    NSDateFormatter *fmt = [[NSDateFormatter alloc]init];

    fmt.dateFormat = @"yyyy年MM月dd日";

    NSString *dateStr = [fmt stringFromDate:date];

    self.txtTime.text = dateStr;

}

@end

你可能感兴趣的:(Datepicker)