开发中会遇到让用户选择城市的需求,这就需要用到UIPickerView的二级联动,实现起来虽然比较简单,但却需要好好思考清楚才能更好的理解代码.
1.搭建界面如下:
2.将textFeild连线至控制器类扩展中,设置控制器为textFeild的代理.
3.创建模型文件,并设置内容如下:
模型.h文件
#import <Foundation/Foundation.h>
@interface DLProvinces : NSObject
@property(nonatomic,strong) NSArray *cities;
@property(nonatomic,strong) NSString *name;
+ (instancetype)provincesWithDict:(NSDictionary *)dict;
@end
模型.m文件
#import "DLProvinces.h"
@implementation DLProvinces
+ (instancetype)provincesWithDict:(NSDictionary *)dict{
DLProvinces *p = [[self alloc] init];
[p setValuesForKeysWithDictionary:dict];
return p;
}
@end
4.在控制器中创建数组来接收模型数据.
@property(nonatomic,strong) NSMutableArray *province;
//数组懒加载
- (NSMutableArray *)province{
if (_province == nil) {
_province = [NSMutableArray array];
NSString *path = [[NSBundle mainBundle] pathForResource:@"provinces.plist" ofType:nil];
NSArray *arr = [NSArray arrayWithContentsOfFile:path];
for (NSDictionary *dict in arr) {
DLProvinces *p = [DLProvinces provincesWithDict:dict];
[_province addObject:p];
}
}
return _province;
}
5.创建UIPickerView,设置textFeild的inputView为cityPicker,并创建一个成员变量cityPicker存储cityPicker.
//成员变量cityPicker
@property(nonatomic,strong) UIPickerView *cityPicker;
- (void)viewDidLoad {
[super viewDidLoad];
//设置加载界面后cityField获取焦点
[_cityField becomeFirstResponder];
//创建城市键盘
[self setCityField];
}
//自定义城市键盘
- (void)setCityField{
UIPickerView *cityPicker = [[UIPickerView alloc] init];
//设置cityPicker的数据源与代理为当前控制器
cityPicker.dataSource = self;
cityPicker.delegate = self;
_cityPicker = cityPicker;
_cityField.inputView = cityPicker;
6.实现数据源与代理方法
注意:定义一个成员变量,记录选中了第0列的哪一行.解决两列同时滚动脚标越界的问题.
@property(nonatomic,assign) NSInteger proIndex;
#pragma mark - UIPickerViewDataSource
//返回列数
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView{
return 2;
}
//返回行数
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
//判断当前是第几列
if (component == 0) {
return self.province.count;
}else{
//取出选中的省会
DLProvinces *p = self.province[_proIndex];
return p.cities.count;
}
}
//返回第component列第row行的文字
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
//判断当前是第几列
if (component == 0) {
DLProvinces *p = self.province[row];
return p.name;
}else{
//取出选中的省会
DLProvinces *p = self.province[_proIndex];
return p.cities[row];
}
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component{
if (component == 0) {
//记录当前选中的省会
_proIndex = [pickerView selectedRowInComponent:0];
[pickerView reloadComponent:1];
}
//获取选中的省会
DLProvinces *p = self.province[_proIndex];
//获取选中的城市
NSInteger cityIndex = [pickerView selectedRowInComponent:1];
NSString *cityName = p.cities[cityIndex];
_cityField.text = [NSString stringWithFormat:@"%@ %@",p.name,cityName];
}
7.设置cityField不能输入文字,加载时显示第0列第0行的数据.
#pragma mark - UITextFieldDelegate
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string{
return NO;
}
//文本框获取焦点时调用
- (void)textFieldDidBeginEditing:(UITextField *)textField;{
[self pickerView:_cityPicker didSelectRow:0 inComponent:0];
}
效果图:
网友评论