【问题标题】:Dependency injection framework for Cocoa? [closed]Cocoa 的依赖注入框架? [关闭]
【发布时间】:2008-11-21 18:32:58
【问题描述】:

Interface Builder 可用于 Cocoa 应用程序中的基本依赖注入,但是当您不想在 NIB 文件中实例化对象时,是否有人知道用于 Objective-C/Cocoa 的更完整的依赖注入框架?

编辑

澄清一下,我承认 IB 可用于基本 DI,但我正在寻找一个功能更完整的框架,包括单独的生产和测试配置,类似于 Groovy 或 Springs。

【问题讨论】:

  • 查看 www.typhoonframework.org
  • Java 肯定仍被认为是一种后期绑定语言。虽然它像 C++ 一样使用 vtable 样式的调度,但凭借虚拟机和类加载器系统,运行时方法拦截仍然是可能的。这种方法比消息传递(objective-c)稍微麻烦一些,并且需要更重的工具才能使其易于使用——比如 JSDK 动态代理、cglib/asm 或 JVM 代理。这启用了诸如 AOP 或“管理对象”(休眠/核心数据)之类的东西,但与 DI 几乎没有关系。我不认为 'java static - needs DI, Objective-C dynamic' 适用。

标签: objective-c cocoa dependency-injection


【解决方案1】:

objection 来自 AtomicObject。它是按照 Guice 的形象塑造的。

【讨论】:

  • 哇,这看起来很邪恶。我仍然不知道我为什么需要这个,但我愿意学习。
  • 谢谢,斯蒂佩特。依赖注入在应用程序开发中最有用。最明显的好处是无需在整个代码库中手动构造对象或维护工厂(或工厂方法)。 DI 库也倾向于通过组合来实现职责分离——我喜欢这一点。然而,它并不适合开发库或“API”,因为 DI 使对象的依赖关系显而易见。可以找到关于 DI 的好文章here
【解决方案2】:

我会不顾一切地谈论这个。最佳答案所描述的依赖注入并没有解决那些寻求使用它的人所面临的核心问题。我们想要一种开发方式,其中组件 A 不直接实例化或引用组件 B。组件 A 由协议绑定到组件 B,并且根本不被组件 A 引用。这允许组件 B 随时被替换,而不会永远感人的 A 部分。我投了反对票,但我会研究你的参考资料,因为似乎有一些人同意你的观点。我不是想辩论,只是想学习。我想更多地了解“不,你不需要这样做”的方法。

【讨论】:

  • Key-Value-Coding “允许随时更换组件 B 而无需接触组件 A”。
  • KVO 没有解释组件 A 如何获得对组件 B 的引用。在 KVO 的大多数典型使用中(或如您所描述的),组件 B 将实例化 A 并绑定到 A 的属性。是的,B 可以是任何关心 A 的对象,但 B 仍然“知道”并实例化 A。也许我错过了什么?
  • 再想一想,我想我明白了一点。 KVC 和鸭子类型允许任何属性访问和消息发送到给定对象,而不管实现如何。这并没有解决谁在 A -> B 的位置实例化依赖项的问题。人们可以使用 IB 将事物连接在一起,这很有趣,但不像实际的依赖注入器那样具有丰富的功能。
  • 有人必须实例化对象。在 Java with Spring 案例中,它是 Spring 容器。对于 Interface Builder “东西”,它是 IB 和运行时(忽略 NSProxy 详细信息)。在应用程序的其余部分,它可能是您代码的一部分。使用 Objective C 类别和鸭子类型解决了动态实例化以改变行为的问题,您剩下的唯一东西就是连接您自己的对象的代码。当您不需要 DI 的其他好处时,为什么还要极端地将其提取到一些 XML 文件中?
  • @Otto 我几个月前不知何故错过了您的回复。我了解您如何使用 NIB 文件执行某些类型的 DI,并且我自己在没有 Spring 容器的情况下这样做了。但是,nib 文件不能作为真正的 DI 容器进行扩展。 (在过去的一年里,当我离开 iOS 时,情况可能有所改善。)此外,我看不出类别能满足我所知道的 DI 的任何好处。我从来没有在运行时使用 DI 来改变行为(你可能会混淆 DI 和 Springframework 提供的 AOP)。这是 2 个正交问题。
【解决方案3】:

我想您会发现在诸如 Objective C、Ruby、Lisp 等后期绑定语言中不需要它。就像 Jamis 透露他在尝试构建 needle 时走上一条过于复杂的道路一样,这是一个 Ruby 的 DI 框架-Net::SSH revisited

