简体   繁体   中英

Swift delegation problem without storyboard and segue

I have a problem with triggering a method in one Controller from another. I set up all my elements(buttons,views..) programmatically and I'm using a NavigationController too.

I want to trigger fetchUsers() method whenever a new user logs in or registers so that the tableView reloads its cells with all the users currently populating Firebase.

The problem is that fetchUsersDelegate?.fetchUsers() method never gets called because loginController.fetchUsersDelegate = self never gets set to self and always stays nil.

So my question is how should i properly set fetchUsersDelegate ?

First class

class LoginController: UIViewController {

var fetchUsersDelegate: FetchUsersDelegate?

lazy var loginRegisterButton: UIButton = { 
    let button = UIButton()
    button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
    button.translatesAutoresizingMaskIntoConstraints = false
    button.setTitle("Register", for: .normal)
    button.setTitleColor(UIColor.white, for: .normal)
    button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
    button.layer.cornerRadius = 25
    button.layer.masksToBounds = true

    button.addTarget(self, action: #selector(handleLoginRegister), for: .touchUpInside)

    return button
}()

@objc func handleLoginRegister(){
    if loginRegisterSegmentedControl.selectedSegmentIndex == 0 {
        handleLogin()
    } else {
        handleRegister()
    }
}

func handleLogin() {

    guard let email = emailTextField.text, let password = passwordTextField.text else {
        print("Registration form is not valid")
        return
    }

    Auth.auth().signIn(withEmail: email, password: password) { (user, error) in

        if error != nil {
            print(error!)
            return
        }

        print("Sucessfully logged in")
        self.dismiss(animated: true, completion: nil)

    }

    self.fetchUsersDelegate?.fetchUsers()

}

Second class

class UsersController: UITableViewController, FetchUsersDelegate{


let cellID = "cellID"
var users = [User]()         
let loginController = LoginController()

override func viewDidLoad() {
    super.viewDidLoad()


    loginController.fetchUsersDelegate = self

    navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(handleLogout))
    checkIfUserIsLoggedIn() 


}

func fetchUsers(){

    Database.database().reference().child("users").observe(.childAdded, with: { (DataSnapshot) in

        if let dictionary = DataSnapshot.value as? [String: AnyObject]{
            let user = User()
            user.name = dictionary["name"] as? String
            user.email = dictionary["email"] as? String
            self.users.append(user)

            // if we call just tableView.reloadData the app will crash, insead we need to call it inside
            // DispatchQueue.main.async

            DispatchQueue.main.async {
                self.tableView.reloadData()
            }

        }

    }, withCancel: nil)

}

Protocol

protocol FetchUsersDelegate {
    func  fetchUsers()
}

*Edit:

This is how i set up my rootViewController in the AppDelegate class

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    FirebaseApp.configure()

    window = UIWindow(frame: UIScreen.main.bounds)
    window?.makeKeyAndVisible()

    window?.rootViewController = UINavigationController(rootViewController: UsersController())

    return true
}

And this is how i present the LoginController, the handleLogout() method is inside the UsersController if that helps.

@objc func handleLogout(){

    do{
        try Auth.auth().signOut()
    } catch let logoutError{
        print(logoutError)
    }

    let loginController = LoginController()
    present(loginController, animated: true, completion: nil)

}

This line

let loginController = LoginController()

is the problem it has no relation to the presented vc and it's a new separate instance , so when you present the user

let user  = UsersController()
self.fetchUsersDelegate = user
present// add child// user

if the user can login at same time the users table exists in screen , then i expect it's a menu list or a child vc

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM