Статьи

Помимо основ JSONModel

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

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

К концу этой статьи вы создадите браузер Flickr для iOS. Приложение будет общаться с JSON API Flickr и отображать коллекцию фотографий, которые я загрузил в Flickr для этого урока.

Вы узнаете, как:

  • обрабатывать сложные ответы API
  • использовать преобразования данных JSONModel для URL и дат
  • сопоставить ключи JSON со свойствами с разными именами
  • создавать пользовательские преобразования данных
  • ответы API предварительной обработки перед их анализом

Готовый браузер Flickr будет выглядеть так:

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

Откройте проект Xcode и найдите время, чтобы проверить его содержимое. Проект имеет простую настройку, один контроллер табличного представления, показывающий пустое табличное представление. Я также включил в проект две библиотеки, JSONModel и SDWebImage .

Создайте и запустите проект, чтобы убедиться, что проект компилируется без ошибок.

Давайте посмотрим на общедоступную ленту фотографий Flickr . Откройте конечную точку API в своем браузере и найдите время, чтобы проверить ответ. Ответ включает только несколько ключей верхнего уровня, таких как title и modified . Там также есть ключ, называемый items содержащий список фото-объектов, каждый из которых имеет title , link , description и т. Д.

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

Давайте начнем с создания модельного класса для отклика на общедоступные фотографии. Создайте новый класс в Xcode, назовите его PublicPhotosModel и сделайте так, чтобы он наследовал от JSONModel . Вас интересуют title и modified ключи ответа JSON, поэтому добавьте два свойства с одинаковыми именами в интерфейс класса PublicPhotoModel . Вы также получите массив фотографий и сохраните их в свойстве, которое мы назовем items . Установите тип свойства items в NSArray как показано ниже.

01
02
03
04
05
06
07
08
09
10
#import «JSONModel.h»
 
@interface PublicPhotosModel : JSONModel
 
@property (copy, nonatomic) NSString *title;
@property (strong, nonatomic) NSDate *modified;
 
@property (strong, nonatomic) NSArray *items;
 
@end

В этом примере вы используете один из встроенных преобразователей данных JSONModel. Если в вашем ответе JSON есть дата, соответствующая формату W3C , вы можете объявить соответствующее свойство модели типа NSDate и JSONModel будет знать, что делать.

Ваш базовый класс модели для извлечения данных JSON из Flickr API готов. Давайте подключим его к табличному представлению в вашем контроллере представления. В качестве источника данных табличного представления вы будете использовать массив items в объекте модели, представляющий ответ API Flickr.

Примечание: вам может быть интересно, как конвертировать даты, если они не соответствуют стандарту W3C или если ответ JSON включает метки времени. Продолжай читать. Перед окончанием этого урока вы узнаете, как преобразовать любое значение в объект Objective-C.

Начните с открытия ViewController.m и в соответствии с существующим оператором импорта добавьте оператор импорта для только что созданного класса модели:

1
#import «PublicPhotosModel.h»

Затем объявите приватное свойство для хранения экземпляра PublicPhotosModel мы будем использовать:

1
2
3
4
5
@interface ViewController ()
 
@property (strong, nonatomic) PublicPhotosModel *photosModel;
 
@end

Вы получите данные JSON с помощью вспомогательного метода fetchPhotos , который мы вскоре реализуем. Мы вызываем fetchPhotos в методе viewDidLoad контроллера представления:

1
2
3
4
5
6
— (void)viewDidLoad {
    [super viewDidLoad];
     
    // Fetch Photos
    [self fetchPhotos];
}

В fetchPhotos мы используем класс NSURLSession для запроса API Flickr, как вы можете видеть ниже:

1
2
3
4
5
6
7
8
— (void)fetchPhotos {
    NSURL *photosURL = [NSURL URLWithString:@»http://api.flickr.com/services/feeds/photos_public.gne?id=46760712@N07&lang=en-us&format=json&nojsoncallback=1″];
     
    [[[NSURLSession sharedSession] dataTaskWithURL:photosURL completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
        // Process Data
         
    }] resume];
}

Реализация очень похожа на то, что вы написали в предыдущей статье о JSONModel . Сначала вы объявляете photosURL , который содержит URL-адрес определенного канала фотографий на Flickr, а затем создаете и NSURLSessionDataTask экземпляр NSURLSessionDataTask чтобы получить список фотографий этого канала.

Примечание. Если у вас есть учетная запись Flickr и вы знаете свой идентификатор Flickr ID, не стесняйтесь включать его в URL-адрес запроса, чтобы приложение получало ваш собственный канал фотографий.

