未在iOS 6上第二次设置值。线程问题?

未在iOS 6上第二次设置值。线程问题?,ios,objective-c,multithreading,networking,concurrency,Ios,Objective C,Multithreading,Networking,Concurrency,我正在编写一个iOS应用程序,它使用从服务器检索的数据填充数组,并在选择器视图中显示它 第一次显示视图时,一切都进展顺利;但是,当切换到另一个使用相机扫描内容的视图并使用滑出菜单(使用构建)切换回时,它无法填充阵列。后台任务完成检索记录后,当我们在UI线程上访问它时,会抛出一个NSRangeException,错误为索引0超出空数组的界限 我非常确定后台任务正在运行,并且在我将每个请求记录到服务器时成功地检索到了数据 我认为这可能是并发性和后台线程没有更新变量的问题 据我们测试,这个问题只出现在

我正在编写一个iOS应用程序,它使用从服务器检索的数据填充数组,并在选择器视图中显示它

第一次显示视图时,一切都进展顺利;但是,当切换到另一个使用相机扫描内容的视图并使用滑出菜单(使用构建)切换回时,它无法填充阵列。后台任务完成检索记录后,当我们在UI线程上访问它时,会抛出一个
NSRangeException
,错误为
索引0超出空数组的界限

我非常确定后台任务正在运行,并且在我将每个请求记录到服务器时成功地检索到了数据

我认为这可能是并发性和后台线程没有更新变量的问题

据我们测试,这个问题只出现在iOS 6上,在iOS 7上没有发生,或者至少还没有发生

这是用于检索和设置数组的代码:

dispatch_queue_t queue = dispatch_queue_create("com.aaa.bbb", NULL);
dispatch_async(queue, ^{
    _events = [_wi getEvents:_auth_token];
    dispatch_async(dispatch_get_main_queue(), ^{
        // code to be executed on the main thread when background task is finished
        [_mPicker reloadComponent:0];
        // Set the default on first row
        [self pickerView:_mPicker didSelectRow:0 inComponent:0];
        [pDialog dismissWithClickedButtonIndex:0 animated:YES];
    });
});
这是my
SidebarViewController
中的
prepareforSegue
方法,用于在从滑出菜单中选择项目时在视图之间切换

- (void) prepareForSegue: (UIStoryboardSegue *) segue sender: (id) sender
{
    // Set the title of navigation bar by using the menu items
    NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
    UINavigationController *destViewController = (UINavigationController*)segue.destinationViewController;
    destViewController.title = [[_menuItems objectAtIndex:indexPath.row] capitalizedString];

    if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
        SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
        swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
            UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
            [navController setViewControllers: @[dvc] animated: NO ];
            [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
        };
    }
}
视图从情节提要链接在一起以进行切换

当我尝试从
pickerView:didSelectRow:incomonent:
方法中的
events
数组中检索特定条目时,会发生此错误:

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

    // Set the current id
    _currentId = [NSString stringWithFormat:@"%d", row];
    _currentName = [[_events objectAtIndex:row] objectForKey:@"event_name"];
          -----------^
...
下面是正在运行的线程和调用堆栈的列表

根据我在安卓系统的经验,我认为这可能与我第一次没有正确完成后台任务有关,或者在后台任务之后应该运行的代码第二次与它一起运行

如果有任何建议能帮助我解决这个问题,我将不胜感激


感谢变量
\u events
是从不同的线程访问的,没有任何同步机制

试试这个:

dispatch_queue_t queue = dispatch_queue_create("com.aaa.bbb", NULL);
dispatch_async(queue, ^{
    NSArray* events = [_wi getEvents:_auth_token];
    dispatch_async(dispatch_get_main_queue(), ^{
        _events = [events copy];
        // code to be executed on the main thread when background task is finished
        [_mPicker reloadComponent:0];
        // Set the default on first row
        [self pickerView:_mPicker didSelectRow:0 inComponent:0];
        [pDialog dismissWithClickedButtonIndex:0 animated:YES];
    });
});

另外
\u events
应该是
NSArray
,而不是
NSMutableArray
,以避免此类问题。

谢谢您的回答。它解决了问题!我猜测它必须与变量锁和线程之间的同步有关,但我不确定如何解决它。