3

我已经安装了Facebook SDK,符合所有要求,它可以从用户的 Facebook 帐户中提取数据,但是一旦登录我就无法执行 segue。

我收到一条错误消息:

警告:Attempt to present <viewController1> on <FBSDKContainerViewController> whose view is not in the window hierarchy!

这是我的代码:

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.


    if (FBSDKAccessToken.currentAccessToken() == nil) {

        print("not logged in")
    }
    else {

        print("logged in")
    }


    let loginButton = FBSDKLoginButton()
    loginButton.readPermissions = ["public_profile", "email", "user_friends"]
    loginButton.center = self.view.center
    loginButton.delegate = self
    self.view.addSubview(loginButton)
}

 func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {


    if ((error) != nil)
    {

    }
    else if result.isCancelled {

    }
    else {

         if result.grantedPermissions.contains("email")
        {
            // Do work

            returnUserData()
            addViewHierarchy()

          //  self.performSegueWithIdentifier("signUpFollowPage", sender: self)


        }
    }
}

任何人都可以帮忙吗?谢谢

4

4 回答 4

7

我一直在努力解决同样的问题(尽管我正在使用FBSDKLoginManager's logInWithReadPermissions)。

虽然问题似乎是didCompleteWithResult在关闭 Safari Web 视图之前调用了回调(或您的委托调用),但我找不到一个好的解决方案。

我的(可怕的)答案是推迟转场,给FBSDKContainerViewController时间自然地解雇。在你的情况下:

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC))), dispatch_get_main_queue(), { () -> Void in
    self.performSegueWithIdentifier("signUpFollowPage", sender: self)
}

有可能以更短的延迟逃脱。

这让我觉得这是 Facebook 登录 SDK 的一个错误。如果我有时间,我可能会查看SDK 源代码。幸运的是,我正在开发的应用程序要到新的一年才能发布,所以我希望这个问题可能会在以后的版本中得到解决。

于 2015-10-28T17:27:21.573 回答
1

您应该使用该viewDidAppear()功能并检查FBSDKAccessToken.currentAccessToken

override func viewDidAppear(animated:Bool){
  if FBSDKAccessToken.currentAccessToken() != nil{
     performSegueWithIdentifier("YOUR_SEGUE",sender:self)
  }
}
于 2016-04-08T00:36:18.620 回答
0

我的解决方案类似于上面的解决方案,但它更具确定性(对我来说,更安全)。

这个解决方案确保我们在展示之前是最顶尖的 VC。

                Timer.scheduledTimer(withTimeInterval: 0.01 / 30.0, repeats: true, block: { (timer) in
                if let app = UIApplication.shared.delegate as? AppDelegate, let window = app.window, let rootVC = window.rootViewController {
                    var topController = rootVC
                    while let nextTop = topController.presentedViewController {
                        topController = nextTop;
                    }
                    if topController == self {
                        // we're good, go for it
                        self.performSegue(withIdentifier: "afterLoginSegue", sender: nil)
                        timer.invalidate()
                    } else {
                        log.debug("waiting to transition until we're presenting...")
                    }
                } else {
                    log.error("couldn't resolve a key variable needed to segue, aborting.")
                    timer.invalidate()
                }
            })

我仍然觉得应该有一种方法可以在呈现的 facebook 登录 safari VC 消失后获得回调,但是在该解决方案出现之前,我可以做到这一点(显然,这段代码可以被清理和模块化以供使用在多个 VC 中,但您可以将其转储到需要的地方)。

于 2019-10-01T22:03:22.283 回答
0

我在使用 FB 登录时遇到了同样的问题。这是我解决它的方法。问题是在导航时,FBContainerView 仍然打开。使用 self.controller 将引用 FBContainerView 而不是 Topmost 控制器,因此没有导航。我们将需要切换回最顶部的控制器,然后执行导航。

您可以通过像这样从顶级控制器呈现视图控制器来执行此操作而无需执行 segue

let topController = self.topMostController()
topController.presentViewController(secondController, animated: true, completion: nil)

要获得最顶层的控制器,请定义一个始终返回最顶层控制器的方法

func topMostController()-> UIViewController {
    var topController = UIApplication.sharedApplication().keyWindow?.rootViewController

    while((topController?.presentedViewController) != nil){
        topController = topController?.presentedViewController
    }
    if(topController != nil){
        return topController!
    }
    else{
        return self
    }

}
于 2016-02-18T06:49:09.640 回答