【问题标题】:Function is not fired in dismiss completion block关闭完成块中未触发函数
【发布时间】:2018-01-20 17:55:32
【问题描述】:

所以我有一个视图控制器,当用户登录时它会被关闭。在关闭函数完成块中,我触发了一个应该重新加载下一个视图控制器的函数。没有任何反应,空白视图控制器。但是,如果我在已经登录的情况下关闭应用程序,然后重新打开它,一切都会正常加载。

这是我的登录功能:

func loginFunc() {

        if emailField.text != "" && passwordField.text != "" {

            Auth.auth().signIn(withEmail: emailField.text!, password: passwordField.text!, completion: { (user, error) in

                if user != nil {
                    // Sign In Successful
                    print("Sign In Sucessful")
                    self.dismiss(animated: true, completion: {
                        self.mainVC.starterMethod()
                    })
                } else {

                    if let myError = error?.localizedDescription {
                        print(myError)
                    } else {
                        print("Error")
                    }

                }

            })

        }

    }

这是我的starterMethod()

func starterMethod() {

        ref = Database.database().reference()

        let userId = Auth.auth().currentUser?.uid

        if userId != nil {
            print("You are logged in...")
        } else {
            present(LoginController(), animated: true, completion: nil)
        }

        setupPicks()
        setupViewsMed()
        fetchGames()
        setNavigationBar()
        setupCircles()

    }

starterMethod()viewDidLoad 中被调用

如果可能的话,我真的很想避免viewDidAppear()

【问题讨论】:

  • 你的completionBlock@escaping 了吗?如果是,你有内存泄漏(这很糟糕,但它应该可以工作,因为 self 被持久化在内存中并且可以访问mainVC。如果不是@escaping,你肯定会冻结 UI,并且不会有任何内存泄漏,但在关闭完成处理程序后,self 不再存在,因此 mainVC 不应该存在
  • 您甚至可以使用通知。委托听起来不错,就像其他人说的那样,但是身份验证比两个 VC 之间的钩子更抽象,用户成功登录后,发送通知,并在 MainVC 中添加观察者
  • @farzadshbfn 如何实现通知和观察者。你能帮我多一点吗? :)
  • 我目前无法访问我的电脑,但是这个帖子会给你一个基本的想法......stackoverflow.com/questions/2191594/…
  • @farzadshbfn 太棒了!谢谢

标签: ios swift


【解决方案1】:

在 iOS12 之前,如果没有 presentingViewController,则不会调用 dismiss(并且完成)。 在 iOS13+ 上 dismiss 不起作用,但它的完成被称为

【讨论】:

  • 嗨 Vadim Zhuk,你是怎么知道的? Apple 是否在某处记录了它?
  • 不,Apple 没有记录它 - mb 这是一个错误,但是这种方法(及其完成)应该只在模态呈现的情况下工作,同时调用完成(在 ios13+ ) 即使dismiss方法不起作用
  • 我注意到,当 isBeingDismissed 在 iOS 12 及更早版本上已经为 true 时,也不会调用完成。在 iOS 13 和更高版本上,isBeingDismissed 在交互式解雇期间为真(可以中止),因此最好依赖完成。
【解决方案2】:

为此,我认为委托方法最适合您。因为被解雇的视图控制器想要通知呈现视图控制器。

来自 Apple 的文档。

当需要关闭呈现的视图控制器时, 首选方法是让呈现视图控制器关闭 它。换句话说,只要有可能,同一个视图控制器 提出的视图控制器也应该负责 解雇它。虽然有几种技术可以通知 呈现视图控制器,其呈现的视图控制器应该 被解雇,首选技术是委托。

【讨论】:

    【解决方案3】:

    从你下面的代码

    self.dismiss(animated: true, completion: {
         self.mainVC.starterMethod()
    })
    

    从代码中我可以假设您在当前正在显示的类中创建了 mainVC (self.mainVC) 的实例。

    当前视图被驳回后,您可能会失去对 mainVC 的引用并导致问题。

    解决方案:

    您可以使用委托方法或通知来监听主vc中的事件。

    您需要在当前视图控制器中创建以下协议 @protocol LoginDoneProtocol { 函数 loginAndDismissed() } 确认您的 mainVC 中的协议,例如

    Class mainVC : UIViewCOntroller , LoginDoneProtocol {
    }
    

    您可以在 mainVC 中实现委托方法,在委托方法中调用您的方法来重置值

    func loginAndDismissed(){
        starterMethod()
    }
    

    在关闭视图控制器的完成块上,您可以简单地调用

    self.dismiss(animated: true, completion: {
    
    delegate.loginAndDismissed()
    
    })
    

    注意:当你的当前视图控制器出现时,你必须从你的 mainVC 将委托分配给当前视图控制器。

    您将获得很多关于如何创建委托的教程。

    【讨论】:

      【解决方案4】:

      我设法找出解决方案。我想这是最简单的方法并且非常可靠。

      首先我声明了一个常量:

      let LOGGED_IN_NOTIFICATION = NSNotification.Name("LoggedInNotification")
      

      然后在dismiss方法完成块中我添加了:

      NotificationCenter.default.post(name: LOGGED_IN_NOTIFICATION, object: nil)
      

      最后在mainVC's viewDidLoad方法中添加了一个观察者

      override func viewDidLoad() {
          super.viewDidLoad()
      
              NotificationCenter.default.addObserver(forName: LOGGED_IN_NOTIFICATION, object: nil, queue: nil) {
                  notification in
      
                  print("Logged in")
      
                  self.reset()
      
                  self.starterMethod()
      
              }
      
          self.starterMethod()
      
      }
      

      【讨论】:

        猜你喜欢
        • 2012-11-13
        • 2017-08-23
        • 1970-01-01
        • 1970-01-01
        • 2012-10-05
        • 1970-01-01
        • 1970-01-01
        • 2014-10-03
        • 2017-07-04
        相关资源
        最近更新 更多