Jawaban:
Karena modalViewController
sudah tidak digunakan lagi di iOS 6, berikut adalah versi yang berfungsi untuk iOS 5+ dan yang terkompilasi tanpa peringatan.
Objective-C:
- (BOOL)isModal {
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}
Cepat:
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
|| self.tabBarController?.presentingViewController is UITabBarController
}
Tip topi untuk jawaban Felipe.
nil == nil
mengembalikan YES
, dan itu bukan hasil yang kita inginkan.
Jika Anda mencari iOS 6+, jawaban ini sudah usang dan Anda harus memeriksa jawaban Gabriele Petronella
Tidak ada cara yang tepat untuk melakukan itu, sebagai properti atau metode asli UIKit. Yang dapat Anda lakukan adalah memeriksa beberapa aspek pengontrol Anda untuk memastikannya disajikan sebagai modal.
Jadi, untuk memeriksa apakah pengontrol saat ini (direpresentasikan seperti self
pada kode di bawah) disajikan dengan cara modal atau tidak, saya memiliki fungsi di bawah ini baik dalam UIViewController
kategori, atau (jika proyek Anda tidak perlu menggunakan pengontrol UIKit lainnya, seperti UITableViewController
misalnya) dalam pengontrol dasar yang diwarisi oleh pengontrol saya yang lain
-(BOOL)isModal {
BOOL isModal = ((self.parentViewController && self.parentViewController.modalViewController == self) ||
//or if I have a navigation controller, check if its parent modal view controller is self navigation controller
( self.navigationController && self.navigationController.parentViewController && self.navigationController.parentViewController.modalViewController == self.navigationController) ||
//or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
[[[self tabBarController] parentViewController] isKindOfClass:[UITabBarController class]]);
//iOS 5+
if (!isModal && [self respondsToSelector:@selector(presentingViewController)]) {
isModal = ((self.presentingViewController && self.presentingViewController.modalViewController == self) ||
//or if I have a navigation controller, check if its parent modal view controller is self navigation controller
(self.navigationController && self.navigationController.presentingViewController && self.navigationController.presentingViewController.modalViewController == self.navigationController) ||
//or if the parent of my UITabBarController is also a UITabBarController class, then there is no way to do that, except by using a modal presentation
[[[self tabBarController] presentingViewController] isKindOfClass:[UITabBarController class]]);
}
return isModal;
}
EDIT: Saya menambahkan pemeriksaan terakhir untuk melihat apakah UITabBarController sedang digunakan, dan Anda menyajikan UITabBarController lain sebagai modal.
EDIT 2: menambahkan cek iOS 5+, di mana UIViewController
tidak menjawab parentViewController
lagi, tetapi presentingViewController
sebagai gantinya.
EDIT 3: Saya telah membuat intinya untuk berjaga-jaga jika https://gist.github.com/3174081
modalViewController
properti ini tidak digunakan lagi mulai iOS 6. Dokumentasi menyarankan untuk digunakan presentedViewController
.
NSLog(@"%@", self.navigationController.parentViewController)
cetakan (null)
- bisakah Anda menjelaskan mengapa? ViewController saya terhubung dengan pengontrol tampilan modal melalui navController di storyboard.
.parentViewController
sudah usang, .presentingViewController
harus digunakan sebagai gantinya.
Di iOS5 +, Seperti yang Anda lihat di Referensi Kelas UIViewController , Anda bisa mendapatkannya dari properti "presentingViewController".
presentingViewController Pengontrol tampilan yang menyajikan pengontrol tampilan ini. (hanya baca)
@property (nonatomik, hanya baca) UIViewController * Diskusi presentingViewController
Jika pengontrol tampilan yang menerima pesan ini disajikan oleh pengontrol tampilan lain, properti ini menahan pengontrol tampilan yang mempresentasikannya. Jika pengontrol tampilan tidak disajikan, tetapi salah satu pendahulunya disajikan, properti ini menahan pengontrol tampilan yang menyajikan leluhur terdekat. Jika tidak ada pengontrol tampilan atau salah satu leluhurnya yang disajikan, properti ini memegang nol.
Ketersediaan
Tersedia di iOS 5.0 dan lebih baru.
Dinyatakan Dalam
UIViewController.h
presentingViewController
. Ini juga akan bekerja di pengontrol tampilan kontainer, karena secara otomatis melintasi leluhur.
Jika tidak ada, Anda bisa mendefinisikan properti untuk this ( presentedAsModal
) di subkelas UIViewController Anda dan menyetelnya ke YES
sebelum menyajikan ViewController sebagai tampilan modal.
childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];
Anda dapat memeriksa nilai ini di viewWillAppear
override Anda .
Saya yakin tidak ada properti resmi yang menyatakan bagaimana tampilan tersebut disajikan, tetapi tidak ada yang menghalangi Anda untuk membuatnya sendiri.
UINavigationController
sebagai modal ... kecuali Anda membuat pengontrol navigasi kustom hanya untuk menambahkan properti ini. Dan setelah itu, di dalam pengontrol, Anda harus terus mentransmisikan self.navigationController
ke kelas khusus ini setiap kali Anda perlu memeriksa apakah pengontrol disajikan sebagai modal
Jawaban Petronella tidak berfungsi jika self.navigationController disajikan secara sederhana tetapi self tidak sama dengan self.navigationController.viewControllers [0], dalam hal ini self didorong.
Inilah cara Anda memperbaiki masalah.
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController && self == self.navigationController.viewControllers[0])
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
Dan di Swift:
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
|| self.tabBarController?.presentingViewController is UITabBarController
Ini seharusnya berhasil.
if(self.parentViewController.modalViewController == self)…
UINavigationController
dan UITabBarController
kasus. Ini bekerja dengan cukup baik sejauh ini
Cara terbaik untuk memeriksanya
if (self.navigationController.presentingViewController) {
NSLog(@"Model Present");
}
Jika Anda tidak perlu membedakan antara tampilan modal layar penuh dan tampilan non-modal, yang merupakan kasus dalam proyek saya (saya berurusan dengan masalah yang hanya terjadi dengan lembar formulir dan lembar halaman), Anda dapat menggunakan modalPresentationStyle properti UIViewController:
switch (self.modalPresentationStyle) {
case 0: NSLog(@"full screen, or not modal"); break;
case 1: NSLog(@"page sheet"); break;
case 2: NSLog(@"form sheet"); break;
}
Di Swift :
func isUIViewControllerPresentedAsModal() -> Bool {
if((self.presentingViewController) != nil) {
return true
}
if(self.presentingViewController?.presentedViewController == self) {
return true
}
if(self.navigationController?.presentingViewController?.presentedViewController == self.navigationController) {
return true
}
if((self.tabBarController?.presentingViewController?.isKindOfClass(UITabBarController)) != nil) {
return true
}
return false
}
Dalam proyek saya, saya memiliki pengontrol tampilan (Detail) yang dapat disajikan baik secara sederhana (saat menambahkan item baru) atau dengan push (saat mengedit yang sudah ada) oleh pengontrol tampilan Master. Ketika pengguna mengetuk [Selesai], pengontrol tampilan Detail memanggil metode pengontrol tampilan Master untuk memberi tahu bahwa itu siap untuk ditutup. Guru harus menentukan bagaimana Detail disajikan untuk mengetahui bagaimana menutupnya. Beginilah cara saya melakukan ini:
UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
[self dismissViewControllerAnimated:YES completion:NULL];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
Peretasan seperti ini mungkin berhasil.
UIViewController* child = self;
UIViewController* parent = child.parentViewController;
while (parent && parent.modalViewController != child) {
child = parent;
parent = child.parentViewController;
}
if (parent) {
// A view controller in the hierarchy was presented as a modal view controller
}
Namun, saya pikir jawaban saya sebelumnya adalah solusi yang lebih bersih.
Apa yang berhasil untuk saya adalah sebagai berikut:
// this is the trick: set parent view controller as application's window root view controller
UIApplication.sharedApplication.delegate.window.rootViewController = viewController;
// assert no modal view is presented
XCTAssertNil(viewController.presentedViewController);
// simulate button tap which shows modal view controller
[viewController.deleteButton sendActionsForControlEvents:UIControlEventTouchUpInside];
// assert that modal view controller is presented
XCTAssertEqualObjects(viewController.presentedViewController.class, MyModalViewController.class);
Sejauh saya mengujinya, ini berfungsi untuk iOS7 dan iOS8. Namun tidak mencoba di iOS6.
Saya telah melihat-lihat untuk menemukan jawaban yang tepat untuk pertanyaan ini, dan saya tidak dapat menemukan jawaban yang mencakup semua kemungkinan skenario. Saya menulis beberapa baris kode ini yang tampaknya berhasil. Anda dapat menemukan beberapa komentar sebaris untuk mencari tahu apa yang telah diperiksa.
- (BOOL)isModal {
BOOL modal = NO;
if ([self presentingViewController]) { //Some view Controller is presenting the current stack
UIViewController *presented = [[self presentingViewController] presentedViewController]; // What's been presented
if ([presented respondsToSelector:@selector(viewControllers)]) { // There's a stack
NSArray *viewControllers = [presented performSelector:@selector(viewControllers)];
modal = [viewControllers firstObject] == self; // Current VC is presented modally if it's the first in the stack
}
else {
modal = presented == self; // Don't think this is actually needed. set modal = YES should do the job tho.
}
}
return modal;
}
Semoga bantuan ini.
Inilah versi modifikasi saya dari @ GabrielePetronella's isModal
, yang berfungsi dengan pengontrol tampilan yang ada di dalamnya yang berjalan naik hierarki parentViewController terlebih dahulu. Juga tarik kode menjadi beberapa baris sehingga jelas apa yang dilakukannya.
var isModal: Bool {
// If we are a child view controller, we need to check our parent's presentation
// rather than our own. So walk up the chain until we don't see any parentViewControllers
var potentiallyPresentedViewController : UIViewController = self
while (potentiallyPresentedViewController.parentViewController != nil) {
potentiallyPresentedViewController = potentiallyPresentedViewController.parentViewController!
}
if self.presentingViewController?.presentedViewController == potentiallyPresentedViewController {
return true
}
if let navigationController = potentiallyPresentedViewController.navigationController {
if navigationController.presentingViewController?.presentedViewController == navigationController {
return true
}
}
return potentiallyPresentedViewController.tabBarController?.presentingViewController is UITabBarController
}