IOS - Come seguire a livello di codice usando swift


185

Sto creando un'app che utilizza Facebook SDK per autenticare gli utenti. Sto cercando di consolidare la logica di Facebook in una classe separata. Ecco il codice (spogliato per semplicità):

import Foundation

class FBManager {
    class func fbSessionStateChane(fbSession:FBSession!, fbSessionState:FBSessionState, error:NSError?){
        //... handling all session states
        FBRequestConnection.startForMeWithCompletionHandler { (conn: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in

            println("Logged in user: \n\(result)");

            let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
            let loggedInView: UserViewController = storyboard.instantiateViewControllerWithIdentifier("loggedInView") as UserViewController

            loggedInView.result = result;

            //todo: segue to the next view???
        }
    }
}

Sto usando il metodo di classe sopra per verificare le modifiche allo stato della sessione e funziona benissimo.

D: Una volta che ho i dati dell'utente, come posso passare alla vista successiva all'interno di questa classe personalizzata?

EDIT: solo per essere chiari, ho un seguito con identificatore nello storyboard e sto cercando di trovare un modo per eseguire un seguito da una classe che non è il controller di visualizzazione


2
Come performSegue:?
È il

Sì, ma il codice non è nel viewController, come posso ottenerlo?
Shlomi Schwartz,

Bene, in quel caso dovresti delegare quel lavoro (il seguente) dall'oggetto in cui fai il lavoro al controller della vista (tramite un blocco di completamento o un metodo delegato).
HA

ottenendo un'eccezione di layout non nulla
Chris Hayes,

Risposte:


340

Se il tuo seguito esiste nello storyboard con un identificatore segue tra le tue due viste, puoi semplicemente chiamarlo a livello di codice usando:

performSegue(withIdentifier: "mySegueID", sender: nil)

Per le versioni precedenti:

performSegueWithIdentifier("mySegueID", sender: nil)

Puoi anche fare:

presentViewController(nextViewController, animated: true, completion: nil)

O se ti trovi in ​​un controller di navigazione:

self.navigationController?.pushViewController(nextViewController, animated: true)

7
Grazie per la risposta, come posso chiamare performSegueWithIdentifier da una classe personalizzata che non è la vista?
Shlomi Schwartz,

2
Se uso il tuo secondo metodo. Come passare i dati alla vista successiva?
iamprem,

2
Dovresti usare func PrepForSegue (segue: UIStoryboardSegue, mittente: AnyObject?) E impostare le proprietà.
Lloyd Sargent,

1
Nota quando si chiama performSequeWithIdentifer (), verrà chiamata un'implementazione di preparForSeque () nel controller chiamante e si possono fare vari dati che vi passano - in effetti, il parametro mittente ricevuto in preparForSeque () è semplicemente ciò che viene passato al parametro mittente in performSequeWithIdentifier ()
timbo

1
Cosa succede se il seguito non esiste nello storyboard? Ad esempio, se si desidera creare un seguito per ViewController stesso?
spaventoso

20

È possibile utilizzare NSNotification

Aggiungi un metodo post nella tua classe personalizzata:

NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)

Aggiungi un osservatore nel tuo ViewController:

NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOFReceivedNotication:", name:"NotificationIdentifier", object: nil)

Aggiungi funzione nel tuo ViewController:

func methodOFReceivedNotication(notification: NSNotification){
    self.performSegueWithIdentifier("yourIdentifierInStoryboard", sender: self)
}

1
Si prega di non abusare di notifiche come questa. Utilizzare un delegato e rendere esplicita la connessione tra il controller della vista e la propria classe. È quasi impossibile osservare il flusso di controllo di una notifica, perché potrebbero esserci più abbonati e le istanze possono iscriversi / annullare l'iscrizione a piacimento.
uliwitness,

17

Se il tuo seguito esiste nello storyboard con un identificatore segue tra le tue due viste, puoi semplicemente chiamarlo a livello di codice usando

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

Se ti trovi nel controller di navigazione

let viewController = YourViewController(nibName: "YourViewController", bundle: nil)        
self.navigationController?.pushViewController(viewController, animated: true)

Ti consiglierò per il secondo approccio usando il controller di navigazione.


self.performSegue (withIdentifier: "yourIdentifierInStoryboard", mittente: self)
Rajneesh071

14

Puoi usare segue in questo modo:

self.performSegueWithIdentifier("push", sender: self)
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    if segue.identifier == "push" {

    }
}

Grazie per la risposta, tuttavia performSegueWithIdentifier è un metodo viewController e il mio codice viene eseguito in una classe esterna
Shlomi Schwartz,

13

Swift 3 - Funziona anche con SpriteKit

È possibile utilizzare NSNotification .

Esempio:

1.) Crea un seguito nello storyboard e dai un nome all'identificatore "segue"

2.) Creare una funzione nel ViewController da cui si sta seguendo.

