superleeyom / blog

:bookmark: 个人博客仓库,用于记录一些幼稚的想法和脑残的瞬间,欢迎 star、watch,该仓库为个人博客,请不要提 issue ,该仓库后端参考了 @yihong0618 的 gitblog 项目,前端参考了@LoeiFy 的 Mirror 项目,感谢!

Home Page:https://blog.leeyom.top

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

[译]如何阅读Apple开发文档

superleeyom opened this issue · comments

周末外面一直下雨,闲着也是没事,尝试花了几个小时,把 Hacking with Swift 的创始人 Paul Hudson 在2019 年写的一篇关于「How to read Apple’s developer documentation」的文章翻译成了中文,虽然距离这篇文章发表已经过去两三年了,但是里面的**和方法却永远不会过时,希望能帮助大家,以下便是译文:

作者:Paul Hudson,日期:2019年1月18日

对于很多人来说,这篇文章看起来可能会比较奇怪,因为我们大多数人已经习惯了Apple的API文档的使用方式,并且也能快速的找到我们自己想要的东西。

但是有一个有意思的事实是:去年很多朋友希望我写一些关于如何阅读Apple开发文档的文章,比如有:你是如何去查看iOS的API接口的?如何在这些开发文档中找到你想要的东西?如何深入了解这些文档或者接口的底层原理?

你是不是曾经也希望有人帮助你去理解Apple的开发文档呢?其实并不只你一个人,有很多人的都有相同的苦恼。所以我希望这篇文章能对你有所帮助:我会尽力去解释它的整体结构,它有什么好的地方和不好的地方,以及我是如何使用Apple的开发者文档的。

更重要的一点是,我将向你展示那些有经验的人是如何去搜寻相关资料,并且这些资料要比Apple的在线文档更有价值。

“它是什么?” vs “你怎么用它?”

任何的API文档应该有以下5种特性之一:

  1. 接口代码通常需要展示:方法名称和参数、属性名称和类型等,并带有一小段文字描述它的功能是什么,它是做什么的。
  2. API应该有用例指导的描述
  3. 示例代码应该多多使用这些API,以使得它们更加的有用
  4. 展示如何使用基础的API代码片段
  5. 需要有一套总结常见的问题的方法:比如:如何做 X,如何做 Y,以及如何做 Z,等等。

通俗点讲,Apple第1点做的很不错,第2和第3点也做的很多,但是第4点做的相当少,第5点几乎就没有。

所以,如果你正在寻找「如何使用Y去做X」的具体示例,你可以尝试从我的「swift的基础知识」教程学起,这也正是这篇教程的用途。

理解 Apple 的文档所要解决的问题,将帮助你最大限度地利用它。它不是一个结构化的教程——它也不会向你介绍一系列的概念来帮助你实现一个目标,它只是作为苹果支持的数千个API 的参考指南。

寻找类

Apple的在线开发文档在:https://developer.apple.com/documentation/,虽然你有一个Xcode的本地离线版本,但是和我交流过的绝大多数的人都是使用的在线的版本,因为他们可以更容易的找到他们想要的东西。

Apple绝大多数的文档都有接口描述,这也是你看的最多的。我想用一个实际的例子,所以请从在你的浏览器中打开https://developer.apple.com/documentation/ (那是所有苹果开发者文档的主页)。

你会看到苹果所有的 API 都被分成了App Frameworks、Graphics 、Games等类别,并且你已经看到了一个重要的东西:所有深蓝色的文本都是可点击的,点击后它将带你进入特定框架的API文档。它使用相同的字体和大小,没有下划线,老实说,深蓝色链接和黑色文本之间没有太大区别,但你仍然需要留意这些链接,其中有很多,你将大量使用它们并进行深入研究。

现在请从App Frameworks类别中选择UIKit,你会看到它的简要概述(为iOS创建用户界面),一个标记为「重要」的黄色大框,然后是一个类别列表。这些黄色的框框确实值得注意:尽管它们被频繁使用,但它们几乎总能阻止你犯一些基础的错误,从而在以后引发一些奇怪的问题。

这个页面描述了UIKit的类别列表,这是也是大多数人通常会迷失的地方:他们想要学习一些类似于UIImage的东西,以至于他们必须查看整个列表,然后在合适的地方找到它。

在这种情况下,你可能会查看「Resource Management」这个类别,因为它的副标题写着 「管理存储在主可执行文件之外的图像、字符串、storyboards 和 nib 文件」,这听起来好像很有希望。 但是,你会感到失望,你需要向下滚动页面到「Images and PDF」 部分才能找到 UIImage

这就是为什么我交谈过的大多数人只使用他们最喜欢的搜索引擎,他们从搜索引擎中输入他们关心的类,只要它有一个像「UI」、「SK」或类似的前缀,通常搜索引擎的第一结果就是他们想要的。

不要误解我的意思,我知道这种方法并不理想。但是当你要搜索一个类,你要么去搜索引擎搜索,要么去 https://developer.apple.com/documentation/ 查询,选择一个框架,选择一个类别,然后再选择一个类,很显然第一种方式会更快。

