【发布时间】:2022-06-15 00:23:24
【问题描述】:
我有一个小项目,它是 Swift UI 练习的扩展,从 Greg Lim 的《Beginning Swift UI》一书中对 Github 进行网络调用: https://github.com/ethamoos/GitProbe
我一直在使用它来练习基本技能,并尝试添加其他可能在实际应用中有用的功能。
与最初的练习相比,我的主要变化是添加了选择要查找的用户的选项(这以前是硬编码的)并允许用户输入。因为这可以返回大量数据,所以我现在想让结果 List .searchable 以便用户可以过滤结果。
我一直在这里学习本教程: https://www.hackingwithswift.com/quick-start/swiftui/how-to-add-a-search-bar-to-filter-your-data
但我意识到这是基于返回的数据是字符串,因此搜索是一个字符串。
我返回的 JSON 解码为用户数据对象列表,因此无法直接搜索。我假设我可以调整它以匹配针对我的自定义对象的字符串搜索,但我不确定如何执行此操作。
为了让你明白我的意思是代码:
import SwiftUI
import URLImage
struct Result: Codable {
let totalCount: Int
let incompleteResults: Bool
let items: [User]
enum CodingKeys: String, CodingKey {
case totalCount = "total_count"
case incompleteResults = "incomplete_results"
case items
}
}
struct User: Codable, Hashable {
let login: String
let id: Int
let nodeID: String
let avatarURL: String
let gravatarID: String
enum CodingKeys: String, CodingKey {
case login, id
case nodeID = "node_id"
case avatarURL = "avatar_url"
case gravatarID = "gravatar_id"
}
}
class FetchUsers: ObservableObject {
@Published var users = [User]()
func search(for user:String) {
var urlComponents = URLComponents(string: "https://api.github.com/search/users")!
urlComponents.queryItems = [URLQueryItem(name: "q", value: user)]
guard let url = urlComponents.url else {
return
}
URLSession.shared.dataTask(with: url) {(data, response, error) in
do {
if let data = data {
let decodedData = try JSONDecoder().decode(Result.self, from: data)
DispatchQueue.main.async {
self.users = decodedData.items
}
} else {
print("No data")
}
} catch {
print("Error: \(error)")
}
}.resume()
}
}
struct ContentView: View {
@State var username: String = ""
var body: some View {
NavigationView {
Form {
Section {
Text("Enter user to search for")
TextField("Enter your username", text: $username).disableAutocorrection(true)
.autocapitalization(.none)
}
NavigationLink(destination: UserView(username: username)) {
Text("Show detail for \(username)")
}
}
}
}
}
struct UserView: View {
@State var username: String
@ObservedObject var fetchUsers = FetchUsers()
@State var searchText = ""
var body: some View {
List {
ForEach(fetchUsers.users, id:\.self) { user in
NavigationLink(user.login, destination: UserDetailView(user:user))
}
}.onAppear {
self.fetchUsers.search(for: username)
}
.searchable(text: $searchText)
.navigationTitle("Users")
}
/// With suggestion added
/// The search results
private var searchResults: [User] {
if searchText.isEmpty {
return fetchUsers.users // your entire list of users if no search input
} else {
return fetchUsers.search(for: searchText) // calls your search method passing your search text
}
}
}
struct UserDetailView: View {
var user: User
var body: some View {
Form {
Text(user.login).font(.headline)
Text("Git iD = \(user.id)")
URLImage(URL(string:user.avatarURL)!){ image in
image.resizable().frame(width: 50, height: 50)
}
}
}
}
对此的任何帮助将不胜感激。
【问题讨论】: