<UITabBarController: 0x197870> के लिए उपस्थिति परिवर्तन शुरू / समाप्त करने के लिए असंतुलित कॉल


119

मैं इसी तरह की त्रुटि का सामना करने वाले एक अन्य उपयोगकर्ता के बारे में एसओ पढ़ता हूं , लेकिन यह त्रुटि अलग मामले में है।

मुझे यह संदेश तब मिला जब मैंने प्रारंभ में एक नियंत्रक जोड़ा:

Unbalanced calls to begin/end appearance transitions for 
<UITabBarController: 0x197870>

एप्लिकेशन की संरचना इस प्रकार है:

मुझे 5 व्यू कंट्रोलर्स से जुड़ा हुआ 5-टैब वाला टैबकार्ट्रोलर मिला। प्रारंभिक शो टैब में, मैं ऐप की शुरूआत के रूप में ओवरले करने के लिए एक नया व्यू कंट्रोलर कहता हूं।

मैं इस कोड का उपयोग परिचय दृश्य नियंत्रक को कॉल करने के लिए करता हूं:

IntroVC *vc = [[IntroVC alloc] init];
[self presentModalViewController:vc animated:YES];
[vc release]; 

इस IntroVCदृश्य नियंत्रक को दिखाने के बाद, उपरोक्त त्रुटि दिखाई देती है।

ps मैं xcode 4.2 और iOS 5.0 SDK का उपयोग कर रहा हूं, iOS 4.3 ऐप विकसित कर रहा हूं।


हाय शिवन, मेरे साथ भी यही समस्या है। लेकिन मैं अभी भी जवाब के नीचे देखने के बाद इसे ठीक नहीं कर सकता। क्या मुझे पता है कि आप परिचय दृश्य नियंत्रक को कहां कहते हैं?
ZYiOS

जवाबों:


98

आसपास के अधिक कोड को देखे बिना मैं निश्चित उत्तर नहीं दे सकता, लेकिन मेरे पास दो सिद्धांत हैं।

  1. आप उपयोग नहीं कर रहे UIViewController'एस प्रारंभकर्ता नामितinitWithNibName:bundle: । सिर्फ इसके बजाय इसका उपयोग करने का प्रयास करें init

  2. इसके अलावा, selfटैब बार नियंत्रक के दृश्य नियंत्रकों में से एक हो सकता है। हमेशा शीर्ष दृश्य नियंत्रक से दृश्य नियंत्रक प्रस्तुत करें, जिसका अर्थ है कि इस मामले में टैब बार नियंत्रक को दृश्य नियंत्रक की ओर से ओवरले व्यू नियंत्रक प्रस्तुत करने के लिए कहें। आप वास्तविक दृश्य नियंत्रक के लिए किसी भी कॉलबैक प्रतिनिधि को अभी भी रख सकते हैं, लेकिन आपके पास टैब बार नियंत्रक मौजूद होना चाहिए और खारिज करना होगा।


2
# 1 मेरे लिए इस समस्या को ठीक किया, मैंने init का उपयोग किया ।NNNName: nil बंडल: init के बजाय nil।
हुआ-यिंग

172
ऐप को इनिशियलाइज़ करने से पहले आप मोडल वीसी पेश करके इस चेतावनी को उत्पन्न कर सकते हैं। यानी एक टैब किए गए एप्लिकेशन टेम्प्लेट एप्लिकेशन को प्रारंभ करें और आवेदन में अंतिम पंक्ति के रूप में self.tabBarController के शीर्ष पर एक मोडल वीसी प्रस्तुत करें: didFinishLaunching। चेतावनी दिखाई देती है। समाधान: स्टैक को पहले खोल दें, मोडल वीसी को किसी अन्य विधि में प्रस्तुत करें, एक प्रदर्शनकर्ता के साथ आह्वान किया डीडीएल: 0.0।
danh

9
और यहाँ एक और सवाल है कि क्यों PerformSelector withDelay काम करता है। stackoverflow.com/questions/1922517/…
fatih

1
दान के समाधान ने मेरे लिए काम किया, लेकिन मुझे 0.0 के बजाय 0.1 का उपयोग करना पड़ा।
ब्रैंडन ओ'रोरके

