DaFileShare 开发笔记
一直以来都觉得电脑分享文件到手机上比较麻烦,试过不少软件,不是收费很贵就是不太方便,至于通过 USB 线——感觉这个更不方便。每次通过微信,QQ 之类的 IM 传了文件之后,就想要开发一个简单的文件分享工具。
DaFileShare 的代码很简单,分成两个部分:
- Command line 的 http server 提供文件分享功能
- Mac App 对其进行封装,提供拖放支持
开发 DaFileShare 之前没有做过 Mac App 的开发,也没有接触过 Swift,一切都是新学,所以记一下Mac App的开发过程,以及遇到的问题,至于 Command line 部分,没有什么好讲的。
第一个遇到的问题就是拖放
。
拖放
Macos 的拖放是通过剪切板实现的,首先App需要注册拖放的类型。第一个纠结的问题是:在哪里注册?
参考了网上的文章和 Apple 的开发文档,NSView 提供了拖放的支持,但是还需要进行一些处理。经过测试,awakFromNib
是一个很好的入口,哪怕用的是StoryBoard
,一样会进入这个函数。
override func awakeFromNib() { |
因为新手的原因,不知道如何把 NSView 类和 StoryBoard,Google 了很久也没有任何发现,直到后来看到 identity inspector
下的 Custom Class
,尝试着把 StoryBoard 中的 view 的类改为自己的类才算成功。
获取拖放的数据
可能是因为 Swift 的快速发展,网上一些文章已经过时,获取剪切板数据的方法在 Xcode 11.4.1 下已经失效了。下面是可以工作的代码:
override func performDragOperation(_ sender: NSDraggingInfo) -> Bool { |
关闭
第二个遇到的大问题是关闭:view 的关闭,窗口的关闭,App 的关闭。
由于想在退出 App 的时候进行一些处理,特别是 Command line 的 http server 进程的关闭,结果就遇到问题了。
同步关闭
首先,点击窗口上的关闭按钮后,只是关闭了窗口,但是 App 没有退出。再次点击 Dock 上的 App 图标,也没有像其他应用一样再次打开窗口,而是没有任何反应。
因为我不需要再打开窗口,只需要同步关闭,这个比较好处理,在 AppDelegate
中加一个函数即可:
func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool { |
不同的关闭方式
然后,只需要找个地方同一处理关闭事件就好了吧?——然而并不是!
正常的关闭方式有三种:关闭按钮,菜单Quit,Cmd+Q。三种方式,三个表现形式!!
关闭按钮
窗口上的关闭按钮可能是最正常的方式了。点击后,ViewController
的 viewDidDisappear
被调用,但是如果你在 AppDelegate
有写applicationShouldTerminate
函数,你会发现这个函数关闭没有调用到。
菜单 Quit
通过菜单——不管是 Dock 上的菜单还是菜单栏上——的Quit,applicationShouldTerminate
被调用到了,但是,viewDidDisappear
没有调用。
Cmd+Q
一句话,什么都不调用!!
通过查阅资料,是因为在”macOS 10.6”中引入了一个叫做Sudden Termination
的机制来快速关闭 App。由于刚开始接触 macos 开发,不想一开始就钻研太深,还是尽早把 App 实现才是正事,所以只看了如何关闭这个机制。没错,这个Sudden Termination
可以关闭,只需要一行代码:
func applicationDidFinishLaunching(_ aNotification: Notification) { |
至此,这三种关闭方式都会调用到applicationShouldTerminate
和viewDidDisappear
,选一个地方处理就可以。我是在viewDidDisappear
中进行处理,因为主要的逻辑代码在ViewController
中。
异常关闭
异常关闭有两种:一种是程序出现 Exception 导致退出的,一种是被 kill 掉。
根据 Windows 上的经验,第一种应该有一个全局处理比如“unCaughtException” 这样的函数来处理,但是我没有尝试;第二种应该是需要捕获 signal 来处理,我尝试了但是没有成功,于是为了省事,把 kill signal屏蔽掉了:
func applicationDidFinishLaunching(_ aNotification: Notification) { |
开发环境
Xcode 11.4.1,Swift 5,macos 10.15.4
Download
你可以下载 DaFileShare