iSnap Toki Tori - ципа, ципа, ципа, ципа
Май 25

В этой статье, продолжающей тему урока “Hello World”, мы рассмотрим работу с табличным представлением “Table View”, аналогичным используемому в приложении IPod для вывода списков воспроизведения.

Шаг 1. Прочтите урок “Hello World”.

Незнакомым с программированием на Objective C и IPhone SDK предлагаю начать с урока Hello World.

Шаг 2. Создайте проект.

newproj
Командой “SelectFile > New Project” или комбинацией клавиш <Apple + Shft + N> вызовите меню нового проекта. В разделе “IPhone OS” из меню слева выберите опцию “Applications“, а среди пиктограмм справа найдите “View Based Application“. Введите имя проекта (в исходном коде я использовал “TableView“).

Теперь в пакете “Classes” четыре файла:

  • TableViewTutorialAppDelegate.h
  • TableViewTutorialAppDelegate.m
  • TableViewTutorialViewController.h
  • TableViewTutorialViewController.m

Шаг 2. Создаем класс контроллеров данных.

picture-1-11

Помимо созданных автоматически четырех файлов нужно добавить новый класс (с соответствующими исходным и заголовочным файлами), где будут храниться отображаемые в представлении данные. Выполните “File > New File” или воспользуйтесь комбинацией клавиш <Command + N>, открыв диалоговое окно “New File“. Создайте новый исходный файл типа “NSObject Subclass” (у меня это “DataController.m“). Обязательно проверьте, чтобы был установлен флажок “Also create “DataController.h“”. (Имя зависит от имени исходного файла).

picture-32

В файл “DataController.h” добавьте экземпляр “NSMutableArray” для хранения реальных данных и вспомогательные методы, возвращающие размер массива, элемент для конкретного индекса, добавляющие и удаляющие объекты. Не забудьте о соответствующем списку свойстве для доступа. Законченный файл примет примерно такой вид:

1
2
3
4
5
6
7
8
9
10
11
#import &lt;UIKit/UIKit.h&gt;
@interface DataController : NSObject
{
NSMutableArray *list;
}
- (unsigned)countOfList; //возвращает количество элементов в спике
- (id)objectInListAtIndex:(unsigned)theIndex; //возвращает объект для данного индекса
- (void)addData:(NSString*)data; //добавляет данные к списку
- (void)removeDataAtIndex:(unsigned)theIndex;
@property (nonatomic, copy, readwrite) NSMutableArray *list;
@end

Шаг 2b. Внедряем методы Data Controller.

Для начала синтезируйте getter’ы и setter’ы, добавив “@synthesize” после строки 11 в файле “DataController.m“. Теперь внедряйте методы, описанные в заголовочном файле.
Метод: “countOfList”

Простейший метод подсчета списка. Запрашиваете метод подсчета в свойстве списка, возвращается результат.

1
2
3
4
- (unsigned)countOfList
{
return [list count];
}

Метод: objectInListAtIndex
Следующий, не менее простой шаг — возвращение элемента для конкретного индекса списка. Обращаетесь к методу списка “objectInListAtIndex“, и возвращается результат:

1
2
3
4
- (id)objectInListAtIndex:(unsigned)theIndex
{
return [list objectAtIndex:theIndex];
}

Метод: removeDataAtIndex
Просто добавьте запрос к структуре списка:

1
2
3
4
- (void)removeDataAtIndex:(unsigned)theIndex
{
[list    removeObjectAtIndex:theIndex];
}

Метод: addData
Сейчас для хранения данных я использую “NSString“, но, возможно, в реальной программе вы решите создать объект предметной области.

1
2
3
4
- (void)addData:(NSString*)data;
{
[list addObject:data];
}

Метод: setList
Мы также отменим метод “set list“, чтобы убедиться, что непостоянный массив остается непостоянным.

1
2
3
4
5
6
7
8
9
//Отдельно заданное средство доступа гарантирует, что новый список останется непостоянным
- (void)setList:(NSMutableArray *)newList
{
if (list != newList)
{
[list release];
list = [newList mutableCopy];
}
}

