我正在努力了解我的代码中的一些大内存泄漏,所以在简化代码之后剩下的就是:
@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
消息。