ios

Материалы по платформе iOS.

View on GitHub

Back

UICollectionView

UICollectionView используется для отображения каких-либо данных, как и UITableView. Однако отличии от UITableView вы можете расположить ячейки как угодно благодаря гибкой системе расположения элементов. Обычно UICollectionView представляет собой некую таблицу, где элементы располагаются в несколько столбцов или строк. Примерами использования являются стандартные приложения Photos или AppStore. Основные преимущества UICollectionView:

UICollectionView elements

В отличии от знакомого нам UITableView, UICollectionView не содержит header и footer. Вместо него используется Supplementary Views.

Key UICollectionView Concepts


Cell and View Reuse

Подобно UITableView, в UICollectionView используется механизм переиспользования ячеек и SupplimentaryView без их дополнительной аллокации. Представим, что у нас есть набор данных, который в данный момент отображен на экране, и есть какие-то ячейки для этих данных. Когда эти ячейки уходят с экрана, они не деинициализируются, а попадают в т.н. “очередь переиспользования” (Reuse queue). Когда UICollectionView потребуется снова получить объект этого элемента, она не создает его заново, а берет уже проинициализированный из очереди. Этот механизм позволяет UICollectionView работать с большим количеством данных, при этом оперируя небольшим количеством ячеек. Чтобы все работало правильно, необходимо проделать несколько действий: Зарегистрировать ячейку и идентификатором:

- (void)registerClass:forCellWithReuseIdentifier:
- (void)registerNib:forCellWithReuseIdentifier:

- (void)registerClass:forSupplementaryViewOfKind:withReuseIdentifier:
- (void)registerNib:forSupplementaryViewOfKind:withReuseIdentifier:

В DataSource методе cellForItemAtIndexPath: вы не должны создавать новую ячейку, а небходимо взять ее из очереди. Делается это с помощью следующих методов:

- (UICollectionViewCell *)dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionReusableView *)dequeueReusableSupplementaryViewOfKind:withReuseIdentifier:forIndexPath:

Данные методы вернут ячейку из очереди если она там есть, а если в очереди ее нет, то создаст за вас новый объект.

[self.collectionView registerClass:MyCustomCollectionViewCell.class
            forCellWithReuseIdentifier:@"MyCustomCollectionViewCell"];

и берем нашу ячейку из очереди:

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
                  cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    MyCustomCollectionViewCell *cell = [collectionView
                                  dequeueReusableCellWithReuseIdentifier:@"MyCollectionViewCellIdentifier"
                                  forIndexPath:indexPath]; // Configure the cell’s content
    return cell;
}

Supplementary Views Reuse

Анологичным образом и для supplementary view. Регистрируем ячейку:

[self.collectionView registerClass:MyHeaderSupplementaryView.class
            forSupplementaryViewOfKind:UICollectionElementKindSectionHeader,
            withReuseIdentifier:@"MyHeaderViewIdentifier"];

и берем нашу ячейку из очереди:

- (UICollectionReusableView *)collectionView:(UICollectionView *)collectionView
           viewForSupplementaryElementOfKind:(NSString *)kind
                                 atIndexPath:(NSIndexPath *)indexPath {
    MyHeaderSupplementaryView *view = [collectionView 
dequeueReusableSupplementaryViewOfKind:UICollectionElementKindSectionHeader
                                          withReuseIdentifier:@"MyCollectionViewCellIdentifier"
                                                    forIndexPath:indexPath];
    // Configure the view
    return view;
}

Однако, как можно заметить, для метода supplementary view есть параметр OfKind. Это тип, и каждый тип представлен произвольной строкой. Туда можно добавить любую строку для того, чтобы идентифицировать типы ваших supplementary view. В стандартном SDK преопределены два типа, это UICollectionElementKindSectionHeader и UICollectionElementKindSectionFooter.


UICollectionViewDelegate

Основное назначение, для которого используется UICollectionViewDelegate:

Interacting with Content

У каждой ячейки есть свойство isSelected и isHighlighted Когда мы нажимаем по ячейке, первым вызывается метод делегата:

UICollectionViewCell

Базовый класс для ячейки в UICollectionView наследуется от UICollectionViewReusableCell. Некоторые нюансы по работе с UICollectionViewCell:


UICollectionViewLayout

Абстрактный базовый класс для создания правил позиционирования и размеров элементов в UICollectionView. UICollectionViewLayout вычисляет атрибуты позиционирования для: Ячеек(Cells), Supplementary views, Decoration views. Так как это абстрактный класс, для того чтобы начать им пользоваться, необходимо создать наследника этого класса.

UICollectionViewLayoutAttributes

Атрибуты позиционирования включают в себя:

UICollectionViewFlowLayout

Чтобы облегчить жизнь UIKit имеет “стандартную” реализацию UICollectionViewLayout - UICollectionViewFlowLayout. Это уже рабочий сабкласс UICollectionViewLayout который позволяет вам быстро начать использовать UICollectionView. Некоторые свойства:

Customization

Все эти свойства могут быть установлены как напрямую через свойства, так и используя UICollectionViewDelegateFlowLayout. Это делегат UICollectionViewFlowLayout, где можно определить методы, в которых можно возвращать конкретные значения.

@property (nonatomic) CGSize itemSize;
layout.itemSize = CGSizeMake(30, 20);

Если мы хотим, чтобы каждый элемент имел отличный размер, нам нужно реализовать метод делегата: collectionView:layout:sizeForItemAtIndexPath: В котором мы возвращает размер для конкретной ячейки

Расстояние между ячейками и линиями можно установить глобально через свойство:

@property (nonatomic) CGFloat minimumLineSpacing;
@property (nonatomic) CGFloat minimumInteritemSpacing;

или рассчитывать для каждого элемента отдельно используя методы делегата

- (CGFloat)collectionView:layout:minimumLineSpacingForSectionAtIndex:
- (CGFloat)collectionView:layout:minimumInteritemSpacingForSectionAtIndex:

@property (nonatomic) UICollectionViewScrollDirection scrollDirection;

Может иметь два значение: вертикальный - UICollectionViewScrollDirectionVertical, горизонтальный - UICollectionViewScrollDirectionHorizontal

или используя методы делегата для каждого элемента в отдельности:

- (CGSize)collectionView:layout:referenceSizeForHeaderInSection:
- (CGSize)collectionView:layout:referenceSizeForFooterInSection:

Может быть установлен глобально:

@property (nonatomic) UIEdgeInsets sectionInset;

Так и для каждой секции отдельно используя метод делегата:

- (UIEdgeInsets)collectionView:layout:insetForSectionAtIndex:

Custom Layout

Basics to override Чтобы создать свой собственный UICollectionViewLayout, необходимо будет переопределить некоторые методы и свойства, такие как:


Collection View Programming Guide for iOS

Creating custom layout