发表评论后,评论单元格不会自动调整大小

Comment Cell isn’t automatically resizing after a comment is posted

我无法在评论 posted 后正确调整评论单元格的大小。

首次加载评论视图时,一切看起来都不错。

但是,在 post 编辑评论后,单元格仍会保留其先前的大小,不会自动调整大小。

这会导致新评论单元格的尺寸错误(见图):

  1. 首次加载时的评论视图。评论单元格大小正确。

  2. 即将 post 一行评论。

  3. 哦不:新评论已 posted 但使用旧的单元格大小。


注释单元格的自动版式约束在故事板中完成。

评论文本视图的 numberOfLines 属性设置为 0。


在 CommentViewController 中,使用了 estimatedRowHeight 和 automaticDimension:

    self.tableView.estimatedRowHeight = 77
            
    self.tableView.rowHeight = UITableView.automaticDimension

编辑:也使用了 layoutIfNeeded()。

在 CommentTableViewCell class 中,prepareForReuse 被调用:

    override func prepareForReuse()
    {
        super.prepareForReuse()
    }

post编辑新评论后,拉动刷新不会重新调整单元格大小。修复它的唯一方法是单击后退按钮并重新进入评论视图。

如何解决这个问题?

感谢您的宝贵时间。


编辑: 添加了我的故事板、层次结构和约束的屏幕截图


编辑:更新约束,将评论标签设为紫色以提高可见度

显示名称标签顶部到内容视图顶部。

评论标签顶部到显示名称标签底部。

评论标签底部到内容视图底部。

在背景中添加了紫色以使其更清楚发生了什么。

重新加载评论后,评论单元格约束无法正确适应评论。我该如何解决这个问题?

感谢您的宝贵时间。


最终编辑:删除了不必要的代码并在评论中post修改了我的解决方案

让我们从更简单的开始...而不是处理您的 API class,我们只使用一个数组并让 table 个单元格工作。

所以,这是一个视图控制器...

  • 顶部的文本字段和“发送”按钮(因此我们暂时不必担心键盘)
  • a table 视图限制在文本字段下方
  • 一个原型细胞

这就是我们将用于单元格的内容 class - 不需要其他代码,因为约束将处理布局:

class CommentsCell: UITableViewCell {
    
    @IBOutlet var userLabel: UILabel!
    @IBOutlet var commenterLabel: UILabel!
    @IBOutlet var timeLabel: UILabel!
    @IBOutlet var commentLabel: UILabel!
    
}

现在,我们将为示例数据创建一个简单的 struct

struct CommentStruct {
    var userID: String = ""
    var commenterID: String = ""
    var commentTime: String = ""
    var commentText: String = ""
}

下面是我们将用于视图控制器的内容 class - 我已经保留了您的一般代码流程,尽管我们目前没有对它做太多事情:

class CommentsViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    @IBOutlet var commentTextField: UITextField!
    @IBOutlet var tableView: UITableView!
    
    var comments: [CommentStruct] = []
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.dataSource = self
        tableView.delegate = self
        tableView.separatorStyle = .none
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return comments.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let c = tableView.dequeueReusableCell(withIdentifier: "commentsCell", for: indexPath) as! CommentsCell
        
        // get the data
        let cs = comments[indexPath.row]
        
        // set text for labels in the cell
        c.userLabel.text = cs.userID
        c.commenterLabel.text = cs.commenterID
        c.timeLabel.text = cs.commentTime
        c.commentLabel.text = cs.commentText
        
        return c
    }
    
    // Actions performed when the Send button is pressed
    @IBAction func sendButton_TouchUpInside(_ sender: UIButton)
    {
        // Post the comment
        self.postComment()
    }
    
    // This function posts a comment
    func postComment()
    {
        // Store the comment text
        //  make sure text was entered
        guard let commentText = self.commentTextField.text,
              !commentText.isEmpty
        else {
            return
        }
        
        let cs = CommentStruct(userID: "User1",
                               commenterID: "Commenter1",
                               commentTime: "1d",
                               commentText: commentText)

        // insert this data to make it the new "top" comment
        comments.insert(cs, at: 0)
        
        // Hide keyboard
        self.view.endEditing(true)
        
        // Refresh the comment feed
        self.refresh()

    }
    
    // This method refreshes comments in the comment feed
    @objc func refresh()
    {
        // Retrieve comments from the database
        loadComments()
    }
    
    // This method loads the comments for a post
    func loadComments()
    {
        // here you would do your api call to get the comment data
        //  and re-populate your dataSource array
        
        // Reload the table view data
        self.tableView.reloadData()
            
        // Unhide the images, views, text fields and buttons???
        //self.unhideViewElements()
    }
    
}

当我们运行这样的时候,每条输入的评论都会插入到dataSource数组的开头,所以新的评论会出现在最上面:

试一试...当您看到单元格大小合适时,然后将此结构与您的 API 数据存储集成。

这是情节提要的来源,您可以仔细查看它:

