iOS. what does "self" mean in a dispatched block? - ios

I have see many blocks use "self.xxx" in a block, then how can I make sure the "self" is the instance I want?
Example:
I am in instance A, whose delegate is B.
And then I call [A.delegate dispatchBlockTest]
The dispatchBlockTest in instance B is like this:
dispatch_async(dispatch_get_main_queue(DISPATCH_UEUE_PRIORITY_DEFAULT, 0),^{
[self printClassName];
});
});
Then, the "self" in the block is definitely B? not A?
Any sort of help is appreciated, thanks.

Fonix's comment is right on. For more information, you can check out this page from the official Apple docs. Specifically take a look at the "Blocks Can Capture Values from the Enclosing Scope" section. The meaning of a variable in a block is always "captured" when the block is declared, so local variables, properties, and references to self are all based on the scope of where the block is declared (in your case, the scope in class A) and NOT based on where the block is called (in your case, class B).
On a side note, one subtle thing it's worth knowing about using self with blocks is that you can create a type of memory leak known as a strong reference cycle or a retain cycle (Check out the section on weak properties here for an explanation). In general, it's good practice to always use a weak reference to self in blocks (Apple has a good example here). Most of the time, using self in a block won't create a strong reference cycle, but if you always use a weak reference to self in a block, you don't have to think about whether or not you risk a reference cycle.

Related

Does object need (a) `__block` modifier or (b) weak reference, when accessed from within a block in Objective-C?

In Objective-C (as of Xcode 7), the __block modifier for use with primitives is clearly explained in Stack Overflow such as here and by Apple here in the Blocks Programming Guide. Without the label, a copy of the primitive is captured and the original cannot be modified from within the block. With the label, no copy, and the original can be modified from within the block.
But for use with pointers to objects, the situation is not so well explained. Here Apple says either “a strong reference is made to self” or “a strong reference is made to the variable”. But then at the end of the page Apple says:
To override this behavior for a particular object variable, you can mark it with the __block storage type modifier.
What does “override this behavior” mean?
Further complicating things is that some posts on Stack Overflow talking about making a weak reference when calling an object from within a block.
I am not trying to establish an object. I just want to modify an existing object’s state from within a block. I believe the block is being called synchronously, within the same thread.
Imagine:
Clicker* myClicker = [[Clicker alloc] init] ;
…
// Declare a block.
void (^myBlock)( );
// Populate the block.
myBlock = ^ void ( ) {
[myClicker click] ; // Updating some state in that object, such as incrementing a counter number or adding an element to a collection.
};
// Call `myBlock` synchronously (same thread) from some other code.
… // … invokes `myBlock` repeatedly …
My questions:
How should that code be modified with __block modifier?
How should that code be modified with weak references?
What other issues apply to an object’s state modified from within a block?
First of all, the basic point of __block is the same for all types of variables (primitive variables, object-pointer variables, and all other variables) -- __block makes the variable shared between the outside scope and the scopes of the blocks that capture it, so that an assignment (=) to the variable in one scope is seen in all other scopes.
So if you don't use __block, if you assign to an object-pointer variable to point to another object outside the block after the block is created, the block won't see the assignment to the variable, and will still see it pointing to the object it was pointing to when the block was created. Conversely, inside the block you won't be able to assign to the variable. If you do use __block, then assignments to the variable to point to another object, either inside or outside the block, will be reflected in the other scopes.
Note that mutation of objects' state has nothing to do with assignment to variables. You mutate objects' state by calling a mutating method on a pointer to the object, or you can alter a field directly using a pointer to the object using the -> syntax. Neither of these involve assigning to a variable holding the pointer to the object. On the other hand, assigning to a variable holding a pointer to an object only makes the pointer point to another object; it does not mutate any objects.
The part you are reading about strong references and "override this behavior" has to do with the separate issue of memory management behavior of blocks under MRC only. Under MRC, there is no concept of variables being __strong or __weak like in ARC. When a variable of object-pointer type is captured by a block in MRC, it is by default captured as a strong reference (the block retains it, and releases it when the block is deallocated), because that is the desired behavior most of the time. If you wanted the block to not retain the captured variable, the only way to do that was to make it __block, which not only made the variable shared between the two scopes, but also made the block not retain the variable. So the two concepts were conflated in MRC.
In ARC, whether a block captures a variable strongly or weakly depends on the captured variable being __strong or __weak (or __unsafe_unretained), and is completely orthogonal with whether the variable is __block or not. You can have object-pointer variables that are __block without being weakly captured, or weakly captured without being __block, or both weakly captured and __block if you want.
You quote the somewhat dated Blocks Programming Topics, which says:
To override this behavior for a particular object variable, you can mark it with the __block storage type modifier.
That document dates back to the days of manual reference counting, back before ARC. In manual reference counting code you could use __block to avoid establishing a strong reference to objects referenced inside the block.
But this behavior has changed with ARC, as outlined in Transitioning to ARC Release Notes. We now use weak in those cases where we don't want to establish strong references to the objects referenced in the block. (You can use unsafe_unretained in special cases where you know the resulting dangling pointer isn't a problem.)
So, go ahead and use __block when dealing with fundamental types that you want to mutate inside the block. But when dealing with objects in blocks under ARC, the __block qualifier generally doesn't enter the discussion. The question is simply whether you want a strong reference or a weak one (or an unsafe, unretained one). And that's largely dictated by the object graph of your app, namely (a) whether you need weak/unretained reference to prevent strong reference cycle; or (b) you don't want want some asynchronously executing block to unnecessarily prolong the life of some object referenced in the block. Neither of those situations would appear to be the case here.

