Преобразование из ASIHTTPRequest в AFNetworking - PullRequest
4 голосов
/ 17 ноября 2011

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

Я нахожу несколько проблем.Мой код для ASIHTTPRequest построен как метод.Этот метод принимает несколько параметров и отправляет параметры в URL-адрес ... возвращая полученные данные.Эти данные всегда являются текстовыми, но в интересах создания универсального метода иногда может использоваться json, иногда XML или иногда HTML.Таким образом, я создал этот метод как автономный загрузчик общих URL-адресов.

Моя проблема в том, что при вызове процедуры I приходится ждать ответа.Я знаю все аргументы "синхронно - это плохо" ... и я не часто это делаю ... но для некоторых методов я хочу синхронность.

Итак, вот мой вопрос.Ниже приведен мой упрощенный код ASIHTTP, за которым следует единственный способ, которым я мог бы придумать кодирование в AFNetworking.У меня есть проблема, что AFNetworking иногда не для ответа, прежде чем вернуться из метода.Намек на то, что @mattt дал [operation waitUntilFinished], полностью не удерживает поток до тех пор, пока не будет вызван блок завершения ... и мой другой метод [queue waitUntilAllOperationsAreFinished] тоже не всегда всегда работает (и НЕ приводит к срабатыванию части ошибкипредложение [operation hasAcceptableStatusCode]).Так что, если кто-то может помочь, БЕЗ вездесущего «проектируйте его асинхронно», пожалуйста.

Версия ASIHTTP:

- (NSString *) queryChatSystem:(NSMutableDictionary *) theDict
{
    NSString *response = [NSString stringWithString:@""];
    NSString *theUrlString = [NSString stringWithFormat:@"%@%@",kDataDomain,kPathToChatScript];

    ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:[NSURL URLWithString:theUrlString]];
    for (id key in theDict)
    {
        [request setPostValue:[theDict objectForKey:key] forKey:key];
    }

    [request setNumberOfTimesToRetryOnTimeout:3];
    [request setAllowCompressedResponse:YES];
    [request startSynchronous];

    NSError *error = [request error];
    if (! error)
    {
        response = [request responseString];
    }

    return response;
}

AFNetworking версия

- (NSString *) af_queryChatSystem:(NSMutableDictionary *) theDict
{
    NSMutableDictionary *theParams = [NSMutableDictionary dictionaryWithCapacity:1];

    for (id key in theDict)
    {
        [theParams setObject:[theDict objectForKey:key] forKey:key];
    }


    AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:kDataDomain]];

    NSMutableURLRequest *theRequest = [httpClient requestWithMethod:@"POST" path:[NSString stringWithFormat:@"/%@",kPathToChatScript] parameters:theParams];


    __block NSString *responseString = [NSString stringWithString:@""];

    AFHTTPRequestOperation *operation = [[[AFHTTPRequestOperation alloc] initWithRequest:theRequest] autorelease];

    operation.completionBlock = ^ {
        if ([operation hasAcceptableStatusCode]) {
            responseString = [operation responseString];
            NSLog(@"hasAcceptableStatusCode: %@",responseString);
        }
        else
        {
            NSLog(@"[Error]: (%@ %@) %@", [operation.request HTTPMethod], [[operation.request URL] relativePath], operation.error);
        }
    };

    NSOperationQueue *queue = [[[NSOperationQueue alloc] init] autorelease];
    [queue addOperation:operation];
    [queue waitUntilAllOperationsAreFinished];
    [httpClient release];


    return responseString;

}

Большое спасибо за любые идеи.

Ответы [ 3 ]

3 голосов
/ 18 ноября 2011
- (void)af_queryChatSystem:(NSMutableDictionary *) theDict block:(void (^)(NSString *string))block {
...
}

Теперь в рамках завершения сделайте:

block(operation.responseString);
Блок

будет выступать в качестве делегата операции. удалить

-waitUntilAllOperationsAreFinished

и

return responseString

Вы называете это как:

[YourInstance af_queryChatSystem:Dict block:^(NSString *string) {
    // use string here
}];

Надеюсь, это поможет. Вы можете обратиться к примеру iOS, AFNetworking имеет

0 голосов
/ 21 января 2013

Мое решение - запустить текущий цикл выполнения потока вручную, пока не будет обработан обратный вызов.

Вот мой код.

- (void)testRequest
{
    MyHTTPClient* api = [MyHTTPClient sharedInstance]; // subclass of AFHTTPClient
    NSDictionary* parameters = [NSDictionary dictionary]; // add query parameters to this dict.
    __block int status = 0;
    AFJSONRequestOperation* request = [api getPath:@"path/to/test"
                                        parameters:parameters
                                           success:^(AFHTTPRequestOperation *operation, id responseObject) {
                                               // success code
                                               status = 1;
                                               NSLog(@"succeeded");
                                           } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
                                               // failure
                                               status = 2;
                                               NSLog(@"failed");
                                           }];
    [api enqueueHTTPRequestOperation:request];
    [api.operationQueue waitUntilAllOperationsAreFinished];

    while (status == 0)
    {

        [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
                                 beforeDate:[NSDate date]];
    }

    STAssertEquals(status, 1, @"success block was executed");
}
0 голосов
/ 18 ноября 2011

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

...