重要的是:无论你选择哪种方法,结果都是一样的,最终都会出现在同一个地方,所以选择最适合你自己的搜索方式就行。现在,请你找到并选择UIImage

阅读类的接口

一旦你选择了你关心的类,页面就会有四个主要组成部分:概述、版本摘要、接口和关系。

概述是我前面提到的「描述一个API应该做什么以及用例指导」,我要求你选择 UIImage,因为它是文本描述的比较好的一个例子。

当这是我第一次使用的类时,尤其是最近才引入的类,我通常会阅读它的概述。 但是对于其他的类,任何我以前至少使用过一次的类,我会直接跳过它,并尝试找我想要的具体类容。 请记住一点,Apple 文档的设计目的并不是作为一种学习工具:当你有特定的目的时,它的效果才是最好的。

如果你并不总是为你所选择的Apple 平台的最新版本进行开发,那么页面右侧的「版本摘要」侧边栏就非常重要了。在这种情况下,你会看到 iOS 2.0+, tvOS 9.0+和watchOS 2.0+,这告诉我们 UIImage 这个类何时在这三个操作系统上第一次使用,并且它仍然可用,如果它被弃用(不再可用),你会看到类似 iOS 2.0-9.0 的东西。

这个页面上的真正内容,以及苹果开发框架中作为特定类主页的所有页面上的内容,都列在「主题」标题下。这将列出这个类支持的所有属性和方法,再细分为使用类别:「获取图像数据」,「获取图像大小和比例」等等。

如果你选择的类有任何自定义初始化器,它们应该总是首先显示。UIImage有很多自定义初始化器,你会看到它们都被列为签名,只是描述它期望的参数的部分。所以,你会看到这样的:

init?(named: String)
init(imageLiteralResourceName: String)

Tip:如果你看到的是Objective-C代码,确保你的语言是Swift。你可以在页面的右上角执行此操作,当重要的 iOS 测试版引入新的变化时,你也可以在此处启用 API 更改选项。

请记住,初始化器被写为 init?而不是init, 是有可能失败的,因为init?返回一个可选的,以便在初始化失败时可以返回nil。

在初始化器的正下方,你有时会看到一些比较特殊的用于创建类的实例方法。这些不是Swift意义上的初始化方式,但它们确实创建了类的实例。对于UIImage,你会看到这样的东西:

class func animatedImageNamed(String, duration: TimeInterval) -> UIImage?

class func意味着你可以调用UIImage.animatedImageNamed().

在初始化器之后,事情变得不那么有组织性了:你会发现属性、方法和枚举全部混合在一起。虽然你可以通过滚动页面找到你要找的东西,但我可以大胆的说,大多数人只是Cmd+F在页面上找到一些文本!

有以下三点需要注意:

  • 嵌套类型(类、结构和枚举)与属性和方法一起列出,这需要一点时间来适应。 例如,UIImage 包含嵌套的枚举 ReizingMode
  • 任何带有一条线的东西则说明被弃用了。 这意味着 Apple 打算在某个时候将其删除,因此你不应将其用于将来的代码,并且你应该开始重写已被已被弃用的代码。 (实际上,大多数 API 在很长一段时间内都处于“弃用”状态,—年复一年)
  • 一些非常复杂的类,比如UIViewController,会有额外的文档页面和它们的方法和属性混合在一起。你看他们旁边的页面图标,都会加上一个简单的英文标题,比如「定位内容相对于安全区」。

在页面底部,你会找到对应的关系,它告诉你它继承自哪个类(在本例中,它直接来自 NSObject),以及它遵循的所有协议。 当你查看协议关系更复杂的 Swift 类型时,本节会更有帮助。

阅读属性和方法页面

你已经选择了一个框架和类,现在是时候查看一个特定的属性或方法了。 查找并选择此方法:

class func animatedResizableImageNamed(String, capInsets: UIEdgeInsets, resizingMode: UIImage.ResizingMode, duration: TimeInterval) -> UIImage?

你应该在创建专用图像对象类别中找到它。

这不是一个复杂的方法,但它确实展示了这些页面的重要部分:

  • Apple 有几种不同的编写方法名称的方式。 前有class func animatedResizableImageNamed , 然后是方法页面标题中显示的表单(animatedResizableImageNamed(_:capInsets:resizingMode:duration:)),以及方法页面的声明部分中的表单。
  • 正如你在版本摘要中看到的(在右侧),此方法是在 iOS 6.0 中引入的。虽然主要的 UIImage 类从第一天就已经存在,但这种方法是在几年后引入的。
  • 方法声明的各个部分,颜色是紫色的都是可点击的。 不过要小心:如果你点击 UIImage.ResizingMode,你会去哪里取决于你点击的是UIImage还是ResizingMode。 (提示:你通常需要单击右侧的那个)
  • 你将看到每个参数的含义和返回值的简要说明。
  • 「Discussion」部分详细介绍了此方法的具体使用说明。 这是几乎是每个页面中最有用的部分,因为在这里你会看到诸如「不要调用此方法」或「当……时要小心」之类的内容。
  • 你可能会发现「See Also」部分,这里的方法列表与我们在前一页中使用的方法相同。

