英文:
How to pass API image from Table View into another View Controller using didselectrowat
问题
以下是您提供的内容的翻译:
"I am a newbie in Swift and I am trying to build an app in which I retrieve plant images and information from this api "https://rapidapi.com/mnai01/api/house-plants2"."
我是Swift的新手,我正在尝试构建一个应用程序,从这个API中检索植物图像和信息:“https://rapidapi.com/mnai01/api/house-plants2”。
"I managed to implement a table view in which I display the name and image of each plant in the api, and when I click on any cell in the table view I displayed that certain plant's information in a new view controller."
我成功实现了一个表视图,在其中显示API中每棵植物的名称和图像,当我点击表视图中的任何单元格时,我在新的视图控制器中显示了特定植物的信息。
"My problem is that no matter what I tried I couldn't also display the image of that plant in that view controller and I don't know what to do to make it work."
我的问题是,无论我尝试什么,我都无法在该视图控制器中显示该植物的图像,我不知道如何使其工作。
"It is also worth to mention that the links for the images are of this format:
- img: "http://www.tropicopia.com/house-plant/thumbnails/5556.jpg""
值得一提的是,图像的链接格式如下:
- 图像: “http://www.tropicopia.com/house-plant/thumbnails/5556.jpg”
这是应该显示图像和信息的视图控制器类:
这是你应该显示图像和信息的视图控制器类:
import UIKit
import SDWebImage
class PlantDetailsViewController: UIViewController {
// 植物图像视图
@IBOutlet weak var plantImage: UIImageView!
// 植物信息的标签
@IBOutlet weak var commonNameLabel: UILabel!
@IBOutlet weak var latinNameLabel: UILabel!
@IBOutlet weak var otherNamesLabel: UILabel!
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var useLabel: UILabel!
@IBOutlet weak var styleLabel: UILabel!
@IBOutlet weak var familyLabel: UILabel!
@IBOutlet weak var bloomSeasonLabel: UILabel!
@IBOutlet weak var wateringLabel: UILabel!
@IBOutlet weak var idealLightLabel: UILabel!
@IBOutlet weak var growthLabel: UILabel!
@IBOutlet weak var climatLabel: UILabel!
@IBOutlet weak var diseaseLabel: UILabel!
@IBOutlet weak var insectsLabel: UILabel!
@IBOutlet weak var leafColourLabel: UILabel!
@IBOutlet weak var bloomsColourLabel: UILabel!
@IBOutlet weak var availabilityLabel: UILabel!
@IBOutlet weak var bearingLabel: UILabel!
@IBOutlet weak var appealLabel: UILabel!
var plants: Plant?
var strCommonName = ""
var strLatinName = ""
var strOtherNames = ""
var strCategory = ""
var strUse = ""
var strStyle = ""
var strFamily = ""
var strBloomSeason = ""
var strWatering = ""
var strIdealLight = ""
var strGrowth = ""
var strClimat = ""
var strDisease = ""
var strInsects = ""
var strLeafColour = ""
var strBloomsColour = ""
var strAvailability = ""
var strBearing = ""
var strAppeal = ""
override func viewDidLoad() {
super.viewDidLoad()
commonNameLabel.text = strCommonName
latinNameLabel.text = strLatinName
otherNamesLabel.text = strOtherNames
categoryLabel.text = strCategory
useLabel.text = strUse
styleLabel.text = strStyle
familyLabel.text = strFamily
bloomSeasonLabel.text = strBloomSeason
wateringLabel.text = strWatering
idealLightLabel.text = strIdealLight
growthLabel.text = strGrowth
climatLabel.text = strClimat
diseaseLabel.text = strDisease
insectsLabel.text = strInsects
leafColourLabel.text = strLeafColour
bloomsColourLabel.text = strBloomsColour
availabilityLabel.text = strAvailability
bearingLabel.text = strBearing
appealLabel.text = strAppeal
// 加载植物图像
if let imageURL = plants?.img {
plantImage.sd_setImage(with: URL(string: imageURL), completed: nil)
}
}
}
这是表视图的didSelectRowAt函数:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let detail: PlantDetailsViewController = self.storyboard?.instantiateViewController(withIdentifier: "showDetails") as! PlantDetailsViewController
detail.strCommonName = plants[indexPath.row].common_name?.first ?? "N/A"
detail.strLatinName = plants[indexPath.row].latin_name ?? "N/A"
detail.strOtherNames = plants[indexPath.row].other_names ?? "N/A"
detail.strCategory = plants[indexPath.row].categories ?? "N/A"
detail.strUse = plants[indexPath.row].use?.first ?? "N/A"
detail.strStyle = plants[indexPath.row].style ?? "N/A"
detail.strFamily = plants[indexPath.row].family ?? "N/A"
detail.strBloomSeason = plants[indexPath.row].blooming_season ?? "N/A"
detail.strWatering = plants[indexPath.row].watering ?? "N/A"
detail.strIdealLight = plants[indexPath.row].light_ideal ?? "N/A"
detail.strGrowth = plants[indexPath.row].growth ?? "N/A"
detail.strClimat = plants[indexPath.row].climat ?? "N/A"
detail.strDisease = plants[indexPath.row].disease ?? "N/A"
detail.strInsects = plants[indexPath.row].insects?.first ?? "N/A"
detail.strLeafColour = plants[indexPath.row].color_of_leaf?.first ?? "N/A"
detail.strBloomsColour = plants[indexPath.row].color_of_blooms ?? "N/A"
detail.strAvailability = plants[indexPath.row].availability ?? "N/A"
detail.strBearing = plants[indexPath.row].bearing ?? "N/A"
detail.strAppeal = plants[indexPath.row].appeal ?? "N/A"
// 传递图像链接给详情视图控制器
detail.plants = plants[indexPath.row]
self.navigationController?.pushViewController(detail, animated: true)
}
在Manager文件夹中,我创建了一个名为“APICaller”的类,用于从API获取数据。以下是执行此操作的函数:
func getAllPlants(completion: @escaping (Result<[Plant], Error>) -> Void) {
guard
<details>
<summary>英文:</summary>
I am a newbie in Swift and I am trying to build an app in which I retrieve plant images and information from this api "https://rapidapi.com/mnai01/api/house-plants2".
I managed to implement a table view in which I display the name and image of each plant in the api, and when I click on any cell in the table view I displayed that certain plant's information in a new view controller.
My problem is that no matter what I tried I couldn't also display the image of that plant in that view controller and I don't know what to do to make it work.
It is also worth to mention that the links for the images are of this format:
- img: "http://www.tropicopia.com/house-plant/thumbnails/5556.jpg"
This is the class of the view controller where the image and information should be displayed:
import UIKit
import SDWebImage
class PlantDetailsViewController: UIViewController {
// image view for the plant
@IBOutlet weak var plantImage: UIImageView!
// labels for the plant information
@IBOutlet weak var commonNameLabel: UILabel!
@IBOutlet weak var latinNameLabel: UILabel!
@IBOutlet weak var otherNamesLabel: UILabel!
@IBOutlet weak var categoryLabel: UILabel!
@IBOutlet weak var useLabel: UILabel!
@IBOutlet weak var styleLabel: UILabel!
@IBOutlet weak var familyLabel: UILabel!
@IBOutlet weak var bloomSeasonLabel: UILabel!
@IBOutlet weak var wateringLabel: UILabel!
@IBOutlet weak var idealLightLabel: UILabel!
@IBOutlet weak var growthLabel: UILabel!
@IBOutlet weak var climatLabel: UILabel!
@IBOutlet weak var diseaseLabel: UILabel!
@IBOutlet weak var insectsLabel: UILabel!
@IBOutlet weak var leafColourLabel: UILabel!
@IBOutlet weak var bloomsColourLabel: UILabel!
@IBOutlet weak var availabilityLabel: UILabel!
@IBOutlet weak var bearingLabel: UILabel!
@IBOutlet weak var appealLabel: UILabel!
var plants: Plant?
var strCommonName = ""
var strLatinName = ""
var strOtherNames = ""
var strCategory = ""
var strUse = ""
var strStyle = ""
var strFamily = ""
var strBloomSeason = ""
var strWatering = ""
var strIdealLight = ""
var strGrowth = ""
var strClimat = ""
var strDisease = ""
var strInsects = ""
var strLeafColour = ""
var strBloomsColour = ""
var strAvailability = ""
var strBearing = ""
var strAppeal = ""
override func viewDidLoad() {
super.viewDidLoad()
commonNameLabel.text = strCommonName
latinNameLabel.text = strLatinName
otherNamesLabel.text = strOtherNames
categoryLabel.text = strCategory
useLabel.text = strUse
styleLabel.text = strStyle
familyLabel.text = strFamily
bloomSeasonLabel.text = strBloomSeason
wateringLabel.text = strWatering
idealLightLabel.text = strIdealLight
growthLabel.text = strGrowth
climatLabel.text = strClimat
diseaseLabel.text = strDisease
insectsLabel.text = strInsects
leafColourLabel.text = strLeafColour
bloomsColourLabel.text = strBloomsColour
availabilityLabel.text = strAvailability
bearingLabel.text = strBearing
appealLabel.text = strAppeal
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
This is is the didSelectRowAt function for the table view:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let detail:PlantDetailsViewController = self.storyboard?.instantiateViewController(withIdentifier: "showDetails") as! PlantDetailsViewController
detail.strCommonName = plants[indexPath.row].common_name?.first ?? "N/A"
detail.strLatinName = plants[indexPath.row].latin_name ?? "N/A"
detail.strOtherNames = plants[indexPath.row].other_names ?? "N/A"
detail.strCategory = plants[indexPath.row].categories ?? "N/A"
detail.strUse = plants[indexPath.row].use?.first ?? "N/A"
detail.strStyle = plants[indexPath.row].style ?? "N/A"
detail.strFamily = plants[indexPath.row].family ?? "N/A"
detail.strBloomSeason = plants[indexPath.row].blooming_season ?? "N/A"
detail.strWatering = plants[indexPath.row].watering ?? "N/A"
detail.strIdealLight = plants[indexPath.row].light_ideal ?? "N/A"
detail.strGrowth = plants[indexPath.row].growth ?? "N/A"
detail.strClimat = plants[indexPath.row].climat ?? "N/A"
detail.strDisease = plants[indexPath.row].disease ?? "N/A"
detail.strInsects = plants[indexPath.row].insects?.first ?? "N/A"
detail.strLeafColour = plants[indexPath.row].color_of_leaf?.first ?? "N/A"
detail.strBloomsColour = plants[indexPath.row].color_of_blooms ?? "N/A"
detail.strAvailability = plants[indexPath.row].availability ?? "N/A"
detail.strBearing = plants[indexPath.row].bearing ?? "N/A"
detail.strAppeal = plants[indexPath.row].appeal ?? "N/A"
self.navigationController?.pushViewController(detail, animated: true)
}
In the Manager folder I created class called "APICaller" where I fetch the data from the API. This is the function that does that:
func getAllPlants (completion: @escaping (Result<[Plant], Error>) -> Void) {
guard let url = URL(string: "\(Constants.baseURL)/all/?rapidapi-key=\(Constants.API_KEY)") else {return}
let task = URLSession.shared.dataTask(with: URLRequest(url: url)) { data, _, error in
guard let data = data, error == nil else {return}
do {
let results = try JSONDecoder().decode([Plant].self, from: data)
completion(.success(results))
} catch {
completion(.failure(APIError.failedTogetData))
}
}
task.resume()
}
And finally this is the Plant struct model:
struct Plant: Codable {
let appeal: String?
let availability: String?
let bearing: String?
let blooming_season: String?
let categories: String?
let climat: String?
let color_of_blooms: String?
let color_of_leaf: [String]?
let common_name: [String]?
let disease: String?
let family: String?
let growth: String?
let insects: [String]?
let latin_name: String?
let light_ideal: String?
let other_names: String?
let style: String?
let use: [String]?
let watering: String?
let id: String?
let img: String?
let url: String?
private enum CodingKeys: String, CodingKey {
case appeal = "Appeal"
case availability = "Availability"
case bearing = "Bearing"
case blooming_season = "Blooming season"
case categories = "Categories"
case climat = "Climat"
case color_of_blooms = "Color of blooms"
case color_of_leaf = "Color of leaf"
case common_name = "Common name"
case disease = "Disease"
case family = "Family"
case growth = "Growth"
case insects = "Insects"
case latin_name = "Latin name"
case light_ideal = "Light ideal"
case other_names = "Other names"
case style = "Style"
case use = "Use"
case watering = "Watering"
case id = "id"
case img = "Img"
case url = "Url"
}
}
I think the problem is that each image is a string which contains a link, and to be able to display it in the table view cells I used SDWebImage. The question is how do I do that to display the image in the detail view controller? Thank you for your time. Any help or piece of advice is greatly appreciated :)
UPDATE- I tried to display it like this :
I wrote this in the viewdidload function in the detail view controller:
var selectedImage: String?
if let imageToLoad = selectedImage {
plantImage.image = UIImage(named: imageToLoad)
}
and then I added this line in the didselectrowat function:
detail.selectedImage = plants[indexPath.row].img
It still doesn't work and I don't know what I am doing wrong
</details>
# 答案1
**得分**: 0
# Swift 5.5, Xcode 14.2
`plantImage.image = UIImage(named: imageToLoad)` 是错误的,named 用于本地图片,当你想从一个 API 中获取图片,比如 "http://www.tropicopia.com/house-plant/thumbnails/5556.jpg" 时,你需要使用:
Github 示例: https://github.com/MaatheusGois/answer-75361391
```swift
let url = URL(string: image.url)
func downloadImage(from url: URL) {
print("Download Started")
getData(from: url) { data, response, error in
guard data != nil, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
// always update the UI from the main thread
DispatchQueue.main.async { [weak self] in
self?.plantImage.image = UIImage(data: data)
}
}
}
func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
重要(常见错误)
https://developer.apple.com/forums/thread/119977
英文:
Swift 5.5, Xcode 14.2
plantImage.image = UIImage(named: imageToLoad)
is wrong, named is to local images, when you want get images from one API, like "http://www.tropicopia.com/house-plant/thumbnails/5556.jpg", you need use :
Github Example: https://github.com/MaatheusGois/answer-75361391
let url = URL(string: image.url)
func downloadImage(from url: URL) {
print("Download Started")
getData(from: url) { data, response, error in
guard let data = data, error == nil else { return }
print(response?.suggestedFilename ?? url.lastPathComponent)
print("Download Finished")
// always update the UI from the main thread
DispatchQueue.main.async { [weak self] in
self?.plantImage.image = UIImage(data: data)
}
}
}
func getData(from url: URL, completion: @escaping (Data?, URLResponse?, Error?) -> Void) {
URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}
IMPORTANT (Common error)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论