I have the following object:
Someobject *Object = [[Someobject alloc] init];
void (^Block)() = ^()
{
Use(Object);
};
DoSomethingWith(Block);
The block is copied in DoSomethingWith and stored somewhere. it might either not be called, called once or called multiple times. I want to tie Object with the block so whenever the block or any of its copies is released, Object is released, and whenever the block or any of its copies is retained or copied, Object will be retained.
Is there a way to do so?
Change your first line to [[[Someobject alloc] init] autorelease] and you're done.
Blocks retain objects declared without and referenced within their body, and release them on release. So will the copy of the block made within DoSomethingWith. Assuming that copy eventually gets released there's no leak. It's pretty cool.
(Exception: if Object were declared __block Someobject *Object, along with the expected effect (removing the 'const' of the block's private reference, allowing the block to assign to Object), this autoretain behavior is also turned off. In that case retain/release is your responsibility again.)
Related
Im doing some research on blocks,
the code here
typedef NSString* (^MyBlock)(void);
#property(copy,nonatomic) MyBlock block1;
in viewdidload
self.block1 = ^{
self
NSLog(#"do block");
return #"a";
};
of course the self is retained, then I do a
self.block = nil;
by checking the retain count of self, I found it reduced by 1, no retain cycle.
I believe this is the correct situation, the block retains self, when release the block, self gets released. retaincount reduced.
I made a litte change, and things coms strange:
make block a local variable.
in viewdidload
MyBlock block1 = ^{
self
NSLog(#"do block");
return #"a";
};
[block copy]; // retain count of self gets added.
[block release]; // retain count of sell still the same
why? I tried Block_release(), its the same. and when putting a local variable like NSArray in the block, the retain count fellows the same rule as self.
there must be some thing different inside of #property, anyone researched this before?
pls help.
Additionally, I do this in ARC, a local variable block will made the retain cycle, and a instance variable didnt, due to the autorelease, it holds the self, and few seconds later, it released and self object get released normally.
is it because the instance variable and local variable are alloc on different parts in memory? stack ? heap?, are they both copied to heap when do a [block copy]?
EDIT :
not instance variable and local variable. using #property makes it different, any explanations?
The problem is that using retainCount to figure out things like this is futile. The retainCount will not reflect autorelease state and the compiler -- the ARC compiler, in particular -- may generate different code (in particular, the optimizer has a tendency to eliminate unnecessary retain/autorelease pairs).
Use the Allocations Instrument and turn on reference event tracking. Then you can look at each retain/release event on the object, the exact stack trace where it happened, and know exactly what is going on.
Under non-ARC, when you assign to an iVar, nothing happens. When you go through the setter, a retain setter will cause the object to be retaind. Under ARC, a block will be copied to the heap automatically in a number of cases, triggering a retain of the captured object when the block is copied.
http://www.whentouseretaincount.com/
I'm trying to write a category based on node.js EventEmitter, which can take a number of blocks, store them weakly in an array, and execute them later if the instance creating the block isn't deallocated (in which case they would be removed from the array). This is in order not to keep filling the array with old, unused blocks.
The problem is that the blocks seem to be copied by the class, and thusly never released, even though the instance creating the block is deallocated.
So the implementation looks something like this;
Usage
[object on:#"change" do:^(id slf, NSArray *args) {
NSLog(#"something changed");
}];
Implementation (WeakReference class found here, courtesy of noa)
- (void)on:(NSString *)eventType do:(Callback)callback
{
NSMutableArray *callbacks = self.emitterEvents[eventType];
__weak Callback wcb = callback;
// Wrap the callback in NSValue subclass in order to reference it weakly
WeakReference *cbr = [WeakReference weakReferenceWithObject:wcb];
callbacks[callbacks.count] = cbr;
}
- (void)emit:(NSString *)eventType withArgs:(NSArray *)objArgs
{
NSInteger idx = 0;
NSMutableIndexSet *indices = [NSMutableIndexSet indexSet];
callbacks = (NSMutableArray *)callbacks;
for (WeakReference *cbv in callbacks) {
__weak id cb = [cbv nonretainedObjectValue];
if (cb) {
Callback callback = (Callback)cb;
__weak id slf = self;
callback(slf, objArgs);
} else {
[indices addIndex:idx];
}
idx++;
}
[callbacks removeObjectsAtIndexes:indices];
}
I read something about blocks being copied when used past their scope, but frankly, reading about all these block semantics is kind of making my head spin right now.
Is this way of approaching the problem even possible?
In Objective-C, blocks are objects, but unlike other objects, they are created on the stack. If you want to use the block outside of the scope it was created you must copy it.
[object on:#"change" do:^(id slf, NSArray *args) {
NSLog(#"something changed");
}];
Here, you are passing a pointer to a block on the stack. Once your current stack frame is out of scope, your block is gone. You could either pass a copy to the block, making the caller the owner of the block, or you could copy the block in the receiver.
If you want the caller to own the block, then you have to keep a strong reference to the block in the caller (e.g. as a property). Once the caller gets deallocated, you lose your strong reference and your weak reference is set to nil.
copy a block which is already copied is same as retain it, so if the caller of the method copy the block first then pass it to the method, it should works as you expected. but this means you cannot simply use the method as you described in your usage section.
you have use it like this
typeofblock block = ^(id slf, NSArray *args) {
NSLog(#"something changed");
};
self.block = [block copy]
[object on:#"change" do:self.block];
to actual solve the problem, you have to figure out owns the block. the caller of on:do:, or the object been called?
sounds to me you want to remove the block when the caller is deallocated, which means the owner of the block is the caller. but your on:do: method does not aware the owner of the block, and cannot remove the block when the caller is deallocated.
one way is to pass the owner of the block into the method and remove the block when it deallocated. this can be done use associate object.
- (void)on:(NSString *)eventType do:(Callback)callback sender:(id)sender
{
// add the block to dict
// somehow listen to dealloc of the sender and remove the block when it is called
}
another way is to add new method to remove the block, and call the method in dealloc or other place to remove the block manually.
your approach is similar to KVO, which require the observer to unregister the observation, and I think is a good practice that you should follow.
Thanks for the answers, I realize I was a little bit off on how blocks are managed. I solved it with a different approach, inspired by Mike Ash's implementation of KVO with blocks & automatic dereferencing, and with xlc's advice on doing it in dealloc.
The approach is along the lines of this (in case you don't want to read the whole gist):
Caller object assigns listener to another object with on:event do:block with:caller
Emitter object creates a Listener instance, with a copy of the block, reference to emitter & the event-type
Emitter adds the copied block to an array inside a table (grouped by event-types), creates an associated object on the caller and attaches the listener
Emitter method-swizzles the caller, and adds a block to its dealloc, which removes itself from the emitter
The caller can then choose to handle the listener-instance, which is returned from the emit-method, if it wants to manually stop the listener before becoming deallocated itself
Source here
I don't know if it is safe for use, I've only tested it on a single thread in a dummy-application so far.
As you know, in ARC, __block variables of object pointer type used in a block are retained by the block. So take the following simplified example:
__block id foo = getObject();
void (^aBlock)() = ^ {
NSLog(#"%#", foo);
foo = getObject();
}
runBlockAsynchronouslyMultipleTimes(aBlock);
The object pointed to by foo is retained by the block, so that when the block is run (asynchronously), the object is still valid and can be printed. When we do the assignment within the block, ARC manages it like any other strong reference (the old value is released and the new value retained). (The assignment forces us to use __block in the first place.) And when the block is not needed anymore, ARC somehow releases its retained object pointed to by foo at that point (it is not leaked).
Okay, now suppose I want to do the same thing under MRC (why is not important; this is an question about the language). As you know, __block variables of object pointer type used in a block are NOT retained by the block in MRC. Which is fine; we'll manage it ourselves (this is MRC, after all). So the attempt looks like this:
__block id foo = [getObject() retain];
void (^aBlock)() = ^ {
NSLog(#"%#", foo);
[foo release];
foo = [getObject() retain];
}
runBlockAsynchronouslyMultipleTimes(aBlock);
// where to release foo?
Most of it is straight-forward -- the object is retained by us initially manually; inside the block, when we re-assign the pointer, we release and retain the new value as appropriate.
But then comes the problem: How do we release the object when the block is not needed anymore? Since we manually manage the memory, we should ideally manually release the object when the block is deallocated. But there doesn't seem to be an easy way to do so.
I could think of maybe one way: using associative references to tie the object to the block. But then to re-assign the associative reference inside the block, the block would need a reference to itself, so the block variable would also need to be __block and the block needs to be copied prior to setting the variable. Which is all very ugly. Or, we put the object inside a mutable container object that is then retained by the block; but that is ugly too.
The mutable container is about as clean as you can get. You could create a simple wrapper with a single object property to clean it up a little, and then you would get memory management from the property accessors.
An approach which would look cleaner, but is actually kind of messy underneath, would be to have an immutable wrapper which took a pointer, and just released that pointer when it was deallocated.
#interface ObjectReleaser : NSObject {
id *objectPointer;
}
- (id)setObjectPointer:(id *)pointer;
- (void)captureMe;
#end
#implementation ObjectReleaser
- (void)setObjectPointer:(id *)pointer {
if(!objectPointer && pointer) {
objectPointer = pointer;
[*objectPointer retain];
}
}
- (void)dealloc {
if(objectPointer) [*objectPointer release];
[super dealloc];
}
- (void)captureMe {} // Blocks can call this to capture the object
#end
The block would catch and retain this object, since it is not __block. You would modify your __block object as usual, with all of the proper retains and releases. Then, when the block is deallocated, it will release the releaser, which will then be deallocated and release whatever your pointer currently points to.
__block id foo = getObject();
ObjectReleaser *releaser = [[ObjectReleaser alloc] init];
void (^aBlock)() = ^ {
[releaser captureMe];
NSLog(#"%#", foo);
[foo release];
foo = [getObject() retain];
}
aBlock = [aBlock copy];
[releaser setObjectPointer:&foo];
Note that you don't need to retain foo just for the block, because the releaser does that for you. You do have to set the releaser's pointer after copying the block, since the copy will change foo's pointer. This is also why it is safe to save the pointer of a stack variable after your function returns: the variable is not actually on the stack.
From the Transitioning to ARC Release Notes
Use Lifetime Qualifiers to Avoid Strong Reference Cycles
You can use lifetime qualifiers to avoid strong reference cycles. For
example, typically if you have a graph of objects arranged in a
parent-child hierarchy and parents need to refer to their children and
vice versa, then you make the parent-to-child relationship strong and
the child-to-parent relationship weak. Other situations may be more
subtle, particularly when they involve block objects.
In manual reference counting mode, __block id x; has the effect of not
retaining x. In ARC mode, __block id x; defaults to retaining x (just
like all other values). To get the manual reference counting mode
behavior under ARC, you could use __unsafe_unretained __block id x;.
As the name __unsafe_unretained implies, however, having a
non-retained variable is dangerous (because it can dangle) and is
therefore discouraged. Two better options are to either use __weak (if
you don’t need to support iOS 4 or OS X v10.6), or set the __block
value to nil to break the retain cycle.
Okay, so what's different about __block variable?
Why set to nil here? Is __block variable retained twice? Who hold all the reference? The block? The heap? The stack? The thread? The what?
The following code fragment illustrates this issue using a pattern that is sometimes used in manual reference counting.
MyViewController *myController = [[MyViewController alloc] init…];
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
};
[self presentViewController:myController animated:YES completion:^{
[myController release];
}];
As described, instead, you can use a __block qualifier and set the myController variable to nil in the completion handler:
MyViewController * __block myController = [[MyViewController alloc] init…]; //Why use __block. my controller is not changed at all
// ...
myController.completionHandler = ^(NSInteger result) {
[myController dismissViewControllerAnimated:YES completion:nil];
myController = nil; //Why set to nil here? Is __block variable retained twice? Who hold all the reference? The block? The heap? The stack? The thread? The what?
};
Also why myController is not set to nil by compiler. Why do we have to do so? It seems that the compiler sort of know when myController will no longer be used again namely when the block expire.
When you have code of this form:
object.block = ^{
// reference object from inside the block
[object someMethodOrProperty];
};
object will retain or copy the block you give to it. But the block itself will also retain object because it is strongly referenced from within the block. This is a retain cycle. Even after the block has finished executing, the reference cycle still exists and neither the object nor the block can be deallocated. Remember that a block can be called multiple times, so it cannot just forget all the variables it references after it has finished executing once.
To break this cycle, you can define object to be a __block variable, which allows you to change its value from inside the block, e.g. changing it to nil to break the cycle:
__block id object = ...;
object.block = ^{
// reference object from inside the block
[object someMethodOrProperty];
object = nil;
// At this point, the block no longer retains object, so the cycle is broken
};
When we assign object to nil at the end of the block, the block will no longer retain object and the retain cycle is broken. This allows both objects to be deallocated.
One concrete example of this is with with NSOperation's completionBlock property. If you use the completionBlock to access an operation's result, you need to break the retain cycle that is created:
__block NSOperation *op = [self operationForProcessingSomeData];
op.completionBlock = ^{
// since we strongly reference op here, a retain cycle is created
[self operationFinishedWithData:op.processedData];
// break the retain cycle!
op = nil;
}
As the documentation describes, there are a number of other techniques you can also use to break these retain cycles. For example, you will need to use a different technique in non-ARC code than you would in ARC code.
I prefer this solution
typeof(self) __weak weakSelf = self;
self.rotationBlock = ^{
typeof (weakSelf) __strong self = weakSelf;
[self yourCodeThatReferenceSelf];
};
What happens is that the block will capture self as a weak reference and there will be no retain cycle. self inside the block is then redefined as __strong self = weakSelf before your code runs. This prevents self from being released while your block runs.
I'm writing an app using ARC, and I'm wondering if the following will cause a problem. Specifically, I'm creating an object 'A', then using GCD I add a code block to the main thread's queue and in the code block I perform some operations on the weak reference to the object. But by the time the code block is executed, my object has already been nullified. Since the code block only has a weak reference to the object, will this cause a problem? Or does the compiler somehow know to keep a reference to the object since my code block needs it when it runs?
Foo *A = [[Foo alloc] init];
__weak Foo *weakA = A;
dispatch_async(dispatch_get_main_queue(), ^{
//...do something here with weakA
});
A = nil;
Thanks!
Why are you using __weak here? If you want the block to "keep a reference to the object since [your] code block needs it when it runs", then you don't need to do anything:
Foo *a = [[Foo alloc] init];
dispatch_async(dispatch_get_main_queue(), ^{
[a something];
});
In the above snippet, the block retains a, so it will exist when the block executes.
As this question explains, the only time you need to use __weak with blocks is to break retain cycles that occur when the block itself is going to be retained. For example:
__weak Foo *someObject = [bar getAFoo];
[someObject doSomeTaskWithCompletionHandler:^{
[someObject doSomethingElse];
}];
Here, if someObject were not declared to be __weak, then you would have a retain cycle since someObject would presumably retain the block (since it would need to keep the block until it was done doing some task), and the block retains someObject. Using __weak here tells the block not to retain someObject, so the error doesn't occur. And you don't need to worry about someObject being nil when the block executes, because someObject owns the block. (If someObject were to be deallocated, then the block wouldn't be executed).
This is an interesting question with some subtleties.
You've explicitly told the compiler to disregard the reference from within the block by tagging it as __weak, so this code is not sufficient to keep the object alive until the block has been executed. It sounds like you're clear on that already, though.
Normally, a weak reference such as weakA would be nullified when the object it refers to is deallocated. However, weakA is a stack variable, so when it's referred to in a block, the block receives a const-ified version of it that memorializes its value at the time of the block's creation. Presumably, this const copy of weakA can't be nullified. See this section of the Apple docs for more on this.
If you change the declaration of weakA to
__block __weak Foo *weakA = A;
then weakA is promoted off the stack and is writable both from its original context and from the block. It still won't keep the referred-to object alive on its own, but at the point of the block's execution you can check to see if its value is nil.
More details on __block can be found here - skip down to the section "ARC Introduces New Lifetime Qualifiers".