如何正确实现嵌套块? IOS

时间:2014-08-26 10:46:32

标签: ios objective-c objective-c-blocks

通过这个类我发送http请求:

     @interface AsyncRequest()
        @property(strong,nonatomic)NSURLRequest* murlRequest;
        @property(copy) OnCompleted onCompletedBlock;
        @end
        @implementation AsyncRequest
        //Async Request object initialization
        -(instancetype)initWithUrl:(NSString*)urlRequest onCompletedBlock:(OnCompleted) onCompeletedBlock
        {
            self = [super init];
            if(self)
            {
                //blocks


                NSURL* url  = [NSURL URLWithString:[NSStringstringWithFormat:@"%@%@",SERVER_URL,urlRequest]];

                self.onCompletedBlock = onCompeletedBlock;
                self.murlRequest = [NSURLRequest requestWithURL:url];
            }
            return self;
        }
    //call this function to execute the specified request
    -(void)ExecuteRequest
    {
        AsyncRequest * __weak weakself = self;

       //localVariable is used by value, a strong reference is made to localVariable in the block
        NSURLRequest *urlRequest = self.murlRequest;
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),^(void){
            NSURLResponse *response = nil;
            NSError *error = nil;
            NSData * data = [NSURLConnection sendSynchronousRequest:urlRequest returningResponse:&response error:&error];
                    //main ui
                    dispatch_async(dispatch_get_main_queue(),^{
                                weakself.onCompletedBlock(data);
                    });
    }
        @end

所以我声明onComplete块并在initWithUrlFunction初始化它们然后我用weakself来运行它。

但问题是我在weakself.onCompletedBlock(data) ->

收到此错误
  

线程1:EXC_BAD_ACCESS(代码= 2,地址=位于0xC)

问题是什么?

2 个答案:

答案 0 :(得分:3)

您需要先将weakself.onCompletedBlock分配给强大的var,然后在调用之前测试它不是nil


在调用之前,你需要测试块不是nil,除非你能保证它不能为零。或者您的应用程序崩溃时出现错误的错误消息。与nil对象上的invoke方法完全不同,调用nil块会导致取消引用无效的内存地址。

block()将编译为block->someFunction(block->someStruct),如果blockNULL / 0,则会导致C ++样式崩溃。


您不想多次访问__weak变量。您必须将其分配给__strong变量,然后才能访问它。否则可能会意外释放,因为它没有被保留。

__weak Foo *obj = // something
[obj dowork];   // obj may be valid value at this point
[obj dootherwork]; // obj may be nil here even previous call success
id foo = obj->somevar;  // may crash with dereference invalid memory address

你需要做的是

__weak Foo *obj = // something
Foo *strongObj = obj;
if (strongObj) { // not always required
    // you know strongObj is retained and will not be released until it go out of scope
    // so you can access strongObj safely without surprise 
}

答案 1 :(得分:0)

这里weakSelf模式不合适。它用于避免强引用周期,这不是风险。在这种情况下,您只希望此dispatch_async块保留其组成对象,直到异步块执行,因此只需使用self

顺便说一下,如果可能在没有提供完成块的情况下调用此方法,则应确保它不是nil,因此:

dispatch_async(dispatch_get_main_queue(),^{
    if (self.onCompletedBlock) {
        self.onCompletedBlock(data);
    }
});
相关问题