🐰

NSSplitViewController傘下の任意のViewControllerを型情報付きで安全に触れるようにするアクセサ

に公開
extension NSSplitViewController {
	
	struct SplitItemInfo<T: NSViewController> {
		let itemIndex: Int
		let item: NSSplitViewItem
		let viewController: T
	}
	
	func firstItemForViewControllerClass(_ class: AnyClass) -> NSSplitViewItem? {
		splitViewItems.first { item in
			type(of: item.viewController) == `class`
		}
	}
	
	func firstPane<T: NSViewController>() -> SplitItemInfo<T>? {
		if let item = firstItemForViewControllerClass(T.self),
		   let index = splitViewItems.firstIndex(of: item),
		   let vc = item.viewController as? T
		{
			return SplitItemInfo<T>(itemIndex: index, item: item, viewController: vc)
		}
		return nil
	}
	
}

class SplitViewController: NSSplitViewController {
	
	// 任意のアクセサを適宜用意(以下例)

	/// サイドバー
	var primarySidebarItemInfo: SplitItemInfo<SidebarViewController>? {
		firstPane()
	}
	
	/// コンテンツ領域
	var contentViewItemInfo: SplitItemInfo<ContentViewController>? {
		firstPane()
	}
	
	/// インスペクタ
	var inspectorViewItemInfo: SplitItemInfo<InspectorViewController>? {
		firstPane()
	}

}

使う時

let splitViewController: SplitViewController =// サイドバーにアクセス
if let info = splitViewController.primarySidebarItemInfo() {
	let vc = info.viewController // SidebarViewController
	let item = info.item // NSSplitViewItem
	let index = info.index // Int (おそらく0になる)
}

// インスペクタにアクセス
if let info = splitViewController.inspectorViewItemInfo() {
	let vc = info.viewController // InspectorViewController
	let item = info.item // NSSplitViewItem
	let index = info.index // Int (構成次第だが、おそらく2になる)
}

Discussion