code: in this code i have already selected cells ids in selectedRows
once i reach the vc those cells are showing as selected and if i select and deselect the cells then getting correct values in array selectedRows and getting wrong names in selectedNamesArray
why? initially when adding selected names in array then also mismatch in names indexes. where ami wrong?
class ViewController2: UIViewController {
@IBOutlet weak var tableView: UITableView!
var selectedRows = [32, 38, 89, 11]
var selectedNamesArray: [String] = []
var arrayModel: [SampleModel] = [SampleModel(id: 32, name: "Apple"),
SampleModel(id: 38, name: "Smasung"),
SampleModel(id: 22, name: "Black berry"),
SampleModel(id: 76, name: "Nokia"),
SampleModel(id: 12, name: "Real me"),
SampleModel(id: 75, name: "Lenova"),
SampleModel(id: 36, name: "Pocco"),
SampleModel(id: 11, name: "Motorola"),
SampleModel(id: 37, name: "Infinix"),
SampleModel(id: 88, name: "China"),
SampleModel(id: 89, name: "Jio")
]
override func viewDidLoad() {
super.viewDidLoad()
if !selectedRows.isEmpty{
selectedNamesArray = arrayModel
.filter { selectedRows.contains($0.id) }
.map { $0.name }
}
print("existing names: \(selectedNamesArray) \n and ids: \(selectedRows)")
}
}
extension ViewController2: UITableViewDelegate, UITableViewDataSource{
func numberOfSections(in tableView: UITableView) -> Int {
2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayModel.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TestTableviewCell1", for: indexPath) as? TestTableviewCell1
cell?.selectionStyle = .none
cell?.titleLbl?.text = arrayModel[indexPath.row].name
cell?.checkBtn.tag = indexPath.row
cell?.isChecked = selectedRows.contains(arrayModel[indexPath.row].id)
cell?.buttonAction = { [self] sender in
if selectedRows.contains(arrayModel[indexPath.row].id) {
if let indexToRemove = selectedRows.firstIndex(of: arrayModel[indexPath.row].id) {
selectedRows.remove(at: indexToRemove)
if indexToRemove < selectedNamesArray.count {
selectedNamesArray.remove(at: indexToRemove) // Remove corresponding name
}
// selectedNamesArray.remove(at: indexToRemove) // Remove the corresponding name
cell?.isChecked = false
}
} else {
selectedRows.append(arrayModel[indexPath.row].id)
selectedNamesArray.append(arrayModel[indexPath.row].name) // Add the corresponding name
cell?.isChecked = true
}
print("Selected rows: \(selectedRows)")
print("Selected names: \(selectedNamesArray)")
}
return cell!
}
}
class TestTableviewCell1: UITableViewCell{
@IBOutlet weak var titleLbl: UILabel!
@IBOutlet weak var checkBtn: UIButton!
var isChecked = false{
didSet{
checkBtn.backgroundColor = isChecked ? .blue : .green
}
}
var buttonAction: ((_ sender: AnyObject) -> Void)?
@IBAction func buttonPressed(_ sender: UIButton) {
self.buttonAction?(sender)
}
}
struct SampleModel{
var id: Int
var name: String
}
o/p:
existing names: ["Apple", "Smasung", "Motorola", "Jio"] and ids: [32, 38, 89, 11] //here also indexes are not matching with both array values
after doing some selection de selection
Selected rows: [32, 38, 89, 36] Selected names: ["Apple", "Smasung", "Motorola", "Pocco"] //agin mis match in indexes
When you filter an array, you get back an array in the same order as the original array.
So, let's simplify things a little...
var arrayModel: [SampleModel] = [
SampleModel(id: 32, name: "Apple"),
SampleModel(id: 76, name: "Nokia"),
SampleModel(id: 11, name: "Motorola"),
SampleModel(id: 89, name: "Jio"),
]
var selectedRows = [11, 76]
let a1 = arrayModel.filter { selectedRows.contains($0.id) }
print("selectedRows:")
print(selectedRows)
print()
print("Filtered:")
print(a1)
We get this output in the debug console:
selectedRows:
[11, 76]
Filtered:
[App.SampleModel(id: 76, name: "Nokia"), App.SampleModel(id: 11, name: "Motorola")]
Seems like it's "out of order"?
The .filter
closure essentially says:
create a new, empty returnArray
then, loops through arrayModel
with:
is element.id in selectedRows?
if yes, append element to returnArray
With the above code, we get:
32 / Apple -- discard
76 / Nokia -- append
11 / Motorola -- append
89 / Jim -- discard
The order of the returned array doesn't care about the order of selectedRows
... it's just checking if .id
is contained in selectedRows
, so the order is:
["Nokia", "Motorola"]
If you want to do something with the "names" in the order they were selected you'll need to sort selectedNamesArray
to match the order of selectedRows
.
Or, instead of trying to maintain a selectedNamesArray
throughout, create it when you want to do something with it, like this:
var selectedNamesArray: [String] = []
selectedRows.forEach { i in
if let m = arrayModel.first(where: { $0.id == i }) {
selectedNamesArray.append(m.name)
}
}
print(selectedNamesArray)
outputs:
["Motorola", "Nokia"]