根据JSON中的枚举显示表视图部分中的行数



我有一个从JSON文件中检索数据的表视图。我的目标是在我的表格视图中创建四个部分["课程"、"指南"、"文章"、"采访"]。如果一个对象具有一个称为"的类型;课程";然后我希望该对象显示在课程部分,依此类推

到目前为止,我有四个部分和准备显示的数据,但我不知道如何计算每个类型对象的对象数量,并将它们添加到部分函数中的行数中。

我的json文件如下:

{
"resources": [
{
"title": "Cooking with Me",
"url": "https://google.com",
"type": "course",
"date": "2020",
"author": "Chef A"
},
{
"title": "Daily Cooking",
"url": "https://google.com",
"type": "guide",
"date": "2020",
"author": "Chef B"
},
{
"title": "Simple Recipes",
"url": "https://google.com",
"type": "guide",
"date": "2020",
"author": "Chef C"
}
]
}  

//型号

struct Resources: Codable {
let resources: [Resource]
}
// MARK: - Resource
struct Resource: Codable {
let title: String
let url: String
let type: TypeEnum
let date, author: String
}
enum TypeEnum: String, Codable {
case article = "article"
case course = "course"
case guide = "guide"
case interview = "interview"
}

//查看控制器

class ResourcesController: UIViewController, UITableViewDelegate, UITableViewDataSource {
//MARK: - Properties
var items = [Resource]()
//MARK: - IBOutlets
@IBOutlet weak var resourceTable: UITableView!
// MARK: - View Life Cycle
override func viewDidLoad() {
super.viewDidLoad()
retrieveDate()

}
//MARK: - Methods
func retrieveDate() {
do {
let data = try Data(contentsOf: Bundle.main.url(forResource: "freeResources", withExtension: "json")!)
let decoded = try JSONDecoder().decode(Resources.self, from: data)
items = decoded.resources
resourceTable.reloadData()
} catch { print(error) }
}
//MARK: - Tableview Data Source
func numberOfSections(in tableView: UITableView) -> Int {
return 4
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if section == 0 {

return "Courses"
} else if section == 1 {
return "Guides"
} else if section == 2 {
return "Articles"
} else {
return "Interview"
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "sourceCell", for: indexPath) as! SourceCell

cell.authorLabel.text = items[indexPath.row].author
cell.titleLabel.text = items[indexPath.row].title
return cell 
}

如果您的枚举TypeEnum中的项与您想要的节的顺序相同(看起来已经有了(,那么您可以使枚举符合CaseIterable,这意味着您可以获得所有项的数组并使用它。

enum TypeEnum: String, Codable, CaseIterable {
case article = "article"
case course = "course"
case guide = "guide"
case interview = "interview"
}

现在你可以在一行中获得计数

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.filter { $0.type == TypeEnum.allCases[section]}.count
}

当创建细胞时

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "sourceCell", for: indexPath) as! SourceCell
let type = TypeEnum.allCases[indexPath.section]
let item = items.filter { $0.type == type }[indexPath.row]
cell.authorLabel.text = item.author
cell.titleLabel.text = item.title
return cell 
}

您也可以更改区段计数功能,以获得更多的未来验证代码

func numberOfSections(in tableView: UITableView) -> Int {
return TypeEnum.allCases.count
}

一种有效的方法是为部分创建另一个结构

struct Section {
let name : String
let items : [Resource]
}

以及适当的数据源阵列

var sections = [Section]()

retrieveDate中,用type将具有Dictionary(grouping:by:)的阵列分组,并将其映射到具有Section的阵列

func retrieveDate() {
do { 
let data = try Data(contentsOf: Bundle.main.url(forResource: "freeResources", withExtension: "json")!)
let decoded = try JSONDecoder().decode(Resources.self, from: data)
let grouped = Dictionary(grouping: decoded.resources, by: {$0.type})
sections = grouped.map({ (key, value) -> Section in
return Section(name: key.rawValue.capitalized + "s", items: value)
})
resourceTable.reloadData()
} catch { print(error) }
}

并将表视图数据源方法更改为

//MARK: - Tableview Data Source
func numberOfSections(in tableView: UITableView) -> Int {
return sections.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sections[section].name
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sections[section].items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "sourceCell", for: indexPath) as! SourceCell
let item = sections[indexPath.section].items[indexPath.row]
cell.authorLabel.text = item.author
cell.titleLabel.text = item.title
return cell 
}

注意:type作为enum实际上对于解析JSON没有任何意义,如果JSON文件在捆绑包中,我建议重构结构以对文件中已经存在的数据进行分组,例如

[{"name":"Guides",
"items": [
{"title": "Daily Cooking", "url": "https://google.com", "date": "2020", "author": "Chef B"},
{"title": "Simple Recipes", "url": "https://google.com", "date": "2020", "author": "Chef C"}
]},
{"name":"Courses",
"items": [
{"title": "Cooking with Me", "url": "https://google.com", "date": "2020", "author": "Chef A"}
]}
]
// MARK: - Resource
struct Resource: Codable {
let title: String
let url: String
let date, author: String
}
struct Section : Decodable {
let name : String
let items : [Resource]
}
...
sections = try JSONDecoder().decode([Section].self, from: data)

如果您想将它们分开,那么您需要为每种类型创建一个数组。

var article = [Resource]()
var course = [Resource]()
var guide = [Resource]()
var interview = [Resource]()

然后返回每个部分的计数:

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch section {
case 0:
return article.count
case 1:
return guide.count
case 2:
return interview.count
case 3:
}

最新更新