我想显示2种类型的cell.Both类型的单元格是来自2个不同API调用的显示数据。所以结构基本上是这样的:
类型A 仅出现1次,来自 API方法A ,这是TableView
的第一个单元格,其余的都是< strong> B类,来自 API方法B 。
为了实现这一点,我做了以下工作:
1)在StoryBoard中,我设置了TableView
的结构,如下所示:
MyTableView
-Type A Cell
--My others view..
-Type B Cell
--My others view..
2)两个Cell都有TableViewCell
类。
3)两个Cell都有自己的模型类来初始化来自API的JSON
最后在我的ViewController中拥有所有这些代码:
All the basic code here
//The NSObject class for both type of cell
var typeAArray = [TypeA]()
var typeBAarray = [TypeB]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.getTypeAData()
self.getTypeBData()
}
func getTypeAData(){
//code to call API,parse JSON and also append to `typeAArray`
//and reload TableView
}
func getTypeBData(){
//code to call API,parse JSON and also append to `typeBArray`
//and reload TableView
}
The code for TableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return typeAArray.count + typeBArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let typeACell = tableView.dequeueReusableCell(withIdentifier: "TypeACell", for: indexPath) as! TypeATableCell
typeACell.data = self.typeAArray[indexPath.row] //Here I get index or of range error
return typeACell
}
let typeBCell = tableView.dequeueReusableCell(withIdentifier: "TypeBCell", for: indexPath) as! TypeBTableCell
typeBCell.data = self.typeBArray[indexPath.row]
return typeBCell
}
到目前为止我得到了什么:
现在使用上面的设置和代码,index out of range
部分出现if indexPath == 0
错误,TableView
中没有任何数据显示。
所以我的问题是:
如何使2种类型的tableViewCell出现在1个单独的TableView中哪个数据来自2个不同的API方法调用?
答案 0 :(得分:2)
采用numberOfSections方法并执行以下操作:
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return typeAArray.count
} else {
return typeBArray.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let typeACell = tableView.dequeueReusableCell(withIdentifier: "TypeACell", for: indexPath) as! TypeATableCell
typeACell.data = self.typeAArray[indexPath.row] //Here I get index or of range error
return typeACell
}
let typeBCell = tableView.dequeueReusableCell(withIdentifier: "TypeBCell", for: indexPath) as! TypeBTableCell
typeBCell.data = self.typeBArray[indexPath.row]
return typeBCell
}
答案 1 :(得分:1)
好的,这是怎么回事。您的numberOfRowsInSection
会返回数组A和B中元素的总数。假设typeBArray
的加载速度超过typeAArray
,您的项目总数将等于typeBArray
。在cellForRowAt
中,您假设第0行的项目属于第一个数据模型,因此您在typeAArray[0]
仍然为空并且不包含任何数据时会尝试访问该func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < self.typeAArray.count {
let typeACell = tableView.dequeueReusableCell(withIdentifier: "TypeACell", for: indexPath) as! TypeATableCell
typeACell.data = self.typeAArray[indexPath.row]
return typeACell
}
let typeBCell = tableView.dequeueReusableCell(withIdentifier: "TypeBCell", for: indexPath) as! TypeBTableCell
typeBCell.data = self.typeBArray[indexPath.row - self.typeAArray.count]
return typeBCell
}
。这会导致崩溃。您需要考虑偏移量:
RewriteEngine On
RewriteCond %{THE_REQUEST} ^.*/index\.php
RewriteRule ^(.*)index.php$ /$1 [R=301,L]
RewriteRule ^(.*)$ public/$1 [L]
但老实说,只需改用部分。
答案 2 :(得分:0)
显然它会给你一个错误,因为你的indexPath.row在TypeBTableCell
的数据源中以1开头,而你的数组元素索引从typeBArray
的0开始。所以它不会相互匹配。
您需要降低indexPath.row
1步的值。还要确保两个数组都包含元素。
试试这个,看看:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let numberOfRows = typeAArray.count + typeBArray.count
print("typeAArray.count = \(typeAArray.count)\n")
print("typeBArray.count = \(typeBArray.count)\n")
print("numberOfRows = \(numberOfRows)\n")
return numberOfRows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var indexPathRowForB = max(0, indexPath.row - 1)
if indexPath.row == 0 && self.typeAArray.count > 0 {
let typeACell = tableView.dequeueReusableCell(withIdentifier: "TypeACell", for: indexPath) as! TypeATableCell
typeACell.data = self.typeAArray[indexPath.row]
return typeACell
} else {
print("self.typeAArray.count is zero")
indexPathRowForB = indexPath.row
}
if self.typeBArray.count > 0 {
let typeBCell = tableView.dequeueReusableCell(withIdentifier: "TypeBCell", for: indexPath) as! TypeBTableCell
typeBCell.data = self.typeBArray[indexPathRowForB]
return typeBCell
} else {
print("self.typeBArray.count is zero")
// return UITableviewCell instance from here......
}
}
答案 3 :(得分:0)
首先有一个数组,存储从API方法A和B 返回的所有数据,而不是有2个单独的数组,这可能会使事情变得更复杂,但要确保你的类型A是第一个数组中的项目。
然后是这样的:
var tableViewDataArray = [Array]()
var typeAArray = [Array]()
var typeBArray = [Array]()
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.delegate = self
self.tableView.dataSource = self
self.getTableViewData()
}
func getTableViewData() {
let queue = DispatchQueue(label: "com.company.app.queue")
let group = DispatchGroup()
group.enter()
queue.async(group: group) {
getTypeAData()
group.leave()
}
queue.async(group: group) {
getTypeBData()
group.leave()
}
group.notify(queue: queue) {
group.wait()
tableViewDataArray.append(typeAArray)
tableViewDataArray.append(typeBArray)
self.tableView.reloadData()
}
}
func getTypeAData() {
let urlRequest: NSURLRequest = ...
let task = self.session?.dataTaskWithRequest(urlRequest, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) in
// parse your response and append to array
self.typeAArray.append(response)
})
}
func getTypeBData() {
let urlRequest: NSURLRequest = ...
let task = self.session?.dataTaskWithRequest(urlRequest, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) in
// parse your response and append to array
self.typeBArray.append(response)
})
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableViewDataArray.count
}
public final func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let customObject = tableViewDataArray[indexPath.section]
if indexPath.row == 0 &&
customObject is TypeAObject {
if let typeACell = tableView.dequeueReusableCell(withIdentifier: TypeACell.identifier, for: indexPath) as? TypeACell {
// do any databinding here
typeACell.customObject = customObject
return typeACell
}
} else if customObject is TypeBObject {
if let typeBcell = tableView.dequeueReusableCell(withIdentifier: TypeBCell.identifier, for: indexPath) as? TypeBCell {
// do any databinding here
typeBcell.customObject = customObject
return typeBcell
}
}
return UITableViewCell()
}
注意:这是在Playground完成的,但希望能让你更好地了解该怎么做。您还应熟悉GCD并按顺序或同时执行异步操作(请参阅RayWenderlich的这些教程:part 1和part 2)