我有以下任务要做:
我有一个segmented control
,其中有两个主要标签,第一个标签必须从网络加载广告和数据,它们每个都通过不同的网址。我想做的是并行查询广告和数据,当它们都完成后,我想将它们合并到一个列表中并显示给用户。只需使用DispatchGroup
和.enter()
,.leave()
就可以完成此操作。但是,由于这是在segmented control
和search bar
中。 DispatchGroup
必须可取消,以便加载一组新的广告和数据。有没有办法取消DispatchGroup
,还是有办法通过其他多线程功能实现这种逻辑?
具有分段控制功能的多线程iOS
•
问答
ccqhjjf 回答:具有分段控制功能的多线程iOS
这正是Combine的优势所在(如果您使用的是iOS 13)。也就是说,您可以使您的网络请求具有当前所选段的功能以及在搜索栏中键入的内容,并且当您调用switchToLatest
时,它将取消所有未完成的请求,并且只保留反映最新状态的大多数请求。我只是写了一个例子,在这里做到了这一点:
https://github.com/joshuajhomann/Combine-NasaMediaSearch
或更简洁地说,设置两个直通主题,一个用于搜索栏,一个用于分段控件,将它们组合成一个网络请求,用`switchToLatest'展平,然后在需要的地方分配结果:
private var data: [MyData] = []
private var searchTermSubject = PassthroughSubject<String,Never>()
private var segmentSubject = PassthroughSubject<SegmentType,Never>()
...
let searchResults = Publishers
.CombineLatest(
searchTermSubject,segmentSubject
)
.debounce(for: .milliseconds(250),scheduler: RunLoop.main)
.map { combined -> AnyPublisher<[MyData],Never> in
let (term,segmentType) = combined
guard !(term.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty) else {
return Just(.empty).eraseToAnyPublisher()
}
return NetworkRequestPublisher
.search(query: term,mediaType: segmentType)
.replaceErrorWith([])
.eraseToAnyPublisher()
}
.switchToLatest()
.receive(on: RunLoop.main)
// assign or sink here depending on what you want to do
如果您未使用iOS 13,则可以使用OperationQueue或直接对数据任务调用cancel。