<?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="kqQ-83-E1D">
    <device id="retina4_7" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <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>
        <!--Comments View Controller-->
        <scene sceneID="vQJ-Cm-Kfe">
            <objects>
                <viewController id="kqQ-83-E1D" customClass="CommentsViewController" customModule="DrawingTutorial" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="LfR-oh-wEI">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="ReB-5o-kkD">
                                <rect key="frame" x="0.0" y="62" width="375" height="585"/>
                                <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                                <prototypes>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="commentsCell" rowHeight="101" id="NdF-XY-hNL" customClass="CommentsCell" customModule="DrawingTutorial" customModuleProvider="target">
                                        <rect key="frame" x="0.0" y="28" width="375" height="101"/>
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="NdF-XY-hNL" id="eLj-wx-ThB">
                                            <rect key="frame" x="0.0" y="0.0" width="375" height="101"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="person.circle" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="WoV-fE-nM7">
                                                    <rect key="frame" x="16" y="11.5" width="40" height="39"/>
                                                    <color key="backgroundColor" red="0.92143100499999997" green="0.92145264149999995" blue="0.92144101860000005" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                    <constraints>
                                                        <constraint firstAttribute="width" constant="40" id="Duy-4K-awo"/>
                                                        <constraint firstAttribute="width" secondItem="WoV-fE-nM7" secondAttribute="height" multiplier="1:1" id="s3a-Ri-9u1"/>
                                                    </constraints>
                                                </imageView>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="252" text="Display Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="OMA-aF-mTL">
                                                    <rect key="frame" x="64" y="11" width="105" height="21"/>
                                                    <color key="backgroundColor" red="0.45009386540000001" green="0.98132258650000004" blue="0.4743030667" 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="Label" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lII-cx-Qfb">
                                                    <rect key="frame" x="64" y="36" width="295" height="54"/>
                                                    <color key="backgroundColor" red="0.45138680930000002" green="0.99309605359999997" blue="1" 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="username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="H3q-YO-OPD">
                                                    <rect key="frame" x="177" y="12.5" width="68" height="18"/>
                                                    <color key="backgroundColor" red="0.99953407049999998" green="0.98835557699999999" blue="0.47265523669999998" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                    <fontDescription key="fontDescription" type="italicSystem" pointSize="15"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                                <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="time" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="el2-VE-HXg">
                                                    <rect key="frame" x="332.5" y="14.5" width="26.5" height="16"/>
                                                    <color key="backgroundColor" red="1" green="0.83234566450000003" blue="0.47320586440000001" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="13"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                            <constraints>
                                                <constraint firstAttribute="bottomMargin" secondItem="lII-cx-Qfb" secondAttribute="bottom" id="77z-al-5f6"/>
                                                <constraint firstItem="WoV-fE-nM7" firstAttribute="top" secondItem="eLj-wx-ThB" secondAttribute="topMargin" id="EBj-fZ-KPe"/>
                                                <constraint firstItem="H3q-YO-OPD" firstAttribute="firstBaseline" secondItem="OMA-aF-mTL" secondAttribute="firstBaseline" id="He3-PN-s3Q"/>
                                                <constraint firstItem="lII-cx-Qfb" firstAttribute="leading" secondItem="WoV-fE-nM7" secondAttribute="trailing" constant="8" id="J5m-6F-mMX"/>
                                                <constraint firstItem="OMA-aF-mTL" firstAttribute="leading" secondItem="WoV-fE-nM7" secondAttribute="trailing" constant="8" id="OUd-aN-EpF"/>
                                                <constraint firstAttribute="trailingMargin" secondItem="lII-cx-Qfb" secondAttribute="trailing" id="RiF-g5-Kqn"/>
                                                <constraint firstItem="el2-VE-HXg" firstAttribute="firstBaseline" secondItem="H3q-YO-OPD" secondAttribute="firstBaseline" id="Ugz-tb-PDS"/>
                                                <constraint firstItem="WoV-fE-nM7" firstAttribute="leading" secondItem="eLj-wx-ThB" secondAttribute="leadingMargin" id="WVE-gb-IZ3"/>
                                                <constraint firstItem="H3q-YO-OPD" firstAttribute="leading" secondItem="OMA-aF-mTL" secondAttribute="trailing" constant="8" id="dpO-0E-5EY"/>
                                                <constraint firstAttribute="trailingMargin" secondItem="el2-VE-HXg" secondAttribute="trailing" id="lj2-pU-CEd"/>
                                                <constraint firstItem="lII-cx-Qfb" firstAttribute="top" secondItem="OMA-aF-mTL" secondAttribute="bottom" constant="4" id="tPn-WG-oP5"/>
                                                <constraint firstItem="OMA-aF-mTL" firstAttribute="top" secondItem="WoV-fE-nM7" secondAttribute="top" id="uLn-3z-aWP"/>
                                            </constraints>
                                        </tableViewCellContentView>
                                        <color key="backgroundColor" red="0.46202266219999999" green="0.83828371759999998" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                                        <connections>
                                            <outlet property="commentLabel" destination="lII-cx-Qfb" id="e6K-Oh-9GU"/>
                                            <outlet property="commenterLabel" destination="H3q-YO-OPD" id="vrd-FX-yk9"/>
                                            <outlet property="timeLabel" destination="el2-VE-HXg" id="tjS-KJ-azE"/>
                                            <outlet property="userLabel" destination="OMA-aF-mTL" id="n2P-vl-MLU"/>
                                        </connections>
                                    </tableViewCell>
                                </prototypes>
                            </tableView>
                            <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="9T9-jd-9hp">
                                <rect key="frame" x="8" y="8" width="291" height="34"/>
                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                <textInputTraits key="textInputTraits"/>
                            </textField>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="npH-eO-rmF">
                                <rect key="frame" x="307" y="10" width="60" height="30"/>
                                <constraints>
                                    <constraint firstAttribute="width" constant="60" id="IqL-gO-uY2"/>
                                </constraints>
                                <state key="normal" title="Send"/>
                                <connections>
                                    <action selector="sendButton_TouchUpInside:" destination="kqQ-83-E1D" eventType="touchUpInside" id="cFF-G9-YEj"/>
                                </connections>
                            </button>
                        </subviews>
                        <viewLayoutGuide key="safeArea" id="7k7-br-c0C"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <constraints>
                            <constraint firstItem="7k7-br-c0C" firstAttribute="trailing" secondItem="ReB-5o-kkD" secondAttribute="trailing" id="BpD-NC-I8a"/>
                            <constraint firstItem="7k7-br-c0C" firstAttribute="bottom" secondItem="ReB-5o-kkD" secondAttribute="bottom" constant="20" id="LZX-74-J2l"/>
                            <constraint firstItem="ReB-5o-kkD" firstAttribute="leading" secondItem="7k7-br-c0C" secondAttribute="leading" id="MrF-Ev-h4l"/>
                            <constraint firstItem="9T9-jd-9hp" firstAttribute="top" secondItem="7k7-br-c0C" secondAttribute="top" constant="8" id="WSE-8f-4vd"/>
                            <constraint firstItem="9T9-jd-9hp" firstAttribute="leading" secondItem="7k7-br-c0C" secondAttribute="leading" constant="8" id="dOf-rz-39l"/>
                            <constraint firstItem="npH-eO-rmF" firstAttribute="centerY" secondItem="9T9-jd-9hp" secondAttribute="centerY" id="iKO-JR-FeT"/>
                            <constraint firstItem="npH-eO-rmF" firstAttribute="leading" secondItem="9T9-jd-9hp" secondAttribute="trailing" constant="8" id="tFt-L3-xDM"/>
                            <constraint firstItem="7k7-br-c0C" firstAttribute="trailing" secondItem="npH-eO-rmF" secondAttribute="trailing" constant="8" id="xTY-Wm-wIc"/>
                            <constraint firstItem="ReB-5o-kkD" firstAttribute="top" secondItem="9T9-jd-9hp" secondAttribute="bottom" constant="20" id="yR9-xm-4XE"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="commentTextField" destination="9T9-jd-9hp" id="oiN-nx-d3k"/>
                        <outlet property="tableView" destination="ReB-5o-kkD" id="0h3-yw-Kt7"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="MMl-5e-W3I" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="368.80000000000001" y="795.6521739130435"/>
        </scene>
    </scenes>
    <resources>
        <image name="person.circle" catalog="system" width="128" height="121"/>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>

