如何在 uitableview 的 cellForRowAt 函数中按 header 日期对响应进行排序
How to sort response by header date in cellForRowAt function in uitableview
我目前收到来自 json 的 json 回复,这是一个 [NSDictionary]。这显示在表格视图中,我能够将排序的日期设置为 headers 但是我在 cellForRowAt 函数中设置 uilabel 时遇到了困难。我要显示的表格视图有一个 header 排序日期的标题(我已经有了),并且在该部分下面是与 header 具有相同日期的名称。我在下面提供了代码。感谢您的帮助和建议。
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
}
}
我从你的问题中了解到:你在 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
}
}
尝试并分享结果。
这是一种不同的方法,它使用 Decodable
协议将 JSON 解码为结构,并使用优化的初始化程序 Dictionary(grouping:by:)
按日期对项目进行分组。
创建一个结构(可以在视图控制器之外)
struct Response : Decodable {
let id : Int
let date : Date
let name : String
}
在视图控制器中为 header 标题创建一个日期格式化程序
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]]()
假设 data
是 viewDidLoad
中的 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: {[=13=].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
}
我目前收到来自 json 的 json 回复,这是一个 [NSDictionary]。这显示在表格视图中,我能够将排序的日期设置为 headers 但是我在 cellForRowAt 函数中设置 uilabel 时遇到了困难。我要显示的表格视图有一个 header 排序日期的标题(我已经有了),并且在该部分下面是与 header 具有相同日期的名称。我在下面提供了代码。感谢您的帮助和建议。
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
}
}
我从你的问题中了解到:你在 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
}
}
尝试并分享结果。
这是一种不同的方法,它使用 Decodable
协议将 JSON 解码为结构,并使用优化的初始化程序 Dictionary(grouping:by:)
按日期对项目进行分组。
创建一个结构(可以在视图控制器之外)
struct Response : Decodable {
let id : Int
let date : Date
let name : String
}
在视图控制器中为 header 标题创建一个日期格式化程序
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]]()
假设 data
是 viewDidLoad
中的 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: {[=13=].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
}