【问题标题】:View-Based NSTableView Scrolling Performance基于视图的 NSTableView 滚动性能
【发布时间】:2020-10-26 16:20:11
【问题描述】:

我有一个 NSTableView,它的父级是 NSMenuItem 的视图。 NSTableView 是一个基于视图的表。我使用来自 NSArrayController 的数据绑定来填充表。

在 NSTableView 中滚动的性能非常糟糕。滚动功能似乎不是“连续的”,只有在我将手指从触控板上抬起时才会滚动。这种行为有点像当您有一个文本字段时,它只在按下返回键时发送其操作,而不是连续发送操作。

如果我打开和关闭菜单的次数足够多,表格将在 NSTableView 的一部分中平滑滚动,但很快就会恢复为生涩的滚动。我也可以单击并拖动以相对流畅地有效滚动行,但同样,两指滚动手势超级笨拙。

下面是如何填充表格的代码。在 IB 中,文本字段绑定到 name 属性,NSImageView 绑定到名为 AmphRunningApp 的自定义类的图标属性。

AmphRunningApp 类:

import Foundation
import Cocoa

class AmphRunningApp: NSObject
{
    @objc var app: NSRunningApplication
    @objc var name: String
    @objc var icon: NSImage

init(app: NSRunningApplication, name: String, icon: NSImage)
{
    self.name = name
    self.app = app
    self.icon = icon
}

填充表格:

@IBAction @objc func updateRunningAppsTable(sender: Any)
{
    // Get all currently running apps
    // and sort them alphabetically by localized name:
    
    let runningApps = NSWorkspace.shared.runningApplications.sorted
    {
        $0.localizedName! < $1.localizedName!
    }

    // For every running app,
    // add it to the array controller:
    
    for app in runningApps
    {
        var duplicateApp = false
        
        // Check that this app does not already exist in the array controller
        for dupeApp in self.menuRunningAppAC.arrangedObjects as! [AnyObject]
        {
            if dupeApp.name == app.localizedName
            {
                duplicateApp = true
            }
        }

        // If this app has not already been added
        // to the array controller, add it
        if duplicateApp == false
        {
            self.menuRunningAppAC.addObject(AmphRunningApp(app: app, name: app.localizedName!, icon: app.icon!))
        }
    }

    self.statusMenuAppTable.reloadData()
}

【问题讨论】:

  • 填充表格的代码是什么样的?
  • 嗨@PhillipMills,感谢您的关注。我已将代码添加到问题中。非常感谢您的意见!
  • 我还添加了另一个更新,试图更好地解释这种行为。似乎只有当我将手指从触控板上抬起时才会发生滚动,滚动应该是连续的,而不是等待我完成/停止滚动手势。
  • 好的最后评论。我想我想通了,但根本原因仍然是个谜。请参阅下面关于 GCD 的回答。

标签: swift scroll nstableview


【解决方案1】:

这个问题似乎与 NSStatusItem 的按钮属性和 GCD 上的 performClick() 函数有关。如果我只是为我的 NSStatusItem 分配一个菜单(并因此通过任何单击(即左键单击或右键单击)打开它,则滚动非常流畅。如果我不使用 GCD 调用 performClick() 函数,滚动也很光滑。**

笨拙的滚动:

@objc func statusItemClicked(_ sender: Any?)
{
    NSApp.activate(ignoringOtherApps: true)

    if (NSApp.currentEvent != nil)
    {
        print("right click")
        let event = NSApp.currentEvent!

        if event.type == NSEvent.EventType.rightMouseUp || event.modifierFlags.contains(.control) // RIGHT-CLICK
        {
            

            // THIS IS THE PROBLEM:
            DispatchQueue.main.asyncAfter(deadline: .now() + 0.01)
            {
                self.statusItem.menu = self.statusItemMenu
                self.statusItem.button?.performClick(nil)
            }
            // END PROBLEM


        }
        else // LEFT-CLICK
        {
            print("left click")
        }
}



黄油般平滑的滚动:

@objc func statusItemClicked(_ sender: Any?)
{
    NSApp.activate(ignoringOtherApps: true)

    if (NSApp.currentEvent != nil)
    {
        print("right click")
        let event = NSApp.currentEvent!

        if event.type == NSEvent.EventType.rightMouseUp || event.modifierFlags.contains(.control) // RIGHT-CLICK
        {
            self.statusItem.menu = self.statusItemMenu
            self.statusItem.button?.performClick(nil)
        }
        else // LEFT-CLICK
        {
            print("left click")
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多