简体   繁体   中英

Swift Protocols not working

I am trying to call a function using delegates and for some reason it is not working. I set loginPresenter as self in the LoginPresenter init() but it still didn't work. I am not sure what else to try? Am i missing how delegates work?

Login View

class LoginView: UIViewController {

    var loginPresenter: LoginPresenterProtocol?

    override func viewDidLoad() {
        super.viewDidLoad()


    }

    @objc func loginHandler() {
        print("Tapped")
        loginPresenter?.loginUser(username: "username", password: "123456")
    }
}

Login Presenter View

class LoginPresenter: LoginPresenterProtocol {
    weak var view: LoginViewProtocol?

    init() {
       view?.loginPresenter = self
    }

    func loginUser(username: String, password: String) {
        print("recieved")
    }
}

Protocols

protocol LoginViewProtocol: class {
    var loginPresenter: LoginPresenterProtocol? { get set }
}

protocol LoginPresenterProtocol: class {
    var view: LoginViewProtocol? { get set }

    func loginUser(username: String, password: String)
}

The root of your problem is that you probably did not inject presenter to the view or it is not the same instance. I do not know how you deal with initialization, so I provide 2 concepts. It is better to use injection with Viper I guess.

Create init method for your presenter which takes view protocol, this applies for both approaches:

init(view: LoginViewProtocol) {
    self.view = view
}

Registering your Dependencies

Below is example of what worked for me using Swinject(transformed to your cause but not tested).

Even though if you are not using storyboard, you can't inject both view to presenter and presenter to view in init. That is why I am using init completed here.

let mainStoryboard = UIStoryboard.init(name: "Main", bundle: nil)

container.register(LoginViewProtocol.self) { _ in
    mainStoryboard.instantiateViewController(
        withIdentifier: String(describing: LoginView.self)
    ) as! LoginViewProtocol
}.initCompleted { (r, loginVC) in
    loginVC.presenter: r.resolve(LoginPresenterProtocol.self)!
}

container.register(LoginPresenterProtocol.self) { r in
    LoginPresenter(
        view: r.resolve(LoginViewProtocol.self)!
    )
}

Then just resolve view controller when needed to be presented.

Without Dependency injection

Or if you do not want to deal with Dependency injection:

in viewDidLoad :

override func viewDidLoad() {
    super.viewDidLoad()
    presenter = LoginPresenter(view: self)
}

This could give you an idea how to deal with that. Anyway you will have to figure out what is the best for your cause. If you are not using Dependency injection I strongly recommend it.

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