I have a class, there's a block proper:
#property(nonatomic, strong) void (^hehe)();
In the init method, I do the following work:
__weak test *weakSelf = self;
self.hehe = ^{
test *self = weakSelf;
NSLog(#"%zd", self.a);
NSLog(#"%zd", self->_a);
NSLog(#"%zd", _a);
};
What is the difference between the last two line in the block.
I thought self->_a is equals to _a.
But the Xcode shows warning on the last line:
Caputuring self strongly in this block is likely to lead a retain cycle
Edit:
I know the local self and the global self is not the same. How the os distinguish the difference. I used clang to rewrite the code, and get the following:
static void __ViewController__init_block_func_0(struct __ViewController__init_block_impl_0 *__cself) {
__Block_byref_weakSelf_0 *weakSelf = __cself->weakSelf; // bound by ref
ViewController *self = (weakSelf->__forwarding->weakSelf);
NSLog((NSString *)&__NSConstantStringImpl__var_folders_gp_6ztdfl3n5919c3y4pb03gd340000gn_T_ViewController_ad5b98_mi_0, ((NSInteger (*)(id, SEL))(void *)objc_msgSend)((id)self, sel_registerName("a")));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_gp_6ztdfl3n5919c3y4pb03gd340000gn_T_ViewController_ad5b98_mi_1, (*(NSInteger *)((char *)self + OBJC_IVAR_$_ViewController$_a)));
NSLog((NSString *)&__NSConstantStringImpl__var_folders_gp_6ztdfl3n5919c3y4pb03gd340000gn_T_ViewController_ad5b98_mi_2, (*(NSInteger *)((char *)self + OBJC_IVAR_$_ViewController$_a)));
}
The last two line is used the same self...
Because it means a different self. A quick rename will make everything clear :
__weak test *weakSelf = self;
self.hehe = ^{
test *strongSelf = weakSelf;
NSLog(#"%zd", strongSelf.a);
NSLog(#"%zd", strongSelf->_a);
NSLog(#"%zd", _a);
};
Now it is clear, that the last line captures self from outside the block. The way you had it named, made it harder to differentiate between the self that was a local variable declared inside a block, and the self that was captured from outside its scope.
Referring to _a is a direct reference to an instance variable from the enclosing scope. That implicitly captures self. It doesn't invoke the property's getter/setter. It points directly to the instance variable.
Don't do that from inside a block that persists. (An "escaping" block, as Apple has started calling it.) Use the weakSelf/strongSelf syntax #Losiowaty showed in his answer.
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?").
I'm trying to get variables and properties in self in a block for actions to complete, but, if I reference self or a global variable in self when self is the object running the block, it warns me of a retain loop. Here's what I'm doing:
I'm adding actions to an NSMutableArray that are of type (void(^)() (in other words, a block returning void with no parameters).
I call it using this syntax later on, where i is an int determined by code (that is in the bounds of the array:
void (^someBlock)() = arrayOfActions[i];
someBlock();
The code works and runs fine, but, because I use properties of self within the block, Xcode warns me of a retain loop. Should I ignore it because it's simply a warning and everything works fine in code (it only executes the block once), or should I do something different?
You should definitely not ignore the warning, but use __weak instead to define a weak reference and eliminate retain cycles as described in the documentation:
__weak SelfType *weakSelf = self;
void (^aBlock)() = ^(){
SelfType *strongSelf = weakSelf;
//User strongSelf
};
Alternatively you can use libextobjc (https://github.com/jspahrsummers/libextobjc) with its convenient #strongify and #weakify annotations.
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 am new to blocks in iOS and had a quick question regarding their use. Say I have the following setup:
viewController.rowLabels = #[#"Hello", #"World"];
viewController.testBlock = ^(NSInteger itemIndex) {
// here i want to access another property of the viewController called foo
};
So, as seen above, I want to access another property of the view controller within the block itself. Do i need to do a *__weak -> strong assignment to achieve this or can i simply access it like NSLog(viewController.foo)?
The simple, but possibly problematic answer, is just to access it as you do the other properties:
viewController.rowLabels = #[#"Hello", #"World"];
viewController.testBlock = ^(NSInteger itemIndex) {
... viewController.foo ...
};
From your fragment we cannot know what viewController is - e.g. it could be a local variable from the method this fragment is in or a global variable etc. If you are just reading the value in viewController, as you are here, this does not matter[1].
The above works but there might be a problem: you probably have a strong reference cycle. The viewController instance references the block through it's testBlock property, and the block references the viewController instance. If both these references are strong (likely) then you have a circular dependency and the viewController instance and the block can never be freed by the system. You can break this cycle using a weak reference:
viewController.rowLabels = #[#"Hello", #"World"];
__weak ViewController *weakViewController = viewController; // make a weak reference to the instance
viewController.testBlock = ^(NSInteger itemIndex)
{
// temporarily make a strong reference - will last just as long as the block
// is executing once the block finishes executing the strong reference is
// removed and no strong reference cycle is left.
ViewController *myController = weakViewController;
// only execute if the `ViewController still exists
if (myController != nil)
{
... myController.foo ...
}
};
HTH
[1] note that the value you are reading is a reference to a ViewController instance and you can modify properties of that instance, what you cannot do (and are not trying to do) is modify which instance the viewController references if viewController is a local variable.
Declare a __block variable containing the view controller object, like so:
__block __weak ViewController *blockVC = viewController;
viewController.testBlock = ^(NSInteger itemIndex) {
NSLog(#"%#", blockVC.foo);
};
I've used both __block and __weak since __block is implicitly strong, but adding __weak as a reference can help break the strong reference cycle while still using __block's strong reference to prevent deallocation.
As of iOS 5.0, it seems as if you can just create a __weak reference as opposed to using a __block variable to access a variable and its properties within a block:
__weak ViewController * weakVC = viewController;
viewController.testBlock = ^(NSInteger itemIndex) {
ViewController * strongVC = weakVC;
if (strongVC) {
NSLog(#"%#", strongVC.foo);
}
};
But note that unlike using __weak in combination with the __block storage type, __weak specifies a reference that might not keep the object alive, i.e. may deallocate, so even within the block, weakVC may be nil before you actually need it. (This is why the if (strongVC) conditional is required when just using a __weak variable alone.)
Mike Ash has written this introduction to ARC where he introduces something like:
__weak Foo *_weakFoo = [object foo];
Why would I want to do that for a local, temporary variable? __weak is a zeroing reference which will set the _weakFoo pointer automatically to nil as soon as the referenced object gets deallocated. Also, __weak is only available in iOS >= 5.
When would I run into trouble when I simply do this?:
Foo *_weakFoo = [object foo];
This is always expected to return an object or nil. My guess is this:
Foo *_weakFoo = [object foo];
[self doSomethingStupid]; // does something bad so foo gets deallocated
[_weakFoo doIt]; // CRASH! msg sent to deallocated instance 0x123456
One thing that still bugs me with ARC is: When does it know that I don't need an object anymore? I'd argue that when I set a pointer to nil or to something else it figures out that the previously referenced object isn't needed by this owner anymore and therefore maybe can go away. But the point is: I set it to nil. So it's nil anyways!
So when would __weak for a local variable make sense, and what kind of crazy thing must I do somewhere else so that I really need that?
I use __weak local variables if I have to manipulate self inside of a block to avoid a retain cycle. Consider this example where I'm using GCD and blocks to perform a network request for a string, and then setting it on a label declared by the class, in this case, TurtlesViewController.
__weak TurtlesViewController *weakSelf = self;
dispatch_queue_t networkQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(networkQueue, ^{
// Kick off a network task for some data that is going to populate a label declared on our class
NSString *returnString = [networkDataSource retrieveTurtleTime];
// Dispatch back to the main thread to populate the UILabel
dispatch_async(dispatch_get_main_queue(), ^{
// Using self.label here creates a retain cycle. Self owns the block and the block has captured self
self.label.text = returnString;
// Instead, we use weakSelf for our reference to the label as it will be torn down by ARC at the end of the loop.
weakSelf.label.text = returnString;
});
});