-2

我使用以下代码创建了一个数组。在不再需要 12 张图像后,我将 imageArray 设置为 nil 并将一组新图像重新加载到该数组中。当我在仪器中运行应用程序时,我可以看到内存累积问题。我还运行了 heapshots,它显示即使我将数组设置为 nil 后仍有 12 个图像仍然存在。我还尝试在它自己的自动释放池中初始化这个数组,认为它是在主线程下方的一个单独线程上创建的。那也没有用。有任何想法吗?

视图控制器.h

@property (strong, nonatomic) NSMutableArray *imageArray;

视图控制器.m

- (void) firstSetOfImages{
  imageArray= [[NSMutableArray alloc] initWithObjects:wordImage1, wordImage2, wordImage3, wordImage4, wordImage5, wordImage6, wordImage7, wordImage8, wordImage9, wordImage10, wordImage11, wordImage12, nil];
}

- (void) clearImages{
  [self setImageArray:nil];
  [imageArray removeAllObjects];
  [self secondSetOfImages];
}

- (void) secondSetOfImages{
    imageArray= [[NSMutableArray alloc] initWithObjects:wordImage1, wordImage2, wordImage3, wordImage4, wordImage5, wordImage6, wordImage7, wordImage8, wordImage9, wordImage10, wordImage11, wordImage12, nil];
}

这是在加载一组 12 个图像和第二组 12 个图像之间拍摄的 1 个 heapshot 的示例。

Snapshot    Timestamp   Heap Growth # Persistent
Heapshot 3  00:39.457.174   53.02 KB    800
 < non-object >     26.05 KB    277
 UIImageView        3.38 KB 36
 CFDictionary (mutable)     3.38 KB 72
 CFBasicHash (key-store)        2.83 KB 73
 CFBasicHash (value-store)      2.83 KB 73
 NSPathStore2       2.25 KB 12
 CGImageReadRef     1.88 KB 12
 CALayer        1.69 KB 36
 CGImage        1.62 KB 13
 CFNumber       1.31 KB 84
 CGImagePlus        1.31 KB 12
 CFData     1.12 KB 24
 CGImageProvider        768 Bytes   12
 CGDataProvider     720 Bytes   5
 UIImage        576 Bytes   12
 CFString (immutable)       416 Bytes   13
 CFArray (mutable-variable)     384 Bytes   12
 CGImageReadSessionRef      192 Bytes   12
 _   UIImageViewExtendedStorage     192 Bytes   4
 __NSArrayM     160 Bytes   5   
     CFDictionary (immutable)       48 Bytes    1

编辑:

我修改了代码并使数组成为 ivar。我在 Instruments 中获取了另一个分配样本。下面是我的 heapshots 的更详细的显示。每次我用 12 个新图像重置我的阵列时,我都会大吃一惊。每个 heapshot 都有大约 35kb 的 heapgrowth。

Snapshot    Timestamp       Heap Growth     # Persistent
Heapshot 4  00:58.581.296       35.63 KB        680
 < non-object >                 13.02 KB        220
 CFDictionary (mutable)         3.38 KB         72
 CFBasicHash (key-store)        2.81 KB     72
 CFBasicHash (value-store)      2.81 KB     72
 NSPathStore2                   2.28 KB     12
 CGImageReadRef                 1.88 KB     12
 CGImage                        1.50 KB     12
 CFNumber                       1.31 KB     84
 CGImagePlus                1.31 KB     12   
 CFData                     1.12 KB     24
 UIImageView                1.12 KB     12
 CGImageProvider            768 Bytes       12
 UIImage                    576 Bytes       12
 CALayer                    576 Bytes       12
 CFString (immutable)       384 Bytes       12
 CFArray (mutable-variable) 384 Bytes       12
 CGImageReadSessionRef      192 Bytes       12
 CGDataProvider             144 Bytes       1
 _UIImageViewExtendedStorage96 Bytes        2
 __NSArrayM                 32 Bytes        1

