【问题标题】:Mistake in WWDC 2019 "Combine in Practice" Code example for CombineLatest?WWDC 2019“Combine in Practice”代码示例中的错误 CombineLatest?
【发布时间】:2019-11-16 10:30:58
【问题描述】:

我尝试关注 WWDC 2019 的 Combine in Practice 谈话(从 26:00 分钟开始)的代码 sn-p 或查看 slides 179 ff。但它不会编译并且查看 API 某些部分对我来说没有意义(例如,使用 closure 类型的第三个参数调用 CombineLatest.init(A, B)。我尝试调整示例以便它们编译。

问题第 1/2 部分:如果我对 WWDC 2019 代码 sn-ps 有误解,谁能帮助我并告诉我?

第一个代码 sn-p(幻灯片 179)

@Published var password: String = ""
@Published var passwordAgain: String = ""

var validatedPassword: CombineLatest<Published<String>, Published<String>, String?> {
    return CombineLatest($password, $passwordAgain) { password, passwordAgain in
        guard password == passwordAgain, password.count > 8 else { return nil }
        return password
    }
}

我只能让这个 sn-p 至少返回给我Publisher fromCombineLatest`

  • Publishers 枚举添加到CombineLatest 的命名空间
  • 移除尾随闭合
  • .Publisher 添加到Published&lt;String&gt;
@Published var password: String = ""
@Published var passwordAgain: String = ""

var validatedPassword: Publishers.CombineLatest<Published<String>.Publisher, Published<String>.Publisher> {
    return Publishers.CombineLatest($password, $passwordAgain)
}

第二个代码 sn-p(幻灯片 185)

@Published var password: String = ""
@Published var passwordAgain: String = ""

var validatedPassword: Map<CombineLatest<Published<String>, Published<String>, String?>> {
    return CombineLatest($password, $passwordAgain) { password, passwordAgain in
        guard password == passwordAgain, password.count > 8 else { return nil }
        return password
    }
    .map { $0 == "password1" ? nil : $0 }
}

我可以让这个 sn-p 在以下情况下编译:

  • 执行为第一个 sn-p 列出的所有步骤
  • Map前面添加Publishers.
  • &lt;&gt; 移动到正确的位置
  • 显式返回Publishers.Map,并使用正确的参数upstream:
@Published var password: String = ""
@Published var passwordAgain: String = ""

var validatedPassword: Publishers.Map<Publishers.CombineLatest<Published<String>.Publisher, Published<String>.Publisher>, String?> {
        return Publishers.Map(upstream: Publishers.CombineLatest($password, $passwordAgain)) { password, passwordAgain in
            guard password == passwordAgain, password.count > 8 else { return nil }
            return password
    }

或者当包括幻灯片中的.map {} 时:

  • 通过将 var 类型包装在另一个 Publishers.Map&lt;..., String?&gt;
@Published var password: String = ""
@Published var passwordAgain: String = ""
var validatedPassword: Publishers.Map<Publishers.Map<Publishers.CombineLatest<Published<String>.Publisher, Published<String>.Publisher>, String?>, String?> {
        return Publishers.Map(upstream: Publishers.CombineLatest($password, $passwordAgain)) { password, passwordAgain in
            guard password == passwordAgain, password.count > 8 else { return nil }
            return password
    }
    .map { $0 == "password1" ? nil : $0 }
}

问题第 2/2 部分:快速的方法是什么?例如,通过使用这样的东西(不能编译):

@Published var password: String = ""
@Published var passwordAgain: String = ""

var validatedPassword: AnyPublisher<String?, Never> {
    return Just($password)
        .combineLatest($passwordAgain) { password, passwordAgain in
            guard password == passwordAgain, password.count > 8 else { return nil }
            return password
    }
    .map{ $0 == "password1" ? nil : $0 }
    .eraseToAnyPublisher()
}

【问题讨论】:

    标签: swift generics swiftui combine combinelatest


    【解决方案1】:

    在第一季度:

    WWDC 演示使用当时存在的 API。时间过去了 - API 已更改。就是这样。

    第二季度:

    尝试如下...

    var validatedPassword: AnyPublisher<String?, Never> {
        return Publishers.CombineLatest($password, $passwordAgain)
            .map { password, passwordRepeat in
                guard password == passwordRepeat, password.count > 8 else { return nil }
                return password
            }
            .map { ($0 ?? "") == "password1" ? nil : $0 }
            .eraseToAnyPublisher()
    }
    

    【讨论】:

    • 谢谢,还有一个问题:为什么我不能在第一个.map 的结果上使用.map { $0 == "password1" ? nil : test }? (在.eraseToAnyPublisher() 之前)。这会导致guard 行中的错误'nil' is incompatible with return type 'String'...我知道我可以简单地在第一个.map() 中添加额外的检查,但我想了解为什么它通常不起作用。
    • 由于您没有显式提供参数类型,编译器会尝试反向构造预期类型,以便为输入和先前的输出对齐(展开泛型)。所以在你的输出中有 nil,但输入试图与字符串进行比较,所以它必须是字符串,但 nil 不能是字符串 - 你得到了错误。所以解决方案应该满足类型检查 - .map { ($0 ?? "") == "password1" ? nil : $0 } 必须为你工作。
    猜你喜欢
    • 1970-01-01
    • 2011-03-07
    • 1970-01-01
    • 1970-01-01
    • 2011-06-03
    • 1970-01-01
    • 2020-06-03
    • 2011-07-18
    相关资源
    最近更新 更多