如何使用 URL 参数和 UITableview 执行干净的 JSON 解码

Posted

技术标签:

【中文标题】如何使用 URL 参数和 UITableview 执行干净的 JSON 解码【英文标题】:How do I perform a clean JSON decoding with URL parameters and UITableview 【发布时间】:2018-06-12 18:08:12 【问题描述】:

我正在尝试创建一个根据 URL 末尾的 ID 解析我的 JSON 的函数。例如:(https://alodjinha.herokuapp.com/produto?categoriaId=1)。在这种情况下,“categoriaId=1”将返回一个“游戏”类别,作为一个填充了游戏的 JSON。它应该根据用户在我的 UICollectionView 类别上单击的每个类别而变化。因此,如果用户在我的 UICollectionView 上单击“电影”,我必须将 url 更改为 id 2(例如)https://alodjinha.herokuapp.com/produto?categoriaId=2,然后我将得到充满电影的 JSON 等等。但是,我做错了什么不起作用?

这就是我尝试获取类别 ID 的方式:

func getCategoriaPorID(IdCategoria:Int, completion:@escaping ([CategoriaIDItems])->Void) 

    let url = URL(string: "https://alodjinha.herokuapp.com/produto?categoriaId=\(IdCategoria)")

    let session = URLSession.shared

    let request = URLRequest(url: url!)

    let dataTask = session.dataTask(with: request)  (data, response, error) in

        guard let unwrappedData = data else  print("Error data"); return

        do 

            let jsonTop10 = try JSONDecoder().decode(CategoriaIDItemsData.self, from: unwrappedData)

            completion(jsonTop10.data)



        catch
            print("Could no get API data")
        
    
    dataTask.resume()


型号:

import Foundation

//Categorias
struct Contents : Decodable 
    let data : [Content]

struct Content : Decodable 
    let id : Int
    let descricao : String
    let urlImagem : String

//Banner
struct BannerData : Decodable 
    let data : [Banner]

struct Banner : Decodable 
    let id : Int
    let urlImagem : String
    let linkUrl : String

//Top10
struct Top10Data:Decodable 
    let data: [Top10]

struct Top10:Decodable 
    let id : Int
    let nome : String
    let urlImagem : String
    let descricao : String
    let precoDe : Int

struct CategoriaIDItemsData:Decodable 
    let data : [CategoriaIDItems]

struct CategoriaIDItems:Decodable 
    let id : Int
    let nome : String
    let urlImagem : String
    let descricao : String
    let precoDe : Int

好吧,之后我进入主文件(ViewController),其中包含我的所有表格,例如 UITableView 和 UICollectionview(所有类别都位于其中)。

    import UIKit

    class ViewController: UIViewController, UICollectionViewDataSource, UITableViewDataSource, UITableViewDelegate, UICollectionViewDelegate 

        @IBOutlet weak var tableViewTopSell: UITableView!
        @IBOutlet var collectionView: UICollectionView!
        @IBOutlet weak var collectionViewBanner: UICollectionView!

        var dataSource: [Content] = [Content]()
        var dataBanner: [Banner] = [Banner]()
        var dataTopSold: [Top10] = [Top10]()
        var dataCategoriaID: [CategoriaIDItems] = [CategoriaIDItems]()

        override func viewDidLoad() 
            super.viewDidLoad()
            //Delegate TableView
            self.tableViewTopSell.delegate = self
            //SetupNavBarCustom
            self.navigationController?.navigationBar.CustomNavigationBar()
            let logo = UIImage(named: "tag.png")
            let imageView = UIImageView(image:logo)
            self.navigationItem.titleView = imageView
            //CallAPIData
            getTopSold  (data) in
                DispatchQueue.main.async 
                    self.dataTopSold = data
                    self.tableViewTopSell.reloadData()
                
            
            getBanner  (data) in
                DispatchQueue.main.async 
                self.dataBanner = data
                self.collectionViewBanner.reloadData()
                
            
            getAudiobooksAPI  (data) in
                DispatchQueue.main.async 
                    self.dataSource = data
                    self.collectionView.reloadData()
                
            
        
        //CollectionView
        func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
            if (collectionView == self.collectionView) 
                return  self.dataSource.count
            else
                return self.dataBanner.count
            
        func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

            if (collectionView == self.collectionView) 
            let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCell", for: indexPath) as! CollectionViewCell

            let content = self.dataSource[indexPath.item]

            cell.bookLabel.text = content.descricao
            cell.bookImage.setImage(url: content.urlImagem, placeholder: "")

            return cell

            else if (collectionView == self.collectionViewBanner) 

                let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionViewCellBanner", for: indexPath) as! CollectionViewCell

                let content = self.dataBanner[indexPath.item]

                cell.bannerImage.setImage(url: content.urlImagem, placeholder: "")


                return cell
            
            return UICollectionViewCell()
        

        func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) 
    var indexPathId: Int 
    if (collectionView == self.collectionView) 
        let content = self.dataSource[indexPath.item]
        indexPathId = content.id
    else if (collectionView == self.collectionViewBanner) 
        let content = self.dataBanner[indexPath.item]
        indexPathId = content.id
    

    getCategoriaPorID(IdCategoria: indexPathId)  (data) in
            self.dataCategoriaID = data
            self.performSegue(withIdentifier: "segueCategorias", sender:self.dataCategoriaID)

            print(self.dataCategoriaID)
    




    //TableView
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return self.dataTopSold.count
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "topSoldCell", for: indexPath) as! TableViewCell

        let content = self.dataTopSold[indexPath.row]
        cell.labelNomeTopSell.text = content.nome
        cell.imageViewTopSell.setImage(url: content.urlImagem, placeholder: "")
        cell.labelPrecoDe.text = "R$ \(content.precoDe)"
        //Colocar strike em cima do Preco Antigo
        let oldPrice = "R$ \(content.precoDe)"
        let promotionString = oldPrice + ""
        let attributedStr = NSMutableAttributedString(string: promotionString)
        let crossAttr = [NSAttributedStringKey.strikethroughStyle: NSUnderlineStyle.styleSingle.rawValue]
        attributedStr.addAttributes(crossAttr, range: NSMakeRange(0, oldPrice.count))
        cell.labelPrecoDe.attributedText = attributedStr
        //
        cell.labelPrecoPor.text = "R$ 119.99"
        return cell
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 

        performSegue(withIdentifier: "segueId", sender:self.dataTopSold[indexPath.row])

        
        override func prepare(for segue: UIStoryboardSegue, sender: Any?) 

            if segue.identifier == "segueId" 

                let des = segue.destination as? TelaDetalheProdutos

                //.item possui uma propriedade instanciada na TelaDetalheProdutos
                des?.item = (sender as? Top10)
                //Segue para CollectionView Categorias
             else if segue.identifier == "segueCategorias" 

                let desc = segue.destination as? TelaCategorias

                desc?.item = (sender as? CategoriaIDItems)
            
        

    
    //Cast UIImage Extension
    extension UIImageView
        func setImage(url : String, placeholder: String, callback : (() -> Void)? = nil)
            self.image = UIImage(named: "no-photo")

            URLSession.shared.dataTask(with: NSURL(string: url)! as URL, completionHandler:  (data, response, error) -> Void in

                guard error == nil else
                    return
                
                DispatchQueue.main.async(execute:  () -> Void in
                    let image = UIImage(data: data!)
                    self.image = image

                    if let callback = callback
                        callback()
                    
                )

            ).resume()
        
    

将接收数据的屏幕:

import UIKit

class TelaCategorias: UIViewController, UITableViewDataSource, UITableViewDelegate 



    //Class Instanciated
    var item:CategoriaIDItems?
    var nome = String()
    override func viewDidLoad() 
        super.viewDidLoad()

        ????

    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return ???
    

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "tableIDCategorias", for: indexPath) as! TelaCategoriasCell

        ????

        return cell
    

应用图片:

Main Screen

【问题讨论】:

【参考方案1】:

问题成功解决。

已修复

【讨论】:

以上是关于如何使用 URL 参数和 UITableview 执行干净的 JSON 解码的主要内容,如果未能解决你的问题,请参考以下文章

UITableView 拉取每个用户的特定请求

如何修复 JSON 不填充我的 UITableView?

缓存 URL 图片 iphone UITableview

如何从 PrepareForReuse 的 UITableView 自定义行中删除视图?

在 URL 中传递参数以在 IOS 中返回 json

如何根据点击的 UITableView 行更改方法的参数?