簡體   English   中英

當我只想從一個控制器到另一個控制器進行通信時,如何設置 delegate = self

[英]How do I set delegate = self when I only want communication from one controller to the other

所以我有一個從 MainController() 呈現的 LoginController()。 所以從技術上講 MainController() 仍然在后台加載並在內存中。 現在在 LoginController() 中,當我按下登錄按鈕時,我想通知 MainController() 登錄按鈕被按下,以便再次獲取當前用戶。 然后我關閉 LoginController()。

我想用協議和委托來做到這一點,但問題是當 MainController() 符合 LoginDelegate 時,我不知道如何將委托設置為 self。 因為當用戶注銷或沒有用戶時,我不想回到登錄控制器,我想回到不同的 WelcomeController()。 如果我想去 LoginController() 那么我知道我可以做到

let loginController = LoginController()
loginController.delegate = self
self.present(loginController)

但就我而言,我想使用完全不同的控制器。 那么我在哪里將委托設置為自我?

這是代碼:

//LoginController()
protocol LoginDelegate {
    func didTapLogIn()
}

class LoginController: UIViewController, UITextFieldDelegate{

    var loginDelegate: LoginDelegate!

    override func viewDidLoad() {
        super.viewDidLoad()
        configureViews()
        formValidation()
    }

    @objc func handleLogin(){
        guard let email = emailTextField.text else {return}
        guard let password = passwordTextField.text else {return}
        Auth.auth().signIn(withEmail: email, password: password) { (auth, error) in
            if let error = error{
                print("There was a problem signing the user in", error.localizedDescription)
                return
            }
            self.loginDelegate.didTapLogIn()
            print("Successfully signed in the user")
            self.dismiss(animated: true, completion: nil)
        }
    }
}

這是符合的 MainController

//MainController() which is a tab bar controller

class MainController: UITabBarController, LoginDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        checkLoggedInUserStatus()
    }

    fileprivate func checkLoggedInUserStatus(){
        if Auth.auth().currentUser == nil{
            DispatchQueue.main.async {
                let welcomeController = UINavigationController(rootViewController: WelcomeController())
                welcomeController.modalPresentationStyle = .fullScreen
                self.present(welcomeController, animated: false, completion: nil)
                return
            }
        } else {
            setupTabBar()
        }
    }

    fileprivate func setupTabBar(){
        tabBar.isTranslucent = false
        tabBar.barTintColor = TDGOtherBlue

        let homeController = HomeController()
        homeController.fetchCurrentUser()
        let homeViewController = UINavigationController(rootViewController: homeController)
    let chatViewController = UINavigationController(rootViewController: EditProfileController())

        viewControllers = [homeViewController, chatViewController]
    }

    func didTapLogIn() {
        checkLoggedInUserStatus()
    }
}
//NOTE: ABOVE IS THE DELEGATED FUNCTION BUT WHERE DO I DO THE DELEGATE SELF DECLARATIOn

筆記:

你的建築看起來像一杯雞尾酒。 但是,盡管如此,請注意:

weak var loginDelegate: LoginDelegate? // should be weak and optional

使用此流程:

            self.dismiss(animated: true) {
            self.loginDelegate.didTapLogIn()
            print("Successfully signed in the user")
}

你沒有描述什么是Auth

有些你不能保證

Auth.auth().currentUser實際上不是 nil

甚至在這里:

