CALayer委托导致僵尸崩溃 - 为什么?

时间:2012-05-18 17:15:05

标签: ios uiviewcontroller core-animation

我是Core Animation的新手,在使用委托中的drawLayer方法实现CALayer对象时遇到问题。

我已将问题缩小到一个非常简单的测试。我有一个名为LBViewController的主viewController,它推送一个名为Level2ViewController的辅助viewController。在2级控制器中,在viewWillAppear:中,我用它的delegate = self(即2级控制器)创建了一个CALayer对象。我是否真的实现了drawLayer:inContext:方法我有同样的问题 - 当我返回主viewController时,我得到一个僵尸崩溃。在分析器中,似乎有问题的对象是第2级viewController对象 - 在弹出后会被释放。

我尝试使用子类CALayer对象而不是委托,它工作正常。如果我注释掉委托分配它也运行正常。我想了解为什么代表团造成了这个问题。非常感谢任何建议。

这是我的代码---

Level2ViewController

@implementation Level2ViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewDidAppear:animated];
    CALayer *box1 = [[CALayer alloc] init];
    box1.delegate = self;   // problem disappears if I comment out this assignment
    box1.backgroundColor = [UIColor redColor].CGColor;
    box1.frame = CGRectMake(10,10,200,300);
    [self.view.layer addSublayer:box1];
    [box1 setNeedsDisplay];

}

// makes no difference whether or not this method is defined as long
// as box1.delegate == self
- (void)drawLayer:(CALayer *)theLayer inContext:(CGContextRef)theContext
{
    CGContextSaveGState(theContext);
    CGContextSetStrokeColorWithColor(theContext, [UIColor blackColor].CGColor);
    CGContextSetLineWidth(theContext, 3);
    CGContextAddRect(theContext, CGRectMake(5, 5, 40, 40));
    CGContextStrokePath(theContext);
    CGContextRestoreGState(theContext);
}

- (void)viewDidUnload
{
    [super viewDidUnload];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

推动二级视图控制器的 LBViewController (主控制器)中的方法

- (IBAction)testAction:(id)sender {
    Level2ViewController *controller = [[Level2ViewController alloc]   
                                  initWithNibName:@"Level2ViewController" bundle:nil];
    controller.title = @"Level2";

    // this push statement is where the profiler tells me the messaged zombie has been malloc'ed
    [self.navigationController pushViewController:controller animated:YES];
    [controller release];
}

1 个答案:

答案 0 :(得分:2)

您可能希望在释放委托对象之前将图层的委托设置为nil。所以在Leve2ViewController执行此操作:

-(void)viewWillDisappear:(BOOL)animated
{
    if (box1) {
        box1.delegate = nil;
    }
    box1 = nil;
}

显然这需要将box1变成一个字段(因此可以在viewWillDisappear:中访问)

由于您在box1中创建viewWillAppear:,因此上述代码使用viewWillDisappear:。最近,当我遇到类似的问题时,我有一个单独的委托对象,其中我使用了initdealloc

注意:您在[super viewDidAppear:animated];中致电viewWillAppear。看起来像拼写错误或复制/粘贴故障: - )