5

我浏览了“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() 时,不会调用 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
4

1 回答 1

6

似乎问题出在内存管理上。可取消是自动发布的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您一起保留仅在释放对象后才释放的可取消项。所以,这应该可以正常工作。

于 2019-08-01T10:57:30.237 回答