将本地对象分配给UICollectionView的dataSource时发生崩溃

时间:2014-12-10 12:13:39

标签: ios objective-c xcode

我在我的课程中定义了以下setter,它扩展了UICollectionView

// @interface ClipsDataSource : NSObject <UICollectionViewDataSource>

- (void)setProject:(Project *)project
{
    _project = project;

    ClipsDataSource *dataSource = [[ClipsDataSource alloc] initWithCollectionView:self];
    dataSource.delegate = self;
    dataSource.fetchedResultsController = project.clipsResultsController;

    self.dataSource = dataSource;
}

当我运行我的应用程序时,我得到以下异常:

-[CALayerArray numberOfSectionsInCollectionView:]: unrecognized selector sent to instance 0x174245490

我意识到实例指针是我在setter中使用的局部变量的地址;班级名称显然是随机的。从这个“发现”我推断该对象在分配后被释放。

通常,Xcode会通过以下方式警告我这些问题:

  

将保留对象分配给不安全的属性;对象将在转让后释放。

当然,如果我将代码更改为此,我会看到警告:

self.dataSource = [[ClipsDataSource alloc] initWithCollectionView:self];

我有两个问题:

  1. Xcode为什么不显示警告?
  2. 为什么.dataSource被认为是不安全的财产?它被定义为(nonatomic, assign)

1 个答案:

答案 0 :(得分:1)

1)为什么Xcode没有显示警告?

因为clang不够智能,无法确定您的数据源实例不会保留在其他位置;只会报告这个明显的案例:

self.dataSource = [[ClipsDataSource alloc] initWithCollectionView:self];

2)为什么.dataSource被认为是不安全的财产?它定义为(非原子,分配)。

这样做是为了防止使用自引用构造的保留周期,这在ViewController代码中经常发生。

想象一下,您的CollectionViewControllerCollectionView的数据源,

self.collectionView.dataSource = self;

这意味着:

  • CollectionViewController保留.collectionView,因为默认情况下,视图控制器会保留其视图。
  • CollectionView保留了它的数据源(CollectionViewController)。

这将导致保留周期,因此Apple决定对.datasource使用不安全的未保留指针。

请注意,assignweak指针都不会保留它们指向的对象。它们之间的区别在于,当引用的对象被释放时,weak将自动无效。

assign指针不会无效,因此它将继续指向内存地址。进一步取消引用该指针(在重新分配之后)可能会导致EXC_BAD_ACCESS,或者您将获得另一个对象(因为在解除分配后可以在该地址中写入另一个对象)。