这里有一些链接,有望为您提供一些示例代码,以在 Objective C 中执行类似的操作。使用类别,您基本上可以在运行时更改任何类的行为。请参阅 Mac Developer Tips – Objective-C: CategoriesCocoa API docs on categories。本质上,您不需要某个中心位置来请求可配置的“执行 x 的事情”,因为您可以直接实例化 TheThingThatDoesX,如果需要更改/挂钩该行为的其他内容,它可以使用类别。

【讨论】:

  • 我认为这说明了 Objective-C 的设计者 Brad Cox 毕生致力于松耦合和软件重用。 Objective-C 的动态特性可以解决 DI 为静态语言解决的问题。 ieeexplore.ieee.org/iel2/190/267/00004852.pdf?arnumber=4852
  • 类别很棒 - 但我个人不明白它们如何让您了解 DI。修改现有类与更改完整实现不同。
  • 重读 Brad Cox 的论文后,我同意……他是个英雄。但是允许后期绑定的系统与 DI 不同。我很想给你赏金让我重新看到 ObjC 的酷炫,但它最终并没有完全回答我的问题。
  • 这个答案没有反映依赖注入背后的核心目的。这个想法不是在运行时覆盖类行为,而是消除绝望组件之间的硬绑定。你能解释一下类别是如何解决这个问题的吗?
  • 我看不出这个接受的答案如何回答 OP 的问题。 DI 是关于松散耦合和良好的应用程序设计。类/对象应该只满足一个特定的目的。与使用 DI(在 Java 中)之前相比,我发现自己编写了许多单一用途的类并将它们注入到对象的构造函数中。这不应该也适用于 Objective-C 吗?
【解决方案4】:

台风

差不多一年前,我发布了:https://github.com/typhoon-framework/Typhoon

Typhoon-website 列出了主要功能。快速总结:

  • 无创。不需要宏或 XML。使用 powerful Objective-C runtime approach

  • 使同一基类或协议的多个配置变得容易。

  • 无魔法字符串 - 支持 IDE 重构、代码完成和编译时检查。

  • 支持视图控制器注入和故事板集成。

  • 支持初始化程序和属性注入,以及生命周期管理。

  • 强大的内存管理功能。提供预配置的对象,没有单例的内存开销。

  • 对循环依赖的出色支持。

  • 精益。它占用空间非常小,因此适用于 CPU 和内存受限的设备。

  • 久经考验 - 用于各种 Appstore 特色应用

  • 一个国际分布的核心团队(我们甚至监控 StackOverflow),因此对您的任何问题的支持都不会遥不可及 :)

API 文档和示例应用

质量控制:

我们还维护着强大的质量控制系统。

  • 每次提交都会触发一系列regression tests
  • 我们保持较高的测试覆盖率。

