能力型 API
计算机最早出现的时候,并没有操作系统的概念,应用程序直接操纵所有硬件资源。这有两个大问题:一是一台电脑上仅可以同时运行单个程序,二是程序代码是和特定硬件平台绑定的。于是操作系统出现了,以分时的方式让多个程序可以同时运行,同时将硬件细节抽象为更易用的高层 API,应用程序不再需要直接与硬件打交道。
自然地,这个时候操作系统 API 的设计,主要考虑点是「如何优雅的将硬件能力暴露给应用程序」。传统的操作系统几乎都是以这样的理念去设计系统 API,所以在 Windows/Linux 等系统上,你能看到各种五花八门脑洞大开的程序,因为系统 API 提供的是能力。
另外除了硬件能力外,还有一部分是调整 OS 自身功能的能力 API。比方说在 Linux 上通过 PAM 机制自定义用户鉴权。
任务型 API
然而从 iOS 开始,这件事开始被显著地改变了,操作系统的 API 的设计方式不再是单一的提供硬件能力,而更可能是为一个既定任务而设计。
举个例子,为了实现垃圾短信过滤,在一个传统操作系统(如塞班)上的 API 工作流可能是:
- 通过 SMS API 读取用户短信列表。
- 判断是否为垃圾短信。
- 通过 SMS API 将垃圾短信删除。
而在 iOS 上,第三方程序要想进行短信过滤,需要使用 Message Filter app extension,API 工作流为:
- 系统收到一条短信,主动唤起选定的 filter extension 程序。
- 程序被告知该短信的内容。
- 程序告知系统判断结果。
- 系统根据该结果进行后续行为,如单独放入垃圾信息中并不进行提醒。
同样是完成垃圾短信过滤这一个任务,在这两种 API 设计理念下,是完全不同的模式。前者是依靠系统开放的 SMS API 的能力,完成了短信过滤任务,但其实这些 API 可以被用于完成多种多样的任务。而后者在设计 API 时,就是专为短信过滤这个任务而准备的。
这两者的区别在于,能力型设计的 API 灵活度高,给了开发者非常大的想象空间,但是很容易出现各种安全和稳定性隐患。而任务型设计的 API,可以在不断丰富系统功能的同时,继续保证系统安全和稳定。但在这种设计下,开发者是很难跳出 Apple 的预先定义去创造新的功能的。
这确实是一个需要抉择和取舍的事情,包括 macOS 在内,目前 Apple 新提供的 API 大多为任务型 API,能力型 API 在不断地被移除。比如原来可通过 socket filter 来实现防火墙、流量劫持等功能。而在最新的版本中,防火墙必须通过 Content Filter Providers 机制实现。
算法型 API
近些年来,Apple 在不断的向开发者提供一些算法型的 API(不过可能应该叫 Framework 更准确)。这部分 API 并不一定非要由操作系统所提供,他们是一些复杂算法的封装。
比如:
- ARKit(Integrate iOS device camera and motion features to produce augmented reality experiences in your app or game.)
- VisionKit(Use the iOS camera to scan documents like those you capture in the Notes app.)
- ShazamKit(Find information about a specific audio recording when a segment of that recording is part of captured sound.)
- Natural Language Framework
这些算法实现起来相当复杂,一般需要具有相应学术背景的工程师才能做的比较好,或者需要从其他企业购买成熟的 SDK。这对于中小型开发者来说很困难。特别是,如果开发者只是在某个边缘功能上需要用到一点点这些算法时,是绝对不会接受所需要付出的时间或金钱的。
然而 Apple 将这些算法作为 API 直接提供给开发者,让开发者可以轻松的「杀鸡用牛刀」。举例来说,在我的密码管理软件 Elpass 中,允许用户通过摄像头直接扫描文件作为附件。VisionKit 可以轻松地实时从摄像头数据中找到文件边缘,然后将文件平整化,得到非常近似于扫描件的效果。我的工作量大概只有 20 行代码左右,如果不是因为 iOS 提供了 VisionKit,我是不可能去考虑实现这个功能的。
通过将复杂算法封装为 API/Framework 提供给开发者,极大地提高了 iOS App 的应用素质,这确实是一件双赢的事情。当然这样也将不少开发者绑定在了 Apple 生态,因为一旦脱离这些 Framework 应用的核心功能可能都无法实现。