2014-12-10 1 views
1

У меня есть следующие сеттер определены в моем классе, который простирается UICollectionView:Сбой при назначении локального объекта на DataSource из 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 

Я понял, что указатель экземпляра - это адрес локальной переменной, которую я использовал в моем сеттере; имя класса очевидно случайное. Из этого «открытия» я решил, что объект был выпущен после назначения.

Обычно Xcode будет предупреждать меня об этих вопросах, говоря:

Назначения удерживаемого объекта к небезопасной собственности; объект будет выпущен после назначения.

И, конечно же, я вижу, что предупреждение, если я изменить мой код для этого:

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

У меня есть два вопроса:

  1. Почему не Xcode показать предупреждение?
  2. Почему .dataSource считается небезопасным владельцем? Он определен как (nonatomic, assign).

ответ

1

1) Почему Xcode не показывает предупреждение?

Поскольку clang недостаточно интеллектуальна, чтобы понять, что ваш экземпляр источника данных не будет сохранен в другом месте; только этот очевидный случай будет сообщен:

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

2) Почему .dataSource считается небезопасной недвижимостью? Он определяется как (неатомный, назначать).

Это делается для предотвращения удержания циклов с самореляционными конструкциями, что довольно часто происходит в коде ViewController.

Представьте, что ваш CollectionViewController является DataSource из CollectionView,

self.collectionView.dataSource = self; 

Это означает:

  • CollectionViewController сохраняет .collectionView, поскольку View контроллеры сохраняют свои мнения по умолчанию.
  • CollectionView сохраняет этот источник данных (это CollectionViewController).

Это приведет к циклу удержания, и поэтому Apple решила использовать небезопасный неуправляемый указатель для .datasource.

Обратите внимание, что оба указателя assign и weak не сохраняют объект, который они указывают. Разница между ними заключается в том, что weak автоматически сбрасывается, когда ссылочный объект освобождается.

Но указатель assign не будет аннулирован, поэтому он будет продолжать указывать на адрес памяти. Дальнейшее разыменование этого указателя (после освобождения), вероятно, вызовет EXC_BAD_ACCESS, или вы получите другой объект (поскольку другой объект может быть записан на этом адресе после освобождения).

+0

Хмм, я не использую 'CollectionViewController' .. поэтому не уверен, как это применимо. –

+0

Вы используете архитектуру MVC? – l0gg3r

+0

Код, который я показал, касается только вещей, связанных с 'UICollectionView'; как таковой, он устанавливает себя как делегат источника данных для украшения ячеек. –

Смежные вопросы