1

我在 Blocks 中使用委托时遇到问题。

在 ARC 开启的情况下,这是显示问题的示例。

- (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];
}

看来我不能在 Blocks 中发布委托。在这种情况下我该怎么办?

我可以改用通知,但我觉得这不是一个好方法。

这是班级的主要部分。如果我不使用weak,请求部分会产生一个retain循环,所以还不知道该怎么做。

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


@implementation URLFilter
@synthesize delegate    = delegate_;

*已解决!!!

它通过制作另一个 __block id blockDelegate 来工作。而且,也没有内存泄漏。

- (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];
}

更新

我再次查看代码,问题可能是由 whatsGoingOn 方法之外的这个块方法引起的。

在这个 twitter api 块方法内部,我称之为 whatsGoingOn 方法,在 whatsGoingOn 方法内部,我放置了 asihttprequest 块方法。

奇怪的是,如果我在块的一侧使用通常的 asihtttprequest 委托方法,它就会崩溃,这就是我选择 asihttprequest 的块方法的原因。

//request tweet data
[twRequest performRequestWithHandler:^(NSData *responseData,
                                         NSHTTPURLResponse *urlResponse,
                                         NSError *error) {
    [self whatsGoingOn];                            
}];
4

3 回答 3

3

很确定问题是请求上的 __weak 限定符。如果我是对的,您将不会在块中获得委托调用,并且您不会得到任何其他东西 - 请求的块副本在它有机会运行之前被清理。

- (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];
}
于 2012-06-20T02:02:34.100 回答
2

永远不要指望弱引用仍然存在。假设请求是在代码中的方法内部创建的,它将在下一行运行之前立即被释放。

随着更新,我看到了参考周期。你应该做的是制作request一个 iVar。然后在块之前这样做:

ASIHTTPRequest __weak *weakRequest = mRequest;

然后参考弱请求而不是强请求。

于 2012-06-20T02:05:55.550 回答
1

它通过制作另一个 __block id blockDelegate 来工作。而且,也没有内存泄漏。:)

//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];
于 2012-06-21T00:02:46.053 回答