【问题标题】:Multiple Image Operations Crash iPhone App多个图像操作崩溃 iPhone 应用程序
【发布时间】:2010-11-05 20:21:27
【问题描述】:

我是 iPhone 应用开发的新手,所以我可能做错了什么。

基本上,我是从互联网上加载一堆图像,然后对其进行裁剪。我设法找到了异步加载图像并将它们添加到视图中的示例。我已经设法通过NSOperation 添加带有NSData 的图像来做到这一点,该NSOperation 添加到NSOperationQueue 中。

然后,因为我必须制作固定大小的拇指,我需要一种方法来裁剪这些图像,所以我在网上找到了一个基本上使用UIGraphicsBeginImageContext()UIGraphicsGetImageFromCurrentImageContext()UIGraphicsEndImageContext()的脚本来绘制裁剪的图像,以及不重要​​的尺寸计算。

问题是,该方法有效,但由于它生成了大约 20 张这样的图像,它会在生成其中一些图像后随机崩溃,或者有时在我关闭并重新打开应用程序一两次后随机崩溃。

在这种情况下我该怎么办?我也尝试使用NSOperationsNSOperationQueue 使这些方法以某种方式异步运行,但没有运气。

如果裁剪代码比我想象的更相关,那就是:

UIGraphicsBeginImageContext(CGSizeMake(50, 50));
CGRect thumbnailRect = CGRectZero;
thumbnailRect.origin = CGPointMake(0.0,0.0); //this is actually generated
                                             // based on the sourceImage size
thumbnailRect.size.width  = 50;
thumbnailRect.size.height = 50;
[sourceImage drawInRect:thumbnailRect];
newImage = UIGraphicsGetImageFromCurrentImageContext();

谢谢!

【问题讨论】:

  • 当崩溃发生时调试器会说什么?另外,这是在设备上运行还是在模拟器中运行??
  • 如果您只是同步完成工作,而不是使用 NSOperationQueue,它还会崩溃吗?神秘崩溃的通常原因是你释放了一些你不应该释放的东西,尤其是当你崩溃时的堆栈跟踪中包含“autorelease”或“pool”这样的词......

标签: iphone objective-c cocoa-touch memory-management


【解决方案1】:

缩放图像的代码看起来太简单了。 这是我正在使用的。如您所见,没有泄漏,不再需要时释放对象。希望这会有所帮助。

    // Draw the image into a pixelsWide x pixelsHigh bitmap and use that bitmap to 
// create a new UIImage 
- (UIImage *) createImage: (CGImageRef) image width: (int) pixelWidth height: (int) pixelHeight
{ 
    // Set the size of the output image 
    CGRect aRect = CGRectMake(0.0f, 0.0f, pixelWidth, pixelHeight); 
    // Create a bitmap context to store the new thumbnail 
    CGContextRef context = MyCreateBitmapContext(pixelWidth, pixelHeight); 
    // Clear the context and draw the image into the rectangle 
    CGContextClearRect(context, aRect); 
    CGContextDrawImage(context, aRect, image); 
    // Return a UIImage populated with the new resized image 
    CGImageRef myRef = CGBitmapContextCreateImage (context); 

    UIImage *img = [UIImage imageWithCGImage:myRef];

    free(CGBitmapContextGetData(context)); 
    CGContextRelease(context);
    CGImageRelease(myRef);

    return img; 
} 


// MyCreateBitmapContext: Source based on Apple Sample Code
CGContextRef MyCreateBitmapContext (int pixelsWide,
                                    int pixelsHigh)
{
    CGContextRef    context = NULL;
    CGColorSpaceRef colorSpace;
    void *          bitmapData;
    int             bitmapByteCount;
    int             bitmapBytesPerRow;

    bitmapBytesPerRow   = (pixelsWide * 4);
    bitmapByteCount     = (bitmapBytesPerRow * pixelsHigh);

    colorSpace = CGColorSpaceCreateDeviceRGB();
    bitmapData = malloc( bitmapByteCount );
    if (bitmapData == NULL)
    {
        fprintf (stderr, "Memory not allocated!");
        CGColorSpaceRelease( colorSpace );
        return NULL;
    }
    context = CGBitmapContextCreate (bitmapData,
                                     pixelsWide,
                                     pixelsHigh,
                                     8,
                                     bitmapBytesPerRow,
                                     colorSpace,
                                     kCGImageAlphaPremultipliedLast);
    if (context== NULL)
    {
        free (bitmapData);
        CGColorSpaceRelease( colorSpace );
        fprintf (stderr, "Context not created!");
        return NULL;
    }
    CGColorSpaceRelease( colorSpace );

    return context;
}

【讨论】:

  • 嗨,已经有一段时间了,但我仍然有这个问题,所以现在我决定查看你的答案。我正在尝试使用您的代码,但我将图像作为 UIImage,并且您的函数需要 CGImageRef。另外,这个脚本只缩放图像,对吧?我还需要裁剪它。
  • 为了后代,UIImage 定义了一个属性 CGImage,它为您提供了该图像的 CGImageRef
【解决方案2】:

这听起来有点像内存不足的崩溃。启动 Leaks 工具并查看您的整体内存趋势。

【讨论】:

    【解决方案3】:

    您的应用程序正在崩溃,因为您正在使用的调用(例如 UIGraphicsBeginImageContext)操纵 UIKit 的上下文堆栈,您只能从主线程安全地执行此操作。

    unforgiven 的解决方案在线程中使用时不会崩溃,因为它不操作上下文堆栈。

    【讨论】:

    • 这是有道理的。事实上,我怀疑这一点,我试图使用 unforgiven 的解决方案,但我不知道如何使用他的函数,因为它需要 CGImageRef 并且我正在将外部图像加载到 UIImage 中。你觉得你能帮我解决这个问题吗?谢谢。
    • 对于 8 年后看到此内容的任何人,请注意,UIGraphicsBeginImageContext 现在是线程安全的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 2011-06-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多