pemberhentianModalViewControllerAnimated tidak digunakan lagi

103

Saya baru saja meningkatkan ke XCode 4.5 untuk memperbarui aplikasi iOS saya agar berjalan pada layar 4 inci untuk iPhone 5, tetapi saya mendapatkan kesalahan dismissModalViewControllerAnimated:' is deprecatedversi yang mengatakan di telepon:

[self dismissModalViewControllerAnimated:NO];

Saya telah mencoba memperbarui ke kelebihan yang direkomendasikan dengan penangan penyelesaian (tetapi disetel ke NULL) seperti ini:

[self dismissModalViewControllerAnimated:NO completion:NULL];

Tapi kemudian baris ini memunculkan dua kesalahan:

warning: 'TabBarController' may not respond to '-presentModalViewController:animated:completion:'
Instance method '-presentModalViewController:animated:completion:' not found (return type defaults to 'id')

Terima kasih!

Mick Byrne
sumber

Jawaban:

307

Metode barunya adalah:

[self dismissViewControllerAnimated:NO completion:nil];

Kata modal telah dihapus; Seperti yang telah dilakukan untuk menyajikan panggilan API:

[self presentViewController:vc animated:NO completion:nil];

Alasannya dibahas dalam Sesi WWDC 2012 236 - Evolusi Pengontrol Tampilan di Video iOS . Pada dasarnya, pengontrol tampilan yang disajikan oleh API ini tidak lagi selalu modal, dan karena mereka menambahkan penangan penyelesaian, inilah saat yang tepat untuk mengganti namanya.

Menanggapi komentar dari Marc:

Apa cara terbaik untuk mendukung semua perangkat 4.3 ke atas? Metode baru tidak berfungsi di iOS4, namun metode lama tidak digunakan lagi di iOS6.

Saya menyadari bahwa ini hampir merupakan pertanyaan terpisah, tetapi saya pikir ini layak untuk disebutkan karena tidak semua orang memiliki uang untuk meningkatkan semua perangkat mereka setiap 3 tahun sehingga banyak dari kita memiliki beberapa perangkat yang lebih tua (sebelum 5.0). Namun, meskipun menyakitkan saya untuk mengatakannya, Anda perlu mempertimbangkan apakah itu layak untuk menargetkan di bawah 5.0. Ada banyak API baru dan keren yang tidak tersedia di bawah 5.0. Dan Apple terus mempersulit target mereka; dukungan armv6 dihapus dari Xcode 4.5, misalnya.

Untuk menargetkan di bawah 5.0 (selama blok penyelesaiannya nihil) cukup gunakan metode praktis respondsToSelector:

if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
    [self presentViewController:test animated:YES completion:nil];
} else {
    [self presentModalViewController:test animated:YES];
}

Menanggapi komentar lain dari Marc:

Itu bisa cukup banyak pernyataan If dalam aplikasi saya! ... Saya berpikir untuk membuat kategori yang merangkum kode ini, apakah membuat kategori di UIViewControler membuat saya ditolak?

dan satu dari Full Decent:

... apakah ada cara untuk menyebabkannya tidak menampilkan peringatan compiler secara manual?

Pertama, tidak, membuat kategori dengan UIViewControllersendirinya tidak akan membuat aplikasi Anda ditolak; kecuali metode kategori itu disebut API pribadi atau yang serupa.

Metode kategori adalah tempat yang sangat bagus untuk kode semacam itu. Selain itu, karena hanya akan ada satu panggilan ke API yang tidak digunakan lagi, hanya akan ada satu peringatan compiler.

Untuk menjawab komentar Full Decent (pertanyaan), ya, Anda dapat menyembunyikan peringatan compiler secara manual. Berikut ini tautan ke jawaban tentang SO tentang subjek itu . Metode kategori juga merupakan tempat yang tepat untuk menyembunyikan peringatan compiler, karena Anda hanya menyembunyikan peringatan di satu tempat. Anda tentunya tidak ingin berkeliling membungkam kompiler secara sembarangan.

