大苏尔大纲视图可扩展项已损坏

我已经启动了一个新的macOS项目(当前在Big Sur beta 3上),并且NSOutlineView节点似乎已损坏。无法分辨这是我还是操作系统。

Here's a sample project演示了此问题。还有一张图片...

大苏尔大纲视图可扩展项已损坏

如您所见,单元格与扩展V形重叠。单击任一人字形将第一行恢复为正确的布局,但不会将其恢复为正确的布局。此外,永远不会调用自动保存方法persistentObjectForItemitemForPersistentObject

测试项目非常简单-我所做的只是将视图库中的SourceView组件添加到默认应用程序项目中,并将委托/数据源连接到视图控制器。还检查了IB中的Autosave Expanded Items,并在Autosave字段中输入了名称。这是整个控制器代码:

class ViewController: NSViewController {
    @IBOutlet var outlineView: NSOutlineView?

    let data = [Node("First item",1),Node("Second item",2)]
}

extension ViewController: NSOutlineViewDataSource {
    func outlineView(_ outlineView: NSOutlineView,child index: Int,ofItem item: Any?) -> Any {
        data[index]
    }
    
    func outlineView(_ outlineView: NSOutlineView,isItemExpandable item: Any) -> Bool {
        true
    }
    
    func outlineView(_ outlineView: NSOutlineView,numberOfChildrenOfItem item: Any?) -> Int {
        item == nil ? data.count : 0
    }
    
    func outlineView(_ outlineView: NSOutlineView,objectvalueFor tableColumn: NSTableColumn?,byItem item: Any?) -> Any? {
        item
    }
    
    func outlineView(_ outlineView: NSOutlineView,persistentObjectForItem item: Any?) -> Any? {
        (item as? Node)?.id
    }
    
    func outlineView(_ outlineView: NSOutlineView,itemForPersistentObject object: Any) -> Any? {
        guard let id = object as? Int else { return nil }
        return data.first { $0.id == id }
    }
}


extension ViewController: NSOutlineViewDelegate {
    func outlineView(_ outlineView: NSOutlineView,viewFor tableColumn: NSTableColumn?,item: Any) -> NSView? {
        guard let node = item as? Node else {
            preconditionFailure("Invalid data item \(item)")
        }
        let view = outlineView.makeView(withIdentifier: nodeCellIdentifier,owner: self) as? NSTableCellView
        view?.textField?.stringValue = node.name
        view?.imageView?.image = NSImage(systemSymbolName: node.icon,accessibilityDescription: nil)
        return view
    }
}


final class Node {
    let id: Int
    let name: String
    let icon: String
    
    init(_ name: String,_ id: Int,_ icon: String = "folder") {
        self.id = id
        self.name = name
        self.icon = icon
    }
}

private let nodeCellIdentifier = NSUserInterfaceItemIdentifier("DataCell")

有没有Mac开发人员可以提供帮助?

iCMS 回答:大苏尔大纲视图可扩展项已损坏

来源列表

