首页 > 解决方案 > Xcode 12,“因特征而异”不起作用(如预期的那样)

问题描述

我有一个相对简单的布局,它分为两个主要部分,我用两个UIViews 将其包含在内,以使其更易于管理。

我的目标是提供两种不同的布局,一种用于纵向,一种用于横向。

我的第一个想法是对“宽度”和“高度”都使用“Vary for Traits”,因此,我将情节提要设置为纵向模式,单击“Vary for Traits”,我在纵向模式下应用了我想要的特征,单击“完成”,切换到横向模式并重复该过程。

如您所见,在情节提要中的方向之间切换效果很好

故事板

除了,当我在设备上运行它时......它不起作用......正如预期的那样

实际设备

好的,所以我想,我回去再做一次,但这一次只是改变“宽度”,再一次,它不起作用。

所以,然后我想,我会去老学校。我会添加每个约束并为特定尺寸类设置一个变体......

约束

(我对两个方向都有不同的约束,因此单个约束对两者都没有变体)

而且......再次,这不起作用。在有人告诉我需要在两个方向上勾选“已安装”之前,不,它没有,这只会让 Xcode 生气并在控制台中吐出很多讨厌的评论。

“问题”

所以,“简单”的问题是,我做错了什么?我是否错过了一些非常明显的东西可以使这项工作,或者对肖像和风景有一个单独的约束只是一个非常愚蠢的想法(我虽然“Vary for Traits”基本上是在做的)

一个“hacky”的解决方法

因此,在花了很多时间在这之后,我又回到了过去用于手动创建 UI 的旧“工作流程”

从为每个变体手动创建约束的点开始,我基本上将所有横向和纵向约束放入单独的IBOutlet集合中,当viewWillTransition被调用时,手动取消/激活所需的约束组......

class ViewController: UIViewController {

    @IBOutlet var landscapeConstraints: [NSLayoutConstraint]!
    @IBOutlet var portraitConstraints: [NSLayoutConstraint]!

    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    enum Orientation {
        case landscape
        case portrait
        case unknown
    }
    
    fileprivate var lastOrientation: Orientation = .unknown
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        updateCurrentConstraints(toSize: view.bounds.size)
    }

    override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
        super.viewWillTransition(to: size, with: coordinator)
        coordinator.animate { (ctx) in
            self.updateCurrentConstraints(toSize: size)
        } completion: { (ctx) in
        }
    }
    
    func updateCurrentConstraints(toSize size: CGSize) {
        var orientation: Orientation = .portrait
        
        if size.width > size.height {
            orientation = .landscape
        }
        
        guard orientation != lastOrientation else { return }
        lastOrientation = orientation

        guard let portraitConstraints = portraitConstraints, let landscapeConstraints = landscapeConstraints else {
            print("No constraits")
            return
        }
        
        var activeConstraints = portraitConstraints
        var inactiveConstraints = landscapeConstraints

        if orientation == .landscape {
            activeConstraints = landscapeConstraints
            inactiveConstraints = portraitConstraints
        }

        for constraint in inactiveConstraints {
            constraint.isActive = false
        }
        for constraint in activeConstraints {
            constraint.isActive = true
        }
        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()
    }
}

这行得通,我希望它没有,我希望我刚刚做了一些非常愚蠢的事情......除了hacky解决方法

如果您没有太多事情可做并且想搞砸它,那么有一个源代码库,我用它来测试这个概念并提出我的“超级、真棒”解决方法,因为我很欣赏任何类型的故事板相关问题是......代码中的一个完整的痛苦

标签: iosswiftxcodestoryboard

解决方案


你遇到的问题是你只为wC hRand设置了 Trait Variations wR hC......所以你的约束不知道当你点击组合时该怎么做,例如wC hC(iPhone 8 / iPhone SE 2 / etc) 或wR hR(iPads )。

您想要做的是针对 Height 类改变您的特征。

这是它在 Storyboard 中的外观:

在此处输入图像描述

在此处输入图像描述

如果我选择 RedView 的width = 175约束,属性检查器会显示:

在此处输入图像描述

与 RedView 的width = 250约束相比:

在此处输入图像描述

