如何在Objective-C中使用自定义代理

52

我需要了解Objective-C中委托方法的用法。有人能指向正确的资料来源吗?


1
嗨Syam,只是想澄清一下,您是来自.NET并询问如何在Objective-C中实现委托(面向对象的函数调用)?还是在询问如何实现Objective-C助手类(也称为委托)? - Adam Alexander
4个回答

129

你需要为你的类声明一个委托协议。例如,对于类Foo,一个委托协议和接口的示例可能如下:

@class Foo;
@protocol FooDelegate <NSObject>
@optional
- (BOOL)foo:(Foo *)foo willDoSomethingAnimated:(BOOL)flag;
- (void)foo:(Foo *)foo didDoSomethingAnimated:(BOOL)flag;
@end

@interface Foo : NSObject {
     NSString *bar;
     id <FooDelegate> delegate;
}

@property (nonatomic, retain) NSString *bar;
@property (nonatomic, assign) id <FooDelegate> delegate;

- (void)someAction;

@end

不要忘记在@implementation中合成您的属性。

这段代码声明了一个名为FooDelegate的协议;符合该协议的类将被声明为@interface SomeClass : SuperClass <FooDelegate> {}。因为此类符合FooDelegate协议,所以它现在可以实现FooDelegate下的方法(要求实现这些方法,请使用@required而不是@optional)。最后一步是在符合FooDelegate的类中实例化一个Foo对象,并为此Foo对象设置其代理属性:

Foo *obj = [[Foo alloc] init];
[obj setDelegate:self];

现在,你的类已经准备好接收来自已正确设置其代理的 Foo 对象的消息。


使用 id<FooDelegate> delegate 和 NSObject<FooDelegate> *delegate 有什么区别? - Filipe Pina
区别在于后者期望delegateNSObject的实例或其子类。前者只期望某种Objective-C对象(它可以是代理,或者更糟糕的是其他根对象)。 - Jonathan Sterling
谢谢!我只是认为@protocol FooDelegate <NSObject>会暗示委托是NSObject的子类。 - Filipe Pina
4
啊,是的,有点令人困惑。事实上,@protocol Blah <NSObject> 中括号里的部分是在表明 协议 <Blah> 继承自 协议 <NSObject>。需要明确的一个关键点是,除了协议 <NSObject> 之外,还有一个类 NSObject - Jonathan Sterling
那很有道理,谢谢Jonathan!虽然我注意到如果我使用id而不是NSObject(作为委托类型),我就不能使用performSelectorOnMainThread,这对于委托非常有用。 - Filipe Pina

7

代理在手动控制应用程序中的视图控制器数组转移方面非常有用。使用代理,您可以很好地管理控制流。

这里是自己的代理的一个小例子...

  1. 创建协议类....(仅.h文件)

SampleDelegate.h

#import
@protocol SampleDelegate
@optional

#pragma Home Delegate

-(NSString *)getViewName;

@end
  1. 在想要成为另一个类的委托的类中导入上述协议类。在我的例子中,我使用AppDelegate来使HomeViewController的对象成为委托。

同时,在Delegate Reference < >中添加上述DelegateName。

ownDelegateAppDelegate.h

#import "SampleDelegate.h"

@interface ownDelegateAppDelegate : NSObject <UIApplicationDelegate, SampleDelegate>
{


}

ownDelegateAppDelegate.m

//setDelegate of the HomeViewController's object as
[homeViewControllerObject setDelegate:self];

//add this delegate method definition
-(NSString *)getViewName
{
    return @"Delegate Called";
}

HomeViewController.h

#import
#import "SampleDelegate.h"

@interface HomeViewController : UIViewController 
{

    id<SampleDelegate>delegate;
}

@property(readwrite , assign) id<SampleDelegate>delegate;

@end

HomeViewController.h

- (void)viewDidAppear:(BOOL)animated 
{

    [super viewDidAppear:animated];
    UILabel *lblTitle = [[UILabel alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    lblTitle.text = [delegate getViewName];
    lblTitle.textAlignment = UITextAlignmentCenter;
    [self.view addSubview:lblTitle];

}

2
如果问题中的对象已经被分配到你编写的类中,比如一个控制器(controller),那么为该对象的类定义的delegate方法必须由被分配的类实现。这样可以有效地控制对象的行为,而无需对对象的类进行子类化以覆盖可能需要大量重复行为的行为。这是Cocoa Touch设计中较为简洁的部分之一。
这是你在学习Cocoa Touch的前几个介绍和教程中应该掌握的内容,例如Cocoa is my Girlfriend的教程。事实上,他们将delegate的解释作为了一个重要的标题。

2

首先,你可以查看苹果公司关于委托方法的说明。文档提供了一些关于委托是什么以及如何使用定义和支持委托的AppKit类以及如何将委托支持编码到自己的对象中的信息。

请参见与对象通信

(如果您有兴趣编写自己的委托支持,请跳到“为自定义类实现委托”部分。)

从委托方法中最重要的方面是,它们使您能够自定义和影响对象的行为,而无需对其进行子类化。

希望这能帮助您入门。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接