GPUImage的作者BardLarson已经merge了我的RP, 该问题已解决。 不过既然都到这里了,我还是建议看完这篇文章,或许对你有帮助:P ***

事情的起因是产品出了一个需求,要对Camera做实时模糊的效果。

首先我想到的是用GPUImage来做,但是在使用GPUImage滤镜的时候发现每次都会出现内存泄露,而且几乎所有滤镜都会有泄漏。后来想到了CoreImage内置了模糊的滤镜,而且CoreImage也支持硬件加速,于是放弃了GPUImage的方案,用CoreImage取而代之(iOS8已经支持自定义Kernel了,感兴趣的可以移步这里)。

就在前几天在github上看到有朋友已经找到了上文中我提到的leak原因,并且提到了解决方案(不想看一大堆废话的可以直接看这里)。不敢私藏,写出来和大家一起分享。

我们知道GCD中的对象在6.0之前是不参与ARC的,而GPUImage目前支持最低的iOS版本是4.3,并且用到了ARC,因此Brad Larson在GPUImage里,用了一些条件编译来实现在iOS6.0之前GCG对象的手动释放。

GPUImage中的条件语句如下:

- (void)dealloc
{
    [self destroyDataFBO];

#if ( (__IPHONE_OS_VERSION_MIN_REQUIRED < __IPHONE_6_0) || (!defined(__IPHONE_6_0)) )
    if (movieWritingQueue != NULL)
    {
        dispatch_release(movieWritingQueue);
    }
    if( audioQueue != NULL )
    {
        dispatch_release(audioQueue);
    }
    if( videoQueue != NULL )
    {
        dispatch_release(videoQueue);
    }
#endif
}

这里判断了当前系统支持的最小版本是否小于6.0,如果你在管理第三方库的时候没有用到Cocoapods,那应该说大多数情况下这么判断是没有问题的。但是如果用到了Cocoapods,细心的你会发现在GPUImage的pod里,compile sources的flag中多了一项DOS_OBJECT_USE_OBJC=0

查了一下关于DOS_OBJECT_USE_OBJC的解释:

我们发现恰恰是因为这一行定义,禁止了当前文件中的GCD对象参与ARC。至此,泄露的原因已经找到。事实上较好的做法是通过检查OS_OBJECT_USE_OBJC,因为在上述这种特定的条件下版本检测并不是完全通用。

但问题是我们还得用Cocoapods来管理所有第三方库啊!或许你可以这样:

1、设置pod时将将GPUImage的git地址改为我的分支,这里我将用到的条件语句改为了推荐的OS_OBJECT_USE_OBJC检查特性而不是检查版本

2、偷懒的办法,fork GPUImage之后将.podspec文件中deployment_target设置为6.0或以上,更新一下pod。

因此,如果你的项目使用Cocoapods来管理第三方库,那就有必要稍微花点时间检查一下,确保没有出现因上述问题而造成的内存泄露。

Over.





blog comments powered by Disqus

Published

09 September 2014

Tags