Block/Closure Understanding

Need clarification on blocks and closure.
How blocks will retain the object? or why we need to use only weak inside block? What will happen if we don't follow this? Or please give some clarity on block.
The below one os for closure.
I have written some code like this. favouriteButton is a property of self.
favouriteButton.hidden = false
dispatch_async(dispatch_get_main_queue(), {
self._collectionView.reloadData()
})
It didn't gave any error. So I thought of doing UI in main thread. So I moved the code to disable hidden inside block like below.
dispatch_async(dispatch_get_main_queue(), {
favouriteButton.hidden = false
self._collectionView.reloadData()
})
It shows an error like
reference to property 'favouriteButton' in closure requires explicit
'self'
dispatch_async(dispatch_get_main_queue(), {
self.favouriteButton.hidden = false
self._collectionView.reloadData()
})
Could any one please explain how to use closure/block effectively.
Does the blocks and closures work in the same way?
In Swift (and Objective-C), a block is a closure. The term closure refers to an individually-executable block of code that captures the values of variables in the enclosing scope. In the case of Swift, the enclosing scope is usually a function, and only variables used within the block are captured.
The reason you need to preface class-level references (properties and function calls) with self. is to make explicit the capturing of self. Doing so allows you to specify how self (or any other object reference) is captured: strong (default) or weak.
There are two reasons to be careful with retaining objects (keeping strong references) within a block.
The most common concern is creating a retain cycle. This is where the block retains a strong reference to an object, which in turn has a strong reference to the block. Until one of the references is explicitly broken, neither the block, nor the object, will be released. (Releasing a block simply cleans up the captured variables. The executable code remains.)
A strong reference to an object within a block can keep the object alive longer than intended. For example, if a block keeps a reference to a view controller that is popped off a navigation stack, you likely don't want that block to act on the view controller when its executed. This can be avoided by capturing a weak reference to the view controller. This allows the view controller to be deallocated when it's popped, and the block becomes a no-op.

Why does the weak/strong dance solve this strong reference cycle? I don't understand

