Swift的Combine框架CombineLatest的问题

时间:2019-08-01 10:23:24

标签: ios swift swift5.1

我观看了WWDC的“ Incomducing Combine”视频,其中有人说,每当发布者的值更新时,就会调用并更新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

1 个答案:

答案 0 :(得分:2)

似乎问题出在内存管理上。 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,您将保留可取消对象,该对象仅在对象释放后才能释放。因此,这应该可以正常工作。