【问题标题】:Conceptional: two controller using the same calculation method - delegate?概念性:两个控制器使用相同的计算方法——委托?
【发布时间】:2014-06-01 17:44:35
【问题描述】:

我有两个甚至更多的视图控制器(A 和 B),它们使用相同的计算方法。我猜最好的方法是将计算方法放在它自己的类中(我们称之为C),定义一个协议,就是这样。如果这是正确的,我怎么知道如何称呼代表?

如果我分配/初始化 C 类的对象(具有计算器方法的对象),例如在 B 类中,我在 B 类中有对象指针 - 没关系。但是我如何获得A类甚至其他类中已知的对象指针(即如何告诉那些想要使用委托的控制器(即相同的计算方法),一旦委托分配/初始化如何处理委托B级?

非常感谢任何帮助!

【问题讨论】:

  • 如果通用代码将是纯粹的“功能性”——不访问输入参数之外的任何“状态”——那么将其设为类方法可能是最简单的。可以在一些“CommonFunctions”类或一些现有的“common”类中。
  • 非常感谢,这对我来说是最好的主意。我会同意的

标签: ios objective-c delegates protocols


【解决方案1】:

我有两个甚至更多的视图控制器(A 和 B),它们使用相同的计算方法。

除非这是用于计算视图布局,否则它可能表明您违反了 MVC。视图控制器通常不应该计算任何东西。他们的工作是管理用户交互。数据和计算属于模型。

如果它是正确的视图控制器计算(例如管理布局),那么您需要委托是正确的。 “委托”是 Cocoa 倾向于称之为策略模式的东西。你将你的算法移动到另一个对象中,这样你就可以在不改变其余代码的情况下改变算法。

因此,在一种情况下,您需要访问某个模型对象,而在另一种情况下,您需要访问某个委托。在任何一种情况下,解决方案都可以相似。我会把这两种情况都称为“C”。

一种解决方案,尤其是您使用情节提要时,是在情节提要中创建“C”并将其与IBOutlet 连接。您可以在情节提要中创建您喜欢的任何对象。只需拖出一个“对象”并将其类设置为适当的类。像其他任何东西一样连接它。(这是一种通常用于 OS X 上的多视图 nib 文件的技术,我记得翻译到情节提要,但它不适用于跨平台共享对象场景,仅在场景中;所以它在 iOS 上没那么有用。)

另一种解决方案,特别是对于模型,是将其实现为单例,或者有一个单独的单例(“模型控制器”)来返回它。您不应该为此使用应用程序委托;使用专门为此目的制作的单例。

您可以在应用程序委托中创建“C”并将其传递给根视图控制器(这是对应用程序委托的正确使用,因为它是全局程序初始化的一部分)。视图控制器可以将对象作为其 segue 的一部分传递。这是我传递模型对象的首选解决方案。

如果它真的是一个布局计算委托,这可能是某种配置系统的一部分(假设它可以改变)。当前配置可以视为模型的一部分,以上所有技术仍然有效。

如果它真的只是共享算法并且没有变化,请不要忘记 C 函数。没有规定您必须将所有代码放入方法中。函数是无状态计算的理想选择。可以通过这种方式使用类别,但简单的函数具有较少的复杂性。

【讨论】:

  • 感谢您的回答。它只是一个算法,所以 C 函数听起来不错。但是,如果我使用委托和故事板,它会如何工作,当你说:“我们拖出一个“对象”并将其类设置为适当的类。像其他任何东西一样连接它。”?我不知道这会如何工作
【解决方案2】:

您的意思是 A 类和 B 类具有共同的依赖关系(可以是 C 类或只是协议 C)。 A 和 B 不需要知道它们是如何被实例化的,他们只需要知道它们最终将被提供一个实现(协议)C 的实例。 另一个重要的事情是,您可能不希望 C 被 A 或 B 强引用所持有。

我会看看哪个类 F 可以负责实例化 A 和 B。 此类(可以描述为工厂)的职责还可以是为 A 和 B 的实例提供 C 实例。

所以我会做什么:定义一个“工厂”类,它具有构建 A 和 B 实例的方法。 这些方法中的每一个也将提供一个 C 实例。如果您希望共享此 C 实例,则它可以是工厂类的属性(或者此工厂类也可以从可用 C 实例池中选择 C ​​实例)。

更新:如果您使用情节提要来实例化控制器,则不实用。在这种情况下,您可能希望使用其他给定的答案或将共享计算函数实现为单例类 C 的方法(例如,参见 How to pass object between several views in storyboard, iOS Dev

【讨论】:

  • 谢谢,我明白你在说什么,直到你提供 C 实例为止。怎么会这样,抱歉,我不知道。
  • 如果您使用情节提要来实例化视图控制器,我的回答并不实用。我知道这就是你在做的,对吗?
  • 是的,无论如何,谢谢,我会使用类 - 解决方案。
【解决方案3】:

为 A 和 B(以及任意数量的附加控制器)使用包含计算方法的超类。通过使用超类,您不必分配 init 另一个类或使用委托,所有子类都可以访问该方法。

另一种更通用的方法是在 UIViewController 上实现一个类别来添加计算方法。这样,任何从 UIViewController 继承的控制器(UITableViewController、UICollectionViewController 等)都可以访问该方法。

编辑后:

我在您的 cmets 中看到您的计算与控制器无关,只是某种算法,因此 UIViewController 的类别或子类可能不是最好的方法。如果你想在另一个类中做,任何需要使用它的控制器,都可以实例化该类的一个实例,将自己设置为委托,并通过委托方法取回结果(也就是说,如果你甚至需要委托-- 如果计算速度很快,那么您可以只从方法返回结果,而不是使用委托)。在您的控制器返回结果后,应该释放实例。您不必担心哪个控制器设置了委托,因为每个控制器都会创建自己的计算类实例,并将自己设置为委托。我将这种结构用于需要从多个控制器从服务器下载的应用程序。下载类被实例化,完成它的工作,在委托方法中发回结果,然后被释放。它只会在需要完成工作的时候停留。

【讨论】:

  • 是的,当 A 类和 B 类实际上可以有一个共同的超类时效果很好,这可能是这种情况,但并非总是如此。
  • 谢谢,好主意,除了这种特殊情况,我的 A 类是 tableviewcontroller,B 类是普通的。但是,会牢记这个想法。
  • @Red,那么类别可能是最简单的方法。我已编辑以包含该选项。
  • @Red,我已根据您的 cmets 将我的答案更新为 Rob 的答案。我认为您在问题中提到的方法是正确的。
猜你喜欢
  • 2014-08-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多