AFNetworking, UITableView and Blocks - ios

So I was reading How do I avoid capturing self in blocks when implementing an API? about how memory management works in regards to referencing self within a completion block and that got me thinking: will the following cause a retain cycle?
Pseudocode:
[AFnetworking requestGet:#"http://www.website.com" completionBlock:(^)(RequestObj* request, NSError* error){
[self.tableView reloadData];
}];
Ignoring syntax problems, does self.tableView cause a retain cycle? Is it necessary to do the following instead?
__weak id weakSelf = self;
[AFnetworking requestGet:#"http://www.website.com" completionBlock:(^)(RequestObj* request, NSError* error){
[weakSelf.tableView reloadData];
}];
Or is there some sort of memory magic that AFNetworking does to prevent this?
Edit courtesy of Aaron Brager
Here you don't have a retain cycle. But if you did, in the completion block, you should convert weakSelf back into a strong reference so it won't get deallocated halfway through your completion block.
id strongSelf = weakSelf;
[strongSelf.tableView reloadData];

A retain cycle occurs when two or more objects have strong references to each other.
In this case, the block will have a strong reference to self, but self doesn't have a strong reference to the block, so you are fine here and no need to use weakSelf.
The case when you'll have a retain cycle and need to break it by using the weakSelf is when the class has a strong reference to the block too like in the following example:
typedef void (^CompletionCallback)(RequestObj* request, NSError* error);
#interface SomeClass() {
/// Strong reference to the block
CompletionCallback completionBlock;
}
#end
#implementation SomeClass()
- (void)someMethod {
completionBlock = ^(RequestObj* request, NSError* error) {
/// Strong reference to the class
[self.tableView reloadData];
};
[AFnetworking requestGet:#"http://www.website.com" completionBlock:completionBlock];
}
#end
In this example, both completionBlock and self have strong references to each other, and therefore you'll have a retain cycle here and need to break it.

Related

Preventing `self` from creating a strong reference in blocks

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 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];
}];
}];

What is the reason of #strongify

In ReactiveCocoa there is macro to prevent retain cycle #weakify and #strongify. From my understanding #weakify do something like what I usually do that is create __weak reference for using in the block, but what about #strongify?
Why do I need to make it strong again in the block?
Here is some sample usage:
#weakify(self);
[RACObserve(self, username) subscribeNext:^(NSString *username) {
#strongify(self);
[self validateUsername];
}];
If you just use a weak reference within the block, self can get deallocated while the block is being executed. But if you want to ensure that self stays in memory until the block finishes execution, you have to convert the weak reference back to strong.
The #weakify(self) and #strongify(self) are equivalent to
__weak typeof(self) __weak_self__ = self; // weakify
[self setBlock:^{
__strong typeof(__weak_self__) self = __weak_self__; // strongify
[self doSomething];
}];
You must use __weak_self__ if there's no #strongify(self) in the block.
So, the most important reason is that you can still use self instead of __weak_self__ in the block. To avoid mistakes like this, copying [self doSomething]; into the block, but forget to change self to __weak_self__. It happens more than "self can get deallocated while the block is being executed".

Messaging a __weak object?

What happens if I send a message to a weak object? Does sending the message possess the object and hold it in memory until return?
I'm thinking of this pattern:
__weak MyObject *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf doSomeAction];
});
Assuming weakSelf is non-nil when the message is sent, might it be deallocated while doSomeAction is working or is it guaranteed to remain valid until doSomeAction returns?
From the Clang ARC documentation:
Reading occurs when performing a lvalue-to-rvalue conversion on an object lvalue.
For __weak objects, the current pointee is retained and then released at the end of the current full-expression. This must execute atomically with respect to assignments and to the final release of the pointee.
Messaging a weak reference performs an lvalue-to-rvalue conversion on the variable, which means the value of the weak reference will be retained and then released at the end of the current full-expression (basically, the statement). It's basically equivalent to assigning to a strong variable whose scope only lasts for the current statement, and then messaging that strong variable.
The takeaway here is if you want to message a weak variable once, and never touch it again, and you don't care about the side-effects of evaluating the arguments to the method in the case where the weak reference ends up nil, then go ahead and message the weak reference directly. But if you need to refer to the weak reference twice (in separate statements), or the side-effects of evaluating the arguments do matter, then you should assign to a strong variable and test for non-nil before proceeding.
You asked:
Assuming weakSelf is non-nil when the message is sent, might it be deallocated while doSomeAction is working or is it guaranteed to remain valid until doSomeAction returns?
This ARC behavior has changed over time. But nowadays, weak references can be released as soon as the last strong reference is removed.
Thus, consider the following:
- (void)dealloc {
NSLog(#"%s", __FUNCTION__);
}
- (void)startBackgroundOperation {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[weakSelf doSomeAction];
[NSThread sleepForTimeInterval:5];
[weakSelf doSomeAction2];
});
}
- (void)doSomeAction {
NSLog(#"%s", __FUNCTION__);
}
- (void)doSomeAction2 {
NSLog(#"%s", __FUNCTION__);
}
If you have some code invoke startBackgroundOperation and let the object be deallocated in the intervening time between doSomeAction and doSomeAction2, you will see the former will be called and the latter will not. I.e. if there were no more strong references, the object could be deallocated in the middle of the block.
So, if you want weak reference, but want an “all or none” sort of behavior whereby it to be retained for the duration of the closure, we perform what is jokingly referred to as the “weakSelf-strongSelf dance”:
- (void)startBackgroundOperation {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
typeof(self) strongSelf = weakSelf; // establish just-in-time strong reference (if `weakSelf` is not yet `nil`)
[strongSelf doSomeAction];
[NSThread sleepForTimeInterval:5];
[strongSelf doSomeAction2];
});
}
This will ensure that the block has a weak reference, but if it is not deallocated by the time it hits the assignment of strongSelf, then it will establish and maintain a strong reference for the duration of the block.
For what it is worth, this weakSelf-strongSelf pattern is essential when dereferencing ivars with -> (avoiding race conditions with weakSelf).
E.g.
- (void)badDeferenceExample {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
if (!weakSelf) { return; }
NSInteger value = weakSelf->_someIVar; // this is race and can crash!!!
...
});
}
- (void)properDeferenceExample {
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
typeof(self) strongSelf = weakSelf; // establish just-in-time strong reference (if `weakSelf` is not yet `nil`)
if (!strongSelf) { return; }
NSInteger value = strongSelf->_someIVar; // this is safe
...
});
}

Resources