【发布时间】:2019-07-23 16:32:00
【问题描述】:
我是 Swift 的新手,对 SwiftUI 更是如此。我开始创建一个小的基本项目。我使用 Github API 来获取存储库列表。
所以我创建了一个“搜索栏”,就像 SwiftUI 没有 SearchBar 组件一样。每次更改我的 Textfield 内容时,我都想执行 fetch 操作。
我不希望过于频繁地调用 fetch 方法。我决定去抖动它。我面临一个问题,我找不到/理解示例。
我尝试实施去抖动解决方案,但它不起作用,我的应用程序崩溃了。
这是我的 BindableObject
import SwiftUI
import Combine
class ReposStore: BindableObject {
private var service: GithubService
let didChange = PassthroughSubject<Void, Never>()
@Published var searchText: String = ""
var repos: [Repository] = [] {
didSet {
didChange.send()
}
}
var error: String = "" {
didSet {
didChange.send()
}
}
var test: String = "" {
didSet {
didChange.send()
}
}
private var cancellable: AnyCancellable? = nil
init(service: GithubService) {
self.service = service
cancellable = AnyCancellable($searchText
.removeDuplicates()
.debounce(for: 2, scheduler: DispatchQueue.main)
.flatMap { self.fetch(matching: $0) }
.assign(to: \.test, on: self)
)
}
func fetch(matching query: String = "") {
print("### QUERY \(query)")
self.service.getUserRepositories(matching: query) { [weak self] result in
DispatchQueue.main.async {
print("### RESULT HERE \(result)")
switch result {
case .success(let repos): self?.repos = repos
case .failure(let error): self?.error = error.localizedDescription
}
}
}
}
}
这是我的观点
import SwiftUI
struct RepositoryList : View {
@EnvironmentObject var repoStore: ReposStore
@State private var userName: String = ""
var body: some View {
VStack {
NavigationView {
VStack(spacing: 0) {
HStack {
Image(systemName: "magnifyingglass").background(Color.blue).padding(.leading, 10.0)
TextField($repoStore.repoUser, placeholder: Text("Search")).background(Color.red)
.padding(.vertical, 4.0)
.padding(.trailing, 10.0)
}
.border(Color.secondary, width: 1, cornerRadius: 5)
.padding()
List {
ForEach(self.repoStore.repos) { repository in
NavigationLink(
destination: RepositoryDetail(repository: repository).environmentObject(self.repoStore)
) {
RepositoryRow(repository: repository)
}
}
}.navigationBarTitle(Text("Repositories"))
}
}
}
}
我尝试使用 Timer 并每 8 秒进行一次调度和操作,但这种方法会导致我的应用程序崩溃。
更多,我真的不知道用“@objc”注释声明一个函数是否是一个好习惯......
有人可以帮我实现一个正确的方法来消除 BindableObject 中的方法吗?
提前谢谢你:)
【问题讨论】:
-
Combine 已经有一个 debounce 操作符。
-
谢谢,能不能说的更准确一点?
-
我会说观看有关 Combine 框架的 WWDC 2019 视频。他们使用的示例与您正在处理的示例完全相同:我们不希望在用户在文本字段中键入时经常执行的网络操作。
-
谢谢,我会看的:)
-
所以我用我的新代码编辑了我的问题。我一直在观看 WWDC 2019,但我仍然无法在“flatMap”指令中调用我的异步方法。你能给我一些线索/告诉我我的代码是否更好吗?