2009-07-23 6 views
0

Je souhaite présenter plusieurs vues modales en séquence (par exemple, afficher une page de confirmation après avoir sélectionné une image dans le sélecteur d'image). Mon problème est que l'animation de licenciement et de présentation dans les étapes suivantes sans délai plante toujours l'application avec un EXC_BAD_ACCESS.Plusieurs transitions de vue modale Crash App

Je suppose que le problème est que CoreAnimation ne fait pas la distinction entre les deux transitions et ne peut pas détecter correctement si le premier est terminé ou non.

Mon travail autour jusqu'à présent est d'introduire un retard de 1 section qui semble résoudre le problème. Cependant, je pense que cela rend le code un peu fragile. Y at-il une autre solution de contournement?

Est-ce un bug dans UIKit et devrais-je soumettre un rapport de bug?

Exemple de code

est ici un cas simple qui reproduit l'accident:

  1. Créer un nouveau projet basé Voir avec la classe suivante comme la mise en œuvre du contrôleur principal

  2. Frapper 'annuler' lorsque la vue du sélecteur d'image est présentée

Comportement attendu: la vue du sélecteur est ignorée et présentée à nouveau en raison de l'appel suivant dans viewDidAppear.

Comportement réel: Il se bloque avec la trace de pile présentée ci-dessous.

code:


#import "SampleViewController.h" 

@implementation SampleViewController 

- (void)showModal { 
    UIImagePickerController *picker = [[UIImagePickerController alloc] init]; 
    [self presentModalViewController:picker animated:YES]; 
    // [picker release]; 
} 

- (void)viewDidAppear:(BOOL)animated { 
    [super viewDidAppear:animated]; 
    [self showModal]; // this line crashes the app 
    // the following works as desired 
    // [self performSelector:@selector(showModal) withObject:nil afterDelay:1]; 
} 

@end 

trace Stack crash:

 
#0 0x30b43212 in -[UIWindowController transitionViewDidComplete:fromView:toView:] 
#1 0x3095828e in -[UITransitionView notifyDidCompleteTransition:] 
#2 0x3091af0d in -[UIViewAnimationState sendDelegateAnimationDidStop:finished:] 
#3 0x3091ad7c in -[UIViewAnimationState animationDidStop:finished:] 
#4 0x00b54331 in run_animation_callbacks 
#5 0x00b54109 in CA::timer_callback 
#6 0x302454a0 in CFRunLoopRunSpecific 
#7 0x30244628 in CFRunLoopRunInMode 
#8 0x32044c31 in GSEventRunModal 
#9 0x32044cf6 in GSEventRun 
#10 0x309021ee in UIApplicationMain 
#11 0x00002794 in main at main.m:14 

Répondre

8

Il y a des chances que vous devez laisser la finition contexte d'animation. Comme vous l'avez déjà découvert

[self performSelector: @selector (showModal) withObject: nil afterDelay: 1];

œuvres, mais de toute évidence, ayant un retard est pas bon, donc faire:

[self performSelector:@selector(showModal) withObject:nil afterDelay:0.0]; 

Lorsque vous utilisez afterDelay: 0.0, il ne remet pas directement le sélecteur, au lieu qu'il enqueues l'invocation sur votre runloop , qui permet à tout votre état (autorelease pools, contextes d'animation, etc) de se connecter correctement, puis d'appeler immédiatement votre invocation lorsque le runloop commence à traiter les événements.

La question qui pourrait croup est que les utilisateurs puissent obtenir UIEvents aller en tapant sur l'écran, mais vous pouvez corriger cela avec en appelant ceci avant que vous êtes animation commence

[[UIApplication sharedApplication] beginIgnoringInteractionEvents]; 

et cette fois que vous avez votre modal final sur l'écran

[[UIApplication sharedApplication] endIgnoringInteractionEvents]; 

en général, vous voulez passer des interactions de l'interface utilisateur pendant que vous animez des transitions rapides de toute façon.

+0

en utilisant 0.0 comme délai résout le problème! Merci! – notnoop

+1

+1 pour la suggestion 'beginIgnoringInteractionEvents'. Je ne savais jamais à ce sujet auparavant. – chakrit

Questions connexes