Диспетчеризация данных службы Best Objective-C (iphone) - PullRequest
0 голосов
/ 15 сентября 2011

Я борюсь с тем, как я собираюсь разработать свой шаблон извлечения службы

Я до сих пор придумал это:

  • ServiceCaller (этобудет единственным классом, который будет использовать клиент, он имеет все методы для доступа к определенной части веб-сервиса, такие как requestHello, requestLogon, requestUserDetails, ...)

  • ServiceConnector(этот класс создается в вызывающей службе, этот класс будет выполнять фактическое соединение с сервером, запрашивать данные и возвращать их вызывающей стороне, которой необходимо отправить их обратно клиенту, в соединителе службы я использую абстрактный шаблон фабрикичтобы отделить логику запроса и определить, какая часть веб-сервисов должна быть вызвана на анализ)

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

, но когда, например, 2 вызова выполняются в 2 отдельных представлениях, я изменяю свойство делегата, которое означает, что только вызов, который будет выполнен в последний раз, получает свой обратный вызов, другой не делает 'т.

У кого-нибудь есть идеи, как мне решить эту проблему?

1 Ответ

0 голосов
/ 15 сентября 2011

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

typedef void(^ContinuationBlock)(id result, NSError *error);

- (void) answerTheDefinitiveQuestion:(Towel *)h2g2Towel do:(ContinuationBlock*) continuation
{
    if (h2g2Towel) {
        double answer = 7 / h2g2Towel.length * (sqrt(h2g2Towel.area+2*h2g2Towel.area+1) - 1) * 6 / h2g2Towel.width;
        continuation([NSNumber numberWithDouble:answer], nil);

    } else {
        NSError *err = [[[NSError alloc] initWithDomain:H2G2Domain code:kMissingTowel userInfo:nil] autorelease];
        continuation(nil, err);
    }
}

Теперь клиент может использовать его таким образом:

- (void) doSomething
{
    [myServiceCaller answerTheDefinitiveQuestion:self.towel do:^(NSNumber * answer, NSError *error) {
        if (!answer) {
            NSLog("No answer available because %@, %@", error, error.userInfo);
        } else {
            NSLog("haha, Zaphod, your answer is %@, %@", answer);
        }
    }];
}

Примечание: этот пример является синхронным, но он прекрасно работает в асинхронном контексте. Например, вы можете заключить в скобки реализацию answerTheDefinitiveQuestion:do: при вызове dispatch_async.

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

self.myClientContinuation = [continuation copy];

PS: вся идея синглтона - зло. По крайней мере, в вашем дизайне, похоже, что ServiceCaller не имеет смысла быть единственным (в отличие от ServiceConnector).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...