将API图像从表视图传递到另一个视图控制器使用`didselectrowat`。

huangapple go评论52阅读模式
英文:

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 &quot;https://rapidapi.com/mnai01/api/house-plants2&quot;.

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&#39;s information in a new view controller.

My problem is that no matter what I tried I couldn&#39;t also display the image of that plant in that view controller and I don&#39;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: &quot;http://www.tropicopia.com/house-plant/thumbnails/5556.jpg&quot;

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 = &quot;&quot;
var strLatinName = &quot;&quot;
var strOtherNames = &quot;&quot;
var strCategory = &quot;&quot;
var strUse = &quot;&quot;
var strStyle = &quot;&quot;
var strFamily = &quot;&quot;
var strBloomSeason = &quot;&quot;
var strWatering = &quot;&quot;
var strIdealLight = &quot;&quot;
var strGrowth = &quot;&quot;
var strClimat = &quot;&quot;
var strDisease = &quot;&quot;
var strInsects = &quot;&quot;
var strLeafColour = &quot;&quot;
var strBloomsColour = &quot;&quot;
var strAvailability = &quot;&quot;
var strBearing = &quot;&quot;
var strAppeal = &quot;&quot;
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: &quot;showDetails&quot;) as! PlantDetailsViewController
detail.strCommonName = plants[indexPath.row].common_name?.first  ?? &quot;N/A&quot;
detail.strLatinName = plants[indexPath.row].latin_name ?? &quot;N/A&quot;
detail.strOtherNames = plants[indexPath.row].other_names ?? &quot;N/A&quot;
detail.strCategory = plants[indexPath.row].categories ?? &quot;N/A&quot;
detail.strUse = plants[indexPath.row].use?.first ?? &quot;N/A&quot;
detail.strStyle = plants[indexPath.row].style ?? &quot;N/A&quot;
detail.strFamily = plants[indexPath.row].family ?? &quot;N/A&quot;
detail.strBloomSeason = plants[indexPath.row].blooming_season ?? &quot;N/A&quot;
detail.strWatering = plants[indexPath.row].watering ?? &quot;N/A&quot;
detail.strIdealLight = plants[indexPath.row].light_ideal ?? &quot;N/A&quot;
detail.strGrowth = plants[indexPath.row].growth ?? &quot;N/A&quot;
detail.strClimat = plants[indexPath.row].climat ?? &quot;N/A&quot;
detail.strDisease = plants[indexPath.row].disease ?? &quot;N/A&quot;
detail.strInsects = plants[indexPath.row].insects?.first ?? &quot;N/A&quot;
detail.strLeafColour = plants[indexPath.row].color_of_leaf?.first ?? &quot;N/A&quot;
detail.strBloomsColour = plants[indexPath.row].color_of_blooms ?? &quot;N/A&quot;
detail.strAvailability = plants[indexPath.row].availability ?? &quot;N/A&quot;
detail.strBearing = plants[indexPath.row].bearing ?? &quot;N/A&quot;
detail.strAppeal = plants[indexPath.row].appeal ?? &quot;N/A&quot;
self.navigationController?.pushViewController(detail, animated: true)
}

In the Manager folder I created class called &quot;APICaller&quot; where I fetch the data from the API. This is the function that does that:
func getAllPlants (completion: @escaping (Result&lt;[Plant], Error&gt;) -&gt; Void) {
guard let url = URL(string: &quot;\(Constants.baseURL)/all/?rapidapi-key=\(Constants.API_KEY)&quot;) 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 = &quot;Appeal&quot;
case availability = &quot;Availability&quot;
case bearing = &quot;Bearing&quot;
case blooming_season = &quot;Blooming season&quot;
case categories = &quot;Categories&quot;
case climat = &quot;Climat&quot;
case color_of_blooms = &quot;Color of blooms&quot;
case color_of_leaf = &quot;Color of leaf&quot;
case common_name = &quot;Common name&quot;
case disease = &quot;Disease&quot;
case family = &quot;Family&quot;
case growth = &quot;Growth&quot;
case insects = &quot;Insects&quot;
case latin_name = &quot;Latin name&quot;
case light_ideal = &quot;Light ideal&quot;
case other_names = &quot;Other names&quot;
case style = &quot;Style&quot;
case use = &quot;Use&quot;
case watering = &quot;Watering&quot;
case id = &quot;id&quot;
case img = &quot;Img&quot;
case url = &quot;Url&quot;
}

}


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&#39;t work and I don&#39;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(&quot;Download Started&quot;)
    getData(from: url) { data, response, error in
        guard let data = data, error == nil else { return }
        print(response?.suggestedFilename ?? url.lastPathComponent)
        print(&quot;Download Finished&quot;)
        // 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?) -&gt; Void) {
    URLSession.shared.dataTask(with: url, completionHandler: completion).resume()
}

IMPORTANT (Common error)

https://developer.apple.com/forums/thread/119977

huangapple
  • 本文由 发表于 2023年2月6日 20:35:44
  • 转载请务必保留本文链接:https://go.coder-hub.com/75361391.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定