自定义的 UITableViewCell 约束似乎被忽略了

Posted

技术标签:

【中文标题】自定义的 UITableViewCell 约束似乎被忽略了【英文标题】:Customized UITableViewCell constraints seem to be ignored 【发布时间】:2020-12-18 18:11:34 【问题描述】:

我有一个带有自定义 UITableViewCellUITableView(具体来说,它是一个 SwipeTableViewCell)。我有一个笔尖文件,我在其中布置了(可重复使用的)单元格。一切都按预期工作,在我的设备上看起来很好。当我完成应用程序时,我注意到我对自定义视图没有约束(其他视图中的约束工作得很好)。因此,在添加缺少的约束后,我运行了该应用程序。所有字段(4 个 UITextFields、2 个 UIImageViews)都在单元格的左上角被“挤压”。我认为我做错了什么......删除了所有这些约束......重新运行,它再次看起来不错。在重新添加约束后,同样的事情发生了。我花了几天时间试图发现我做错了什么(这是我的第一个定制单元)。我找到了一个 SO 项目:Autolayout is ignored in Custom UITableViewCell 看起来和听起来都很好,但它与我所拥有的不符,也没有解决我的问题。我也试过不使用笔尖,而是直接将文本字段和图像视图添加到原型单元格......不幸的是,结果相同。我已经阅读了很多教程,但没有一个能解决我的问题。救命!!

class EducationTableViewController: SwipeTableViewController 
    ...
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = super.tableView(tableView, cellForRowAt: indexPath) as! EducationTableCell

        let education = educations[indexPath.row]
        cell.configurateTheCell(education)
        
        return cell
    
    ...
   

class EducationTableCell: SwipeTableViewCell 
    
    @IBOutlet weak var classNameLabel: UILabel!

    override func prepareForReuse() 
        super.prepareForReuse()
        
        classNameLabel.text = nil
    
    
    // MARK: Cell Configuration
    func configurateTheCell(_ education: Education) 
        Bundle.main.loadNibNamed("Education", owner: self, options: nil)

        backgroundColor = UIColor(hexString: education.color)
        let contrastingBgColor = UIColor.init(contrastingBlackOrWhiteColorOn: backgroundColor, isFlat: false)
        
        classNameLabel.text = education.name
        if (contrastingBgColor == UIColor.init(red: 0, green: 0, blue: 0, alpha: 1)) 
            classNameLabel.textColor = K.Education.titleTextColor
         else 
            classNameLabel.textColor = UIColor.yellow
        
        classNameLabel.font = UIFont(name: K.UIConstants.fontNameBold, size: 35)
        contentView.addSubview(classNameLabel)
        ...
      

我在 Storyboard 中为笔尖添加了约束。如果您查看上面的 SO 项目,您会看到我提到的“挤压”,但如果有帮助,我很乐意附上图片。

https://sites.google.com/view/schoolscheduler/home/junk

ios:14.3 X代码:12.3 斯威夫特 5.3.2

【问题讨论】:

您发布的一小段代码看起来有问题。如果您为您的单元格创建一个 nib/xib 文件,则没有理由调用.loadNibNamed(除非您在那里加载另一个 nib 视图?)。另外,如果你在 IB 中设计了你的单元,为什么在运行时添加 classNameLabel 作为子视图? 嗯。我认为这是我在原型单元中看到视图时遗留下来的。让我修改并重新发布代码。 好吧,如果我省略 .loadNibNamed() 那么表中没有任何内容。我已经在 IB 中设计了单元格,但是当它不起作用时将其删除到笔尖(应用约束时视图也“挤压”)。我会贴一张我在 IB 中的照片,也许会更清楚。 嗯...有点混乱。您想要在 xib 中设计您的单元格吗?还是作为故事板原型? 好吧,我只想让它工作! ;-)。我切换回 IB,布置了单元格......在我添加第一个约束之前看起来不错,然后一切都移动到单元格的左上角(即挤压)。谷歌搜索我发现:medium.com/better-programming/…,我克隆并安装了....看起来不错。我仍在尝试看看他们做了我不做的事情。 【参考方案1】:

根据您显示的图像,您做错了一些事情。

首先,对于您使用 XIB 的尝试,您在 xib 中使用了 UIView。应该是UITableViewCell

其次,原型布局...大部分看起来正确(ish)。您已经为 Class Name Label 提供了前导和尾随约束 centerX 约束。 centerX 约束不做任何事情,因为标签已经延伸到前导值和尾随值。此外,您的 Stack View 前导约束可能应该相对于 Star Image View 的后沿,而不是单元格的前导。

