正如很多开发者一样,进入一个新平台开发连带学习,通常都会开发一个极简的应用,很多人都会开发Todo类应用,这类应用一般来说比较简单容易上手。我也打算开发一个,一来是练手,二来是写一个自己用的极简Todo类应用。
目前市面上的Todo类应用,一般来说,都比较复杂,太多我不需要的功能了,而且还有一些增值付费,对于我来说,根本没有那么多的复杂需求,只需要一个随手打开和关闭的记录而已,放在托盘上就非常的方便。
所以,需求如下:
- macOS托盘应用,随手打开和关闭;
- 带有分页标签,以便标记不同类型的todo;
- 最好有利用iCloud的数据云同步,方便未来与其他平台同步数据;
基于以上需求,做一个技术选型:
- 由于SwiftUI在macOS上表现实在是不敢恭维,所以选用传统的AppKit进行开发;
- 基于个人写Android应用的习惯,更倾向于使用代码或者XML的方式构建界面,所以在使用AppKit时,不使用Storyboard或者XIB的方式构建界面。
一、创建项目
打开Xcode,创建一个新的macOS项目,语言选择swift,Interface暂时选storyboard,先创建项目,在稍后删除相关的storyboard文件和配置。
二、项目配置
2.1 删除Main.storyboard
首先,删除自动创建的storyboard文件Main.storyboard,此时再构建项目会出现错误,先不用着急,接下来进行修改。
2.2 替换应用程序入口
其次,在target目录下,创建一个main.swift文件,然后把AppDelegate.swift中的@main
注解删除掉,main.swift文件内容如下:
1 | import Cocoa |
2.3 创建托盘应用的基本框架
在AppDelegate.swift文件中,添加相关代码以实现点击托盘图标,主窗口的显示/隐藏。
创建一个Tray类,用于管理托盘图标的创建和窗口的弹出。
1 | class Tray { |
此类中,接收两个构造参数,一个是图标名称,对应着资源名称或者是SF Symbols图标名称,另外一个参数就是ViewController的具体实现。
在AppDelegate中的applicationDidFinishLaunching
方法中,执行Tray.install()
,就添加了一个系统图标。
1 | class AppDelegate: NSObject, NSApplicationDelegate { |
此处需要注意的是,必须要声明一个Tray的成员变量,如果不声明成员变量,则系统图标不会添加成功。
现在在ViewController中,显示一个Hello World。
1 | class ViewController: NSViewController { |
注意此处的text.translatesAutoresizingMaskIntoConstraints = false
,这里如果不设置的话,弹出窗口是不会填满整个父布局的。
translatesAutoresizingMaskIntoConstraints 是一个布尔属性,用于指示是否启用自动布局中的自动转换。
在 iOS 和 macOS 开发中,通常使用自动布局来管理界面的布局。自动布局系统使用约束(constraints)来描述视图之间的关系和布局规则。当你通过 Interface Builder 或代码创建视图时,默认情况下,视图的 translatesAutoresizingMaskIntoConstraints 属性是设置为 true 的。这意味着视图会根据其 frame 和 autoresizingMask 属性自动转换为相应的约束。
但是,在使用自动布局时,通常推荐将 translatesAutoresizingMaskIntoConstraints 设置为 false。这样做的原因是,如果你手动创建约束来布局视图,那么这些约束将会和自动转换的约束发生冲突,导致布局问题。通过将 translatesAutoresizingMaskIntoConstraints 设置为 false,你可以明确地告诉系统不要自动转换视图的 autoresizingMask 为约束,从而避免这种冲突。
最终的效果如下:
另外,若要应用图标不显示在Docker栏上,需要在Info.plist上设置 Application is agent (UIEelement) 为YES。
Author: boybeak