Delegated 是一个非常小的包,可以帮助您在使用基于闭包的委托时避免循环引用。
新的 Medium 文章 这里。
原始 Medium 文章 (Delegated 0.1.2) 这里。
🚨 警告! Delegated 2.0 与 Delegated 0.1.2 不兼容。 如果您不想迁移当前的代码库,请停留在 Delegated 0.1.2。 请参阅 Delegated 0.1.2 的文档 这里。 如果您需要从 0.1.x 迁移到 2.0.x 的任何帮助,请提出一个 issue。
final class TextField {
var didUpdate: (String) -> () = { _ in }
}
// later...
self.textField.didUpdate = { [weak self] text in
guard let strongSelf = self else {
return
}
strongSelf.label.text = text
}
final class TextField {
@Delegated var didUpdate: (String) -> ()
}
// later...
textField.$didUpdate.delegate(to: self) { (self, text) in
// `self` is weak automatically!
self.label.text = text
}
没有循环引用! 没有内存泄漏! 没有 [weak self]
!🎉
final class TextField {
@Delegated var didUpdate: (String) -> ()
}
这只会为具有恰好一个参数且没有返回值的闭包编译。 要使用任何其他数量的参数,请使用这个
final class TextField {
@Delegated0 var didStartEditing: () -> Void
@Delegated1 var didUpdate: (String) -> Void
@Delegated2 var didReplace: (String, String) -> Void
}
开箱即用地提供了 Delegated0
- Delegated4
。 Delegated
是 Delegated1
的类型别名。
// somewhere inside init() or viewDidLoad() or similar
self.textField = TextField()
textField.$didUpdate.delegate(to: self) { (self, text) in
self.label.text = text
}
默认情况下,delegate(to:with:)
会将 self
包装在一个弱引用中,这样您就不需要每次都记住编写 [weak self]
。 这是 Delegated 的主要功能,但如果您不希望这样,可以使用 manuallyDelegate(with:)
// somewhere inside init() or viewDidLoad() or similar
self.textField = TextField()
textField.$didUpdate.manuallyDelegate { (text) in
print(text)
}
final class TextField {
@Delegated var didUpdate: (String) -> Void
/// ...
private func didFinishEditing() {
self.didUpdate(self.text)
}
}
如果您的委托函数旨在具有返回值(非 Void),请使用 @ReturningDelegated
包装器。
final class TextField {
@ReturningDelegated var shouldReturn: (String) -> Bool?
@ReturningDelegated0 var shouldBeginEditing: () -> Bool?
@ReturningDelegated2 var shouldReplace: (String, String) -> Bool?
}
// ...
textField.$shouldReturn.delegate(to: self) { (self, string) -> Bool in
if string.count > 5 {
return true
} else {
return false
}
}
重要提示:确保您的 @ReturningDelegated
函数返回一个可选值。 如果没有设置委托,它将返回 nil
。
默认的 @ReturningDelegated
支持正好一个输入参数。 如果您需要不同数量的参数,请使用 @ReturningDelegated0
- @ReturningDelegated4
(参见上文)。
@Delegated var didUpdate: (String) -> ()
// ...
self.$didUpdate.removeDelegate()
Delegated 仅通过 Swift 包管理器正式提供。
在 Xcode 11 或更高版本中,在您的项目中,选择:File > Swift Packages > Add Pacakage Dependency
在搜索栏中输入
https://github.com/dreymonde/Delegated
当您找到该包时,可以使用 next 按钮继续安装。
如果您在 Swift Packages 面板中找不到任何内容,您可能尚未添加您的 github 帐户。 您可以在 Xcode 的 Preferences 面板中的 Accounts 部分执行此操作。
对于基于命令行的应用程序,您可以直接将其添加到您的 Package.swift 文件中
dependencies: [
.package(url: "https://github.com/dreymonde/Delegated", from: "2.1.0"),
]
当然,您可以选择复制和粘贴代码 - Delegated 只是一个文件,所以请随意。