先来个预览
在下面的代理中设置每一列每一行的数据
- (nullable NSString*)pickerView:(UIPickerView*)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component__TVOS_PROHIBITED;
如果在该代理中设置城市和区的值时,使用[picker ViewselectedRowInComponent:0]来获取第一列索引来更新第二列的数据源,同时滑动就会出现数组越界的错误,因此应该在设置列里的row数量的时候,使用一个全局变量保存一下这一个数据源模型,更新下一列数据的时候直接去保存的变量里取数据,而不是从动态获取第一列、第二列的所以去model拿数据,详情见代码。
数据源Model:
@class City;
@interface Province :NSObject
@property (strong, nonatomic) NSString *province;
@property (strong, nonatomic) NSArray <City *>*city;
@end
@interface City :NSObject
@property (strong, nonatomic) NSString *cityName;
@property (strong, nonatomic) NSArray *county;
@end
解决数组越界重点代码:
使用变量保存中间数据模型:
@property (strong, nonatomic) Province *_oldPro;
@property (strong, nonatomic) City *_oldCity;
设置row数量的代理(numberOfRowsInComponent)
- (NSInteger)pickerView:(UIPickerView*)pickerView numberOfRowsInComponent:(NSInteger)component{
if(component ==0) {
return _model.data.count>0?_model.data.count:0;
}else if(component ==1){
NSInteger firstRow = [pickerView selectedRowInComponent:0];
_oldPro=_model.data[firstRow]; //保存一下省份的数据模型
return _oldPro.city.count>0?_oldPro.city.count:0;
}else{
NSInteger firstRow = [pickerView selectedRowInComponent:0];
NSInteger secondRow = [pickerView selectedRowInComponent:1];
if(_model.data[firstRow].city.count>0){
_oldCity=_oldPro.city[secondRow]; //保存一下城市的数据模型
return _oldCity.county.count;
}else{
_oldCity=nil;
}
}
return 0;
}
设置row数据的代理(titleForRow)
- (NSString*)pickerView:(UIPickerView*)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component{
if(component ==0) {
return _model.data[row].province;
}else if(component ==1){
//直接从保存的中间省份模型中拿数据,不要动态的获取索引后再去找到这个省份模型
return _oldPro.city[row].cityName?_oldPro.city[row].cityName:@"";
}else{
//直接从保存的中间城市模型中拿数据
return _oldCity.county[row]?_oldCity.county[row]:@"";
}
return@"";
}
改成这样,数组越界问题就解决了
PS: 我一开始的解决办法是和网上很多帖子上说的一样,动态获取row索引后,判断下当前索引是不是小于数据源模型对应城市的count,如果大于说明了数据源还没更新,此时已经越界,但是这个方法用于有区的三列选择器,并不能解决问题。。。