2011-06-13 86 views
4

我正在我的App Delegate类中异步下载JSON订阅源。现在数据需要一段时间才能加载,因此我的表格视图首先显示为空,然后在几秒钟后填充。因此,我想要:异步加载JSON并显示活动指标视图

1-找出导致此延迟的原因。因此,请保留应用程序中的所有活动:didFinishLaunchingWithOptions方法,并且只加载所有内容后才加载VC。

OR

2-显示活动性指示符直到表填充数据。

现在在第一种情况下,我非常肯定我在错误的时间推视图控制器。我尝试过使用它,但似乎这是我的应用程序构建和运行的唯一方式。

在第二种情况下,我想知道哪个“连接”方法首先被调用,哪一个最后被调用。因此,我将能够在第一种方法中启动活动指示器视图,并在最后一种方法结束时释放。

以下是我的代码。任何建议/帮助非常感谢。谢谢你的阅读。

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { 
     [responseData setLength:0]; 
} 

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { 
    [responseData appendData:data]; 
} 

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { 

    UIAlertView *alert = [[UIAlertView alloc] 
         initWithTitle:@"Error" 
         message:@"Please check your network connection and relaunch the application" 
         delegate:self 
         cancelButtonTitle:@"Dismiss" 
         otherButtonTitles:nil, nil]; 
    [alert show]; 
    [alert release]; 
} 

- (void)connectionDidFinishLoading:(NSURLConnection *)connection { 

    NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding]; 

    if ([responseString isEqualToString:@"Unable to find specified resource."]) { 
     NSLog(@"Unable to find specified resource.n"); 
    } 

     else { 

     ListingsViewController *listingsViewController = [[ListingsViewController alloc] initWithNibName:@"ListingsViewController" bundle:nil]; 
     listingsViewController.jsonData = responseString; 
     [self.navigationController pushViewController:listingsViewController animated:NO]; 
     [self.navigationController setViewControllers:[NSArray arrayWithObject:listingsViewController] animated:NO]; 
     [listingsViewController release]; 
    } 

    [connection release]; 
    [responseData release]; 
} 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 

    // Start the HTTP request 
    responseData = [[NSMutableData data] retain]; 
    NSURLRequest *request = [NSURLRequest requestWithURL: 
         [NSURL URLWithString:@"http://www.shoofeetv.com/iphonexml/view/all_channels.json"]]; 
    [[NSURLConnection alloc] initWithRequest:request delegate:self]; 

    // Display the navigation controller 
    self.window.rootViewController = self.navigationController; 
    [self.window makeKeyAndVisible]; 

    return YES; 
} 

回答

2

与选项2.转到这是很好的用户界面设计,以尽可能快地显示的东西,即使在将数据加载它至少让你的应用程序的用户感觉的东西是UI可能不是有用发生。

在didFinishLaunchingWithOptions中弹出用户界面,显示活动指示符并在connectionDidFinishLoading中隐藏和销毁活动指示器。

我也建议包装所有的异步HTTP请求逻辑到另一个类,并使其接受委托,再例如,你可以拨打:

{ 
    // Show activity indicator 
    [httpClient get:@"www.example.com/json" withDelegate:self]; 
} 

-(void)httpClientSuccessful:(NSData*)response 
{ 
    // hide activity indicator 
} 
+0

将所有aysnc http请求包装到另一个方法或另一个类中?你知道我在哪里可以找到一个关于objective-c http异步方法的好教程吗?我到处寻找,我似乎还没有很好地理解它。谢谢.. – darksky 2011-06-13 08:24:38

+0

在另一个类 - 例如称之为HttpClient。老实说,最好的地方是苹果文档http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSURLConnection_Class/Reference/Reference.html - 阅读所有的方法你可以实现和每个人都做什么。如果你真的无法理解它(或者根本不能被打扰),请查看http://allseeing-i.com/ASIHTTPRequest/How-to-use - 特别是异步的东西。这是NSURLConnection的一个很好的包装类,应该让你的生活更轻松。 – Tyler 2011-06-13 08:55:43

