如何在Objective-C中执行回调

Rea*_*ion 118 cocoa objective-c callback

如何在Objective-C中执行回调函数?

我只想看一些完整的例子,我应该理解它.

Jen*_*ton 136

为了完整性,由于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);
}];
Run Code Online (Sandbox Code Playgroud)

  • @Ahruman:"void"(^ _completionHandler)(int someParameter)中的"^"字符是什么;" 意思?你能解释一下这行吗? (2认同)
  • 您能否解释为什么需要复制回调处理程序? (2认同)

Jon*_*ess 94

通常,目标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
Run Code Online (Sandbox Code Playgroud)

实施(.m)文件

@implementation MyClass
- (void)setDelegate:(id)aDelegate {
    delegate = aDelegate; /// Not retained
}

- (void)doSomething {
    [delegate myClassWillDoSomething:self];
    /* DO SOMETHING */
    [delegate myClassDidDoSomething:self];
}
@end
Run Code Online (Sandbox Code Playgroud)

这说明了一般方法.您在NSObject上创建了一个声明回调方法名称的类别.NSObject实际上并没有实现这些方法.这种类型被称为非正式协议,您只是说许多对象可能实现这些方法.它们是一种转发声明选择器类型签名的方法.

接下来,您有一些对象是"MyClass"的委托,MyClass根据需要调用委托上的委托方法.如果你的委托回调是可选的,你通常会在调度站点用"if([delegate respondsToSelector:@selector(myClassWillDoSomething :)){"来保护它们.在我的示例中,委托需要实现这两种方法.

您也可以使用@protocol定义的正式协议,而不是非正式协议.如果这样做,您将更改委托设置器的类型,并将实例变量更改为" id <MyClassDelegate>"而不是" id".

此外,您会注意到代理人未被保留.这通常是因为"拥有""MyClass"实例的对象通常也是委托.如果MyClass保留了其委托,则会有一个保留周期.在类的dealloc方法中有一个好主意,它有一个MyClass实例,并且它是委托来清除该委托引用,因为它是一个弱后向指针.否则,如果某些东西使MyClass实例保持活动状态,那么你将有一个悬空指针.


Jon*_*ess 49

这是一个保持委托概念的示例,只是进行原始回调.

@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
Run Code Online (Sandbox Code Playgroud)

通常,方法 - [Foo doSomethingAndNotifyObject:withSelector:]将是异步的,这将使回调比它在这里更有用.


Rya*_*die 9

为了使这个问题保持最新,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);
}];
Run Code Online (Sandbox Code Playgroud)

如果你忘记了Objective-C的Block语法,总会有F****ng Block语法.


Ani*_*pta 5

回调:Objective C 中有 4 种类型的回调

  1. Selector type : 你可以看到 NSTimer,UIPangesture 是 Selector 回调的例子。用于非常有限的代码执行。

  2. 委托类型:常见且在 Apple 框架中最常用。UITableViewDelegate,NSNURLConnectionDelegate。它们通常用于显示从服务器异步下载许多图像等。

  3. NSNotifications : NotificationCenter 是 Objective C 的功能之一,用于在事件发生时通知许多接收者。
  4. :块在 Objective C 编程中更常用。这是一个很棒的功能,用于执行代码块。你也可以参考教程来理解:积木教程

如果有其他答案,请告诉我。我会很感激的。