func goToDifferentView() {

    self.performSegue(withIdentifier: "segue", sender: self)

}

3.) Nel ViewDidLoad () del ViewController stai seguendo la creazione dell'osservatore.

NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: "segue" as NSNotification.Name, object: nil)

Aggiornamento - L'ultima volta che l'ho usato ho dovuto cambiare la .addObserverchiamata al seguente codice per silenziare gli errori.

NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: NSNotification.Name(rawValue: "segue"), object: nil)

4.) Nel ViewController o nella scena a cui stai seguendo, aggiungi il metodo Post ovunque desideri che il seguito venga attivato.

NotificationCenter.default.post(name: "segue" as NSNotification.Name, object: nil)

Aggiornamento - L'ultima volta che l'ho usato ho dovuto cambiare la .postchiamata al seguente codice per silenziare gli errori.

NotificationCenter.default.post(NSNotification(name: NSNotification.Name(rawValue: "segue"), object: nil) as Notification)

Swift 3:NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: NSNotification.Name(rawValue: "segue"), object: nil)
Michael Samoylov,

3

Quello che vuoi fare è davvero importante per i test unitari. Fondamentalmente è necessario creare una piccola funzione locale nel controller di visualizzazione. Assegna un nome alla funzione, includi semplicemente il performSegueWithIndentifier.

func localFunc() {
    println("we asked you to do it")
    performSegueWithIdentifier("doIt", sender: self)
}

Successivamente cambia la tua classe di utilità FBManager per includere un inizializzatore che accetta un argomento di una funzione e una variabile per contenere la funzione di ViewController che esegue i seguenti.

public class UtilClass {

    var yourFunction : () -> ()

    init (someFunction: () -> ()) {
        self.yourFunction = someFunction
        println("initialized UtilClass")
    }

    public convenience init() {
        func dummyLog () -> () {
            println("no action passed")
        }
        self.init(dummyLog)
    }

    public func doThatThing() -> () {
        // the facebook login function
        println("now execute passed function")
        self.yourFunction()
        println("did that thing")
    }
}

(La convenienza init ti consente di usarlo nel test unitario senza eseguire il seguente.)

Infine, dove hai // todo: segue la vista successiva ???, metti qualcosa sulla falsariga di:

self.yourFunction()

Nei test unitari, puoi semplicemente invocarlo come:

let f = UtilClass()
f.doThatThing()

dove doThatThing è il tuo cambio di sessione e UtilClass è FBManager.

Per il tuo codice attuale, passa localFunc(senza parentesi) alla classe FBManager.


2

Questo ha funzionato per me.

Prima di tutto, dai al controller della vista nello storyboard un ID storyboard all'interno della finestra di ispezione identità. Quindi utilizza il seguente codice di esempio (assicurandoti che la classe, il nome dello storyboard e l'ID della storyboard corrispondano a quelli che stai utilizzando):

let viewController:
UIViewController = UIStoryboard(
    name: "Main", bundle: nil
).instantiateViewControllerWithIdentifier("ViewController") as UIViewController
// .instantiatViewControllerWithIdentifier() returns AnyObject!
// this must be downcast to utilize it

self.presentViewController(viewController, animated: false, completion: nil)

Per maggiori dettagli vedi http://sketchytech.blogspot.com/2012/11/instantiate-view-controller-using.html migliori auguri


1

Puoi fare questa cosa usando la performSegueWithIdentifierfunzione.

Immagine dello schermo

Sintassi:

func performSegueWithIdentifier(identifier: String, sender: AnyObject?)

Esempio :

 performSegueWithIdentifier("homeScreenVC", sender: nil)

1

Un'altra opzione è quella di utilizzare segue modale

PASSAGGIO 1: vai allo storyboard e assegna a View Controller un ID storyboard . Puoi trovare dove modificare l'ID dello storyboard nella finestra di ispezione identità a destra. Consente di chiamare l'ID storyboardModalViewController

PASSAGGIO 2: apri il controller di visualizzazione "mittente" (chiamiamolo ViewController) e aggiungi questo codice

public class ViewController {
  override func viewDidLoad() {
    showModalView()
  }

  func showModalView() {
    if let mvc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ModalViewController") as? ModalViewController {
      self.present(mvc, animated: true, completion: nil)
    }
  }
}

Si noti che viene chiamato anche il View Controller che vogliamo aprire ModalViewController

PASSAGGIO 3: per chiudere ModalViewController, aggiungerlo ad esso

public class ModalViewController {
   @IBAction func closeThisViewController(_ sender: Any?) {
      self.presentingViewController?.dismiss(animated: true, completion: nil)
   }
}

0

Questo ha funzionato per me:

//Button method example
 @IBAction func LogOutPressed(_ sender: UIBarButtonItem) {

        do {
            try Auth.auth().signOut()
            navigationController?.popToRootViewController(animated: true)

        } catch let signOutError as NSError {
          print ("Error signing out: %@", signOutError)
        }


    }
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.