安道

博客文章

第一个 Mac APP

在译完一本书之后,我习惯休息几天,清空对上一本书的记忆,为翻译下一本书做好准备。昨天提交了过去两个月翻译的一本书,本准备好好休息一下,可以今早六点醒了之后就睡不着了。在网上闲逛了大半天,下午决定为自己的一个需求开发一个 Mac APP。

其实这个 APP 计划很久了,只是一直没动手。我给出版社翻译的书,出版之后出版社会赠送几本(一般是五本)样书给我,我自己会留一本作纪念,剩下则免费送给网友(比如这本这本)。如果你看了这两个送书的帖子会发现,我之前使用的赠送规则是有缺陷的:一本的规则是先到先得,一本的规则是根据彩票开奖结果匹配楼层数。这两种赠送规则都会打击用户的参与积极性,要不来晚了就没了,要不只有一定范围内的楼层有效。所以我想开发的就是一个简单的“抽奖”程序。

这类程序实现起来不难,我之前用过 JavaScript 实现的“抽奖”程序。不过因为我最近对 Mac APP 开发比较感兴趣,所以决定自己动手写一个类似的程序。我规划的 UI 及操作流程是这样的:

  • 打开应用后,界面中显示一个标签和一个按钮
  • 标签用于显示“抽奖”的主题
  • 点击按钮后开始抽奖
  • 抽奖结束后弹出一个窗口,显示抽奖结果

在编写样板代码阶段,一切顺利,毕竟样板代码写了很多次,而且基本都一样。可是实现具体功能时却遇到了几个问题。

  • 如何从数组中随机选取元素
  • 如何实现延时操作
  • 如何弹出窗口

随机选取元素涉及到生成随机数,要使用 arc4random_uniform() 函数,还要做些类型转换。这一点我在以前看过的 iOS 视频教程中就知道了,可是记不住该怎么转换类型。熟悉 Ruby 语言的开发者大概都知道,在 Ruby 中 Array 类有个 #sample 方法,用于从数组中随机选取元素。如果在 Swift 中也能这么做就好了。这时我想起了之前在 GitHub 中关注的一个项目——ExSwift。ExSwift 对 Swift 的原生类型做了很多扩展,实现了大量 Ruby 和 Rails 中的实用方法。很巧,ExSwift 也在 Array 类上实现了 sample() 方法(代码)。这样第一个问题解决了——找到了从数组中随机选取元素的方式。

下面是第二个问题。我之所以想实现延迟,是因为这个应用的功能太简单,运行的很快,就像没运行一样。为了让它看起来在背后做了很多事情,我想让结果等待一段时间再出现(在弹出窗口中)。可是怎么实现延迟呢?我首先想到的是“sleep”。可是 sleep() 函数和 NSThread. sleepForTimeInterval(_:) 方法都会导致 UI 无响应,就像假死一样。经过一番搜索之后,我知道这种效果应该使用 dispatch_after(_:_:_:) 函数实现。现在还剩最后一个问题了。

我前面一直在用“弹出”这个词,因为我以为我要实现的效果是“pop-up”。可是搜了好久都没找到相关的 API,最后才发现应该使用“提醒”(NSAlert)。不过在使用 beginSheetModalForWindow(_:completionHandler:) 方法时,处理回调用了很长时间。这体现了我对 Swift 语言(尤其是闭包)的理解还很浅显。

大概用了三个小时,期间不断地搜索、查 API 文档和纠错,最终这个应用总算实现了规划的功能,顺利运行起来了。

LuckyMan
LuckyMan

这是我自己规划功能、自己动手开发的第一个 Mac APP,因此特写此文,以作纪念。在开发的过程中,我学到了:

  • Swift 语言是基础
  • 大部分工作是要熟悉 Cocoa API
  • Dash 买得值

我想,再过一段时间这个应用就能派上用场了。