This question already has answers here:
Strong reference to a weak references inside blocks
(2 answers)
Closed 6 years ago.
I am trying to understand this code :
__weak LoginViewController *weakSelf = self;
NSTimer *networkTimer = [NSTimer pym_scheduledTimerWithTimeInterval:15.0 block:^{
LoginViewController *strongSelf = weakSelf;
[strongSelf timeout];
} repeats:NO];
[PYMAuthManager loginWithUsername:username password:password completionHandler:^(BOOL successful) {
if (successful) {
[networkTimer invalidate].......
it's for a network timer, that will timeout after 15 seconds if no activity. Why is the pointer *strongSelf = weakSelf created in the block? Is it not okay just to use [weakSelf timeout]? I understood that whenever accessing self in a block we have to use a weak reference, why is another pointer created here? Any help would be great, thank you.
Edit: Updated to better reflect actual system semantics (as pointed out by Darren).
By using weakSelf in the block, you are avoiding retain cycles. If you were to replace the block code with [weakSelf timeout], there would be no difference; the object is retained for the duration of the timeout execution.
If you had instead used __unsafe_unretained to create your weakSelf, it's possible that the machine could release the memory back to the system and cause your app to EXC_BAD_ACCESS while executing timeout. Creating a strong reference in this instance would avoid this error.
When you create a strong reference, it is held within its scope; in this case, for the duration of the block. Because your block only effectively executes one statement, the replacement to [weakSelf timeout] causes no harm. If you had multiple statements that all used weakSelf or relied on the state of weakSelf, then you would want to create a strong reference for the scope of all of the statements.
Related
In a class, I've declared a thread like:
#property (nonatomic, strong) dispatch_queue_t databaseQueue;
and then I perform an operation this thread like
dispatch_async(self.databaseQueue, ^{
[self.dao deleteRetries];
});
Can this potentially create a retain cycle?
AND
the current class holds a strong reference to viewControllerToDismiss and there is a code which looks like:
[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
[self performSomeAction];
}
is this a retain cycle?
It is merely a strong reference to self that is eliminated automatically when the block finishes running and GCD releases the block. Note, this is a strong reference between the queue object itself, the block, and self, but not to databaseQueue. E.g. even if databaseQueue was some local reference that had fallen out of scope after you dispatched but before it ran, you'd still have a strong reference between the queue object, the block, and self.
If you don't want that strong reference at all, use weakSelf pattern:
typeof(self) __weak weakSelf = self;
dispatch_async(self.databaseQueue, ^{
[weakSelf.dao deleteRetries];
});
You asked:
Please could you elaborate more on "Note, this is a strong reference between the queue object itself, the block, and self, but not to databaseQueue"?
Consider:
- (void)runManyTasks {
dispatch_queue_t queue = dispatch_queue_create("com.domain.app.foo", 0);
for (NSInteger i = 0; i < 10; i++) {
dispatch_async(queue, ^{
[self doSomething];
});
}
}
- (void)doSomething {
[NSThread sleepForTimeInterval:1];
}
Even though I have no references in my code to that local variable, queue, after runManyTasks finishes, if I call runManyTasks, GCD will keep its own strong reference to the actual underlying queue object until all tasks finish, and the queue will keep copies of those blocks until they finish running, and those blocks will maintain a strong reference to self until GCD finishes with all of them (roughly 10 seconds, in this example).
You go on to edit your question and ask:
the current class holds a strong reference to viewControllerToDismiss and there is a code which looks like:
[viewControllerToDismiss dismissViewControllerAnimated:shouldAnimateDismiss completion:^{
[self performSomeAction];
}
is this a retain cycle?
For all practical considerations, no. That block is released as soon as the dismissal animation is done, so you generally wouldn't complicate your code with weakSelf pattern here. In fact, that view controller isn't dismissed until the animation finishes, anyway, so there's absolutely nothing gained from weakSelf pattern (other than making code more convoluted).
First, you have not declared a thread. It’s a queue, that’s something different. (Fortunately, as working directly with threads is a pain.)
You are dispatching a block into the queue. The block retains self and the queue retains the block, which means you do have a retain cycle, since the queue, being a strong property, is retained by self:
self -> queue -> block -> self -> queue -> …
BUT the block should be short-lived, judging by the API. When the block is finished, it will get released from the queue, breaking the retain cycle. So I would not worry about a case like this.
Using self directly in blocks will create strong retain cycle.
To avoid retain cycle, please check below code
__weak YourViewController *weakSelf = self;
dispatch_async(self.databaseQueue, ^{
if (weakSelf){
YourViewController *strongSelf = weakSelf;
[strongSelf.dao deleteRetries];
}
});
For more info visit this link Working with blocks
I am new to blocks and while reading over the internet I found that I must use weak variables to blocks, because blocks retains the variables. I am little confuse while using self with blocks. lets have an example:
#interface ViewController : UIViewController
#property (copy, nonatomic) void (^cyclicSelf1)();
-(IBAction)refferingSelf:(id)sender;
-(void)doSomethingLarge;
#end
Here I have a ViewController and it has declared block property with copy attribute. I don't want to make a retain cycle so I know when using self in the block I need to create weak object of self eg:
__weak typeof(self) weakSelf = self;
What I want to make sure is my block executes on background thread and may be user hit back before it get finish. My block are performing some valuable task and I don't want that to loose. So I need self till the end of block. I did following in my implementation file:
-(IBAction)refferingSelf:(id)sender
{
__weak typeof(self) weakSelf = self; // Weak reference of block
self.cyclicSelf1 = ^{
//Strong reference to weak self to keep it till the end of block
typeof(weakSelf) strongSelf = weakSelf;
if(strongSelf){
[strongSelf longRunningTask];//This takes about 8-10 seconds, Mean while I pop the view controller
}
[strongSelf executeSomeThingElse]; //strongSelf get nil here
};
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), self.cyclicSelf1);
}
According to me, using typeof(weakSelf) strongSelf = weakSelf; should create a strong reference of my self and when user hit back, self will still have one strong reference inside block until the scope get over.
Please help me to understand why this get crash? Why my strongSelf is not holding the object.
Your reference is not strong. Just add __strong directive like this:
__strong typeof(weakSelf) strongSelf = weakSelf;
I've found an answer. I was really curious myself, because your code seemed legit to me. The idea at least. So I've set up a similar project and experimented a little. The problem is this line:
typeof(weakSelf) strongSelf = weakSelf;
Change it to either
__strong typeof(weakSelf) strongSelf = weakSelf;
as suggested by #LDNZh or
typeof(self) strongSelf = weakSelf;
And your code will work.
UPDATE: Since this question shows up a lot I've made some changes to my example project. I'm making it available on github for everyone for future reference.
This question already has answers here:
WeakSelf in blocks
(2 answers)
How do I avoid capturing self in blocks when implementing an API?
(8 answers)
Closed 7 years ago.
Just like the following code:
__weak typeof(self) weakSelf = self;
[self methodThatTakesABlock:^ {
[weakSelf doSomething];
//[self doSomething];//Why not this line?
}];
[self methodThatTakesABlock:^ {
[self doSomething];
}];
Does not cause a retain cycle unless the completion block is stored within self. If it is a property then, self will have a strong reference to the block and the block will have a strong reference to self causing a retain cycle. That is why you need to use weak, to avoid this retain cycle. But remember, you must use a weak self only within blocks that are stored as properties or ivars within self.
If the completion block is only called in the methodThatTakesABlock then you don't have to use a weak self since the block is not retained. In this case, the block will have a strong reference to self but self will not have one towards the block, so no retain cycle in this case.
I got a question regarding objc blocks. If you want to use self in a block you should weakify it and strongify it again in the block so you don't get into a retain cycle. In my case I also want to write a property of the class where the block exists in. Now I'm a little bit confused if this makes sense and if I ever can access this property later or if I totally loose the reference to this property.
Here's my code example:
__weak typeof(self)weakSelf = self;
void (^handleRequestBlock)(NSURLSessionDataTask*, id) = ^(NSURLSessionDataTask *task, id responseObject)
{
__strong typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
strongSelf->_response = [strongSelf extractResponseData:responseObject forRequestType:requestType];
[strongSelf postSuccessNotification:strongSelf->_response];
}
};
First of all make this code completely sense or is there something to optimize?
Could someone maybe explain again what happens internally in objc. I read several articles now and I am more confused than before about retain cycles. As far as I know a block is an object and if it captures vars the vars are copied internally and declared as const by default as long as you don't use the __block declaration (what about properties that life in a global scope?). I still don't completely get what's the lifetime of a block and why pointers could dangling around, because the whole block object and its content should be deallocated when they finished. If someone has the time I would appreciate a nerdy and detailed answer or a link to a good reading resource! :)
Thanks in advance :)
I want to explain 3 ways to write the block.
First: use self
void (^handleRequestBlock)(NSURLSessionDataTask*, id) = ^(NSURLSessionDataTask *task, id responseObject)
{
self->_response = [strongSelf extractResponseData:responseObject forRequestType:requestType];
[weakSelf postSuccessNotification:self->_response];
};
the block handleRequestBlock retain self, if self has a property that owns the block, there will be a retain circle. The block will keep self retained until you release the block. So if you release the block after call the block (set the block to nil to release it), the cycle will not exist.
Note: Most implementation will not release the block after call it, because we may need it afterwards, so the retain circle will exist all the time.
Second: Use weak self
__weak typeof(self)weakSelf = self;
NSLog(#"%p", &weakSelf) ;
void (^handleRequestBlock)(NSURLSessionDataTask*, id) = ^(NSURLSessionDataTask *task, id responseObject)
{
NSLog(#"%p", &weakSelf) ;
weakSelf->_response = [strongSelf extractResponseData:responseObject forRequestType:requestType];
[weakSelf postSuccessNotification:weakSelf->_response];
};
the block will not retain self and if the instance of self is deallocated, weakSelf is nil.
More about this example: I add two lines of log to show that : the address of variable weakSelf out of the block scope and inside the block scope are different. Because weakSelf is a stack local and __weak variable, so block capture it with a variable that has same value of weakSelf but not send retain message to the instance it indicates, weakSelf here is another variable with different address.
Third: retain self only when it is needed.
__weak typeof(self)weakSelf = self;
void (^handleRequestBlock)(NSURLSessionDataTask*, id) = ^(NSURLSessionDataTask *task, id responseObject)
{
__strong typeof(weakSelf)strongSelf = weakSelf;
if (strongSelf) {
strongSelf->_response = [strongSelf extractResponseData:responseObject forRequestType:requestType];
[strongSelf postSuccessNotification:strongSelf->_response];
}
};
There is a disadvantage on the second way: If self is not deallocated when the block is executing the first line of code, after executing this line of code , the instance of self is deallocated (because we didn't retain it, it may be sent release method on other thread and it will be deallocated), at the second line of code , weakSelf is nil, so something bad will happen, it depends on the logic of your code.
So the third way solved that, it only retain self when the block is executing and release self at the end of the block (release means decrease retain count by 1).
More Links :
Working with blocks
A look inside blocks
How do i avoid caturing self in blocks...
I'm trying to figure out if I do this right:
If I have one block, I'll do this:
__weak MyClass *weakSelf = self;
[self performBlock:^{ //<< Should I use self, or weakSelf here?
[weakSelf doSomething];
} afterDelay:delay];
But what happens if there's a block in a block? Would this be correct?
__weak MyClass *weakSelf = self;
[self performBlock:^{
[weakSelf doSomething];
[self performBlock:^{
[weakSelf doSomething];
} afterDelay:1.0f];
} afterDelay:delay];
Also, in the function below, do I need to use [block copy]?
- (void)performBlock:(void (^)(void))block afterDelay:(float)delay
{
if (block)
{
if (delay > 0)
{
[self performSelector:#selector(executeBlockAfterDelay:) withObject:[block copy] afterDelay:delay];
}
else
{
[self executeBlockAfterDelay:[block copy]];
}
}
}
- (void)executeBlockAfterDelay:(void(^)(void))block
{
if (block)
block();
}
In this case (below) use just strong self, because the block is copied just for those few seconds. And usually if you want the self to perform block, you want to it to stay alive until that time, so strong reference is perfectly okay.
[self performBlock:^{
[self doSomething]; // strong is OK
} afterDelay:delay];
Block inside a block? In your case those two block are just delayed one-shot blocks, so the same as above, use strong. But there are differences between blocks. If you store the block for longer time, maybe for multiple invocations you should avoid retain-cycles.
Example:
self.callback = ^{
[self doSomething]; // should use weakSelf
};
This may cause retain-cycle. In fact it depends on how the block is used. We see that the block is stored (copied) in property for later use. However, you can prevent the retain-cycles by nullifying block that will not be used any more. In this case:
self.callback(); //invoke
self.callback = nil; //release
When using ARC, you don't have to copy blocks yourself. There were bugs in early versions after blocks were added, but now the compiler under ARC knows when to copy blocks. It is clever enough to copy it in this case:
[self performSelector:#selector(executeBlockAfterDelay:) withObject:block afterDelay:delay];
Rather than implementing -performBlock:afterDelay:, just use dipatch_after(). Among other things, that's not a message delivered to an object, so there's no question of what receiver to target it at.
Actually, there's no memory management issue here at all. One typically only needs to do a "weak self" approach when an object retains a block and the block (perhaps implicitly) retains that same object. However, the object is not retaining the block. It is being retained by the framework until the -performSelector:withObject:afterDelay: fires, but that's not a retain cycle.
If there were a retain cycle, then you should not reference self in the blocks. So, your nested case is wrong in invoking a message on self rather than weakSelf.
Finally, yes, you do need [block copy] whenever you are keeping a block after execution leaves the scope of its declaration or if you pass it to non-block-specific API that does. That is, you don't need to copy a block when you pass it to, say, dispatch_async() because that's a block-aware API that knows to make its own copy as necessary. But -performSelector:withObject:afterDelay: is not block-aware. It just treats its argument as a generic object and retains it. So, you do have to copy the block when passing it to that.
One the most important thing to understand about blocks is that they capture a piece of code (including values) in an abstract entity that can be manipulated as an atomic object (keep it somewhere, pass it, copy, etc...). Actually it is implemented in a way that guarantee that by default your block will remain valid and executable safely later.
Then capturing and retaining the required dependencies inside the block is necessary.
Unfortunately, in some cases (quite often actually) the block is retained by the instance that creates it and it retains itself that instance. This is called a retain loop and makes your object and your block impossible to dealloc unless you break one of the retaining relation yourself. This can happen if you reference your block with an instance variable for example and you don't nillify it manually.
This is probably the main issue with blocks especially because sometime, you don't know that your block retains your self instance (NSAssert within your block for example). Then:
If you execute your block immediately and release it (use your block
with dispatch release it after execution) there is no risk since you
are sure your object referenced by self still exist.
But if the execution is delayed it is important to retain your object within your block. But in that case your object should not retain your block to avoid a retain loop (A retains B and B retains A). If you define and optionally reference your block in the private scope of method it is perfect.
About copy. Yes it can be safer to use copy if your block in passed as a method argument to be sure you have a clean exclusive block in this scope with a +1 retainCount. But maybe ARC already do it for you. Not sure about that. For example it performWithSelector seems to do it for free, then copy is not dangerous. Just a useless. Sometime the compiler can optimise that by removing it but it has to be checked.
I usually do this:
__unsafe_unretained __block id blockSelf = self;
and then use it in my blocks no issues.
So in your case:
__unsafe_unretained __block MyClass *blockSelf = self;
[self performBlock:^{
[weakSelf doSomething];
[self performBlock:^{
[weakSelf doSomething];
} afterDelay:1.0f];
} afterDelay:delay];
Also to make your life a tad easier - make a utilities class and put this in the header
void RunAfterDelay(NSTimeInterval delayInSeconds, dispatch_block_t block);
and then this in the .m file
void RunAfterDelay(NSTimeInterval delayInSeconds, dispatch_block_t block)
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC), dispatch_get_main_queue(), block);
}
Import the utilities into your prefix and you can go:
__unsafe_unretained __block MyClass *blockSelf = self;
RunAfterDelay(1.0f,^{
[blockSelf doSomething];
RunAfterDelay(delay,^{
[blockSelf doSomething];
})
});
I find it a bit nicer to read than the verbose default ones.
Hope this helps :)