2

I have a view controller that lists some data in an UITableView. To get the data downloaded I use ASIHTTPRequest which methods I have put in another class.

In my view controller I have setup the appropriate delegates to handle the data that is being retrieved from ASIHTTPRequest. So from my view controller in - viewDidLoad I alloc and init my class that holds the ASIHTTPRequest methods like so:

self.officesParser = [[[OfficesParser alloc] init] autorelease]; // retained property

Then in - viewDidAppear: I call [officesParser downloadOffices];

My - downloadOffices method looks like this:

- (void)downloadOffices {

    // 1. Downloaded offices.json
    NSURL *officesUrl = [NSURL URLWithString:@"http://example.com/example.json"];
    ASIHTTPRequest *officesRequest = [ASIHTTPRequest requestWithURL:officesUrl];

    // Always ask the server if there is new content available, 
    // If the request fails, use data from the cache even if it should have expired.
    [officesRequest setCachePolicy:ASIAskServerIfModifiedCachePolicy|ASIFallbackToCacheIfLoadFailsCachePolicy];

    // Store the cache permanently
    [officesRequest setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];

    [officesRequest setTag:1];

    OfficesViewController *vc = [[OfficesViewController alloc] init];
    [officesRequest setDelegate:vc];
    [vc release];
    [officesRequest startAsynchronous];
}

Everytime after calling the [officesParser downloadOffices] method I get:

*** -[OfficesViewController respondsToSelector:]: message sent to deallocated instance 0x6a2f6c0

What am I doing wrong here?

Peter Warbo
  • 11,136
  • 14
  • 98
  • 193

1 Answers1

3

You want vc to be delegate for officesRequest, however, after you allocate and initialize vc and set it to be the delegate, you immediately release it. Please note that delegate properties are usually assign, not retain. You are then responsible for keeping your delegate object in existence until no longer needed. So, if you plan to send messages to it in a near future, you can't immediately release it.

MiguelB
  • 1,913
  • 18
  • 20
  • So what says in this post is "wrong" then? http://stackoverflow.com/questions/3924484/how-to-set-a-delegate-in-a-different-class/3924570#3924570 – Peter Warbo Jul 31 '11 at 09:22
  • @Peter Warbo: Yes, that other question does't handle memory management correctly (unless it's a retaining property). – Eiko Jul 31 '11 at 09:28
  • @Peter Warbo: Well, if it is released immediately I wouldn't expect it to work. But I checked the documentation for NSXMLParser (http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSXMLParser_Class/Reference/Reference.html) and it says the following in the setDelegate instance method: "delegate: An object that is the new delegate. It is not retained." – MiguelB Jul 31 '11 at 09:30
  • So, how would I properly handle my vc object memory-wise? Should I `autorelease` it? – Peter Warbo Jul 31 '11 at 09:36
  • 1
    That is up to you, really. But sometimes `autorelease` might be too soon. One thing you could do is set `vc` to another property that has a retain policy (you would then place a release call in -dealloc). – MiguelB Jul 31 '11 at 09:52
  • I'm curious though. Because in my `vc` I have a property for the `OfficesParser`. And in the `OfficesParser` I have a property for the `vc`. Will there not be like some kind of weird infinite recursion? – Peter Warbo Jul 31 '11 at 14:41
  • Yes, probably, and the delegate pattern doesn't like that. Its hard to say how you should set up things, since I can't see the whole code. But brush up a bit on delegation patterns, and it should become clear to you. – MiguelB Aug 02 '11 at 11:27