चेतावनी: प्रस्तुत करने का प्रयास * पर * जिसका दृश्य खिड़की में नहीं है पदानुक्रम - स्विफ्ट


83

ViewController यदि डेटा मॉडल में कोई सहेजा गया डेटा है, तो मैं प्रस्तुत करने का प्रयास कर रहा हूं । लेकिन मुझे निम्नलिखित त्रुटि मिलती है:

चेतावनी: प्रस्तुत करने का प्रयास * पर * जिसका दृश्य खिड़की पदानुक्रम में नहीं है "

प्रासंगिक कोड:

override func viewDidLoad() {
    super.viewDidLoad()
    loginButton.backgroundColor = UIColor.orangeColor()

    var request = NSFetchRequest(entityName: "UserData")
    request.returnsObjectsAsFaults = false

    var appDel:AppDelegate = (UIApplication.sharedApplication().delegate as AppDelegate)
    var context:NSManagedObjectContext = appDel.managedObjectContext!

    var results:NSArray = context.executeFetchRequest(request, error: nil)!

    if(results.count <= 0){
        print("Inga resultat")
    } else {
        print("SWITCH VIEW PLOX")
        let internVC = self.storyboard?.instantiateViewControllerWithIdentifier("internVC") as internViewController
        self.presentViewController(internVC, animated: true, completion: nil)
    }
}

मैंने बिना सफलता के Google का उपयोग करते हुए विभिन्न समाधानों की कोशिश की है।


क्या आपने स्टोरीबोर्ड में अपना ViewController कनेक्ट किया है? आप यहां एक नैविगेशन कंट्रोलर का उपयोग कर रहे हैं?
डेरीडा

अगर मैं ViewControllerस्टोरीबोर्ड में अपना कनेक्ट कर चुका हूं तो आपका क्या मतलब है ? मैं NavigationController
Nils Wasell

कोशिश करें: ViewDidLoad में self.addChildViewController (childController: UIViewController)
derdida

यह एक त्रुटि उत्पन्न करता है। यह "प्रकार नाम" ( UIViewControllerभाग) के बाद एक सदस्य का नाम या कंस्ट्रक्टर कॉल की उम्मीद करता है । @ यर्डिडा
निल्स वासेल

आपने ऐसा कहां लिखा है? अपने MainViewController के ViewDidLoad में?
derdida

जवाबों:


127

आपके कोड में इस बिंदु पर दृश्य नियंत्रक का दृश्य केवल बनाया गया है, लेकिन किसी भी दृश्य पदानुक्रम में नहीं जोड़ा गया है। यदि आप उस दृश्य नियंत्रक से जल्द से जल्द प्रस्तुत करना चाहते हैं तो आपको इसे viewDidAppearसबसे सुरक्षित होने के लिए करना चाहिए ।


2
अगर मैं इसे viewDidAppear में डालता हूं, तो जब मैं प्रस्तुत दृश्यकंट्रोलर को खारिज करता हूं, तो यह फिर से viewDidAppear विधि को कॉल करेगा और viewController को फिर से प्रस्तुत करेगा। मेरे पास प्रस्तुत करने से पहले एक सशर्त विवरण डालने का एक वर्कअराउंड है, लेकिन क्या इसे डालने के बजाय कोई तरीका है सशर्त बयान?
पुनीत

2
मैं कहूंगा कि जब कोई स्क्रीन दिखाई देती है, तो दूसरे मोडल को सही तरीके से पेश करने की कोशिश करना शुरू होता है, इसलिए एक राज्य बूल शायद ही सबसे बुरा समाधान है। उसी समय, उस मूल कारण के बारे में सोचें जिसके लिए आपको मोडल प्रदर्शित करने की आवश्यकता है और देखें कि क्या आप उस जानकारी तक पहुँच सकते हैं।
ऐची

2
यदि आप इसे ViewWillAppear में करते हैं, तो आपके पास अपनी प्रस्तुति शुरू करने के समय स्थिति होगी। वैकल्पिक रूप से इसे व्यूप्लेयर में डाल दिया जाएगा लेकिन संक्रमण के पूरा होने में कोड जोड़ने के लिए iOS 8 में ट्रांज़ोकोर्डिनेटर प्रॉपर्टी का उपयोग करें। अधिक जानकारी यहाँ पाया जा सकता है। developer.apple.com/library/prerelease/ios/documentation/UIKit/…
Acey

36

उद्देश्य c में: mpmovieplayer के शीर्ष पर viewcontroller प्रस्तुत करते समय इसने मेरी समस्या को हल किया

- (UIViewController*) topMostController
{
    UIViewController *topController = [UIApplication sharedApplication].keyWindow.rootViewController;

    while (topController.presentedViewController) {
        topController = topController.presentedViewController;
    }

    return topController;
}

34

स्विफ्ट 3

