2011-06-13 61 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); 
          } 

         } 
]; 

這樣我可以事先調用方法激活的活性指示器並刪除它一旦數據被檢索同時我可以處理錯誤。

我希望這有助於;)

相關問題