SwiftUI版通知栏应用开发(1) ——通知栏开发

3,439 阅读2分钟

开篇,之前使用 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 的书。多学多收益吧,从各种语言里学会一些精髓的东西,挺有意思的。

未完待续