UIImage是一个旧类,它没有太多改变,所以它的文档状态很好。但是一些较新的api,以及许多不像UIKit那样受欢迎的老API,仍然没有得到足够的文档支持。例如,来自SceneKitSCNAnimation,或来自UIKitUITextDragPreviewRenderer:都是在iOS 11中引入的,并且在发布 18 个月后,它们的文档中仍然包含「没有可用的概述」。

当你看到「没有可用的概述」时,你的心会沉下去,但不要放弃:让我告诉你我接下来要做什么……

查看代码

尽管 Apple 的在线文档非常好,但你经常会遇到「没有可用的概述」,或者你发现没有足够的信息来回答你的问题。

康威定律指出,「设计系统的架构受制于产生这些设计的组织的沟通结构」,也就是说,如果你以某种方式工作,你也会以类似的方式设计东西。

Apple 在我们行业的独特地位使他们以一种相当不寻常的方式工作,这几乎可以肯定这与你自己公司的工作方式完全不同。他们有API审查讨论,试图研究在两种语言下API应该是什么样子,他们有专门的团队来制作文档和示例代码。

但是他们获得示例代码的门槛非常高:通常需要非常好的代码才能获得示例代码,并且要经过多层审查,例如法律问题。虽然我可以在一个小时内输出一个项目,然后直接把它作为一篇文章实时发布,但 Apple 做同样的事情要花更长的时间,他们非常重视自己的形象。如果你曾经好奇为什么Swift 官方博客上很少有文章出现,现在你知道了!

现在我说这些的原因是Apple 有一个被广泛使用的捷径:他们的工程师在他们的代码中留下注释的门槛似乎很低,这意味着你经常会在Xcode中找到有价值的信息。这些评论就像金粉一样:它们直接来自Apple 的开发者而不是他们的开发者发行团队,尽管我非常喜欢devpub,但很高兴直接从源头那里找到。

还记得我之前提到 SceneKitSCNAnimation 在 Apple 的开发者网站上没有记录吗? 好吧,让我们看看 Xcode 可以显示什么:按 Shift+Cmd+O 调出 Open Quickly 菜单,确保右侧的 Swift 图标是彩色的而不是空心的,然后输入SCNAnimation

你将看到列出的一些选项,但你正在寻找在 SCNAnimation.h 中定义的选项。 如果你不确定,最好选择 YourClassName.h 文件。

无论如何,如果你打开SCNAnimation.h, Xcode会显示一个生成的SCNAnimation头文件的版本。因为原始版本是Objective-C,所以Xcode为Swift做了一个实时翻译,这就是 Open Quickly 框中带颜色的 Swift 标志的含义。

现在,如果你按下 Command+F 并搜索「class SCAnimation」,你会发现:

/**
 SCNAnimation represents an animation that targets a specific key path.
 */
@available(iOS 11.0, *)
open class SCNAnimation : NSObject, SCNAnimationProtocol, NSCopying, NSSecureCoding {  
    /*!
     Initializers
     */

    /**
     Loads and returns an animation loaded from the specified URL.

     @param animationUrl The url to load.
     */
    public /*not inherited*/ init(contentsOf animationUrl: URL)

而这仅仅是开始。 是的,该类及其所有内部结构都有文档,包括使用说明、默认值等。 所有这些确实应该在在线文档中,但无论出于何种原因,它仍然没有出现,所以准备好查找代码可以作为一个有用的补充。

最后的提示

此时,你应该能够查找你喜欢的任何代码的在线文档,并查找头文件注释以获取额外的使用说明。

但是,在你准备好面对所有 Apple 开发文档之前,你还需要了解两件事。

首先,你会经常遇到标记为「已归档」、「旧版」或「已停用」的文档,即使是相对较新的文档。 当它真的很旧时,你会看到这样的消息:「这个文档可能不代表当前开发的最佳实践,下载和其他资源的链接可能不再有效」。

尽管Apple 是世界上最大的公司之一,但它的工程和开发团队还没有达到人满为患的地步,他们不可能在更新所有内容的同时还涵盖新的 API。所以,你看到「归档」文档或类似文件时,请进行判断:如果它是Swift 的某个版本,至少你知道它是最近的,即使不是,你可能仍然会发现有很多有价值的信息。

其次,Apple 还有一些特别有价值且非常出色的文档。 这些都列在 https://developer.apple.com 的页脚中,但主要的是人机交互界面指南。 这份文档这将带你了解苹果平台应用设计的各个部分,包括用图片来说明关键点,并提供大量具体建议。 尽管此文档是构建 iOS 应用程序时要考虑的非常重要的一个文档,但令人惊讶的是,似乎很少有开发人员阅读过它!

接下来?

我之前写过关于 Apple 文档问题的文章,虽然那里没有鼓励,但至少它可以帮助你在挣扎时感觉不那么孤单。

幸运的是,我有很多可能更有用的材料:

你认为阅读 Apple 文档最有效的方法是什么? 在 Twitter 上和我交流你的想法:@twostraws