开篇,之前使用 Election + Vue 构建一版 MAC版任务栏日历,但是打包出来后体积很大,而且 Election 发布不到 Mac Store 上。
所以,今天萌生出使用 Swift 原生再写一个,权当是学习 Swift 语言了。
今天,重点在于模拟一个通知栏。
开始
我一直想学习 SwiftUI,这回总算是有了借口了。创建新应用,选择 Interface: SwiftUI, Language: Swift。
在 fanlymenuApp 中,我们把主页面删除:
var body: some Scene {
Settings {
EmptyView()
}
}
这样,就会直接去除主页面布局了,重心放在通知栏上。
这时候,需要使用 NSApplicationDelegateAdaptor
了:
@NSApplicationDelegateAdaptor(AppDelegate.self) var delegate
创建 AppDelegate
类:
class AppDelegate: NSObject, NSApplicationDelegate {}
类的作用是创建一个 NSStatusItem
和点击状态栏弹出一个 NSPopover
:
// Status Bar Item...
var statusItem: NSStatusItem?
// PopOver...
var popOver = NSPopover()
在 func applicationDidFinishLaunching(_ notification: Notification)
方法里我们初始化它们:
// Menu View...
let menuView = ContentView()
// Creating PopOver...
popOver.behavior = .transient
popOver.animates = true
// Setting Empty View Controller...
// And Setting View as SwiftUI View...
// with the help of Hosting Controller...
popOver.contentViewController = NSViewController()
popOver.contentViewController?.view = NSHostingView(rootView: menuView)
这个比较好理解,主要是在 popOver
载入 ContentView
。
这个
ContentView
就是一开始创建项目时就有的 Demo。
把这个 View
当作主要的页面:
// also Making View as Main View...
popOver.contentViewController?.view.window?.makeKey()
下一步创建初始化 NSStatusItem
:
// Creating Status Bar Button...
statusItem = NSStatusBar.system.statusItem(withLength: NSStatusItem.variableLength)
// Safe Check if status Button is Available or not...
if let MenuButton = statusItem?.button {
MenuButton.image = NSImage(systemSymbolName: "icloud.and.arrow.up.fill", accessibilityDescription: nil)
MenuButton.imagePosition = NSControl.ImagePosition.imageLeft
MenuButton.title = "demo"
MenuButton.action = #selector(MenuButtonToggle)
}
创建后,增加它的按钮事件:
// Button Action
@objc func MenuButtonToggle(sender: AnyObject) {
// For Safer Sice...
if popOver.isShown {
popOver.performClose(sender)
} else {
// Showing PopOver
if let menuButton = statusItem?.button {
// Top Get Button Location For Popover Arrow...
self.popOver.show(relativeTo: menuButton.bounds, of: menuButton, preferredEdge: NSRectEdge.maxY)
}
}
}
点击通知栏,在下方弹出 PopOver
页面,就如一开始所示。
到此,基本把状态栏模拟出来了,接下来就是在 dock 隐藏本应用图标,就是简简单单的通知栏应用。
在 Info
增加 Application is agent (UIElement)
为 YES
总结
折腾完 Election
+ Vue
,开始折腾 Swift
,最近也在看 Rust
的书。多学多收益吧,从各种语言里学会一些精髓的东西,挺有意思的。
未完待续