Метод: Init and dealloc
Использовался для инициализации объектов и свободной памяти, соответственно:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
- (id)init
{
if (self = [super init])
{
//Список с приписываемыми значениями
NSMutableArray *localList = [[NSMutableArray alloc] init];
self.list = localList;
[localList release];
9
//Добавляем начальные данные
[self addData:@"Item 1"];
[self addData:@"Item 2"];
}
return self;
}

- (void)dealloc
{
[list release];
[super dealloc];
}

Шаг 3. Обновление контроллера табличного представления.

Сейчас контроллер “TableViewTutorialViewController” наследует класс “UIViewController“, который необходимо заменить на “UITableViewController“. Еще одна задача — добавить класс контроллера данных для получения данных, отображаемых в строках табличного представления. Для этой цели добавим к заголовочному файлу контроллера представления описатель “@class“, создадим экземпляр данного класса и добавим свойство экземпляра. Дополнительно будет создано представление для хранения “tableview” с соответствующим свойством. Код для “TableViewTutorialViewController.h” должен выглядеть примерно так:

1
2
3
4
5
6
7
8
9
10
11
12
#import &lt;UIKit/UIKit.h&gt;

@class DataController;
@interface TableViewTutorialViewController : UITableViewController
{
DataController *dataController;
UIView * myView;
}

@property (nonatomic, retain) DataController *dataController;
@property (nonatomic, retain) UIView * myView;
@end

Шаг 4. Внедряем класс “Table View Controller”.

Код для файла “TableViewTutorialViewController.m” представлен ниже. Я подробнее остановлюсь на отдельных строках и группах строк. В общих словах: обрисовываем интерфейс (”initWithStyle” и “loadView“), связываем его с контроллером (”loadView” строки 24 и 25), а затем внедряем обратные вызовы и обработчики событий (все остальные методы).

1
2
3
4
5
6
7
8
9
//Строка 1 уже должна присутствовать в автоматически созданном файле, но мы добавляем ее, поскольку собираемся задействовать методы
//класса контроллера данных.
#import "TableViewTutorialViewController.h"
#import "DataController.h"

//Строка 3 генерируется автоматически, но мы добавляем строки 4 и 5, создавая getter'ы and setter'ы для соответствующих атрибутов
@implementation TableViewTutorialViewController
@synthesize dataController;
@synthesize myView;

Метод: initWithStyle

1
2
3
4
5
6
7
8
9
10
//Эквивалент конструктора: использовался для инициализации контроллера представления (self) и контроллера данных
- (id)initWithStyle:(UITableViewStyle)style
{
if (self = [super initWithStyle:style])
{
self.dataController = [[DataController alloc] init];
}

return self;
}

Метод: loadView

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Определяем интерфейс и связываем с объектом контроллера, назначая "self" делегатом и источником данных

-(void)loadView
{
// создаем и настраиваем представление
CGRect cgRct = CGRectMake(0, 10, 320, 400); //определяем размер и положение представления
myView = [[UIView alloc] initWithFrame:cgRct]; //инициализируем представление
myView.autoresizesSubviews = YES;              //позволяем менять размер элементов в представлении
self.view = myView;                            //настраиваем свойство представления для контроллера вновь созданного представления
UITableView * tableView = [[UITableView alloc] initWithFrame:cgRct style:UITableViewStylePlain];
tableView.editing = YES//Это позволит пользователю добавлять и удалять элементы из списка
tableView.dataSource = self;
tableView.delegate = self; //делаем текущий объект обработчиком данных для представления
[self.view addSubview:tableView];
}

Метод: numberOfSectionsInTableView

1
2
3
4
5
6
//Внедряем это, так как объект является источником данных для табличного представления
//Жестко запрограммированное количество разделов в таблице 1, так как в примере мы создаем только один список
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}

Метод: numberOfRowsInSection

1
2
3
4
5
6
7
8
//У нас только один раздел с единственным источником данных, поэтому просто возвращаем количество элементов в
//источнике данных. Плюс один объясняется занесением специального элемента в начало списка //, что позволит дополнять его новыми пунктами. Подробнее об этом ниже

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Только один раздел, поэтому возвращаем число элементов в списке
return [dataController countOfList]+1;
}

