Segue adaptif di storyboard Xcode 6. Apakah push tidak digunakan lagi?

121

Pembuat antarmuka Xcode 6 secara default memiliki kotak centang baru "gunakan kelas ukuran". Itu membuat tampilan menjadi adaptif. masukkan deskripsi gambar di sini

Ketika saya mencoba membuat segue antara 2 tampilan di papan cerita saya, saya memiliki opsi baru: masukkan deskripsi gambar di sini

bukan tua:

masukkan deskripsi gambar di sini

Sekarang kita memiliki "show" dan "present modally" daripada "push" dan "modal". Opsi lama ditandai sebagai usang. Saya telah memilih opsi "tampilkan", karena dalam pengaturan segue disebut "tampilkan (mis. Dorong)

masukkan deskripsi gambar di sini

Tapi itu tidak memaksa. Animasi segmen terlihat seperti slide dari bawah (modal) dan bilah navigasi menghilang.

Pertanyaannya adalah: Bagaimana cara membuat "pertunjukan" berfungsi seperti push? Apakah mungkin atau haruskah saya menggunakan "push (deprecated)"? Di mana saya dapat menemukan informasi tentang jenis baru segue? Satu-satunya hal yang saya temukan di pustaka pengembang iOS8 adalah Storyboards Membantu Anda Merancang Antarmuka Pengguna Anda tetapi tidak ada informasi tentang "show" segue.

MEMPERBARUI

Saya mencoba membuat proyek baru dan "show" benar-benar berfungsi seperti "push". Saya pikir masalah dalam proyek saya bisa jadi karena saya menggunakan kembali pengontrol navigasi dengan kode seperti ini, tetapi saya tidak tahu cara memperbaikinya.

if ( [segue isKindOfClass: [SWRevealViewControllerSegue class]] ) {
    SWRevealViewControllerSegue *swSegue = (SWRevealViewControllerSegue*) segue;
    
    swSegue.performBlock = ^(SWRevealViewControllerSegue* rvc_segue, UIViewController* svc, UIViewController* dvc) {
        
        UINavigationController* navController = (UINavigationController*)self.revealViewController.frontViewController;
        [navController setViewControllers: @[dvc] animated: NO ];
        [self.revealViewController setFrontViewPosition: FrontViewPositionLeft animated: YES];
    };
    
}

Setelah itu saya coba push NewViewController setelah MainViewController masukkan deskripsi gambar di sini

PEMBARUAN 2:

Sepertinya saya hanya masalah iOS 7, iOS 7.1.

John Kakon
sumber

Jawaban:

97

Ya, gunakan 'Tampilkan' alih-alih 'Dorong'

Bagaimana cara membuat "pertunjukan" berfungsi seperti push? Apakah mungkin atau haruskah saya menggunakan "push (depricated)"?

Itu harus; itu untuk saya. Saya menggunakan Xcode 6 beta 2 dan untuk menguji saya menggunakan template tampilan tunggal (memanggil pengontrol tampilan yang dibuat sebelumnya di IB 'VC_A'). Saya kemudian menambahkan pengontrol tampilan lain ('VC_B'). Saya kemudian menambahkan tombol di VC_A untuk menampilkan VC_B dan tombol lainnya dari VC_B kembali ke VC_A. Saat saya menambahkan pengontrol navigasi sebagai pengontrol tampilan awal di storyboard dan menjadikan VC_A sebagai rootViewController, 'push' dan 'show' memiliki efek yang sama. Jika saya tidak memiliki pengontrol navigasi awal dan saya menggunakan 'show', saya mengerti apa yang Anda jelaskan bahwa VC_B melakukan slide ke atas dari bawah. Jika saya mencoba untuk 'mendorong' saya mengalami crash karena untuk melakukan push saya harus memiliki pengontrol navigasi.

Di mana saya dapat menemukan informasi tentang jenis baru segue?

Jadi saya menemukan beberapa informasi dalam sesi 'What's New in Interface Builder' di sini . Jika Anda melihat slide, Anda akan melihat satu slide (41) menyebutkan perubahannya. Saat menonton video sesi tersebut, Anda dapat melompat ke menit ke 38:00 di mana mereka mulai berbicara tentang segmen adaptif. Mereka menjelaskan bahwa segmen adaptif 'tampilkan', misalnya, mempertimbangkan konteks saat memutuskan bagaimana melakukan presentasi pengontrol tampilan baru.

