{"action":"created","comment":{"url":"https://api.github.com/repos/NSHipster/articles/pulls/comments/29208865","id":29208865,"diff_hunk":"@@ -0,0 +1,244 @@\n+---\n+title: \"Swift 1.2\"\n+category: Swift\n+author: Nate Cook\n+tags: swift\n+translator: Croath Liu\n+excerpt: \"Swift 正如其名，速度飞快。随着 Swift 1.2 beta 版本的发布，其开发团队在这次快速加速俯冲中一次性响应了开发社区的诸多需求，带来了许多让激动人心的新特性。本周我们会花一点时间关注这个版本的两个明显提升使用体验的新功能：一个是 `if let` 语句 optional 绑定的巨大变化，另一个是 Objective-C 中的空值标注。\"\n+hiddenlang: \"\"\n+---\n+\n+Swift 正如其名，速度飞快。本周将关注 Swift 1.2 版本的一个 *重大* 更新。Swift 开发团队在这次快速加速俯冲中一次性响应了开发社区的诸多需求，带来了许多让激动人心的新特性。本次发布的每一个小更新都带来了巨大的好处：增量构建、丰富了 Xcode 中的错误信息、提升 Xcode 稳定性、静态类属性、支持 C 的 union 和 bitfield、将 Swift 中的 `enum` 打通到 Objective-C 中、更安全的类型转换、单行闭包的提升等等。\n+\n+在这么多的更新中我们主要关注两个明显提升使用体验的新功能：一个是 `if let` 语句 optional 绑定 *终于有了* 巨大变化，另一个是 Objective-C 中的空值标注。\n+\n+\n+## 提升 Optional 绑定\n+\n+Swift 1.2 允许通过多值并行 optional 绑定来避免 `if let` 语句的多重深嵌套。多个 optional 绑定可以通过逗号分隔开，并且可以带一个和传统的 `if` 语句同样效果的 `where` 分句。这样的话，拜占庭的 [厄运金字塔](http://www.scottlogic.com/blog/2014/12/08/swift-optional-pyramids-of-doom.html) 就可以被修缮成中世纪风格的现代牧场了：\n+\n+**从前：**\n+\n+```swift\n+let a = \"10\".toInt()\n+let b = \"5\".toInt()\n+let c = \"3\".toInt()\n+\n+if let a = a {\n+    if let b = b {\n+        if let c = c {\n+            if c != 0 {\n+                println(\"(a + b) / c = \\((a + b) / c)\")\n+            }\n+        }\n+    }\n+}\n+```\n+\n+**现在：**\n+\n+```swift\n+if let a = a, b = b, c = c where c != 0 {\n+    println(\"(a + b) / c = \\((a + b) / c)\")     // (a + b) / c = 5\n+}\n+```\n+\n+> 这两个例子中判断语句的执行顺序是一样的。使用新的语法可以让每个绑定都按顺序执行，如果某一个绑定是 `nil` 就会停下来。只有在所有的 optional binding 都成功的情况下才会进行 `where` 语句检查。\n+> \n+> 一个 `if` 语句可以包含多个通过逗号分隔的 `let` 绑定。因为每个 `let` 可以绑定多个 optional *和* 一个 `where` 分句，所以通过这种方式可以支持真正更高级的逻辑。（感谢 [Stephen Celis](https://twitter.com/stephencelis) 帮忙解释清楚这点。）\n+\n+更棒的是，后续的绑定语句可以引用之前的绑定。这意味着你只用一个 `if let` 语句就可以解析 `Dictionary` 对象或者对 `AnyObject?` 值进行强制类型转换，然后将其用户另一个语句中。\n+\n+让我们回顾一个经典的例子，将 [这样一个庞大的 JSON 块](http://jsonplaceholder.typicode.com/users) 在 Swift 1.2 中解析。样例中用一个 `if let` 将 JSON 解析成指定的包含 `NSBundle`、`NSURL` 和 `NSData` 类型以及一些 `AnyObject?` 值的对象：\n+\n+```swift\n+var users: [User] = []\n+\n+// load and parse the JSON into an array\n+if let\n+    path     = NSBundle.mainBundle().pathForResource(\"users\", ofType: \"json\"),\n+    url      = NSURL(fileURLWithPath: path),\n+    data     = NSData(contentsOfURL: url),\n+    userList = NSJSONSerialization.JSONObjectWithData(data, options: nil, error: nil) as? [[String: AnyObject]] \n+{\n+    // extract individual users\n+    for userDict in userList {\n+        if let\n+            id      = userDict[\"id\"] as? Int,\n+            name    = userDict[\"name\"] as? String,\n+            email   = userDict[\"email\"] as? String,\n+            address = userDict[\"address\"] as? [String: AnyObject]\n+        {\n+            users.append(User(id: id, name: name, ...))\n+        }\n+    }\n+}\n+```\n+```JSON\n+[\n+  {\n+    \"id\": 1,\n+    \"name\": \"Leanne Graham\",\n+    \"username\": \"Bret\",\n+    \"email\": \"Sincere@april.biz\",\n+    \"address\": {\n+      \"street\": \"Kulas Light\",\n+      \"suite\": \"Apt. 556\",\n+      \"city\": \"Gwenborough\",\n+      \"zipcode\": \"92998-3874\",\n+      \"geo\": {\n+        \"lat\": \"-37.3159\",\n+        \"lng\": \"81.1496\"\n+      }\n+    },\n+    \"phone\": \"1-770-736-8031 x56442\",\n+    \"website\": \"hildegard.org\",\n+    \"company\": {\n+      \"name\": \"Romaguera-Crona\",\n+      \"catchPhrase\": \"Multi-layered client-server neural-net\",\n+      \"bs\": \"harness real-time e-markets\"\n+    }\n+  },\n+  {\n+    \"id\": 2,\n+    \"name\": \"Ervin Howell\",\n+    \"username\": \"Antonette\",\n+    \"email\": \"Shanna@melissa.tv\",\n+    \"address\": {\n+      \"street\": \"Victor Plains\",\n+      \"suite\": \"Suite 879\",\n+      \"city\": \"Wisokyburgh\",\n+      \"zipcode\": \"90566-7771\",\n+      \"geo\": {\n+        \"lat\": \"-43.9509\",\n+        \"lng\": \"-34.4618\"\n+      }\n+    },\n+    \"phone\": \"010-692-6593 x09125\",\n+    \"website\": \"anastasia.net\",\n+    \"company\": {\n+      \"name\": \"Deckow-Crist\",\n+      \"catchPhrase\": \"Proactive didactic contingency\",\n+      \"bs\": \"synergize scalable supply-chains\"\n+    }\n+  },\n+  ...\n+]\n+```\n+\n+我感觉我们之后写的代码中会有不少的逗号出现。\n+\n+\n+\n+## 空值标注\n+\n+在 Swift 第一版发布的时候，每一个对 Cocoa API 的调用方法都会返回一个模糊解析的 optional 类型（比如说 `AnyObject!`）。因为它们会在读取过程中让程序崩溃，所以如果没有清晰的文档表明该方法是否会返回一个 null 值name这种模糊解析内在是不安全的。这些都是不好的现象。Swift 确实能够调用 Cocoa API 了，但调用方法长得真奇怪。","path":"2015-02-09-swift-1.2.md","position":135,"original_position":135,"commit_id":"106c5ece1d65565cedd1614292792f603a7667a8","original_commit_id":"106c5ece1d65565cedd1614292792f603a7667a8","user":{"login":"croath","id":1398729,"avatar_url":"https://avatars.githubusercontent.com/u/1398729?v=3","gravatar_id":"","url":"https://api.github.com/users/croath","html_url":"https://github.com/croath","followers_url":"https://api.github.com/users/croath/followers","following_url":"https://api.github.com/users/croath/following{/other_user}","gists_url":"https://api.github.com/users/croath/gists{/gist_id}","starred_url":"https://api.github.com/users/croath/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/croath/subscriptions","organizations_url":"https://api.github.com/users/croath/orgs","repos_url":"https://api.github.com/users/croath/repos","events_url":"https://api.github.com/users/croath/events{/privacy}","received_events_url":"https://api.github.com/users/croath/received_events","type":"User","site_admin":false},"body":"是 `那么`...","created_at":"2015-04-28T01:48:47Z","updated_at":"2015-04-28T01:48:47Z","html_url":"https://github.com/NSHipster/articles/pull/283#discussion_r29208865","pull_request_url":"https://api.github.com/repos/NSHipster/articles/pulls/283","_links":{"self":{"href":"https://api.github.com/repos/NSHipster/articles/pulls/comments/29208865"},"html":{"href":"https://github.com/NSHipster/articles/pull/283#discussion_r29208865"},"pull_request":{"href":"https://api.github.com/repos/NSHipster/articles/pulls/283"}}},"pull_request":{"url":"https://api.github.com/repos/NSHipster/articles/pulls/283","id":34175293,"html_url":"https://github.com/NSHipster/articles/pull/283","diff_url":"https://github.com/NSHipster/articles/pull/283.diff","patch_url":"https://github.com/NSHipster/articles/pull/283.patch","issue_url":"https://api.github.com/repos/NSHipster/articles/issues/283","number":283,"state":"open","locked":false,"title":"Translation of article - Swift 1.2","user":{"login":"croath","id":1398729,"avatar_url":"https://avatars.githubusercontent.com/u/1398729?v=3","gravatar_id":"","url":"https://api.github.com/users/croath","html_url":"https://github.com/croath","followers_url":"https://api.github.com/users/croath/followers","following_url":"https://api.github.com/users/croath/following{/other_user}","gists_url":"https://api.github.com/users/croath/gists{/gist_id}","starred_url":"https://api.github.com/users/croath/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/croath/subscriptions","organizations_url":"https://api.github.com/users/croath/orgs","repos_url":"https://api.github.com/users/croath/repos","events_url":"https://api.github.com/users/croath/events{/privacy}","received_events_url":"https://api.github.com/users/croath/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-04-27T14:42:10Z","updated_at":"2015-04-28T01:48:47Z","closed_at":null,"merged_at":null,"merge_commit_sha":"1376903cb354d18394e61e21e8e1ca352bb1309c","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/NSHipster/articles/pulls/283/commits","review_comments_url":"https://api.github.com/repos/NSHipster/articles/pulls/283/comments","review_comment_url":"https://api.github.com/repos/NSHipster/articles/pulls/comments{/number}","comments_url":"https://api.github.com/repos/NSHipster/articles/issues/283/comments","statuses_url":"https://api.github.com/repos/NSHipster/articles/statuses/106c5ece1d65565cedd1614292792f603a7667a8","head":{"label":"croath:swift-1.2","ref":"swift-1.2","sha":"106c5ece1d65565cedd1614292792f603a7667a8","user":{"login":"croath","id":1398729,"avatar_url":"https://avatars.githubusercontent.com/u/1398729?v=3","gravatar_id":"","url":"https://api.github.com/users/croath","html_url":"https://github.com/croath","followers_url":"https://api.github.com/users/croath/followers","following_url":"https://api.github.com/users/croath/following{/other_user}","gists_url":"https://api.github.com/users/croath/gists{/gist_id}","starred_url":"https://api.github.com/users/croath/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/croath/subscriptions","organizations_url":"https://api.github.com/users/croath/orgs","repos_url":"https://api.github.com/users/croath/repos","events_url":"https://api.github.com/users/croath/events{/privacy}","received_events_url":"https://api.github.com/users/croath/received_events","type":"User","site_admin":false},"repo":{"id":17640698,"name":"articles","full_name":"croath/articles","owner":{"login":"croath","id":1398729,"avatar_url":"https://avatars.githubusercontent.com/u/1398729?v=3","gravatar_id":"","url":"https://api.github.com/users/croath","html_url":"https://github.com/croath","followers_url":"https://api.github.com/users/croath/followers","following_url":"https://api.github.com/users/croath/following{/other_user}","gists_url":"https://api.github.com/users/croath/gists{/gist_id}","starred_url":"https://api.github.com/users/croath/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/croath/subscriptions","organizations_url":"https://api.github.com/users/croath/orgs","repos_url":"https://api.github.com/users/croath/repos","events_url":"https://api.github.com/users/croath/events{/privacy}","received_events_url":"https://api.github.com/users/croath/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/croath/articles","description":"Weekly articles for NSHipster.com","fork":true,"url":"https://api.github.com/repos/croath/articles","forks_url":"https://api.github.com/repos/croath/articles/forks","keys_url":"https://api.github.com/repos/croath/articles/keys{/key_id}","collaborators_url":"https://api.github.com/repos/croath/articles/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/croath/articles/teams","hooks_url":"https://api.github.com/repos/croath/articles/hooks","issue_events_url":"https://api.github.com/repos/croath/articles/issues/events{/number}","events_url":"https://api.github.com/repos/croath/articles/events","assignees_url":"https://api.github.com/repos/croath/articles/assignees{/user}","branches_url":"https://api.github.com/repos/croath/articles/branches{/branch}","tags_url":"https://api.github.com/repos/croath/articles/tags","blobs_url":"https://api.github.com/repos/croath/articles/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/croath/articles/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/croath/articles/git/refs{/sha}","trees_url":"https://api.github.com/repos/croath/articles/git/trees{/sha}","statuses_url":"https://api.github.com/repos/croath/articles/statuses/{sha}","languages_url":"https://api.github.com/repos/croath/articles/languages","stargazers_url":"https://api.github.com/repos/croath/articles/stargazers","contributors_url":"https://api.github.com/repos/croath/articles/contributors","subscribers_url":"https://api.github.com/repos/croath/articles/subscribers","subscription_url":"https://api.github.com/repos/croath/articles/subscription","commits_url":"https://api.github.com/repos/croath/articles/commits{/sha}","git_commits_url":"https://api.github.com/repos/croath/articles/git/commits{/sha}","comments_url":"https://api.github.com/repos/croath/articles/comments{/number}","issue_comment_url":"https://api.github.com/repos/croath/articles/issues/comments{/number}","contents_url":"https://api.github.com/repos/croath/articles/contents/{+path}","compare_url":"https://api.github.com/repos/croath/articles/compare/{base}...{head}","merges_url":"https://api.github.com/repos/croath/articles/merges","archive_url":"https://api.github.com/repos/croath/articles/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/croath/articles/downloads","issues_url":"https://api.github.com/repos/croath/articles/issues{/number}","pulls_url":"https://api.github.com/repos/croath/articles/pulls{/number}","milestones_url":"https://api.github.com/repos/croath/articles/milestones{/number}","notifications_url":"https://api.github.com/repos/croath/articles/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/croath/articles/labels{/name}","releases_url":"https://api.github.com/repos/croath/articles/releases{/id}","created_at":"2014-03-11T18:06:35Z","updated_at":"2015-02-03T07:27:19Z","pushed_at":"2015-04-27T14:41:07Z","git_url":"git://github.com/croath/articles.git","ssh_url":"git@github.com:croath/articles.git","clone_url":"https://github.com/croath/articles.git","svn_url":"https://github.com/croath/articles","homepage":null,"size":2273,"stargazers_count":6,"watchers_count":6,"language":null,"has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":4,"mirror_url":null,"open_issues_count":0,"forks":4,"open_issues":0,"watchers":6,"default_branch":"master"}},"base":{"label":"NSHipster:zh-Hans","ref":"zh-Hans","sha":"d83fe6aba3c38f4afeb96589ad0dbf2c56b13004","user":{"login":"NSHipster","id":3135314,"avatar_url":"https://avatars.githubusercontent.com/u/3135314?v=3","gravatar_id":"","url":"https://api.github.com/users/NSHipster","html_url":"https://github.com/NSHipster","followers_url":"https://api.github.com/users/NSHipster/followers","following_url":"https://api.github.com/users/NSHipster/following{/other_user}","gists_url":"https://api.github.com/users/NSHipster/gists{/gist_id}","starred_url":"https://api.github.com/users/NSHipster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NSHipster/subscriptions","organizations_url":"https://api.github.com/users/NSHipster/orgs","repos_url":"https://api.github.com/users/NSHipster/repos","events_url":"https://api.github.com/users/NSHipster/events{/privacy}","received_events_url":"https://api.github.com/users/NSHipster/received_events","type":"Organization","site_admin":false},"repo":{"id":7414142,"name":"articles","full_name":"NSHipster/articles","owner":{"login":"NSHipster","id":3135314,"avatar_url":"https://avatars.githubusercontent.com/u/3135314?v=3","gravatar_id":"","url":"https://api.github.com/users/NSHipster","html_url":"https://github.com/NSHipster","followers_url":"https://api.github.com/users/NSHipster/followers","following_url":"https://api.github.com/users/NSHipster/following{/other_user}","gists_url":"https://api.github.com/users/NSHipster/gists{/gist_id}","starred_url":"https://api.github.com/users/NSHipster/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/NSHipster/subscriptions","organizations_url":"https://api.github.com/users/NSHipster/orgs","repos_url":"https://api.github.com/users/NSHipster/repos","events_url":"https://api.github.com/users/NSHipster/events{/privacy}","received_events_url":"https://api.github.com/users/NSHipster/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/NSHipster/articles","description":"Weekly articles for NSHipster.com","fork":false,"url":"https://api.github.com/repos/NSHipster/articles","forks_url":"https://api.github.com/repos/NSHipster/articles/forks","keys_url":"https://api.github.com/repos/NSHipster/articles/keys{/key_id}","collaborators_url":"https://api.github.com/repos/NSHipster/articles/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/NSHipster/articles/teams","hooks_url":"https://api.github.com/repos/NSHipster/articles/hooks","issue_events_url":"https://api.github.com/repos/NSHipster/articles/issues/events{/number}","events_url":"https://api.github.com/repos/NSHipster/articles/events","assignees_url":"https://api.github.com/repos/NSHipster/articles/assignees{/user}","branches_url":"https://api.github.com/repos/NSHipster/articles/branches{/branch}","tags_url":"https://api.github.com/repos/NSHipster/articles/tags","blobs_url":"https://api.github.com/repos/NSHipster/articles/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/NSHipster/articles/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/NSHipster/articles/git/refs{/sha}","trees_url":"https://api.github.com/repos/NSHipster/articles/git/trees{/sha}","statuses_url":"https://api.github.com/repos/NSHipster/articles/statuses/{sha}","languages_url":"https://api.github.com/repos/NSHipster/articles/languages","stargazers_url":"https://api.github.com/repos/NSHipster/articles/stargazers","contributors_url":"https://api.github.com/repos/NSHipster/articles/contributors","subscribers_url":"https://api.github.com/repos/NSHipster/articles/subscribers","subscription_url":"https://api.github.com/repos/NSHipster/articles/subscription","commits_url":"https://api.github.com/repos/NSHipster/articles/commits{/sha}","git_commits_url":"https://api.github.com/repos/NSHipster/articles/git/commits{/sha}","comments_url":"https://api.github.com/repos/NSHipster/articles/comments{/number}","issue_comment_url":"https://api.github.com/repos/NSHipster/articles/issues/comments{/number}","contents_url":"https://api.github.com/repos/NSHipster/articles/contents/{+path}","compare_url":"https://api.github.com/repos/NSHipster/articles/compare/{base}...{head}","merges_url":"https://api.github.com/repos/NSHipster/articles/merges","archive_url":"https://api.github.com/repos/NSHipster/articles/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/NSHipster/articles/downloads","issues_url":"https://api.github.com/repos/NSHipster/articles/issues{/number}","pulls_url":"https://api.github.com/repos/NSHipster/articles/pulls{/number}","milestones_url":"https://api.github.com/repos/NSHipster/articles/milestones{/number}","notifications_url":"https://api.github.com/repos/NSHipster/articles/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/NSHipster/articles/labels{/name}","releases_url":"https://api.github.com/repos/NSHipster/articles/releases{/id}","created_at":"2013-01-02T22:04:00Z","updated_at":"2015-04-20T08:34:26Z","pushed_at":"2015-04-27T14:42:47Z","git_url":"git://github.com/NSHipster/articles.git","ssh_url":"git@github.com:NSHipster/articles.git","clone_url":"https://github.com/NSHipster/articles.git","svn_url":"https://github.com/NSHipster/articles","homepage":null,"size":4757,"stargazers_count":390,"watchers_count":390,"language":null,"has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":166,"mirror_url":null,"open_issues_count":10,"forks":166,"open_issues":10,"watchers":390,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/NSHipster/articles/pulls/283"},"html":{"href":"https://github.com/NSHipster/articles/pull/283"},"issue":{"href":"https://api.github.com/repos/NSHipster/articles/issues/283"},"comments":{"href":"https://api.github.com/repos/NSHipster/articles/issues/283/comments"},"review_comments":{"href":"https://api.github.com/repos/NSHipster/articles/pulls/283/comments"},"review_comment":{"href":"https://api.github.com/repos/NSHipster/articles/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/NSHipster/articles/pulls/283/commits"},"statuses":{"href":"https://api.github.com/repos/NSHipster/articles/statuses/106c5ece1d65565cedd1614292792f603a7667a8"}}}}