@objc func handleLogin(){
//....
Auth.auth().signIn( ... {
///here
/// check it!
})

所以,如果沒有,請使用

protocol LoginDelegate {
    func didTapLogIn(user: User)
}

反而

編輯

很明顯,如果在 LoginViewController 關閉時你什么都沒有,你可以將數據發送到 AppDelegate。

final class AppDelegate: UIResponder {
}
extension AppDelegate: LoginDelegate { ... }

要檢索 AppDelegate 共享實例,您可以使用:

let appDelegate = UIApplication.sharedApplication().delegate as! AppDelegate

第二種解決方案,您可以使用 AppDelegate 獲取您的視圖控制器。 這邊走:

let rootViewController = appDelegate.window?.rootViewController

我不知道如何將委托設置為自我。 因為當用戶注銷或沒有用戶時,我不想回到登錄控制器,我想回到不同的 WelcomeController()。

聽起來 MainController 真的在運行這個節目。 您還沒有對 WelcomeController 說太多,但聽起來流程是這樣的:

  1. 應用程序啟動、創建並顯示 MainController。
  2. 如果 MainController 沒有用戶,它會創建並顯示一個 WelcomeController。
  3. 用戶點擊 WelcomeController 中的某個按鈕表示他/她想要登錄。 WelcomeController 向 MainController 發送一條消息,告訴它開始登錄過程,然后被解除。
  4. MainController 創建一個 LoginController 並顯示它。
  5. LoginController 獲取用戶的憑據,將它們發送到 MainController,然后被解除。
  6. 在某些時候用戶注銷,此時沒有用戶,因此轉到第 2 步。

所以答案是 MainController 在步驟 4 中將自己設置為 LoginController 的委托,介於創建和顯示 LoginController 之間。

您需要從准備函數中分配委托值。 或者,如果您不想使用故事板/xib,您可以從您的 ViewController 中分配具有 initialize RedScreenVC(self) 的委托。

import UIKit

class ViewController: UIViewController, NavDelegate {
    func navigate(text: String, isShown: Bool) {
        print("text: \(text) isShown: \(isShown)")
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if (segue.identifier == "RedScreenVC") {
            let redScreenVC = segue.destination as? RedScreenVC
            redScreenVC?.delegate = self
        }
    }

    @IBAction func nextPageButtonEventLustener(_ sender: Any) {
        performSegue(withIdentifier: "RedScreenVC", sender: sender)
    }
}



import UIKit

protocol NavDelegate {
    func navigate(text: String, isShown: Bool)
}
class RedScreenVC: UIViewController {

    weak var delegate: NavDelegate?

    var redView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height))

    var navigateButton: UIButton = {
        let button = UIButton(frame: CGRect(x: 200, y: 350, width: 150, height: 50))
        button.setTitle("Navigate", for: .normal)
        button.addTarget(self, action: #selector(buttonAction), for: .touchUpInside)
        button.backgroundColor = .blue
        return button
    }()

    @objc func buttonAction(){
        if self.redView.backgroundColor == .gray {
            self.redView.backgroundColor = .systemPink
        }
    self.delegate.navigate(text:"", isShown: true)

    }

    override func viewDidLoad() {
        navigateButton.layer.cornerRadius = 25
        redView.backgroundColor = UIColor.gray

        delegate.navigate(text: "Navigation Success", isShown: true)

        view.addSubview(redView)

        view.addSubview(navigateButton)
    }

}

如果您不想使用故事板並像這樣初始化

讓 redScreenVC = RedScreenVC()

redScreenVC.delegate = self

class RedScreenVC: UIViewController {
  override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
    super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

init() {
    super.init(nibName: nil, bundle: nil)
    self.initialize()
}

func initialize() {
    self.view.backgroundColor=CustomColor.PAGE_BACKGROUND_COLOR_1
    //From here you need to create your email and password textfield
}
}
let vc = FirstViewController.instantiate(fromStoryboard: .Profile)
    vc.callback = { (address, lat, lon) in
        self.updateLocation(address: address ?? "", lat: lat ?? 0.0, lon: lon ?? 0.0)
    }
    self.navigationController?.pushViewController(vc, animated: true)

然后在第二個VC

var callback : (( address: String?, latitude: Double?,_ longitude: Double?)-> Void)!

然后,當您想將該值傳遞回之前的 VC 時,請在單擊或解除事件中添加。

callback(address,Double(lat),Double(lon))

在視圖和控制器之間必須進行委派。 您應該在這種情況下使用Notification。

callback發布通知:

,,,

    Auth.auth().signIn(withEmail: email, password: password) { (auth, error) in
        if let error = error{
            print("There was a problem signing the user in", error.localizedDescription)
            return
        }
        // self.loginDelegate.didTapLogIn() // user didn't tap anything here! this is the callback!
        print("Successfully signed in the user")
        NotificationCenter.default.post(.init(name: .init(rawValue: "LoggedStatusChanged")))
        self.dismiss(animated: true, completion: nil)
    }

在任何需要的地方(例如MainController )觀察此通知:

,,,
    override func viewDidLoad() {
        super.viewDidLoad()

        NotificationCenter.default.addObserver(self, selector: #selector(checkLoggedInUserStatus), name: .init(rawValue: "LoggedStatusChanged"), object: nil)

        ,,,
    }

    @objc private func checkLoggedInUserStatus() {
        ,,,
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM