Block that can access self and be used throughout an instance - objective-c

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...

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!
}

Objective-C self->_ivar access with explicit vs implicit self->

General Problem
Until now, I always thought self->_ivar is equivalent to _ivar. Today I found out that this is not entirely true.
See, for example the following code snippet:
#interface TestClass : NSObject {
NSString *_testIVar;
}
#end
#implementation TestClass
- (instancetype)init
{
if ((self = [super init])) {
_testIVar = #"Testing Only";
}
return self;
}
- (void)test
{
{
NSInteger self = 42;
NSLog(#"without arrow: %#", _testIVar); /* OK */
NSLog(#"with arrow: %#", self->_testIVar); /* COMPILER ERROR! */
}
}
#end
Even though I hid the original self with some NSInteger also named self, the implicit ivar syntax _testIVar still finds the "original" self whereas self->_testIVar obviously does not. In the latter case the compiler correctly complains with
Member reference type 'NSInteger' (aka 'long') is not a pointer
In the first case however, it just works.
The Real-world Problem
This example might seem rather artificial but it's not at all. For example the ExtObjC project (used by ReactiveCocoa ) defines the very handy #weakify(var) and #strongify(var) which help against strongly capturing self (and other objects) in blocks by defining a really handy syntax (no need to write the odd and cumbersome to write __weak typeof(self) weakSelf = self; [...] ^{ __strong typeof(self) strongSelf = weakSelf; [...] } anymore). For example:
- (void)someMethod
{
#weakify(self);
dispatch_async(self.someQueue, ^{
#strongify(self);
NSLog(#"self # %p", self);
}
}
Without #weakify and #strongify, the block would capture a strong reference to self. With the #weakify and #strongify it doesn't. So the deallocation of self would not be postponed until the block has been run. The main advantage though is that you don't need to remember to use weakSelf or strongSelf instead of self because the "original" self is hidden.
That's very handy, the ExtObjC implements #weakify / #strongify by generating something similar like the following with macros:
- (void)someMethod
{
__weak typeof(self) _weakSelf = self;
dispatch_async(self.someQueue, ^{
__strong typeof(self) self = _weakSelf;
NSLog(#"self # %p", self);
}
}
Fair enough, that's even better because we can just continue to use self without actually capturing a strong reference to self. However, as soon as we use the implicit-ivars-of-self-syntax, a strong reference to the "original" self will still be captured!
- (void)someMethod
{
#weakify(self);
dispatch_async(self.someQueue, ^{
#strongify(self); /* compiler warning: Unused variable self here!!! */
NSLog(#"self->_testIVar: %#", _testIVar);
}
}
Misc
When using ivars in blocks, we're definitely capturing self. See for example this screenshot:
.
Another fun thing about the screenshot is that the warning messages are
Unused variable 'self'
and in the line below
Capturing 'self' strongly in this block is likely to lead to a retain cycle
That's why I think there are two versions of self :-)
Question
The actual question here is: What exactly does _testIVar mean? How does it find the "original" self pointer?
To clarify (also see my screenshot): As #MartinR pointed out (which is what I think as well), there is some special version of self which cannot be changed and is only used for implicit-self-ivar-access. Is that documented somewhere? Basically where is defined what the implicit self refers to? It seems to behave the same way that for example Java does (with this) but with the difference that this is a reserved keyword that you cannot override.
The question is also not how to "fix" it, just writing self->_testIVar will be what I want in the #weakify/#strongify example. It's more that I thought by using #weakify/#strongify you cannot make the mistake of implicitly strongly capturing self anymore but that simply does not seem to be the case.
All Objective-C methods are called with two hidden arguments (from the "Objective-C Runtime Programming Guide"):
The receiving object
The selector for the method
and a method can refer to the receiving object as self (and to its own selector as _cmd).
Now _ivar is equivalent to self->_ivar where self is this implicit first
function parameter.
As long as you don't define a new variable self in an inner scope, _ivar == self->_ivar holds true.
If you define a new variable self in an inner scope then you have
The locally defined self,
the "implicit self" which is the first function parameter,
and _ivar still refers to the "implicit self"! This explains the compiler warnings in your block, which seem to contradict each other:
"Unused variable 'self'" refers to the locally defined self,
"Capturing 'self' strong in this block ..." refers to the "implicit self" of the function.
The following code demonstrates also this:
#interface MyClass : NSObject
{
NSString *_ivar;
}
#end
#implementation MyClass
- (void)test
{
_ivar = #"foo"; // Set instance variable of receiver
{
MyClass *self = [MyClass new]; // Redefine self in inner scope
self->_ivar = #"bar"; // Set instance variable of redefined self
NSLog(#"%# - %#", self->_ivar, _ivar);
// Output: bar - foo
}
}
#end

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