旧坑不填,喜开新坑。这两天又计划开发一款macOS应用,之前开发的速记完全是练手,反正现在是不想填坑了,索性再开一个。实际做一个项目,是学习的最佳途径。本文记录了我在开发中遇到的各种问题,以及找到的解决办法,权当以后查阅的笔记。如果能给某位朋友带来帮助,是我的荣幸。如果发现问题,敬请评论吐槽。
开发环境:Xcode 9.1 + Swift4
StatusBar
设置按钮
在applicationDidFinishLaunching方法中调用下面代码,设置StatusBar按钮
1 | func createButtonStatusBar() { |
itemActionShowView是实现的点击方法,Swift4.0之后,必须增加@objc修饰符,是因为Swift4.0之后去掉了Swift3.x对隐式类型推断的特性,必须手动管理@objc,保证oc和Swift代码能互相调用。
设置菜单
在Main.storyboard的Application Scene中拖入NSMenu,将NSMenu拖线到AppDelegate中。如同上面设置statusBar按钮一样,不需要设置按钮的target和action,需要设置menu。
1 | weak var toolMenu: NSMenu! |

添加NSMenu的点击事件,直接拖线action即可。
Dock和Window
隐藏Dock上的应用图标
开发statusBar应用,不需要弹出Window界面,可以在Main.storyboard中的Window Controller Scene中取消Is Initial Controller的勾选。
不需要在Dock上出现应用图标,Info.plist中添加Key - Value:Application is agent (UIElement) - YES
Window居中
1 | window.center()//居中 |
Window的层级关系
Window有一个level属性,标识Window的层级关系。设置Window的level:
1 | self.window?.level = .floating //Window设置为浮动的 |
还有好多其他层级关系,诸如normal、submenu、tornOffMenu……
启动Window
弹出一个Window页面,并将其设置为keyWindow(第一响应者的Window窗口):
1 | //将addWindowController.window启动,并设置为keyWindow |
有时候该方法只能将Window显示出来,并不能设置为keyWindow,如果是normal层级的Window,Window都不能覆盖其他应用窗口,只会在其他应用窗口下面显示。特别是statusBar应用,在其他应用窗口为keyWindow时,点击工具条上的statusBar,启动Window,无法完成keyWindow设置。
需要调用下面代码,将其他应用都取消keyWindow
1 | NSApp.activate(ignoringOtherApps: true) |
NSTextField
输入时隐藏蓝色边框
xib中在Focus Ring中选择None

或者在代码中执行:
1 | textField.focusRingType = .none |
文本框第一响应者
1 | self.window?.makeFirstResponder(textField)//设置为第一响应者 |
获取版本号
macOS版本号
macOS10.10及以上,使用下面的方法:
1 | let version = ProcessInfo.processInfo.operatingSystemVersion |
还有如下方式(已弃用)
1 | #import <CoreServices/CoreServices.h> |
其他方式请见:查找Mac OS X版本号
app版本号
1 | let version = Bundle.main.object(forInfoDictionaryKey: "CFBundleShortVersionString") |
设置快捷键和关闭退出应用
快捷键
xib或storyboard设置快捷键很方便,直接在Key Equivalend输入快捷键即可。

退出应用
从action拖线到Application,选择stop:方法即可:


或者拖线到First Responder,选择terminate:方法

或者调用代码:
1 | NSApplication.shared().terminate(self) |
关闭应用
拖线到First Responder,选择performClose:方法
其他操作
发送邮件
使用NSSharingService调用macOS邮件应用,发送邮件。
1 | let emailService = NSSharingService(named: NSSharingService.Name.composeEmail)! |
在浏览器中打开网页
1 | NSWorkspace.shared.open(URL(string: "http://markmiao.com")!) |