Objective-C 块不会跳过代码,然后执行它



我使用的是GPUImage框架,我注意到编译器会自动跳过setColorAverageProcessingFinishedBlock括号内的所有内容。它完全跳过这些内容,继续执行代码中的所有其他内容。一旦执行完所有其他内容,它就会返回到括号内的内容。显然,这会产生意想不到的副作用。

NSMutableArray *redValues = [NSMutableArray array];
NSMutableArray *arrayOne = [NSMutableArray array];
NSUInteger arrayOneLength = [arrayOne count];
__block int counter = 0;
int amount = 1;
float totalOne, diffForAverage;
NSInteger j;
GPUImageVideoCamera *videoCamera = [[GPUImageVideoCamera alloc] initWithSessionPreset:AVCaptureSessionPreset640x480 cameraPosition:AVCaptureDevicePositionBack];
videoCamera.outputImageOrientation = UIInterfaceOrientationPortrait;
GPUImageAverageColor *averageColor = [[GPUImageAverageColor alloc] init];
[averageColor setColorAverageProcessingFinishedBlock:^(CGFloat redComponent, CGFloat greenComponent, CGFloat blueComponent, CGFloat alphaComponent, CMTime frameTime)
{ // the compiler runs until here, then skips everything within these brackets
NSLog(@"%f", redComponent);
[redValues addObject:@(redComponent * 255)];
}]; // after the brackets close, it executes everything that is below this
// once everything below this has been executed, it goes back to the brackets and executes
// everything between them
[videoCamera addTarget:averageColor];
[videoCamera startCameraCapture];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 27 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[videoCamera stopCameraCapture];
});
totalOne = [redValues[24] floatValue];
float average = totalOne / amount;
NSUInteger redValuesLength = [redValues count];
for (j = (counter + 24); j < (redValuesLength - 24); j++)
{
diffForAverage = average - [redValues[j + 1] floatValue];
if (diffForAverage > -1 && diffForAverage < 1)
{
totalOne += [redValues[j + 1] floatValue];
amount++;
[arrayOne addObject:[NSNumber numberWithInt:(j - 24)]];
counter++;
}
}

我该如何解决这个问题?

上面的代码有两个问题:内存管理问题和对块如何工作的误解。

首先,在方法中创建一个GPUImageVideoCamera实例,但不将其保留为实例变量。我假设这是使用自动引用计数的代码,如果这是真的,那么这个相机实例将在方法完成的那一刻被释放。在解除分配之前,您最多可以从相机中捕获一帧。在最坏的情况下,这将崩溃,因为相机和连接到它的整个过滤器链在操作过程中被释放。

在包含类上创建一个实例变量,并将GPUImageVideoCamera实例分配给它,使其持续足够长的时间以发挥作用。

上面的第二个问题是对块如何以及何时执行的误解。块只是可以传递的代码部分,它们不一定与周围的其他代码串行执行。

在这种情况下,您提供的块是一个回调,它将在通过平均颜色操作处理每一帧视频后触发。这种处理在后台队列上异步进行,您必须设计代码来确认这一点。

如果您希望建立X值,请将每个测量值添加到该块内的数组中,然后在块内检查是否达到X值。在这一点上,平均下来,用它们做任何事情。基本上,只要计数大于X,就在块中添加一个检查,并将之后的代码移动到要运行的块中。如果你只需要停止相机捕捉,你可能希望在这一点上停止相机捕捉。

您发布的代码正按照预期工作。颜色平均处理需要一段时间,所以它是在后台线程上完成的,这样主线程就不会停滞。处理完成后,然后调用块。

任何在处理完成之前不应该执行的代码都需要进入块内部。

最新更新