【问题标题】:Pass API data when tap on CollectionVC to TableVC点击 CollectionVC 时将 API 数据传递给 TableVC
【发布时间】:2021-02-13 02:13:23
【问题描述】:

我正在尝试将数据从新闻 Api 传递到 tableView,但我遇到了一个问题,当它传递给 SectorNewsVC 时,数据返回 nil,而当它到达 infoVC 时,它仍然是nil,但是当我在数据传递到那里之前打印数据时。有人可以解释我做错了什么,以及我该如何解决它?谢谢!!

这是我创建 URLSession 并获取数据的地方,并尝试将数据传递给 Viewcontroller,该 Viewcontroller 正在调用 fetchSectorNews() 以从 API 中检索数据。

struct FetchCategoryResponse {
    
    let sectorUrl = "https://stocknewsapi.com/api/v1/category?section=alltickers&items=50&type=article&token=\(Key.api_key)"
    
    func fetchSectorNews(sector: String) {
        let urlString = "\(sectorUrl)&sector=\(sector)"
        performRequest(urlString: urlString)
        print(urlString)
    }
    
    func performRequest(urlString: String) {
        // create url
        if let url = URL(string: urlString) {
            // create url session
            let session = URLSession(configuration: .default)
            // give session a task
            let task = session.dataTask(with: url) { (data, response, error) in
                if error != nil {
                    print(error!)
                    return
                }
                if let safeData = data {
                    if let news = self.parseJson(sectorData: safeData) {
                        DispatchQueue.main.async {
                            let vc = SectorNewsVC()
                            vc.dataToPass = news
                        }
                    }
                }
            }
            task.resume()
        }
    }
    
    // parse the jason data
    func parseJson(sectorData: Data) -> SectorModel? {
        let decoder = JSONDecoder()
        
        do {
            let decodedData = try decoder.decode(CatergoryData.self, from: sectorData)
            
            let newsUrl = decodedData.data[1].title
            let imageUrl = decodedData.data[1].news_url
            let title = decodedData.data[1].title
            let source = decodedData.data[1].source_name
            
            
            let sectorPayload = SectorModel(url: newsUrl, image: imageUrl, title: title, source: source)
            
            // this sectorpayload gets saved to the news var in the performrequest() bc its being return
            return sectorPayload
        }
        catch {
            print(error)
            return nil
        }
    }
} // END Struct

所以在这个 ViewController 中,我正在设置 collectionViewController 并调用 fetchSectorNews() 并将标签的标题作为函数的参数传递,同时尝试将数据传递给 detialViewController

var titleArr = ["Technology", "Materials", "HealthCare"]
    var dataToPass: SectorModel?
    var fetchNews = FetchCategoryResponse()

extension SectorNewsVC: UICollectionViewDelegate, UICollectionViewDataSource {
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return titleArr.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath) as! SectorCollectionCell
        
        cell.listLabel.text = titleArr[indexPath.row]
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        let curentIndex = indexPath.item
        
        if curentIndex == 0 {
            fetchNews.fetchSectorNews(sector: "technology")
        }
        else if curentIndex == 1 {
            fetchNews.fetchSectorNews(sector: "materials")
        }
        else if curentIndex == 2 {
            fetchNews.fetchSectorNews(sector: "healthcare")
        }
        performSegue(withIdentifier: "segue", sender: nil)
    } // end cv()
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "segue" {
            if let indexPath = self.collectionView.indexPathsForSelectedItems {
                let detailVC = segue.destination as! infoVC
                detailVC.newData = dataToPass
                print(indexPath)
            }
        }
    }
}
Here is where I want to display the data
class infoVC: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!
    
    var newData: SectorModel?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.delegate = self
        tableView.dataSource = self
        tableView.separatorStyle = .none
        tableView.showsVerticalScrollIndicator = false
        tableView.backgroundColor = #colorLiteral(red: 0.1926331222, green: 0.2233074605, blue: 0.3540094197, alpha: 1)
        tableView.register(UINib(nibName: "DifferentSectorCell", bundle: nil), forCellReuseIdentifier: "cellId")
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 100
    }
    
    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
        cell.backgroundColor = UIColor.clear
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 5
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("tap")
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! DifferentSectorCell
        
        
        cell.titleLabel.text = "hey"
        cell.sourceLabel.text = "hello"
        return cell
    }

}

【问题讨论】:

    标签: ios swift


    【解决方案1】:

    我会建议一种不同的方法。将部分发送到子控制器,并对子控制器执行请求。这是以前对我有用的方法

    在父控制器上:

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        
        let curentIndex = indexPath.item
        var sector = ""
        if curentIndex == 0 {
            sector = "technology"
        }
        else if curentIndex == 1 {
            sector =  "materials"
        }
        else if curentIndex == 2 {
            sector = "healthcare"
        }
        performSegue(withIdentifier: "segue", sender: sector)
    } 
    
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "segue" {
                let detailVC = segue.destination as! infoVC
                detailVC.sector = sender as! String
            }
        }
    }
    

    在子控制器上:

    var sector = ""
    
    override func viewWillAppear() {
        super.viewWillAppear()
        fetchNews.fetchSectorNews(sector: self.sector)
    }
    

    【讨论】:

    • 有趣的解决方案。那么如何获取数据并更新 TableView?
    • 从 performRequest 获取 JSON 后,将其分配给 rowAtIndexPath 和 tableView.reload() 中使用的局部变量
    • 谢谢,感谢您的帮助。我明白了。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-01-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-25
    • 2019-05-25
    • 1970-01-01
    相关资源
    最近更新 更多