【问题标题】:how can I use NSURLConnection Asynchronously?如何异步使用 NSURLConnection?
【发布时间】:2013-07-05 10:46:58
【问题描述】:

我正在使用此代码将数据加载到我的应用程序中,您能告诉我如何异步进行吗?

NSMutableURLRequest *request2 = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:requestString] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10.0];


NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request2 delegate:self];
if (connection)
{
    NSLog(@"NSURLConnection connection==true");
    NSURLResponse *response;
    NSError *err;
    NSData *responseData = [NSURLConnection sendSynchronousRequest:request2 returningResponse:&response error:&err];
    self.news =[NSJSONSerialization JSONObjectWithData:responseData options:nil error:nil];
    NSLog(@"responseData: %@", self.news);
}
else
{
    NSLog(@"NSURLConnection connection==false");
};

【问题讨论】:

    标签: objective-c nsurlconnection


    【解决方案1】:

    我认为您应该为阅读文档而烦恼。有一个sendAsynchronousRequest:queue:completionHandler: 方法。

    【讨论】:

    • 我已经读过了,不知道要传递给 queue 或 completionHandler 什么,只需要示例代码
    【解决方案2】:

    创建与initWithRequest:delegate:startImmediately: 的连接,将自己设置为它的委托并实现委托方法。

    【讨论】:

    • 请注意,此方法现在已过时,取而代之的是基于块的 sendAsynchronousRequest:queue:completionHandler: 消息。
    • @H2CO3 我不同意 - 这不是真的。这是一种“方便”的方法——它可以在“工作”时使用。通常它只在示例、玩具程序、演示其他东西的代码 sn-ps 等中起作用。甚至异步便捷方法是同步便捷方法的包装器。说真的,使用代表。
    【解决方案3】:

    块代码是你的朋友。我已经为你创建了一个类

    Objective-C 块代码。在这里创建这个类

    接口类

    #import <Foundation/Foundation.h>
    #import "WebCall.h"
    
    @interface WebCall : NSObject
    {
        void(^webCallDidFinish)(NSString *response);
    
    }
    
    @property (nonatomic, retain) NSMutableData *responseData;
    
    -(void)setWebCallDidFinish:(void (^)(NSString *))wcdf;
    
    -(void)webServiceCall :(NSString *)sURL_p : (NSMutableArray *)valueList_p : (NSMutableArray *)keyList_p;
    
    @end
    

    实现类

    #import "WebCall.h"
    #import "AppDelegate.h"
    @implementation WebCall
    
    @synthesize responseData;
    
    -(void)setWebCallDidFinish:(void (^)(NSString *))wcdf
    {
        webCallDidFinish = [wcdf copy];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
    {
        NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
        int responseStatusCode = [httpResponse statusCode];
    
        NSLog(@"Response Code = %i", responseStatusCode);
        if(responseStatusCode < 200 || responseStatusCode > 300)
        {
            webCallDidFinish(@"failure");
        }
    
    
    
        [responseData setLength:0];
    }
    
    - (BOOL)connection:(NSURLConnection *)connection canAuthenticateAgainstProtectionSpace:(NSURLProtectionSpace *)protectionSpace
    {
    
        return [protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge
    {
        [challenge.sender useCredential:[NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust] forAuthenticationChallenge:challenge];
    
        [challenge.sender continueWithoutCredentialForAuthenticationChallenge:challenge];
    }
    
    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
    {
        [responseData appendData:data]; 
    }
    
    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
    {
    
        NSLog(@"WebCall Error: %@", error);
        webCallDidFinish(@"failure");
    }
    
    - (void)connectionDidFinishLoading:(NSURLConnection *)connection
    {
    
            NSString *response = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
            response = [response stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
            webCallDidFinish(response);
    
    }
    
    -(void)webServiceCall :(NSString *)sURL_p : (NSMutableArray *)valueList_p : (NSMutableArray *)keyList_p
    {
        NSMutableString *sPost = [[NSMutableString alloc] init];
    
        //If any variables need passed in - append them to the POST
        //E.g. if keyList object is username and valueList object is adam will append like
        //http://test.jsp?username=adam
        if([valueList_p count] > 0)
        {
            for(int i = 0; i < [valueList_p count]; i++)
            {
                if(i == 0)
                {
                        [sPost appendFormat:@"%@=%@", [valueList_p objectAtIndex:i],[keyList_p objectAtIndex:i]];
                }
                else
                {
    
                        [sPost appendFormat:@"&%@=%@", [valueList_p objectAtIndex:i], [keyList_p objectAtIndex:i]];
                }
            }
        }
    
    
        NSData * postData = [sPost dataUsingEncoding:NSASCIIStringEncoding allowLossyConversion:NO];
        NSString * postLength = [NSString stringWithFormat:@"%d",[postData length]];
    
    
    
        NSURL * url = [NSURL URLWithString:sURL_p];
        NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:5];
        [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPMethod:@"POST"];
        [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
        [request setHTTPBody:postData];
    
        NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
    
        if (theConnection)
        {
            self.responseData = [NSMutableData data];
        }
    
    
    }
    
    @end
    

    然后你打这个网络电话,你这样称呼它

         WebCall *webCall = [[WebCall alloc] init];
    
    
            [webCall setWebCallDidFinish:^(NSString *response){
    
                //This method is called as as soon as the web call is finished
    
    NSString *trimmedString = [response stringByTrimmingCharactersInSet:
                                       [NSCharacterSet whitespaceAndNewlineCharacterSet]];
            if([trimmedString rangeOfString:@"failure"].location == NSNotFound)
            {
               //Successful web call
            }
            else
            {
               //If the webcall failed due to an error
            }
    
            }];
    
    
            //Make web call here
            [webCall webServiceCall:@"http://www.bbc.co.uk/" :nil :nil];
    

    查看 setWebCallDidFinish 方法,直到 webcall 结束才会调用它。

    希望有帮助!!

    【讨论】:

    • 感谢代码,我使用此代码获取 json,但在 setWebCallDidFinish 方法中使用此行时出现错误: NSArray *test=[NSJSONSerialization JSONObjectWithData:trimmedString options:nil error:nil];
    • trimmedString 是 String 类型,JSON 序列化方法需要传入一个 NSData 对象。我提供的示例代码返回一个字符串,如果您愿意,可以修改代码以返回一个 NSdata 对象而是
    【解决方案4】:

    这是我在我的应用程序中使用的一些代码:

                NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:yourURL]];
            [NSURLConnection sendAsynchronousRequest:request
                                               queue:[NSOperationQueue mainQueue]
                                   completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
                                       if (error) {
                                           NSLog(@"Error loading data from %@. Error Userinfo: %@",yourURL, [error userInfo]);
                                       } else {
                                       NSDictionary *dataFromServer = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
                                       contentAsString = [[[dataFromServer objectForKey:@"page"] objectForKey:@"content"] stripHtml];
                                       completionHandler(contentAsString);
                                   }];
    

    仅供参考:stripHTML 是一个 NSString 类别,用于从 JSON 中删除 HTML 标签 --> Found it Here

    你可以像这样在你的课堂上调用你的内容:

    [yourClass getDataWithcompletionHandler:^(NSString *content) {
        yourObject.content = content;
        [yourClass saveManagedObjectContext];
    }];
    

    如果你实现一次,你就不想再使用同步连接了……

    【讨论】:

    • 感谢示例代码,我没看懂第二部分,你能解释一下 getDataWithcompletionHandler 的用途吗?什么时候可以使用?
    • 通过使用完成处理程序,您可以确保在这种情况下字符串具有来自您的连接的内容,因为完成处理程序中的代码仅在连接成功终止后执行。由于 sendAsynchronousRequest 是在主线程之外的另一个线程中执行的,因此您的程序运行速度可能比您的连接速度更快,并且您的数据(或此处的字符串)将为零,因为您的设备尚未从服务器获得响应。因此,您使用完成处理程序将值分配给完成块中的对象。我在我声明的地方使用它
    • 将我的对象保存在 Core Data 中。 sendAsynchronousRequest 仍然比同步请求快,因为它不会阻止程序的其余部分被执行,并且没有任何东西(除了完成块中的代码)等待请求完成。尤其是您的 UI 流程不会被请求中断。
    【解决方案5】:

    看看这个:HTTPCachedController

    它将帮助您发送 POST 和 GET 请求,同时它会缓存响应,然后在没有可用的互联网连接时返回缓存的数据。

    HTTPCachedController *ctrl = [[[HTTPCachedController alloc] initWithRequestType:1 andDelegate:self] autorelease];
    [ctrl getRequestToURL:@"https://api.github.com/orgs/twitter/repos?page=1&per_page=10"];
    

    当通过委托方法获取数据时,您会收到通知:

    -(void)connectionFinishedWithData:(NSString*)data andRequestType:(int)reqType
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-03-02
      • 1970-01-01
      • 1970-01-01
      • 2013-08-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多