Приложение ios — сбой при нескольких переходах одновременно (переход к другому переходу во время анимации одного)

Пока идет анимация одного перехода (например, perforrmsegue), если происходит другой переход (если пользователь в это время нажимает другую кнопку), то приложение падает.

Та же проблема для pop и pushViewController в UINavigationController решается здесь.

Можем ли мы использовать тот же трюк для перехода или есть другое решение.

Я получаю следующий стек после сбоя. (Исключение при [NSException initWithCoder:]).

0   CoreFoundation  0x2f9fbf4b  __exceptionPreprocess
1   libobjc.A.dylib 0x39d8b6af  objc_exception_throw
2   CoreFoundation  0x2f9fbe8d  -[NSException initWithCoder:]
3   UIKit   0x3217a48f  -[UIView(Internal) _addSubview:positioned:relativeTo:]
4   UIKit   0x3217a417  -[UIView(Hierarchy) addSubview:]
5   UIKit   0x32342b71  __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke
6   UIKit   0x321806e5  +[UIView(Animation) performWithoutAnimation:]

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


person Pushparaj    schedule 15.03.2014    source источник
comment
Я использую performSegueWithIdentifier во многих местах моего контроллера для события кнопки. Кстати, приложение работает нормально, но вылетает только иногда, если одновременно нажать две кнопки.   -  person Pushparaj    schedule 15.03.2014
comment
Я думаю, что аналогичная проблема объясняется здесь - stackoverflow.com/questions/19560198/. поэтому многие люди также должны столкнуться с этой проблемой при переходе.   -  person Pushparaj    schedule 15.03.2014
comment
Что ты в итоге сделал? Вы ввели BOOL или есть какой-то флаг, который предоставляет iOS?   -  person Stefan Arn    schedule 03.04.2014
comment
Для тех, кто ищет решение. У меня это работало безупречно: stackoverflow. ком/вопросы/20083276/   -  person Stefan Arn    schedule 03.04.2014
comment
Я добавил shouldPerformSegueWithIdentifier:sender: и в этом методе проверьте значение ((RS_AppDelegate *)[UIApplication sharedApplication].delegate).animatingViewControllerTransition и верните NO, если он анимируется, иначе верните YES.   -  person Pushparaj    schedule 08.04.2014


Ответы (2)


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

1)

Сначала добавьте свойство BOOL в файл .h вашего приложения appDelegate.

@property (nonatomic) BOOL animatingViewControllerTransition;

Также реализуйте UINavigationControllerDelegate:

@interface Your_AppDelegate : UIResponder <UIApplicationDelegate, UINavigationControllerDelegate>

Установите Your_AppDelegate в качестве делегата UINavigationController в application:didFinishLaunchingWithOptions: вашего appDelegate:

((UINavigationController *)self.window.rootViewController).delegate = self;

2)

Теперь добавьте этот метод UINavigationControllerDelegate в файл .m вашего appDelegate:

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{

    // Push/pop operation is allowed now.
    ((Your_AppDelegate *)[UIApplication sharedApplication].delegate).animatingViewControllerTransition = NO;
}

3)

Наконец, добавьте следующий код всякий раз, когда вы переходите

- (BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    // Don't allow to segue if already one of the view controllers is being animated
    BOOL viewControllerIsTransitioning = ((Your_AppDelegate *)[UIApplication sharedApplication].delegate).animatingViewControllerTransition;
    if (viewControllerIsTransitioning)
    {
        return NO;
    }

    return YES;
}

Надеюсь, это поможет тем, у кого возникла проблема с крахом segue.

person Pushparaj    schedule 08.04.2014
comment
animatingViewControllerTransition не существует - person Pablo Martinez; 19.11.2014
comment
animatingViewControllerTransition — это свойство BOOL в вашем appDelegate, которое вы должны добавить. - person Pushparaj; 20.11.2014
comment
1) Во многих случаях rootViewController не является экземпляром UINavigationController, поэтому, например, когда используется UITabBarController, мы должны установить делегат для всех контроллеров навигации в rootViewController.viewControllers. 2) Вы также должны установить флаг YES в willShowViewController. - person Tomasz Slanina; 12.10.2016

Я думаю, что это более простое решение:

-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
    return self == [self.navigationController.viewControllers lastObject] ? YES : NO;
}
person flyerz    schedule 14.05.2015
comment
Да, это довольно просто, и есть много способов решить эту проблему, но я предпочел тот, который указал в своем ответе, потому что я также использую tabControler и другую библиотеку, связанную с navigationController, например MMDrawerController, поэтому она обрабатывает все случаи. - person Pushparaj; 15.05.2015
comment
Если вы хотите заменить метод во всех подклассах, вы можете использовать метод swizzling: nshipster.com/method-swizzling - person flyerz; 16.05.2015