Untuk apa Unwind segues dan bagaimana Anda menggunakannya?

584

iOS 6 dan Xcode 4.5 memiliki fitur baru yang disebut "Unwind Segue":

Seg Unwind dapat memungkinkan transisi ke instance adegan yang ada di storyboard

Selain entri singkat ini dalam catatan rilis Xcode 4.5, UIViewController sekarang tampaknya memiliki beberapa metode baru:

- (BOOL)canPerformUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
- (UIViewController *)viewControllerForUnwindSegueAction:(SEL)action fromViewController:(UIViewController *)fromViewController withSender:(id)sender
- (UIStoryboardSegue *)segueForUnwindingToViewController:(UIViewController *)toViewController fromViewController:(UIViewController *)fromViewController identifier:(NSString *)identifier

Bagaimana cara kerja ruas segues dan apa yang dapat digunakan untuk itu?

Imre Kelényi
sumber

Jawaban:

1267

Pendeknya

Sebuah Shalawat bersantai (kadang-kadang disebut exit Shalawat ) dapat digunakan untuk kembali menavigasi melalui segues push, modal atau popover (seperti jika Anda muncul item navigasi dari bar navigasi, ditutup popover atau diberhentikan controller tampilan modally disajikan). Selain itu, Anda benar-benar dapat bersantai melalui tidak hanya satu tetapi serangkaian push / modal / popover segues, misalnya "kembali" beberapa langkah dalam hierarki navigasi Anda dengan tindakan bersantai tunggal.

Saat Anda melakukan segue pelepasan, Anda perlu menentukan tindakan, yang merupakan metode tindakan dari pengontrol tampilan yang ingin Anda pelonggarkan.

Tujuan-C:

- (IBAction)unwindToThisViewController:(UIStoryboardSegue *)unwindSegue
{
}

Cepat:

@IBAction func unwindToThisViewController(segue: UIStoryboardSegue) {
}

Nama metode tindakan ini digunakan saat Anda membuat segmen santai di storyboard. Selanjutnya, metode ini disebut sesaat sebelum segue bersantai dilakukan. Anda bisa mendapatkan pengontrol tampilan sumber dari UIStoryboardSegueparameter yang dikirimkan untuk berinteraksi dengan pengontrol tampilan yang menginisiasi segue (misalnya untuk mendapatkan nilai properti dari pengontrol tampilan modal). Dalam hal ini, metode ini memiliki fungsi yang sama dengan prepareForSegue:metode UIViewController.

Pembaruan iOS 8: Unwind segues juga berfungsi dengan segues adaptif iOS 8, seperti Show dan Show Detail .

Sebuah contoh

Mari kita memiliki storyboard dengan pengontrol navigasi dan tiga pengontrol tampilan anak:

masukkan deskripsi gambar di sini

Dari Green View Controller Anda dapat bersantai (menavigasi kembali) ke Red View Controller. Dari Biru Anda dapat bersantai ke Hijau atau Merah melalui Hijau. Untuk mengaktifkan unwinding, Anda harus menambahkan metode tindakan khusus ke Merah dan Hijau, misalnya di sini adalah metode tindakan dalam Merah:

Tujuan-C:

@implementation RedViewController

- (IBAction)unwindToRed:(UIStoryboardSegue *)unwindSegue
{
}

@end

Cepat:

@IBAction func unwindToRed(segue: UIStoryboardSegue) {
}

Setelah metode tindakan telah ditambahkan, Anda dapat menentukan segmen pelepasan di storyboard dengan menyeret kontrol ke ikon Exit. Di sini kami ingin bersantai ke Merah dari Hijau ketika tombol ditekan:

masukkan deskripsi gambar di sini

Anda harus memilih tindakan yang ditentukan dalam pengontrol tampilan yang ingin Anda hilangkan:

masukkan deskripsi gambar di sini

Anda juga dapat bersantai ke Merah dari Biru (yang merupakan "dua langkah lagi" di tumpukan navigasi). Kuncinya adalah memilih tindakan relaksasi yang benar.

Sebelum segue pelepasan dilakukan, metode tindakan dipanggil. Dalam contoh ini saya mendefinisikan segmen bersantai ke Merah dari Hijau dan Biru. Kami dapat mengakses sumber pelepasan dalam metode tindakan melalui parameter UIStoryboardSegue:

Tujuan-C:

- (IBAction)unwindToRed:(UIStoryboardSegue *)unwindSegue
{
    UIViewController* sourceViewController = unwindSegue.sourceViewController;

    if ([sourceViewController isKindOfClass:[BlueViewController class]])
    {
        NSLog(@"Coming from BLUE!");
    }
    else if ([sourceViewController isKindOfClass:[GreenViewController class]])
    {
        NSLog(@"Coming from GREEN!");
    }
}

Cepat:

