Search code examples
iosswiftuiviewxib

View Controller not respecting XIB autoresizing mask


A UIView subclass was created in a XIB of type CustomUIView: UIView. It contains several outlets, each one constraint using autoresize (NOT auto layout).

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

This XIB's view is loaded like this:

// In CustomUIView class

  // Initializer used by Interface Builder.
  required init?(coder: NSCoder) {
    super.init(coder: coder)
    initialize()
  }

  func initialize() {
    // Load the view
    let contentView = // typical func to load view from NIB. Owner argument is self. 
    addSubview(contentView)
   }

This CustomUIView is added to a view controller like this: enter image description here

The issue is that the view controller's view is not respecting the autoresizing parameters defined in the XIB.

enter image description here

Now, in theory one can tell the view controller's view to clip to bounds but that is not a proper solution. What am I missing?


Solution

  • It's a little tough to tell, without seeing more details, but...

    Here is an example that's working for me (pretty close to the layout you show):

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

    How it's laid-out in Storyboard:

    enter image description here

    Result:

    enter image description here

    Rotated (to show the auto-resizing):

    enter image description here


    TwoLabelView.swift class:

    class TwoLabelView: UIView {
    
        @IBOutlet var contentView: UIView!
        @IBOutlet var topLabel: UILabel!
        @IBOutlet var botLabel: UILabel!
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            setup()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            setup()
        }
    
        func setup() {
            let nib = UINib(nibName: "TwoLabelView", bundle: nil)
            nib.instantiate(withOwner: self, options: nil)
            addSubview(contentView)
    
            contentView.frame = self.bounds
    
        }
    }
    

    and, source to TwoLabelView.xib file:

    <?xml version="1.0" encoding="UTF-8"?>
    <document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="15505" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
        <device id="retina4_7" orientation="portrait" appearance="light"/>
        <dependencies>
            <deployment identifier="iOS"/>
            <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15510"/>
            <capability name="Safe area layout guides" minToolsVersion="9.0"/>
            <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
        </dependencies>
        <objects>
            <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="TwoLabelView" customModule="scratchy" customModuleProvider="target">
                <connections>
                    <outlet property="botLabel" destination="AKB-d8-jMk" id="QpL-mN-x4M"/>
                    <outlet property="contentView" destination="iN0-l3-epB" id="klb-G5-hj6"/>
                    <outlet property="topLabel" destination="btE-jS-Ur5" id="LkK-0w-J4z"/>
                </connections>
            </placeholder>
            <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
            <view contentMode="scaleToFill" id="iN0-l3-epB">
                <rect key="frame" x="0.0" y="0.0" width="233" height="71"/>
                <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                <subviews>
                    <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="btE-jS-Ur5">
                        <rect key="frame" x="16" y="8" width="197" height="21"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES" flexibleMaxY="YES"/>
                        <color key="backgroundColor" red="0.79527050256729126" green="0.96349185705184937" blue="0.73112398386001587" 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="251" verticalHuggingPriority="251" fixedFrame="YES" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AKB-d8-jMk">
                        <rect key="frame" x="16" y="37" width="197" height="21"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES"/>
                        <color key="backgroundColor" red="0.0" green="0.47790580987930298" blue="0.99864691495895386" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <fontDescription key="fontDescription" type="system" pointSize="17"/>
                        <nil key="textColor"/>
                        <nil key="highlightedColor"/>
                    </label>
                </subviews>
                <color key="backgroundColor" red="0.68716365098953247" green="0.31972628831863403" blue="0.86903256177902222" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
                <viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
                <point key="canvasLocation" x="282.39999999999998" y="-218.1409295352324"/>
            </view>
        </objects>
    </document>
    

    Edit

    Another view of the xib in IB:

    enter image description here

    Notes:

    • File's Owner is set to our custom class
    • The xib's view itself is connected to @IBOutlet var contentView: UIView!

    Edit 2

    To make sure the view loaded from the xib resizes correctly, either:

    A) Set the Layout property for contentView in the xib to Translates Mask Into Constraints, or

    B) If Layout is set to Automatic, we can modify our setup() func:

    func setup() {
        let nib = UINib(nibName: "TwoLabelView", bundle: nil)
        nib.instantiate(withOwner: self, options: nil)
        addSubview(contentView)
    
        // make sure we're using the right sizing method
        if contentView.translatesAutoresizingMaskIntoConstraints == false {
            contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        }
    
        contentView.frame = self.bounds
    
    }