3

Facebook SDKをインストールし、すべての要件に従っています。ユーザーの Facebook アカウントからデータを抽出できるので動作しますが、ログインするとセグエを実行できません。

エラー メッセージが表示されます。

警告: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 ログイン サファリ VC がなくなったら、コールバックを取得する方法があるはずだとまだ感じていますが、その解決策が実現するまで、これは私ができる限り良いことです (明らかに、このコードはクリーンアップされ、モジュール化されて使用される可能性があります)。複数のVCで、必要な場所にこれをダンプできます)。

于 2019-10-01T22:03:22.283 に答える
0

FBでログインしているときに同じ問題に直面しました。これが私がそれを解決した方法です。問題は、ナビゲート中に、FBContainerView がまだ開いていることです。self.controller を使用すると、最上位のコントローラーではなく FBContainerView が参照されるため、ナビゲーションは行われません。一番上の Most Controller に戻り、ナビゲーションを実行する必要があります。

このようにトップコントローラーからビューコントローラーを提示することにより、セグエを実行せずにこれを行うことができます

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 に答える