Swift:如何在 TableView 内的 CollectionView 中显示解析的 JSON 数据?

Posted

技术标签:

【中文标题】Swift:如何在 TableView 内的 CollectionView 中显示解析的 JSON 数据?【英文标题】:Swift: How to Display Parsed JSON Data in CollectionView inside a TableView? 【发布时间】:2016-11-02 11:39:59 【问题描述】:

我正在尝试将我的数据显示为 image.

我的问题是表格视图行中显示的数据都是一样的,而它应该显示数组的所有数据。

这是我用来在tableView中显示collectionView的代码:

var onlineNews = ["local", "Economy", "Variety", "international", "sport"]

var storedOffsets = [Int: CGFloat]()

var tableIndexPath: IndexPath!

@IBOutlet var listTableView: UITableView!

var tableIndex: Int = 0

var categoryResults = [JSON]() 
    didSet 
        listTableView.reloadData()
    


let requestManager = RequestManager()


override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)

    for i in onlineNews 
        requestManager.categoryList(sectionName: i)
    



func numberOfSections(in tableView: UITableView) -> Int 
    return 1


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return onlineNews.count


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

    tableIndex = indexPath.row

    return cell


func tableView(_ tableView: UITableView,
               willDisplay cell: UITableViewCell,
               forRowAt indexPath: IndexPath) 
        guard let tableViewCell = cell as? NewsTableViewCell else  return 

        tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: (indexPath as NSIndexPath).row)
        tableViewCell.collectionViewOffset = storedOffsets[(indexPath as NSIndexPath).row] ?? 0


func tableView(_ tableView: UITableView,
               didEndDisplaying cell: UITableViewCell,
               forRowAt indexPath: IndexPath) 

        guard let tableViewCell = cell as? NewsTableViewCell else  return 

        storedOffsets[(indexPath as NSIndexPath).row] = tableViewCell.collectionViewOffset


func numberOfSections(in collectionView: UICollectionView) -> Int 
    return 1


func collectionView(_ collectionView: UICollectionView,
                    numberOfItemsInSection section: Int) -> Int 

    return categoryResults.count