这是此布局的情节提要源代码......它将正确处理设备旋转,无需代码:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="5gV-rv-xrH">
    <device id="retina6_1" orientation="landscape" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="HjL-cd-83j">
            <objects>
                <viewController id="5gV-rv-xrH" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="hIj-xH-n33">
                        <rect key="frame" x="0.0" y="0.0" width="896" height="414"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Q3p-xw-14f" userLabel="LeftButton">
                                <rect key="frame" x="64" y="5.5" width="46" height="30"/>
                                <color key="backgroundColor" red="0.97625964880000005" green="0.85085996409999998" blue="0.83597719680000004" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
                                <state key="normal" title="Button"/>
                            </button>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="This is a title" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="35a-vA-spC" userLabel="TitleLabel">
                                <rect key="frame" x="118" y="0.0" width="660" height="41"/>
                                <color key="backgroundColor" red="0.83216959239999999" green="0.98548370600000001" blue="0.47333085539999997" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                <fontDescription key="fontDescription" style="UICTFontTextStyleTitle0"/>
                                <nil key="textColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                            <button opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OqS-4d-vWh" userLabel="RightButton">
                                <rect key="frame" x="786" y="5.5" width="46" height="30"/>
                                <color key="backgroundColor" red="0.97625964880000005" green="0.85085996409999998" blue="0.83597719680000004" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
                                <state key="normal" title="Button"/>
                            </button>
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TjE-LU-Mo5" userLabel="RedView">
                                <rect key="frame" x="60" y="49" width="175" height="219"/>
                                <color key="backgroundColor" red="0.96804410220000003" green="0.21863630410000001" blue="0.1990364194" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="175" id="FPV-f9-dlF"/>
                                    <constraint firstAttribute="width" constant="250" id="NhS-uQ-oMA"/>
                                    <constraint firstAttribute="width" secondItem="TjE-LU-Mo5" secondAttribute="height" multiplier="0.8" id="PY6-e6-WhI"/>
                                </constraints>
                                <variation key="default">
                                    <mask key="constraints">
                                        <exclude reference="NhS-uQ-oMA"/>
                                    </mask>
                                </variation>
                                <variation key="heightClass=regular">
                                    <mask key="constraints">
                                        <exclude reference="FPV-f9-dlF"/>
                                        <include reference="NhS-uQ-oMA"/>
                                    </mask>
                                </variation>
                            </view>
                            <view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Y45-dN-gv7" userLabel="YellowView">
                                <rect key="frame" x="243" y="49" width="609" height="344"/>
                                <color key="backgroundColor" red="0.98267000910000002" green="0.80788773300000005" blue="0.061180472370000002" alpha="1" colorSpace="custom" customColorSpace="displayP3"/>
                            </view>
                        </subviews>
                        <viewLayoutGuide key="safeArea" id="9Rq-n0-LVs"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <constraints>
                            <constraint firstItem="Y45-dN-gv7" firstAttribute="leading" secondItem="9Rq-n0-LVs" secondAttribute="leading" id="6IU-UQ-CvM"/>
                            <constraint firstItem="TjE-LU-Mo5" firstAttribute="top" secondItem="35a-vA-spC" secondAttribute="bottom" constant="8" id="BpX-Pw-rla"/>
                            <constraint firstItem="35a-vA-spC" firstAttribute="leading" secondItem="Q3p-xw-14f" secondAttribute="trailing" constant="8" id="FyN-qU-7qE"/>
                            <constraint firstItem="35a-vA-spC" firstAttribute="top" secondItem="9Rq-n0-LVs" secondAttribute="top" id="G1f-Jl-psr"/>
                            <constraint firstItem="Y45-dN-gv7" firstAttribute="top" secondItem="35a-vA-spC" secondAttribute="bottom" constant="8" id="KOB-Fp-exO"/>
                            <constraint firstItem="35a-vA-spC" firstAttribute="centerX" secondItem="hIj-xH-n33" secondAttribute="centerX" id="W6m-QY-p2X"/>
                            <constraint firstItem="Y45-dN-gv7" firstAttribute="leading" secondItem="TjE-LU-Mo5" secondAttribute="trailing" constant="8" id="XLC-WY-foP"/>
                            <constraint firstItem="9Rq-n0-LVs" firstAttribute="bottom" secondItem="Y45-dN-gv7" secondAttribute="bottom" id="esx-I8-2Kb"/>
                            <constraint firstItem="TjE-LU-Mo5" firstAttribute="centerX" secondItem="hIj-xH-n33" secondAttribute="centerX" id="j57-y5-TqD"/>
                            <constraint firstItem="9Rq-n0-LVs" firstAttribute="trailing" secondItem="Y45-dN-gv7" secondAttribute="trailing" id="lLd-bZ-wF2"/>
                            <constraint firstItem="Q3p-xw-14f" firstAttribute="centerY" secondItem="35a-vA-spC" secondAttribute="centerY" id="m4s-gF-g1G"/>
                            <constraint firstItem="OqS-4d-vWh" firstAttribute="leading" secondItem="35a-vA-spC" secondAttribute="trailing" constant="8" id="quQ-DP-nmi"/>
                            <constraint firstItem="9Rq-n0-LVs" firstAttribute="trailing" secondItem="OqS-4d-vWh" secondAttribute="trailing" constant="20" id="uDD-sD-XqW"/>
                            <constraint firstItem="Q3p-xw-14f" firstAttribute="leading" secondItem="9Rq-n0-LVs" secondAttribute="leading" constant="20" id="wgq-II-OyY"/>
                            <constraint firstItem="OqS-4d-vWh" firstAttribute="centerY" secondItem="35a-vA-spC" secondAttribute="centerY" id="wyP-rt-5dh"/>
                            <constraint firstItem="Y45-dN-gv7" firstAttribute="top" secondItem="TjE-LU-Mo5" secondAttribute="bottom" constant="8" id="xQD-Ne-8vP"/>
                            <constraint firstItem="TjE-LU-Mo5" firstAttribute="leading" secondItem="9Rq-n0-LVs" secondAttribute="leading" constant="16" id="zcb-xN-hZU"/>
                        </constraints>
                        <variation key="default">
                            <mask key="constraints">
                                <exclude reference="j57-y5-TqD"/>
                                <exclude reference="xQD-Ne-8vP"/>
                                <exclude reference="6IU-UQ-CvM"/>
                            </mask>
                        </variation>
                        <variation key="heightClass=regular">
                            <mask key="constraints">
                                <exclude reference="zcb-xN-hZU"/>
                                <include reference="j57-y5-TqD"/>
                                <exclude reference="KOB-Fp-exO"/>
                                <include reference="xQD-Ne-8vP"/>
                                <exclude reference="XLC-WY-foP"/>
                                <include reference="6IU-UQ-CvM"/>
                            </mask>
                        </variation>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="AZb-ld-i79" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="74.400000000000006" y="908.09595202398805"/>
        </scene>
    </scenes>
    <resources>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>

推荐阅读