6

我有一个 UIViewController 和一个用于向 UIViewController 添加方法的类别。类中有一个方法:

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

}

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

[self someAddedMethod];

但是,我只想允许这种方法一次运行一个。例如,如果我一个接一个地打两个电话

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

我希望第二个电话等到第一个电话完成。我知道 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];
                                      }];
                 }];

}

所以我从屏幕顶部显示一个“横幅”,等待一段时间(CGFloat)然后将视图滑出屏幕并删除。由于这是一个类别,我无法添加实例变量。所以我想要实现的是,如果对该方法进行了多次调用,我希望第一次调用无需等待即可执行,但之后的每次调用等到上一个通话结束。

4

3 回答 3

2

如果它只是关于你可以检查的动画if ([someView.layer animationForKey:@"sameKeyAsOnCreation"] == nil)。如果它当前没有运行,那么你只会添加一个动画。

您还可以使用关联对象自行存储状态(动画正在运行/未运行)。

于 2013-05-23T09:37:31.817 回答
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];
    }
}

请注意,您不需要任何@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();
    }
}
于 2013-05-23T09:46:53.927 回答
0

尝试使用这个。self并在@synchronized指令中使用。

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

注意:@synchronized()指令将任何Objective-C对象(包括 self)作为其唯一参数。该对象称为互斥信号量互斥量。它允许一个线程锁定一段代码以防止它被其他线程使用。

于 2013-05-23T08:08:40.433 回答