如何用 Swift 写一个手电筒 App

花火田丁 花火田丁 2020-02-03 15:11:18 +0000


题图来自于NextDay


这次的 HOW TO 跟以往有些不一样,严格意义上来说,不算一个实操的教程,而是作为一个程序设计思路的展现。或者说,是我努力把自己从复杂的思维模式中捞出来的一个尝试。这个例子是我准备给家里的小朋友讲 Swift 编程的第一个例子。所以,专业人士,可以不用往下看了。

审题

写一个手电筒 App

在我看到这个标题时,首先想到了手机上的手电筒功能,打开手机手电筒,会从闪光灯射出白光来。如果是在黑暗中,状态就是,打开手电筒看到白光,关掉手电筒继续黑暗。

是这样,没错吧。

于是第一反应,这个 App 必须要通过控制手机闪光灯来实现。一上来就控制手机硬件,也太“速成”了吧,不太符合 Apple 一贯循序渐进的风格,要知道这个开发教程是面向毫无开发经验的初学者的呢。

陷入困境

作为一个多年开发经验的程序媛,在这个时候不得不承认自己有点思维定势了(这是后话),我似乎陷入了某种「越想越复杂」的漩涡中,除了控制闪光灯,想不到更简单的办法了。

最后 …… 

就像学生时代做模拟题时一样,我…偷看了答案 🤦‍♀️

啊!原来如此!竟然这么简单!

