reloadRowsAtIndexPaths:withRowAnimation: crashes my app

后端 未结 8 1984
谎友^
谎友^ 2021-02-07 01:33

I got a strange problem with my UITableView: I use reloadRowsAtIndexPaths:withRowAnimation: to reload some specific rows, but the app crashes with an seemingly unre

8条回答
  •  独厮守ぢ
    2021-02-07 02:00

    I had this problem which was being caused by a block calling reloadRowsAtIndexPaths:withRowAnimation: and a parallel thread calling reloadData. The crash was due to reloadRowsAtIndexPaths:withRowAnimation finding an empty table even though I'd sanity checked numberOfRowsInSection & numberOfSections.

    I took the attitude that I don't really care if it causes an exception. A visual corruption I could live with as a user of the App than have the whole app crash out.

    Here's my solution to this which I'm happy to share and would welcome constructive criticism. If there's a better solution I'm keen to hear it?

    - (void) safeCellUpdate: (NSUInteger) section withRow : (NSUInteger) row {
        // It's important to invoke reloadRowsAtIndexPaths implementation on main thread, as it wont work on non-UI thread
        dispatch_async(dispatch_get_main_queue(), ^{
            NSUInteger lastSection = [self.tableView numberOfSections];
            if (lastSection == 0) {
                return;
            }
            lastSection -= 1;
            if (section > lastSection) {
                return;
            }
            NSUInteger lastRowNumber = [self.tableView numberOfRowsInSection:section];
            if (lastRowNumber == 0) {
                return;
            }
            lastRowNumber -= 1;
            if (row > lastRowNumber) {
                return;
            }
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
            @try {
                if ([[self.tableView indexPathsForVisibleRows] indexOfObject:indexPath] == NSNotFound) {
                    // Cells not visible can be ignored
                    return;
                }
                [self.tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone];
            }
    
            @catch ( NSException *e ) {
                // Don't really care if it doesn't work.
                // It's just to refresh the view and if an exception occurs it's most likely that that is what's happening in parallel.
                // Nothing needs done
                return;
            }
        });
    }
    

提交回复
热议问题