iOS自定義日期、時(shí)間、城市選擇器實(shí)例代碼
選擇器,我想大家都不陌生,當(dāng)需要用戶去選擇某些范圍值內(nèi)的一個(gè)固定值時(shí),我們會(huì)采用選擇器的方式。選擇器可以直觀的提示用戶選擇的值范圍、統(tǒng)一信息的填寫(xiě)格式,同時(shí)也方便用戶快速的進(jìn)行選擇,比如對(duì)于性別,正常情況下就只有男女兩種情況,那這時(shí)候用一個(gè)選擇器給用戶進(jìn)行選擇的話,可以避免錯(cuò)誤數(shù)據(jù)的輸入,也更方便用戶去填寫(xiě)。再比如需要獲取用戶的生日信息時(shí),采用選擇器的方式可以統(tǒng)一生日的格式,如果讓用戶自行輸入的話,可能會(huì)出現(xiàn)各種各樣的生日信息格式,不利于數(shù)據(jù)的存儲(chǔ),但是采用選擇器的方式的話,用戶可找到對(duì)應(yīng)的日期進(jìn)行選擇即可。
在iOS有專(zhuān)門(mén)的一個(gè)選擇器類(lèi)UIPickerView,進(jìn)入U(xiǎn)IPickerView的頭文件,我們可以發(fā)現(xiàn) UIPickerView直接繼承了UIView,其事件處理通過(guò)代理方法完成,所以創(chuàng)建UIPickerView的時(shí)候記得簽它的代理UIPickerViewDataSource和UIPickerViewDelegate。其實(shí)它和UITbleView有點(diǎn)像,不過(guò)UIPickerView還多了個(gè)列屬性,UITbleView我們都很熟了,所以可以對(duì)比UITbleView的相關(guān)屬性和代理方法來(lái)學(xué)習(xí)記憶UIPickerView。
一. UIPickerView的代理方法
(1)UIPickerViewDataSource對(duì)應(yīng)的代理方法有(其代理方法必須要實(shí)現(xiàn)):
返回顯示的列數(shù)
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView;
返回每一列中需要顯示的行數(shù)
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component;
(2)UIPickerViewDelegate對(duì)應(yīng)的代理方法(其代理方法根據(jù)需求進(jìn)行選擇性實(shí)現(xiàn)):
返回每一列的寬度
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component;
返回每一列的高度
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component ;
返回UIPickerView控件中指定列的列表項(xiàng)的要顯示的內(nèi)容
- (nullable NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component ;
返回UIView,作為該UIPickerView控件中指定列的指定行的顯示視圖
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view ;
選擇指定列中的指定行
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component ;
二、UIPickerView和UIDatePicker。
UIDatePicker是系統(tǒng)幫我們封裝好的一個(gè)時(shí)間日期選擇器,繼承于UIControl,UIDatePicker有一定的局限性,因?yàn)樗挥兴姆N顯示樣式:
UIDatePickerModeTime, UIDatePickerModeDate, UIDatePickerModeDateAndTime, UIDatePickerModeCountDownTimer,
如果需求和這四種樣式都不符合的話,那么就沒(méi)辦法使用UIDatePicker,比如當(dāng)只需要顯示年、月信息的時(shí)候,顯然UIDatePicker沒(méi)辦法滿足我們的需求,那這時(shí)我們只能通過(guò)UIPickerView來(lái)自定義自己想要的選擇器。
三、UIPickerView的自定義使用
(1)創(chuàng)建基類(lèi)繼承于UIView的WXZBasePickView。
我們常見(jiàn)的選擇器的樣式是一個(gè)帶透明背景色的view,底部是內(nèi)容的選擇器,有確定和取消按鈕,大致如圖:

