Ios WebImage未更新视图-SwiftUI(Xcode 12)
我的问题是,当我将observed objects string属性更改为另一个值时,它会更新打印出更新值的Ios WebImage未更新视图-SwiftUI(Xcode 12),ios,json,xcode,swiftui,sdwebimage,Ios,Json,Xcode,Swiftui,Sdwebimage,我的问题是,当我将observed objects string属性更改为另一个值时,它会更新打印出更新值的JSON图像值(使用Unsplash API),但WebImage(来自SDWebImageSwiftUI)不会更改 结果适用于的结构: struct Results : Codable { var total : Int var results : [Result] } struct Result : Codable { var id : String
JSON
图像值(使用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
}
以下是包含要更新的Web图像的视图:
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()
}
}
}
}
结果是您更新了搜索文本,但不再搜索。看,这就是诀窍:
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
}
还有。我更新了您的代码以使用环境对象
。如果在整个应用程序中使用对象的一个实例。考虑使它成为<代码>环境对象< /代码>,不必一直传递它。
添加它很容易。将其添加到您的@main
场景中
导入快捷键
@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
}
另外,请不要让搜索结果出现在数组中,只需将结果附加到数组中,不要删除旧的结果。这就是为什么更新后仍能看到第一批图像的原因。新的只在底部追加。向下滚动以查看它们。如果您不想这样做,只需在
搜索时清空带有结果的数组
谢谢您的回答!我做了更改,但我得到了一些类型错误“实例方法”onReceive(uquo:perform:)”要求“结果”符合“发布者”和“无法将“结果”类型的值转换为预期的参数类型“Int”,因此我用JSON结果更新了我的问题。希望这能有所帮助。