对Objective-c观点,代表和出口的混淆

时间:2013-01-22 16:32:11

标签: objective-c cocoa design-patterns cocoa-design-patterns

我正在尝试自学Objective-c,但是从Python / Java背景来看,它证明是非常困难的。我试图发布一些我很困惑的点,但它被标记为过于模糊,所以我会把它分成几个部分。

首先,我发现的每个代表和插座的例子都使用cocoa视图代码来实现这个想法。不幸的是,我还没有理解足够的代码来掌握这个例子的观点。那么,任何人都可以提供代表的更基本的例子吗?我的理解是它是一种子类化的方式;这比传统的子类更好吗?为什么每个cocoa项目都自动包含appDelegate.m?代表可以用于其他目的,而不仅仅是GUI的东西吗?

好的,我想我明白了。因此委托是一个符合其他类协议的类。协议只是一个方法和变量的列表,必须(或可以,如果设置为可选)在委托类中实现。要创建委托,您必须使用@interface关键字,然后使用委托的名称,然后(在<>标志中)使用协议名称?因此,如果类c1想要将自己设置为类c的委托,则类c必须首先指定协议,对吧?然后,您将能够在c1中的c协议中实现所有内容: @interface c1; 我觉得我在那里缺少一些东西,但希望我有正确的概念。 :)这也解释了神秘的少于和大于标志;他们声明了委托实现的接口。

Outlets同样总是与视图代码绑定。它们似乎是某种对象间消息传递系统。是对的吗?同样,未与复杂GUI语句混合的基本插座的示例将是很好的。 所以不需要出口?我知道除了与Interface Builder一起使用外,不需要IBOutlet和IBAction,但我认为出口比这更通用?文档似乎表明它们甚至不是专门用于接口,但可以用于任何事情。

提前感谢您的帮助。

5 个答案:

答案 0 :(得分:2)