这是 UIImage 中这些 Persistent 项之一的堆栈跟踪。它并不指向创建它的特定代码行。不知道从这里去哪里?

  24 FourGameCenter 0x4b4bf
  23 FourGameCenter 0x4b538
  22 UIKit UIApplicationMain
  21 GraphicsServices GSEventRunModal
  20 CoreFoundation CFRunLoopRunInMode
  19 CoreFoundation CFRunLoopRunSpecific
  18 CoreFoundation __CFRunLoopRun
  17 CoreFoundation __CFRunLoopDoSource1
  16 CoreFoundation __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__
  15 GraphicsServices PurpleEventCallback
  14 GraphicsServices _PurpleEventCallback
  13 UIKit _UIApplicationHandleEvent
  12 UIKit -[UIApplication sendEvent:]
  11 UIKit -[UIWindow _sendTouchesForEvent:]
  10 UIKit -[UIControl touchesEnded:withEvent:]
   9 UIKit -[UIControl(Internal) _sendActionsForEvents:withEvent:]
   8 UIKit -[UIControl sendAction:to:forEvent:]
   7 UIKit -[UIApplication sendAction:toTarget:fromSender:forEvent:]
   6 UIKit -[UIApplication sendAction:to:from:forEvent:]
   5 FourGameCenter 0x8d7fa
   4 FourGameCenter 0x71830
   3 FourGameCenter 0x797e6
   2 libobjc.A.dylib _objc_rootAllocWithZone
   1 libobjc.A.dylib class_createInstance
   0 libsystem_c.dylib calloc
4

4 回答 4

2

您不能在 中执行以下操作clearImages

[self setImageArray:nil];
[imageArray removeAllObjects];

在上面的代码段中,您刚刚设置imageArraynil. 然后您不能向nil对象发送removeAllObjects消息:它只会默默地什么都不做。

您需要将行重新排序为:

[imageArray removeAllObjects];
[self setImageArray:nil];
于 2013-05-07T11:20:36.200 回答
1
[self setImageArray:nil]

将自动删除图像对象,因此无需执行 removeObjects。

但是,如果您在其他地方的 UIImageViews 中使用这些图像,并且这些 UIImageViews 在其他地方的视图中保留或使用,您也需要从超级视图中释放这些/删除 UIImageView。

[imageView removeFromSuperview];

或者,如果您在数组中有 UIImageViews:

[imageViewArray makeObjectsPerformSelector:@selector(removeFromSuperview)];
于 2013-05-07T13:29:08.517 回答
0

检查是否在 scheme:diagnostics 中打开了僵尸。尽管 Zombies 在 ARC 下不太可能出现,但该项目可能仍会启用此功能,这使得检查内存泄漏看起来像是一切都在泄漏。

于 2013-05-07T12:57:26.917 回答
0

您在这里混合了隐喻-您使用了一个属性,但将其设置为 ivar-它可能会造成泄漏。此外,如果您释放数组,则不必释放每个对象,因为它会为您执行此操作。

因此,使用 ivar

@MyClass...
{
  NSMutableArray *imageArray;
}

现在您可以将其设置为新数组,并确保释放旧数组。如果要完全释放数组,只需将其设置为 nil。

或者,如果要使用属性,则在更改对象时,请使用:

self.imageArray = ...;

现在,第二个问题 - 您的代码直接访问 imageArray(没有前导“_”) - 您是否使用相同的名称合成了 ivar?这可能不是一个好主意,因为它只会让人们在阅读您的代码时感到困惑。如果您只是删除@synthesize,您现在可以“免费”获得 ivar 作为带有“_”前缀的属性名称。您可以直接访问该 ivar,但任何阅读您的代码的人都会知道它附加到一个属性。

编辑:您显然没有释放您认为的对象。您的问题与此问题非常相似。你需要做的如下:

1)创建UIImage子类,并在dealloc中添加日志语句。您将创建 MyImages(子类)而不是创建 UIImages,这意味着您将需要您的子类 .h 文件在任何您想使用它的地方(请在调试时将它放在 pch 文件中)。首先执行此操作以查看图像是否已发布。如果不是你知道你的问题。

2)子类NSArray(不是NSMutableArray,不是你在上面显示的代码中真的不需要可变数组)。如果有必须使用可变数组的原因,那么在设置 ivar 时,请先使用 [MyArray arrayWithArray:theMutableArray]。记录dealloc。

现在运行你的测试。数组或图像都没有被释放。一旦你知道是哪个,你就可以追踪保留问题。

有句老话,我会杀了它,但它是这样的,当你尝试一切可能导致问题的事情,但并不能解决问题时,你必须假设它是不是实际上的问题。

于 2013-05-07T13:52:40.903 回答