Yanıtlar:
modalViewController
İOS 6'da kullanımdan kaldırıldığından bu yana , iOS 5+ için çalışan ve uyarı olmadan derlenen bir sürümü burada bulabilirsiniz.
Objective-C:
- (BOOL)isModal {
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}
Swift:
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
|| self.tabBarController?.presentingViewController is UITabBarController
}
Felipe'nin cevabına şapka bahşiş.
nil == nil
geri dönüyor YES
ve istediğimiz sonuç bu değil.
İOS 6+ arıyorsanız, bu cevap kullanımdan kaldırılmıştır ve Gabriele Petronella'nın cevabını kontrol etmelisiniz.
UIKit'e özgü bir özellik veya yöntem olarak bunu yapmanın düzgün bir yolu yoktur. Yapabileceğiniz şey, kontrolörünüzün modal olarak sunulduğundan emin olmak için çeşitli yönlerini kontrol etmektir.
Dolayısıyla, mevcut ( self
aşağıdaki kodda gösterildiği gibi ) denetleyicinin modsal bir şekilde sunulup sunulmadığını kontrol etmek için, aşağıdaki işlevi bir UIViewController
kategoride veya (projenizin diğer UIKit denetleyicilerini kullanması gerekmiyorsa) UITableViewController
örneğin) diğer denetleyicilerimin devraldığı bir temel denetleyicide
-(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;
}
DÜZENLEME: Bir UITabBarController'ın kullanılıp kullanılmadığını görmek için son kontrolü ekledim ve modal olarak başka bir UITabBarController sunuyorsunuz.
DÜZENLEME 2: artık UIViewController
yanıt vermeyen parentViewController
, presentingViewController
bunun yerine iOS 5+ kontrolü eklendi .
DÜZENLEME 3: https://gist.github.com/3174081 durumunda bunun için bir öz oluşturdum
modalViewController
Özelliğin iOS 6 itibariyle kullanımdan kaldırıldığını unutmayın . Belgeler presentedViewController
bunun yerine kullanılmasını önerir .
NSLog(@"%@", self.navigationController.parentViewController)
baskılar (null)
- lütfen nedenini açıklar mısınız? My ViewController, film şeridindeki navController aracılığıyla modal görünüm denetleyicisine bağlanır.
.parentViewController
kullanımdan kaldırıldı, .presentingViewController
onun yerine kullanılmalı.
İOS5 + 'da, UIViewController Sınıf Başvurusu'nda görebileceğiniz gibi , bunu "presentingViewController" özelliğinden alabilirsiniz.
presentingViewController Bu görünüm denetleyicisini sunan görünüm denetleyicisi. (Sadece oku)
@property (nontomic, readonly) UIViewController * presentingViewController
Discussion
Bu mesajı alan görünüm denetleyicisi başka bir görünüm denetleyicisi tarafından sunulursa, bu özellik onu sunan görünüm denetleyicisini tutar. Görünüm denetleyicisi sunulmuyorsa, ancak atalarından biri sunuluyorsa, bu özellik en yakın atayı sunan görünüm denetleyicisini tutar. Ne görünüm denetleyicisi ne de onun atalarından biri sunulmuyorsa, bu özellik nil tutar.
Kullanılabilirlik
iOS 5.0 ve sonrasında mevcuttur.
UIViewController.h'de
Bildirildi
presentingViewController
. Ataları otomatik olarak geçtiği için konteyner görünümü denetleyicilerinde de çalışacaktır.
Eğer yoksa, presentedAsModal
UIViewController alt sınıfınızda this ( ) için bir özellik tanımlayabilir YES
ve ViewController'ı modal bir görünüm olarak sunmadan önce bunu ayarlayabilirsiniz .
childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];
Bu değeri viewWillAppear
geçersiz kılmanızda kontrol edebilirsiniz .
Görüntünün nasıl sunulduğunu belirten resmi bir mülk olmadığına inanıyorum, ancak hiçbir şey sizi kendi görünümünüzü yaratmaktan alıkoyamıyor.
UINavigationController
Sadece bu özelliği eklemek için özel bir gezinti denetleyicisi oluşturmadığınız sürece, ... modal olarak sunuyorsanız bu çözüm çalışmaz . Ve bundan sonra, denetleyicilerin içinde, denetleyicinin self.navigationController
modal olarak sunulup sunulmadığını her kontrol etmeniz gerektiğinde bu özel sınıfa yayınlamaya devam etmeniz gerekecek
Eğer self.navigationController modsal olarak sunulursa, ancak self, self.navigationController.viewControllers [0] 'a eşit değilse, bu durumda self'e basıldığında Petronella'nın cevabı işe yaramaz.
İşte sorunu nasıl çözebileceğiniz.
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]];
Ve Swift'de:
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
|| self.tabBarController?.presentingViewController is UITabBarController
Bu çalışmalı.
if(self.parentViewController.modalViewController == self)…
UINavigationController
ve UITabBarController
durumları kontrol etmek için bir cevap ekledim . Şu ana kadar oldukça iyi çalışıyor
Kontrol etmenin en iyi yolu
if (self.navigationController.presentingViewController) {
NSLog(@"Model Present");
}
Tam ekran modal görünümler ve modal olmayan görünümler arasında ayrım yapmanız gerekmiyorsa, ki projemdeki durum budur (yalnızca form sayfaları ve sayfa sayfalarında oluşan bir sorunla uğraşıyordum), modalPresentationStyle'ı kullanabilirsiniz. UIViewController özelliği:
switch (self.modalPresentationStyle) {
case 0: NSLog(@"full screen, or not modal"); break;
case 1: NSLog(@"page sheet"); break;
case 2: NSLog(@"form sheet"); break;
}
In 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
}
Projemde, mod olarak (yeni bir öğe eklerken) veya Ana görünüm denetleyicisi tarafından (mevcut olanı düzenlerken) itme ile sunulabilen bir görünüm denetleyicisine (Ayrıntı) sahibim. Kullanıcı [Bitti] 'ye dokunduğunda, Detay görünüm denetleyicisi kapatılmaya hazır olduğunu bildirmek için Ana görünüm denetleyicisinin yöntemini çağırır. Kaptanın nasıl kapatılacağını bilmek için Ayrıntının nasıl sunulacağını belirlemesi gerekir. Ben bunu böyle yapıyorum:
UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
[self dismissViewControllerAnimated:YES completion:NULL];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
Bunun gibi bir hack işe yarayabilir.
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
}
Ancak, önceki cevabımın daha temiz bir çözüm olduğunu düşünüyorum.
Benim için işe yarayan şey şudur:
// 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);
Test ettiğim kadarıyla, bu iOS7 ve iOS8 için çalışıyor. Ancak iOS6'da denemedim.
Bu soruya doğru cevabı bulmak için biraz etrafa baktım ve olası tüm senaryoları kapsayan hiçbirini bulamadım. İşi yapıyor gibi görünen bu birkaç satır kod yazdım. Neyin kontrol edildiğini anlamak için birkaç satır içi yorum bulabilirsiniz.
- (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;
}
Umarım bu yardımcı olur.
İşte benim değiştirilmiş @ GabrielePetronella isModal
sürümüm, ilk önce parentViewController hiyerarşisini yürüterek içerilen görünüm denetleyicileri ile çalışır. Ayrıca kodu birden çok satıra çekti, böylece ne yaptığı açık.
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
}