1
votes

I'm having a problem with using delegate inside Blocks.

With ARC on, this is example to show the issue.

- (void)whatsGoingOn {

    NSString *address = @"someAddress";    

    //setting for request
    NSURL *requestURL               = [NSURL URLWithString:address];    
    __weak ASIHTTPRequest *request  = [ASIHTTPRequest requestWithURL:requestURL];    

    [delegate_ postDelegateMethod]; //This delegation works fine       

    [request setCompletionBlock:^{     
        [delegate_ postDelegateMethod]; //This delegation doesn't work        
    }];

    [request startAsynchronous];
}

It seems that I can't post delegation inside Blocks. What should I do in this situation?

I can use notification instead, but I don't feel that's a good way to go.

This is the head part of the class. If I don't use weak, the request part will make a retain cycle, so not sure what to do yet.

@interface URLFilter : NSObject {
      id __weak                   delegate_;
}
@property (nonatomic, weak) id                              delegate;


@implementation URLFilter
@synthesize delegate    = delegate_;

*SOLVED!!!

It worked by making another __block id blockDelegate. And, there is no memory leak either.

- (void)whatsGoingOn {

    NSString *address = @"someAddress";    

    //setting for request
    NSURL *requestURL               = [NSURL URLWithString:bitlyAPIAddress];    
    __weak ASIHTTPRequest *request  = [ASIHTTPRequest requestWithURL:requestURL];    

    //set blockDelegate since delegate_ will be gone inside blocks
    __block id blockDelegate        = delegate_;

    [request setCompletionBlock:^{        

        //it works
        [blockDelegate postDelegateMethod];
    }];

    [request startAsynchronous];
}

UPDATE

I looked at the code again, and the issue might be caused by this block method outside of that whatsGoingOn method.

Inside of this twitter api block method, I call that whatsGoingOn method, and inside of whatsGoingOn method, I put asihttprequest block method.

Strangely, if I use usual delegate method of asihtttprequest in side of blocks, it crushes, that's why I picked up block method of asihttprequest.

//request tweet data
[twRequest performRequestWithHandler:^(NSData *responseData,
                                         NSHTTPURLResponse *urlResponse,
                                         NSError *error) {
    [self whatsGoingOn];                            
}];
3
how is delegate_ declared and initialized?danh
By the way, where are you actually setting your delegate?borrrden
Yes, it works outside [request setCompletionBlock:^{Non Umemoto

3 Answers

3
votes

Pretty sure that the problem is the __weak qualifier on the request. If I'm right, you won't get the delegate invocation in the block and you won't get anything else - the request's copy of the block is getting cleaned up before it has a chance to run.

- (void)whatsGoingOn {

    NSString *address = @"someAddress";    

    //setting for request
    NSURL *requestURL        = [NSURL URLWithString:address];    
    ASIHTTPRequest *request  = [ASIHTTPRequest requestWithURL:requestURL];    

    [request setCompletionBlock:^{
        NSLog(@"proof we got here.  delegate = %@", self.delegate);   
        [self.delegate postDelegateMethod]; // This delegation _should_ work        
    }];

    [request startAsynchronous];
}
2
votes

NEVER count on weak references sticking around. Assuming the request is created inside the method in your code, it will be immediately deallocated before the next line even runs.

With the update, I see the reference cycle. What you should do is make request an iVar. Then before the block do this:

ASIHTTPRequest __weak *weakRequest = mRequest;

Then refer to the weak request instead of the strong one.

1
votes

It worked by making another __block id blockDelegate. And, there is no memory leak either. :)

//setting for request
NSURL *requestURL               = [NSURL URLWithString:bitlyAPIAddress];    
__weak ASIHTTPRequest *request  = [ASIHTTPRequest requestWithURL:requestURL];    

//set blockDelegate since delegate_ will be gone inside blocks
__block id blockDelegate        = delegate_;

[request setCompletionBlock:^{        

    //it works
    [blockDelegate postDelegateMethod];
}];

[request startAsynchronous];