Неуравновешенные вызовы для перехода на начало/конец для <UITabBarController: 0x197870>

Я читаю SO о том, что другой пользователь сталкивается с аналогичной ошибкой, но эта ошибка в другом случае.

Я получил это сообщение, когда я сначала добавил контроллер просмотра:

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

Структура приложения следующая:

У меня есть 5-Tab TabBarController, связанный с 5 Контроллерами просмотра. На вкладке предварительного просмотра я вызываю новый контроллер просмотра для наложения в виде приложения.

Я использую этот код для вызова контроллера представления:

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

После появления этого диспетчера представлений IntroVC отображается приведенная выше ошибка.

p.s. Я использую xCode 4.2 и iOS 5.0 SDK, разрабатывая приложение iOS 4.3.

Ответ 1

Не видя больше окружающего кода, я не могу дать однозначного ответа, но у меня есть две теории.

  • Вы не используете UIViewController назначенный инициализатор initWithNibName:bundle:. Попробуйте использовать его вместо init.

  • Кроме того, self может быть одним из контроллеров представления контроллера панели вкладок. Всегда представляйте контроллеры представлений от верхнего контроллера представления, что означает, что в этом случае попросите контроллер панели вкладок представить контроллер отображения наложения для имени контроллера вида. Вы все равно можете удерживать делегатов callback в реальном контроллере представления, но вы должны иметь контроллер панели вкладок и уволить.

Ответ 2

Я исправил эту ошибку, изменив анимацию с YES на NO.

From:

[tabBarController presentModalViewController:viewController animated:YES];

To:

[tabBarController presentModalViewController:viewController animated:NO];

Ответ 3

Как отправлено danh

Вы можете создать это предупреждение, представив modal vc до того, как приложение будет завершено. 1. Запустите приложение шаблона приложения с вкладками и представите modal vc поверх self.tabBarController в качестве последней строки в приложении: doneFinishLaunching. Появляется предупреждение. Решение: пусть сначала распакуется стек, представляет модальный vc в другом методе, вызывается с помощью performSelector withDelay: 0.0

Попробуйте переместить метод в viewWillAppear и сохраните его, чтобы он выполнялся только один раз (рекомендуется настроить свойство)

Ответ 4

У меня была та же проблема, когда мне нужно было представить контроллер входа в систему с другого контроллера просмотра. Если пользователь не авторизовался, я сделал это в методе ViewDidLoad моего другого контроллера просмотра (если не авторизован → presentModalViewController). Когда я начну использовать метод ViewDidAppear, я решил эту проблему. Я думаю, что ViewDidLoad только инициализирует свойства, и после этого начинается фактический алгоритм просмотра! Вот почему вы должны использовать метод viewDidAppear для создания модальных переходов!

Ответ 5

У меня такая же проблема. Я вызвал метод внутри 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 секунды. После изменения задержки на более высокое значение все заработало нормально. Это похоже на то, что после другого сеанса переход не может быть выполнен слишком быстро.

Ответ 6

Другим решением для многих случаев является обеспечение того, чтобы переход между UIViewController выполнялся после, когда процедура не подходит (как при инициализации) заканчивается, делая:

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

Это общее для также pushViewController:animated: и т.д.

Ответ 7

У меня было много проблем с той же проблемой. Я решил этот

  • Инициирование ViewController с помощью метода initbase instantiateViewControllerWithIdentifier. iee Intro *vc = [self.storyboard instantiateViewControllerWithIdentifier:@"introVC"];
  • [self.tabBarController presentModalViewController : vc animated:YES];

У меня есть viewcontroller в моей раскадровке, почему-то использование только [[introvc alloc] init]; не работает для меня.

Ответ 8

Я решил это, написав

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

Ответ 9

У меня была эта проблема из-за опечатки:

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

вместо

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

Он называл "WillAppear" в супер вместо "DidAppear"

Ответ 10

