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

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

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:

确定