发送到解除分配的实例

时间:2010-03-04 04:59:42

标签: iphone objective-c calayer retain

每当我将一个视图控制器推到我的堆栈上,然后将其弹出,我收到此错误:

*** -[CALayer retainCount]: message sent to deallocated instance <memory address>

似乎恰好在弹出的视图控制器上调用dealloc之后发生,并且仅对此视图控制器是独占的。我确定CALayer与视图本身有关,因为我不使用它们。

有什么想法吗?

编辑: 这是回溯

(gdb) bt
#0  0x01fcd3a7 in ___forwarding___ ()
#1  0x01fa96c2 in __forwarding_prep_0___ ()
#2  0x01fc10e8 in CFGetRetainCount ()
#3  0x01cbc770 in CA::release_root_if_unused ()
#4  0x01cbc707 in x_hash_table_remove_if ()
#5  0x01cbc4ec in CA::Transaction::commit ()
#6  0x01cc4838 in CA::Transaction::observer_callback ()
#7  0x01fa5252 in __CFRunLoopDoObservers ()
#8  0x01fa465f in CFRunLoopRunSpecific ()
#9  0x01fa3c48 in CFRunLoopRunInMode ()
#10 0x027dd615 in GSEventRunModal ()
#11 0x027dd6da in GSEventRun ()
#12 0x0057cfaf in UIApplicationMain ()
#13 0x00002dec in main (argc=1, argv=0xbfffeed0) 

7 个答案:

答案 0 :(得分:12)

我有类似的问题;结果我没有正确地保留UIButton。我是如何找到原因的:   - 启用僵尸   - 使用'Allocations'仪器运行项目   - 使用该应用程序触发错误   - 检查Instruments在时间线上显示消息“Zombie Messaged”   - 应该有一个链接打开CALayer详细信息:分配和解除分配时   - 你对分配的地方感兴趣,应该是啊啊!放在你的代码中

祝你好运!

答案 1 :(得分:7)

这有点棘手,我的是在一个类(m / xib)的dealloc函数中的双重释放,我在tableview中作为行样式。仪器没有对该对象有太多了解,但检查callstack 确实有助于确定哪一个类是-1。

Sample

答案 2 :(得分:4)

我有类似的问题。我的问题是在接口中声明的一个对象变量被错误地声明为(nonatomic, assign)而不是(nonatomic, retain),就像它应该的那样。这导致释放消息被发送到已经具有保留计数0(=崩溃)的对象。

答案 3 :(得分:3)

我遇到了同样的错误,因为我使用buttonWithType(例如[UIButton buttonWithType:UIButtonTypeRoundedRect])创建了UIButton并在之后发布了它。这是错误的,因为buttonWithType已包含autorelease。所以我删除了release,错误消失了。

答案 4 :(得分:1)

追踪哪个视图真有帮助!如果您知道框架以及哪个超级层和子层与该视图相关,那么这可能非常简单......如果您记录所有图层,那么只需搜索并找到相同的内存地址即可。祝好运! :)

将此类别添加到您的应用程序

类别-部首:

#import "CALayer+debug.h"

@interface CALayer (Debug)

-(NSString*)debugDescription;
-(NSString*)debugLayerTree;

@end

类别-实现:

#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import "CALayer+debug.h"
#import <UIKit/UIKit.h>
#import <objc/runtime.h> 
#import <objc/message.h>


@implementation CALayer (Debug)

//....

void Swizzle(Class c, SEL orig, SEL new)
{
    Method origMethod = class_getInstanceMethod(c, orig);
    Method newMethod = class_getInstanceMethod(c, new);
    if(class_addMethod(c, orig, method_getImplementation(newMethod), method_getTypeEncoding(newMethod)))
        class_replaceMethod(c, new, method_getImplementation(origMethod), method_getTypeEncoding(origMethod));
    else
        method_exchangeImplementations(origMethod, newMethod);
}

+ (void)swizzle {
    Swizzle([self class], @selector(init), @selector(newInit));
}

- (id)newInit {
    self = [self newInit];

    [self performSelector:@selector(log) withObject:self afterDelay:0.5];

    return self; // calls old method
} 

- (void)log { 
    NSLog(@"%@", [self debugDescription]);
}

- (NSString *)debugDescription {
    return [NSString stringWithFormat:@"%@ frame=%@ zAnchor=%1.1f, superlayer: %@>", [self description], NSStringFromCGRect(self.frame), self.zPosition, self.superlayer];
}


@end

来自例如的appdelegate

[CALayer swizzle];

答案 5 :(得分:0)

我怀疑它与自动释放池有关......

答案 6 :(得分:0)

我得到了同样的错误。我创建了一个UIView对象来保存两个按钮,然后我将其添加到导航项rightBarButtonItem中。问题是我使用工厂buttonWithType方法创建按钮,但我只是allocinitWithFrame我的视图。然后,在我完成视图后,我发布了它,之后系统试图释放两个按钮(已经发布的UIView的子视图) - 崩溃 - 它正在向已经发送消息释放按钮。希望能帮助别人节省一些类似的麻烦。