Jika saya menulis metode kategori sederhana untuk ini, mungkin akan seperti ini:

@implementation UIViewController (NJ_ModalPresentation)
-(void)nj_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion{
    NSAssert(completion == nil, @"You called %@ with a non-nil completion. Don't do that!",NSStringFromSelector(_cmd));
    if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
        [self presentViewController:viewControllerToPresent animated:flag completion:completion];
    } else {
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [self presentModalViewController:viewControllerToPresent animated:flag];
#pragma clang diagnostic pop
    }
}
@end
NJones
sumber
2
Apa cara terbaik untuk mendukung semua perangkat 4.3 ke atas? Metode baru tidak berfungsi di iOS4, namun metode lama tidak digunakan lagi di iOS6. Rock dan tempat yang sulit?
Marc
@Marc Saya menambahkan jawaban saya untuk mengatasi kekhawatiran Anda.
NJones
Terima kasih. Itu bisa jadi cukup banyak pernyataan If dalam aplikasi saya! Saya kira pendekatan yang sama bisa bekerja saat menggunakan properti 'modalViewController'. Saya berpikir untuk membuat kategori yang merangkum kode ini, apakah membuat kategori di UIViewControler membuat saya ditolak?
Marc
Untuk kode, if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; }apakah ada cara untuk menyebabkannya secara manual agar tidak menampilkan peringatan kompiler?
William Entriken
@FullDent Ya Anda bisa. Saya mengedit jawaban saya dengan beberapa informasi tentang itu.
NJones
6

Sekarang di iOS 6 dan lebih tinggi, Anda dapat menggunakan:

[[Picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];

Dari pada:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

... Dan Anda dapat menggunakan:

[self presentViewController:picker animated:YES completion:nil];

Dari pada

[self presentModalViewController:picker animated:YES];    
Dipang
sumber
4

[self dismissModalViewControllerAnimated:NO]; sudah tidak digunakan lagi.

Gunakan [self dismissViewControllerAnimated:NO completion:nil];sebagai gantinya.

Jayprakash Dubey
sumber
4

Menggunakan

[self dismissViewControllerAnimated:NO completion:nil];
Mak083
sumber
3

Peringatannya masih ada. Untuk menghilangkannya, saya memasukkannya ke selektor seperti ini:

if ([self respondsToSelector:@selector(dismissModalViewControllerAnimated:)]) {
    [self performSelector:@selector(dismissModalViewControllerAnimated:) withObject:[NSNumber numberWithBool:YES]];
} else {
    [self dismissViewControllerAnimated:YES completion:nil];
}

Ini bermanfaat bagi orang dengan OCD seperti saya;)

kjoelbro
sumber
Anda harus mengganti pernyataan if karena saya percaya bahwa metode yang tidak digunakan lagi tidak akan respondsToSelectormengembalikan false. Dengan demikian, yang baru dismissViewControllerAnimated:tidak akan pernah dipanggil sampai pembaruan di masa mendatang di mana mereka mungkin menghapus dismissModalViewControllerAnimated:semuanya.
Jsdodgers
0

Berikut adalah versi presentViewController yang sesuai yang saya gunakan jika membantu pemula lain seperti saya:

if ([self respondsToSelector:@selector(presentModalViewController:animated:)]) {
    [self performSelector:@selector(presentModalViewController:animated:) withObject:testView afterDelay:0];
} else {
    [self presentViewController:configView animated:YES completion:nil];
}
[testView.testFrame setImage:info]; //this doesn't work for performSelector
[testView.testText setHidden:YES];

Saya telah menggunakan ViewController 'secara umum' dan bisa mendapatkan tampilan modal untuk tampil berbeda tergantung apa yang dipanggil untuk dilakukan (menggunakan setHidden dan setImage). dan semuanya bekerja dengan baik sebelumnya, tetapi performSelector mengabaikan hal-hal 'set', jadi pada akhirnya ini tampaknya menjadi solusi yang buruk jika Anda mencoba menjadi efisien seperti yang saya coba ...

Walter
sumber