Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何从两个发布服务器a和B创建快速组合发布服务器,其中发布服务器 ;B使用publisher 的值;A._Swift_Combine_Userdefaults_Grdb_Grdbcombine - Fatal编程技术网

Swift 如何从两个发布服务器a和B创建快速组合发布服务器,其中发布服务器 ;B使用publisher 的值;A.

Swift 如何从两个发布服务器a和B创建快速组合发布服务器,其中发布服务器 ;B使用publisher 的值;A.,swift,combine,userdefaults,grdb,grdbcombine,Swift,Combine,Userdefaults,Grdb,Grdbcombine,我想创建一个Swift Combine publisher,它可以实现以下目标: 发布者应通过(aUserDefaultsSwift包)或GRDB sqlite数据库值的更改(使用)触发 应在发布服务器的数据库查询中使用从发布服务器接收的更新的UserDefaults 以下是我迄今为止尝试过的方法的简化版本: func tasksPublisher() -> AnyPublisher<[Task], Never> { Defaults.publisher(.myUs

我想创建一个Swift Combine publisher,它可以实现以下目标:

  • 发布者应通过(a
    UserDefaults
    Swift包)或GRDB sqlite数据库值的更改(使用)触发
  • 应在发布服务器的数据库查询中使用从发布服务器接收的更新的
    UserDefaults
以下是我迄今为止尝试过的方法的简化版本:

func tasksPublisher() -> AnyPublisher<[Task], Never> {
    Defaults.publisher(.myUserDefault)
        .flatMap { change in
            let myUserDefault = change.newValue

            return ValueObservation
                .tracking { db in
                    try Task.
                        .someFilter(myUserDefault)
                        .fetchAll(db)
                }
                .removeDuplicates()
                .publisher(in: database)
                .eraseToAnyPublisher()
        }
        .eraseToAnyPublisher()
}
func tasksPublisher()->AnyPublisher{
publisher(.myUserDefault)
.flatMap{中的更改
让myUserDefault=change.newValue
返回值观测
.跟踪{db in
试试这个任务。
.someFilter(myUserDefault)
.fetchAll(db)
}
.removeDuplicates()
.publisher(在:数据库中)
.删除任何发布者()
}
.删除任何发布者()
}
但是,此发布服务器会产生以下错误(根据上面我的发布服务器的简化版本进行编辑):

无法将类型为“AnyPublisher”(也称为“AnyPublisher”)的返回表达式转换为返回类型为“AnyPublisher”


我敢打赌,这两个发布者的值不同,这是一个问题:
[Task]
Defaults.KeyChange
。但是,我找不到解决此问题的方法。

假设您希望在默认发布服务器每次发出更改时启动一个新的数据库发布服务器,则需要操作员

此操作员需要协调来自两个发布服务器的错误。这里,由于Defaults.publisher具有
从不
故障类型,因此我们可以使用运算符来聚合数据库发布服务器故障类型:
错误

这使得:

func tasksPublisher() -> AnyPublisher<[Task], Error> {
    Defaults
        .publisher(.myUserDefault)
        .setFailureType(to: Error.self)
        .map({ change -> DatabasePublishers.Value<[Task]> in
            let myUserDefault = change.newValue
            return ValueObservation
                .tracking { db in
                    try Task
                        .someFilter(myUserDefault)
                        .fetchAll(db)
                }
                .removeDuplicates()
                .publisher(in: database)
        })
        .switchToLatest()
        .eraseToAnyPublisher()
}

感谢您提供了一个很好的解决方案!但是,
switchToLatest()
返回的表达式类型在没有更多上下文的情况下是不明确的。但是没有它,它工作得非常好。关于您建议的错误处理:其目的是否与GRDBCombine的演示应用程序中的
.catch{{inempty()}
相同?我上面提供的示例代码确实使用Xcode 11.4编译,因此我无法避免您的
表达式类型在没有更多上下文的情况下不明确。毕竟,这不是关于Swift编译器的问题。是的,我想
.catch{{inempty()}
扮演着同样的角色。不要盲目复制:你必须首先弄清楚你的应用程序需要什么,评估你的选项,并编写表达你意图的代码。这需要时间,但它是值得的。但是缺少
switchToLatest()
不应该在这里导致一些问题,因为我们在一个系统中有两个发布者吗?
// Traps on database error
func tasksPublisher() -> AnyPublisher<[Task], Never> {
    Defaults
        .publisher(.myUserDefault)
        .map({ change -> AnyPublisher<[Task], Never> in
            let myUserDefault = change.newValue
            return ValueObservation
                .tracking { db in
                    try Task
                        .someFilter(myUserDefault)
                        .fetchAll(db)
                }
                .removeDuplicates()
                .publisher(in: database)
                .assertNoFailure("Unexpected database failure")
                .eraseToAnyPublisher()
        })
        .switchToLatest()
        .eraseToAnyPublisher()
}