Spencer Hall
sumber
Terima kasih atas jawaban Anda. Saya mencoba membuat proyek baru dan "show" benar-benar berfungsi seperti push dengan pengontrol navigasi. Dalam proyek saya, saya memiliki struktur yang rumit dengan sidebar dari pelajaran ini appcoda.com/ios-programming-sidebar-navigation-menu dan push bekerja, tidak terlihat. Mungkin alasannya adalah saya menggunakan kembali pengontrol navigasi. Saya telah memperbarui pertanyaan saya dengan kode penggunaan kembali.
John Kakon
Jadi, hal pertama yang saya lihat saat melihat pembaruan Anda adalah bahwa Anda menggunakan segue khusus yang diharapkan: 'SWRevealViewControllerSegue' jadi ya, mungkin tidak masuk akal untuk menggunakan 'show' atau 'push' dalam kasus Anda karena itu sudah ada di dalamnya segues sedangkan Anda ingin menjalankan kode kustom Anda sendiri. Ketika saya mengunduh proyek sampel, itu bahkan menunjukkan pemilihan 'kustom' pada segues di file storyboard.
Spencer Hall
Saya tidak bermaksud segue ini. Saya berbicara tentang membuat UIViewController baru di samping "MainViewController" (memiliki Pengontrol Navigasi, dan "pembaruan" saya hanya menunjukkan bagaimana cara mendapatkannya di sana) dan mencoba mendorong View baru ke MainViewController. Tangkapan Layar Storyboard Saya akan berterima kasih jika Anda mengaktifkan "menggunakan kelas ukuran" dalam proyek sampel, membuat NewViewController, dan mencoba memisahkan antara MainViewController dan NewViewController dengan "show". Anda akan melihat apa yang saya bicarakan.
John Kakon
Apakah itu barusan dan setidaknya bagi saya "pertunjukan" dioperasikan seperti "dorong".
Spencer Hall
9
Anda dapat mengatasi bug dengan memastikan bahwa semua jalan ke pengontrol tampilan Anda memiliki UINavigationController di root mereka. Bahkan jika itu berarti meletakkan UINavigationController ke dalam storyboard Anda yang tidak akan pernah bisa diakses. Sepertinya kabel digunakan untuk menyimpulkan perilaku.
Scott Robertson
33

Sudah ada jawaban yang diterima, tetapi saya ingin memberikan sedikit lebih banyak informasi, mungkin informasi yang sebelumnya tidak tersedia.

Seperti yang telah disebutkan sebelumnya, segmen "push" dan "modal" sudah tidak digunakan lagi, dan masing-masing telah digantikan oleh "show" dan "present modally". Menurut dokumentasi Apple, segue baru telah dibagi lagi menjadi segue yang beradaptasi dengan kelas ukuran. Yang lebih lama seharusnya hanya digunakan untuk mendukung versi iOS yang lebih lama dari iOS 8.

Dokumen di tautan berikut menjelaskan itu dan deskripsi semua segmen yang tersedia, lama dan baru.

Menambahkan Segue Antar Adegan di Papan Cerita

Jika URL berubah di masa mendatang, berikut adalah penjelasan yang diberikan untuk setiap segmen baru:

Menunjukkan

Sajikan konten dalam detail atau master area tergantung pada konten layar. Jika aplikasi menampilkan master dan tampilan detail, konten didorong ke area detail. Jika aplikasi hanya menampilkan master atau detailnya, konten akan didorong ke atas tumpukan pengontrol tampilan saat ini.

Tunjukkan Detail

Sajikan konten di area detail. Jika aplikasi menampilkan master dan tampilan detail, konten baru menggantikan detail saat ini. Jika aplikasi hanya menampilkan master atau detailnya, konten tersebut menggantikan bagian atas tumpukan pengontrol tampilan saat ini.

Hadir Secara Modally

Sajikan konten dengan sopan. Ada opsi untuk memilih gaya presentasi (UIModalPresentationStyle) dan gaya transisi (UIModalTransitionStyle).

Hadir sebagai Popover

Sajikan konten sebagai popover yang ditambatkan ke tampilan yang sudah ada. Ada opsi untuk menentukan kemungkinan arah panah yang ditampilkan di salah satu tepi tampilan popover (UIPopoverArrowDirection). Ada juga opsi untuk menentukan tampilan jangkar.

alondono.dll
sumber
24

tldr; Hapus Segue yang tidak didorong dengan benar dan buat kembali di storyboard dengan menyeret dari UIView / UIControl ke pengontrol tampilan target.

Tidak ada yang salah dengan jawaban yang lain tetapi yang ini menjelaskan apa yang terjadi, bagaimana Anda dapat memverifikasi bahwa itu terjadi dan bagaimana mengurangi masalah di masa depan.

Latar Belakang

