将2个组件一起滚动时,UIPickerView崩溃

时间:2013-04-21 13:21:30

标签: ios objective-c crash uipickerview nszombies

实际上,之前我曾问过同样的问题,但我还没有办法解决它,所以我又来了。

我的情况:

我有一个带有2个相关组件的UIPickerView,第二个或右侧组件中行的数量和内容随着第一个或左侧组件中当前选定的行而变化,这是非常常见且有用的UIPickerView的功能。

现在,如果我使用2个拇指将两个组件一起滚动,我的应用程序很快就会崩溃,很快就会有以下信息:

*** Terminating app due to uncaught exception of class '_NSZombie_NSException'
libc++abi.dylib: terminate called throwing an exception

具有讽刺意味的是,我无法调试它。

实际上,如果我在pickerView:didSelectRow:inComponent方法中添加断点,我甚至无法快速滚动两个组件,因为每次我将手指放在屏幕上时它都会在断点处停止。 / p>

我只能猜测原因是当滚动第一个组件时,第二个组件中假定的行数不断变化,但同时,UIPickerView要求第二个组件的标题和编号然后就崩溃了。

但我没有找到任何可用于判断组件是否正在滚动的方法。因此,我无法找到正确的时间来拒绝pickerView的{​​{1}}和delegate对第二个组件的请求。

有没有人遇到类似的情况?

感谢您的帮助!我非常感激!


在我的代码中,错误与dataSource有关,因此我删除了与typePicker无关的所有其他代码。

此处,typePickertype是核心数据中的两个实体,名为detailTypes的多对多关系从detailstype

例如,如果类型为“Nations”,detailsTypes将是“美国”,“法国”,“中国”等。

因此在detailTypes中,第一个或左侧组件显示所有类型实体,第二个或右侧组件根据第一个组件中当前选择的类型显示相应的typePicker个实体。

detailTypes中的两个组件的第一行始终为“无”,以允许用户不选择特定类型,这就是代码中有许多“+1”的原因。

typePicker

2 个答案:

答案 0 :(得分:6)

崩溃是由于你的代表中的这一行

NSUInteger majorTypeRow = [self.typePicker selectedRowInComponent:0] - 1;

正如其他人指出的那样,你需要保留两个单独的数组或对象,它们可以为各个组件提供dataSource。

您有一个majorType和detailType。您可以拥有majorTypesselectedMajorType的数组。保留额外的selectedMajorType无需使用selectedRowInComponent:,也不会再崩溃该应用。

#pragma mark - UIPickerViewDataSource

- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 2;
}

- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    NSInteger rows = 0;
    if (component) {
         rows = [self.selectedMajorType.minorTypes count];
    }else{
        rows = [self.majorTypes count];
    }
    return rows+1;
}

UIPickerViewDelegate实施

- (NSString *)pickerView:(UIPickerView *)pickerView
             titleForRow:(NSInteger)row
            forComponent:(NSInteger)component
{
    row--;
    NSString *title = @"None";
    if (component) {
        NSArray *minorTypes = [self.selectedMajorType.minorTypes allObjects];
        if (row >= 0 && row < [minorTypes count]) {
            MinorType *minorType = minorTypes[row];
            title = minorType.name;
        }
    }else{
        if(row>=0 && row < [self.majorTypes count]){
            MajorType *majorType = self.majorTypes[row];
            title =  majorType.name;
        }
    }
    return title;
}

- (void)pickerView:(UIPickerView *)pickerView
      didSelectRow:(NSInteger)row
       inComponent:(NSInteger)component
{
    row--;
    if (component==0) {
        if (row >= 0 && row < [self.majorTypes count]) {
             self.selectedMajorType = self.majorTypes[row];
        }else {
           self.selectedMajorType = nil;
        }

        [pickerView reloadComponent:1];
    }
}

Demo Source Code

答案 1 :(得分:1)

好的,我想我明白了这个问题:

将两个组件一起滚动的问题在于,由于您使用数据关系创建的依赖性,UIPickerView数据源可能会发生变化。我认为您需要创建两个分别代表左右的数组,并根据您更改的组件重新填充!

通过查看类似问题可以找到解决方案! UIPickerView with two components crashes when scrolling both

此外,关于检查您的UIPickerView是否正在滚动,您只需设置一个计时器。这里有一个有用的链接:Determining if UIPickerWheel is scrolling!通过检查当前行是否匹配,您可以(在短时间内)判断用户是否已移动轮子!

我希望这是明确和有用的!