如何在 Objective-C 中执行回调

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1015608/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:44:52  来源:igfitidea点击:

How to perform Callbacks in Objective-C

objective-ccocoacallback

提问by ReachConnection

How to perform call back functions in Objective-C?

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

I would just like to see some completed examples and I should understand it.

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

采纳答案by Jon Hess

Normally, callbacks in objective C are done with delegates. Here's an example of a custom delegate implementation;

通常,目标 C 中的回调是通过委托完成的。这是自定义委托实现的示例;



Header File:

头文件:

@interface MyClass : NSObject {
    id delegate;
}
- (void)setDelegate:(id)delegate;
- (void)doSomething;
@end

@interface NSObject(MyDelegateMethods)
- (void)myClassWillDoSomething:(MyClass *)myClass;
- (void)myClassDidDoSomething:(MyClass *)myClass;
@end


Implementation (.m) File

实施 (.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.

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

Next you have some object be the delegate of "MyClass" and MyClass calls the delegate methods on the delegate as appropriate. If your delegate callbacks are optional, you'll typically guard them at the dispatch site with something like "if ([delegate respondsToSelector:@selector(myClassWillDoSomething:)) {". In my example, the delegate is required to implement both methods.

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

Instead of an informal protocol, you can also use a formal protocol defined with @protocol. If you do that, you'd change the type of the delegate setter, and instance variable to be "id <MyClassDelegate>" instead of just "id".

除了非正式协议,您还可以使用由@protocol 定义的正式协议。如果你这样做,你会改变委托 setter 的类型,并将实例变量更改为“ id <MyClassDelegate>”,而不仅仅是“ id”。

Also, you'll notice the delegate is not retained. This is typically done because the object that "owns" instances of "MyClass" is typically also the delegate. If MyClass retained its delegate, then there would be a retain cycle. It's a good idea in the dealloc method of a class that that has a MyClass instance and is its delegate to clear that delegate reference since it's a weak back pointer. Otherwise if something is keeping the MyClass instance alive, you'll have a dangling pointer.

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

回答by Jens Ayton

For completeness, since StackOverflow RSS just randomly resurrected the question for me, the other (newer) option is to use blocks:

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

回答by Jon Hess

Here's an example that keeps the concepts of delegates out, and just does a raw call back.

这是一个将委托概念排除在外的示例,仅进行原始回调。

@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

Typically the method -[Foo doSomethingAndNotifyObject:withSelector:] would be asynchronous which would make the callback more useful than it is here.

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

回答by Ryan Brodie

To keep this question up-to-date, iOS 5.0's introduction of ARCmeans this can be achieved using Blockseven more concisely:

为了让这个问题保持最新状态,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);
}];

There's always F****ng Block Syntaxif you ever forget Objective-C's Block syntax.

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

回答by Anil Gupta

CallBack: There are 4 types of callback in Objective C

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

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

  2. Delegate Type: Common and most used in Apple framework. UITableViewDelegate, NSNURLConnectionDelegate. They are usually used to show Downloading many images from server asynchronously etc.

  3. NSNotifications: NotificationCenter is one of features of Objective C which used to notify many receiptants at time when event occur.
  4. Blocks: Blocks are more commonly used in Objective C programming. It is great feature and used for executing chunk of code. You can also refer tutorial to understand : Blocks tutorial
  1. Selector type: 你可以看到 NSTimer,UIPangesture 是 Selector 回调的例子。用于非常有限的代码执行。

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

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

Please let me if any other answer for it. I will appreciate it.

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