Najeeb ur Rehman
Najeeb ur Rehman

Reputation: 413

Is @syncronized block in Objective-C guarantees to execute the block completely before context is switched to execute other piece of code?

I have a datasource for the UITableView. Sometimes I get an indexOutOfBound exception in cellForRowAt method because it can happen when the tableView's numberOfRowsInSection method has invoked and then context switches and there for some reason the items in the dataSource needs to update(removes specific items and add updated versions of these items) but when it just removes the items and before addition of new items the context is switched back and try to load cells but then some items are removed so it throws an exception.

I want to make bind removal and addition in a block so it only change context after executing the complete block i.e.

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

I want that the context never switch after the first statement. It must execute till the last statement.

Is @syncronized block can serve this purpose? But remember all is done in Main Thread.

Upvotes: 0

Views: 121

Answers (1)

Matic Oblak
Matic Oblak

Reputation: 16774

I don't think this makes much sense in your case. Table view may choose to call any of the data source methods at any given time. You need to take care of your data so that it is consistent. Generally when you alter your data source you should call reloadData or do the begin/end updates procedure on the table view. Since the table view works on main thread you should do the same when dealing with data.

So if you are working on multiple threads or anyhow uncontrollably modify your data source then you should always create a copy when you are done. Then use this copy as a data source and reload the table view. In worst case scenario you should do something like:

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

In this case self.dataArray should be used in table view data source methods and it should never fail you.

Upvotes: 1

Related Questions