CoreMeta 2.0.1

CoreMeta 2.0.1

测试已测试
语言语言 SwiftSwift
许可证 Apache 2
发布最后发布2017年1月
SwiftSwift版本3.0
SPM支持SPM

Josh GretzJosh Gretz维护。



CoreMeta 2.0.1

CoreMeta

CoreMeta是一个用Swift编写的轻量级框架,为iOS应用程序提供控制反转(IoC)和依赖注入(DI)。

主要由Josh GretzTruefit编写。您可以在iOS Conf上查看一个示例项目。

入门

概述

您可以在互联网上了解更多关于IoC / DI的信息,但总的来说,它是一种使代码解耦合并可移除大量“管道”代码的方法。

安装

作为一个Cocoa Pod

作为一个子模块

  • 您可以将此仓库克隆下来,并将其添加到现有git项目的子模块中。我倾向于将所有的子模块放在一个子模块文件夹中。
$ git submodule add https://github.com/jgretz/CoreMeta.git
  • 打开您的项目,并将CoreMeta.xcodeproj拖入项目树
  • 将CoreMeta作为链接框架添加
    • 在树中单击您的项目
    • 选择“常规”选项卡
    • 向下滚动到“链接框架和库”
    • 单击加号
    • 从列表中选择CoreMeta.framework

编写可注入的类和/或协议

不幸的是,Swift在反射(或坦白地说甚至尚未开始)方面还没有赶上。因此,我们仍然需要依赖于随NSObject一起提供的反射方法。这意味着您需要从NSObject派生您的类,并以@objc标记您的协议。

选择容器模式

通常,我发现每个项目中有一个容器,并且您希望此容器是一个共享的单一实例。尽管这会略微破坏封装,但如果您接受此方法,我可以提供一些相当出色的语法糖方法,使得配置代码易于阅读。这是一个权衡,我和我的团队通常愿意做出。

话虽如此,我不想把你逼进死角,因此CMContainer实现了CMContainerProtocol。然后您可以手动创建容器,并仅将其注入到您选择公开属性的对象上。

配置容器

一旦实例化(无论使用框架提供的单例还是您自己的),您需要配置容器。虽然您可以要求容器提供任何类型的对象,并为您创建它,但它只会注入您已配置的类和协议。

类注册

要注册需要配置的类,您可以在容器上调用register方法

container.registerClass(Foo.self)

或者如果您使用的是单例容器,您可以以我认为更易读的方式注册类

Foo.register()

此外,还有方法重载可以让容器缓存对象(用于仓库和其他有状态对象),在每次创建对象后执行闭包。

协议注册

如果您更喜欢使用协议解耦代码(参见SOLID),CoreMeta也支持。您需要通知容器哪些类实现了容器要注入的每个协议。

要定义这一点

container.registerClassAsProtocol(Foo.self, p: Bar.self)

或者

Foo.registerClassAsProtocol(Bar.self)

类型重定向

有时请求一个基类并返回一个继承类实例是有用的。例如,您可能需要针对iPhone和iPad略有不同的类实现,但主要逻辑是相同的。您可以在配置时让容器返回适当的基类请求实现。

container.registerClassAsClass(iPadFoo.self, replacedClass: Foo.self)

或者

iPadFoo.registerClassAsClass(Foo.self)

自动注册

作为拥有包含所有注册信息单个类的替代方案(我通常更喜欢这样做),您可以让每个类通过实现CMContainerAutoRegister协议来声明它应该被注册。

然后您只需在您使用的容器上调用autoregister方法

创建对象

大多数情况下,容器会为您创建对象,是为了将其注入其他对象。但有时您可能需要手动创建对象(无论是链中的第一个对象,还是出于某些原因您想要限制实例的生存周期范围)。

以下是创建对象的几个代码示例(根据您的情况适用)

let foo = container.objectForType(Foo.self)
let foo:Foo = container.objectForType()
let foo:Foo = Foo.object()

关于协议的快速说明,因为我不能保证您已经配置了协议,所以我必须以Optional的形式返回它。这也意味着您需要解包它。

let foo = container.objectForProtocol(Bar.self)!
let foo = NSObject.objectForProtocol(Bar.self)!

属性注入

让容器将属性注入到对象上相当直接。任何符合以下条件的属性都将被注入

  • 声明为var
  • 类/协议实现了NSObject / @objc
  • 类/协议已登记到容器中

向现有对象注入

任何从NSObject派生的对象在实例化之后也可以进行注入。这主要在你希望注入UIViewControllers并且使用Storyboard的情况下发挥作用。

以下是几个示例

container.inject(foo)
foo.inject()

缓存对象

有时你希望在内存中只有一个对象的实例,并且所有需要访问它的对象(例如仓库、设置、配置等)都获得相同的对象。如果没有使用IOC / DI,你最终会有一堆单例对象或者在各个地方都有静态全局变量。这是CoreMeta可以帮你解耦代码的绝佳地方之一。

以下是缓存对象的几个示例

  • 在注册时:通过将类标记为cache: true,容器将自动缓存它创建的第一个该类的实例。
  • 创建之后,你可以通过调用put: container.put()foo.put() 将对象放入容器中

其他想法

为什么是属性注入?

通常在IOC / DI讨论中,你会找到很多人偏好构造函数注入而不是属性注入。然而,CoreMeta仅支持属性注入。我计划写一篇更长的博客文章来讨论这个主题,但简而言之,以下是我的理由。

尽管Swift和Objective-C没有传统的构造函数,但它们通常使用init模式(实际上这是Swift在编译时强制执行的)。虽然Introspection框架允许找到这些方法,但它不会在编译时记录参数的类型。这意味着所有容器(或任何类)都知道方法的参数列表,如果参数是对象、结构体或值类型。这意味着我们不能根据当前的容器配置进行匹配。虽然我曾考虑使用命名约定做一些事情,但这感觉过于黑客式,所以我决定不尝试。

分支

master分支已经更新到了新的CoreMeta Swift版本。这个版本是一个彻底的重写(虽然我显然盗用了很多v1的概念)。在这个过程中,我添加了测试、类名前缀、错误修复以及容器的协议。我还尝试以减少需要强制转换一切的方式编写它

如果你在寻找最初用Objective-C编写的原始版本,你可以在v1.0-objc分支中找到它

许可证

版权所有 2011 TrueFit Solutions

许可协议为Apache License,版本2.0(以下简称“许可证”);除非遵守许可证或书面同意,否则不使用此文件。你可以在以下位置获得许可证副本:

https://apache.ac.cn/licenses/LICENSE-2.0

除非适用法律要求或书面同意,否则根据许可证分发的软件按“原样”基础分发,不提供任何形式(明确或暗示)的保证或条件。有关许可证的具体语言规范权限和限制,请参阅许可证。