Вопрос

Я пишу небольшое приложение для iOS, которое запрашивает веб -сервис REST XML. Используемая сетевая структура Afnetworking.

Ситуация

Чтобы запрашивать веб -сервис, я подкладывал Afhttpclient:

@interface MyApiClient : AFHTTPClient

И в реализации я делаю это доступным в качестве синглтона:

+ (MyApiClient *)sharedClient {
    static MySharedClient *_sharedClient = nil;
    static dispatch_once_t oncePredicate;
    dispatch_once(&oncePredicate, ^{
        _sharedClient = [[self alloc] initWithBaseUrl:[NSUrl URLWithString:@"http://url.to.the.webservice"]];
    });

    return self;
} 

А в initwithbaseurl я говорю Afnetworking ожидать контента XML:

[self registerHTTPOperationClass:[AFXMLRequestOperation class]];

Теперь я могу позвонить в GetPatch на Singleton из моего ViewController и в блоке успеха, когда он анализирует мой возвращен XML. В методах nsxmlparserdelegate в ViewController я могу выбрать части XML, которые меня интересуют, и делать с ним.

Проблема

Я хочу иметь методы в моем Httpclient Singleton, которые обрабатывают все, что связано с веб -сервисом и возвращать модели данных или список моделей вместо XML.

Например, я хочу сделать что -то вроде этого:

ServerModel *status = [[MyApiClient sharedClient] getServerStatus];

Затем Apiclient внутренне позвонит на веб -сервис, анализирует XML и вернет модель. Как я могу это сделать? Обычно я использовал бы делегата, который называется, как только XML будет проанализирован, но из -за синглтонской природы апиклента может быть несколько делегатов?

Надеюсь, кто -то сможет пролить свет на это, спасибо!

Это было полезно?

Решение

(Заранее извиняюсь за этот «своего рода» ответ, но мы работаем над лучшим решением ...)

Вам нужно сделать шаг назад и внимательно подумать о своем дизайне.

У вас проблемы, потому что у вас есть идея, что что -то в вашем дизайне должно быть синглтоном, но либо:

1) Это на самом деле не обязательно,

2) Что -то уже может существовать, что делает эту работу для вас (например, HTTP Lib, который вы используете),

или же

3) Вы не ошибаетесь в одиночестве, или вы не разместили свой дизайн в соответствующие части, чтобы хорошо работать с идеей Синглтона

Итак, можете ли вы явно сказать мне, почему вы идете на синглтонский подход? Это просто для того, чтобы гарантировать, что только один сетевой запрос может произойти одновременно? Есть ли в вашем объекте Singleton есть представление о состоянии состояния? Тогда я обновлю этот ответ или комментарий и т. Д.

(Отступление: Я также добавил бы, что в некоторых случаях может быть настоящая потребность в 'сильный«Синглтон - под которым я имею в виду, что на самом деле есть только один возможный экземпляр, и этот механизм запечен прямо в ваш объект, как вы делаете, но это не так. Альтернатива - это 'слабый'Singleton, под которым я имею в виду ваш основной объект, который на самом деле выполняет работу. init Метод, как обычно, но общий доступ к общему объекту проходит через другой объект, который является своего рода простой «фабрикой», которая экстремирует/удерживает общий экземпляр. Преимущество этой слабой идеи в одиночестве состоит в том, что ваш код более повторно используется в разных контекстах - например, вы можете принять решение выполнить несколько HTTP -запросов/сеансов одновременно в более позднее время - и иногда это делает тексты менее проблематичными).

Другие советы

Используйте блоки вместо делегатов.

Из моего класса Apiclient:

- (void)getPath:(NSString *)path 
     parameters:(NSDictionary *)parameters 
        success:(void (^)(id response))success 
        failure:(void (^)(NSError *error))failure 
{   
    NSURLRequest *request = [self requestWithMethod:@"GET" path:path parameters:parameters];
    [self enqueueHTTPOperationWithRequest:request success:success failure:failure];
}

-(void)fetchAllUsersSuccess:(void (^)(id))success 
                     failure:(void (^)(NSError *))failure
{
    [self getPath:@"/api/mobile/user/" 
       parameters:nil 
          success:^(id response) {  

                      if([response isKindOfClass:[NSXMLParser class]]){
                          //parse here to new dict
                          success(newDict);
                      } else
                          success(response);

          } failure:^(NSError *error) {
              failure(error);
          }];
}

Теперь я могу использовать это как:

ServiceApiClient *apiClient = [ServiceApiClient sharedClient];

[apiClient fetchAllUsersSuccess:^(id dict) {
    for (NSDictionary *object in [dict objectForKey:@"objects"]) {
        [ServiceUser addUserFromDictionary:object
                                 inContext:self.managedObjectContext];
    }
    NSError *error= nil;
    [self.managedObjectContext save:&error];
    if (error) {
        NSLog(@"%@", error);
    }
} failure:^(NSError * error) {
    NSLog(@"%@", error);
}];
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top