How to perform Callbacks in Objective-C

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

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

106960 次浏览

通常,目标 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

That illustrates the general approach. You make a category on NSObject that declares the names of your callback methods. NSObject doesn't actually implement these methods. This type of category is called an informal protocol, you're just saying that many objects might implement these methods. They're a way to forward declare the type signature of the selector.

接下来,您有一些对象是“ MyClass”的委托,并且 MyClass 根据需要调用委托的委托方法。如果您的委托回调是可选的,那么您通常会使用类似于“ If ([ committee response dsToSelector:@selector (myClassWillDoSomething:)){”的内容在分派站点上保护它们。在我的示例中,需要委托来实现这两个方法。

您也可以使用@protocol 定义的正式协议来代替非正式协议。如果你这样做,你会改变委托设置实例变量的类型,并将其设置为“ id <MyClassDelegate>”而不仅仅是“ 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 doSomething AndNotifyObject: withSelector: ]将是异步的,这将使回调比这里更有用。

为了完整起见,由于 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);
}];

To keep this question up-to-date, iOS 5.0's introduction of ARC means this can be achieved using 积木 even more concisely:

@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 块语法

CallBack: 在目标 C 中有4种回调类型

  1. Selector type : You can see NSTimer,UIPangesture are the examples of Selector callback. Used for very limited execution of code.

  2. 委托类型 : 苹果框架中常用且最常用的类型。UITableView氏委托,NSNURLConnection氏委托。它们通常用于显示从服务器异步下载许多图像等。

  3. NSNotification : NotificationCenter 是 Objective C 的一个特性,它用于在事件发生时通知许多收件人。
  4. : 块在 Objective C 编程中更常用。它是一个很好的特性,用于执行代码块。你也可以参考下面的教程来理解: < a href = “ https://www.appcoda.com/Objective-c-block-lessons/”rel = “ noReferrer”> Block lessons

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