Обсуждение

Обсуждение

Процесс перемещения разделов и ячеек таблицы отличается от их замены. Рассмотрим пример, помогающий лучше понять эту разницу. Допустим, у нас есть табличный вид с тремя разделами, A, B и C. Если передвинуть раздел A к разделу C, то табличный вид заметит это и переместит раздел B туда, где до этого находился раздел A. Но если раздел B будет перемещен на место раздела C, то табличному виду вообще не придется перемещать раздел A, так как он находится «выше» двух перемещаемых разделов и не участвует в передвижениях B и C. В данном случае раздел B попадет на место раздела C, а раздел C — на место раздела B. Такая же логика применяется в табличных видах при перемещении ячеек.

Для демонстрации таких взаимодействий создадим табличный вид и загрузим в него три раздела, в каждом из которых есть три собственные ячейки. Начнем с файла реализации контроллера вида:

#import «ViewController.h»

static NSString *CellIdentifier = @"CellIdentifier";

@interface ViewController () <UITableViewDelegate, UITableViewDataSource>

@property (nonatomic, strong) UITableView *myTableView;

@property (nonatomic, strong) NSMutableArray *arrayOfSections;

@end

Контроллер вида становится источником данных для табличного вида. В табличном виде есть разделы, а в каждом разделе — ячейки. Мы, в сущности, работаем с массивом массивов: массив первого порядка содержит разделы, а каждый раздел, в свою очередь, является массивом, содержащим ячейки. Отвечать за этот функционал будет элемент arrayOfSections, определяемый в заголовочном файле контроллера вида. Итак, заполним этот массив:

— (NSMutableArray *) newSectionWithIndex:(NSUInteger)paramIndex

withCellCount:(NSUInteger)paramCellCount{

NSMutableArray *result = [[NSMutableArray alloc] init];

NSUInteger counter = 0;

for (counter = 0;

counter < paramCellCount;

counter++){

[result addObject: [[NSString alloc] initWithFormat:@"Section %lu

Cell %lu",

(unsigned long)paramIndex,

(unsigned long)counter+1]];

}

return result;

}

— (NSMutableArray *) arrayOfSections{

if (_arrayOfSections == nil){

NSMutableArray *section1 = [self newSectionWithIndex:1

cellCount:3];

NSMutableArray *section2 = [self newSectionWithIndex:2

cellCount:3];

NSMutableArray *section3 = [self newSectionWithIndex:3

cellCount:3];

_arrayOfSections = [[NSMutableArray alloc] initWithArray:@[

section1,

section2,

section3

]

];

}

return _arrayOfSections;

}

Затем мы инстанцируем табличный вид и реализуем необходимые методы в протоколе UITableViewDataSource, чтобы заполнить табличный вид данными:

— (NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{

return self.arrayOfSections.count;

}

— (NSInteger) tableView:(UITableView *)tableView

numberOfRowsInSection:(NSInteger)section{

NSMutableArray *sectionArray = self.arrayOfSections[section];

return sectionArray.count;

}

— (UITableViewCell *) tableView:(UITableView *)tableView

cellForRowAtIndexPath:(NSIndexPath *)indexPath{

UITableViewCell *cell = nil;

cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier

forIndexPath: indexPath];

NSMutableArray *sectionArray = self.arrayOfSections[indexPath.section];

cell.textLabel.text = sectionArray[indexPath.row];

return cell;

}

— (void)viewDidLoad{

[super viewDidLoad];

self.myTableView =

[[UITableView alloc] initWithFrame: self.view.bounds

style: UITableViewStyleGrouped];

[self.myTableView registerClass: [UITableViewCell class]

forCellReuseIdentifier: CellIdentifier];

self.myTableView.autoresizingMask =

UIViewAutoresizingFlexibleWidth |

UIViewAutoresizingFlexibleHeight;

self.myTableView.delegate = self;

self.myTableView.dataSource = self;

[self.view addSubview: self.myTableView];

}

Теперь посмотрим, что получается. Сначала проверим, как разделы перемещаются на новое место. Напишем метод, который будет перемещать раздел 1 на место раздела 3:

