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.