本篇文章为大家展示了怎么在iOS中实现一个三级联动选择器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。
创新互联专注于越城企业网站建设,响应式网站建设,商城网站建设。越城网站建设公司,为越城等地区提供建站服务。全流程按需定制制作,专业设计,全程项目跟踪,创新互联专业和态度为您提供的服务
1)怎么设置默认值,关键代码
[self.pickerView selectRow:xxx inComponent:xxx animated:YES];
2)怎么让三级之间联动 ,关键代码
[self pickerView:self.pickerView didSelectRow:0 inComponent:0 ];//联动轮子1 必须得本轮有数据后触发否则crash
先看下效果图
关于设置默认值,三级联动,用UIPickView的话就是有3个轮子(component),首先我们要想到,第一次向后台发起请求,我们只能获取到第0个component的数据,只有当你滚动轮子的时候才会获取到省的Id发起请求来获得该省的市的数据,也就是第1个component的数据,依此类推,滚动第1个component发起请求来获取第2个component的数据,因此,pickView的监听轮子滚动的代理起了重要作用
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component;
我们通过接口获取第0个component的数据,这边是后台规定的使用id=0,获取到以后,默认选中第0个component的第0个row并主动调用触发pick的轮子滚动代理来联动第1个component【要在获取数据成功后再执行这部操作,因此放在数据请求成功的回调内】,代码为
[self pickerView:self.pickerView didSelectRow:0 inComponent:0 ];
在各轮子滚动过程中,用一个中间值
_selectedRow0记录下第0个component的选中行
_selectedRow1记录下第1个component的选中行
_selectedRow2记录下第2个component的选中行,
这里需要记住,滚动某个轮子只能对它后面的轮子产生影响,所以当滚动第0个component的时候使_selectedRow1,_selectedRow2均置为0,这里注意,上面提到的
默认选中第0个component的第0个row并主动调用触发pick的轮子滚动代理来联动第1个component
要先将轮子上的数据渲染好,设置好默认值才能主动调用监听轮子滚动的代理,否则会导致崩溃,另一个防崩溃的点如下图
发现第三级没数据的时候,如果你在代码里没加【安全措施】,那也会导致崩溃,要在请求到第三级的数据后做下判断,如果个数为空,将该级对应的数据源置为nil。(其它两级的轮子最好也加判断)
最后,由于这是个封装的类,最终要得到选中的详细信息,可通过代理或block传值给controller。
又是你们最喜欢show code环节:
.h文件
#import//定制代理协议 @protocol ZLMAddressPickerViewDelegate - (void)addressPickerViewDidSelected:(NSString *)areaName;//点击上方完成按钮的代理传回拼接好的选中地址 - (void)addressPickerViewDidClose;//点击关闭代理 @end @interface ZLMAddressPickerView : UIView @property (weak, nonatomic) id delegate; @end
.m文件
#import "ZLMAddressPickerView.h" #import "AFHttpUtils.h" #import "AreaModel.h" @interface ZLMAddressPickerView ()@property (strong, nonatomic) UIPickerView *pickerView; @property (strong, nonatomic) AreaModel *provBridge; @property (strong, nonatomic) AreaModel *cityBridge; @property (strong, nonatomic) AreaModel *areaBridge; @property (copy, nonatomic) NSArray * provDataArr;//省数组 @property (copy, nonatomic) NSArray * cityDataArr;//市数组 @property (copy, nonatomic) NSArray * areaDataArr;//区数组 @end @implementation ZLMAddressPickerView { NSInteger _selectRow0;//记录第0个轮子的选择行 NSInteger _selectRow1; NSInteger _selectRow2; NSString *_areaString;//最后要传回的详细地址拼接字符串 Area *_proModel;//记录下选中省的数据 Area *_cityModel; Area *_areaModel; } - (instancetype)initWithFrame:(CGRect)frame { self = [super initWithFrame:frame]; if (self) { [self setup]; } return self; } - (void)setup { _selectRow0 = 0; _selectRow1 = 0; _selectRow2 = 0; self.backgroundColor = [UIColor whiteColor]; UIToolbar *toolbar = [[UIToolbar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.bounds), 44)]; toolbar.backgroundColor = [UIColor whiteColor]; [self addSubview:toolbar]; UIBarButtonItem *closeItem = [[UIBarButtonItem alloc] initWithTitle:@"关闭" style:UIBarButtonItemStylePlain target:self action:@selector(selectAddressClose)]; UIBarButtonItem *completeItem = [[UIBarButtonItem alloc] initWithTitle:@"完成" style:UIBarButtonItemStylePlain target:self action:@selector(selectAddressComplete)]; UIBarButtonItem *spaceItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; toolbar.items = @[closeItem, spaceItem, completeItem]; self.pickerView.frame = CGRectMake(0, 44, CGRectGetWidth(self.bounds), CGRectGetHeight(self.bounds) - 44); [self addSubview:self.pickerView]; [self downloadProv]; } #pragma mark - http methods /*省*/ - (void)downloadProv { NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary: @{@"id":@(0)} ]; [AFHttpUtils sendPostTaskWithUrl:[NSString stringWithFormat:@"%@/app/member/area",BASE_DOMAIN_URL] paramenters:dic successHandle:^(NSURLSessionDataTask *task, id responseObject) { NSLog(@"PROV:%@",responseObject); self.provBridge = [AreaModel mj_objectWithKeyValues:responseObject]; if (self.provBridge.error_code==0) { self.provDataArr=self.provBridge.data; [self pickerView:self.pickerView didSelectRow:0 inComponent:0 ];//联动轮子1 必须得本轮有数据后才能触发didselect [self.pickerView reloadAllComponents]; } } errorHandle:^(NSError *error) { }]; } /*市*/ - (void)downloadCityWithId:(NSInteger)provId { NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary: @{@"id":@(provId)} ]; [AFHttpUtils sendPostTaskWithUrl:[NSString stringWithFormat:@"%@/app/member/area",BASE_DOMAIN_URL] paramenters:dic successHandle:^(NSURLSessionDataTask *task, id responseObject) { NSLog(@"CITY:%@",responseObject); self.cityBridge = [AreaModel mj_objectWithKeyValues:responseObject]; if (self.cityBridge.error_code==0) { self.cityDataArr=self.cityBridge.data; [self.pickerView reloadComponent:1]; [self.pickerView selectRow:0 inComponent:1 animated:YES];//默认选择row0 [self pickerView:self.pickerView didSelectRow:0 inComponent:1 ];//联动轮子2 必须得本轮有数据后才能触发didselect _cityModel = self.cityDataArr[_selectRow1]; [self downloadAreaWithId:_cityModel.area_id]; } } errorHandle:^(NSError *error) { }]; } /*区*/ - (void)downloadAreaWithId:(NSInteger)cityId { NSMutableDictionary *dic = [NSMutableDictionary dictionaryWithDictionary: @{@"id":@(cityId)} ]; [AFHttpUtils sendPostTaskWithUrl:[NSString stringWithFormat:@"%@/app/member/area",BASE_DOMAIN_URL] paramenters:dic successHandle:^(NSURLSessionDataTask *task, id responseObject) { NSLog(@"AREA:%@",responseObject); self.areaBridge = [AreaModel mj_objectWithKeyValues:responseObject]; if (self.areaBridge.error_code==0&&self.areaBridge.data.count>0) { self.areaDataArr=self.areaBridge.data; }else{ self.areaDataArr=nil; } [self.pickerView reloadComponent:2]; [self.pickerView selectRow:0 inComponent:2 animated:YES]; [self pickerView:self.pickerView didSelectRow:0 inComponent:2 ]; } errorHandle:^(NSError *error) { }]; } #pragma mark - events response - (void)selectAddressComplete { [self.delegate addressPickerViewDidSelected:_areaString]; } - (void)selectAddressClose { [self.delegate addressPickerViewDidClose]; } #pragma mark - UIPickerViewDataSource //确定picker的轮子个数 - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 3; } //确定picker的每个轮子的item数 - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { if (component==0) { return self.provDataArr.count; }else if(component==1){ return self.cityDataArr.count; }else{ return self.areaDataArr.count; } } - (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component{ return 36; } //确定每个轮子的每一项显示什么内容 - (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component{ NSDictionary * attrDic = @{NSForegroundColorAttributeName:[UIColor blackColor], NSFontAttributeName:[UIFont systemFontOfSize:12]}; Area *area; if (component==0) { area = self.provDataArr[row]; }else if(component==1){ area = self.cityDataArr[row]; }else{ area = self.areaDataArr[row]; } NSAttributedString * attrString = [[NSAttributedString alloc] initWithString:area.name attributes:attrDic]; return attrString; } //监听轮子的移动 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { if (component==0) { _selectRow0 = [pickerView selectedRowInComponent:0]; _selectRow1 = 0; _selectRow2 = 0; _proModel = self.provDataArr[_selectRow0]; [self downloadCityWithId:_proModel.area_id]; }else if(component==1){ _selectRow1 = [pickerView selectedRowInComponent:1]; _selectRow2 = 0; _cityModel = self.cityDataArr[_selectRow1]; [self downloadAreaWithId:_cityModel.area_id]; }else{ _selectRow2 = [pickerView selectedRowInComponent:2]; if (self.areaDataArr&&self.areaDataArr.count>0) { _areaModel = self.areaDataArr[_selectRow2]; }else{ _areaModel = nil; } } if(_areaModel==nil){ _areaString = [NSString stringWithFormat:@"%@ %@",_proModel.name,_cityModel.name]; }else{ _areaString = [NSString stringWithFormat:@"%@ %@ %@",_proModel.name,_cityModel.name,_areaModel.name]; } } #pragma mark - getters and setters - (UIPickerView *)pickerView { if (_pickerView == nil) { _pickerView = [[UIPickerView alloc] init]; _pickerView.delegate = self; _pickerView.dataSource = self; } return _pickerView; } @end
最后在controller中调用
(1)导入
#import "ZLMAddressPickerView.h"
(2)定义一个对象并遵守代理协议
@property (strong, nonatomic) ZLMAddressPickerView *addressPickerView;
(3)懒加载生成对象(个人习惯)
- (ZLMAddressPickerView *)addressPickerView { if (!_addressPickerView) { _addressPickerView = [[ZLMAddressPickerView alloc] initWithFrame:CGRectMake(0, SCREEN_HEIGHT-244-64, SCREEN_WIDTH, 244)]; _addressPickerView.delegate = self; } return _addressPickerView; }
(4)在点击跳出三级联动选择器的地方
[self.view addSubview:self.addressPickerView];
(5)别忘了实现代理
#pragma mark - ZLMAddressPickerViewDelegate - (void)addressPickerViewDidSelected:(NSString *)areaName { self.areaLabel.text = areaName;//将传回的详细地址字符串赋值 [self addressPickerViewDidClose]; } - (void)addressPickerViewDidClose { [self.addressPickerView removeFromSuperview]; }
上述内容就是怎么在iOS中实现一个三级联动选择器,你们学到知识或技能了吗?如果还想学到更多技能或者丰富自己的知识储备,欢迎关注创新互联行业资讯频道。