在NSOperation completionBlock中,animateWithDuration没有正确运行

时间:2013-06-28 21:38:40

标签: ios objective-c objective-c-blocks nsoperation

我正在尝试使用第三方库AFNetworking下载文件, 在其核心有一个NSOperation对象,可以为下载完成时设置完成块。

不知何故,此块中的animateWithDuration:无法正常运行:它的完成块和实际动画都会延迟~5或60秒,或者根本不运行。知道它开始的唯一方法是通过NSLog调用。

让我演示一下:

[UIView animateWithDuration:0.1
    animations:^{
        controller.view.alpha=0.5;
        NSLog(@"First Try Start");
    }
    completion:^(BOOL finished) {
        NSLog(@"First Try End");
}];


// Here comes the NSOperation completion block
[self->currentConnection setCompletionBlock:^{
        NSLog(@"downloadComplete!");
        [UIView animateWithDuration:0.1
            animations:^{
                controller.view.alpha=0.5; // this doesn't run immediately, only the NSLog line
                NSLog(@"Second Try Start");
    }
    completion:^(BOOL finished) {
                             NSLog(@"Second Try End");
    }];
}];

控制台输出:

2013-06-28 23:22:11.374 ML[7831:c07] First Try Start
2013-06-28 23:22:11.477 ML[7831:c07] First Try End
2013-06-28 23:22:11.742 ML[7831:1303] downloadComplete!
2013-06-28 23:22:11.745 ML[7831:1303] Second Try Start
2013-06-28 23:23:05.007 ML[7831:c07] Second Try End

非常感谢帮助!

2 个答案:

答案 0 :(得分:5)

UIKit不是特别线程安全的。在主线程以外的线程中操作UIKit对象将导致不可预测的结果,主要是以不明显响应状态变化的对象的形式。

您可以在完成块中使用GCD来安排在主线程上运行的块:

[self->currentConnection setCompletionBlock:^{
    NSLog(@"downloadComplete!");
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    dispatch_async(mainQueue, ^{
        [UIView animateWithDuration:0.1
            animations:^{
                    controller.view.alpha=0.5;
                    NSLog(@"Second Try Start");
            }
            completion:^(BOOL finished
                NSLog(@"Second Try End");
            }
        ];
    });
}];

答案 1 :(得分:0)

//在你的班级中定义以下方法

-(void)updateView:(UIView *)paramView {
   paramView = 0.5
}

//并在您设置controller.alpha = 0.5的位置调用以下代码行 //现在你正在主线程上更新alpha

[self performSelectorOnMainThread:@selector(updateView:)  withObject:controller.view waitUntilDone:YES];