使用FBSDK登录,无法执行segue
Posted
技术标签:
【中文标题】使用FBSDK登录,无法执行segue【英文标题】:Login with FBSDK, cannot perform segue 【发布时间】:2015-10-16 10:44:25 【问题描述】:我已经安装了 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)
有人可以帮忙吗? 谢谢
【问题讨论】:
贴出用FB登录的代码。 我已经添加了相应的代码。谢谢 同样的问题,没有“漂亮”的解决方案。对此有何建议? 【参考方案1】:我一直在为同样的问题苦苦挣扎(尽管我使用的是FBSDKLoginManager
的logInWithReadPermissions
)。
虽然问题似乎是在关闭 Safari 网络视图之前调用了回调(或您的 didCompleteWithResult
委托调用),但我找不到一个好的解决方案。
我的(可怕的)答案是推迟转场,让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 source。幸运的是,我正在开发的应用程序要到新年才能发布,所以我希望这个问题可能会在以后的版本中得到解决。
【讨论】:
改进:检查self.view.window
是否为nil
。如果不是,您可以立即执行 segue。【参考方案2】:
您应该使用viewDidAppear()
函数并检查FBSDKAccessToken.currentAccessToken
:
override func viewDidAppear(animated:Bool)
if FBSDKAccessToken.currentAccessToken() != nil
performSegueWithIdentifier("YOUR_SEGUE",sender:self)
【讨论】:
viewDidAppear 在您加载后发生 - 但如果您从您的 VC 启动 FB 登录对话框,则在其解除后 viewDid/WillAppear 不会再次被调用(对我而言,至少在 ios13 中)。所以这个解决方案不适合我。【参考方案3】:我在使用 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
【讨论】:
【参考方案4】:我的解决方案类似于上面的解决方案,但它更具确定性(对我来说,更安全)。
此解决方案可确保我们在展示之前成为最顶尖的 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 中使用,但您可以将其转储到需要的地方)。
【讨论】:
以上是关于使用FBSDK登录,无法执行segue的主要内容,如果未能解决你的问题,请参考以下文章