【发布时间】:2020-11-23 19:45:57
【问题描述】:
我想在用户在搜索字段中输入 3 个或更多字母时执行 API 调用。
我终于让它工作了,但不幸的是,当我关闭服务器并在服务器上发现Publisher 在第一个错误时终止,并且当用户再次在搜索字段中键入文本时,没有进行 API 调用。
我在Combine 上观看了 WWDC 2019 视频并阅读了一些博客文章,但似乎Combine API 经常变化,每个来源的所有内容都不同,当我修补它时,编译器经常抛出无用的错误,例如Fix: Replace type X with type X(见截图)
PS:我知道我可以使用 filter 过滤掉少于 3 个字母的查询,但不知何故我无法让发布者和类型正常工作。我觉得我在 Combine 上遗漏了一些基本内容。 ..
代码如下:
DictionaryService.swift
class DictionaryService {
func searchMatchesPublisher(_ query: String,
inLangSymbol: String,
outLangSymbol: String,
offset: Int = 0,
limit: Int = 20) -> AnyPublisher<[TranslationMatch], Error> {
...
}
DictionarySearchViewModel.swift
class DictionarySearchViewModel: ObservableObject {
@Published var inLang = "de"
@Published var outLang = "en"
@Published var translationMatches = [TranslationMatch]()
@Published var text: String = ""
private var cancellable: AnyCancellable? = nil
init() {
cancellable = $text
.debounce(for: .seconds(0.2), scheduler: DispatchQueue.main)
.removeDuplicates()
.map { [self] queryText -> AnyPublisher<[TranslationMatch], Error> in
if queryText.count < 3 {
return Future<[TranslationMatch], Error> { promise in
promise(.success([TranslationMatch]()))
}
.eraseToAnyPublisher()
} else {
return DictionaryService.sharedInstance()
.searchMatchesPublisher(queryText, inLangSymbol: self.inLang, outLangSymbol: self.outLang)
}
}
.switchToLatest()
.eraseToAnyPublisher()
.replaceError(with: [])
.receive(on: DispatchQueue.main)
.assign(to: \.translationMatches, on: self)
}
}
【问题讨论】:
-
是的.. 我没见过那个。明天将通过您书中的示例,但老实说,我在这里偶然发现了这个问题:swiftwithmajid.com/2020/04/22/catching-errors-in-combine(建议在
flatMap中捕获错误)。我尝试使用.replaceError(with: [])和catch,但无法正确输入类型。我只是觉得我误解了发布的值/错误的类型在哪里改变以及如何处理。不过,感谢您的链接。 -
我会在这里添加一个答案...
-
正如您所说的那样,部分问题在于您无法正确获取类型(当然,来自编译器的错误消息并不是很有帮助)。但那是另一回事。学习在 Combine 中正确输入类型是一门艺术。我在我的在线教程中给出了一些开发管道的提示:apeth.com/UnderstandingCombine/tricksandtips.html
-
请注意:显示解决方案的最佳 Stack Overflow 方式是将其作为答案,而不是将其包含在问题中.
标签: ios swift swiftui reactive-programming combine