我试图在用户成功登录到他们的帐户后切换视图控制器,但它无法正常工作。我不能直接使用segue,因为如果单击登录按钮,它将转到该视图控制器,无论信息是否正确。我已经尝试了所有我知道但没有成功的事情。这是我正在尝试的代码。
@IBAction func loginTapped(sender: AnyObject) {
let username = usernameField.text
let password = passwordField.text
if username.isEmpty || password.isEmpty {
var emptyFieldsError:UIAlertView = UIAlertView(title: "Please try again", message: "Please fill in all the fields we can get you logged in to your account.", delegate: self, cancelButtonTitle: "Try again")
emptyFieldsError.show()
}
PFUser.logInWithUsernameInBackground(username, password:password) {
(user: PFUser?, error: NSError?) -> Void in
if user != nil {
self.performSegueWithIdentifier("Klikur", sender: self)
} else {
if let errorString = error!.userInfo?["error"] as? String {
self.errorMessage = errorString
}
self.alertView("Please try again", message: "The username password combiation you have given us does not match our records, please try again.", buttonName: "Try again")
}
}
}
我将故事板ID设置为"测试"当输入正确的信息时,它不会切换视图控制器。有人可以帮我解决我的问题吗?
答案 0 :(得分:66)
[假设你的代码没有崩溃,而是只是没有发生错误]
至少有一个问题是:
self.performSegueWithIdentifier("Test", sender: self)
应该是:
dispatch_async(dispatch_get_main_queue()) {
[unowned self] in
self.performSegueWithIdentifier("Test", sender: self)
}
请记住,必须在主线程的队列上执行所有UI操作。你可以通过检查来证明你自己错了!
NSThread.isMainThread() // is going to be false in the PF completion handler
<强>附录强>
如果有任何机会self
可能变为零,例如因为不需要而被解雇或以其他方式解除分配,则应该将自我弱化为[weak self]
而不是unowned
,并使用安全解包:if let s = self { s.doStuff() }
或可选链接:self?.doStuff(...)
ADDENDUM 2
这似乎是一个受欢迎的答案,所以在这里提到这个更新的替代方案很重要:
NSOperationQueue.mainQueue().addOperationWithBlock {
[weak self] in
self?.performSegueWithIdentifier("Test", sender: self)
}
注意,来自https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-swift:
NSOperation vs. Grand Central Dispatch(GCD)
GCD [dispatch_ * calls]是一种轻量级方式,用于表示将要同时执行的工作单元。
与GCD相比,NSOperation增加了一些额外的开销,但您可以在各种操作之间添加依赖关系并重新使用,取消或暂停它们。
ADDENDUM 3
Apple隐藏了单线程规则:
请注意
在大多数情况下,只能从应用程序的主线程中使用UIKit类。 对于从UIResponder或其派生的类来说尤其如此 涉及以任何方式操纵您的应用程序的用户界面。
SWIFT 4
DispatchQueue.main.async(){
self.performSegue(withIdentifier: "Test", sender: self)
}
参考:
答案 1 :(得分:18)
我在登录问题上遇到了同样的问题。可能我们做同样的教程。在命名segue标识符后,您需要替换:
performSegueWithIdentifier("Klikur", sender: self)
使用:
dispatch_async(dispatch_get_main_queue()){
self.performSegueWithIdentifier("Klikur", sender: self)
}
需要将类型的seque设置为&#34; show(例如Push)&#34;在故事板segue。 希望它能奏效。
答案 2 :(得分:12)
确保您放置:
self.performSegue(withIdentifier: ..., ...)
在viewDidAppear或更高版本中。它无法在viewWillAppear或viewDidLoad中工作。
答案 3 :(得分:8)
您传递给performSegueWithIdentifier(_:sender:)
的segue标识符必须完全与您在故事板中为segue指定的ID匹配。我假设您在登录视图控制器和成功视图控制器之间有一个segue,它应该是这样的;如果没有,则从第一个视图控制器中按住ctrl +拖动,然后在故事板中选择segue的图标并将其ID设置为Klikur
。正如一位评论者所说,不要在按钮点击上执行导航,因为这违背了设置segues的主要目的,即提供应用程序的 visual 指示在故事板中流动。
编辑:这是登录视图控制器的代码:
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var usernameField: UITextField!
@IBOutlet weak var passwordField: UITextField!
@IBAction func attemptLogin(sender: AnyObject) {
if !usernameField!.text!.isEmpty && !passwordField!.text!.isEmpty {
performSegueWithIdentifier("Klikur", sender: self)
}
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if "Klikur" == segue.identifier {
// Nothing really to do here, since it won't be fired unless
// shouldPerformSegueWithIdentifier() says it's ok. In a real app,
// this is where you'd pass data to the success view controller.
}
}
}
答案 4 :(得分:7)
swift 3.x
DispatchQueue.main.async(){
self.performSegue(withIdentifier: "Klikur", sender: self)
}
答案 5 :(得分:4)
)
答案 6 :(得分:1)
检查以确保在可见的视图控制器上运行perform segue。
这是一个边缘情况,但当我尝试在属于我当前不可见的UIPageViewController的视图控制器上运行时,我的执行segue失败了。如果我试图在属于我的UIPageViewController的所有视图控制器上执行segue,包括当前可见的视图控制器,它也会失败。修复是跟踪我的UIPageViewController中当前可见的视图控制器,并且只在该视图控制器上执行segue。
答案 7 :(得分:1)
登录中的示例。单击按钮(操作)后,如果登录成功,可以使用:
self.performSegue(withIdentifier: "loginSucess", sender: nil)
但是如果您要启动应用程序并且从钥匙链获得凭据,则需要将其用作theard的一部分:
DispatchQueue.main.async(){
self.performSegue(withIdentifier: "sessionSuccess", sender: nil)
}