Permitir que un método llame a la vez a un método de categoría ios (@sincronizado)

Tengo un UIViewController y una categoría para agregar methods al UIViewController. Hay un método en la categoría:

@implementation UIViewController (AlertAnimationsAndModalViews) -(void)someAddedMethod { UIView *someView; //do some animation with the view that lasts 3 seconds //remove the view and return } 

Y en cualquier controller de vista puedo llamar a este método

 [self someAddedMethod]; 

Sin embargo, solo quiero permitir que este método se ejecute uno por vez. Por ejemplo, si hago dos llamadas una tras otra

 [self someAddedMethod];//call1 [self someAddedMethod];//call2 

Quiero que la segunda llamada espere hasta que se complete la primera llamada. Entiendo que UIView animationWithduration … se ejecuta en un hilo separado, y viendo que no puedo crear iVars en la categoría que realmente no puedo usar @synchronized (someObject) ..

¿Algún consejo?

¡Gracias por adelantado!

EDITAR

El método se ve así:

  -(void)showTopBannerWithHeight:(CGFloat)height andWidth:(CGFloat)width andMessage:(NSString *)message andDuration:(CGFloat)duration { UILabel *messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, -height, width, height)]; [self.view.superview addSubview:messageLabel]; [UIView animateWithDuration:0.5 delay:0 options: UIViewAnimationOptionBeginFromCurrentState animations:^{ messageLabel.frame = CGRectMake(0, 0, SCREEN_WIDTH, height); } completion:^(BOOL finished){ [UIView animateWithDuration: 0.5 delay:duration options: UIViewAnimationOptionBeginFromCurrentState animations:^{ messageLabel.frame = CGRectMake(0, -height, SCREEN_WIDTH, height); } completion:^(BOOL finished){ [messageLabel removeFromSuperview]; }]; }]; 

}

Así que muestro un "banner" desde la parte superior de la pantalla, espero una duración (CGFloat), luego deslice la vista de la pantalla y elimínela. Como esto está en una categoría, no puedo agregar variables de instancia … así que lo que quiero lograr es que si se realiza más de una llamada a este método, quiero que la primera llamada se ejecute sin esperar, pero cada llamada después de eso Espere hasta que finalice la llamada anterior.

Suponiendo que desee comenzar la siguiente animation después de que la anterior haya finalizado. De esta forma, puede usar un almacenamiento NSMutableArray* _animationQueue compartido:

 -(void)someAddedMethod { NSTimeInterval duration = 3.0; void (^animationBlock)() = ^{ //do some animations here self.view.frame = CGRectOffset(self.view.frame, 40, 0); }; __block void (^completionBlock)(BOOL) = ^(BOOL finished){ [_animationQueue removeObjectAtIndex:0]; if([_animationQueue count]>0) { [UIView animateWithDuration:duration animations:_animationQueue[0] completion:completionBlock]; } }; [_animationQueue addObject:animationBlock]; if([_animationQueue count]==1) { [UIView animateWithDuration:duration animations:animationBlock completion:completionBlock]; } } 

Tenga en count que no necesita ninguna característica @synchronized , ya que todo sigue en el hilo principal.

ACTUALIZACIÓN: el código a continuación hace exactamente lo que necesita:

 -(void)showTopBannerWithHeight:(CGFloat)height andWidth:(CGFloat)width andMessage:(NSString *)message andDuration:(CGFloat)duration { static NSMutableArray* animationQueue = nil; if(!animationQueue) { animationQueue = [[NSMutableArray alloc] init]; } void (^showMessageBlock)() = ^{ UILabel *messageLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, width, height)]; messageLabel.text = message; [self.view.superview addSubview:messageLabel]; [UIView animateWithDuration: 0.5 delay:duration options:UIViewAnimationOptionBeginFromCurrentState animations:^{ messageLabel.frame = CGRectOffset(messageLabel.frame, 0, -height); } completion:^(BOOL finished){ [messageLabel removeFromSuperview]; [animationQueue removeObjectAtIndex:0]; if([animationQueue count]>0) { void (^nextAction)() = [animationQueue objectAtIndex:0]; nextAction(); } }]; }; [animationQueue addObject:showMessageBlock]; if([animationQueue count]==1) { showMessageBlock(); } } 

Si se trata solo de las animaciones, puede comprobar if ([someView.layer animationForKey:@"sameKeyAsOnCreation"] == nil) . De lo que solo agregará una animation, si no se está ejecutando actualmente.

También puede usar objects asociados para almacenar el estado por su count (animation ejecutándose / no ejecutándose).

Trate de usar este. Y se utiliza en @ directiva synchronized .

 - (void)criticalMethod { @synchronized(self) { // Critical code. } } 

Nota: La directiva @synchronized() toma como su único argumento cualquier object Objective-C , incluido uno mismo. Este object se conoce como semáforo de exclusión mutua o mutex . Permite que un subprocess bloquee una sección de código para evitar su uso por otros subprocesss.