iphone - iOS 5 NSURLConnection - 通过 UI 反馈建立多个连接

标签 iphone ios5 nsurlconnection

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

我使用的是 iOS 5,并且 NSURLConnection 和 JSON 序列化/反序列化可以与 native 库正常工作。每个 WS POST 方法调用当前都驻留在其自己的具有所有委托(delegate)方法的 Obj-C 类中。此外,每个类都处理本地数据存储插入和更新。

每个 NSURLConnection 都是异步的,所有 WS 调用都是由 View Controller 的按钮事件驱动的。

我的问题是:

  1. 就代码封装和重用而言,这种设置正确吗?
  2. 如何在保留用户的同时处理多个 WS 调用 通过用户界面通知?

目前有两个表格可供下载。这意味着应用程序将调用 WS 两次以获取初始数据,并在每次刷新期间再次调用两次。我知道,由于每个 NSURLConnection 都是异步的,因此连接将发出请求,但 UI 将在委托(delegate)处理数据下载时继续运行。我对 GCD 和 NSOperation/Queue 进行了一些研究,但我对其中任何一个都没有足够的了解来编写解决方案,也不知道这是否是正确的解决方案。

任何见解都会非常有帮助!

编辑 #1:向 UI 提供实时更新怎么样? Mint 应用程序在更新交易和帐户时会执行类似的操作。它们有一个小状态栏,在发出请求时会在底部弹出。

编辑#2:好的,我相信我已经取得了一些进展。我们正在使用 Storyboard,入口点是登录 View / Controller 。单击登录按钮时,将与 Web 服务建立 NSURLConnection。如果connectionDidFinishLoading:(NSURLConnection *)connection中的响应状态代码为200,则执行segue以进入数据同步 View 。此 View 的目的是初始化或更新数据库,同时向用户提供反馈。更新或初始化都需要两次额外的 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 调用的最佳方法是什么?谢谢!!!

最佳答案

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

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

就代码封装和重用而言,这是正确的设置吗?

  • 查看您的代码,您没有遵守 MVC。您的看法 Controller 不应管理加载 URL 连接。您可以创建一个 执行此操作并使用委托(delegate)通知 View Controller 的类 数据是否下载或下载失败等

如何处理多个 WS 调用,同时通过 UI 通知用户?

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

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

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

引用URL Loading System Programming Guide

我的另一个评论是你的方法名称,方法名称以小写字母开头。其余部分看起来不错。 Coding Guidelines for Cocoa

关于iphone - iOS 5 NSURLConnection - 通过 UI 反馈建立多个连接,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9561318/

相关文章:

ios - NSOperation 和 NSURLConnection 迷惑了

ios - 如何在不阻塞主线程的情况下等待网络调用在 iOS 上返回数据?

iphone - 如何增加iPhone中UITabBarItem的大小?

iphone - 在 objective-c 中计算直角三角形的角度

ios - 如何将效果应用到麦克风输入?(iOS Core Audio & Audio Graph)

ios5 - 带 Storyboard的 viewController 自定义 init 方法

iphone - 在 NSURLRequest 中通过 POST 发送 JSON

iphone - CMake 和 XCode : "cannot find interface declaration for ' NSObject'"

iphone - iPhone 5 的 hw.machine 有什么值(value)?

iphone - 应用程序/启动图标未出现在 iPhone 5.0 模拟器或设备中