<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Runtime on Chen</title><link>https://hechen.github.io/zh-cn/tags/runtime/</link><description>Recent content in Runtime on Chen</description><generator>Hugo</generator><language>zh-cn</language><lastBuildDate>Sun, 19 Nov 2017 18:17:15 +0000</lastBuildDate><atom:link href="https://hechen.github.io/zh-cn/tags/runtime/index.xml" rel="self" type="application/rss+xml"/><item><title>模块化 Xcode 工程</title><link>https://hechen.github.io/zh-cn/post/modular-xcode-projects/</link><pubDate>Sun, 19 Nov 2017 18:17:15 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/modular-xcode-projects/</guid><description>&lt;blockquote&gt;
&lt;p&gt;原文：&lt;a href="https://ppinera.es/2017/09/29/modular-xcode-projects.html"&gt;Modular Xcode projects&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;原作者 &amp;amp; Copyright &lt;a href="http://twitter.com/pepibumur"&gt;@pepibumur&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;翻译：&lt;a href="https://twitter.com/OgreMergO"&gt;@OgreMergO&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;使用 Xcode 构建模块化的工程就需要对工程结构以及其基础概念有很好的理解才行。&lt;/p&gt;
&lt;p&gt;我们平时不怎么关注工程结构本身，只有在工程逐渐变大，要添加更多依赖的时候才会注意的到。而即使到了这个时候，我们大多数的工程都会使用 &lt;a href="https://cocoapods.org/"&gt;CocoaPods&lt;/a&gt; 来设置那些依赖项，或者 &lt;a href="https://github.com/carthage"&gt;Carthage&lt;/a&gt;, 后者虽然没有帮我们做依赖性的设置，但是使得我们会更容易的，通过在工程的 build phase 选项中添加一些内容，达到同样的目的。当配置项越来越复杂，我们就很容易产生困惑，这是因为我们并没有完全掌握 Xcode 工程中所涉及的所有元素。我经常被问到的问题如下：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;我能不能在工程里同时使用 Carthage，Cocoapods 以及自己个人的依赖设置？&lt;/li&gt;
&lt;li&gt;我添加了依赖，但是当模拟器打开 App 的时候 Crash 了。&lt;/li&gt;
&lt;li&gt;为什么我需要只在某些 targets 里嵌入 framework？&lt;/li&gt;
&lt;li&gt;我的 framework 应该是静态的还是动态的？&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;在这篇博文中，我会引导你遍历 Xcode Project 中的各个元素，指导你如何通过改变这些元素来模块化你的设置项。我希望下次你遇到上面这些问题的时候，你不需要再花大量时间取 Stack Overflow 上查这些确定的答案。&lt;/p&gt;
&lt;h3 id="elements-"&gt;Elements ⚒&lt;/h3&gt;
&lt;h4 id="target"&gt;Target&lt;/h4&gt;
&lt;p&gt;工程（Projects）都是由多个更小的叫做 target 的单元组成的。这些 target 包含编译特定平台产品，比如 frameworks, libraries, apps, testing bundles, extensions 等所需要的配置。 你可以在&lt;a href="https://github.com/xcodeswift/xcproj/blob/master/Sources/xcproj/PBXProductType.swift"&gt;这里&lt;/a&gt;看到 target 所有可用的类型。 Target 可以相互依赖，当一个 target A 依赖另外一个 target B 的时候，target B 就会被先构建出来以便 target A 使用其产出。而 target 的配置项会涉及以下几个地方：&lt;/p&gt;</description></item><item><title>处理 Swift 中非可选的可选值类型</title><link>https://hechen.github.io/zh-cn/post/handling-non-optional-optionals-in-swift/</link><pubDate>Tue, 14 Nov 2017 21:53:52 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/handling-non-optional-optionals-in-swift/</guid><description>&lt;blockquote&gt;
&lt;p&gt;原文：&lt;a href="https://www.swiftbysundell.com/articles/handling-non-optional-optionals-in-swift/"&gt;Handling non-optional optionals in Swift&lt;/a&gt;
原作者 &amp;amp; Copyright &lt;a href="https://twitter.com/johnsundell"&gt;@johnsundell&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;可选值（optionals）无可争议的是 &lt;code&gt;swift&lt;/code&gt; 语言中最重要的特性之一，也是和其他语言，例如 &lt;code&gt;Objective-C&lt;/code&gt; 的最大区别。通过强制处理那些有可能出现 &lt;code&gt;nil&lt;/code&gt; 的地方，我们就能写出更有预测性的以及更健壮的代码。&lt;/p&gt;
&lt;p&gt;然而，有些时候可选值可能会致你于尴尬的境地，尤其是你作为开发者了解（甚至是有些猜测的成分在），有的特定变量始终是非空（non-nil）的，即使它是一个可选类型。例如，我们在一个视图控制器中处理视图的时候：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;TableViewController&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UIViewController&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;tableView&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;UITableView&lt;/span&gt;&lt;span class="p"&gt;?&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kr"&gt;override&lt;/span&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kc"&gt;super&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;viewDidLoad&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tableView&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;UITableView&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;bounds&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;view&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;addSubview&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tableView&lt;/span&gt;&lt;span class="p"&gt;!)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;viewModelDidUpdate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;_&lt;/span&gt; &lt;span class="n"&gt;viewModel&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ViewModel&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;tableView&lt;/span&gt;&lt;span class="p"&gt;?.&lt;/span&gt;&lt;span class="n"&gt;reloadData&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;这也是对于很多 Swift 程序员争论比较激烈的地方，程度不亚于讨论 tabs 和 spaces 的用法。有的人会说：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;既然它是一个可选值，你就应该时刻使用 &lt;code&gt;if let&lt;/code&gt; 或者 &lt;code&gt;guard let&lt;/code&gt; 的方式进行解包。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;然而另外一些人则采用完全相反，说：&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;既然你知道这个变量在使用的时候不会为 &lt;code&gt;nil&lt;/code&gt;，使用 &lt;code&gt;!&lt;/code&gt; 强制解包多好。崩溃也要比让你的程序处于一个未知状态要好吧。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;本质上来讲，我们这里讨论的是要不要采用防御性编程（&lt;a href="https://en.wikipedia.org/wiki/Defensive_programming"&gt;defensive programming&lt;/a&gt;）的问题。我们是试图让程序从一个未知状态恢复还是简单的放弃，然后让它崩溃掉？&lt;/p&gt;
&lt;p&gt;如果非得让我对这个问题给出一个答案的话，我更倾向于后者。未知状态真的很难追踪 bug，会导致执行很多不想执行的逻辑，采用防御性编程就会使得你的代码很难追踪，出现问题很难追踪。&lt;/p&gt;
&lt;p&gt;但是，我不太喜欢给出一个二选一的答案。相反，我们可以寻找一些技术手法，用更精妙的方式的解决上面提到的问题。&lt;/p&gt;
&lt;h2 id="它真的可选的吗"&gt;它真的可选的吗？&lt;/h2&gt;
&lt;p&gt;那些可选类型的，但是被代码逻辑真实需要的变量和属性，实际上是架构瑕疵的一个体现。如果在某些地方确实需要它，但是它又不在，就会使得你的代码逻辑处于未知状态，那么它就不应该是可选类型的。&lt;/p&gt;
&lt;p&gt;当然，在某些特定场景下，可选值确实很难避免（尤其是和特定的系统 API 交互的时候），那对于大部分这种情况，我们有一些技术来处理从而避免可选值。&lt;/p&gt;
&lt;h3 id="lazy-要比非可选的可选值更好"&gt;lazy 要比非可选的可选值更好&lt;/h3&gt;
&lt;p&gt;某些属性的值需要在其父类创建之后再生成（比如视图控制器中的那些视图，应该在 &lt;code&gt;loadView()&lt;/code&gt;或者 &lt;code&gt;viewDidLoad()&lt;/code&gt;方法中被创建），对于这种属性要避免其可选类型的方法就是使用 &lt;code&gt;lazy&lt;/code&gt; 属性。一个&lt;code&gt;lazy&lt;/code&gt;属性是可以是非可选类型的，同时也不在其父类的初始化方法里被需要，它会在其第一次被获取的时候创建出来。&lt;/p&gt;
&lt;p&gt;让我们改一下上面的代码，使用 lazy 来改造 tableView 属性：&lt;/p&gt;</description></item><item><title>Capturing objects in Swift closures</title><link>https://hechen.github.io/zh-cn/post/capturing-objects-in-swift-closures/</link><pubDate>Sun, 12 Nov 2017 20:56:50 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/capturing-objects-in-swift-closures/</guid><description>&lt;blockquote&gt;
&lt;p&gt;原文：&lt;a href="https://www.swiftbysundell.com/posts/capturing-objects-in-swift-closures"&gt;Capturing objects in Swift closures&lt;/a&gt;
原作者 &lt;a href="https://twitter.com/johnsundell"&gt;@johnsundell&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;自从 Block 在 iOS4 被引入 Objective-C 的世界之后就成为了 Apple 各平台上最时髦的 API 的重要组成部分了。当 Swift 语言出现的时候，blocks 的概念就摇身一变通过 closure 的形式引入，成为了目前我们可能每一天都在用的语言特性之一了。&lt;/p&gt;
&lt;p&gt;Closure 目前已经被我们广泛的使用了，即使如此，我们在使用它的时候还是需要有很多需要注意的点，并且需要做很多额外的操作。这篇文章，我们来近距离的了解 closure，主要是了解其捕获变量的机制以及那些能够更好的让我们来处理变量捕获的技术。&lt;/p&gt;
&lt;h2 id="伟大的-escape"&gt;伟大的 escape&lt;/h2&gt;
&lt;p&gt;Closure 有两种类型：escaping 和 non-escaping。当一个 closure 是 escaping（使用 &lt;code&gt;@escaping&lt;/code&gt; 修饰闭包参数）的，也就意味着其会被以各种形式存储下来（无论是通过 property 还是被其他 closure 捕获）。相反，Non-Escaping 的　closure 意味着其不能被存储，而且在使用它的地方就必须直接被执行。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;译者注： 可以参见 &lt;a href="http://hechen.info/2017/11/12/autoclosure-escape/"&gt;《@autoclosure &amp;amp;&amp;amp; @escape》&lt;/a&gt; 一文。&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;一个显而易见的例子就是当你在一个集合类型上使用函数式操作的时候，例如 &lt;code&gt;forEach&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;[1, 2, 3].forEach { number in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; ...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;如上代码所示，closure 都直接作用于集合的每一个元素上，也就无需把该闭包变为 escaping 的。&lt;/p&gt;
&lt;p&gt;而 escaping 的 closures 最常见的就是在那些异步 API 中，例如 &lt;code&gt;DispatchQueue&lt;/code&gt;。例如，当你异步执行某 closure 的时候，这个 closure 就会 escape。&lt;/p&gt;</description></item><item><title>@autoclosure &amp;&amp; @escape</title><link>https://hechen.github.io/zh-cn/post/autoclosure-escape/</link><pubDate>Sun, 12 Nov 2017 20:01:54 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/autoclosure-escape/</guid><description>&lt;p&gt;我们知道在 &lt;code&gt;swift&lt;/code&gt; 中，闭包（closure）是一等公民，因此可以被当作参数传递，在学习 swift 的过程中经常会看到某些关键字修饰该闭包，&lt;code&gt;@autoclosure&lt;/code&gt;， &lt;code&gt;@escape&lt;/code&gt; 就是其中比较常见的两种关键字。&lt;/p&gt;
&lt;h3 id="escape-和-nonescape"&gt;@escape 和 @nonescape&lt;/h3&gt;
&lt;p&gt;当一个闭包被当作参数传递给一个函数，但是当该函数内容执行完毕返回之后，该闭包才会被执行，我们就称该闭包要 escape 某个函数，那 &lt;code&gt;@escape&lt;/code&gt; 关键字就是用来表示该闭包是允许在函数返回之后被调用的。&lt;/p&gt;
&lt;p&gt;我们用 swift 官方文档的例子来看，如下所示&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;completionHandlers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;someFunctionWithEscapingClosure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;completionHandler&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="n"&gt;escaping&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;completionHandlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;completionHandler&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;someFunctionWithEscapingClosure(_:)&lt;/code&gt; 的参数是一个闭包，函数内部会把传入的闭包存到之前声明的数组里以便之后进行调用，可以看到，在函数参数的声明部分添加了 &lt;code&gt;@escaping&lt;/code&gt; 关键字，如果这里不添加的话，就会在编译的时候报错：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;error: passing non-escaping parameter &lt;span class="s1"&gt;&amp;#39;completionHandler&amp;#39;&lt;/span&gt; to &lt;span class="k"&gt;function&lt;/span&gt; expecting an @escaping closure
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; completionHandlers.append&lt;span class="o"&gt;(&lt;/span&gt;completionHandler&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;针对标记了 @escaping 关键字含义代表你必须在该闭包内部显式的使用 self 关键字，官方文档中又列举了另外一个例子，如下所示：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-swift" data-lang="swift"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;someFunctionWithNonescapingClosure&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;closure&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;closure&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;SomeClass&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nv"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nf"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;someFunctionWithEscapingClosure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="kc"&gt;self&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;someFunctionWithNonescapingClosure&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;200&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nv"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;SomeClass&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Prints &amp;#34;200&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;completionHandlers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="bp"&gt;first&lt;/span&gt;&lt;span class="p"&gt;?()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="bp"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;instance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;// Prints &amp;#34;100”&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;&lt;code&gt;someFunctionWithEscapingClosure(_:)&lt;/code&gt; 是一个可逃逸的闭包，意味着你需要显示的调用 self 关键字， 而 &lt;code&gt;someFunctionWithNonescapingClosure(_:)&lt;/code&gt; 是非逃逸的闭包，意味着你可以隐式的调用 self。&lt;/p&gt;</description></item><item><title>关于 iOS10 Notification 的那些事儿</title><link>https://hechen.github.io/zh-cn/post/ios-notification/</link><pubDate>Sat, 20 May 2017 10:10:54 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/ios-notification/</guid><description>&lt;h2 id="概览"&gt;概览&lt;/h2&gt;
&lt;p&gt;推送通知我们大家都不陌生，可以说几乎每个使用智能手机的人每天都会被不同的通知 &lt;em&gt;打扰&lt;/em&gt; 到，正式因为合适的推送是吸引用户注意力的利器，其成为了各 App 吸引用户，将用户带回到 App 本身，提升用户的活跃度的一种必要的方式。&lt;/p&gt;
&lt;p&gt;当然，过度的推送本身则是一件对用户影响特别大的事情，毕竟注意力被打断，因此合适的推送时机也是各个 App 开发者所要注意的，否则他的 App 就会成为用户勿扰名单里的一员了。&lt;/p&gt;
&lt;p&gt;之前刚开始学习 iOS 开发的时候还整理了下当时部署 iOS 远程推送的流程，详见：&lt;a href="http://hechen.info/2015/07/30/iOS-Push-Notification/"&gt;iOS 远端推送部署详解&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;接下来，我们大致回顾一下 iOS 平台关于推送都有哪些历程？&lt;/p&gt;
&lt;h2 id="历史"&gt;历史&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&amp;lt;= iOS 6&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;远程推送通知 （iOS 3）&lt;/li&gt;
&lt;li&gt;本地通知 （iOS 4）&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;iOS 7 参考&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引入 Silent Remote Notifications&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;iOS 8 参考 &lt;a href="https://developer.apple.com/videos/play/wwdc2014/713/"&gt;WWDC 2014 Session 713&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引入 Actionable Notifications&lt;/li&gt;
&lt;li&gt;修改 Notification 的权限请求&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;iOS 9 参考 &lt;a href="https://developer.apple.com/videos/play/wwdc2015/720/"&gt;WWDC 2015 Session 720&lt;/a&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;引入 Text Input Action&lt;/li&gt;
&lt;li&gt;UIUserNotificationActionBehavior&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;iOS 10 参考 &lt;a href="https://developer.apple.com/videos/play/wwdc2016/707"&gt;WWDC 707 Introduction to Notifications&lt;/a&gt; &amp;amp;&amp;amp; &lt;a href="https://developer.apple.com/videos/play/wwdc2016/708"&gt;WWDC 708 Advanced Notifications&lt;/a&gt;&lt;/p&gt;</description></item><item><title>如何使用UIBezierPath实现一个弹性视图动画</title><link>https://hechen.github.io/zh-cn/post/elastic-view-animation-using-uibezierpath/</link><pubDate>Wed, 02 Dec 2015 18:53:51 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/elastic-view-animation-using-uibezierpath/</guid><description>&lt;blockquote&gt;
&lt;p&gt;原文：&lt;a href="https://hackernoon.com/elastic-view-animation-or-how-i-built-dgelasticpulltorefresh-269a3ba8636e"&gt;Elastic view animation, or how I built DGElasticPullToRefresh&lt;/a&gt;
原作者 &lt;a href="https://twitter.com/gontovnik"&gt;@gontovnik&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href="https://github.com/gontovnik/DGElasticPullToRefresh"&gt;DGElasticPullToRefresh&lt;/a&gt; 展示了如何实现一个弹性效果。效果如下图所示：&lt;/p&gt;
&lt;p&gt;&lt;img alt="DGElasticPullToRefresh.gif" loading="lazy" src="https://i.imgur.com/NzdoFS9.gif"&gt;&lt;/p&gt;
&lt;p&gt;开发环境：
Xcode 7
Swift 2.0&lt;/p&gt;
&lt;p&gt;要求：
开发者至少对 UIBezierPath 和 UIGestureRecognizer 有一定的了解.&lt;/p&gt;
&lt;h3 id="理解业务逻辑"&gt;理解业务逻辑&lt;/h3&gt;
&lt;p&gt;你可能从上面的效果图上可以看到一些端倪，这个动画中我们主要使用到了UIBezierPath来实现上面这种效果。
我们首先创建一个贝塞尔曲线路径的CAShapeLayer，然后当你的手指在屏幕上移动的时候我们将移动所有的控制点来呈现动画。每一个控制点会使用一个可见的UIView来表示。下面有几张图来演示它们是如何工作的，我将所有的控制点标识成了红色：&lt;/p&gt;
&lt;p&gt;&lt;img alt="1_vAmk8ulHh4OJji_X35zW4g" loading="lazy" src="media/1_vAmk8ulHh4OJji_X35zW4g.png"&gt;&lt;/p&gt;
&lt;p&gt;&lt;img alt="1_ru8KwJ6DZWXgJm1tm_Sw_Q" loading="lazy" src="media/1_ru8KwJ6DZWXgJm1tm_Sw_Q.png"&gt;&lt;/p&gt;
&lt;p&gt;第二章图片中将每个表示控制点的 View 的变量名称标记出来了，如L3，L2等。&lt;/p&gt;
&lt;p&gt;当你的手指释放的时候，我们就播放Spring动画，让所有的控制点向其初始位置以一定的回弹效果移动。当所有的视图在动画播放过程中，我们需要时刻计算并我们的贝塞尔曲线（每一帧都进行计算）。因此，我们准备使用CADisplayLink，CADisplayLink在主循环中运行而且每一帧都会去执行指定的方法。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A CADisplayLink object is a timer object that allows your application to synchronize its drawing to the refresh rate of the display. - Apple doc&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;让我们开始Code吧~&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="build"&gt;Build&lt;/h3&gt;
&lt;p&gt;创建一个单视图控制器，然后将下面这些代码粘贴到viewController.swift文件的类声明中。&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// MARK: -
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// MARK: Vars
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;private let minimalHeight: CGFloat = 50.0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;private let shapeLayer = CAShapeLayer()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// MARK: -
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;override func loadView() {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; super.loadView()
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; shapeLayer.frame = CGRect(x: 0.0, y: 0.0, width: view.bounds.width, height: minimalHeight)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; shapeLayer.backgroundColor = UIColor(red: 57/255.0, green: 67/255.0, blue: 89/255.0, alpha: 1.0).CGColor
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; view.layer.addSublayer(shapeLayer)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; view.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: &amp;#34;panGestureDidMove:&amp;#34;))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// MARK: -
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;// MARK: Methods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;func panGestureDidMove(gesture: UIPanGestureRecognizer) {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; if gesture.state == .Ended || gesture.state == .Failed || gesture.state == .Cancelled {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; } else {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; shapeLayer.frame.size.height = minimalHeight + max(gesture.translationInView(view).y, 0)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; }
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;override func preferredStatusBarStyle() -&amp;gt; UIStatusBarStyle {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; return .LightContent
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;以上代码中，我们做的工作主要有以下几点：&lt;/p&gt;</description></item><item><title>Objective-C中Category的一点东西</title><link>https://hechen.github.io/zh-cn/post/objective-c%E4%B8%ADcategory%E7%9A%84%E4%B8%80%E7%82%B9%E4%B8%9C%E8%A5%BF/</link><pubDate>Mon, 14 Sep 2015 15:36:07 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/objective-c%E4%B8%ADcategory%E7%9A%84%E4%B8%80%E7%82%B9%E4%B8%9C%E8%A5%BF/</guid><description>&lt;p&gt;Objective-C中的分类（category）是一种编译时的手段，其允许我们通过给某个已知类添加方法来扩充该类的一种方式。当然这其中是有限制的，就是不能给已知类添加新的实例变量。&lt;/p&gt;
&lt;p&gt;如下代码展示：&lt;/p&gt;
&lt;p&gt;类&lt;code&gt;MyClass&lt;/code&gt;为一个简单的类，其中有实例方法 &lt;code&gt;-print&lt;/code&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objectivec" data-lang="objectivec"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#import &amp;lt;Foundation/Foundation.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt; : &lt;span class="nc"&gt;NSObject&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;#import &amp;#34;MyClass.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@implementation MyClass
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;- (void)print
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;{
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; NSLog(@&amp;#34;MyClass...&amp;#34;);
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;@end
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;我们向为MyClass再添加一个方法Hello，那我们就可以用分类的方法实现，我们为其添加分类MyAddition1和MyAddition2，如下所示：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objectivec" data-lang="objectivec"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#import &amp;#34;MyClass.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt; &lt;span class="nl"&gt;(MyAddition1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@property&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nonatomic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;NSString&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objectivec" data-lang="objectivec"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#import &amp;#34;MyClass+MyAddition1.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@implementation&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt; &lt;span class="nl"&gt;(MyAddition1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;hello&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;NSLog&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;@&amp;#34;hello!!!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;其中MyAddition为分类的名称，而文件名字约定俗成用“类名+扩展名”的形式。这样，我们就能够为MyClass类添加hello方法了，如下调用：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objectivec" data-lang="objectivec"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#import &amp;#34;MyClass+MyAddition1.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;MyClass&lt;/span&gt; &lt;span class="n"&gt;my&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;MyClass&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;my&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c1"&gt;//...
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Category 的使用场景主要有以下几种：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;需求变更，需要为已知类添加方法；&lt;/li&gt;
&lt;li&gt;将类的不同模块实现划分: a)具体可以将类的实现分开到不同的文件里面； b)将不同功能的分类文件交由不同的开发者实现；&lt;/li&gt;
&lt;li&gt;想为Apple基础类库添加自己需要的方法，实际上和1相似；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但是分类的使用目前也有需要注意的地方：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Category可以访问原有类的实例变量，但不能添加实例变量；&lt;/li&gt;
&lt;li&gt;Category中实现和原有类中相同签名的方法时，会覆盖原有类的方法；&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;但是这两点均可以通过其他方式实现：&lt;/p&gt;
&lt;h3 id="为分类添加实例变量"&gt;为分类添加实例变量&lt;/h3&gt;
&lt;p&gt;为分类添加实例变量主要通过关联对象的方法。如下所示：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objectivec" data-lang="objectivec"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#import &amp;#34;MyClass.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@interface&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt; &lt;span class="nl"&gt;(MyAddition1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@property&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;nonatomic&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;copy&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;NSString&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objectivec" data-lang="objectivec"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#import &amp;#34;MyClass+MyAddition1.h&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#import &amp;lt;objc/objc-runtime.h&amp;gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@implementation&lt;/span&gt; &lt;span class="nc"&gt;MyClass&lt;/span&gt; &lt;span class="nl"&gt;(MyAddition1)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;setName:&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NSString&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nv"&gt;name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;objc_setAssociatedObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;OBJC_ASSOCIATION_COPY&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;NSString&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;name&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;NSString&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;objc_getAssociatedObject&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;key&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;@end&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h4 id="如果调用被分类覆盖掉的原方法"&gt;如果调用被分类覆盖掉的原方法&lt;/h4&gt;
&lt;p&gt;实际上，通过查看Objc runtime源码可以获知，分类方法并不是绝对意义上的覆盖原有类的方法，只是在调用的时候调用顺序导致而已，这涉及到Objc runtime的一些内容。&lt;/p&gt;</description></item><item><title>理解Objective-C运行时</title><link>https://hechen.github.io/zh-cn/post/understanding-the-objective-c-runtime/</link><pubDate>Mon, 07 Sep 2015 17:55:33 +0000</pubDate><guid>https://hechen.github.io/zh-cn/post/understanding-the-objective-c-runtime/</guid><description>&lt;p&gt;Objective-C 运行时对于刚刚踏入 Cocoa/Objective 世界的人是很容易忽
略的 Objective-C 语言的特性之一。原因就是尽管 Objective-C 是一门几个小时之内入门的语言，但是投身 Cocoa 的新手们会花费大量时间在 Cocoa 框架中，试图搞清楚他到底是怎么工作的。 我觉得每个开发者都应该对其有深入的了解，明白一些内部的实现细节，而不仅仅只知道代码 &lt;code&gt;[target doMethodWith:var]&lt;/code&gt; 会被编译器转换成 &lt;code&gt;objc_msgSend(target,@selector(doMethodWith:),var1);&lt;/code&gt; 而已。了解 Objective-C 运行时的原理有助于你对 Objective-C 语言有更深入的理解，清楚你得 App 是怎么运行的。我觉得这对无论是 Mac/iPhone 新手或者老手都会有所帮助。&lt;/p&gt;
&lt;p&gt;[TOC]&lt;/p&gt;
&lt;h4 id="objective-c运行时是开源的"&gt;Objective-C运行时是开源的&lt;/h4&gt;
&lt;p&gt;Objective-C 运行时是开源的，你可以随时从 &lt;a href="http://opensource.apple.com"&gt;Apple&lt;/a&gt; 获取到。实际上查看 Objective-C 运行时源码是我搞清楚这个语言是怎么运作的首选方法，而不是去查看和它相关的苹果文档。你可以到&lt;a href="http://opensource.apple.com/tarballs/objc4/objc4-437.1.tar.gz"&gt;这里&lt;/a&gt; 下载到运行时的源码（截止到译者翻译的时候，最新版本的文件是objc4-647.tar.gz）。&lt;/p&gt;
&lt;h4 id="动态-vs-静态"&gt;动态 Vs. 静态&lt;/h4&gt;
&lt;p&gt;Objective-C 是一门动态的面向对象语言，这意味着它可以将编译链接时决定的事情推迟到运行时进行。这就给了你很大的灵活性，你可以按照自己的需要重定向消息到适当的对象上，你甚至可以交换方法实现（译者注：method swizzling，方法调配，开发者常用此技术向原有实现中添加新功能）。而运行时可以使对象明白自己可以响应哪些消息，不能响应哪些消息（译者注：introspect 内省），并正确的派发消息。&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;译者注： 内省（introspection）是面向对象语言和环境的一个强大特性，Objective-C和Cocoa在这个方面尤其的丰富。内省是对象揭示自己作为一个运行时对象的详细信息的一种能力。这些详细信息包括对象在继承树上的位置，对象是否遵循特定的协议，以及是否可以响应特定的消息。NSObject协议和类定义了很多内省方法，用于查询运行时信息，以便根据对象的特征进行识别。&lt;/p&gt;
&lt;p&gt;参考: &lt;a href="https://developer.apple.com/library/archive/documentation/General/Conceptual/CocoaEncyclopedia/Introspection/Introspection.html"&gt;Objective-C 的 Introspection&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;我们将这些特征和C语言进行对比来看，在C中，你从&lt;code&gt;main()&lt;/code&gt;函数开始，然后按顺序从上往下写你的代码逻辑或者执行函数方法。C结构体是无法将请求转发到其他目标对象来执行方法的。你很可能写了如下类似的代码：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objectivec" data-lang="objectivec"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt; stdio.h &amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;argc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;**&lt;/span&gt;&lt;span class="n"&gt;argv&lt;/span&gt;&lt;span class="p"&gt;[])&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;Hello World!&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;编译器解析、优化然后将优化后的代码转换成如下的汇编语言：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-objectivec" data-lang="objectivec"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;text&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;align&lt;/span&gt; &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mh"&gt;0x90&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;globl&lt;/span&gt; &lt;span class="n"&gt;_main&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;_main&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;Leh_func_begin1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;pushq&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;Llabel1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;movq&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rsp&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;Llabel2&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;subq&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rsp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;Llabel3&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;movq&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rsi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rax&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;movl&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;edi&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;ecx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;movl&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;ecx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;movq&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;xorb&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;al&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;al&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;leaq&lt;/span&gt; &lt;span class="n"&gt;LC&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rip&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rcx&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;movq&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rcx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rdi&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;call&lt;/span&gt; &lt;span class="n"&gt;_printf&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;movl&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;movl&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;eax&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;addq&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="mi"&gt;16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rsp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;popq&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt;&lt;span class="n"&gt;rbp&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;ret&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;Leh_func_end1&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cstring&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nl"&gt;LC&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;asciz&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Hello World!&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;然后将其和C库链接生成可执行文件。相比之下，Objective-C语言整个过程和上面类似，不过代码的产生依赖Objective-C运行时的具体表现（译者注：运行时按照不同情况，生成不同的代码吧）。当我们刚接触Objective-C语言的时候，我们可能被告知像如下代码&lt;/p&gt;</description></item></channel></rss>