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.
Related
With the recent XCode update some code blocks are displaying as warnings where "Block implicitly retains 'self'"
It is my understanding that the when you create blocks it is best practice to create a weak self to keep from creating a strong reference that will not be garbage collected.
In the below example I set the myArray to self->myArray as recommended by XCode. Does this create the strong reference? Why can't I use 'weakSelf->myArray`? Attempting to do so results in this error:
Dereferencing a __weak pointer is not allowed due to possible null
value caused by race condition, assign it to strong variable first
I thought the whole point was to create weak refrences? Isn't weakSelf just a pointer to self?
Is the self-> even necessary in the below instance?
#interface SomeViewController (){
NSMutableArray * myArray;
}
#end
- (void) doSomethingInBackground {
// Do NSURLSessionTask on the background and onCompletion call mySuccessBlock.
}
- (SomeBlock) mySuccessBlock {
__block __typeof__(SomeViewController) __weak * weakSelf = self;
return ^(NSDictionary* result){
//this line is my related to my question
self->myArray = [weakSelf sortResultsAlphabetically: result];
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf.tableView reloadData]
});
};
}
Would recasting to be the correct way?
SomeViewController * strongSelf = weakSelf;
strongSelf->myArray = [weakSelf sortResultsAlphabetically: result];
The error message is right. You have to do the "weak-strong dance". You are only doing half of the dance. Pass self into the block as weak, but then immediately assign it, inside the block, to a strong reference (as in your edited "Would recasting to be the correct way?").
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.
`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.
I thought I understood the usage of self in a block that is copied is a no no.
But in an attempt to clean my code i enabled a bunch of warnings in Xcode, one called "Sending messages to weak pointers"
so now in all my blocks, every time I use my created weakself reference __weak typeof(self) weakself = self;
I get this warning: Weak receiver may be unpredictably set to nil
a trivial example:
__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{
[weakself doSomething]; //warning.
}];
I have seen answers which define a version of self within the block like so:
__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{
typeof(self) selfref = weakself;
[selfref doSomething]; //no warning.
}];
So I'm wondering what actually happens here:
Am I just tricking the compiler?
what does a strong reference to a weak reference do?
anything else I'm missing.
Thanks.
I thought I understood the usage of self in a block is a no no.
This is not strictly correct. Blocks retain the objects in them, so don't use self in a block if your block is retained by self.
For example, you can use self just fine in a UIView animation block. This is because your view controller (or whatever code is calling the animation) doesn't have a pointer to the UIView animation block.)
Am I just tricking the compiler?
No.
What does a strong reference to a weak reference do?
If the weak reference is not nil, the retain count of the receiver is increased. This will stop the object from being deallocated while you're using it.
Remember, ARC will deallocate objects when there are no longer strong references to them. By creating a strong reference inside the block, you're preventing possible deallocation until you're done with it.
anything else I'm missing.
I recommend reading the Practical Memory Management section of the Advanced Memory Management Programming Guide. Especially, read the subsection "Use Weak References to Avoid Retain Cycles".
Remember that in ARC, an object will not be deallocated as long as there's a strong reference to it.
When an object has a weak reference, the object might be deallocated (if there's no other strong reference to the same object), so a weak reference doesn't ensure the objects life.
By doing this:
typeof(self) selfref = weakself;
you're ensuring that you have a strong reference to that object before you use it (selfref is the strong reference pointing to the same object weakself is referring to). If you don't do this, the object could be deallocated while you use it.
Strong reference to a weak reference retains an object. It could be important in following case
__weak typeof(self) weakself = self;
[aClass doSomethingInABlock:^{
[weakself allocateSomething]; // (1)
// ..... code (2)
[weakself freeSomething]; // (3)
}];
If Weak receiver will be unpredictably set to nil in line (2) resources could be successfully allocated in (1) but not freed in (3). To avoid such problems strong reference could be used.
[aClass doSomethingInABlock:^{
typeof(self) selfref = weakself;
[selfref allocateSomething]; // (1)
// ..... code (2)
[selfref freeSomething]; // (3)
}];
Now if selfref is not nil in (1) it will also be valid in (2) and (3).
Suppose I already create a weak self using
__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
...
}];
Inside that block, if I nest another block:
[weakSelf doAnotherBlockOperation:^{
[weakSelf doSomething];
}
will it create a retain cycle? Do I need to create another weak reference to the weakSelf?
__weak typeof(self) weakerSelf = weakSelf;
[weakSelf doAnotherBlockOperation:^{
[weakerSelf doSomething];
}
Your code will work fine: the weak reference will not cause a retain cycle as you explicitly instruct ARC not to increase the retainCount of your weak object. For best practice, however, you should create a strong reference of your object using the weak one. This won't create a retain cycle either as the strong pointer within the block will only exist until the block completes (it's only scope is the block itself).
__weak typeof(self) weakSelf = self;
[self doABlockOperation:^{
__strong typeof(weakSelf) strongSelf = weakSelf;
if (strongSelf) {
...
}
}];
It depends.
You only create a retain cycle if you actually store the block (because self points to the block, and block points to self). If you don't intend to store either of the blocks, using the strong reference to self is good enough --- block will be released first after it got executed, and then it will release it's pointer to self.
In your particular example, unless you're performing more operations which are not shown, you don't need to create any weakerWeakerEvenWeakerSelfs.