Will the block contains references to self? - objective-c

-(void) vAfterMainVariable
{
__weak BGGeneralCatalogView * weakSelf=self;
[_loAIOnebyOne vLoadStuffsWithURLBlock:^(){
NSString * URL= [weakSelf strGetURLToDownloadStuffs];
return URL;
} andPermaToastMessage: #"Loading Catalog" andCompletionBlock:^{}];
//[self.loAIOnebyOne vLoadStuffsWithURLBlock:<#^NSString *(void)blURL#> andPermaToastMessage:<#(NSString *)#> andCompletionBlock:<#^(void)completionBlock#>]
}
-(NSString *) strGetURLToDownloadStuffs
{
NSString * URL = [BGMakeURL URLforGetCatalogID:self.arArray];
return URL;
}
I uses weakSelf in the block. Yet, that weakSelf refer to a function that call self.arArray
So will the block has any strong pointer to self? When self, which is a viewController is gone from navigationController will it be deallocated soon?
To be exact, the block does NOT refer to self. The block refer to weakSelf that calls a method that refer to self. However the self in that method is the weakSelf.
Basically I followed that with this:
- (void)dealloc
{
[_loAIOnebyOne vCancelAllStuffs];
}
And it turns out dealloc is simply not called until after the block is finish. So the block must have contained self. But how?
Also how do I know which object still refer to my object?
The only object that refer to my object should be the UINavigationController object. The next one would be the block which is executing on the stack.

weakSelf needs to be a block variable. When the block is copied, it creates its own variable containing a copy of weakSelf, and that copy isn't weak.

Related

Using an ivar inside a method which is called from a block

I want to use an ivar in a method that is being called from a block. Is it fine to call the ivar directly from it without causing a retain cycle?
I have seen other questions related to calling properties- saying that we 'can' use self. Just wanted to make sure about ivars, can we call ivar directly or do we need to use self->_myInstanceVariable explicitly?
__weak MyClassName *weakSelf = self;
[MyBlockCreator myBlock:^{
MyClassName *strongSelf = weakSelf;
[strongSelf doSomething];
}];
- (void) doSomething {
_myInstanceVariable = someObject
// is it fine to use the ivar directly above?
// or do we want use self explicitly?
// like self->_myInstanceVariable
}
In this case you don't need to make the reference weak/strong at all, the only situation in which you can cause a retain cycle is if self references a block and a strong version of self is captured within that block. Since self doesn't retain the block in question, there would be no retain cycle even using a strong reference.
[Foo doWithBlock:^{
bar.baz = #"Hello World"; // Totally fine without weak/strong since bar doesn't retain the block here.
}];
In situations where self holds a strong reference to a block and the block refers to self, you need to make the reference weak outside the block then make it strong again inside.
__weak id weakSelf = self;
[self doWithBlock:^{
id strongSelf = weakSelf;
strongSelf.baz = #"Ok";
}];

Do methods called from within a block need to use weakSelf?

If the code inside a block calls a method, will a retain cycle exist if that method references self? In other words, does all code downstream of a block need to use the weakSelf/strongSelf pattern?
For example:
__weak __typeof__(self) weakSelf = self;
Myblock block = ^{
[weakSelf doSomething];
};
. . .
- (void)doSomething
{
self.myProperty = 5; // Is this ok or does it need to use a weakSelf?
}
Objective-C is not scoped like you suggest, namely, you don't have access to weakSelf from within -doSomething. Furthermore, as you are calling -doSomething on weakSelf, "self" within that call is actually referring to the same object that weakSelf is.
In short, no, you shouldn't, you can't and you shouldn't.
Retain cycle will be triggered only if you retain self inside the block. Otherwise it will just throw a warning only.
This is fine you can use this. Because block retains every vars used inside, so retain cycle would be like
Self would retain block
If block retains self then
Self would again retain block
block would retain self, so cycle goes on
The thing you are doing in method is just message passing. Everytime block is called a message would be sent to self to doSomething. And you can retain self in doSomething method it wont trigger retain cycle because this method dont have cycle loop to self. Hope you understand :)
- (void)doSomething
{
self.myProperty = 5; // Is this ok or does it need to use a weakSelf?
}
you can do this to get rid of retain cycle problem.
[self class] __weak *weakSelf = self;
self.completionBlock = ^{
[self class] __strong *strongSelf = weakSelf
[weakSelf doSomething];
};

Objective-C Blocks: Is it ok to modify self in an external method if called from a weak pointer to self?