— (void) moveSection1ToSection3{

NSMutableArray *section1 = [self.arrayOfSections objectAtIndex:0];

[self.arrayOfSections removeObject: section1];

[self.arrayOfSections addObject: section1];

[self.myTableView moveSection:0

toSection:2];

}

Оставляю на ваш выбор окончательное решение о том, как инициировать этот метод, ведь на данный момент у нас в пользовательском интерфейсе нет специальной кнопки для этой цели. Можно просто создать навигационный контроллер и разместить на нем навигационную кнопку, которая и будет запускать данный метод.

Как только вы запустите приложение в обычном режиме, на экране появятся разделы с 1-го по 3-й (рис. 4.12).

Рис. 4.12. Табличный вид с тремя разделами, в каждом из которых находятся по три ячейки

После запуска метода moveSection1ToSection3 вы увидите, что раздел 1 переходит на место раздела 3, раздел 3 переходит на место, ранее занятое разделом 2, и, наконец, раздел 2 перемещается на то место, где раньше находился раздел 1 (рис. 4.13).

Рис. 4.13. Раздел 1 перешел на место раздела 3, после чего последовательно переместились и другие разделы

Перемещение ячеек очень напоминает перемещение разделов. Для этого нужно просто пользоваться методом moveRowAtIndexPath: toIndexPath:. Не забывайте, что ячейка может перемещаться либо в пределах одного раздела, либо из одного раздела в другой. Начнем с простого — переместим ячейку 1 из 1-го раздела на место ячейки 2 того же раздела и посмотрим, что получится:

— (void) moveCell1InSection1ToCell2InSection1{

NSMutableArray *section1 = [self.arrayOfSections objectAtIndex:0];

NSString *cell1InSection1 = [section1 objectAtIndex:0];

[section1 removeObject: cell1InSection1];

[section1 insertObject: cell1InSection1

atIndex:1];

NSIndexPath *sourceIndexPath = [NSIndexPath indexPathForRow:0

inSection:0];

NSIndexPath *destinationIndexPath = [NSIndexPath indexPathForRow:1

inSection:0];

[self.myTableView moveRowAtIndexPath: sourceIndexPath

toIndexPath: destinationIndexPath];

}

Что же происходит в этом коде? Нам нужно гарантировать, что в источнике данных содержится корректная информация, которая отобразится в табличном виде по окончании всех перестановок. Поэтому сначала убираем ячейку 1 в разделе 1. В результате ячейка 2 переходит на место, освобожденное ячейкой 1, а ячейка 3 — на место, ранее занятое ячейкой 2. В массиве остается всего 2 ячейки. Потом мы вставляем ячейку 1 в индекс 1 (второй объект) массива. Таким образом, в массиве будут содержаться ячейка 2, ячейка 1, а потом ячейка 3. И вот теперь мы на самом деле переместили ячейки в табличном виде.

Теперь немного усложним задачу. Попробуем переместить ячейку 2 из раздела 1 на место ячейки 1 из раздела 2:

— (void) moveCell2InSection1ToCell1InSection2{

NSMutableArray *section1 = [self.arrayOfSections objectAtIndex:0];

NSMutableArray *section2 = [self.arrayOfSections objectAtIndex:1];

NSString *cell2InSection1 = [section1 objectAtIndex:1];

[section1 removeObject: cell2InSection1];

[section2 insertObject: cell2InSection1

atIndex:0];

NSIndexPath *sourceIndexPath = [NSIndexPath indexPathForRow:1

inSection:0];

NSIndexPath *destinationIndexPath = [NSIndexPath indexPathForRow:0

inSection:1];

[self.myTableView moveRowAtIndexPath: sourceIndexPath

toIndexPath: destinationIndexPath];

}

Результаты перехода показаны на рис. 4.14.

Рис. 4.14. Ячейка 2 из раздела 1 перемещена на место ячейки 1 из раздела 2

Данный текст является ознакомительным фрагментом.



Поделитесь на страничке

Следующая глава >

Похожие главы из других книг:

Обсуждение

Из книги автора

Обсуждение Обычно после того, как пользователь успешно снимет фотографию на устройство с iOS, он ожидает, что этот снимок сохранится в его библиотеке фотографий. Однако приложения, не входящие в стандартный комплект программ iOS, могут запросить пользователя сделать снимок


Обсуждение

