Статьи

Интерактивный Орни

Это третья часть продолжающейся серии. Вы можете прочитать или просмотреть предыдущие разделы об Основах разработки iOS и приложениях iOS с Tasty UI . В продолжение серии Orny мы собираемся разработать приложение под названием «Orny». Мы на самом деле не объясняли это в прошлой статье, но в двух словах это инструмент, который …

  • Позволяет орнитологам (или потенциальным орнитологам) искать виды птиц
  • Позволяет орнитологам снимать и отслеживать фотографии птиц (и их местоположения)
  • Позволяет обмениваться этими данными с орнитологическим сообществом (и другими)

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

Настройка

На этот раз мы собираемся основываться на предыдущем проекте. Вы можете получить исходный текст, который я использую в качестве отправной точки для этого урока, из Github BuildMobile Project Orny . Исходный код приложения в том виде, в каком он существует в конце этого руководства, будет в свое время доступен в отдельной ветке. Загрузите архив, распакуйте его и откройте в Xcode.

Ложь детям

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

UITableView состоит из UITableViewCells. Код в его нынешнем виде просто создает ячейку для каждой записи в таблице. Постоянно создавать ячейки немного неэффективно. Apple дает нам довольно простой способ повторного использования существующих ячеек после их прокрутки за пределами экрана (предотвращая более широкое использование восхитительной, драгоценной памяти).

В BirdListViewController.m найдите метод tableView:(UITableView*)table cellForRowAtIndexPath и измените его так, чтобы он выглядел следующим образом:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *newCell; if((newCell = [tableView dequeueReusableCellWithIdentifier:@"birdList"]) == nil) { newCell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier:@"birdList"] autorelease]; } NSDictionary *thisBird = [birds objectAtIndex:[indexPath row]]; UILabel *newCellLabel = [newCell textLabel]; [newCellLabel setText:[thisBird objectForKey:@"name"]]; return newCell; } 

Ключевым моментом здесь является использование dequeueReusableCellWithIdentifier для получения любых «запасных» ячеек. Если ячейка находится за пределами экрана и не отображается, мы получаем указатель на нее и «редактируем» ее, чтобы она была той, которую мы хотим. Если ни один из них не является резервным, этот метод возвращает nil, и мы создаем совершенно новую ячейку.

Чтобы это работало, все ячейки в данной таблице должны использовать один и тот же идентификатор (следовательно, использование @"birdList" в [[UITableViewCell alloc] initWithStyle] ). Имейте это в виду для любого использования этой техники в будущем. Намного лучше!

Создание кликабельных строк

Теперь мы хотим сделать наши строки таблицы кликабельными. При щелчке мы покажем пользователю изображение выбранной птицы (с небольшим текстом атрибуции, объясняющим, откуда пришло изображение).

Для этого нам нужно, чтобы наш BirdListViewController соответствовал части протокола UITableViewDelegate . Для этого измените BirdListViewController.h :

 @interface BirdListViewController : UIViewController <UITableViewDataSource, UITableViewDelegate> { } 

Мы хотим реализовать только один конкретный метод для BirdListViewControllertableView:didSelectRowAtIndexPath . Добавьте следующее в BirdListViewController.m :

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; NSDictionary *thisBird = [birds objectAtIndex:[indexPath row]]; NSString *message = [NSString stringWithFormat:@"You clicked: %@", [thisBird objectForKey:@"name"]]; UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:@"You clicked a bird!" message:message delegate:self cancelButtonTitle:@"Neat!"otherButtonTitles:nil] autorelease]; [alert dismissWithClickedButtonIndex:0 animated:TRUE]; [alert show]; } 

У нас есть метод на месте — теперь нам нужно подключить наш UITableView для использования нашего контроллера в качестве делегата. Откройте BirdListViewController.xib и щелкните правой кнопкой мыши UITableView.

Интерактивная Орни Рисунок 1

фигура 1

Перетащите курсор из круга справа от слова «делегат» в поле «Владелец файла» слева.

Интерактивная Орни Рисунок 2

фигура 2

Yippee-kai-ay: Сборка и запуск, и вы должны увидеть всплывающее предупреждение при нажатии на ячейку таблицы.

Создание нашего просмотра изображений

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

