ios - 如何使用GCD控制动画序列

标签 ios animation grand-central-dispatch

我有一个View显示和隐藏给用户一些提示。

显示和隐藏方法看起来像这样:

-(void)show{
    [UIView animateWithDuration:3.0f
                 animations:^{
                     //do something to show self to give hint;
                     self.frame = CGRectMake(0,0,0,0);
                 } completion:nil];
}

-(void)hide{
    [UIView animateWithDuration:3.0f
                 animations:^{
                     //do something to hide self to give hint;
                     self.frame = CGRectMake(centerX,centerY,100,100);
                 } completion:nil];
}

当显示新 View 时,我必须调用hide method ,然后 show method 。但持续时间延迟3.0f会导致一些错误。我正在使用这样的方法:

dispatch_async(dispatch_get_main_queue(), ^{
    [view hide];
});

dispatch_async(dispatch_get_main_queue(), ^{
    [view show];
});

我正在打电话show method就在hide method之后。动画无法按照提交到队列的顺序执行。我想要的是show method恰好在 hide method 之后执行完全的。如何控制这两个方法的顺序。

我认为我无法使用完成处理程序,因为我无法确定在何处调用这两个方法,或者当我调用另一个 show method 时是否显示 View 或hide method .

如果我不清楚,有什么建议吗?我将重新编辑我的问题。


PS:

这不仅仅是一闪而过。下次什么时候show方法被调用时,我无法保证最后一个 View 被显示或隐藏以及最后一个 View 显示多长时间,也就是说,如果正在显示 View 并且 hide方法已经被调用并且已经完成,那么show调用方法,结果是正确的。如果正在显示 View ,则需要呈现另一个提示 View ,我将调用 hide首先,然后show ,自 main_queue是串行的,但动画 block 是同步执行的,所以结果是错误的。我正在寻找 GCD 中是否有某种锁可以帮助我在最后一个排队 block 完成后执行一个 block ,而不是在 show 内更改和hide方法。因为有许多其他电话到 showhide方法具有许多不同类型的参数,我需要修复代码中的许多地方。

最佳答案

如果您想按照任务添加到队列的顺序一次执行一个任务,请使用串行队列。

因此,您可以使用串行队列按添加的顺序一次执行显示和隐藏任务。是的,主队列就可以了。

然而 UIView -animateWithDuration:animations: 方法是一种异步调用,该方法立即返回。所以你需要等到完成 block 被调用。

如果您想等到某些任务完成,请使用调度组。但你应该避免像这样在主队列上等待。它阻塞了主队列。糟糕的应用程序。

因此,您可能需要使用串行队列和调度组,如下所示。

属性和初始化

@property (nonatomic, strong) dispatch_queue_t serialQueue;
@property (nonatomic, strong) dispatch_group_t group;

-(void)initQueue {
    // create a serial queue
    self.serialQueue = dispatch_queue_create("com.example.serialQueue", 0);
    // create a dispatch group
    self.group = dispatch_group_create();
}

使用串行队列和调度组的方法

-(void)animateSyncWithDuration:(NSTimeInterval)duration animations:(block_t)animations {
    dispatch_async(self.serialQueue, ^{
        /*
         * This block is invoked on the serial queue
         * This block would never be executed concurrently
         */

        /*
         * Enter the dispatch group
         */
        dispatch_group_enter(self.group);

        dispatch_async(dispatch_get_main_queue(), ^{
            /*
             * This block is invoked on the main queue
             * It is safe to use UIKit
             */
            [UIView animateWithDuration:duration animations:animations completion:^{
                /*
                 * This completion block is invoked on the main queue
                 * Now leave the dispatch group
                 */
                dispatch_group_leave(self.group);
            }];
        });

        /*
         * Wait until leaving the dispatch group from the UIView animation completion block
         * It means it blocks the serial queue
         */
        dispatch_group_wait(self.group, DISPATCH_TIME_FOREVER);
    });
}

显示和隐藏

-(void)show{
    [self animateSyncWithDuration:3.0f animations:^{
        //do something to show self to give hint;
        self.frame = CGRectMake(0,0,0,0);
    }];
}

-(void)hide{
    [self animateSyncWithDuration:3.0f animations:^{
        //do something to hide self to give hint;
        self.frame = CGRectMake(centerX,centerY,100,100);
    }];
}

关于ios - 如何使用GCD控制动画序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27601758/

相关文章:

objective-c - 释放 GCD 调度队列属性的正确方法是什么?

ios - 当应用程序在后台时,POItracker 会工作吗?

javascript - jQuery/CSS 动画 - 用线条和图像连接不同的按钮和表单

ios - "The app must ask for a basic read permission at install time"

r - 在 RMarkdown 中使用 LaTeX 动画包

javascript - 下拉菜单动画卡住

objective-c - dispatch_sync(dispatch_get_main_queue() UI 怪异

sql - Go 相当于 GCD 串行调度队列

ios - 防止 uitableView 重新加载

ios - 自定义选项卡组加速器