Search code examples
swiftuitableviewnslayoutconstraint

UITableViewCell Label's content missing


I am setting a tableView but when running the app, the label's content is not stable, sometimes it shows full content, sometimes it doesn't. Looking for advise. I attached the images for .xib setup and how tableView is displayed. The code is my ViewController enter image description here

enter image description here enter image description here enter image description here


    @IBOutlet weak var tableView: UITableView!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "customCell")
        tableView.estimatedRowHeight = 44
        tableView.rowHeight = UITableView.automaticDimension
        tableView.dataSource = self
        tableView.delegate = self
    }

    func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 4
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as? CustomTableViewCell else {
            return UITableViewCell()
        }
        switch indexPath.row {
        case 0:
            cell.titleLabel.text = "Remaining Last Statement Balance"
            cell.amountLabel.text = "$22198.45"
        case 1:
            cell.titleLabel.text = "Minimum Payment Due"
            cell.amountLabel.text = "$2222198.45"
        case 2:
            cell.titleLabel.text = "Current Ballance"
            cell.amountLabel.text = "$2198.45"
        case 3:
            cell.titleLabel.text = "Last Statement Balance"
            cell.amountLabel.text = "$2198.45"
        default:
            break
        }

        return cell
    }
    
}

Solution

  • I would recommend that you embed your labels in a horizontal stack view:

    enter image description here

    Stack view settings:

    enter image description here

    As you see... far fewer constraints to set.

    You will also want to set the content Hugging and Compression Resistance priorities on the labels...

    Title Label:

    enter image description here

    Amount Label:

    enter image description here

    Here is the source for the cell XIB:

    <?xml version="1.0" encoding="UTF-8"?>
    <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
        <device id="retina6_12" orientation="portrait" appearance="light"/>
        <dependencies>
            <deployment identifier="iOS"/>
            <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21678"/>
            <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
        </dependencies>
        <objects>
            <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
            <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" rowHeight="94" id="mQo-go-dfm" customClass="CustomTableViewCell" customModule="TBPreScroll" customModuleProvider="target">
                <rect key="frame" x="0.0" y="0.0" width="393" height="94"/>
                <autoresizingMask key="autoresizingMask"/>
                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="mQo-go-dfm" id="VQH-35-Ynp">
                    <rect key="frame" x="0.0" y="0.0" width="393" height="94"/>
                    <autoresizingMask key="autoresizingMask"/>
                    <subviews>
                        <stackView opaque="NO" contentMode="scaleToFill" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="gyE-fR-4jD">
                            <rect key="frame" x="20" y="11" width="353" height="72"/>
                            <subviews>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wCe-WN-C6L">
                                    <rect key="frame" x="0.0" y="0.0" width="277" height="72"/>
                                    <color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                    <nil key="textColor"/>
                                    <nil key="highlightedColor"/>
                                </label>
                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="1000" verticalHuggingPriority="251" horizontalCompressionResistancePriority="1000" text="Amount" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tBE-pD-h4s">
                                    <rect key="frame" x="293" y="0.0" width="60" height="72"/>
                                    <color key="backgroundColor" red="0.53920841880000003" green="0.97934550050000002" blue="0.93539970709999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                    <nil key="textColor"/>
                                    <nil key="highlightedColor"/>
                                </label>
                            </subviews>
                        </stackView>
                    </subviews>
                    <constraints>
                        <constraint firstItem="gyE-fR-4jD" firstAttribute="top" secondItem="VQH-35-Ynp" secondAttribute="topMargin" id="IcT-FV-MXp"/>
                        <constraint firstAttribute="bottomMargin" secondItem="gyE-fR-4jD" secondAttribute="bottom" id="Kmb-iH-0hG"/>
                        <constraint firstAttribute="trailingMargin" secondItem="gyE-fR-4jD" secondAttribute="trailing" id="PNM-XS-qfi"/>
                        <constraint firstItem="gyE-fR-4jD" firstAttribute="leading" secondItem="VQH-35-Ynp" secondAttribute="leadingMargin" id="rFD-8G-ZY2"/>
                    </constraints>
                </tableViewCellContentView>
                <connections>
                    <outlet property="amountLabel" destination="tBE-pD-h4s" id="bDf-1M-yrP"/>
                    <outlet property="titleLabel" destination="wCe-WN-C6L" id="cSF-sO-EgO"/>
                </connections>
                <point key="canvasLocation" x="307.63358778625951" y="10.563380281690142"/>
            </tableViewCell>
        </objects>
    </document>
    

    Then your cell class:

    class CustomTableViewCell: UITableViewCell {
        @IBOutlet var titleLabel: UILabel!
        @IBOutlet var amountLabel: UILabel!
    }
    

    and view controller class - slightly modified... I added a single-point red border around the table view so we can see its frame. In storyboard, I inset the table view 20-points on all 4 sides for clarity:

    class CustomTableWithXIBViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
        
        @IBOutlet var tableView: UITableView!
        
        override func viewDidLoad() {
            super.viewDidLoad()
            
            tableView.register(UINib(nibName: "CustomTableViewCell", bundle: nil), forCellReuseIdentifier: "customCell")
            
            // don't need these
            //tableView.estimatedRowHeight = 44
            //tableView.rowHeight = UITableView.automaticDimension
            
            tableView.dataSource = self
            tableView.delegate = self
            
            // let's add a border to the table view
            //  so we can see its frame at run-time
            tableView.layer.borderColor = UIColor.red.cgColor
            tableView.layer.borderWidth = 1
        }
        
        func numberOfSections(in tableView: UITableView) -> Int {
            return 1
        }
        
        func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return 4
        }
        
        func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
            let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
            switch indexPath.row {
            case 0:
                cell.titleLabel.text = "Remaining Last Statement Balance"
                cell.amountLabel.text = "$22198.45"
            case 1:
                cell.titleLabel.text = "Minimum Payment Due"
                cell.amountLabel.text = "$2222198.45"
            case 2:
                cell.titleLabel.text = "Current Ballance"
                cell.amountLabel.text = "$2198.45"
            case 3:
                cell.titleLabel.text = "Last Statement Balance"
                cell.amountLabel.text = "$2198.45"
            default:
                break
            }
            
            return cell
        }
        
    }
    

    Looks like this:

    enter image description here