macOS App 中 NSTableView 行中可变高度的可编辑 NSTextFields

Editable NSTextFields with Variable Height in NSTableView Rows in macOS App

Xcode 10.1,Swift 4.2,macOS 10.14.2

我正在尝试为 macOS 制作一个简单的待办事项列表应用程序,其中有一系列 NSTableView 行,每行中都有一个 NSTextField。每个字段都是一个待办事项。我希望扩展 NSTableView 行以适合每个 NSTextField.

中的文本大小

我有以下所有工作:

  1. 设置 NSTextField 中的文本会使 NSTableView 行根据需要展开。我的故事板中设置了自动布局约束。
  2. 使用 tableView.reloadData(forRowIndexes: ..., columnIndexes: ...) 设置文本并正确调整 table 行的大小。 但是执行 tableView.reloadData() 总是会将每个 NSTextField 重置为单行文本,如下所示: 有趣的是,如果您在重新加载整个 table 后单击 NSTextField,该字段会重新调整大小以适合其内容:

我相信我已经在我的 NSTextField 上设置了所有适当的自动布局约束,并且我也在为它使用自定义子类(来自 helpful answer here):

class FancyField: NSTextField{
  override var intrinsicContentSize: NSSize {
    // Guard the cell exists and wraps
    guard let cell = self.cell, cell.wraps else {return super.intrinsicContentSize}

    // Use intrinsic width to jibe with autolayout
    let width = super.intrinsicContentSize.width

    // Set the frame height to a reasonable number
    self.frame.size.height = 150.0

    // Calcuate height
    let height = cell.cellSize(forBounds: self.frame).height

    return NSMakeSize(width, height)
  }

  override func textDidChange(_ notification: Notification) {
    super.textDidChange(notification)
    super.invalidateIntrinsicContentSize()
  }
}

⭐️这是一个示例项目: https://d.pr/f/90CTEh

我不知道还能尝试什么。有什么想法吗?

我认为界面生成器中的约束存在一些基本问题。调整 window 的大小会使一切变得不稳定。另外,您应该在 FancyField class 中的 textDidChange(forBounds:) 中调用 validateEditing()。 我创建了一个示例项目,可以在 Github

上执行您想要的操作

如果您有任何问题,请发表评论。

稍微考虑一下,我想我会在这里添加代码的内容。唯一真正需要工作的是更新 "Tasks" 时对 NSTextField 的更新。以下是 NSTextField 所需的代码。

public class DynamicTextField: NSTextField {
   public override var intrinsicContentSize: NSSize {
      if cell!.wraps {
         let fictionalBounds = NSRect(x: bounds.minX, y: bounds.minY, width: bounds.width, height: CGFloat.greatestFiniteMagnitude)
         return cell!.cellSize(forBounds: fictionalBounds)
      } else {
         return super.intrinsicContentSize
      }
   }

   public override func textDidChange(_ notification: Notification) {
      super.textDidChange(notification)

      if cell!.wraps {
         validatingEditing()
         invalidateIntrinsicContentSize()
      }
   }
}

希望对您有所帮助。