2

When I was programming the logout button, it was working fine when it was just by itself and not in a cell. However, I came across this issue where I created a table view through storyboard and then added some cells to it, I then added that same logout button to the cell and created SettingsTableViewCell.Swift file, which is a cell file and not a view controller. So the code I was using before did not work as a cell and a view controller are not the same thing. And I cannot find the code that does the same things it was doing before but from a cell.

When the button was in the view controller file, I was able to log out, send the user to the login screen if the logout was successful, and then return user to home (not settings) if they login again. I want to code somethings that does the exact same thing, but from a cell.

Here is my previous code in SettingsViewController.Swift:

@IBAction func logUserOut(_ sender: Any) {
    // Display an Alert to user to confirm logging out
    let actionSheet = UIAlertController(title: "Log Out", message: "Are you sure you want to log out?", preferredStyle: .actionSheet)
    actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
    actionSheet.addAction(UIAlertAction(title: "Log Out", style: .destructive, handler: { _ in
        AuthManager.shared.logOut(completion: {success in
            DispatchQueue.main.async {
                if (success) {
                    // Go to login after logout
                    let loginVC = self.storyboard?.instantiateViewController(identifier: "login")
                    loginVC?.modalPresentationStyle = .fullScreen
                    self.present(loginVC!, animated: true, completion: {
                        self.navigationController?.popToRootViewController(animated: false)
                        self.tabBarController?.selectedIndex = 0
                    })
                    }
                else {
                    // Error Occurd
                    fatalError("Could not log out user")
                }
            }
        })
    }))
    
    present(actionSheet, animated: true)
} // End logUserOut method

present and navigationController are not part of a UITableViewCell so I cannot use this code.

In case you want to see what is in AuthManager.shared.logOut, here is the code for it:

// Log out user
public func logOut(completion: (Bool) -> Void) {
    do {
        try Auth.auth().signOut()
        completion(true)
        return
    }
    catch {
        print(error)
        completion(false)
        return
    }
} // End logOut method
Omar
  • 41
  • 6
  • 2
    You need to get the event from your cell back to your view controller. You can use the techniques in this answer https://stackoverflow.com/questions/28659845/how-to-get-the-indexpath-row-when-an-element-is-activated/38941510 You probably don't need the indexpath but you can use the delegation or closure approaches – Paulw11 Jul 17 '21 at 21:45
  • I tried that and now when I click on the logout button, I am basically getting a white screen with a bunch of cells that are empty. Not sure what the issue is – Omar Jul 17 '21 at 23:22
  • "where I created a table view through storyboard and then added some cells to it" Where? – El Tomato Jul 18 '21 at 00:47
  • I added the cells in the tableview through storyboard – Omar Jul 18 '21 at 00:54

1 Answers1

1

I think the best thing to do in your case is delegate callback.

You have to define a protocol and implement it in your View Controller

protocol LoginDelegate {
    
    func didPressLogOut()
}

class SettingsViewController : LoginDelegate {
    
    func didPressLogOut() {

        // Display an Alert to user to confirm logging out
        let actionSheet = UIAlertController(title: "Log Out", message: "Are you sure you want to log out?", preferredStyle: .actionSheet)
        actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        actionSheet.addAction(UIAlertAction(title: "Log Out", style: .destructive, handler: { _ in
            AuthManager.shared.logOut(completion: {success in
                DispatchQueue.main.async {
                    if (success) {
                        // Go to login after logout
                        let loginVC = self.storyboard?.instantiateViewController(identifier: "login")
                        loginVC?.modalPresentationStyle = .fullScreen
                        self.present(loginVC!, animated: true, completion: {
                            self.navigationController?.popToRootViewController(animated: false)
                            self.tabBarController?.selectedIndex = 0
                        })
                    }
                    else {
                        // Error Occurd
                        fatalError("Could not log out user")
                    }
                }
            })
        }))
    
        present(actionSheet, animated: true)
    }
}

When initializing your custom cell in the view controller, make sure to see the delegate to the viewcontroller

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

        // Rest of the cell setup code

        return cell
    }

Then in your cell class, on the IBAction, you just call the delegate method.

class SettingsTableViewCell {
    
    var loginDelegate: LoginDelegate?


    @IBAction func logUserOut(_ sender: Any) {

        // Callback to the delegate
        self.loginDelegate?.didPressLogOut()
    }
}