Reputation: 183
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 ?
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
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
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
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