带有 NSView 子类自定义视图的 NSToolbar 不会在自定义工具栏面板中呈现

问题描述 投票:0回答:1

我在 AppKit 应用程序中使用自定义视图以编程方式创建了一些

NSToolbarItem
。工具栏项目在工具栏中显示(并运行)正常。自定义工具栏时会出现问题。

带有

NSToolbarItem
子类自定义视图的
NSView
确实会在工具栏和 "... 中呈现,或者将默认设置拖到自定义面板的工具栏" 区域(底部),但不在 中“将您最喜欢的项目拖到工具栏...” 自定义面板区域(顶部)。相同的代码生成所有 3 个
NSToolbarItem
实例。

使用

NSButton

NSTextField
 和其他控件作为自定义视图的 
工具栏项目在所有情况下都会呈现,但基于
NSView
的工具栏项目不会呈现。我需要做什么才能使基于
NSView
的自定义工具栏项在自定义工具栏窗格的两个区域中都可见?

这是

NSWindowController
的简化版本,它创建工具栏(并充当工具栏的代理)

import AppKit

public class DocumentWindowController : NSWindowController, NSToolbarDelegate {
    
    private struct ToolbarItemIdentifiers {
        fileprivate static let addPhotos = NSToolbarItem.Identifier("add-photos")
        fileprivate static let thumbnailSize = NSToolbarItem.Identifier("thumbnail-size")
    }
    
    public override init (
        window: NSWindow?
    ) {
        super.init(window: window)

        let toolbar = NSToolbar(identifier: "toolbar-identifier.document")
        toolbar.delegate = self
        toolbar.allowsUserCustomization = true
        toolbar.autosavesConfiguration = true
        toolbar.displayMode = .default
        window?.toolbarStyle = .unified
        window?.titleVisibility = .visible
        window?.toolbar = toolbar
    }
    
    // MARK: - NSToolbarDelegate
    
    public func toolbar (
        _ toolbar: NSToolbar,
        itemForItemIdentifier itemIdentifier: NSToolbarItem.Identifier,
        willBeInsertedIntoToolbar flag: Bool
    ) -> NSToolbarItem? {
        switch itemIdentifier {
            case ToolbarItemIdentifiers.addPhotos:
                let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
                toolbarItem.label = "Add Photos"
                toolbarItem.image = NSImage(systemSymbolName: "plus", accessibilityDescription: "Add Photos Icon")
                toolbarItem.target = self
                toolbarItem.action = #selector(self.addPhotosButtonTapped)
                return toolbarItem
            case ToolbarItemIdentifiers.thumbnailSize:
                let toolbarItem = NSToolbarItem(itemIdentifier: itemIdentifier)
                toolbarItem.label = "Thumbnail Size"
                toolbarItem.view = ThumbnailSizeView() // an unremarkable NSView subclass
                return toolbarItem
            default:
                return nil
        }
    }
    
    public func toolbarAllowedItemIdentifiers (_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        return [
            ToolbarItemIdentifiers.addPhotos,
            ToolbarItemIdentifiers.thumbnailSize
        ]
    }
    
    public func toolbarDefaultItemIdentifiers (_ toolbar: NSToolbar) -> [NSToolbarItem.Identifier] {
        return [
            ToolbarItemIdentifiers.addPhotos,
            ToolbarItemIdentifiers.thumbnailSize
        ]
    }
}

class ThumbnailSizeView : NSView {
    
    private let slider = NSSlider()
    
    init(min minValue: Int64, max maxValue: Int64, initial initialValue: Int64) {
        super.init(frame: .zero)
        
        let minusIcon = NSImageView()
        minusIcon.image = NSImage(
            systemSymbolName: "minus",
            accessibilityDescription: "Smaller"
        )?.withSymbolConfiguration(.init(scale: .small))
        minusIcon.translatesAutoresizingMaskIntoConstraints = false
        minusIcon.setContentCompressionResistancePriority(.required, for: .horizontal)
        minusIcon.setContentHuggingPriority(.required, for: .horizontal)
        addSubview(minusIcon)
        NSLayoutConstraint.activate([
            minusIcon.leadingAnchor.constraint(equalTo: leadingAnchor),
            minusIcon.centerYAnchor.constraint(equalTo: centerYAnchor)
        ])
        
        slider.minValue = Double(minValue)
        slider.maxValue = Double(maxValue)
        slider.intValue = Int32(initialValue)
        slider.sliderType = .linear
        slider.controlSize = .mini
        slider.translatesAutoresizingMaskIntoConstraints = false
        addSubview(slider)
        NSLayoutConstraint.activate([
            slider.leadingAnchor.constraint(equalTo: minusIcon.trailingAnchor, constant: 4),
            slider.centerYAnchor.constraint(equalTo: centerYAnchor),
            slider.widthAnchor.constraint(equalToConstant: 66)
        ])
        
        let plusIcon = NSImageView()
        plusIcon.image = NSImage(
            systemSymbolName: "plus",
            accessibilityDescription: "Larger"
        )?.withSymbolConfiguration(.init(scale: .small))
        plusIcon.translatesAutoresizingMaskIntoConstraints = false
        plusIcon.setContentCompressionResistancePriority(.required, for: .horizontal)
        plusIcon.setContentHuggingPriority(.required, for: .horizontal)
        addSubview(plusIcon)
        NSLayoutConstraint.activate([
            plusIcon.leadingAnchor.constraint(equalTo: slider.trailingAnchor, constant: 4),
            plusIcon.centerYAnchor.constraint(equalTo: centerYAnchor),
            plusIcon.trailingAnchor.constraint(equalTo: trailingAnchor)
        ])
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
}

就上下文而言,我在 macOS Ventura 13.5.1 上使用 Xcode 14.3.1

macos appkit programmatically-created nstoolbar nstoolbaritem
1个回答
0
投票

不久前我也遇到了类似的问题...我认为我的情况的修复方法是不总是在工具栏中返回一个新的 NSToolbarItem:itemForItemIdentifier:willBeInsertedIntoToolbar: 而是根据标识符缓存它们并始终返回相同的。自定义面板的副本是通过其他方式在内部创建的......

© www.soinside.com 2019 - 2024. All rights reserved.