【讨论】:

    【解决方案5】:

    您不必在 NIB 文件中实例化对象。如果您将文件的所有者设置为对象的类,然后将视图/窗口/任何内容中的内容链接到该类,则可以通过手动加载 nib 文件在运行时将对象设置为所有者。这样你就可以拥有一个对象的动态实例,它仍然可以正确注入依赖项。

    【讨论】:

    • 但是对于不是 nib 所有者的对象的依赖注入呢?我可以在 nib 中实例化它们,从而使用 IB 进行依赖注入,但这不是一个非常可扩展的解决方案(nib 文件很快就会变得笨拙)
    • 你说“笔尖文件”,好像只有一个。您可以拥有任意数量的 nib 文件,这一点也不笨重。笔尖甚至不必拥有所有者,您可以将任何您喜欢的对象放入没有所有者的笔尖中,并在加载 NIB 文件后手动将它们取出。
    • 我想我通过提到 IB 来绕过讨论。我正在寻找类似 Spring 或 Groovy 的东西。
    【解决方案6】:

    Objective-IOC 的依赖注入实现怎么样

    【讨论】:

      【解决方案7】:

      ObjectivePim 呢? ObjectivePim

      【讨论】:

        【解决方案8】:

        我写了一个非常简单的DI容器,代码在GitHub。它只能做最基本的事情,即。发现一个对象的依赖关系并使用其他给定的对象来满足它们。我发现要在现实世界的应用程序中使用,代码非常简单,而且很有趣。

        【讨论】:

          【解决方案9】:

          有人看过 Mac OS X 10.6 的 Associative References 功能吗?

          我相信这样就有可能构建或已经拥有类似于 DI 的东西。 然而,据我所见,对象中所需的任何引用都必须使用 objc_getAssociatedObject() 手动获取。

          曼弗雷德

          【讨论】:

          • 有趣的想法。关联引用旨在允许从例如类类别添加有效的实例变量,而不必诉诸丑陋的黑客。我不确定它是否适合成为 DI 系统的基础,但这是一个非常有趣的想法。谢谢。
          • 您可能也会觉得这很有趣。我刚刚写了一篇关于 Objective-C 依赖注入的博客。我的第一个博客。 swbymabe.wordpress.com/2010/02/20/…
          • 我阅读了您的博客文章,它看起来不错,显然您在其中投入了大量工作,但我留下的问题是:当您可以实例化您需要的对象时,为什么还要这样做?我认为@Otto 在他的回答中说得很好。不过,感谢关联参考链接,我以前没有见过这个,我认为它可以很好地解决我正在努力解决的问题。
          • 好吧。 DI 用于解耦直接对象依赖关系。使用依赖配置对象可以在运行时连接在一起。它在单元测试中也有很大帮助,您可以更轻松地测试具有依赖关系的对象。然而,Objective-C 运行时提供了在更需要 DI 的语言中不可用的方法。例如,Objective-C 运行时函数 objc_setClass() (developer.apple.com/mac/library/documentation/Cocoa/Reference/…) 可以在运行时交换对象的类。这在 Java 中是不可能的。
          • 您链接到那里的非常有趣的功能:直到现在才知道。我也许可以修改一些使用此功能的非常糟糕的代码。有没有人为这些纯 C 函数编写了一个不错的 Objective-C 包装器?
          【解决方案10】:

          Interface Builder 不进行任何依赖注入。它不需要。 Interface Builder 序列化对象。当笔尖“唤醒”(又名打开)时,没有“依赖关系”需要解决——只有要设置的属性。非常非常简单。打开 nib 完全依赖于 NSCoding 协议和键值编码。

          依赖注入,在最好的情况下几乎是一个临时项目,或者充其量是独立设计的组件之间的通用粘合层,在编写良好的 Objective-C 代码中是没有用的。您要求的是您不需要的工具。

          在 Objective-C 中,需要匿名服务的软件声明了一个协议。然后服务采用此协议。客户端将服务加载为动态插件。另一方面,如果服务器是在客户端之前编写的,那么只需编写一个新的插件来使现有接口适应协议。与尝试定义中间数据驱动系统以在运行时“发现”(请)接口相比,这工作量更少,而且更直接。

          难道不是每个人都清楚 DI 的最大秘密在于它是一种用 XML 而不是本地语言编写代码的方法吗?我真的很想听到一个很好的论点,说明 XML 如何在某种程度上比真正的编程语言更好。这没有任何意义。

          【讨论】:

          • 依赖注入与 XML 没有任何关系。你甚至不需要图书馆来使用它。
          【解决方案11】:

          我整天都在使用 Spring,并且检查过 Groovy。我绝不是 XCode/Cocoa 专家,但 IB 只做了一些依赖注入,而 Groovy 甚至没有真正声称这样做。

          我认为您不是在寻找 DI,而是在寻找一组编译良好的集成库,这样您就不必输入其他人也输入过的大量代码。我认为 Cocoa 没有类似 Spring 的框架,因为出于某种原因,人们倾向于将“开源”视为“不依赖于平台”,因此 Cocoa 有点被冷落了。

          不过,根据您的需要,有一些可用于 Cocoa 的不错的免费开源库,所有这些库都列在 CocoaDev 的 nice list 中。

          我知道这不是 Spring,但我希望它有所帮助。

          【讨论】:

          • 不,其实我在找DI库。
          【解决方案12】:

          DI 是需要动态绑定的运行时执行环境的属性。我对 Obj-C 和 Cocoa 很陌生,所以我可能会说话不顺。除非我遗漏了什么,否则我看不出如何实现 DI,除非通过解释 Obj C 而不是编译它,或者通过修改运行时环境。

          我怀疑 IB 类似 DI 的行为是因为有一个特定于域的运行时环境与使用它构建的应用程序相关联。

          我很高兴得到纠正。

          类别似乎是 mixin 的实现,允许将方法动态分派给委托。相当酷,类似于Java的接口概念,认为细节不同,从以下,我看不出是否可以在类别中定义常量,尽管成员字段不能。

          objective-c categories

          【讨论】:

          • 唉,是什么让你认为动态绑定对 Objective-C 来说是陌生的? Have a look...
          猜你喜欢
          • 1970-01-01
          • 2015-08-26
          • 2014-09-06
          • 1970-01-01
          • 2021-01-07
          • 1970-01-01
          • 2011-03-27
          • 2010-09-14
          • 1970-01-01
          相关资源
          最近更新 更多