如何为重用准备约束?

Posted

技术标签:

【中文标题】如何为重用准备约束?【英文标题】:How to prepare constraints for reuse? 【发布时间】:2020-10-19 21:33:26 【问题描述】:

我有一个包含多个部分的UITableViewController。每个部分都包含带有自定义UITableViewCells 的行。该单元格有 4 个主要元素:

姓名标签 数量标签 检查按钮 个人资料图片

我正在努力解决的是如何重复使用单元格。在this 的答案中,我读到与内容无关的事情应该在prepareForReuse 中完成,与内容相关的“重置”应该在cellForRowAt 中完成。但是,我无法弄清楚我该怎么做。目前,一件主要的事情似乎出了问题。

约束未正确“转移”

这是我现在cellForRowAt 中的代码:

        let cell = tableView.dequeueReusableCell(withIdentifier: "taskCell", for: indexPath) as! TaskCell
        let currentItem = sections[indexPath.section].items[indexPath.row]
        
        cell.taskNameLabel.text = currentItem.name
        cell.uid = currentItem.uid
        cell.delegate = self
        cell.indexSection = indexPath.section
        cell.indexRow = indexPath.row
        cell.itemID = currentItem.itemID
        cell.items = sections[indexPath.section].items
        cell.quantity = ""
        cell.quantity = currentItem.quantity
        
        if currentItem.quantity != nil && currentItem.quantity != "" && currentItem.quantity != " " 
            cell.quantityLabel.isHidden = false
            cell.quantityLabel.text = currentItem.quantity?.uppercased()
            cell.taskNameLabel.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = false
         else 
            cell.quantityLabel.isHidden = true
            cell.taskNameLabel.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = true
        
        
        if currentItem.uid == Auth.auth().currentUser?.uid 
            cell.profilePicture.isHidden = true
         else 
            cell.profilePicture.isHidden = false
        
        
        if currentItem.checked 
            cell.checkBoxOutlet.setBackgroundImage(#imageLiteral(resourceName: "checkBoxFILLED "), for: UIControl.State.normal)
         else 
            cell.checkBoxOutlet.setBackgroundImage(#imageLiteral(resourceName: "checkBoxOUTLINE "), for: UIControl.State.normal)
        

cell.taskNameLabel.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = truecell.taskNameLabel.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = false这行被注释掉时,代码呈现的就像左边的模拟器:https://www.loom.com/share/fcc332ff862741a8ae346e43820b0b60?from_recorder=1

发生的情况是,例如,当第 2 行没有数量时,new 第 2 行的数量也被隐藏(而该单元格 应该有数量)。当关于约束的行被注释掉时,一切正常,但是当它被包含时,奇怪的情况发生了。

如何确保约束(将名称标签在 Y 轴居中如果单元格没有数量)准备好重复使用?

很抱歉,如果我不清楚,我真的不知道如何走得更远,坦率地说,迷路了。

致 *** 社区:非常感谢!

【问题讨论】:

【参考方案1】:

听起来您希望输出看起来像这样:

如果是这样,这就是我设计单元格的方式:

那是:

一个按钮 带有两个标签的垂直堆栈视图 图像视图

个人资料图像视图的尾随锚点与内容视图的尾随锚点相距 16 磅,并且它有一个 CenterY 锚点。

按钮被约束Leading: 0, CenterY ... Top和Bottom都大于6

堆栈视图受约束 Leading-to-ButtonTrailing: 8, Trailing-to-ProfileImageViewLeading: -8, CenterY ... and Top 和 Bottom 都大于等于4

这样,我们告诉自动布局使单元格高度:

至少比堆栈视图高 8 点 至少比按钮高 12 分

当我们有一个数量时,两个标签都将被填充并且不隐藏。所以堆栈视图将比按钮高,其顶部/底部约束将优先。

如果我们没有数量,名称标签将可见,但数量标签将隐藏。因此,按钮会更高,其顶部/底部约束将优先。

在这两种情况下,单元格中的所有内容都将保持垂直居中。

这里是单元类的简化版本:

class TaskCell: UITableViewCell 

    @IBOutlet var checkBoxOutlet: UIButton!
    @IBOutlet var taskNameLabel: UILabel!
    @IBOutlet var quantityLabel: UILabel!
    @IBOutlet var profilePicture: UIImageView!
    
    func fillData(_ task: Task, profileImage: UIImage?) -> Void 
        
        let sysName: String = task.checked ? "largecircle.fill.circle" : "circle"
        if let img = UIImage(systemName: sysName) 
            checkBoxOutlet.setBackgroundImage(img, for: .normal)
        
        
        taskNameLabel.text = task.name.uppercased()
        
        // make sure quantity is not " "
        let q = task.quantity.trimmingCharacters(in: .whitespacesAndNewlines)
        quantityLabel.text = q.uppercased()
        quantityLabel.isHidden = q == ""
        
        profilePicture.image = profileImage
        profilePicture.isHidden = profileImage == nil
        
    

这是故事板的源代码,您可以检查单元格布局:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17156" targetRuntime="ios.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="0rh-3w-bzr">
    <device id="retina4_7" orientation="portrait" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17125"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Example Table View Controller-->
        <scene sceneID="RP6-4O-gi2">
            <objects>
                <tableViewController id="0rh-3w-bzr" customClass="ExampleTableViewController" customModule="DelMe" customModuleProvider="target" sceneMemberID="viewController">
                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="9oA-oN-4sp">
                        <rect key="frame" x="0.0" y="0.0"  />
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <prototypes>
                            <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="taskCell" rowHeight="104" id="0OE-gK-JaO" customClass="TaskCell" customModule="DelMe" customModuleProvider="target">
                                <rect key="frame" x="0.0" y="28"  />
                                <autoresizingMask key="autoresizingMask"/>
                                <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="0OE-gK-JaO" id="GeB-v3-7H5">
                                    <rect key="frame" x="0.0" y="0.0"  />
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Rrf-x2-kgv">
                                            <rect key="frame" x="16" y="36.5"  />
                                            <constraints>
                                                <constraint firstAttribute="width" constant="32" id="aBr-zc-Hi1"/>
                                                <constraint firstAttribute="width" secondItem="Rrf-x2-kgv" secondAttribute="height" multiplier="1:1" id="t6J-WJ-4Dq"/>
                                            </constraints>
                                            <state key="normal" backgroundImage="circle" catalog="system"/>
                                        </button>
                                        <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="ugR-45-YpU">
                                            <rect key="frame" x="56" y="31"  />
                                            <subviews>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d1t-1z-Pyt">
                                                    <rect key="frame" x="0.0" y="0.0"  />
                                                    <color key="backgroundColor" red="0.55634254220000001" green="0.97934550050000002" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                    <fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="efT-dG-UOP">
                                                    <rect key="frame" x="0.0" y="24.5"  />
                                                    <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="15"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                        </stackView>
                                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Hlp-8o-qHO">
                                            <rect key="frame" x="319" y="40"  />
                                            <color key="tintColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="width" constant="24" id="4ax-ud-MaN"/>
                                                <constraint firstAttribute="width" secondItem="Hlp-8o-qHO" secondAttribute="height" multiplier="1:1" id="V9i-E8-rqH"/>
                                            </constraints>
                                        </imageView>
                                    </subviews>
                                    <constraints>
                                        <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="ugR-45-YpU" secondAttribute="bottom" constant="4" id="5Tm-8S-wzZ"/>
                                        <constraint firstItem="Rrf-x2-kgv" firstAttribute="top" relation="greaterThanOrEqual" secondItem="GeB-v3-7H5" secondAttribute="topMargin" constant="6" id="D7D-hZ-deP"/>
                                        <constraint firstItem="ugR-45-YpU" firstAttribute="leading" secondItem="Rrf-x2-kgv" secondAttribute="trailing" constant="8" id="F7l-d8-Raf"/>
                                        <constraint firstItem="ugR-45-YpU" firstAttribute="centerY" secondItem="GeB-v3-7H5" secondAttribute="centerY" id="Gzg-V9-jnW"/>
                                        <constraint firstItem="Rrf-x2-kgv" firstAttribute="centerY" secondItem="GeB-v3-7H5" secondAttribute="centerY" id="Kmx-OQ-LVg"/>
                                        <constraint firstItem="ugR-45-YpU" firstAttribute="top" relation="greaterThanOrEqual" secondItem="GeB-v3-7H5" secondAttribute="topMargin" constant="4" id="LVP-0M-KbC"/>
                                        <constraint firstAttribute="trailingMargin" secondItem="Hlp-8o-qHO" secondAttribute="trailing" constant="16" id="QpT-89-Kci"/>
                                        <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="Rrf-x2-kgv" secondAttribute="bottom" constant="6" id="STP-yS-UR0"/>
                                        <constraint firstItem="Rrf-x2-kgv" firstAttribute="leading" secondItem="GeB-v3-7H5" secondAttribute="leadingMargin" id="Sum-If-WiN"/>
                                        <constraint firstItem="Hlp-8o-qHO" firstAttribute="centerY" secondItem="GeB-v3-7H5" secondAttribute="centerY" id="h42-Iy-CAV"/>
                                        <constraint firstItem="Hlp-8o-qHO" firstAttribute="leading" secondItem="ugR-45-YpU" secondAttribute="trailing" constant="8" id="wTj-7Z-ZCr"/>
                                    </constraints>
                                </tableViewCellContentView>
                                <connections>
                                    <outlet property="checkBoxOutlet" destination="Rrf-x2-kgv" id="EVr-hk-wdw"/>
                                    <outlet property="profilePicture" destination="Hlp-8o-qHO" id="HjC-EX-P2D"/>
                                    <outlet property="quantityLabel" destination="efT-dG-UOP" id="vzF-FI-zX3"/>
                                    <outlet property="taskNameLabel" destination="d1t-1z-Pyt" id="kSQ-K6-gqc"/>
                                </connections>
                            </tableViewCell>
                        </prototypes>
                        <connections>
                            <outlet property="dataSource" destination="0rh-3w-bzr" id="Iqt-W7-ziA"/>
                            <outlet property="delegate" destination="0rh-3w-bzr" id="CJ8-AF-j5x"/>
                        </connections>
                    </tableView>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="jyI-jf-7cF" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="183.19999999999999" y="180.35982008995504"/>
        </scene>
    </scenes>
    <resources>
        <image name="circle" catalog="system"  />
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>

【讨论】:

哇。非常感谢您抽出宝贵时间如此清晰和详细地回答这个问题。我马上去看!非常感谢:) 我希望模组允许这个谢谢你的评论,但我想说以下。你是一个绝对的传奇。你不知道我花了多长时间试图修复这个烦人的错误,以及我无法弄清楚它是多么沮丧。您的解决方案完美运行,我非常感谢您花时间如此清晰和详细地解释这一点。非常感谢,非常感谢。 嘿@DonMag,只是跟进我在这段代码中遇到的问题 - moveRow 动画现在消失了。之前,这个self.tableView.moveRow(at: IndexPath(row: indexRow, section: indexSection), to: IndexPath(row: lastRow, section: indexSection)) 动画行更改,但现在它只是有点卡到位。 This is what I mean。你知道为什么会这样吗?非常感谢,- 马特。 @Matt - 很难从那个视频中分辨出来。您必须显示您正在运行的代码。 感谢您的回复; this 是 GitHub 项目,可以吗? “moveRow”在 TableViewController.swift 中的第 393 行。

以上是关于如何为重用准备约束?的主要内容,如果未能解决你的问题,请参考以下文章

如何为 tensorflow 服务准备预热请求文件?

如何为 svmstruct 准备输入文件

如何为所有 Android 分辨率准备图像?

如何为生产准备 nodejs?

如何为超级通胀做好准备

如何为包含大量异常值的 ML 分类任务准备 IOT 数据?