CALayer导致ARC内存泄漏

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CALayer导致ARC内存泄漏相关的知识,希望对你有一定的参考价值。

我正在努力了解我的代码中的一些大内存泄漏,所以在简化代码之后剩下的就是:

@interface TestLayer: CALayer
@end
@implementation TestLayer
-(void)dealloc
{
    NSLog(@"dealloc called");
}
@end

@implementation AppDelegate
#define ENABLE_LEAK 1
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    for (int i=0; i<10; i++) {
        @autoreleasepool {
            TestLayer* test = [TestLayer layer];
#if ENABLE_LEAK
            CALayer* l = [CALayer layer];
            [test addSublayer:l];
            [l removeFromSuperlayer];
            l = nil;
#endif
            test = nil;
        }
    }
return YES;
}
.....

如果ENABLE_LEAK设置为0,则TestLayer中的dealloc被正确调用10次。但是如果它在TestLayer中设置为1 dealloc,则在此之前不调用application:didFinishLaunchingWithOptions:return。实际上只是调用[test setNeedsLayout];没有添加任何子图层导致TestLayer泄漏。

我使用类似的代码生成一些离线内容,不会用于最终应用程序,只会使用预生成的离线内容。

有没有人知道什么是引用我的TestLayer,我怎么能说服它发布它?

答案

让我猜一下 - 你的项目中不使用ARC吗?

我已经尝试了几种方法来重现你上面的泄漏声称,但却找不到实现它的方法。

我在你的课程中添加了一个标签:

@interface TestLayer: CALayer
@property (nonatomic, assign) int tag;
@end

@implementation TestLayer
-(void)dealloc
{
    NSLog(@"dealloc called for %d", self.tag);
}
@end

首先,我在同一个地方尝试了你的代码AppDelegate:

for (int i=0; i<10; i++) {
    @autoreleasepool {
        TestLayer* test = [TestLayer layer];
        test.tag = 100;
        CALayer* l = [CALayer layer];
        [test addSublayer:l];
        [l removeFromSuperlayer];
        l = nil;
        test = nil;
    }
}

它每次打印dealloc

然后,在我的第一个视图控制器中,我稍微修改了它:

- (void)viewDidLoad {
    [super viewDidLoad];

    tl = [TestLayer layer]; // its an ivar
    tl.tag = 100;
    for (int i=0; i<10; i++) {
      @autoreleasepool {
        TestLayer *l = [TestLayer layer];
        l.tag = i + 10;
        [tl addSublayer:l];
        [tl removeFromSuperlayer];  // tried this, also tried commenting it out
      }
    }
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 1 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
        NSArray *sl = [self->tl.sublayers copy];
        for (TestLayer *l in sl) {
            [l removeFromSuperlayer];
        }
        self->tl = nil;
    });

}

我可以做的唯一结论是你没有使用ARC,你应该提到它。

PS:如果不使用ARC,我只能假设CALayer layer返回一个保留计数为1的对象,并且它没有自动释放。如果是这样,您需要明确地向它发送release消息。

以上是关于CALayer导致ARC内存泄漏的主要内容,如果未能解决你的问题,请参考以下文章

iOS:内存泄漏代码

在片段中保存活动实例:是否会导致内存泄漏?

使用导致内存泄漏的音频片段

ARC 内存泄漏

ARC CCSprite 内存泄漏

返回参数对象时 ARC 的内存泄漏