【问题标题】:Swift TableViewCell xib doesn't have constraintsSwift TableViewCell xib 没有约束
【发布时间】:2017-09-17 04:13:45
【问题描述】:

我有两个TableViews,当我设计原件时,我使用情节提要中的原型单元设计它,为了使其可重复使用,我尝试将其拉出到.xib 并加载它。当它从cellID.xib 加载时,它会在运行时失去所有约束,并且所有内容都相互叠加。

TableViewController

let cellIdentifier = "cellID"
override func viewDidLoad() {
    super.viewDidLoad()

    tableView.register(UINib(nibName: cellIdentifier, bundle: nil), forCellReuseIdentifier: cellIdentifier)
    tableView.rowHeight = UITableViewAutomaticDimension
    tableView.estimatedRowHeight = 300
}

Storyboard 中的原型单元(用于工作)

复制粘贴到 XIB 时的单元格

约束

XIB 视图层次结构

【问题讨论】:

  • @KKRocks 不,我已经尝试过了。约束在原型单元格中时工作正常,只有当我复制并粘贴到笔尖时它突然停止工作。
  • @KKRocks 你没注意。 UITableViewAutomaticDimension 工作得很好。
  • 尝试在返回单元格之前添加此行:cell.setNeedsUpdateConstraints() cell.updateConstraintsIfNeeded()
  • @KKRocks 没有修复它,我现在收到此警告 Warning once only: Detected a case where constraints ambiguously suggest a height of zero for a tableview cell's content view. We're considering the collapse unintentional and using standard height instead.
  • 你能把视图层次的截图粘贴到笔尖吗(左边的面板就够了)?

标签: ios xcode uitableview uistoryboard xib


【解决方案1】:

问题

在您的问题标题中,您询问了如何解决“Swift TableViewCell xib 没有约束”的问题。此外,在赏金中,您指定答案应该是:

一个充分的答案,说明为什么在移动到 xib,当它们存在于 xib 中时,以及如何解决这个问题。

据我了解,您的问题分为两部分:

  1. 自定义 TableViewCell xib 没有约束的问题
  2. 为什么从 Storyboard 原型复制/粘贴到 xib 时会丢失约束

对于问题 #1,我使用了与您在自定义单元格 xib 中的屏幕截图中显示的几乎所有相同的约束,并且它有效。我将在下面更详细地解释。

对于问题 #2,我发现约束并没有丢失。您可能需要共享您的项目,以便其他人可以复制您遇到的问题。我将具有类似约束的 Storyboard 原型单元复制/粘贴到 xib 上,但约束没有任何问题。所以我可以确认复制/粘贴功能确实有效。

解决方案演示

我创建了以下演示来测试您的问题。请参阅下面的屏幕截图。 tableView 包含六个单元格。第一个和第二个是相同的并且具有重用标识符MyCell。第 3 和第 4 是相同的并且具有重用标识符MyCopyPasteCell。第 5 和第 6 是相同的并且具有重用标识符MyPrototypeCell

MyCell 存在于 xib 中,并使用几乎与屏幕截图中显示的所有相同约束。如您所见,没有约束问题。 MyCopyPasteCell 使用类似的约束,并从 Storyboard 原型复制/粘贴到 xib。 MyPrototypeCell 是复制的原始原型。即使原型被复制到 xib,最后四个单元格看起来完全相同。约束从原型转移到 xib 没有问题。

约束

在下面的代码中,我列出了您在屏幕截图中为 ContentView 显示的所有约束。 (请注意,我还实现了height=20aspect=1:1height=75 约束,尽管它们没有在下面列出。)两个约束被注释掉了,因为我没有使用它们。我还添加了一个约束来替换另一个未使用的约束。

// bottomMargin = Profile Image View.bottom + 188.5
bottomMargin = Profile Image.bottom + 17
Profile Image View.top = Username Label.top
Profile Image View.leading = leadingMargin + 2
Profile Image View.top = topMargin + 20
Username Label.leading = Content Text View.leading    
// Username Label.top = topMargin + 20        
Username Label.trailing = Content Text View.trailing
Username Label.leading = Profile Image View.trailing + 15
trailingMargin = Username Label.trailing + 10
Content Text View.top = Username Label.bottom + 5
Content Text View.leading = leadingMargin + 92
bottomMargin = Content Text View.bottom + 20

第一个注释约束// bottomMargin = Profile Image View.bottom + 188.5 没有意义,因为它将图像底部与单元格底部分开 188.5。这也与您的 Storyboard 中的原型单元格(用于工作) 屏幕截图完全不匹配。我用bottomMargin = Profile Image.bottom + 17替换了它,它只是用17替换了188.5。

第二个注释约束// Username Label.top = topMargin + 20(将用户名和topMargin 分开20)在技术上可以工作。但是,它的功能对于 Profile Image.top = topMargin + 20(将 Profile Image 和 topMargin 分隔 20)和 Profile Image View.top = Username Label.top(将 Profile Image 和 Username 设置为相同的顶部分隔,即 20)是多余的。

MyTableViewController

