GPUImage和GPUImageView:应用由于内存错误而终止

432

我正在使用GPUImage和许多GPUImageView实例。目的是显示原始图像,在过滤后的图像的顶部分层放置几层,最后在原始图像上缓慢地对切片滤镜进行动画处理。想象一下图像上有一些棕褐色的条形滚动显示部分的正常图像和棕褐色图像。

我将此功能包装在UIView的子类中,如下所示:

import Foundation
import QuartzCore

class FilteredImageMaskView : UIView {

init(frame: CGRect, image: UIImage){
    super.init(frame: frame);

    let imageViewFrame = CGRectMake(frame.origin.x, 0.0, frame.size.width, frame.size.height);

    let origImage = GPUImagePicture(image: image);
    origImage.forceProcessingAtSizeRespectingAspectRatio(imageViewFrame.size);

    // Display the original image without a filter
    let imageView = GPUImageView(frame: imageViewFrame);
    origImage.addTarget(imageView);
    origImage.processImageWithCompletionHandler(){
        origImage.removeAllTargets();

        var contentMode = UIViewContentMode.ScaleAspectFit;
        imageView.contentMode = contentMode;

        // Width of the unfiltered region
        let regularWidth: CGFloat = 30.0;
        // Width of filtered region
        let filterWidth: CGFloat = 30.0;

        // How much we are moving each bar
        let totalXMovement = (regularWidth + filterWidth) * 2;

        // The start X position
        var currentXForFilter: CGFloat = -totalXMovement;

        // The filter being applied to an image
        let filter = GPUImageSepiaFilter();
        filter.intensity = 0.5;
        // Add the filter to the originalImage
        origImage.addTarget(filter);

        let filteredViewCollection = FilteredViewCollection(filteredViews: [GPUImageView]());

        // Iterate over the X positions until the whole image is covered
        while(currentXForFilter < imageView.frame.width + totalXMovement){
            let frame = CGRectMake(currentXForFilter, imageViewFrame.origin.y, imageViewFrame.width, imageViewFrame.height);
            var filteredView = GPUImageView(frame: frame);
            filteredView.clipsToBounds = true;
            filteredView.layer.contentsGravity = kCAGravityTopLeft;

            // This is the slice of the overall image that we are going to display as filtered
            filteredView.layer.contentsRect = CGRectMake(currentXForFilter / imageViewFrame.width, 0.0, filterWidth / imageViewFrame.width, 1.0);
            filteredView.fillMode = kGPUImageFillModePreserveAspectRatio;

            filter.addTarget(filteredView);

            // Add the filteredView to the super view
            self.addSubview(filteredView);

            // Add the filteredView to the collection so we can animate it later
            filteredViewCollection.filteredViews.append(filteredView);

            // Increment the X position           
            currentXForFilter += regularWidth + filterWidth;
        }

        origImage.processImageWithCompletionHandler(){
            filter.removeAllTargets();

            // Move to the UI thread
            ThreadUtility.runOnMainThread(){
                // Add the unfiltered image
                self.addSubview(imageView);
                // And move it behind the filtered slices
                self.sendSubviewToBack(imageView);

                // Animate the slices slowly across the image
                UIView.animateWithDuration(20.0, delay: 0.0, options: UIViewAnimationOptions.Repeat, animations: { [weak filteredViewCollection] in
                    if let strongfilteredViewCollection = filteredViewCollection {
                        if(strongfilteredViewCollection.filteredViews != nil){
                            for(var i = 0; i < strongfilteredViewCollection.filteredViews.count; i++){
                                strongfilteredViewCollection.filteredViews[i].frame.origin.x += totalXMovement;
                                strongfilteredViewCollection.filteredViews[i].layer.contentsRect.origin.x += (totalXMovement / imageView.frame.width);
                            }
                        }
                    }
                }, completion: nil);
            }
        }
    }
}

required init(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder);
}

}

class FilteredViewCollection {
    var filteredViews: [GPUImageView]! = [GPUImageView]();

    init(filteredViews: [GPUImageView]!){
        self.filteredViews = filteredViews;
    }
}

的实例以FilteredImageMaskView编程方式添加到viewController中的视图。当关闭该viewController时,假定资源将被处置-我小心地避免了保留周期。当我在实际设备上的调试器中查看内存消耗时,当关闭viewController时,内存确实会适当减少。但是,如果我反复加载该viewController以查看图像,然后将其关闭,然后再次重新加载,则最终我将遇到“由于内存错误导致应用程序终止”

