Swift转场无效?

3

我的Swift segue完全不起作用,也没有任何错误提示。断点显示应用程序停在这一行,但什么都没有发生:

self.performSegueWithIdentifier("SignupSegue", sender: self)

代码块是一个使用Facebook进行登录的表单:
if let accessToken: FBSDKAccessToken = FBSDKAccessToken.currentAccessToken() {
    PFFacebookUtils.logInInBackgroundWithAccessToken(result.token, block: {
        (user: PFUser ? , error : NSError ? ) - > Void in
        if user!.isNew {
            self.performSegueWithIdentifier("SignupSegue", sender: self)
        } else {
            self.navigateToInGame(true)
        }
    })
}

这里是segue应该调用的函数,但它甚至无法到达此处:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
    {
        if (segue.identifier == "SignupSegue") {
            let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
            let vc = storyboard.instantiateViewControllerWithIdentifier("SignUpViewController") 
            self.showViewController(vc, sender: self)
        }
    }

有什么想法吗?

我只是想澄清一下,为什么在Storyboard中设置segue后需要显示viewController?您可能没有使用标识符“SignupSegue”设置segue。因此,请仔细检查。如果我错了,请纠正我。 - Boopathy
好的,我明白了。我注释掉了“showViewController”这一行(我从谷歌搜索中得到了这个)。我只是想建立一个从一个故事板到另一个故事板的segue。即使我注释掉了那个,仍然会出现错误。谢谢! - winston
6个回答

3

一般来说,任何 UI 更新都必须在主线程中进行。我认为在上述情况下,PFFacebookUtils.logInInBackgroundWithAccessToken 的块仍处于后台状态。也许可以尝试在 dispatch_async(dispatch_get_main_queue(), {}) 中触发 showViewController,看看是否有任何不同。

dispatch_async(dispatch_get_main_queue(), {
    let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
    let vc = storyboard.instantiateViewControllerWithIdentifier("SignUpViewController")
    self.showViewController(vc, sender: self)
})

派发确实有帮助!现在我收到一个错误 LoginViewController has no segue with identifier 'SignupSegue。通常情况下,当我在故事板中没有绘制segue时,我会看到这个错误。然而,由于它们是单独的故事板,我希望 if identifier 函数可以通过编程方式完成这个操作。我错过了什么吗? - winston
如果我理解得没错的话,@james ,你是说你有一个单独的Storyboard,它的名字不是"Main",是吗? UIStoryboard(name: "SomethingElse", bundle: nil) - Allen
抱歉,我有Main.storyboard和Login.storyboard。 我想将LoginViewController(Login.storyboard)转换到SignUpViewController(Main.storyboard)。 - winston
我设置了ID,但它没有起作用。错误显示找不到segue,所以我认为Storyboard ID已经正确设置了。我很困惑为什么它找不到segue,即使我在函数中已经设置好了:/ - winston
@james 嗯,这应该非常直接。我刚刚创建了一个样例项目,你可以在这里下载它作为参考 https://db.tt/LLPH8Kvh - Allen
显示剩余5条评论

2

好的,我刚试了一下。希望你已经完成了StoryBoard Reference相关的所有工作。我也遇到了performSegueWithIdentifier的同样问题。

例如:假设有两个故事板mainsignup

1) 在main.storyboard中创建一个Storyboard Reference。将Storyboard Reference中的storyboardId设置为signup,并将referencedId设置为位于signup.storyboard中的场景(viewController)的storyboardId。点击此链接以查看清晰的图片:从Storyboard到Storyboard

2) 在main.storyboard中,在viewControllerStoryboard Reference之间设置segue标识符。

3) 由于我遇到了与performSegueWithIdentifier相同的问题,因此我用shouldPerformSegueWithIdentifier替换了它。

override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
    if(identifier == "segue_identifier"){
       // segue_identifier is the viewController and storyBoard Reference segue identifier.
        print("hello")
    }
    return true;
}

如果你发现任何问题,请告诉我。对我而言,它是有效的。


1

执行segue将呈现一个新的视图控制器。您不需要在prepareForSegue中创建和显示视图控制器。它看起来像这样:

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
    {
        if (segue.identifier == "SignupSegue") {

            let vc = segue.destinationViewController

        }
    }

@james 你可以使用故事板引用(适用于iOS 8及以上版本)。否则,你将无法在故事板之间使用segue。 - Lumialxk
哦,好的...我在想是否应该将所有内容都合并到我的主故事板上。 - winston
@james 别这么做,我试过,当你打开故事板文件时 Xcode 会变得非常非常慢(花费了我三分钟)。 - Lumialxk
为了尝试一下,我将LoginViewController移动到了Main storyboard中。即使两个控制器在同一个segue中,self.performSegueWithIdentifier("SignupSegue", sender: self)仍然会产生错误LoginViewController has no segue with identifier 'SignupSegue''。感到很困惑。 - winston
我认为 dispatch_async(dispatch_get_main_queue(), { self.performSegueWithIdentifier("SignupSegue", sender: self) }) 可能会出问题。但如果我不使用它,那么应用程序根本不会运行这行代码。 - winston
显示剩余2条评论

0

你可以尝试这个...

override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
    {
    if (segue.identifier == "SignupSegue") {
        if let destination = segue.destination as? SignUpViewController {
         ...
        }

    }
}

请编辑您的答案,解释这段代码为什么回答了问题。 - André Kool
因为我认为这些不是必需的。 --> 让storyboard:UIStoryboard = UIStoryboard(name:“Main”,bundle:nil) 让vc = storyboard.instantiateViewControllerWithIdentifier(“SignUpViewController”) - Ali Ihsan URAL

0

我能够克服同样的问题的最接近方法是:

在类中创建触发器var segueLogin : Bool = false并初始化值。

当PFFacebookUtils获取所需的segue值时,将触发器更改为true:

PFFacebookUtils.logInInBackground(withReadPermissions: permissions) {
            (user: PFUser?, error: Error?) -> Void in
            if let user = user {
                if user.isNew {
                    print("User signed up and logged in through Facebook!")
                    self.segueLogin = true

                } else {
                    print("User logged in through Facebook!")
                    self.segueLogin = true
                }
            } else {
                print("Uh oh. The user cancelled the Facebook login.")
                self.loginCancelledLabel.alpha = 1
            }
        }

然后在 viewDidAppear 类中添加了代码。发现它每次都会在 PFFacebookUtils 完成后启动。因此,它会检查返回值是否为 true,并在成功的 PFFacebookUtils 会话后执行 segue:

override func viewDidAppear(_ animated: Bool) {
        if segueLogin == true {
            self.performSegue(withIdentifier: "segueSingup", sender: self)
        }
    }

0

Swift 3 已解决:

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
            if (segue.identifier == "SignupSegue") {
                DispatchQueue.main.async {
                    let storyboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
                    let vc = storyboard.instantiateViewController(withIdentifier: "SignUpViewController")
                    self.show(vc, sender: self) 
                }
          }
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接