Гарантирует ли блок @syncronized в Objective-C выполнение блока полностью до переключения контекста для выполнения другого фрагмента кода? - PullRequest
0 голосов
/ 11 июня 2019

У меня есть источник данных для UITableView.Иногда я получаю indexOutOfBound исключение в методе cellForRowAt, потому что это может произойти, когда метод tableView's numberOfRowsInSection вызвал и затем переключает контекст, и там по какой-то причине элементы в dataSource необходимо обновить (удаляет определенные элементы и добавляет обновленныеверсии этих элементов), но когда он просто удаляет элементы и перед добавлением новых элементов контекст переключается обратно и пытается загрузить ячейки, но затем некоторые элементы удаляются, поэтому выдается исключение.

Я хочу удалить и добавить привязку в блоке, чтобы он менял контекст только после выполнения полного блока, т. Е.

[self removeObjects:@[ lastUserChatMessage ]]; lastUserChatMessage.state = KUSChatMessageStateFailed; [self upsertObjects:@[ lastUserChatMessage ]];

Я хочу, чтобы контекст никогда не переключался после первого утверждения.Он должен выполняться до последнего оператора.

Может ли блок @syncronized служить этой цели?Но помните, что все сделано в главной теме.

1 Ответ

1 голос
/ 11 июня 2019

Я не думаю, что это имеет большой смысл в вашем случае. В табличном представлении можно выбрать вызов любого из методов источника данных в любой момент времени. Вы должны заботиться о своих данных, чтобы они были последовательными. Обычно, когда вы изменяете свой источник данных, вы должны вызывать reloadData или выполнять процедуру начала / конца обновлений в табличном представлении. Поскольку табличное представление работает в основном потоке, вы должны делать то же самое при работе с данными.

Так что, если вы работаете с несколькими потоками или каким-либо образом неконтролируемо изменяете свой источник данных, вам всегда следует создавать копию, когда вы закончите. Затем используйте эту копию в качестве источника данных и перезагрузите табличное представление. В худшем случае вы должны сделать что-то вроде:

- (void)setNewData:(NSArray *)newData {
    NSArray *duplicate = [newData copy];
    dispatch_async(dispatch_get_main_queue(), ^(void){
        self.dataArray = duplicate;
        [self.tableView reloadData];
    });
}

В этом случае self.dataArray следует использовать в методах источника данных табличного представления, и это никогда не должно вас подвести.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...