I want table view multiple row selection with a fav image in Swift

I have an array of countries lists that I show in my table view now I want to select those countries in which the first letter is A/B/C... etc. when I select those rows containing the first letter "A" then I don't want to select other countries which first letter contains B/C/D... etc. the problem is when I select those countries which first letter contain "A" selected fine but others rows are also auto-select that I don't want. here is my code please check it and help me thanks in advance.

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet weak var myTable: UITableView!

var countries:[String] = ["Afghanistan","Albania","Algeria","Andorra","Angola","Anguilla","Antigua & Barbuda","Argentina","Armenia","Aruba","Australia","Austria","Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin","Bermuda","Bhutan","Bolivia","Bosnia & Herzegovina","Botswana","Brazil","British Virgin Islands","Brunei","Bulgaria","Burkina Faso","Burundi","Cambodia","Cameroon","Cape Verde","Cayman Islands","Chad","Chile","China","Colombia","Congo","Cook Islands","Costa Rica","Cote D Ivoire","Croatia","Cruise Ship","Cuba","Cyprus","Czech Republic","Denmark","Djibouti","Dominica","Dominican Republic","Ecuador","Egypt","El Salvador","Equatorial Guinea","Estonia","Ethiopia","Falkland Islands","Faroe Islands","Fiji","Finland","France","French Polynesia","French West Indies","Gabon","Gambia","Georgia","Germany","Ghana","Gibraltar","Greece","Greenland","Grenada","Guam","Guatemala","Guernsey","Guinea","Guinea Bissau","Guyana","Haiti","Honduras","Hong Kong","Hungary","Iceland","India","Indonesia","Iran","Iraq","Ireland","Isle of Man","Israel","Italy","Jamaica","Japan","Jersey","Jordan","Kazakhstan","Kenya","Kuwait","Kyrgyz Republic","Laos","Latvia","Lebanon","Lesotho","Liberia","Libya","Liechtenstein","Lithuania","Luxembourg","Macau","Macedonia","Madagascar","Malawi","Malaysia","Maldives","Mali","Malta","Mauritania","Mauritius","Mexico","Moldova","Monaco","Mongolia","Montenegro","Montserrat","Morocco","Mozambique","Namibia","Nepal","Netherlands","Netherlands Antilles","New Caledonia","New Zealand","Nicaragua","Niger","Nigeria","Norway","Oman","Pakistan","Palestine","Panama","Papua New Guinea","Paraguay","Peru","Philippines","Poland","Portugal","Puerto Rico","Qatar","Reunion","Romania","Russia","Rwanda","Saint Pierre & Miquelon","Samoa","San Marino","Satellite","Saudi Arabia","Senegal","Serbia","Seychelles","Sierra Leone","Singapore","Slovakia","Slovenia","South Africa","South Korea","Spain","Sri Lanka","St Kitts & Nevis","St Lucia","St Vincent","St. Lucia","Sudan","Suriname","Swaziland","Sweden","Switzerland","Syria","Taiwan","Tajikistan","Tanzania","Thailand","Timor L'Este","Togo","Tonga","Trinidad & Tobago","Tunisia","Turkey","Turkmenistan","Turks & Caicos","Uganda","Ukraine","United Arab Emirates","United 
 Kingdom","Uruguay","Uzbekistan","Venezuela","Vietnam","Virgin Islands 
 (US)","Yemen","Zambia","Zimbabwe"]   

  var sectionTitle = [String]()

 var countryDict = [String: [String]]()
 var favDic = [Int:Bool]()

  override func viewDidLoad() {
  super.viewDidLoad()
 // Do any additional setup after loading the view.

sectionTitle = Array(Set(countries.compactMap({String($0.prefix(1))})))

sectionTitle.sort()

for title in sectionTitle {
    countryDict[title] = [String]()
}

for country in countries {
    countryDict[String(country.prefix(1))]?.append(country)
}

blankFavList ()
   }

func blankFavList ()
{
for i in 0...countries.count
{
    favDic[i] = false
}
 }

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return countryDict[sectionTitle[section]]!.count
 }

   func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = myTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell

if favDic[indexPath.row] == true
{
    cell.lblName?.text = countryDict[sectionTitle[indexPath.section]]?[indexPath.row]
    cell.mySelect.image = UIImage(named: "chk")
}
else
{
    cell.lblName?.text = countryDict[sectionTitle[indexPath.section]]?[indexPath.row]
    cell.mySelect.image = UIImage(named: "unchk")
}

return cell
 }

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

  func sectionIndexTitles(for tableView: UITableView) -> [String]? {
return sectionTitle
  }

   func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return sectionTitle[section]
 }

  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

let cell = myTable.cellForRow(at: indexPath) as! MyTableViewCell

//if mobileList[indexPath.row] == "Samsung"
if sectionTitle[indexPath.section] == "A"
{
    cell.mySelect.image = UIImage(named: "chk")
    favDic[indexPath.row] = true
    print(sectionTitle[indexPath.section])
    print(countryDict[sectionTitle[indexPath.section]]?[indexPath.row] as Any)
}
else
{
    let alert = UIAlertController(title: "Message", message: "Please Select only those country which first letter is A", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default))
    
    self.present(alert, animated: true, completion: nil)
}
}

 func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {

let cell = myTable.cellForRow(at: indexPath) as! MyTableViewCell

//if mobileList[indexPath.row] == "Samsung"
if sectionTitle[indexPath.section] == "A"
{
    cell.mySelect.image = UIImage(named: "unchk")
    favDic[indexPath.row] = false
    print(sectionTitle[indexPath.section])
    print(countryDict[sectionTitle[indexPath.section]]?[indexPath.row] as Any)
}
else
{
    let alert = UIAlertController(title: "Message", message: "Please Select only those country which first letter is A", preferredStyle: .alert)
    alert.addAction(UIAlertAction(title: "OK", style: .default))
    
    self.present(alert, animated: true, completion: nil)
}


}
}

