Saya menerima laporan kerusakan ini, tetapi saya tidak tahu bagaimana cara debug itu.
Fatal Exception NSInvalidArgumentException
Can't add self as subview
0 ... CoreFoundation __exceptionPreprocess + 130
1 libobjc.A.dylib objc_exception_throw + 38
2 CoreFoundation -[NSException initWithCoder:]
3 UIKit -[UIView(Internal) _addSubview:positioned:relativeTo:] + 110
4 UIKit -[UIView(Hierarchy) addSubview:] + 30
5 UIKit __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke + 1196
6 UIKit +[UIView(Animation) performWithoutAnimation:] + 72
7 UIKit -[_UINavigationParallaxTransition animateTransition:] + 732
8 UIKit -[UINavigationController _startCustomTransition:] + 2616
9 UIKit -[UINavigationController _startDeferredTransitionIfNeeded:] + 418
10 UIKit -[UINavigationController __viewWillLayoutSubviews] + 44
11 UIKit -[UILayoutContainerView layoutSubviews] + 184
12 UIKit -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 346
13 QuartzCore -[CALayer layoutSublayers] + 142
14 QuartzCore CA::Layer::layout_if_needed(CA::Transaction*) + 350
15 QuartzCore CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
16 QuartzCore CA::Context::commit_transaction(CA::Transaction*) + 228
17 QuartzCore CA::Transaction::commit() + 314
18 QuartzCore CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 56
Versi iOS adalah 7.0.3. Adakah yang mengalami kecelakaan aneh ini?
MEMPERBARUI:
Saya tidak tahu di mana dalam kode saya menyebabkan kerusakan ini, jadi saya tidak dapat memposting kode di sini, maaf.
UPDATE kedua
Lihat jawabannya di bawah.
ios
iphone
objective-c
Arnol
sumber
sumber
Jawaban:
Saya berspekulasi berdasarkan pada sesuatu yang serupa yang saya debug baru-baru ini ... jika Anda mendorong (atau pop) view controller dengan Animated: YES tidak langsung selesai, dan hal-hal buruk terjadi jika Anda melakukan push atau pop lain sebelum animasi selesai. Anda dapat dengan mudah menguji apakah ini memang benar terjadi dengan mengubah sementara operasi Push dan Pop Anda menjadi Animated: NO (sehingga semuanya selesai secara serempak) dan melihat apakah itu menghilangkan crash. Jika ini memang masalah Anda dan Anda ingin menghidupkan kembali animasi, maka strategi yang benar adalah menerapkan protokol UINavigationControllerDelegate. Ini termasuk metode berikut, yang dipanggil setelah animasi selesai:
Pada dasarnya Anda ingin memindahkan beberapa kode yang diperlukan ke dalam metode ini untuk memastikan bahwa tidak ada tindakan lain yang dapat menyebabkan perubahan pada tumpukan NavigationController akan terjadi sampai animasi selesai dan tumpukan siap untuk lebih banyak perubahan.
sumber
[newViewController setLabelTitle:...]
baru setelah memanggil pushViewController denganAnimated:YES.
Dan saya memecahkan masalah dengan memindahkan metode setLabelTitle ke viewDidLoad pada newViewController. Terima kasih telah memberi saya petunjuk.Kami mulai mendapatkan masalah ini juga, dan kemungkinan besar kemungkinan kami disebabkan oleh masalah yang sama.
Dalam kasus kami, kami harus menarik data dari ujung belakang dalam beberapa kasus, yang berarti pengguna mungkin mengetuk sesuatu dan kemudian akan ada sedikit keterlambatan sebelum dorongan nav terjadi. Jika pengguna dengan cepat mengetuk sekitar, mereka mungkin berakhir dengan dua dorongan nav dari pengontrol tampilan yang sama, yang memicu pengecualian ini.
Solusi kami adalah kategori pada UINavigationController yang mencegah push / pops kecuali vc atas adalah sama dari titik waktu tertentu.
file .h:
file .m:
Sejauh ini tampaknya ini telah menyelesaikan masalah bagi kami. Contoh:
Pada dasarnya, aturannya adalah: sebelum ada penundaan terkait pengguna ambil kunci dari nav controller yang relevan, dan sertakan dalam panggilan untuk push / pop.
Kata "kunci" mungkin kata-kata yang sedikit buruk karena mungkin menyindir ada beberapa bentuk kunci yang perlu dibuka, tetapi karena tidak ada metode "membuka" di mana pun, mungkin tidak apa-apa.
(Sebagai sidenote, "keterlambatan yang tidak terkait dengan pengguna" adalah keterlambatan apa pun yang disebabkan oleh kode, yaitu apa pun yang tidak sinkron. Pengguna yang mengetuk kontroler nav yang didorong secara animasi tidak masuk hitungan dan tidak perlu melakukan navigasiLock: versi untuk itu kasus.)
sumber
Kode ini menyelesaikan masalah: https://gist.github.com/nonamelive/9334458
Ini menggunakan API pribadi, tetapi saya dapat mengonfirmasi bahwa itu adalah App Store aman. (Salah satu aplikasi saya yang menggunakan kode ini disetujui oleh App Store.)
sumber
Saya akan menjelaskan lebih detail tentang kerusakan ini di aplikasi saya dan menandainya sebagai jawaban.
Aplikasi saya memiliki UINavigationController dengan pengendali root adalah UITableViewController yang berisi daftar objek catatan. Objek note memiliki properti konten dalam html. Pilih catatan akan pergi ke pengontrol detail.
Pengontrol detail
Pengontrol ini memiliki UIWebView, menampilkan konten catatan yang diteruskan dari pengontrol root.
Pengontrol ini adalah delegasi dari kontrol tampilan web. Jika catatan berisi tautan, ketuk tautan akan masuk ke peramban web dalam aplikasi.
Saya menerima laporan kerusakan di atas setiap hari. Saya tidak tahu di mana dalam kode saya menyebabkan kerusakan ini. Setelah beberapa penyelidikan dengan bantuan pengguna, saya akhirnya dapat memperbaiki kerusakan ini. Konten html ini akan menyebabkan crash:
Dalam metode viewDidLoad dari pengontrol detail, saya memuat html ini ke kontrol tampilan web, tepat setelah itu, metode delegasi di atas dipanggil segera dengan request.URL adalah sumber iframe (google.com). Metode delegasi ini memanggil metode pushViewController saat dalam viewDidLoad => crash!
Saya memperbaiki kerusakan ini dengan memeriksa jenis navigasi:
Semoga ini membantu
sumber
viewDidLoad
?Saya memiliki masalah yang sama, yang hanya berhasil bagi saya adalah mengubah Animated: Yes to Animated: Tidak.
Sepertinya masalah itu karena animasi tidak selesai tepat waktu.
Semoga ini bisa membantu seseorang.
sumber
Untuk mereproduksi bug ini, cobalah mendorong dua pengontrol tampilan secara bersamaan. Atau mendorong dan meletus pada saat yang sama. Contoh:
Saya telah membuat kategori yang mencegat panggilan ini dan membuatnya aman dengan memastikan bahwa tidak ada dorongan lain yang terjadi saat satu sedang berlangsung. Cukup salin kode ke proyek Anda dan karena metode swizzling Anda akan baik untuk pergi.
sumber
popToRootViewController
ataupopToViewController:
ketika Anda sudah di controller tampilan root atau pada viewController akan muncul, makadidShowViewController
tidak akan dipanggil dan itu akan terjebakviewTransitionInProgress
.self.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)viewController; [self.interactivePopGestureRecognizer setEnabled:YES];
Kapan pengenal dinonaktifkan? Dan bagaimana Anda tahu apa yang seharusnya menjadi delegasi? Dengan garis-garis itu, bagi saya itu merusak gerakan pop setelah muncul sekali.Baru saja mengalami masalah ini juga. Biarkan saya tunjukkan kode saya:
Kesalahan muncul karena baris ini:
Anda tidak dapat menambahkan diri ke subview. Saya mengubah baris kode menjadi:
Kesalahan hilang dan saya bisa melihat kedua pandangan. Hanya berpikir ini akan membantu siapa saja yang ingin melihat contoh.
sumber
Cari kode Anda untuk "addSubview".
Di salah satu tempat yang Anda panggil metode ini, Anda mencoba menambahkan tampilan ke array sub-view sendiri menggunakan metode ini.
Sebagai contoh:
Atau:
sumber
[View2.view addSubview:View2.view]
dengan demikian, menambahkan diri sebagai subview.Saya pikir bahwa mendorong / memunculkan view controller dengan animasi di setiap titik harus baik-baik saja dan SDK harus dengan anggun menangani antrian panggilan untuk kita.
Oleh karena itu tidak dan semua solusi mencoba untuk mengabaikan dorongan berikutnya, yang dapat dianggap sebagai bug karena tumpukan navigasi akhir bukan apa yang dimaksud kode.
Saya malah menerapkan antrian panggilan push:
Itu tidak menangani antrian campuran push dan pops, tetapi itu adalah awal yang baik untuk memperbaiki sebagian besar crash kami.
Intisari: https://gist.github.com/rivera-ernesto/0bc628be1e24ff5704ae
sumber
Maaf terlambat datang ke pesta. Saya baru-baru ini mengalami masalah ketika bilah navigasi saya rusak karena mendorong lebih dari satu pengontrol tampilan sekaligus. Ini terjadi karena pengontrol tampilan lain didorong saat pengontrol tampilan pertama masih hidup. Mengambil petunjuk dari jawaban yang tidak ramah saya datang dengan solusi sederhana saya yang berfungsi dalam kasus saya. Anda hanya perlu
UINavigationController
mensubclass dan mengganti metode pushViewController dan memeriksa apakah animasi pengontrol tampilan sebelumnya sudah selesai. Anda dapat mendengarkan penyelesaian animasi dengan membuat kelas Anda menjadi delegasiUINavigationControllerDelegate
dan mengatur delegasiself
.Saya telah mengunggah inti di sini untuk mempermudah.
Pastikan Anda mengatur kelas baru ini sebagai NavigationController di storyboard Anda.
sumber
Berdasarkan @RobP petunjuk besar saya membuat subclass UINavigationController untuk mencegah masalah seperti itu. Ini menangani mendorong dan / atau bermunculan dan Anda dapat dengan aman menjalankan:
Jika flag 'acceptConflictingCommands' benar (secara default) pengguna akan melihat animasi mendorong vc1, vc2, vc3 dan kemudian akan melihat animasi popping vc3. Jika 'acceptConflictingCommands' salah, semua permintaan push / pop akan dibuang sampai vc1 sepenuhnya didorong - maka 3 panggilan lainnya akan dibuang.
sumber
animated:true
bendera?solusi nonamelive mengagumkan. Tetapi jika Anda tidak ingin menggunakan api pribadi, Anda dapat mencapai
UINavigationControllerDelegate
metode ini. Atau Anda dapat mengubah animasiYES
menjadiNO
. Ini adalah contoh kode, Anda dapat mewarisinya. Semoga bermanfaat :)https://github.com/antrix1989/ANNavigationController
sumber
Saya telah banyak mencari masalah ini, mungkin mendorong dua atau lebih VC pada saat yang sama, yang menyebabkan masalah animasi yang mendorong, Anda dapat merujuk ini: Tidak Dapat Menambahkan Diri sebagai Subview 崩溃 解决 办法
pastikan saja ada satu VC pada kemajuan transisi pada saat yang bersamaan , semoga sukses.
sumber
Terkadang Anda secara keliru mencoba menambahkan tampilan ke tampilan sendiri.
ubah ini ke sub tampilan Anda.
sumber
Saya juga mengalami masalah ini. Ketika saya melakukan analisis log Firebase, saya menemukan bahwa masalah ini hanya terjadi ketika aplikasi dingin dimulai. Jadi saya menulis demo yang dapat mereproduksi crash ini.
.
Saya juga menemukan bahwa ketika viewcontroller root jendela ditampilkan, melakukan beberapa dorongan tidak akan menyebabkan masalah yang sama lagi. (Anda dapat mengomentari testColdStartUp (rootNav) di AppDelegate.swift, dan batalkan komentar pada testColdStartUp () komentar di ViewController.swift)
ps: Saya menganalisis tempat kecelakaan ini di aplikasi saya. Ketika pengguna mengklik notifikasi push untuk memulai aplikasi dengan dingin, aplikasi tersebut masih di halaman Luncurkan dan mengklik push lain untuk melompat. Pada saat ini, aplikasi mungkin muncul Kecelakaan. My current Solusinya adalah dengan men-cache push atau tautan Universal mulai dingin untuk membuka halaman lompatan App, menunggu rootviewcontroller untuk ditampilkan, dan kemudian menunda eksekusi.
sumber
coba navigasi Anda menggunakan metode penundaan, untuk menyelesaikan animasi navigasi terakhir,
[self performSelector:<#(SEL)#> withObject:<#(id)#> afterDelay:<#(NSTimeInterval)#>]
sumber
Tampilan tidak dapat ditambahkan sebagai subview di dalamnya.
Tampilan mempertahankan hierarki orangtua-anak jadi jika Anda menambahkan tampilan sebagai subview dalam dirinya sendiri akan melalui pengecualian.
jika suatu kelas adalah UIViewController maka untuk mendapatkan pandangannya Anda menggunakan self.view.
jika suatu kelas adalah Kelas UIView maka untuk mendapatkan pandangannya Anda menggunakan sendiri.
sumber
Anda tidak dapat menambahkan diri sebagai subview jika akan menjadi Kelas UiViewController. Anda dapat menambahkan diri sebagai subview jika akan menjadi Kelas UiView.
sumber
Jika Anda ingin menambahkan Subview ke Tampilan, Anda dapat melakukannya seperti ini;
sumber