जवाबों:
चूंकि modalViewController
आईओएस 6 में पदावनत किया गया है, यहां एक संस्करण है जो आईओएस 5+ के लिए काम करता है और जो चेतावनी के बिना संकलित करता है।
उद्देश्य सी:
- (BOOL)isModal {
return self.presentingViewController.presentedViewController == self
|| (self.navigationController != nil && self.navigationController.presentingViewController.presentedViewController == self.navigationController)
|| [self.tabBarController.presentingViewController isKindOfClass:[UITabBarController class]];
}
स्विफ्ट:
var isModal: Bool {
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController)
|| self.tabBarController?.presentingViewController is UITabBarController
}
फेलिप के जवाब के लिए हैट टिप।
nil == nil
रिटर्न YES
, और यह वह परिणाम नहीं है जो हम चाहते हैं।
यदि आप iOS 6+ की तलाश कर रहे हैं, तो यह उत्तर पदावनत है और आपको गेब्रियल पेट्रोनेला के उत्तर की जाँच करनी चाहिए
UIKit के लिए एक संपत्ति या विधि के रूप में ऐसा करने का कोई साफ तरीका नहीं है। यह सुनिश्चित करने के लिए कि आप क्या कर सकते हैं अपने नियंत्रक के कई पहलुओं की जाँच करें ताकि इसे मोडल के रूप में प्रस्तुत किया जा सके।
इसलिए, यह जांचने के लिए कि क्या करंट ( self
कोड बलो में दर्शाया गया है) कंट्रोलर को मोडल तरीके से प्रस्तुत किया गया है या नहीं, मेरे पास फंक्शन बलो है या तो एक UIViewController
श्रेणी में, या (यदि आपके प्रोजेक्ट को अन्य यूकीट कंट्रोलर का उपयोग करने की आवश्यकता नहीं है, तो UITableViewController
उदाहरण के लिए) एक आधार नियंत्रक में जो मेरे अन्य नियंत्रकों को विरासत में मिला है
-(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;
}
संपादित करें: मैंने अंतिम चेक को यह देखने के लिए जोड़ा कि क्या UITabBarController का उपयोग किया जा रहा है, और आप एक और UITabBarController मॉडल के रूप में प्रस्तुत करते हैं।
EDIT 2: iOS 5+ चेक जोड़ा गया, जहां अब UIViewController
और parentViewController
नहीं, बल्कि इसका जवाब है presentingViewController
।
EDIT 3: मैंने इसके लिए केवल https://gist.github.com/3174081 मामले में एक जिस्ट बनाया है
modalViewController
संपत्ति आईओएस 6 के रूप में पदावनत है। प्रलेखन presentedViewController
इसके बजाय उपयोग करने का सुझाव देता है ।
NSLog(@"%@", self.navigationController.parentViewController)
प्रिंट (null)
- आप कृपया समझा सकते हैं क्यों? मेरा ViewController स्टोरीबोर्ड में navController के माध्यम से मोडल व्यू कंट्रोलर के साथ जुड़ा हुआ है।
.parentViewController
पदावनत है, .presentingViewController
इसके बजाय इसका उपयोग किया जाना चाहिए।
IOS5 + में, जैसा कि आप UIViewController Class Reference में देख सकते हैं , आप इसे प्रॉपर्टी "प्रेजेंटिव्यूक्रैड्रोलर" से प्राप्त कर सकते हैं।
presentingViewController दृश्य नियंत्रक जिसने यह दृश्य नियंत्रक प्रस्तुत किया है। (सिफ़ पढ़िये)
@property (गैर-परमाणु, आसानी से) UIViewController * presentingViewController
चर्चा
यदि यह संदेश प्राप्त करने वाला दृश्य नियंत्रक किसी अन्य दृश्य नियंत्रक द्वारा प्रस्तुत किया जाता है, तो यह गुण उस दृश्य नियंत्रक को रखता है जो इसे प्रस्तुत कर रहा है। यदि दृश्य नियंत्रक प्रस्तुत नहीं किया गया है, लेकिन इसके पूर्वजों में से एक को प्रस्तुत किया जा रहा है, तो यह संपत्ति निकटतम पूर्वज को प्रस्तुत करने वाला दृश्य नियंत्रक रखती है। यदि न तो दृश्य नियंत्रक और न ही इसके पूर्वजों को प्रस्तुत किया जा रहा है, तो यह संपत्ति शून्य है।
उपलब्धता
आईओएस 5.0 और बाद में उपलब्ध है।
UIViewController.h में
घोषित किया गया
presentingViewController
। यह कंटेनर दृश्य नियंत्रकों में भी काम करेगा, क्योंकि यह स्वचालित रूप से पूर्वजों का पता लगाता है।
यदि ऐसा नहीं है, तो आप presentedAsModal
अपने UIViewController उपवर्ग में इसके लिए ( ) संपत्ति को परिभाषित कर सकते हैं और YES
ViewController को एक दृश्य के रूप में प्रस्तुत करने से पहले इसे सेट कर सकते हैं।
childVC.presentedAsModal = YES;
[parentVC presentModalViewController:childVC animated:YES];
आप अपने viewWillAppear
ओवरराइड में इस मान की जाँच कर सकते हैं।
मेरा मानना है कि कोई आधिकारिक संपत्ति नहीं है जो बताती है कि दृश्य कैसे प्रस्तुत किया जाता है, लेकिन कुछ भी आपको अपना स्वयं का निर्माण करने से रोकता है।
UINavigationController
मोडल के रूप में प्रस्तुत कर रहे हैं तो यह समाधान काम नहीं करता है ... जब तक कि आप केवल इस संपत्ति को जोड़ने के लिए एक कस्टम नेविगेशन नियंत्रक नहीं बनाते हैं। और उसके बाद, नियंत्रकों के अंदर, आपको self.navigationController
हर बार इस कस्टम वर्ग के लिए कास्टिंग रखना होगा कि आपको यह जांचना है कि क्या नियंत्रक को मोडल के रूप में प्रस्तुत किया गया है
पेट्रोनेला का जवाब काम नहीं करता है अगर self.navigationController को औपचारिक रूप से प्रस्तुत किया गया है, लेकिन स्वयं self.navigationController.viewControllers [0] के बराबर नहीं है, उस स्थिति में स्वयं को धक्का दिया जाता है।
यहां बताया गया है कि आप समस्या को कैसे ठीक कर सकते हैं।
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]];
और स्विफ्ट में:
return self.presentingViewController?.presentedViewController == self
|| (self.navigationController != nil && self.navigationController?.presentingViewController?.presentedViewController == self.navigationController && self.navigationController?.viewControllers[0] == self)
|| self.tabBarController?.presentingViewController is UITabBarController
यह काम करना चाहिए।
if(self.parentViewController.modalViewController == self)…
UINavigationController
और UITabBarController
मामलों की जांच के लिए सिर्फ एक उत्तर जोड़ा । यह अब तक बहुत अच्छा काम कर रहा है
यदि आपको पूर्ण-स्क्रीन मोडल दृश्यों और गैर-मोडल विचारों के बीच अंतर करने की आवश्यकता नहीं है, जो कि मेरी परियोजना में है (मैं एक समस्या से निपट रहा था जो केवल फॉर्म शीट और पेज शीट के साथ होती है), आप modalPresentation.tyle का उपयोग कर सकते हैं 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;
}
में स्विफ्ट :
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
}
मेरे प्रोजेक्ट में मेरे पास एक व्यू कंट्रोलर (डिटेल) है जिसे मास्टर व्यू कंट्रोलर द्वारा या तो औपचारिक रूप से प्रस्तुत किया जा सकता है (जब कोई नया आइटम जोड़ रहा हो) या पुश के साथ (किसी मौजूदा को एडिट करते समय)। जब उपयोगकर्ता टैप करता है [हो गया] डिटेल व्यू कंट्रोलर मास्टर व्यू कंट्रोलर का तरीका बताता है कि यह बंद होने के लिए तैयार है। मास्टर को यह निर्धारित करना है कि इसे कैसे बंद किया जाए, यह जानने के लिए विस्तार से प्रस्तुत किया गया है। यह है कि मैं यह कैसे करते हैं:
UIViewController *vc = self.navigationController.viewControllers.lastObject;
if (vc == self) {
[self dismissViewControllerAnimated:YES completion:NULL];
} else {
[self.navigationController popViewControllerAnimated:YES];
}
इस तरह एक हैक काम कर सकता है।
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
}
हालांकि, मुझे लगता है कि मेरा पिछला जवाब एक क्लीनर समाधान है।
मेरे लिए क्या काम कर रहा है:
// 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);
जहाँ तक मैंने इसका परीक्षण किया है, यह iOS7 और iOS8 के लिए काम करता है। हालांकि iOS6 पर कोशिश नहीं की।
मैंने इस प्रश्न का सही उत्तर खोजने के लिए चारों ओर देखा है, और मुझे ऐसा कोई भी नहीं मिला, जो सभी संभावित परिदृश्यों को कवर करता हो। मैंने कोड की ये कुछ पंक्तियाँ लिखी हैं जो काम करती प्रतीत होती हैं। आपको पता लगाने के लिए कुछ इनलाइन टिप्पणियाँ मिल सकती हैं।
- (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;
}
उममीद है कि इससे मदद मिलेगी।
यहाँ मेरा संशोधित संस्करण @ GabrielePetronella है isModal
, जो इसमें सम्मिलित दृश्य नियंत्रकों के साथ काम करता है, जो पहले पैरेंटव्यूकंट्रोलर पदानुक्रम तक चलता है। साथ ही कोड को कई लाइनों में खींच लिया ताकि यह स्पष्ट हो जाए कि यह क्या कर रहा है।
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
}