如果我在关闭viewController之后等待一会儿,内存错误的出现频率似乎降低了,这使我相信在关闭viewController之后内存仍在释放中……?但是在不那么迅速打开和关闭viewController几次之后,我也看到了错误。

我必须使用效率低下的GPUImage和/或GPUImageView,并且正在寻找指导。

谢谢!

编辑:请参阅下面的视图控制器实现。

import UIKit

class ViewImageViewController: UIViewController, FetchImageDelegate {

    var imageManager = ImageManager();

    @IBOutlet var mainView: UIView!

    override func viewDidLoad() {
        super.viewDidLoad()

        imageManager.fetchImageAsync(delegate: self);
    }

    // This callback is dispatched on the UI thread
    func imageFetchCompleted(imageData: [UInt8]) {
        let imageView = FilteredImageMaskView(frame: self.mainView.frame, image: UIImage(data: imageData));
        mainView.addSubview(imageView);

        var timer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(10.0), target: self, selector: Selector("displayReminder"), userInfo: nil, repeats: false);
    }

    func displayReminder(){
        // Show an alert or message here
    }

}

class ImageManager {

    func fetchImageAsync(delegate: FetchImageDelegate) {
        // This dispatches a high priority background thread
        ThreadUtility.runOnHighPriorityBackgroundThread() { [weak delegate] in
            // Get the image (This part could take a while in the real implementation)
            var imageData = [UInt8]();

            // Move to the UI thread
            ThreadUtility.runOnMainThread({
                if let strongDelegate = delegate {
                    strongDelegate.imageFetchCompleted(imageData);
                }
            });
        }
    }
}

现在,我正在浏览这个精简的版本,即使我将其引用到后台线程,传递selfImageManager创建保留循环的操作也可以weak吗?我可以从中将其作为弱参考ViewImageViewController吗?当然有可能ViewImageViewControllerfetchImageAsync方法完成并调用回调之前将关闭

编辑:我想我找到了问题。如果您ViewImageViewController在回调中查看,则会创建一个NSTimer并传递self。我的怀疑是,如果在计时器执行之前将viewController关闭,则会创建一个保留周期。这就可以解释为什么如果我再等待几秒钟,就不会收到内存错误-因为计时器触发并且viewController正确处理。这是解决方法(我认为)。

// This is on the ViewImageViewController
var timer: NSTimer!;

// Then instead of creating a new variable, assign the timer to the class variable
self.timer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(10.0), target: self, selector: Selector("displayReminder"), userInfo: nil, repeats: false);

// And finally, on dismiss of the viewcontroller (viewWillDisappear or back button click event, or both)
func cancelTimer() {
    if(self.timer != nil){
        self.timer.invalidate();
        self.timer = nil;
    }
}
432

我想我找到了问题。如果您ViewImageViewController在回调中查看,则会创建一个NSTimer并传递self。我的怀疑是,如果在计时器执行之前将viewController关闭,则会创建一个保留周期。那可以解释为什么如果我再等待几秒钟,我不会收到内存错误-因为计时器启动并且viewController正确处理。这是解决方法(我认为)。

// This is on the ViewImageViewController
var timer: NSTimer!;

// Then instead of creating a new variable, assign the timer to the class variable
self.timer = NSTimer.scheduledTimerWithTimeInterval(NSTimeInterval(10.0), target: self, selector: Selector("displayReminder"), userInfo: nil, repeats: false);