Для этого мы будем использовать UINavigationController, но сначала давайте создадим представление отображения изображений. Я собираюсь немного затмить шаги здесь, потому что мы создали новые UIViewControllers и XIB файлы несколько раз прежде. Начать с:

  1. Добавьте новый подкласс BirdListDetailViewController с именем BirdListDetailViewController с помощью файла XIB.
  2. Отредактируйте файл XIB и перетащите UIImageView в представление

Когда вы перетаскиваете изображение и удерживаете его там какое-то время, вы должны найти, что оно изменяет размеры, чтобы занять все пространство вида. Ухоженная!

IBOutlet, ты будешь Inlet?

Теперь мы хотим подключить наш BirdListDetailViewController к UIImageView в файле XIB. Нам нужно создать «дескриптор» для UIImageView в контроллере и присоединить UIImageView к контроллеру в файле XIB.

Мы делаем это, создавая свойство на контроллере, называемое IBOutlet (Outlet Builder Outlet).
Сделайте так, чтобы BirdListDetailViewController.h выглядел следующим образом:

 @interface BirdListDetailViewController : UIViewController { IBOutlet UIImageView *imageView; } @property (nonatomic, assign) IBOutlet UIImageView *imageView; @end 

Мы объявили свойство, поэтому нам нужно @synthesize его — верху BirdListViewController.m понадобится что-то вроде этого:

 @implementation BirdListDetailViewController @synthesize imageView; 

Переключитесь на XIB и щелкните правой кнопкой мыши свой UIImageView. Вы должны увидеть обычное меню правой кнопки мыши; перетащите линию от «Новый источник ссылок» к значку «Владелец файла» слева.

Интерактивная Орни Рисунок 3

Рисунок 3

Теперь ваш контроллер знает о существовании UIImageView в вашем представлении (файл XIB). Вам не нужно делать это для каждого элемента — только для тех, с которыми вы хотите взаимодействовать во время выполнения.

Получить некоторые изображения

Нам нужны некоторые изображения наших птиц, если мы хотим показать их пользователю. К счастью для вас, я нашел несколько, которые мы можем использовать:

На момент написания статьи оба изображения были выпущены под лицензией Creative Commons. В случае с изображением Rosella от пользователя Flickr, изображение лицензировано по лицензии Creative Commons Attribution No Derivatives (CC-BY-ND) — мы можем использовать ее, если мы признаем автора и не изменить изображение.

В случае изображения «Сорока», созданного пользователем Teknorat от Flick, лицензия — Creative Commons Attribution Share Alike (CC-BY-SA) — мы можем использовать изображение, пока мы приписываем автора, и делиться любыми производными его работы, которые мы делаем. по той же лицензии.

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

В любом случае загрузите копии этих изображений и сохраните их там, где вы их запомните (обычно это папка «Загрузки»). Удостоверьтесь, что вы называете их в здравом смысле (например, rosella.jpg и magpie.jpg ) и обратите внимание на нижний регистр! Щелкните правой кнопкой мыши по вашему проекту и выберите «Добавить файлы в« Orny »»

Интерактивная Орни Рисунок 4

Рисунок 4

Выберите файлы, убедитесь, что установлен флажок «Копировать объекты в папку целевой группы (при необходимости)», и нажмите «Добавить». Если это не так, перетащите изображения в «Вспомогательные файлы». Это не существенный шаг, но хорошо держать вещи организованными. Нам понадобятся эти изображения через мгновение.

Назад и вперед с UINavigationController

Мы будем использовать UINavigationController, чтобы помещать представления в стек, отображать их пользователю и управлять переходами (с помощью кнопок) на главный экран.

Это означает, что нам нужно перемонтировать наши MainWindow_iPhone.xib и MainWindow_iPad.xib . Оба этих файла содержат окно и вид, причем вид установлен как RootViewController для окна.

Зайдите в каждый файл и удалите объект View (вы можете выбрать его слева, затем нажать «Delete», чтобы удалить его). Найдите контроллер навигации на панели объектов и перетащите его в файл XIB.

Интерактивная Орни Рисунок 5

Рисунок 5

Щелкните правой кнопкой мыши объект «Окно» и перетащите линию от «RootViewController» к объекту «Navigation Controller» на левой панели значков (или «Navigation Controller» в представлении редактирования).

Наконец, выберите представление «Свойства» и измените «Пользовательский класс» контроллера навигации на BirdListViewContoller .

Теперь, когда ваше приложение запускается, представление нашего BirdListViewController будет помещено в UINavigationController по умолчанию.

Загрузка изображения