Can you modify self from an instance method called from a weak self pointer within a block?
-(void)someMethod:(AnotherClassName *)anObject {
__weak MyClassName *weakSelf = self;
[anObject requestSomethingWithCompletion:^{
[weakSelf updateSomething];
}];
}
-(void)updateSomething {
self.something = #"update"; // Will this cause a memory leak?
}
So basically I am calling an instance method from the same class I am in, but I am doing it from a weak pointer and then changing self.
According to Apple's Programming with Objective-C Guide this is how to call a method on self within a block but it isn't clear weather I can directly modify self in that method.
If you know the answer based on something you've read before please include the source.
Thanks!
You can modify properties and call methods. There will be no memory leaks.
But your block is not thread safe now. If requestSomethingWithCompletion will run block asynchronously your class (self) could be deallocated during block execution and weakSelf will become nil. This could cause problems (depends on what does your block do). Good practice to avoid this is to write it following way
-(void)someMethod:(AnotherClassName *)anObject {
__weak MyClassName *weakSelf = self;
[anObject requestSomethingWithCompletion:^{
MyClassName *strongSelf = weakSelf;
[strongSelf updateSomething];
}
}
-(void)updateSomething {
self.something = #"update"; // No leaks here!
}

Blocks with reference to self and instance vars

What's the correct way to reference 'self' (and ivars) within blocks without the block creating a strong reference (and thus incrementing the ref count)?
For instance, I've found the following increments the ref count for 'self':
^(id sender) {
[self.navigationController popViewControllerAnimated:YES];
}
In order to circumvent the above, I've been doing the following:
__weak WhateverController *weakSelf = self;
^(id sender) {
[weakSelf.navigationController popViewControllerAnimated:YES];
};
And yes, I realize this is pseudocode.
Also, an indirect reference to self also creates a retain on self. For example, if _ivar were an instance variable, accessing it is an implicit reference to self so the following would also retain self.
^(id sender) {
[_ivar popViewControllerAnimated:YES];
}
Furthermore, to expand on your weak example, it is OK to send a message to a weak reference. If it's nil, nothing will happen. If not, then the compiler will generate code that ensures the reference remains valid through the invocation of the method.
So, this is fine:
__weak Foo *weakSelf = self;
^(id sender) {
[weakSelf.foo doSomething];
}
because foo will either be nil or if not, it is guaranteed to remain non-nil throughout the execution of doSomething.
However, the following would be inadvisable because self could go to nil in-between calls, which is probably not what you want:
__weak Foo *weakSelf = self;
^(id sender) {
[weakSelf.foo doSomething];
[weakSelf.foo doSomethingElse];
}
In that case, you probably want to create your own strong reference inside the block, so you have a consistent value throughout the execution of the block.
On the other hand, if you access iVars directly through a weak reference, you must do the weak-strong dance because this code:
__weak Foo *weakSelf = self;
^(id sender) {
weakSelf->_foo = bar;
}
will blow up if weakSelf is nil.
Thus, in the last two situations above, you want to do something like:
__weak Foo *weakSelf = self;
^(id sender) {
Foo *strongSelf = weakSelf;
if (!strongSelf) return;
// Now, do anything with strongSelf, as it is guaranteed to be around
}
Of course, the iVar situation is only a problem if you actually access iVars directly...
Apple's notation is sself but other than that - you're fine.
In a non arc project use the following code to prevent 'self' from being retained by the block:
__block id sself = self

Block that can access self and be used throughout an instance

I want a block that is available throughout a class, so it can be re-used many times by different methods in the instance.
I want that block to be able to reference self.
I want to not have the block create any nasty retain cycles by retaining self.
So far I am stumped. I managed to create block in the .m outside of any method definitions, and that got me partway - I could reuse the block everywhere, but I couldn't access self. I tried putting the block into an ivar but I'm doing something wrong there and now I'm getting random EXC_BAD_ACCESS. Can someone explain it simply, line by line?
Try the following:
typedef void (^MyBlock)();
#implementation MyClass
{
MyBlock block;
}
- (id) init
{
self = [super init];
if (!self)
return nil;
__block MyClass* _self = self;
block = [^ {
[_self sendSomeMsg];
} copy];
}
Note the __block storage type. Quoting this: "At function level are __block variables. These are mutable within the block (and the enclosing scope) and are preserved if any referencing block is copied to the heap."
This idiom may help you to remove the exc_bad_access (ARC code).
// get a weak reference to self
__weak id weakSelf = self;
block = ^()
{
// now the block is executing so we get a strong reference to self
// (this prevents self from disappearing until the block is done executing)
id strongSelf = weakSelf;
if (strongSelf != nil)
{
// do whatever work you intended for this block
}
};
I figured it out.
In MyClass.h:
typedef void (^DefaultFailureBlock)();
#property (copy) DefaultFailureBlock defaultFailureBlock;
in the init method:
__block MyClass *selfReq = self;
self.defaultFailureBlock = ^{
//use selfReq instead of self in here.
};
Interestingly, if you accidentally refer to self inside the block, you will have a retain cycle, and Analyze will not complain. I put an NSLog in dealloc to prove that it is actually being dealloced, and it is.
Oh and don't forget to [defaultFailureBlock release]; in dealloc too...