看看这里显示的约束:

单元格显示为“单元格”,因为这是我给它的重用标识符,但自定义类设置为 EducationTableCell

输出如下:

这是产生该输出的示例代码:

import UIKit

class EducationTableCell: UITableViewCell 
    
    @IBOutlet var className: UILabel!
    @IBOutlet var classLocation: UILabel!
    @IBOutlet var classDays: UILabel!
    @IBOutlet var classTime: UILabel!
    
    @IBOutlet var starImageView: UIImageView!
    @IBOutlet var itemImageView: UIImageView!
    


class EducationTableViewController: UITableViewController 

    override func viewDidLoad() 
        super.viewDidLoad()
    

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int 
        return 1
    

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
        return 20
    

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! EducationTableCell

        cell.className.text = "Name \(indexPath.row)"
        cell.classLocation.text = "Location \(indexPath.row)"
        cell.classDays.text = "Days \(indexPath.row)"
        cell.classTime.text = "Time \(indexPath.row)"

        return cell
    


这里是 Storyboard 的源代码,因此您可以检查布局约束:

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Rco-aF-G6p">
    <device id="retina4_7" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17506"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Education Table View Controller-->
        <scene sceneID="0rL-fH-xZI">
            <objects>
                <tableViewController id="Rco-aF-G6p" customClass="EducationTableViewController" customModule="PanZoom" 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="Nk0-AL-MEx">
                        <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="cell" rowHeight="138" id="SUJ-72-5Po" customClass="EducationTableCell" customModule="PanZoom" 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="SUJ-72-5Po" id="G9i-wf-fpQ">
                                    <rect key="frame" x="0.0" y="0.0"  />
                                    <autoresizingMask key="autoresizingMask"/>
                                    <subviews>
                                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="className" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mVQ-Zs-26O">
                                            <rect key="frame" x="21" y="16"  />
                                            <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                            <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                            <nil key="textColor"/>
                                            <nil key="highlightedColor"/>
                                        </label>
                                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3yA-G1-vya">
                                            <rect key="frame" x="21" y="56.5"  />
                                            <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="width" constant="50" id="TjC-BK-Udr"/>
                                                <constraint firstAttribute="width" secondItem="3yA-G1-vya" secondAttribute="height" multiplier="1:1" id="vWg-SJ-7vR"/>
                                            </constraints>
                                        </imageView>
                                        <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="cs2-jh-xoS">
                                            <rect key="frame" x="324" y="71.5"  />
                                            <color key="backgroundColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                            <constraints>
                                                <constraint firstAttribute="width" constant="30" id="ndl-Lm-Bz0"/>
                                                <constraint firstAttribute="width" secondItem="cs2-jh-xoS" secondAttribute="height" multiplier="1:1" id="oHy-eo-dLd"/>
                                            </constraints>
                                        </imageView>
                                        <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="6" translatesAutoresizingMaskIntoConstraints="NO" id="tgj-yg-vqL">
                                            <rect key="frame" x="81" y="46.5"  />
                                            <subviews>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="classLocation" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="axi-2z-HNT">
                                                    <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="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="classDays" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="UK3-x3-XGT">
                                                    <rect key="frame" x="0.0" y="26.5"  />
                                                    <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="251" verticalHuggingPriority="251" text="classTime" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="tqR-li-CIc">
                                                    <rect key="frame" x="0.0" y="53"  />
                                                    <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>
                                            </subviews>
                                        </stackView>
                                    </subviews>
                                    <constraints>
                                        <constraint firstAttribute="bottomMargin" relation="greaterThanOrEqual" secondItem="tgj-yg-vqL" secondAttribute="bottom" constant="5" id="0xW-En-RuB"/>
                                        <constraint firstItem="3yA-G1-vya" firstAttribute="top" secondItem="mVQ-Zs-26O" secondAttribute="bottom" constant="20" id="38Z-Q2-z0J"/>
                                        <constraint firstItem="mVQ-Zs-26O" firstAttribute="leading" secondItem="G9i-wf-fpQ" secondAttribute="leadingMargin" constant="5" id="3J5-7X-0l3"/>
                                        <constraint firstItem="cs2-jh-xoS" firstAttribute="leading" secondItem="tgj-yg-vqL" secondAttribute="trailing" constant="10" id="7TA-sg-Zod"/>
                                        <constraint firstItem="mVQ-Zs-26O" firstAttribute="top" secondItem="G9i-wf-fpQ" secondAttribute="topMargin" constant="5" id="8Hh-cA-6Se"/>
                                        <constraint firstItem="3yA-G1-vya" firstAttribute="leading" secondItem="G9i-wf-fpQ" secondAttribute="leadingMargin" constant="5" id="R99-Wc-e7A"/>
                                        <constraint firstAttribute="trailingMargin" secondItem="cs2-jh-xoS" secondAttribute="trailing" constant="5" id="TZq-bM-V5Q"/>
                                        <constraint firstAttribute="trailingMargin" secondItem="mVQ-Zs-26O" secondAttribute="trailing" constant="5" id="YaH-eA-zBR"/>
                                        <constraint firstItem="cs2-jh-xoS" firstAttribute="top" secondItem="mVQ-Zs-26O" secondAttribute="bottom" constant="35" id="YcB-tX-G3j"/>
                                        <constraint firstItem="tgj-yg-vqL" firstAttribute="top" secondItem="mVQ-Zs-26O" secondAttribute="bottom" constant="10" id="r6S-UG-b0o"/>
                                        <constraint firstItem="tgj-yg-vqL" firstAttribute="leading" secondItem="3yA-G1-vya" secondAttribute="trailing" constant="10" id="xdc-Jv-acQ"/>
                                    </constraints>
                                </tableViewCellContentView>
                                <connections>
                                    <outlet property="classDays" destination="UK3-x3-XGT" id="3b4-tW-ATv"/>
                                    <outlet property="classLocation" destination="axi-2z-HNT" id="59P-Dm-VIx"/>
                                    <outlet property="className" destination="mVQ-Zs-26O" id="SaH-dm-Gxi"/>
                                    <outlet property="classTime" destination="tqR-li-CIc" id="FNG-WI-vOC"/>
                                    <outlet property="itemImageView" destination="cs2-jh-xoS" id="MKG-Dz-kFh"/>
                                    <outlet property="starImageView" destination="3yA-G1-vya" id="dDq-hC-USx"/>
                                </connections>
                            </tableViewCell>
                        </prototypes>
                        <connections>
                            <outlet property="dataSource" destination="Rco-aF-G6p" id="Ear-AM-DTS"/>
                            <outlet property="delegate" destination="Rco-aF-G6p" id="DsX-fk-NBi"/>
                        </connections>
                    </tableView>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="ujd-EG-Zzl" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="284" y="174.96251874062969"/>
        </scene>
    </scenes>
    <resources>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>