// And finally, on dismiss of the viewcontroller (viewWillDisappear or back button click event, or both)
func cancelTimer() {
    if(self.timer != nil){
        self.timer.invalidate();
        self.timer = nil;
    }
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

由于内存错误而终止的应用

来自分类Dev

应用程序崩溃并显示消息“由于内存错误而终止”

来自分类Dev

应用因内存错误而终止-iPad应用

来自分类Dev

由于内存压力而终止

来自分类Dev

当我使用Photos.app时,我的iOS应用由于内存压力而终止

来自分类Dev

由于内存不足而导致应用程序终止时,不会调用onLowMemory()

来自分类Dev

当我使用Photos.app时,我的iOS应用由于内存不足而终止

来自分类Dev

由于未捕获的异常“ NSRangeException范围或索引超出范围”,导致iOS错误终止应用

来自分类Dev

应用引擎错误。进程由于超出配额而终止。配额页面不显示任何超出的配额

来自分类Dev

我该如何解决一个较早启动但现在“由于内存压力而终止”的应用程序?

来自分类Dev

我该如何解决一个较早启动但现在“由于内存不足而终止”的应用程序?

来自分类Dev

如何防止由于SSL错误而终止

来自分类Dev

由于“内存过多”,App Engine进程随机终止

来自分类Dev

iOS 7应用因内存压力而终止

来自分类Dev

调试Mac应用程序时,“来自调试器的消息:由于代码签名错误而终止”?

来自分类Dev

由于未捕获的异常“ NSRangeException范围或索引超出范围”,导致iOS错误终止应用程序

来自分类Dev

由于未捕获的异常而导致未终止应用程序(由于未添加父节点而尝试添加一个SKNode)错误

来自分类Dev

拍摄和显示图片的应用程序中的内存错误

来自分类Dev

Cgroup内存限制和进程终止

来自分类Dev

来自调试器的XCode消息:由于使用UIImageJPEGRepresentation时由于内存问题而终止

来自分类Dev

由于未捕获的异常“ _HKObjectValidationFailureException”而终止应用程序

来自分类Dev

由于未捕获的异常'NSInternalInconsistency而终止应用程序:

来自分类Dev

UICollectionViewController:由于未捕获的异常“ NSInternalInconsistencyException”而终止应用程序

来自分类Dev

由于未捕获的异常“ NSInternalInconsistencyException”问题而终止应用程序

来自分类Dev

“由于未捕获的异常'NSInvalidArgumentException'而终止应用程序”

来自分类Dev

由于NSInvalidArgumentException而导致SpriteKit终止应用程序

来自分类Dev

SIGABRT由于未捕获的异常而终止了应用程序

来自分类Dev

由于Google Maps API未捕获的异常“ NSRangeException”而终止了应用

来自分类Dev

UICollectionViewController:由于未捕获的异常“ NSInternalInconsistencyException”而终止应用程序

Related 相关文章

  1. 1

    由于内存错误而终止的应用

  2. 2

    应用程序崩溃并显示消息“由于内存错误而终止”

  3. 3

    应用因内存错误而终止-iPad应用

  4. 4

    由于内存压力而终止

  5. 5

    当我使用Photos.app时,我的iOS应用由于内存压力而终止

  6. 6

    由于内存不足而导致应用程序终止时,不会调用onLowMemory()

  7. 7

    当我使用Photos.app时,我的iOS应用由于内存不足而终止

  8. 8

    由于未捕获的异常“ NSRangeException范围或索引超出范围”,导致iOS错误终止应用

  9. 9

    应用引擎错误。进程由于超出配额而终止。配额页面不显示任何超出的配额

  10. 10

    我该如何解决一个较早启动但现在“由于内存压力而终止”的应用程序?

  11. 11

    我该如何解决一个较早启动但现在“由于内存不足而终止”的应用程序?

  12. 12

    如何防止由于SSL错误而终止

  13. 13

    由于“内存过多”,App Engine进程随机终止

  14. 14

    iOS 7应用因内存压力而终止

  15. 15

    调试Mac应用程序时,“来自调试器的消息:由于代码签名错误而终止”?

  16. 16

    由于未捕获的异常“ NSRangeException范围或索引超出范围”,导致iOS错误终止应用程序

  17. 17

    由于未捕获的异常而导致未终止应用程序(由于未添加父节点而尝试添加一个SKNode)错误

  18. 18

    拍摄和显示图片的应用程序中的内存错误

  19. 19

    Cgroup内存限制和进程终止

  20. 20

    来自调试器的XCode消息:由于使用UIImageJPEGRepresentation时由于内存问题而终止

  21. 21

    由于未捕获的异常“ _HKObjectValidationFailureException”而终止应用程序

  22. 22

    由于未捕获的异常'NSInternalInconsistency而终止应用程序:

  23. 23

    UICollectionViewController:由于未捕获的异常“ NSInternalInconsistencyException”而终止应用程序

  24. 24

    由于未捕获的异常“ NSInternalInconsistencyException”问题而终止应用程序

  25. 25

    “由于未捕获的异常'NSInvalidArgumentException'而终止应用程序”

  26. 26

    由于NSInvalidArgumentException而导致SpriteKit终止应用程序

  27. 27

    SIGABRT由于未捕获的异常而终止了应用程序

  28. 28

    由于Google Maps API未捕获的异常“ NSRangeException”而终止了应用

  29. 29

    UICollectionViewController:由于未捕获的异常“ NSInternalInconsistencyException”而终止应用程序

热门标签

归档