Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto resizing issue in UITableView in Xcode 6

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

like image 534
Vivek Yadav Avatar asked Oct 07 '14 06:10

Vivek Yadav


People also ask

What is the difference between Uitableview and UICollectionView?

Tableiw is a simple list, which displays single-dimensional rows of data. It's smooth because of cell reuse and other magic. 2. UICollectionView is the model for displaying multidimensional data .

How do I change cell height in Swift?

To change the height of tableView cell in ios dynamically, i.e resizing the cell according to the content available, we'll need to make use of automatic dimension property.

What is tableView?

A table view displays a single column of vertically scrolling content, divided into rows and sections. Each row of a table displays a single piece of information related to your app.


3 Answers

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.

like image 82
Cemen Avatar answered Sep 29 '22 01:09

Cemen


I had the same problem recently. I added a label in my UITableViewCell's content view and every time it's hide (x >> 320). I realized that the problem was in the SOURCE CODE XML.

The XML was:

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

To solve my problem is just change "tableViewCell" and "tableViewCellContentView" to:

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

and

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

So, problem solved! I hope this help you guys.

like image 45
rcmstark Avatar answered Sep 29 '22 02:09

rcmstark


After hours of messing with this I just set the frames manually in cellForRowAtIndexPath...

In my situation, the label I had was supposed to always be 8 points away from the right edge of the cell... I would run it and the label would disappear. So in the cellForRowAtIndexPath, I added a little "hack" to fix the frame...

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 in that case was my label's width (131) plus the padding I wanted from the right side of the cell (7)...

It's not exactly pretty, but it works for me!

like image 43
tcd Avatar answered Sep 29 '22 03:09

tcd