11
शून्य के एक performSelectorWithDelay का उपयोग करने के बजाय, यह viewDidAppad या whatnot के बजाय viewDidAppear में प्रदर्शन करें।
टूल्यूसर

40

मैंने इस त्रुटि को YES से NO में एनिमेटेड बदलकर ठीक किया।

से:

[tabBarController presentModalViewController:viewController animated:YES];

सेवा:

[tabBarController presentModalViewController:viewController animated:NO];

4
यदि आप एनीमेशन की परवाह नहीं करते हैं, तो यह समस्या को ठीक करता है, लेकिन अगर आपको एनिमेटेड की आवश्यकता है: हाँ, स्वीकृत उत्तर पर दान की टिप्पणी की कोशिश करें: stackoverflow.com/questions/7886096/…
wxactly

3
FYI करें: presentModalViewController: एनिमेटेड: iOS6 में पदावनत किया गया था।
ZS

16

जैसा कि दन्ह द्वारा पोस्ट किया गया

ऐप को इनिशियलाइज़ करने से पहले आप मोडल वीसी पेश करके इस चेतावनी को उत्पन्न कर सकते हैं। यानी एक टैब किए गए एप्लिकेशन टेम्प्लेट एप्लिकेशन को प्रारंभ करें और आवेदन में अंतिम पंक्ति के रूप में self.tabBarController के शीर्ष पर एक मोडल वीसी प्रस्तुत करें: didFinishLaunching। चेतावनी दिखाई देती है। समाधान: स्टैक को पहले खोल दें, मोडल वीसी को किसी अन्य विधि में प्रस्तुत करें, एक प्रदर्शनकर्ता के साथ लगाया गया

विधि को व्यूविलेयर में ले जाने की कोशिश करें और इसे गार्ड करें ताकि यह सिर्फ एक बार निष्पादित हो (एक संपत्ति स्थापित करने की सिफारिश करेगा)


क्यों viewWillAppearऔर क्या नहीं viewDidAppear?
साइबरएम

6

कई मामलों के लिए एक अन्य समाधान सुनिश्चित करें कि के बीच संक्रमण बनाने के लिए है UIViewControllerरों होता है के बाद , नहीं-उपयुक्त (आरंभीकरण के दौरान की तरह) प्रक्रिया खत्म करने से:

__weak MyViewController *weakSelf = self;
dispatch_async(dispatch_get_main_queue(), ^{
    [weakSelf presentViewController:vc animated:YES];
});

यह भी सामान्य है pushViewController:animated:, आदि।


4

मुझे भी यही समस्या थी। मैंने viewDidLoadअपने पहले के अंदर एक विधि को बुलायाUIViewController

- (void)viewDidLoad{
    [super viewDidLoad];

    [self performSelector:@selector(loadingView)
               withObject:nil afterDelay:0.5];
}

- (void)loadingView{

    [self performSegueWithIdentifier:@"loadedData" sender:self];
}

दूसरे के अंदर UIViewControllerमैंने 0.5 सेकंड की देरी के साथ भी यही किया। देरी को उच्च मूल्य में बदलने के बाद, इसने ठीक काम किया। यह ऐसा है जैसे किसी अन्य सेगमेंट के बाद सेग को बहुत तेज प्रदर्शन नहीं किया जा सकता है।


7
दृश्य जीवनचक्र विधि viewDidAppear इस उद्देश्य के लिए प्रदान किया गया है, और कृत्रिम विलंब, fiviw को शुरू करने की तुलना में अधिक विश्वसनीय होगा।
टूलूस

1
यह सही उत्तर है, जब तक कि नेविगेशन नियंत्रक एक नए नेविगेशन के लिए तैयार न हो जाए, तब तक प्रतीक्षा करने के लिए 0 को छोड़कर पर्याप्त उत्तर है।
मल्हल

यह पूरी तरह से सही है, आपको इसे अंदर बुलाना होगा viewDidAppearइसलिए UINavigationControllerइसे संभालने के लिए तैयार है। मैंने अपनी पोस्ट को इसमें बदल दिया;)
एलेक्स Cio

मुझे ऐसा लगता है कि यह देखने के लिए स्थानांतरित किया जाना चाहिएWillAppear तो आप को देखने के बारे में चिंता करने की ज़रूरत नहीं है कि दृश्य ने आरंभीकृत किया है या नहीं।
घोड़ाजॉकिज

