2014-04-03 59 views
0

我在這裏設置的是,我有一個UITableView與故事板中定義的靜態單元格。在其中一個靜態單元格中,我有一個嵌套的UITableView,它是動態的,並以編程方式填充其內容。我已經研究過這一點,並假設這是一個完全有效的配置,因爲您可以在UITableViewCell內擁有任何種類的UIView子類(即表視圖)。但是,無論何時加載視圖,即使我的後備數據結構是有效的,我也會得到一個超出邊界異常的索引,並且我已確保所有內部表視圖的委託方法都返回正確的值。我在我的cellForRowAtIndexPath:方法中放置了斷點,但這沒有用,因爲在調用該方法之間拋出異常。所以我不知道我在做什麼錯誤,或者如果偷偷地說這是一個無效的配置。UITableView裏面的UITableViewCell問題

此界面的目標是在同一屏幕上顯示發票及其所有關聯的訂單項(嵌套/嵌入式表格視圖),與之前我點擊查看訂單項的方式一個單獨的UITableViewController視圖。

查看我的截圖和下面的代碼。

Screenshot of table view layout

#pragma mark - Table view data source 

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView 
    { 
     NSInteger count = 0; 

     if (tableView == self.tableView) { 
      count = [super numberOfSectionsInTableView:tableView]; 
     } else if (tableView == itemsTable) { 
      count = 3; 
     } 

     return count; 
    } 

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

     if (tableView == self.tableView) { 
      count = [super tableView:tableView numberOfRowsInSection:section]; 
     } else if (tableView == itemsTable) { 
      switch (section) { 
       case 0: 
        // Header 
        count = 1; 
        break; 
       case 1: 
        // Items 
        count = assoicatedInvoice.items.count; 
        break; 
       case 2: 
        // Add item 
        count = 1; 
        break; 
       default: 
        break; 
      } 
     } 

     return count; 
    } 

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    { 
     UITableViewCell * cell; 

     if (tableView == self.tableView) { 
      cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 
     } else if (tableView == itemsTable) { 
      InvoiceDetailEmbeddedLineItemViewCell * iCell; 

      switch (indexPath.section) { 
       case 0: 
        // Header section 
        iCell = (InvoiceDetailEmbeddedLineItemViewCell *) [tableView dequeueReusableCellWithIdentifier:invoiceDetailLineItemHeadersViewCellIdentifier]; 
        break; 

       case 1: { 
        // Item 
        InvoiceItem * associatedItem = [assoicatedInvoice.items objectAtIndex:indexPath.row]; 

        iCell = (InvoiceDetailEmbeddedLineItemViewCell *) [tableView dequeueReusableCellWithIdentifier:invoiceDetailEmbeddedLineItemViewCellIdentifier]; 
        iCell.nameLabel.text = associatedItem.name; 
        iCell.qtyLabel.text = [UtilityFunctions decimalFormatForInput:associatedItem.quantity minDecimalPlaces:0 maxDecimalPlaces:2]; 
        iCell.priceLabel.text = [UtilityFunctions currencyFormatForInput:associatedItem.price]; 
        iCell.taxLabel.text = [UtilityFunctions percentageFormatForInput:associatedItem.tax minDecimalPlaces:0 maxDecimalPlaces:2]; 
        break; 
       } 

       case 2: 
        // Add new item 
        iCell = (InvoiceDetailEmbeddedLineItemViewCell *) [tableView dequeueReusableCellWithIdentifier:invoiceDetailLineItemAddItemCellIdentifier]; 
        break; 

       default: 
        break; 
      } 

      cell = iCell; 
     } 

     return cell; 
    } 

    - (NSString *) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { 
     NSString * title = nil; 

     if (tableView == self.tableView) { 
      if (section != 0) { 
       title = [super tableView:tableView titleForHeaderInSection:section]; 
      } else { 
       title = [Invoice friendlyNameForInvoiceType:assoicatedInvoice.invoiceType]; 
      } 
     } 

     return title; 
    } 

    - (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { 
     if (tableView == self.tableView) { 
      return [super tableView:tableView viewForHeaderInSection:section]; 
     } else if (tableView == itemsTable) { 
      return nil; 
     } 

     return nil; 
    } 

    - (CGFloat) tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { 
     CGFloat height = 0.0; 

     if (tableView == self.tableView) { 
      if (indexPath.section != 1) { 
       height = [super tableView:tableView heightForRowAtIndexPath:indexPath]; 
      } else { 
       height = itemsTable.contentSize.height; 
      } 
     } else if (tableView == itemsTable) { 
      height = 30.0; 
     } 

    // height = [super tableView:tableView heightForRowAtIndexPath:indexPath]; 
     return height; 
    } 

運行後,這是堆棧跟蹤我得到。以創新的方式

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]' 
    *** First throw call stack: 
    (
     0 CoreFoundation      0x041dc1e4 __exceptionPreprocess + 180 
     1 libobjc.A.dylib      0x0303a8e5 objc_exception_throw + 44 
     2 CoreFoundation      0x041908b2 -[__NSArrayI objectAtIndex:] + 210 
     3 UIKit        0x0244935f -[UITableViewDataSource tableView:indentationLevelForRowAtIndexPath:] + 127 
     4 UIKit        0x021c2f34 -[UITableViewController tableView:indentationLevelForRowAtIndexPath:] + 61 
     5 UIKit        0x01fe02cf __53-[UITableView _configureCellForDisplay:forIndexPath:]_block_invoke + 1786 
     6 UIKit        0x01f5481f +[UIView(Animation) performWithoutAnimation:] + 82 
     7 UIKit        0x01f54868 +[UIView(Animation) _performWithoutAnimation:] + 40 
     8 UIKit        0x01fdfbd0 -[UITableView _configureCellForDisplay:forIndexPath:] + 108 
     9 UIKit        0x01fe713d -[UITableView _createPreparedCellForGlobalRow:withIndexPath:] + 442 
     10 UIKit        0x01fe71f3 -[UITableView _createPreparedCellForGlobalRow:] + 69 
     11 UIKit        0x01fc8ece -[UITableView _updateVisibleCellsNow:] + 2428 
     12 UIKit        0x01fdd6a5 -[UITableView layoutSubviews] + 213 
     13 UIKit        0x01f5d964 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355 
     14 libobjc.A.dylib      0x0304c82b -[NSObject performSelector:withObject:] + 70 
     15 QuartzCore       0x02f2345a -[CALayer layoutSublayers] + 148 
     16 QuartzCore       0x02f17244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380 
     17 QuartzCore       0x02f170b0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26 
     18 QuartzCore       0x02e7d7fa _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294 
     19 QuartzCore       0x02e7eb85 _ZN2CA11Transaction6commitEv + 393 
     20 QuartzCore       0x02f3c5b0 +[CATransaction flush] + 52 
     21 UIKit        0x01eec9bb _UIApplicationHandleEventQueue + 13095 
     22 CoreFoundation      0x0416577f __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15 
     23 CoreFoundation      0x0416510b __CFRunLoopDoSources0 + 235 
     24 CoreFoundation      0x041821ae __CFRunLoopRun + 910 
     25 CoreFoundation      0x041819d3 CFRunLoopRunSpecific + 467 
     26 CoreFoundation      0x041817eb CFRunLoopRunInMode + 123 
     27 GraphicsServices     0x044395ee GSEventRunModal + 192 
     28 GraphicsServices     0x0443942b GSEventRun + 104 
     29 UIKit        0x01eeef9b UIApplicationMain + 1225 
     30 Field Manage      0x000aae7d main + 141 
     31 libdyld.dylib      0x0355d701 start + 1 
    ) 
    libc++abi.dylib: terminating with uncaught exception of type NSException 
