月度存档: 四月 2012

在 Mac App 中支持全屏和文件版本控制

前言

在 Mac OS X 10.7 Lion 中,新增了两个特性对用户来说可能比较有用的特性,一个是全屏程序,一个是文件版本控制。

全屏程序可以使用户集中注意力到一个程序上,并且隐藏菜单栏、Dock 等不相关的界面元素,使得工作区最大化,更加有效地利用有限的屏幕空间。

文件版本控制可以让用户在不借助于 Time Machine、Git 或者 SVN 这些工具的时候,也可以轻松恢复文件到之前保存过的版本,防止一些误操作删除了重要内容。

全屏程序

全屏功能可以让程序以全屏方式显示,这样用户可以拥有最大的操作区域,并隐藏与程序无关的视觉元素。

在全屏方式下,Dock 和菜单栏都会自动隐藏,可以通过将鼠标移动到屏幕边缘的方式来重新显示 Dock 或者菜单栏。

目前全屏程序有一个问题是在使用双屏的情况下,有一个屏幕会无法使用,只能显示背景图片,而不能同时使用两个屏幕,或者将另外一个程序全屏在另一个屏幕。

另外,全屏程序切换是使用水平动画切换,对我来说可能动作太大,不是很习惯,这是题外话了。

要设置一个 App 支持全屏很简单,只需要设置对应 Window 的属性即可。

Full Screen 有两种模式,分别为 NSWindowCollectionBehaviorFullScreenPrimaryNSWindowCollectionBehaviorFullScreenAuxiliary,其中多数时候只需要使用 NSWindowCollectionBehaviorFullScreenPrimary 即可。

在设置 NSWindowCollectionBehaviorFullScreenPrimary 后,就会在相应的 Window 右上角显示一个全屏按钮,用户通过这个按钮就可以切换程序到全屏方式使用。

全屏模式切换菜单

有些时候,为了用户使用方便,需要设置一个快捷键,或者菜单来供用户进行全屏模式的切换,这时,只需要添加一个 NSMenuItem 到主菜单的 View 菜单中,将 selector 连接到 First Responder 的 toggleFullScreen: 即可。

Cocoa 在运行时会自动寻找 View 菜单中 selector 为 toggleFullScreen: 的菜单项目,并根据当前窗体的显示情况来自动更新菜单标题为 Enter Full Screen 或 Exit Full Screen。

文件版本控制

在 Lion 中对普通用户来说,一个非常有用的特性就是文件版本控制了。在不需要 Time Machine,不需要 Git、SVN 等版本控制参与的情况下,只需要程序支持这个功能,就可以直接找回编辑过文件的以前版本。

在文件版本控制之后,其实是自动保存功能在起作用,要实现文件版本控制,只需要 Mac App 实现自动保存即可,文件版本的控制会有框架来做,不需要开发者过多参与。

对于 NSDocument based 的 Mac App 来说,要实现文件自动保存,一般情况下,只需要在 NSDocument 的子类中实现以下方法就行了:

+ (BOOL)autosavesInPlace {
    return YES:
}

当然,这是在 Mac App 中,是以 NSDocument 提供的诸如 - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError 或者 - (NSFileWrapper *)fileWrapperOfType:(NSString *)typeName error:(NSError **)outError 来保存文件内容为基础,而不是自己去实现写文件内容到磁盘,那样的话就算有 autosaveInPlace 也是不行的。

另外,同样需要使用 - (BOOL)readFromURL:(NSURL *)absoluteURL ofType:(NSString *)typeName error:(NSError **)outError 等 NSDocument 提供的 API 来获取内容。

另外,在 NSWindowDelegate 也有一些新的方法,可以控制程序在浏览文件的以往版本时,控制程序窗口的样式,例如大小,设置控件的状态等。例如,在默认情况下,浏览文件以往版本会改变当前文档窗口的大小,而如果不想修改文档窗口大小,只是缩放显示的话,可以在 window:willResizeForVersionBrowserWithMaxPreferredSize:maxAllowedSize: 方法中指定窗口要变化到的目标大小:

- (NSSize)window:(NSWindow *)window willResizeForVersionBrowserWithMaxPreferredSize:(NSSize)maxPreferredFrameSize maxAllowedSize:(NSSize)maxAllowedFrameSize {
    NSSize winSize = [window frame].size;
    return winSize;
}

NSWindowDelegate 的 Managing Presentation in Version Browsers 一节中,还有另外一个 delegate 方法,可以得知当前文档窗口正在进入版本浏览,或者退出版本浏览等状态,从而可以设置界面控件,将一些无关的界面元素隐藏,使用户可以更加清晰的观察到文件不同版本之间的差别。

要实现文件版本控制的支持,开发者并没有很多工作需要做,多数功能已经由框架实现。

参考资料

— EOF —