Is it ok if i do something like:
-(void)example{
__weak __typeof__(self) weakSelf = self;
dispatch_queue_t dispatchQueue = dispatch_queue_create("q_getRestaurants", NULL);
dispatch_async(dispatchQueue, ^{
dispatch_async(dispatch_get_main_queue(), ^{
[weakSelf doSomething];
});
});
}
-(void)doSomething{
//can i use self inside this method????
self.view.backgroundColor = [UIColor redColor];
}
The thing is that i wanna know if there is ok if i use self inside the do something method that is being called from a queue that has a weakSelf call.
Yes. You're good there. Only variables inside the block itself are retained.
Related
I usually use block like this if there might be a retain-cycle:
- (void)someFunction {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
[weakSelf doSomething];
}];
}
But recently I saw another way like:
- (void)someFunctionWithParam:(id)param {
__weak __typeof(param) weakParam = param;
[self setHandler:^{
__typeof(weakParam) strongParam = weakParam;
[strongParam doSomething];
}];
}
What's the difference between them?
Edit1: Does it mean the param won't be release when self running the handler?
In the second example, there is no benefit to creating the strongSelf variable in that specific case, but I can show you an example where there is a benefit.
In the first example, the statement [weakSelf doSomething] loads the reference in weakSelf, retains it, sends the doSomething message, and then (after doSomething returns) releases the reference. The second example does essentially exactly the same steps “by hand”.
Here's a slightly different example:
- (void)someFunction {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
[weakSelf doSomething];
[weakSelf doAnotherThing];
}];
}
In my code, suppose there's only one strong reference to the self object at the time the block is called. The [weakSelf doSomething] statement creates a second, temporary strong reference to it. While doSomething is running, another thread releases the other strong reference. When doSomething returns, the statement releases its temporary strong reference. Now self has no more strong references, so it is deallocated and weakSelf is set to nil.
Then the [weakSelf doAnotherThing] statement runs. It wants to load and retain the contents of weakSelf, but because weakSelf is now nil, the statement just uses nil. It sends the doAnotherThing message to nil, which is allowed and doesn't crash. It just does nothing. It doesn't call the method.
This might not be behavior you want. Maybe you always want doAnotherThing to run on self if doSomething ran. That's when you need the pattern in your second example:
- (void)someFunctionWithParam:(id)param {
__weak __typeof(self) weakSelf = self;
[self setHandler:^{
__typeof(weakSelf) strongSelf = weakSelf;
[strongSelf doSomething];
[strongSelf doAnotherThing];
}];
}
Here, when the block is called, it immediately stores a strong reference to self in strongSelf (or it stores nil if weakSelf has already been set to nil). The strongSelf reference can't be released until after the last use of the strongSelf variable, so it's impossible for self to be deallocated after doSomething but before doAnotherThing.
In my view-controller usually I load some data from server and call some function to render data or do some action when request data comes back from server. following is the snippet of such code.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
__weak typeof(self) weakSelf = self;
[MyRequestManager loadObjects: ^(MyObject* object, NSError* error) {
weakSelf.textField.text = object.text;
//do some other actions
}];
}
If before data comes from server view is disappeared/unloaded, will callback will be called? If it is called there are chances of crash of unexpected things to happen. So how can we prevent that from happening?
I can think of one way to set a variable in viewWillAppear and viewWillDisappear. What is recommended way of doing this?
As you're keeping weakself inside, self won't be retained, so it will be dealloced. You should make your weakself a strong value inside, use the strong one and it won't crash.
__weak typeof(self) weakSelf = self;
dispatch_group_async(_operationsGroup, _operationsQueue, ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomething];
[strongSelf doSomethingElse];
}
});
You may find more depth information eg here: http://albertodebortoli.github.io/blog/2013/08/03/objective-c-blocks-caveat/
Do I need to check if weak self is nil in blocks?
I create weakSelf pointer like:
__weak typeof(self) weakSelf = self;
and in the beginning of the blocks I do
if(!weakSelf){return;}
is this unnecessary? or does it depend on whether I coded the rest correctly so that when the self dies, others die too?
That check is unnecessary, and is giving you a false sense of security.
Here's the problem:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
if (!weakSelf) { return; }
// THE LINE OF INTEREST
[weakSelf doSomething];
});
At THE LINE OF INTEREST, some other thread might clear the last strong reference to self, at which point weakSelf is set to nil. So the doSomething message gets sent to nil, which is “safe” (it does nothing), but might not be what you expected!
It's worse if you want to take a different action when weakSelf is nil, e.g.
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
if (weakSelf) {
[weakSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
In this case, between the time the block verifies that weakSelf is not nil and the time it sends the doSomething message, weakSelf might become nil, and neither doSomething nor doSomethingElse will actually run.
The correct solution is this:
__weak typeof(self) weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
typeof(self) strongSelf = weakSelf;
if (strongSelf) {
[strongSelf doSomething];
} else {
[someOtherObject doSomethingElse];
}
});
In this case, copying weakSelf to strongSelf (which is strong by default) is atomic. If weakSelf was nil, strongSelf will be nil. If weakSelf was not nil, strongSelf will not be nil, and will be a strong reference to the object, preventing it from being deallocated before the doSomething message.
It seems quite unnecessary since calling a message on nil is a no-op. (Nothing happens)
^{
[weakSelf doSomething]; //Does nothing if weakSelf is nil
}
The only reason I can think you might want to do this is if other messages (not on self) shouldn't be called
^{
// Here I don't want to add weakSelf as an observer if it's nil
if (!weakSelf) return;
[OtherClass addObserverForSomething:weakSelf];
}
Weak references do not retain the referred object. If none else is retaining it, the object is released and the weak references refers to nil.
Therefore it is possible that your code is executed with a weakSelf that refers nil. But this is no reason to check for it at all. Especially in Objective-C you use a defined behavior, if you send a message nil. I. e. it is perfect code, if you set a property using a nil reference. It simply goes to nowhere.
Of course sometime you do not want to interact with nil. In such a case you have to check for it.
BTW: You need weakSelf only in some, rarely circumstances. It is an urban legend that in closures in general references to self has to be weak to prevent retain cycles. It has not been true, it is not true and it will never be true.
This is what I have learned: when using self retained block
I need a weakSelf to break retain cycle
I need a strongSelf to prevent self from becoming nil half-way
so I want to test if a strongSelf can really keep self alive like so:
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"viewDidLoad");
self.test = #"test";
NSLog(#"%#",self.test);
__weak typeof(self)weakSelf = self;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
__strong typeof(weakSelf)strongSelf = weakSelf;
strongSelf.test = #"newTest";
NSLog(#"%#",strongSelf.test);
});
}
- (void)dealloc {
NSLog(#"dealloc");
}
#end
The ViewController will be pushed into a navigationController and pop out immediately. The output is
why the null?
There is another question I have a project which contains tons of weakSelf without strongSelf in the block and I get plenty of signal 11 crash. Is it related? Is it worth to add strongSelf to each of them?
strongSelf ensures that if self was not released yet, it won't during the execution of the block.
If the self is gone before you create strongSelf, it will be nil.
You should check, if strongSelf does contain something:
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
typeof(weakSelf)strongSelf = weakSelf; // __strong is not needed
if(strongSelf){
strongSelf.test = #"newTest";
NSLog(#"%#",strongSelf.test);
}
});
The code in your block is executed after 3s delay. So by this time the weakSelf is already nil. That's why strongSelf is nil
I think you don't hit the problem right. Using weakself will break the retain cycle, however this line:
__strong typeof(weakSelf)strongSelf = weakSelf;
Does not capture strong reference to self until block is executed. Hence if your pointer to VC outside of block is nil, VC will be released and weakSelf will be nil when you hit the block - meaning your strongSelf will be nil also. Capturing strong reference guarantee only that if you have weak self at the begin of the block, you will have it until the end and it won't be dealloc meanwhile. However if weakSelf is nil at begin of the block - strongSelf will be nil also. Moreover you do not need to declare it as strong inside block, as it will be strong by definition, hence it could be replaced by:
typeof(weakSelf)strongSelf = weakSelf;
or
id strongSelf = weakSelf;
I usually get a warning when I call anything on self in a block retained by self:
[self.someView doSomething:^{
self.aVar = #"Hello!";
}];
I have to do:
__weak SomeObject *weakSelf = self;
[self.someView doSomething:^{
weakSelf.aVar = #"Hello!";
}];
But if I call a method on weakSelf, and that method uses self, will that lead to a retain cycle even though I don't get a warning? I am talking about this:
__weak SomeObject *weakSelf = self;
[self.someView doSomething:^{
weakSelf.aVar = #"Hello!";
[weakSelf aMethod];
}];
and aMethod uses self
As long as your weakSelf is declared outside your block, there is no retain cycle.
Use of objects inside the block implicitly increments the retain count. But you'd be calling aMethod on weakSelf rather than self, so the retain count is not affected.
You should declare the __weak to self outside of your block:
__weak SomeObject *weakSelf = self;
[self.someView doSomething:^{
weakSelf.aVar = #"Hello!";
[weakSelf aMethod];
}];
Else the compiler would have already retained self since it is used with the block.
Beter even is using the __block directive, because __weak is iOS 5 and higher only.
__block SomeObject *weakSelf = self;
[self.someView doSomething:^{
weakSelf.aVar = #"Hello!";
[weakSelf aMethod];
}];
About an other method calling self and causing retain, I've never seen this behavior. I always use the __block directive which might catch that one as well.