【讨论】:

谢谢。将在几分钟内尝试。想说“classStarImage”并不总是出现(仅当底层记录发生更改时)因此“ClassInfo Stack View”可能无法与之绑定。我会尝试两种方式并告诉你。 你可能不相信,但你的简单代码对我不起作用。失败太容易了,但我把所有的子视图都“挤”到了左上角。我已经盯着它看了一段时间,但不明白我是怎么搞砸的。 github.com/davidhmobley/TestSchoolItems。我想了一会儿,这可能与我的新 macbook(硅)有关,所以我在我 5 岁的 macbook 上尝试了它......没有任何区别(幸运的是)。我会继续寻找。 突破!!!我刚刚在 Github 项目上注意到“推荐的”rowHeight 是 198 ......我已经将它设置为,我认为,130。当我将它重置为 200 时,它呈现得很好。现在回到我的“真实”项目。如果它有效(我认为它会),我会接受你的回答。 @DavidM - “推荐”行高无关紧要。我在您的 GitHub 项目中看到您也有不需要的行 tableView.rowHeight = 150。我还在您的项目中注意到您将单元格的 Content View 设置为与单元格相同的类 - 这几乎肯定是导致您的问题的原因。 @DavidM - 如果您只想有时显示星图视图,最好的方法可能是将starImageViewclassInfoStackViewitemImageView 放入水平堆栈视图。然后你可以在星形图像视图上设置.isHidden --- 除非你想要空白空间,在这种情况下保持原样(并且仍然使用.isHidden 属性来显示/隐藏它)。

以上是关于自定义的 UITableViewCell 约束似乎被忽略了的主要内容,如果未能解决你的问题,请参考以下文章

在自定义 UITableViewCell 中忽略自动布局

自定义 UITableViewCell 的内容配置错误

带有标题的自定义 UITableViewCell - 约束

具有 AccessoryType 的自定义 UITableViewCell 打破了约束

关于单元重用的自定义 UITableViewCell 约束问题

从 UITableView 中删除以编程方式自定义的 UITableViewCell 时约束中断