Ok, I understand the reason for the strong weak dance.
One example being, let's say B strongly references a block, and we set that block inside B to strongly reference itself(B). We now have B strongly referencing our block, perhaps our block is allocated to the heap to run later (async perhaps), and our block is strongly referencing B. Let's say only some object A strongly reference B. If we kill A, then B -> block AND block -> B. Strong reference cycle and memory leak.
Another way we might see this is A strongly references B. B strongly references C. Perhaps C has a block property, and B says C.block = ^{ self.blah = blah }. Now we have B strongly referencing C, and C strongly referencing B. A is killed, and we have a strong reference cycle once again. Correct me if I'm wrong on any of this.
Now I'm seeing a strong reference cycle that in my mind should not be a strong reference cycle.
I have a class, let's call it A. A has a function fooBar. Inside fooBar, we call
[[MySingleton sharedInstance] doSomeBackgroundJazz: ^{
self.blah = blah;
}];
We're seeing a strong reference cycle and A isn't getting deallocated. Now, in my mind, A does not have a strong reference to MySingleton. Maybe for the duration of fooBar it does, but the class itself does not. But when fooBar is done, its removed from the stack, and there is no reference to MySingleton any longer. Correct me if I'm wrong at any point here. Now, we know our block code that is in [MySingleton doSomeBackgroundJazz] strongly references A. However, why does this matter? A doesn't reference MySingleton. MySingleton strongly references A. No need for the weak strong dance.
However, when I put the weak strong dance in.. our problems our alleviated. A no longer sticks around. (Right now the real world problem we are having is leaving a view and coming back, keep creating a new view plus retaining the previous ones. Each one listens for a notification, and does an API call. So we can potentially have dozens of API calls going out every second).
Why is the weak strong dance solving this?
Assuming A is your caller to -doSomeBackgroundJazz:
It appears your MySingleton class stores your block off into a property.
Because you captured self (A) in your block, when the block is stored into a property it is also retained.
So this means that as long as your singleton instance (sharedInstance) is retained, it's block property is retained, and therefore your captured A is retained.
It doesn't matter that A doesn't retain the sharedInstance, it clearly is hanging around for whatever reason.
The rule of thumb is to cast self with __weak whenever the block is going to be stored into a property. However it doesn't hurt to always make a __weak cast anyways, there rarely should be the case where you want a block to retain an object

Do I need to use use Strongify and Weakify in blocks if the variable calling it is local [duplicate]

