如何使用代码块保留对象?或者:如何正确布置异步操作?

时间:2016-12-08 10:19:36

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

首先,我的任务是通过带有HTTP协议的套接字下载内容。为此,我选择使用GCDAsyncSocket打开套接字连接,工作正常。 http协议实现也可以正常工作。

这个课的结构基本上是这样的:

//REQUEST OBJECT
@implementation HttpRequest{
//completion and fail block which will be called to the receiver
   void (^_failBlock)();
   void (^_completionBlock)();
}



-(void)performRequest:completionBlock andFailBlock:failBlock{
    //assigning blocks for later use
    _completionBlock = completionBlock;
    _failBlock = failBlock;
   //start the request
}

-(void)receiveAsyncSocketCallback{
 //receive the answer and parse it
 // if the request is complete call completionBlock or failBlock
}

我的问题是,在我开始这样的请求之后,我的请求对象立即被解除分配(并且没有强烈的引用):

-(void)viewDidLoad{
    HttpRequest* request =  [[HttpRequest alloc] init];

    [request performUrlRequest:@"https://someurl.com/someFile"
              completionBlock:^(int statusCode, NSDictionary *httpHeader, NSData *body) {

            //Do something with the retrieved data

          }
                failBlock:^(int statusCode, NSDictionary *httpHeader, NSData *body) {

            //connection failed for some reason

                }];


}

我的理解是没有任何对象保留我的请求对象,因为我没有从其上任何其他对象持有强引用。好的。

但我之前的理解是,当我在另一个仍处于活动状态的对象中实现代码块时,这将保留我的请求对象,直到调用代码块为止。我已经在其他项目中完成了这项工作,但是我无法发现差异。

为了避免对象的重新分配,我可以将它分配给我创建它的对象中的某些ivar以及我需要该请求的响应的地方。但我不喜欢拿这些引用,因为它感觉有点无意义所以我选择让对象保留自己

__strong HttpRequest *_retained_self;

我也不喜欢因为潜在的内存泄漏。我觉得我在这里错过了一个好的建筑。

有人可以给我一个如何正确布局的建议吗?

2 个答案:

答案 0 :(得分:0)

如果您在两个区块内访问request,那么当您复制该区块时,您就可以了。运行时将保留对该对象的强引用。最简单的方法是使用类型为copy的属性作为块。对块的强引用是不够的。

@property (copy, nonatomic) void (^failBlock)();
@property (copy, nonatomic) void (^completionBlock)();

答案 1 :(得分:0)

使用(copy)将它们作为属性,然后实现dealloc方法,将其设置为nil以避免内存泄漏。