Retain Cycle Even when using Weak/Strong ARC Semantics - ios

`I admit that I am not an expert on ARC and retain cycles though through some research and some great articles (like this), I believe I get the basics.
However, I am currently stumped. I have a property defined as follows.
#property (nonatomic,retain) Foo *foo;
Inside my init, I do the following.
if(self = [super init]) {
_foo = [[Foo alloc] initWithDelegate:self];
// async the rest
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,
(unsigned long)NULL), ^(void) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf.foo != nil) {
[strongSelf.foo runTests];
}
});
}
return self;
}
and here is my dealloc
- (void)dealloc {
_foo = nil;
}
If the dispatch_aync block is commented out, I see my Foo dealloc get called immediately after foo is set to nil. With the block commented in, foo's delloc is not called.
I've got a retain cycle correct? Any idea how?

No, you do not necessarily have a retain cycle (now known as a "strong reference cycle" in ARC). You have code that, if foo existed by the time strongSelf was defined, foo will be retained until the dispatched code finishes.
The only potential strong reference cycle here is the delegate you passed to foo. If that delegate is defined as strong property of the Foo class, then you have a strong reference cycle. If it's defined as a weak property, then you have no strong reference cycle.

Related

when weakSelf will be nil in block ,when should add strongSelf

By using weakSelf in the block ,you are avoiding retain cycle.But sometime you should hold weakSelf until block retain ,therefor you need use strongSelf just like
__weak __typeof__(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
__typeof__(self) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doSomethingElse];
} );
I want know when weakSelf will be nil ,then we should add__strong typeof(self) strongSelf = weakSelf
Example: If your aunty asked you, "Please purchase the umbrella from the market before I leave for my flight". You went to the market and it was very hard to find an umbrella. Finally you found a nice umbrella after few hours and you reach home but you find out that your aunt has left and you feel bad. But that was the right thing for your aunt because the flight is more important than the umbrella.
But in your coding problem what you're trying to do is
You are visiting market and taking your aunt's passport with you so that she won't leave until you come back.
I guess that's rude, but if you still want to do that, use self instead of strongSelf
dispatch_group_async(_operationsGroup, _operationsQueue, ^
{
[self doSomething];
[self doSomethingElse];
} );
It all depends on your requirements. There's no one, right answer.
Capturing self weakly allows the instance to be deallocated, even if the block is still retained somewhere. If self is released before the block is executed, it will be nil within the block.
If the block should not do anything when self has already been deallocated, there is no reason to capture self strongly. Simply test for nil and exit early. Or do whatever work is needed in the block that doesn't act on self.
If self should not disappear until the block has executed, capture self strongly, but avoid retain cycles by ensuring that self does not have a strong reference to the block.
If it's OK for self to disappear before the block begins executing, but must stick around until the block finishes, the block should capture a strong reference to the weakly-captured self when it begins.
If question is: "when weakSelf will be nil".
The answer is: When no one own the instance of self
For example, you have a UIViewController instance named vc, vc have a dependency for query API named apiHandler, and api have a callback block named successCallback.
like this:
#interface ApiHandler: NSObject
#property (nonatomic, copy) void (^successCallback)();
#end
#interface vc : UIViewController
#property (nonatomic, strong) ApiHandler *apiHandler;
#end
#implementation vc
- (void)doQuery {
self.apiHandler.successCallback = ^{
[self doSomething];
};
}
- (void)doSomething {
}
If vc be pop or dismiss, the vc instance WILL NOT BE dealloc. Because of retain cycle.
vc own apiHandler, apiHandler own successCallback and successCallback own vc.
So, using weak vc in block can avoid retain cycle.
like this:
- (void)doQuery {
__weak __typeof__(self) weakSelf = self;
self.apiHandler.successCallback = ^{
[weakSelf doSomething];
};
}
And now, if your vc be pop or dismiss, the vc instance will be dealloc, and weakSelf will be nil.
When apiHandler do query success in background thread and invoke successCallback, the message doSomething will send to nil object. (Zombie)
This is why you need to use strongSelf in block like you said.

Should I use weakSelf in nested blocks?

I'm trying to correctly avoid retain cycles with blocks in Objective C, and am not sure about having nested blocks.
If I write a simple block like this:
[self doSomethingWithBlock:^{
[self doSomethingElse];
}];
The compiler catches and warns me that this could cause retain cycles. I change it as follows to avoid the cycle:
__weak __typeof(self)weakSelf = self;
[self doSomethingWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doSomethingElse];
}];
When I write something like this:
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
[self doYetAnotherThing];
}];
}];
The compiler is happy, but I'm not convinced that it's safe. Even though there is an intermediary object in between, it still looks conceptually the same as above, but now it's a cycle with 3 retains.
Should it be like this instead?
[self doSomethingWithBlock:^(MyObject* object){
__weak __typeof(self)weakSelf = self;
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doYetAnotherThing];
}];
}];
Or like this?
__weak __typeof(self)weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf)strongSelf = weakSelf;
[strongSelf doYetAnotherThing];
}];
}];
In this situation, you are not worried about cyclic references. What you are worried about is a situation where the object self isn't actually needed anymore, but using self inside a nested block would keep it unnecessarily alive. For example, if you have a view controller that should go away when the view is removed by the screen, but you download an image that you would like to display in the controllers view. If the image arrives long after the view is already gone, you don't want the view controller alive anymore.
Best is
__weak typeof (self) weakSelf = self;
before calling the outermost method. Then within every block that ought to use self, you add
typeof (self) strongSelf = weakSelf;
and use strongSelf within that block. Depending on the situation, you might want to check that strongSelf isn't nil at that point, but sending messages to strongSelf when it is nil has no effect, so if all you do is sending messages and getting or setting properties, then a check for nil is not necessary.
What happens if you don't do this? The difference will be that self may be kept alive unnecessarily into the innermost block, if you use self everywhere (or just in the innermost block).
You should not capture something weakly just because you get a warning from the compiler; the compiler warning is just guessing; it doesn't know how the methods you call make the references. You should only do this if you understand the architecture of the references and determine that there is a cycle and determine that capturing a weak reference instead still preserves the intended behavior. You haven't shown us the code of -doSomethingWithBlock:. It would only create a retain cycle if inside that method it assigns the block to a property or instance variable of self. Does it do that or not? If not, then there is no retain cycle, and there is no point to the outer block capturing self weakly.
Assuming that the outer block capturing self weakly is right, the examples where the outer block captures self strongly are out of the question. The remaining questions would be whether the inner block should capture self (or whatever version of self, e.g. strongSelf, is appropriate) strongly. In other words, whether you would do something like this:
__weak __typeof(self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[object doSomethingElseWithBlock:^{
[strongSelf doYetAnotherThing];
}];
}
}];
or something like this:
__weak __typeof(self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[object doSomethingElseWithBlock:^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doYetAnotherThing];
}
}];
}
}];
Again, the main issue to determine is whether there is a retain cycle if the inner block captures self strongly. There would only be a retain cycle if [object doSomethingElseWithBlock:... somehow assigns the block to a property or instance variable of self. But how could it? The method is called on object, not self. The method does not get self in any way. Unless there is something complicated going on, the method is not going to assign to a property or instance variable of self, so it is unlikely to create a retain cycle. This means that the inner block capturing self weakly is not necessary to prevent a retain cycle.
But whether the inner block captures self weakly or strongly could affect the behavior. Namely, if the inner block captures self weakly, self could be deallocated by the time the block is run, in which case [strongSelf doYetAnotherThing]; will not be executed, whereas if the inner block captured self strongly, it would keep self alive and [strongSelf doYetAnotherThing]; would be executed. So it depends on what -doYetAnotherThing does. If it performs some UI operation on self which is a UI view or something, then whether you perform it on a view that is no longer displayed doesn't make a difference. But if it for example sends something to the network or something, then whether or not it is executed can make a big difference.
Xcode 8 beta 4 underlines the self keyword, and warns of a possible retain cycle for having used it inside the block.
Per Apple Developer Connection's Programming in Objective-C (Working with Blocks):
Avoid Strong Reference Cycles when Capturing self If you need to
capture self in a block, such as when defining a callback block, it’s
important to consider the memory management implications.
Blocks maintain strong references to any captured objects, including
self, which means that it’s easy to end up with a strong reference
cycle if, for example, an object maintains a copy property for a block
that captures self:
#interface XYZBlockKeeper : NSObject
#property (copy) void (^block)(void);
#end
#implementation XYZBlockKeeper
- (void)configureBlock {
self.block = ^{
[self doSomething]; // capturing a strong reference to self
// creates a strong reference cycle
};
}
...
#end
The compiler will warn you for a simple example like this, but a more
complex example might involve multiple strong references between
objects to create the cycle, making it more difficult to diagnose.
To avoid this problem, it’s best practice to capture a weak reference
to self, like this:
- (void)configureBlock {
XYZBlockKeeper * __weak weakSelf = self;
self.block = ^{
[weakSelf doSomething]; // capture the weak reference
// to avoid the reference cycle
}
}
By capturing the weak pointer to self, the block won’t maintain a
strong relationship back to the XYZBlockKeeper object. If that object
is deallocated before the block is called, the weakSelf pointer will
simply be set to nil.
This site reportedly provides a means for making the self keyword weak whenever it's used inside a block; it also provides instructions for returning a weak self or class object formerly strong, strong again:
https://coderwall.com/p/vaj4tg/making-all-self-references-in-blocks-weak-by-default
Look at the answer for this question.
I'd do this
__weak typeof (self) weakSelf = self;
[self doSomethingWithBlock:^(MyObject* object){
[object doSomethingElseWithBlock:^{
[weakSelf doYetAnotherThing];
}];
}];

Can __weak self turn nil in the middle of the block?

When using a __weak self reference in my block that runs on a background thread, do I only need to check for nil in the beginning, or can the __weak self become nil even during execution after the first nil test has passed? I want to access some ivars from self in the block and I need the latest values at the time the block is executing.
If no one is holding a reference to self then yes. You can mitigate this by taking a strong reference in the block
__weak __typeof(self) weakSelf = self;
^{
__strong __typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) {
return;
}
};
You can avoid having your reference set to nil by strongly referencing it from inside the block.
Get a strong reference to your weak pointer inside the block.
__weak MyObject *weakSelf = self; // a weak reference
myBlock = ^{
MyObject *innerSelf = weakSelf; // a block-local strong reference
NSLog(#"MyObject: %#", innerSelf);
};
Avoid using the variables directly, because it will cause retain cycles.
If you use an instance variable directly within a block, the block will capture self so you'll have to reference the instance variables using their accessors.
__weak MyObject *weakSelf = self;
myBlock = ^{
MyObject *innerSelf = weakSelf; // a block-local strong reference
NSLog(#"MyObject: %#", innerSelf);
NSLog(#"MyObject ID: %d", innerSelf.objectID);
};
If you use the instance variables directly like this:
NSLog(#"MyObject ID: %d", _objectID);
The compiler interprets _objectID as self->_objectID, where self is captured by your block.
It is in the nature of a weak reference that it can become nil at any time, when the last strong reference is removed in another thread. This is fatal if you access member variables because you will crash, and it is fatal if you call a method on that weak variable, since self is unsafe unretained.
There is a trivial way to fix this which everyone uses: Store the weak variable into a string one before doing anything, without any checks. Then you check whether the strong variable is nil; that check is needed once.
Turn all warnings on in Xcode, so you will get a warning if you do anything dangerous.

strong reference in block

I've known about the best practice of block is like that
__weak SomeObjectClass *weakSelf = self;
SomeBlockType someBlock = ^{
SomeObjectClass *strongSelf = weakSelf;
if (strongSelf == nil) {
// The original self doesn't exist anymore.
// Ignore, notify or otherwise handle this case.
}
[self someMethod];
};
I understand using weakSelf is used to prevent retain cycle and using strongSelf in case of weakSelf might nil.
But I just wonder using strongSelf can cause retain cycle again because block capture and retain strongSelf and strongSelf is also pointer of self.
can someone give me a explain ,thanks.
Ask yourself: How long does strongSelf exists?
strongSelf only exists while the block is executing. So basically, it holds a strong reference while someMethod is executing, and not any longer.
I assume you meant
[strongSelf someMethod];
and not
[self someMethod];
because the former holds a strong reference to strongSelf (which is equal to self) while the block is executing while latter will hold a strong reference to self while the block exists.
From documentation:
You can use lifetime qualifiers to avoid strong reference cycles. For
example, typically if you have a graph of objects arranged in a
parent-child hierarchy and parents need to refer to their children and
vice versa, then you make the parent-to-child relationship strong and
the child-to-parent relationship weak. Other situations may be more
subtle, particularly when they involve block objects.*
In manual reference counting mode, __block id x; has the effect of not
retaining x. In ARC mode, __block id x; defaults to retaining x (just
like all other values). To get the manual reference counting mode
behavior under ARC, you could use __unsafe_unretained __block id x;.
As the name __unsafe_unretained implies, however, having a
non-retained variable is dangerous (because it can dangle) and is
therefore discouraged. Two better options are to either use __weak (if
you don’t need to support iOS 4 or OS X v10.6), or set the __block
value to nil to break the retain cycle.
And som more documentation:
If you need to capture self in a block, such as when defining a
callback block, it’s important to consider the memory management
implications.
Blocks maintain strong references to any captured objects, including
self, which means that it’s easy to end up with a strong reference
cycle
As to your example - no retain cycle there, as CouchDeveloper said, because block will keep reference to self only while being executed. But there will be, no matter your __weak declaration, if we change code to this:
__weak SomeObjectClass *weakSelf = self;
self.someBlock = ^{
SomeObjectClass *strongSelf = weakSelf;
if (strongSelf == nil) {
// The original self doesn't exist anymore.
// Ignore, notify or otherwise handle this case.
}
[self someMethod];
};
Now we have retain cycle - we have reference to block and inside block we have reference to self. To avoid this, you should use __weak approach:
__weak SomeObjectClass *weakSelf = self;
self.someBlock = ^{
SomeObjectClass *strongSelf = weakSelf;
if (strongSelf == nil) {
// The original self doesn't exist anymore.
// Ignore, notify or otherwise handle this case.
} else {
[strongSelf someMethod];
}
};
Some more articles:
https://coderwall.com/p/vaj4tg
http://teohm.com/blog/2012/09/03/breaking-arc-retain-cycle-in-objective-c-blocks/
First, you must understand life cycle of strongSelf, it only exists in someBlock, after someBlock finished the object referenced by strongSelf will be released.
When the someBlock translated to MRR will like this:
^{
SomeObjectClass *strongSelf = [weakSelf retain];
if (strongSelf == nil) {
// The original self doesn't exist anymore.
// Ignore, notify or otherwise handle this case.
}
[self someMethod];
[strongSelf release];
};

weak reference cause crash bug

I have seen the following code in WWDC 2011- Session 322 Objective-C Advancement in Depth
-(void) startBlinker{
__weak MyClass * weakSelf = self;
blinker = [BlinkerService register:^{
MyClass *strongSelf = weakSelf;
if(strongSelf){
[strongSelf->myView blink];
}
}];
}
I think I can implement it just check weakSelf like
if(weakSelf){
[weakSelf->myView blink];
}
why the code use a strongSelf?
If the object a weak reference points to is deallocated, the weak reference evaluates to nil. Calling methods on nil is okay but accessing fields using the arrow operator is not. So you have to make sure the pointer is not nil before accessing the field via the arrow pointer.
if(weakSelf){ // no weak sheeps this week
// weakSelf may get deallocated at this point.
// In that case the next line will crash the app.
[weakSelf->myView blink];
}
The strong self guarantees that self will not be deallocated between the if and the statements in the if block.
Usually a weak reference is done like this to avoid retain cycles in blocks. Blocks retain self which causes a retain cycle if you try to access a strong reference to self. So you create a weak self outside the block and access it within the block to avoid the retain cycle.
Ahmed Mohammed is correct, however another possible solution is to declare myView as a property, rather than as an iVar and do this:
-(void) startBlinker{
__weak MyClass * weakSelf = self;
blinker = [BlinkerService register:^{
MyClass *strongSelf = weakSelf;
[strongSelf.myView blink];
}];
}
This way, you don't really care if strongSelf is nil or not.

Resources