मुझे यह एक नौसिखिया के रूप में सामने आता रहा और पाया गया कि वर्तमान में मॉडल्स के दृश्य लोड होते हैं जिन्हें खारिज किया जा सकता है लेकिन रूट कंट्रोलर पर स्विच करना सबसे अच्छा है अगर आपको मोडल दिखाने की आवश्यकता नहीं है।

मैं यह प्रयोग कर रहा था

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc  = storyboard?.instantiateViewController(withIdentifier: "MainAppStoryboard") as! TabbarController
present(vc, animated: false, completion: nil)

इसके बजाय मेरे टैबकंट्रोलर के साथ इसका उपयोग करना:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let view = storyboard.instantiateViewController(withIdentifier: "MainAppStoryboard") as UIViewController
let appDelegate = UIApplication.shared.delegate as! AppDelegate
//show window
appDelegate.window?.rootViewController = view

यदि आपको कई स्टोरीबोर्ड स्क्रीन के बीच स्विच करने की आवश्यकता है, तो बस एक दृश्य नियंत्रक को समायोजित करें।


16

स्विफ्ट 3।

इस फ़ंक्शन को सर्वोच्च दृश्य नियंत्रक प्राप्त करने के लिए कॉल करें, फिर उस दृश्य नियंत्रक को मौजूद करें।

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
        while (topController.presentedViewController != nil) {
            topController = topController.presentedViewController!
        }
        return topController
    }

उपयोग:

let topVC = topMostController()
let vcToPresent = self.storyboard!.instantiateViewController(withIdentifier: "YourVCStoryboardID") as! YourViewController
topVC.present(vcToPresent, animated: true, completion: nil)

1
इसके लिए थैंक्स @ जैकोब डेविस! मैंने इसे एक चेतावनी प्रस्तुत करने के लिए उपयोग किया है क्योंकि मैं चेतावनी प्राप्त कर रहा था नियंत्रक: वर्तमान में प्रयास करें ....
गैरी मैनस्टैड

यह बहुत उपयोगी है। कुछ जो मुझे प्रस्तुत करने वाला नियंत्रक मिल रहा है लेकिन स्क्रीन दिखाई नहीं दे रहा है। अचानक इसके खारिज कर दिया। किसी अन्य कोड को लागू करने की आवश्यकता है? कृपया सुझाव दें
सीतलक्ष्मी_सुमेर 36

13

स्विफ्ट के लिए

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

1
धन्यवाद! यह एकमात्र चीज थी जिसने मेरे लिए इस त्रुटि को हल किया। मैं पूरी तरह से लोड किए गए दृश्य (Xcode 8 / iOS 10 में) के बाद एक जेस्चर पहचानकर्ता द्वारा ट्रिगर किए गए फ़ंक्शन से एक मोडल वीसी पेश करने की कोशिश कर रहा था। अजीब तरह से, topControllerइस फ़ंक्शन द्वारा लौटाया गया वही वीसी selfहै जब सीधे उपयोग करने की कोशिश की जाती है self.presentViewController(myModalVC), लेकिन जब मैं आपके फ़ंक्शन का उपयोग करके वीसी को प्रस्तुत करता हूं, तो कोई पदानुक्रम त्रुटि नहीं होती है।
नटालिया

13

आपको बस एक देरी के साथ चयनकर्ता प्रदर्शन करने की आवश्यकता है - (0 सेकंड काम करता है)।

override func viewDidLoad() {
    super.viewDidLoad()
    perform(#selector(presentExampleController), with: nil, afterDelay: 0)
}

@objc private func presentExampleController() {
    let exampleStoryboard = UIStoryboard(named: "example", bundle: nil)
    let exampleVC = storyboard.instantiateViewController(withIdentifier: "ExampleVC") as! ExampleVC
    present(exampleVC, animated: true) 
}

बहुत बहुत धन्यवाद। मैं एक घंटे के लिए इस समस्या में फंस गया।
रेजा

धन्यवाद ... @objc func presentExampleController ()
विलियम चोय

मुझे लगता है कि यह एक अद्भुत जवाब है!
mazend

यह एक हैक है (जो अब काम कर सकता है), लेकिन आपको अनपेक्षित मामलों में टूटने वाली चीज़ के लिए स्थापित करेगा।
विलियम ग्रैंड

6

स्विफ्ट 4

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.shared.keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

1
एक स्पष्टीकरण और उदाहरण सहायक होगा @AllenWixted
Eury Pérez Beltré

2

स्विफ्ट 3.0 और उससे अधिक के लिए

public static func getTopViewController() -> UIViewController?{
if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
  return topController
}
return nil}

2

उपयोगकर्ता के डीपलिंक को खोलने के बाद नियंत्रक को प्रस्तुत करते समय मुझे यह त्रुटि मिल रही थी। मुझे पता है कि यह सबसे अच्छा समाधान नहीं है, लेकिन यदि आप कम समय सीमा में हैं तो यहां एक त्वरित समाधान है - बस अपना कोड इसमें शामिल करें asyncAfter:

