iOS NSNotificationCenter奇怪的延迟

时间:2014-01-22 11:31:35

标签: ios delay nsnotificationcenter

在我的应用中,我需要检测ImagePicker是否已准备好拍照。我在这里找到了一个解决方案:How to know if iPhone camera is ready to take picture?

所以我在viewDidLoad:

中得到了这段代码
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(showButton:)
name:AVCaptureSessionDidStartRunningNotification object:nil];

和选择器如下所示:

- (void)showButton:(NSNotification *)notification{

    NSLog(@"---CAMERA READY");

    [button setHidden:NO];
    [button setAlpha:0.0];
    [button setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.5, 1.5)];

    [UIView animateWithDuration:.2 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        [button setAlpha:1.0];
        [button setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.0)];
    } completion:^(BOOL finished) {

    }];

    NSLog(@"---CAMERA READY");

}

这里发生了一些奇怪的事情,因为两个NSLog都会立即出现,但整个按钮动画甚至会在30秒后触发。

UIView是否单独更新?如何同步日志和动画?

1 个答案:

答案 0 :(得分:2)

将其放在答案框中以供将来的用户查看..

您遇到的情况会使您看起来未在主线程上调用通知,并且在后台线程上更新UI是未定义的行为。解决这个问题很简单,只需将方法的内容包装在dispatch_async()调用中,然后将所有内容发送回主队列。

- (void)showButton:(NSNotification *)notification {

    dispatch_async(dispatch_get_main_queue(), ^{
        NSLog(@"---CAMERA READY");

        [button setHidden:NO];
        [button setAlpha:0.0];
        [button setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.5, 1.5)];

        [UIView animateWithDuration:.2 delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
            [button setAlpha:1.0];
            [button setTransform:CGAffineTransformScale(CGAffineTransformIdentity, 1.0, 1.0)];
        } completion:nil];

        NSLog(@"---CAMERA READY");
    });
}

作为替代方法,您可以使用不同的NSNotificationCenter实例方法。具体来说,-addObserverForName:object:queue:usingBlock:允许您指定应在哪个操作队列上执行回调块。在这种情况下,您需要传递[NSOperationQueue mainQueue];

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSNotificationCenter_Class/Reference/Reference.html#//apple_ref/occ/instm/NSNotificationCenter/addObserverForName:object:queue:usingBlock

NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue];
self.localeChangeObserver = [center addObserverForName:NSCurrentLocaleDidChangeNotification object:nil
    queue:mainQueue usingBlock:^(NSNotification *note) {

        NSLog(@"The user's locale changed to: %@", [[NSLocale currentLocale] localeIdentifier]);
    }];