IOS - Cara memisahkan secara terprogram menggunakan swift

185

Saya membuat aplikasi yang menggunakan SDK Facebook untuk mengautentikasi pengguna. Saya mencoba untuk mengkonsolidasikan logika facebook di kelas yang terpisah. Berikut adalah kode (dilucuti untuk kesederhanaan):

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???
        }
    }
}

Saya menggunakan metode kelas di atas untuk memeriksa perubahan status sesi, dan berfungsi dengan baik.

T: Setelah saya memiliki data pengguna, bagaimana saya bisa memisahkan ke tampilan berikutnya dari dalam kelas khusus ini?

EDIT: hanya untuk memperjelas, saya memiliki segue dengan pengenal di storyboard, dan saya mencoba menemukan cara untuk melakukan segue dari kelas yang bukan pengontrol tampilan

Shlomi Schwartz
sumber
2
Suka performSegue:?
TELAH
Ya, tetapi kodenya tidak ada di viewController, bagaimana saya bisa mencapai ini?
Shlomi Schwartz
Nah, dalam hal ini Anda harus mendelegasikan pekerjaan itu (segueing) dari objek yang Anda lakukan pekerjaan ke controller tampilan (melalui blok penyelesaian atau metode delegasi).
TELAH
mendapatkan pengecualian tata letak nihil
Chris Hayes

Jawaban:

340

Jika segue Anda ada di storyboard dengan pengenal segue antara dua tampilan Anda, Anda bisa menyebutnya pemrograman menggunakan:

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

Untuk versi yang lebih lama:

performSegueWithIdentifier("mySegueID", sender: nil)

Anda juga bisa:

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

Atau jika Anda berada di pengontrol Navigasi:

self.navigationController?.pushViewController(nextViewController, animated: true)
Jérôme
sumber
7
Terima kasih atas jawabannya, bagaimana saya bisa memanggil performSegueWithIdentifier dari kelas kustom yang bukan tampilan?
Shlomi Schwartz
2
Jika saya menggunakan metode kedua Anda. Bagaimana cara mengirimkan data ke tampilan berikutnya?
iamprem
2
Anda akan menggunakan func prepForSegue (segue: UIStoryboardSegue, pengirim: AnyObject?) Dan atur propertinya.
Lloyd Sargent
1
Catatan saat memanggil performSequeWithIdentifer (), implementasi dari prepForSeque () di pengontrol panggilan Anda akan dipanggil dan Anda dapat melakukan berbagai data yang lewat di sana - pada kenyataannya, parameter pengirim yang diterima di prepForSeque () hanyalah apa yang dilewatkan ke parameter pengirim di performSequeWithIdentifier ()
timbo
1
Bagaimana jika segue tidak ada di storyboard? Misalnya, jika Anda ingin membuat segue ke ViewController sendiri?
scaryguy
20

Anda dapat menggunakan NSNotification

Tambahkan metode posting di kelas khusus Anda:

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

Tambahkan pengamat di ViewController Anda:

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

Tambahkan fungsi di ViewController Anda:

func methodOFReceivedNotication(notification: NSNotification){
    self.performSegueWithIdentifier("yourIdentifierInStoryboard", sender: self)
}
Rodrigo Otero
sumber
1
Tolong jangan penyalahgunaan pemberitahuan seperti ini. Gunakan delegasi dan buat koneksi antara pengontrol tampilan dan kelas Anda secara eksplisit. Hampir tidak mungkin untuk mengamati aliran kontrol pemberitahuan, karena mungkin ada beberapa pelanggan, dan mesin virtual dapat berlangganan / berhenti berlangganan sesuka hati.
uliwitness
17

Jika segue Anda ada di storyboard dengan pengenal segue di antara dua tampilan Anda, Anda bisa menyebutnya pemrograman menggunakan

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

Jika Anda berada di pengontrol Navigasi

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

Saya akan merekomendasikan Anda untuk pendekatan kedua menggunakan pengontrol navigasi.

