Архитектурный подход к HTTP-коммуникациям и синтаксический анализ возвращаемого JSON в iOS

#iphone #objective-c #ios #design-patterns

#iPhone #objective-c #iOS #шаблоны проектирования

Вопрос:

Добрый вечер, ребята,

Мой вопрос скорее относится к инженерному подходу / шаблону проектирования, чем к конкретно техническому.

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

Я объясню, что у меня есть на данный момент (в псевдокоде и объявлениях), и посмотрим, сможете ли вы помочь:

  1. Класс выборки HTTP, реализующий необходимые методы делегирования NSURLConnection. Я инициализирую класс с помощью селектора метода обратного вызова следующим образом для возврата к вызывающему классу по завершении
     @implementation HTTPFetcher{
        - (id)initWithUrlRequest:(NSURLRequest *)aRequest receiver:(id)aReceiver action:(SEL)aReceiverAction
        {
         //set the member variables etc..
        }
    
        //all NSURLConnection delegate methods
    
        - (void)connectionDidFinishLoading...
        {
            [receiver performSelector:action withObject:self];
        }
    }
     
  2. Затем у меня есть одноэлементный класс HTTPController для вызова HTTPFetcher:
     - (void)postWithRequestString:(NSString *)aRequestString
    {
        [urlRequest setHTTPBody:[aRequestString dataUsingEncoding:NSUTF8StringEncoding]];
    
        fetcher = [[HTTPFetcher alloc]initWithUrlRequest:urlRequest receiver:self action:@selector(receivedDataFromService:)];
        [fetcher start];
    }
    
    - (void)receivedDataFromService:(HTTPFetcher *)aFetcher{
        //handle the received data and split the parent object into an NSMutableDictionary
    }
     

Теперь этот подход работает фантастически хорошо для приложения, которое я специально выделил для отдельных объектов, которые я должен моделировать (в основном у меня будет одноэлементный HTTPController для каждого объекта).

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

Должен ли я включать методы для облегчения синтаксического анализа в одноэлементных классах или мне следует создать дополнительные контроллеры для синтаксического анализа действий?

Я с нетерпением жду вашего ответа

Спасибо

Ответ №1:

Я бы рекомендовал вам использовать существующую библиотеку синтаксического анализа JSON, в частности Джона Энгельхарта JSONKit , учитывая, что это, возможно, самая высокопроизводительная библиотека синтаксического анализа JSON для iOS. Позволяет вообще не использовать пользовательский синтаксический анализ JSON, но особенно экономит время при реализации кода, который оказывается слишком медленным для ваших нужд, а затем вам нужно будет итеративно дорабатывать его, пока он не станет достаточно быстрым для использования.

Я знаю, что для HTTP-запросов вы уже реализовали поведение, но вы можете захотеть исследовать ASIHTTPRequest или AFNetworking использовать сетевые библиотеки общего назначения, которые имеют репутацию довольно надежных. В Note AFNetworking используется вышеупомянутая JSONKit библиотека для синтаксического анализа JSON.


Способ ASIHTTPRequest (библиотека, которую я использую в своих проектах) работает с использованием объекта делегата, реализующего протокол ASIHTTPRequestDelegate , который вы назначаете после создания запроса с URL. Существует глобальная сетевая очередь, которая является просто an NSOperationQueue , и которая обрабатывает асинхронные или несколько одновременных активных запросов.

Вы можете setDelegate: , чтобы объект начал проверять, реализовал ли ваш делегат какой-либо из методов в разных точках, например, didReceiveData: или requestDidFinish: по умолчанию, но вы также можете установить пользовательский путь выбора для проверки, используя методы для отдельных операций ( setDidFinishSelector:@selector(downloadComplete:) ) .

Что вы могли бы сделать, когда, например, didReceiveData: происходит обратный вызов, это передать вновь полученные данные в буфер, хранящийся в классе-оболочке для ASIJSONRequest (или use AFNetworking , который уже инкапсулирует это). Когда буфер таков, что в нем есть полный объект JSON, который можно правильно проанализировать, тогда вы вызываете to JSONKit , чтобы выполнить основную работу, а затем, возможно, самостоятельно отправить другой обратный ASIJSONRequestDelegate вызов for didReceiveData: , но теперь данные находятся в формате, который доступен для чтения остальной частью вашего приложения.


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

Комментарии:

1. Спасибо за ответ. ASIHTTPRequest — очень хороший вызов — я действительно рассматривал это при первоначальном просмотре сборки приложения, но спецификации клиентов уменьшили любую выгоду, которую он мог бы предложить. Кроме того, клиент неохотно включает сторонние библиотеки везде, где это возможно. Хороший ответ, хотя — спасибо, что нашли время.

Ответ №2:

Одной из возможностей было бы, чтобы View или view controller запрашивали у объекта модели любое состояние, которое ему нужно (включая данные с удаленного сервера). Объекту модели будет сообщено, когда появятся какие-либо новые данные с сервера, и затем он может вызвать любые требуемые процедуры обработки данных, необходимые для обновления его внутреннего состояния (например, преобразование списков или json в более канонический формат словаря).