Can the __weak attribute be used to pass a parameter to blocks that lead to memory leaks?

In my code that supports iOS ARC, I need to pass the "I" and other objects to the block. In particular, I need to interact with myself and with the object ASIHTTPRequestinside ASIHTTPRequest completionBlock.

_operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(parseServerReply) object:nil];
_request = [ASIHTTPRequest requestWithURL:@"server.address"];

// ...

[_request setCompletionBlock:^{
    [self setResponseString:_request.responseString];
    [[MyAppDelegate getQueue] addOperation:_operation];
}];

To avoid the following warning: Capturing "self" strongly in this block will likely lead to a retain cycle. I changed my code to add the __weakattributes of the objects that are used in the block following this message: Fix the warning "Capturing [object] strongly in this block probably leads to a hold cycle" in ARC-enabled code

Final code:

_operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(parseServerReply) object:nil];
_request = [ASIHTTPRequest requestWithURL:@"server.address"];

// ...
__weak NSOperation * operation = _operation;
__weak ASIHTTPRequest * request = _request;
__weak typeof(self) * self_ = self;

[request setCompletionBlock:^{
    [self_ setResponseString:request.responseString];
    [[MyAppDelegate getQueue] addOperation:operation];
}];

I want to know if this can still lead to the loss of loops and memory leaks. If so, is there a way to avoid leaks?

+3
2

( ).

. ARC . dealloc , . , , .

, . dealloc, .

, , , , .

...

id object = getMeSomeObject();
// <object> is implicitly __strong, and now has a reference.

dealloc, . , , , , .

A __weak reference - , AS LONG AS OBJECT LIVES. , __weak, , . dealloc(), __weak nil.

, _weak . , , , dealloc. , dealloc , .

, , __strong , , .

...

[_request setCompletionBlock:^{
    [self setResponseString:_request.responseString];
    [[MyAppDelegate getQueue] addOperation:_operation];
}];

, , self. , , . ...

// weakSelf will be "magically" set to nil if <self> deallocs
__weak SelfType *weakSelf = self;
[_request setCompletionBlock:^{
    // If <self> is alive right now, I want to keep it alive while I use it
    // so I need to create a strong reference
    SelfType *strongSelf = weakSelf;
    if (strongSelf) {
        // Ah... <self> is still alive...
        [strongSelf setResponseString:_request.responseString];
        [[MyAppDelegate getQueue] addOperation:_operation];
    } else {
        // Bummer.  <self> dealloc before we could run this code.
    }
}];

, self, ... . ? _request _operation . , self.

...

// weakSelf will be "magically" set to nil if <self> deallocs
__weak SelfType *weakSelf = self;
[_request setCompletionBlock:^{
    // If <self> is alive right now, I want to keep it alive while I use it
    // so I need to create a strong reference
    SelfType *strongSelf = weakSelf;
    if (strongSelf) {
        // Ah... <self> is still alive...
        [strongSelf setResponseString:strongSelf->_request.responseString];
        [[MyAppDelegate getQueue] addOperation:strongSelf->_operation];
    } else {
        // Bummer.  <self> dealloc before we could run this code.
    }
}];

, , " ", .

, self, self dealloc, .

, , strongSelf , weakSelf. ...

if (weakSelf) {
    // Hey, the object exists at the time of the check, but between that check
    // and the very next line, its possible that the object went away.
    // So, to prevent that, you should ALWAYS assign to a temporary strong reference.
    [weakSelf doSomething];
}

strongSelf = weakSelf;
// OK, now IF this object is not nil, it is guaranteed to stay around as long as
// strongSelf lives.

, self, , self deallocs , - self , - - .

+14

. Brad Larson .

+1

All Articles