Dalam kasus saya, tidak ada Show Segues saya yang berfungsi meskipun saya sudah memiliki UINavigationController sebagai pengontrol tampilan awal saya (dengan konten saya UIViewController sebagai root).

Mengapa dan Bagaimana Pertunjukan Segue Istirahat

Segue acara berhenti jika memiliki tindakan yang terkait dengan segue dalam xml sumber storyboard. Skenario umum yang menyebabkan hal ini mungkin terjadi jika Anda telah mendefinisikan ulang segmen dari segmen manual yang sebelumnya disebut dalam kode. Ini menyisakan bit berikut di storyboard xml.

<connections>
    <segue destination="85t-Z1-hxf" kind="show" identifier="ToOptions" action="showDetailViewController:sender:" id="gdZ-IX-KcN">
</connections>

Nota Bene Untuk melihat storyboard sebagai xml; Klik kanan file storyboard dan pilih Open as> Source Code . Untuk mengembalikan, gunakan Open as> Interface Builder - Storyboard

Untuk mengakomodasi tindakan kustom apa pun saat menggunakan segue dari storyboard, seseorang cukup mengetuk prepforSegue dan mencegat pengontrol tampilan tujuan dan memanggil metode apa pun dari lokasi itu. Bagaimanapun, efek samping untuk bug kecil ini (bug adalah kenyataan bahwa ketika Anda mendefinisikan ulang segue, itu tidak diatur dengan benar di xml ~ yaitu tindakan tetap bahkan setelah Anda mengubah segue ke yang beroperasi dari UIView (atau UIControl) ke pengontrol tampilan target).

Sayangnya solusi yang paling langsung gagal. Jadi, hanya menghapus atribut xml untuk tindakan dari dalam Storyboard TIDAK akan memperbaiki masalah. Sebaliknya, seseorang hanya perlu menghapus dan membuat ulang segue di storyboard.

Saat dibuat ulang, storyboard xml tidak lagi memiliki tindakan yang terkait dengan segmen tertentu dan Pertunjukan akan dijalankan sebagai Push.

Contoh Xml untuk Show Segue yang benar

  <connections>
    <segue destination="RbV-Au-WV9" kind="show" identifier="ToOptions" id="5dm-os-bcS"/>
  </connections>

Mitigasi

Untuk mencegah pengulangan, seseorang hanya perlu tetap menggunakan segmen storyboard non-manual jika memungkinkan dengan menggunakan preparedForSegue untuk menambahkan tindakan yang diperlukan berdasarkan pengontrol tampilan tujuan. Atau jika Anda harus mencampur dan mencocokkan, lakukan tindakan pencegahan untuk memverifikasi bahwa Tampilkan segues Anda tidak memiliki tindakan yang dilampirkan di papan cerita xml. Jika Anda berurusan dengan proyek yang lebih lama maka Anda harus memberikan perhatian khusus pada kode sumber Storyboard karena saya telah menemukan beberapa masalah.

Tommie C.
sumber
3
Setelah berjam-jam, ini menyelamatkan saya mungkin beberapa jam lainnya. Berikut adalah, apa yang saya sarankan berdasarkan hal di atas: Buka storyboard sebagai Kode Sumber , cari kind = "show" dan lihat apakah baris tersebut berisi sesuatu seperti action = "showDetailViewController: sender:" , jika demikian, hapus semuanya dari tindakan = hingga penutupan " . Saya memiliki storyboard yang sangat besar dan seque yang terpengaruh tidak berisi parameter tindakan ini, tetapi baris lain yang tidak terkait melakukannya. Setelah saya menghapus tindakan, semua urutan adaptif berfungsi kembali seperti yang diharapkan. Hanya menghapus urutan yang terpengaruh tidak ' t bekerja.
Marcus
Ini menyelamatkan saya juga.
Adam Bardon
1
Menghapus atribut tindakan di XML berhasil untuk teman saya.
Brent Royal-Gordon
menyelamatkan saya juga
Jimmy George Thomas
Menghapus atribut tindakan di file xml, dan voila, itu berfungsi. Tidak akan pernah menemukan masalah tanpa posting ini.
krizzzn
20

Seperti yang dikomentari Scott Robertson di sini , ini tampak seperti bug di iOS 7.

Tampaknya di iOS 8, transisi disimpulkan pada waktu proses (perilaku yang benar), sedangkan di iOS 7 transisi disimpulkan pada waktu desain (perilaku buggy).