@IBAction func unwindToRed(unwindSegue: UIStoryboardSegue) {
    if let blueViewController = unwindSegue.sourceViewController as? BlueViewController {
        println("Coming from BLUE")
    }
    else if let redViewController = unwindSegue.sourceViewController as? RedViewController {
        println("Coming from RED")
    }
}

Unwinding juga bekerja melalui kombinasi push / modal segues. Misalnya jika saya menambahkan pengontrol tampilan Kuning lain dengan modal segue, kita bisa melepas dari Yellow kembali ke Red dalam satu langkah:

masukkan deskripsi gambar di sini

Tidak tergulung dari Kode

Saat Anda menentukan segmen pelepas dengan menyeret-kan sesuatu ke simbol Keluar dari pengontrol tampilan, segue yang baru muncul di Document Outline:

masukkan deskripsi gambar di sini

Memilih segue dan pergi ke Inspektur Atribut mengungkapkan properti "Identifier". Gunakan ini untuk memberikan pengidentifikasi unik ke segue Anda:

masukkan deskripsi gambar di sini

Setelah ini, segmen pelepasan dapat dilakukan dari kode sama seperti segmen lainnya:

Tujuan-C:

[self performSegueWithIdentifier:@"UnwindToRedSegueID" sender:self];

Cepat:

performSegueWithIdentifier("UnwindToRedSegueID", sender: self)
Imre Kelényi
sumber
12
+1 jawaban yang bagus. Kedengarannya sangat bagus, tetapi tidak dapatkah metode menyukai dismissViewControllerAnimated:completion:atau popViewControllerAnimated:mencapai hal yang sama?
Sam Spencer
32
Tentu mereka bisa. Namun, jika Anda menggunakan storyboard, segues bersantai dapat sering mencapai hal yang sama dengan kode jauh lebih sedikit. Sebenarnya, sekarang Anda dapat mengabaikan pengontrol tampilan yang disajikan secara modern tanpa menulis kode apa pun. Tentu saja, masih ada banyak kasus ketika menutup pengontrol dari kode adalah hal yang benar untuk dilakukan.
Imre Kelényi
7
Pastikan untuk menambahkan metode tindakan Anda ke file header Anda atau Storyboard tidak akan tahu.
Kyle C
17
Keuntungan lain lebih dari dismissViewControllerAnimated:completion:atau popViewControllerAnimated:adalah bahwa metode yang Anda tambahkan ke pengontrol tampilan yang Anda inginkan disebut dan sehingga Anda memiliki cara mudah untuk mengetahui pengontrol tampilan yang disajikan selesai tanpa harus membuat pengendali tampilan penyajian delegasi dari pengontrol tampilan yang disajikan .
honus
8
Bisakah saya menyarankan sedikit edit? Tidak "jelas" jelas bahwa Anda meletakkan - (IBAction) melepas relTRed: (UIStoryboardSegue *) melepas RelaxS di RedViewController.m, dan pada gilirannya ini tersedia secara universal di "salah" tombol keluar hijau untuk papan cerita apa pun. Jawaban yang fantastis dan sekarang saya akan menggunakan ini untuk masalah lain. Terima kasih!
John Ballinger
166

Sejauh cara menggunakan segue bersantai di StoryBoard ...

Langkah 1)

Buka kode untuk pengontrol tampilan yang ingin Anda hilangkan dan tambahkan ini:

Objektif-C

- (IBAction)unwindToViewControllerNameHere:(UIStoryboardSegue *)segue {
    //nothing goes here
}

Pastikan juga mendeklarasikan metode ini dalam file .h Anda di Obj-C

Cepat

@IBAction func unwindToViewControllerNameHere(segue: UIStoryboardSegue) {
    //nothing goes here
}

Langkah 2)

Di storyboard, buka tampilan yang ingin Anda hilangkan dan cukup tarik segue dari tombol Anda atau apa pun hingga ikon "EXIT" oranye kecil di kanan atas tampilan sumber Anda.

masukkan deskripsi gambar di sini

Seharusnya sekarang ada opsi untuk terhubung ke "- melepasToViewControllerNameHere"

Itu saja, segue Anda akan santai ketika tombol Anda diketuk.

Travis M.
sumber
5
Saya telah menemukan bahwa dengan Xcode 4.5 dan sebelumnya perlu untuk menyatakan IBAction di header. Saya tidak tahu apakah ini masih benar.
Steven Fisher
2
Apakah ada cara untuk melakukan Langkah 2 tanpa storyboard, yaitu secara terprogram? Storyboard saya (pembangun antarmuka) kacau dan tidak menunjukkan segmen bersantai (bug xcode).
Van Du Tran
46

Seg Unwind digunakan untuk "kembali" ke beberapa pengontrol tampilan, dari mana, melalui sejumlah segues, Anda sampai ke pengontrol tampilan "saat ini".

