web-dev-qa-db-ja.com

Swift performSegueWithIdentifierが機能しない

ユーザーがアカウントに正常にログインした後、View Controllerを切り替えようとしていますが、正しく機能していません。ログインボタンをクリックすると、情報が正しいかどうかに関係なく、そのView Controllerに移動するため、セグエを直接使用できません。知っていることはすべて試したが成功しなかった。これは私が試しているコードです。

   @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を「テスト」に設定していますが、正しい情報が入力されたときにView Controllerが切り替わりません。誰かが私の問題を解決するのを手伝ってくれますか?

Here is the code for the LoginViewControllerHere is the attributes panel for the KlikurTableViewController

37
Trenton Tyler

[コードがクラッシュせず、単にセグエに失敗すると仮定する]

少なくとも1つの問題は次のとおりです。

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がnilになってしまう可能性がある場合は、unownedではなく[weak self]として自分自身を弱くキャプチャし、安全なアンラップ:if let s = self { s.doStuff() }またはオプションのチェーン:self?.doStuff(...)を使用する必要があります

補遺2

これは一般的な回答のようですので、ここでこの新しい代替案について言及することが重要です:

NSOperationQueue.mainQueue().addOperationWithBlock {
     [weak self] in
     self?.performSegueWithIdentifier("Test", sender: self)
}

注: https://www.raywenderlich.com/76341/use-nsoperation-nsoperationqueue-Swift

NSOperation対Grand Central Dispatch(GCD)

GCD [dispatch_ * calls]は、同時に実行される作業単位を表す軽量な方法です。

NSOperationはGCDと比較して少し余分なオーバーヘッドを追加しますが、さまざまな操作に依存関係を追加し、それらを再利用、キャンセル、または一時停止できます。

補遺3

Appleはここでシングルスレッドルールを隠しています。

注意

ほとんどの場合、アプリのメインスレッドからのみUIKitクラスを使用します。これは、UIResponderから派生したクラス、またはアプリのユーザーインターフェースを何らかの方法で操作するクラスに特に当てはまります。

Swift 4

DispatchQueue.main.async(){
   self.performSegue(withIdentifier: "Test", sender: self)
}

参照:

https://developer.Apple.com/documentation/uikit

67
BaseZen

ログインの問題にも同じ問題があります。おそらく同じチュートリアルを行います。セグエ識別子に名前を付けたら、次のものを置き換える必要があります。

performSegueWithIdentifier("Klikur", sender: self)

で:

dispatch_async(dispatch_get_main_queue()){

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

}

シークのタイプは、ストーリーボードセグエで「show(e.g. Push)」として設定する必要があります。それがうまくいくことを願っています。

18
Mette

次のものを入れていることを確認してください:self.performSegue(withIdentifier: ..., ...)

viewDidAppear以降。 viewWillAppearまたはviewDidLoadでは機能しません。

13
GregJaskiewicz

performSegueWithIdentifier(_:sender:)に渡すセグエ識別子はexactlyストーリーボードでセグエに指定したIDと一致する必要があります。ログインビューコントローラーと成功ビューコントローラーの間にセグエがあると仮定します。そうでない場合は、Ctrlキーを押しながら最初のView Controllerから2番目のView Controllerにドラッグし、ストーリーボードでセグエのアイコンを選択し、そのIDをKlikurに設定します。 Do n'tボタンクリックでナビゲーションを実行します。これは、セグエを持つ主な目的を無効にするためです。これは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.
        }
    }

}

そして、私が話しているセグエプロパティのスクリーンショット: enter image description here

8
NRitH

Swift 3.x

DispatchQueue.main.async(){
    self.performSegue(withIdentifier: "Klikur", sender: self)
}
7
Felecia Genet
DispatchQueue.main.async() {
    self.performSegue(withIdentifier: "GoToHomeFromSplash", sender: self)`  
}
4
ibk

表示されているView Controllerで実行セグエを実行していることを確認してください。

これはEdgeの場合ですが、現在表示されていないUIPageViewControllerに属するView Controllerで実行しようとすると、実行セグエが失敗しました。また、現在表示されているView Controllerを含む、UIPageViewControllerに属するすべてのView Controllerでセグエを実行しようとしても失敗しました。修正は、UIPageViewControllerで現在どのView Controllerが表示されているかを追跡し、そのView Controllerでのみセグエを実行することでした。

1
Justin Domnitz

ログインの例。ボタン(アクション)をクリックした後、ログインに成功すると、次を使用できます。

self.performSegue(withIdentifier: "loginSucess", sender: nil)

ただし、アプリを起動し、キーチェーンから資格情報を取得した場合は、これを一部として使用する必要があります。

DispatchQueue.main.async(){
    self.performSegue(withIdentifier: "sessionSuccess", sender: nil)
}
1
Ppillo