Xcode 6中UITableView的自动调整大小问题

20
我正在使用xcode 6中的自动调整大小功能在UITableview中,但它无法正常工作。我想要使用autoresizing。我从storyboard中向UITableviewController类的静态单元格添加了textfield。无论是横向还是纵向,textfield都超出屏幕。我不想使用autolayout,我的整个项目都在使用autoresizing。Textfield
演示项目
3个回答

30

这是关于Xcode 6 .xib 和 .storyboard 处理问题的。简单来说,Xcode会给表格视图单元格和它的contentView设置不正确的框架。让我解释得更深入一些。

自动调整大小掩码的工作原理

基本上,它将视图的frame限制在其父视图的frame中。我们可以指定哪些边距和尺寸是灵活的,哪些是固定的。 当父视图改变其边界时,根据我们的自动调整大小规范,我们的视图边界也会发生变化。 这不仅在运行时发生,而且在Xcode界面构建器中也发生。试着创建一个带有子视图的视图,将不同的自动调整大小选项设置给子视图并调整主视图的大小。你会发现,子视图也会在Xcode中正确地调整大小。方便吧?

错误的来源

我第一次发现完全相同的问题是在将表格视图单元格从iPhone storyboard复制到iPad storyboard后。经过一番对.storyboard文件的挖掘,我发现单元格及其contentView在.storyboard中仍然具有320x91的框架(而不是iPad大小的768x91),而在屏幕上和检查器中它们都是正确的尺寸。这是实际序列化数据和视觉表示之间的不一致。

<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="91" sectionHeaderHeight="22" sectionFooterHeight="22" id="nKc-Lp-03y">
    <rect key="frame" x="0.0" y="58" width="768" height="901"/>
    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
    <prototypes>
        <tableViewCell contentMode="scaleToFill" selectionStyle="blue" accessoryType="disclosureIndicator" hidesAccessoryWhenEditing="NO" indentationLevel="1" indentationWidth="0.0" reuseIdentifier="PriceEvaluateCell" rowHeight="91" id="cis-7J-9wV" customClass="PriceEvaluateCell">
            <rect key="frame" x="0.0" y="434" width="320" height="91"/>
            <!-- note how small frame is! But it is drawn with iPad width -->
            <autoresizingMask key="autoresizingMask"/>
            <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="cis-7J-9wV" id="cYU-lI-DGN">
                <rect key="frame" x="0.0" y="0.0" width="320" height="90"/>
                <!-- here is same issue -->
                <autoresizingMask key="autoresizingMask"/>
                <subviews>
                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="TItle" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="AOE-zL-Dv0">
                        <rect key="frame" x="9" y="3" width="305" height="21"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                        <!-- this view draws OK, it has small size, left alignment and flexible right margin -->
                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                        <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
                        <color key="highlightedColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                    </label>
                    <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" text="FGPrice" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="wPa-dC-JzV">
                        <rect key="frame" x="623" y="20" width="104" height="21"/>
                        <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
                        <!-- this is bad view, it has flexible LEFT and will misplace every time you open the file -->
                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                        <color key="textColor" red="0.40000000600000002" green="1" blue="0.40000000600000002" alpha="1" colorSpace="calibratedRGB"/>
                        <color key="highlightedColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
                    </label>
                </subviews>
            </tableViewCellContentView>
            <connections>
                <!-- ... -->
            </connections>
        </tableViewCell>
    </prototypes>
    <connections>
        <!-- ... -->
    </connections>
</tableView>

因此,当我根据iPad的尺寸(例如x="624" y="19" width="80" height="21")以及可变左边距设置单元格子视图frame时,它在单元格内部超出了界限,而在视觉上它仍然看起来设置正确。当存储板上的文件并重新加载后,单元格及其contentView自动从320x91调整为768x91,由于其自动调整大小,该子视图会自动向右移动。

现在让我们看看您的情况。您有一个具有可变宽度的文本字段。每次打开项目时,它的框架都会变得越来越宽。看起来就像存储的宽度和可视宽度之间存在不一致。打开您项目的.storyboard文件后,我们可以看到表视图单元格及其contentView根本没有指定任何frame!因此,我们可以说Xcode隐式地将非常小的框架设置为您的单元格及其contentView

这就是里面的样子。

<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="246" sectionHeaderHeight="22" sectionFooterHeight="22" id="zuY-va-uVD">
    <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
    <sections>
        <tableViewSection id="KFU-cy-GoW">
            <cells>
                <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="245" id="WCc-Ec-YKn">
                <!-- note there is no frame at all -->
                    <autoresizingMask key="autoresizingMask"/>
                    <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WCc-Ec-YKn" id="DtD-vs-Xwy">
                        <!-- and here too -->
                        <autoresizingMask key="autoresizingMask"/>
                        <subviews>
                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="autorsizing" borderStyle="roundedRect" minimumFontSize="17" id="NCA-qk-Isa">
                                <!-- and here frame is already went wrong... -->
                                <rect key="frame" x="60" y="108" width="900" height="30"/>
                                <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
                                <color key="backgroundColor" red="0.89019607840000003" green="0.89019607840000003" blue="0.89019607840000003" alpha="1" colorSpace="calibratedRGB"/>
                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                <textInputTraits key="textInputTraits"/>
                            </textField>
                        </subviews>
                    </tableViewCellContentView>
                </tableViewCell>
            </cells>
        </tableViewSection>
    </sections>
    <connections>
        <outlet property="dataSource" destination="1kU-E8-zzp" id="pca-5d-SRg"/>
        <outlet property="delegate" destination="1kU-E8-zzp" id="WxC-Qa-ToS"/>
    </connections>