更新:代表 不符合协议。协议只是让要求某些类更容易拥有方法。它允许您确定一个已设置为委托的对象实现某个方法,以便您可以安全地调用它,并允许编译器验证该方法确实已实现(如果您将委托实例变量声明为{{1}如果您尝试将id<SomeProtocol> delegate设置为不符合delegate的类的对象,编译器将发出警告或错误。

协议有助于确保安全,但它们并非绝对必要。一个类可以有一个委托(或多个!),它们根本不必符合任何协议。

至于outlet,不,它们是专门用于Interface Builder的。 SomeProtocolIBOutlet关键字对代码没有影响(它们甚至在编译时被删除) - 它们只是Interface Builder要查找的标记,因此它知道哪些属性和方法应该是可在界面中访问。术语“出口”是对标记为IBAction的东西的直接引用,实际上并未用于我能说出的任何其他上下文中。

再次,如果您不立即理解这一点,那也没关系。想一想,在某些时候,它只是'点击'。我被代理人赶上很长的时间,就像这样,在一天之前,我意识到代表们真的没什么特别的。它们是其他对象引用的常规对象 - 只是这个设计模式有一个特殊的名称(委托),而这些对象只是被称为委托。它们可以很容易地称为IBOutletgyros,净效果也是一样的。 :P
您不需要将对象falafels命名为委托;这只是一个惯例。


关于代表:首先要理解的是,这让我有一段时间,直到我有了适当的“啊哈!”那一刻,“代表”没有什么特别之处。 “委托”一词只是另一类所依赖的一类对象的标题,通常用于内容或决策。当开发人员不希望(或不能)通过名称将其中一个类绑定到另一个类时,它将使用委托 - 这是一种面向对象的解耦方式,使类更通用。

现在,类通常会要求委托者拥有他们所依赖的特定方法,并且有一种方法可以确保使用协议(通常称为Java中的接口)。协议定义了一系列方法;如果类声明它们在接口中声明(例如delegate)并且它们实现了它们所需的所有方法,那么它们“符合”协议。协议也可以有可选的方法。

此模型通常与视图控制器,视图和GUI一起使用,因为许多AppKit和UIKit类被编写为尽可能通用。例如,@interface IFObject : NSObject <SomeProtocol> { ... }实现了它可能实现的最基本的行为,而不需要任何特定于实现的信息;对于其余的,它依赖于其他符合NSTableViewNSTableViewDelegate协议的对象。 任何对象都可以符合协议,只要它们实现正确的方法(在这种情况下,控制器类通常会实现两种协议的方法,但不一定如此) 。事实上,更好地理解这个主题的一个简单方法是查看NSTableViewDataSource - 它有一个NSTableView属性和一个delegate属性,但实际上,它们没有什么不同。 dataSource可以被称为delegate,这个概念仍然有效。关键是不要将代表视为黑匣子 - 他们没有什么特别之处。

代表也可用于非GUI目的;正如您所提到的,一个具体的例子是应用程序委托。 monkeyButt发送代理通知,让它知道应用程序何时启动(以及其他内容),以便它可以设置商店。同样,任何对象可以是任何其他对象的委托,用于任何目的。这只是一个惯例。


简要说明网点:正如其他人所提到的,网点只是XIB中定义的接口与您的代码之间的连接。它们是让Xcode将接口链接到适当元素的一种方式,这样当你的应用程序加载接口文件时,它就可以加载正确的代码片段或执行它们。

它们通常是设置界面的一种更简单的方法 - 它们并非严格必要(您可以通过编程方式创建界面,而不使用XIB文件),但如果您决定采用XIB路线,那么它们就是'了解如何将界面与代码相关联。

答案 1 :(得分:1)

委托是一个对象,它由一个对象委托一些任务,它声明自己是委托。假设一个对象做了一些任务,然后需要通知对象“拥有”它,可以这么说。为了允许对象在任何条件下工作,不能让它知道它应该联系什么类型的对象,所以我们设置它的委托并遵守它的协议。设置对象的委托就像是说“这是我希望你使用的对象与你的协议中声明的消息联系。我保证对象实际上实现了协议中的方法。”例如,您可能会看到这一点。

@protocol SpriteDelegateProtocol
    @required
    - (void) projectionMatrix;
    @optional
    - (void) animation:(int)animationIndex willCompleteFrameNumber:(int)frame forSprite:(id)sender;
@end

@interface Sprite
@property (nonatomic, assign) id<SpriteDelegateProtocol> delegate;
@end

我们的sprite对象的接口声明它有一个名为delegate的属性,类型为id。它可以是任何对象,但必须遵守三角括号中的协议。如果它说它遵守协议,它来实现@required下声明的方法,而可以实现@optional下列出的方法。由我们决定我们的委托是否实际使用respondsToSelector:之类的东西来实现可选方法。如果我们有很多方法可以存储返回值,我们甚至可以存储返回值。

应用程序委托的特殊之处在于它是我们的UIApplication对象的委托。它接收有关应用程序状态的消息,例如applicationDidEnterBackground:。您可以查看我们的应用程序委托here所遵循的协议中的哪些方法。

代理可以与任何对象一起使用。任何对象都可以说它有一个要设置的委托属性,并且它必须具有如上所示的以下方法。该协议本质上是一个可移植的接口,可用于告诉另一个对象我们需要它实现什么,以便我们可以调用所述方法将一部分功能委托给它。我们可以在任务完成时通知我们的代表,要求它给我们提供信息(通常称为数据源而不是委托,以便他们可以根据需要设置不同的对象)或询问我们是否应该执行某项任务所有

出口是一种将在NIB或故事板中实例化的视图连接到其控制器中的属性的方法。因此,如果您将UIViewController放入主故事板并将其类更改为MyGreatControllerSubclass然后继续在该控制器的视图中放置一个按钮,您可能希望将该按钮挂钩到控制器界面中的“outlet”(属性),以便您可以稍后从控制器访问该按钮。

答案 2 :(得分:0)

没有代表不是子类化的方式。我也来自Java,现在已经做了近5年的O-C。

代表通常符合协议,它们等同于接口。这样做的好处在于它为您实现委托所涵盖的内容提供了很大的灵活性。因此,例如,您将看到可以通过扩展UITableViewController或实现委托来实现表视图。这样,如果您有一个组合视图,用户从一个表中选择项目并将它们放入另一个表中,您可以执行单个控制器并让它为两个视图执行委派。

考虑委托的最佳方式是面向消息/事件的回调示例。你有没有听过这样一个说法:什么使一个框架与普通编程不同的是,通过一个框架,它告诉你它想要你做什么来确保你寻求的结果?这就是代表团的意思。昨晚我正在做一个收藏视图,无法进入编辑菜单。只提供三种方法的委托,对调用菜单的方式,Long Press手势处理程序的位置等都不了解。

请注意,委托是在O-C世界中不需要依赖注入的粘合剂。我更喜欢他们。

答案 3 :(得分:0)

代表是常见的设计模式(http://en.wikipedia.org/wiki/Delegation_pattern),它们不是客观特定的。

Outlets可能会绑定Controller和View(GUI)。您可能知道MVC范例(模型 - 视图 - 控制器)吗?因此,您使用Interface Builder构建GUI(来自MVC的视图),并使用插座将此GUI的元素(如按钮,文本字段等)绑定到Obj-C代码(来自MVC的Controller)。

答案 4 :(得分:0)

看一下这篇文章:Conforming Objective-C’s Protocols in C# Codes

不要担心标题中的“C#”这个词,你可以忽略那个部分。这篇文章的主要部分讨论了Objective-C中的protocolsdelegates。这可能会有所帮助。