CocoaNavigationController
类似于 UINavigationController,macOS
如何使用
let navigationController = CocoaNavigationController(withFrame: NSApp.keyWindow!.frame, rootViewController: nil)
let window = NSWindow(contentViewController: self.navigationController!)
window.makeKeyAndOrderFront(nil)
// Push
let vc = TestViewController(nibName: "TestViewController", bundle: nil)
navigationController.pushViewController(vc, animated: true)
// Pop
navigationController?.popViewController(vc, animated: true)
内部结构
实际上,我们只是在 root 视图包含的两个子视图之间进行切换。
水平排列这两个子视图。然后从右到左滑动整个视图以执行推入(push)操作,反之进行弹出(pop)操作。
Push
◀─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─
┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┐
│ │ │ │
│ │ │ │
│ From │ │ To │
│ │ │ │
│ │ │ │
└ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ┘
─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ▶
Pop
为了保证过渡的流畅性,我们将 from-view 和 to-view 快照作为占位符,隐藏所有添加/删除操作。
并且,与 iOS 中的 drawViewHierarchyInRect:afterScreenUpdates
类似,NSView 支持以下类似方法
extension NSView {
func snapshot() -> NSImage? {
// Returns a bitmap-representation object suitable for caching the specified portion of the view.
guard let bitmapRep = bitmapImageRepForCachingDisplay(in: bounds) else { return nil }
cacheDisplay(in: bounds, to: bitmapRep)
let image = NSImage()
image.addRepresentation(bitmapRep)
bitmapRep.size = bounds.size
return image
}
}