</tableView>

如何修复

目前还没有最终解决方案,但我们可以通过变通方法来解决这个问题。如果Xcode本身无法正确设置框架,我们可以手动设置。使用任何文本编辑器打开storyboard(它是纯XML),并修正框架:

<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="246" sectionHeaderHeight="22" sectionFooterHeight="22" id="zuY-va-uVD">
    <rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
    <color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
    <sections>
        <tableViewSection id="KFU-cy-GoW">
            <cells>
                <tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="245" id="WCc-Ec-YKn">
                    <autoresizingMask key="autoresizingMask"/>
                    <!-- we insert the correct frame (exact size we can get from xcode editor, which draws it properly) -->
                    <rect key="frame" x="0.0" y="0.0" width="320" height="245"/>
                    <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="WCc-Ec-YKn" id="DtD-vs-Xwy">
                        <!-- and here we do the same -->
                        <rect key="frame" x="0.0" y="0.0" width="320" height="244"/>
                        <autoresizingMask key="autoresizingMask"/>
                        <subviews>
                            <textField opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" text="autorsizing" borderStyle="roundedRect" minimumFontSize="17" id="NCA-qk-Isa">
                                <!-- set any size that is smaller than parent frame. You will be able to change it with Xcode later -->
                                <rect key="frame" x="60" y="108" width="200" height="30"/>
                                <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMaxY="YES"/>
                                <color key="backgroundColor" red="0.89019607840000003" green="0.89019607840000003" blue="0.89019607840000003" alpha="1" colorSpace="calibratedRGB"/>
                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                <textInputTraits key="textInputTraits"/>
                            </textField>
                        </subviews>
                    </tableViewCellContentView>
                </tableViewCell>
            </cells>
        </tableViewSection>
    </sections>
    <connections>
        <outlet property="dataSource" destination="1kU-E8-zzp" id="pca-5d-SRg"/>
        <outlet property="delegate" destination="1kU-E8-zzp" id="WxC-Qa-ToS"/>
    </connections>
</tableView>

然后关闭Xcode,保存编辑器中的故事板,重新打开Xcode。大功告成!文本字段已经离开其疯狂的状态,现在按预期工作。


真的是一篇很好的解释。谢谢,你节省了我很多工作时间。@Vivek Yadav必须将其设置为正确答案。 - Goppinath
因为这个问题,我开始使用自动布局,现在它运行良好。 - Joey
@Joey 我也开始在我的下一个项目中使用它了 :) - Cemen
为什么最新的xCode Beta版本中没有修复这个问题?我的项目中有数百个单元格,不可能手动处理所有这些。 - SAHM
@SAHM,我不知道。这个bug至少存在于第一个非beta版Xcode发布以来。我很久以前就提交了一个bug,他们回复说这是一个重复的bug,但仍然没有任何改变...看起来他们只是想推动我们所有人使用约束 :) - Cemen
显示剩余3条评论

10

最近我遇到了同样的问题。我在UITableViewCell的内容视图中添加了一个标签,每当它隐藏时(x>>320),我意识到问题在于源代码XML。

XML如下:

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="InvoiceCell" rowHeight="60" id="B9T-xx-TCx" customClass="InvoiceCell"> 
    // My custom cell is 60 height
    <rect key="frame" x="0.0" y="0.0" width="320" height="44"/> 
    // Wrong Autoresizing
    <autoresizingMask key="autoresizingMask"/> 
    <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="B9T-xx-TCx" id="nvL-MG-mGs">
        //No rect frame and wrong autoresizing mask
        <autoresizingMask key="autoresizingMask"/>

解决我的问题只需要将"tableViewCell"和"tableViewCellContentView"更改为:

<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="InvoiceCell" rowHeight="60" id="B9T-xx-TCx" customClass="InvoiceCell"> 
    //Add/change this 2 lines in <tableViewCell>
    <rect key="frame" x="0.0" y="0.0" width="320" height="60"/>
    <autoresizingMask key="autoresizingMask" widthSizable="YES"/>

<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="B9T-xx-TCx" id="nvL-MG-mGs">
    //Add/change this 2 lines in <tableViewCellContentView>
    <rect key="frame" x="0.0" y="0.0" width="320" height="60"/>
    <autoresizingMask key="autoresizingMask" widthSizable="YES"/>

所以,问题解决了!希望这能帮到你们。


我很高兴它能帮到你。 - rcmstark

1

经过数小时的尝试,我最终在cellForRowAtIndexPath中手动设置了框架...

在我的情况下,标签应该始终与单元格的右边缘相隔8个点... 我运行它,但标签会消失。因此,在cellForRowAtIndexPath中,我添加了一个小“hack”来修复框架...

if (cell.weight.frame.origin.x != cell.frame.size.width - 138) {
    CGRect frame = cell.weight.frame;
    frame.origin.x = cell.frame.size.width - 138;
    cell.weight.frame = frame;
}

在这种情况下,138是我的标签宽度(131),加上我想要从单元格右侧获得的填充(7)...

虽然不太美观,但对我很有用!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接