3

जब मुझे दूसरे व्यू कंट्रोलर से मेरा लॉगिन व्यू कंट्रोलर पेश करने की आवश्यकता होती है तो मुझे भी यही समस्या थी यदि उपयोगकर्ता अधिकृत नहीं है, तो मैंने इसे अपने दूसरे व्यू कंट्रोलर के व्यूडीडलॉड मेथड (यदि अधिकृत नहीं है -> presentModalViewController) में किया है। जब मैंने इसे ViewDidAppear विधि में बनाना शुरू किया, तो मैंने इस समस्या को हल किया। मुझे लगता है कि ViewDidLoad केवल गुणों को इनिशियलाइज़ करता है और उसके बाद वास्तविक शो व्यू एल्गोरिथ्म शुरू होता है! Thats क्यों आप modal बदलाव करने के लिए viewDidAppear विधि का उपयोग करना चाहिए!


3

एक टाइपो के कारण मुझे यह समस्या थी:

override func viewDidAppear(animated: Bool) {
    super.viewWillAppear(animated)

के बजाय

override func viewDidAppear(animated: Bool) {
    super.viewDidAppear(animated)

यह "DidAppear" के बजाय सुपर में "WillAppear" कह रहा था


2

मुझे एक ही मुद्दे के साथ बहुत समस्या थी। मैंने इसे एक हल किया

  1. स्टोरीबॉड InstantiateViewControllerWithIdentifier विधि का उपयोग करके ViewController की शुरुआत। अर्थातIntro *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"introVC"];
  2. [self.tabBarController presentModalViewController : vc animated:YES];

मेरे पास मेरे स्टोरीबोर्ड में व्यू कंट्रौलर है, किसी कारण से केवल [[introvc alloc] init];मेरे लिए काम नहीं किया।


1
आपको नई स्टोरीबोर्डिंग सुविधा का उपयोग करके देखना अच्छा है। लेकिन मैं अपने मामले में स्टोरीबोर्ड का उपयोग नहीं कर रहा था ...
Raptor

बस यह इंगित करना चाहता था कि "InstantiateViewControllerWithIdentifier" नियंत्रक की पहचानकर्ता लेता है। अधिक जानकारी के लिए stackoverflow.com/questions/8186375/…
किशोर कुंदन सेप

2

मैंने इसे लिखकर हल किया

[self.navigationController presentViewController:viewController 
                                        animated:TRUE 
                                      completion:NULL];

3
FYI करें अधिक मुहावरेदार (और सुरक्षित!) आपको करना चाहिए: एनिमेटेड: हाँ पूरा करना: nil
powerj1984

2
मैं आपको अधिक मुहावरेदार अनुदान दूंगा, लेकिन यह कैसे सुरक्षित है?
ज़ेव ईसेनबर्ग

2

मुझे एक तृतीय पक्ष कोड के साथ यह समस्या थी। कोई व्यक्ति कस्टम TabBarCerroller क्लास में व्यूविलेपियर और व्यूवैलडिसैपियर के सुपर के अंदर सेट करना भूल गया।

- (void) viewWillAppear:(BOOL)animated {

    [super viewWillAppear:animated];
    // code...
}

or

- (void) viewWillDisappear:(BOOL)animated {

    [super viewWillDisappear:animated];
    // code...
}

2

यदि आप transitioningDelegate(इस प्रश्न के उदाहरण में मामला नहीं) का उपयोग कर रहे हैं , तो भी सेट modalPresentationStyleकरें .Custom

तीव्र

let vc = storyboard.instantiateViewControllerWithIdentifier("...")
vc.transitioningDelegate = self
vc.modalPresentationStyle = .Custom

1

मेरी भी यही त्रुटि थी। मेरे पास 3 आइटम के साथ एक टैब बार है और मैं अनजाने में अपने टैब बार के उपयोग के आइटम 2 में आइटम 1 के मूल दृश्य नियंत्रक को कॉल करने की कोशिश कर रहा था performSegueWithIdentifier

क्या होता है कि यह व्यू कंट्रोलर को कॉल करता है और कुछ सेकंड के बाद आइटम 2 के रूट व्यू कंट्रोलर पर वापस जाता है और उस एरर को लॉग करता है।

जाहिरा तौर पर, आप किसी आइटम के रूट व्यू कंट्रोलर को किसी अन्य आइटम पर कॉल नहीं कर सकते।

इसलिए इसके बजाय performSegueWithIdentifier

मैंनें इस्तेमाल किया [self.parentViewController.tabBarController setSelectedIndex:0];

आशा है कि यह किसी की मदद करता है।


1

मुझे भी यही समस्या थी और मुझे लगता था कि मैं किसी और के समान होने की स्थिति में पोस्ट करूंगा।

मेरे मामले में, मैंने अपने UITableViewController के लिए एक लंबी प्रेस इशारा पहचानकर्ता को संलग्न किया था।

UILongPressGestureRecognizer *longPressGesture = [[[UILongPressGestureRecognizer alloc]
                                                   initWithTarget:self
                                                   action:@selector(onLongPress:)]
                                                  autorelease];
[longPressGesture setMinimumPressDuration:1];
[self.tableView addGestureRecognizer:longPressGesture];

मेरे onLongPress चयनकर्ता में, मैंने अपना अगला व्यू कंट्रोलर लॉन्च किया।

- (IBAction)onLongPress:(id)sender {

    SomeViewController* page = [[SomeViewController alloc] initWithNibName:@"SomeViewController" bundle:nil];

    [self.navigationController pushViewController:page animated:YES];

    [page release];

}

मेरे मामले में, मुझे त्रुटि संदेश मिला क्योंकि लंबे समय से प्रेस पहचानकर्ता को एक से अधिक बार निकाल दिया गया था और परिणामस्वरूप, मेरे "SomeViewController" को कई बार स्टैक पर धकेल दिया गया था।

समाधान का संकेत करने के लिए एक बूलियन जोड़ना था जब SomeViewController स्टैक पर धकेल दिया गया था। जब मेरी UITableViewController की व्यूवल एपियर विधि को कॉल किया गया, तो मैंने बूलियन को NO पर सेट किया।


1

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


1

में स्विफ्ट 2 + मेरे लिए काम करता है:

मेरे पास स्टोरीबोर्ड में UITabBarViewController है और मेरे पास इस तरह से चयनित संपत्ति थी:

यहां छवि विवरण दर्ज करें

लेकिन मैं इसे हटा देता हूं, और अपनी प्रारंभिक कक्षा के अपने व्यूडीडलॉड विधि में इसे शामिल करता हूं:

override func viewDidLoad() {
   super.viewDidLoad()
   self.tabBarController?.selectedIndex = 2
}

मुझे उम्मीद है कि मैं किसी की मदद कर सकता हूं।


0

वास्तव में आपको पुश एनीमेशन समाप्त होने तक प्रतीक्षा करने की आवश्यकता है। तो आप UINavigationController प्रतिनिधि कर सकते हैं और एनीमेशन समाप्त होने तक धक्का देने से रोक सकते हैं।

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
    waitNavigation = NO;
}