以下是我的视图控制器。基本上我创建了三个部分,每个部分有两个单元格/行。 MyCellMyCopyPasteTableViewCell 来自 xib,并在 viewDidLoad() 中注册。 MyPrototypeCell 来自 Storyboard,未在 viewDidLoad() 中注册。

//  MyTableViewController.swift
import UIKit    
class MyTableViewController: UITableViewController {

    let myCell = "MyCell"
    let myCopyPasteCell = "MyCopyPasteTableViewCell"
    let myPrototypeCell = "MyPrototypeCell"

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UINib(nibName: myCell, bundle: nil), forCellReuseIdentifier: myCell)
        tableView.register(UINib(nibName: myCopyPasteCell, bundle: nil), forCellReuseIdentifier: myCopyPasteCell)
        tableView.rowHeight = UITableViewAutomaticDimension
        tableView.estimatedRowHeight = 300
    }

    // MARK: - Table view data source
    override func numberOfSections(in tableView: UITableView) -> Int {
        return 3
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 2
    }

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        if indexPath.section == 0 {
            let cell = tableView.dequeueReusableCell(withIdentifier: myCell, for: indexPath)
            return cell
        } else if indexPath.section == 1 {
            let cell = tableView.dequeueReusableCell(withIdentifier: myCopyPasteCell, for: indexPath)
            return cell
        } else {
            let cell = tableView.dequeueReusableCell(withIdentifier: myPrototypeCell, for: indexPath)
            return cell
        }
    }
}

Github 链接

https://github.com/starkindustries/TableViewCellConstraintsTest

【讨论】:

    【解决方案2】:

    问题与解决方案

    您可能已禁用 Autolayout 以便您的 XIB 将其打开 ON 从右上角菜单转到 File Inspector

    您可以按照简单的步骤从 Xib 创建单元格 ?

    1. 使用.xib 创建UITableCell(✅ 也创建 Xib 文件)

    2.给出小区标识符

    3. 布局约束

    ? ImageView 提供来自 TopLeftBottom 的内容 高度常数和纵横比[我设置了边框以显示框架]

    ? UIlabletitle lable 提供三个方面的约束 来自 TopLeftRight NumberOflines=0 (? 不要给出高度常数 - ⚠️ 如果发出警告继续更新约束)

    ? UIlableDescriptions lable 提供来自所有四个方面的约束 NumberOflines=0 (⚠️这会给你一个错误去建议并改变UIlable约束的优先级)

    见下方截图

    改变优先级 而不是再次更新约束

    4.代码在UIViewController

     @IBOutlet var tableView: UITableView!
    
        var cellIdentifier="cell"
        var cellXibName = "MyTableCell"
    
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
    
            tableView.register(UINib(nibName: cellXibName, bundle: nil), forCellReuseIdentifier: cellIdentifier)
            tableView.rowHeight = UITableViewAutomaticDimension
            tableView.estimatedRowHeight = 320
    
    
        }
    
    
    
        func numberOfSections(in tableView1: UITableView) -> Int {
            return 3
        }
    
         func tableView(_ tableView1: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
                let cell :MyTableCell = tableView1.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! MyTableCell
    
    
                return cell
        }
    

    最后输出如你所愿

    输出

    我希望这对你有用......如果这对你有用,请告诉我。

    【讨论】:

      【解决方案3】:

      解决方案:

      我已经解决了您的问题。希望对你有帮助

      我使用uiview来剪辑所有单元格元素。

      和细胞设计

      代码:

      类视图控制器:UIViewController {

      @IBOutlet var tableView: UITableView!
      
      
      
       override func viewDidLoad() {
              super.viewDidLoad()
      
              self.tableView.estimatedRowHeight = 100
              self.tableView.rowHeight = UITableViewAutomaticDimension
              self.tableView.register(UINib(nibName: "TestCell", bundle: Bundle.main), forCellReuseIdentifier: "TestCell")
      
              // Do any additional setup after loading the view, typically from a nib.
          }
      
          override func didReceiveMemoryWarning() {
              super.didReceiveMemoryWarning()
              // Dispose of any resources that can be recreated.
          }
      
      
      }
      
      extension ViewController : UITableViewDataSource, UITableViewDelegate {
          func numberOfSections(in tableView: UITableView) -> Int {
              return 1;
          }
      
          func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
              return 10
          }
      
          func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
              let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as! TestCell
      
              cell.selectionStyle = .none
      
              return cell
          }
      
      }
      

      结果:

      【讨论】:

        【解决方案4】:

        似乎单元格高度是问题,对吧?因此,约束无法正常工作。

        当你使用XIB files时你需要这个覆盖函数:

        override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
                    return 300
        }
        

        但是,您的约束一定是错误的,或者让我们说它们并不完美。我知道他们正在使用情节提要中的原型单元,但这并不能使它们 100% 完美地工作,对吗? 您的UIImageView 没有heightwidth。您应该尝试使用一些约束来设置它。 (或者您设置width 并使用Aspect Ratio 约束)

        【讨论】:

        • 您将如何跨视图控制器重用单元格?设置明确的高度不是答案,因为我需要自动高度。
        • 我可以理解,但 xibs 需要它。试试吧。它应该可以工作,如果没有,您的代码和 xib 文件的实现中还有更多问题。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-12-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-08-30
        相关资源
        最近更新 更多