Если вы читали первую статью о JSONModel , то вы уже знаете, как превратить объект NSData , возвращаемый задачей данных, в объект JSONModel . Flickr, однако, не всегда возвращает правильный ответ JSON. Другими словами, вам необходимо выполнить некоторую предварительную обработку перед созданием объекта модели.

API Flickr имеет специальную функцию, которая экранирует одинарные кавычки в ответе JSON. Проблема состоит в том, что это делает ответ JSON недействительным в соответствии с текущими стандартами, и в результате API-интерфейс NSJSONSerialization не может его обработать.

Чтобы это исправить, вам нужно всего лишь удалить экранированные одинарные кавычки в ответе JSON. Затем вы можете безопасно создать свой модельный объект. Заменить // Process Data следующим фрагментом:

1
2
3
4
5
6
7
8
9
NSString* rawJSON = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
rawJSON = [rawJSON stringByReplacingOccurrencesOfString:@»\\’» withString:@»‘»];
 
self.photosModel = [[PublicPhotosModel alloc] initWithString:rawJSON error:nil];
 
dispatch_async(dispatch_get_main_queue(), ^{
    self.title = self.photosModel.title;
    [self.tableView reloadData];
});

Вы начинаете с создания объекта NSString из экземпляра NSData который вам возвращает задача данных. Можно с уверенностью предположить, что текст в кодировке UTF8, поскольку Flickr использует только UTF8. Затем вы заменяете все вхождения \' на ' чтобы подготовить ответ JSON для JSONModel.

Поскольку у вас уже есть ответ JSON в качестве строкового объекта, вы можете использовать собственный инициализатор JSONModel, initWithString:error: для создания экземпляра модели. Вы используете GCD для обновления пользовательского интерфейса в главном потоке. Заголовок контроллера представления обновляется свойством PublicPhotosModel экземпляра PublicPhotosModel и табличное представление перезагружается.

Создайте и запустите проект, чтобы убедиться, что заголовок установлен, что указывает на правильную инициализацию объекта модели. Дайте приложению время для извлечения данных JSON из Flickr API. Вы должны увидеть заголовок канала в верхней части экрана:

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

1
2
3
4
5
6
NSError *err;
self.photosModel = [[PublicPhotosModel alloc] initWithString:rawJSON error:&err];
 
if (err) {
    NSLog(@»Unable to initialize PublicPhotosModel, %@», err.localizedDescription);
}

Как вы можете видеть, JSONModel использует стандартную парадигму обработки ошибок Какао, что означает, что вы можете проверить, если initWithString:error: выдает ошибку.

На данный момент JSONModel обрабатывает массив элементов как обычный массив, содержащий объекты NSDictionary . Пока это хорошо, но позже мы создадим подходящую фотомодель в этом уроке. Пришло время заполнить табличное представление элементами в массиве.

Давайте начнем с создания пользовательского интерфейса. Сначала вы установите заголовок заголовка раздела табличного представления, в котором будет отображаться дата последнего изменения канала Flickr. Вы можете использовать экземпляр NSDateFormatter чтобы преобразовать объект NSDate в читаемую строку и вернуть его из tableView:titleForHeaderInSection: ::

1
2
3
4
5
6
— (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateStyle = NSDateFormatterMediumStyle;
    formatter.timeStyle = NSDateFormatterMediumStyle;
    return [formatter stringFromDate: self.photosModel.modified];
}

Затем добавьте два обязательных метода протокола источника данных табличного представления, чтобы сообщить табличному представлению, сколько разделов и строк оно содержит. Используйте self.publicPhotos.items качестве источника данных табличного представления:

1
2
3
4
5
6
7
— (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}
 
— (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.photosModel.items.count;
}

Поскольку представление изображений класса UITableViewCell не загружает удаленные изображения асинхронно, вам потребуется пользовательский подкласс UITableViewCell . Создайте новый класс Objective C, назовите его ImageCell и сделайте его подклассом UITableViewCell . Откройте ImageCell.h и добавьте свойство типа UIImageView , webImageView :

1
2
3
4
5
6
7
#import <UIKit/UIKit.h>
 
@interface ImageCell : UITableViewCell
 
@property (strong, nonatomic) UIImageView *webImageView;
 
@end

