5

我使用以下代码绘制子图像

UIImage* subIm = getSubImage( large, rect );
[subIm drawInRect:self.bounds];

其中getSubImage定义如下

    UIImage* getSubImage(UIImage* uim, CGRect rc){
      CGImageRef imref  = CGImageCreateWithImageInRect(uim.CGImage, rc); 
      UIImage*   sub = [UIImage imageWithCGImage:imref];
      CGImageRelease(imref);
        NSLog(@"subimage retainCount=%d", [sub  retainCount]); // is 1
      return sub;
   }//getSubImage

代码是否正确?

“CGImageRelease”imref 是否安全?

有子“CGImageRetained”imref 吗?

我应该释放 subIm 吗(如果我这样做会出错)?

subIm 是否包含在自动释放池中,如果是,我怎么知道?

一般来说,可以检查一个对象是否包含在自动释放池中(出于调试目的)?

4

4 回答 4

15

不要调用 -retainCount

保留计数返回的数字是对象的绝对保留计数。可能有许多你无法控制的保留,因为它们是框架的实现细节。有更好的方法来验证代码的内存管理。

保留计数应仅视为增量;如果您使保留计数增加,则必须使其减少。

鉴于:

UIImage* getSubImage(UIImage* uim, CGRect rc){
  CGImageRef imref  = CGImageCreateWithImageInRect(uim.CGImage, rc); 
  UIImage*   sub = [UIImage imageWithCGImage:imref];
  CGImageRelease(imref);
    NSLog(@"subimage retainCount=%d", [sub  retainCount]); // is 1
  return sub;
}//getSubImage

imageWithCGImage:返回一个自动释放的对象。保留计数无关紧要,因为它imageWithCGImage:可能在内部做任何可能影响保留计数的事情——缓存等。

get*是 Cocoa 编程中使用的一种奇怪模式。你只是没有看到那么多。

我建议像:

- (UIImage *) subImage: (UIImage *) anImage inRect: (CGRect) aRect
{
      CGImageRef imageRef  = CGImageCreateWithImageInRect(anImage.CGImage, aRect); 
      UIImage*   subImage = [UIImage imageWithCGImage: imageRef];
      CGImageRelease(imageRef);
      return subImage;
}
于 2010-12-28T18:50:14.960 回答
6

内存管理有一个命名约定。所有Cocoa 代码都遵循这个规则:

基本内存管理规则

我强烈建议您阅读本文档并遵守规则。命名规则也是 Cocoa 的一部分。

从参考文档:

您拥有您创建的任何对象。您使用名称以“alloc”或“new”开头或包含“copy”的方法“创建”一个对象(例如,alloc、newObject 或 mutableCopy)。

使用完对象后,您必须放弃对它们的所有权。您通过向对象发送释放消息或自动释放消息来放弃对对象的所有权(自动释放在“自动释放”中有更详细的讨论)。因此,在 Cocoa 术语中,放弃对象的所有权通常称为“释放”对象。

Core Foundation 框架的 C 函数也有类似的规则。然而,没有这种类似自动释放的东西。如果你想用 C 函数创建 Objective-C 对象,你必须澄清文档中的所有内容。

这可能对您有帮助: imageWithCGImage and memory

于 2010-12-28T16:43:34.810 回答
4

SubIm 被注册到 AutoRelease Pool 中,因为这个对象实际上是由类方法 imageWithCGImage 创建的,并且规则是类方法创建的实例应该总是返回自动释放的实例。

代码是正确的,虽然我不明白你为什么使用 C 语法而不是 Obj-C 语法来定义你的函数

于 2010-12-28T13:27:03.857 回答
0
  CGImageRelease(imref);
    NSLog(@"subimage retainCount=%d", [sub  retainCount]); // is 1
  return sub;

因为您的方法没有关键字 alloc、retain、copy...,所以您必须在返回 UIImage 之前自动释放它。但是 UIImage 的工厂方法已经为您做到了。请注意,即使您自动释放子,保留计数仍然是 1

于 2010-12-28T13:28:01.497 回答