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:
- Is this the better way to handle this?
- Is a __block an NSObject? a C declaration?
- Why do I have to
copyit? Is it not possible just toretainit? - If it’s not an Obj-C Object, why I can call to
[... copy]and[... retain]as it were?
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).It’s a C storage qualifier.
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.
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
NSStringandCFStringRef— the objects are designed to make this possible.)