您的位置:首页 > 产品设计 > UI/UE

UIPickerView城市选择

2015-01-05 19:53 337 查看

我使用UIPickerView写了一个城市选择器,可是我发现在省份滚轮滚动的时候如果同时再滚动城市滚轮会崩溃,代码如下:

@interface GLViewController ()<UIPickerViewDataSource, UIPickerViewDelegate>
@property (nonatomic, strong) NSArray *provinces;

@property (nonatomic, weak) UIPickerView *pickerView;

@end

@implementation GLViewController

- (void)viewDidLoad
{
[super viewDidLoad];

// 1.创建pickerview
// pickerview有默认的frame
UIPickerView *pickerView = [[UIPickerView alloc] init];
pickerView.dataSource = self;
pickerView.delegate = self;
[self.view addSubview:pickerView];
self.pickerView = pickerView;
}

#pragma mark - UIPickerViewDataSource
// 告诉系统有多少列
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
return 2;
}
// 告诉系统有多少行
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
if (0 == component) {
// 省份列
return self.provinces.count;
}else
{
// 城市列
// 获取第0列选中的行
NSInteger selectIndex = [self.pickerView selectedRowInComponent:0];
// 1.根据第0列选中的行数获取对应的省
NJProvince *province = self.provinces[selectIndex];
// 2.获取对应省份对应的城市
NSArray *cities = province.cities;
// 3.返回城市的个数r
return cities.count;
}
}
#pragma mark - UIPickerViewDelegate
// 告诉系统每一行显示什么内容
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
{
NSLog(@"titleForRow");

if (0 == component) {
// 省份
// 1.获取对应行对应的省份模型
NJProvince *province = self.provinces[row];
// 2.返回省份的名称
return province.name;
}else
{
// 城市列
// 0.获取第0列选中的行数
NSInteger selectIndex = [pickerView selectedRowInComponent:0];
// 1.获取对应的省份
NJProvince *province = self.provinces[selectIndex];
// 2.获取对应的城市
return province.cities[row];
}
}

// 监听pickerView的选中
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component
{
// 判断是否修改了第0列(省份列)
if (0 == component) {
// 刷新第1列对应的数据
[pickerView reloadComponent:1];
// 让第1列滚动到第0行
[pickerView selectRow:0 inComponent:1 animated:YES];
}
}

#pragma mark - 懒加载
- (NSArray *)provinces
{
if (_provinces == nil) {
//        加载资源
NSArray *array = [NSArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"cities" ofType:@"plist"]];
//        转换为模型
NSMutableArray *models = [NSMutableArray arrayWithCapacity:array.count];
for (NSDictionary *dict in array) {
NJProvince *province = [NJProvince provinceWithDictionary:dict];
[models addObject:province];
}
_provinces = [models copy];
}
return _provinces;
}
@end
这个崩溃现象是由于省份滚轮在滚动过程中[pickerView selectedRowInComponent]一直在变化,而代理方法-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component只有在滚轮停止滚动式才会调用。我们滚动城市的滚轮时会调用代理- (NSInteger)pickerView:(UIPickerView *)pickerView
numberOfRowsInComponent:(NSInteger)component,进而需要调用[pickerView selectedRowInComponent],此时如果省份也是滚动的获取到得省份的行是变化的,所以在滚动城市取数据过程中出现的数组越界,解决方法就是设置一个省份行的属性,只有在停止滚动的时候在-(void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component设置,在其他代理中通过这个索引更新数据。于是我用了另一种写法:
@interface TCityPickerView ()<UIPickerViewDataSource, UIPickerViewDelegate>
@property (nonatomic, weak) UIPickerView *pickerView;
@property (nonatomic, strong) NSArray *citiesArray;
@property (nonatomic, assign) NSInteger provinceIndex;
@end

@implementation TCityPickerView

#pragma mark - public
+ (instancetype)cityPickerView {
TCityPickerView *pickerView = [[TCityPickerView alloc] init];
pickerView.backgroundColor = kColorBarBg;
pickerView.show = NO;
pickerView.frame = CGRectMake(0, kScreenHeight - 64, kScreenWidth, 244);
[pickerView hiddenPickerView];
return pickerView;
}

#pragma mark - lazy
- (NSArray *)citysArray {
if (!_citiesArray) {
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"cities.plist" ofType:nil];
_citiesArray = [NSArray arrayWithContentsOfFile:filePath];
}
return _citiesArray;
}

#pragma mark - init
- (instancetype)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {

self.provinceIndex = 0;
[self initSubViews];
}
return self;
}

- (void)initSubViews {
UIPickerView *picker = [[UIPickerView alloc] init];
picker.dataSource = self;
picker.delegate = self;
[self addSubview:picker];
self.pickerView = picker;
}

#pragma mark - UIPickerViewDataSource
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {
return 2;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {
if (component == 0) {
return self.citysArray.count;
} else {
return [self.citysArray[self.provinceIndex][@"cities"] count];
}
}

#pragma mark - UIPickerViewDelegate
- (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *title = nil;
if (component == 0) {
title = self.citysArray[row][@"name"];
} else {
title = self.citysArray[self.provinceIndex][@"cities"][row];
}
return title;
}

- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

if (component == 0) {
self.provinceIndex = [pickerView selectedRowInComponent:0];
[self.pickerView reloadComponent:1];
[self.pickerView selectRow:0 inComponent:1 animated:YES];
}

}

@end


                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息