在 swift 中创建弱 selectors/functions
Create weak selectors/functions in swift
我在一个项目中使用 RxSwift
,我发现当我直接绑定到一个选择器时,它会捕获来自自身的强引用并且 deinit
没有被调用。
我想知道如何让 selector/func 只处理一个 weak
的 self 引用。
viewModel.title
.drive(onNext: updateTitle)
.disposed(by: disposeBag)
func updateTitle(_ title: String) {
navigationItem.title = title
}
我试过的是
func updateTitle(_ title: String) {
weak var weakSelf = self
weakSelf?.navigationItem.title = title
}
但是 deinit
仍然没有被调用。
当然,一种解决方案是完全删除 function
viewModel.title
.drive(onNext: { [weak self] title in
self?.updateTitle(title)
)
.disposed(by: disposeBag)
但我不想失去简洁的绑定代码。
经过一番观察,显然你不能让一个 func 变弱,因为它没有保存在内存中,另一方面,闭包捕获它周围的环境。
所以我的解决方案是创建一个闭包作为 var:
viewModel.title
.drive(onNext: updateTitle)
.disposed(by: disposeBag)
lazy var updateTitle: ((String) -> Void)? = { [weak self] _ in
self?.navigationItem.title = [=10=]
}
这是一个解决方案,但仍然好奇我们是否可以让选择器捕获弱引用。
玩弄它,我发现您可以获得如下语法:
viewModel.title
.drive(onNext: weakCapture(self, method: YourViewController.updateTitle))
.disposed(by: disposeBag)
药比病痛,还算有点意思。下面是辅助方法的定义:
func weakCapture<T: AnyObject, A1>(
_ target: T,
method: @escaping (T) -> (A1) -> Void
) -> (A1) -> Void {
return { [weak target] arg in
guard let strongTarget = target else { return }
method(strongTarget)(arg)
}
}
这是一个用法示例:
var c: C? = C()
let weaklyCapturedFooMethod = weakCapture(c!, method: C.foo)
weaklyCapturedFooMethod(123) // Runs foo(i: 123)
print(c as Any)
c = nil
weaklyCapturedFooMethod(123) // does nothing
不太好看。 :P
我建议只使用:{ [weak self] self?.updateTitle([=13=]) }
我在一个项目中使用 RxSwift
,我发现当我直接绑定到一个选择器时,它会捕获来自自身的强引用并且 deinit
没有被调用。
我想知道如何让 selector/func 只处理一个 weak
的 self 引用。
viewModel.title
.drive(onNext: updateTitle)
.disposed(by: disposeBag)
func updateTitle(_ title: String) {
navigationItem.title = title
}
我试过的是
func updateTitle(_ title: String) {
weak var weakSelf = self
weakSelf?.navigationItem.title = title
}
但是 deinit
仍然没有被调用。
当然,一种解决方案是完全删除 function
viewModel.title
.drive(onNext: { [weak self] title in
self?.updateTitle(title)
)
.disposed(by: disposeBag)
但我不想失去简洁的绑定代码。
经过一番观察,显然你不能让一个 func 变弱,因为它没有保存在内存中,另一方面,闭包捕获它周围的环境。
所以我的解决方案是创建一个闭包作为 var:
viewModel.title
.drive(onNext: updateTitle)
.disposed(by: disposeBag)
lazy var updateTitle: ((String) -> Void)? = { [weak self] _ in
self?.navigationItem.title = [=10=]
}
这是一个解决方案,但仍然好奇我们是否可以让选择器捕获弱引用。
玩弄它,我发现您可以获得如下语法:
viewModel.title
.drive(onNext: weakCapture(self, method: YourViewController.updateTitle))
.disposed(by: disposeBag)
药比病痛,还算有点意思。下面是辅助方法的定义:
func weakCapture<T: AnyObject, A1>(
_ target: T,
method: @escaping (T) -> (A1) -> Void
) -> (A1) -> Void {
return { [weak target] arg in
guard let strongTarget = target else { return }
method(strongTarget)(arg)
}
}
这是一个用法示例:
var c: C? = C()
let weaklyCapturedFooMethod = weakCapture(c!, method: C.foo)
weaklyCapturedFooMethod(123) // Runs foo(i: 123)
print(c as Any)
c = nil
weaklyCapturedFooMethod(123) // does nothing
不太好看。 :P
我建议只使用:{ [weak self] self?.updateTitle([=13=]) }