func collectionView(_ collectionView: UICollectionView,
                    cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

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


  cell.contentType.text = categoryResults[indexPath.row]["ContentType"].stringValue **// This is where I get the same values for all table view rows**
    cell.sectionName.text = onlineNews[tableIndex]


    return cell

我确信有人绝对可以帮助我解决这个问题,因为我知道只需稍作调整即可使其发挥作用,但不确定在哪里。

更新:

我遵循了一种我认为应该可行的方法,即将 JSON 数组声明为这样的 [[JSON]],然后使用 categoryResults[collection.tag][indexPath.item]["ContentType"] .stringValue 以获取该值。但是,它给了我“索引超出范围”的消息。你知道我该如何解决这个问题吗?

var onlineNews = ["local", "Economy", "Variety", "international", "sport"]

var storedOffsets = [Int: CGFloat]()

@IBOutlet var listTableView: UITableView!

var tableIndex: Int = 0

var categoryResults = [[JSON]]()  // updated
    didSet 
        listTableView.reloadData()
    


let requestManager = RequestManager()

override func viewDidLoad() 
    super.viewDidLoad()

    requestManager.resetCategory()

    updateSearchResults()

    NotificationCenter.default.addObserver(self, selector: #selector(ViewController.updateSearchResults), name: NSNotification.Name(rawValue: "categoryResultsUpdated"), object: nil)




override func viewWillAppear(_ animated: Bool) 
    super.viewWillAppear(animated)

    for i in 0..<onlineNews.count 
        requestManager.categoryList(sectionName: onlineNews[i])


    



func updateSearchResults() 
    categoryResults = [requestManager.categoryResults] // updated


func numberOfSections(in tableView: UITableView) -> Int 
    return 1


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return onlineNews.count


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

    tableIndex = indexPath.row

    return cell


func tableView(_ tableView: UITableView,
               willDisplay cell: UITableViewCell,
               forRowAt indexPath: IndexPath) 
        guard let tableViewCell = cell as? NewsTableViewCell else  return 

        tableViewCell.setCollectionViewDataSourceDelegate(dataSourceDelegate: self, forRow: (indexPath as NSIndexPath).row)
        tableViewCell.collectionViewOffset = storedOffsets[(indexPath as NSIndexPath).row] ?? 0



func tableView(_ tableView: UITableView,
               didEndDisplaying cell: UITableViewCell,
               forRowAt indexPath: IndexPath) 

        guard let tableViewCell = cell as? NewsTableViewCell else  return 

        storedOffsets[(indexPath as NSIndexPath).row] = tableViewCell.collectionViewOffset




func numberOfSections(in collectionView: UICollectionView) -> Int 
    return 1



func collectionView(_ collectionView: UICollectionView,
                    numberOfItemsInSection section: Int) -> Int 
    return categoryResults[collectionView.tag].count // updated



func collectionView(_ collectionView: UICollectionView,
                    cellForItemAt indexPath: IndexPath) -> UICollectionViewCell 

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


    cell.contentType.text = categoryResults[collectionView.tag][indexPath.row]["ContentType"].stringValue // updated



    return cell

这是 RequestManager 类的内容(我在这里调用 API):

var categoryResults = [JSON]()

func categoryList(sectionName: String) 

    let url = "http://mobile.example.com/api/Content?MobileRequest=GetCategoryNews&PageNo=1&RowsPerPage=10&Category=\(sectionName)&IssueID=0&Type=online"
    print("this is the url \(url)")

    Alamofire.request(url, method: .get).responseJSON response in
        if let results = response.result.value as? [String:AnyObject] 
            let items = JSON(results["Data"]?["OnlineCategoryNews"]! as Any).arrayValue

            self.categoryResults += items

            NotificationCenter.default.post(name: NSNotification.Name(rawValue: "categoryResultsUpdated"), object: nil)

        

    



func resetCategory() 
    categoryResults = []


deinit 
    NotificationCenter.default.removeObserver(self)

更新 2:

这是分配collectionView.tag的方法。这被添加到 tableViewCell 类中:

func setCollectionViewDataSourceDelegate
    <D: protocol<UICollectionViewDataSource, UICollectionViewDelegate>>
    (dataSourceDelegate: D, forRow row: Int) 

    collectionView.delegate = dataSourceDelegate
    collectionView.dataSource = dataSourceDelegate
    collectionView.tag = row
    collectionView.bounds.size.width = self.bounds.size.width
    collectionView.reloadData()




【问题讨论】:

【参考方案1】:

集合视图委托方法不知道其集合视图的上下文。您应该根据 collectionView 实例计算 onlineNews 索引,而不是使用 indexPath.row,它是内部集合视图索引路径。

编辑:更好的选择(避免滚动和布局问题)是使用单个集合视图,其中单元格按行分组。如果你不想做布局管理器,你可以通过在部分之间添加小但非常宽的分隔视图来实现这样的布局

编辑2:

cell.contentType.text = categoryResults[indexPath.row]["ContentType"].stringValue

使用此集合视图的本地 indexPath。您可以将标签分配给tableViewCell.collectionView,其值为所需的 categoryResults 索引。然后你可以像categoryResults[collectionView.tag]一样使用这个标签

【讨论】:

感谢您的回复。您能否解释一下如何以及在何处使用该索引来显示结果?我尝试了不同的方法,例如使用 collectionView.tag 而不是 indexPath.row,但它不起作用,但不确定如何分配索引来显示 JSON 结果。我需要一些进一步的解释。 我的意思是我需要解释如何计算索引,如您所说,以帮助获得 JSON 结果。 更新了我的答案 我已经对我的代码进行了更改,但出现了索引超出范围错误。请帮我解决这个问题。我已经通过添加 cmets 指出了我在哪里进行了更改。 非常感谢您的帮助,它现在运行良好!我发现我发现的最后一个问题是因为 JSON URL 中缺少数据,这与我的代码无关。再次感谢您的大力帮助!

以上是关于Swift:如何在 TableView 内的 CollectionView 中显示解析的 JSON 数据?的主要内容,如果未能解决你的问题,请参考以下文章

IOS swift如何在tableView单元格内创建一条小水平线

如何使我在 UIAlertController 内的 UITextField 中输入的数据通过 Swift 中的重置持续存在?

Swift - tableView中的可移动行仅在一个部分内,而不是在一个部分之间

如何在 swift 中在动态 TableView 中创建动态 tableView?

如何将按钮中的 panGesture 传递给 tableView? (斯威夫特 4)

如何在 Swift 中本地化 tableView 单元格?