Delegated - 自动实现闭包的 weak self

Delegated - 自动 weak self

Closure,在平常代码中会常常使用到。使用它时,为了防止可恶的内存泄漏,要时常记得写 [weak self] 这样的代码。但对于程序员来讲写这种模板代码是很枯燥的,因此, Delegated 就应运而生了。经过它注册事后的 Closure,能够自动的 weak self。下面就来看一下它的基本使用吧。git

基本使用

它的使用很简单,经过下面两个步骤就能够实现自动的 weak self:程序员

  • 使用 @Delegated 声明 Closure。
  • 使用 delegate() 函数来调用 Closure。

来看一个具体的例子:github

final class TextField {
    // 第一步:使用 @Delegated 声明 Closure。
    @Delegated var didUpdate: (String) -> ()
}

// 第二步:使用 delegate() 函数来调用 Closure。
textField.$didUpdate.delegate(to: self) { (self, text) in
    // `self` is weak automatically!
    self.label.text = text
}
复制代码

经过上面的两步就实现了自动 weak self,没有循环引用,没有内存泄漏,没有 [weak self]!🎉swift

实现原理

掌握了它的使用方法以后,下面来看一下它的实现原理。它的代码很简单,只有一个 Delegated.swift 文件,代码只有 410 行。api

全部类的说明:markdown

  • Delegated0:对应无返回值,无参数的 Closure。
  • Delegated1:对应无返回值,一个参数的 Closure。
  • Delegated2:对应无返回值,两个参数的 Closure。
  • Delegated3:对应无返回值,三个参数的 Closure。
  • ReturningDelegated0:对应有返回值,无参数的 Closure。
  • ReturningDelegated1:对应有返回值,一个参数的 Closure。
  • ReturningDelegated2:对应有返回值,两个参数的 Closure。
  • ReturningDelegated3:对应有返回值,三个参数的 Closure。

虽然代码包含上面 8 个类,但实质上只要理解了其中的任意一个类便可,由于其余的类只是参数和有无返回值的不一样而已。app

在这里,拿 Delegated1 来举例说明一下它的实现原理。函数

@propertyWrapper
public final class Delegated1<Input> {
    public init() { self.callback = { _ in } }
    private var callback: (Input) -> Void
    public var wrappedValue: (Input) -> Void { return callback }
    
    public var projectedValue: Delegated1<Input> {
        return self
    }
}

public extension Delegated1 {
    func delegate<Target: AnyObject>(
        to target: Target,
        with callback: @escaping (Target, Input) -> Void
    ) {
        self.callback = { [weak target] input in
            guard let target = target else {
                return
            }
            return callback(target, input)
        }
    }
    
    func manuallyDelegate(with callback: @escaping (Input) -> Void) {
        self.callback = callback
    }
    
    func removeDelegate() {
        self.callback = { _ in }
    }
}
复制代码

首先,来分析一下 Delegated1 类。能够看到它使用了 @propertyWrapper 关键字来修饰,@propertyWrapper 的做用简单来讲就是用来封装日常的模板代码。关于@propertyWrapper更详细的介绍能够看这里oop

接着,它经过定义 Input 来实现参数支持泛型,而后声明了 callback 属性来存储 Closure。对于 wrappedValue 和 projectedValue 则是重写的 @propertyWrapper 的内置参数。spa

接着,来看一下 extension 中的 delegate 函数。delegate 函数接受两个参数:

  • target:须要 weak 的对象。
  • callback:实际用到的 closure。

能够看到,在 delegate 函数体内,就是自动 weak self 的关键部分。对 callback 进行了从新赋值:

self.callback = { [weak target] input in
    // 经过这里实现自动 weak self
    guard let target = target else {
        return
    }
    return callback(target, input)
}
复制代码

extension 中还有两个函数,它们的代码也很好理解:

  • manuallyDelegate:手动管理,即不使用自动 weak self。经过代码也能够看出它是直接给 callback 赋值,没有进行上面的 weak self 操做。
  • removeDelegate:移除代理。

至此,源码就分析完了。能够看到这个库的代码仍是很是短小精悍的。

总结

  • 经过 @propertyWrapper 来进行模板代码封装。
  • 经过 callback 的从新赋值来实现自动 weak self。
相关文章
相关标签/搜索