0

I set the view controller to be the delegate of a local variable ASIHTTPFormDataRequest request.

But, tapping "Back" before the request has finished, pops and deallocates the view controller. So, when the request completes and sends the message -requestDidFinish: to the now nonexistent delegate, the app crashes with an EXEC_BAD_ACECESS exception.

How do I fix this crash?

  1. One way I could think of solving this is to set the delegate to nil immediately after the navigation controller pops it. But, if that's the solution, how do I do that? (ARC's weak references would be sweet right now.)

  2. Another way I can think of is to make request an instance variable of the view controller and call [request clearDelegatesAndCancel]; [request release]; in the view controller's dealloc method. This approach is outlined in ASIHTTPRequest Example Code, but I've been advised it's best to make requests local variables instead of instance variables. And, this particular view controller is a settings table view controller and has 13 switches. For automatic saving to the server, each switch creates & sends a new request each time it's toggled. If I made ivars, I'd have to make 13. That's a lot of code!

Thoughts? Ideas?

ma11hew28
  • 121,420
  • 116
  • 450
  • 651

2 Answers2

3

I think the first question is: What do you want to happen if the user presses back after pressing a switch? ie. Should the http request be cancelled, or is it important that the request does get to the server? I'll assume for now that you do want to cancel them, as that seems to be implied in your question.

I've been advised it's best to make requests local variables instead of instance variables

I'm not sure if that was good advice - you almost always want requests to not be local variables so you can cope with cases like this.

For your case, you could consider using an NSOperationQueue.

Rough steps to do this would be:

  1. Create an NSOperationQueue in your view controller init.
  2. When you want to make a http request, add it to the ASIHTTPRequest queue instead of call startAsynchronous
  3. In dealloc, iterate the objects in the queue, calling [request clearDelegatesAndCancel]; for each one, and then release the queue.

That should solve the crash without needing 13 ivars!

JosephH
  • 37,173
  • 19
  • 130
  • 154
  • Thank you for your solution. This is a nobel & perfectly valid answer, but I chose to [retain the request delegate](http://stackoverflow.com/questions/6515191/asihttprequest-popviewcontrolleranimated-delegate-exec-bad-access/6529829#6529829) like `NSURLConnection` does because I trust Apple's design decisions, it's cleaner, and it allows the requests to continue loading even if the view controller is popped, which is actually what I want. – ma11hew28 Jun 30 '11 at 04:11
0

I solved this by retaining the request delegate like NSURLConnection retains its delegate.

Community
  • 1
  • 1
ma11hew28
  • 121,420
  • 116
  • 450
  • 651