简体   繁体   English

没有情节提要和segue的Swift委托问题

[英]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. 我以编程方式设置了所有元素(按钮,视图..),我也使用了NavigationController

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. 我想在新用户登录或注册时触发fetchUsers()方法,以便tableView使用当前正在填充Firebase的所有用户重新加载其单元格。

The problem is that fetchUsersDelegate?.fetchUsers() method never gets called because loginController.fetchUsersDelegate = self never gets set to self and always stays nil. 问题是fetchUsersDelegate?.fetchUsers()方法永远不会被调用,因为loginController.fetchUsersDelegate = self永远不会设置为self,并且始终保持为零。

So my question is how should i properly set fetchUsersDelegate ? 所以我的问题是我应该如何正确设置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 这是我在AppDelegate类中设置rootViewController的方式

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. 这就是我目前使用LoginController的方式,如果有帮助,则handleLogout()方法位于UsersController内。

@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 是问题,它与所呈现的vc无关,并且是一个新的单独实例,因此当您呈现用户时

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 如果用户可以同时登录用户表存在于screen中,那么我希望它是菜单列表或子vc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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