FinderとNotesには、私が再現しようとしている特異な動作があります。 NSToolbarの 'flexible space'は分割ビューの大きさを考慮しているようです。例えば、第1のボタン群は、左側でサイドバーの右側と整列する。第2のグループのアイコンは、第1の列の右側と整列する。サイドバーを広げると、ツールバーの項目も一緒に移動します。NSToolbarItemsをNSSplitView列に揃えます。
これを再現できますか?
ソリューション
@KenThomasesが提供するソリューションでは、次のように、私はこれを実装している:
final class MainWindowController: NSWindowController {
override func windowDidLoad() {
super.windowDidLoad()
window?.toolbar?.delegate = self
// Make sure that tracking is enabled when the toolbar is completed
DispatchQueue.main.async {
self.trackSplitViewForFirstFlexibleToolbarItem()
}
}
}
extension MainWindowController: NSToolbarDelegate {
func toolbarWillAddItem(_ notification: Notification) {
// Make sure that tracking is evaluated only after the item was added
DispatchQueue.main.async {
self.trackSplitViewForFirstFlexibleToolbarItem()
}
}
func toolbarDidRemoveItem(_ notification: Notification) {
trackSplitViewForFirstFlexibleToolbarItem()
}
/// - Warning: This is a private Apple method and may break in the future.
func toolbarDidReorderItem(_ notification: Notification) {
trackSplitViewForFirstFlexibleToolbarItem()
}
/// - Warning: This method uses private Apple methods that may break in the future.
fileprivate func trackSplitViewForFirstFlexibleToolbarItem() {
guard var toolbarItems = self.window?.toolbar?.items, let splitView = (contentViewController as? NSSplitViewController)?.splitView else {
return
}
// Add tracking to the first flexible space and remove it from the group
if let firstFlexibleToolbarItem = toolbarItems.first, firstFlexibleToolbarItem.itemIdentifier == NSToolbarFlexibleSpaceItemIdentifier {
_ = firstFlexibleToolbarItem.perform(Selector(("setTrackedSplitView:")), with: splitView)
toolbarItems.removeFirst()
}
// Remove tracking from other flexible spaces
for flexibleToolbarItem in toolbarItems.filter({ $0.itemIdentifier == NSToolbarFlexibleSpaceItemIdentifier }) {
_ = flexibleToolbarItem.perform(Selector(("setTrackedSplitView:")), with: nil)
}
}
}
これはうまくいくようです。 2つのコメント:(1) 'toolbarWillAddItem:'は、このメソッドが呼び出されたときにツールバーの項目が更新されないため、わずかに異なる動作が必要です。代わりに 'setTrackedSplitView:'はこのネットアイテムに対して直接呼び出されるべきです。 (2)残りの項目をnilに設定すると、動作が異常になり、種類が「認識できないセレクタ」というエラーが発生します。 – Eitot
残りの** flexible-space **項目は 'nil'を追跡するように設定してください。私は、フードの下に、それらのアイテムのための特定のサブクラスがあると仮定します。以前にそれらのいずれかに設定してから注文を変更した可能性があるため、追跡された分割ビューをクリアする必要があります。 '-toolbarWillAddItem:'に関して、私のコードは 'dispatch_async()'をメインキューに使ってループサイクルの最後までアイテムの更新を延期します。 –
'DispatchQueue.main.async()'でそれを呼び出すことは、アプリケーションが動作しているときにだけ自分のコードで動作しますが、起動時には動作しないようです。あなたはこれをどのように実装したかの例を挙げられますか? – Eitot