Manish Mahajan
sumber
self.performSegue (withIdentifier: "yourIdentifierInStoryboard", pengirim: self)
Rajneesh071
14

Anda dapat menggunakan segue seperti ini:

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

    }
}
Rudra
sumber
Terima kasih atas jawabannya, namun performSegueWithIdentifier adalah metode viewController, dan kode saya berjalan di kelas eksternal
Shlomi Schwartz
13

Swift 3 - Juga berfungsi dengan SpriteKit

Anda dapat menggunakan NSNotification .

Contoh:

1.) Buat segue di storyboard dan beri nama pengenal "segue"

2.) Buat fungsi di ViewController yang Anda pilih.

func goToDifferentView() {

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

}

3.) Dalam ViewDidLoad () dari ViewController Anda, Anda segueing dari membuat pengamat.

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

Pembaruan - Terakhir kali saya menggunakan ini saya harus mengubah .addObserverpanggilan ke kode berikut untuk membungkam kesalahan.

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

4.) Dalam ViewController atau Scene yang Anda segueing, tambahkan Metode Post di mana Anda ingin segue dipicu.

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

Pembaruan - Terakhir kali saya menggunakan ini saya harus mengubah .postpanggilan ke kode berikut untuk membungkam kesalahan.

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

Apa yang ingin Anda lakukan sangat penting untuk pengujian unit. Pada dasarnya Anda perlu membuat fungsi lokal kecil di view controller. Beri nama fungsi apa saja, cukup sertakan performSegueWithIndentifier.

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

Selanjutnya, ubah kelas utilitas Anda FBManageruntuk menyertakan inisialisasi yang mengambil argumen fungsi dan variabel untuk menahan fungsi ViewController yang melakukan segue.

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")
    }
}

(Kenyamanan init memungkinkan Anda untuk menggunakan ini dalam pengujian unit tanpa mengeksekusi segue.)

Akhirnya, di mana Anda memiliki // todo: segue ke tampilan selanjutnya ???, letakkan sesuatu di sepanjang baris:

self.yourFunction()

Dalam pengujian unit Anda, Anda dapat memanggilnya sebagai:

let f = UtilClass()
f.doThatThing()

di mana doThatThing adalah fbessionstatechange Anda dan UtilClassFBManager.

Untuk kode Anda yang sebenarnya, localFunckirimkan (tidak ada tanda kurung) ke kelas FBManager.

Tagihan
sumber
2

Ini berhasil untuk saya.

Pertama-tama berikan view controller ID Storyboard Anda di dalam inspektur identitas. Kemudian gunakan kode contoh berikut (memastikan kelas, nama papan cerita dan ID papan cerita cocok dengan yang Anda gunakan):

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)

Untuk perincian lebih lanjut, lihat http://sketchytech.blogspot.com/2012/11/instantiate-view-controller-using.html keinginan terbaik

amdan
sumber
1

Anda dapat melakukan hal ini menggunakan performSegueWithIdentifierfungsi.

Tangkapan layar

Sintaks:

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

Contoh:

 performSegueWithIdentifier("homeScreenVC", sender: nil)
Jayprakash Dubey
sumber
1

Pilihan lain adalah menggunakan modal segue

LANGKAH 1: Pergi ke storyboard, dan berikan View Controller ID Storyboard . Anda dapat menemukan tempat untuk mengubah ID storyboard di Inspektur Identitas di sebelah kanan. Mari kita memanggil ID storyboardModalViewController

LANGKAH 2: Buka pengontrol tampilan 'pengirim' (sebut saja ViewController) dan tambahkan kode ini ke dalamnya

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)
    }
  }
}

Perhatikan bahwa View Controller yang ingin kita buka juga dipanggil ModalViewController

LANGKAH 3: Untuk menutup ModalViewController, tambahkan ini ke sana

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

Ini bekerja untuk saya:

//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)
        }


    }

sumber