9 Replies
      Latest reply on Dec 4, 2019 8:29 PM by japio
      japio Level 1 Level 1 (0 points)

        I have a table view and an array of strings. When I swipe a row, I want to add the clicked string to an array of strings. How do I get the value stored in the table view row. I have it set up like this:

         

        import UIKit
        
        var myStringArray: [String]?
        
        var someStringArray: [String] = ["Hot Dogs", "Soda", "Chips", "Hamburgers", "Plates", "Dessert", "Napkins", "Fruit",
        "Potatoe Salad", "Brats"]
        
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                return someStringArray.count
            }
            
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath)
            cell.textLabel?.text = someStringArray[indexPath.row]
            cell.textLabel?.adjustsFontSizeToFitWidth = true
            cell.textLabel?.font = UIFont.systemFont(ofSize: 22)
            return cell
        }
        
        func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
                
            let object: String = someStringArray[indexPath.row]
                
            let add = UIContextualAction(style: .normal, title: "Add") { (contextualAction, view, actionPerformed: @escaping (Bool) -> Void) in
                    
            let alert = UIAlertController(title: "Add ", message: "Are you sure you want to add '\(object)' to your list?", preferredStyle: .alert)
                    
            alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { (alertAction) in
                actionPerformed(false)
                }))
        
            alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alertAction) in
                self.addObject()
                   
                }))
                        
                self.present(alert, animated: true)
            }
            
            return UISwipeActionsConfiguration(actions: [add, taken])
        }
        
        func addObject(index: Int) {
                    
            let index = table.indexPathForSelectedRow
                    
            let _index = (index?[someStringArray.hashValue])!
                    
            if myStringArray!.isEmpty {
                myStringArray?.insert(someStringArray[_index], at: 0)
            } else {
                myStringArray?.append(someStringArray[_index])
            }
        }
                 
        
        • Re: How do I get the value of a selected row in a table view?
          Claude31 Level 8 Level 8 (7,255 points)

          To get the cell content:

           

          tableView.cellForRow(at: indexPath)

           

          So, in addObject (I assume table is the tableView declared as an IBOutlet)

           

          func addObject(index: Int) {
                    
              let index = table.indexPathForSelectedRow
              let cell = table.cellForRow(at: index)

           

          Note: why do you need _index ?

            • Re: How do I get the value of a selected row in a table view?
              japio Level 1 Level 1 (0 points)

              I don't need _index. I was just trying different things. I implemented your method I am getting an error at runtime at line 3. Unexpectedly found nil while unwrapping an Optional value.

                • Re: How do I get the value of a selected row in a table view?
                  Claude31 Level 8 Level 8 (7,255 points)

                  You do not show what table is and how defined.

                  I guessed it was the tableView. Correct ?

                   

                  You say error (Unexpectedly found nil while unwrapping an Optional value) at line 3 ? Here ?

                      let index = table.indexPathForSelectedRow

                   

                  But you call table.table.indexPathForSelectedRow at line 3 in your original code, so there should not be an error here if your code compiles.

                   

                  func addObject(index: Int) { 
                               
                      let index = table.indexPathForSelectedRow 
                               
                      let _index = (index?[someStringArray.hashValue])! 
                               
                      if myStringArray!.isEmpty { 
                          myStringArray?.insert(someStringArray[_index], at: 0) 
                      } else { 
                          myStringArray?.append(someStringArray[_index]) 
                      } 
                  }

                   

                  So, change next line into

                   

                  if  let cell = table.cellForRow(at: index)  {
                       // Do what you need with cell, such as
                       let theString = cell.textLabel?.text
                  }
                    • Re: How do I get the value of a selected row in a table view?
                      japio Level 1 Level 1 (0 points)

                      I can't figure it out. On line 34 of my original post, I don't have anything in addOject() parameters. What am I supposed to pass through its parameters? Thank you for your help.

                      • Re: How do I get the value of a selected row in a table view?
                        japio Level 1 Level 1 (0 points)

                        This is the actual file from my app. Can you help me please? When I run it, line 71 is throwing an error that it found nil while unwrapping a nil value.

                         

                        import UIKit
                        
                        var myRoster: [String]?
                        
                        struct DataToPass {
                            var playerData: String = ""
                        }
                        
                        @available(iOS 11.0, *)
                        class Top_30_Quarterbacks: UIViewController, UITableViewDelegate, UITableViewDataSource {
                            
                            var objectsArray: [String] = ["1. Patrick Mahomes, KC", "2. Deshaun Watson, HOU", "3. Aaron Rodgers, GB", "4. Matt Ryan, ATL", "5. Baker Mayfield, CLE", "6. Carson Wentz, PHI", "7. Jared Goff, LAR", "8. Cam Newton, CAR", "9. Andrew Luck, IND", "10. Drew Brees, NO", "11. Ben Roethlisberger, PIT", "12. Dak Prescott, DAL", "13. Russell Wilson, SEA", "14. Tom Brady, NE", "15. Lamar Jackson, BAL", "16. Mitchell Trubisky, CHI",  "17. Jameis Winston, TB", "18. Philip Rivers, LAC", "19. Kirk Cousins, MIN", "20. Derek Carr, OAK", "21. Sam Darnold, NYJ", "22. Josh Allen, BUF", "23. Matthew Stafford, DET", "24. Marcus Mariota, TEN", "25. Jimmy Garoppolo, SF", "26. Andy Dalton, CIN", "27. Eli Manning, NYG", "28. Nick Foles, JAC", "29. Joe Flacco, DEN", "30. Ryan Fitzpatrick, MIA"
                            ]
                            
                            func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
                                return objectsArray.count
                            }
                            
                            func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
                                let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath as IndexPath)
                                cell.textLabel?.text = objectsArray[indexPath.row]
                                cell.textLabel?.adjustsFontSizeToFitWidth = true
                                cell.textLabel?.font = UIFont.systemFont(ofSize: 22)
                                return cell
                               }
                            
                            func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
                                top30QuarterbacksTable.deselectRow(at: indexPath, animated: true)
                            }
                            
                            func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
                                
                                let player: String = objectsArray[indexPath.row]
                                
                                let add = UIContextualAction(style: .normal, title: "Add") { (contextualAction, view, actionPerformed: @escaping (Bool) -> Void) in
                                    let alert = UIAlertController(title: "Add Player", message: "Are you sure you want to add '\(player)' to your roster?", preferredStyle: .alert)
                                    
                                    alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { (alertAction) in
                                        actionPerformed(false)
                                    }))
                                    
                                    alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alertAction) in
                                        self.addPlayer(index: indexPath.row)
                                    }))
                                    
                                    self.present(alert, animated: true)
                                }
                                add.backgroundColor = .systemGreen
                                
                                let taken = UIContextualAction(style: .normal, title: "Taken") { (contextualAction, view, actionPerformed: @escaping (Bool) -> Void) in
                                    
                                    let alert = UIAlertController(title: "Player Taken", message: "Are you sure you want to mark '\(player)' as not available?", preferredStyle: .alert)
                                    
                                    alert.addAction(UIAlertAction(title: "No", style: .cancel, handler: { (alertAction) in
                                        actionPerformed(false)
                                    }))
                                    
                                    alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alertAction) in
                                        
                                        
                                    }))
                                    
                                    self.present(alert, animated: true)
                                }
                                taken.backgroundColor = .systemRed
                                return UISwipeActionsConfiguration(actions: [taken, add])
                            }
                            
                            func addPlayer(index: Int) {
                                
                                let index = top30QuarterbacksTable.indexPathForSelectedRow!
                                
                                if let cell = top30QuarterbacksTable.cellForRow(at: index) {
                                    
                                    let string = objectsArray[0]
                                    
                                    cell.textLabel?.text = string
                                    
                                    if myRoster!.isEmpty {
                                        myRoster?.insert(string, at: 0)
                                    } else {
                                        myRoster?.append(string)
                                    }
                                }
                            }
                            
                            func markAsTaken() {
                                
                                
                                
                            }
                            
                            
                            @IBOutlet weak var top30QuarterbacksTable: UITableView!
                            @IBOutlet var view1: UIView!
                            @IBOutlet weak var view2: UIView!
                            @IBOutlet weak var label: UILabel!
                            override func viewDidLoad() {
                                super.viewDidLoad()
                            
                            }
                        }
                          • Re: How do I get the value of a selected row in a table view?
                            Claude31 Level 8 Level 8 (7,255 points)

                            Are you sure you made any selection in tableView ?

                             

                            To avoid crash, test for nil, with :

                             

                            guard let index = top30QuarterbacksTable.indexPathForSelectedRow else { return }     // Do not add player
                            // After this, continue with your code

                             

                             

                            But you should ease your life.

                             

                            Change paramet in addPlayer to the full indexPath

                                        alert.addAction(UIAlertAction(title: "Yes", style: .destructive, handler: { (alertAction) in 
                                            self.addPlayer(index: indexPath) 
                                        })) 

                             

                            Then, no need to look for selected.

                            It is still safer to test for nil:

                             

                               func addPlayer(index: IndexPath) { 
                                     
                                    guard let cell = top30QuarterbacksTable.cellForRow(at: index) else { return }          // Should never occur
                                         
                                    let string = objectsArray[0] 
                                    cell.textLabel?.text = string 
                                         
                                    if myRoster!.isEmpty { 
                                            myRoster?.insert(string, at: 0) 
                                     } else { 
                                            myRoster?.append(string) 
                                      } 
                                }