+0

你想實現什麼真正的事情?我不認爲在表單元格中嵌套UITableView是一種很好的代碼模式。 – x4snowman

回答

2

榮譽把動態原型細胞在靜態表:)

靜態細胞表視圖實現很多的大小相關的方法(在這種情況下indentationLevelForRowAtIndexPath),並返回內部數組值。由於您正在嘗試爲這兩個tableviews使用相同的委託和數據源,因此您需要爲幾乎所有與調整大小有關的委託方法提供重寫。更好的解決方案可能是使用不同的數據源,並完全委託嵌入的表格。

+0

謝謝:)我看到你在說什麼,但是在我的覆寫中,我不會確定這些值應該是什麼嗎?當我以前從未覆蓋過這些方法時,看起來像很多工作。或者我應該讓我的嵌入式表視圖的委託另一個'UITableViewController'的子類? –

+0

如果你給你的嵌入表一個單獨的委託和數據源(也許是UITableViewController的一個子類,但不一定),那麼你不必重寫所有的方法,可能不會超過你目前的。問題在於您對基表使用靜態佈局,它提供了一些通常不提供的方法的「非標準」實現。 –

+0

要從@ GeneralMike的答案中竊取某種東西,爲包含的單元格創建一個自定義的單元格類型,然後將其設置爲它所包含的表格視圖的數據源和委託。 –

1

我在嵌套UICollectionView s的應用程序中做了這樣的事情。我找到了最簡單的方法來製作嵌入在其中的表格的每個CELLdataSourcedelegate。因此,您必須總共創建2個UITableViewCell的自定義子類,將您的靜態單元設置爲第一個子類的實例,然後在.m中爲該第一個UITableViewCell子類實施諸如cellForRowAtIndexPath:之類的操作,並讓它創建並返回第二個子類的一個實例。