Solusi paling sederhana adalah dengan menambahkan pengontrol navigasi yang tidak digunakan ke storyboard dan menautkannya sehingga pengontrol tampilan yang dimaksud adalah bagian dari pengontrol navigasi ini. Anda tidak benar-benar harus membuat instantiate pengontrol navigasi, Anda hanya perlu pengontrol tampilan buggy untuk mengetahui bahwa itu tertanam di pengontrol navigasi.

Catatan: Mensimulasikan bilah navigasi tidak cukup untuk tujuan ini; Anda harus benar-benar memiliki pengontrol navigasi di tumpukan dorongnya.

Untuk mereproduksi bug:

  1. Buat papan cerita baru yang menggunakan kelas ukuran.
  2. Buat dua pengontrol tampilan (tanpa pengontrol navigasi).
  3. Buat pengontrol tampilan pertama menunjukkan pengontrol tampilan kedua melalui segue Tampilkan (mis. Tekan) yang ditautkan ke tombol, misalnya.
  4. Dalam kode, tampilkan pengontrol tampilan pertama, tetapi sematkan di pengontrol navigasi melalui initWithRootViewController:metode.
  5. Jalankan aplikasi di iOS 7.
  6. Ketuk tombol yang seharusnya melakukan dorongan.
  7. Anda akan mendapatkan transisi modal alih-alih push di iOS 7. Di iOS 8, Anda akan mendapatkan perilaku push yang benar.

masukkan deskripsi gambar di sini

Untuk memperbaiki bug:

  1. Tambahkan pengontrol navigasi ke storyboard dan setel pengontrol tampilan pertama menjadi pengontrol tampilan root. (Catatan: menambahkan yang kedua sebagai pengontrol tampilan root TIDAK akan memperbaiki bug ini.)
  2. Berikan pengenal sampah untuk menyembunyikan peringatan tentang pengontrol navigasi yang tidak dapat diakses, dan untuk mendokumentasikan kepada Anda sendiri bahwa ini hanya ada sebagai solusi. (misalnya workaround for show segues in iOS 7).

masukkan deskripsi gambar di sini

Perhatikan bagaimana pengontrol navigasi ditambahkan di gambar kedua, dan bagaimana pengontrol tersebut tidak memiliki panah masuk (yaitu tidak ada cara untuk membuat instance selain menggunakan pengenal pengontrol tampilan).

Senseful
sumber
1
Terima kasih, trik dengan NavigationController melakukannya untuk saya ketika saya Menukar root NavigationControllers ViewController-Stack
Peter Pint
1
Solusi terbaik. Terima kasih
Илья Голованов
13

Saya tahu saya terlambat untuk ini tetapi saya ingin membagikan apa yang saya pelajari. Ini sebenarnya bug dan masih ada sampai sekarang (2014-12-18).

Saya menulis artikel tentang ini di sini .

Ini mudah direproduksi; di iOS8 akan bekerja dengan baik dan bahkan di iOS7.x selama Anda tidak mendorong pengontrol tampilan secara terprogram ke tumpukan sebelum memanggil Showsegue.

Jika Anda hanya mendorong ke tumpukan menggunakan koneksi papan cerita, ini akan berfungsi; tetapi tampaknya jika Anda mendorong melalui kode entah bagaimana, navigationControllerproperti yang didorong UIViewControllerakan menjadi nildan ketika Anda memanggilnya Showakan menganggapnya sebagai modal karena tidak ada navigasi untuk mengontrol tumpukan.

Satu-satunya solusi sejauh ini adalah tidak mendorong melalui kode (tidak layak) atau menggunakan yang sekarang sudah usang Push.

Saya mengajukan radar (tautan di artikel). Jangan ragu untuk mengajukan duplikat dengan harapan Apple memperbaiki masalah ini.

esttorhe
sumber
3
Ini persis masalah saya, terima kasih! menggunakan push yang tidak digunakan lagi tampaknya menjadi solusi yang lebih jahat dalam kasus ini.
Moshe Gottlieb
Solusi lainnya adalah menambahkan pengontrol navigasi (tidak digunakan) ke storyboard. Lihat stackoverflow.com/questions/24184003/…
Masuk akal
Nop! Ini terjadi di sini dan penyebabnya bukanlah dorongan secara terprogram. Dalam kasus saya, saya melakukan Showsegue, lalu pada Showsegue kedua disajikan secara sederhana, Solusi?
Frade
@Frade dapatkah Anda menautkan ke repo github yang dapat direproduksi? Apakah Anda menjalankan versi iOS yang mana?
esttorhe
proyek pribadi .. Itu terjadi saat mencoba melakukan (detik) ShowviewController di iOS 7
Frade
2

