适用于iOS 7的UIImage +效果模糊效果减慢应用程序 - 450MB?

时间:2014-05-22 12:07:36

标签: ios iphone memory uiimage grand-central-dispatch

这是我使用artworkImage模糊一个名为UIImage+Effects的UIImage来获取iOS 7模糊效果的方法:

-(void)viewDidAppear:(BOOL)animated{

    MPMediaItem *currentItem = [self.musicPlayer nowPlayingItem];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0ul), ^(void) {
        @autoreleasepool {

            MPMediaItemArtwork *artwork = [currentItem valueForProperty: MPMediaItemPropertyArtwork];
            UIImage *artworkImage = [artwork imageWithSize: CGSizeMake (618, 618)];

            artworkImage = [artworkImage applyDarkEffect];

            dispatch_async(dispatch_get_main_queue(), ^{

                [backgroundImageView setImage:artworkImage];

                UIGraphicsEndImageContext();
            });
        }
    });
}

我的应用程序非常慢,所以我研究了如何找出原因,并且我遇到了仪器,它向我展示了这个:

450MB?!

所以我研究了一些如何解决这个问题,并遇到dispatch_async,所以我将实际模糊放到后台并更新前面的UI。它仍然非常缓慢。

每次音乐播放器跳过歌曲时,此UIImage都会更新artworkImage。我将Apple的示例项目(称为UIImage+Effects.h)中的iOS 7模糊效果应用于此UIImage。

请告诉我该做什么 - 我搜索了无数线程,这些线程都说使用autorelease,我当然不能使用ARC。

非常感谢任何帮助,谢谢。

2 个答案:

答案 0 :(得分:3)

这里最有可能发生的事情是你从上述处理中构建了一系列UIImages,导致你的应用程序最终耗尽内存并崩溃。

Apple的UIImage+Effects类别使用一系列盒子模糊确实模糊了CPU端。它不是世界上最快的过程。除此之外,创建UIImage可能会很慢,就像将UIImage设置为UIImageView进行显示一样。几乎所有这些都是在CPU上完成的,而不是GPU。

因此,如果每次更新UI元素时触发上述方法,您将首先将一系列块调度到默认后台队列,然后异步调度到主队列。后者最有可能发生内存堆积,因为每个块都会保留其中的对象。如果您的处理和UIImageView更新花费的时间超过了触发上述方法的时间间隔,您将在调度队列中构建块,并且每个块都将在其中包含UIImages。这将很快导致内存堆积和崩溃。

有两种方法可以解决这个问题。首先,您可以使用调度信号量来确保每个后台队列上只运行一个块。我描述了一个用于此here的过程。这样可以防止内存累积,但可能无助于模糊速度。

为此,您可以查看Apple提供的模糊类别的替代方案。我的开源GPUImage框架具有GPU加速模糊replicates Apple's default effect。如果您需要更深层次的变体,我会谈谈如何修改此here的变体。往返于UIImages仍然很慢,但是通过将模糊传递到GPUImageView而不是UIImageView,你至少可以替换你在这里进行的慢速处理的后半部分。直接过滤到GPUImageView进行显示会将所有这些内容保留在GPU上。

答案 1 :(得分:0)

我正在使用Stackblur

https://github.com/tomsoft1/StackBluriOS

非常易于使用,并且具有良好的优化性。