Ios 如何保护tableview在InsertRowsatindExpath和设备旋转期间不崩溃

Ios 如何保护tableview在InsertRowsatindExpath和设备旋转期间不崩溃,ios,uitableview,Ios,Uitableview,如果在行动画期间不断旋转设备,此示例应用程序将在一段时间后崩溃。我的真实应用程序有时甚至在行动画的第一次旋转时崩溃 我应该如何保护我的应用程序在使用同步行动画进行旋转时不会崩溃?请不要建议在动画完成之前禁止旋转。数据源依赖于网络抓取,这可能需要1到30秒的时间,具体取决于用户网络,如果用户看到应用程序在启动后可以更好地在横向视图中查看,则希望旋转设备 - (void)viewDidAppear:(BOOL)animated { [super viewDidAppear:animated]

如果在行动画期间不断旋转设备,此示例应用程序将在一段时间后崩溃。我的真实应用程序有时甚至在行动画的第一次旋转时崩溃

我应该如何保护我的应用程序在使用同步行动画进行旋转时不会崩溃?请不要建议在动画完成之前禁止旋转。数据源依赖于网络抓取,这可能需要1到30秒的时间,具体取决于用户网络,如果用户看到应用程序在启动后可以更好地在横向视图中查看,则希望旋转设备

- (void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{

        for (int i = 0; i < 30; i++) {

            [NSThread sleepForTimeInterval:0.2]; // imitates fetching and parsing
            [self.array addObject:[NSString stringWithFormat:@"cell number %d", i]];

            dispatch_async(dispatch_get_main_queue(), ^{

                // perform on main
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
                [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            });
        }
    });
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.array.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell" forIndexPath:indexPath];

    // Configure the cell...
    cell.textLabel.text = self.array[indexPath.row];

    return cell;
}

- (NSMutableArray *)array
{
    if (!_array) {
        _array = [[NSMutableArray alloc] init];
    }
    return _array;
}
你能换衣服吗

dispatch_async(dispatch_get_main_queue(), ^{

                // perform on main
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
                [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            });
与:


你基本上创造了一个竞赛条件

问题是,您正在后台线程中操作
self.array
,而
self.tableView insertRowsAtIndexPaths
正在主线程上运行,并且将访问
self.array

因此,在某个时刻,
self.tableView insertRowsAtIndexPaths
(或由此调用的其他tableView方法)正在主线程上运行,期望在
self.array
中有一定数量的对象,但后台线程进入其中并添加另一个对象

要修复模拟,请执行以下操作:

dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{

    for (int i = 0; i < 30; i++) {

        [NSThread sleepForTimeInterval:0.2]; // imitates fetching and parsing
        NSString *myNewObject = [NSString stringWithFormat:@"cell number %d", i]];

        dispatch_async(dispatch_get_main_queue(), ^{

            // perform on main
            [self.array addObject: myNewObject];
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
            [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        });
    }
});
dispatch\u queue\u t queue=dispatch\u get\u global\u queue(dispatch\u queue\u PRIORITY\u DEFAULT,0);
调度异步(队列^{
对于(int i=0;i<30;i++){
[NSThread sleepForTimeInterval:0.2];//模拟获取和解析
NSString*myNewObject=[NSString stringWithFormat:@“单元号%d”,i]];
dispatch\u async(dispatch\u get\u main\u queue()^{
//在主干道上表演
[self.array addObject:myNewObject];
NSIndexPath*indexPath=[NSIndexPath indexPathForRow:i第1节:0];
[self.tableView insertRowsAtIndexPaths:@[indexath]带行动画:uitableview行动画自动];
});
}
});

能否请您尝试使用同步:-

它声明了代码块周围的关键部分。在多线程代码中,@synchronized保证在任何给定时间块中只有一个线程可以执行该代码

@synchronized(self.tableView) {
 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{

        for (int i = 0; i < 30; i++) {

            [NSThread sleepForTimeInterval:0.2]; // imitates fetching and parsing
            [self.array addObject:[NSString stringWithFormat:@"cell number %d", i]];

            dispatch_async(dispatch_get_main_queue(), ^{

                // perform on main
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
                [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            });
        }
    });                                    
                                }
@synchronized(self.tableView){
调度队列=调度获取全局队列(调度队列优先级默认为0);
调度异步(队列^{
对于(int i=0;i<30;i++){
[NSThread sleepForTimeInterval:0.2];//模拟获取和解析
[self.array addObject:[NSString stringWithFormat:@“单元号%d”,i]];
dispatch\u async(dispatch\u get\u main\u queue()^{
//在主干道上表演
NSIndexPath*indexPath=[NSIndexPath indexPathForRow:i第1节:0];
[self.tableView insertRowsAtIndexPaths:@[indexath]带行动画:uitableview行动画自动];
});
}
});                                    
}

希望有帮助。如果我们必须使用其他解决方案,请告诉我。

不确定设备旋转是否会对其产生影响请参阅我关于比赛条件的回答。旋转是一种转移注意力的方法,但由于改变了两个线程上发生的事情的时间,它发生的可能性可能会增加。我发现的唯一区别是UITableViewRowAnimationNone,这没有任何效果。应用程序仍在崩溃。请尝试在dispatch_async(queue,^{in ViewDidapperi不知道@synchronized)结束时重新加载您的tableview。但应用程序仍然与您的代码一起崩溃。Mike Pollard的建议实际上有效。根据我对@synchronized和locks的了解,这不是一个解决方案。请参阅
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{

    for (int i = 0; i < 30; i++) {

        [NSThread sleepForTimeInterval:0.2]; // imitates fetching and parsing
        NSString *myNewObject = [NSString stringWithFormat:@"cell number %d", i]];

        dispatch_async(dispatch_get_main_queue(), ^{

            // perform on main
            [self.array addObject: myNewObject];
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
            [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
        });
    }
});
@synchronized(self.tableView) {
 dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_async(queue, ^{

        for (int i = 0; i < 30; i++) {

            [NSThread sleepForTimeInterval:0.2]; // imitates fetching and parsing
            [self.array addObject:[NSString stringWithFormat:@"cell number %d", i]];

            dispatch_async(dispatch_get_main_queue(), ^{

                // perform on main
                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
                [self.tableView insertRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];
            });
        }
    });                                    
                                }