I have tableView that populates multiple cells. In one of the cell I want to populate 'xib1', if I have data in my array. But if I have 'nil' in my array I want to populate 'xib2' in the same tableview instead of 'xib1'.
How shall I achieve this behaviour in Swift.
I tried using condition say, if the array is nil show xib2 and if not show xib1. Didnt work. it loops in 2nd condition and keeps showing that data where as I want it to show rest of the cells as well which dont have any such conditions.
CodePudding user response:
While the question describes displaying different .xib files conditionally dependent on the array's contents, it is much simpler to create two different subclasses of UITableViewCell, each with its own associated .xib, and then register both subclasses of cell for your table. This is what Duncan C is referring to in his comment.
If you do this, determining which cell to display in the cellForRowAt
method becomes very straightforward: just do a test for nil at the corresponding array index, and return a different cell based on the result. Below is a minimal example of this, which I've tested and confirmed works:
VIEW CONTROLLER CODE
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var table: UITableView!
var stuff: [String?] = ["abc", nil, "def", "ghi", nil, "jkl", nil, nil]
override func viewDidLoad() {
super.viewDidLoad()
table.dataSource = self
table.register(UINib(nibName: "Cell1", bundle: nil), forCellReuseIdentifier: "nonNilCell")
table.register(UINib(nibName: "Cell2", bundle: nil), forCellReuseIdentifier: "nilCell")
}
}
extension ViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return stuff.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if stuff[indexPath.row] != nil {
let cell = tableView.dequeueReusableCell(withIdentifier: "nonNilCell", for: indexPath) as! Cell1
cell.label.text = stuff[indexPath.row]
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "nilCell", for: indexPath) as! Cell2
return cell
}
}
}
FIRST CELL (for non-nil array items)
import UIKit
// This is the cell for array entries that are not nil
class Cell1: UITableViewCell {
@IBOutlet weak var label: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
SECOND CELL (for nil array items)
import UIKit
// This is the cell for array items which are nil
class Cell2: UITableViewCell {
override func awakeFromNib() {
super.awakeFromNib()
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
And here are the two .xib files (the text on the green one changes to reflect the value from the array):