【问题标题】:High Sierra update causes NSTableView to flip and scrambleHigh Sierra 更新导致 NSTableView 翻转和打乱
【发布时间】:2017-08-18 20:06:42
【问题描述】:

我正在将一个多年来运行良好的现有项目更新到 High Sierra。视图正确加载并且看起来像往常一样:

然后,在我打开一个弹出窗口并再次关闭它后,视图会移动东西,翻转东西,并且通常看起来很疯狂:

请注意,信息标题下降到底部,左侧文本项倒序,日期和下拉文本翻转。发生这种情况时,鼠标交互似乎也很混乱。

我不知道从哪里开始解决这个问题,有人有什么想法吗?

这是使用 xcode 9 beta 5 和 High Sierra Beta 6。
更新:这也在 xcode 9 GM 和 High Sierra GM 种子中

更新

我已经确定当我在该视图所在的 NSTableView 上调用 reloadData 时会发生这种情况。所以现在的问题似乎是如何刷新表格数据而不会出现问题。

【问题讨论】:

  • 看起来好像某些视图改变了它的 Y 方向。我不知道新 SDK 中 NSView 的“翻转”属性是否发生了变化,但我会检查您的代码是否使用它(覆盖 isFlipped)。
  • @Sashah。嗨,我对 reloadData() 和 CAShapeLayers、NSImageView 有类似的问题。 reloadData() 影响出现在 NSImageView 中的 CAShapeLayers。看起来 NSTableView 的 reloadData() 是 High Sierra 中更普遍的问题。 stackoverflow.com/questions/46423303/…
  • 我在生产 High Sierra 中看到了同样的问题
  • 还在 10.13.2 更新中...
  • 我找到了解决办法。在执行对 reloadData() 的调用后,我在主线程上调用以将表视图的宽度调整为 1.0(使用约束),经过短暂的延迟。然后,在又一个短暂的延迟之后,我恢复了约束更改。当您看到反转的文本时,有一个非常小的时刻,但除此之外它有效。

标签: xcode9 macos-high-sierra xcode9-beta5


【解决方案1】:

似乎 reloadData 和 reloadDataForRowIndexes:columnIndexes: 都在 High Sierra 中产生了奇怪的行为。我的解决方法如下:

-(void)refreshAllCells {
    NSMutableIndexSet* rowIndexes = [[NSMutableIndexSet alloc] init];
    if (self.myTable.numberOfRows != 0)
        [rowIndexes addIndexesInRange:NSMakeRange(0, (self.myTable.numberOfRows))];
    [self.myTable removeRowsAtIndexes:rowIndexes withAnimation:NO];
    [self.myTable insertRowsAtIndexes:rowIndexes withAnimation:NO];
}

如果有更好的答案,我仍然希望看到它。

【讨论】:

  • 嗨,我也有同样的问题,遗憾的是,您的解决方案仅部分适用于我......在我实施您的解决方案之前,我的所有单元格都将变得不可见,现在只有显示的单元格可见但当我向下滚动时,其他的仍然不可见。第二次刷新后,所有单元格再次不可见。你有什么建议吗?
  • 我只是在猜测,但可能没有在滚动条上调用 refreshAllCells?
  • WO 有点难看,但确实有效!你拯救了我的一天;-)
【解决方案2】:

对我来说,在我的子类中添加 WantUpdateLayer 解决了这个问题。

override open var wantsUpdateLayer: Bool { return true }