-(void)showGScreen:(id)gvc{

    if (!waitNavigation) {
        waitNavigation = YES;
        [_nav popToRootViewControllerAnimated:NO];
        [_nav pushViewController:gvc animated:YES];
    }
}

एक सेल चुने जाने पर मैं इसे कॉल करता हूं। यह वास्तव में आप पर निर्भर करता है
ymutlu

0

जैसा कि @danh ने सुझाव दिया, मेरा मुद्दा यह था कि मैं UITabBarControllerतैयार होने से पहले मॉडल वीसी प्रस्तुत कर रहा था । हालाँकि, मैंने दृश्य नियंत्रक को पेश करने से पहले एक निश्चित देरी पर भरोसा करने में असहज महसूस किया (मेरे परीक्षण से, मुझे 0.05-0.1s देरी का उपयोग करने की आवश्यकता थी performSelector:withDelay:)। मेरा समाधान एक ब्लॉक को जोड़ना है जिसे UITabBarController's viewDidAppear:विधि ' कहा जाता है :

PRTabBarController.h:

@interface PRTabBarController : UITabBarController

@property (nonatomic, copy) void (^viewDidAppearBlock)(BOOL animated);

@end

PRTabBarController.m:

#import "PRTabBarController.h"

@implementation PRTabBarController

