在动态UITableView原型中访问行高

时间:2017-02-10 13:31:45

标签: ios swift uitableview

行。有许多问题涉及到这一点,但没有一个问题实际上解决了我的需要。

我需要的,很简单,就是获取我在IB中为DYNAMIC(非静态)表格单元原型的“自定义行高”设置的值。

如果表格设置了静态原型,那么这将自动兑现。但是,在使用动态原型时,将忽略此值以支持表的主rowHeight值。

我希望能够访问此值,因此我可以使用tableView(_:heightForRowAt:)方法返回它。我可以手动执行此操作,具有内部高度表,并与原型匹配,但这很麻烦,并且要求原型始终出现在某一行中。

当调用tableView(_:heightForRowAt:)时,我可以合成reuseID,但我想避免在适当的时间(tableView(_:cellForRowAt:))之前加载视单元。

有没有一种好方法可以访问它?我没有看到Apple文档中有关访问原型的任何文献。

1 个答案:

答案 0 :(得分:2)

编辑:好的,我知道你的问题是什么。在iOS开发中,我们使用UITableCell的不同子类处理这样的任务。像这样:

+ (CGFloat)layoutHeightWithEntity:(id)entity {
    CGFloat layoutHeight = 0;
    // use data to calculate layout height dynamically if needed
    // id data = [entity data];
    // layoutHeight = layoutHeight + [data ...];

    // or use a static layout height if the height of this kind of cells do not change
    layoutHeight = 100;

    return layoutHeight;
}

在视图控制器中,您需要为表视图准备数据源,如下所示:

NSMutableArray *dataList = [NSMutableArray new];

NSMutableArray *firstSection = [NSMutableArray new];
[firstSection addObject:[XXXTableEntity entityWithReuseCellID:@"nameCell" data:someData cellClass:[XXXNameCell class]];
[dataList addObject:firstSection];

NSMutableArray *secondSection = [NSMutableArray new];
[firstSection addObject:[XXXTableEntity entityWithReuseCellID:@"pickerCell" data:someData cellClass:[XXXPickerCell class]];
[dataList addObject:secondSection];

[self setDataList:dataList];

您的CustomTableEntity可能如下所示:

+ (instancetype)entityWithEntityID:(NSString *)entityID
                       cellReUseID:(NSString *)cellReUseID
                         cellClass:(Class<XXXBaseTableCellLayout>)cellClass
                        dataEntity:(id)dataEntity
                precalculateHeight:(BOOL)precalculateHeight {

    XXXBaseTableCellEntity *entity = [self new];

    [entity setEntityID:entityID];
    [entity setReuseCellID:cellReUseID];
    [entity setDataEntity:dataEntity];

    [entity setCellClass:cellClass];

    if (precalculateHeight) {
        [entity setLayoutHeight:[cellClass layoutHeightWithEntity:dataEntity]];
    }

    return entity;
}

- (CGFloat)layoutHeight {
    if (_layoutHeight > 0) {

        return _layoutHeight;
    }

    _layoutHeight = [[self cellClass] layoutHeightWithEntity:[self dataEntity]];

    return _layoutHeight;
}

然后在你的UITableViewDataSource方法中:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    return self.dataList.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    return [self.dataList[section] count];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

    return [[[[self dataList] objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]] layoutHeight];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    XXXTableEntity *entity = [[[self dataList] objectAtIndex:[indexPath section]] objectAtIndex:[indexPath row]];

    XXXBaseTableCell *cell = [tableView dequeueReusableCellWithIdentifier:[entity reuseCellID] forIndexPath:indexPath];
    [cell configureWithEntity:entity];

    return cell;
}

上面的代码基本上来自我为公司编写的框架,但你应该明白这个想法。该框架有3个与表视图相关的类:XXXBaseTableCellXXXBaseTableViewControllerXXXBaseTableCellEntity。所有视图控制器都包含一个表视图子类XXXBaseTableViewController,所有表格单元都是子类XXXBaseTableCell,所有表实体都是子类XXXBaseTableCellEntity

我可以问你为什么要这样做?我认为你在表视图方面遇到了一些问题。如果您能解释为什么要这样做,也许我可以帮助您,这样您根本不需要这样做。

您无法在标准方法中访问原型单元格的高度。但实际上,如果您真的想要这样做,您可以访问故事板文件中的任何数据。以下是如何:

Storyboard是一个XML文件。在IB中编辑故事板文件时所做的一切都是在XML文件中编码的。您可以通过自己解析XML文件来访问所需的任何信息。您可以在故事板文件中读取XML数据并将其提供给XML解析器以获取DOM数据。然后,您可以查询DOM以获取数据。以下是包含表视图控制器的测试故事板的XML视图:

    <!--Table View Controller-->
    <scene sceneID="hbL-mT-mfb">
        <objects>
            <tableViewController id="XNl-aA-YKn" customClass="TableViewController" sceneMemberID="viewController">
                <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="44" sectionHeaderHeight="28" sectionFooterHeight="28" id="lX1-Ry-xNl">
                    <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                    <prototypes>
                        <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="cell" rowHeight="100" id="4rn-ee-JoI">
                            <rect key="frame" x="0.0" y="28" width="375" height="100"/>
                            <autoresizingMask key="autoresizingMask"/>
                            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="4rn-ee-JoI" id="bdN-kI-rps">
                                <rect key="frame" x="0.0" y="0.0" width="375" height="99"/>
                                <autoresizingMask key="autoresizingMask"/>
                            </tableViewCellContentView>
                        </tableViewCell>
                    </prototypes>
                    <connections>
                        <outlet property="dataSource" destination="XNl-aA-YKn" id="GlZ-SO-7gG"/>
                        <outlet property="delegate" destination="XNl-aA-YKn" id="gqq-QI-tZD"/>
                    </connections>
                </tableView>
            </tableViewController>
            <placeholder placeholderIdentifier="IBFirstResponder" id="RCX-w1-742" userLabel="First Responder" sceneMemberID="firstResponder"/>
        </objects>
        <point key="canvasLocation" x="118" y="798"/>
    </scene>

请不要这样做......