I know if I use a class method or property variable I can resolve this. but is there any way to retain this object (which declared inside a function). I tried __strong
and __block
with the object, but not working.
Your code is trying to solve a problem which doesn't exist and it doing so creates one.
The purpose of the weakSelf
/strongSelf
pattern it to deal with harmful reference cycles (not all reference cycles are harmful, indeed some are useful). You should only use it if you have identified you that there is such a harmful cycle.
Let's look at your code without any weakSelf
/strongSelf
dance:
1 @implementation AViewController
2 {
3 -(void)methodA
4 { LocalClass *object = [LocalClass alloc] init];
5 [object aMethodWithCompletionBlock:^(NSDictionay *result) { ... }];
6 }
7 }
8
9 @implementation LocalClass
10 {
11 - (void)aMethodWithCompletionBlock:(void (^)(NSDictionay *result))completionHandler
12 { [NetworkClass methodToMakeRESTRequestOnComplete:^(NSDictionay *someResult)
13 {
14 if (!self)
15 return;
16
17 //some code execution
18 if (completionHandler != nil)
19 completionHandler(someModifiedResult);
20 }];
21 }
22 }
Now what will happen when you have an instance of AViewController
and invoke methodA
?
- At line 3 a new instance of
LocalClass
is created and a reference to it stored in object
. The type of object
is implicitly __strong LocalClass *
and so the new instance has a strong reference to it and will stay alive.
- At line 5 the method
aMethodWithCompletionBlock:
is called on the object referenced by object
passing it a closure. Note that neither methodA
or the instance of AViewController
it is being called for keep a reference to this closure, it is just passed to the method. Therefore after the call there is no possibility of a reference cycle between a local variable belonging to methodA
or an instance variable belonging to AViewController
and the closure.
At line 12 method methodToMakeRESTRequestOnComplete:
of NetworkClass
is called passing it a closure
- This closure references
self
so it contains a strong reference back to the instance of LocalClass
on which aMethodWithCompletionBlock:
was called
- This is the same instance of
LocalClass
that was created at Line 3 and so there are now two strong references to that object.
- The closure also contains a strong reference to the block referenced by the parameter
completionHandler
At line 20 methodToMakeRESTRequestOnComplete:
returns, as the passed block is a completion block it is unlikely to have been called yet. So at this point NetworkClass
has a reference to that completion block, and the completion block has a reference to the LocalClass
instance.
- At line 21
aMethodWithCompletionBlock:
returns. The instance of LocalClass
it was called on has kept no references to the parameter completionHandler
.
- At line 6
methodA
returns. This destroys its local variable object
which drops the strong reference to the LocalClass
instance it referenced. The system can consider destroying that instance at this point, however as NetworkClass
has a strong reference to a completion block which in turn has a strong reference to this same LocalClass
instance it is still needed and not destroyed.
- At some future time line 14 is reached after
NetworkClass
invokes the block reference it kept. The self
variable contains a strong reference to the LocalClass
instance originally created at line 4, that instance therefore still exists and all is well with the world.
- At line 20 the completion block returns. If at this point
NetworkClass
drops its strong reference to the block the block can be (probably – assuming there are no other strong references to it) destroyed. That destruction removes the strong references the block has to the objects referenced by its self
and completionHandler
and so those objects can also (probably...) be destroyed and the objected originally created at line 4 bites the dust.
There are no harmful cycles, no need for any weak references to manage them.
HTH