自从更新到Xcode 9(和iOS 11)

时间:2017-10-27 16:51:41

标签: ios11 xcode9

在我的应用程序上,我有一个启动画面,用于检查用户是否已使用Facebook登录。如果不是,则启动屏幕会将登录屏幕推送到导航堆栈。如果用户已登录,则启动屏幕也会按下登录屏幕,但在登录屏幕的viewDidAppear上调用一个推送主应用程序屏幕的方法。

因此,当用户登录时,我应该在我的应用程序上看到以下视图控制器堆栈:

SplashViewController > LoginViewController > MainViewController.

此流程在iOS 9和iOS 10上没有问题。

然而,自从我升级到iOS 11后,此流程停止了工作。

现在,如果用户已登录,则主视图控制器不会出现,只有登录视图控制器仍然可见。我检查了调试器,确实调用了主应用程序屏幕上的performSegue。

有两个奇怪的细节。首先,此登录视图控制器上的按钮不再起作用(有一个按钮从FacebookLogin SDK调用Facebook登录流程)。

第二个是如果我去Xcode并点击" Debug View Hierarchy"按钮,当Xcode处理并创建视图层次时,主视图控制器突然出现在我的应用程序上。

似乎正在推动主视图控制器,但其视图未被呈现;所以LoginViewController上的segue不再工作了。但是,按下" Debug View Hierarchy"似乎触发了更新视图层次结构的东西。

我正在使用Xcode 9.0.1。这个问题在Xcode模拟器和目前运行iOS 11.0.3的iPad Mini 2上都有发生。

感谢。

1 个答案:

答案 0 :(得分:1)

我不知道为什么会发生这种情况,但我能够通过以下方式解决这个问题。

在SplashViewController上,我将直接 segue调用到登录视图控制器,这将调用viewWillAppear()方法上的另一个segue,我强制在主队列上执行segue:

// SplashViewController
struct Identifier {
    static let login = "Login"
    static let direct = "Direct"
}

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    login()
}

func login() {
    // If there already exists a Facebook token we try to login directly.
    if let accessToken = AccessToken.current {
         bm.login(facebookToken: accessToken.authenticationToken, completion: { (error, user) in
            guard error == nil else {
                self.performSegue(withIdentifier: Identifier.login, sender: self)
                return
            }
            // This call on the main queue wasn't needed on iOS 10
            DispatchQueue.main.async {
                self.performSegue(withIdentifier: Identifier.direct, sender: self)
            }
        })
    } else {
        performSegue(withIdentifier: Identifier.login, sender: self)
    }
}

然后在LoginViewController上:

// LoginViewController
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    if direct {
        // Without calling the previous segue on the main queue this 
        // segue would be called but the pushed view controller's 
        // view would not appear on the screen until a refresh event 
        // was triggered.
        self.performSegue(withIdentifier: Identifier.direct, sender: nil)
    }
}