Проблема памяти / перевыпуск с навигационным контроллером и представлением, содержащим sub CALayer - PullRequest
4 голосов
/ 21 февраля 2011

Я не смог решить эту проблему в выходные ... Я думал, что у меня есть хорошие знания в управлении памятью Objective-C, но это очень трудно решить.

Подводя итогконтекст: у меня есть sulaslassed UIViewController, который я нажимаю в моем навигационном контроллере.Этот UIViewController содержит UIScrollView (созданный в IB).В функции viewDidLoad () UIViewController я добавляю фоновый PDF (в CATiledLayer подслоя слоя UIview ).

Проблема заключается в том, что при извлечении 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];".Если субслой не добавлен, UIViewController не перевыпускается.

Я нажимаю свой ViewController следующим образом:

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

Мне интересно, что я делаю неправильно.Я уверен, что уважаю руководство по управлению памятью.Я думаю, что проблема исходит от CALayer.Я попытался использовать PDF-файл в CALayer и без него, но он ничего не меняет ...

Но как бы я его ни кодировал, это всегда приводит к: ** - [PlanViewController isKindOfClass:]: сообщение отправленоосвобожденный экземпляр 0xc641750 **

Инструменты Зомби показывают мне перевыпуск на:

88 PlanViewController Zombie -1 6909541120 0x64a6a00 0 UIKit - [UIView (Иерархия) _makeSubtreePerformSelector: withObject:1027 *

У вас есть подсказка?

Большое спасибо за вашу помощь

1 Ответ

5 голосов
/ 21 февраля 2011

решено !!! Может быть, это может помочь:

Фактически, асинхронные перерисовки вызываются CATiledLayer. При выпуске UIViewController вы должны сказать CATiledLayer, что его делегат больше не жив. Я добавил ссылку (назначить) в мой CATiledLayer и в своей функции dealloc я делаю:

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

Надеюсь, вы не потеряете столько времени, сколько я потерял ...

...