2012-06-09 46 views
13

我有一個UITableView填充標準的NSFetchedResultsController。不過,我想預先安排一行或一個部分(最好是行,但任一個都可以正常工作)。NSFetchedResultsController前置一行或部分

我現在可能看到的唯一方法就是在處理段時手動重寫所有NSIndexPath /行處理來自NSFetchedResultsController的數據,以欺騙它在索引0處看到部分,並在索引0處從行開始。這看起來像是一個非常糟糕的主意,很快就會令人困惑,所以我希望避免這種情況。

這是一個很好的例子,在官方的Twitter應用程序中,當你第一次啓動時,我會引導你添加朋友列表中的一些人。

Screenshot of Twitter app's suggestions page, with the relevant sections highlighted

紅色的部分是相當多想什麼,我來實現的,黃色的部分,我認爲是從NSFetchedResultsController在同一節的結果(儘管他們的自定義樣式它可能是一個獨立的)

+0

的[添加額外的行而NSFetchedResultsController管理一個UITableView]可能重複(http://stackoverflow.com/questions/ 9604410/add-extra-row-to-a-uitableview-managed-by-nsfetchedresultscontroller) – JosephH

回答

31

這是可以做到一個相當乾淨的方式。

我假設你開始使用一個標準的tableview設置與使用Apple的示例代碼的標準NSFetchResultsController。

首先,你需要兩個實用的功能:

- (NSIndexPath *)mapIndexPathFromFetchResultsController:(NSIndexPath *)indexPath 
{ 
    if (indexPath.section == 0) 
     indexPath = [NSIndexPath indexPathForRow:indexPath.row+1 inSection:indexPath.section]; 

    return indexPath; 
} 

- (NSIndexPath *)mapIndexPathToFetchResultsController:(NSIndexPath *)indexPath 
{ 
    if (indexPath.section == 0) 
     indexPath = [NSIndexPath indexPathForRow:indexPath.row-1 inSection:indexPath.section]; 

    return indexPath; 
} 

這些應該是相當自我解釋 - 他們只是幫手對付添加額外的行,當我們要使用索引的路徑從獲取的成果控制器訪問表格,或以其他方式移除表格。

然後,我們需要創建額外的單元格:

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

    if (indexPath.section == 0 && indexPath.row == 0) 
    { 
     UITableViewCell *cell; 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease]; 
     cell.selectionStyle = UITableViewCellSelectionStyleGray; 
     cell.textLabel.text = NSLocalizedString(@"Extra cell text", nil); 

     return cell; 
    } 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 
    if (cell == nil) { 
     cell = [UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:nil] autorelease]; 
    } 

    [self configureCell:cell atIndexPath:indexPath]; 

    return cell; 
} 

確保我們配置它正確(configurecell纔會被調用從獲取結果控制器單元):

// the indexPath parameter here is the one for the table; ie. it's offset from the fetched result controller's indexes 
- (void)configureCell:(SyncListViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { 
    indexPath = [self mapIndexPathToFetchResultsController:indexPath]; 

    id *obj = [fetchedResultsController objectAtIndexPath:indexPath]; 
    <... perform normal cell setup ...> 
} 

,並告訴它存在的tableview:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 
    NSInteger numberOfRows = 0; 

    if ([[fetchedResultsController sections] count] > 0) { 
     id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section]; 
     numberOfRows = [sectionInfo numberOfObjects]; 
    } 

    if (section == 0) 
     numberOfRows++; 

    return numberOfRows; 
} 

並回應選擇:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    [tableView deselectRowAtIndexPath:indexPath animated:YES]; 

    if (indexPath.section == 0 && indexPath.row == 0) 
    { 
     [self doExtraAction]; 
     return; 
    } 

    ... deal with selection for other cells ... 

,然後重新映射,我們從結果控制器得到任何更新:

- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { 
    UITableView *tableView = self.tableView; 

    indexPath = [self mapIndexPathFromFetchResultsController:indexPath]; 
    newIndexPath = [self mapIndexPathFromFetchResultsController:newIndexPath]; 

    switch(type) { 
     ... handle as normal ... 
+0

如果在這種方法中,我喜歡動態刪除第一行,這是可能的。 – cocoaNoob

+0

@cocoaNoob是的,這將工作正常。只要你正確映射indexPath,你就可以做任何事情。 – JosephH

+0

是的,我試過,而不是使用1,我正在使用實例變量。一個非常好的和明確的方法。感謝您分享您的解決方案@JosepH。 – cocoaNoob

3

我瞭解您對複雜度的擔憂,但實際上只是在numberOfRowsInSection:上加1,並在cellForRowAtIndexPath:(除了添加第0行的代碼之外)中的indexPath.row上加1。

另一種解決方案不需要非常複雜,變得更加麻煩。

這就是說,你提出的「標題」看起來似乎是節標題的典型候選者。

+0

這是一個公平的觀點,我主要是檢查是否沒有一些方法我不知道NSFetchedResultsController讓你預先或者將一組行附加到它返回的結果中,以便您可以自定義它們。 –

相關問題