【问题标题】:Memory issue / overrelease with navigationcontroller and view containing sub CALayer导航控制器的内存问题/过度释放和包含子 CALayer 的视图
【发布时间】:2011-07-01 04:39:28
【问题描述】:

我在周末没能解决这个问题...我想对 Objective-C 内存管理有很好的了解,但是这个很难解决。

总结上下文:我有一个子类 UIViewController,我将它推入我的导航控制器。这个 UIViewController 包含一个 UIScrollView(在 IB 中创建)。在 UIViewController viewDidLoad() 函数中,我添加了一个背景 PDF(在 UIview 层的 CATiledLayer 子层中)。

问题是当我从导航控制器弹出 UIViewController 时,应用程序崩溃了。

使用 Zombies 工具和 NSZombieLevel 表明这是因为 UIViewController 过度释放

这是 UIViewController :

@interface PlanViewController : UIViewController <UIScrollViewDelegate> {
    UIScrollView *panelScrollView;
    UIView *myContentView;
    CGPDFDocumentRef myDocumentRef;
    CGPDFPageRef myPageRef;
}

@property (nonatomic, retain) IBOutlet UIScrollView *panelScrollView;
@property (nonatomic, retain) UIView *myContentView;

@end

@implementation PlanViewController
@synthesize panelScrollView;
@synthesize myContentView;

- (void)viewDidLoad {
    [self setTitle:@"Plan"];

    myDocumentRef = CGPDFDocumentCreateWithURL((CFURLRef)[[NSBundle mainBundle] URLForResource:@"salonMap" withExtension:@"pdf"]);
    myPageRef = CGPDFDocumentGetPage(myDocumentRef, 1);
    CGRect pageRect = CGRectIntegral(CGPDFPageGetBoxRect(myPageRef, kCGPDFCropBox));

    CATiledLayer *tiledLayer = [[CATiledLayer alloc] init];
    [tiledLayer setDelegate:self];
    [tiledLayer setTileSize:CGSizeMake(1024.0, 1024.0)];
    [tiledLayer setLevelsOfDetail:4];
    [tiledLayer setLevelsOfDetailBias:8];
    [tiledLayer setFrame:pageRect];

    UIView *newView = [[UIView alloc] initWithFrame:pageRect];
    [newView.layer addSublayer:tiledLayer];
    [newView setTag:555];
    [self setMyContentView:newView];
    [newView release];
    [tiledLayer release];

    [panelScrollView setDelegate:self];
    [panelScrollView setContentSize:pageRect.size];
    [panelScrollView setMaximumZoomScale:5];
    [panelScrollView addSubview:myContentView];
    [panelScrollView setClipsToBounds: YES];
    [panelScrollView setMaximumZoomScale:20.0];
    [panelScrollView setMinimumZoomScale:1.0];
    [panelScrollView setZoomScale:1];

    [self initPinsOnMap];
}

- (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx
{
    CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
    CGContextFillRect(ctx, CGContextGetClipBoundingBox(ctx));
    CGContextTranslateCTM(ctx, 0.0, layer.bounds.size.height);
    CGContextScaleCTM(ctx, 1.0, -1.0);
    CGContextConcatCTM(ctx, CGPDFPageGetDrawingTransform(myPageRef, kCGPDFCropBox, layer.bounds, 0, true));
    CGContextDrawPDFPage(ctx, myPageRef);
}

- (void)dealloc {
    [panelScrollView release];
    [myContentView release];
    CGPDFDocumentRelease(myDocumentRef), myDocumentRef = NULL;
    myPageRef = NULL;
    [super dealloc];
}

@end

在玩了几个小时后,我发现只有当我“[newView.layer addSublayer:tiledLayer];”时才会出现过度释放的问题。如果没有添加 subLayer,则 UIViewController 不会被过度释放。

我像这样推送我的 ViewController:

PlanViewController *trailsController = [[PlanViewController alloc] initWithNibName:@"PlanView" bundle:nil ];
[self.navigationController pushViewController:trailsController animated:YES];
[trailsController release];

我想知道我做错了什么。我肯定会尊重内存管理指南。我认为问题来自CALayer。我尝试在 CALayer 中使用和不使用 pdf,但它没有任何改变......

但无论我如何编码,它总是会导致: ** -[PlanViewController isKindOfClass:]:消息发送到已释放实例 0xc641750**

Instruments Zombies 向我展示了一个过度释放:

88 PlanViewController Zombie -1 6909541120 0x64a6a00 0 UIKit -[UIView(Hierarchy) _makeSubtreePerformSelector:withObject:withObject:copySublayers:]

你有提示吗?

非常感谢您的帮助

【问题讨论】:

  • 已解决!!!self.PDFTiledLayer.contents=nil; self.PDFTiledLayer.delegate=nil; [self.PDFTiledLayer removeFromSuperlayer];
  • 嘿 - 不要用答案编辑你的问题 - 实际上在下面的框中回答它;)

标签: iphone cocoa-touch memory-management uinavigationcontroller release-management


【解决方案1】:

解决了!!!也许它可以帮助:

实际上,异步重绘是由 CATiledLayer 调用的。释放 UIViewController 时,您必须对 CATiledLayer 说它的委托不再存在。我在我的 CATiledLayer 和我的 dealloc 函数中添加了一个引用(分配):

self.PDFTiledLayer.contents=nil;
self.PDFTiledLayer.delegate=nil;
[self.PDFTiledLayer removeFromSuperlayer];

我希望你不会失去我失去的那么多时间......

【讨论】:

  • 来法国巴黎吧:)
  • 我今天遇到了完全相同的问题。我独立解决了它,但后来我去寻找一些现有的答案来支持并找到你的。人员:消除您的代理设置如此很重要!这是一个非 ARC 弱引用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-05-07
  • 2018-04-27
  • 2019-08-18
  • 1970-01-01
相关资源
最近更新 更多