- (void)viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    if (self.viewDidAppearBlock) {
        self.viewDidAppearBlock(animated);
    }
}

@end

में अब application:didFinishLaunchingWithOptions:

PRTabBarController *tabBarController = [[PRTabBarController alloc] init];

// UIWindow initialization, etc.

__weak typeof(tabBarController) weakTabBarController = tabBarController;
tabBarController.viewDidAppearBlock = ^(BOOL animated) {
    MyViewController *viewController = [MyViewController new];
    viewController.modalPresentationStyle = UIModalPresentationOverFullScreen;
    UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:viewController];
    [weakTabBarController.tabBarController presentViewController:navigationController animated:NO completion:nil];
    weakTabBarController.viewDidAppearBlock = nil;
};

0

आपको यह सुनिश्चित करने की आवश्यकता है - (शून्य) startAppearanceTransition: (BOOL) isAppearing एनिमेटेड: (BOOL) एनिमेटेड और - (शून्य) endAppearanceTransition कक्षा में एक साथ बनाया जाता है।


0

मेरी भी यही समस्या थी। जब मैं स्क्रीन को बायपास करना चाहता था तब विकसित करना। मैं एक दृश्य नियंत्रक से दूसरे में viewDidLoad में चयनकर्ता विधि को कॉल करके नेविगेट कर रहा था।

मुद्दा यह है कि हमें ViewController को दूसरे ViewController में बदलने से पहले संक्रमण को खत्म करने देना चाहिए।

इससे मेरी समस्या हल हो गई: ViewControllers को दूसरे को बदलने से पहले संक्रमण को खत्म करने की अनुमति देना आवश्यक है।

self.perform(#selector(YOUR SELECTOR METHOD), with: self, afterDelay: 0.5)

0

स्विफ्ट 5

 func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {


//Delete or comment the below lines on your SceneDelegate.

//        guard let windowScene = (scene as? UIWindowScene) else { return }
//        window?.windowScene = windowScene
//        window?.makeKeyAndVisible()

        let viewController = ListVC()
        let navViewController = UINavigationController(rootViewController: viewController)
        window?.rootViewController = navViewController

    }

-1

मुझे यह समस्या तब हुई जब मैंने रूट टीवीसी से टीवीसी ए से टीवीसी बी तक नेविगेट किया था। टीवीसी बीआई में "लोड" बटन को टैप करने के बाद सीधे रूट टीवीसी पर वापस कूदना चाहता था (टीवीसी ए को फिर से शुरू करने की कोई आवश्यकता नहीं है, इसलिए ऐसा करें) । मैं था:

//Pop child from the nav controller
[self.navigationController popViewControllerAnimated:YES];
//Pop self to return to root
[self.navigationController popViewControllerAnimated:YES];

... जो त्रुटि "शुरू / अंत आदि के लिए असंतुलित कॉल" देता है। निम्नलिखित ने त्रुटि को ठीक किया, लेकिन कोई एनीमेशन नहीं:

//Pop child from the nav controller
[self.navigationController popViewControllerAnimated:NO];
//Then pop self to return to root
[self.navigationController popViewControllerAnimated:NO];

यह मेरा अंतिम समाधान था, कोई त्रुटि नहीं और फिर भी एनिमेटेड:

//Pop child from the nav controller
[self.navigationController popViewControllerAnimated:NO];
//Then pop self to return to root, only works if first pop above is *not* animated
[self.navigationController popViewControllerAnimated:YES];

-1

मुझे इस त्रुटि का सामना करना पड़ा जब मैंने एक स्टोरीबोर्ड सेग एक्शन (आईबी में) के लिए एक यूआईब्यूटॉन को झुका दिया, लेकिन बाद में आईबी performSegueWithIdentifierसे पहले एक को हटाने के लिए बटन को प्रोग्रामिक रूप से कॉल करने का फैसला किया ।

संक्षेप में, इसने दो बार सेग कॉल किया, यह त्रुटि दी और वास्तव में मेरे विचार को दो बार धक्का दिया। फिक्स में से एक कॉल को हटाना था।

आशा है कि यह किसी को मेरी तरह थका देने में मदद करता है!

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