2010-10-31 52 views
0

我有一個DetailsViewController類和一個ItemsViewController類。 (都源自UITableViewController)什麼時候是reloadData的合適時間

選擇ItemsViewController中的任何項目都會調出DetailsViewController。爲了得到它顯示在任何新的數據,但第一位的,我現在有

 
- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    [[self navigationItem] setTitle:title]; 
    [[self tableView] reloadData]; 
} 

工作,但感覺就像殺死一隻蒼蠅用大錘。什麼是更好這樣做的方法?

由於提前,

艾倫

+0

從什麼是上面這個代碼段? ItemsView或DetailsView ...你說他們都是桌子。 – 2010-10-31 05:05:41

+0

對不起,我應該提到。這是來自DetailsView。 – Alan 2010-11-01 10:46:32

回答

1

從一些意見在這裏結合的想法變量到Details控制器。

然後在細節控制器:

 
- (void)setData:(DataClass *)value { 
    if (value == data) 
     return; 
    id pointer = data; 
    data = [value retain]; 
    [pointer release];  // release after retain 
    needReload = TRUE; 
} 

- (void)viewWillAppear:(BOOL)animated 
{ 
    [super viewWillAppear:animated]; 
    if(needReload){ 
     [[self navigationItem] setTitle:title]; 
     [[self tableView] reloadData]; 
     needReload = FALSE; 
    } 
} 
0

如果您知道,只有特定的行或部分將被改變,你可以直接烘烤,以便重新加載只有那些行或部分。除此之外,-reloadData是大多數表視圖的方式。

0

我假設細節表上的項目根據項目表上的選定項目而變化。所以,是的,這應該沒問題。

除此之外,您可以檢查上次是否選擇了相同的項目,而不是在這種情況下調用reloadData。

0

艾倫,

你的聲明「爲了得到它顯示在任何但是第一個新的數據」我擔心 - 因爲它告訴我,你有可能有一個DetailsViewController實例。

在您的第一個表視圖ItemsViewController中,您可能有一個didSelectRowAtIndexPath:方法,用於將DetailsViewController推送到UINavigationController堆棧。

我如何解決這個問題是每次我的用戶在視圖之間輕敲時簡單地創建/銷燬新的DetailsViewController。所以,我經常didSelectRowAtIndexPath:看起來像:

- (void) didSelectRowAtIndexPath:(NSIndexPath*)indexPath 
{ 
    NSInteger selectedRow = indexPath.row; 

    // Create a new view controller 
    DetailsViewController *tmpVC = [[DetailsViewController alloc] initWithNibName:@"foo" bundle:nil]; 

    // Tell our new view controller what data it should be using 
    tmpVC.tableData = [self.someArrayOfData objectAtIndex:selectedRow]; 

    // Push view controller and release it 
    [self.navigationController pushViewController:tmpVC animated:YES]; 
    [tmpVC release]; 
} 

此示例假設您擁有所有必要爲您的ItemsViewController兩個視圖控制器的數據 - 可能並非如此..?

無論如何,通過這樣做,您的DetailsViewController會自動加載數據。當你點擊「後退」返回到ItemsViewController時,UINavigationController會釋放它並銷燬它。然後,當用戶點擊不同的單元格時,我們再次運行此代碼,創建一個全新的數據控制器 - 當然,當它顯示時,它會自動加載數據 - 它以前從未顯示過。

它聽起來像你可能會在你的代碼中做的是保留DetailsViewController作爲ItemsViewController類的屬性,然後重新使用該對象。如果你關心分配(例如,如果它是一個非常「繁重」的分配來創建DetailsViewController),那麼這也可以起作用,但是我認爲調用reloadData的最佳位置不在類內部 - 但而不是來自ItemsViewController的didSelectRowAtIndexPath:方法。

我推動創建/銷燬方法而不是「flyweight模式」方法的原因是它使代碼更加分離 - 視圖控制器之間的聯繫越少越好。當然,ItemsViewController將始終依賴和了解DetailsViewController,但它不一定必須是另一種方式 - 如果將reloadData調用添加到viewWillAppear:animated:,則隱式地在兩者之間添加了非代碼依賴關係。您知道當ItemsViewController是導航堆棧中的「父」時,這是正確的行爲 - 但是如果您突然開始在應用的其他部分重新使用該視圖而不需要重新加載,該怎麼辦?這是一個性能問題,而且,它是一種隱藏的依賴性,可能最終會在一天內出現一個令人討厭的跟蹤錯誤。所以,如果確實需要只有1個DetailsViewController(而不是每次重新創建它的第一個想法),我會保持細節愚蠢並使項目包含所有複雜性。

+0

你對我所做的事情的假設完全正確。我需要更多地考慮分配和取消分配detailsview的相關成本。嗯.. – Alan 2010-11-01 10:45:55

+0

你的數據有多大?通常項目中有多少行?詳情中有多少數據? – makdad 2010-11-01 12:16:23

0

我會建議reloadData和setTitle在viewDidLoad和setter中 - 我假設你在DetailsViewController中設置了一個屬性,它改變了表的數據源。因此,viewDidLoad會重新加載並設置標題,如果屬性已設置,則setter將重新加載並設置標題(如果isViewLoaded且新值與舊值不同)。

添加

BOOL needReload
作爲成員:

- (void)setSmth:(SmthClass *)value { 
    if (value == smth) // if they are the same and SmthClass is immutable, 
         // otherwise use isEqual and [self.tableView reloadData] 
         // before returning... 
     return; 
    id pointer = smth; // if it's a retain property 
    smth = [value retain]; 
    [pointer release];  // release after retain just to be extra safe 

    if ([self isViewLoaded]) { 
      [self.tableView reloadData]; 
      [self setTitle:title]; 
    } 
} 

- (void)viewDidLoad { 
    if (smth) { 
     [self.tableView reloadData]; // maybe redundant... 
     [self setTitle:title]; 
    } 
} 

或者你可以使用鍵 - 值觀察(NSKeyValueObserving協議)來觀察您的通知財產和reloadData ...

+0

這不會減少reloadData被調用的次數,並且會增加額外的開銷。但我認爲這是解決方案的一部分(特別是與下面的Altealice結合) – Alan 2010-11-01 10:48:30

+0

另外,viewDidLoad在每次顯示控制器時都不會被調用。 – Alan 2010-11-01 10:52:58

相關問題