Метод: cellForRowAtIndexPath

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Обратный вызов от интерфейса при прорисовке табличного представления. Метод создает ячейку для каждой
//строки и добавляет текст, в зависимости от набора символов, полученных от источника данных. Обратите внимание: он запрашивается для каждого
/индекса от нуля до количества строк, возвращаемых предыдущим методом (numberOfRowsInSection). Нулевая
//строка жестко запрограммирована для вывода текста "New Item" — с добавлением новых строк к таблице.

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Пробуем получить многоразовую ячейку
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"CellIdentifier"];
if (cell == nil)
{
//Если такой возможности нет, создаем новую
cell = [[[UITableViewCell alloc] initWithFrame:CGRectMake(0,0,0,0) reuseIdentifier:@"CellIdentifier"]
autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}

// Получаем набор символов для отображения, задаем значение в ячейке
if(indexPath.row == 0)
{
//Первая(или нулевая ячейка) содержит набор символов "New Item" и используется для добавления элементов к списку
cell.text  = @"New Item...";
}
else
{
//Освобождаем текст из источника данных, -1 объясняется тем, что первый элемент жестко запрограммирован на текст"New Item"
cell.text = [dataController objectInListAtIndex:indexPath.row-1];
}
return cell;
}

Метод: editingStyleForRowAtIndexPath

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//Описывает стиль редактирования для каждой строки, например, наличие значка удаления (красный круг со знаком минус) или
//добавления (зеленый круг со знаком плюс). Первую строку я запрограммировал жестко (с текстом "New Item") — в ней выводится знак "плюс". В остальных — знак "минус".

- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:
(NSIndexPath *)indexPath
{
if(indexPath.row == 0)
{
return UITableViewCellEditingStyleInsert;
}
else
{
return UITableViewCellEditingStyleDelete;
}
}

Метод: commitEditingStyle

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
//Метод вызывается по окончании редактирования пользователем одной из строк таблицы. Три соответствующих параметра:
// редактирование таблицы, редактирование стиля строки ("Add" или "Delete"), редактирование
//строки. При удалении стиля мы избавляемся от соответствующего элемента в источнике данных, а потом удаляем строку из
///представления. При добавлении стиля вносим еще один элемент в исходный код и заново загружаем данные в табличное представление.
//В реальности с добавлением элемента, вероятно, должно загружаться новое представление для ввода пользователем текста, но об этом в следующий раз.
//Здесь же мы жестко программируем добавляемый текст.

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Удаленную строку убираем из списка.
if (editingStyle == UITableViewCellEditingStyleDelete)
{
[dataController removeDataAtIndex:indexPath.row-1];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
}
else if(editingStyle == UITableViewCellEditingStyleInsert)
{
[dataController addData:@"New Row Added"];
[tableView reloadData];
}
}

- (void)dealloc
{
[super dealloc];
}
@end

Шаг 5. Загружаем “TableView”.

В методе “applicationDidFinishLaunching” файла “TableViewTutorialAppDelegate.m” инициализируйте контроллер “tableview” и добавьте его в качестве подпредставления. Код будет выглядеть примерно так:

1
2
3
4
5
6
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
viewController = [[TableViewTutorialViewController alloc] initWithStyle:UITableViewStylePlain];
[window addSubview:viewController.view];
[window makeKeyAndVisible];
}

picture-14

Шаг 6. Опробуйте интерфейс в действии.

После запуска кода должен появиться вот такой интерфейс. По щелчку на красном значке удаления отображается соответствующая кнопка.

picture-22

Щелчок на ней удаляет из таблицы строку.

picture-3-1

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

Надеюсь, урок был полезен.Спасибо и удачи.

Исходный код скачать можно [здесь]

Текст оригинальной статьи на английском языке [здесь]

Уважаемые читатели, данный материал был переведен и подготовлен к публикации проектом LookApp.ru, при публикации на другом сайте ссылка на LookApp.ru обязательна.

1 звезда2 звезд3 звезд4 звезд5 звезд (5 голосов, средний: 4.40 из 5)
Загрузка ... Загрузка ...


Оставьте комментарий