Saya memiliki masalah yang sama dengan segues di Xcode 7 dan iOS 7.1.2. Show segues (fitur baru dari iOS 8) berfungsi seperti modal segues di iOS 7 dan tidak memungkinkan Anda untuk mendorong View Controllers ke dalam stack Pengontrol Navigasi saat Anda menentukan jenis segue dengan Xcode di Storyboard Anda. Itulah mengapa self.navigationController Anda akan mengembalikan nihil, karena Pengontrol Tampilan tidak didorong ke tumpukan dan Anda tidak dapat memunculkannya.

Saya tidak mengerti mengapa Apple tidak menambahkan pemberitahuan apa pun untuk kasus ini di Xcode ketika Anda membutuhkan aplikasi Anda untuk bekerja di iOS 7. Mereka mengatakan bahwa metode Push tidak digunakan lagi, tetapi Show tidak bekerja dengan benar dengan iOS 7.

Apa yang telah saya lakukan untuk mengatasi masalah tersebut:

Saya telah membuat kelas MYShowSegue dengan .h

#import <UIKit/UIKit.h>

@interface MYShowSegue : UIStoryboardSegue

@end

Dan file .m dengan hanya satu metode perform :

#import "MYShowSegue.h"

@implementation MYShowSegue

- (void) perform {

    if ([[[self sourceViewController] navigationController] respondsToSelector:@selector(showViewController:sender:)]) {

        id sender = nil;
        [[[self sourceViewController] navigationController] showViewController:[self destinationViewController] sender:sender];
    }else{

        [[[self sourceViewController] navigationController] pushViewController:[self destinationViewController] animated:YES];
    }
}

@end

Daripada Anda perlu mengatur jenis Kustom untuk setiap segmen di Storyboard Anda dan memilih kelas baru untuknya, dalam kasus saya itu adalah MYShowSegue.

Contoh Segue Ubahsuaian

Solusi ini akan membantu Anda mendapatkan dukungan penuh untuk aplikasi iOS 7 Anda, mereka akan menggunakan metode pushViewController untuk mendorong Tampilan Anda dan untuk iOS 8,9 dll. Segue Anda akan bekerja dengan metode baru (iOS 8) showViewController

Jangan lupa untuk melakukan hal yang sama dengan semua segmen Anda di Storyboard.

Igor Tikhonov
sumber
Solusi bagus - berhasil untuk saya (alih-alih menambahkan pengontrol navigasi yang "tidak digunakan" ...
Laurenz Glück
1

Ini masih terjadi di iOS 10.x

Menghapus dan memasang kembali segmen tidak menyelesaikan apa pun untuk saya:

Masalah: Fungsionalitas yang dibutuhkan adalah 7 segues yang hanya beroperasi sebagai 'push' (sebenarnya adalah detail pertunjukan) tetapi sebenarnya hanya segue pertama yang saya tambahkan yang akan mendorong, yang lain semua akan berperilaku sederhana. Ini meskipun Interface Builder mendeskripsikan setiap segmen secara identik.

Solusi: Saya harus menambahkan tindakan ke 6 segues yang tidak memilikinya.

XML Papan Cerita Asli

<connections>
  <segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
  <segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" id="Uod-JC-786"/>
  <segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" id="3PW-nV-hWl"/>
  <segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" id="WUK-ju-KDm"/>
  <segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" id="Id6-bW-Huc"/>
  <segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" id="G0L-XW-7f4"/>
  <segue destination="AET-S1-O6h" kind="showDetail" identifier="G" id="3NK-93-wTy"/>
</connections>

Saya mengubah ini dengan menambahkan showViewController: sender

<connections>
  <segue destination="tIr-4a-WfZ" kind="showDetail" identifier="A" action="showViewController:sender:" id="8yd-Ne-7KA"/>
  <segue destination="4mB-YE-5dM" kind="showDetail" identifier="B" action="showViewController:sender:" id="Uod-JC-786"/>
  <segue destination="Qh5-bJ-KcE" kind="showDetail" identifier="C" action="showViewController:sender:" id="3PW-nV-hWl"/>
  <segue destination="EI6-f4-QBB" kind="showDetail" identifier="D" action="showViewController:sender:" id="WUK-ju-KDm"/>
  <segue destination="nTz-N4-fpW" kind="showDetail" identifier="E" action="showViewController:sender:" id="Id6-bW-Huc"/>
  <segue destination="JEp-CH-6dW" kind="showDetail" identifier="F" action="showViewController:sender:" id="G0L-XW-7f4"/>
  <segue destination="AET-S1-O6h" kind="showDetail" identifier="G" action="showViewController:sender:" id="3NK-93-wTy"/>
</connections>
Damo
sumber