(这句台词大概在此处等我等得很是辛苦了

审完了题

在这个类似 Hello World 的例子里,取名为「Light」的 App 其实要实现的是一个非常简单的功能:

将屏幕从黑色变为白色。当用户轻点某个按钮时,还可以变回原样。

摘录来自: “使用 Swift 开发 App。” Apple Books.

正如审题时,我想到的,开灯是白光,关灯是黑暗,用屏幕的颜色来表示,最直白不过了。当然不能作为真正意义上的「手电筒」来使用,但白屏时亮度足够的话,也还是能起到「照亮」的作用呢。

我怎么没想到呢?(请往下看,这种灵魂的拷问不止一次

正式开始解题了

根据 Apple 的指引,首先我们需要在屏幕上放一个按钮,我们用 Xcode 的 Interface Builder 在 Storyboard 上添加了一个按钮。

图片来自 Apple Books,版权归原作者所有

首先,我们需要用一个变量来记录目前的状态是黑还是白,通常我们会用一个布尔值 True 或者 False 来标示,比如,我们用 lightOn(灯是否开着)这个变量来表示。给它一个初始值 true,true 为真,表示灯是开着的状态。

var lightOn = true

接着,我们要来处理按钮的事件,实现点击它更改 lightOn 值的功能。

@IBAction func buttonPressed(_ sender: AnyObject) {
lightOn = !lightOn
}

接下来,也就是最核心的部分,通过判断 lightOn 的值来改变屏幕的颜色。

if lightOn {
    view.backgroundColor = .white
} else {
    view.backgroundColor = .black
}

合起来,并且考虑到代码的整洁,业务功能的可复用性,以及日后方便查错,最终这个按钮点击事件的函数如下:

@IBAction func buttonPressed(_ sender: AnyObject) {
lightOn = !lightOn
updateUI()
}
 
func updateUI() {
if lightOn {
view.backgroundColor = .white
} else {
view.backgroundColor = .black
}
}

至此,核心功能其实已经完成了,点击按钮屏幕可以变黑变白。但为了让这个 App 更友好一些,我们来做个小小的优化。

根据 lightOn 的状态改变按钮的文字,就像我们家里开关上都会标着 ON/OFF 一样。

于是,updateUI 函数中就多了两行改变按钮文字的代码。

func updateUI() {
if lightOn {
view.backgroundColor = .white
lightButton.setTitle("Off", for: .normal)
} else {
view.backgroundColor = .black
lightButton.setTitle("On", for: .normal)
}
}

现在,点按或轻点按钮就可以更改背景颜色和按钮文本了。但是有一个缺陷:在点按按钮之前,按钮文本仍显示为“Button”,而不是“On”或“Off”。如何更新代码来解决此问题呢?

我们需要在第一次载入时确保按钮的文本与灯的开关状态相匹配,即,在 viewDidLoad() 函数中调用一次 updateUI()

override func viewDidLoad() {
    super.viewDidLoad()
    updateUI()
}

至今,似乎万事大吉了,App 启动的时候,按钮的文字也会显示为 Off。

最后,我们想想还有没有可以改进的地方?

再看一看按钮,你可能会觉得文本有点多余。对于灯的当前状态(打开或关闭),从背景颜色上即可一目了然。按钮文本对于用户而言是否是必需的?

按钮在屏幕上的位置重要吗?另外,用户在大部分屏幕上都不可轻点,这是不是有点奇怪?

摘录来自: “使用 Swift 开发 App。” Apple Books.

这里将出现第二次「我怎么没想到呢?」

目的:用户可以轻点屏幕上的任何位置来开灯和关灯。

好了,脑中那个复杂的漩涡又开始启动了,我开始考虑屏幕(view)的点击事件,完全抛开了按钮。然而 Apple 的方案更微妙:

将按钮文本移除并使按钮填满整个屏幕。这样用户可以轻点屏幕上的任何位置来切换背景颜色。

图片来自 Apple Books,版权归原作者所

正如 Apple 所说,同时也是这么去实践的,Apple 自带的系统应用都是极简却又功能强大。

“在构建任何 app 时,一定要抓住 app 设计中的微妙细节,让用户界面尽可能简单直观、功能强大。”

摘录来自: “使用 Swift 开发 App。” Apple Books.

既然不需要按钮文字了,我们需要再次来修改 updateUI() 函数,将更改按钮文字的代码删除。

func updateUI() {
if lightOn {
view.backgroundColor = .white
lightButton.setTitle("Off", for: .normal)
} else {
view.backgroundColor = .black
lightButton.setTitle("On", for: .normal)
}
}

总结

我的总结大概就是那句「这么简单,我怎么没想到呢」

有时候,我们总是习惯性地把事情想得很复杂,而忽略了事情本身真正的意义,有时候,事情就是那么简单。

附上 Apple 的总结

你已成功创建了一个 app,当用户轻点按钮时,屏幕即会在黑色与白色之间进行切换,就像手电筒一样。此外,你还简化了该 app 的设计,并合理地通过删除按钮标题以及将整个屏幕都变成可轻点的区域来改进了用户体验。尽管你对 Swift 的了解有限,但你可以逐行调试代码,参考文档来完成此项目。

摘录来自: “使用 Swift 开发 App。” Apple Books.

有兴趣看完整的示例请移步 Apple 官网,找到「使用 Swift 开发 App」教程,查看第一单元的内容。


关于「HOW TO」系列

这个系列的初衷,我在 回归初心 中提到的,因为平时写的关于「WHY」或者心理活动方面的文章,「HOW TO」系列更偏向于实用。另外一点在于,我发现,有些本行业内认为小儿科或者不值得一提的工具或者方法,对于大多数行业外的人来说,还是比较陌生的,本着「抛砖引玉」的想法,想让大家可以通过这些「砖」打开思路,也可以了解到一些平常不太接触得到的一些东西。

旧文参考:

如何快速制作「一图看懂」

如何用 GitHub 搭建个人博客

如何用 RSSHub 打造个性阅读器

QuickTime Player 实用技巧

如何用 ImageMagick 处理图片

如何用 iMovie 做看上去很高级的视频

如何用 Python 写一个最简单的爬虫

如何用 ffmpeg 处理视频

如何用 ifttt 做一些自动化提醒



撒欢吧
谈理想
聊人生
讲故事
相对论
花火田丁
微信号:huahuoding
花火田丁
不折腾不人生