views:

130

answers:

2

I am using an UITableView to show some string messages, and I use NSOperationQueue to hold an customized NSOperation which fetchs message in background thread. After one message fetched successfully, customized NSOperation will notify the UITableView controller to show it.

If I click back button on the navigation bar to switch from the UITableView to other view after all message loaded, every thing is OK. But, if i click the back button while some message still loading, an EXC_BAD_ACCESS is throw. I have checked that the exception happened while customized NSOperation notify UITableView controller with performSelectorOnMainThread method. Sound like the target UITableView controller is not invalid after view switched, but I think Navigation Controller will hold the view controller instance. May I know how to resolve this issue? Thanks.

Customized operation is initialized in the UITableView controller with following code:

StatusMessageLoadingOperation *operation = [[StatusMessageLoadingOperation alloc] 
                                            initWithData:person
                                            messageArray:cachedStatusMessages
                                            target:self 
                                            action:@selector(didFinishStatusMessages:)];
[operationQueue addOperation:operation];
[operation release];

The customized NSOperation class will update UITableView with following code:

- (void)main{
    for (int i = 0; i < [[person statusMessages] count]; i++) {
        [target performSelectorOnMainThread:action withObject:messageArray waitUntilDone:NO];
    }
}
A: 

Have you tried calling [operationQueue cancelAllOperations] in your viewWillDisappear method?

Frank Schmitt
Beside calling [operationQueue cancelAllOperations] in viewWillDisappear, need check [super isCancelled] in the main function of customized NSOperation class, if canceled, avoid to call performSelectorOnMainThread to update the UI of tableview. Because tableview's -deallock methods is called while popping a view controllers, the context of tableView has been destroyed. (Refer answer of Alex Reynolds). Thanks to Frank and Alex, my issue has been resolved perfectly.
Yanhua
A: 

Because popping a view controller calls that controller's -dealloc method, you may be releasing your queue too early, and some other part of your application is trying to access the queue or an operation inside it that no longer exists.

My recommendation is to put your NSOperationQueue *myQueue instance into your application delegate.

Use the app delegate's -applicationDidFinishLaunching: and -dealloc methods to initialize and release your queue and its contents.

By separating your queue from the view controller, your queue won't get released when you pop off a view controller from your navigation stack. It and any remaining operations should still be available to the rest of the application.

To make it easier to access your queue, set up the following macro definition:

#define UIAppDelegate ((MyAppDelegate *)[UIApplication sharedApplication].delegate)

You can then use the macro to access your queue as follows, e.g.:

NSLog(@"%@", [[UIAppDelegate myQueue] operations]);

Or, for example:

[[UIAppDelegate myQueue] addOperation:myOperation];
Alex Reynolds