目录
PickerView
IOS中PickerView包括UIDatePicker和UIPickerView,UIPickerView和UIDatePicker没有父子关系,他们是各自单独分开的。
当打开控件对象库输入“picker”的时候会出现Date Picker和Picker View两个对象供选择:
1 UIDatePicker
1.1 UIDatePicker的四种模式
UIDatePicker是日期选择器,有4种类型,可以通过修改Mode来选不同的类型,
1.1.1 日期模式
1.1.2 时间模式
1.1.3 日期时间模式
1.1.4 倒计时定时器模式
1.1.5 UIDatePicker属性
在Interface Builder中选中UIDatePicker后,从其属性选择器中可以看到它的相关属性
Mode:设置如期选择器的4中模式
Local:做本地化,选择国家
Interval:设定间隔时间,单位分钟。可以看到下面设定间隔为1分钟和30分钟的效果图是不一样的
Date:设定初始化的时间,默认是当前时间和日期,如果选择Custom自定的话,下面三个当前值、最大值、最小值需要设定
Timer:倒计时定时器模式下设置倒计时的秒数
1.2 实例应用
1.2.1 实例需求
按照下面布局,但点击按钮的时候在UILabelView上显示选择的时间
1.2.2 源码
#import "ViewController.h"
@interface ViewController ()
@property (strong, nonatomic) IBOutlet UIDatePicker *datePicker;
@property (strong, nonatomic) IBOutlet UILabel *labelView;
@property (strong, nonatomic) IBOutlet UIButton *pickerButton;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//给按钮添加点击事件
[self.pickerButton addTarget:self action:@selector(onClickButton:) forControlEvents:UIControlEventTouchDown];
}
- (IBAction)onClickButton:(id)sender {
NSDate *date = self.datePicker.date;//取出UIDatePicker的时间
NSLog(@"The date is:%@",[date descriptionWithLocale:[NSLocale currentLocale]]);
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
dateFormat.dateFormat = @"YYYY-MM-dd HH:mm:ss";
NSString *dateString = [dateFormat stringFromDate:date];
NSLog(@"formate date is:%@", dateString);
self.labelView.text = dateString;
}
@end
1.2.3 测试
1.2.4 github地址
https://github.com/cmyeyi/UIDatePicker.git
UIPickerView
2.1 UIPickerView介绍
除了日期时间之外,我们有时候还需要做别的内容的选择,比如地区选择:省-市-区,(湖北省-武汉市-汉口区),比如学校选择:北京大学-工商管理系。由于时间选择是比较复杂的,IOS系统提供了UIDatePicker,但是和UIPickerView没有父子关系,UIPickerView选择器更加通用,栏目数和内容都是可以自定义的,但是必须遵循很重要的两个协议UIPickerViewDelegate和UIPickerViewDataSource。
2.2 UIPickerView实例学习
2.2.1需求
为了简单起见,我们根据省市二级联动来设计实例,这里省市数据没有,我们设计一个类似的:
A
A-1、A-2
2.2.1 布局
布局最后效果如下:
2.2.2 创建plist资源文件
很重要先注意:
重要的事情提前说,很多初学者在通过上面添加plist文件的时候,添加出错最重要的一个原因就是因为给某一个Array添加item的时候没有先点开其前面的三角符号向下,然后导致点击+增加项目的时候添加的是同级别的项目。
New files > Resource > Property List 命名为provinces
打开文件添加信息,当鼠标点击在Root上会出现一个+,点击+添加一级菜单A、B、C、D、E、F、G、H,然后点击A后面的Type属性,点击String,弹出对话框选择Array,
先点击A、B、C、D、E、F、G、H前面的三角形,点击指向下面的时候,再点击后面的+,给一级菜单增加项目[A1、A2、A3、A4......]、[B1、B2、B3、B4......]等,
注意如果不是将Type设置Array属性,不把一级目录前面三角形点击向下,点击加号增加的项目就是同级别的,增加好的数据如下图:
如果这个数据不正确的话,运行就会报错。
重要的事情在说一遍,很多初学者在通过上面添加plist文件的时候,添加出错最重要的一个原因就是因为给某一个Array添加item的时候没有先点开其前面的三角符号向下,然后导致点击+增加项目的时候添加的是同级别的项目。
2.2.3 实例代码
根据Inteface Builder在故事板布局好了之后,通过拖拽连线的方式生成pickerView、labelView和button的引用变量备用,然后再定义属性:allData(全部数据字典的内容)、level1(以及目录数据)、level2(二级目录数据)
然后最重要的是分配UIPickerViewDataSource,UIPickerViewDelegate这两个协议,
通过代码分配:
self.pickerView.dataSource = self;
self.pickerView.delegate = self;
或者Inteface Builder连线分配,这种方式这里不讲,用代码比较直观点。
具体代码如下:
#import "ViewController.h"
@interface ViewController ()<UIPickerViewDataSource,UIPickerViewDelegate>
@property (strong, nonatomic) IBOutlet UIPickerView *pickerView;
@property (strong, nonatomic) IBOutlet UILabel *labelView;
@property (strong, nonatomic) IBOutlet UIButton *button;
@property (strong, nonatomic) NSDictionary *allData;
@property (strong, nonatomic) NSArray *level1;//一级目录数据
@property (strong, nonatomic) NSArray *level2;//二级目录数据
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//将委托协议和数据源协议分配给pickerView
self.pickerView.dataSource = self;
self.pickerView.delegate = self;
[self initData];
[self.button addTarget:self action:@selector(onCLickButton:) forControlEvents:UIControlEventTouchDown];
}
- (IBAction)onCLickButton:(id)sender {
NSInteger row1 = [self.pickerView selectedRowInComponent:0];
NSInteger row2 = [self.pickerView selectedRowInComponent:1];
NSString *seleted1 = [self.level1 objectAtIndex:row1];
NSString *seleted2 = [self.level2 objectAtIndex:row2];
NSString *title = [[NSString alloc]initWithFormat:@"%@ | %@", seleted1, seleted2];
self.labelView.text = title;
}
- (void)initData {
//获取资源文件路径
NSString *plistPath = [[NSBundle mainBundle]pathForResource:@"provinces" ofType:@"plist"];
//获取资源文件中的全部数据
NSDictionary *dictionary = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
self.allData = dictionary;
//获取一级数据
self.level1 = [self.allData allKeys];
//获取第一个一级单位下的数据
NSString *seletedLevel1 = [self.level1 objectAtIndex:0];
self.level2 = [self.allData objectForKey:seletedLevel1];
}
#pragma mark 实现UIPickerViewDataSource协议
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
}
- (NSInteger) pickerView:(nonnull UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
if(component == 0) {
return [self.level1 count];
} else {
return [self.level2 count];
}
}
#pragma mark 实现UIPickerViewDelegate协议
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if(component == 0) {
return [self.level1 objectAtIndex:row];
} else {
return [self.level2 objectAtIndex:row];
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if(component == 0) {
NSString *seletedP1 = [self.level1 objectAtIndex:row];
NSArray *array = [self.allData objectForKey:seletedP1];
self.level2 = array;
[self.pickerView reloadComponent:1];
}
}
@end
测试效果:
2.2.4 实例代码分析
上面代码最重要的是对两个协议的实现,也就是UIPickerViewDataSource和UIPickerViewDelegate,有关协议的知识点,这里暂时不需要深入,可以理解为高级控件在数据加载时候以及绘制的过程中回调的一些方法,有的方法用来给控件提供数据,有的方法是用户和控件交互之后回调的接口,特别是android开发者对于这点应该有很深刻的理解,比如ListView在加载数据的过程中会回调一些必要的方法,壮哉数据,渲染界面,点击反馈等!
2.2.5 UIPickerViewDelegate
UIPickerViewDelegate主要是实现下面两个方法,一个是显示赋值用,一个是选择中的回调。
#pragma mark 实现UIPickerViewDelegate协议
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
if(component == 0) {
return [self.level1 objectAtIndex:row];
} else {
return [self.level2 objectAtIndex:row];
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
if(component == 0) {
NSString *seletedP1 = [self.level1 objectAtIndex:row];
NSArray *array = [self.allData objectForKey:seletedP1];
self.level2 = array;
[self.pickerView reloadComponent:1];
}
}
2.2.6 UIPickerViewDataSource
UIPickerViewDataSource主要是实现下面两个方法,numberOfComponentsInPickerView返回的2表示PickerView显示的是两列,另一个方法返回的每个row的数量
#pragma mark 实现UIPickerViewDataSource协议
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
}
- (NSInteger) pickerView:(nonnull UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
if(component == 0) {
return [self.level1 count];
} else {
return [self.level2 count];
}
}
2.2.7 UIPickerView实例地址
实例github上的地址:https://github.com/cmyeyi/UIPickerView.git
可下载下来对照学习更方便