Ранее мы написали функцию для обработки случая, когда пользователь нажимает на строку таблицы. Мы хотим переписать эту функцию, чтобы вместо этого инициализировать BirdListDetailViewController, сообщить ему, какое изображение загрузить, и вставить его в UINavigationController. Это представит его пользователю, с кнопкой «назад», чтобы вернуться на наш главный экран.

Тем не менее, мы должны быть внимательны к порядку, в котором эти операции происходят, и к тому, как мы их обрабатываем. BirdListDetailViewController будет инициализирован первым, но его представление не будет «пробуждено» из его файла XIB (или, на более старом языке, NIB), пока UINavigationController не поместит представление в поле зрения пользователя.

Это означает, что мы не можем установить изображение в UIImageView внутри BirdListDetailViewController напрямую — вместо этого мы передадим имя файла и заставим BirdListDetailViewController загрузить его, когда его представление оживет. Сначала мы добавим свойство ‘filename’ в BirdListDetailViewController.h :

 @interface BirdListDetailViewController : UIViewController { IBOutlet UIImageView *imageView; NSString *filename; } @property (nonatomic, assign) IBOutlet UIImageView *imageView; @property (nonatomic, retain) NSString *filename; @end 

Помните, опять же, что нам нужно @synthesize в BirdListViewController.m :

 @implementation BirdListDetailViewController @synthesize imageView, filename; ... 

Далее мы хотим, чтобы BirdListViewController загружал этот файл в представление изображения при его загрузке. Помня о том, что мы достигли выше, сделайте viewDidLoad в BirdListViewController.m следующим образом:

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view from its nib. UIImage *image = [UIImage imageWithContentsOfFile: [[NSBundle mainBundle] pathForResource:self.filename ofType:@"jpg"]]; [self.imageView setImage:image]; } 

Толкая и скользя и скользя

Это измученная ссылка Теофилуса Тистлера. Посмотри на YouTube.

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

Измените tableView:didSelectRowAtIndexPath в BirdListViewController.m чтобы он BirdListViewController.m следующим образом:

 - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:NO]; NSDictionary *thisBird = [birds objectAtIndex:[indexPath row]]; BirdListDetailViewController *detail = [[BirdListDetailViewController alloc] initWithNibName:@"BirdListDetailViewController" bundle:[NSBundle mainBundle]]; detail.filename = [thisBird objectForKey:@"image"]; [[self navigationController] pushViewController:detail animated:YES]; [detail release]; } 

В итоге, эта функция:

  • Получает соответствующий элемент словаря для выбранной строки
  • Создает экземпляр BirdListDetailViewController
  • Сообщает BirdListDetailViewController, какое имя файла мы хотим загрузить, и
  • Вставляет BirdListDetailViewController в UINavigationController

Имена файлов

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

Из-за способа, которым мы pathForResource в методе loadView , мы на самом деле этого не хотим. Итак, отредактируйте loadBirdData в BirdListViewController.m таким образом:

 -(void)loadBirdData { birds = [[NSMutableArray alloc] init]; // Add a Magpie to our bird array [birds addObject: [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:@"Magpie", @"magpie", @"Black and white and crafty all over!", nil] forKeys:[NSArray arrayWithObjects:@"name", @"image", @"description", nil] ] ]; // And another! [birds addObject: [NSDictionary dictionaryWithObjects: [NSArray arrayWithObjects:@"Rosella", @"rosella", @"A red and blue parrot", nil] forKeys:[NSArray arrayWithObjects:@"name", @"image", @"description", nil] ] ]; } 

Если вы нажмете Run, вы должны увидеть изображения, когда нажимаете на названия птиц.

Режим соревнования!

На этой неделе я оставлю вас с несколькими проблемами.

  • Как вы можете изменить название контроллера корневого представления с «Root View Controller»?
  • Как вы можете изменить кнопку «Назад» на BirdListDetailViewController?
  • Как бы вы изменили проект для работы с разными форматами файлов?
  • Какие методы мы можем использовать, чтобы добавить больше видов птиц в нашу таблицу, не указывая их вручную в loadBirdData?

Заключение и дальнейшее чтение

Мы сделали наше приложение значительно более интерактивным, и теперь пользователи могут видеть изображения некоторых видов птиц, которые мы перечисляем. В следующий раз мы расширим приложение, извлекая данные о видах птиц из базы данных CoreData!

Серия «Орни»

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