+0

谢谢泰勒.. – darksky 2011-06-13 11:57:58

2

选项2肯定是要走的正确方法。在网络操作完成之前,您不应该阻止用户界面。如果您的接待很差,您不希望几秒钟内没有反应迟钝的应用程序。用户将杀死它。

NSURLConnection代表方法以didReceiveResponse,didReceiveData(可能多次),connectionDidFinishLoading的顺序调用。可以随时调用didFailWithError

我已经成功地使用了一种模式,我立即创建并显示表格视图。只要数据尚未加载,我将显示一个带有活动指示器和文本“加载数据...”的单元格单元格。

更新:

下面是一些代码(只是主要部分)。其主要思想是管理目前的状态,要么不加载,加载失败或准备:

@interface MyViewController : UITableViewController<NSURLConnectionDelegate> 
{ 
    NSInteger state; 
    NSURLConnection* connection; 
    MyData* data; 
} 

... 
@end 

@implementation MyViewController 

typedef enum LoadingState { 
    eNotLoaded, 
    eLoading, 
    eFailed, 
    eReady 
} LoadingState; 

- (void) viewWillAppear: (BOOL) animated 
{ 
    [super viewWillAppear: animated]; 
    // Start loading the data when the table view appears for the first time 
    if (state == eNotLoaded) { 
    NSURLRequest request = // create the request 
    connection = [NSURLConnection initWithRequest:request delegate:self]; 
    [request release]; 
    state = eLoading; 
    } 
} 

- (void) connection: (NSURLConnection*) connection didReceiveData: (NSData*) data 
{ 
    // record and process the received data 
} 

- (void) connectionDidFinishLoading: (NSURLConnection*) connection 
{ 
    // parse the received data and store it into 'data' 
    [connection release]; 
    connection = nil; 

    // state changed; redisplay the table view 
    state = eReady; 
    [[self tableView] reloadData]; 
} 

- (NSInteger) tableView: (UITableView*) tableView numberOfRowsInSection: (NSInteger) section 
{ 
    if (state == eReady) { 
    return [data numberOfRows]; 
    } else { 
    return 1; 
    } 
} 

- (UITableViewCell*) tableView: (UITableView*) tableView cellForRowAtIndexPath: (NSIndexPath*) indexPath 
{ 
    static NSString* DefaultCellIdentifier = @"Default"; 

    UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier: DefaultCellIdentifier]; 
    if (cell == nil) { 
    cell = [[[UITableViewCell alloc] initWithStyle: UITableViewCellStyleDefault reuseIdentifier: DefaultCellIdentifier] autorelease]; 
    } 
    if (state == eReady) { 
    cell.textLabel.text = [data labelAtRow: indexPath.row]; 
    if (state == eLoading) { 
    cell.textLabel.text = @"Loading..."; 
    } else { 
    cell.textLabel.text = @"Failed"; 
    } 
    return cell; 
} 
+0

你说过:“我已经成功地使用了一种模式,我立即创建并显示了表格视图,只要数据尚未加载,我将显示一个包含活动指示符的表格单元格,一个文字说“加载数据...”。“怎么样 ???任何细节? – viral 2012-01-04 12:32:32

+0

我已经添加了一些代码。这只是解释模式的重要部分。一个真正的解决方案将不得不处理连接故障,在数据加载之前留下视图,正确清理,重新加载数据等。 – Codo 2012-01-04 22:14:34

0

我用NSURLConnection类方法sendAsynchronousRequest:queue:completionHandler:这是真正有用的和直接的。

它让我发送一个块作为回调用于分析错误或成功为指定的请求:

[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:url] 
            queue:[NSOperationQueue currentQueue] 
         completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 
          if (!error) { 
           [self parseData:data]; 
          } else { 
           NSLog(@"ERROR %@", error); 
          } 

         } 
]; 

这样我可以事先调用方法激活的活性指示器并删除它一旦数据被检索同时我可以处理错误。

我希望这有助于;)

相关问题