Reputation: 3541
I'm trying to write a generic function to start and end events into my Obj-C (iOS) application. I'm defining - (void)startEvent:(void (^)())completion
. In the body of this function I take an action that launches an animation. What I need is call to completion
when an specific time interval pass.
So, I make a copy of completion
and assign it to a global variable (in class scope).
This is how I do this:
void (^startEventCompletionClosure)();
- (void)startEvent:(void (^)())completion {
// side note: I have NO access to "complete" closure of - [UIView animateWithDuration:...]
...
[self performSelector:@selector(startEventCompleted) withObject:nil afterDelay:kDealy];
startEventCompletionClosure = [completion copy];
}
- (void)startEventCompleted {
startEventCompletionClosure();
[startEventCompletionClosure release];
}
But, I have a few questions:
copy
it? Is it not possible just to retain
it?[... copy]
and [... retain]
as it were?Upvotes: 0
Views: 2067
Reputation: 1269
UIView also has nice block based animation methods now...
animateWithDuration:animations: animateWithDuration:animations:completion: animateWithDuration:delay:options:animations:completion:
[UIView animateWithDuration:kAnimationDurationTime animations:^{
// animate some animatable properties
// do some other stuff
} completion:^(BOOL finished) {
// code that you want to run
// when the animation has finished
}];
I've found this a very useful way to animate things.
Upvotes: 0
Reputation: 16861
First, we call them "blocks", not "closures" in Objective-C. Secondly, -performSelector:withObject:afterDelay:
is something we used before we had blocks. These days, you should probably use dispatch_after()
. Finally, blocks are objects, and they conform to the NSObject
protocol.
Upvotes: 1
Reputation: 410932
Is this the better way to handle this?
Depending on your usage, you may want to store this as an instance variable (unless you really want the block to be shared between classes, and thus changed for all classes anytime startEvent:
is called).
Is a __block an NSObject? a C declaration?
It's a C storage qualifier.
Why do I have to copy it? Is it not possible just to retain it?
You can retain it, but it probably won't do what you want it to do. In C and Objective-C, blocks are created on the stack. When you copy it, it (and any variables it closed over) are copied to the heap. If you retain it, it and its variables are not copied to the heap.
If it's not an Obj-C Object, why I can call to
[... copy]
and[... retain]
as it were?
Magic. :) More seriously, in Objective-C, blocks are designed to act as Objective-C objects. (It's similar to the reason you can seamlessly cast between NSString
and CFStringRef
-- the objects are designed to make this possible.)
Upvotes: 2