Current output: image which I select

second image auto selects other rows when I select my selection row

3rd image for validation

It seems you misunderstand IndexPath: it is section and then row is the position in this section, not an absolute position. So your favDict is wrong.

favDic is wrong. You could either:

  • simply define an array of Bool
10.     var favDic = [Bool]()
  • And keep the same blankFavListand
  • and define a func to compute absolute position from an indexPath (just sum the previous section count and add its section row)
func absolutePos(_ indexPath: IndexPath) -> Int {
    
    var pos = 0
    for section in 0..<indexPath.section {
        pos = pos + (countryDict[sectionTitle[section]]?.count ?? 0)
    }
    pos += indexPath.row
    
    return pos
}

Or

  • define a dictionary, but key would be indexPath
  • Then, change blankFavListand accordingly

Your code is badly indented, makes it more hard to read… I've numbered lines to reference more easily

1. class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
2.     
3.     @IBOutlet weak var myTable: UITableView!
4.     
5.     var countries:[String] =  // removed to save space
6.     
7.     var sectionTitle = [String]()
8.     
9.     var countryDict = [String: [String]]()
10.     var favDic = [Int:Bool]()
11.     
12.     override func viewDidLoad() {
13.         super.viewDidLoad()
14.         // Do any additional setup after loading the view.
15.         
16.         sectionTitle = Array(Set(countries.compactMap({String($0.prefix(1))})))
17.         
18.         sectionTitle.sort()
19.         
20.         for title in sectionTitle {
21.             countryDict[title] = [String]()
22.         }
23.         
24.         for country in countries {
25.             countryDict[String(country.prefix(1))]?.append(country)
26.         }
27.         
28.         blankFavList ()
29.     }
30.     
31.     func blankFavList ()
32.     {
33.         for i in 0...countries.count
34.         {
35.             favDic[i] = false
36.         }
37.     }
38.     
39.     func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
40.         return countryDict[sectionTitle[section]]!.count
41.     }
42.     
43.     func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
44.         let cell = myTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
45.         
46.         if favDic[indexPath.row] == true
47.         {
48.             cell.lblName?.text = countryDict[sectionTitle[indexPath.section]]?[indexPath.row]
49.             cell.mySelect.image = UIImage(named: "chk")
50.         }
51.         else
52.         {
53.             cell.lblName?.text = countryDict[sectionTitle[indexPath.section]]?[indexPath.row]
54.             cell.mySelect.image = UIImage(named: "unchk")
55.         }
56.         
57.         return cell
58.     }
59.     
60.     func numberOfSections(in tableView: UITableView) -> Int {
61.         return sectionTitle.count
62.     }
63.     
64.     func sectionIndexTitles(for tableView: UITableView) -> [String]? {
65.         return sectionTitle
66.     }
67.     
68.     func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
69.         return sectionTitle[section]
70.     }
71.     
72.     func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
73.         
74.         let cell = myTable.cellForRow(at: indexPath) as! MyTableViewCell
75.         
76.         //if mobileList[indexPath.row] == "Samsung"
77.         if sectionTitle[indexPath.section] == "A"
78.         {
79.             cell.mySelect.image = UIImage(named: "chk")
80.             favDic[indexPath.row] = true
81.             print(sectionTitle[indexPath.section])
82.             print(countryDict[sectionTitle[indexPath.section]]?[indexPath.row] as Any)
83.         }
84.         else
85.         {
86.             let alert = UIAlertController(title: "Message", message: "Please Select only those country which first letter is A", preferredStyle: .alert)
87.             alert.addAction(UIAlertAction(title: "OK", style: .default))
88.             
89.             self.present(alert, animated: true, completion: nil)
90.         }
91.     }
92.     
93.     func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
94.         
95.         let cell = myTable.cellForRow(at: indexPath) as! MyTableViewCell
96.         
97.         //if mobileList[indexPath.row] == "Samsung"
98.         if sectionTitle[indexPath.section] == "A"
99.         {
100.             cell.mySelect.image = UIImage(named: "unchk")
101.             favDic[indexPath.row] = false
102.             print(sectionTitle[indexPath.section])
103.             print(countryDict[sectionTitle[indexPath.section]]?[indexPath.row] as Any)
104.         }
105.         else
106.         {
107.             let alert = UIAlertController(title: "Message", message: "Please Select only those country which first letter is A", preferredStyle: .alert)
108.             alert.addAction(UIAlertAction(title: "OK", style: .default))
109.             
110.             self.present(alert, animated: true, completion: nil)
111.         }
112.         
113.     }
114. }

Some questions first: line 33: why

33.         for i in 0...countries.count

and not

33.         for i in 0..<countries.count

You could also simplify some code:

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = myTable.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! MyTableViewCell
        
        cell.lblName?.text = countryDict[sectionTitle[indexPath.section]]?[indexPath.row]
        cell.mySelect.image = favDic[indexPath.row] ? UIImage(named: "chk") : UIImage(named: "unchk")
        
        return cell
    }

If you cannot make it work, please explain where. Otherwise don't forget to close the thread.

I want table view multiple row selection with a fav image in Swift
 
 
Q