Weakify 0.5.0

Weakify 0.5.0

测试已测试
语种语言 SwiftSwift
许可证 MIT
发布最后发布2017年10月
SwiftSwift 版本4.0
SPM支持 SPM

Kevin Lundberg 维护。



Weakify 0.5.0






工作原理

Weakify 是一个 µ 框架,提供了一些常用的 weakify() 函数的变体。 weakify() 主要是一种能够将类的方法作为“闭包”值使用的方法,该值由其他组件管理,但同时又防止内存泄漏的发生。

如果您要定义一个(诚然是人为的)类,如下所示

class Thing {
    func doSomething() {
        print("Something!")
    }

    var callback: () -> Void = {}

    func registerCallback() {
        callback = self.doSomething
    }
}

let thing = Thing()
thing.registerCallback()

您将创建一个保留周期,并且 thing 永远不会被释放。每次您引用一个对象上的方法却不调用它时,该方法所绑定类的实例将被方法捕获并持续到方法引用的生存期。这是因为 Swift 中实例方法是实际方法:您在类和实例上编写的实际方法会闭包引用 self(强引用)来确保这些引用的生存期至少与方法的生命周期一样长。

您可以在注册回调方法中这样做以解决这个问题

func registerCallback() {
	callback = { [weak self] in
		self?.doSomething()
	}
}

这打破了保留周期。然而,如果要在具有相同签名的方法上这样做,就必须创建一个新闭包,这略显繁琐,这正是 weakify() 的作用所在。使用它,您可以这样重写此方法

func registerCallback() {
	callback = weakify(self, type(of: self).doSomething)
}

weakify() 使用静态方法引用将对象实例与方法分离(您可以使用 Thing.doSomethingtype(of: self).doSomething 静态地引用 doSomething 方法,其类型为 (Thing) -> () -> ()),这两种方式都有等效类型。在这个例子中,weakify 弱引用地将 self 应用到函数的第一个参数,返回一个闭包,当调用时将执行 仅当 self 没有被释放时doSomething 方法(这与前面定义的捕获 self 的手动闭包类似)。

用法

该库提供了一些可用的不同版本的 weakify 以供您使用

func weakify <T: AnyObject, U>(_ owner: T, _ f: (T) -> () -> ()) -> (U) -> ()
func weakify <T: AnyObject, U>(_ owner: T, _ f: (T) -> () throws ->()) -> (U) throws -> ()

可以被应用于不接受任何参数且不返回任何值的任何方法。生成的闭包可以接受一个参数,该参数将被简单地忽略(在类似于 NSNotificationCenter 的情况下很有用,因为此时您不需要关于 notification 参数的信息),或者类型也可以表示 Void,这意味着不需要输入参数。

func weakify <T: AnyObject, U>(_ owner: T, _ f: (T) -> (U) -> ()) -> (U) -> ()
func weakify <T: AnyObject, U>(_ owner: T, _ f: (T) -> (U) throws ->()) -> (U) throws -> ()

可以被应用于接受参数且不返回任何值的函数,生成的闭包会反映这个函数。

func weakify <T: AnyObject, U, V>(_ owner: T, _ f: (T) -> (U) -> V) -> (U) -> V?
func weakify <T: AnyObject, U, V>(_ owner: T, _ f: (T) -> (U) throws -> V) -> (U) throws -> V?

可以被应用于接受和返回某些值的函数;实质上是前两种情况的联合。

func weakify <T: AnyObject, U, V>(_ owner: T, _ f: (T) -> (U?) -> ()) -> (V) -> ()
func weakify <T: AnyObject, U, V>(_ owner: T, _ f: (T) -> (U?) throws -> ()) -> (V) throws -> ()

可以应用于接受可选值的函数。生成的闭包对输入参数的类型可以完全不同。如果在调用时,owner不是nil,则使用as?运算符有条件地将生成闭包的参数从V转换为U,并将转换结果传递给原始函数(这就是为什么它必须接受可选值,以防转换失败)。

需求

  • 支持Xcode 8/Swift 3的版本0.4.0
  • 支持Xcode 8/Swift 3或Xcode 7.3/Swift 2.2+的版本0.3.0
  • 支持Xcode 8/Swift 2.3或Xcode 7/Swift 2.x的版本0.2.3
  • 支持Xcode 6.3+/Swift 1.2的版本0.1.3
  • 支持iOS 8+/OS X 10.9+/watchOS 2+/tvOS 9+

安装

Swift包管理器

在您的Package.swift文件的依赖项列表中添加以下行(根据您的目标swift版本,适当修改版本号)

.Package(url: "https://github.com/klundberg/weakify.git", versions:Version(0,4,0)..<Version(0,5,0)),

手动安装

如果您无法使用CocoaPods(例如,如果您还需要至少针对iOS 7进行目标开发),建议将这个库安装到您的项目中,只需将weakify.swift从repo复制到您的项目中。您还可以选择将此repo作为git子模块引用,这留给您自行决定。

作者

Kevin Lundberg,kevin at klundberg dot com

贡献

如果您希望增加Weakify的其他变体,请随时提交pull request!请为任何更改包括单元测试。

许可证

Weakify可在MIT许可下使用。有关更多信息,请参阅LICENSE文件。