IOS提供了日期选择器UIDatePicker,它可以实现对日期的选择。日期选择器有4种模式:日期、日期和时间、时间和倒计时定时器。日期选择器使用比较简单,这里我们就不去实现它了。
有的时候我们可能需要输入除了日期之外的其他内容,比如籍贯等。IOS为我们提供了UIPickerView,它是UIDatePicker的父类。UIPickerView是非常灵活的,它的滚轮可以设定,每一个滚轮的内容也可以设定。与UIDatePicker不同的是,UIPickerView需要两个非常重要的协议——UIPickerViewDelegate和UIPickerViewDataSource。
这里我们简单实现一个省和市联动的选择器。有两个滚轮,一个选择省,一个选择市。选择省,列出相应的市;选定后把联动结果用label显示出来。
在实现之前我们需要建立数据,我们用plist文件保存数据:
需求比较简单,直接贴代码(基于storyboard和ARC)。
ViewController.h相关代码:
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController<UIPickerViewDataSource,UIPickerViewDelegate>
@property (weak, nonatomic) IBOutlet UILabel *selectedLabel;
@property (weak, nonatomic) IBOutlet UIPickerView *pickerView;
@property (strong,nonatomic) NSDictionary *pickerData;
@property (strong,nonatomic) NSArray *pickerProvincesData;
@property (strong,nonatomic) NSArray *pickerCitiesData;
@end
这里的pickerData用于保存所有的数据,pickerProvincesData用于保存“省”数据,pickerCitiesData用于保存“市”数据。
ViewController.m相关代码:
#import "ViewController.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
self.pickerView.delegate=self;
self.pickerView.dataSource=self;
//获取所有数据
NSString *dataPath=[[NSBundle mainBundle] pathForResource:@"provinces_cities" ofType:@"plist"];
self.pickerData=[NSDictionary dictionaryWithContentsOfFile:dataPath];
//省数据
self.pickerProvincesData=[self.pickerData allKeys];
//默认显示第一个省得市
self.pickerCitiesData=[self.pickerData objectForKey:[self.pickerProvincesData objectAtIndex:0]];
[self showSelected];
}
//UIPickerViewDataSource
//选择器中拨轮的数目
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
//UIPickerViewDataSource
//选择器中某个拨轮的行数
-(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if(component==0){//省
return [self.pickerProvincesData count];
}else{//市
return [self.pickerCitiesData count];
}
}
//UIPickerViewDelegate
//选中选择器中某个拨轮的某行时触发
-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if(component==0){//选中省时显示对应的市
NSString *province=[self.pickerProvincesData objectAtIndex:row];
NSArray *cities=[self.pickerData objectForKey:province];
self.pickerCitiesData=cities;
//重新加载市的数据
[self.pickerView reloadComponent:1];
}
[self showSelected];
}
//UIPickerViewDelegate
//选择器中某个拨轮的某行显示的数据
-(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
if(component==0){
return [self.pickerProvincesData objectAtIndex:row];
}else{
return [self.pickerCitiesData objectAtIndex:row];
}
}
-(void)showSelected
{
NSInteger provinceRow=[self.pickerView selectedRowInComponent:0];
NSInteger cityRow=[self.pickerView selectedRowInComponent:1];
NSString *str=[NSString stringWithFormat:@"%@:%@",[self.pickerProvincesData objectAtIndex:provinceRow],[self.pickerCitiesData objectAtIndex:cityRow]];
self.selectedLabel.text=str;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
与UITextField等简单控件不同的是,UIPickerView除了委托协议外,还有数据源协议。数据源和委托的角色不同:委托对象负责控制控件外观,如选择器的宽度、选择器的行高等信息,此外,还负责对控件的事件和状态变化做出反应。数据源对象是控件与应用数据的桥梁,如选择器的行数、滚轮数等信息。
数据源协议中(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView和
(NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component方法是必须要实现的。
代理协议中我们通常只需要实现下面两个常用的方法即可,
(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;
(NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component