iOS 5 NSURLConnection - 使用UI反馈建立多个连接

时间:2012-03-05 03:35:46

标签: iphone ios5 nsurlconnection

我目前正在设计一款iOS 5 iPhone应用程序,它将使用.NET RESTful Web服务来提供数据更新。最初安装应用程序时,它将连接到WS以JSON格式下载所有数据。此后,它只会执行更新。 WS为每个表提供了一个POST方法,如GetAllTableRecords()和GetLastUpdatedTableRecords()。

我正在使用iOS 5,我已经使用NSURLConnection和JSON序列化/反序列化与本机库一起正常工作。每个WS POST方法调用当前都驻留在自己的Obj-C类中,并带有所有委托方法。此外,每个类都处理本地数据存储区插入和更新。

每个NSURLConnection都是异步的,并且所有WS调用都是从视图控制器驱动的按钮事件。

我的问题是:

  1. 在代码封装和重用方面,这是正确的设置吗?
  2. 如何在保留用户的同时处理多个WS调用 通过用户界面通知?
  3. 目前有两个表可供下载。这意味着应用程序将调用WS两次以获取初始数据,并在每次刷新期间再次调用两次。我知道,由于每个NSURLConnection都是异步的,因此连接将发出请求,但是当委托处理数据下载时,UI将继续。我已经对GCD和NSOperation / Queue进行了一些研究,但是我不知道任何一个编码解决方案或知道这是否是一个正确的解决方案。

    任何见解都会非常有用!

    编辑#1 :如何将实时更新提供回用户界面?更新交易和帐户时,Mint应用程序会执行类似操作。他们有一个小的状态栏,在发出请求时会弹出底部。

    编辑#2:好的,我相信我已经取得了一些进展。我们正在使用故事板,入口点是登录视图/控制器。单击登录按钮时,将对Web服务进行NSURLConnection。如果connectionDidFinishLoading:(NSURLConnection *)连接中的响应状态代码为200,则执行segue以进入数据同步视图。此视图的目的是在向用户提供反馈的同时初始化或更新数据库。更新或初始化需要两个额外的Web服务调用。

    这是我的 DataSyncView.m

    @synthesize pvStatus, lbStatus;
    
    // pvStatus = progress indicator
    // lbStatus = label
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view from its nib.
    }
    
    - (void)viewDidUnload
    {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
    }
    
    - (void)viewDidAppear:(BOOL)animated
    {
        [super viewDidAppear:animated];
        [self StartDataSync];
    }
    
    - (void)StartDataSync
    {    
        [lbStatus setText:@"Syncing data..."];
        [pvStatus setProgress:0.0f];
    
        // TODO: Determine if database is popuplated
        [self PerformInitialSync];  
    
        // Next screen
        [self performSegueWithIdentifier:@"SegueFromSync" sender:self];
    }
    
    // Populates data store will data from web service
    - (void)PerformInitialSync
    {
        // Kicks off a series of synchronous requests
        [self DownloadAllEmployeeDataA];
    }
    
    - (void)DownloadAllDataA
    {
        // Dictonary holds POST values
        NSMutableDictionary *reqDic = [NSMutableDictionary dictionary];
    
        // Populate POST key/value pairs
        [reqDic setObject:passWord forKey:@"Password"];
        [reqDic setObject:userName forKey:@"UserName"];
    
        NSError *error = nil;
        NSData *jsonData = [NSJSONSerialization dataWithJSONObject:reqDic options:NSJSONWritingPrettyPrinted error:&error];
    
        // Convert dictionary to JSON
        NSString *requestJSON = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];    
    
        // Declare Webservice URL, request, and return data
        NSURL *url = [[NSURL alloc] initWithString:@"http://wsurl/getalla"];
    
        NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:url];
        NSData *postData = [NSData dataWithBytes:[requestJSON UTF8String] length:[requestJSON length]];
    
        // Build the request
        [request setHTTPMethod:@"POST"];
        [request setValue:[NSString stringWithFormat:@"%d", [postData length]] forHTTPHeaderField:@"Content-Length"];
        [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        [request setHTTPBody:postData];
        [request setCachePolicy:NSURLRequestUseProtocolCachePolicy];
        [request setTimeoutInterval:60.0];
    
        NSURLResponse *response;
    
        [lbStatus setText:@"Downloading employee data..."];
        [pvStatus setProgress:0.1f];
    
        // Make the response
        NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    
        // If return data received
        if(returnData)
        {
            // Get the response and check the code
            NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
            int code = [httpResponse statusCode];
    
            // Check to make sure successful code
            if (code == 200) 
            {
                // Convert JSON objects to Core Data Entity
                // Update UIProgressView and Label
    
                // Call next WS call
                [self DownloadAllEmployeeDataA];
            }
        }
    }
    
    - (void)DownloadAllDataB
    {                
        // Same code as above but with different URL and entity
    }
    

    我遇到的问题是:UIProgressView和Label在进行调用时没有更新。正如我之前所说,我甚至不知道这是否是进行这些通话的最佳方式。我似乎没有阻止主线程,但我可能是错的。同样,我将提出一个问题:在保持UI更新进度的同时进行多个url调用的最佳方法是什么?感谢!!!

1 个答案:

答案 0 :(得分:2)

// Make the response
    NSData *returnData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];

在你的问题中,你说你做了异步加载url请求。但是在上面的代码行中你正在进行同步请求吗?

在代码封装和重用方面,这是正确的设置吗?

  • 查看您的代码,您并不遵守MVC。你的观点 控制器不应管理加载URL连接。你可以创建一个 执行此操作并使用委托的类通知视图控制器 无论是下载数据还是下载失败等

如何在通过用户界面保持用户通知的同时处理多个WS调用?

  • 如果要进行并发URL连接,请使用NSOperation 和NSOperationQueue。尝试避免使用GCD(请参阅WWDC 2010会话 208)。

我遇到的问题是:UIProgressView和Label在调用时没有更新。

  • 您正在主线程上发出同步URL请求。根据你的 代码UIProgressView不应该更新。

参考URL Loading System Programming Guide

我的另一个评论是你的方法名,用小写字母开始方法名。其余的看起来很好。 Coding Guidelines for Cocoa