DispatchQueue.main.asyncAfter(deadline: .now() + 0.7, execute: { [weak self] in
                                navigationController.present(signInCoordinator.baseController, animated: animated, completion: completion)
                            })

यह आपके प्रस्तुतकर्ता को कॉल करने के लिए समय देगा viewDidAppear


1
let storyboard = UIStoryboard(name: "test", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "teststoryboard") as UIViewController
UIApplication.shared.keyWindow?.rootViewController?.present(vc, animated: true, completion: nil)

यह सुनिश्चित करने के लिए काम किया गया कि यह सबसे ऊपर का दृश्य है।

मुझे एक त्रुटि मिल रही थी

चेतावनी: myapp.testController: 0x7fdd01703990 myapp.testController पर प्रस्तुत करने का प्रयास करें: 0x7fdd01703690 जिसका दृश्य विंडो पदानुक्रम में नहीं है!

आशा है कि यह अन्य लोगों को तेजी से 3 में मदद करता है


1

मैंने कई अनुमोदन की कोशिश की है! केवल उपयोगी चीज है:

if var topController = UIApplication.shared.keyWindow?.rootViewController
{
  while (topController.presentedViewController != nil)
  {
    topController = topController.presentedViewController!
  }
}

1

यहां TopViewController के लिए सभी कार्यान्वयन पूरी तरह से मामलों का समर्थन नहीं करते हैं जब आपके पास होता है UINavigationControllerया UITabBarControllerउन दो के लिए आपको कुछ अलग से निपटने की आवश्यकता होती है:

के लिए UITabBarControllerऔर UINavigationControllerआपको एक अलग कार्यान्वयन की आवश्यकता है।

यहाँ कोड है जिसका उपयोग मैं topMostViewController पाने के लिए कर रहा हूँ:

protocol TopUIViewController {
    func topUIViewController() -> UIViewController?
}

extension UIWindow : TopUIViewController {
    func topUIViewController() -> UIViewController? {
        if let rootViewController = self.rootViewController {
            return self.recursiveTopUIViewController(from: rootViewController)
        }

        return nil
    }

    private func recursiveTopUIViewController(from: UIViewController?) -> UIViewController? {
        if let topVC = from?.topUIViewController() { return recursiveTopUIViewController(from: topVC) ?? from }
        return from
    }
}

extension UIViewController : TopUIViewController {
    @objc open func topUIViewController() -> UIViewController? {
        return self.presentedViewController
    }
}

extension UINavigationController {
    override open func topUIViewController() -> UIViewController? {
        return self.visibleViewController
    }
}

extension UITabBarController {
    override open func topUIViewController() -> UIViewController? {
        return self.selectedViewController ?? presentedViewController
    }
}

1

पिछले उत्तर उस स्थिति से संबंधित हैं जहां दृश्य नियंत्रक को 1 दृश्य प्रस्तुत करना चाहिए) दृश्य पदानुक्रम में अभी तक जोड़ा नहीं गया है, या 2) शीर्ष दृश्य नियंत्रक नहीं है।
एक और संभावना यह है कि एक चेतावनी प्रस्तुत की जानी चाहिए जबकि एक अन्य चेतावनी पहले से ही प्रस्तुत की गई है, और अभी तक खारिज नहीं की गई है।


1

स्विफ्ट विधि, और एक डेमो की आपूर्ति।

func topMostController() -> UIViewController {
    var topController: UIViewController = UIApplication.sharedApplication().keyWindow!.rootViewController!
    while (topController.presentedViewController != nil) {
        topController = topController.presentedViewController!
    }
    return topController
}

func demo() {
    let vc = ViewController()
    let nav = UINavigationController.init(rootViewController: vc)
    topMostController().present(nav, animated: true, completion: nil)
}

1

स्विफ्ट 5.1 :

let storyboard = UIStoryboard.init(name: "Main", bundle: Bundle.main)
let mainViewController = storyboard.instantiateViewController(withIdentifier: "ID")
let appDeleg = UIApplication.shared.delegate as! AppDelegate
let root = appDeleg.window?.rootViewController as! UINavigationController
root.pushViewController(mainViewController, animated: true)

1

मेरे लिए काम करने वाले व्यू कंट्रोलर को प्रस्तुत करने और खारिज करने के लिए मुख्य सूत्र का उपयोग।

DispatchQueue.main.async { self.present(viewController, animated: true, completion: nil) }

0

शीर्ष दृश्य नियंत्रक खोजने के बजाय, कोई भी उपयोग कर सकता है

viewController.modalPresentationStyle = UIModalPresentationStyle.currentContext

जहाँ ViewController नियंत्रक है जिसे आप प्रस्तुत करना चाहते हैं यह तब उपयोगी होता है जब पदानुक्रम में विभिन्न प्रकार के दृश्य होते हैं जैसे कि TabBar, NavBar, हालांकि अन्य सही प्रतीत होते हैं, लेकिन हैकिश के अधिक प्रकार

अन्य प्रस्तुति शैली सेब डॉक्टर पर पाई जा सकती है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.