什么是来源清单?它是NSOutlineView(这是{ NSTableView)和特殊 治疗。 Finder屏幕截图:

enter image description here

要创建来源列表,您要做的就是设置 selectionHighlightStyle属性 .sourceList。该文档说:

NSTableView的源列表样式。在10.5上,浅蓝色渐变用于突出显示选定的行。

它的作用是什么?在Xcode中跳转到定义并阅读注释(文档中未包含):

NSTableView的源列表样式。在10.10及更高版本上,模糊选择用于突出显示行。在此之前,使用了浅蓝色渐变。注意:具有drawsBackground属性的单元格应将其设置为NO。否则,它们将覆盖NSTableView所做的突出显示。设置此样式将具有将背景色设置为“源列表”背景色的副作用。此外,在NSOutlineView中,更改了以下属性以获取标准的“源列表”外观:indentationPerLevel,rowHeight和intercellSpacing。调用setSelectionHighlightStyle之后:可以根据需要更改其他任何属性。在10.11中,如果将背景颜色从“源列表”背景颜色更改为其他颜色,则该表将不再以源列表模糊样式来绘制所选内容,而是将正常显示为蓝色。

由于您位于大苏尔,因此请注意SelectionHighlightStyle.sourceList已过时。 一个人应该使用styleeffectiveStyle

示例项目

Xcode:

  • 新项目
    • macOS和App(Storyboard和AppKit App委托和Swift)
  • Main.storyboard
    • 添加源列表控件
      • 位置和修复约束
      • 将委托和数据源设置为ViewController
      • 启用自动保存展开的项目
      • 将“自动保存”设置为您想要的任何值(我在那里有FinderLikeSidebar
        • 明智地选择,因为扩展状态保存在用户默认设置中 在NSOutlineView Items FinderLikeSidebar键下
      • 创建@IBOutlet var outlineView: NSOutlineView!
    • 添加另一个文本表单元格视图(无图像)
      • 将标识符设置为GroupCell
  • ViewController.swift
    • 下面的注释代码

屏幕截图

enter image description here

如您所见,它几乎像Finder一样-第二级仍然缩进。原因 这是因为 Documents 节点是可扩展的(有子级)。我有它们在这里演示自动保存。

如果要将所有第二级节点移到左侧,只需删除它们。

enter image description here

ViewController.swift代码

关于它,除了-没有其他要说的内容,请阅读评论:)

import Cocoa

// Sample Node class covering groups & regular items
class Node {
    let id: Int
    let title: String
    let symbolName: String?
    let children: [Node]
    let isGroup: Bool
    
    init(id: Int,title: String,symbolName: String? = nil,children: [Node] = [],isGroup: Bool = false) {
        self.id = id
        self.title = title
        self.symbolName = symbolName
        self.children = children
        self.isGroup = isGroup
    }
    
    convenience init(groupId: Int,children: [Node]) {
        self.init(id: groupId,title: title,children: children,isGroup: true)
    }
}

extension Node {
    var cellIdentifier: NSUserInterfaceItemIdentifier {
        // These must match identifiers in Main.storyboard
        NSUserInterfaceItemIdentifier(rawValue: isGroup ? "GroupCell" : "DataCell")
    }
}

extension Array where Self.Element == Node {
    // Search for a node (recursively) until a matching element is found
    func firstNode(where predicate: (Element) throws -> Bool) rethrows -> Element? {
        for element in self {
            if try predicate(element) {
                return element
            }
            if let matched = try element.children.firstNode(where: predicate) {
                return matched
            }
        }
        return nil
    }
}

class ViewController: NSViewController,NSOutlineViewDelegate,NSOutlineViewDataSource {
    @IBOutlet var outlineView: NSOutlineView!
    
    let data = [
        Node(groupId: 1,title: "Favorites",children: [
            Node(id: 11,title: "AirDrop",symbolName: "wifi"),Node(id: 12,title: "Recents",symbolName: "clock"),Node(id: 13,title: "Applications",symbolName: "hammer")
        ]),Node(groupId: 2,title: "iCloud",children: [
            Node(id: 21,title: "iCloud Drive",symbolName: "icloud"),Node(id: 22,title: "Documents",symbolName: "doc",children: [
                Node(id: 221,title: "Work",symbolName: "folder"),Node(id: 221,title: "Personal",symbolName: "folder.badge.person.crop"),])
        ]),]
    
    override func viewWillAppear() {
        super.viewWillAppear()
        
        // Expanded items are saved in the UserDefaults under the key:
        //
        // "NSOutlineView Items \(autosaveName)"
        //
        // By default,this value is not present. When you expand some nodes,// an array with persistent objects is saved. When you collapse all nodes,// the array is removed from the user defaults (not an empty array,// but back to nil = removed).
        //
        // IOW there's no way to check if user already saw this source list,// modified expansion state,etc. We will use custom key for this
        // purpose,so we can expand group nodes (top level) when the source
        // list is displayed for the first time.
        //
        // Next time,we wont expand anything and will honor autosaved expanded
        // items.
        if UserDefaults.standard.object(forKey: "FinderLikeSidebarAppeared") == nil {
            data.forEach {
                outlineView.expandItem($0)
            }
            UserDefaults.standard.set(true,forKey: "FinderLikeSidebarAppeared")
        }
    }
    
    // Number of children or groups (item == nil)
    func outlineView(_ outlineView: NSOutlineView,numberOfChildrenOfItem item: Any?) -> Int {
        item == nil ? data.count : (item as! Node).children.count
    }
    
    // Child of a node or group (item == nil)
    func outlineView(_ outlineView: NSOutlineView,child index: Int,ofItem item: Any?) -> Any {
        item == nil ? data[index] : (item as! Node).children[index]
    }
    
    // View for our node
    func outlineView(_ outlineView: NSOutlineView,viewFor tableColumn: NSTableColumn?,item: Any) -> NSView? {
        guard let node = item as? Node,let cell = outlineView.makeView(withIdentifier: node.cellIdentifier,owner: self) as? NSTableCellView else {
            return nil
        }
        
        cell.textField?.stringValue = node.title
        
        if !node.isGroup {
            cell.imageView?.image = NSImage(systemSymbolName: node.symbolName ?? "folder",accessibilityDescription: nil)
        }
        
        return cell
    }

    // Mark top level items as group items
    func outlineView(_ outlineView: NSOutlineView,isGroupItem item: Any) -> Bool {
        (item as! Node).isGroup
    }
    
    // Every node is expandable if it has children
    func outlineView(_ outlineView: NSOutlineView,isItemExpandable item: Any) -> Bool {
        !(item as! Node).children.isEmpty
    }
    
    // Top level items (group items) are not selectable
    func outlineView(_ outlineView: NSOutlineView,shouldSelectItem item: Any) -> Bool {
        !(item as! Node).isGroup
    }
    
    // Object to save in the user defaults (NSOutlineView Items FinderLikeSidebar)
    func outlineView(_ outlineView: NSOutlineView,persistentObjectForItem item: Any?) -> Any? {
        (item as! Node).id
    }
    
    // Find an item from the saved object (NSOutlineView Items FinderLikeSidebar)
    func outlineView(_ outlineView: NSOutlineView,itemForPersistentObject object: Any) -> Any? {
        guard let id = object as? Int else { return nil }
        return data.firstNode { $0.id == id }
    }
}
本文链接:https://www.f2er.com/1864500.html

大家都在问