我的问题是,当我将观察到的对象字符串属性更改为另一个值时,它会更新JSON Image值(使用Unsplash API)并打印出更新后的值,但WebImage (来自SDWebImageSwiftUI)没有更改。
结果应用于的结构:
struct Results : Codable {
var total : Int
var results : [Result]
}
struct Result : Codable {
var id : String
var description : String?
var urls : URLs
}
struct URLs : Codable {
var small : String
}以下是视图,其中包含应该更新的webImage:
struct MoodboardView: View {
@ObservedObject var searchObjectController = SearchObjectController.shared
var body: some View {
List {
VStack {
Text("Mood Board: \(searchObjectController.searchText)")
.fontWeight(.bold)
.padding(6)
ForEach(searchObjectController.results, id: \.id, content: { result in
Text(result.description ?? "Empty")
WebImage(url: URL(string: result.urls.small) )
.resizable()
.frame(height:300)
})
}.onAppear() {
searchObjectController.search()
}
}
}
} 下面是执行API请求的类:
class SearchObjectController : ObservableObject {
static let shared = SearchObjectController()
private init() {}
var token = "gQR-YsX0OpwkYpbjhPVi3b4kSR-DtWrR5phwDm2kPMM"
@Published var results = [Result]()
@Published var searchText : String = "forest"
func search () {
let url = URL(string: "https://api.unsplash.com/search/photos?query=\(searchText)")
var request = URLRequest(url: url!)
request.httpMethod = "GET"
request.setValue("Client-ID \(token)", forHTTPHeaderField: "Authorization")
print("request: \(request)")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else {return}
print(String(data: data, encoding: .utf8)!)
do {
let res = try JSONDecoder().decode(Results.self, from: data)
DispatchQueue.main.async {
self.results.append(contentsOf: res.results)
}
//print(self.results)
} catch {
print("catch: \(error)")
}
}
task.resume()
}
}下面是我如何更改按钮中searchText的值,如果你想看的话:
struct GenerateView: View {
@ObservedObject var searchObjectController = SearchObjectController.shared
@State private var celsius: Double = 0
var body: some View {
ZStack {
Color.purple
.ignoresSafeArea()
VStack{
Text("Generate a Random Idea")
.padding()
.foregroundColor(.white)
.font(.largeTitle)
.frame(maxWidth: .infinity, alignment: .center)
Image("placeholder")
Slider(value: $celsius, in: -100...100)
.padding()
Button("Generate") {
print("topic changed to\(searchObjectController.searchText)")
searchObjectController.searchText.self = "tables"
}
Spacer()
}
}
}
}发布于 2021-04-17 17:55:15
事实证明,您更新了搜索文本,但不再搜索。看这个能起到作用:
Button("Generate") {
print("topic changed to\(searchObjectController.searchText)")
searchObjectController.searchText.self = "tables" // you changed the search text but didnt search again
self.searchObjectController.search() // adding this does the trick
}还有。我更新了您的代码以使用EnvironmentObject。如果您在整个应用程序中使用对象的一个实例。考虑让它成为一个EnvironmentObject,这样就不必一直传递它。
添加它很容易。将其添加到@main场景中
导入SwiftUI
@main
struct StackoverflowApp: App {
@ObservedObject var searchObjectController = SearchObjectController()
var body: some Scene {
WindowGroup {
ContentView().environmentObject(self.searchObjectController)
}
}
}使用它甚至更简单:
struct MoodboardView: View {
// Env Obj. so we reference only one object
@EnvironmentObject var searchObjectController: SearchObjectController
var body: some View {
Text("")
}
}以下是包含更改的代码,并按预期工作:我对所做的更改添加了注释
struct ContentView: View {
var body: some View {
MoodboardView()
}
}
struct GenerateView: View {
@EnvironmentObject var searchObjectController: SearchObjectController
@State private var celsius: Double = 0
var body: some View {
ZStack {
Color.purple
.ignoresSafeArea()
VStack{
Text("Generate a Random Idea")
.padding()
.foregroundColor(.white)
.font(.largeTitle)
.frame(maxWidth: .infinity, alignment: .center)
Image("placeholder")
Slider(value: $celsius, in: -100...100)
.padding()
Button("Generate") {
print("topic changed to\(searchObjectController.searchText)")
searchObjectController.searchText.self = "tables" // you changed the search text but didnt search again
self.searchObjectController.search() // adding this does the trick
}
Spacer()
}
}
}
}
class SearchObjectController : ObservableObject {
//static let shared = SearchObjectController() // Delete this. We want one Object of this class in the entire app.
//private init() {} // Delete this. Empty Init is not needed
var token = "gQR-YsX0OpwkYpbjhPVi3b4kSR-DtWrR5phwDm2kPMM"
@Published var results = [Result]()
@Published var searchText : String = "forest"
func search () {
let url = URL(string: "https://api.unsplash.com/search/photos?query=\(searchText)")
var request = URLRequest(url: url!)
request.httpMethod = "GET"
request.setValue("Client-ID \(token)", forHTTPHeaderField: "Authorization")
print("request: \(request)")
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
guard let data = data else {return}
print(String(data: data, encoding: .utf8)!)
do {
let res = try JSONDecoder().decode(Results.self, from: data)
DispatchQueue.main.async {
self.results.append(contentsOf: res.results)
}
//print(self.results)
} catch {
print("catch: \(error)")
}
}
task.resume()
}
}
struct MoodboardView: View {
// Env Obj. so we reference only one object
@EnvironmentObject var searchObjectController: SearchObjectController
var body: some View {
List {
VStack {
Text("Mood Board: \(searchObjectController.searchText)")
.fontWeight(.bold)
.padding(6)
ForEach(searchObjectController.results, id: \.id, content: { result in
Text(result.description ?? "Empty")
WebImage(url: URL(string: result.urls.small) )
.resizable()
.frame(height:300)
})
}.onAppear() {
searchObjectController.search()
}
// I added your update button here so I can use it.
GenerateView()
}
}
}
struct Results : Codable {
var total : Int
var results : [Result]
}
struct Result : Codable {
var id : String
var description : String?
var urls : URLs
}
struct URLs : Codable {
var small : String
}Ps。请注意,在搜索时,您只需将结果添加到数组中,而不是删除旧的结果。这就是为什么你在更新后仍然可以看到第一张图片的原因。新的只会被附加到底部。向下滚动查看它们。如果您不想这样,只需在search上清空结果数组即可
https://stackoverflow.com/questions/67131978
复制相似问题