【问题标题】:viewDidLoad deallocated prematurely in ARC?viewDidLoad 在 ARC 中过早释放?
【发布时间】:2015-08-01 01:07:07
【问题描述】:

我正在编写一个具有NSOutlineView 的应用程序和一个实现NSOutlineViewDataSource 的接口。但是,在运行时,应用程序崩溃并显示一条消息已发送到已释放实例的错误。我对僵尸和仪器进行了一些调试,并找到了被释放的地址。

我不太明白这里发生了什么。我已经确定,如果我为 ViewController.m 禁用 ARC,它不会出现段错误。这是相关代码。

-(void)viewDidLoad {
    [super viewDidLoad];
    NSArray * array = [[NSArray alloc]initWithObjects:@"chrisdotcode",@"Mop",@"ollien", nil];
    [self.namesList setDataSource:[[ArrayOutlineDataSource alloc] init:array]];
}

这里是 ArrayOutlineDataSource,它实现了 NSOutlineViewDataSource。

@implementation ArrayOutlineDataSource
    -(id)init:(NSArray *)array{
        self.array = array;
        return [super init];
    }
    -(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item{
        return self.array[index];
    }
    -(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item{
        return false;
    }
    -(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item{
        NSLog(@"Item:%@",item);
        NSLog(@"Item count:%lu",(unsigned long)[self.array count]);
        return [self.array count];
    }
    -(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item{
        return self.array;
    }



@end

【问题讨论】:

    标签: objective-c macos automatic-ref-counting


    【解决方案1】:

    documentation 说:

    大纲视图不拥有其数据源。同样,它不拥有从数据源获取的对象——如果它们被释放,您的应用程序可能会崩溃,除非您告诉大纲视图重新加载其数据。

    数据源是一个控制器对象,你有责任确保在大纲视图完成之前它不会被释放(通常数据源是一个对象,例如基于文档的应用程序中的文档对象,所以没有额外的工作要做)。反过来,数据源负责保留它提供给大纲视图的所有对象,并在模型发生更改时更新大纲视图。因此,除非您不再在大纲视图中显示它,否则释放根项(或任何子项)是不安全的。

    底线,大纲视图不保持对其数据源的强引用。 (这很常见:通常数据源和委托都是弱引用。)问题中的代码示例没有保留ArrayOutlineDataSource

    创建您自己的属性以保持对此ArrayOutlineDataSource 的强引用:

    @property (nonatomic, strong) ArrayOutlineDataSource *dataSource;
    

    然后:

    - (void)viewDidLoad {
        [super viewDidLoad];
        NSArray * array = [[NSArray alloc]initWithObjects:@"chrisdotcode",@"Mop",@"ollien", nil];
        self.dataSource = [[ArrayOutlineDataSource alloc] init:array];
        [self.namesList setDataSource:self.dataSource];
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-12
      • 1970-01-01
      • 1970-01-01
      • 2012-03-18
      • 1970-01-01
      • 1970-01-01
      • 2017-04-18
      • 1970-01-01
      相关资源
      最近更新 更多