如何在Objective-C中执行回调函数?
我只想看一些完整的例子,我应该理解它.
为了完整性,由于StackOverflow RSS只是为我随机复活了这个问题,另一个(更新的)选项是使用块:
@interface MyClass: NSObject { void (^_completionHandler)(int someParameter); } - (void) doSomethingWithCompletionHandler:(void(^)(int))handler; @end @implementation MyClass - (void) doSomethingWithCompletionHandler:(void(^)(int))handler { // NOTE: copying is very important if you'll call the callback asynchronously, // even with garbage collection! _completionHandler = [handler copy]; // Do stuff, possibly asynchronously... int result = 5 + 3; // Call completion handler. _completionHandler(result); // Clean up. [_completionHandler release]; _completionHandler = nil; } @end ... MyClass *foo = [[MyClass alloc] init]; int x = 2; [foo doSomethingWithCompletionHandler:^(int result){ // Prints 10 NSLog(@"%i", x + result); }];
通常,目标C中的回调是通过代理完成的.这是自定义委托实现的示例;
头文件:
@interface MyClass : NSObject { id delegate; } - (void)setDelegate:(id)delegate; - (void)doSomething; @end @interface NSObject(MyDelegateMethods) - (void)myClassWillDoSomething:(MyClass *)myClass; - (void)myClassDidDoSomething:(MyClass *)myClass; @end
实施(.m)文件
@implementation MyClass - (void)setDelegate:(id)aDelegate { delegate = aDelegate; /// Not retained } - (void)doSomething { [delegate myClassWillDoSomething:self]; /* DO SOMETHING */ [delegate myClassDidDoSomething:self]; } @end
这说明了一般方法.您在NSObject上创建了一个声明回调方法名称的类别.NSObject实际上并没有实现这些方法.这种类型被称为非正式协议,您只是说许多对象可能实现这些方法.它们是一种转发声明选择器类型签名的方法.
接下来,您有一些对象是"MyClass"的委托,MyClass根据需要调用委托上的委托方法.如果你的委托回调是可选的,你通常会在调度站点用"if([delegate respondsToSelector:@selector(myClassWillDoSomething :)){"来保护它们.在我的示例中,委托需要实现这两种方法.
您也可以使用@protocol定义的正式协议,而不是非正式协议.如果这样做,您将更改委托设置器的类型,并将实例变量更改为" id
"而不是" id
".
此外,您会注意到代理人未被保留.这通常是因为"拥有""MyClass"实例的对象通常也是委托.如果MyClass保留了其委托,则会有一个保留周期.在类的dealloc方法中有一个好主意,它有一个MyClass实例,并且它是委托来清除该委托引用,因为它是一个弱后向指针.否则,如果某些东西使MyClass实例保持活动状态,那么你将有一个悬空指针.
这是一个保持委托概念的示例,只是进行原始回调.
@interface Foo : NSObject { } - (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector; @end @interface Bar : NSObject { } @end @implementation Foo - (void)doSomethingAndNotifyObject:(id)object withSelector:(SEL)selector { /* do lots of stuff */ [object performSelector:selector withObject:self]; } @end @implementation Bar - (void)aMethod { Foo *foo = [[[Foo alloc] init] autorelease]; [foo doSomethingAndNotifyObject:self withSelector:@selector(fooIsDone:)]; } - (void)fooIsDone:(id)sender { NSLog(@"Foo Is Done!"); } @end
通常,方法 - [Foo doSomethingAndNotifyObject:withSelector:]将是异步的,这将使回调比它在这里更有用.
为了使这个问题保持最新,iOS 5.0引入ARC意味着可以更简洁地使用Blocks实现这一点:
@interface Robot: NSObject + (void)sayHi:(void(^)(NSString *))callback; @end @implementation Robot + (void)sayHi:(void(^)(NSString *))callback { // Return a message to the callback callback(@"Hello to you too!"); } @end [Robot sayHi:^(NSString *reply){ NSLog(@"%@", reply); }];
如果你忘记了Objective-C的Block语法,总会有F****ng Block语法.