4

由于该项目的工作不幸中止,我正在将我的应用程序例程从 ASIHTTP 转换为 AFNetworking ......以及后来我发现是更好和更小的 AFNetworking 代码库。

我发现了几个问题。我的 ASIHTTPRequest 代码是作为方法构建的。此方法接受一些参数并将参数发布到 url ...返回结果数据。这些数据总是文本,但为了制作通用方法,有时可能是 json,有时是 XML,有时是 HTML。因此,我将此方法构建为独立的通用 URL 下载器。

我的问题是,当调用例程时,我必须等待响应。我知道那里所有的“同步是坏的”论点......而且我不经常这样做......但对于某些方法我想要同步。

所以,这是我的问题。下面是我简化的 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;
}

AF联网版

- (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;

}

非常感谢您的任何想法。

4

3 回答 3

3
- (void)af_queryChatSystem:(NSMutableDictionary *) theDict block:(void (^)(NSString *string))block {
...
}

现在在 completionBlock 中执行:

block(operation.responseString);

块将充当操作的委托。消除

-waitUntilAllOperationsAreFinished

return responseString

你这样称呼它:

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

希望能帮助到你。您可以参考 AFNetworking 的 iOS 示例

于 2011-11-17T20:52:21.770 回答
0

我强烈建议利用这个机会转换为 Apple 自己的NSURLConnectionAPI,而不是采用另一个第三方 API。通过这种方式,您可以确定它不会停产。我发现让它工作所需的额外工作很少- 但事实证明它更加健壮且不易出错。

于 2011-11-17T20:31:05.477 回答
0

我的解决方案是手动运行当前线程 runloop,直到处理完回调。

这是我的代码。

- (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");
}
于 2013-01-21T02:50:09.153 回答