【讨论】:

    【解决方案3】:

    在 IB 中,勾选复选框以在 tableView 的视图上使用 CALayers。我为 tableView 视图层次结构中的所有视图打开了它们,所有翻转都停止了!

    无法发布图片,因为我没有足够的声誉,但此链接显示 IB 复选框:

    【讨论】:

    【解决方案4】:

    我也遇到了这个错误,在实现 another answer 时,我发现了这个错误的真正原因,因为现在引发了一个异常:

    在我的例子中,reloadData 被调用再次,而reloadData 仍在执行中。这导致了渲染问题。

    “循环”是在 tableView(_:, viewFor:, row:) 中调用 tableView.makeView(withIdentifier: identifier, owner: self) 的副作用。 owner: self 导致控制器的awakeFromNib() 再次被调用,这反过来又触发了reloadData()。在我的设置中,我没有(还)为表格单元格使用单独的 XIB,而是使用在表格视图中设置的单元格作为可见的界面生成器。

    因此解决方案是将tableView.makeView(withIdentifier: identifier, owner: self) 更改为tableView.makeView(withIdentifier: identifier, owner: nil),并为表格单元格使用单独的XIB。

    【讨论】:

      【解决方案5】:

      我在 10.13 中也看到了这一点,当时 10.12 工作得很好。奇怪的是,我能够通过在其[layout] 中重新添加单元格视图的子视图来解决此问题:

      - (void)layout{
          if([self needsLayout]){
              for(NSView* v in [[self subviews] copy]){
                  [self addSubview:v];
              }
          }
      
          [super layout];
      }
      

      【讨论】:

        【解决方案6】:

        我也经历过。进一步的测试表明,在更新 tableview 数据源时正在绘制内容。通过消除虚假更新,我能够消除问题。

        我在 draw 方法中重新加载数据,但是我已将数据更新代码移到该方法之外。不确定这是否有助于 OP,但它对我有用。

        【讨论】:

          【解决方案7】:

          突然间,我收到了几封来自客户的邮件,他们抱怨所有表格文本都垂直翻转。他们都使用 macOS Mojave。

          经过大量黑客攻击,并尝试了上面详述的解决方案(可惜无济于事),我决定禁用 NSTableView 的 autoSave 属性:

          //Swift.print("Now setting autosaveName of primaryView to \(self.className).primary")
          //primaryTableView.autosaveName = "\(self.className).primary"
          //primaryTableView.autosaveTableColumns = true
          

          然后问题立即消失了。但现在我的客户无法再更改和保存列宽和顺序。因此,不要以编程方式使用 tableView.autosaveName = "autosavename";我现在在表格视图属性中设置了 autoSave 属性,并在属性检查器中检查了“列信息”(同时显示 xib 文件)。然后它就可以正常工作了..

          我使用当前最新版本的 Xcode (10.1 10B61),问题仅在使用 macOS Mojava 10.14.0 - 10.14.2 时出现。高塞拉利昂和塞拉利昂没有遇到任何麻烦。无论我是在 High Sierra 还是 Mojave 编译项目,都没有区别。

          所以,我希望这对面临这个奇怪问题的其他人有所帮助。我认为这是 macOS Mojave 中的一个错误。

          【讨论】:

          • 唉,几天后打开应用程序几次,不知何故问题又回来了。我现在已经在整个应用程序中完全禁用了自动保存功能,现在它似乎已永久解决。我认为 macOS Mojave 在处理(至少)NSTableView 的自动保存属性时存在错误。保存列设置几次后,首选项(.plist)文件中的某些内容似乎损坏(或至少引发了错误),并且 macOS Mojave 不知何故认为它必须翻转 NSTableView 中的所有单元格。因此,目前,除了禁用自动保存属性之外没有其他解决方案。
          【解决方案8】:

          有同样的问题,可在 High Sierra 和 Mojave 上重现。问题出在 NSOutlineView autosaveName 上,其他解决方案没有帮助。但是我需要这个功能。

          将添加/重新加载数据移动到“viewDidAppear()”而不是“viewDidLoad()”解决了这个问题。

          编辑: 它仅在以下情况下发生:

          1. 存在自动保存
          2. 在应用排序之前,项目会在 viewDidLoad 上加载
          3. 应用排序后会重新加载相同的项目列表
          4. 以上所有情况都发生在 viewDidLoad

          如果您尝试访问 tableView.sortingDescriptors(或 NSOutlineView) - 它会自动应用排序。如果它在加载数据之前发生 - 它可以正常工作。

          在 viewDidAppear 上加载数据看起来仍然是一个更好的选择。

          【讨论】:

            猜你喜欢
            • 2018-03-07
            • 1970-01-01
            • 2019-02-08
            • 2018-05-06
            • 2018-06-09
            • 1970-01-01
            • 1970-01-01
            • 2018-06-19
            • 2018-03-14
            相关资源
            最近更新 更多