是在主线程中调用的AVAssetImageGenerator完成处理程序?

时间:2014-02-01 08:51:47

标签: ios multithreading nsoperation avassetimagegenerator

  1. 我想从视频中获取一系列图片。它运行良好,但我怀疑在哪个线程中调用完成处理程序。

  2. 我在新操作中调用了此方法(generateCGImagesAsynchronouslyForTimes:),并在完成处理程序中更新了UI。用户界面得到更新。

  3. 但通常在辅助线程中不会发生UI更新?我的疑问是在当前调用线程或主线程中调用的完成处理程序?

  4. 我的代码是:

    __block unsigned int i = 0;
    AVAssetImageGeneratorCompletionHandler handler = ^(CMTime requestedTime, CGImageRef im, CMTime actualTime, AVAssetImageGeneratorResult result, NSError *error){
    
        i++;
        if(result == AVAssetImageGeneratorSucceeded){
    
            //Create a block to save the image in disk
            NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
                NSFileManager *fileMgr = [NSFileManager defaultManager];
                NSString *documentsDirectory = [NSHomeDirectory()
                                                stringByAppendingPathComponent:@"Documents"];
                NSError *error = nil;
    
                //Create file path for storing the image
                NSString *videoOutputPath = [documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"VideoFrames%i.png", i]];
    
                //Delete if already any image exist 
                if ([fileMgr fileExistsAtPath:videoOutputPath]){
                    if ([fileMgr removeItemAtPath:videoOutputPath error:&error] != YES)
                        NSLog(@"Unable to delete file: %@", [error localizedDescription]);
                }
    
                //Convert the CGImageRef to UIImage
                UIImage *image = [UIImage imageWithCGImage:im];//**This line gives error: EXE_BAD_ACCESS**
    
                //Save the image
                if(![UIImagePNGRepresentation(image) writeToFile:videoOutputPath options:NSDataWritingFileProtectionNone error:&error])
                    NSLog(@"Failed to save image at path %@", videoOutputPath);
            }];
    
            //Add the operation to the queue
            [self.imageWritingQueue addOperation:operation];
        }
       }
    };
    

2 个答案:

答案 0 :(得分:4)

文件清楚地说明了这一点:

  

与AV Foundation同步编程

     

来自AV Foundation的调用 - 块,键值观察器和通知处理程序的调用 - 不保证在任何特定线程或队列上进行。相反,AV Foundation会在执行其内部任务的线程或队列上调用这些处理程序。您负责测试调用处理程序的线程或队列是否适合您要执行的任务。如果不是(例如,如果要更新用户界面并且标注不在主线程上),则必须将任务的执行重定向到您识别的安全线程或队列,或者您为其创建的队列。目的

另请参阅:AV Foundation Programming Guide

修改

问题是,您不保留/释放参数 im 中提供的CGImageRef图像,因为您稍后在NSBlockOperation中使用它。在调用块之前,需要保留在块之外(来自NSBlockOperation),并在块返回之前(在块内)释放它。

答案 1 :(得分:2)

IIRC,是的。但是你可以测试它,为了安全起见,你可以将代码包装在一个块中,然后将它发送到主线程。

一般来说,回调必须返回主线程,因为如果它不是主线程,则无法保证它的运行循环运行的线程。

除非你正在安排你正在创建与其他操作(依赖项)相关的块,否则我不确定该块给你带来了什么好处,因为图像加载是异步的,所以你可以从主线程触发它而不用阻止任何事情。


根据您的评论,在这种情况下,您应该切换代码。在完成块内创建块操作,为您提供图像。将每个块操作添加到队列中。块操作只需获取图像并将其保存到磁盘。