如何在uitableview中的cellForRowAt函数中按标题日期对响应进行排序

时间:2018-07-26 13:12:47

标签: ios swift uitableview sorting uitableviewsectionheader

我目前收到来自json的json响应,该响应是[NSDictionary]。这显示在表格视图中,我能够将排序日期设置为标题,但是在cellForRowAt函数中设置uilabel时遇到了困难。我要显示的表视图具有已排序日期(我已经拥有)的标题标题,并且在此部分下的名称与标题具有相同的日期。我在下面提供了此代码。感谢您的帮助和建议。

import UIKit
import Alamofire

class JSONTableViewController: UITableViewController 

{

var responseValue:[NSDictionary] = []
var sortedResponsevalue:[NSDictionary] = []
var sectionHeaderArray:[String] = []
var rowTitle:[String] = []

override func viewDidLoad() {
    super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    for response in self.responseValue {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        let responseDate = response.object(forKey: "date") as! String
        let date = dateFormatter.date(from: responseDate)
        print(date!.toString(dateFormat: "MMM d, yyyy"))
        self.sectionHeaderArray.append(date!.toString(dateFormat: "MMM d, yyyy"))
        self.rowTitle.append(response.object(forKey: "name") as! String)
    }
    print(self.sectionHeaderArray.count)
}

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return self.sectionHeaderArray[section]
}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
    return self.sectionHeaderArray.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return self.sectionHeaderArray[section].count
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 80
}


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

    if let nameString = self.responseValue[indexPath.row].object(forKey: "name") as? String {
        cell.jsonLabel.text = nameString

    }


      return cell
    }
}

2 个答案:

答案 0 :(得分:0)

我从您的问题中了解到的是:您在cellForRow方法中获得了与“ nameString ”相同的标题。

问题是

if let nameString = self.responseValue[indexPath.row].object(forKey: "name") as? String {
        cell.jsonLabel.text = nameString
    }

您正在传递段数 self.sectionHeaderArray.count 。因为总部分数= 100,并且每个部分只有1行,所以标题将始终保持不变。

尝试:使用 indexPath.section 代替 indexPath.row 获得不同的标题

if let nameString = self.responseValue[indexPath.section].object(forKey: "name") as? String {
        cell.jsonLabel.text = nameString
    }

编辑

class JSONTableViewController: UITableViewController
{
    var responseValue:[NSDictionary] = []
    var sortedResponsevalue:[NSDictionary] = []
    var sectionHeaderArray = [[String: Any]]()

    override func viewDidLoad() {
        super.viewDidLoad()

    }

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

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        var currentDate: String? = nil
        var nameArray = [String]()
        for (index,response) in self.responseValue.enumerated() {
            let responseDate = response.object(forKey: "date") as! String
            let date = dateFormatter.date(from: responseDate)
            let dateString = date!.toString(dateFormat: "MMM d, yyyy")
            let nameString = response.object(forKey: "name") as! String
            if currentDate == nil {
                // FIRST TIME
                currentDate = dateString
                nameArray.append(nameString)

            } else {
                // CHECK IF DATES EQUAL, THEN KEEP ADDING
                if currentDate == dateString {
                    nameArray.append(nameString)
                    if index == self.responseValue.count - 1 {
                        let dictToAppend: [String : Any] = ["date": currentDate!, "names": nameArray]
                        self.sectionHeaderArray.append(dictToAppend)
                    }
                } else {
                    let dictToAppend: [String : Any] = ["date": currentDate!, "names": nameArray]
                    self.sectionHeaderArray.append(dictToAppend)
                    currentDate = dateString
                    nameArray.removeAll()
                    nameArray.append(nameString)
                }
            }
        }

    }

    override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
        let dictInfo = self.sectionHeaderArray[section]
        let dateString = dictInfo["date"]
        return dateString as? String
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return self.sectionHeaderArray.count
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        let dictInfo = self.sectionHeaderArray[section]
        let namesArray = dictInfo["names"] as! [String]

        return namesArray.count
    }

    override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }


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

        let dictInfo = self.sectionHeaderArray[indexPath.section]
        let namesArray = dictInfo["names"] as! [String]
        let nameString = namesArray[indexPath.row]
        cell.jsonLabel.text = nameString

        return cell
    }
}

尝试并分享结果。

答案 1 :(得分:0)

这是一种不同的方法,使用Decodable协议将JSON解码为结构,并使用优化的初始化程序Dictionary(grouping:by:)来按日期对项目进行分组。

创建一个结构(可以在视图控制器之外)

struct Response : Decodable {
    let id : Int
    let date : Date
    let name : String
}

在视图控制器内部,为标题创建一个dateformatter

let dateFormatter : DateFormatter = {
    let formatter = DateFormatter()
    formatter.locale = Locale(identifier: "en_US_POSIX")
    formatter.dateFormat = "MMM d, yyyy"
    return formatter
}()

和用于数据源的 native 词典(从不NSDictionary)和用于Date实例的节的数组。使用Date的好处是可以排序(字符串日期格式不能正确排序)

var sections = [Date]()
var dataSource = [Date:[Response]]()

假设dataviewDidLoad中的JSON数据,将data解码为该结构并填充数据源。方法Dictionary(grouping:by:)Response的数组分组为一个以日期为键的字典。

override func viewDidLoad() {
    super.viewDidLoad()

    // put here the code to retrieve the JSON data in the variable `data`
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd"
    let decoder = JSONDecoder()
    decoder.dateDecodingStrategy = .formatted(dateFormatter)
    do {
        let result = try decoder.decode([Response].self, from: data)
        dataSource = Dictionary(grouping: result, by: {$0.date})
        sections = dataSource.keys.sorted()
        self.tableView.reloadData()
    } catch {
        print(error)
    }
}

数据源和委托方法是

override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    return dateFormatter.string(from: sections[section])
}

// MARK: - Table view data source

override func numberOfSections(in tableView: UITableView) -> Int {
    // #warning Incomplete implementation, return the number of sections
   return sections.count
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let sectionDate = sections[section]
    return dataSource[sectionDate]!.count
}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    return 80
}


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

    let sectionDate = sections[indexPath.section]
    let item = dataSource[sectionDate]![indexPath.row]
    cell.jsonLabel.text = item.name

    return cell
}