Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/19.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 快速组合正确使用未来_Swift_Future_Combine - Fatal编程技术网

Swift 快速组合正确使用未来

Swift 快速组合正确使用未来,swift,future,combine,Swift,Future,Combine,假设我有一个三层架构(数据、域和视图),我想访问并提供一些数据。这三个层是不同目标的一部分,并使用依赖项注入进行初始化 在域层中,我有以下类型: 协议BookListRepository:AnyObject{ func getAll()->Future } final class BookService{ 私有let存储库:BookListRepository init(存储库:BookListRepository){ self.repository=存储库 } func getAll()->

假设我有一个三层架构(数据、域和视图),我想访问并提供一些数据。这三个层是不同目标的一部分,并使用依赖项注入进行初始化

在域层中,我有以下类型:

协议BookListRepository:AnyObject{
func getAll()->Future
}
final class BookService{
私有let存储库:BookListRepository
init(存储库:BookListRepository){
self.repository=存储库
}
func getAll()->Future{
repository.getAll()
}
}
在数据中,我定义了以下内容:

类BookApi:BookListRepository{
func getAll()->Future{
.init{promise in
let cancelable=urlSession
.dataTaskPublisher(用于:url)
.tryMap(){element->中的数据
警卫
让httpResponse=element.response作为?HTTPURLResponse,
httpResponse.statusCode==200
else{throw URLError(.badServerResponse)}
返回元素.data
}
.decode(类型:[Book]].self,解码器:JSONDecoder())
.sink(receiveCompletion:{completion in
防护罩let.故障(错误)=完成
承诺(失败(错误))
},
receiveValue:{中的图书
承诺(成功(书籍))
}
}
}
在我的视图层中,我将以与此类似的方式访问它:

let服务:BookService=.init(存储库:BookApi())
服务
.getAll()
.receive(在:DispatchQueue.main上)
.sink(接收完成:{打印($0)}{中的书籍
//显示
}
.store(在:&可取消项中)
我的问题是:这是否是一个好的实践,如果不是,那么实现我想要的正确/首选方法是什么。

在Combine(和其他类似框架)中,订阅者关心发布者发出的值和错误,因此习惯上在API边界使用
AnyPublisher

protocol BookListRepository: AnyObject {
    func getAll() -> AnyPublisher<[Book], Error>
}

为什么要将
URLSession.DataTaskPublisher
转换为
Future
?为什么您认为应该首先使用
Future
?您的联合收割机接口在大多数情况下都不应该公开实际的底层
Publisher
,因此您的返回类型应该是
AnyPublisher
。“这在任何方面都是一个好的实践吗”不,可能不是。在将来包装数据任务发布者没有什么意义(数据任务发布者本身就是未来),并将整个管道包装起来,一直到水槽和商店,放在另一个出版商里面,这简直是疯了。这里似乎违背了联合收割机的全部宗旨和精神。非常感谢您的反馈,我是新来联合收割机的,需要了解它的精神。
final class BookService {
    private let repository: BookListRepository

    func getAll() -> AnyPublisher<[Book], Error> {
        repository.getAll()
    }
}

class BookApi: BookListRepository {
    func getAll() -> AnyPublisher<[Book], Error> {
        urlSession
            .dataTaskPublisher(for: url)
            .tryMap() { element -> Data in
                 guard 
                     let httpResponse = element.response as? HTTPURLResponse,
                     httpResponse.statusCode == 200 
                 else { throw URLError(.badServerResponse) }

                 return element.data
            }
            .decode(type: [Book].self, decoder: JSONDecoder())
            .eraseToAnyPublisher()
    }
}