Using self. in blocks causes retain cycles, so I need to create a reference to weakSelf. I understand this
BUT!
If from my block I call a method which uses self", does this too cause a retain cycle? For instance, if I reload a UITableView from a block and in some of my UITableView delegate methods I call self., am I causing a retain cycle? Does that mean I have to pass around this weak reference everywhere? Seems hokey.
I might be misreading your question, but your wording:
If from my block I call a method which uses "self.", does this too cause a retain cycle? For instance if I reload a UITableView from a block and in some of my UITableView delegates I call "self.", I'm causing a retain cycle? That means I have to pass around this weakReference everywhere?
suggests you are misunderstanding what self is. Hopefully if so the following will help and not hinder your understanding...
What is self?
The identifier self is just the name of one of the parameters to your method, it is just passed implicitly rather then explicitly like the other parameters. For example if you have a class:
#implementation MyClass
- (void) someMethod:(NSInteger)value
{
... self ... value
}
#end
then the method is effectively (i.e. bending the facts just a little for clarity):
- (void) someMethod:(NSInteger)value withObject:(MyClass *)self
{
... self ... value
}
When an instance method is called the value passed for the self parameter is a reference to the instance the method should operate on, e.g. the call
MyClass *someInstance = ...
[someInstance someMethod:42];
is effectively a call to:
someMethod:42 withObject:someInstance
Strong reference cycles
An object - which includes both instances of classes and blocks - is kept alive as long as there exists a strong reference to the object.
If an object A holds a strong references, e.g. in an instance variable or property, to an object B, then B will be kept alive at least (there could be other strong references to B) as long as A is alive.
If an object A holds a strong reference to B and B holds one to A then you have a strong reference cycle - each object is keeping the other alive and neither will ever be collected. This could lead to a memory leak - where unused memory is never collected - unless both A and B are meant to live from creation till the end of the program.
Further, you do not create a strong reference cycle simply by having references stored in the local variables and parameters of methods. By their nature such variables, and therefore their contents, are transient and are destroyed when the method returns.
Using self in blocks
using "self." in blocks causes retain cycles so I need to create a reference to weakSelf.
Not quite. When you use self in a block, either directly or indirectly by referencing an instance variable, then the compiler will warn you that you may create a reference cycle.
(Note: There are other ways to create reference cycles, both with and without using blocks, and the compiler will not warn you at all. Managing cycles is just something you need to be aware of.)
You will only actually create a cycle if you store a reference to the block in the object referenced by self. However this is not bad in itself, as long as at some point you break the cycle manually - say by storing nil in the variable referencing the block - the cycle need not be problematic at all.
Finally...
You have nothing per se to worry about with your:
UITableView delegates I call "self."
as that self is just a local parameter to the delegate whose initial value, at some point going back up the call chain, came from you evaluating your weakSelf reference and determining that it was not nil and then calling methods on it.
HTH
First of all: self does NOT cause a retain cycle. This is an urban legend. The incorrectness is obvious: A single reference can never cause a cycle. The usage of self inside a block causes a retain cycle, if the block is directly or indirectly referred by self, too, for example via a property.
To your Q:
If you "call" a method inside the block, the message probably has the receiver self, so you have a usage of self inside the block. For this reason it is captured and retained.
If you really have no usage of self inside the block by neither using self nor using a property of self you do not have a usage of self and it is not captured, therefore not retained. But in this case you can have a dangling pointer or a nil'd reference.
You don't need to worry about references while the block is executing - eventually it finishes doing whatever it does, and all these references go away.
What you need to worry about are the references that are captured when the block is created. These references stay until the block goes away. So if your block has a reference to "self", that reference is there just because the block exists. And if you store that block in a property of self, you have a cycle.
So if you store a block as a property in self, then the block shouldn't capture self. That's easily done by letting it access and capture a weak copy of self. Remember that when the block is executing, the weak copy of self may be nil. Which means the self object has already left our world, and your block might not need to do anything.
Short answer: no, in this situation self is not retained.
Long answer
First of all, retaining self and a reference cycle are not the same thing. Reference cycle is a cycle of strong references between a number of objects: A->B->C->A is a retain cycle.
The general idea is, you want to always guarantee that if you are referencing self in a block, you don't reference this block strongly, and don't reference it through a chain of strong references. In reality, retain cycles can be used purposefully if you are making sure you're breaking the retain cycle under certain conditions. Not that I personally recommend this.
Take a look at documentation on Apple's website. It clearly states that values are captured in blocks, and capturing an object reference retains this object in block.
Basically what this means is that referencing an object in a block increments its retainCount by 1, and when this block gets deallocated, retainCount is decremented by 1.
However, when using a __weak pointer in a block, the retain count is untouched.
Here's an example:
- (void) doSomething {
NSLog(#"%#", self);
}
- (void) callBlock {
__weak typeof(self) weakSelf = self;
dispatch_block_t block = ^{
[weakSelf doSomething];
};
}
When you write [obj method:params] this actually translates into following call:
objc_msgSend(obj, #selector(method:), params). One of the features of Objective-C is that if you call a method on nil pointer, it returns nil. This is guaranteed by the fact that objc_msgSend(nil, #selector(anyselector), ...) always return nil. Note that SEL is just a const char[] under the covers, so it doesn't affect retain counts by any means.
Hence when the block will be executed, if your object was deallocated, the weak weakSelf variable will be nullified, and the block's body will translate into objc_msgSending to zero, which does nothing except of wasting few CPU cycles.
To sum it up, the Objective-C messaging system is implemented in such a way that calling a method does not retain this object or this method or this method's implementation, as it's a simple function call.

Do I need to use a weak self pointer if a method called from a Block uses self?

Using self. in blocks causes retain cycles, so I need to create a reference to weakSelf. I understand this
BUT!
If from my block I call a method which uses self", does this too cause a retain cycle? For instance, if I reload a UITableView from a block and in some of my UITableView delegate methods I call self., am I causing a retain cycle? Does that mean I have to pass around this weak reference everywhere? Seems hokey.
I might be misreading your question, but your wording:
If from my block I call a method which uses "self.", does this too cause a retain cycle? For instance if I reload a UITableView from a block and in some of my UITableView delegates I call "self.", I'm causing a retain cycle? That means I have to pass around this weakReference everywhere?
suggests you are misunderstanding what self is. Hopefully if so the following will help and not hinder your understanding...
What is self?
The identifier self is just the name of one of the parameters to your method, it is just passed implicitly rather then explicitly like the other parameters. For example if you have a class:
#implementation MyClass
- (void) someMethod:(NSInteger)value
{
... self ... value
}
#end
then the method is effectively (i.e. bending the facts just a little for clarity):
- (void) someMethod:(NSInteger)value withObject:(MyClass *)self
{
... self ... value
}
When an instance method is called the value passed for the self parameter is a reference to the instance the method should operate on, e.g. the call
MyClass *someInstance = ...
[someInstance someMethod:42];
is effectively a call to:
someMethod:42 withObject:someInstance
Strong reference cycles
An object - which includes both instances of classes and blocks - is kept alive as long as there exists a strong reference to the object.
If an object A holds a strong references, e.g. in an instance variable or property, to an object B, then B will be kept alive at least (there could be other strong references to B) as long as A is alive.
If an object A holds a strong reference to B and B holds one to A then you have a strong reference cycle - each object is keeping the other alive and neither will ever be collected. This could lead to a memory leak - where unused memory is never collected - unless both A and B are meant to live from creation till the end of the program.
Further, you do not create a strong reference cycle simply by having references stored in the local variables and parameters of methods. By their nature such variables, and therefore their contents, are transient and are destroyed when the method returns.
Using self in blocks
using "self." in blocks causes retain cycles so I need to create a reference to weakSelf.
Not quite. When you use self in a block, either directly or indirectly by referencing an instance variable, then the compiler will warn you that you may create a reference cycle.
(Note: There are other ways to create reference cycles, both with and without using blocks, and the compiler will not warn you at all. Managing cycles is just something you need to be aware of.)
You will only actually create a cycle if you store a reference to the block in the object referenced by self. However this is not bad in itself, as long as at some point you break the cycle manually - say by storing nil in the variable referencing the block - the cycle need not be problematic at all.
Finally...
You have nothing per se to worry about with your:
UITableView delegates I call "self."
as that self is just a local parameter to the delegate whose initial value, at some point going back up the call chain, came from you evaluating your weakSelf reference and determining that it was not nil and then calling methods on it.
HTH
First of all: self does NOT cause a retain cycle. This is an urban legend. The incorrectness is obvious: A single reference can never cause a cycle. The usage of self inside a block causes a retain cycle, if the block is directly or indirectly referred by self, too, for example via a property.
To your Q:
If you "call" a method inside the block, the message probably has the receiver self, so you have a usage of self inside the block. For this reason it is captured and retained.
If you really have no usage of self inside the block by neither using self nor using a property of self you do not have a usage of self and it is not captured, therefore not retained. But in this case you can have a dangling pointer or a nil'd reference.
You don't need to worry about references while the block is executing - eventually it finishes doing whatever it does, and all these references go away.
What you need to worry about are the references that are captured when the block is created. These references stay until the block goes away. So if your block has a reference to "self", that reference is there just because the block exists. And if you store that block in a property of self, you have a cycle.
So if you store a block as a property in self, then the block shouldn't capture self. That's easily done by letting it access and capture a weak copy of self. Remember that when the block is executing, the weak copy of self may be nil. Which means the self object has already left our world, and your block might not need to do anything.
Short answer: no, in this situation self is not retained.
Long answer
First of all, retaining self and a reference cycle are not the same thing. Reference cycle is a cycle of strong references between a number of objects: A->B->C->A is a retain cycle.
The general idea is, you want to always guarantee that if you are referencing self in a block, you don't reference this block strongly, and don't reference it through a chain of strong references. In reality, retain cycles can be used purposefully if you are making sure you're breaking the retain cycle under certain conditions. Not that I personally recommend this.
Take a look at documentation on Apple's website. It clearly states that values are captured in blocks, and capturing an object reference retains this object in block.
Basically what this means is that referencing an object in a block increments its retainCount by 1, and when this block gets deallocated, retainCount is decremented by 1.
However, when using a __weak pointer in a block, the retain count is untouched.
Here's an example:
- (void) doSomething {
NSLog(#"%#", self);
}
- (void) callBlock {
__weak typeof(self) weakSelf = self;
dispatch_block_t block = ^{
[weakSelf doSomething];
};
}
When you write [obj method:params] this actually translates into following call:
objc_msgSend(obj, #selector(method:), params). One of the features of Objective-C is that if you call a method on nil pointer, it returns nil. This is guaranteed by the fact that objc_msgSend(nil, #selector(anyselector), ...) always return nil. Note that SEL is just a const char[] under the covers, so it doesn't affect retain counts by any means.
Hence when the block will be executed, if your object was deallocated, the weak weakSelf variable will be nullified, and the block's body will translate into objc_msgSending to zero, which does nothing except of wasting few CPU cycles.
To sum it up, the Objective-C messaging system is implemented in such a way that calling a method does not retain this object or this method or this method's implementation, as it's a simple function call.

Resources