所以我們創(chuàng)建一個(gè)基類(lèi)view,這個(gè)view的樣式如圖所示樣式,之后根據(jù)內(nèi)容的差別創(chuàng)建基于該view的選擇器。
在.h中聲明各個(gè)屬性及方法
#import <UIKit/UIKit.h> @interface WXZBasePickView : UIView @property (nonatomic, strong) UIView *contentView; //選擇器 @property (nonatomic, strong)UIPickerView *pickerView; //取消按鈕 @property (nonatomic, strong)UIButton *cancelButton; //確定按鈕 @property (nonatomic, strong)UIButton *confirmButton; //選擇器每一列的高度 @property (nonatomic, assign)CGFloat pickerViewHeight; /** * 創(chuàng)建視圖,初始化視圖時(shí)初始數(shù)據(jù) */ - (void)initPickView; /** * 確認(rèn)按鈕的點(diǎn)擊事件 */ - (void)clickConfirmButton; /** * pickerView的顯示 */ - (void)show; /** * 移除pickerView */ - (void)disMiss; @end
在.m中實(shí)現(xiàn)相關(guān)方法
#import "WXZBasePickView.h"
#define ScreenWidth [UIScreen mainScreen].bounds.size.width
#define ScreenHeight [UIScreen mainScreen].bounds.size.height
@implementation WXZBasePickView
- (instancetype)init
{
self = [super init];
if (self) {
_pickerViewHeight = 250;
self.bounds = [UIScreen mainScreen].bounds;
self.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.64];
self.layer.opacity = 0.0;
UITapGestureRecognizer *tap=[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(disMiss)];
self.userInteractionEnabled = YES;
[self addGestureRecognizer:tap];
[self addSubview:self.contentView];
[self.contentView addSubview:self.pickerView];
[self.contentView addSubview:self.cancelButton];
[self.contentView addSubview:self.confirmButton];
[self initPickView];
}
return self;
}
//初始化選擇器內(nèi)容,創(chuàng)建子類(lèi)時(shí)需實(shí)現(xiàn)該父類(lèi)方法
-(void)initPickView{
}
//點(diǎn)擊確定按鈕
- (void)clickConfirmButton
{
[self disMiss];
}
//點(diǎn)擊取消按鈕
- (void) clickCancelButton
{
[self disMiss];
}
//顯示選擇器
- (void)show
{
[[UIApplication sharedApplication].keyWindow addSubview:self];
[self setCenter:[UIApplication sharedApplication].keyWindow.center];
[[UIApplication sharedApplication].keyWindow bringSubviewToFront:self];
CGRect frame = self.contentView.frame;
frame.origin.y -= self.contentView.frame.size.height;
[UIView animateWithDuration:0.4 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.layer setOpacity:1.0];
self.contentView.frame = frame;
} completion:^(BOOL finished) {
}];
}
//移除選擇器
- (void)disMiss
{
CGRect frame = self.contentView.frame;
frame.origin.y += self.contentView.frame.size.height;
[UIView animateWithDuration:0.4 delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{
[self.layer setOpacity:0.0];
self.contentView.frame = frame;
} completion:^(BOOL finished) {
[self removeFromSuperview];
}];
}
//設(shè)置選擇器的高度
- (void)setPickerViewHeight:(CGFloat)pickerViewHeight
{
_pickerViewHeight = pickerViewHeight;
self.contentView.frame = CGRectMake(self.contentView.frame.origin.x, self.contentView.frame.origin.y, self.contentView.frame.size.width, pickerViewHeight);
}
- (UIView *)contentView
{
if (!_contentView) {
_contentView = [[UIView alloc]initWithFrame:CGRectMake(0, ScreenHeight, ScreenWidth, self.pickerViewHeight)];
[_contentView setBackgroundColor:[UIColor whiteColor]];
}
return _contentView;
}
- (UIPickerView *)pickerView
{
if (!_pickerView) {
_pickerView = [[UIPickerView alloc]initWithFrame:CGRectMake(0, 0, self.contentView.frame.size.width, self.contentView.frame.size.height)];
[_pickerView setBackgroundColor:[UIColor whiteColor]];
}
return _pickerView;
}
- (UIButton *)cancelButton
{
if (!_cancelButton) {
_cancelButton = [[UIButton alloc]initWithFrame:CGRectMake(16, 0, 44, 44)];
[_cancelButton setTitle:@"取消" forState:UIControlStateNormal];
[_cancelButton setTitleColor:[UIColor grayColor] forState:UIControlStateNormal];
[_cancelButton.titleLabel setFont:[UIFont systemFontOfSize:16]];
[_cancelButton addTarget:self action:@selector(clickCancelButton) forControlEvents:UIControlEventTouchUpInside];
}
return _cancelButton;
}
- (UIButton *)confirmButton
{
if (!_confirmButton) {
_confirmButton = [[UIButton alloc]initWithFrame:CGRectMake(self.contentView.frame.size.width - self.cancelButton.frame.size.width - self.cancelButton.frame.origin.x, self.cancelButton.frame.origin.y, self.cancelButton.frame.size.width, self.cancelButton.frame.size.height)];
[_confirmButton setTitle:@"確定" forState:UIControlStateNormal];
[_confirmButton setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[_confirmButton.titleLabel setFont:[UIFont systemFontOfSize:16]];
[_confirmButton addTarget:self action:@selector(clickConfirmButton) forControlEvents:UIControlEventTouchUpInside];
}
return _confirmButton;
}
@end
(2)、自定義一個(gè)日期選擇器,可選擇顯示年、月或者年、月、日以及是否顯示“至今”選項(xiàng)。
創(chuàng)建繼承于我們自定義好的WXZBasePickView的日期選擇器WXZPickDateView
.h聲明相關(guān)屬性和方法
#import "WXZBasePickView.h" @class WXZBasePickView; //選擇器的選擇代理方法 @protocol PickerDateViewDelegate<NSObject> - (void)pickerDateView:(WXZBasePickView *)pickerDateView selectYear:(NSInteger)year selectMonth:(NSInteger)month selectDay:(NSInteger)day; @end @interface WXZPickDateView : WXZBasePickView @property(nonatomic, weak)id <PickerDateViewDelegate>delegate ; @property(nonatomic, assign)BOOL isAddYetSelect;//是否增加至今的選項(xiàng) @property(nonatomic, assign)BOOL isShowDay;//是否顯示日 //設(shè)置默認(rèn)顯示的值 -(void)setDefaultTSelectYear:(NSInteger)defaultSelectYear defaultSelectMonth:(NSInteger)defaultSelectMonth defaultSelectDay:(NSInteger)defaultSelectDay; @end
.m實(shí)現(xiàn)相關(guān)方法
#import "WXZPickDateView.h"
@interface WXZPickDateView()<UIPickerViewDataSource, UIPickerViewDelegate>
/** 選擇的年 */
@property (nonatomic, assign)NSInteger selectYear;
/** 選擇的月 */
@property (nonatomic, assign)NSInteger selectMonth;
/** 選擇的日 */
@property (nonatomic, assign)NSInteger selectDay;
@property (nonatomic, assign)NSInteger currentYear;
@property (nonatomic, assign)NSInteger currentMonth;
@property (nonatomic, assign)NSInteger currentDay;
@property (nonatomic, assign)NSInteger defaultYear;
@property (nonatomic, assign)NSInteger defaultMonth;
@property (nonatomic, assign)NSInteger defaultDay;
@property (nonatomic, assign)NSInteger minShowYear;
@property (nonatomic, assign)NSInteger yearSum;
@end
@implementation WXZPickDateView
- (void)initPickView
{
[super initPickView];
_minShowYear = 1940;//最小年份
NSCalendar *gregorian = [[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
// 獲取當(dāng)前日期
NSDate* dt = [NSDate date];
// 指定獲取指定年、月、日、時(shí)、分、秒的信息
unsigned unitFlags = NSCalendarUnitYear |
NSCalendarUnitMonth | NSCalendarUnitDay |
NSCalendarUnitHour | NSCalendarUnitMinute |
NSCalendarUnitSecond | NSCalendarUnitWeekday;
// 獲取不同時(shí)間字段的信息
NSDateComponents* comp = [gregorian components: unitFlags fromDate:dt];
_yearSum = comp.year-_minShowYear+1;
_currentYear=comp.year;
_currentMonth=comp.month;
_currentDay=comp.day;
_selectYear = comp.year;
_selectMonth = comp.month;
_selectDay = comp.day;
_defaultYear = comp.year;
_defaultMonth = comp.month;
_defaultDay=comp.day;
[self.pickerView setDelegate:self];
[self.pickerView setDataSource:self];
}
-(void)setDefaultTSelectYear:(NSInteger)defaultSelectYear defaultSelectMonth:(NSInteger)defaultSelectMonth defaultSelectDay:(NSInteger)defaultSelectDay{
if (defaultSelectYear!=0) {
_defaultYear=defaultSelectYear;
}
if (defaultSelectMonth!=0) {
_defaultMonth = defaultSelectMonth;
}
if (defaultSelectDay!=0) {
_defaultDay=defaultSelectDay;
}
if (defaultSelectYear==-1) {
_defaultYear=_currentYear+1;
_defaultMonth=1;
_defaultDay=1;
}
[self.pickerView selectRow:(_defaultYear - _minShowYear) inComponent:0 animated:NO];
[self.pickerView reloadComponent:1];
[self.pickerView selectRow:(_defaultMonth - 1) inComponent:1 animated:NO];
if (_isShowDay==YES) {
[self.pickerView reloadComponent:2];
[self.pickerView selectRow:_defaultDay inComponent:1 animated:NO];
}
[self refreshPickViewData];
}
-(void)setIsAddYetSelect:(BOOL)isAddYetSelect{
_isAddYetSelect = isAddYetSelect;
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
//判斷是否要顯示日,如果顯示則返回3列,反之返回2列
if (_isShowDay==YES) {
return 3;
}else{
return 2;
}
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == 0) {
if (_isAddYetSelect==YES) {
//顯示至今選項(xiàng)的話,需要比總共要顯示的年份多返回一行
return self.yearSum+1;
}else{
return self.yearSum;
}
}else if(component == 1) {
NSInteger yearSelected = [pickerView selectedRowInComponent:0] + self.minShowYear;
if (yearSelected==_currentYear+1) {
//至今選項(xiàng)的時(shí)候月份信息不返回
return 0;
}else{
return 12;
}
}else {
NSInteger yearSelected = [pickerView selectedRowInComponent:0] + self.minShowYear;
if (yearSelected==_currentYear+1) {
//至今選項(xiàng)的時(shí)候日信息不返回
return 0;
}else{
NSInteger yearSelected = [pickerView selectedRowInComponent:0] + self.minShowYear;
NSInteger monthSelected = [pickerView selectedRowInComponent:1] + 1;
return [self getDaysWithYear:yearSelected month:monthSelected];
}
}
}
//根據(jù)年、月判斷日期天數(shù)
- (NSInteger)getDaysWithYear:(NSInteger)year
month:(NSInteger)month
{
switch (month) {
case 1:
return 31;
break;
case 2:
if (year%400==0 || (year%100!=0 && year%4 == 0)) {
return 29;
}else{
return 28;
}
break;
case 3:
return 31;
break;
case 4:
return 30;
break;
case 5:
return 31;
break;
case 6:
return 30;
break;
case 7:
return 31;
break;
case 8:
return 31;
break;
case 9:
return 30;
break;
case 10:
return 31;
break;
case 11:
return 30;
break;
case 12:
return 31;
break;
default:
return 0;
break;
}
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
//每一行的高度
return 36;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
NSInteger selectYear;
NSInteger selectMonth;
switch (component) {
case 0:
[pickerView reloadComponent:1];
if (_isAddYetSelect==YES) {
selectYear = row+_minShowYear+1;
}else{
selectYear = row+_minShowYear;
}
if (_isShowDay==YES) {
[pickerView reloadComponent:2];
}
break;
case 1:
selectMonth = row+1;
if (_isShowDay==YES) {
[pickerView reloadComponent:2];
}
default:
break;
}
[self refreshPickViewData];
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view
{
NSString *text;
if (component == 0) {
if (_isAddYetSelect==YES) {
if (row+_minShowYear==_currentYear+1) {
text=@"至今";
}else{
text = [NSString stringWithFormat:@"%zd年", row + _minShowYear];
}
}else{
text = [NSString stringWithFormat:@"%zd年", row + _minShowYear];
}
}else if (component == 1){
if (_isAddYetSelect==YES) {
NSInteger yearSelected = [pickerView selectedRowInComponent:0] + self.minShowYear;
if (yearSelected==_currentYear+1) {
text = [NSString stringWithFormat:@""];
}else{
text = [NSString stringWithFormat:@"%zd月", row + 1];
}
}else{
text = [NSString stringWithFormat:@"%zd月", row + 1];
}
}else{
text = [NSString stringWithFormat:@"%zd日", row + 1];
}
UILabel *label = [[UILabel alloc]init];
label.textAlignment = 1;
label.font = [UIFont systemFontOfSize:16];
label.text = text;
return label;
}
- (void)clickConfirmButton
{
if ([self.delegate respondsToSelector:@selector(pickerDateView:selectYear:selectMonth:selectDay:)]) {
[self.delegate pickerDateView:self selectYear:self.selectYear selectMonth:self.selectMonth selectDay:self.selectDay];
}
[super clickConfirmButton];
}
- (void)refreshPickViewData
{
self.selectYear = [self.pickerView selectedRowInComponent:0] + self.minShowYear;
self.selectMonth = [self.pickerView selectedRowInComponent:1] + 1;
if (_isShowDay==YES) {
self.selectDay = [self.pickerView selectedRowInComponent:2] + 1;
}
}
- (void)setYearLeast:(NSInteger)yearLeast
{
_minShowYear = yearLeast;
}
- (void)setYearSum:(NSInteger)yearSum
{
_yearSum = yearSum;
}
-(void)setIsShowDay:(BOOL)isShowDay{
_isShowDay=isShowDay;
}
@end
(3) 創(chuàng)建繼承于WXZBasePickView的時(shí)間選擇器WXZPickTimeView。
.h聲明屬性及相關(guān)方法
#import "WXZBasePickView.h" @class WXZPickTimeView; @protocol PickTimeViewDelegate<NSObject> - (void)pickerTimeView:(WXZPickTimeView *)pickerTimeView selectHour:(NSInteger)hour selectMinute:(NSInteger)minute ; @end @interface WXZPickTimeView : WXZBasePickView @property(nonatomic, weak)id <PickTimeViewDelegate>delegate ; -(void)setDefaultHour:(NSInteger)hour defaultMinute:(NSInteger)minute ; @end
.m實(shí)現(xiàn)相關(guān)方法
#import "WXZPickTimeView.h"
@interface WXZPickTimeView () <UIPickerViewDataSource, UIPickerViewDelegate>{
UIDatePicker *_datePicker;
}
@property (nonatomic, assign)NSInteger selectHour;
@property (nonatomic, assign)NSInteger selectMinute;
@property (nonatomic, assign)NSInteger day;
@property (nonatomic, assign)NSInteger defaultHour;
@property (nonatomic, assign)NSInteger defaultMinute;
@end
@implementation WXZPickTimeView
- (void)initPickView
{
[super initPickView];
NSCalendar *gregorian = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
// 獲取當(dāng)前日期
NSDate* dt = [NSDate date];
// 定義一個(gè)時(shí)間字段的旗標(biāo),指定將會(huì)獲取指定年、月、日、時(shí)、分、秒的信息
unsigned unitFlags = NSCalendarUnitYear |
NSCalendarUnitMonth | NSCalendarUnitDay |
NSCalendarUnitHour | NSCalendarUnitMinute |
NSCalendarUnitSecond | NSCalendarUnitWeekday;
// 獲取不同時(shí)間字段的信息
NSDateComponents* comp = [gregorian components: unitFlags
fromDate:dt];
_selectHour=comp.hour;
_selectMinute=comp.minute;
[self.pickerView setDelegate:self];
[self.pickerView setDataSource:self];
[self.pickerView selectRow:_selectHour inComponent:0 animated:NO];
[self.pickerView selectRow:_selectMinute inComponent:1 animated:NO];
}
-(void)setDefaultHour:(NSInteger)hour defaultMinute:(NSInteger)minute{
if (hour!=0) {
_defaultHour=hour;
}else{
_defaultHour=_selectHour;
}
if (minute!=0) {
_defaultMinute = minute;
}else{
_defaultMinute=_selectMinute;
}
[self.pickerView selectRow:_defaultHour inComponent:0 animated:NO];
[self.pickerView reloadComponent:1];
[self.pickerView selectRow:_defaultMinute inComponent:1 animated:NO];
[self refreshPickTimeViewData];
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == 0) {
return 24;
}else {
return 60;
}
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 36;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
switch (component) {
case 0:
[pickerView reloadComponent:1];
break;
case 1:
default:
break;
}
[self refreshPickTimeViewData];
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view
{
NSString *text;
if (component == 0) {
if (row<10) {
text = [NSString stringWithFormat:@"0%zd時(shí)", row];
}else{
text = [NSString stringWithFormat:@"%zd時(shí)", row];
}
}else if (component == 1){
if (row<10) {
text = [NSString stringWithFormat:@"0%zd分", row ];
}else{
text = [NSString stringWithFormat:@"%zd分", row ];
}
}else{
}
UILabel *label = [[UILabel alloc]init];
label.textAlignment = 1;
label.font = [UIFont systemFontOfSize:16];
label.text = text;
return label;
}
- (void)clickConfirmButton
{
if ([self.delegate respondsToSelector:@selector(pickerTimeView:selectHour:selectMinute:)]) {
[self.delegate pickerTimeView:self selectHour:self.selectHour selectMinute:self.selectMinute];
}
[super clickConfirmButton];
}
- (void)refreshPickTimeViewData
{
self.selectHour = [self.pickerView selectedRowInComponent:0];
self.selectMinute = [self.pickerView selectedRowInComponent:1];
}
@end
(4)創(chuàng)建繼承于WXZBasePickView的城市選擇器WXZPickCityView。
.h聲明相關(guān)屬性和方法
#import "WXZBasePickView.h" @class WXZPickCityView; @protocol PickerCityViewDelegate<NSObject> - (void)pickerArea:(WXZPickCityView *)pickerArea selectProvince:(NSString *)province selectCity:(NSString *)city; @end @interface WXZPickCityView : WXZBasePickView @property(nonatomic, weak)id <PickerCityViewDelegate>delegate ; /**設(shè)置默認(rèn)的省市*/ -(void)setDefaultCity:(NSString *)defaultCity DefaultProvience:(NSString *)defaultProvience; @end
.m實(shí)現(xiàn)相關(guān)方法
#import "WXZPickCityView.h"
@interface WXZPickCityView()<UIPickerViewDataSource, UIPickerViewDelegate>
@property (nonatomic, strong, nullable)NSArray *areaDataSource;
@property (nonatomic, strong, nullable)NSMutableArray *provinceArray;
@property (nonatomic, strong, nullable)NSMutableArray *cityArray;
@property (nonatomic, strong, nullable)NSMutableArray *selectedArray;//當(dāng)前選中的數(shù)組
@property (nonatomic, strong, nullable)NSString *selectProvince;
@property (nonatomic, strong, nullable)NSString *selectCity;
@end
@implementation WXZPickCityView
- (void)initPickView
{
[super initPickView];
for (NSDictionary *dic in self.areaDataSource) {
[self.provinceArray addObject:dic[@"state"]];
}
NSMutableArray *citysArr = [NSMutableArray arrayWithArray:[self.areaDataSource firstObject][@"cities"]];
for (NSDictionary *dic in citysArr) {
[self.cityArray addObject:dic[@"city"]];
}
self.selectProvince = self.provinceArray[0];
self.selectCity = self.cityArray[0];
[self.pickerView setDelegate:self];
[self.pickerView setDataSource:self];
}
//設(shè)置默認(rèn)顯示的省市
-(void)setDefaultCity:(NSString *)defaultCity DefaultProvience:(NSString *)defaultProvience{
for (NSInteger i = 0; i<_provinceArray.count; i++) {
if ([_provinceArray[i] isEqualToString:defaultProvience]) {
[self.pickerView selectRow:i inComponent:0 animated:NO];
self.selectedArray = self.areaDataSource[i][@"cities"];
[self.cityArray removeAllObjects];
[self.selectedArray enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self.cityArray addObject:obj[@"city"]];
}];
for (NSInteger j= 0; j<_cityArray.count; j++) {
if ([defaultCity isEqualToString:_cityArray[j]]) {
[self.pickerView selectRow:i inComponent:0 animated:NO];
[self.pickerView reloadComponent:1];
[self.pickerView selectRow:j inComponent:1 animated:NO];
[self refreshSelectAreaData];
}
}
}
}
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (component == 0) {
return self.provinceArray.count;
}else {
return self.cityArray.count;
}
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 36;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
if (component == 0) {
self.selectedArray = self.areaDataSource[row][@"cities"];
[self.cityArray removeAllObjects];
[self.selectedArray enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL * _Nonnull stop) {
[self.cityArray addObject:obj[@"city"]];
}];
[pickerView reloadComponent:1];
[pickerView selectRow:0 inComponent:1 animated:YES];
}else if (component == 1) {
if (self.selectedArray.count == 0) {
self.selectedArray = [self.areaDataSource firstObject][@"cities"];
}
}else{
}
[self refreshSelectAreaData];
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view
{
for(UIView *singleLine in pickerView.subviews)
{
if (singleLine.frame.size.height < 1)
{
singleLine.backgroundColor =[UIColor grayColor];
}
}
NSString *text;
if (component == 0) {
text = self.provinceArray[row];
}else if (component == 1){
text = self.cityArray[row];
}else{
}
UILabel *label = [[UILabel alloc]init];
label.textAlignment = 1;
label.font = [UIFont systemFontOfSize:16];
label.text = text;
return label;
}
- (void)clickConfirmButton
{
[self.delegate pickerArea:self selectProvince:self.selectProvince selectCity:self.selectCity];
[super clickConfirmButton];
}
- (void)refreshSelectAreaData
{
NSInteger provienceIndex = [self.pickerView selectedRowInComponent:0];
NSInteger cityIndex = [self.pickerView selectedRowInComponent:1];
self.selectProvince = self.provinceArray[provienceIndex];
self.selectCity = self.cityArray[cityIndex];
}
- (NSArray *)areaDataSource
{
if (!_areaDataSource) {
NSString *path = [[NSBundle bundleForClass:[WXZPickCityView class]] pathForResource:@"area" ofType:@"plist"];
_areaDataSource = [[NSArray alloc]initWithContentsOfFile:path];
}
return _areaDataSource;
}
- (NSMutableArray *)provinceArray
{
if (!_provinceArray) {
_provinceArray = [NSMutableArray array];
}
return _provinceArray;
}
- (NSMutableArray *)cityArray
{
if (!_cityArray) {
_cityArray = [NSMutableArray array];
}
return _cityArray;
}
- (NSMutableArray *)selectedArray
{
if (!_selectedArray) {
_selectedArray = [NSMutableArray array];
}
return _selectedArray;
}
@end
(5)創(chuàng)建繼承于WXZBasePickView的單列選擇器WXZCustomPickView,可根據(jù)傳進(jìn)來(lái)的數(shù)組顯示相關(guān)的選擇內(nèi)容
.h聲明相關(guān)屬性和方法
#import "WXZBasePickView.h" @class WXZCustomPickView; @protocol CustomPickViewDelegate<NSObject> - (void)customPickView:(WXZCustomPickView *)customPickView selectedTitle:(NSString *)selectedTitle; @end @interface WXZCustomPickView :WXZBasePickView @property (nonatomic, strong)NSMutableArray *dataArray; @property(nonatomic, copy)NSString *defalutSelectRowStr; @property(nonatomic, weak)id <CustomPickViewDelegate>delegate; @end
.m實(shí)現(xiàn)相關(guān)方法
#import "WXZCustomPickView.h"
@interface WXZCustomPickView()<UIPickerViewDataSource, UIPickerViewDelegate>
/** 1.選中的字符串 */
@property (nonatomic, strong, nullable)NSString *selectedTitle;
@end
@implementation WXZCustomPickView
- (void)initPickView
{
[super initPickView];
_dataArray=[NSMutableArray mutableCopy];
[self.pickerView setDelegate:self];
[self.pickerView setDataSource:self];
}
-(void)setDefalutSelectRowStr:(NSString *)defalutSelectRowStr{
_defalutSelectRowStr=defalutSelectRowStr;
for (NSInteger i = 0; i<_dataArray.count; i++) {
if ([_dataArray[i] isEqualToString:_defalutSelectRowStr]) {
[self.pickerView reloadAllComponents];
[self.pickerView selectRow:i inComponent:0 animated:NO];
}
}
}
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
return self.dataArray.count;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component
{
return 36;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component
{
return self.frame.size.width;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
self.selectedTitle = self.dataArray[row];
}
- (UIView *)pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(nullable UIView *)view
{
for(UIView *singleLine in pickerView.subviews)
{
if (singleLine.frame.size.height < 1)
{
singleLine.backgroundColor =[UIColor grayColor];
}
}
UILabel *label = [[UILabel alloc]init];
label.font=[UIFont systemFontOfSize:16];
label.textAlignment = 1;
label.text=self.dataArray[row];
return label;
}
#pragma mark -點(diǎn)擊確定按鈕
- (void)clickConfirmButton
{
[self.delegate customPickView:self selectedTitle:self.selectedTitle];
[super clickConfirmButton];
}
- (void)setDataArray:(NSMutableArray *)dataArray
{
_dataArray = dataArray;
_selectedTitle = dataArray.firstObject;
[self.pickerView reloadAllComponents];
}
@end
這樣,幾種類(lèi)型的選擇器我們都定義好了,在需要選擇器的地方,根據(jù)需求創(chuàng)建相應(yīng)的選擇器即可。
四、如何使用已創(chuàng)建好的自定義選擇器
引入自定義好的選擇器,聲明相關(guān)屬性,簽相關(guān)協(xié)議
#import "ViewController.h"
#import "WXZPickDateView.h"
#import "WXZPickAreaView.h"
#import "WXZPickTimeView.h"
#import "WXZCustomPickView.h"
@interface ViewController ()<PickerDateViewDelegate,PickerAreaViewDelegate,PickTimeViewDelegate,CustomPickViewDelegate>{
UIButton *dateButton;
UIButton *selectAreabutton;
UIButton *selectTimeButton;
UIButton *singlePickViewSelectButton;
BOOL isShowDay;//是否顯示日信息
}
@end
創(chuàng)建相應(yīng)的按鈕,觸發(fā)相應(yīng)的選擇器
- (void)viewDidLoad {
[super viewDidLoad];
dateButton=[UIButton buttonWithType:UIButtonTypeCustom];
dateButton.frame=CGRectMake(100, 100, 100, 50);
[dateButton setTitle:@"選擇日期" forState:UIControlStateNormal];
[self.view addSubview:dateButton];
[dateButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[dateButton addTarget:self action:@selector(pickViewSelect:) forControlEvents:UIControlEventTouchUpInside];
dateButton.tag = 1000;
selectAreabutton=[UIButton buttonWithType:UIButtonTypeCustom];
selectAreabutton.frame=CGRectMake(100, 200, 100, 50);
[selectAreabutton setTitle:@"選擇地區(qū)" forState:UIControlStateNormal];
[self.view addSubview:selectAreabutton];
[selectAreabutton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[selectAreabutton addTarget:self action:@selector(pickViewSelect:) forControlEvents:UIControlEventTouchUpInside];
selectAreabutton.tag = 1001;
selectTimeButton=[UIButton buttonWithType:UIButtonTypeCustom];
selectTimeButton.frame=CGRectMake(100, 300, 100, 50);
[selectTimeButton setTitle:@"選擇時(shí)間" forState:UIControlStateNormal];
[self.view addSubview:selectTimeButton];
[selectTimeButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[selectTimeButton addTarget:self action:@selector(pickViewSelect:) forControlEvents:UIControlEventTouchUpInside];
selectTimeButton.tag = 1002;
singlePickViewSelectButton=[UIButton buttonWithType:UIButtonTypeCustom];
singlePickViewSelectButton.frame=CGRectMake(100, 400, 100, 50);
[singlePickViewSelectButton setTitle:@"單個(gè)數(shù)據(jù)選擇器" forState:UIControlStateNormal];
[self.view addSubview:singlePickViewSelectButton];
[singlePickViewSelectButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[singlePickViewSelectButton addTarget:self action:@selector(pickViewSelect:) forControlEvents:UIControlEventTouchUpInside];
singlePickViewSelectButton.tag = 1003;
}
按鈕的點(diǎn)擊事件:
-(void)pickViewSelect:(UIButton *)button{
if (button.tag==1000) {
WXZPickDateView *pickerDate = [[WXZPickDateView alloc]init];
[pickerDate setIsAddYetSelect:YES];//是否顯示至今選項(xiàng)
[pickerDate setIsShowDay:YES];//是否顯示日信息
[pickerDate setDefaultTSelectYear:2007 defaultSelectMonth:4 defaultSelectDay:1];//設(shè)定默認(rèn)顯示的日期
[pickerDate setValidTime:2010];
[pickerDate setDelegate:self];
[pickerDate show];
}else if (button.tag==1001){
WXZPickAreaView *pickerArea = [[WXZPickAreaView alloc]init];
[pickerArea setDelegate:self];
[pickerArea setDefaultCity:@"上海" DefaultProvience:@"上海"];
[pickerArea show];
[self.view endEditing:YES];
}else if (button.tag==1002){
WXZPickTimeView *pickerArea = [[WXZPickTimeView alloc]init];
[pickerArea setDelegate:self];
[pickerArea setDefaultHour:14 defaultMinute:20];
[pickerArea show];
[self.view endEditing:YES];
}else{
NSMutableArray *arrayData = [NSMutableArray arrayWithObjects:@"2k以下",@"2k-5k",@"5k-10k",@"10k-15k",@"15k-25k",@"25k-50k",@"50k以上", nil];
WXZCustomPickView *pickerSingle = [[WXZCustomPickView alloc]init];
[pickerSingle setDataArray:arrayData];
[pickerSingle setDefalutSelectRowStr:arrayData[0]];
[pickerSingle setDelegate:self];
[pickerSingle show];
[self.view endEditing:YES];
}
}
選擇器的代理方法
-(void)pickerDateView:(WXZBasePickView *)pickerDateView selectYear:(NSInteger)year selectMonth:(NSInteger)month selectDay:(NSInteger)day{
NSLog(@"選擇的日期是:%ld %ld %ld",year,month,day);
if (isShowDay==YES) {
[dateButton setTitle:[NSString stringWithFormat:@"%ld年 %ld月 %ld日",year,month,day] forState:UIControlStateNormal];
}else{
[dateButton setTitle:[NSString stringWithFormat:@"%ld年 %ld月",year,month] forState:UIControlStateNormal];
}
}
-(void)pickerArea:(WXZPickAreaView *)pickerArea selectProvince:(NSString *)province selectCity:(NSString *)city{
NSLog(@"省市的選擇%@ %@",province,city);
[selectAreabutton setTitle:[NSString stringWithFormat:@"%@%@",province,city] forState:UIControlStateNormal];
}
-(void)customPickView:(WXZCustomPickView *)customPickView selectedTitle:(NSString *)selectedTitle{
NSLog(@"選擇%@",selectedTitle);
[singlePickViewSelectButton setTitle:selectedTitle forState:UIControlStateNormal];
}
-(void)pickerTimeView:(WXZPickTimeView *)pickerTimeView selectHour:(NSInteger)hour selectMinute:(NSInteger)minute{
NSLog(@"選擇的時(shí)間:%ld %ld",hour,minute);
[selectTimeButton setTitle:[NSString stringWithFormat:@"%ld時(shí) %ld分",hour,minute] forState:UIControlStateNormal];
}
最后,看看效果圖:

有需要的可以下載demo看看
github地址:https://github.com/wxzwork/CustomPickView
demo地址:CustomPickView_jb51.rar
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
IOS 應(yīng)用程序管理的實(shí)現(xiàn)
這篇文章主要介紹了IOS 應(yīng)用程序管理的實(shí)現(xiàn)的相關(guān)資料,希望通過(guò)本文能幫助到大家,讓大家實(shí)現(xiàn)這樣的功能,需要的朋友可以參考下2017-10-10
iOS中自動(dòng)實(shí)現(xiàn)對(duì)象序列化的方法詳解
這篇文章主要給大家介紹了在iOS中自動(dòng)實(shí)現(xiàn)對(duì)象序列化的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起看看吧。2017-05-05
iOS 實(shí)現(xiàn)簡(jiǎn)單的加載等待動(dòng)畫(huà)示例(思路與實(shí)現(xiàn))
本篇文章主要介紹了iOS 實(shí)現(xiàn)簡(jiǎn)單的加載等待動(dòng)畫(huà)示例(思路與實(shí)現(xiàn)),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-05-05
IOS textField限制字節(jié)長(zhǎng)度
這篇文章主要介紹了IOS textField限制字節(jié)長(zhǎng)度的相關(guān)資料,需要的朋友可以參考下2016-02-02
iOS開(kāi)發(fā)實(shí)現(xiàn)計(jì)算器功能
這篇文章主要為大家詳細(xì)介紹了iOS開(kāi)發(fā)實(shí)現(xiàn)計(jì)算器功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-10-10

