iOS_Developer
iOS_Developer

Reputation: 183

mainThread implementaion in iOS

I am doing some stuffs in objective C (iOS) but stuck in a crash which happens sometimes only. Here is my code (which is inside a block getting called when a txn gets complete).

        dispatch_async(dispatch_get_main_queue(), ^{
        //array which is used to show table view rows
        //someOtherArray is array which has data from response of a txn
        myArray = [[NSMutableArray alloc] initWithArray:someOtherArray] ;
        [self callSomeMethod] ;
    }) ;

the callSomeMethod is as below

- (void) callSomeMethod`{
dispatch_async(dispatch_get_main_queue(), ^{
    //reload tableview here
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic] ;
}) ;
}

my questions: 1. is this okay to call mainThread inside a main thread, as here I am calling a method callSomeMethod and I hv another main thread inside that method ?

  1. By the time my table view is busy in reloading the section 0, the response came again and the content of myArray got changed so the application is crashing.

Any help is appreciated.

Thanks a ton.

EDIT: My exact requirements are. 1. Have multiple sections 2. Can move the sections up n down 3. Have multiple txns which are updating frequently and I hv to update tableview accordingly 4. Reloading the tableview sections when I am getting the response from server and that s changing the contents of data source array

Upvotes: 2

Views: 281

Answers (3)

Ben Resplendent
Ben Resplendent

Reputation: 408

It can be dangerous to call a table update asynchronously after you've updated the data that you're performing the data update for.

In your example, you are essentially doing the following:
1) myArray = [[NSMutableArray alloc] initWithArray:someOtherArray];
2) dispatch asynchronously to main
3) [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationAutomatic];

Say shortly after, you tried doing something like the following:
4) [myArray insertObject:newObject atIndex:0];
5) dispatch asynchronously to main
6) [self.tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:0 inSection:0]] withRowAnimation:UITableViewRowAnimationAutomatic];

In the above examples, you need 3) to happen after 1), but not after 4). If 3) happens after 4), 3)'s refresh will cause the refresh you desired, as well as the row insert. By the time 6) is then hit, it will be trying to insert a row that has already been inserted, and the app will crash.

Because of your asynchronous dispatch's on 2) and 5), the above scenario can happen, where 3) can get called after 4).

To fix this, get rid of the asynchronous dispatches between your data updates and table refreshes. In the above example, that would involve getting rid of 2), and any other similar instances of it, such as 5).

Upvotes: 1

Ian MacDonald
Ian MacDonald

Reputation: 14010

Using dispatch_sync to synchronously launch to the main thread from the main thread will halt your app. Using dispatch_async is safe from any thread.

If you are having trouble with table data updating while the table is loading cells, you'll have to stop that from happening. Store your data somewhere else and only call reloadData once you've fully updated.

Upvotes: 0

fyell
fyell

Reputation: 221

Yes it is ok to call dispatch_async to the main queue again. However, keep in mind what dispatch_async does. Since it's performing asynchronously, callSomeMethod will not occur in the same execution flow as the first dispatch_async call. As for your crashing, does callSomeMethod need to dispatch_async to the main queue? It might help to remove the dispatch_async in callSomeMethod and just ensure that whoever is calling callSomeMethod does it on the main thread.

Upvotes: 0

Related Questions