UITableView内部UITableViewCell问题

时间:2014-04-03 17:06:27

标签: ios objective-c uitableview

我在这里的设置是我在故事板中定义了一个UITableView静态单元格。在一个静态单元格中,我有一个动态的嵌套UITableView,并以编程方式填充其内容。我已经研究了这个,并假设这是一个完全有效的配置,因为你可以在UIView内拥有任何类型的UITableViewCell子类(即表格视图)。

但是,无论何时加载视图,我都会获得超出边界异常的索引,即使我的后台数据结构有效并且我确保所有内部表视图的委托方法都返回正确的值。我在我的cellForRowAtIndexPath:方法中放置了断点,但这没有结果,因为在调用该方法之间会抛出异常。所以我不确定我做错了什么,或者暗地说这是一个无效的配置。

此界面的目标是在同一屏幕上显示发票及其所有关联的订单项(嵌套/嵌入的表格视图),而不是我之前点击以查看订单上的订单项的方式。单独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

2 个答案:

答案 0 :(得分:2)

赞赏将动态原型单元放入静态表的创新方法:)

静态单元格表​​视图实现了许多与大小相关的方法(在本例中为indentationLevelForRowAtIndexPath)并从内部数组返回值。由于您尝试对两个tableviews使用相同的委托和dataSource,因此您需要为几乎所有与大小调整有关的委托方法提供覆盖。更好的解决方案可能是使用不同的数据源并完全委托嵌入式表。

答案 1 :(得分:1)

我在我的应用程序中使用嵌套的UICollectionView执行类似的操作。我找到了最简单的方法,使其中的每个 CELL dataSourcedelegate嵌入其中。因此,您必须总共创建2个UITableViewCell的自定义子类,将静态单元格设置为第一个子类的实例,然后在.m中为第一个UITableViewCell实现cellForRowAtIndexPath: 之类的内容子类,让它创建并返回第二个子类的实例。