gpt4 book ai didi

ios - Swift Combine,避免在可选项上嵌套订阅者

转载 作者:行者123 更新时间:2023-12-05 05:03:14 25 4
gpt4 key购买 nike

我有一个包含用户对象的 AccountService 类。用户对象从网络请求中设置为异步。在我的 UI 中,我正在显示用户并希望使更改保持最新。我正在使用 Swift Combine Framework 来执行此操作。

问题:有没有办法避免对象上的嵌套订阅者?

我写了一些测试代码来说明这一点:

import UIKit
import Combine

class User: ObservableObject, CustomDebugStringConvertible {
@Published
var name: String

init(name: String) {
self.name = name
}

var debugDescription: String {
return self.name
}
}

class AccountService {

@Published
var user: User? = nil

var userCancel: AnyCancellable?
var userContentCancel: AnyCancellable?
init() {
self.userCancel = self.$user.sink { (user) in
print("Set user: \(String(describing: user))")

guard let user = user else { return }
self.userContentCancel = user.$name.sink { _ in
print("new name: \(String(describing: self.user))")
}
}
}

func setUseru(user: User) {
self.user = user
}

func changeUserName(name: String) {
self.user?.name = name
}
}

let x = AccountService()
x.setUseru(user: User(name: "Philipp"))
x.changeUserName(name: "Tom")
x.setUseru(user: User(name: "Anna"))

在 Playgroud Xcode 版本 11.4.1、Swift 5 中运行

输出

Set user: nil
Set user: Optional(Philipp)
new name: nil
new name: Optional(Philipp)
Set user: Optional(Anna)
new name: Optional(Tom)

理想情况下,我只想听取 self.$user.sink 以了解何时设置对象 AND 以了解何时更改对象的内容。我在设置用户名时使用了 self.objectWillChange.send(),但我无法触发外部发布者。

我正在寻找摆脱的方法

guard let user = user else { return }
self.userContentCancel = user.$name.sink { _ in
print("new name: \(String(describing: self.user))")
}

在我的实现中,只是从相同的 self.$user.sink { (user) in 实现中驱动所有内容。

最佳答案

是的,有办法。您可以简单地使用 Combine 的 flatMap运算符(operator):

Transforms all elements from an upstream publisher into a new publisher up to a maximum number of publishers you specify.

我的工作示例:

import Foundation
import Combine

class User: ObservableObject {
@Published var name: String

init(name: String) {
self.name = name
}

var debugDescription: String {
return self.name
}
}

class AccountService {
@Published var user: User? = nil
var userCancel: AnyCancellable?

init() {
self.userCancel = self.$user
.filter { $0 != nil }
.flatMap { $0!.$name }
.sink(receiveValue: { name in
print(name)
})
}

func setUseru(user: User) {
self.user = user
}

func changeUserName(name: String) {
self.user?.name = name
}
}

let x = AccountService()
x.setUseru(user: User(name: "Philipp"))
x.changeUserName(name: "Tom")
x.setUseru(user: User(name: "Anna"))

程序的输出将是:

Philipp
Tom
Anna

关于ios - Swift Combine,避免在可选项上嵌套订阅者,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61785359/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com