我需要理解为什么Objective-C中的委托如此重要,是什么让它如此特别?

时间:2014-09-13 19:26:11

标签: ios objective-c swift delegates delegation

所以我已经阅读了很多代表性的解释和做法,但我似乎仍然没有得到它,我有特定的问题,我希望能得到一些有见地的简单答案。

  1. 为什么使用委托实例方法?在UIAlertView中,为什么不将– alertView:clickedButtonAtIndex:作为将在我的UIAlertView实例上调用的实例方法?

  2. 什么是委托属性?为什么我必须创建委托属性并使用奇怪的语法@property (nonatomic, strong) id <ClassesDelegate> delegate

  3. 定义它
  4. 委托和协议是硬币的两个面孔吗?

  5. 我何时知道我应该在我的应用中实施委托而非直接通话?

  6. 委托在Swift中使用的次数和重要性一样吗?

  7. 首先叫什么,为什么?班上让自己成为代表的方法?或者声明它的类中的委托方法本身?

  8. 感谢您抽出宝贵的时间来解决这个问题,我正在拼命寻找我的问题的清晰而有用的答案,随时举例或介绍一些相关话题!

5 个答案:

答案 0 :(得分:3)

委派的优点是依赖倒置。

通常,代码在运行时调用依赖项的相同方向上具有编译时依赖性。如果是这种情况,UITableview类将对我们的代码产生编译时依赖,因为它调用了我们的代码。通过使用委托将其反转,我们的代码对UITableview类具有编译时依赖性,但UITableview类在运行时调用我们的代码。

涉及成本:我们需要设置委托,UITableview必须在运行时检查委托方法是否已实现。

注意:当我说UITableview时,我包括UITableviewDelegateUITableviewDatasource

请参阅:Dependency inversion principleClean Code, Episode 13

答案 1 :(得分:3)

也许现实生活中的例子可以更好地描述委托设计模式中的不同之处。

假设您开设了一家新公司,并且您有一名会计师来处理官僚主义的事情。

情景#1

你去他的办公室,给他所需要的信息:

  • 公司名称
  • 公司#number / id
  • 员工人数
  • 电子邮件地址
  • 街道地址

然后会计师会将数据存储在某个地方,并且可能会告诉你“如果有任何变化,请不要忘记给我打电话”

明天您雇用了一名新员工,但忘记通知您的会计师。他仍将使用您提供给他的原始过时数据。

情景#2

使用委托模式,您可以转到您的会计师,并向他提供您的电话号码(代表),而不是其他任何内容。

稍后,他会打电话给你,问:商业名称是什么?

后来,他会打电话给你,问:你有多少员工?

稍后,他会打电话给你,问:你公司的地址是什么?

雇用新员工的第二天。

2天后,他会打电话给你问:你有多少员工?

在委派模型(场景#2)中,您会看到您的会计师始终拥有按需的最新数据,因为他每次需要数据时都会给您打电话。这就是“不叫我,我会打电话给你”的意思,当谈到控制倒置时(从会计角度来看)。

在开发中转置它,例如填充表格,你有2个选项:

  • 实例化一个表格控件,传递所有数据(要显示的项目列表),然后让表格自行渲染
  • 实例化一个表控件,给它一个指向委托的指针,并在需要知道时让它调用委托:
    • 表格中的行数
    • 要显示在行号上的数据。 Ñ
    • 行的高度没有。 n应该有
    • 等。 但也是在:
    • 排号。 n已被点击
    • 标题已被点击

答案 2 :(得分:1)

首先,如果事情还不清楚,那就不要感到难过。这是一个很好的例子,起初看起来很棘手,但只需花时间点击。这将在你知道之前发生:-)。我将尝试回答上述各点:

1)以这种方式思考 - 现在UIAlertView的工作方式,它允许Apple“委托”alertView的实现:clickedButtonAtIndex:给你。如果这是UIAlertView的实例方法,那么对每个人来说都是相同的实现。然后,要定制实现将需要子类化 - 通常过度依赖设计模式。 Apple倾向于在框架中使用组合而不是继承,这就是一个例子。您可以在此处详细了解该概念:http://en.wikipedia.org/wiki/Composition_over_inheritance

2)delegate属性是对实现委托方法的对象的引用,应该使用哪些对象来“委托”这些任务。奇怪的语法只是意味着这个 - 一个属性,它包含对遵循协议的对象的引用。

3)不完全 - 委托利用协议作为其实施的手段。在上面的示例中,这是一个协议的名称,该对象可以被视为该类的委托必须遵守。在该协议内部定义了该类的委托必须实现的方法。您也可以使用可选的协议方法,但这是一个不同的主题。

4)如果我正确理解了这个问题,我认为你可能希望实现一个委托而不是简单地向你的对象添加实例方法的一个好兆头就是当你认为你可能想要实现这些方法时容易换掉或改变。当这些方法的实施根据建筑物的功能在何处/如何使用而发生很大变化时

5)绝对! Objective-C和Swift是编程语言,委托模式是设计模式的一个例子。一般而言,设计模式是超越编程语言垂直的高级概念。

6)我不确定我是否完全理解你,但我认为这个问题存在一些误解 - 该方法不会被调用两次。在委托协议中声明的方法被调用一次 - 通常来自包含委托属性的类。该类通过以下方式调用该属性的委托实现:

[self.delegate someMethodThatMyDelegateImplemented];

我希望其中一些有帮助!

答案 3 :(得分:0)

  1. 有时您希望UIAlertView在不同的环境中工作不同。如果将自定义UIAlertView设置为自己的委托,则必须提供所有这些上下文(很多if / else语句)。您还可以为每个上下文设置单独的委托。
  2. 这样您就可以向编译器说明实现协议ClassesDelegate的每个类(id)都可以设置为此属性。作为旁注,通常应该weak而不是strong不引入参考周期(A类持有B,B持有A)
  3. 协议(其他语言中的接口)用于定义应由类实现的方法集。如果类符合协议,则可以在不知道特定类的情况下调用此方法。委托是一种模式,其中A类将一些工作委托给B类(例如抽象打印机委托他的工作真正的打印机)
  4. 当你需要几个不同的行为时,这些行为取决于上下文(例如ContactsViewController需要在下载完成时刷新他的列表,但SingleContactViewController需要重新加载图像,标签等。)
  5. 这是编程中最基本的模式之一,是的。
  6. 这是同样的方法

答案 4 :(得分:0)

您无法向UIAlertView添加方法,因为您没有源代码。您必须继承UIAlertView的子类。但由于您使用UIAlertView不止一次,因此您需要多个子类。这非常不方便。

现在让我们假设你使用一个子类UIAlertView的库,提供更多功能。这很麻烦,因为现在你需要子类化这个子类而不是UIAlertView。

现在让我们说库使用不同的UIAlertview子类,具体取决于你是在iOS 7或8上运行,还是在iOS 6上UIAlertview不变。你有麻烦了。你的子类化模式崩溃了。

相反,您创建一个委托来完成特定于一个UIAlertview的所有事情。该代表将与图书馆合作很好。您可以编写一个非常简单的类,而不是继承一个庞大而复杂的类。很可能使用UIAlertview的代码确切知道代理应该做什么,因此您可以将代码保存在一起。