Auto resizing issue in UITableView in Xcode 6

Vivek Yadav picture Vivek Yadav · Oct 7, 2014 · Viewed 7.7k times · Source

I am using auto resizing in xcode 6 in UITableview but it is not working properly. I want to use autoresizing.I have added textfield in static cell in UITableviewController class from storyboard. Textfield beyond the screen either in landscape or portrait. I dont want use autolayout my whole project is in autoresizing. Textfield

Demo Project

Answer

Cemen picture Cemen · Oct 18, 2014

It is Xcode 6 .xib and .storyboard handling issue. Shortly, Xcode sets improper frame to table view cell and its contentView. Let me explain a bit deeper.

How autoresizing masks work

Basically, it bounds view frame to its superview's frame. We can specify what margins and dimensions will be flexible and what will be fixed. When superview change its bounds, our view bounds will also change according to our autoresize specifications. This occured not only at runtime, but in Xcode Interface Builder too. Try to make some view with subviews, set different autoresizing options to the subviews and resize the master view. You'll see that subviews are resized right in Xcode. Convenient, huh?

The source of error

I first discovered exactly same issue after copying table view cells from iPhone storyboard to iPad storyboard. After some digging into .storyboard file, I figured out that cell and its contentView still have frames 320x91 (instead of iPad sizing 768x91) in .storyboard, while on screen and in inspectors it both was correct sizes. it is inconsistency between actual serialized data and visual representation.

<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>

So, when I set cell subview frame according to iPad size (for example x="624" y="19" width="80" height="21"), and flexible left margin. It becomes beyond bounds of the cell internally, while visually it still appears correctly set up. And when storyboard saved and then re-loaded from the file, cell and its contentView automatically resized from 320x91 to 768x91, and that subview due to its autoresizing automatically goes far right.

Now let's take a look at your case. You have the text field with flexible width. And its frame getting wider and wider every time I open the project. Looks like same inconsistency between stored width and visual width. After opening .storyboard of your project, we can see that both table view cell and its contentView does not any frame specified at all! So we can say that in your case Xcode implicitly set some very small frame to both your cell and its contentView.

That's how it looks inside.

<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>

How to fix

There is no final solution found yet, but we can workaround the bug. If Xcode itself cannot set proper frames, we can do it manually. Open the storyboard with any text editor (it's plain XML) and fix the frames:

<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>

Then close Xcode, save the storyboard from your editor, and reopen Xcode. Voila! Text field left its crazy way and now behaves as expected.