无聊ing...封装个省市区三级联动选择器的小demo吧。

上家公司的三级地区选择器的数据是一次性通过网络请求就能获取到的,但新东家这边并不是,而是先选择了省获取省的Id再去获取市,再通过得到市的Id获取区域,show code之前,先看下需要考虑的几个点:
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 <UIKit/UIKit.h> //定制代理协议 @protocol ZLMAddressPickerViewDelegate <NSObject> - (void)addressPickerViewDidSelected:(NSString *)areaName;//点击上方完成按钮的代理传回拼接好的选中地址 - (void)addressPickerViewDidClose;//点击关闭代理 @end @interface ZLMAddressPickerView : UIView @property (weak, nonatomic) id<ZLMAddressPickerViewDelegate> delegate; @end
.m文件
#import "ZLMAddressPickerView.h"
#import "AFHttpUtils.h"
#import "AreaModel.h"
@interface ZLMAddressPickerView () <UIPickerViewDataSource, UIPickerViewDelegate>
@property (strong, nonatomic) UIPickerView *pickerView;
@property (strong, nonatomic) AreaModel *provBridge;
@property (strong, nonatomic) AreaModel *cityBridge;
@property (strong, nonatomic) AreaModel *areaBridge;
@property (copy, nonatomic) NSArray<Area *> * provDataArr;//省数组
@property (copy, nonatomic) NSArray<Area *> * cityDataArr;//市数组
@property (copy, nonatomic) NSArray<Area *> * 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三级联动选择器
# ios
# 三级城市选择器
# iOS实现自定义起始时间选择器视图
# iOS自定义日期、时间、城市选择器实例代码
# Android自定义View仿IOS圆盘时间选择器
# iOS实现自定义日期选择器示例
# Android开发中实现IOS风格底部选择器(支持时间 日期 自定义)
# iOS开发之UIPickerView实现城市选择器的步骤详解
# iOS中使用UIDatePicker制作时间选择器的实例教程
# 本轮
# 默认值
# 要在
# 选择器
# 到第
# 先看
# 几个
# 放在
# 也会
# 是有
# 又是
# 就能
# 依此类推
# 才会
# 你在
# 当你
# 最喜欢
# 这部
# 要想
# 再去
相关文章:
c# F# 的 MailboxProcessor 和 C# 的 Actor 模型
如何选择适合PHP云建站的开源框架?
青浦网站制作公司有哪些,苹果官网发货地是哪里?
深圳防火门网站制作公司,深圳中天明防火门怎么编码?
哪家制作企业网站好,开办像阿里巴巴那样的网络公司和网站要怎么做?
如何选择建站程序?包含哪些必备功能与类型?
建站之星安装失败:服务器环境不兼容?
矢量图网站制作软件,用千图网的一张矢量图做公司app首页,该网站并未说明版权等问题,这样做算不算侵权?应该如何解决?
专业公司网站制作公司,用什么语言做企业网站比较好?
c++如何打印函数堆栈信息_c++ backtrace函数与符号名解析【方法】
邀请函制作网站有哪些,有没有做年会邀请函的网站啊?在线制作,模板很多的那种?
表情包在线制作网站免费,表情包怎么弄?
seo网站制作优化,网站SEO优化步骤有哪些?
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
建站之星代理如何优化在线客服效率?
怎么用手机制作网站链接,dw怎么把手机适应页面变成网页?
一键制作网站软件下载安装,一键自动采集网页文档制作步骤?
建站之星安装后如何自定义网站颜色与字体?
广州网站制作的公司,现在专门做网站的公司有没有哪几家是比较好的,性价比高,模板也多的?
网站制作员失业,怎样查看自己网站的注册者?
如何在景安云服务器上绑定域名并配置虚拟主机?
宝塔建站无法访问?如何排查配置与端口问题?
如何在建站之星网店版论坛获取技术支持?
建站之星安装后如何配置SEO及设计样式?
如何通过NAT技术实现内网高效建站?
如何在阿里云高效完成企业建站全流程?
建站VPS选购需注意哪些关键参数?
香港网站服务器数量如何影响SEO优化效果?
,柠檬视频怎样兑换vip?
专业网站设计制作公司,如何制作一个企业网站,建设网站的基本步骤有哪些?
网站制作模板下载什么软件,ppt模板免费下载网站?
建站之星安装模板失败:服务器环境不兼容?
如何在建站宝盒中设置产品搜索功能?
,想在网上投简历,哪几个网站比较好?
齐河建站公司:营销型网站建设与SEO优化双核驱动策略
如何快速生成凡客建站的专业级图册?
名字制作网站免费,所有小说网站的名字?
Android自定义控件实现温度旋转按钮效果
广州美橙建站如何快速搭建多端合一网站?
开封网站制作公司,网络用语开封是什么意思?
如何基于云服务器快速搭建网站及云盘系统?
C++用Dijkstra(迪杰斯特拉)算法求最短路径
Python lxml的etree和ElementTree有什么区别
胶州企业网站制作公司,青岛石头网络科技有限公司怎么样?
Java解压缩zip - 解压缩多个文件或文件夹实例
沈阳制作网站公司排名,沈阳装饰协会官方网站?
宝塔面板创建网站无法访问?如何快速排查修复?
宝塔面板如何快速创建新站点?
定制建站方案优化指南:企业官网开发与建站费用解析
高端云建站费用究竟需要多少预算?
*请认真填写需求信息,我们会在24小时内与您取得联系。