У меня была такая же ошибка. У меня есть панель вкладок с тремя элементами, и я бессознательно пытался вызвать контроллер корневого представления элемента 1 в элементе 2 моей панели вкладок с помощью performSegueWithIdentifier.

Что происходит, так это то, что он вызывает контроллер вида и через несколько секунд возвращается к контроллеру корневого представления элемента 2 и регистрирует эту ошибку.

По-видимому, вы не можете вызвать контроллер корневого представления элемента для другого элемента.

Итак, вместо performSegueWithIdentifier

Я использовал [self.parentViewController.tabBarController setSelectedIndex:0];

Надеюсь, это поможет кому-то.

Ответ 11

У меня была такая же проблема, и я подумал, что отправлю на случай, если кто-то столкнется с чем-то подобным.

В моем случае я привязал длинный идентификатор распознавания жестов к моему 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 был перенесен в стек. Когда был вызван мой метод viewWillAppear UITableViewController, я вернул логическое значение NO.

Ответ 12

У меня была эта проблема с сторонним кодом. Кто-то забыл установить супер внутри viewWillAppear и viewWillDisappear в настраиваемом классе TabBarController.

- (void) viewWillAppear:(BOOL)animated {

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

or

- (void) viewWillDisappear:(BOOL)animated {

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

Ответ 13

В Swift 2 + для меня работает:

У меня есть UITabBarViewController в раскадровке, и я выбрал свойствоIndex следующим образом:

введите описание изображения здесь

Но я удаляю его и добавляю в свой метод viewDidLoad моего начального класса, например:

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

Я надеюсь, что смогу помочь кому-то.

Ответ 14

Если вы используете transitioningDelegate (не в этом примере), установите modalPresentationStyle на .Custom.

Свифта

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

Ответ 15

На самом деле вам нужно дождаться окончания анимации push. Таким образом, вы можете делегировать 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];
    }
}

Ответ 16

Как я сказал @danh, моя проблема заключалась в том, что я представлял модальный vc до того, как UITabBarController был готов. Тем не менее, мне было неудобно полагаться на фиксированную задержку перед представлением контроллера вида (из моего тестирования мне нужно было использовать задержку 0,05-0,1 с в performSelector:withDelay:). Мое решение состоит в том, чтобы добавить блок, который вызывается методом UITabBarController 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;
};

Ответ 17

Я обнаружил, что если вы используете раскадровку, вам нужно поместить код, представляющий новый контроллер представления в viewDidAppear. Он также избавится от предупреждения "Представление диспетчеров представлений на контроллерах отключенных представлений предупреждает".

Ответ 18

вам нужно убедиться - (void) beginAppearanceTransition: (BOOL) isAppearing анимированный: (BOOL) анимированный и - (void) endAppearanceTransition создается вместе в классе.

Ответ 19

Я была такая же проблема. При разработке я хотел обойти экраны. Я переходил от одного контроллера представления к другому в viewDidLoad, вызывая метод селектора.

Проблема в том, что мы должны позволить ViewController завершить переход, прежде чем переходить к другому ViewController.

Это решило мою проблему: задержка необходима, чтобы позволить ViewControllers завершить переход перед переходом к другому.

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

Ответ 20

У меня была эта проблема, когда я перешел с корневого TVC на TVC A, а затем на TVC B. После нажатия кнопки "load" в TVC BI захотелось вернуться прямо к корневому TVC (нет необходимости пересматривать TVC A, поэтому почему сделай это). У меня было:

//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];

Ответ 21

Я столкнулся с этой ошибкой, когда я подключил UIButton к действию segue раскадровки (в IB), но позже решил, что кнопка программно вызывает performSegueWithIdentifier, забывая удалить первый из IB.

В сущности он дважды выполнил вызов segue, дал эту ошибку и фактически дважды отодвинул мой взгляд. Исправление заключалось в том, чтобы удалить один из вызовов segue.

Надеюсь, это поможет кому-то так же устало, как мне!