解决方案

几天后阅读了几十个线程,我设法通过向评论文本标签添加高度约束并在每次重复使用单元格时根据评论文本长度手动设置标签高度来解决这个问题.

这不仅解决了评论布局问题,还解决了滚动评论部分导致单元格高度剧烈波动的另一个问题。


以下是我采取的步骤:

  1. 除了单元格的其他布局约束外,还向注释文本标签添加高度约束。

    Link单元格视图中作为出口的高度约束。

    向单元格添加 numberOfLines 属性以跟踪注释标签中的行数。

  2. 在Comment Cell的prepareForReuse()方法中class:

    根据评论文本长度以编程方式设置高度约束的值。

    在我的例子中,高度限制是 numberOfLines 乘以 17(一行文本的注释标签的高度)。

    可以找到计算文本标签中行数的函数

    我将我的线计算函数命名为:calculateMaxLines()。

    // Set the number of lines for the comment label
    cell.commentLabel.numberOfLines =  cell.commentLabel.calculateMaxLines()
    
    // Set the height constraint to numberOfLines * 17
    cell.commentLabelHeightConstraint.constant = CGFloat(cell.commentLabel.numberOfLines) * 17)
    
    // Layout the cell
    cell.contentView.layoutIfNeeded()
    
  3. 在 Comment View Controller 的 tableView 的“cellForRowAt”函数中添加相同的代码。

    这有助于解决我程序中的多个单元格布局问题。

    希望遇到类似问题的人会发现这个答案有用。