Objective C: How to release delegates in this situation
Asked Answered
T

3

5

I am using custom delegate objects to do some cleanup tasks after a request finishes. ASIHTTPRequest doesn't retain delegates so I can't autorelease them. Right now this is how I am allocating and releasing the delegates.

App Delegate

MyDelegate *delegate = [[MyDelegate alloc] init];   
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request setDelegate:delegate];

MyDelegate.m

- (void)requestFinished:(ASIHTTPRequest *)request
{
    [self release];
}

- (void)requestFailed:(ASIHTTPRequest *)request
{
    [self release];
}

Is there a better way to do this? Having the delegates release themselves seems ugly and Xcode's build and analyze feels uncomfortable with what I'm doing.

Turnout answered 5/1, 2011 at 22:5 Comment(0)
S
4

A simple approach would be to maintain a mutable set of delgates for each active request in your main controller (the app delegate, in this case):

@interface MyAppController
{
    NSMutableSet * activeDelegates;
}
@end

@implementation MyAppController

- (id)init
{
    if ((self = [super init]) == nil) { return nil; }
    activeDelegates = [[NSMutableSet alloc] initWithCapacity:0];
    return self;
}

- (void)dealloc
{
    [activeDelegates release];
}

- (void)createRequest
{
    MyDelegate *delegate = [[MyDelegate alloc] init];
    [activeDelegates addObject:delegate];
    [delegate release];

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];

    ...
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    MyDelegate *delegate = [request delegate];
    [delegate doSomething];
    [activeDelegates removeObject:delegate];
{

- (void)requestFailed:(ASIHTTPRequest *)request
{
    [activeDelegates removeObject:[request delegate]];
}

@end
Salicaceous answered 5/1, 2011 at 23:7 Comment(0)
D
4

Why do you have a separate class purely to be a delegate? That's not how delegate objects typically work. Normally the controller that created the ASIHTTPRequest becomes the delegate, at which point you don't have to worry about releasing it because it will outlive the ASIHTTPRequest already (and if your controller gets dealloced before the ASIHTTPRequest is done, you need to cancel the request).

Doting answered 5/1, 2011 at 22:9 Comment(4)
Because the delegates need to delete associated managed objects from my core data store (only when a request is successful). Each request therefore has to have a unique delegate, which contains information about the associated managed object.Turnout
Another approach you might consider, then, is taking advantage of the request's userInfo dictionary to store that information you need. See allseeing-i.com/ASIHTTPRequest/…Bunde
Also from Sixten Otto's link: "... where you want to parse the response in the background, create a minimal subclass of ASIHTTPRequest for each type of request, and override requestFinished: and failWithProblem:"Salicaceous
Thanks for the answers! I tried both approaches and ended up going with the userInfo dictionary.Turnout
S
4

A simple approach would be to maintain a mutable set of delgates for each active request in your main controller (the app delegate, in this case):

@interface MyAppController
{
    NSMutableSet * activeDelegates;
}
@end

@implementation MyAppController

- (id)init
{
    if ((self = [super init]) == nil) { return nil; }
    activeDelegates = [[NSMutableSet alloc] initWithCapacity:0];
    return self;
}

- (void)dealloc
{
    [activeDelegates release];
}

- (void)createRequest
{
    MyDelegate *delegate = [[MyDelegate alloc] init];
    [activeDelegates addObject:delegate];
    [delegate release];

    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request setDelegate:self];

    ...
}

- (void)requestFinished:(ASIHTTPRequest *)request
{
    MyDelegate *delegate = [request delegate];
    [delegate doSomething];
    [activeDelegates removeObject:delegate];
{

- (void)requestFailed:(ASIHTTPRequest *)request
{
    [activeDelegates removeObject:[request delegate]];
}

@end
Salicaceous answered 5/1, 2011 at 23:7 Comment(0)
T
0

If You don't want to create a "controller" class for all your delegate instances, i would still at least follow the memory convention rules, and release the delegate immediately after setting it to asihhtprequest. Then i would include a propery in the delegate, something with a name managesItsOwnLifetime (BOOL) and on setting this to YES i would do a [self retain] ...

Tintinnabulum answered 5/1, 2011 at 22:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.