Swift 的 Combine 框架 CombineLatest 的问题
Issues with Swift's Combine framework CombineLatest
我浏览了 "Introducing Combine" 的 WWDC 视频,据说每当更新发布者值时,就会调用和更新 CombineLatest。但是我创建的代码片段运行起来很奇怪。
class Mango {
var enableButton = false
@Published var userName = "admin"
@Published var password = "poweruser"
@Published var passwordAgain = "poweruser"
var validatePassword: AnyCancellable {
Publishers.CombineLatest($password, $passwordAgain).map { (password, reenterpass) -> String? in
print("Is Password Same to \(password)? :", password == reenterpass)
guard password == reenterpass else { return nil }
return password
}.eraseToAnyPublisher()
.map { (str) -> Bool in
print("In Map", str != nil)
guard str != nil else { return false }
return true
}.assign(to: \.enableButton, on: self)
}
init() {
validatePassword
}
func checkSub() {
print("1. Is password same? ->",enableButton)
password = "nopoweruser"
print("2. Is password same? ->",enableButton)
}
}
当我初始化并调用函数 checkSub() 时,发布者 'password' 已更新,CombineLatest 不会被调用。为什么它表现异常?
输入:
let mango = Mango()<br>
mango.checkSub()
输出:
Is Password Same to poweruser? : true
In Map true
1. Is password same? -> true
2. Is password same? -> true
看来问题出在内存管理上。 validatePassword
可取消是自动释放的,这意味着订阅在您创建后立即完成,因为您没有保留它。使用 lazy var
使其成为 属性 而不是计算 属性,它应该可以正常工作。
lazy var validatePassword: AnyCancellable = {
Publishers.CombineLatest($password, $passwordAgain).map { (password, reenterpass) -> String? in
print("Is Password Same to \(password)? :", password == reenterpass)
guard password == reenterpass else { return nil }
return password
}.eraseToAnyPublisher()
.map { (str) -> Bool in
print("In Map", str != nil)
guard str != nil else { return false }
return true
}.assign(to: \.enableButton, on: self)
}()
使用 lazy
,您将保留仅在释放对象后才释放的可取消对象。所以,这应该可以正常工作。
我浏览了 "Introducing Combine" 的 WWDC 视频,据说每当更新发布者值时,就会调用和更新 CombineLatest。但是我创建的代码片段运行起来很奇怪。
class Mango {
var enableButton = false
@Published var userName = "admin"
@Published var password = "poweruser"
@Published var passwordAgain = "poweruser"
var validatePassword: AnyCancellable {
Publishers.CombineLatest($password, $passwordAgain).map { (password, reenterpass) -> String? in
print("Is Password Same to \(password)? :", password == reenterpass)
guard password == reenterpass else { return nil }
return password
}.eraseToAnyPublisher()
.map { (str) -> Bool in
print("In Map", str != nil)
guard str != nil else { return false }
return true
}.assign(to: \.enableButton, on: self)
}
init() {
validatePassword
}
func checkSub() {
print("1. Is password same? ->",enableButton)
password = "nopoweruser"
print("2. Is password same? ->",enableButton)
}
}
当我初始化并调用函数 checkSub() 时,发布者 'password' 已更新,CombineLatest 不会被调用。为什么它表现异常?
输入:
let mango = Mango()<br>
mango.checkSub()
输出:
Is Password Same to poweruser? : true
In Map true
1. Is password same? -> true
2. Is password same? -> true
看来问题出在内存管理上。 validatePassword
可取消是自动释放的,这意味着订阅在您创建后立即完成,因为您没有保留它。使用 lazy var
使其成为 属性 而不是计算 属性,它应该可以正常工作。
lazy var validatePassword: AnyCancellable = {
Publishers.CombineLatest($password, $passwordAgain).map { (password, reenterpass) -> String? in
print("Is Password Same to \(password)? :", password == reenterpass)
guard password == reenterpass else { return nil }
return password
}.eraseToAnyPublisher()
.map { (str) -> Bool in
print("In Map", str != nil)
guard str != nil else { return false }
return true
}.assign(to: \.enableButton, on: self)
}()
使用 lazy
,您将保留仅在释放对象后才释放的可取消对象。所以,这应该可以正常工作。