Bayangkan Anda memiliki sesuatu MyNavControllerdengan Asebagai pengontrol tampilan root. Sekarang Anda menggunakan tombol tekan untuk B. Sekarang pengendali navigasi memiliki A dan B dalam viewControllerssusunannya, dan B terlihat. Sekarang Anda hadir secara modern C.

Dengan segue pelepasan, Anda sekarang dapat melepaskan "kembali" dari Cke B(yaitu mengabaikan pengontrol tampilan yang disajikan secara moderat), pada dasarnya "membatalkan" modal segue. Anda bahkan dapat melepas semua jalan kembali ke pengontrol tampilan root A, membatalkan baik modal segue dan push segue.

Lepas segues memudahkan untuk mundur. Misalnya, sebelum iOS 6, praktik terbaik untuk memberhentikan pengontrol tampilan yang disajikan adalah mengatur pengendali tampilan yang disajikan sebagai delegasi pengontrol tampilan yang disajikan, kemudian memanggil metode delegasi khusus Anda, yang kemudian menolak disajikanViewController . Kedengarannya rumit dan rumit? Dulu. Itu sebabnya bersantai segues bagus.

Yang Meyer
sumber
7
Anda dapat menelepon dismissViewController:animateddari pengontrol yang disajikan. Anda tidak perlu mendelegasikan itu. Tentu saja jika Anda perlu mengirimkan data kembali, maka Anda perlu pendelegasian atau metode lain.
mxcl
3
Meskipun Anda dapat menelepon dismissViewController:animated:dari pengontrol yang disajikan, "praktik terbaik" memang memanggil metode delegasi pada pengontrol yang hadir untuk melakukan itu untuk Anda, seperti yang disebutkan.
Chris Nolet
36

Sesuatu yang saya tidak lihat disebutkan dalam jawaban lain di sini adalah bagaimana Anda berurusan dengan unwinding ketika Anda tidak tahu di mana awal segue berasal, yang bagi saya adalah kasus penggunaan yang lebih penting. Misalnya, Anda memiliki pengontrol tampilan bantuan ( H ) yang Anda tampilkan secara modal dari dua pengontrol tampilan yang berbeda ( A dan B ):

AH
BH

Bagaimana Anda mengatur Segue bersantai sehingga Anda kembali ke pengontrol tampilan yang benar? Jawabannya adalah bahwa Anda mendeklarasikan tindakan pelepasan dalam A dan B dengan nama yang sama , misalnya:

// put in AViewController.swift and BViewController.swift
@IBAction func unwindFromHelp(sender: UIStoryboardSegue) {
    // empty
}

Dengan cara ini, pelepasan akan menemukan pengontrol tampilan mana saja ( A atau B ) yang memulai segue dan kembali ke sana.

Dengan kata lain, memikirkan tindakan unwind sebagai menjelaskan di mana Shalawat tersebut datang dari , daripada di mana ia akan.

shawkinaw
sumber
2
Terima kasih atas info ini, saya mencari ini.
Madhu
2
Sungguh luar biasa menyebutkan info ini karena saya sudah menerapkan solusi dan tidak ada yang terjadi sampai saya mendapatkan tip Anda di sini terima kasih banyak atas dukungan Anda
Amr Angry
Ini adalah informasi yang sangat bagus! Terima kasih banyak!
Dominique Vial
24

IOS Swift:

Langkah 1: tentukan metode ini ke tampilan pengontrol MASTER Anda. di mana Anda ingin kembali:

//pragma mark - Unwind Seques
@IBAction func goToSideMenu(segue: UIStoryboardSegue) {

    println("Called goToSideMenu: unwind action")

}

Langkah 2: (StoryBoard) Klik kanan pada Anda tombol BUDAK / ANAK KELUAR dan Pilih "goToSideMenu" Sebagai tindakan untuk Menghubungkan Anda Tombol di mana Anda akan mengklik untuk kembali ke Anda tampilan pengendali MASTER:

masukkan deskripsi gambar di sini langkah 3: Bangun dan Jalankan ...

Vinod Joshi
sumber
1

Misalnya jika Anda menavigasi dari viewControllerB ke viewControllerA maka dalam viewControllerA Anda delegasi di bawah ini akan memanggil dan data akan dibagikan.

@IBAction func unWindSeague (_ sender : UIStoryboardSegue) {
        if sender.source is ViewControllerB  {
            if let _ = sender.source as? ViewControllerB {
                self.textLabel.text = "Came from B = B->A , B exited"
            }
            
        }

}
  • Lepaskan Pengendali Tampilan Sumber Seague (Anda Perlu menyambungkan Tombol Keluar ke ikon keluar VC dan menghubungkannya untuk melepaskan diri:

masukkan deskripsi gambar di sini

  • Unwind Seague Completed -> TextLabel viewControllerA Berubah.

masukkan deskripsi gambar di sini

Tech
sumber