Откройте ImageCell.m и перезапишите инициализатор Xcode, вставленный для вас. В initWithStyle: вам необходимо скрыть представление изображения по умолчанию и создать новое пользовательское представление изображения. Хотите верьте, хотите нет, но это то, что нужно для асинхронной загрузки изображений в ячейку табличного представления.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
— (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
     
    if (self) {
        self.webImageView = [[UIImageView alloc] initWithFrame: CGRectMake(0.0, 0.0, 40.0, 40.0)];
        [self addSubview: self.webImageView];
         
        UIGraphicsBeginImageContextWithOptions(CGSizeMake(20.0, 20.0), NO, kNilOptions);
        self.imageView.image = UIGraphicsGetImageFromCurrentImageContext();
        UIGraphicsEndImageContext();
    }
     
    return self;
}

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

Пересмотрите ViewController.m и, в соответствии с существующими операторами импорта, добавьте оператор импорта для созданного нами пользовательского класса UITableViewCell .

1
#import «ImageCell.h»

Вы готовы к завершающей части головоломки, методу источника данных для создания ячеек для вашей таблицы:

01
02
03
04
05
06
07
08
09
10
11
12
13
— (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *const cellId = @»ImageCell»;
     
    ImageCell *cell = [self.tableView dequeueReusableCellWithIdentifier: cellId];
     
    if (!cell) {
        cell = [[ImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: cellId];
    }
     
    cell.textLabel.text = [@(indexPath.row) stringValue];
     
    return cell;
}

Создайте и запустите проект еще раз, чтобы увидеть, что таблица теперь отображает одну ячейку для каждого из объектов, найденных в items . Говоря о items , пришло время создать фотомодель.

Как мы видели в предыдущем уроке , вам нужно создать отдельный класс модели для списка объектов в ответе JSON, списка элементов фотографии в нашем примере. Создайте новый класс Objective C, назовите его PhotoModel , сделайте его подклассом JSONModel .

Посмотрите еще раз на необработанный ответ JSON, который вы получаете от Flickr API, и решите, какие ключи должен иметь каждый объект фотографии:

Вы хотите получить заголовок, URL фотографии, когда она была опубликована, и ссылку на страницу с подробностями на Flickr. У нас проблема, хотя. URL фотографии находится в еще одном объекте под media ключом. Означает ли это, что вам нужно создать другой подкласс JSONModel только для извлечения одного ключа m , содержащего URL-адрес фотографии?

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

Начнем с объявления свойств, которые нам нужны в классе PhotoModel :

01
02
03
04
05
06
07
08
09
10
#import «JSONModel.h»
 
@interface PhotoModel : JSONModel
 
@property (copy, nonatomic) NSString *title;
@property (strong, nonatomic) NSURL *url;
@property (strong, nonatomic) NSURL *link;
@property (strong, nonatomic) NSDate *published;
 
@end

Мы используем два встроенных преобразователя данных JSONModel. published тип NSDate а JSONModel обязательно конвертирует дату W3C в объект NSDate . Свойства url и link имеют тип NSURL а JSONModel преобразует соответствующие строки ответа JSON в объекты NSURL .

Откройте PhotoModel.m и добавьте следующий фрагмент кода, чтобы настроить сопоставление клавиш для фотомодели:

1
2
3
4
5
6
+ (JSONKeyMapper*)keyMapper {
    NSDictionary *map = @{ @»published»: @»date»,
                           @»media.m» : @»url» };
     
    return [[JSONKeyMapper alloc] initWithDictionary:map];
}

В keyMapper вы переопределяете метод keyMapper . Он возвращает экземпляр JSONKeyMapper , объект, который сопоставляет ключи JSON с именами свойств. Класс JSONKeyMapper имеет удобный инициализатор, который принимает словарь и создает сопоставление ключей между данными JSON и вашим классом.

В приведенной выше реализации keyMapper вы определяете следующее сопоставление клавиш:

  • published ключ в ответе JSON отображается на свойство date модели.
  • Ключ m объекта media в ответе JSON сопоставляется с url в модели.

С реализованным keyMapper JSONModel может анализировать ответ JSON и инициализировать фотомодель в соответствии с классом PhotoModel .

Прежде чем двигаться дальше, откройте PhotoModel.h еще раз и в верхней части объявите протокол с тем же именем, что и имя класса:

01
02
03
04
05
06
07
08
09
10
11
12
13
#import «JSONModel.h»
 
@protocol PhotoModel
@end
 
@interface PhotoModel : JSONModel
 
@property (copy, nonatomic) NSString *title;
@property (strong, nonatomic) NSURL *url;
@property (strong, nonatomic) NSURL *link;
@property (strong, nonatomic) NSDate *published;
 
@end

Переключитесь на PublicPhotoModel.h и добавьте оператор импорта вверху:

1
#import «PhotoModel.h»

Чтобы все это работало, сделайте свойство PhotoModel протоколу PhotoModel , который мы объявили недавно в классе PhotoModel :

1
@property (strong, nonatomic) NSArray<PhotoModel> *items;

Теперь вам нужно внести пару изменений в ваш класс ViewController . Для загрузки и отображения фотографий в ячейках табличного представления вы будете использовать метод, объявленный в библиотеке SDWebImage , которая была включена в проект, с которого вы начали. Откройте ViewController.m и добавьте новый оператор импорта вверху:

1
#import «UIImageView+WebCache.h»

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

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
— (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *const cellId = @»ImageCell»;
     
    ImageCell *cell = [self.tableView dequeueReusableCellWithIdentifier: cellId];
     
    if (!cell) {
        cell = [[ImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: cellId];
    }
     
    PhotoModel *photo = self.photosModel.items[indexPath.row];
     
    cell.textLabel.text = photo.title;
    [cell.webImageView setImageWithURL:photo.url placeholderImage:nil];
     
    return cell;
}

Сначала вы PhotoModel объект PhotoModel соответствующий строке в табличном представлении, а затем заполняете текстовую метку ячейки заголовком фотографии. Вы используете SDIebImage setImageWithURL:placeholderImage: для асинхронной загрузки и отображения фотографии с заданного URL.

Хотите верьте, хотите нет, у вас уже есть работающий поток фотографий. Создайте и запустите проект, чтобы увидеть результат:

В этом разделе вы создадите пользовательскую функцию для класса PhotoModel , которая преобразует строку из ответа JSON в пользовательский класс Objective-C. Это научит вас, как преобразовывать любые данные JSON в любой класс Objective-C.

В данных JSON для фотографии есть ключ tags который содержит строку тегов. Вы добавите новое свойство в класс PhotoModel . Типом этого свойства будет пользовательский класс Objective C, который может обрабатывать теги.

Примечание. Вы не ограничены в преобразовании данных JSON в пользовательские классы Objective-C. Вы можете конвертировать данные JSON в любой класс Какао. Например, вы можете преобразовать шестнадцатеричный цвет, такой как # cc0033 , в его эквивалент UIColor . Продолжайте читать, чтобы увидеть, как это сделать.

Создайте новый класс, назовите его Tags и сделайте его подклассом NSObject . Откройте Tags.h и добавьте свойство для хранения списка тегов и объявите пользовательский инициализатор:

01
02
03
04
05
06
07
08
09
10
11
#import <Foundation/Foundation.h>
 
@interface Tags : NSObject
 
@property (strong, nonatomic) NSArray* tags;
 
#pragma mark —
#pragma mark Initialization
— (instancetype)initWithString:(NSString*)string;
 
@end

Переключитесь на Tags.m и внедрите инициализатор, который вы только что объявили. Как видите, в этом нет ничего особенного. Вы используете строку для создания массива тегов и хранения тегов в tags :

1
2
3
4
5
6
7
8
9
— (instancetype)initWithString:(NSString*)string {
    self = [super init];
     
    if (self) {
        self.tags = [string componentsSeparatedByString:@» «];
    }
     
    return self;
}

Теперь у вас есть собственный класс Tags , но как вы используете его в своей модели? Откройте PhotoModel.h , импортируйте новый класс вверху и объявите новое свойство в интерфейсе класса:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
#import «JSONModel.h»
 
#import «Tags.h»
 
@protocol PhotoModel
@end
 
@interface PhotoModel : JSONModel
 
@property (copy, nonatomic) NSString *title;
@property (strong, nonatomic) NSURL *url;
@property (strong, nonatomic) NSURL *link;
@property (strong, nonatomic) NSDate *published;
@property (strong, nonatomic) Tags *tags;
 
@end

Создайте и запустите ваш проект, чтобы увидеть, что произойдет.

Поскольку свойство tags имеет тип Tags , который JSONModel не знает, как обрабатывать, приложение будет аварийно завершено, и вы должны увидеть следующее сообщение об ошибке в консоли XCode:

Пришло время познакомиться с новым классом библиотеки JSONValueTransformer классом JSONValueTransformer . В большинстве случаев JSONValueTransformer работает за кулисами и преобразует базовые типы данных для вас, NSNumber в число с float , NSString в NSNumber или NSString в NSDate . Класс, однако, не может иметь дело с пользовательскими классами, потому что он не знает, как с ними работать.

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

Выберите New> File … из меню File Xcode и выберите категорию Objective C из списка шаблонов. Нажмите Далее, чтобы продолжить.

Назовите категорию Теги и установите для параметра Категория значение JSONValueTransformer . Нажмите Далее, чтобы продолжить.

В этой категории в JSONValueTransformer вы можете определить необходимые методы для обработки свойств типа Tags . Откройте JSONValueTransformer + Tags.h и импортируйте файл заголовка класса Tags . Затем добавьте следующие два метода в интерфейс категории:

01
02
03
04
05
06
07
08
09
10
#import «JSONValueTransformer.h»
 
#import «Tags.h»
 
@interface JSONValueTransformer (Tags)
 
— (id)TagsFromNSString:(NSString*)string;
— (id)JSONObjectFromTags:(Tags*)tags;
 
@end

Давайте внимательнее посмотрим на названия этих методов.

  • TagsFromNSString: состоит из имени класса или типа, в который вы хотите преобразовать, Tags , затем From, а затем введите тип данных JSON для соответствующего ключа, NSString . Короче говоря, когда JSONModel находит свойство типа Tags , он пытается сопоставить ключ JSON типа NSString . Когда совпадение найдено, оно вызовет TagsFromNSString:
  • JSONObjectFromTags: обрабатывает обратное преобразование. Когда JSONModel экспортирует объект вашей модели обратно в данные JSON, он должен вызвать метод, который возьмет объект Tags и вернет правильную строку. Таким образом, имя метода — JSONObjectFrom за которым следует имя класса или типа свойства Tags .

Как только вы определите эти два метода, любой подкласс JSONModel сможет обрабатывать объекты типа Tags . Добавление категории в JSONValueTransformer — это очень простой способ добавить функциональность в классы моделей вашего приложения.

Давайте теперь посмотрим на реализацию двух методов в нашей категории. Давайте сначала реализуем метод, который принимает объект NSString и возвращает объект Tags :

1
2
3
— (id)TagsFromNSString:(NSString*)string {
    return [[Tags alloc] initWithString: string];
}

Благодаря пользовательскому инициализатору initWithString: реализация проста. Он берет строку тегов из данных JSON и возвращает объект Tags , который назначен вашему свойству tags в классе PhotoModel .

Затем реализуйте второй метод, который вызывается, когда объект модели преобразуется в строку. Этот метод будет вызываться при вызове toDictionary и toDictionary toJSON .

1
2
3
— (id)JSONObjectFromTags:(Tags*)tags {
    return [tags.tags componentsJoinedByString:@» «];
}

Когда экземпляр PublicPhotosModel инициализируется, он автоматически создает объекты PhotoModel и сохраняет их в свойстве items . Каждый объект PhotoModel также создает объект Tags для своего свойства tags . Все это происходит автоматически благодаря категории, которую мы создали на JSONValueTransformer .

Теперь давайте воспользуемся свойством tags в классе PhotoModel . Откройте ViewController.m и обновите реализацию tableView:cellForRowAtIndexPath: текстовую метку ячейки подробным списком тегов фотографии.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
— (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    static NSString *const cellId = @»ImageCell»;
     
    ImageCell *cell = [self.tableView dequeueReusableCellWithIdentifier: cellId];
     
    if (!cell) {
        cell = [[ImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier: cellId];
    }
     
    PhotoModel *photo = self.photosModel.items[indexPath.row];
     
    cell.textLabel.text = photo.title;
    cell.detailTextLabel.text = [photo.tags.tags componentsJoinedByString:@», «];
    [cell.webImageView setImageWithURL:photo.url placeholderImage:nil];
     
    return cell;
}

Постройте и запустите проект. Вы должны увидеть теги каждой фотографии, перечисленные ниже названия фотографии.

Чтобы сделать наш браузер Flickr завершенным, реализуйте tableView:didSelectRowAtIndexPath: протокола UITableViewDelegate . В tableView:didSelectRowAtIndexPath: мы выбираем соответствующую фотографию и открываем страницу с подробностями фотографии в Safari.

1
2
3
4
5
6
7
8
9
— (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.tableView deselectRowAtIndexPath: indexPath animated:YES];
     
    PhotoModel *photo = self.photosModel.items[indexPath.row];
     
    if ([[UIApplication sharedApplication] canOpenURL:photo.link]) {
        [[UIApplication sharedApplication] openURL:photo.link];
    }
}

При нажатии на строку в табличном представлении вы попадете на страницу сведений о фотографии на Flickr:

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