2013-03-20 67 views
0

我有一個UITableView從web服務器內的xml文件加載內容。TBXML tableview內容不會更新

  • TableView是在一個標籤欄控制器;
  • 我打電話[table reloadData]裏面的TBXMLSuccessBlock;
  • 問題是,TableView的內容不更新。
  • 我正在使用TBXML庫;

按鈕被點擊後,如何對tableVIew說XML文件已被下載並顯示出來?

- (IBAction)leftButton:(UIButton *)sender { 
    if (a<=2 && a != 0) { 
     a = a - 1; 

     NSString *leftURL = self.getDate; 
     [self loadURL:leftURL]; 
    } 

} 

- (void)loadURL:(NSString *)newURL{ 

    if (newURL == NULL) { 
     newURL = self.getDate; 
    } 

    // Create a success block to be called when the asyn request completes 
    TBXMLSuccessBlock successBlock = ^(TBXML *tbxmlDocument) { 
     NSLog(@"PROCESSING ASYNC CALLBACK"); 

     [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 
     // If TBXML found a root node, process element and iterate all children 
     if (tbxmlDocument.rootXMLElement) 
     { 
      // Obtain root element 
      TBXMLElement * root = tbxml.rootXMLElement; 
     if (root) 
     { 
      _storeArray = [NSMutableArray new]; 
      TBXMLElement * elem_PLANT = [TBXML childElementNamed:@"news" parentElement:root]; 
      while (elem_PLANT !=nil) 
      { 
       TBXMLElement * elem_title = [TBXML childElementNamed:@"title" parentElement:elem_PLANT]; 
       NSString *titleName = [TBXML textForElement:elem_title]; 

       TBXMLElement * elem_artist = [TBXML childElementNamed:@"text" parentElement:elem_PLANT]; 
       NSString *artistName = [TBXML textForElement:elem_artist]; 

       TBXMLElement * elem_thumb = [TBXML childElementNamed:@"thumb_url" parentElement:elem_PLANT]; 
       NSString *thumbName = [TBXML textForElement:elem_thumb]; 

       NSDictionary *dictionary = [[NSDictionary alloc]initWithObjects:@[titleName, artistName, thumbName] forKeys:@[@"title", @"text", @"thumb"]]; 
       elem_PLANT = [TBXML nextSiblingNamed:@"news" searchFromElement:elem_PLANT]; 
       [_storeArray addObject:dictionary]; 

      } 

     } 

      [_tableView reloadData]; 
     } 
    }; 

    // Create a failure block that gets called if something goes wrong 
    TBXMLFailureBlock failureBlock = ^(TBXML *tbxmlDocument, NSError * error) { 
     NSLog(@"Error! %@ %@", [error localizedDescription], [error userInfo]); 
    }; 

    // Initialize TBXML with the URL of an XML doc. TBXML asynchronously loads and parses the file. 
    tbxml = [[TBXML alloc] initWithURL:[NSURL URLWithString:newURL] 
           success:successBlock 
           failure:failureBlock]; 
} 

編輯:ReloadData內部buttonClick

- (IBAction)leftButton:(UIButton *)sender { 
    if (a<=2 && a != 0) { 
     a = a - 1; 

     NSString *leftURL = self.getDate; 
     [self loadURL:leftURL]; 
     [_tableView reloadData]; 
    } 

    } 

- (IBAction)rightButton:(UIButton *)sender { 
    if (a<2) { 
     a = a + 1; 
     NSString *rightURL = self.getDate; 
     [self loadURL:rightURL]; 
     [_tableView reloadData]; 
    } 
} 

當應用啓動: - URL數1被裝載; - 顯示URL編號1; 當我單擊右側一次: - 加載URL編號2; - 什麼都沒有發生; 當我再次點擊右鍵時: - 加載了URL編號3; - 顯示URL編號2; 當我點擊一次: - URL 2加載; - 顯示URL 3;當我再次點擊一次時: - 加載URL 1; - 顯示URL 2;

回答

1

你說:

當應用程序啓動: - URL數量1加載; - 顯示URL編號1;當我單擊右鍵時: - 加載URL編號2; - 什麼都沒發生;當我再次點擊右鍵時: - 加載URL編號3; - 顯示網址2;當我點擊一次時: - URL 2被加載; - 顯示URL 3;當我再次點擊時: - URL 1被加載; - 顯示URL 2;

從這一點,我們知道:

  1. URL/XML負載的工作原理,數據有被顯示,但顯示沒有發生時,它應該。
  2. 表重新加載工作 - 在稍後的按鈕按下時,顯示較早的數據,但顯示不同的數據。
  3. 表重裝過早發生 - 這就是它顯示以前的URL/XML數據的原因。

您的按鈕動作(間接)使用需要成功/失敗塊(S)庫使URL加載通話,所以這裏發生了什麼,大致爲:

  1. 的IBAction爲調用loadUrl:,它運行TBXML的initWithURL:success:failure:
  2. initWithURL:success:failure:存儲成功和失敗塊,並在單獨的線程(「在後臺」)中啓動實際的網絡操作,並在網絡操作完成之前幾乎可以肯定地返回。
  3. IBAction調用reloadData
  4. 之後,在後臺,網絡動作結束,成功或失敗塊運行。

因此,將reloadData調用移動到成功塊中,以便在處理XML數據後重新裝入表。

但是最初這個墜毀與包括一個錯誤:

這可能是從輔助線程調用到的UIKit的結果。

UIKit調用 - 粗略地說,影響用戶界面的任何方法調用 - 必須在主線程上進行。對於一些使用塊回調的異步庫(特別是AFNetworking),出於這個原因,塊回調被保證在主線程上運行。對於TBXML,顯然,塊回調在後臺運行,可能與實際的網絡加載操作相同。所以,我們需要一些方法使reloadData調用UITableView發生在主線程上。

有幾種方法可以做到這一點。我的第一選擇通常是使用的主要操作隊列(我們開始使用上NSOperationQueuemainQueue類的方法),這是在主線程上執行操作的隊列:

[[NSOperationQueue mainQueue] addOperationWithBlock:^{ 
    [_tableView reloadData]; 
}]; 

主要操作隊列,然後自動儘可能在主線程上執行塊。或者,但還是在的Objective-C /可可/ CocoaTouch水平,您可以在表視圖使用performSelectorOnMainThread:withObject:waitUntilDone:

[_tableView performSelectorOnMainThread:@selector(reloadData) 
          withObject:nil 
          waitUntilDone:NO]; 

(或YES用於等到做,可能不會在這種情況下重要),這具有完全相同的效果。第三個選項,但一般不會在這種情況下首選,是直接使用大中央調度:

dispatch_async(dispatch_get_main_queue(), ^{ 
    [_tableView reloadData]; 
}]; 

(但是,當有喜歡NSOperationQueue路線或performSelectorOnMainThread:withObject:waitUntilDone:路線更高層次的選擇,他們應該使用這種較低級的C Grand Central Dispatch例程;同樣,將dispatch_async更改爲dispatch_sync與前面示例中的將waitUntilDone:NO更改爲waitUntilDone:YES的效果相同。

+0

我確信_tableView指向我在xib中的表視圖,dataSource和委託指向File所有者和我在UIViewController類中實現。當我可以在viewDidAppear裏面的時候,reloadData可以工作,但它只是加載一次,當我點擊按鈕時它不會更新。 NSURL也是有效的。 – Marckaraujo 2013-03-23 00:32:10

+0

在將新數據加載到數據源中後,單擊按鈕時是否嘗試調用'reloadData'? – Isaac 2013-03-23 00:33:55

+0

看到我的編輯,你可以看到reloadData「works」,但它更新了以前的數據。 – Marckaraujo 2013-03-23 02:35:13

-1

正如你說的,你有調用方法reloadData然後它應該刷新表視圖..我認爲那麼問題是不存在,你有沒有嘗試過某人,而不使用標籤欄控制器..可能有時候標籤欄控制器的bcoz問題可能會出現...所以只是嘗試一次.. &讓我們知道..或我們以另一種方式幫助你

+0

我需要使用標籤欄控制器,並且我不知道標籤欄控制器如何解決此問題。 – Marckaraujo 2013-03-23 15:37:03