允许一次调用一个方法到类别方法ios(@synchronized)

Tyl*_*den 6 animation objective-c synchronized uiviewanimation ios

我有一个UIViewController和一个类别,用于向UIViewController添加方法.该类别中有一种方法:

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

}
Run Code Online (Sandbox Code Playgroud)

在任何视图控制器中我都可以调用此方法

[self someAddedMethod];
Run Code Online (Sandbox Code Playgroud)

但是,我只想让这个方法一次运行一个.例如,如果我一个接一个地打两个电话

[self someAddedMethod];//call1
[self someAddedMethod];//call2
Run Code Online (Sandbox Code Playgroud)

我希望第二个电话等到第一个电话完成.我知道UIView animationWithduration ...是在一个单独的线程中运行,并且看到我无法在类别中创建iVars我真的不能使用@synchronized(someObject)..

有什么建议?

提前致谢!

编辑

该方法如下所示:

 -(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];
                                      }];
                 }];
Run Code Online (Sandbox Code Playgroud)

}

所以我从屏幕顶部显示一个"横幅",等待一段时间(CGFloat)然后将视图滑出屏幕并移除.因为这是一个类别我不能添加实例变量..所以我想要实现的是,如果进行多次调用此方法,我希望第一次调用执行而不等待,但每次调用之后,等到上次通话结束.

one*_*ray 1

假设您想在上一个动画完成后开始下一个动画。这样你就可以使用一些共享NSMutableArray* _animationQueue存储:

-(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];
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,您不需要任何@synchronized功能,因为一切都在主线程上进行。

更新:下面的代码正是您所需要的:

-(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();
    }
}
Run Code Online (Sandbox Code Playgroud)