0

美好的一天,这就是我想要做的:

  • 我有一个使用 AVFoundation 拍摄图像的照片处理应用程序
  • 我有一个 DeviceMotion 队列,它以 60Hz 处理设备位置
  • 拍摄图像时,需要对其进行裁剪和保存。DeviceMotion 需要保持运行并及时更新界面

我看到的是:在图像裁剪期间,来自 DeviceMotion 队列的接口更新被冻结。

这就是我开始更新 DeviceMotion 的方式:

self.motionManager.deviceMotionUpdateInterval = 1.0f/60.0f;
gyroQueue = [[NSOperationQueue alloc] init];

[self.motionManager startDeviceMotionUpdatesToQueue:gyroQueue withHandler:^(CMDeviceMotion *motion, NSError *error){
        [NSThread setThreadPriority:1.0];
        [self processMotion:motion withError:error];
    }];

当图像从 AVFoundation 返回时,它被添加到队列中进行处理:

imageProcessingQueue = [[NSOperationQueue alloc] init];
    [imageProcessingQueue setName:@"ImageProcessingQueue"];
    [imageProcessingQueue setMaxConcurrentOperationCount:1];

//[imageProcessingQueue addOperationWithBlock:^{
    //[self processImage:[UIImage imageWithData:imageData]];
//}];

    NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(processImage:) object:[UIImage imageWithData:imageData]];
    [operation setThreadPriority:0.0];
    [operation setQueuePriority:NSOperationQueuePriorityVeryLow];
    [imageProcessingQueue addOperation:operation];

及图像处理方法:

- (void)processImage:(UIImage*)image {

    CGSize cropImageSize = CGSizeMake(640,960);

    UIImage *croppedImage  = [image resizedImageWithContentMode:UIViewContentModeScaleAspectFit bounds:cropImageSize interpolationQuality:kImageCropInterpolationQuality];

    NSData *compressedImageData = UIImageJPEGRepresentation(croppedImage, kJpegCompression);

    [self.doc addPhoto:compressedImageData];
}

问题是:

  • 使用 NSOperationQueue 处理图像时,在图像裁剪期间会阻止 devicemotion 更新

如果我使用 performSelectorInBackground 处理图像 - 它可以按需要工作(没有延迟到 DeviceMotion 队列)

[self performSelectorInBackground:@selector(processImage:) withObject:[UIImage imageWithData:imageData]];

关于我对后台线程的理解需要更新的任何想法?:)

PS。这个问题我之前也问过,但是没找到,所以重新发帖

4

1 回答 1

0

我已经为这个问题找到了一个解决方案(或可靠的解决方法):

我没有使用 将 deviceMotion 更新路由到队列startDeviceMotionUpdatesToQueue,而是创建了一个 CADisplayLink 计时器,它不会干扰其他后台队列 - 虽然它与屏幕刷新率匹配,但它的本质是最高优先级:

[self.motionManager startDeviceMotionUpdates];

gyroTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(processMotion)];
    [gyroTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
于 2013-04-07T22:26:32.833 回答