Из книги автора

Обсуждение Фреймворк Assets Library — удобный посредник между разработчиком и библиотекой фотографий. Как будет указано в разделе 13.6, в iOS SDK вам предоставляются встроенные компоненты графического пользовательского интерфейса, которыми можно пользоваться для доступа к


Обсуждение

Из книги автора

Обсуждение Чтобы пользователь мог выбирать фотоснимки или видеоролики из своей библиотеки фотографий, необходимо установить свойство sourceType экземпляра UIImagePickerController в значение UIImagePickerControllerSourceTypePhotoLibrary и только потом открывать перед пользователем инструмент для выбора


Обсуждение

Из книги автора

Обсуждение Библиотека ресурсов подразделяется на группы. В каждой группе содержатся ресурсы, а каждый ресурс имеет свойства, например URL (универсальные локаторы ресурсов) и объекты представления.Все ресурсы всех типов можно получать из библиотеки ресурсов с помощью


Обсуждение

Из книги автора

Обсуждение Класс UIVideoEditorController, содержащийся в iOS SDK, позволяет программисту вывести на экран перед пользователем специальный интерфейс для редактирования. Все, что требуется сделать, — предоставить URL видеоролика, который предполагается отредактировать, а потом


Обсуждение

Из книги автора

Обсуждение В зависимости от того, на работу в какой версии iOS рассчитано ваше приложение, его можно запускать и выполнять на различных устройствах, где установлены разные версии iOS. Например, вы можете разрабатывать приложение в последней версии iOS SDK, но в качестве целевой


Обсуждение

Из книги автора

Обсуждение Когда приложение переходит в фоновый режим, работа его основного потока приостанавливается. Потоки, которые вы создаете в своем приложении с помощью метода класса detachNewThreadSelector: toTarget: withObject:, относящегося к классу NSThread, также приостанавливаются. Если вы


Обсуждение

Из книги автора

Обсуждение Многие приложения, ежедневно поступающие на рынок App Store, обладают возможностями соединения с теми или иными серверами. Некоторые выбирают с сервера данные для обновления, другие отсылают информацию на сервер и т. д. В течение долгого времени в iOS существовал


Обсуждение

Из книги автора

Обсуждение В iOS приложение может запросить продолжить воспроизведение своих аудиофайлов, даже если оно само переходит в фоновый режим. В этом разделе мы воспользуемся плеером AVAudioPlayer, который прост и удобен в обращении. Наша задача — запустить аудиоплеер и воспроизвести


Обсуждение

Из книги автора

Обсуждение Когда приложение работает в приоритетном режиме, можно получать от экземпляра CLLocationManager делегатные сообщения, информирующие вас о том, что iOS обнаружила перемещение устройства на новое место. Однако если приложение переходит в фоновый режим и становится


Обсуждение

Из книги автора

Обсуждение Допустим, пустое приложение iOS (то есть приложение всего с одним окном, для которого еще не написан код) впервые запускается на устройстве с iOS, поддерживающем работу в многозадачном режиме. Оно запускается именно впервые, а не возвращается из фонового режима в


Обсуждение

Из книги автора

Обсуждение При работе с приложениями, которые используют класс NSURLConnection, но, уходя в фоновый режим, не запрашивают у iOS дополнительного времени, обращаться с соединениями не составляет никакого труда. Рассмотрим на примере, как будет действовать асинхронное соединение,


Обсуждение

Из книги автора

Обсуждение Пока ваше приложение работает в фоновом режиме, может произойти многое! Например, пользователь может вдруг изменить локализацию устройства с iOS на странице Settings (Настройки) и задать, к примеру, испанский язык вместо английского. Приложения могут


Обсуждение

Из книги автора

Обсуждение В приложениях, написанных для iOS, файл пакета настроек может быть предоставлен пользователю для внесения собственных настроек. Эти настройки будут доступны пользователю в приложении (Settings) на устройстве. Чтобы лучше понять, как работает этот механизм,


Обсуждение

Из книги автора

Обсуждение Пуш-уведомления похожи на локальные уведомления тем, что позволяют сообщать пользователю определенную информацию, даже если ваше приложение неактивно при поступлении уведомления. В то время как локальные уведомления назначаются самим приложением,