我有一个CSV文件,我想将其导入到tableview中,它看起来如下。
我希望Headers Headlight Wiper Bumper 和剧透 作为Section的文本和每个部分下面列出的每列的值。
所以TableView看起来应该是这样的:
大灯
123个
10
雨刷
456个
11
保险杠
789个
12
spiler
999个
888
到目前为止,我的CSV导入程序返回一个String [[String]]
数组的数组我的代码如下:
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
@IBOutlet weak var tableView: UITableView!
@IBAction func buttonPressed(_ sender: Any) {
print(bins)
}
var bins = [[String]]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.delegate = self
tableView.dataSource = self
importCsv()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: -Table View Delegate & DataSource
func numberOfSections(in tableView: UITableView) -> Int {
return self.bins.count > 0 ? self.bins[0].count : 0
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.bins.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "BinCell")!
let bin = self.bins[indexPath.row]
cell.textLabel?.text = bin[0]
return cell
}
func importCsv() -> Void {
let path = "/Users/philipchan/Downloads/test.csv"
let defaultImporter = CSVImporter<[String]>(path: path)
defaultImporter.startImportingRecords{ $0 }.onFinish { importedRecords in
self.bins = importedRecords
print(self.bins)
self.tableView.reloadData()
}
}
}
这是我打印到输出结果时得到的2d数组。
[["Headlight", "Wiper", "Bumper", "spoiler"], ["123", "456", "789", "999"], ["10", "11", "12", "888"]]
在表格视图中渲染此2D数组的正确方法是什么?
答案 0 :(得分:1)
表格视图不显示2D数据。它们显示一维列表,可能会也可能不会划分为多个部分。
如果是我,我只需要显示4列数据,我可能会创建单元格,其中每个单元格中有4个标签,以及显示列标题的标题,就像表格一样显示在帖子的开头。这似乎是显示数据的最清晰方式。
无论如何,关于你的问题:
您的数据是一种棘手的格式。
它按行排列,然后按行排列在每行的数组中。为了让事情更加令人困惑,您的章节标题位于阵列的第一个位置。
通常,您希望外部数组的数据是部分,然后是内部数组,其中包含给定部分中每行的数据。这样你就可以让每个部分的行数不同。
你应该&#34;剥离&#34;部分标题,然后使用数组的其余部分提供表格视图的数据源方法。像这样:
var sectionTitles: [String]!
var tableData: [[String]]!
/**
This is the input data for our table view. The section titles are in the first array.
Use a DidSet method so that if the input "bins" variable changes, we format the data
And reload the table
*/
var bins: [[String]]? {
//If the bins array changed, parse it's data.
didSet {
if let bins = bins {
//Peel off the section titles into a separate array
sectionTitles = bins[0]
//Remove the section titles from the tableData array
tableData = Array(bins.dropFirst(1))
//Tell the table view to reload itself.
tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
bins = [
["Headlight", "Wiper", "Bumper", "Spoiler"],
["123", "456", "789", "999"],
["10", "11", "12", "888"]
]
}
override func numberOfSections(in tableView: UITableView) -> Int {
return sectionTitles?.count ?? 0
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let row = indexPath.row
let section = indexPath.section
cell?.textLabel?.text = tableData[row][section]
return cell!
}
override func tableView(_ tableView: UITableView,
titleForHeaderInSection section: Int) -> String {
return sectionTitles[section]
}
上面的代码可以工作,但按行存储数据,每行存储的数据都是错误的。表视图设计为具有任意数量的节,然后每个节在该节中可以具有不同的行数。当您将数据存储为每行中的行和节数据数组时,您无法执行此操作。您可以改为在每行中有一定数量的行,然后是可变数量的部分,这是 NOT 表视图的工作方式。
鉴于您正在从CSV文件中读取数据,您可能对输入格式没有太多选择,但您可以将其重组为按部分组织,然后按每个部分中的行进行组织。以下是上述的等效代码,但以更有意义的方式重构数据:
var sectionTitles: [String]!
var tableData: [[String]]!
/**
This is the input data for our table view. The section titles are in the first array.
Use a DidSet method so that if the input "bins" variable changes, we format the data
And reload the table
*/
var bins: [[String]]? {
//If the bins array changed, parse it's data.
didSet {
if let bins = bins {
//Peel off the section titles into a separate array
sectionTitles = bins[0]
//Remove the section titles from the tableData array
let inputData = Array(bins.dropFirst(1))
//The code below restructures the arrays to be "section major". It assumes the arrays are not
//"jagged" and will crash if they ARE jagged.
//Create a new array of arrays for the output
var output = [[String]]()
let rows = inputData.count
let sections = inputData.first?.count ?? 0
for section in 0..<sections {
//Create an array for this section
var aSection = [String]()
for row in 0..<rows {
//populate this section with an entry from each row
aSection.append(inputData[row][section])
}
//Add the finished section to the output array
output.append(aSection)
}
tableData = output
//Tell the table view to reload itself.
tableView.reloadData()
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
bins = [
["Headlight", "Wiper", "Bumper", "Spoiler"],
["123", "456", "789", "999"],
["10", "11", "12", "888"]
]
}
override func numberOfSections(in tableView: UITableView) -> Int {
return sectionTitles?.count ?? 0
}
override func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int {
guard tableData.count > section else {
return 0
}
return tableData[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")
let row = indexPath.row
let section = indexPath.section
cell?.textLabel?.text = tableData[section][row]
return cell!
}
override func tableView(_ tableView: UITableView,
titleForHeaderInSection section: Int) -> String {
return sectionTitles[section]
}