Wir bekamen auch dieses Problem, und es war sehr wahrscheinlich, dass unser Problem durch dasselbe Problem verursacht wurde.
In unserem Fall mussten wir in einigen Fällen Daten aus dem Back-End abrufen, was bedeutete, dass ein Benutzer möglicherweise auf etwas tippte und es dann eine leichte Verzögerung gab, bevor der Navigations-Push auftrat. Wenn ein Benutzer schnell herum tippte, wurden möglicherweise zwei Navigationsschübe vom selben Ansichts-Controller ausgeführt, was genau diese Ausnahme auslöste.
Unsere Lösung ist eine Kategorie im UINavigationController, die Pushs / Pops verhindert, es sei denn, die oberste VC ist zu einem bestimmten Zeitpunkt dieselbe.
.h Datei:
@interface UINavigationController (SafePushing)
- (id)navigationLock; ///< Obtain "lock" for pushing onto the navigation controller
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock; ///< Uses a horizontal slide transition. Has no effect if the view controller is already in the stack. Has no effect if navigationLock is not the current lock.
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock; ///< Pops view controllers until the one specified is on top. Returns the popped controllers. Has no effect if navigationLock is not the current lock.
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated navigationLock:(id)navigationLock; ///< Pops until there's only a single view controller left on the stack. Returns the popped controllers. Has no effect if navigationLock is not the current lock.
@end
.m Datei:
@implementation UINavigationController (SafePushing)
- (id)navigationLock
{
return self.topViewController;
}
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock
{
if (!navigationLock || self.topViewController == navigationLock)
[self pushViewController:viewController animated:animated];
}
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated navigationLock:(id)navigationLock
{
if (!navigationLock || self.topViewController == navigationLock)
return [self popToRootViewControllerAnimated:animated];
return @[];
}
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock
{
if (!navigationLock || self.topViewController == navigationLock)
return [self popToViewController:viewController animated:animated];
return @[];
}
@end
Bisher scheint dies das Problem für uns gelöst zu haben. Beispiel:
id lock = _dataViewController.navigationController.navigationLock;
[[MyApi sharedClient] getUserProfile:_user.id success:^(MyUser *user) {
ProfileViewController *pvc = [[ProfileViewController alloc] initWithUser:user];
[_dataViewController.navigationController pushViewController:pvc animated:YES navigationLock:lock];
}];
Grundsätzlich gilt die Regel: Bevor nicht benutzerbezogene Verzögerungen auftreten , nehmen Sie eine Sperre vom entsprechenden Navigationscontroller und nehmen Sie sie in den Aufruf zum Drücken / Pop auf.
Das Wort "Sperre" ist möglicherweise etwas schlecht formuliert, da es möglicherweise darauf hindeutet, dass eine Art Sperre stattfindet, die entsperrt werden muss. Da es jedoch nirgendwo eine "Entsperr" -Methode gibt, ist dies wahrscheinlich in Ordnung.
(Nebenbei bemerkt, "nicht benutzerbezogene Verzögerungen" sind alle Verzögerungen, die der Code verursacht, dh alles, was asynchron ist. Benutzer, die auf einen Navigationscontroller tippen, der animiert gedrückt wird, zählen nicht und es ist nicht erforderlich, die navigationLock: -Version für diese auszuführen Fälle.)