使用按钮从 API 加载图像
Load image from API using a button
在我的应用中,用户可以从特定 API 中搜索图像,然后单击按钮获取该图像的 url。我的问题是如何向用户显示图像?
内容视图:
@StateObject var dataModel = DataModel()
var body: some View {
// Text to display the link of the Image, when clicked on, it opens in Safari:
Text("\(dataModel.imageURL)")
.padding()
.onTapGesture {
let url = URL(string: dataModel.imageURL)
guard let recievedURL = url, UIApplication.shared.canOpenURL(recievedURL) else { return }
UIApplication.shared.open(recievedURL)
}
// TextField where the user enters the search word:
TextField("Search Images...", text: $dataModel.searchTerm)
// After pressing this button, the DataModel fetches the data and presents the url in the text above:
Button(action: {
dataModel.fetchAPI()
}, label: {
Text("Fetch Image")
})
}
DataModel() 中获取数据的函数:
@Published var imageURL = String()
@Published var searchTerm = String()
func fetchAPI() {
guard let url = URL(string:{The url including the searchWord}) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let recievedData = data, error == nil else {
print("ERROR: \(String(describing: error?.localizedDescription))")
return
}
do {
let model = try JSONDecoder().decode(ImageData.self, from: recievedData)
DispatchQueue.main.async {
self.imageURL = model.data.first?.url ?? "No URL"
}
} catch {
print("Error: \(error.localizedDescription)")
}
}
.resume()
}
当我尝试根据接收到的数据创建图像时,应用程序立即崩溃,因为数据为零。那么如何在用户按下按钮获取数据后显示图像?
获得 URL 后,您可以启动另一个网络调用以从 URL 获取数据。然后,您可以像这样从 Data
创建一个 UIImage
:
UIImage(data: receivedData)
如果你添加一个 UIImage
属性 到你的数据模型,你会得到这样的东西:
@Published var image : UIImage?
//after you get the data from your network call:
image = UIImage(data: receivedData)
然后,在您的 ContentView
中,您可以显示该图像(如果存在):
if let image = dataModel.image {
Image(uiImage: image)
}
您的数据模型中的函数可能看起来像这样来实现此目的:
class DataModel : ObservableObject {
//other published properties
@Published var image : UIImage?
var cancellable : AnyCancellable?
func getImageFromURL(url: URL) {
self.cancellable =
URLSession.shared.dataTaskPublisher(for: url)
.receive(on: RunLoop.main)
.sink(receiveCompletion: { (completion) in
//handle errors
}, receiveValue: { (output) in
self.image = UIImage(data: output.data)
})
}
//your original function to get the JSON and decode it...
}
注意:确保在文件顶部导入 Combine,否则 AnyCancellable
将不可用
在我的应用中,用户可以从特定 API 中搜索图像,然后单击按钮获取该图像的 url。我的问题是如何向用户显示图像?
内容视图:
@StateObject var dataModel = DataModel()
var body: some View {
// Text to display the link of the Image, when clicked on, it opens in Safari:
Text("\(dataModel.imageURL)")
.padding()
.onTapGesture {
let url = URL(string: dataModel.imageURL)
guard let recievedURL = url, UIApplication.shared.canOpenURL(recievedURL) else { return }
UIApplication.shared.open(recievedURL)
}
// TextField where the user enters the search word:
TextField("Search Images...", text: $dataModel.searchTerm)
// After pressing this button, the DataModel fetches the data and presents the url in the text above:
Button(action: {
dataModel.fetchAPI()
}, label: {
Text("Fetch Image")
})
}
DataModel() 中获取数据的函数:
@Published var imageURL = String()
@Published var searchTerm = String()
func fetchAPI() {
guard let url = URL(string:{The url including the searchWord}) else { return }
URLSession.shared.dataTask(with: url) { (data, response, error) in
guard let recievedData = data, error == nil else {
print("ERROR: \(String(describing: error?.localizedDescription))")
return
}
do {
let model = try JSONDecoder().decode(ImageData.self, from: recievedData)
DispatchQueue.main.async {
self.imageURL = model.data.first?.url ?? "No URL"
}
} catch {
print("Error: \(error.localizedDescription)")
}
}
.resume()
}
当我尝试根据接收到的数据创建图像时,应用程序立即崩溃,因为数据为零。那么如何在用户按下按钮获取数据后显示图像?
获得 URL 后,您可以启动另一个网络调用以从 URL 获取数据。然后,您可以像这样从 Data
创建一个 UIImage
:
UIImage(data: receivedData)
如果你添加一个 UIImage
属性 到你的数据模型,你会得到这样的东西:
@Published var image : UIImage?
//after you get the data from your network call:
image = UIImage(data: receivedData)
然后,在您的 ContentView
中,您可以显示该图像(如果存在):
if let image = dataModel.image {
Image(uiImage: image)
}
您的数据模型中的函数可能看起来像这样来实现此目的:
class DataModel : ObservableObject {
//other published properties
@Published var image : UIImage?
var cancellable : AnyCancellable?
func getImageFromURL(url: URL) {
self.cancellable =
URLSession.shared.dataTaskPublisher(for: url)
.receive(on: RunLoop.main)
.sink(receiveCompletion: { (completion) in
//handle errors
}, receiveValue: { (output) in
self.image = UIImage(data: output.data)
})
}
//your original function to get the JSON and decode it...
}
注意:确保在文件顶部导入 Combine,否则 AnyCancellable
将不可用