对Objective-C中的代表有点困惑

时间:2009-08-28 22:34:30

标签: objective-c delegates

我对Objective-C有很多了解,而且我正在开发一本iPhone SDK书(来自Obj-C书,它刚刚完成了控制台程序)。它试图解释代表虽然它很匆忙,并没有真正理解它试图传达的内容。我对它们是什么以及何时使用它们感到有点困惑。

基本上它说它们是负责代表另一个对象做某些事情的类。

有人想详细说明吗?

谢谢!

6 个答案:

答案 0 :(得分:20)

将代理视为反转依赖的方向。在大多数框架中,客户端会将所需的依赖项注入到实例中,通常在构造函数中或由setter注入。

可可做了相反的事;实例代替在需要时请求数据。

委托方法有四种主要类型:

  • 有条件地在之前 - 信号即将发生,但代表可能会中止。名称始终包含单词“。” 示例:searchBar Should EndEditing:
  • 无条件地之前 - 信号即将发生。名称始终包含单词will 示例:application Will Terminate:
  • 无条件地之后 - 发生了一些信号。名称总是包含单词did 示例:application Did FinishLaunching:
  • 定制程序 - 请求有关如何运作的信息。名称包括所需的信息 示例tableView: viewForHeaderInSection :

所有委托方法始终将其发件人作为参数之一。任何委托方法都可能有一个返回值,可以改变发送者的行为方式。

答案 1 :(得分:7)

假设您要向用户显示提醒,并且您希望在用户触摸其中一个按钮时运行方法。问题是,当有人触摸按钮时,你怎么知道调用什么方法,哪个对象?

为了使一个类成为一个委托,你必须声明它。在上面的示例中,假设您有一个ApplicationController对象来控制应用程序的流程。在声明中,我们会说

@interface ApplicationController : NSObject <UIAlertViewDelegate>

这告诉编译器ApplicationController将在UIAlertViewDelegate协议中实现一些方法。我们在文档中查看该协议,并查看方法列表。由于我们想在按下按钮时执行某些操作,我们会看到:

alertView:clickedButtonAtIndex: - 当用户单击警报视图上的按钮时发送给代理。这个方法是可选的。

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex

因此,如果我们在ApplicationController中实现一个名为alertView:clickedButtonAtIndex的方法,创建一个ApplicationController对象,然后将该对象设置为我们显示的警报的委托,则设置所有内容。只要有人按下警报上的按钮,就会调用alertView:clickedButtonAtIndex方法,传递alertView和按下按钮的索引。

这使您可以使用该信息执行任何操作。一个简单的案例陈述:

if( buttonIndex == 0 ) {
    _myString = @"Pressed the button";
} else {
    _myString = @"Pressed the other button";
}

Objective-C参考文档非常非常好,并且所有委托协议都非常自我解释。

答案 2 :(得分:6)

理解代表的好方法是通过示例。一个例子是UITableView(或NSTableView,取决于我们是在谈论iPhone还是Mac OS)。无论哪种方式,表视图都有delegatedataSource(两者都充当接收者的辅助对象)。

而不是UITableView处理事件,例如,当用户点击其中一行时,它会告诉其delegate“嘿!我已经在这一行上点击了这个部分,做你想做的!“。通常,delegate是某种控制器,它实现了正确的方法。所以表视图(在检查delegate实际上是否有方法的定义之后)发送如下消息:

[delegate tableView:self didSelectRowAtIndexPath:indexPath];

由于您的Controller是表的委托,并且它实现了该方法,因此它决定了该做什么。当方法完成时(在这种情况下它应该只返回void),然后在表视图上继续执行。

代表是一个概念。它不是Objective-C的语言功能。 UITableView的delegate成员就像任何其他对象一样。虽然代理人通常保留,但却会分配(以避免retain个周期)。

当你掌握它们时,它们非常方便。我建议用像TableViews这样的例子来练习(NSTableView,就像我之前说过的那样,以类似的方式工作,只是使用不同的方法)。

答案 3 :(得分:2)

委托(意思是代表)是一个类(对象),它也想表示(继承)另一个不相关的类。委托对象能够通过“符合”(具有一些实现)不相关类所需的协议方法从其他不相关的类继承,该协议方法向外部类指示该对象现在能够适当地排列其最基本的信息。

如果希望相关类共享方法,请使用继承。如果希望无关的类共享方法,可以使用委托。委托方法允许来自一个类的对象从其他不相关的类继承方法。 “委托对象”或“代表对象”是从外部类继承的对象;它被指定为该远程类的代表,委托,因此当您将对象指定为类的委托时,您也授予它表示该类的权限,即使它通常不从该类继承。 (如果它继承自类,那么你不需要将它设置为该类的委托;它已经可以访问类的方法。但是你希望这个不相关的对象从类中继承一些方法,表示class,并将一些信息返回给它的sender类,所以你使它成为该类的委托代表,即使它继承自不同的类集。)这实质上允许一个不相关的类继承自另一个不相关的类,但是其基本遗传系列的最小并发症。

当您希望对象从单独的类执行代码时,可以使用委托系统。例如,as described here,当您在文本字段中按Enter键时,文本字段实际上不知道如何处理该信息。它的作用是查看其委托对象的类(例如文档的窗口控制器或文档),并使用该类的相关方法,该方法符合在其文本字段委托协议中找到的文本字段的相应方法,类似于textFieldShouldReturn。因此,在这种情况下,您将窗口控制器或文档设置为文本字段的委托,因为文本字段需要该类来表示它所给出的信息。

A类需要B类的方法,但A类不从B类继承。首先,告诉编译器A类符合B类协议:

@interface ClassA : NSObject <ClassBDelegateProtocol>

在Apple文档中,每个类引用都显示在顶部,“继承自”和“符合”。例如,NSDocumentController继承自NSObject并符合NSUserInterfaceValidationsNSCodingNSObject(NSObject)。与NSCoding的一致性来自NSDocumentController.h中的接口声明

@interface NSDocumentController : NSObject <NSCoding>

和NSDocumentController.h中方法声明的NSUserInterfaceValidations

-(BOOL)validateUserInterfaceItem:(id <NSValidatedUserInterfaceItem>)item;

以及#import

#import <AppKit/NSUserInterfaceValidation.h>

因此NSDocumentController继承自NSObject,它还需要 NSCodingNSUserInterfaceValidation的帮助。通过符合他们的协议方法将自己定义为符合这些方法,以及导入任何必要的头文件以使用这些方法,它可以从这些外来类中获得帮助

答案 4 :(得分:0)

在这里查看关于委托设计模式的教程:http://www.jonmsterling.com/blog/?p=74。我希望有所帮助。

答案 5 :(得分:0)

你并不孤单,我自己也在学习。如果我试着用文字而不是代码来解释它,我认为它是最好的。有一个协议可以保存您想要完成的某种方法或操作。委托从协议中获取方法,因此能够使用它来促进动作或方法。我发现这篇文章非常有帮助 http://rypress.com/tutorials/objective-c/protocols。希望这可以帮助。