Objective-C块不会跳过代码,然后再执行它 [英] Objective-C block doesn't skips code and then later executes it

查看:103
本文介绍了Objective-C块不会跳过代码,然后再执行它的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用GPUImage框架,并且我注意到编译器会自动跳过setColorAverageProcessingFinishedBlock括号内的所有内容.它会完全跳过这些内容,并继续执行代码中的所有其他内容.一旦执行完所有其他操作,便回到括号内的内容.显然,这有意想不到的副作用.

I'm using the GPUImage framework and I've noticed that the compiler automatically skips everything that is within the brackets of the setColorAverageProcessingFinishedBlock. It completely skips over these contents and continues on, executing everything else in the code. Once everything else has been executed, it comes back to the content within the brackets. Obviously, this has unintended side effects.

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++;
    }
}

我该如何解决这个问题?

How can I solve this problem?

推荐答案

上面的代码有两个问题:一个是内存管理问题,另一个是关于块如何工作的误解.

There are two issues with the above code: a memory management one, and a misunderstanding of how blocks work.

首先,您正在方法中创建一个GPUImageVideoCamera实例,但没有将其保留为实例变量.我将假定这是使用自动引用计数的代码,如果是这样,则在方法完成后立即释放此相机实例.最好,在解除分配之前,您可能会从相机捕获一帧.在最坏的情况下,这会崩溃,因为摄像机和与其相连的整个滤镜链在操作过程中会被重新分配.

First, you're creating a GPUImageVideoCamera instance within a method, but not retaining it as an instance variable. I'm going to assume this is code using automatic reference counting, and if that's true, this camera instance will be deallocated the instant your method is finished. At best, you'll capture maybe one frame from the camera before this is deallocated. At worst, this will crash as the camera and the entire filter chain attached to it are deallocated mid-operation.

在您的包含类上创建一个实例变量,然后将您的GPUImageVideoCamera实例分配给它,以使其持续足够长的时间才有用.

Make an instance variable on your containing class and assign your GPUImageVideoCamera instance to it to have it last long enough to be useful.

以上所述的第二个问题是关于如何以及何时执行块的误解.块仅仅是您可以传递的代码部分,它们不一定与周围的其余代码串行执行.

The second issue with the above is a misunderstanding about how and when blocks will execute. Blocks are merely sections of code you can pass around, and they don't necessarily execute in serial with the rest of the code around them.

在这种情况下,您提供的块是一个回调,将在通过平均颜色运算处理完视频的每一帧后触发该回调.该处理在后台队列上异步进行,并且您必须设计代码以确认这一点.

In this case, the block you're providing is a callback that will be triggered after every frame of video is processed through the average color operation. This processing takes place asynchronously on a background queue, and you have to design your code to acknowledge this.

如果要建立X值,请将每个测量值添加到该块内部的数组中,然后在该块内检查要达到的X值.在那一点上,平均并与他们做任何事情.基本上,在块内添加一个检查,然后在计数大于X时将其后的代码移至要运行的块中.如果需要,您可能希望在那一刻停止摄像头捕获.

If you want X values to be built up, have each measurement be added to an array inside that block, and then within the block check for X values to be reached. At that point, average and do whatever with them. Basically, add a check within the block and move the code you have after it into the block to be run whenever the count is greater than X. You may wish to stop camera capture at that point, if that's all you need.

这篇关于Objective-C块不会跳过代码,然后再执行它的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