Kami mulai mendapatkan masalah ini juga, dan kemungkinan besar kemungkinan kami disebabkan oleh masalah yang sama.
Dalam kasus kami, kami harus menarik data dari ujung belakang dalam beberapa kasus, yang berarti pengguna mungkin mengetuk sesuatu dan kemudian akan ada sedikit keterlambatan sebelum dorongan nav terjadi. Jika pengguna dengan cepat mengetuk sekitar, mereka mungkin berakhir dengan dua dorongan nav dari pengontrol tampilan yang sama, yang memicu pengecualian ini.
Solusi kami adalah kategori pada UINavigationController yang mencegah push / pops kecuali vc atas adalah sama dari titik waktu tertentu.
file .h:
@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
file .m:
@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
Sejauh ini tampaknya ini telah menyelesaikan masalah bagi kami. Contoh:
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];
}];
Pada dasarnya, aturannya adalah: sebelum ada penundaan terkait pengguna ambil kunci dari nav controller yang relevan, dan sertakan dalam panggilan untuk push / pop.
Kata "kunci" mungkin kata-kata yang sedikit buruk karena mungkin menyindir ada beberapa bentuk kunci yang perlu dibuka, tetapi karena tidak ada metode "membuka" di mana pun, mungkin tidak apa-apa.
(Sebagai sidenote, "keterlambatan yang tidak terkait dengan pengguna" adalah keterlambatan apa pun yang disebabkan oleh kode, yaitu apa pun yang tidak sinkron. Pengguna yang mengetuk kontroler nav yang didorong secara animasi tidak masuk hitungan dan tidak perlu melakukan navigasiLock: versi untuk itu kasus.)