[
  {
    "path": "README.md",
    "content": "Developing iOS 9 Apps with Swift 字幕简体中文翻译项目\n---\n\niTunes U 课程地址：[iTunes U/Developing iOS 9 Apps Swift](https://itunes.apple.com/cn/course/developing-ios-9-apps-swift/id1104579961)\n\nCS193P 课程地址：[CS193P iPhone Application Development](http://web.stanford.edu/class/cs193p/cgi-bin/drupal/)\n\n### 相关链接\n\n[Developing iOS 8 Apps with Swift 字幕翻译](https://github.com/X140Yu/Developing_iOS_8_Apps_With_Swift)\n\n### 校对规则\n\n请参见文档：[校对规则](https://github.com/X140Yu/Developing_iOS_8_Apps_With_Swift/blob/master/proofread-rules.md)。\n\n### 字幕下载\n\n直接点击[项目 Zip 包](https://github.com/X140Yu/Developing-iOS-9-Apps-with-Swift/archive/master.zip)进行全部已有字幕的下载。\n\n### 视频及课件下载\n\n[Download](./download.md)\n\n### 联系我们\n\n如果您想参与项目，请直接在 [Issues](https://github.com/X140Yu/Developing-iOS-9-Apps-with-Swift/issues) 区发言。\n\n如果仅仅是想了解翻译的进度，关注项目的更新或者到 [Issues](https://github.com/X140Yu/Developing-iOS-9-Apps-with-Swift/issues) 区发言即可。\n\n### 版权说明\n\nThe original work by Stanford University is licensed under a Creative Commons Attribution-Noncommercial-Share Alike 3.0 United States License.\n\n<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/3.0/us/\"><img alt=\"Creative Commons License\" style=\"border-width:0\" src=\"https://i.creativecommons.org/l/by-nc-sa/3.0/us/88x31.png\" /></a><br />This work is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-nc-sa/3.0/us/\">Creative Commons Attribution-NonCommercial-ShareAlike 3.0 United States License</a>.\n"
  },
  {
    "path": "download.md",
    "content": "# Video\n[lecture 1](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic1/v4/64/b0/84/64b084ce-11d0-a3ff-e901-bcb0b38340b9/318-3290009375018043679-01_iTunes_CS193P_03_28_16_1080_720p_1500cc.m4v)\n\n[lecture 2](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/45/74/46/45744676-931d-e1d4-1787-952713e66c45/320-8373286204145257290-02_CS193P_3_30_16_720p1500cc.mp4)\n\n[lecture 3](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/a8/92/8e/a8928e55-ff74-cd37-6c9d-a91d1dda2b71/309-7506772204647137370-03_CS193P_4_04_16_1080p_3mb_cc2.m4v)\n\n[lecture 4](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/70/86/bf/7086bfd5-f133-6686-a319-7ba7947bae16/305-7247414449295650666-04_CS193P_4_06_16_1080p_3mb_cc.m4v)\n\n[lecture 5](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/36/91/d6/3691d659-ec3b-d34f-b8ec-a92e1183095f/328-1962441713930624806-05_CS193P_4_11_16_1080p_3mb_cc.m4v)\n\n[lecture 6](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic30/v4/ab/b2/70/abb270a8-6473-7658-72b6-f614a3bd5489/333-2664853460560613531-06_CS193P_4_13_16_rev_1080p_3mb.m4v)\n\n[lecture 7](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/81/b0/1f/81b01f26-ccd9-9df7-df6f-c5d34aea47aa/302-7208808734861639493-07_CS193__4_18_16_1080p_3mb_cc.m4v)\n\n[lecture 8](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/99/1e/e0/991ee064-fcd4-267f-4595-361d14bc09d0/336-4841244943511706201-08_CS193_4_20_16_1080p_3mb_cc.m4v)\n\n[lecture 9](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic30/v4/b3/4f/d0/b34fd003-ee43-43dc-4b21-6c355688fb3c/311-4524248345011539875-09_CS193_4_25_16_1_1080p_3mb.m4v)\n\n[lecture 10](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/df/93/44/df9344e9-03cf-fcfe-e550-3548d53c190d/326-7677824725330965182-10_CS193_4_27_16_1_1080p_3mb.m4v)\n\n[lecture 11](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/d8/08/29/d80829e3-fced-1630-5942-5306cc663461/322-952121251318135044-11_CS193_5_02_16_1080p_3mb.m4v)\n\n[lecture 12](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/64/6c/40/646c4016-9bd4-d378-a880-2ac977f38093/330-2525015638168359918-12_CS193_5_04_16_rev2_1080p_3mb.m4v)\n\n[lecture 13](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/14/a3/b6/14a3b675-ba6c-7594-fcb7-fc0b4e82a0b7/310-1407346536923462131-13_CS193_5_09_16_1080p_3mb.m4v)\n\n[lecture 14](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/f1/ca/44/f1ca444b-4578-8114-7297-555f4cdc9b57/326-7999025039413500594-14_CS193_5_11_16_1080p_3mb.m4v)\n\n[lecture 15](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/80/eb/65/80eb6594-3604-9eac-1a93-187de9e32c1e/337-4900765140487554688-15_CS193_5_16_16_1080p_3mb.m4v)\n\n[lecture 16](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/2b/9a/58/2b9a58e0-7761-b64f-45a2-2582d7f93644/324-5681395727728634007-16_CS193_5_18_16_1080p_3mb.m4v)\n\n[lecture 17](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/bb/39/61/bb3961d5-73a0-42ec-1e71-0336508e9dfa/311-3400152801833314139-17_CS193_5_23_16_1080p_3mb.m4v)\n\n[lecture 18](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/c8/db/e9/c8dbe99d-6f8e-28f5-47f4-ffe0c873d021/335-740161242915993166-18_CS193_5_25_16_1080p_3mb.m4v)\n\n# Slides\n[lecture 1 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic1/v4/f4/05/ff/f405ffb5-50b0-95c6-fd17-a6c262311a2d/321-5596613686960899183-CS193P_S16_Lecture_1_Slides.pdf)\n\n[lecture 2 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/ef/31/cc/ef31cc34-7cd0-e3c4-425c-e7f75a262f00/321-3432256539360740647-CS193P_S16_Lecture_2_Slides.pdf)\n\n[lecture 3 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/e6/a1/7e/e6a17ee2-b99f-3221-addd-da39d12d8802/321-6470380314597358395-CS193P_S16_Lecture_3_Slides.pdf)\n\n[lecture 4 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/fb/b9/58/fbb95870-c6be-79e2-77c5-c6474b8a40bf/307-5050413922657858617-CS193P_S16_Lecture_4_Slides.pdf)\n\n[lecture 5 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/7d/de/00/7dde003d-b32b-93fc-9786-0ec16c29ffb5/334-741241953225611839-CS193P_S16_Lecture_5_Slides.pdf)\n\n[lecture 6 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/ae/3e/6e/ae3e6ece-fead-e585-2035-756ccd82bfd0/308-1536759857490550427-CS193P_S16_Lecture_6_Slides.pdf)\n\n[lecture 7 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/47/02/9e/47029e12-1843-f40c-095c-ce3781137ed0/308-1708618185040143775-CS193P_S16_Lecture_7_Slides.pdf)\n\n[lecture 8 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/57/48/6c/57486c13-678e-7892-9cb4-9dbd58ab6fae/328-2295701575035385283-CS193P_S16_Lecture_8_Slides.pdf)\n\n[lecture 9 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/31/fb/33/31fb33c5-65ff-8e07-9c8a-2c49dd75f734/319-404525925375936666-CS193P_S16_Lecture_9_Slides.pdf)\n\n[lecture 10 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/7c/36/24/7c36249c-605a-8fc7-5c6c-a49abe0c8d37/317-3926700305190050506-CS193P_S16_Lecture_10_Slides.pdf)\n\n[lecture 11 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/52/74/73/52747331-a857-1914-9ebb-dc4a6dde68e7/319-3727135049627801646-CS193P_S16_Lecture_11_Slides.pdf)\n\n[lecture 12 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/f2/9c/61/f29c6128-8f92-5c81-b1ce-6d0d62d29f0c/318-7132989426423920990-CS193P_S16_Lecture_12_Slides.pdf)\n\n[lecture 13 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/c5/37/96/c537967b-6e29-f272-b57a-88e0ce60d531/306-350276286767890645-CS193P_S16_Lecture_13_Slides.pdf)\n\n[lecture 14 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/9b/5e/59/9b5e5936-5126-85d4-6b18-4a13d9e7afc5/335-2050748076731576057-CS193P_S16_Lecture_14_Slides.pdf)\n\n[lecture 15 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/55/28/db/5528dbac-7421-90ea-0d18-61d8b085e7e1/304-2868878214971040553-CS193P_S16_Lecture_15_Slides.pdf)\n\n[lecture 16 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/42/13/f9/4213f984-9a28-80ac-8db8-b242dd377c4c/335-760378487450689313-CS193P_S16_Lecture_16_Slides.pdf)\n\n[lecture 17 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/d8/aa/24/d8aa2482-9c87-d22a-ecec-c5bff601bc0e/322-3967892605293848768-CS193P_S16_Lecture_17_Slides.pdf)\n\n[lecture 18 slides](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/d9/38/2c/d9382c15-0379-0000-3cbe-233ac1f92023/328-8624592354314154483-CS193P_S16_Lecture_18_Slides.pdf)\n\n[project 1](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic30/v4/8b/a7/8c/8ba78c73-a911-b9d9-7406-7b6c35b1a635/330-4665516795304515844-CS193P_S16_Programming_Project_1.pdf)\n\n[project 2](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/62/62/f2/6262f2b4-721c-d325-3c23-ced31802068d/303-6526141645397285536-Programming_2.pdf)\n\n[project 3](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/90/64/be/9064beaa-cc04-ad7f-30e4-a9330e21caba/320-5665175142130618734-CS193P_S16_Programming_Project_3.pdf)\n\n[project 4](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic30/v4/0b/d2/ad/0bd2ad88-4abf-29a5-b406-cefeb3637c55/315-4965520355348488665-CS193P_S16_Programming_Project_4.pdf)\n\n[project 5](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic18/v4/e8/ba/cc/e8bacc96-9c52-8652-5613-950db7b65e5e/328-5947046615294240890-CS193P_S16_Programming_Project_5.pdf)\n\n[project 6](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic20/v4/46/05/9a/46059aff-bffb-1dcf-00ef-0d22bad80b47/322-6708752098278348100-CS193P_S16_Programming_Project_6.pdf)\n\n[reading 1](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic60/v4/df/8f/72/df8f7285-414d-f3f3-318a-6bb7246252b8/329-6584533342020921682-Reading_1.pdf)\n\n[reading 2](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic30/v4/32/fc/8b/32fc8b6a-bc29-8977-9035-1fc2b1b427d3/323-869352964012275742-Reading_2.pdf)\n\n[reading 3](https://itunesu-assets.itunes.apple.com/apple-assets-us-std-000001/CobaltPublic30/v4/4a/d9/8f/4ad98f9f-18ba-7d7e-8a3e-99e8bebd2e82/313-6521184191452265856-Reading_3_2.pdf)\n\n"
  },
  {
    "path": "subtitles/1. Course Overview and Introduction to iOS, Xcode, and Swift.srt",
    "content": "1\n00:00:00,001 --> 00:00:08,207\n[SOUND] Stanford University. >> All right well welcome\n斯坦福大学\n\n2\n00:00:08,209 --> 00:00:13,212\nto Stanford CS193P. This is Spring of 2016 version and\n欢迎来到 2016 年春季的斯坦福 CS193P 课程\n\n3\n00:00:13,214 --> 00:00:16,982\ntoday I'm gonna give you a real quick explanation of what\n今天我会快速阐述一下这门课是关于什么的\n\n4\n00:00:16,984 --> 00:00:20,986\nthis class is to make sure you're in the right place. I'm\n以免你们来错了地方\n\n5\n00:00:20,988 --> 00:00:23,722\ngonna talk about prerequisites cuz it's super important to be\n也会介绍一下参加这门课程的前提\n\n6\n00:00:23,724 --> 00:00:27,159\nsuccessful in this class to have the prerequisites.\n要想上好这门课，有些准备还是很重要的\n\n7\n00:00:27,161 --> 00:00:30,129\nThen I'm just gonna give you the briefest overview of what\n接着我会介绍一下 iOS 是什么\n\n8\n00:00:30,131 --> 00:00:34,466\niOS is. Most of you know because you have iPhones or\n你们应该都知道\n\n9\n00:00:34,468 --> 00:00:35,300\niPads or something like that, so\n因为你们用过 iPhone 或者 iPad\n\n10\n00:00:35,302 --> 00:00:38,037\nI'm not gonna waste a lot of time talking about that. And\n我不会在介绍 iOS 上浪费很多时间\n\n11\n00:00:38,039 --> 00:00:41,206\nthen finally I'm gonna dive right into a big demo that's\n最后我会带你们做一个大一点的 demo\n\n12\n00:00:41,208 --> 00:00:43,475\ngonna build our first application. Cuz I really\n直接开始打造我们的第一个应用程序\n\n13\n00:00:43,477 --> 00:00:45,411\ndon't believe in wasting a lot of time with overhead.\n因为我不太想花太多时间讲一些理论的知识\n\n14\n00:00:45,413 --> 00:00:47,513\nWe're just gonna dive right in and start learning how to do\n我们就直接开始上手做一些东西\n\n15\n00:00:47,515 --> 00:00:51,984\nthis stuff, okay? We only have ten weeks to learn iOS. That's\n因为我们的课程只有 10 周\n\n16\n00:00:51,986 --> 00:00:54,753\na short amount of time for it. It's a very powerful system.\n对于一个这么强大的系统来说，这点学习时间太短了\n\n17\n00:00:54,755 --> 00:00:59,158\nSo we're gonna have to really go at break neck speed. So\n所以需要以飞快的速度进行学习\n\n18\n00:00:59,160 --> 00:01:00,292\nwhat will you learn in this class?\n在这门课程中你将学到什么？\n\n19\n00:01:00,294 --> 00:01:02,561\nYou're gonna learn to build cool apps, all right.\n你将会学到如何打造很酷的 App\n\n20\n00:01:02,563 --> 00:01:05,064\niOS apps are cool. Why are they cool?\niOS App 很酷，为什么呢？\n\n21\n00:01:05,066 --> 00:01:07,466\nWell, they're cool because they sit in your pocket, and\n因为它们就在你的口袋里\n\n22\n00:01:07,468 --> 00:01:09,468\nyou can bring it out and show your friends.\n你可以直接拿出来给你的朋友们看\n\n23\n00:01:09,470 --> 00:01:12,171\nThey're cool because they're really easy to distribute.\n还有就是，App 很容易被发布\n\n24\n00:01:12,173 --> 00:01:12,304\nIf you build an app,\n如果你开发了一款应用\n\n25\n00:01:12,306 --> 00:01:15,040\nyou can put it on the app store with no work. Boom,\n你可以很轻松地把它放到 App Store 上\n\n26\n00:01:15,042 --> 00:01:19,078\nship it out to your customers. And also it's a very vibrant,\n通过 App Store 把它移交给你的顾客\n\n27\n00:01:19,080 --> 00:01:22,448\ncommunity. All right? A lot of people doing iOS development,\niOS 开发的社区也很活跃\n\n28\n00:01:22,450 --> 00:01:24,416\nand they're very excited about it.\n很多人在做 iOS 开发，并且他们也很热爱\n\n29\n00:01:24,418 --> 00:01:28,320\nAnd, also the apps that you build have animation, a lot of\nApp 也会包含一些很酷的动画\n\n30\n00:01:28,322 --> 00:01:31,323\nreally cool interactions with users, so they're fun apps to\n和用户之间很炫的交互\n\n31\n00:01:31,325 --> 00:01:33,725\nbuild. Okay, so you probably know all that,\n所以制作 App 是很有趣的\n\n32\n00:01:33,727 --> 00:01:36,161\nthat's why you're here. Another thing you're gonna\n你们都知道这一点，这也是你们为什么来到这里的原因\n\n33\n00:01:36,163 --> 00:01:38,197\nlearn though and you're gonna get out of this class\n你们还会从这门课中学到\n\n34\n00:01:38,199 --> 00:01:40,899\nis real-life object-oriented programming.\n面向对象编程的知识\n\n35\n00:01:40,901 --> 00:01:43,569\niOS is entirely object-oriented in its design.\niOS 在设计上是完全面向对象的\n\n36\n00:01:43,571 --> 00:01:46,505\nAll the writing of code you have to do is object-oriented\n你们写的每一行代码都会是面向对象的\n\n37\n00:01:46,507 --> 00:01:49,141\nprogramming. And you're really gonna get the experience of\n你们将会从现实的面向对象编程中\n\n38\n00:01:49,143 --> 00:01:52,444\nbuilding a real-world thing using object-oriented\n获得很多经验\n\n39\n00:01:52,446 --> 00:01:55,481\nprogramming which is a great programming paradigm. And\n面向对象编程也是一个很好的编程范式\n\n40\n00:01:55,483 --> 00:01:57,282\nsome of the things your going to learn for example using\n你们将会使用\n\n41\n00:01:57,284 --> 00:02:00,085\nobject-oriented programming. Object-oriented databases,\n面向对象的数据库\n\n42\n00:02:00,087 --> 00:02:02,521\nwere going to do graphics with object oriented programming.\n使用面向对象来编写界面\n\n43\n00:02:02,523 --> 00:02:04,790\nObviously going to be some multimedia stuff,\n而且还会有一些关于多媒体的东西，\n\n44\n00:02:04,792 --> 00:02:06,959\nmulti threading, animation, networking.\n多线程、动画、网络等\n\n45\n00:02:06,961 --> 00:02:08,927\nAll kinds of stuff that you're learning in your other\n你们从其它 CS 课程中学到的知识\n\n46\n00:02:08,929 --> 00:02:11,163\ncomputer science classes, you're going to do for\n都会在这门课程中\n\n47\n00:02:11,165 --> 00:02:13,065\nreal, real life here in this class. So\n得到真实的应用\n\n48\n00:02:13,067 --> 00:02:15,734\nthat's really good, it's kind of a good synthesis class or\n这很好，这就像一门综合的课程\n\n49\n00:02:15,736 --> 00:02:18,570\npractical synthesis class for all that stuff.\n来运用你学所学到的知识\n\n50\n00:02:18,572 --> 00:02:22,908\nThe prerequisites are really important in this class.\n这门课的前提非常重要\n\n51\n00:02:22,910 --> 00:02:25,110\nThe main one is object-oriented programming.\n最主要的一个是面向对象编程\n\n52\n00:02:25,112 --> 00:02:27,746\nI really don't have time in ten weeks to take the time to\n我不会在这 10 周中花时间教你们\n\n53\n00:02:27,748 --> 00:02:30,015\nteach you object-oriented programming first, so\n如何使用面向对象编程\n\n54\n00:02:30,017 --> 00:02:32,851\nyou really need to know that coming in. So in terms of\n你们需要知道在这门课中会用到\n\n55\n00:02:32,853 --> 00:02:37,890\nStanford's prerequisites that means CS106A&B or CS106X.\n所以在学这门课之前需要先学习 CS106A&B 或 CS106X\n\n56\n00:02:37,892 --> 00:02:40,259\nThat's absolutely required okay, so you get some\n这是必须要有的前提\n\n57\n00:02:40,261 --> 00:02:44,062\nJava experience in there and a little bit of object-oriented.\n所以我假定你们现在有了一些 Java 的编程经验和一些面向对象的基础\n\n58\n00:02:44,064 --> 00:02:47,399\nAnd then really important to take some,\n在上这门课这之前\n\n59\n00:02:47,401 --> 00:02:50,202\njust some class where you're gonna do a lot of programming.\n上过一些写了很多代码的课程也是很重要的\n\n60\n00:02:50,204 --> 00:02:53,305\nOkay like CS107 which is not hugely object-oriented but\n例如 CS107，虽然没有大量关于面向对象的东西\n\n61\n00:02:53,307 --> 00:02:54,273\nthere's a lot of programming.\n但是上那门课会写很多代码\n\n62\n00:02:54,275 --> 00:02:58,043\nCS108 which is an awesome prerequisite for this class.\n如果你在参加这门课之前上过 CS108 是非常好的\n\n63\n00:02:58,045 --> 00:02:59,912\nOkay, that's basically object-oriented Programming.\n它讲是关于面向对象编程的东西\n\n64\n00:02:59,914 --> 00:03:02,548\nSo if you've taken CS108, you're gonna be well prepared\n所以如果你上过 CS108，你就已经准备好上这门课了\n\n65\n00:03:02,550 --> 00:03:05,551\nfor this class. CS110, again, not really object oriented\nCS110，同样也没有太多关于面向对象的知识\n\n66\n00:03:05,553 --> 00:03:07,553\nper-se, but there's a lot of coding in there.\n但同样是一门非常好的编程课程，因为其中有大量的编程实践\n\n67\n00:03:07,555 --> 00:03:10,189\nYou know, preferably you've taken some other CS classes,\n你最好还上过其它的一些 CS 课程\n\n68\n00:03:10,191 --> 00:03:12,925\nyou've written a lot of code because, let me warn you,\n写过很多代码\n\n69\n00:03:12,927 --> 00:03:16,728\nthis class is a lot of coding. All your assignments are all\n因为上这门课需要写很多代码\n\n70\n00:03:16,730 --> 00:03:19,731\ncoding. You're gonna write a ton of code in this class.\n所有的作业都是写代码，你会在这门课中写大量的代码\n\n71\n00:03:19,733 --> 00:03:22,267\nSo if you're not comfortable writing a ton of code,\n所以如果你真的不太适应写比较多的代码\n\n72\n00:03:22,269 --> 00:03:24,703\nthen this class is going to be a lot of work for you.\n那么这门课程对你来说将是一个挑战\n\n73\n00:03:24,705 --> 00:03:27,639\nYou're gonna find it, maybe you'll be a little underwater.\n你会慢慢发现的\n\n74\n00:03:27,641 --> 00:03:31,677\nOkay so be prepared for a lot of coding.\n所以做好要写很多代码的准备\n\n75\n00:03:32,379 --> 00:03:33,779\nWhen it comes to object-oriented programming,\n当谈到面向对象编程\n\n76\n00:03:33,781 --> 00:03:36,515\nyou should know all these terms like the back of your\n你就应该像了解你的手背一样了解这些术语\n\n77\n00:03:36,517 --> 00:03:37,616\nhand. You shouldn't be looking at those and\n你不应该连一些类似\n\n78\n00:03:37,618 --> 00:03:40,652\ngoing what, what's that, super class, I don't get it.\n「父类」的术语都不懂\n\n79\n00:03:40,654 --> 00:03:42,354\nOkay, you should not even be here, okay.\n如果是那样的话，你不应该来参加这门课程\n\n80\n00:03:42,356 --> 00:03:45,691\nGo take these other classes and then come back.\n先去参加别的课程，然后再回来\n\n81\n00:03:46,260 --> 00:03:50,062\nThis is an upper-level CS course, this is not 106 or\n这是一门更高等级的 CS 课程\n\n82\n00:03:50,064 --> 00:03:52,965\n107. Okay? It's a next level up. So if you haven't\n它不是 CS106 或 CS107，它是更高一级的东西\n\n83\n00:03:52,967 --> 00:03:56,802\nwritten a fairly sophisticated app before, okay, then you're\n如果你还没有写过一些比较复杂的程序\n\n84\n00:03:56,804 --> 00:04:00,472\ngonna find out whoa, this is a lot of work, okay. So\n那你就会发现，你需要学习的东西有很多\n\n85\n00:04:00,474 --> 00:04:02,674\nthat's the prerequisites, make sure you're prepared, for\n这就是参加这门课程的条件，确定你已经准备好了\n\n86\n00:04:02,676 --> 00:04:05,210\nthis class. And if you're not, just go take those classes and\n如果没有，就先去参加其它课程，然后再回来\n\n87\n00:04:05,212 --> 00:04:08,180\ncome back. All right. So, what's in iOS?\n什么是 iOS？\n\n88\n00:04:08,182 --> 00:04:10,749\nYou all know what's in iOS from a user standpoint.\n从一个用户的角度，你们应该都知道 iOS 是什么\n\n89\n00:04:10,751 --> 00:04:12,951\nI'm sure, you've used, all used iOS. So\n你确定你们全都用过 iOS\n\n90\n00:04:12,953 --> 00:04:16,622\nwhat's kinda under the covers? What are the programming APIs?\n但更深层的东西是什么？编程的 API 都是什么？\n\n91\n00:04:16,624 --> 00:04:19,791\nEveryone know what the words API means? That basically\n大家都知道 API 是什么意思\n\n92\n00:04:19,793 --> 00:04:23,161\nprogramming interface, it's the functions, and methods,\n它其实就是编程接口的意思，它是使 iOS App\n\n93\n00:04:23,163 --> 00:04:26,698\nand classes that we use to make an iOS app work. So\n工作的函数、方法和类\n\n94\n00:04:26,700 --> 00:04:30,936\nwhat are those APIs that we use? Well they're huge. Okay,\n我们能调用的 API 都有什么？它们有很多\n\n95\n00:04:30,938 --> 00:04:33,772\nthere's so much of it I can barely even summarize it here,\nAPI 实在太多了，我都没办法概括出来\n\n96\n00:04:33,774 --> 00:04:36,708\nbut I'm gonna summarize it by dividing it into four layers\n但是我可以把它分成四个层次来总结\n\n97\n00:04:36,710 --> 00:04:40,445\nokay? The core OS which is kind of near the hardware\nCore OS 层很接近硬件\n\n98\n00:04:40,447 --> 00:04:44,216\nall the way up to Cocoa Touch which is near the user, okay?\nCocoa Touch 层很接近用户\n\n99\n00:04:44,218 --> 00:04:46,318\nAnd then there's some layers in between. So\n在这两层之间还有一些层\n\n100\n00:04:46,320 --> 00:04:46,918\nlet's talk about these layers,\n所以我们先分层次来讨论\n\n101\n00:04:46,920 --> 00:04:50,055\nlet's start down at the bottom there. The hardware.\n先从底部开始看，硬件层\n\n102\n00:04:50,057 --> 00:04:54,159\nSo, people don't really realize this, but an iPhone\n大部分人都没有发现其实 iPhone 运行着 UNIX 系统\n\n103\n00:04:54,161 --> 00:04:58,330\nis running Unix, okay? There's basically a version of Unix\nUNIX 的最基本版本\n\n104\n00:04:58,332 --> 00:05:02,567\nrunning on it, so it has full multitasking, Unix filesystem,\n所以它有多线程、UNIX 文件系统\n\n105\n00:05:02,569 --> 00:05:04,303\neverything in there. And, you know,\n所有 UNIX 有的东西\n\n106\n00:05:04,305 --> 00:05:08,206\nyou get the power of that when you build iOS apps, okay? And\n在做 iOS 开发的时候你可以运用这些强大的能力\n\n107\n00:05:08,208 --> 00:05:09,675\nthat includes all these things here. Now,\niPhone 包含所有这些\n\n108\n00:05:09,677 --> 00:05:12,911\nthere's some things that this Unix layer, that are specific\n还有在 UNIX 这一层特意为了移动设备而打造的东西\n\n109\n00:05:12,913 --> 00:05:15,447\nto a mobile device like Power Management is really\n例如很重要的电量管理\n\n110\n00:05:15,449 --> 00:05:19,351\nimportant, Keychain Access to make sure that the people\nKeychain，来管理\n\n111\n00:05:19,353 --> 00:05:21,753\nare not accessing things on the phone that shouldn't,\n用户在手机上不应该接触的东西\n\n112\n00:05:21,755 --> 00:05:25,524\netc. But this is basically Unix in all its glory,\n但这最底层，基本上都是 UNIX 带来的光芒\n\n113\n00:05:25,526 --> 00:05:30,095\ndown at this low level. Next, there's a core services layer.\n在它上一层，是 Core Services 层\n\n114\n00:05:30,097 --> 00:05:33,265\nBecause we wanna program in object-oriented programming as\n因为我们在编写程序的时候尽量用到面向对象\n\n115\n00:05:33,267 --> 00:05:36,702\nmuch as possible, there's a layer which is written in\n这一层是在 UNIX 之上使用面向对象语言编写的\n\n116\n00:05:36,704 --> 00:05:40,906\nobject-oriented language, on top of Unix so that you can\n你可以在这一层得到\n\n117\n00:05:40,908 --> 00:05:44,743\nget at things like networking and multithreading and\n网络、多线程\n\n118\n00:05:44,745 --> 00:05:48,513\nnetwork, or preferences and SQL for databases.\n或者 SQL 数据库之类的东西\n\n119\n00:05:48,515 --> 00:05:51,083\nYou can get at these things using object oriented APIs.\n你可以通过面向对象的 API 来调用这些\n\n120\n00:05:51,085 --> 00:05:54,319\nSo this is kind of an object oriented layer on top of\n所以这一层是在 Core Services 之上的面向对象的一层\n\n121\n00:05:54,321 --> 00:05:57,589\nthe core services. Okay but there is no UI in this layer.\n在这一层是没有 UI(用户界面) 的\n\n122\n00:05:57,591 --> 00:06:01,126\nOkay this is kind of base layer. Now the next layer,\n有点像比较基础的层\n\n123\n00:06:01,128 --> 00:06:04,596\nsuper important. Ironically I don't have a lot of time to\n下一个非常重要的层\n\n124\n00:06:04,598 --> 00:06:07,899\ntalk about this in this class. I'll kind of let you know it's\n我没有太多时间在课堂上介绍它\n\n125\n00:06:07,901 --> 00:06:10,369\nthere but it'll be something you'll have to dive into\n你对这一层的了解取决你想要做些什么东西\n\n126\n00:06:10,371 --> 00:06:13,605\ndepending on what you want to do. But that's multimedia.\n这一层就是多媒体层\n\n127\n00:06:13,607 --> 00:06:17,909\nSo this is video, all kinds of different audio frameworks.\n在这一层，有视频、音频库\n\n128\n00:06:17,911 --> 00:06:21,680\nAnd then of course still pictures like JPEGs,\n处理例如 JPEG 图片的\n\n129\n00:06:21,682 --> 00:06:22,414\nthings like that and\n图片库\n\n130\n00:06:22,416 --> 00:06:26,551\ndrawing okay the Quartz API for drawing in 2D. OpenGL for\n用于 2D 绘图的 Quartz API\n\n131\n00:06:26,553 --> 00:06:29,388\ndrawing in 3D. So there's a lot of stuff here okay we\n用于 3D 绘图的 OpenGL\n\n132\n00:06:29,390 --> 00:06:32,257\nobviously don't have time in ten weeks to teach you OpenGL\n显然在 10 周的课程之内我不会教你们 OpenGL\n\n133\n00:06:32,259 --> 00:06:35,427\nyou're gonna have to learn that in a graphics class but\n你们需要在图形课程里学习\n\n134\n00:06:35,429 --> 00:06:36,962\nyou'll be able to use it here, okay.\n并在那里运用\n\n135\n00:06:36,964 --> 00:06:39,664\nAnd then at the top layer, this is where were going to\n最顶层，就是我们要花几乎所有的时间在的层\n\n136\n00:06:39,666 --> 00:06:41,800\nspend most of our time, is Cocoa touch, okay.\n就是 Cocoa Touch 层\n\n137\n00:06:41,802 --> 00:06:46,638\nIt is object-oriented API for building user interfaces okay?\n它提供了面向对象的 API 来搭建 UI\n\n138\n00:06:46,640 --> 00:06:49,341\nAnd these user interfaces are not just buttons and\n这些 UI 元素不仅仅包含\n\n139\n00:06:49,343 --> 00:06:52,043\nsliders on the screen. But things like,\n屏幕上的按扭的滑块\n\n140\n00:06:52,045 --> 00:06:54,012\nwhat to do when you shake your phone? Or\n还有当你摇动手机的时候应该怎么处理\n\n141\n00:06:54,014 --> 00:06:58,250\nusing the orientation of the phone as input for example,\n或者把设备的方向当作输入\n\n142\n00:06:58,252 --> 00:07:01,086\nokay. It also includes animation because in iOS,\n它还包含动画\n\n143\n00:07:01,088 --> 00:07:04,890\nin a lot of the apps there's a lot of animation going on.\n因为在 iOS 中，大量的 App 使用动画\n\n144\n00:07:04,892 --> 00:07:06,992\nIt's just part of the way it's being built and\n它被搭建的时候这就是其中的一部分了\n\n145\n00:07:06,994 --> 00:07:09,461\na lot of the stuff at this level is really high\n这一层的许多东西都是非常高层次的\n\n146\n00:07:09,463 --> 00:07:12,264\nlevel. Like there are objects that basically let you put\n例如，你可以对一个对象进行操作\n\n147\n00:07:12,266 --> 00:07:16,701\nan entire Safari browser in a rectangle inside your app.\n把整个 Safari 浏览器放进你 App 的一块区域中\n\n148\n00:07:16,703 --> 00:07:18,336\nOkay, this one object you just drag it in,\n你可以拖进来一个对象\n\n149\n00:07:18,338 --> 00:07:20,071\nboom you've got it. All you have to do,\n然后你就有对应的功能了\n\n150\n00:07:20,073 --> 00:07:23,108\nmaybe wire up the back button and you're ready to go.\n你也许只需要做一个连线就可以了\n\n151\n00:07:23,110 --> 00:07:26,278\nSame thing with maps. You've seen the whole map 3D maps and\n关于地图，你可能见过一些 2D，3D 地图\n\n152\n00:07:26,280 --> 00:07:28,814\nall that stuff. Again one thing you drag it in,\n同样的，你把它拖进来\n\n153\n00:07:28,816 --> 00:07:30,816\nnow you've got full map functionality\n你就有了全部地图相关的功能\n\n154\n00:07:30,818 --> 00:07:34,986\nin you application. So this is super powerful objects. Again\n它是非常强大的对象\n\n155\n00:07:34,988 --> 00:07:37,355\nin 10 weeks and I can only show you the basics of this.\n在 10 周的课程内，我只能展示给你这些对象的基本用途\n\n156\n00:07:37,357 --> 00:07:39,858\nHopefully the things I've chosen to teach you\n好在我选择教给你们的东西\n\n157\n00:07:39,860 --> 00:07:43,261\nwill have paradigms for using them. That you can apply to\n都有一些使用的范式\n\n158\n00:07:43,263 --> 00:07:45,730\nthe things that I don't have time to teach you, okay.\n你可以把它运用到我没有教给你的东西上面\n\n159\n00:07:45,732 --> 00:07:48,033\nSo I'm going to try and teach you the basics\n所以我会尽量教给你们让\n\n160\n00:07:48,035 --> 00:07:51,436\nof how to make it all work in a way that lets you go out and\n这些东西基本运行起来的方式\n\n161\n00:07:51,438 --> 00:07:54,973\nlearn new things quite straightforwardly. Okay, so\n然后你们就可以通过这种方式来直接学习新的东西了\n\n162\n00:07:54,975 --> 00:08:00,145\nthat's basically what's an iOS in three minutes or less.\n所以这就是关于什么是 iOS 的小演讲\n\n163\n00:08:00,147 --> 00:08:02,848\nThe components of the platform that we're gonna be developing\n以下这些东西是在这个平台开发所需要的\n\n164\n00:08:02,850 --> 00:08:07,185\non are as follows. First, there's some tools. Really,\n首先是工具\n\n165\n00:08:07,187 --> 00:08:11,323\nXcode 7 is 99% of what you're gonna be using in this class.\n99% 的时间你们都要使用 Xcode 7\n\n166\n00:08:11,325 --> 00:08:13,959\nOkay? It's your editor, your debugger,\n它是编辑器，debug 的工具\n\n167\n00:08:13,961 --> 00:08:15,894\nsource code management, everything is in Xcode7,\n源码管理，Xcode 7 都有\n\n168\n00:08:15,896 --> 00:08:20,131\nit's kind of a one stop shop. There is an extra thing there\n它类似于一个一站式的工具\n\n169\n00:08:20,133 --> 00:08:22,133\ninstruments which kind of plugs in with Xcode7 for\nXcode 7 中还有类似于插件一样的 Instruments 工具\n\n170\n00:08:22,135 --> 00:08:24,669\ndoing things like performance, measurement things like that\n做一些性能检测之类的事情\n\n171\n00:08:24,671 --> 00:08:27,372\nbut basically we're going to be in Xcode7. Okay, that's\n但是基本我们会在 Xcode 7 中干活\n\n172\n00:08:27,374 --> 00:08:32,344\nwhere we're gonna be doing all our work. Language, languages,\n编程语言\n\n173\n00:08:32,346 --> 00:08:34,279\nthere's actually two languages you can develop for\n做 iOS 开发你可以使用两种语言\n\n174\n00:08:34,281 --> 00:08:37,215\nin iOS. We're gonna teach you the more modern one which is\n我们会教你更现代的那个，Swift\n\n175\n00:08:37,217 --> 00:08:39,618\ncalled Swift, okay? But there's another one called\n另一个叫作 Objective-C\n\n176\n00:08:39,620 --> 00:08:42,187\nObjective C, I'm not really gonna talk about Objective C\n我不会太介绍 Objective-C\n\n177\n00:08:42,189 --> 00:08:47,425\nin this class, at least not primarily in the lecture. So\n至少在 lecture 中不是作为主要讲解的语言\n\n178\n00:08:47,427 --> 00:08:48,960\nyou will have to learn a new language,\n所以你得学一门新的语言\n\n179\n00:08:48,962 --> 00:08:50,729\nI'm sure none of you know Swift, or\n我知道你们都不了解 Swift\n\n180\n00:08:50,731 --> 00:08:52,964\nif you do, it's because you already know iOS.\n如果你了解，是因为你对 iOS 也已经有了了解\n\n181\n00:08:52,966 --> 00:08:55,500\nSo Swift will be a new language you'll have to learn,\nSwift 会作为你们必须要学习的新语言\n\n182\n00:08:55,502 --> 00:08:57,802\nI'll spend the first two weeks really trying to\n前两周我会尽力用火箭一般的速度\n\n183\n00:08:57,804 --> 00:09:01,406\ngive you rocket speed learning of this new language.\n给你们讲解这门新的语言\n\n184\n00:09:01,408 --> 00:09:03,275\nThen there's a lot of frameworks,\n然后还有大量的框架\n\n185\n00:09:03,277 --> 00:09:06,811\nlike foundation and UI kit which is the kinda that base\n例如 Foundation 和 UIKit\n\n186\n00:09:06,813 --> 00:09:09,247\ncore services stuff and the UI stuff, but\n它们分别是核心服务和 UI 之类的东西\n\n187\n00:09:09,249 --> 00:09:12,551\nthere's also core data and core motion and map kit for\n还有 Core Data、 Core Motion 和 MapKit\n\n188\n00:09:12,553 --> 00:09:16,087\nall these things like the gyro and the accelerometer and\n它们分别是对象数据库、陀螺仪和加速计\n\n189\n00:09:16,089 --> 00:09:19,724\nthe object database so there's a lot of frameworks and\n还有地图相关的东西\n\n190\n00:09:19,726 --> 00:09:22,327\nwe'll cover as many of them as we can. And\n还有一些其它的框架，我们将会尽可能地介绍它们\n\n191\n00:09:22,329 --> 00:09:24,229\nreally just as important of all these things,\n还有和这些东西一样重要的一样东西\n\n192\n00:09:24,231 --> 00:09:28,667\nthere's a design strategy or design methodology, okay, for\n就是设计 iOS 应用的一种设计策略或设计方式\n\n193\n00:09:28,669 --> 00:09:31,970\niOS called MVC, it's used on other platforms as well.\n叫作 MVC，在其它平台上也有应用\n\n194\n00:09:31,972 --> 00:09:35,040\nHow many people here have programmed before in an MVC\n有多少同学在之前使用过 MVC\n\n195\n00:09:35,042 --> 00:09:38,143\ntype of environment? See, so about half of you.\n哦，大概一半\n\n196\n00:09:38,145 --> 00:09:40,412\nNow I'm going to, since it's only half of you,\n既然只有一半的人了解 MVC\n\n197\n00:09:40,414 --> 00:09:41,212\nI will spend Wednesday,\n在周三 lecture\n\n198\n00:09:41,214 --> 00:09:44,482\nthe start of the lecture, explaining MVC. Okay, how,\n开始的时候，我会介绍 MVC\n\n199\n00:09:44,484 --> 00:09:49,454\nwhat MVC is, how it applies in iOS development. But it's very\n什么是 MVC，在 iOS 开发中如何运用\n\n200\n00:09:49,456 --> 00:09:51,990\nimportant to know, it's a very important thing to know. And\n这都非常重要\n\n201\n00:09:51,992 --> 00:09:55,093\nI'm even going to mention it a little bit in my demo today.\n我也会在今天的 demo 中介绍一些\n\n202\n00:09:55,095 --> 00:09:59,197\nAnd I'll just give you the 10 second overview of\n我只会给你们简单地讲述一下它\n\n203\n00:09:59,199 --> 00:10:02,701\nit. Because I can't really do anything, I can't show you any\n因为我还不能做任何事情\n\n204\n00:10:02,703 --> 00:10:06,304\ndemo without talking about MVC, it's that important.\n在介绍 MVC 之前我不能做任何 demo，它就是这么重要\n\n205\n00:10:06,306 --> 00:10:10,775\nOkay? So this next slide here is kind of giving you\n下一张幻灯片简单地介绍了一下\n\n206\n00:10:10,777 --> 00:10:13,144\na summary of what I'm gonna show you in the demo today.\n今天的这个 demo 大概要做些什么\n\n207\n00:10:13,146 --> 00:10:15,146\nYou don't need to read this slide now,\n你现在还不需要阅读这上面的内容\n\n208\n00:10:15,148 --> 00:10:18,216\nmy slides will be posted for you so you'll always going to\n幻灯片都会在课后发给你们\n\n209\n00:10:18,218 --> 00:10:20,919\nbe able to go back. This is a kind of slide you go back and\n这一张就是那种课后回去阅读\n\n210\n00:10:20,921 --> 00:10:24,456\nlook at later to make sure, yeah did I understand that in\n问问自己到底有没有看懂之类的幻灯片\n\n211\n00:10:24,458 --> 00:10:27,192\nthe demo, etc. Also as I'm doing the demo you'll\n你们还会有我做 demo 时候的视频\n\n212\n00:10:27,194 --> 00:10:30,629\nhave the video of it. You'll have a video of this demo so\n所以在我做 demo 的时候\n\n213\n00:10:30,631 --> 00:10:32,197\nyou don't need to furiously take notes or\n你们不需要非常着急地记笔记\n\n214\n00:10:32,199 --> 00:10:34,499\ntry to follow along to understand what I'm doing.\n或者完全跟着我同步做\n\n215\n00:10:34,501 --> 00:10:39,004\nYou can watch it at your leisure later.\n你可以在课后看视频\n\n216\n00:10:39,006 --> 00:10:42,307\nAll right, so I'm not going get back to my slides before,\n在 demo 之后，就不回放之前的幻灯片了\n\n217\n00:10:42,309 --> 00:10:45,577\nafter the demo so let me tell you what's coming up and then\n所以我先告诉你们后续会发生什么\n\n218\n00:10:45,579 --> 00:10:50,682\nthe rest of this is gonna be a demo. Today I have assigned\n然后这门课的后半部分都会是 demo\n\n219\n00:10:50,684 --> 00:10:54,119\nand it's on Piasa already, reading assignment number 1.\n今天我已经把第一次作业放到 Piazza（他们的课程平台） 上了\n\n220\n00:10:54,121 --> 00:10:57,355\nOkay, the reading assignments in this class are all learning\n这节课的阅读作业都是关于 Swift 的\n\n221\n00:10:57,357 --> 00:10:59,958\nSwift. You're gonna have three reading assignments and\n一共会有三次阅读作业\n\n222\n00:10:59,960 --> 00:11:01,693\nall of the three of them are gonna basically\n这几次作业\n\n223\n00:11:01,695 --> 00:11:05,897\ntake you through the entire Swift language guide, okay. So\n会让你对 Swift 有一个完整的了解\n\n224\n00:11:05,899 --> 00:11:09,034\nthat's what the reading assignments are all about.\n阅读作业的内容就是这些\n\n225\n00:11:09,269 --> 00:11:11,369\nOn Wednesday, I'm gonna continue the demo that I'm\n周三，我会继续进行这个 demo\n\n226\n00:11:11,371 --> 00:11:13,938\ndoing today. I'm gonna talk about MVC as I said and\n会介绍 MVC\n\n227\n00:11:13,940 --> 00:11:18,109\nthen programming assignment number 1 will go out. And\n第一次编程作业也会放出\n\n228\n00:11:18,111 --> 00:11:20,045\nthat's going to be due one week later.\n一周后截至\n\n229\n00:11:20,047 --> 00:11:25,483\nBefore lecture the next Wednesday. On Friday we\n在下周三的 lecture 之前\n\n230\n00:11:25,485 --> 00:11:29,087\nhave an optional section, room and time to be determined.\n会有个可选的部分，时间和地点有待确定\n\n231\n00:11:29,089 --> 00:11:32,023\nProbably around 1 o' clock. I'm not sure where.\n也许 1 点左右，我也不太确定在哪\n\n232\n00:11:32,025 --> 00:11:34,926\nThis Friday's and each Friday sometimes we'll have these\n有的周五都会有课\n\n233\n00:11:34,928 --> 00:11:36,561\nsections, sometimes not and it's optional,\n它们是可选的\n\n234\n00:11:36,563 --> 00:11:38,430\nyou don't have to show up if you don't want to but\n你不必须参加\n\n235\n00:11:38,432 --> 00:11:39,998\nit's gonna be pretty valuable information.\n但是课上会有很有价值的信息\n\n236\n00:11:40,000 --> 00:11:42,734\nThis Friday is how to use the debugger, which as you can\n这个周五会介绍如何使用 debugger，还是挺有价值的内容\n\n237\n00:11:42,736 --> 00:11:49,240\nimagine pretty valuable. Next Monday next week in general\n下周一\n\n238\n00:11:49,242 --> 00:11:52,143\nwe will be doing more of the same of getting started here\n会介绍如何上手\n\n239\n00:11:52,145 --> 00:11:54,713\nwith Swift and Xcode 7. You're, you're reading\nSwift 和 Xcode 7\n\n240\n00:11:54,715 --> 00:11:57,716\nassignment from today is gonna be due on Monday, and\n今天的阅读作业会在周一之前截至\n\n241\n00:11:57,718 --> 00:11:59,684\nthen, you'll have Reading Assignment 2 go\n接下来会有第二个阅读作业\n\n242\n00:11:59,686 --> 00:12:01,352\nout which will be due the next Monday, so\n下周一之前截至\n\n243\n00:12:01,354 --> 00:12:03,088\nthe Reading Assignments for the first three weeks\n前三周的阅读作业\n\n244\n00:12:03,090 --> 00:12:05,423\nare overlapping the Program Assignments. The first two\n和编程作业是重叠的\n\n245\n00:12:05,425 --> 00:12:08,026\nprograming assign- assignments are quite easy. So\n前两个作业是比较简单的\n\n246\n00:12:08,028 --> 00:12:10,328\nthere won't be a problem where you're really overloaded.\n所以这些作业对于你们来说也不会显得很多\n\n247\n00:12:10,330 --> 00:12:12,530\nStarting with programming assignment number 3,\n第三次编程作业\n\n248\n00:12:12,532 --> 00:12:15,166\nit gets quite a bit steeper, okay.\n会有一个很大的跳跃\n\n249\n00:12:15,168 --> 00:12:15,834\nQuestion? >> The programming\n有问题？ \n\n250\n00:12:15,836 --> 00:12:19,270\nassignments, they ask you to solve specific tasks?\n>> 编程作业是解决特定的编程任务吗？\n\n251\n00:12:19,272 --> 00:12:22,006\nAre there any ones that are more predicted?\n会有一些主观的问题吗？\n\n252\n00:12:22,008 --> 00:12:22,707\n>> Yes, so the question is\n>> 问题是，\n\n253\n00:12:22,709 --> 00:12:24,409\ndo the programming assignments ask you to solve\n编程作业是让你解决特定的编程任务\n\n254\n00:12:24,411 --> 00:12:27,011\na specific task, or are they kind of open-ended? And\n还是有一些开放性的问题？\n\n255\n00:12:27,013 --> 00:12:29,781\nthe answer is the program assignments have very specific\n答案是，编程作业有很明确的需求\n\n256\n00:12:29,783 --> 00:12:33,551\nrequired tasks that you must do. You can do them any way\n你可以通过任何方式完成\n\n257\n00:12:33,553 --> 00:12:36,154\nyou want, but you must satisfy the required tasks.\n但是你必须要满足指定的任务要求\n\n258\n00:12:36,156 --> 00:12:39,157\nAs far as open ended is, your gonna have a final project in\n提到开放性任务，你们最终持续三周的项目\n\n259\n00:12:39,159 --> 00:12:40,825\nthree weeks, that's completely open ended.\n是完全开放性的\n\n260\n00:12:40,827 --> 00:12:42,594\nYou get to choose entirely what you're gonna do,\n你可以自己选择你想要做什么\n\n261\n00:12:42,596 --> 00:12:45,396\ncompletely on your own, okay? If you read the document\n如果你读 Piazza 上的文档\n\n262\n00:12:45,398 --> 00:12:48,800\nthat's on Piazza, it explains all that, okay? So for\n上面就会有相关的解释了\n\n263\n00:12:48,802 --> 00:12:50,902\nthose of you who arrived late, read that doc,\n所以对于迟到的这些同学，去读文档\n\n264\n00:12:50,904 --> 00:12:54,005\nget on Piazza, read it, stay on Piazza, it's all about\n上 Piazza，读内容，泡在 Piazza 上\n\n265\n00:12:54,007 --> 00:12:56,207\nPiazza in this class in terms of communication.\nPiazza 就是用来交流的工具\n\n266\n00:12:56,209 --> 00:12:59,477\nSo get on there. Okay, all right,\n好的\n\n267\n00:12:59,479 --> 00:13:03,648\nthat's it. I'm going to dive right into this demo right\n我们现在开始做 demo\n\n268\n00:13:03,650 --> 00:13:08,620\nhere. We're going to start by launching Xcode.\n先启动 Xcode\n\n269\n00:13:08,622 --> 00:13:11,589\nXcode is free, you just go to the Mac app store and\n它是免费的，可以到 Mac App Store 上下载\n\n270\n00:13:11,591 --> 00:13:15,226\ndownload it. And when you launch it, you're going to get\n启动它\n\n271\n00:13:15,228 --> 00:13:19,697\nthis splash screen is going to appear right here. Let's hide\n会显示一个启动画面\n\n272\n00:13:19,699 --> 00:13:23,134\nthese other things. So here's Xcode. This spash screen has\n把其它的隐藏起来，这就是 Xcode\n\n273\n00:13:23,136 --> 00:13:25,703\na list of all the projects that you've been working on so\n启动界面的这个列表包含你当前进行的项目\n\n274\n00:13:25,705 --> 00:13:28,540\nright now we have none cuz it's the start of the quarter.\n现在还没有，因为课程才刚开始\n\n275\n00:13:28,542 --> 00:13:30,441\nBut you'll have you know each week you're gonna\n但你应当知道\n\n276\n00:13:30,443 --> 00:13:33,344\nhave more and more projects piling up in this side. And\n随着课程的进行，你会有越来越多的项目\n\n277\n00:13:33,346 --> 00:13:35,747\nthen these three choices are the three ways to kinda\n这三个选项是进入 Xcode 的三个选项\n\n278\n00:13:35,749 --> 00:13:38,416\nget into Xcode. 1, Here, playground,\n第一个选项 playground\n\n279\n00:13:38,418 --> 00:13:42,921\nthat's basically, it gives you the ability to write iOS apps,\n它给了你写 iOS App 的能力\n\n280\n00:13:42,923 --> 00:13:45,924\nand play with Xcode without building an app. Okay.\n但不需要新建一个 App\n\n281\n00:13:45,926 --> 00:13:49,194\nSo you can call APIs, put things on screen, draw things,\n所以你可以调用 API，画一些控件或图形等等\n\n282\n00:13:49,196 --> 00:13:52,330\netc. It's kind of a playground for playing around with iOS.\n它就像一个学习开发 iOS 应用的小训练场\n\n283\n00:13:52,332 --> 00:13:54,599\nWe really won't be using that much in this app.\n我们不会在这个 App 中使用它\n\n284\n00:13:54,601 --> 00:13:57,001\nBut in this class, in my demos, but\n但在这门课，或者 demo 中\n\n285\n00:13:57,003 --> 00:13:59,404\nyou can certainly you're welcome to use them,\n在你了解 Xcode 的过程中，\n\n286\n00:13:59,406 --> 00:14:01,439\nas you're playing around with Xcode.\n还是欢迎你使用它的\n\n287\n00:14:01,441 --> 00:14:03,508\nIt's kind of a fun environment. Down at\n它是个很有趣的编程环境\n\n288\n00:14:03,510 --> 00:14:06,911\nthe bottom here you can check out an existing Xcode,\n在最下面，你可以添加已有\n\n289\n00:14:06,913 --> 00:14:11,716\nproject, iOS project, that is in Source Code, management.\n源码管理的 Xcode 项目\n\n290\n00:14:11,718 --> 00:14:14,118\nOkay, now we're going to talk about Source Code management\n也许会在周五的课程中讨论源码管理\n\n291\n00:14:14,120 --> 00:14:16,888\nprobably at a Friday section in this quarter but\n但是不会在\n\n292\n00:14:16,890 --> 00:14:18,122\nnot right at the beginning of the class.\n这门课程刚开始的时候就讲\n\n293\n00:14:18,124 --> 00:14:20,859\nBut Source Code manager is basically a way that you can\n源码管理就是你可以通过类似数据库的方式\n\n294\n00:14:20,861 --> 00:14:23,728\ncheck your code in and out of like a database okay,\n来管理你的源代码\n\n295\n00:14:23,730 --> 00:14:27,131\nso that you can work with a team, each make changes,\n通过这种方式进行团队协作\n\n296\n00:14:27,133 --> 00:14:28,099\nmerge your changes, all that stuff.\n每个人对代码产生一些修改，然后合并这些修改之类的\n\n297\n00:14:28,101 --> 00:14:32,370\nSo here is where you would check out your project to work\n所以这个就是你获取已有源码管理项目的地方\n\n298\n00:14:32,372 --> 00:14:36,207\non. And this middle one is to create a new Xcode project,\n中间的这个是新建一个 Xcode 项目\n\n299\n00:14:36,209 --> 00:14:38,176\na new Xcode App and that's we're gonna do right now,\n现在就进行这一项\n\n300\n00:14:38,178 --> 00:14:41,212\nokay? We're gonna create from scratch a new app. Most of my\n从头开始创建一个新的 App\n\n301\n00:14:41,214 --> 00:14:44,449\ndemos involved creating an application from scratch,\n几乎所有的 demo 都是从头开始创建的\n\n302\n00:14:44,451 --> 00:14:45,750\nokay? Just because I think it's easier for\n因为在目前阶段\n\n303\n00:14:45,752 --> 00:14:49,120\nyou to learn if there's no magic behind the scenes where\n从零开始写项目\n\n304\n00:14:49,122 --> 00:14:49,921\nthings are appearing out of nowhere. So\n对你们来说更容易一些\n\n305\n00:14:49,923 --> 00:14:53,658\nwhere gonna start from scratch and go from there each time.\n所以我们从头开始新建应用\n\n306\n00:14:53,660 --> 00:14:55,660\nAll right, so I'm gonna click on this.\n点这里\n\n307\n00:14:55,662 --> 00:14:58,029\nYou can see it wants to create an app for me so\n它会为我新建一个应用\n\n308\n00:14:58,031 --> 00:14:59,264\nit's gonna ask me some questions.\n会问我几个问题\n\n309\n00:14:59,266 --> 00:15:01,866\nFirst it wants to know what kind of app I wanna build, and\n首先，它问我想要创建哪种类型的应用\n\n310\n00:15:01,868 --> 00:15:04,903\nwe wanna build an iOS application. So make sure you\n我们想新建 iOS App\n\n311\n00:15:04,905 --> 00:15:09,974\nclick iOS Application here, not watch app, or AppleTV app,\n所以确认你点击了 iOS Application，而不是其它的\n\n312\n00:15:09,976 --> 00:15:12,610\nor an OS X app, okay? We don't want any of that.\n我们不想要其它的\n\n313\n00:15:12,612 --> 00:15:16,047\nWe want iOS application. And inside there we have some\n我们想要 iOS 应用\n\n314\n00:15:16,049 --> 00:15:20,652\nchoices of the kind of iOS app we wanna build, like a game or\n在这里，它问我们想要建哪种类型的 iOS 应用\n\n315\n00:15:20,654 --> 00:15:23,087\nthis master detail which is usually for browsing\n例如是 Game 还是为了浏览数据库的 Master Detail Application\n\n316\n00:15:23,089 --> 00:15:25,890\na database. We're almost always gonna choose this one,\n我们几乎只会先择这一项\n\n317\n00:15:25,892 --> 00:15:30,028\nsingle view application. The view there is kinda referring\nSingle View Application，这里的 View 代表\n\n318\n00:15:30,030 --> 00:15:32,196\nto the view in MVC, model view controller.\nMVC 中的 V\n\n319\n00:15:32,198 --> 00:15:35,667\nThat design paradigm but this is the ba-, most basic\n这个模板会为我们的创建最基本的\n\n320\n00:15:35,669 --> 00:15:39,003\ntemplate and it gives us the least amount of code to start\nMVC 骨架，它会产生最少量的代码\n\n321\n00:15:39,005 --> 00:15:41,472\nwith, which is what we want cuz we're learning so we wanna\n这也是我们希望的\n\n322\n00:15:41,474 --> 00:15:44,676\nwrite the code. We don't want it to, write any code for us.\n我们正在学习，所以希望写代码的是我们，而不是 Xcode\n\n323\n00:15:44,678 --> 00:15:46,678\nSo we're gonna pick single view template there.\n所以这里选择 Single View 的模板\n\n324\n00:15:46,680 --> 00:15:49,447\nNow it wants to know a few things about our app,\n现在它需要知道关于 App 的几点信息\n\n325\n00:15:49,449 --> 00:15:52,784\nwhat the name of our app is, etc. The app we're going\nApp 的名字是什么等等\n\n326\n00:15:52,786 --> 00:15:55,853\nto build today is a calculator and it's gonna look quite\n今天要创建的应用是一个计算器\n\n327\n00:15:55,855 --> 00:15:58,790\na bit like this calculator, not exactly the same, but\n它看起来非常像一个计算器，但又不完全一致\n\n328\n00:15:58,792 --> 00:16:01,826\nsimilar to this calculator. This is a basic calculator,\n它会像这个，最基本的计算器\n\n329\n00:16:01,828 --> 00:16:04,262\nit comes with Mac OS and it's gonna look like this,\n是 Mac OS 上的原生应用\n\n330\n00:16:04,264 --> 00:16:06,464\nit's gonna have some keypads, gonna have some operations,\n它会有键盘，会有运算符\n\n331\n00:16:06,466 --> 00:16:09,867\ngonna have a little display in here. Basically a calculator,\n在这里还会有个小显示器\n\n332\n00:16:09,869 --> 00:16:11,336\nso I'm gonna call my app calculator.\n所以给我的 App 起名为 calculator\n\n333\n00:16:11,338 --> 00:16:13,938\nSo that's the name of this app. When I look at it on my\n它就是 App 的名字，当我在手机上查看它的时候\n\n334\n00:16:13,940 --> 00:16:16,074\nphone it's gonna say calculator is the name of it.\n上面显示的名字就会是 calculator\n\n335\n00:16:16,076 --> 00:16:19,010\nOkay? This organization name can be anything you want.\n这个组织名你可以随意填\n\n336\n00:16:19,012 --> 00:16:22,880\nIt's basically gonna appear in the copyright of your code.\n它会显示在你代码的版权信息上\n\n337\n00:16:22,882 --> 00:16:23,748\nOkay? When you write code,\n当你写代码的时候\n\n338\n00:16:23,750 --> 00:16:25,116\nat the top it's gonna say copyright,\n在最上面会显示版权信息\n\n339\n00:16:25,118 --> 00:16:26,718\nwhatever you put here. Put whatever you want.\n你可以在这里放什么都行\n\n340\n00:16:26,720 --> 00:16:28,953\nYour name or whatever. This however,\n姓名之类的\n\n341\n00:16:28,955 --> 00:16:33,925\nwants to uniquely identify you, okay, as a developer. And\n这里，需要一个不重复的标识\n\n342\n00:16:33,927 --> 00:16:36,728\na good way to do it is this reverse DNS notation here,\n一个解决这个问题的很好方式是这个逆向的 DNS 标志\n\n343\n00:16:36,730 --> 00:16:40,698\nedu.stanford.cs193p and then instead of putting instructor,\nedu.stanford.cs193p\n\n344\n00:16:40,700 --> 00:16:44,268\nput your SU net ID. Cuz no one else has that.\n在 instructor 那里填上你的学号就好，因为这不会重复\n\n345\n00:16:44,270 --> 00:16:46,304\nThis would uniquely identify you in the universe.\n这会在宇宙中唯一确定你\n\n346\n00:16:46,306 --> 00:16:49,407\nNo one else is going to have that organization identifier.\n没人会跟你重复的\n\n347\n00:16:49,409 --> 00:16:50,875\nAnd then it builds a unique\n随后它会产生一个独一无二的标识\n\n348\n00:16:50,877 --> 00:16:54,679\nidentifier from the app by combining these two things.\n通过把这两个结合起来的方式\n\n349\n00:16:54,681 --> 00:16:57,315\nOkay? You get to choose the language you want to program\n在这里选择你想要编程的语言\n\n350\n00:16:57,317 --> 00:17:00,385\nin here. It actually doesn't matter what you choose\n在这里选择什么无关紧要\n\n351\n00:17:00,387 --> 00:17:03,154\nhere, this is just going to be the language that the initial\n它只会为你创建\n\n352\n00:17:03,156 --> 00:17:05,723\ntemplate is going to give you it starts out in.\n相关语言的初始模板\n\n353\n00:17:05,725 --> 00:17:07,525\nYou can freely mix Objective C and\n在写 iOS 应用的时候\n\n354\n00:17:07,527 --> 00:17:10,561\nSwift when you're building IOS apps. Okay? Back and\n你可以把 Swift 和 Objective-C 混合起来\n\n355\n00:17:10,563 --> 00:17:13,364\nforth they're, you don't have to pick one and be stuck with\n你不需要在选择完一个之后就卡在这了\n\n356\n00:17:13,366 --> 00:17:16,234\nit. We're going to do all of our programming in this class\n在这门课中我们所有的编程都会使用 Swift\n\n357\n00:17:16,236 --> 00:17:19,570\nin Swift however. Then this is whether we want\n这里决定我们是要搭建一个\n\n358\n00:17:19,572 --> 00:17:21,139\nto build an iPhone only calculator.\n专属 iPhone 的\n\n\n359\n00:17:21,141 --> 00:17:24,909\nAn iPad only calculator. Or a universal calculator that will\n还是 iPad 的\n\n360\n00:17:24,911 --> 00:17:27,979\nwork on either iPad or iPhone. Okay? And\n或者是它们都可以使用的计算器\n\n361\n00:17:27,981 --> 00:17:30,181\nwe're gonna go universal even though the first two weeks\n选择 universal，尽管前两周\n\n362\n00:17:30,183 --> 00:17:33,151\nwe're going to be focusing on iPhone only. In the third week\n我们只会专注在 iPhone 上\n\n363\n00:17:33,153 --> 00:17:37,688\nwe'll expand our calculator to work on an iPad as well. Here,\n在第三周，我们会让计算器在 iPad 上也正常地跑起来\n\n364\n00:17:37,690 --> 00:17:39,657\nwe're not going to be using databases yet, that will be\n目前我们还不需要使用数据库\n\n365\n00:17:39,659 --> 00:17:43,661\nabout week six and we will be talking about testing later in\n第六周我们会讨论测试\n\n366\n00:17:43,663 --> 00:17:45,563\nthe quarter. Probably in a Friday section again, but\n也许在周五的课程中\n\n367\n00:17:45,565 --> 00:17:48,733\nwe're not doing it now so you can leave these unchecked.\n我们现在不会处理这些，所以这些不需要勾选\n\n368\n00:17:48,735 --> 00:17:49,767\nAll right, so now I hit Next, and\n点 Next\n\n369\n00:17:49,769 --> 00:17:53,037\nit says where do you wanna put this project? I'm gonna put\n它问你想把项目放在哪里\n\n370\n00:17:53,039 --> 00:17:56,808\nit in my home directory, in a folder called Developer, and\n我把它放到 ~/Developer 中\n\n371\n00:17:56,810 --> 00:17:59,444\nI highly recommend you do the same, okay.\n我也建议你们这样做\n\n372\n00:17:59,446 --> 00:18:02,180\nHome Directory Developer, so all your apps will start\n~/Developer，你们所有的 App 都放到这里\n\n373\n00:18:02,182 --> 00:18:05,750\npiling up in here. Here's the source control thing I was\n关于源码管理\n\n374\n00:18:05,752 --> 00:18:07,785\ntalking about, we're not gonna do this at the beginning, so\n我们一开始先不管\n\n375\n00:18:07,787 --> 00:18:10,521\nwe're gonna leave this unchecked. All right. So\n所以先不勾选\n\n376\n00:18:10,523 --> 00:18:13,324\nwe hit create, and it creates our first app. Now, it's\n点 create，它就创建了我们的第一个 App\n\n377\n00:18:13,326 --> 00:18:16,961\nactually created these six files, over here on the side.\n它实际上创建了这 6 个文件，在这侧边\n\n378\n00:18:16,963 --> 00:18:17,762\nAnd over the course of the quarter,\n在课程期间\n\n379\n00:18:17,764 --> 00:18:20,498\nI'll show you what all six of these are about. Today,\n我会告诉你们这 6 个文件都是做什么的\n\n380\n00:18:20,500 --> 00:18:23,768\nwe're only gonna focus on two of them.\n今天我们只会关注这两个\n\n381\n00:18:24,871 --> 00:18:27,772\nHow many of you have used Xcode before, for any class or\n你们有谁用过 Xcode？\n\n382\n00:18:27,774 --> 00:18:31,509\nanything? Okay, so about a third of you.\n好，大概 1/3\n\n383\n00:18:31,511 --> 00:18:34,178\nSo let me explain a little bit about Xcode's UI,\n我先介绍一下 Xcode 的 UI\n\n384\n00:18:34,180 --> 00:18:36,781\nwhat it looks like. You see this area on the left,\n左边这里\n\n385\n00:18:36,783 --> 00:18:40,051\nthis blue area? That's called the Navigator and\n蓝色的区域，它是 Navigator(导航器)\n\n386\n00:18:40,053 --> 00:18:43,554\nit's basically for navigating your project.\n它用来导航你的项目\n\n387\n00:18:43,556 --> 00:18:44,755\nAnd you can do it in different ways.\n通过几种不同的方式\n\n388\n00:18:44,757 --> 00:18:48,459\nThis is the Project Navigator that we see right here, and\n现在这个是项目导航\n\n389\n00:18:48,461 --> 00:18:50,595\nit's basically showing you your files.\n它用来显示项目的文件\n\n390\n00:18:50,597 --> 00:18:52,029\nYou can arrange them in folders and stuff, but\n你可以通过文件夹来重新组织它们\n\n391\n00:18:52,031 --> 00:18:55,166\njust basically the files in your app. But you can navigate\n但只是导航 App 中的文件\n\n392\n00:18:55,168 --> 00:18:58,669\nby searching, okay, you can type some search text in here,\n但是你可以通过搜索来查找 App 文件中的内容\n\n393\n00:18:58,671 --> 00:19:01,472\nsearch for it in your app. You can navigate all your\n如果你在 debug 的时候\n\n394\n00:19:01,474 --> 00:19:04,675\nbreakpoints if you're debugging. You can go back and\n可以在这里查看所有断点\n\n395\n00:19:04,677 --> 00:19:07,345\nlook at all your old builds to see any errors or\n查看之前编译版本的错误或警告\n\n396\n00:19:07,347 --> 00:19:11,149\nwarnings you have, okay, even if you fixed it you go back,\n即使你已经修复了它们并返回了\n\n397\n00:19:11,151 --> 00:19:13,484\nand look at them. So the navigator is kind\nNavigator 就像是用来关注\n\n398\n00:19:13,486 --> 00:19:16,521\nof how you keep track of what's going on in your app.\n你的 App 到底发生了什么事情的地方\n\n399\n00:19:16,523 --> 00:19:19,457\nOn the right hand side here we have the utilities area,\n在右手边，有 Utilities(工具) 区\n\n400\n00:19:19,459 --> 00:19:22,426\nwhich is actually two windows, see it's split top and\n有两个窗口，分成上下两部分\n\n401\n00:19:22,428 --> 00:19:26,230\nbottom here. The top part is essentially an inspector,\n上部是 Inspector(监视器)\n\n402\n00:19:26,232 --> 00:19:29,800\nit's going to let you analyze and change attributes of\n你可以通过它看到或改变\n\n403\n00:19:29,802 --> 00:19:33,004\nwhatever's selected in this main window. Right now we\n在主窗口选中的东西的属性\n\n404\n00:19:33,006 --> 00:19:35,673\ndon't have anything selected, so it's not showing anything.\n现在没有选中任何东西，所以没显示任何东西\n\n405\n00:19:35,675 --> 00:19:38,676\nAnd this bottom is essentially like a palette. Okay,\n这下面的部分就像一个调色板\n\n406\n00:19:38,678 --> 00:19:41,979\nyou're gonna be an artist building your app, okay, and\n在写应用的时候，你就是一个艺术家\n\n407\n00:19:41,981 --> 00:19:45,983\nyou're gonna need things like buttons and web views,\n因为你需要类似于 button 或 web view 之类的东西\n\n408\n00:19:45,985 --> 00:19:47,818\nand things like that, to build your app, and\n用来搭建你的应用\n\n409\n00:19:47,820 --> 00:19:48,953\nyou're gonna be finding them all,\n你会在这里找到它们\n\n410\n00:19:48,955 --> 00:19:51,122\nand pulling them all out of here. So it's your palette,\n然后可以从这里把它们拖出来，所以这就是你的调色板\n\n411\n00:19:51,124 --> 00:19:54,825\nyour artist palette, as you build things. Okay? You can\n你的艺术调色板，用来创造东西\n\n412\n00:19:54,827 --> 00:19:57,361\nshow and hide these two side panels with these buttons,\n你可以通过这些按扭显示或者隐藏侧面的面板\n\n413\n00:19:57,363 --> 00:20:00,831\nup here. I will tend to not do command keys, except for\n我尽量不使用快捷键，除了复制粘贴\n\n414\n00:20:00,833 --> 00:20:03,801\nlike copy and paste, so that you can see what's going on.\n所以你们就可以知道我到底做了哪些事情\n\n415\n00:20:03,803 --> 00:20:06,204\nBut there are tons of command keys in Xcode, and\n但是 Xcode 中有大量的快捷键\n\n416\n00:20:06,206 --> 00:20:10,441\nif you go To Xcode preferences and look under\n在 Xcode 的设置界面\n\n417\n00:20:10,443 --> 00:20:12,610\nkey bindings right here you can see all of them and\n你可以发现有大量大量的快捷键\n\n418\n00:20:12,612 --> 00:20:15,680\nthere's tons and tons and tons and you can even change them.\n你也可以对它们进行定制\n\n419\n00:20:15,682 --> 00:20:17,348\nOf course if you don't like them but\n如果你不喜欢它们也没关系\n\n420\n00:20:17,350 --> 00:20:18,849\nit has a lot of commands. All right, so\n但是它有大量的快捷键\n\n421\n00:20:18,851 --> 00:20:21,886\nI'll try to avoid using those command keys. So you can hide\n我尽量不使用快捷键\n\n422\n00:20:21,888 --> 00:20:25,756\nthose with these things so you have hidden both sides, right.\n可以使用按扭来做这些事情\n\n423\n00:20:25,758 --> 00:20:28,426\nSo you can kind of manage your screen real estate.\n你可以管理屏幕的分辨率\n\n424\n00:20:28,428 --> 00:20:31,662\nNow I have a very low-resolution screen here, so\n我电脑的分辨率非常低\n\n425\n00:20:31,664 --> 00:20:34,732\nI have to manage my real estate quite efficiently.\n所以为了高效我需要改变自己的分辨率\n\n426\n00:20:34,734 --> 00:20:36,567\nIf you have a higher resolution screen,\n如果你的分辨率很高\n\n427\n00:20:36,569 --> 00:20:39,837\nthen you would obviously not be doing as much hiding and\n你就不需要把这些东西给隐藏起来了\n\n428\n00:20:39,839 --> 00:20:44,108\nshowing of these things. So if we look at the navigator,\n现在我们看 Navigator\n\n429\n00:20:44,110 --> 00:20:44,775\nwhat's selected right now?\n当前选中的是什么？\n\n430\n00:20:44,777 --> 00:20:48,980\nIt's the project itself at the very top level, this blue bar.\n是最顶层的项目本身\n\n431\n00:20:48,982 --> 00:20:49,680\nThis selecting the project.\n它选中了项目\n\n432\n00:20:49,682 --> 00:20:53,217\nSo we're actually seeing the project, the kind\n所以在主窗口\n\n433\n00:20:53,219 --> 00:20:55,820\nof settings of the project, in the main window here.\n我们可以看到这个项目的设置\n\n434\n00:20:55,822 --> 00:20:59,624\nThis main window. Here are some of them here, right?\n这个主窗口，这里有一些设置\n\n435\n00:20:59,626 --> 00:21:01,325\nSome of these we set on that first page,\n第一页有一些可以设置的\n\n436\n00:21:01,327 --> 00:21:05,029\nlike the bundle identifier and whether it was universal or\n例如 Bundle Identifier（包的 ID）\n\n437\n00:21:05,031 --> 00:21:07,898\niPad and iPhone, etc. But there's plenty more\n是通用的还是只为了 iPhone 或 iPad 而造\n\n438\n00:21:07,900 --> 00:21:10,868\nsettings over here. We'll get to most of those settings as\n这里还有许多其它设置信息\n\n439\n00:21:10,870 --> 00:21:14,372\nthe quarter goes by. The only setting that's important for\n随着课程的进行，我们会逐渐了解这些设置\n\n440\n00:21:14,374 --> 00:21:16,540\nyou to know now, is this team setting.\n现在需要知道的设置信息是这个 team\n\n441\n00:21:16,542 --> 00:21:19,477\nSee here where it says team none? You're gonna wanna be\n现在上面显示的是 none\n\n442\n00:21:19,479 --> 00:21:24,782\nable to write your app, and have it run on a device. Okay.\n你想让你写的 App 运行在真实的设备上\n\n443\n00:21:24,784 --> 00:21:26,817\nIt has a simulator, which I'm gonna use today.\n我们今天会使用模拟器\n\n444\n00:21:26,819 --> 00:21:29,253\nBut you also wanna be able to run on a device. And\n但是你想让它运行在真实的设备上\n\n445\n00:21:29,255 --> 00:21:33,124\nto do that you need to register an Apple ID.\n为了这样，我们需要注册一个 Apple ID\n\n446\n00:21:33,126 --> 00:21:36,060\nSo here I already have mine, this CS193p Instructor, but\n我已经注册好了\n\n447\n00:21:36,062 --> 00:21:39,630\nyou're going to go down here to add an account, and\n不过你需要在这下面添加一个账号\n\n448\n00:21:39,632 --> 00:21:42,466\nyou're going to give an Apple ID and password. Any Apple ID\n填入 Apple ID 和密码\n\n449\n00:21:42,468 --> 00:21:45,736\nwill do, you don't have to join any program or anything,\n任意一个 Apple ID 都可以，不需要加入什么开发者计划之类的\n\n450\n00:21:45,738 --> 00:21:48,372\njust any Apple ID will work here. And\n普通的 Apple ID 就可以\n\n451\n00:21:48,374 --> 00:21:49,874\nyou'll put the ID and password in, and\n填入 ID 和密码\n\n452\n00:21:49,876 --> 00:21:51,676\nthen you're going to select it here. And\n选这里\n\n453\n00:21:51,678 --> 00:21:56,280\nthen it's going to appear here, like this. Okay? Now,\n它会在这里出现\n\n454\n00:21:56,282 --> 00:21:59,617\nwhen you have a team selected now you can plug a device\n当 team 有选择的东西以后，你就可以插上一个设备\n\n455\n00:21:59,619 --> 00:22:02,720\nin and you're gonna get this warning here, no provisioning\n会有一个没有证书的警告\n\n456\n00:22:02,722 --> 00:22:07,158\nprofiles found. And you just click fix issue right there.\n点这里的 fix issue \n\n457\n00:22:07,160 --> 00:22:08,926\nYou have to be connected to the network at the time,\n这时你需要联网\n\n458\n00:22:08,928 --> 00:22:11,829\nall right? Fix issue and it'll fix that.\n它会修复这个问题\n\n459\n00:22:11,831 --> 00:22:14,198\nIt'll basically get the ID of your device,\n它会获取你设备的 ID\n\n460\n00:22:14,200 --> 00:22:18,436\nregister it with you as the developer and off you go.\n注册成为开发者，然后就可以了\n\n461\n00:22:18,438 --> 00:22:21,672\nOkay? So you'll need to do that. You only really need to\n你只需要在想把 App 运行在真实设备的时候\n\n462\n00:22:21,674 --> 00:22:23,808\ndo that when it comes to running on a device.\n才需要解决这个问题\n\n463\n00:22:23,810 --> 00:22:25,476\nWhen we're running in a simulator you're not gonna\n当在模拟器上运行的时候\n\n464\n00:22:25,478 --> 00:22:28,913\nneed to do that, but you might as well get this started now.\n就不用这么做\n\n465\n00:22:29,048 --> 00:22:32,316\nOkay? Now what about these other files over here in the\nNavigator 中的其它这些文件\n\n466\n00:22:32,318 --> 00:22:35,453\nnavigator that it made these 6 files. Well like I said, were\n都有什么作用呢？\n\n467\n00:22:35,455 --> 00:22:37,922\nnot going to talk about all of them. This one for example,\n我不会对它们每一个都进行详细讲解\n\n468\n00:22:37,924 --> 00:22:42,093\nassets.xcassetts. That's all your media assets. So that's\n例如 assets.xcassets 是存放媒体文件的地方\n\n469\n00:22:42,095 --> 00:22:46,997\nimages, sounds, icons, things like that. Here for example is\n图片，声音和图标之类的东西\n\n470\n00:22:46,999 --> 00:22:47,965\nthe app icon which I haven't set so\n例如这里的应用图标\n\n471\n00:22:47,967 --> 00:22:51,635\nall of these are all blank. So we're not really gonna talk\n我还没有设置，所以这些都是空白的\n\n472\n00:22:51,637 --> 00:22:53,738\nabout that today but we'll eventually talk about it.\n我今天不会介绍，但总有一天会介绍的\n\n473\n00:22:53,740 --> 00:22:56,841\nAnd in fact not only am I not gonna talk about\n实际上今天我不但不会介绍这个 xcassets 文件\n\n474\n00:22:56,843 --> 00:22:59,877\nthis xcassets thing right here, but I'm also not gonna\n同样我也不会介绍\n\n475\n00:22:59,879 --> 00:23:02,813\ntalk about this app delegate or the launch screen or\nAppDelegate 和 LaunchScreen 还有\n\n476\n00:23:02,815 --> 00:23:06,350\nthe info.plist. Okay, so I'm gonna select all those and\ninfo.plist 文件\n\n477\n00:23:06,352 --> 00:23:10,254\nright-click on them and choose new group from selection and\n我选中它们\n\n478\n00:23:10,256 --> 00:23:13,424\nput them all in a folder. Okay, which I'm gonna call\n然后右键为它们新建一个组\n\n479\n00:23:13,426 --> 00:23:17,261\nsupporting files. Because that's what they are really,\n起名为 Supporting files\n\n480\n00:23:17,263 --> 00:23:19,330\nthey're kind of files to support my app.\n因为它们对我 App 起的就是支持作用\n\n481\n00:23:19,332 --> 00:23:20,264\nYou see they're still there,\n你看，它们还在这里\n\n482\n00:23:20,266 --> 00:23:21,799\nI just kind of got them out of the way so\n我只是把它们清理一下\n\n483\n00:23:21,801 --> 00:23:23,834\nwe can focus on these two files\n这样我就可以关注这两个文件\n\n484\n00:23:23,836 --> 00:23:27,972\nwhich is the most important thing to our demo today. Okay?\n它俩是今天 demo 中最重要的部分\n\n485\n00:23:27,974 --> 00:23:31,409\nNow what are these two files? Now is where I have to talk\n这俩文件是干什么的？\n\n486\n00:23:31,411 --> 00:23:34,812\nabout this MVC thing, okay? So MVC stands for\n现在我就得讲讲 MVC 了\n\n487\n00:23:34,814 --> 00:23:39,917\nModel View Controller, okay? Model View Controller is a way\nMVC 代表 Model(模型) View(视图) Controller(控制器)\n\n488\n00:23:39,919 --> 00:23:43,354\nof kind of dividing up all the classes in our object orient\nMVC 是一种把我们面向对象 App 中的类分成几种不同组的方式\n\n489\n00:23:43,356 --> 00:23:46,457\napp into three different groups, the model group,\nModel 组\n\n490\n00:23:46,459 --> 00:23:48,826\nthe view group, and the controller group.\nView 组和 Controller 组\n\n491\n00:23:48,828 --> 00:23:52,163\nOkay, what are those three groups? The model group is\n这三个组都是什么？Model 组是\n\n492\n00:23:52,165 --> 00:23:55,900\nwhat our program does It's UI independent.\n关于我们的 App 是做什么的，它与 UI 是独立的\n\n493\n00:23:55,902 --> 00:23:58,736\nSo for a calculator it's going to be all the calculating.\n对于计算器来说，它是关于计算的\n\n494\n00:23:58,738 --> 00:24:01,172\nThe things that actually does the calculations, right?\n它实际做的事情就是计算，对吧？\n\n495\n00:24:01,174 --> 00:24:04,275\nThat's UI independent, that's going to be our model, okay?\n它是 UI 独立的，它就是我们的 Model\n\n496\n00:24:04,277 --> 00:24:08,012\nThe view is the user interface that the user interacts with.\nView 就是用户直接接触的 UI 界面\n\n497\n00:24:08,014 --> 00:24:11,315\nSo for the calculator it's the buttons and the display and\n对于计算器来说就是按扭还有显示之类的东西\n\n498\n00:24:11,317 --> 00:24:14,051\nall that stuff. That is the view. Okay, usually that's\n这就是 View\n\n499\n00:24:14,053 --> 00:24:17,254\nmade of generic user interface elements like buttons and\n通常它是由基本的例如按扭之类的 UI 元素组成\n\n500\n00:24:17,256 --> 00:24:20,391\nthings like that. And then there's the controller,\n接着就是 Controller\n\n501\n00:24:20,393 --> 00:24:23,461\nthe controller is the glue between the model and\ncontroller 是 model 与 view 之间的粘合剂\n\n502\n00:24:23,463 --> 00:24:26,130\nthe view. Okay, it's the thing that listens to what's\n它会监听UI发生了些什么事情\n\n503\n00:24:26,132 --> 00:24:30,267\nhappening in the UI, makes decisions, updates the model,\n做出决定，传达给 model，让 model 更新\n\n504\n00:24:30,269 --> 00:24:30,901\nsomething changes in the model,\nmodel 里的一些东西就会发生改变\n\n505\n00:24:30,903 --> 00:24:34,438\nmaybe it changes the UI. Okay, back and forth is really where\n可能会改变UI，好的，说来说去\n\n506\n00:24:34,440 --> 00:24:37,608\nthe interface, the logic of our entire app really\n我们 app 的整套逻辑生存在 controller 里\n\n507\n00:24:37,610 --> 00:24:41,879\nlives in our controller, okay? So, this file right here,\nokay? 所以，这有一个文件\n\n508\n00:24:41,881 --> 00:24:45,950\nViewController.swift, that is our controller, okay?\nViewController.swift，这就是我们的 controller，okay?\n\n509\n00:24:45,952 --> 00:24:51,355\nOur app only has one MVC, okay? Which is the calculator,\n我们的app仅有一个 MVC，okay? 就是这个计算器\n\n510\n00:24:51,357 --> 00:24:54,024\nMVC and this is it's controller, okay,\nMVC和它是这个app的 controller，okay?\n\n511\n00:24:54,026 --> 00:24:59,296\nthe C of MVC. Now, here is your first look at Swift. E,\nMVC中的 C，现在，这里是你看到的第一个 swift 程序\n\n512\n00:24:59,298 --> 00:25:00,598\nwe're gonna, I'm gonna explain this little,\n我等下将会解释一下这个东西\n\n513\n00:25:00,600 --> 00:25:04,168\nreal briefly. You can see that Xcode has thrown in a couple\n非常简单，你可以看到 Xcode 里有一些方法\n\n514\n00:25:04,170 --> 00:25:07,571\nof methods for me. Everyone knows what a method is.\n大家都知道方法是什么\n\n515\n00:25:07,573 --> 00:25:09,874\nThey're so exciting that I'm gonna delete them, okay?\n我要删除掉它们，它们显得非常 exciting! okay?\n\n516\n00:25:09,876 --> 00:25:12,910\nThat's because I, I don't wanna distract you with a lot\n因为我不想你们被这些代码带走注意力\n\n517\n00:25:12,912 --> 00:25:15,513\nof random code, so we're gonna keep down just to the minimal\n所以我们只保留我们要用的代码\n\n518\n00:25:15,515 --> 00:25:16,547\ncode we're gonna use. We don't,\n所以我们只保留我们要用的代码\n519\n00:25:16,549 --> 00:25:19,783\nwe will be using those methods later in the course.\n我们在后续课程中会用到这些方法\n\n520\n00:25:19,785 --> 00:25:21,318\nThose are part of what's called the view-controller\n这些就是所说的 view-controller 的一部分\n\n521\n00:25:21,320 --> 00:25:25,189\nlifecycle. But we don't need it for our calculator app. So\n但我们的计算器里不需要它\n\n522\n00:25:25,191 --> 00:25:26,357\nlet's look at what we have left here.\n所以我们看看留在这里的代码\n\n523\n00:25:26,359 --> 00:25:30,461\nThis import is kind of like an include in other languages or\n这个 import 就像其它语言里的 include 一样\n\n524\n00:25:30,463 --> 00:25:33,864\nimport in other languages. But this is not a file,\n或是其它语言里的 import，但这不是一个文件\n\n525\n00:25:33,866 --> 00:25:37,368\nthis is a module. And in Swift, you can group a whole\n它是一个模块，在 swift 中，你可以把一堆类打包在一起\n\n526\n00:25:37,370 --> 00:25:42,306\nbunch of classes together. And that's called a module. And\n这就可以叫做一个模块\n\n527\n00:25:42,308 --> 00:25:45,976\nwhen you import a module all those classes will be visible,\n当你导入一个模块，里面所有的类都对你可见\n\n528\n00:25:45,978 --> 00:25:49,947\nif they're public classes, to whatever is using it. So here,\n当然如果它们是 public 类的话，不管谁用都如此\n\n529\n00:25:49,949 --> 00:25:53,751\nUI kit has all these interface things, buttons, text fields,\n所以这个 UIkit 里有所有的的界面，按钮，文本框\n\n530\n00:25:53,753 --> 00:25:56,620\nall that stuff is in there. And so since we're building\n所有的东西都在这个模块里，因为我们要做一个 UI app\n\n531\n00:25:56,622 --> 00:25:59,924\na UI app here, a calculator, we're gonna import UIkit, and\n一个计算器，我们我们要导入 UIkit\n\n532\n00:25:59,926 --> 00:26:02,059\nyou're almost always gonna import UIkit,\n你几乎总是需要导入这个模块\n\n533\n00:26:02,061 --> 00:26:04,828\nokay? Now in our model, where it's UI independent,\n现在在我们的 model 中，UI是独立的\n\n534\n00:26:04,830 --> 00:26:07,298\nwe're gonna probably be importing foundation.\n我们也许需要导入 foundation 框架\n\n535\n00:26:07,300 --> 00:26:09,967\nFoundation is that core services thing, okay?\nFoundation 是一个核心框架，okay？\n\n536\n00:26:09,969 --> 00:26:11,268\nCuz we might be doing networking and\n因为我们可能需要网络编程\n\n537\n00:26:11,270 --> 00:26:13,370\ndatabasing in our model, but we're not doing buttons and\n或者使用数据库，但我们不需要做一些按钮之类的东西\n\n538\n00:26:13,372 --> 00:26:17,374\nstuff. So those are the two main things you import, okay.\n所以这两个模块你需要导入\n\n539\n00:26:17,376 --> 00:26:21,078\nHere is the definition, declaration really,\n这里是 swift 里对一个类进行定义时看起来的样子\n\n540\n00:26:21,080 --> 00:26:24,248\nof a class in Swift is what it looks like.\n这里是 swift 里对一个类进行定义时看起来的样子\n\n541\n00:26:24,250 --> 00:26:28,052\nYou've got the class keyword. This is the name of the class,\n你需要用到 class 关键字，这是这个类的名字\n\n542\n00:26:28,054 --> 00:26:30,020\nViewController. Now this is a pretty bad name,\nViewController，一个很差劲的名字\n\n543\n00:26:30,022 --> 00:26:33,190\nokay, because its very generic, ViewController\n因为 ViewController 这个名字不够具体\n\n544\n00:26:33,192 --> 00:26:36,160\nprobably be better called calculator controller, or\n我们最好叫它计算器 controller\n\n545\n00:26:36,162 --> 00:26:37,394\ncalculator view controller.\n或者计算器 view controller 之类的名字\n\n546\n00:26:37,396 --> 00:26:39,363\nI'm not gonna show you how to rename that now.\n我现在不会教你们怎么重命名\n\n547\n00:26:39,365 --> 00:26:42,766\nBut I will show you next week. But this is the name of our\n在下周我会展示给你看，这是我们 controller 类的名字\n\n548\n00:26:42,768 --> 00:26:46,937\ncontroller class. This colon UIViewController, means that\n这个 UIViewController 意味着\n\n549\n00:26:46,939 --> 00:26:50,808\nUIViewController is the class our controller inherits from.\n我们的类继承于 UIViewController 类\n\n550\n00:26:50,810 --> 00:26:53,277\nThis is object oriented program, we have inheritance.\n这是个面向对象程序，需要继承机制\n\n551\n00:26:53,279 --> 00:26:56,914\nThis is the inheritance. Single inheritance in Swift.\n这就是一个 swift 里单继承的例子\n\n552\n00:26:56,916 --> 00:27:01,485\nAll controllers, all MVC controllers must inherit from\n所有的 controller，所有的 MVC controller 都必须\n\n553\n00:27:01,487 --> 00:27:04,521\nUIViewController either directly or indirectly from\n直接或间接地继承于 UIViewController\n\n554\n00:27:04,523 --> 00:27:08,125\nUIViewController. Okay, then we have a curly brace here,\nOkay，这里我们有了大括号\n\n555\n00:27:08,127 --> 00:27:11,695\ninside those curly braces goes all of our properties and\n所有的属性和方法写在这个括号里\n\n556\n00:27:11,697 --> 00:27:14,131\nmethods. Properties are like instance variables.\n比方说一些变量\n\n557\n00:27:14,133 --> 00:27:15,299\nEveryone knows what an instance variable is,\n每个人都该知道什么是实例变量\n\n558\n00:27:15,301 --> 00:27:18,636\nright? So our property, we call them properties in Swift.\n在 swift 中我们称 property 是属性\n\n559\n00:27:18,638 --> 00:27:21,438\nThey're very powerful in Swift, the instance variables.\n实例变量在 swift 里面非常有用\n\n560\n00:27:21,440 --> 00:27:23,007\nThey can have behavior associated with them and\n它们可以被一些有关联的行为改变\n\n561\n00:27:23,009 --> 00:27:26,543\nthings like that. But all that goes inside these curly\n但所有的一切都发生在这对大括号里\n\n562\n00:27:26,545 --> 00:27:30,247\nbraces, okay? So that's your intro to Swift.\n好吗？ 所以这就是对 swift 的简短介绍\n\n563\n00:27:30,249 --> 00:27:33,350\nWhat about this other file over here? Main.storyboard,\n这个 Main.storyboard 文件又是怎么回事？\n\n564\n00:27:33,352 --> 00:27:39,089\nwhat's that? That's the V for view of our MVC. That's\n它是什么呢？就是 MVC 里面的 V\n\n565\n00:27:39,091 --> 00:27:42,559\nthe graphical representation of our calculator.\n它代表着我们的计算器的图形界面\n\n566\n00:27:42,561 --> 00:27:44,962\nSo let's click on that, and see what it looks like.\n所以我们点它一下， 看看会发生什么\n\n567\n00:27:44,964 --> 00:27:49,833\nRight now, it's just a big square. Big empty square here.\n现在，它只是一个大方块，大的空方块\n\n568\n00:27:49,835 --> 00:27:51,935\nAnd I can zoom in and out, so I'll zoom to 50%,\n我可以放大和缩小，那我就缩小50%\n\n569\n00:27:51,937 --> 00:27:55,572\nsee? Here's our UI, now, it's kinda interesting,\n看，这就是我们的UI, 有点意思对不对\n\n570\n00:27:55,574 --> 00:28:02,946\nthis UI is square, okay? How many iOS products are square?\n这个UI是方形的，okay? 有多少iOS程序是方形的？\n\n571\n00:28:02,948 --> 00:28:06,717\nZero, right? None of them are, they're all rectangular, okay?\n零个，记住了吗？没有一个是方形的，它们都是长方形的\n\n572\n00:28:06,719 --> 00:28:09,520\nSo they're either landscape or portrait, you know, iPads,\n而且他们不是横屏的就是竖屏的，你知道的\n\n573\n00:28:09,522 --> 00:28:11,388\nwhatever. None of them are square.\n没有一个是方形的\n\n574\n00:28:11,390 --> 00:28:16,093\nSo how are we building our UI in a square UI? Well we're\n所以如何在这个方形UI中建立我们自己的UI?\n\n575\n00:28:16,095 --> 00:28:19,263\ndoing that to remind us that we want to build our UI so\n时刻谨记，我们要建立自己的UI\n\n576\n00:28:19,265 --> 00:28:23,901\nthat it stretches and expands and moves things around so\n它能够伸缩自如，也得能移动UI里的东西\n\n577\n00:28:23,903 --> 00:28:26,470\nthat it will fit in any shape. Okay,\n并且能够适应不同的设备\n\n578\n00:28:26,472 --> 00:28:29,039\nso we're gonna build one UI, it's gonna work on iPad,\n所以我们要做一个可以在各种iPad \n\n579\n00:28:29,041 --> 00:28:32,209\niPhone, tall iPhones, short iPhones, high resolution ones,\niPhone，长iPhone，短iPhone，高分辨率设备\n\n580\n00:28:32,211 --> 00:28:35,713\nlow resolution, all of them from this one UI. And this is\n低分辨率设备，所有的设备只需要一个UI\n\n581\n00:28:35,715 --> 00:28:39,516\nsquare to remind us that if this were vertical rectangle,\n这个方形提醒我们 如果这是个垂直长方形\n\n582\n00:28:39,518 --> 00:28:42,186\nprobably our UI would look great in portrait, but\n或许它更适合竖屏使用\n\n583\n00:28:42,188 --> 00:28:42,386\ngood in landscape. This way, square, it's constantly\n这样，对于横屏使用来讲\n\n584\n00:28:42,388 --> 00:28:45,089\nmaybe not so\n或许就不那么合适\n\n585\n00:28:45,091 --> 00:28:47,591\nreminding us that we have to build this flexible UI.\n不要忘了我们要做一个足够灵活的UI\n\n586\n00:28:47,593 --> 00:28:49,059\nNow today, I'm not gonna do that.\n今天我并不打算做这件事\n\n587\n00:28:49,061 --> 00:28:52,463\nI'm gonna build the UI all up in the upper left corner right\n我会在这个左上角上建立我们的UI\n\n588\n00:28:52,465 --> 00:28:54,531\nhere so that it looks good in any, or\n或许好看\n\n589\n00:28:54,533 --> 00:28:58,569\nnot looks good, but at least shows up in any shape. But\n或许不好看，但至少适用于任何设备\n\n590\n00:28:58,571 --> 00:29:01,472\non Wednesday, we'll put in the flexibility to make it,\n星期三的时候，我们教你们一些方法\n\n00:29:01,474 --> 00:29:06,577\ndo what it needs to do, okay. So, how do we build this UI?\n来给它注入更多的灵活性。所以，我们如何建造这个UI?\n\n592\n00:29:06,579 --> 00:29:09,747\nWe build our entire UI graphically. Okay,\n我们用图形拖拽的方式，Okay?\n\n593\n00:29:09,749 --> 00:29:12,116\nwith the mouse. Okay, we do not write code,\n用鼠标，我们不需要写任何代码\n\n594\n00:29:12,118 --> 00:29:16,420\nto say put button here, to put text field there. We just\n把按钮放在这里，把文本框放在那里\n\n595\n00:29:16,422 --> 00:29:20,557\nbuild it all graphically, and wire it up with our mouse. And\n我们只需要用图形的方式来完成，用鼠标做这事\n\n596\n00:29:20,559 --> 00:29:22,559\nso we're just going to dive right into doing that.\n现在我们马上就开始做这个UI\n\n597\n00:29:22,561 --> 00:29:26,263\nI'm building a calculator. A calculator needs some buttons.\n我要做一个计算器，一个计算器需要一些按键\n\n598\n00:29:26,265 --> 00:29:27,464\nSo let's start with a button.\n那么我们就从按键开始\n\n599\n00:29:27,466 --> 00:29:30,834\nI told you that in this utilities window at the bottom\n我告诉过你们在 utilities 窗口\n\n600\n00:29:30,836 --> 00:29:34,037\nthere's the palette of things you as an artist, and now we\n有一个“调色板”提供给你这个“艺术家”\n\n601\n00:29:34,039 --> 00:29:37,975\nare UI artists here, are going to build our UI out of. And\n现在我们就是UI设计艺术家，将要创造我们的UI\n\n602\n00:29:37,977 --> 00:29:41,645\nyou can see there is whoops. Get that back out of the way.\n你可以看见，whoops，把它放到后面去\n\n603\n00:29:41,647 --> 00:29:44,848\nThere we go. Lots and lots of things that we can build our\n好了，这里面有很多很多东西我们可以拿来\n\n604\n00:29:44,850 --> 00:29:47,918\nUI out of here, and we'll talk about actually most of these\n构造我们的UI,接下面的几周这些东西\n\n605\n00:29:47,920 --> 00:29:50,654\nin the ten weeks we have, but we're gonna start about\n大多我们都会介绍，但从大概这个四分之一\n\n606\n00:29:50,656 --> 00:29:54,258\na quarter of the way down with this one right here button.\n的位置这的这个按钮开始\n\n607\n00:29:54,260 --> 00:29:56,026\nAnd I'm just gonna pick this up.\n我将会点击它\n\n608\n00:29:56,028 --> 00:29:59,496\nAnd drag it out, it's my UI. Now when I do that,\n把它拖出来，这就是我的UI，当我做这事的时候\n\n609\n00:29:59,498 --> 00:30:02,566\nnotice that these blue lines appear and disappear.\n注意下这些出现又消失蓝色的线条\n\n610\n00:30:02,568 --> 00:30:06,603\nThe blue lines help you put something in a theoretical or\n这些蓝色线条帮你把东西放在合适的地方\n\n611\n00:30:06,605 --> 00:30:10,774\nconceptual place. Like this would be putting the button\n就像这个给我参考，让我把这个按钮放在\n\n612\n00:30:10,776 --> 00:30:13,477\nin the conceptual center of my UI. So\n我UI框架的中心\n\n613\n00:30:13,479 --> 00:30:16,079\nif I am portrait it's going to be centered in portrait.\n如果我竖屏，它会处于竖屏的中心位置\n\n614\n00:30:16,081 --> 00:30:18,882\nIf I go to landscape it will move over and be in landscape.\n如果我横屏，它会移动到横屏的中心位置去\n\n615\n00:30:18,884 --> 00:30:22,853\nDo you understand what I'm saying? These blue lines allow\n你明白我在说什么吗？这些蓝色线条\n\n616\n00:30:22,855 --> 00:30:25,088\nus to put things in various places and\n让我们能把UI元素放在很多地方\n\n617\n00:30:25,090 --> 00:30:26,423\nthis is a big part of how we're going to\n对于如何做出一个灵活的UI来说，这些\n\n618\n00:30:26,425 --> 00:30:29,159\nmake this flexible UI. But since I told you I'm not gonna\n蓝色线条很关键，不过我已经说了周三再来展示\n\n619\n00:30:29,161 --> 00:30:31,094\nshow you that until Wednesday, we're not gonna do that.\n所以今天我不会管它\n\n620\n00:30:31,096 --> 00:30:33,764\nWe're not gonna use the blue lines, okay. But you'll see me\n我们不使用这些蓝色线条，okay，等到周三\n\n621\n00:30:33,766 --> 00:30:35,766\nusing the blue lines on Wednesday quite a bit and\n我才会告诉你们怎么使用这些线条\n\n622\n00:30:35,768 --> 00:30:37,234\nyou'll want to always use the blue lines.\n然后你们就离不开它了\n\n623\n00:30:37,236 --> 00:30:41,071\nThe blue lines are super important to building this\n对于做一个足够灵活的UI来讲\n\n624\n00:30:41,073 --> 00:30:42,139\nflexible adaptable UI.\n这些蓝色线条特别重要\n\n625\n00:30:42,141 --> 00:30:44,608\nAll right, so we have our button right here, now we\n好了，所有现在我们的按键摆在那了\n\n626\n00:30:44,610 --> 00:30:47,711\ndon't want it to say button on there. Okay, we want it to be\n现在我不想要这个空白按键呆在那，我想要\n\n627\n00:30:47,713 --> 00:30:50,747\none of the numbers this is gonna be part of our keypad.\n它变成我们的一个数字按键\n\n628\n00:30:50,749 --> 00:30:53,016\nSo I'm gonna make this be my five button. And\n所以我要把它变成“5”这个按键\n\n629\n00:30:53,018 --> 00:30:55,552\nto change the text you can just double click on it and\n要改变它的文本信息你只需要双击它\n\n630\n00:30:55,554 --> 00:30:58,989\nchange it. So I'm gonna make it 5. You notice it also has\n然后改成你要的文本，所以我把它改成“5”，\n\n631\n00:30:58,991 --> 00:31:01,825\nthese little handles around the edge. You can use those to\n你可以看见这些边缘上的小框框，你可以用它改变按钮的大小\n\n632\n00:31:01,827 --> 00:31:05,229\nresize it to whatever you want. So this is computer\n这是一门计算机科学课\n\n633\n00:31:05,231 --> 00:31:09,466\nscience class, so we'll make it be 64 by 64, okay? Although\n所以我们把它做成64*64大小的，okay?\n\n634\n00:31:09,468 --> 00:31:12,636\nit really doesn't matter what size I make this, because when\n不过我把它做成什么大小真的不重要\n\n635\n00:31:12,638 --> 00:31:15,072\nit starts being flexible it's gonna start you know,\n因为面对不同的环境的时，一个灵活的UI\n\n636\n00:31:15,074 --> 00:31:18,141\nresizing it to fit depending on what's the environment, but\n可以让这些按钮自动变换到合适的尺寸\n\n637\n00:31:18,143 --> 00:31:21,345\nanyway we'll do that. Now other things I wanna change\n不过我还是示范下，现在，这个按钮还有一些需要改变的地方\n\n638\n00:31:21,347 --> 00:31:23,480\nabout this button I don't do directly.\n但我不直接做\n\n639\n00:31:23,482 --> 00:31:27,517\nI need to use this top half of the utilities window here,\n我需要用到 utilities 窗口的上半部分\n\n640\n00:31:27,519 --> 00:31:30,721\nwhich is the Inspector. Okay, now there's different kinds of\n这是一个检测窗口，Okay，现在这有一些\n\n641\n00:31:30,723 --> 00:31:33,557\ninspectors along the top you'll see here. What you,\n不同的种类的检测\n\n642\n00:31:33,559 --> 00:31:35,926\nwhat's showing now is the Attributes Inspector.\n现在你看到的是属性监测\n\n643\n00:31:35,928 --> 00:31:39,129\nThat, that is the attributes of whatever is selected.\n无论我选中了什么属性都会展示在上边\n\n644\n00:31:39,131 --> 00:31:41,899\nHere is the size inspector. So if I click that, for\n这里时一个尺寸监测，所以如果我点击它\n\n645\n00:31:41,901 --> 00:31:45,269\nexample here's my 64 by 64 and I can edit it here as well.\n这里就是我的64*64，我们同样也能在这里改变尺寸\n\n646\n00:31:45,271 --> 00:31:50,774\nI can say 200 by 64, see how this got wide, all right?\n我可以改成200*64，看这个怎么变得更宽，all right?\n\n647\n00:31:50,776 --> 00:31:53,443\nWe can go back to 64.\n我们也可以改回64\n\n648\n00:31:53,445 --> 00:31:55,979\nOkay. I'm going to go back to the app.\n好了，回到我们的app\n\n649\n00:31:55,981 --> 00:31:58,415\nAnd we will talk about these other ones the identity and\n我们将会在之后再介绍身份监测，这之类些东西\n\n650\n00:31:58,417 --> 00:32:01,752\nSpector later. But lets go back here to attributes and\n回到我们的属性界面\n\n651\n00:32:01,754 --> 00:32:04,154\ninspector this is actually object oriented. So\n这是面向对象的，所以\n\n652\n00:32:04,156 --> 00:32:06,623\nhere I can set the attributes of a button because that's\n所以我能设置这个按钮的属性\n\n653\n00:32:06,625 --> 00:32:10,027\nwhat's selected here. And also I can set the attributes of\n同样我也能设置这个 controls 属性\n\n654\n00:32:10,029 --> 00:32:13,830\na control, which is buttons super class, and\n它是按键的父类\n\n655\n00:32:13,832 --> 00:32:17,634\nthen attributes of view, which is controls super class.\n再设置 view 里面的属性，它是 controls 的父类\n\n656\n00:32:17,636 --> 00:32:20,537\nSo this goes right up the hierarchy of the inherit\n所以它们遵循着继承的体系，一个类继承于另一个\n\n657\n00:32:20,539 --> 00:32:23,640\nhierarchy, rather, and lets me set various things.\n现在让我设置一些东西\n\n658\n00:32:23,642 --> 00:32:26,543\nFor example, I want this five to be bigger, so\n比如，我想要这个“5”更大一点\n\n659\n00:32:26,545 --> 00:32:30,447\nI look here in the buttons attributes and I see font,\n所以我看看这个按钮的属性，我看到了“字体”\n\n660\n00:32:30,449 --> 00:32:33,850\nsystem font, 15 point. I'm gonna click this and\n系统字体，15号，我点击它一下\n\n661\n00:32:33,852 --> 00:32:37,154\nchange this to be 30 point system font. Okay,\n把它变成30号的字体，Okay\n\n662\n00:32:37,156 --> 00:32:41,291\nthat looks a lot better. And if I go back and look at this\n看起来好多了，如果我再回去看看这个计算器\n\n663\n00:32:41,293 --> 00:32:43,961\ncalculator, see how some of the buttons have a background,\n看如何使这个按钮有不同颜色的背景\n\n664\n00:32:43,963 --> 00:32:46,763\nlike grey or orange? I want that too so I'm gonna set\n比如绿色或者橘色，所以我设置一下\n\n665\n00:32:46,765 --> 00:32:49,599\nthe background of this to something, so I'm gonna\n这个按钮的背景色\n\n666\n00:32:49,601 --> 00:32:52,803\ngo down that turns out to be something that button inherits\n所以我往下滑，发现这个按钮的背景\n\n667\n00:32:52,805 --> 00:32:55,205\nfrom view, right here background.\n继承于 view，就在这里\n668\n00:32:55,207 --> 00:32:59,042\nSo I can set it by, you know, using crayons,\n所以我可以用不同色的蜡笔来改变它\n\n669\n00:32:59,044 --> 00:33:02,045\nokay, whatever you can use sliders or I can\nokay, 无论你用什么都行\n\n670\n00:33:02,047 --> 00:33:05,782\nuse maybe recently used ones like here's light grey, okay?\n我可以用我最近用过的颜色，比如浅灰，okay?\n\n671\n00:33:05,784 --> 00:33:08,185\nSo, I've substituted my nice little background here so,\n这样我就更换了我们这个按钮的背景颜色\n\n672\n00:33:08,187 --> 00:33:10,721\nyou know, you can go and edit these things and make them\n你们可以编辑这些东西，把按键变成任何你们想要的样子\n\n673\n00:33:10,723 --> 00:33:14,858\nlook however you want, what's interesting about what's going\n有趣的地方在这\n\n674\n00:33:14,860 --> 00:33:18,261\non here is this...there's no code generation step gonna\n这里并没有产生任何代码\n\n675\n00:33:18,263 --> 00:33:21,932\nhappen here. You're actually editing these objects live.\n你只是改变了这个按键的样子\n\n676\n00:33:21,934 --> 00:33:25,669\nOkay. By changing things in the inspector you're sending\n通过改变检测窗口里的东西\n\n677\n00:33:25,671 --> 00:33:29,172\nmessages to this button to set the way it is and\n你在给按键发送信息，把它设置成你想要的样子\n\n678\n00:33:29,174 --> 00:33:33,610\nthen the Xcode has a way to essentially freeze dry\n接着 Xcode 就有办法完成你的请求\n\n679\n00:33:33,612 --> 00:33:35,545\nall the attributes, and it's object oriented.\n改变按钮的属性，这是面向对象\n\n680\n00:33:35,547 --> 00:33:37,147\nIn other words, the objects are participating and\n换言之，Xcode 能够把这些操作\n\n681\n00:33:37,149 --> 00:33:42,419\nfreeze drying themselves. And in fact, the whole mechanism\n转换成对按键对象的代码的操作，事实上\n\n682\n00:33:42,421 --> 00:33:45,856\nof this part of Xcode which we call interface builder,\nXcode 的这套机制被我们叫做 ”interface builder”\n\n683\n00:33:45,858 --> 00:33:48,925\ncuz we're building our user interface, is extensible and\n因为我们在为用户做界面，它是可扩展的\n\n684\n00:33:48,927 --> 00:33:51,495\nyou can put your own objects in here, okay.\n你也可以在这里加入自己的对象\n\n685\n00:33:51,497 --> 00:33:53,563\nYour own things they draw, custom drawing or whatever.\nUI上所画的一切你都可以自己控制\n\n686\n00:33:53,565 --> 00:33:56,633\nAnd we'll show you all about that as the weeks go by.\n过几周我就会给你们展示\n\n687\n00:33:56,635 --> 00:33:59,603\nAll right. So, I have one button here, that's good.\n好的，现在我有一个按钮在这，非常好\n\n688\n00:33:59,605 --> 00:34:01,171\nI could even run my app right now.\n我甚至已经可以运行这个app了\n\n689\n00:34:01,173 --> 00:34:03,673\nSo how do I run this application? You\n那么我如何运行它呢？\n\n690\n00:34:03,675 --> 00:34:07,544\ngo up here to the top, you see where it says iPhone 6s Plus.\n看上来，在顶栏这，你能看到这上面写着 “iPhone 6s Plus”\n\n691\n00:34:07,546 --> 00:34:10,914\nThis is actually a list of simulators that you can choose\n这实际上是你要选择的模拟器列表\n\n692\n00:34:10,916 --> 00:34:14,985\nto run your app on, all right? So, you could also run it on\n来运行你的app，明白了吗？当然你也可以在一个设备上运行它\n\n693\n00:34:14,987 --> 00:34:18,889\na device. If you connected a device and did that team thing\n如果你连接了设备然后配好对\n\n694\n00:34:18,891 --> 00:34:22,626\nI was talking about, you can run it on your device here but\n我现在讲的是，你可以在你的设备上运行app\n\n695\n00:34:22,628 --> 00:34:23,460\nI didn't connect a device so\n但我没有连接任何设备\n\n696\n00:34:23,462 --> 00:34:25,529\nI'm going to run it on an iPhone 6. Okay, so\n所以我打算在 iPhone 6 模拟器上运行它\n\n697\n00:34:25,531 --> 00:34:30,000\nI just pick iPhone 6 and then I just press Play right here,\n我只需要选择 iPhone 6 接着按下这个运行键\n\n698\n00:34:30,002 --> 00:34:32,969\nso we press play it's gonna bring up\n好了我们按下运行键，它会产生一个\n\n699\n00:34:32,971 --> 00:34:34,571\nan iPhone simulator okay and\niPhone模拟器\n\n700\n00:34:34,573 --> 00:34:36,206\nthen the iPhone simulator is gonna run this app.\n接着我们的app就会在这个iPhone模拟器上运行\n\n701\n00:34:36,208 --> 00:34:39,309\nNow this iPhone simulator that you see appearing right here,\n现在你看到，这个iPhone模拟器上\n\n702\n00:34:39,311 --> 00:34:42,112\nit's showing our app. This is more than just our app.\n有了我们的app，当然模拟器有的不只是我们的app\n\n703\n00:34:42,114 --> 00:34:45,649\nThis is actually a full simulator of the iPhone.\n它可以模拟iPhone的各种行为\n\n704\n00:34:45,651 --> 00:34:48,485\nAnd in fact, if I go Hardware, Home, that's\n实际上，我点击这个 “Hardware”，“Home”\n\n705\n00:34:48,487 --> 00:34:51,221\njust like pressing the Home button. You know the little\n它就会像真正按在 home 键上一样，就像\n\n706\n00:34:51,223 --> 00:34:55,058\nHome button on your iPhone? Watch this. Press Home, and\n按你iPhone上的 home 键，看，点击home\n\n707\n00:34:55,060 --> 00:34:57,227\nit goes to here. And I got Settings, Photo,\n它就回到主界面，这里就是些设置，相册\n\n708\n00:34:57,229 --> 00:35:02,499\nCalendar, Safari, other apps, etc. Okay, and here's my app.\n日历，Safari，各种app。Okay?这里是我的app\n\n709\n00:35:02,501 --> 00:35:05,669\nThis my assistive app, calculator has no app icon.\n这就是我的计算机app，目前还没有一个图标\n\n710\n00:35:05,671 --> 00:35:08,038\nBut, there it is. Now, I can go back. Okay? So\n但是看这里，我可以点进去，okay？\n\n711\n00:35:08,040 --> 00:35:11,508\nit's really simulating the device here. Now,\n所以它像一个真正的iPhone\n\n712\n00:35:11,510 --> 00:35:16,680\nwhat happens if I touch this button? Nothing. Okay?\n那么现在我按下这个按钮会怎样呢？什么都不会发生，okay？\n\n713\n00:35:16,682 --> 00:35:19,149\nThat's because we haven't really taught our\n因为当这个按钮按下的时候\n\n714\n00:35:19,151 --> 00:35:23,487\ncalculator app what to do when this button is touched. So\n我的计算器并不知道该做些什么，我还没有教它\n\n715\n00:35:23,489 --> 00:35:26,089\nlet's go do that. Now how are we gonna do that?\n所以我们现在来教它，怎么做呢？\n\n716\n00:35:26,091 --> 00:35:28,959\nRemember I told you that the V, the view here is kind of\n记得我告诉过你们的, MVC 里的 V\n\n717\n00:35:28,961 --> 00:35:31,761\ngeneric UI buttons and sliders and that there's a model which\n这个按键是一个原生的按键，我们现在还没有\n\n718\n00:35:31,763 --> 00:35:34,931\nwe don't have yet okay? And then there's the controller.\n一个 model 来控制它，okay？这是我们的 controller\n\n719\n00:35:34,933 --> 00:35:37,968\nSo the way that touching on buttons causes anything to\n按下按按键发生的所有事情都是这个 controller 来完成的\n\n720\n00:35:37,970 --> 00:35:42,038\nhappen is via the controller. So somehow we have to connect\n所以我们得把按钮和 controller 连接起来\n\n721\n00:35:42,040 --> 00:35:45,542\nthis button up to our controller. In fact,\n所以我们得把按钮和 controller 连接起来\n\n722\n00:35:45,544 --> 00:35:47,544\nwhat we wanna do is, when we touch this button,\n所以，我现在需要做的，就是当我们按下这个按钮时\n\n723\n00:35:47,546 --> 00:35:51,882\nwe wanna invoke a method in our controller object, right?\n我们想调用 controller 中的一个方法，好吗？\n \n724\n00:35:51,884 --> 00:35:53,183\nSounds nice and object oriented.\n听起来非常面向对象\n\n725\n00:35:53,185 --> 00:35:56,286\nThat's what we wanna do. So how do we set that up, okay?\n那么我们如何完成这件事呢？\n\n726\n00:35:56,288 --> 00:35:59,489\nWe're gonna set that up by getting the controller and\n我们需要把 controller 和 view 放在\n\n727\n00:35:59,491 --> 00:36:02,592\nthe view on screen at the same time. Okay, and\n同一个屏幕上，okay？\n\n728\n00:36:02,594 --> 00:36:05,362\nthen we're gonna wire it up graphically with the mouse.\n然后我们用鼠标把它们连接起来\n\n729\n00:36:05,364 --> 00:36:06,630\nSo let's get both on there at the same time.\n现在我们把它们两个放在屏幕上\n\n730\n00:36:06,632 --> 00:36:08,865\nThe way we do that is with this button right here this\n怎么做呢？看见编辑栏右边的\n\n731\n00:36:08,867 --> 00:36:12,469\nlittle round circle the assistant editor. This brings\n小圈圈了吗？点击它可以\n\n732\n00:36:12,471 --> 00:36:17,207\nup the controller and the view on screen at the same time\n把 controller 和 view 放在同一个屏幕上\n\n733\n00:36:17,209 --> 00:36:20,277\nagain I have low resolution so it's all kinda smashed so\n这个界面现在很小，那么现在关闭\n\n734\n00:36:20,279 --> 00:36:23,580\nlet's close our navigator and close our utilities. Okay,\n左边和的导航栏和右边的工具栏，okay？\n\n735\n00:36:23,582 --> 00:36:27,584\nand we can share this space however we want. Okay, so\n我们可以随便改变，okay？\n\n736\n00:36:27,586 --> 00:36:28,251\nwe have plenty of room for our code.\n现在我们有足够的空间展示代码了\n\n737\n00:36:28,253 --> 00:36:32,589\nAnd here's our controller. So, now this is gonna seem wacky,\n这是我们的 controller，这可能看起来会有一点怪异\n\n738\n00:36:32,591 --> 00:36:34,591\nbut it's actually really, really cool. Okay.\n但实际上这非常，非常，酷，okay？\n\n739\n00:36:34,593 --> 00:36:37,694\nThe way that we hook up that button, to call a method in\n我们现在把按钮和 controller 里的方法连接起来\n\n740\n00:36:37,696 --> 00:36:41,932\nour controller, is by holding down the control key, okay.\n只需要按住 control 键\n\n741\n00:36:41,934 --> 00:36:43,066\nI'm gonna hold down the control key.\n好，我现在按住了 control 键\n\n742\n00:36:43,068 --> 00:36:47,938\nAnd drag, from the button [LAUGH] into my coat, okay.\n然后拖动，从按钮拖动到我的代码里来，okay？\n\n743\n00:36:47,940 --> 00:36:50,774\nNow I know it really seems weird but it's cool, okay.\n我知道现在看起来非常怪异，但是也很酷，okay？\n\n744\n00:36:50,776 --> 00:36:53,843\nSo I can put it wherever I want in my class here. And\n我可以随意拖动它到我的代码里面\n\n745\n00:36:53,845 --> 00:36:57,514\nwhen I let go, it's gonna say okay, what kind of connection\n然后当我松开鼠标，需要设置些东西\n\n746\n00:36:57,516 --> 00:37:00,817\ndo you wanna make between this user interface object and\n比如我们UI对象和 controller 之间\n\n747\n00:37:00,819 --> 00:37:03,086\nyour controller? And there's really two choices,\n需要什么样的连接？这里有2个选择\n\n748\n00:37:03,088 --> 00:37:04,521\none is called an outlet which I'm gonna talk\n一个是调用 “outlet”，这个我稍后再讲\n\n749\n00:37:04,523 --> 00:37:07,290\nabout in a moment and the other one is called an action.\n另一个叫做 “action”\n\n750\n00:37:07,292 --> 00:37:10,493\nSo an action is when you want something that happens in UI\n“action” 就是当UI中发生了一些事件后，\n\n751\n00:37:10,495 --> 00:37:12,762\nto invoke a method in your controller. Okay?\ncontroller 里的方法将被调用，okay？\n\n752\n00:37:12,764 --> 00:37:15,999\nExactly what we want here, that's what an action is. So\n这就是我们想要的，这就是 “action” 的作用\n\n753\n00:37:16,001 --> 00:37:18,702\nhere it's asking the name, it wants to know the name\n那么这里需要一个名字，它需要知道这个方法的名字\n\n754\n00:37:18,704 --> 00:37:22,239\nof the method. So here I'm touching a digit button,\n因为我需要按下一个按钮\n\n755\n00:37:22,241 --> 00:37:24,908\nso I'm gonna call this touchDigit. Okay.\n所以我这在输入 “touchDigit”，okay？\n\n756\n00:37:24,910 --> 00:37:26,910\nSo this is just the name of the method that,\n这就是在我的 controller 里\n\n00:37:26,912 --> 00:37:29,479\nis gonna be created in my controller.\n建立的方法的名字\n\n758\n00:37:29,481 --> 00:37:31,514\nNotice that my method can have arguments.\n注意，我的方法可以有参数\n\n759\n00:37:31,516 --> 00:37:32,882\nYou see down here where it says arguments?\n你看下面，这里写着 ”Arguments”\n\n760\n00:37:32,884 --> 00:37:37,053\nIt could have no arguments. Okay. Which is fine, right.\n它可以不需要参数, 没有任何问题。\n\n761\n00:37:37,055 --> 00:37:38,622\nI don't want an argument, that'd be fine.\n我不需要参数，这样设置就好了\n\n762\n00:37:38,624 --> 00:37:42,225\nIt can have one argument which is the sender, in other words,\n也可以有一个参数，叫做 sender，换言之\n\n763\n00:37:42,227 --> 00:37:44,728\nthe button that is sending me this method, okay.\n这个按钮会把我送到这个方法里来，okay？\n\n764\n00:37:44,730 --> 00:37:47,297\nThat's really valuable argument, okay. Especially in\n这是个很有价值的参数，okay？\n\n\n765\n00:37:47,299 --> 00:37:50,033\nthis case because I'm gonna have a whole bunch of buttons.\n特别是当我有很多按键的时候\n\n766\n00:37:50,035 --> 00:37:52,235\nThey're each gonna be sending touch digit, and\n每一个按键都会发送一个数字\n\n767\n00:37:52,237 --> 00:37:53,336\nI wanna know which one sent it to me.\n我会想知道哪个按键发送给我了信息\n\n768\n00:37:53,338 --> 00:37:56,506\nSo the fact that it's gonna pass itself as an argument to\n事实上，按键会把它自己当作参数\n\n769\n00:37:56,508 --> 00:37:59,843\nthis method is great. The only problem is if you see this\n传递给方法，有个问题就是\n\n770\n00:37:59,845 --> 00:38:03,246\ntype right here any object. That's going to be the type\n你看见这里有一个 “any object”，它的类型就是一个 object\n\n771\n00:38:03,248 --> 00:38:05,982\nof the object. It's this generic any [LAUGH] object\n它可以是右边任意类型的对象\n\n772\n00:38:05,984 --> 00:38:08,184\nthing right here. We don't want that. Okay?\n我们不需要，okay？\n\n773\n00:38:08,186 --> 00:38:12,522\nSo when you're doing your homework don't miss this step.\n当你做家庭作业的时候，不要错过这一步\n\n774\n00:38:12,524 --> 00:38:17,527\nOkay? Change this from any object to UI button.\nokay？把它从 “any object” 改成 “UIButton”\n\n775\n00:38:17,529 --> 00:38:20,630\nBecause of course the thing sending us this message is UI\n因为发送给我们消息的显然是一个 UIbutton\n\n776\n00:38:20,632 --> 00:38:23,833\nbutton. It's unfortunate that this is not the default but\n不幸的是它不是默认设置\n\n777\n00:38:23,835 --> 00:38:27,304\nyou must do this. Okay? So, this I wanna click Connect,\n所以你必须自己搞定，okay？现在，我来点击 “Connect”\n\n778\n00:38:27,306 --> 00:38:30,440\nthis is just what event is causing this a touch on\n这是按下按键后会触发的事件\n\n779\n00:38:30,442 --> 00:38:34,277\nthe button that goes up inside the buttons bounds. Okay?\n按键会重新“弹起来”\n \n780\n00:38:34,279 --> 00:38:36,046\nSo I'm gonna hit connect right here and\n所以我现在点击一下\n781\n00:38:36,048 --> 00:38:37,614\nit's gonna write the code for a method.\n它会写下这个方法的代码\n782\n00:38:37,616 --> 00:38:40,917\nYou're gonna see your first Swift method here we go. Okay?\n你会在这里看到第一个 swift 方法，okay？\n\n783\n00:38:40,919 --> 00:38:44,354\nThis is your first Swift method. Now this is actually\n这是你的第一个 swift 方法\n\n784\n00:38:44,356 --> 00:38:46,923\nnot part of Swift. Okay, it's not part of this method.\n这里不是 swift 的一部分，okay？它不是方法的一部分\n\n785\n00:38:46,925 --> 00:38:49,659\nThis is something Xcode puts in here. So that this little\n这是 Xcode 放在这里的东西\n\n786\n00:38:49,661 --> 00:38:52,996\nround circle appears. You see that round circle right there?\n所以这里有一个小圈圈，你看了这个小圈圈了吗？\n\n787\n00:38:52,998 --> 00:38:54,764\nIf I mouse over that round circle,\n如果我把鼠标放上去\n\n788\n00:38:54,766 --> 00:38:59,502\nyou see how it shows me what thing in my view is hooked up\n你可以看见，方法和UI里的东西是怎样连接的\n789\n00:38:59,504 --> 00:39:02,072\nto this method you see? Okay so that's what this is so\n看见了吗？ 这就是它的作用\n790\n00:39:02,074 --> 00:39:06,242\nthat's really not part of the Swift method. Okay so this is\n它不是 swift 方法的一部分\n\n791\n00:39:06,244 --> 00:39:10,547\nall the Swift method. Okay so what is Swift method syntax?\n这才是 swift 里的方法，okay？swift 的方法语法是怎样的呢？\n\n792\n00:39:10,549 --> 00:39:14,184\nFunc, okay, func means this is a function on a class,\n先是一个func，func 代表的是这个类里的一个函数\n\n793\n00:39:14,186 --> 00:39:17,420\na method is essentially a function on a class, right?\n方法本质上就是类里的函数，好吗？\n\n794\n00:39:17,422 --> 00:39:21,858\nI suppose this could be called Method. Like the breaking bad\n这可以被叫做方法。\n\n795\n00:39:21,860 --> 00:39:25,261\nversion of what you'll call meth maybe. But func is good,\n和《绝命毒师》里的冰毒发音类似，但是 func 是好的\n\n796\n00:39:25,263 --> 00:39:28,631\nfunc is good because you can have global funcs also.\nfunc 还好在你还可以写全局函数\n\n797\n00:39:28,633 --> 00:39:32,335\nOkay, you can have the same syntax outside of a class,\n使用同样的语法，你可以在类的外面写一个函数\n\n798\n00:39:32,337 --> 00:39:34,871\ndescription outside of these braces.\n定义在这些大括号的外面\n\n799\n00:39:34,873 --> 00:39:36,306\nAnd it will be a global function.\n这样它就是个全局函数\n\n800\n00:39:36,308 --> 00:39:37,540\nAnd we're gonna see some of those.\n我们之后会见到一些全局函数\n\n801\n00:39:37,542 --> 00:39:39,042\nLike square root is a function I'm gonna\n就像平方根函数\n\n802\n00:39:39,044 --> 00:39:42,345\nuse when I add square root to my calculator. All right, so\n比如，当我在计算器里加上根号的时候\n\n803\n00:39:42,347 --> 00:39:44,748\nthat's the key words just like class is the key word for\n“class”，这是创建一个类的的关键字\n\n804\n00:39:44,750 --> 00:39:47,684\ncreating a class. Func is the key word for adding a method.\n“func” 是添加一个方法的关键字\n\n805\n00:39:47,686 --> 00:39:52,155\nTouch digit is the name, obviously of this method.\n“touchDight” 是它的名字，显然它是一个方法\n\n806\n00:39:52,157 --> 00:39:54,691\nParentheses has the arguments, okay?\n括号内可以有参数\n\n807\n00:39:54,693 --> 00:39:58,561\nWe only have one argument called sender of type\n我们只有一个叫做 “sender” 的参数\n\n808\n00:39:58,563 --> 00:40:02,599\nUIButton, so that's what : UIButton means.\n类型是 UIButton， 这就是 UIButton 的意思\n\n809\n00:40:02,601 --> 00:40:06,102\nAny time you're defining a type of something in Swift,\n当你在swift定义一个东西的类型的时候\n\n810\n00:40:06,104 --> 00:40:08,838\ncolon and the type after the name of the thing.\n使用冒号，后面跟着它需要的类型的名字\n\n811\n00:40:08,840 --> 00:40:10,807\nOkay, and that's true for arguments to methods,\n方法中的参数也是这样\n\n812\n00:40:10,809 --> 00:40:12,609\nit's also true for local variables, everything.\n局部变量，所有东西，都是这样\n\n813\n00:40:12,611 --> 00:40:15,812\nColon and the type, okay? Now if we had more arguments,\n冒号，然后类型名字，okay？现在如果我们有多个参数\n\n814\n00:40:15,814 --> 00:40:20,617\nthey would just be separated by comma, like otherArgument\n它们应该被逗号分隔开，如同这个 otherArgument\n\n815\n00:40:20,619 --> 00:40:24,654\nmight be an Int, okay, so I put an Int there.\n它可以是一个Int， okay？所以我写一个 Int 在这\n\n816\n00:40:24,656 --> 00:40:26,990\nSo, this is another argument, second argument here, and\n所以这是第二个参数\n\n817\n00:40:26,992 --> 00:40:29,926\nI can have as many as I want, and they each have to have\n我需要多少个参数都可以，每一个都需要一个参数名\n\n818\n00:40:29,928 --> 00:40:34,030\na key word, which describes, what they are. If this had\n来表示它们是干什么的\n\n819\n00:40:34,032 --> 00:40:39,068\na return value, it looks like this. Returns String. Okay, or\n如果这个方法有返回值，就这样写，返回一个 String\n\n820\n00:40:39,070 --> 00:40:41,938\nreturns Double. Okay, something like that.\n或者返回一个 Double, okay?就像这样\n\n821\n00:40:41,940 --> 00:40:45,809\nThat's how a return looks like, okay. Now I'm gonna\nreturn 就这样写，okay？\n\n822\n00:40:45,811 --> 00:40:48,445\ntake a timeout here from writing our calculator and\n现在我要开始写我们的计算器了\n\n823\n00:40:48,447 --> 00:40:50,180\njust show you what its like to call a method.\n教你如何调用一个方法\n\n824\n00:40:50,182 --> 00:40:52,916\nOkay? This is we're declaring the method. What if I wanted\nOkay? 我们在这里声明了一个方法\n\n825\n00:40:52,918 --> 00:40:55,919\nto call this method on myself? Okay it would be recursive\n如果我自己想调用这个方法呢？那么就会出现递归\n\n826\n00:40:55,921 --> 00:40:57,887\nhere because I'm inside touched as your butt.\n因为这是自己调用自己\n\n827\n00:40:57,889 --> 00:41:00,089\nI just wanna show you the syntax for calling okay?\n我只是展示一下调用方法的语法\n\n828\n00:41:00,091 --> 00:41:02,325\nSo if I want to send something to myself.\n如果我想给我自己发送点信息\n\n829\n00:41:02,327 --> 00:41:05,495\nI use the key word self, and then to send a message it's\n我用关键字 “self”，然后发送信息\n\n830\n00:41:05,497 --> 00:41:08,298\njust like Java you press dot, okay?\n如果JAVA一样，按下“.”，okay？\n\n831\n00:41:08,300 --> 00:41:10,333\nThe thing you want to send it to dot and\n你想发送什么，按下一个“.”\n\n832\n00:41:10,335 --> 00:41:14,504\nthen you type the name of the method or of the property if\n然后输入你需要调用的方法或属性\n\n833\n00:41:14,506 --> 00:41:17,207\nyou wanna access an instance variable exactly the same.\n如果你想调用一个实例变量，也是相同的办法\n\n834\n00:41:17,209 --> 00:41:17,740\nThe name of the property or\n对某个对象，你想调用的属性的名字\n\n835\n00:41:17,742 --> 00:41:20,043\nthe method that you wanna access in that object.\n或者方法的名字\n\n836\n00:41:20,045 --> 00:41:22,645\nSo here I want to do touchDigit and you're going\n在这我想调用 touchDigit\n\n837\n00:41:22,647 --> 00:41:25,014\nto notice here that Xcode is helping me a lot as I type,\n你会发现 Xcode 会帮助我输入\n\n838\n00:41:25,016 --> 00:41:27,817\nit's giving me lists of things that I can choose that\n给我一张列表供我选择\n\n839\n00:41:27,819 --> 00:41:30,987\nare likely. Here touchDigit, it's putting that on the top\n这里，touchDigit，在最顶上\n\n840\n00:41:30,989 --> 00:41:33,356\ncuz that's the only method that is in my class.\n因为这是这个类中的唯一的方法\n\n841\n00:41:33,358 --> 00:41:36,092\nI inherit a lot of methods from my superclasses but\n我从父类中继承了非常多的方法\n\n842\n00:41:36,094 --> 00:41:38,862\nthis is the only one in my class and in fact if I just\n但这是这个类中的唯一的方法，事实上\n\n843\n00:41:38,864 --> 00:41:41,531\npress Tab, it starts filling it out. I'm not even,\n如果我按下 Tab，它会自动补全，不需要全部手打\n\n844\n00:41:41,533 --> 00:41:44,167\nI don't even have to type it okay, cuz it knows that's what\n因为 Xcode 知道我们想要什么\n\n845\n00:41:44,169 --> 00:41:48,771\nI want. Now, it takes two argument. The first argument\n现在它有两个参数\n\n846\n00:41:48,773 --> 00:41:51,508\nyou just put it in. So the first argument was a button so\n这里的第一个参数是一个 button， 所以\n\n847\n00:41:51,510 --> 00:41:55,078\nmaybe, you know, some button or something like that. Okay,\n我输入 someButton 之类的东西，okay\n\n848\n00:41:55,080 --> 00:41:56,446\nsome variable that would have to be a button.\n某些变量会是一个 button\n\n849\n00:41:56,448 --> 00:41:59,115\nI don't have one but that's what it would be.\n现在我没有这个变量，不过以后会有的\n\n850\n00:41:59,117 --> 00:42:00,783\nThe second argument here, okay, and\n这里的第二个参数\n\n851\n00:42:00,785 --> 00:42:03,753\nI'm just hitting Tab to go to each argument, is an Int,\n我按了 Tab 键来跳到每个参数，它是一个 Int\n\n852\n00:42:03,755 --> 00:42:06,256\nso let's say I put 5, okay, so this is how I would\n那么我放一个5在这里，okay，我就打算这么做了\n\n853\n00:42:06,258 --> 00:42:08,958\ncall this thing. Now what's interesting about this is,\n现在，有趣的事\n\n854\n00:42:08,960 --> 00:42:12,662\nnotice that this keyword is actually included,\n注意这个关键字也出现了\n\n855\n00:42:12,664 --> 00:42:15,532\nin other languages this would look like this. All right?\n在其它语言中会是这个样子，All right?\n\n856\n00:42:15,534 --> 00:42:17,934\nYou would just have the two arguments, sender and\n你只需要两个参数，sender 和 argument\n\n857\n00:42:17,936 --> 00:42:22,272\nargument, but here in Swift, sorry, in Swift,\n但是在 swift 里\n\n858\n00:42:22,274 --> 00:42:27,844\nwe put the explicit, name of the argument here for\n需要非常详尽，参数名也需要写出来\n\n859\n00:42:27,846 --> 00:42:30,680\nreadability and clarity except for we don't do it with\n这是为了可读，清晰，但我们不写第一个参数的参数名\n\n860\n00:42:30,682 --> 00:42:35,151\nthe first one. Okay? The first one we don't do.\nokay？不要写第一个参数的参数名\n\n861\n00:42:35,153 --> 00:42:37,620\nThat's because usually the first one is implicit in\n因为 swift 里通常都这样做\n\n862\n00:42:37,622 --> 00:42:41,758\nthe name, okay? But, that's what, now there is a way to\nokay？非得写出这个参数名的话\n\n863\n00:42:41,760 --> 00:42:44,394\nmake it so you have to do the first one, for but generally\n也是有一个方法的，但是最好别这样做\n\n864\n00:42:44,396 --> 00:42:46,729\nwe don't. In other words we don't type sender this.\n换言之不要把 sender 写出来\n\n865\n00:42:46,731 --> 00:42:48,598\nAnd in fact, it's wrong to type sender that.\n事实上，这样做是错误的\n\n866\n00:42:48,600 --> 00:42:50,967\n>> Would that be an error?\n这样会造成错误吗？\n\n867\n00:42:50,969 --> 00:42:51,000\n>> It would be an error.\n是的，这会造成错误\n\n868\n00:42:51,002 --> 00:42:55,705\nIt would not compile. Okay? So that's the syntax for sending.\n它不会编译，okay？这就是发送一个消息的语法了\n\n869\n00:42:55,707 --> 00:42:58,041\nAnd you'll have to get used to putting these in for\n你们会逐渐习惯这样的写法\n\n870\n00:42:58,043 --> 00:43:00,944\nall the subsequent arguments besides the first.\n除了第一个，其他的参数都要写参数名\n\n871\n00:43:00,946 --> 00:43:04,447\nOkay. So let's gret rid of all this stuff we added. So\nokay，删掉这些我们加上的东西\n\n872\n00:43:04,449 --> 00:43:08,084\nhere's our touchDigit. let's just have touchDigit\n这是我们的 touchDigit，现在让它\n\n873\n00:43:08,086 --> 00:43:10,587\nprint something out to the console. Okay?\n打印个什么，输出到控制台里，okay？\n\n874\n00:43:10,589 --> 00:43:11,621\nGreat thing to know for debugging, and\n这是 debug 的好方法，什么的\n\n875\n00:43:11,623 --> 00:43:14,958\nstuff like that. You do that with the method print. And\n在方法里写上打印语句\n\n876\n00:43:14,960 --> 00:43:17,026\nI'm just going to say, print touchDigit.\n我打印一个 “touchDigit”\n\n877\n00:43:17,028 --> 00:43:19,562\nSo it's gonna print touchDigit after the console.\n它会在控制台里打印一个 “touchDigit” 出来\n\n878\n00:43:19,564 --> 00:43:22,899\nNotice no semicolons on the end of lines or anything like\n注意，句尾没有分号或其他东西\n\n879\n00:43:22,901 --> 00:43:27,270\nthat. In Swift the carriage return is the end of line.\nswift 里，回车表示这一行的结束\n\n880\n00:43:27,272 --> 00:43:29,072\nAnd if you wanna put two statements on the same line\n如果你想把两条语句打在一行里\n\n881\n00:43:29,074 --> 00:43:30,440\nyou can use a semicolon in between, but\n在语句中间加上分号就行了\n\n882\n00:43:30,442 --> 00:43:34,077\ngenerally the carriage return is the end of line, okay? So\n但一般情况，我们用回车作为语句结尾，okay？\n\n883\n00:43:34,079 --> 00:43:37,046\nwe print touch digit here. Let's go ahead and run and\n所以把 print 语句写在这\n\n884\n00:43:37,048 --> 00:43:45,188\nsee if that works. Changes our simulator.\n现在运行一下看它是否能正常工作，改变下我们的模拟器\n\n885\n00:43:45,190 --> 00:43:45,955\nNow, where is the console?\n现在，控制台在哪里？\n\n886\n00:43:45,957 --> 00:43:49,258\nIt's going to appear magically at the bottom here as soon as\n当有东西出现在控制台里的时候\n\n887\n00:43:49,260 --> 00:43:51,060\nsomething appears on the console. So, here we go.\n它会神器地从底部出现，所以，here we go\n\n888\n00:43:51,062 --> 00:43:55,164\nReady? 5, there it is. There's the console in here. 5 again,\nReady? 5, 它出来了，这就是控制台，再按一下，5\n\n889\n00:43:55,166 --> 00:43:57,800\nokay we got two of them. Okay, we press a whole bunch of\nokay，我们现在有2个5了\n\n890\n00:43:57,802 --> 00:44:00,403\ntimes, and get a whole bunch of them. Go back here, scroll\n我们按几次5它就出现几次，回到这里来\n\n891\n00:44:00,405 --> 00:44:04,507\naround. This bottom area has the console on the right,\n滚动一下，底部区域里，右边是控制台\n\n892\n00:44:04,509 --> 00:44:07,944\nand your debugger output on the left. This is where when\n左边是调试器，debug 的时候你会用到\n\n893\n00:44:07,946 --> 00:44:09,712\nwe start to do debugging you'll see it on the left.\n它会出现在左边\n\n894\n00:44:09,714 --> 00:44:13,416\nYou can hide one or the other, like we could hide our\n也可以隐藏它们，我们可以隐藏调试器\n\n895\n00:44:13,418 --> 00:44:16,252\ndebugger and just see our console here. Okay, so\n只留下我们的控制台，okay？\n\n896\n00:44:16,254 --> 00:44:19,222\nthis is cool, this is great. Except for we're gonna\n这很酷，非常棒\n\n897\n00:44:19,224 --> 00:44:23,292\nhave a lot of buttons not just this one button, this 5.\n但是如果有一堆按键而不是一个呢？这是个5\n\n898\n00:44:23,294 --> 00:44:26,195\nOkay, so let's go back to our UI. By the way you can hide\n现在回到我们的UI，顺便说一下\n\n899\n00:44:26,197 --> 00:44:29,565\nthis thing by either dragging it down or pressing this\n你可以通过拖拽来隐藏它们，或者点击这个按钮\n\n900\n00:44:29,567 --> 00:44:32,935\nbutton up here. Okay, just like you hide this thing\n就像你点击这个隐藏这个\n\n901\n00:44:32,937 --> 00:44:36,105\nwith that you hide with this with that. All right, so we'll\n就像你点击这个隐藏这个\n\n902\n00:44:36,107 --> 00:44:39,509\nstop. Now I wanna make a whole keypad worth of buttons here.\n停止运行，现在我想做出一个完整的键盘\n\n903\n00:44:39,511 --> 00:44:41,611\nInstead of just having a 5, I want a whole bunch.\n不只是一个5，而是所有数字\n\n904\n00:44:41,613 --> 00:44:42,979\nSo I'm gonna do that with copy and paste.\n我通过复制粘贴来完成\n\n905\n00:44:42,981 --> 00:44:47,550\nCopy, paste okay? There we go, paste another one here.\n复制，粘贴，okay？好了，再粘贴一个\n\n906\n00:44:47,552 --> 00:44:51,387\nOkay? Maybe this is our 4, 5 and 6.\nokay？这个是我们的4，5，6\n\n907\n00:44:51,389 --> 00:44:55,525\nI can actually select all three and copy paste. Okay.\n我可以选中这三个，再复制和粘贴\n\n908\n00:44:55,527 --> 00:45:00,463\n1, 2, and 3 and may you paste again.\n1，2，3，然后再粘贴一次\n\n909\n00:45:00,465 --> 00:45:05,635\nGo up here. 7, 8, 9 and we'll copy and\n移到上面来，7，8，9，再复制\n\n910\n00:45:05,637 --> 00:45:11,407\npaste one more to make our 0. Okay?\n粘贴出我们的0，okay？\n\n911\n00:45:11,409 --> 00:45:15,511\nSo here's our nice little keypad right here. And,\n这就是我们的小键盘了\n\n912\n00:45:15,513 --> 00:45:20,583\nnow we can run. And we'll notice\n现在我们运行它\n\n913\n00:45:20,585 --> 00:45:24,287\nthat all of these buttons are sending touch digit. You see?\n注意所有的按键都会发送信息给 touchDigit\n\n914\n00:45:24,289 --> 00:45:26,055\nOkay, so they're all sending touch digit.\n他们都会发送信息给 touchDigit\n\n915\n00:45:26,057 --> 00:45:28,991\nWhich is good, that's kind of nice. We can also tell they're\n很棒，很不错，我们还能通过这个小圈圈\n\n916\n00:45:28,993 --> 00:45:30,259\nall sending it with this little circle.\n看到它们连接在一起\n\n917\n00:45:30,261 --> 00:45:32,395\nWatch what happens when I mouse over. You see?\n看看我移开鼠标会发生什么？看见了吗？\n\n918\n00:45:32,397 --> 00:45:35,898\nIt's selecting them all to say they're all sending it. Okay.\n选中了全部按键，他们都能发送信息\n\n919\n00:45:35,900 --> 00:45:40,169\nBut, we really wanna know which one is sending it. Okay.\n但，我们需要知道是那一个按键发送了信息，okay\n\n920\n00:45:40,171 --> 00:45:42,472\nSo we're gonna have to look at this sender argument,\n所以我们需要看看这个 sender 参数\n\n921\n00:45:42,474 --> 00:45:45,775\nto see which button is sending us this touch digit.\n看看是哪个按键发给它了信息\n\n922\n00:45:45,777 --> 00:45:48,511\nOkay. So I'm gonna create a local variable here.\nokay，我打算建立一个局部变量\n\n923\n00:45:48,513 --> 00:45:51,714\nThis is how you create a local variable, var. The name,\n这就是如何建立一个局部变量，var，然后是变量名\n\n924\n00:45:51,716 --> 00:45:55,451\nwhich I'm gonna call digit. And I'm gonna set it equal to,\n我打算叫它 digit，我打算把它设置成\n\n925\n00:45:55,453 --> 00:45:59,522\nwhatever I get from asking the sender, what its title is.\n给被按下的按键的数字，按键的名字\n\n926\n00:45:59,524 --> 00:46:02,658\nOkay? Now, how do I do that? Well, we know that we\nokay？怎么做呢？ 我们知道\n\n927\n00:46:02,660 --> 00:46:06,229\nsend a message to something by doing the object, right,\n得到这个名字肯定和sender这个对象有关，对吗？\n\n928\n00:46:06,231 --> 00:46:11,434\nsender and a dot, okay? Unfortunately, button has, mm,\nsender 然后一个“.”，okay？不幸的是\n929\n00:46:11,436 --> 00:46:15,471\nquite a few methods, okay? I mean probably hundreds, okay?\n按键拥有很多方法，okay？可能几百个，okay？\n\n930\n00:46:15,473 --> 00:46:18,808\nBecause it's inheriting things from control and view and\n因为它继承于 control，view\n\n931\n00:46:18,810 --> 00:46:18,875\nstuff like that.\n类似的东西\n\n932\n00:46:18,877 --> 00:46:21,978\nSo it's a pretty much, a bummer trying to find out how\n所以找到按键名似乎还是很困难\n\n933\n00:46:21,980 --> 00:46:25,681\nto know what to give this. So we need documentation here.\n所以我们在这种时候\n\n934\n00:46:25,683 --> 00:46:28,184\nWe need some help, okay. So the way to do that\n就需要文档的帮助，okay？怎么做呢？\n\n935\n00:46:28,186 --> 00:46:30,219\nis you're gonna hold down the option key, okay.\n按下你的键盘上的 option 键，okay？\n\n936\n00:46:30,221 --> 00:46:32,321\nI already showed you Control is an important key for\n我已经告诉你了 control 键很重要\n\n937\n00:46:32,323 --> 00:46:35,792\ndragging between your view and your thing. Now Option is\n特别是对UI拖拽来说，现在 option 键\n\n938\n00:46:35,794 --> 00:46:38,194\nan important key. And when you hold down Option,\n也非常重要，当你按下 option 键\n\n939\n00:46:38,196 --> 00:46:40,029\nlook what happens when you mouse over things.\n再移动鼠标，看看会发生什么\n\n940\n00:46:40,031 --> 00:46:43,900\nThey get this dash blue underline going. And what that\n下方出现了蓝色虚线，这意味着\n\n941\n00:46:43,902 --> 00:46:46,536\nmeans is if you click on them Xcode's gonna tell you\n如果你点击了它们，Xcode 会告诉你\n\n942\n00:46:46,538 --> 00:46:49,705\nas much as it can about that thing. So let's click on\n关于它们的一切信息，所以我们在\n943\n00:46:49,707 --> 00:46:53,309\nUIButton and when we do we get this little window that\nUIButton 这点击，我们得到了一个小窗口\n944\n00:46:53,311 --> 00:46:57,547\nhas a complete description of UIButton in here. And really\n它拥有关于 UIButton 完整信息，非常重要的是\n\n945\n00:46:57,549 --> 00:47:01,150\nimportantly down at the bottom it has a reference link.\n在最底下，有一个引用链接\n\n946\n00:47:01,152 --> 00:47:03,686\nSee this reference link? And if I click this, this is gonna\n看见这个引用链接了吗？如果我点它一下\n\n947\n00:47:03,688 --> 00:47:07,757\ntake me to the documentation for UIButton. So there we go.\n它会把我带到 UIButton 的文档里，所以我们点击它\n\n948\n00:47:07,759 --> 00:47:10,226\nHere it is, UIButton. Here's all the methods and\n这就是了，UIButton，这是它所有的方法\n\n949\n00:47:10,228 --> 00:47:14,530\nproperties in UIButton. Here's all the description of it.\n所有的属性，所有的关于它的描述\n\n950\n00:47:14,532 --> 00:47:19,769\nAnd there is all kinds of text here that describes all\n各种各样的文本来告诉你这些方法\n\n951\n00:47:19,771 --> 00:47:22,171\nthe methods and how they work, okay.\n是如何工作的，okay？\n\n952\n00:47:22,173 --> 00:47:26,375\nNow, I need to find something about the title so\n现在，我要找出关于 ”title”(标题) 的一些信息\n\n953\n00:47:26,377 --> 00:47:29,846\nI could search here by just doing Cmd+f to search, and\n我可以按下Cmd+f进行搜索\n\n954\n00:47:29,848 --> 00:47:32,982\nI could search for title but unfortunately the title\n我可以搜索一下 “title”，不幸的是\n\n955\n00:47:32,984 --> 00:47:37,286\nis mentioned a lot, see? So that's no good. So\n“title” 在文档里被提及的太多了，很不好\n\n956\n00:47:37,288 --> 00:47:39,522\nI can go over here to the summary of all the methods and\n然后我可以看下 summary 这里，它有所有的方法和属性\n\n957\n00:47:39,524 --> 00:47:42,792\nproperties. We could look here. Getting dimensions,\n我们可以看过来，看看它包括些什么\n\n958\n00:47:42,794 --> 00:47:46,128\nno I don't wanna do that. Configuring edge insets we\n不，我不想这样做，我们甚至还不知道什么是\n\n959\n00:47:46,130 --> 00:47:48,998\ndon't even know what that is yet. Getting the current state\n“Configuring edge insets”，“获取目前状态”这个听起来\n\n960\n00:47:49,000 --> 00:47:50,700\nthat sounds pretty good, getting the current state.\n还不错，获取目前状态\n961\n00:47:50,702 --> 00:47:53,302\nLet's see what we've got, button type okay here's how I\n看看这里有什么？按键类型，okay，它在这\n\n962\n00:47:53,304 --> 00:47:54,670\ncan get the button's type that's good.\n我现在可以得到按键的类型了，不错\n\n963\n00:47:54,672 --> 00:47:58,741\nCurrent title, the current title displayed on the button,\n“Current title”，按键上的名称\n\n964\n00:47:58,743 --> 00:48:00,643\nvictory, that's what we want. Okay,\n胜利了！这就是我们要的，okay？\n\n965\n00:48:00,645 --> 00:48:03,012\nnow when we find something in the documentation we want,\n现在，当我们需要在文档中找东西时\n\n966\n00:48:03,014 --> 00:48:06,115\nyou're gonna see that there is a Swift explanation\n你可以看见这里有关于swift解释\n\n967\n00:48:06,117 --> 00:48:08,918\nof it, and and objective C explanation. So we're always\n或者关于 Objective C 的解释\n\n968\n00:48:08,920 --> 00:48:12,021\ngoing to be looking at the Swift version in this class.\n我们看看这个类的解释的 swift 版本\n\n969\n00:48:12,357 --> 00:48:13,322\nSo what is this thing, okay?\n这是个什么？\n\n970\n00:48:13,324 --> 00:48:16,926\nThis is not a method because it would say func right here.\n它不是一个方法，因为方法前面有一个 “func”\n\n971\n00:48:16,928 --> 00:48:19,595\nIf this were a method on UIButton you would have func.\n如果它是 UIButton 里的方法，你会看到一个 ”func”\n\n972\n00:48:19,597 --> 00:48:22,265\nInstead it has var, that means it's a property.\n但这有一个 “var”，意味着它是一个属性\n\n973\n00:48:22,267 --> 00:48:25,034\nSo a property's like an instance variable, okay?\n属性就像一个实例变量，okay？\n\n974\n00:48:25,036 --> 00:48:27,436\nNow this is an interesting property because it's got this\n这是个有趣的属性\n\n975\n00:48:27,438 --> 00:48:31,908\nlittle terminology on the end, which means it's read only. So\n因为在末尾有个这个东西，意味着它是只读的\n\n976\n00:48:31,910 --> 00:48:34,877\nwe can't set the button's title here with current title.\n所以我们不能通过它来设置这个按键的名称\n\n977\n00:48:34,879 --> 00:48:37,413\nTurns out that's because there's another method up here\n但是呢还有一个方法\n\n978\n00:48:37,415 --> 00:48:40,750\ncalled setTitle forState for setting the button's title.\n叫 “setTitle forState“ 来设置按键的名称\n979\n00:48:40,752 --> 00:48:41,884\nBecause when you set the button's title,\n因为当你设置一个按键名称的时候\n\n980\n00:48:41,886 --> 00:48:44,320\nyou wanna set the title for what state it's in,\n你需要知道这个按键的状态\n\n981\n00:48:44,322 --> 00:48:46,589\nhighlighted, disabled, whatever. But luckily there's\n高亮？禁用？无所谓\n\n982\n00:48:46,591 --> 00:48:50,493\na current title here that just gets you the current title.\n幸运的是这里有一个 “current title” 让你获取当前按键名称\n\n983\n00:48:50,862 --> 00:48:52,995\nIn whatever state the button is currently in.\n不管这个按键当前是什么状态的\n\n984\n00:48:52,997 --> 00:48:55,998\nSo, here is, so that's why it says var instead of func.\n这就是这为什么是 var 而不是 func\n\n985\n00:48:56,000 --> 00:48:59,635\nHere's the name of the property, currentTitle.\n这里是属性的名字，currentTitle\n\n986\n00:48:59,637 --> 00:49:00,436\nHere is the type.\n这里是它的类型\n\n987\n00:49:00,438 --> 00:49:03,906\nI promised you that it was always colon and type. Now,\n我向你保证类型前总是有一个冒号\n\n988\n00:49:03,908 --> 00:49:09,011\nthe type of this is string? >> [LAUGH]\n现在这个类型是 String??\n\n989\n00:49:09,013 --> 00:49:11,614\n>> Wha? Maybe. Okay? We're\n啥？可能是吧，okay\n\n990\n00:49:11,616 --> 00:49:14,984\ngonna suspend our disbelief here because that question\n现在刹住你们的疑问，因为这个问号\n\n991\n00:49:14,986 --> 00:49:18,721\nmark actually means something. We're gonna kinda hope that\n意味着些什么，我们希望这是一个 string\n\n992\n00:49:18,723 --> 00:49:22,158\nthis is a string, but it's not going to be. But that's okay.\n但它不是，不过没有关系\n\n993\n00:49:22,160 --> 00:49:24,860\nSo we're gonna try and assume it is. All right? So anyway,\n我们就假设它是，好吗？\n\n994\n00:49:24,862 --> 00:49:26,495\nthis is how we look things up in the documentation\n无论如何，这就在文档里如何找东西的办法\n\n995\n00:49:26,497 --> 00:49:30,199\nto see the way it works. Now, there's another way to do it,\n现在，也有其他办法来做这事\n\n996\n00:49:30,201 --> 00:49:32,468\nokay, which is even cooler. I type this dot.\n更酷一点，我输入这个”.”\n\n997\n00:49:32,470 --> 00:49:35,538\nI want the title so I'm just going to start typing title.\n我想使用”title”，所以我就继续输入”title”\n\n998\n00:49:35,540 --> 00:49:37,840\nOkay I don't know there is a method called title,\nokay，我不知道这里是否有一个方法，名字是title\n\n999\n00:49:37,842 --> 00:49:40,843\nin fact there isn't. But as soon as I started typing title\n事实上是没有的，但只要我输入完之后\n\n1000\n00:49:40,845 --> 00:49:43,346\nit shows me all the methods that start with title.\n它会告诉我所有以 “title” 开头的方法的名字\n\n1001\n00:49:43,348 --> 00:49:48,617\nAll the methods that include title in the name. See?\n所有名字里包含了 title 的方法，看见了吗？\n\n1002\n00:49:48,753 --> 00:49:54,156\nAnd all the methods that have T-I-T-L-E in the order. Okay,\n还有所有含有 T-I-T-L-E 这个字母顺序的方法\n\n1003\n00:49:54,158 --> 00:49:57,093\nand it gives it to you in the order you might expect right?\n这会按照你期望的顺序呈现\n\n1004\n00:49:57,095 --> 00:50:00,363\nTitle first and then. So this is kinda helping,\n含有 title 这个词的优先，别的在后面，这提供了一种帮助\n\n1005\n00:50:00,365 --> 00:50:00,997\nyou can search basically.\n你可以这么搜索\n\n1006\n00:50:00,999 --> 00:50:03,599\nAnd when you do this you would quickly see current title,\n当你这么做的时候，你快速浏览到 currentTitle\n\n1007\n00:50:03,601 --> 00:50:06,769\nthat looks like what I want. And you can double click here,\n这看起来像是我想要的。你就在这双击\n\n1008\n00:50:06,771 --> 00:50:09,138\nactually, and it will put in there. Okay? So\n这样就会出现在这里。\n\n1009\n00:50:09,140 --> 00:50:12,942\nthere's our current title. Now instead of printing touch\n这就是我们要的 currentTitle\n\n1010\n00:50:12,944 --> 00:50:17,313\ndigit we basically wanna print which one, which digit was,\n现在我们想打印具体按到的某个数字，而不是 touchDigit\n\n1011\n00:50:17,315 --> 00:50:22,485\ntouched here. So I'm gonna say touched, we could say percent,\n所以这里要换成\n\n1012\n00:50:22,487 --> 00:50:25,254\ns digit. Comma digit.\n“touched %s digit”, digit\n\n1013\n00:50:25,256 --> 00:50:27,790\nThis is what it would look like in C. For example,\n这就看起来像是C语言\n\n1014\n00:50:27,792 --> 00:50:31,327\nis everyone familiar with this print F like format?\n所以你们对 printf 熟悉吗\n\n1015\n00:50:31,329 --> 00:50:33,696\nOkay good, cuz you can't do it in Swift.\n很好，但你不能在 Swift 里这样做\n\n1016\n00:50:33,698 --> 00:50:34,096\nOkay. >> [LAUGH]\n\n1017\n00:50:34,098 --> 00:50:35,164\n>> We don't do that in Swift.\n我们在 Swift 里不这么做\n\n1018\n00:50:35,166 --> 00:50:37,633\nInstead, we do backslash, open parentheses,\n我们用反斜杠、括号代替\n\n1019\n00:50:37,635 --> 00:50:40,903\nclose parentheses. And then we can put anything we want in\n然后里面放任何我们想放的\n\n1020\n00:50:40,905 --> 00:50:43,806\nhere. Okay clean digit. And we don't need this out here on\n删掉 digit，引号外不需要它\n\n1021\n00:50:43,808 --> 00:50:47,510\nthe side. Okay, so this will be invaluated converted to\n所以这会被转换成 string 类型\n\n1022\n00:50:47,512 --> 00:50:50,279\na string. Some things can't be converted to strings but\n有的不能被转换，但大多数可以\n\n1023\n00:50:50,281 --> 00:50:53,215\nmost things can, so you put that in there. Okay,\n所以你可以把它放在里面\n\n1024\n00:50:53,217 --> 00:50:56,652\nif you can't you'll get a warning, okay? All right, so\n如果不可以，你会被警告\n\n1025\n00:50:56,654 --> 00:50:58,054\nthat's how we do that. So, let's go ahead and\n所以我们就这么做了\n\n1026\n00:50:58,056 --> 00:51:01,357\nsee what's going on. But now maybe we should start paying\n继续看看接下来会发生什么\n\n1027\n00:51:01,359 --> 00:51:02,024\nattention to our warnings.\n我想现在应该开始注意一下这个警告了\n\n1028\n00:51:02,026 --> 00:51:05,428\nOkay, when you submit your homework, no warnings please.\n当你们交作业的时候，不准有警告\n\n1029\n00:51:05,430 --> 00:51:07,463\nOkay, no warnings. And certainly no errors,\n没有警告，当然也不能有错误\n\n1030\n00:51:07,465 --> 00:51:10,433\nthose are red things those won't build, no warnings. So\n有错误的时候就不能 build\n\n1031\n00:51:10,435 --> 00:51:12,535\nwhat is this warning, let's take a look at this warning.\n这个警告是什么呢？我们来看看\n\n1032\n00:51:12,537 --> 00:51:14,170\nYou look at a warning by clicking on it.\n我们通过点击来看一个警告\n\n1033\n00:51:14,172 --> 00:51:16,572\nSo I'm gonna click on it, and it says here,\n我点击他，这里是这么写的\n\n1034\n00:51:16,574 --> 00:51:21,644\nvariable digit with never mutated, consider changing to\ndigit 这个变量没有被改变过\n\n1035\n00:51:21,646 --> 00:51:26,082\nlet constant. Okay, what does that mean?\n是不是考虑把他变成 let 型常量。这是什么意思呢？\n\n1036\n00:51:26,084 --> 00:51:31,020\nThat means that instead of var here, it wants us to put let.\n这里的意思是，希望我们用 let 而不是 var\n\n1037\n00:51:31,022 --> 00:51:34,623\nAnd in fact, you should always do that. Anytime you declare\n事实上我们应该这么做\n\n1038\n00:51:34,625 --> 00:51:37,793\na local variable, okay, or even a property that is\n任何时候申明一个局部变量，或者一个属性\n\n1039\n00:51:37,795 --> 00:51:40,629\ninitialized at the beginning and never changes, in other\n在初始化后就一直没被改变，换句话说，\n\n1040\n00:51:40,631 --> 00:51:43,599\nwords, it's a constant, use let instead of var.\n就是个常量，我们就应该用 let 而不是 var\n\n1041\n00:51:43,601 --> 00:51:46,268\nNow why do you want to do that? Two reasons really, one,\n那么我们现在为什么要这么做？两个理由\n\n1042\n00:51:46,270 --> 00:51:48,804\nit helps people reading your code realize this thing's\n一、这帮助别人读你的代码的时候意识到\n\n1043\n00:51:48,806 --> 00:51:51,040\nnever going to change, I don't have to worry about it,\n这个一直不会变，不需要去担心它\n\n1044\n00:51:51,042 --> 00:51:54,243\nit's just like a constant. And two, if that thing were for\n这只是个常量。二、如果那个东西，\n\n1045\n00:51:54,245 --> 00:51:57,613\nexample, an array, or a dictionary, and you use let,\n比如说是一个数组或者字典，你用了 let\n\n1046\n00:51:57,615 --> 00:52:00,883\nthat means nothing can be put into that dictionary or\n这就意味着没有什么可以放进字典或从字典拿出\n\n1047\n00:52:00,885 --> 00:52:04,553\ntaken out. Or into the array or taken out okay. So\n也可以放进数组或从数组拿出\n\n1048\n00:52:04,555 --> 00:52:08,023\nit's how you can create read only arrays and dictionaries\n这就是你如何创建只读的数组或者是字典\n\n1049\n00:52:08,025 --> 00:52:12,628\nokay. So, always use let when you are doing a constant.\n所以申明常量的时候一定记得用 let\n\n1050\n00:52:12,630 --> 00:52:14,563\nAnd in fact notice that XCode is saying,\n注意 Xcode 这里说的\n\n1051\n00:52:14,565 --> 00:52:17,733\nhey if you click here I'll fix it for you. Okay,\n如果你点这里，我会为你修复这个问题\n\n1052\n00:52:17,735 --> 00:52:21,904\nsee how it says fix it replays var with let. Sure. Okay, and\n看一下它如何用 let 代替 var 修正这个问题\n\n1053\n00:52:21,906 --> 00:52:24,773\nit did it and now the warnings gone. Okay, so\n所以它做到了，警告没了\n\n1054\n00:52:24,775 --> 00:52:29,678\nlet's run, see if this is working. We're crossing our\n来跑一下，看看是不是能行\n\n1055\n00:52:29,680 --> 00:52:32,915\nfingers about that whole string question mark thing.\n我们越过我们的手指关于整串问号的事情\n\n1056\n00:52:32,917 --> 00:52:35,518\nAll right, so here we go, let's press 5.\n好了，来按下 5\n\n1057\n00:52:36,921 --> 00:52:40,189\nThe heck is going on down there? Okay, touched\n这下面就会显示数字\n\n1058\n00:52:40,191 --> 00:52:45,294\noptional 5 digit? Okay so what is this optional business.\ntouched optional(\"5\") digit？这里的 optional 是什么\n\n1059\n00:52:45,296 --> 00:52:47,163\nHere you all wanna take a deep breath,\n所以这里你们得深呼吸\n\n1060\n00:52:47,165 --> 00:52:50,332\nclear your minds, and pay close attention okay. Because\n清空你们的脑袋，集中全部注意力\n\n1061\n00:52:50,334 --> 00:52:52,935\nthis is a very important thing in Swift, it's ubiquitous\n因为这是 Swift 里非常非常重要的东西\n\n1062\n00:52:52,937 --> 00:52:57,740\nthroughout the entire iOS API okay. Very cool feature, but\n这在 iOS API 里无处不在，一个非常酷的特性\n\n1063\n00:52:57,742 --> 00:53:00,442\nit requires a little bit of getting used to in terms of\n但是需要一段时间来熟悉这个语法\n\n1064\n00:53:00,444 --> 00:53:05,381\nits syntax okay? This is the feature of optionals. Okay?\n这是一个叫 optional（可选类型）的特性\n\n1065\n00:53:05,383 --> 00:53:09,818\nIn Swift, there is a type called optional.\n在Swift里，有一种类型叫 optional\n\n1066\n00:53:09,820 --> 00:53:12,388\nIt's a type like int or boolean or anything else,\n这是一种类似于 int 或 bool 的类型\n\n1067\n00:53:12,390 --> 00:53:14,323\nstring, it's dictionary, array,\n或者是 string、dictionary、array 这样的类型\n\n1068\n00:53:14,325 --> 00:53:18,360\noptional. Optional is just a type. This type can only have\noptional 只是一个类型，这个类型只有两个值\n\n1069\n00:53:18,362 --> 00:53:23,699\ntwo values. One value is not set. Okay?\n一个值是没有被赋值\n\n1070\n00:53:23,701 --> 00:53:28,070\nThat's expressed in Swift with the key word nil, N-I-L.\n在 Swift 里表示它的关键字是 nil\n\n1071\n00:53:28,072 --> 00:53:31,473\nNil only means, this optional is not set.\nnil 只表示这个 optional 没有被赋值\n\n1072\n00:53:31,475 --> 00:53:33,709\nThat's all it means in Swift. It doesn't mean zero.\n这就是他在 Swift 里全部的含义，这不代表它为零\n\n1073\n00:53:33,711 --> 00:53:36,245\nIt doesn't mean a pointer that doesn't point anywhere, like\n这不像别的语言，它不代表一个不指向任何地方的指针\n\n1074\n00:53:36,247 --> 00:53:39,882\nin other languages. Nil means an optional that's not set.\nnil 代表一个 optional 没有被赋值\n\n1075\n00:53:39,884 --> 00:53:45,120\nThe other state that an optional can be is set,\n另一个状态就是一个 optional 被赋值了\n\n1076\n00:53:45,122 --> 00:53:48,691\nokay? Now, if it's in the set state, it can have\n如果它在被赋值状态\n\n1077\n00:53:48,693 --> 00:53:52,995\nan associated value, okay? An associated value,\n他就可以有一个关联值\n\n1078\n00:53:52,997 --> 00:53:55,698\nwhich can be of any other type, okay? Actually it also\n一个可以是其他任何类型的关联值\n\n1079\n00:53:55,700 --> 00:53:57,199\ncould also be an optional. You can have an optional,\n实际上，它还可以是一个 optional 。你可以有一个 optional\n\n1080\n00:53:57,201 --> 00:54:00,970\noptional, but that associated value is just associated with\n但是关联值只和它赋值的状态关联\n\n1081\n00:54:00,972 --> 00:54:03,405\nthis set state, okay? In the not set state,\n在未赋值状态\n\n1082\n00:54:03,407 --> 00:54:06,375\nthere is no associated value cuz it's not set. Okay?\n它就没有关联值，因为它没有被赋值\n\n1083\n00:54:06,377 --> 00:54:09,011\nNow what does it look like to declare it optional? Well,\n那么把它申明为 optional 看起来是什么样呢？\n\n1084\n00:54:09,013 --> 00:54:12,615\nlet's go back with our option key and take a look at current\n让我们回过头看一下我们的 option 键看一下 currentTitle\n\n1085\n00:54:12,617 --> 00:54:15,017\ntitle. Okay, you remember this from the documentation?\n还记得这段文档吗？\n\n1086\n00:54:15,019 --> 00:54:20,289\nIt says var currentTitle string? That means this is\n这里写到 \"var currentTitle: string?\"\n\n1087\n00:54:20,291 --> 00:54:25,694\nan optional whose associated value is a string. Okay?\n这里的意思是这是个关联值为 string 的 optional\n\n1088\n00:54:25,696 --> 00:54:28,063\nSo if someone looks at this property and\n所以如果有人看到这个属性\n\n1089\n00:54:28,065 --> 00:54:29,198\nsays, what type is that property?\n当他问这个是什么类型的时候\n\n1090\n00:54:29,200 --> 00:54:32,701\nAnd they say, it's a string but it's optional no, no.\n他可能会说，这是个 string，但是是 optional。不！\n\n1091\n00:54:32,703 --> 00:54:37,973\nThis is an optional and it's associated values of string,\n这是个 optional，他的关联值是 string\n\n1092\n00:54:37,975 --> 00:54:42,311\nokay? Get used to saying, this type is optional, okay? So\n要习惯于说这个类型是 optional\n\n1093\n00:54:42,313 --> 00:54:45,114\nthis is an optional string, that's what would say.\n这是个 optional string（可选字符串），这才是正确的\n\n1094\n00:54:45,116 --> 00:54:47,516\nIt's an optional string, okay? But primarily,\n这是个 optional string。主要是个 optional\n\n1095\n00:54:47,518 --> 00:54:51,053\nit's an optional. Okay, it's associated value is a string.\n关联值是 string\n\n1096\n00:54:51,055 --> 00:54:53,922\nSo this currentTitle, why is it an optional? Well,\n所以这个 currentTitle 为什么是个 optional?\n\n1097\n00:54:53,924 --> 00:54:58,560\nbecause we might have a button here that has no title set.\n这是因为一个按钮的标题可能不会被赋值\n\n1098\n00:54:58,562 --> 00:55:02,064\nNot set. Okay, so the title needs to be an optional,\n没有赋值，所以它应该是个 optional\n\n1099\n00:55:02,066 --> 00:55:05,367\nso it can represent the case where it's not set. Now,\n所以它就可以表示没有被赋值的情况\n\n1100\n00:55:05,369 --> 00:55:08,304\nanything can be an optional. Not just pointers, or objects.\n所以任何东西都可以是 optional。不只是指针或对象\n\n1101\n00:55:08,306 --> 00:55:11,440\nInts could be optional. You could have an optional int,\nint 可以是 optional，你可以有一个 optional int\n\n1102\n00:55:11,442 --> 00:55:15,077\nokay? But here we are representing the title,\n但这里我们代表了一个标题\n\n1103\n00:55:15,079 --> 00:55:18,414\nthe button, which is the string and it might be not set\n这个按钮的标题是个 string，这可能不会被赋值\n\n1104\n00:55:18,416 --> 00:55:20,382\nokay? So we need that to be an optional.\n我们需要这个是个 optional\n\n1105\n00:55:20,384 --> 00:55:23,519\nSo how do I get the string, because I don't want\n所以我怎么得到这个 string\n\n1106\n00:55:23,521 --> 00:55:27,690\nthis digit, which currently is also an optional string?\n我不希望这个 digit，现在还是个 optional string\n\n1107\n00:55:27,692 --> 00:55:30,559\nIsn't it kinda weird here when I said let digit equal,\n当这里是 \"let digit ＝\" 的时候不是很奇怪吗\n1108\n00:55:30,561 --> 00:55:34,029\nnobody said how come you didn't say colon string?\n没人觉得你为什么不加上 \":string\" 呢？\n\n1109\n00:55:34,031 --> 00:55:37,900\nOkay? I didn't say the type. I declared a local variable.\n我没有说类型，我申明一个局部变量\n\n1110\n00:55:37,902 --> 00:55:41,170\nIt didn't even have a type. How was that possible?\n我甚至都没有一个类型，这怎么可能？\n\n1111\n00:55:41,172 --> 00:55:46,742\nIn Swift, Swift will infer the type all the time, okay? If\n在 Swift 里，Swift 会一直推断类型\n\n1112\n00:55:46,744 --> 00:55:49,411\nit's possible for it to know the type it will infer it.\n如果它可以在这里知道他的类型，那么就会推断这个类型\n\n1113\n00:55:49,413 --> 00:55:54,183\nAnd in fact it's wrong really bad coding style to put that\n实际上，这里写上类型是个非常差的编程风格\n\n1114\n00:55:54,185 --> 00:55:58,220\ntype in there. It's better to just say let digit equal and\n这里最好就这么写\n\n1115\n00:55:58,222 --> 00:56:01,190\nlet swift infer it. And here Swift has inferred.\n让 Swift 来推断他的类型。这里 Swift 也做到了\n\n1116\n00:56:01,192 --> 00:56:03,325\nThe digit must be of type string question mark,\n这里的 digit 一定会是个 \"string?\" 类型\n\n1117\n00:56:03,327 --> 00:56:06,228\nthat's because this is of type string question mark.\n因为后面的也是个 \"string?\" 类型\n\n1118\n00:56:06,230 --> 00:56:09,365\nSo of course digit has to be that. You see what's happening\n所以 digit 当然也应该是那个类型。你看到那发生什么了吗？\n\n1119\n00:56:09,367 --> 00:56:12,668\nthere? So you're going to see type inference all the time in\nSwift 里你会时时看到类型推断的结果\n\n1120\n00:56:12,670 --> 00:56:14,203\nSwift, it makes your code much more compact,\n这让你代码更加简洁\n\n1121\n00:56:14,205 --> 00:56:18,374\na lot less repeated stuff, is that a question in the back?\n很多更少重复的工作，那边的同学有问题吗？\n\n1122\n00:56:18,376 --> 00:56:19,875\n>> Yeah, is that the same for\n这对 var 是一样的吗？\n\n1123\n00:56:19,877 --> 00:56:20,209\nvar too. >> Is the question is\n问题是：\n\n1124\n00:56:20,211 --> 00:56:22,277\nthat same for var too, absolutely it's the same for\n这对 var 是一样的吗？\n\n1125\n00:56:22,279 --> 00:56:26,382\nvar, okay? So, how do I get that string though?\n完全一样。所以我怎么获得那个 string 呢？\n\n1126\n00:56:26,384 --> 00:56:28,951\nIf this button title is set, how do I get that\n如果这个按钮的标题已经有了，那我如何\n\n1127\n00:56:28,953 --> 00:56:32,721\nassociated value thing, okay, out of this optional?\n从这个 optional 里面获取这个关联值？\n\n1128\n00:56:32,723 --> 00:56:36,525\nAnd the answer is you put an exclamation point in the end,\n方法是你在最后放一个感叹号\n\n1129\n00:56:36,527 --> 00:56:39,328\nokay. Now, optional is question mark on the end of\noptional 在定义的末尾有个问号\n\n1130\n00:56:39,330 --> 00:56:42,831\na declaration. Exclamation point is unwrap this thing and\n感叹号是用来 unwarp（解包）这个 optional\n\n1131\n00:56:42,833 --> 00:56:46,402\ngive me the associative value. So this is very succinct,\n然后给我这个关联值。这是很简明的\n\n1132\n00:56:46,404 --> 00:56:50,038\none character for each side of you using this, okay?\n每次可以使用一种符号\n\n1133\n00:56:50,040 --> 00:56:51,774\nQuestion. >> Can you briefly talk about\n学生问题：\n\n1134\n00:56:51,776 --> 00:56:52,074\nwhy you want the title to,\n\n1135\n00:56:52,076 --> 00:56:53,976\nwhy you design the title to be optional instead of like\n\n1136\n00:56:53,978 --> 00:56:59,114\nan empty string? >> Okay, so the question is,\n问题是\n\n1137\n00:56:59,116 --> 00:57:02,384\nwhy does Swift have this optional thing instead of just\n为什么 Swift 不直接用空字符\n\n1138\n00:57:02,386 --> 00:57:05,120\ndoing empty string to mean a button without a title?\n而是用 optional 来表示一个没有标题的 button？\n\n1139\n00:57:05,122 --> 00:57:10,492\nOr maybe for an int minus 1. I don't know. Or for a point or\n或者是一个 -1 的 int\n\n1140\n00:57:10,494 --> 00:57:14,463\n0 memory address or something like that. The main reason for\n又或者是一个指针、一个不占内存的地址或者类似的什么东西\n\n1141\n00:57:14,465 --> 00:57:18,100\nthat is for example, pointers to objects in Swift, you don't\n这主要的原因是，Swift 里的指针\n\n1142\n00:57:18,102 --> 00:57:21,703\nsee the memory address. So you couldn't have it be 0, okay,\n你是看不见内存地址的。所以你不能让他为 0\n\n1143\n00:57:21,705 --> 00:57:23,906\nthat's hidden from you. So there'd be no way to do it.\n这对你是隐藏的。所以没法这样做\n\n1144\n00:57:23,908 --> 00:57:28,076\nFor an int, if you wanted an optional int, is it minus 1 or\n对于 int，如果你想要一个 optional int\n\n1145\n00:57:28,078 --> 00:57:31,280\n0, max int? What is it, it don't know what it is.\n它到底是 -1？是 0？还是别的什么？他不知道应该是多少。\n\n1146\n00:57:31,282 --> 00:57:34,817\nSo Swift is trying to be consistent across all things.\n所以Swift 想涵盖所有情况\n\n1147\n00:57:34,819 --> 00:57:38,854\nInts, pointers to objects, whatever to make sure that\nInts ，指向对象的指针\n\n1148\n00:57:38,856 --> 00:57:40,456\nwe can tell which ones are not set. Okay, so\n无论是什么，要保证我们能知道他有没有被赋值\n\n1149\n00:57:40,458 --> 00:57:42,591\nthat's the thought behind it. It's really great actually,\n这就是 optional 背后的思考，非常棒\n\n1150\n00:57:42,593 --> 00:57:46,094\nonce you get used to it it's fantastic. All right, so\n一旦你习惯这种做法，真的非常赞\n\n1151\n00:57:46,096 --> 00:57:47,830\nwe unwrap it with this exclamation point.\n我们用感叹号对它进行 unwarp\n\n1152\n00:57:47,832 --> 00:57:51,767\nNow what would happen if that current title value was\n如果这里的 currentTitle 没有被赋值，会发生什么？\n\n1153\n00:57:51,769 --> 00:57:54,903\nnot set? And this exclamation point tried to pull out\n这个感叹号试着去把值取出来\n\n1154\n00:57:54,905 --> 00:57:57,873\nthe associated value? What do you think would happen?\n你觉得会发生什么\n\n1155\n00:57:57,875 --> 00:57:58,674\n>> Error.\n错误\n\n1156\n00:57:58,676 --> 00:58:00,576\n>> Error, yeah, bad error.\n错误，是的大错特错\n\n1157\n00:58:00,578 --> 00:58:02,644\nIt would crash my app, okay? So\n这会让你的应用崩溃\n\n1158\n00:58:02,646 --> 00:58:05,247\nexclamation point crashes your app if you tried to\n如果你试着 unwarp 一个没有被赋值的 optional\n\n1159\n00:58:05,249 --> 00:58:08,750\nunwrap an optional that's in the not set state, okay,\n感叹号会让你的应用崩溃\n\n1160\n00:58:08,752 --> 00:58:12,921\nif it's nil. Now some of you conservative folks might be\n如果它为空。有些保守的人会说\n\n1161\n00:58:12,923 --> 00:58:15,257\nsaying I'm never using exclamation point, that's so\n他从来不用感叹号\n\n1162\n00:58:15,259 --> 00:58:18,927\neasy to crash my app. Okay? And the answer to that is yes\n因为太容易让应用崩溃。但答案是\n\n1163\n00:58:18,929 --> 00:58:22,498\nit is, but sometimes crashing your app is a good thing.\n是的，确实容易让应用崩溃，但有时候这是好事\n\n1164\n00:58:22,500 --> 00:58:23,999\nIt helps you find a bug, okay?\n这会帮助你找到 bug\n\n1165\n00:58:24,001 --> 00:58:26,869\nBecause something that you expect to be set by a certain\n因为有的时候你希望他被赋予一个确定的值\n\n1166\n00:58:26,871 --> 00:58:28,737\npoint isn't, and it crashes your app, and\n如果没有，那就让应用崩溃\n\n1167\n00:58:28,739 --> 00:58:31,206\nyou find it before it goes out to your customer. And some\n你在 app 发布给你的用户之前就找到这个 bug\n\n1168\n00:58:31,208 --> 00:58:33,842\nunexpected thing is happening because something's not set.\n因为有些没被赋值，会发生一些预期之外的事情\n\n1169\n00:58:33,844 --> 00:58:36,311\nNow, I'm gonna show you a little later how you can\n我稍后会给你们展示\n\n1170\n00:58:36,313 --> 00:58:38,046\nunwrap the optional and get the associated value\n如何不让应用崩溃的情况下 unwarp optional 并获取关联值\n\n1171\n00:58:38,048 --> 00:58:41,250\nwithout crashing. Basically, test to see if it's set and\n总的来说，自测一下它有没有被赋值\n\n1172\n00:58:41,252 --> 00:58:44,286\ndo it, okay? So I'm gonna show you that in a little bit.\n我过一会会做给你们看\n\n1173\n00:58:44,421 --> 00:58:45,954\nAll right, so we've unwrapped this, optional.\n我们已经 unwarp 了这个 optional\n\n1174\n00:58:45,956 --> 00:58:49,224\nWe're gonna crash if it's not set, that's fine. And so\n如果没有被赋值会让应用崩溃，这没问题\n\n1175\n00:58:49,226 --> 00:58:52,661\nnow, notice when I do the option click on digit,\n注意我按住 option 键 然后点这个 digit\n\n1176\n00:58:52,663 --> 00:58:57,299\nwhat's the type? String, not optional string,\n什么类型呢？不是 optional string\n\n1177\n00:58:57,301 --> 00:59:00,569\nstring, that's good because we unwrapped it. So now when we\n就是 string，这很棒，因为我们 unwarp 了\n\n1178\n00:59:00,571 --> 00:59:05,240\nrun, instead of saying touched optional 6 digit down there,\n现在跑一下，就不会说 \"touched optional 6 digit\" 了\n\n1179\n00:59:05,242 --> 00:59:10,579\nit's going to say touch the 6 digit, touch 2, touch 4, 8, 9,\n而是说 \"touch the 6 digit\" 或者 \"touch 2、4、8、9\"\n\n1180\n00:59:10,581 --> 00:59:17,019\nokay? Got it? Okay, now, this is going good, but we\n明白了吗？这很棒\n\n1181\n00:59:17,021 --> 00:59:21,123\ndon't really want this to be printing out in the console.\n但我们不想它在控制台打印出来\n\n1182\n00:59:21,125 --> 00:59:23,725\nWe want our calculator to have a display and\n我们希望我们的计算器有个显示\n\n1183\n00:59:23,727 --> 00:59:26,762\nwe want the digits we typed to go in the display, right. So\n我们希望我们按下的 digits 能显示出来\n\n1184\n00:59:26,764 --> 00:59:29,665\nlet's go do that. Let's add a display to our\n所以现在来做这个。加一个显示\n\n1185\n00:59:29,667 --> 00:59:32,534\nuser interface here. We're gonna put it at the top, okay?\n到 UI 上。我们会把这个放在顶部\n\n1186\n00:59:32,536 --> 00:59:35,537\nI'm talking about this thing right up here where this 0 is.\n我指的是这个右上角零的这个\n\n1187\n00:59:35,539 --> 00:59:37,439\nAnd I wanna it to kinda look similar to that,\n我希望看起来很像这个\n\n1188\n00:59:37,441 --> 00:59:39,241\nmaybe some different colors but kinda like that.\n可能是不同颜色，但是类似吧\n\n1189\n00:59:39,243 --> 00:59:44,479\nSo I'm gonna go back to my utilities area over here and\n现在回到组件的区域\n\n1190\n00:59:44,481 --> 00:59:45,547\ngo to the bottom. And this time,\n到最底部，这次\n\n1191\n00:59:45,549 --> 00:59:48,617\ninstead of grabbing a button, I'm gonna grab one of these,\n不是抓一个 button，而是抓一个这个\n\n1192\n00:59:48,619 --> 00:59:52,921\na label. So a label is Read only text,\n一个 label，label 是一个只读的文本\n\n1193\n00:59:52,923 --> 00:59:55,691\nokay? The user can't touch on it, and then type\n用户不能碰这个\n\n1194\n00:59:55,693 --> 00:59:58,527\nwith the little keyboard on the iPhone, okay? This is read\n然后用键盘输入\n\n1195\n00:59:58,529 --> 01:00:01,229\nonly text which is what we want on my calculator. So\n这是一个我们计算器上需要的只读的文本\n\n1196\n01:00:01,231 --> 01:00:04,099\nI'm gonna bring it over here, bring it out, again same way\n我会让它到这里，拖出来\n\n1197\n01:00:04,101 --> 01:00:08,503\nas before. I can resize it, I can change what's in there,\n跟之前一样，我可以重新定义它的大小\n\n1198\n01:00:08,505 --> 01:00:11,273\nI can change the font over here. Let's make this one\n可以改变文字。现在让它字变大\n\n1199\n01:00:11,275 --> 01:00:15,978\nreally big, how about 40 point. I can even make it\n差不多 40pt 吧。我还可以让它右对齐\n\n1200\n01:00:15,980 --> 01:00:18,747\nright aligned, you know how in calculators usually\n你知道一般计算器都是右对齐\n\n1201\n01:00:18,749 --> 01:00:21,316\nthe text is on the right so there's an alignment thing for\n这里有个 label 对齐选项\n\n1202\n01:00:21,318 --> 01:00:23,952\nthe label here, so we'll do that. Maybe I want to change\n我们可以这么做。\n\n1203\n01:00:23,954 --> 01:00:27,189\nthe background color for this one too, how about blue, okay\n我也想换一下背景颜色，蓝色就不错\n\n1204\n01:00:27,191 --> 01:00:30,158\nthere's blue. I don't really like black on blue, here's\n但我不喜欢蓝底黑字\n\n1205\n01:00:30,160 --> 01:00:33,829\na color of the text, we'll go white on blue. Okay, so\n这里是文字颜色，蓝底白字就挺好\n\n1206\n01:00:33,831 --> 01:00:37,099\nI can basically set it however I want, okay, got this UI,\n我可以随意设置这些\n\n1207\n01:00:37,101 --> 01:00:39,001\nI could use the blue lines by the way,\n也可以用蓝线辅助\n\n1208\n01:00:39,003 --> 01:00:43,405\nto line it up nicely here, but again not so important because\n这样就可以很整齐的放置\n\n1209\n01:00:43,407 --> 01:00:46,742\nI'm going to do the flexible UI thing on Wednesday, but\n不是特别重要的是，我会在周三教自适应的 UI 布局\n\n1210\n01:00:46,744 --> 01:00:51,780\nI could do it. All right, so now, how about connecting this\n我可以做这些。\n\n1211\n01:00:51,782 --> 01:00:55,050\nto our controller? This is a little different because this\n那么如何把这个 label 跟 controller 联系起来？\n\n1212\n01:00:55,052 --> 01:00:58,220\nis not a case where the user's gonna touch this thing and\n这有点不太一样，因为这不是那种用户点一下\n\n1213\n01:00:58,222 --> 01:00:58,887\nit's gonna invoke a method.\n就调用一个方法的情况\n\n1214\n01:00:58,889 --> 01:01:02,524\nIt's more the other way around. I wanna talk to it.\n这是另外一种情况，我想跟它交互\n\n1215\n01:01:02,526 --> 01:01:04,359\nOkay, I wanna put things in the display.\n我想把东西放进去展示\n\n1216\n01:01:04,361 --> 01:01:07,863\nSo this is communication coming from the controller to\n这是一个从 controller 到显示的通信\n\n1217\n01:01:07,865 --> 01:01:11,500\nthe display instead of from a button to the controller. So\n而不是一个按钮到 controller 的通信\n\n1218\n01:01:11,502 --> 01:01:15,771\nwe still connect them up in the same way using control and\n我们还是一样用按住 control 拖拽的方式\n\n1219\n01:01:15,773 --> 01:01:20,275\ndrag, okay, to put something into our controller. But\n把一些东西放进 controller\n\n1220\n01:01:20,277 --> 01:01:24,179\nthis time instead of action up here we're going to do outlet.\n但这次我们选 outlet 而不是 action\n\n1221\n01:01:24,181 --> 01:01:27,149\nAnd what outlet means is instead of creating a method,\noutlet 的意思是新建一个属性\n\n1222\n01:01:27,151 --> 01:01:30,285\ncreate a property. Right? An instance variable,\n而不是方法。一个实例变量\n\n1223\n01:01:30,287 --> 01:01:32,721\njust like currentTitle is an instance variable, or\n就像 currentTitle 是一个实例变量\n\n1224\n01:01:32,723 --> 01:01:34,256\nproperty, we're gonna have a property here.\n或者一个属性，这里我们有了一个属性\n\n1225\n01:01:34,258 --> 01:01:36,992\nAnd this property is going to point to this display for\n这个属性会指向显示屏\n\n1226\n01:01:36,994 --> 01:01:39,628\nus so we can access it any time we want. So\n这样我们就可以在任何需要的时候获取它\n\n1227\n01:01:39,630 --> 01:01:44,299\nI'm gonna call this property display, not that, display,\n我准备叫这个属性 display\n\n1228\n01:01:44,301 --> 01:01:47,469\nokay? Luckily it got the type right here, it didn't say any\n碰巧这里有类型，这没说有任何对象\n\n1229\n01:01:47,471 --> 01:01:50,338\nobjects. It's good, it knows it was a UI label. And don't\n这很好，它知道是个 UILabel\n\n1230\n01:01:50,340 --> 01:01:52,974\nworry about this storage, weak or strong, we'll talk about\n也不用担心这个 storage 是 strong 或是 weak\n\n1231\n01:01:52,976 --> 01:01:55,043\nthat next week, so you can just ignore that for now.\n我们下周再说，所以你现在就可以忽略他\n\n1232\n01:01:55,045 --> 01:01:58,213\nOkay, so I hit connect and it creates,\n我点击 connect，它就被创建了\n\n1233\n01:01:58,215 --> 01:02:02,250\ninstead of creating a method here, it created a property.\n这里创建了一个属性而不是一个方法\n\n1234\n01:02:02,252 --> 01:02:06,722\nNow again, this IB outlet is just something that Xcode puts,\n再一次，这个 IBOutlet 只是 Xcode 放这的。\n\n1235\n01:02:06,724 --> 01:02:07,989\nput this little circle here. So\n放了一个小圆圈在这里\n\n1236\n01:02:07,991 --> 01:02:11,159\nwe can see what it's connected to, so you can ignore that.\n我们可以看到这个链接到了什么，所以你可以忽略那个\n\n1237\n01:02:11,161 --> 01:02:12,060\nI told you to ignore weak and\n我说了可以忽略 weak 和 strong\n\n1238\n01:02:12,062 --> 01:02:14,730\nstrong, so you can ignore that. And so hopefully\n所以可以忽略它\n\n1239\n01:02:14,732 --> 01:02:18,533\nthis is familiar to you, it looks like current title, var.\n这个看起来很熟悉，有点像 currentTitle\n\n1240\n01:02:18,535 --> 01:02:21,636\nThis is a property on our controller. Okay,\n这是你 controller 里的一个属性\n\n1241\n01:02:21,638 --> 01:02:24,005\nan instance variable, if you wanna think of it that way.\n一个实例变量，如果你想这么认为的话\n\n1242\n01:02:24,007 --> 01:02:29,544\nIt's called display. Its type is UI label exclamation point.\n这叫 display。类型是 UILabel!\n\n1243\n01:02:29,546 --> 01:02:33,648\nOkay, now what the heck is that, exclamation point? Okay,\n这里的感叹号又是什么意思呢？\n\n1244\n01:02:33,650 --> 01:02:35,784\nI thought exclamation point was unwrapping optionals,\n我认为感叹号是用来 unwrapping optional 的\n\n1245\n01:02:35,786 --> 01:02:38,153\nwhy is there an exclamation point here, it makes no sense.\n这里为什么有个感叹号？这不科学。\n\n1246\n01:02:38,155 --> 01:02:42,424\nAnd in fact you can put a question mark here because\n事实上你可以在这里放个问号\n\n1247\n01:02:42,426 --> 01:02:44,860\nexclamation point also means optional.\n因为感叹号也代表了 optional\n\n1248\n01:02:44,862 --> 01:02:47,329\nIt means the same kinda optional as question mark.\n这跟问号表示的 optional 是一个意思\n\n1249\n01:02:47,331 --> 01:02:48,830\nAnd I'm gonna leave this question mark, and\n我会先在这放一个问号\n\n1250\n01:02:48,832 --> 01:02:50,599\nI'm gonna keep working on this demo, and\n继续完成这个 demo\n\n1251\n01:02:50,601 --> 01:02:51,099\nthen I'm gonna go back and\n然后回过头来\n\n1252\n01:02:51,101 --> 01:02:52,167\nchange it to an exclamation point, and\n把它改成感叹号\n\n1253\n01:02:52,169 --> 01:02:55,604\nshow you what exclamation point means. Okay? But\n告诉你们感叹号是什么意思。\n\n1254\n01:02:55,606 --> 01:02:58,073\nexclamation point and question mark both mean optional,\n当你定义的时候，\n\n1255\n01:02:58,075 --> 01:03:02,744\nwhen you're declaring. Okay, so now I have this display.\n感叹号和问号都表示 optional。所以现在你有了这个 display\n\n1256\n01:03:02,746 --> 01:03:06,515\nWhen numbers get touched here, I want to, basically, append\n当数字被按下的时候，我想\n\n1257\n01:03:06,517 --> 01:03:09,684\nthese digits onto whatever's already in the display,\n不管显示了什么都把 digit 加到 display 上\n\n1258\n01:03:09,686 --> 01:03:12,287\nall right? So let's go ahead and do that.\n所以现在来做这个\n\n1259\n01:03:12,289 --> 01:03:14,556\nWe can get rid of this print to the console.\n删掉这个打印到控制台的\n\n1260\n01:03:14,558 --> 01:03:16,658\nWe don't need to do that anymore. So I'm gonna create\n我们不再需要它\n\n1261\n01:03:16,660 --> 01:03:19,294\nanother local variable which is also gonna be a constant,\n我需要再新建一个局部变量，当然也是个常量\n\n1262\n01:03:19,296 --> 01:03:24,366\nso it's let. I'm gonna call it textCurrentlyInDisplay, okay?\n所以是let 。我叫它 textCurrentlyInDisplay\n\n1263\n01:03:24,368 --> 01:03:28,904\nSo I wanna get the text that's in this display currently. So\n我想获得现在 display 里的字符\n\n1264\n01:03:28,906 --> 01:03:33,241\nI'm going to send a message to display here, right? Display.\n我要在这给 display 发一个消息\n\n1265\n01:03:33,243 --> 01:03:35,377\nAnd the message, we can look it up in the documentation.\n这个信息，我们可以从文档中得知\n\n1266\n01:03:35,379 --> 01:03:37,913\nBut the message that I want to send is text. Okay?\n但是我想发的消息是文字\n\n1267\n01:03:37,915 --> 01:03:41,416\nThat gives me the text in the display. This is a UI label\n这会给我 display 里的文字。这是个 UILabel 方法\n\n1268\n01:03:41,418 --> 01:03:45,453\nmethod. But this is giving me an error. Okay, and\n但这里却告诉我是个错误\n\n1269\n01:03:45,455 --> 01:03:48,690\nthe error that it's giving me here is that I haven't\n这个错误说我这里没有 unwarp display\n\n1270\n01:03:48,692 --> 01:03:51,927\nunwrapped display. You see that display is an optional\n你看 display 是个 optional label\n\n1271\n01:03:51,929 --> 01:03:55,730\nlabel. You can't send text to the type optional Okay, and\n你不能把一个 text 赋给一个 optional\n\n1272\n01:03:55,732 --> 01:03:58,633\noptional doesn't understand the message text.\n optional 不理解什么是文字\n\n1273\n01:03:58,635 --> 01:04:02,003\nUILabel does. So, we need to get that associated value\n但 UILabel 知道。所以我们要获得 display 的 label 的关联值\n\n1274\n01:04:02,005 --> 01:04:05,207\nof label, of a display, which is the UILabel, and\n是一个 UILabel\n\n1275\n01:04:05,209 --> 01:04:07,843\nwe do that with the exclamation point, here.\n我们会在这放一个感叹号\n\n1276\n01:04:07,845 --> 01:04:10,645\nAnd, again, notice it's offering, here, to fix it. So,\n注意这里，提供了修复选项\n\n1277\n01:04:10,647 --> 01:04:13,515\nI'm gonna fix it, and i put the exclamation point in\n所以我来修复他，就会放一个感叹号在这\n\n1278\n01:04:13,517 --> 01:04:17,752\nthere. Now, this is a UILabel. It's an unwrapped,\n现在这里是个 UILabel，这一个 unwarpped\n\n1279\n01:04:17,754 --> 01:04:20,589\noptional UILabel, right? This is a UILabel,\noptional UILabel，对吗？这是一个 UILabel\n\n1280\n01:04:20,591 --> 01:04:22,624\nand I'm sending it the message text,\n我把那个文字值发给他\n\n1281\n01:04:22,626 --> 01:04:24,626\nactually text is a property, just like currentTitle\n实际上 text 是个属性， 就像 currentTitle\n\n1282\n01:04:24,628 --> 01:04:29,030\nis a property on button, text is a property on UILabel. And,\n是一个 button 的属性，text 是 UILabel 的一个属性\n\n1283\n01:04:29,032 --> 01:04:33,001\nin fact, if I option+click on it, you'll see var text is an\n如果我按住 option 点它，你可以看见 var text\n\n1284\n01:04:33,003 --> 01:04:37,806\noptional string. Why? Because UILabel might be not set.\n是一个 optional string。为什么？因为 UILabel 可能没有被赋值\n\n1285\n01:04:37,808 --> 01:04:40,275\nThe text in it might not be set. So it also is an option,\n它里面的 text 可能没有被赋值，所以这也是个 optional\n\n1286\n01:04:40,277 --> 01:04:45,647\njust like currentTitle. So I need to unwrap that as well.\n就像 currentTitle 一样，我需要同样需要 unwarp\n\n1287\n01:04:46,316 --> 01:04:48,950\nOkay? And so now I have a string,\n所以我现在有个 string\n\n1288\n01:04:48,952 --> 01:04:51,052\nwhich is the string that's in there. Now you're probably\n就是这里这个\n\n1289\n01:04:51,054 --> 01:04:52,654\ngetting tired of these exclamation points and so\n现在你可能对这个感叹号感到有点疲惫，我也是\n\n1290\n01:04:52,656 --> 01:04:54,422\nam I, and we're gonna be able to get rid of them.\n我们将要去掉它\n\n1291\n01:04:54,424 --> 01:04:56,358\nSome in a second here, so not to worry.\n一会就去掉，不用担心\n\n1292\n01:04:56,360 --> 01:04:58,693\nAnyway, I have this text currently in display.\n不管怎样，我现在在 display 里拿到了这个文字\n\n1293\n01:04:58,695 --> 01:05:02,697\nSo now I'm just gonna say that the displays, okay, and\n所以现在，display\n\n1294\n01:05:02,699 --> 01:05:07,002\nI'm unwrapping it, text = textCurrentlyInDisplay. I'm\nunwarp 它，\"text ＝ textCurrentlyInDisplay\"\n\n1295\n01:05:07,004 --> 01:05:11,706\njust hitting tab here, okay, + the digit that was pressed.\n我在这按了 tab 键，然后代码写 \"＋ digit\"\n\n1296\n01:05:11,708 --> 01:05:14,809\nOkay, notice that you can use + to concatenate strings.\n注意你用加号来串联字符\n\n1297\n01:05:14,811 --> 01:05:17,913\nThat's really fun. Okay, some language allow that, some not.\n这很有趣，有的语言允许这么做，有的不允许\n\n1298\n01:05:17,915 --> 01:05:21,816\nSo it does. Notice also that when I'm setting the value of\nSwift 可以。同时注意我在给 optional 赋值的时候\n\n1299\n01:05:21,818 --> 01:05:25,120\nan optional, remember text here is an optional string.\n记住这里的 text 是个 optional string\n\n1300\n01:05:25,122 --> 01:05:28,123\nI can set it to be a string, and that means,\n我可以把它赋值为 string，这意味着\n\n1301\n01:05:28,125 --> 01:05:32,294\nby definition, set this optional to set and\n根据定义，是赋值给 optional 来设定\n\n1302\n01:05:32,296 --> 01:05:37,332\nuse this as its associated value. Right? Now,\n把它赋为这个的关联变量\n\n1303\n01:05:37,334 --> 01:05:41,736\nhow do you think I would set this optional to not be set?\n那么你认为我怎么才能给这个 optional 赋一个不赋值的状态？\n\n1304\n01:05:41,738 --> 01:05:45,206\nAnyone know? You would say,\n有人知道吗？\n\n1305\n01:05:45,208 --> 01:05:49,878\nset this thing to be nil. This keyword means opp,\n把它赋值为 nil，这个关键字\n\n1306\n01:05:49,880 --> 01:05:52,781\noptional not set. So that would set this text.\n表示 optional 没有被赋值。所以会赋这个值\n\n1307\n01:05:52,783 --> 01:05:56,051\nIt would blank out this text. It would set it to be not set.\n这个栏里为空，这会把它赋为没有被赋值\n\n1308\n01:05:56,053 --> 01:05:58,119\nOkay, so an optional you can, when you're setting it,\n所以一个 optional，在你给它赋值的时候\n\n1309\n01:05:58,121 --> 01:06:02,190\nyou can set it to either nil or to an associated value.\n你可以把它赋为 nil 或者是 关联值\n\n1310\n01:06:03,060 --> 01:06:06,261\nOkay? Sound good? So let's run.\n听起来不错？让我继续\n\n1311\n01:06:11,435 --> 01:06:13,401\nAll right, so hopefully when we press these buttons,\n所以，理想情况下当我们按下按钮\n\n1312\n01:06:13,403 --> 01:06:15,971\nit's going to append it on to the end, here. So let's try\n数字就会被加到末尾\n\n1313\n01:06:15,973 --> 01:06:20,976\nfive, it did it. Eight, nine, although I'm not really a fan\n5，它做到了。8，9，但是我不喜欢\n\n1314\n01:06:20,978 --> 01:06:25,313\nof a zero at the beginning there. Okay, that zero is not\n前面有个 0.所以\n\n1315\n01:06:25,315 --> 01:06:27,849\nreally how a calculator would work. Okay, when I press that\n这不是一个计算器应该有的样子。当我按五的时候\n\n1316\n01:06:27,851 --> 01:06:30,452\nfive, I'm essentially typing a new number. It would get rid\n实际上我是按了一个新数字。\n\n1317\n01:06:30,454 --> 01:06:33,021\nof the zero. So, we really need a way to keep track of\n它应该取代 0。所以需要一个方法\n\n1318\n01:06:33,023 --> 01:06:35,757\nwhether we're in the middle of typing a number or not. Cuz if\n来追踪我们是不是在输入中\n\n1319\n01:06:35,759 --> 01:06:37,425\nwe're in the middle of typing a number,\n因为如果我们在输入中\n\n1320\n01:06:37,427 --> 01:06:37,926\nwe do the apend thing, but\n那就得把数字加到尾部\n\n1321\n01:06:37,928 --> 01:06:39,260\nif we're not in the middle of typing a number,\n如果不是\n\n1322\n01:06:39,262 --> 01:06:42,163\nthen we just replace whatever is in that display, right? So,\n那就把之前的数字替换掉，对吗？\n\n1323\n01:06:42,165 --> 01:06:46,368\nI'm going to add a new var, okay, a new instance variable,\n我要加一个变量，实例变量\n\n1324\n01:06:46,370 --> 01:06:47,769\na new property, called,\n一个新的属性\n\n1325\n01:06:47,771 --> 01:06:51,706\nuserIsInTheMiddleOfTyping. >> [LAUGH]\n叫做 userIsInTheMiddleOfTyping（笑\n\n1326\n01:06:51,708 --> 01:06:52,474\n>> Okay, now you laugh,\n我知道你们为什么笑\n\n1327\n01:06:52,476 --> 01:06:54,609\nyou laugh because that seems like a lot of typing, but\n你们笑是因为这个变量名字太长了\n\n1328\n01:06:54,611 --> 01:06:57,479\nI will never have to type that again. Okay?\n但我不会再做第二遍\n\n1329\n01:06:57,481 --> 01:06:59,948\nBecause Xcode is always gonna escape complete things for\n因为 Xcode 总会帮我自动补全\n\n1330\n01:06:59,950 --> 01:07:02,751\nme. So, long names like that are actually good.\n所以长变量名挺好的\n\n1331\n01:07:02,753 --> 01:07:05,286\nOkay, you wanna pick the shortest name that, you know,\n你可以选一个短一点的名字\n\n1332\n01:07:05,288 --> 01:07:08,123\nit conveys what you want but you want your names,\n这名字要能体现出你想要什么\n\n1333\n01:07:08,125 --> 01:07:10,258\nas you know in computer science naming is everything,\n计算机科学里命名就是一切，你懂的\n\n1334\n01:07:10,260 --> 01:07:14,429\nyou want your names to be very, very, very good for\n你希望你的命名对读你代码的人\n\n1335\n01:07:14,431 --> 01:07:17,432\nthe reader to understand what's going on, okay? Now,\n非常非常非常的好理解\n\n1336\n01:07:17,434 --> 01:07:20,702\nthis userIsInTheMiddleOfTyping is a Bool, okay?\nuserIsInTheMiddleOfTyping 是个 Bool\n\n1337\n01:07:20,704 --> 01:07:21,603\nSo, I'm giving you it's type,\n我给它一个 Bool 类型\n\n1338\n01:07:21,605 --> 01:07:23,905\nBool. It's not an optional Bool. It's just a Bool. So\n这不是个 optional Bool，就是个 Bool\n\n1339\n01:07:23,907 --> 01:07:27,442\nno question mark here. Okay, it's either true or false.\n所以这里没有问候，这里无论 true 还是 false\n\n1340\n01:07:27,444 --> 01:07:28,777\nI'm either in the middle of typing or I'm not.\n我不是在输入中或没输入\n\n1341\n01:07:28,779 --> 01:07:32,313\nNow as soon as I put that in there I got an error.\n一旦我把这些放在这，就报错了\n\n1342\n01:07:32,315 --> 01:07:34,282\nSee that error up there? What? That's not fair.\n看到上面那个报错符合了吗？这不科学啊\n\n1343\n01:07:34,284 --> 01:07:38,753\nI didn't do anything up there. What is that? Let's click it.\n我在上面什么都没做啊，那是什么？点一下看看\n\n1344\n01:07:38,755 --> 01:07:41,456\nClass ViewController has no initializers.\nClass ViewController has no initializers\n\n1345\n01:07:41,458 --> 01:07:43,725\nOkay, now you're doing your homework and you're like,\n这里如果你们正在做作业\n\n1346\n01:07:43,727 --> 01:07:46,161\nwhat the, there's nothing to do, what I just did.\n你会发现，我们什么都没做\n\n1347\n01:07:46,163 --> 01:07:48,496\nI just typed in var here, what does that mean? Okay,\n我只是刚才声明了一个变量，这是什么意思？\n\n1348\n01:07:48,498 --> 01:07:51,366\nwell the reason you're getting that error is cuz in Swift,\n你在这报错的原因是\n\n1349\n01:07:51,368 --> 01:07:55,336\nall properties, every single one, have to have an initial\n在 Swift 里，所以的属性，每一个，都必须有一个初始化的值\n\n1350\n01:07:55,338 --> 01:07:59,340\nvalue. There's no, you are not allowed to have\n如果你不这么做\n\n1351\n01:07:59,342 --> 01:08:02,710\nany properties that don't have an initial value. Okay?\n就不能有一个未初始化的变量\n\n1352\n01:08:02,712 --> 01:08:04,612\nSo how do we give this thing an initial value?\n所以我们怎么给它一个初始值？\n\n1353\n01:08:04,614 --> 01:08:07,715\nWell, there's two ways. One, we create an initializer.\n有两种方式，一种，对它进行初始化\n\n1354\n01:08:07,717 --> 01:08:08,683\nThat's why you're getting this warning.\n这就是为什么会报错\n\n1355\n01:08:08,685 --> 01:08:11,486\nNow I'm not gonna talk about initializers til next week. So\n但下周前我不会讲怎么初始化\n\n1356\n01:08:11,488 --> 01:08:13,822\nwe can't do that because I'm not gonna talk about it yet,\n所以我们不能做，因为我还没讲\n\n1357\n01:08:13,824 --> 01:08:16,324\nokay? What's the other way that we can do it?\n所以另一种是什么方式呢？\n\n1358\n01:08:16,326 --> 01:08:21,729\nWe can just say = false. Okay, so we just initialize that,\n我们直接给它赋一个 false 值，我们这就对它初始化了\n\n1359\n01:08:21,731 --> 01:08:24,933\nand the write error goes away. Woo hoo, were winning, and\n那个报错就消失了～\n\n1360\n01:08:24,935 --> 01:08:26,067\nI know some of you are saying, yeah,\n我知道你们可能会说\n\n1361\n01:08:26,069 --> 01:08:30,839\nwhat about this one? Okay, you didn't initialize that. Okay,\n那么这个呢？你没对它初始化啊\n\n1362\n01:08:30,841 --> 01:08:33,741\nthat's because optionals are treated specially.\n因为 optional 是很特殊的\n\n1363\n01:08:33,743 --> 01:08:39,047\nThey are always automatically initialized to not set.\n他们会自动被初始化为空\n\n1364\n01:08:39,049 --> 01:08:42,550\nOkay? So this is basically always happening\n这就是你申明一个 optional 的时候会发生的\n\n1365\n01:08:42,552 --> 01:08:44,686\nwhen you have an optional, or var that's an optional.\n或者是一个 var 的 optional\n\n1366\n01:08:44,688 --> 01:08:46,287\nWhich makes sense, right? You have an optional.\n能理解吗？你有一个 optional\n\n1367\n01:08:46,289 --> 01:08:47,589\nIt's not set until you set it to something.\n它没有被赋值，直到你给它赋一个值\n\n1368\n01:08:47,591 --> 01:08:51,960\nSo it starts out not set. Okay, so that's why it is set.\n所以它会以没有赋值开始。这就是为什么它被赋值了\n\n1369\n01:08:51,962 --> 01:08:55,630\nIt's set to not set. Okay? All right, so\n它被赋值为没有赋值\n\n1370\n01:08:55,632 --> 01:08:57,665\nwe have this thing now, we have this. Let's go ahead and\n所以我们现在有了这个，继续\n\n1371\n01:08:57,667 --> 01:09:00,635\nuse this thing we created. Actually, I'm going to do one\n所有现在用我们刚刚创建的这个\n\n1372\n01:09:00,637 --> 01:09:05,940\nmore thing here. You see this : Bool? Do we need that? No.\n我还要在这多做一件事。: Bool 我们真的需要这个吗？不\n\n1373\n01:09:05,942 --> 01:09:09,611\nOkay, why don't we need that? Because false can only be\n为什么我们不需要这个呢？\n\n1374\n01:09:09,613 --> 01:09:15,750\na Bool, so Swift can infer that the type of this is Bool.\n因为false 只能是个Bool 型。所以Swift 可以推导它就是个Bool 型\n\n1375\n01:09:15,886 --> 01:09:19,821\nSee that? Okay? All right. So, we have this\n看到了吗？所以我们现在有了 userIsInTheMiddleOfTyping\n\n1376\n01:09:19,823 --> 01:09:23,057\nuserIsInTheMiddleOfTyping. We only wanna do this business\n我们只想它处理\n\n1377\n01:09:23,059 --> 01:09:25,493\nright here if the user is in the middle of typing.\n用户是不是正在输入中的问题\n\n1378\n01:09:25,495 --> 01:09:26,995\nSo now we're gonna see in if statement.\n所以我接下来输入\n\n1379\n01:09:26,997 --> 01:09:28,263\nIf the user is in the middle of typing,\nIf userIsInTheMiddleOfTyping\n\n1380\n01:09:28,265 --> 01:09:31,232\nnow again, I'm just hitting Tab here. Look Mom, no hands,\n我按下 Tab 键，这一串就输入好了。\n\n1381\n01:09:31,234 --> 01:09:34,302\nor one hand. If the user is in the middle of typing,\nIf userIsInTheMiddleOfTyping\n\n1382\n01:09:34,304 --> 01:09:36,938\nthen we're gonna do this thing. Okay.\n然后我们做这些\n\n1383\n01:09:36,940 --> 01:09:40,742\nIf the user's not in the middle of typing,\n如果用户不是在输入中\n\n1384\n01:09:40,744 --> 01:09:43,378\nthen we're gonna set the displays text\n那么就让 display 的文本\n\n1385\n01:09:43,380 --> 01:09:46,481\nequal to the digit we just typed. Okay, the five, or\n等于 digit 的数字。比如 5，或者别的什么\n\n1386\n01:09:46,483 --> 01:09:49,417\nwhatever, we're gonna replace what's in the display. And,\n我们会替换 display 里的文本\n\n1387\n01:09:49,419 --> 01:09:52,921\nof course, in either case, the user is definitely, no long,\n当然，另一种情况，用户\n\n1388\n01:09:52,923 --> 01:09:56,024\nis definitely, now, in the middle of typing. Okay,\n一定是在输入中\n\n1389\n01:09:56,026 --> 01:09:59,561\ncuz you just touched a digit, we're clearly in the middle of\n因为你刚刚按了输入按钮，我们显然是在输入中\n\n1390\n01:09:59,563 --> 01:10:03,097\ntyping. Now I'm getting pretty tired of typing display\n我现在真的对每次都\n\n1391\n01:10:03,099 --> 01:10:05,466\nexclamation point all the time, okay?\n输入display! 感到疲惫\n\n1392\n01:10:05,468 --> 01:10:08,303\nAll the time typing display exclamation point, when in\n每次都输入 display! ，实际上\n\n1393\n01:10:08,305 --> 01:10:12,307\nfact, I know that that display is pretty much always set.\n我知道 display 一定是被赋值的状态\n\n1394\n01:10:12,309 --> 01:10:14,776\nOkay, the only time that this is not set is for\n它唯一没被赋值的时间就是\n\n1395\n01:10:14,778 --> 01:10:18,546\na nanosecond when this starts to come on screen,\n当他一出现在屏幕上的时候\n\n1396\n01:10:18,548 --> 01:10:22,650\nbefore iOS has a chance to wire it up to this UILabel.\n在 iOS 把他变成 UILabel 类型之前\n\n1397\n01:10:22,652 --> 01:10:25,119\nBut once it's wired up, it's set forever. And\n一旦他被连接上，那就永远被赋值了\n\n1398\n01:10:25,121 --> 01:10:27,589\ncertainly by the time users are touching on digits,\n而且很确定的是，当用户点在数字上时\n\n1399\n01:10:27,591 --> 01:10:31,226\nthe UIs completely on screen, and wired up, and so I know\nUI 已经在屏幕上创建好、链接好了，\n\n1400\n01:10:31,228 --> 01:10:36,097\nthat's never going to be nil. Never, okay, in this code. So\n所以我知道它用不会为空\n\n1401\n01:10:36,099 --> 01:10:38,199\nwhy am I forced to type display, exclamation point,\n所以我为什么非要\n\n1402\n01:10:38,201 --> 01:10:39,801\ndisplay, exclamation point, over and over, okay?\n重复输入 display! 呢？\n\n1403\n01:10:39,803 --> 01:10:42,670\nAnd the answer is you don't have to because we're\n答案是你不需要，\n\n1404\n01:10:42,672 --> 01:10:46,007\ngonna go back and change this question mark to be\n我们只要把一开始这个问号\n\n1405\n01:10:46,009 --> 01:10:48,910\nexclamation point. Basically if you put the exclamation\n改成感叹号。总的来说，\n\n1406\n01:10:48,912 --> 01:10:53,481\npoint where you declare it, it says that anyone can use\n在你定义的时候放个感叹号，就表示所有对象都可以用这个\n\n1407\n01:10:53,483 --> 01:10:57,252\nthis thing, and it will implicitly unwrap it, okay?\n就 implicitly unwarp（注：隐式解包）了这个对象\n\n1408\n01:10:57,254 --> 01:10:57,986\nIt will automatically unwrap it.\n这就会自动 unwarp\n\n1409\n01:10:57,988 --> 01:10:59,988\nNow its still unwrapping it, so if that was nil,\n现在它还是会 unwarp，如果他是 nil\n\n1410\n01:10:59,990 --> 01:11:04,292\nit will still crash, okay? But it allows me to get rid of all\n它还是会让你的应用崩溃。但是它允许我\n\n1411\n01:11:04,294 --> 01:11:08,529\nof these exclamation points. Okay? Because it's implicit\n去掉这里所有的感叹号\n\n1412\n01:11:08,531 --> 01:11:10,365\nthat there's an exclamation point on all of them,\n因为这里的感叹号 implicit unwarp（隐式解包）了所有的对象\n\n1413\n01:11:10,367 --> 01:11:12,200\nbecause instead of putting a question mark here,\n因为我在这放了个感叹号\n\n1414\n01:11:12,202 --> 01:11:13,468\nI put the exclamation point up there.\n而不是问号\n\n1415\n01:11:13,470 --> 01:11:15,837\nEveryone got that? >> [INAUDIBLE].\n都懂了吗\n\n1416\n01:11:15,839 --> 01:11:16,471\n>> It would crash down here,\n可能会在下面这里崩溃\n\n1417\n01:11:16,473 --> 01:11:18,906\nin this code down here. As soon as you access this,\n这一块代码，一旦你跑到这\n\n1418\n01:11:18,908 --> 01:11:21,709\nif that were nil, boom, it would be unwrapping it,\n如果是个 nil，就会 unwarp\n\n1419\n01:11:21,711 --> 01:11:24,445\ncuz it's implicitly unwrapped >> And again,\n因为它 implicitly unwarp 了\n\n1420\n01:11:24,447 --> 01:11:25,980\nif I change this back to a question mark,\n如果我把它改回问号\n\n1421\n01:11:25,982 --> 01:11:28,416\nnow I'm gonna get all kinds of warnings down here.\n现在就会出现好多警告、错误\n\n1422\n01:11:28,418 --> 01:11:30,485\nSee errors, because I'm not unwrapping it, but\n因为我没有 unwarp 它\n\n1423\n01:11:30,487 --> 01:11:31,719\nif I put the exclamation point,\n如果我在这放一个感叹号\n\n1424\n01:11:31,721 --> 01:11:33,821\nnow I'm in implicitly unwrapping it everywhere.\n这样我就在所有地方 implicitly unwarp 了\n\n1425\n01:11:33,823 --> 01:11:36,658\nOkay, that's called an implicitly unwrap optional.\n这样就可以叫它 implicitly unwarp 的 optional\n\n1426\n01:11:36,660 --> 01:11:39,694\nVery important,\n非常重要\n\n1427\n01:11:39,696 --> 01:11:43,765\nOkay, so now let's go see if that fixed everything?\n我们现在看看它是不是修复了所有问题\n\n1428\n01:11:47,404 --> 01:11:47,602\n>> All right, so\n所以\n\n1429\n01:11:47,604 --> 01:11:48,536\nnow hopefully when we press five,\n当我们按下5\n\n1430\n01:11:48,538 --> 01:11:50,772\nit will get rid of the zero. Five. There it is, and\n就会去掉 0 显示 5\n\n1431\n01:11:50,774 --> 01:11:53,808\nthis is still working. Okay? So that's good. We're\n我们做的很好\n\n1432\n01:11:53,810 --> 01:11:56,778\ndoing great. Our keyboard is basically fully functional at\n这下我们的键盘功能完全了\n\n1433\n01:11:56,780 --> 01:11:59,147\nthis point. So now we want to add a,\n现在要加一个操作\n\n1434\n01:11:59,149 --> 01:12:02,216\nan operation. Now, because of our technical thing,\n因为技术上的原因\n\n1435\n01:12:02,218 --> 01:12:04,319\nwe're running out of time, but I have 3 minutes left.\n我们快没时间了，但还有三分钟\n\n1436\n01:12:04,321 --> 01:12:07,021\nI'm gonna add the pi button. Okay, pi is a very\n我要加一个 π 按钮\n\n1437\n01:12:07,023 --> 01:12:10,024\nsimple operation. It's just gonna put pi in the display.\nπ 是个很简单的操作。只是放个 π 在 display 上\n\n1438\n01:12:10,026 --> 01:12:13,461\nSo let's do that. I'm gonna do that by taking the 7 button\n来做这个吧。我要选中 7 这个按钮\n\n1439\n01:12:13,463 --> 01:12:14,362\nand copying and pasting it.\n复制粘贴它\n\n1440\n01:12:14,364 --> 01:12:17,665\nThat's a really bad idea, as you'll see in a moment. But,\n现在看来这很不好\n\n1441\n01:12:17,667 --> 01:12:20,768\nI'm just going to do that and call it pi, okay? Now,\n但我就这么做了，叫它 π\n\n1442\n01:12:20,770 --> 01:12:24,706\nof course, pi is not a digit button, it's an operation, so\n当然，π 不是个数字，是一个操作\n\n1443\n01:12:24,708 --> 01:12:30,044\nI'm going to Ctrl drag down here to create another action,\n我要按住 ctrl 键拖到这里，创建另外一个 action\n\n1444\n01:12:30,046 --> 01:12:30,878\na different action.\n一个不同的 action\n\n1445\n01:12:30,880 --> 01:12:34,082\nThis action is performOperation because pi\n这是个 performOperation 因为 π 是个操作\n\n1446\n01:12:34,084 --> 01:12:36,517\nis an operation. I'm gonna have all my operation buttons\n我会把所有操作的按钮叫做 performOperation\n\n1447\n01:12:36,519 --> 01:12:39,721\ncalled performOperation. And of course I'm not gonna forget\n当然我不会忘了\n\n1448\n01:12:39,723 --> 01:12:41,289\nto change that to UI button, okay,\n把它换成 UIButton\n\n1449\n01:12:41,291 --> 01:12:43,491\neither are you on your homework, right? Okay?\n你们做作业的时候也别忘了\n\n1450\n01:12:43,493 --> 01:12:47,095\nAnd here it is, so there's perform operation right there,\n所以 performOperation 就在这了\n\n1451\n01:12:47,097 --> 01:12:50,064\nokay. And perform operation, I'm gonna do the exact same\n对 performOperation 我要做跟\n\n1452\n01:12:50,066 --> 01:12:52,734\nthing that I did at the beginning of touch digit,\n之前按 digit 一样的事情\n\n1453\n01:12:52,736 --> 01:12:55,002\nwhich is I'm gonna ask the sender which\n要问 sender\n\n1454\n01:12:55,004 --> 01:13:00,208\noperation are you? So I'm gonna let mathematicalSymbol =\n你是哪个操作\n\n1455\n01:13:00,210 --> 01:13:05,580\nthe sender.currentTitle. Now of course\nlet mathematicalSymbol = sender.currentTitle\n\n1456\n01:13:05,582 --> 01:13:09,083\nI want the string so I could do the exclamation point,\n我需要 string，我可以用感叹号\n\n1457\n01:13:09,085 --> 01:13:13,321\nokay? But if this were blank, what if I just wanted to\n如果这是空的，如果我只想忽略\n\n1458\n01:13:13,323 --> 01:13:17,658\nignore that operation press? Okay, instead of crashing.\n这个按下的动作呢？而不是让它崩溃\n\n1459\n01:13:17,660 --> 01:13:20,027\nOkay, what if it was legal to have that\n如果让它为空是合法的\n\n1460\n01:13:20,029 --> 01:13:24,165\nbe blank. Okay? I basically want to unwrap\n我只想它被赋值的时候 unwarp\n\n1461\n01:13:24,167 --> 01:13:29,036\nonly if this is set. So the way you do that is\n你做这个的方式\n\n1462\n01:13:29,038 --> 01:13:32,240\nyou don't put the exclamation point there. Instead,\n就是不要在这放个感叹号\n\n1463\n01:13:32,242 --> 01:13:37,412\nyou put if at the beginning. And what's nice about this is\n如果你在前面放个 if\n\n1464\n01:13:37,414 --> 01:13:42,116\nvery little typing but also look how it reads, okay? If I\n这很好，也看看这是怎么写的。\n\n1465\n01:13:42,118 --> 01:13:47,422\ncan let mathematicalSymbol = sender .currentTitle, then I'm\nif let mathematicalSymbol = sender.currentTitle\n\n1466\n01:13:47,424 --> 01:13:50,458\ngonna do something. Okay, so it reads just like English,\n然后再做一些什么。读起来像是英文\n\n1467\n01:13:50,460 --> 01:13:54,462\nit's a really nice way to unwrap. So inside this if,\n这是 unwarp 的很好的方式\n\n1468\n01:13:54,464 --> 01:13:57,064\nthis will be a string. It'll be the associated\n在这个 if 里，这会是个 string\n\n1469\n01:13:57,066 --> 01:14:00,701\nvalue of currenttype, Title. Outside of this if,\n这会是 currentTitle 的关联值\n\n1470\n01:14:00,703 --> 01:14:01,302\nit's not even defined.\nif 之外，它甚至没有被定义\n\n1471\n01:14:01,304 --> 01:14:04,071\nmathematicalSymbol won't even be defined. Okay? Super\nmathematicalSymbol 甚至没被定义\n\n1472\n01:14:04,073 --> 01:14:10,011\nsimple. So here I can just say if mathematicalSymbol = pi,\n超简单，所以我们只要 let mathematicalSymbol == π\n\n1473\n01:14:10,013 --> 01:14:14,782\nby the way Alt + P to make pi, okay, then I can set my\n按alt ＋ P 就是π ，然后设置display\n\n1474\n01:14:14,784 --> 01:14:18,619\ndisplays. I don't even need the exclamation point anymore.\n我甚至不再需要感叹号\n\n1475\n01:14:18,621 --> 01:14:22,924\nText = pi, which _pi is pi if we\nText = M_PI\n\n1476\n01:14:22,926 --> 01:14:27,762\nAlt click on this. This is a symbol. See? M under bar PI.\n按 alt 点它。这是个符号。M_PI\n\n1477\n01:14:27,764 --> 01:14:30,865\nIt's a double. It's a double vision value of PI. Now,\n是个 double。这是个 double 类型的 π 值\n\n1478\n01:14:30,867 --> 01:14:33,301\nwe have an error here. Why do we have an error?\n这里报错了，为什么呢？\n\n1479\n01:14:33,303 --> 01:14:36,504\nBecause it says it cannot assign a type double to\n因为不能把一个 double 赋值给\n\n1480\n01:14:36,506 --> 01:14:39,073\nsomething that is a string question mark, right?\n一个 string？\n\n1481\n01:14:39,075 --> 01:14:42,577\nWe know the display.text right here is a string question mark\n我们知道这是个 display.text 是个 string？\n\n1482\n01:14:42,579 --> 01:14:45,780\nso we can't do that. So, how do we convert this double to\n我们不能这么做，所以我们怎么把这个 double\n\n1483\n01:14:45,782 --> 01:14:49,317\na string? And the answer is we have to create a new string.\n转换成一个 string？答案是新建一个 string\n\n1484\n01:14:49,319 --> 01:14:51,886\nOkay, and now you're gonna see how to create new\n这样你会看到我们如何\n\n1485\n01:14:51,888 --> 01:14:56,290\ninstances of objects in Swift, and the answer is you just put\n在 Swift 里新建一个实例。答案是\n\n1486\n01:14:56,292 --> 01:14:59,694\nthe name of the class and then parentheses and then inside\n打出这个类型名，然后把\n\n1487\n01:14:59,696 --> 01:15:02,263\nthe parentheses you can put anything that the class\n任何允许你转换的值\n\n1488\n01:15:02,265 --> 01:15:06,501\nwill allow you to create one of itself with. Okay, and\n放在括号里\n\n1489\n01:15:06,503 --> 01:15:07,702\nyou can have multiple of these.\n你可以多次创建\n\n1490\n01:15:07,704 --> 01:15:10,538\nThese are the initializers referred to earlier. And\n这是个早前的初始化方式\n\n1491\n01:15:10,540 --> 01:15:14,141\nstring happens to be able to take a double as one of\nstring 可以把一个 double\n\n1492\n01:15:14,143 --> 01:15:16,444\nthe things that it knows how to create a new string. So\n创建成一个新的 string\n\n1493\n01:15:16,446 --> 01:15:19,947\nthis creates a new string, okay, from a double. So\n所以它从一个 double 创建一个新的 string\n\n1494\n01:15:19,949 --> 01:15:22,683\nthe string class knows how to look at a double, turn it into\nstring 类知道如何把一个 double\n\n1495\n01:15:22,685 --> 01:15:27,455\na bunch of characters that are a double, okay? So\n转换成一个字符串\n\n1496\n01:15:27,457 --> 01:15:34,161\nwe'll run this. Okay,\n所以再跑一下\n\n1497\n01:15:34,163 --> 01:15:37,732\nso here we go, this is still working and if we press Pi,\n这还是好用的，当我们按下 π\n\n1498\n01:15:37,734 --> 01:15:40,568\nwe get Pi [SOUND], we got a problem, okay?\n我们得到 π 值，但有个问题\n\n1499\n01:15:40,570 --> 01:15:41,836\nIt's not fitting the whole Pi,\n没有显示全 π\n\n1500\n01:15:41,838 --> 01:15:43,971\nall the digits. We can fix that really easily.\n我们可以很简单的修复一下\n\n1501\n01:15:43,973 --> 01:15:47,475\nI'm gonna go back to here. And if we look at the inspector,\n我们回到这里，看一下 inspector\n\n1502\n01:15:47,477 --> 01:15:51,245\nthere's a nice feature in label called autoshrink.\n有个非常好的 UILabel 特性叫 autoshrink\n\n1503\n01:15:51,247 --> 01:15:53,881\nAnd I'm gonna make it so it autoshrinks but\n我会让这个 autoshrink\n\n1504\n01:15:53,883 --> 01:15:59,320\nno smaller than 9 point, okay. That's gonna fix that one.\n不小于 9 点。这就会修复\n\n1505\n01:15:59,322 --> 01:16:02,757\nWe have one more problem. Okay, so we have,\n我们还有个问题\n\n1506\n01:16:02,759 --> 01:16:05,960\nthis is working, pi, what's that?\n这个 π 又是啥\n\n1507\n01:16:05,962 --> 01:16:09,196\nWe got a little pi on the end there and also look at this,\n我们在最后有一个 π，还有，看这个\n\n1508\n01:16:09,198 --> 01:16:12,600\nthat, what a mess. So we got two problems there. For\n这很不好。我们现在这里有两个问题了\n\n1509\n01:16:12,602 --> 01:16:15,436\nsome reason when we press pi, it puts pi on the end.\n因为一些原因，当我们按 π，最后有个 π 在末尾\n\n1510\n01:16:15,438 --> 01:16:19,173\nWell,why is that? Okay. That's because, let's look at\n为什么呢？因为看这个\n\n1511\n01:16:19,175 --> 01:16:22,276\nthis little thing. Okay. Pi is sending that, right?\nπ 会发送这个\n\n1512\n01:16:22,278 --> 01:16:26,480\nHow about this one? Pi is sending that too.\n这个呢？π 也会发送这个\n\n1513\n01:16:26,482 --> 01:16:31,252\nYou see, it's sending touch digit and perform operation.\n它同时响应两个方法\n\n1514\n01:16:31,254 --> 01:16:33,754\nThat's because I copied and pasted the 7\n因为我复制黏贴了7\n\n1515\n01:16:33,756 --> 01:16:37,358\nwhich sent touch digit and then I added this one. Okay,\n所以也发送上面的这个方法\n\n1516\n01:16:37,360 --> 01:16:40,061\nnow how do we fix that? You fix that by right-clicking on\n那我怎么修复呢？\n\n1517\n01:16:40,063 --> 01:16:42,663\nthe button. If you right-click on anything in your UI, you'll\n可以右击这个按钮\n\n1518\n01:16:42,665 --> 01:16:45,266\nsee all of the connections that it has. Very important to\n可以看到所有按钮关联的东西\n\n1519\n01:16:45,268 --> 01:16:47,668\nunderstand right-click, okay. So you right-click and\n理解右击很重要\n\n1520\n01:16:47,670 --> 01:16:49,203\nyou can see it only has two connections here.\n右击，你可以在这看到两个链接\n\n1521\n01:16:49,205 --> 01:16:52,239\nIt's connected to touch digit and to perform operation, so\n这链接了两个方法\n\n1522\n01:16:52,241 --> 01:16:55,509\nI'm just gonna get rid of the touch digit by clicking this,\n我只是需要去掉 touchDigit\n\n1523\n01:16:55,511 --> 01:16:57,178\ngone. Now it only does perform digit,\n这样就只想响应下面这个方法了\n\n1524\n01:16:57,180 --> 01:17:00,715\nor perform operation, okay. So we fixed that problem where\n所以我们修复了\n\n1525\n01:17:00,717 --> 01:17:02,149\nwe're just putting pi on the end, all right.\n这个末尾有π 的问题\n\n1526\n01:17:02,151 --> 01:17:05,453\nAnd the other problem was that when we have the pi and\n另一个问题是，当我们有π 的时候\n\n1527\n01:17:05,455 --> 01:17:05,987\nI started typing numbers,\n再按数字\n\n1528\n01:17:05,989 --> 01:17:07,922\nit thought I was in the middle of typing a number and\n会认为你在输入中\n\n1529\n01:17:07,924 --> 01:17:11,025\nit was adding them on. So that's simple, I'm just gonna\n会在末尾加数字，这很简单\n\n1530\n01:17:11,027 --> 01:17:14,228\nsay userIsInTheMiddleofTyping number = false.\nuserIsInTheMiddleofTyping = false\n\n1531\n01:17:14,230 --> 01:17:16,364\nOkay, whenever we perform an operation,\n无论我什么时候操作\n\n1532\n01:17:16,366 --> 01:17:19,767\nit's gonna wipe out what's in my display so I'm obviously\n就会去掉之前 display 上的东西\n\n1533\n01:17:19,769 --> 01:17:22,703\nnot in the middle of typing a number anymore and we have\n因为我很显然不是在输入中\n\n1534\n01:17:22,705 --> 01:17:28,242\na fully functional calculator with one operation. 45 pi 89,\n现在我有了个全功能的计算器按钮\n\n1535\n01:17:28,244 --> 01:17:32,780\nokay? So on Wednesday, we'll pick up\n周三，我们会继续\n\n1536\n01:17:32,782 --> 01:17:35,516\nwith some more, make a more powerful calculator. Sorry to\n做个更强的计算器\n\n1537\n01:17:35,518 --> 01:17:38,486\nrun over a little bit because of technical difficulties,\n抱歉，因为技术难题拖课了一会\n\n1538\n01:17:38,488 --> 01:17:40,054\nsee you then. >> For\n下回见\n\n1539\n01:17:40,056 --> 01:17:40,087\nmore please visit us at stanford.edu.\n更多内容详见：stanford.edu\n"
  },
  {
    "path": "subtitles/10. Core Data.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,469\n[MUSIC]\n\n2\n00:00:03,471 --> 00:00:09,508\nStanford University. >> Welcome to Lecture Number\n\n3\n00:00:09,510 --> 00:00:13,746\n10 of Stanford CS193P. It's the Spring of 2016.\n\n4\n00:00:13,748 --> 00:00:18,250\nToday we have one topic only, which is Core Data, okay,\n\n5\n00:00:18,252 --> 00:00:22,221\nwhich is an object oriented database. Sometimes when\n\n6\n00:00:22,223 --> 00:00:24,957\nyou're building an app you need to store a huge amount of\n\n7\n00:00:24,959 --> 00:00:27,926\ndata like you're doing some kind of twitter thing where\n\n8\n00:00:27,928 --> 00:00:29,294\nyou're collecting all the tweets and\n\n9\n00:00:29,296 --> 00:00:29,995\nyou've got all these tweets and\n\n10\n00:00:29,997 --> 00:00:31,030\nyou want to search through them and\n\n11\n00:00:31,032 --> 00:00:33,632\ndo some kind of queries or something like that. And\n\n12\n00:00:33,634 --> 00:00:36,735\nof course there's lots of technologies out there for\n\n13\n00:00:36,737 --> 00:00:40,005\ndoing that kind of thing. SQL databases and\n\n14\n00:00:40,007 --> 00:00:42,274\nthings like that. But really when we're programming,\n\n15\n00:00:42,276 --> 00:00:45,778\nwe want obviously all of our stuff to be object oriented.\n\n16\n00:00:45,780 --> 00:00:49,648\nSo iOS has this awesome object oriented database system\n\n17\n00:00:49,650 --> 00:00:53,252\ncalled Core Data. It's very powerful.\n\n18\n00:00:53,254 --> 00:00:55,020\nIt's actually based on SQL underneath so\n\n19\n00:00:55,022 --> 00:00:58,090\nit's got all the full kind of power of that.\n\n20\n00:00:58,325 --> 00:01:01,393\nAnd yet it interacts with your code just like all your other\n\n21\n00:01:01,395 --> 00:01:02,761\nobject oriented stuff that you do,\n\n22\n00:01:02,763 --> 00:01:04,997\nespecially if you're doing things like table and\n\n23\n00:01:04,999 --> 00:01:07,666\nstuff like that that has a lot of good integration,\n\n24\n00:01:07,668 --> 00:01:10,269\nwith that. So it's essentially a way of\n\n25\n00:01:10,271 --> 00:01:14,039\ncreating an object graph that's backed by a database,\n\n26\n00:01:14,041 --> 00:01:14,840\na SQL database in this case.\n\n27\n00:01:14,842 --> 00:01:17,776\nIt can actually be backed by other kinds of databases\n\n28\n00:01:17,778 --> 00:01:19,678\nlike XML or just in memory stuff but\n\n29\n00:01:19,680 --> 00:01:23,015\nprimarily we're using Core Data with SQL as our,\n\n30\n00:01:23,017 --> 00:01:25,050\nbacking store. And the way it works,\n\n31\n00:01:25,052 --> 00:01:29,054\nis you're going to create this visual mapping, okay? And\n\n32\n00:01:29,056 --> 00:01:32,024\nthen you're gonna create objects in your code. Visual\n\n33\n00:01:32,026 --> 00:01:33,892\nmapping's gonna basically describe your database,\n\n34\n00:01:33,894 --> 00:01:36,061\nthen you're gonna create objects in your code,\n\n35\n00:01:36,063 --> 00:01:38,831\nthat are in that database. And you're gonna access\n\n36\n00:01:38,833 --> 00:01:41,800\nthe columns in the database, and the rows, and\n\n37\n00:01:41,802 --> 00:01:42,000\nthe columns and\n\n38\n00:01:42,002 --> 00:01:44,069\nthe tables if you want to think of it that way, but\n\n39\n00:01:44,071 --> 00:01:46,738\nyou can access the attributes just using vars.\n\n40\n00:01:46,740 --> 00:01:49,141\nSo you're gonna have objects and vars on them and\n\n41\n00:01:49,143 --> 00:01:52,211\nthose are gonna be stored in the database, okay.\n\n42\n00:01:52,213 --> 00:01:54,813\nSo I'm gonna walk you through all that. Let's start with\n\n43\n00:01:54,815 --> 00:01:57,916\ncreating that visual mapping of the database, okay.\n\n44\n00:01:57,918 --> 00:02:01,253\nNow just like anything, that you do when you're\n\n45\n00:02:01,255 --> 00:02:04,189\nadding a new file to x code, whether it's a swift file or\n\n46\n00:02:04,191 --> 00:02:07,593\nsomething like that, you're going to start with new file.\n\n47\n00:02:07,595 --> 00:02:08,527\nBut in this case, we're not going\n\n48\n00:02:08,529 --> 00:02:11,196\nto be adding a code file, we're actually going to be\n\n49\n00:02:11,198 --> 00:02:15,134\nadding a database mapping file. So, you say new file,\n\n50\n00:02:15,136 --> 00:02:18,570\nand you're going to go down to iOS Core Data, okay? You see\n\n51\n00:02:18,572 --> 00:02:23,075\nwhere it says Core Data down there instead of, iOS source,\n\n52\n00:02:23,077 --> 00:02:25,611\nand inside of there, you're gonna pick data model.\n\n53\n00:02:25,613 --> 00:02:30,115\nDon't pick mapping model, you want data model, okay? And\n\n54\n00:02:30,117 --> 00:02:32,818\nit's gonna ask you what you wanna call this mapping.\n\n55\n00:02:32,820 --> 00:02:33,986\nOkay, this mapping, by the way,\n\n56\n00:02:33,988 --> 00:02:37,089\nwhat we're mapping between is these objects that we're gonna\n\n57\n00:02:37,091 --> 00:02:40,692\ndescribe in this database and what's gonna be in our code.\n\n58\n00:02:40,694 --> 00:02:44,796\nAnd usually if you only have one database in your app\n\n59\n00:02:44,798 --> 00:02:47,599\nyou'll call it model, because it's usually the model for\n\n60\n00:02:47,601 --> 00:02:49,601\na lot of your view controllers, but you could\n\n61\n00:02:49,603 --> 00:02:52,571\nalso call it the name or your app or if you had multiple of\n\n62\n00:02:52,573 --> 00:02:55,307\nthem you could kind of name them appropriately, right, so\n\n63\n00:02:55,309 --> 00:02:59,845\nany name will, is fine here. When you create it,\n\n64\n00:02:59,847 --> 00:03:03,415\nlooks like this, okay? It's called Model.xcdatamodeld\n\n65\n00:03:03,417 --> 00:03:07,319\nright here. And this is the contents of it, right?\n\n66\n00:03:07,321 --> 00:03:10,022\nWe're looking at the contents of it. And,\n\n67\n00:03:10,024 --> 00:03:14,026\nit's kind of like a storyboard for the database, okay?\n\n68\n00:03:14,028 --> 00:03:14,626\nYou're gonna graphically,\n\n69\n00:03:14,628 --> 00:03:19,198\nvisually edit your database schema right here. So\n\n70\n00:03:19,200 --> 00:03:21,934\nthe database lets you store things obviously.\n\n71\n00:03:21,936 --> 00:03:25,003\nThe main things that you're storing are called entities,\n\n72\n00:03:25,005 --> 00:03:28,407\nokay? And they're kinda analogous to objects,\n\n73\n00:03:28,409 --> 00:03:31,076\nall right? So here I'm gonna create an entity so\n\n74\n00:03:31,078 --> 00:03:33,645\nI'm gonna click on this add entity button at the bottom.\n\n75\n00:03:33,647 --> 00:03:37,249\nAnd just say add entity. When I do, it creates one up here.\n\n76\n00:03:37,251 --> 00:03:39,218\nAnd I'm gonna change the name of it to Tweet.\n\n77\n00:03:39,220 --> 00:03:42,321\nSo for my examples today, let's say we're building\n\n78\n00:03:42,323 --> 00:03:44,523\na database that's storing some Twitter stuff.\n\n79\n00:03:44,525 --> 00:03:45,524\nWe're all in kinda Twitter mode\n\n80\n00:03:45,526 --> 00:03:48,660\nright now with your assignment stuff. So we'll store some\n\n81\n00:03:48,662 --> 00:03:54,333\ntweets and some Twitter users into this database, okay? Now\n\n82\n00:03:54,335 --> 00:03:57,769\nthis entity Tweet that we're gonna store in the database,\n\n83\n00:03:57,771 --> 00:04:01,673\nthey're gonna appear in our code as NSManagedObject\n\n84\n00:04:01,675 --> 00:04:05,978\ninstances. So there's a class in iOS NSManagedObject, okay.\n\n85\n00:04:05,980 --> 00:04:09,381\nAnd so all these entities will appear in our code as\n\n86\n00:04:09,383 --> 00:04:14,953\nNSManagedObject, okay. All right so in addition\n\n87\n00:04:14,955 --> 00:04:19,024\nto entities these entities have attributes. So those\n\n88\n00:04:19,026 --> 00:04:21,727\nare kind of like properties on a class right there.\n\n89\n00:04:21,729 --> 00:04:25,030\nThey have relationships. Relationships are kind of like\n\n90\n00:04:25,032 --> 00:04:29,668\nvars that point to other objects in the database, okay.\n\n91\n00:04:29,670 --> 00:04:32,337\nAnd then there also have this thing down here called fetch\n\n92\n00:04:32,339 --> 00:04:35,340\nproperties. Which I'm not gonna really talk about but\n\n93\n00:04:35,342 --> 00:04:36,708\nkind of the name implies what they are.\n\n94\n00:04:36,710 --> 00:04:40,045\nThey're essentially properties that are, that basically\n\n95\n00:04:40,047 --> 00:04:43,382\nrepresent fetching in the database. So pulling objects\n\n96\n00:04:43,384 --> 00:04:46,018\nout that meet some query or something like that. You can\n\n97\n00:04:46,020 --> 00:04:48,353\nmake it look like that's just a property on you're entity.\n\n98\n00:04:48,355 --> 00:04:50,422\nUnfortunately, don't have time to talk about that.\n\n99\n00:04:50,424 --> 00:04:53,525\nWe're gonna focus here on these attributes and\n\n100\n00:04:53,527 --> 00:04:55,560\nrelationships, okay?\n\n101\n00:04:55,562 --> 00:04:58,897\nSo to add an attribute, we're going to hit this little plus\n\n102\n00:04:58,899 --> 00:05:00,399\nsign right here under the attributes and\n\n103\n00:05:00,401 --> 00:05:03,502\nit's going to add one. Here, I'm doing a Tweet, right,\n\n104\n00:05:03,504 --> 00:05:06,371\nthat's my entity as a Tweet, so I'm going to put the text\n\n105\n00:05:06,373 --> 00:05:10,342\nof the Tweet. Notice as soon as I type, as I added this and\n\n106\n00:05:10,344 --> 00:05:12,444\ntyped it in, I get start getting an error right here.\n\n107\n00:05:12,446 --> 00:05:15,847\nSee, red error up in the, upper corner there, okay.\n\n108\n00:05:15,849 --> 00:05:17,816\nAnd that's because this Tweet or\n\n109\n00:05:17,818 --> 00:05:21,053\nthis text attribute on the Tweet has no type, okay.\n\n110\n00:05:21,055 --> 00:05:24,089\nEverything that goes in there obviously has to have a type,\n\n111\n00:05:24,091 --> 00:05:26,525\nso you just click on this type to set it and\n\n112\n00:05:26,527 --> 00:05:30,896\nI'm gonna set the text to be a string. Okay, so these are all\n\n113\n00:05:30,898 --> 00:05:34,566\nthe types that the attributes, the vars in your Tweet entity\n\n114\n00:05:34,568 --> 00:05:38,737\ncan be basically. All the ones like integers, decimal,\n\n115\n00:05:38,739 --> 00:05:42,541\ndouble, float, even Boolean, those are actually stored as\n\n116\n00:05:42,543 --> 00:05:46,645\nan NS number. Those appear in your code as an NS number.\n\n117\n00:05:46,647 --> 00:05:50,015\nOkay, this binary data is in NS data.\n\n118\n00:05:50,017 --> 00:05:55,420\nThe date is an NSDate, and the string here is an NSString.\n\n119\n00:05:55,422 --> 00:05:58,690\nNow remember that you get the automatic bridging, right?\n\n120\n00:05:58,692 --> 00:06:01,660\nFrom NSString to string, things like that,\n\n121\n00:06:01,662 --> 00:06:04,363\neven from double and int to NSNumbers, right?\n\n122\n00:06:04,365 --> 00:06:07,232\nSo, even though these are NSNumbers and NSString,\n\n123\n00:06:07,234 --> 00:06:09,601\nyou're still gonna get your Swift-like things when you're\n\n124\n00:06:09,603 --> 00:06:14,005\nusing them, in your code. Now, you can set any of these\n\n125\n00:06:14,007 --> 00:06:17,876\nthings, like this text attribute using these two\n\n126\n00:06:17,878 --> 00:06:21,480\nmethods right here on NSManagedObject, okay?\n\n127\n00:06:21,482 --> 00:06:25,217\nValue for key which gets the value, and set value for\n\n128\n00:06:25,219 --> 00:06:28,720\nkey. Okay, so valueForKey returns any object,\n\n129\n00:06:28,722 --> 00:06:32,457\ncould be an NSNumber or an NSDate or an NSData, right.\n\n130\n00:06:32,459 --> 00:06:36,561\nAnd setValue(forKey:) the key is a string like text and\n\n131\n00:06:36,563 --> 00:06:41,466\nthe value is, again, NSNumber, NSData, NSDate, whatever,\n\n132\n00:06:41,468 --> 00:06:45,203\nokay? So that's how you can set the data on your object\n\n133\n00:06:45,205 --> 00:06:47,005\nonce you get a hold of one of these NSManagedObject.\n\n134\n00:06:47,007 --> 00:06:50,041\nNow I haven't shown you how to get those NSManagedObject yet,\n\n135\n00:06:50,043 --> 00:06:51,209\nbut I will soon.\n\n136\n00:06:51,578 --> 00:06:54,813\nSee the error's gone because I set this to be a string. So,\n\n137\n00:06:54,815 --> 00:06:57,716\nhere's I'm going to add some more attributes, an ID,\n\n138\n00:06:57,718 --> 00:07:00,585\nwhich is some unique identifier for this Tweet.\n\n139\n00:07:00,587 --> 00:07:03,588\nAlso created, which is the date the Tweet was created,\n\n140\n00:07:03,590 --> 00:07:06,758\nyou can see that's an NSDate right there. By the way,\n\n141\n00:07:06,760 --> 00:07:10,529\nthis ID you're probably going to want that in your homework.\n\n142\n00:07:10,531 --> 00:07:10,862\nJust a little hint.\n\n143\n00:07:10,864 --> 00:07:13,665\nI like to give you hints sometimes in the lecture.\n\n144\n00:07:13,667 --> 00:07:17,436\nSo you'll need your unique ID there at some point.\n\n145\n00:07:17,704 --> 00:07:20,906\nWe're looking at these attributes on this entity in\n\n146\n00:07:20,908 --> 00:07:24,943\nkind of a table format here. But we can also do it in\n\n147\n00:07:24,945 --> 00:07:27,746\na graphical way by clicking on this little button down here,\n\n148\n00:07:27,748 --> 00:07:31,416\nthis editor style. It changes the style of this editor and\n\n149\n00:07:31,418 --> 00:07:34,719\nit looks like this. So the graphical one basically has\n\n150\n00:07:34,721 --> 00:07:37,889\nall of my entities and my attributes, but in kind of\n\n151\n00:07:37,891 --> 00:07:41,026\non a graph paper graphical format. And this is going to\n\n152\n00:07:41,028 --> 00:07:44,596\nmake sense when I start having a lot of relationships between\n\n153\n00:07:44,598 --> 00:07:45,263\nentities, right.\n\n154\n00:07:45,265 --> 00:07:48,333\nThen I'm gonna be able to see them here on the graph paper\n\n155\n00:07:48,335 --> 00:07:49,267\nall pointing to each other so\n\n156\n00:07:49,269 --> 00:07:51,603\nI can see what their relationships are. Okay, so\n\n157\n00:07:51,605 --> 00:07:55,140\nlet's add another entity in this. We can add entities and\n\n158\n00:07:55,142 --> 00:07:58,376\nattributes in this view just as much as in the table view.\n\n159\n00:07:58,378 --> 00:08:00,645\nSo I'm gonna go down here and add another entity.\n\n160\n00:08:00,647 --> 00:08:04,549\nThis is gonna be a Twitter user, okay? And you can see it\n\n161\n00:08:04,551 --> 00:08:07,419\nadded the Twitter user here. It has no attributes or\n\n162\n00:08:07,421 --> 00:08:09,221\nrelationships yet. What's really cool,\n\n163\n00:08:09,223 --> 00:08:12,224\nif you move these around and they do have wires pointing\n\n164\n00:08:12,226 --> 00:08:14,960\nto each other, it'll rearrange the wires all over the place\n\n165\n00:08:14,962 --> 00:08:19,231\nto look nice, okay? So that's kinda fun. I can also add\n\n166\n00:08:19,233 --> 00:08:20,832\nattributes from here. So I'm just going down here and\n\n167\n00:08:20,834 --> 00:08:23,869\nsay add attribute to add an attribute to my Twitter user.\n\n168\n00:08:23,871 --> 00:08:27,305\nI'm gonna call this attribute screen name, okay,\n\n169\n00:08:27,307 --> 00:08:30,442\nthat's like the at sign, whatever, screen name\n\n170\n00:08:30,444 --> 00:08:33,745\nof the user. Notice that if I have this selected,\n\n171\n00:08:33,747 --> 00:08:37,716\nthen the Inspector over here can be used to inspect things\n\n172\n00:08:37,718 --> 00:08:41,753\nabout this attribute. So let's do that. Here's a screen name,\n\n173\n00:08:41,755 --> 00:08:43,688\nits attributes. For example, here's its type.\n\n174\n00:08:43,690 --> 00:08:46,458\nI'm going to say this type to be a string. It has some other\n\n175\n00:08:46,460 --> 00:08:48,860\nattributes here which I'm not really going to have time to\n\n176\n00:08:48,862 --> 00:08:51,429\ntalk about. But you'll definitely, you can look up.\n\n177\n00:08:51,431 --> 00:08:53,765\nYou won't need it for any of your homework obviously, but\n\n178\n00:08:53,767 --> 00:08:55,066\nfor your final project you might. So\n\n179\n00:08:55,068 --> 00:08:58,670\nyou can look those up in the documentation for core data.\n\n180\n00:08:58,672 --> 00:09:02,207\nMkay I'm gonna add another attribute here which is name.\n\n181\n00:09:02,209 --> 00:09:03,341\nSo that's the user's real name.\n\n182\n00:09:03,343 --> 00:09:06,278\nOkay not their at time whatever but their actual real\n\n183\n00:09:06,280 --> 00:09:09,714\nname. So I'll add that. And now I'm gonna add\n\n184\n00:09:09,716 --> 00:09:13,685\na relationship between these two entities and of course we\n\n185\n00:09:13,687 --> 00:09:17,522\nknow that a Twitter user Is the one who tweets the tweet.\n\n186\n00:09:17,524 --> 00:09:21,259\nRight? So, there's a relationship between this two.\n\n187\n00:09:21,261 --> 00:09:23,795\nAnd to create a relationship between these two,\n\n188\n00:09:23,797 --> 00:09:25,764\nI just Ctrl-drag from one to the other.\n\n189\n00:09:25,766 --> 00:09:27,699\nAnd I can Ctrl-drag from either to the other.\n\n190\n00:09:27,701 --> 00:09:29,034\nIt really doesn't matter which direction.\n\n191\n00:09:29,036 --> 00:09:32,070\nAnd when I do that, it's going to create\n\n192\n00:09:32,072 --> 00:09:36,608\na new thing over here called a relationship on both sides,\n\n193\n00:09:36,610 --> 00:09:38,577\nit called it new relationship by default,\n\n194\n00:09:38,579 --> 00:09:41,112\nwe're going to change the name of that, okay, on both sides,\n\n195\n00:09:41,114 --> 00:09:44,049\nand you can see it's got an arrow that points both ways.\n\n196\n00:09:44,051 --> 00:09:46,651\nSo now we know there's a relationship on both sides.\n\n197\n00:09:46,653 --> 00:09:49,287\nNow, we want to rename these relationships\n\n198\n00:09:49,289 --> 00:09:51,756\njust like the attributes have names that are meaningful,\n\n199\n00:09:51,758 --> 00:09:55,961\nwe want these to be meaningful names too. So the tweet okay,\n\n200\n00:09:55,963 --> 00:09:58,530\nif you look at this relationship to this guy.\n\n201\n00:09:58,532 --> 00:10:01,466\nThis is the tweeter. Okay this is the tweeter for\n\n202\n00:10:01,468 --> 00:10:04,336\nthis tweet so I'm gonna call the relationship tweeter\n\n203\n00:10:04,338 --> 00:10:07,672\non this side. Okay I could probably call it user or\n\n204\n00:10:07,674 --> 00:10:10,842\nsomething as well but tweeter is kind of fun.\n\n205\n00:10:10,844 --> 00:10:13,378\nOn the other side this is tweet. Okay.\n\n206\n00:10:13,380 --> 00:10:19,117\nSo this is the tweet that this user has tweeted. Okay.\n\n207\n00:10:19,119 --> 00:10:22,921\nNow notice when you do this if you inspect either one,\n\n208\n00:10:22,923 --> 00:10:24,956\nlike if you inspect tweets right there,\n\n209\n00:10:24,958 --> 00:10:26,891\nit's showing me that the inverse is tweeter.\n\n210\n00:10:26,893 --> 00:10:29,494\nSo it knows the inder-, inverse right there,\n\n211\n00:10:29,496 --> 00:10:32,197\nokay. Now there's something different though about\n\n212\n00:10:32,199 --> 00:10:36,901\nthis tweets relationship to the tweeter relationship. Cuz,\n\n213\n00:10:36,903 --> 00:10:41,940\nthere are multiple tweets per Twitter user, right?\n\n214\n00:10:41,942 --> 00:10:45,210\nSo user could have tweeted hundreds of times. So\n\n215\n00:10:45,212 --> 00:10:46,911\nthis basically is multiple things,\n\n216\n00:10:46,913 --> 00:10:50,548\nthis is a to-many relationship to use database jargon there\n\n217\n00:10:50,550 --> 00:10:53,385\nare many tweets per user even though there's only one user\n\n218\n00:10:53,387 --> 00:10:57,455\nper tweet. And you define that up here in the inspector,\n\n219\n00:10:57,457 --> 00:10:58,423\nif you have tweet selected.\n\n220\n00:10:58,425 --> 00:11:01,793\nYou go here to the type of relationship it is. And\n\n221\n00:11:01,795 --> 00:11:05,930\nyou can say it's a too many relationship. And when I do\n\n222\n00:11:05,932 --> 00:11:09,668\nthat notice I get this little double arrow right here. Okay?\n\n223\n00:11:09,670 --> 00:11:13,672\nThat's telling me that there's many tweets per Twitter user.\n\n224\n00:11:13,674 --> 00:11:16,241\nNow, this is gonna show up differently in my code.\n\n225\n00:11:16,243 --> 00:11:19,678\nThis one right here is gonna show up in my code, okay,\n\n226\n00:11:19,680 --> 00:11:21,613\nthis tweet thing that I have, this\n\n227\n00:11:21,615 --> 00:11:24,115\ntweet entity is gonna have a var, right here,\n\n228\n00:11:24,117 --> 00:11:28,386\ncalled tweeter. It's gonna be of type NSManagedObject,\n\n229\n00:11:28,388 --> 00:11:31,289\nbecause I told you all of these entities, this, and\n\n230\n00:11:31,291 --> 00:11:34,559\nthis, are gonna show up in your code as NSManagedObject,\n\n231\n00:11:34,561 --> 00:11:36,227\nso that's gonna be the type of this var.\n\n232\n00:11:36,229 --> 00:11:42,233\nThe type of this var over here is gonna be ns set. Okay?\n\n233\n00:11:42,235 --> 00:11:45,136\nAnd NSSet I can't remember if we talked about that earlier\n\n234\n00:11:45,138 --> 00:11:49,074\nin the quarter but it's very similar to NSArray, okay?\n\n235\n00:11:49,076 --> 00:11:53,745\nBut it's unordered and unique. Ok, so an NS\n\n236\n00:11:53,747 --> 00:11:56,881\narray can have the same object in it multiple times and\n\n237\n00:11:56,883 --> 00:11:59,684\nan NS array is also in order. And in a set,\n\n238\n00:11:59,686 --> 00:12:02,120\nit's just a bunch of objects in there, and\n\n239\n00:12:02,122 --> 00:12:05,256\nif you add in the same object again, it would do nothing.\n\n240\n00:12:05,258 --> 00:12:06,991\nOkay, so it's basically a unique set and\n\n241\n00:12:06,993 --> 00:12:10,895\nthere's no order to it's just a big jumble of them. Okay,\n\n242\n00:12:10,897 --> 00:12:14,132\nand since these Tweets are basically a big jumble of\n\n243\n00:12:14,134 --> 00:12:17,168\ntweets done by this user in no particular order, that's why\n\n244\n00:12:17,170 --> 00:12:23,208\nit's an NS set. Now, there is in Swift a struck called set,\n\n245\n00:12:23,210 --> 00:12:27,178\nand is automatically bridged just like NS array,\n\n246\n00:12:27,180 --> 00:12:28,813\nautomatically bridged to an array. Okay?\n\n247\n00:12:28,815 --> 00:12:31,382\nSo you can think of this as just being a set, but in fact,\n\n248\n00:12:31,384 --> 00:12:35,286\nit's an NSSet. Okay? And what's in that set? Of course,\n\n249\n00:12:35,288 --> 00:12:39,190\nManageObject, NSManageObject, cuz these are in there. Okay?\n\n250\n00:12:39,192 --> 00:12:43,595\nSo it's exactly what you would think. All right? Now.\n\n251\n00:12:43,597 --> 00:12:46,464\nThere's lots of things you can do, okay, in core data.\n\n252\n00:12:46,466 --> 00:12:49,601\nWe're gonna focus on a small part of it, but\n\n253\n00:12:49,603 --> 00:12:51,770\nthe core of it, which is entities, attributes, and\n\n254\n00:12:51,772 --> 00:12:54,706\nrelationships, these things that I just told you about.\n\n255\n00:12:54,708 --> 00:12:58,176\nOkay. How do you access all this stuff in the code?\n\n256\n00:12:58,178 --> 00:13:00,612\nYou need an instance of one of these.\n\n257\n00:13:00,614 --> 00:13:04,082\nNSManagedObjectContext. You can think of that as kind of\n\n258\n00:13:04,084 --> 00:13:11,523\nthe window into the world of your database of objects,\n\n259\n00:13:11,525 --> 00:13:13,958\nokay? So you need one of these to be able to do anything\n\n260\n00:13:13,960 --> 00:13:17,862\nfrom the database. All right? So how do I get one of these?\n\n261\n00:13:17,864 --> 00:13:20,765\n[LAUGH] Okay? I need one of these, how do I get it? Well,\n\n262\n00:13:20,767 --> 00:13:23,434\nthere's really two ways to get it, and you use them kind\n\n263\n00:13:23,436 --> 00:13:26,404\nof about equally. One's not really necessarily preferred\n\n264\n00:13:26,406 --> 00:13:29,841\nover the other. One of them is when you create your project,\n\n265\n00:13:29,843 --> 00:13:31,609\ndo you remember when we create a project there was a little\n\n266\n00:13:31,611 --> 00:13:34,078\nbutton at the bottom, there's three switches at the bottom.\n\n267\n00:13:34,080 --> 00:13:37,949\nOne was You, are you gonna do testing or UI testing? And\n\n268\n00:13:37,951 --> 00:13:40,418\nthe other one on the top of the three buttons was\n\n269\n00:13:40,420 --> 00:13:44,656\nI'm using Core Data. Do you remember that button? Anyway,\n\n270\n00:13:44,658 --> 00:13:45,857\nit's there, I promise you. And\n\n271\n00:13:45,859 --> 00:13:49,861\nif you click that button when you create your application,\n\n272\n00:13:49,863 --> 00:13:52,330\nthen you're going to get a bunch of code\n\n273\n00:13:52,332 --> 00:13:56,034\nProvided to you.. One of which is a method that gives you one\n\n274\n00:13:56,036 --> 00:14:00,038\nof these shared in your whole application. Okay, and\n\n275\n00:14:00,040 --> 00:14:02,941\nI'm going to talk about how that works in a second.\n\n276\n00:14:02,943 --> 00:14:05,977\nThe second way you can get one of these little guys\n\n277\n00:14:05,979 --> 00:14:09,180\nis to create a U-I managed document, okay?\n\n278\n00:14:09,182 --> 00:14:12,350\nThe U-I managed document has a var on it called managed\n\n279\n00:14:12,352 --> 00:14:16,421\nobject context, which will give you one of these. Okay?\n\n280\n00:14:16,423 --> 00:14:19,357\nSo, I'm going to talk about both of these mechanisms for,\n\n281\n00:14:19,359 --> 00:14:21,926\nfor getting this. All right. So, the first one,\n\n282\n00:14:21,928 --> 00:14:25,363\nwhere you click the switch: When you flip that switch,\n\n283\n00:14:25,365 --> 00:14:28,366\nyou're going to, essentially get some code\n\n284\n00:14:28,368 --> 00:14:31,035\nput in that AppDelegate.Swift file. Remember\n\n285\n00:14:31,037 --> 00:14:34,038\nthe AppDelegate.Swift? It's one of the files we always\n\n286\n00:14:34,040 --> 00:14:35,240\nmove in to supporting files.\n\n287\n00:14:35,242 --> 00:14:37,141\nOne of the first things I ever do, is okay,\n\n288\n00:14:37,143 --> 00:14:41,045\nlet's take image assets and AppDelegate and info.plist.\n\n289\n00:14:41,047 --> 00:14:43,114\nLet's move them into a little folder called supporting\n\n290\n00:14:43,116 --> 00:14:45,550\nfiles. Well, we haven't looked at that AppDelegate cuz\n\n291\n00:14:45,552 --> 00:14:49,420\nthere's really not much in there at this point but\n\n292\n00:14:49,422 --> 00:14:52,757\nin there will be a bunch of code for core data, okay,\n\n293\n00:14:52,759 --> 00:14:56,127\nif you flip that switch. Okay, and one of the things in that\n\n294\n00:14:56,129 --> 00:14:58,763\nbunch of code is a method called managedObject,\n\n295\n00:14:58,765 --> 00:15:00,765\nit's a var actually called managedObjectContext.\n\n296\n00:15:00,767 --> 00:15:04,102\nAnd all you need to do is call that var and boom, you'll have\n\n297\n00:15:04,104 --> 00:15:05,837\na managedObjectContext to the database for\n\n298\n00:15:05,839 --> 00:15:09,440\nthis app. And App Delegate is kinda a global resource but\n\n299\n00:15:09,442 --> 00:15:11,542\nyour database is often a global resource, right?\n\n300\n00:15:11,544 --> 00:15:14,712\nAll your view controllers want to be able to see the data in\n\n301\n00:15:14,714 --> 00:15:17,348\nthe database, so it's reasonable. Now, the way you\n\n302\n00:15:17,350 --> 00:15:20,418\nget at it, you get this AppDelegate. It's a little,\n\n303\n00:15:20,420 --> 00:15:22,687\nit seems a little complicated, but it's not too bad.\n\n304\n00:15:22,689 --> 00:15:25,924\nWe're going to call this, this, class method on new\n\n305\n00:15:25,926 --> 00:15:29,260\napplication called Shared Application. And this returns\n\n306\n00:15:29,262 --> 00:15:33,331\nyou the one and only instance of UI application,\n\n307\n00:15:33,333 --> 00:15:36,467\nwhich is just a class that represents your app.\n\n308\n00:15:36,469 --> 00:15:39,637\nOk now that object, UI application dot shared\n\n309\n00:15:39,639 --> 00:15:42,707\napplication, has a delegate. You all know what delegation\n\n310\n00:15:42,709 --> 00:15:47,278\nis. It has a delegate. That delegate is that app delegate,\n\n311\n00:15:47,280 --> 00:15:51,282\nthe place where that manage object code got thrown.\n\n312\n00:15:51,284 --> 00:15:54,719\nSo you're going to cast it though as app delegate.\n\n313\n00:15:54,721 --> 00:15:57,689\nYou could do question mark here and then If it comes\n\n314\n00:15:57,691 --> 00:16:01,492\nbacks nil, I'm guess you're SOL you have any database, but\n\n315\n00:16:01,494 --> 00:16:04,896\nhere I'm gonna force cast it because if I can't get this\n\n316\n00:16:04,898 --> 00:16:08,066\nmanaged object contacts. Then I can't do anything with my\n\n317\n00:16:08,068 --> 00:16:10,902\napp, so I'm going to let it crash here for\n\n318\n00:16:10,904 --> 00:16:14,339\nsome reason my app delegate is not my delegate of\n\n319\n00:16:14,341 --> 00:16:17,241\nmy UI application. So anyway, you do this line of code and\n\n320\n00:16:17,243 --> 00:16:20,044\nthis is going to give you back your managed object context.\n\n321\n00:16:20,046 --> 00:16:22,046\nSo, now you have the portal that you need.\n\n322\n00:16:22,048 --> 00:16:24,782\nTo do all the database stuff. Okay? So that's one way to get\n\n323\n00:16:24,784 --> 00:16:28,286\nthis portal. The other way is UIManagedDocument. Okay,\n\n324\n00:16:28,288 --> 00:16:31,689\nUIManagedDocument is a class it inherits from UIDocument\n\n325\n00:16:31,691 --> 00:16:35,059\nand it's only job really is to encapsulate a core data\n\n326\n00:16:35,061 --> 00:16:38,129\ndatabase, that's what it does. It encapsulates a core data\n\n327\n00:16:38,131 --> 00:16:41,866\ndatabase, I mean, a file on disk Alright?\n\n328\n00:16:42,369 --> 00:16:45,036\nAnd, the way you create a UIManagedDocument,\n\n329\n00:16:45,038 --> 00:16:47,305\nUIManagedDocument is actually really easy. And you might\n\n330\n00:16:47,307 --> 00:16:50,274\nask, why would I ever do that other clicking the switch and\n\n331\n00:16:50,276 --> 00:16:53,044\nthe- creating my project in AppDelegate? All that.\n\n332\n00:16:53,046 --> 00:16:55,646\nWhy would I do that when I have this UIManagedDocument?\n\n333\n00:16:55,648 --> 00:16:58,549\nI just create one and get the managed object context.\n\n334\n00:16:58,551 --> 00:17:02,120\nWell, the reason it's a little more complicated here is\n\n335\n00:17:02,122 --> 00:17:04,355\nbecause it does it's work asynchronously.\n\n336\n00:17:04,357 --> 00:17:07,558\nYou guys are only just getting used to asynchrony, so\n\n337\n00:17:07,560 --> 00:17:09,027\nit might seem a little complicated to you. Once\n\n338\n00:17:09,029 --> 00:17:12,263\nyou're used to it it won't seem complicated at all, but\n\n339\n00:17:12,265 --> 00:17:13,998\nwhen asynchrony is new to you,\n\n340\n00:17:14,000 --> 00:17:16,601\nUIManagedDocument might seem a little\n\n341\n00:17:16,603 --> 00:17:19,570\nKind of how does that work? Here is how it works. Okay,\n\n342\n00:17:19,572 --> 00:17:23,241\nhere's a UIManagedDocument, I'm going to create it.\n\n343\n00:17:23,243 --> 00:17:26,811\nFirst I'm going to get an NS File Manager here.\n\n344\n00:17:26,813 --> 00:17:29,447\nThis is a thing we haven't talked about yet, which lets\n\n345\n00:17:29,449 --> 00:17:32,150\nyou access the file system. And of course, I'm going to\n\n346\n00:17:32,152 --> 00:17:34,519\nstore my UIManagedDocument in the file system. So,\n\n347\n00:17:34,521 --> 00:17:37,722\nI obviously need this little file manager guy right here.\n\n348\n00:17:37,724 --> 00:17:40,425\nThen, I also need to know where to put my managed\n\n349\n00:17:40,427 --> 00:17:43,327\ndocument. And I'm gonna put it in the documents\n\n350\n00:17:43,329 --> 00:17:47,632\ndirectory for my app. So we're gonna learn later that\n\n351\n00:17:47,634 --> 00:17:48,733\nyour app has a documents directory,\n\n352\n00:17:48,735 --> 00:17:52,303\nit has a caches directory, it has a temporary directory.\n\n353\n00:17:52,305 --> 00:17:55,740\nIt has all these kind of named magic directories\n\n354\n00:17:55,742 --> 00:17:59,143\nwhere you put stuff, and the document directory right here\n\n355\n00:17:59,145 --> 00:18:02,447\nis the one where you probably wanna put your users data.\n\n356\n00:18:02,449 --> 00:18:04,282\nOkay, that's what that directory's really for.\n\n357\n00:18:04,284 --> 00:18:06,117\nSo you're gonna do this thing URLs for\n\n358\n00:18:06,119 --> 00:18:08,553\ndirectory which returns the document directory and\n\n359\n00:18:08,555 --> 00:18:09,487\nthen you can get the first one.\n\n360\n00:18:09,489 --> 00:18:13,591\nThis returns an array of URLs like there might be multiple\n\n361\n00:18:13,593 --> 00:18:15,193\ndocument directories out there.\n\n362\n00:18:15,195 --> 00:18:16,494\nIn iOS, there's always only one.\n\n363\n00:18:16,496 --> 00:18:19,764\nIf you're on the Mac, some of these directories can return\n\n364\n00:18:19,766 --> 00:18:21,632\nmultiple things because there might be one on the network,\n\n365\n00:18:21,634 --> 00:18:23,201\nthere might be one on your local machine, etc. But\n\n366\n00:18:23,203 --> 00:18:26,304\nin iOS, there's always only the users, so it's always only\n\n367\n00:18:26,306 --> 00:18:29,574\none. So we just get the first one out of there. Okay now, I\n\n368\n00:18:29,576 --> 00:18:32,777\nhave the document's directory. Now I'm just going to append\n\n369\n00:18:32,779 --> 00:18:35,413\nto the end of that, it's a URL. So, I'm gonna append\n\n370\n00:18:35,415 --> 00:18:38,516\nto the end of that URL the name of the document.\n\n371\n00:18:38,518 --> 00:18:41,018\nOkay, so the URL is pointing to the document's directory.\n\n372\n00:18:41,020 --> 00:18:44,689\nIf I append the name of the document now I've got a URL to\n\n373\n00:18:44,691 --> 00:18:47,658\nthe document. Now that I have that I can just create a new\n\n374\n00:18:47,660 --> 00:18:51,696\nUIManagedDocument. Right? Just tell at the URL where it is.\n\n375\n00:18:51,698 --> 00:18:55,233\nBoom, so now I have UIManagedDocument. Okay, and\n\n376\n00:18:55,235 --> 00:18:57,902\nI could go get the managed object context from it,\n\n377\n00:18:57,904 --> 00:19:02,406\nexcept that managed object context is no good unless it's\n\n378\n00:19:02,408 --> 00:19:06,677\nopen. Okay? So here's where the asynchrony comes in. Okay,\n\n379\n00:19:06,679 --> 00:19:09,480\nwe have to open this ui managed document okay?\n\n380\n00:19:09,482 --> 00:19:12,116\nUsually we check first to see if it's already open.\n\n381\n00:19:12,118 --> 00:19:15,887\nOkay, you can ask the document is your document state normal?\n\n382\n00:19:15,889 --> 00:19:18,055\nThat means it's already open and ready to go. So\n\n383\n00:19:18,057 --> 00:19:20,291\nif that if it's in that state then you're good to go.\n\n384\n00:19:20,293 --> 00:19:23,494\nYou can just start using that managed object context thing,\n\n385\n00:19:23,496 --> 00:19:26,097\nbut it might be in this state closed right here,\n\n386\n00:19:26,099 --> 00:19:28,533\nwhich means it has not yet been opened. In that case,\n\n387\n00:19:28,535 --> 00:19:31,469\nyou cannot use the managed object context yet. Now,\n\n388\n00:19:31,471 --> 00:19:32,803\nwhat if it's closed? How do you open it?\n\n389\n00:19:32,805 --> 00:19:35,439\nWell, you have to use this asynchronous method here.\n\n390\n00:19:35,441 --> 00:19:40,211\nOkay? It's called open with completion handler, all right?\n\n391\n00:19:40,213 --> 00:19:42,813\nFirst you can find out if the file exists right here by\n\n392\n00:19:42,815 --> 00:19:46,217\nusing this file manager thing, file exists at path. Okay,\n\n393\n00:19:46,219 --> 00:19:48,452\nsee if you Document's already there.\n\n394\n00:19:48,454 --> 00:19:50,254\nIf it does exist then you're gonna open it,\n\n395\n00:19:50,256 --> 00:19:51,622\nby calling openWithCompletionHandler,\n\n396\n00:19:51,624 --> 00:19:54,091\nif it doesn't exist you're gonna create it by using\n\n397\n00:19:54,093 --> 00:19:57,461\nsaveToURL. These are both methods in UIMangedDocument\n\n398\n00:19:57,463 --> 00:20:02,433\nright? Notice that they take, both of them, a closure.\n\n399\n00:20:02,435 --> 00:20:06,737\nSee that? Okay? Why do they take that closure?\n\n400\n00:20:06,739 --> 00:20:09,840\nThat's because the open, or save, happens on another\n\n401\n00:20:09,842 --> 00:20:13,578\nthread. Why is that? Well, because UIManageDocument is\n\n402\n00:20:13,580 --> 00:20:16,714\nreally awesome. It works great with iCloud for\n\n403\n00:20:16,716 --> 00:20:17,648\nexample, okay? And\n\n404\n00:20:17,650 --> 00:20:20,418\nso, it might actually make a quick check on the network\n\n405\n00:20:20,420 --> 00:20:23,054\nto see what the status of this document is. Okay,\n\n406\n00:20:23,056 --> 00:20:26,457\nyou do not want that block in your main queue, okay.\n\n407\n00:20:26,459 --> 00:20:29,360\nSo these things, these closures, get called\n\n408\n00:20:29,362 --> 00:20:31,462\nafter the document has been opened, asynchronously.\n\n409\n00:20:31,464 --> 00:20:34,565\nNow usually these documents open almost instantaneously,\n\n410\n00:20:34,567 --> 00:20:38,169\nbut you're still going to get them open with this callback\n\n411\n00:20:38,171 --> 00:20:41,005\nand it tells you whether it was successful in doing it.\n\n412\n00:20:41,007 --> 00:20:43,741\nOkay? So the fact that this is asynchronous is\n\n413\n00:20:43,743 --> 00:20:45,810\ngonna make your code a little trickier, okay?\n\n414\n00:20:45,812 --> 00:20:47,645\nCuz you wanna open the document and start\n\n415\n00:20:47,647 --> 00:20:50,314\nusing ManagedObjectContext right away, but you can't.\n\n416\n00:20:50,316 --> 00:20:52,383\nYou have to wait until this closure gets called,\n\n417\n00:20:52,385 --> 00:20:56,654\nthen you can start using your ManagedObjectContext, okay?\n\n418\n00:20:56,656 --> 00:20:59,090\nThat's the only trickiness about it. All right, and\n\n419\n00:20:59,092 --> 00:21:01,726\nit's a little tricky that you have to see if it exists or,\n\n420\n00:21:01,728 --> 00:21:04,695\nto know whether to open it or to save it. Okay,\n\n421\n00:21:04,697 --> 00:21:07,131\nwhen you save it for the first time you're gonna do\n\n422\n00:21:07,133 --> 00:21:11,636\nforSaveOperation .ForCreating, okay? You can actually save\n\n423\n00:21:11,638 --> 00:21:14,572\nyour document if you want on top of the existing one by\n\n424\n00:21:14,574 --> 00:21:19,510\ndoing forSaveOperation for overriding. Okay.\n\n425\n00:21:19,512 --> 00:21:23,281\nSo it's all asynchronous so be careful about that.\n\n426\n00:21:23,283 --> 00:21:25,049\nThere's other states besides closed and\n\n427\n00:21:25,051 --> 00:21:28,085\nnormal that you might run into. These are pretty rare\n\n428\n00:21:28,087 --> 00:21:30,221\nstates I'm not gonna talk about any of them.\n\n429\n00:21:30,223 --> 00:21:31,856\nSome of them have Have to do with iCloud,\n\n430\n00:21:31,858 --> 00:21:34,692\nlike in conflict. Remember iCloud let's you see this\n\n431\n00:21:34,694 --> 00:21:36,527\ndocument on two different devices, your iPad and\n\n432\n00:21:36,529 --> 00:21:39,363\nyour iPhone, let's say. And you might change it on one and\n\n433\n00:21:39,365 --> 00:21:41,365\nthen try to change it on the other and now they conflict,\n\n434\n00:21:41,367 --> 00:21:44,902\nthe two changes might conflict in the database, right? So\n\n435\n00:21:44,904 --> 00:21:46,504\nthey can be in that state.\n\n436\n00:21:46,506 --> 00:21:49,307\nI'm not gonna ask you to handle any iCloud or\n\n437\n00:21:49,309 --> 00:21:50,641\nanything like that for this class,\n\n438\n00:21:50,643 --> 00:21:52,576\nbut you need to know if you're gonna do iCloud.\n\n439\n00:21:52,578 --> 00:21:55,112\nThen you might have some of these other states cropping\n\n440\n00:21:55,114 --> 00:21:59,483\nup. I thought it might be a fun thing to do in your final\n\n441\n00:21:59,485 --> 00:22:02,286\nproject. One of the things in your final project you have to\n\n442\n00:22:02,288 --> 00:22:04,288\ndo some feature I didn't go over in lecture.\n\n443\n00:22:04,290 --> 00:22:06,824\nWell, iCloud might be one of those. So maybe that would be\n\n444\n00:22:06,826 --> 00:22:10,795\nsomething you want to do. All right, let's talk about saving\n\n445\n00:22:10,797 --> 00:22:13,497\nthe document, because I got this managed object context.\n\n446\n00:22:13,499 --> 00:22:16,467\nAnd I'm going to be getting these in as managed objects,\n\n447\n00:22:16,469 --> 00:22:16,867\nlike tweets and\n\n448\n00:22:16,869 --> 00:22:18,769\ntwitter users aren't going to be changing them.\n\n449\n00:22:18,771 --> 00:22:21,906\nWhen does is actually get saved? Okay, and for\n\n450\n00:22:21,908 --> 00:22:25,109\nUIManagedDocument, it autosaves, which is really\n\n451\n00:22:25,111 --> 00:22:28,245\ncool. Basically autosaves when it thinks it's a good time, so\n\n452\n00:22:28,247 --> 00:22:31,615\nyou really don't ever have to save a UIManagedDocument.\n\n453\n00:22:31,617 --> 00:22:34,352\nYou can, by doing that ForOverwriting that I was\n\n454\n00:22:34,354 --> 00:22:38,456\ntalking about. But you really don't ever have to do that,\n\n455\n00:22:38,458 --> 00:22:40,624\nokay? It's just gonna automatically autosave for\n\n456\n00:22:40,626 --> 00:22:47,798\nyou. Closing the document, it also automatically closes,\n\n457\n00:22:47,800 --> 00:22:50,101\nso as soon nobody has a strong pointer to it and\n\n458\n00:22:50,103 --> 00:22:53,137\nit wants to leave the heap, it'll close automatically and\n\n459\n00:22:53,139 --> 00:22:56,607\nthen leave the heap. So that's cool too. But if you wanted to\n\n460\n00:22:56,609 --> 00:23:00,244\nforcible close it and still keep a strong pointer to it,\n\n461\n00:23:00,246 --> 00:23:02,246\nyou could do close with completion handler,\n\n462\n00:23:02,248 --> 00:23:04,382\nagain here's a closure, it takes time for\n\n463\n00:23:04,384 --> 00:23:08,753\nit to close. Probably micro seconds but anyway this will\n\n464\n00:23:08,755 --> 00:23:12,289\ntell you when it is actually closed. And then it's state,\n\n465\n00:23:12,291 --> 00:23:16,961\ndocument state will go back to dot closed okay.\n\n466\n00:23:16,963 --> 00:23:21,098\nAll right so now we have an NSManagedObjectContext.\n\n467\n00:23:21,100 --> 00:23:23,634\nWe either call that method in our app delegate to get it or\n\n468\n00:23:23,636 --> 00:23:26,537\nwe create new unmanaged document, opened it. And\n\n469\n00:23:26,539 --> 00:23:29,673\nin the closure once the closure's executed, bam, now\n\n470\n00:23:29,675 --> 00:23:33,210\nwe have this managed object context that we can access our\n\n471\n00:23:33,212 --> 00:23:37,715\ndatabases, okay? So, what do we do with it? How do we make\n\n472\n00:23:37,717 --> 00:23:41,051\nit work, okay? Well, let's talk about putting objects\n\n473\n00:23:41,053 --> 00:23:43,220\nin the database cuz until we've put something in there,\n\n474\n00:23:43,222 --> 00:23:44,989\nwe can't really do anything else with it.\n\n475\n00:23:44,991 --> 00:23:47,925\nHow do we do that? Well, we create objects\n\n476\n00:23:47,927 --> 00:23:52,096\nin the database by using this method right here called\n\n477\n00:23:52,098 --> 00:23:54,999\nInsertNewObjectForEntityForN- ame, okay?\n\n478\n00:23:55,001 --> 00:23:58,068\nThis is a static method, a class method.\n\n479\n00:23:58,070 --> 00:23:59,336\nIn the class NSEntityDescription.\n\n480\n00:23:59,338 --> 00:24:02,873\nNSEntityDescription is kind of a simple little class,\n\n481\n00:24:02,875 --> 00:24:05,042\nThat just describes the entities okay,\n\n482\n00:24:05,044 --> 00:24:07,978\nknows what all the properties are and all that.\n\n483\n00:24:07,980 --> 00:24:12,416\nWe only really use it for this one thing which is to create\n\n484\n00:24:12,418 --> 00:24:14,652\none of these things in the database okay. But\n\n485\n00:24:14,654 --> 00:24:17,855\nnotice that it takes in managedObjectContext, so\n\n486\n00:24:17,857 --> 00:24:19,490\nyou have to have a managedObjectContext or\n\n487\n00:24:19,492 --> 00:24:23,527\nyou cannot create a new object. Okay now when you\n\n488\n00:24:23,529 --> 00:24:26,197\ncreate this document or this object in there,\n\n489\n00:24:26,199 --> 00:24:30,434\nall of its properties or either nil or you can actually\n\n490\n00:24:30,436 --> 00:24:33,838\ngo in the inspector. In the little visual mapper.\n\n491\n00:24:33,840 --> 00:24:38,209\nYou can set defaults for some of the properties. Okay, so\n\n492\n00:24:38,211 --> 00:24:39,543\nit's either gonna be the default you set there or\n\n493\n00:24:39,545 --> 00:24:41,812\nif you didn't set a default, it'll just be nil. Okay, and\n\n494\n00:24:41,814 --> 00:24:44,682\nremember they're all objects, they're NSNumbers, NSDates,\n\n495\n00:24:44,684 --> 00:24:49,420\nall these properties. So that'll just be nil, okay. So\n\n496\n00:24:49,422 --> 00:24:52,756\nthis creates one. So now you've got a Tweet, it's of\n\n497\n00:24:52,758 --> 00:24:56,594\nclass, look what its class is, NSManagedObject, right.\n\n498\n00:24:56,596 --> 00:24:59,096\nTweet is an NSManagedObject. I just created one, so\n\n499\n00:24:59,098 --> 00:25:03,534\nI've got an empty Tweet. All it's Properties, it's text and\n\n500\n00:25:03,536 --> 00:25:07,071\neverything is nil, okay? All right, so\n\n501\n00:25:07,073 --> 00:25:10,374\nnow I've got one of these. How do I set the values?\n\n502\n00:25:10,376 --> 00:25:12,109\nOkay, well I already told you how to do that,\n\n503\n00:25:12,111 --> 00:25:14,445\nit's with this set value for key. Right,\n\n504\n00:25:14,447 --> 00:25:18,415\nso I can do setValue, some string, for key text, and I\n\n505\n00:25:18,417 --> 00:25:22,353\ncan set the text of the Tweet for example, okay? Same thing,\n\n506\n00:25:22,355 --> 00:25:25,256\nI kept the value for the key. One thing that's kind of cool,\n\n507\n00:25:25,258 --> 00:25:29,226\nthere's also this method called valueForKeyPath, okay?\n\n508\n00:25:29,228 --> 00:25:32,296\nThere's valueForKey and valueForKeyPath and\n\n509\n00:25:32,298 --> 00:25:36,166\nvalueForKeyPath, the string you pass to it can have dots\n\n510\n00:25:36,168 --> 00:25:41,105\nin it to follow relationships. So, if you said on a Tweet,\n\n511\n00:25:41,107 --> 00:25:45,042\nvalueForKeyPath Tweeter dot name,\n\n512\n00:25:45,044 --> 00:25:48,979\nit would give you the name of the Twitter user. It would\n\n513\n00:25:48,981 --> 00:25:52,983\nfollow that relationship over to the user and get the name.\n\n514\n00:25:52,985 --> 00:25:55,920\nEven though I'd be saying valueForKeyPath on a Tweet,\n\n515\n00:25:55,922 --> 00:25:58,556\ntweeter dot name on a Tweet is followed through\n\n516\n00:25:58,558 --> 00:26:03,060\nthe relationship so that's what the keyPath will do,\n\n517\n00:26:03,062 --> 00:26:07,064\ngot that? Now that sounds exciting I'm sure, but\n\n518\n00:26:07,066 --> 00:26:08,999\nwe actually almost never use these methods and\n\n519\n00:26:09,001 --> 00:26:12,136\nyou'll find out, in a moment why that is, okay.\n\n520\n00:26:12,138 --> 00:26:15,606\nSo that's the key that's the value I already talked about\n\n521\n00:26:15,608 --> 00:26:18,909\nwhat all the values are right NSData NSDate,\n\n522\n00:26:18,911 --> 00:26:22,046\nNSSet if it's a to-many relationship.\n\n523\n00:26:22,048 --> 00:26:24,381\nAn NSManagedObject if it's not, okay?\n\n524\n00:26:24,383 --> 00:26:28,485\nAll right, now changes, when you're changing something\n\n525\n00:26:28,487 --> 00:26:31,355\nin the database, that only happens in memory, okay?\n\n526\n00:26:31,357 --> 00:26:34,425\nDoesn't actually get stored in the database on disk until\n\n527\n00:26:34,427 --> 00:26:37,661\nit saves. Now, we know that UIManagedDocument autosaves,\n\n528\n00:26:37,663 --> 00:26:40,598\nso we're good to go there. But what if you use that other\n\n529\n00:26:40,600 --> 00:26:43,968\nManagedObjectContext? It's not in the UIManagedDocument, so\n\n530\n00:26:43,970 --> 00:26:47,605\nthere's no autosave there. You have to save it, okay. And\n\n531\n00:26:47,607 --> 00:26:51,008\nyou do that with this method called save, you send it to\n\n532\n00:26:51,010 --> 00:26:53,310\nthe ManagedObjectContext, right, so here's that\n\n533\n00:26:53,312 --> 00:26:55,946\nManagedObjectContext I got from my app delegate.\n\n534\n00:26:55,948 --> 00:26:59,283\nAnd I wanna save it so I'm gonna say contact.save.\n\n535\n00:26:59,285 --> 00:27:00,317\nNow, that looks simple, right,\n\n536\n00:27:00,319 --> 00:27:04,121\nsimple little four-letter function name there saved. But\n\n537\n00:27:04,123 --> 00:27:06,156\nactually it's gonna cause me to have to give you two or\n\n538\n00:27:06,158 --> 00:27:09,660\nthree slides worth of information about swift, okay?\n\n539\n00:27:09,662 --> 00:27:12,863\nBecause, this is the method that I'm showing you in this\n\n540\n00:27:12,865 --> 00:27:17,401\nclass that can throw an error, okay?\n\n541\n00:27:17,403 --> 00:27:21,805\nAnd why might save throw an error? Eh, disk could be full,\n\n542\n00:27:21,807 --> 00:27:24,875\nthere could be some problem the database that it can't be\n\n543\n00:27:24,877 --> 00:27:26,377\nsaved, there's lots of reasons,\n\n544\n00:27:26,379 --> 00:27:29,079\nokay that it could so, throw an error, but\n\n545\n00:27:29,081 --> 00:27:31,649\nwhat you need to know is how do I deal with that?\n\n546\n00:27:31,651 --> 00:27:33,784\nOkay, if it throws an error, what do I do,\n\n547\n00:27:33,786 --> 00:27:36,553\nhow do I look at the error, etc. And to do that, you need\n\n548\n00:27:36,555 --> 00:27:39,890\nto learn about how throw works in Swift. So let's take\n\n549\n00:27:39,892 --> 00:27:42,559\na little time out from Core Data, you probably, you're\n\n550\n00:27:42,561 --> 00:27:44,928\nsupposed to read about this in your reading assignment, but\n\n551\n00:27:44,930 --> 00:27:46,397\nI'm sure it probably went right over your.\n\n552\n00:27:46,399 --> 00:27:47,898\nHow many people in this room feel like yeah,\n\n553\n00:27:47,900 --> 00:27:51,201\nI pretty much understand throw? See, zero.\n\n554\n00:27:51,203 --> 00:27:53,804\nOkay, so that's why I'm gonna take a couple slides here and\n\n555\n00:27:53,806 --> 00:27:56,407\nexplain it to you. So all right, this is throwing errors\n\n556\n00:27:56,409 --> 00:27:59,743\nin Swift, a little side, you know, okay. So any function in\n\n557\n00:27:59,745 --> 00:28:03,714\nSwift, like the save method in MSManagedObjectContext if\n\n558\n00:28:03,716 --> 00:28:06,850\nit can throw an error, it will have the word throws,\n\n559\n00:28:06,852 --> 00:28:10,554\nat the end of its declaration, okay? So, the functions,\n\n560\n00:28:10,556 --> 00:28:12,690\nyou read that when you're reading the closing,\n\n561\n00:28:12,692 --> 00:28:17,094\nthe function save throws, all right?\n\n562\n00:28:17,096 --> 00:28:19,463\nSo, if you have a function that throws,\n\n563\n00:28:19,465 --> 00:28:24,501\nyou must deal with that. You cannot just ignore the fact\n\n564\n00:28:24,503 --> 00:28:28,305\nthat it throws, you must catch the error usually, okay?\n\n565\n00:28:28,307 --> 00:28:29,773\nThere's other ways to deal with it, but\n\n566\n00:28:29,775 --> 00:28:33,110\ngenerally you must catch it. So, how do you catch it? Well,\n\n567\n00:28:33,112 --> 00:28:36,880\nyou just put the word try in front of it. The try just\n\n568\n00:28:36,882 --> 00:28:40,584\nmeans please try this. Because I know it might throw but\n\n569\n00:28:40,586 --> 00:28:44,388\ntry it. Okay, so that's why it's called try. And if it's\n\n570\n00:28:44,390 --> 00:28:47,825\nsuccessful fine, if it doesn't then it throws an error.\n\n571\n00:28:47,827 --> 00:28:51,161\nNow when it throws the error you have to catch it and\n\n572\n00:28:51,163 --> 00:28:55,866\nthe way you catch it is you put this try inside of a do.\n\n573\n00:28:55,868 --> 00:28:58,736\nSee it says do open curly brace closed curly brace?\n\n574\n00:28:58,738 --> 00:29:03,474\nAnything inside this do that you try that throws,\n\n575\n00:29:03,476 --> 00:29:08,345\nwill allow you to catch the error right after the do,\n\n576\n00:29:08,347 --> 00:29:11,381\nokay? And so I can take catch let error here,\n\n577\n00:29:11,383 --> 00:29:14,218\nI can actually catch different kinds of errors by having\n\n578\n00:29:14,220 --> 00:29:18,288\nmultiple catches here. Catch this, catch that, catch this,\n\n579\n00:29:18,290 --> 00:29:21,225\nas many catches as I want, okay. And\n\n580\n00:29:21,227 --> 00:29:23,560\nwhen I catch it you see I have this let error,\n\n581\n00:29:23,562 --> 00:29:26,930\nthat basically lets this local variable here that's gonna be\n\n582\n00:29:26,932 --> 00:29:32,202\nin this context error, it lets it be equal to the error\n\n583\n00:29:32,204 --> 00:29:36,340\nthat was thrown, okay. So now you have this error and\n\n584\n00:29:36,342 --> 00:29:38,709\nyou, inside here inside this second curly brace here,\n\n585\n00:29:38,711 --> 00:29:41,211\nyou can look at that error and find out what it is and\n\n586\n00:29:41,213 --> 00:29:45,249\nwhy clean up or try again or whatever you want to do,\n\n587\n00:29:45,251 --> 00:29:48,819\nyou can do it in here. Now these errors that get thrown\n\n588\n00:29:48,821 --> 00:29:54,424\nthey are all implementors of this protocol ErrorType.\n\n589\n00:29:54,426 --> 00:29:56,527\nAnd this ErrorType protocol doesn't have much in it.\n\n590\n00:29:56,529 --> 00:29:59,630\nIt's mostly just a way to identify that this is an error\n\n591\n00:29:59,632 --> 00:30:04,835\nthat got thrown, okay. Now iOS has a very important class\n\n592\n00:30:04,837 --> 00:30:08,539\ncalled NSError which implements this protocol.\n\n593\n00:30:08,541 --> 00:30:10,908\nWhen iOS throws an error it's always gonna\n\n594\n00:30:10,910 --> 00:30:15,045\nbe an NSError. Okay, and that class you should go look at.\n\n595\n00:30:15,047 --> 00:30:19,049\nOkay, it has methods in there like localized description of\n\n596\n00:30:19,051 --> 00:30:21,485\nthe error. Things like that that\n\n597\n00:30:21,487 --> 00:30:24,621\nyou can use to put errors up to the user even or certainly\n\n598\n00:30:24,623 --> 00:30:26,723\nput things on the console to say what's going on or\n\n599\n00:30:26,725 --> 00:30:29,793\njust to look at it yourself, like what did that error etc.,\n\n600\n00:30:29,795 --> 00:30:32,963\nokay. So NSError is kind of iOS's thing.\n\n601\n00:30:32,965 --> 00:30:35,833\nBut if you had something that you thought\n\n602\n00:30:35,835 --> 00:30:36,633\nwould be good to throw an error,\n\n603\n00:30:36,635 --> 00:30:39,870\nyou can invent your own thing that gets thrown as long as\n\n604\n00:30:39,872 --> 00:30:42,472\nit implements this ErrorType protocol,\n\n605\n00:30:42,474 --> 00:30:45,042\nokay. Now usually the things that implement the ErrorType\n\n606\n00:30:45,044 --> 00:30:48,812\nprotocol are enums. Because when you have something that\n\n607\n00:30:48,814 --> 00:30:51,014\ncan throw an error it usually can throw two or\n\n608\n00:30:51,016 --> 00:30:52,616\nthree different kinds of things. And so\n\n609\n00:30:52,618 --> 00:30:56,954\nthat each of those is an enum case with associated data that\n\n610\n00:30:56,956 --> 00:31:00,324\ngoes along with the error. All right, that's the great thing\n\n611\n00:31:00,326 --> 00:31:02,860\nabout enums, if you've got this associated data so\n\n612\n00:31:02,862 --> 00:31:05,729\nif there's an error you can, you know, hand along some\n\n613\n00:31:05,731 --> 00:31:08,432\ninteresting information about the error. Okay,\n\n614\n00:31:08,434 --> 00:31:13,270\nnow if inside the catch you can't deal with this error,\n\n615\n00:31:13,272 --> 00:31:16,740\nyou could re-throw it by just saying throw error.\n\n616\n00:31:16,742 --> 00:31:18,575\nIn fact in general anytime you wanna throw an error,\n\n617\n00:31:18,577 --> 00:31:20,077\nthat's how you do it, you say throw error and\n\n618\n00:31:20,079 --> 00:31:23,447\nagain this has to be a type error type protocol there.\n\n619\n00:31:23,449 --> 00:31:24,314\nYou can throw it and re-throw it now,\n\n620\n00:31:24,316 --> 00:31:26,950\nthe only thing about this is if you're gonna re-throw here\n\n621\n00:31:26,952 --> 00:31:31,622\nmaybe then your whole method also has to say throws at\n\n622\n00:31:31,624 --> 00:31:36,827\nthe end, because you might be re-throwing, okay? Okay,\n\n623\n00:31:36,829 --> 00:31:39,229\nso that's basically how fundamentally works.\n\n624\n00:31:39,231 --> 00:31:43,200\nNow, there's an extra little interesting thing here which\n\n625\n00:31:43,202 --> 00:31:45,469\ntry with an exclamation point.\n\n626\n00:31:45,471 --> 00:31:48,805\nOkay, if you try with an exclamation point, that means\n\n627\n00:31:48,807 --> 00:31:51,341\nforget all this junk. I'm not gonna put in a do.\n\n628\n00:31:51,343 --> 00:31:54,645\nI'm not gonna catch anything. And if this throws,\n\n629\n00:31:54,647 --> 00:31:57,547\ncrash my app. Okay, we know that exclamation point\n\n630\n00:31:57,549 --> 00:32:00,550\nusually means force this thing and crash if it doesn't work.\n\n631\n00:32:00,552 --> 00:32:03,787\nThat's what for implicit for Optional unwrapping right,\n\n632\n00:32:03,789 --> 00:32:06,924\nwe do exclamation point boom that means crash if this thing\n\n633\n00:32:06,926 --> 00:32:10,460\nis nil. So same thing here you can say try and it'll crash.\n\n634\n00:32:10,462 --> 00:32:13,230\nNow you would never wanna do that with context save because\n\n635\n00:32:13,232 --> 00:32:16,767\ncontext save can get errors unpredictably right.\n\n636\n00:32:16,769 --> 00:32:17,834\nSo you never wanna do that here but\n\n637\n00:32:17,836 --> 00:32:20,871\nother methods sometimes it's like this method has to\n\n638\n00:32:20,873 --> 00:32:24,074\nsucceed or I'm just doomed. So I'm going to\n\n639\n00:32:24,076 --> 00:32:26,977\ntry exclamation point. There's one other way which I'm going\n\n640\n00:32:26,979 --> 00:32:29,579\nto talk about in a few slides which is try question mark.\n\n641\n00:32:29,581 --> 00:32:34,551\nOkay? Try question mark means try this, I'm not going to\n\n642\n00:32:34,553 --> 00:32:38,755\ncatch the error, but return nil if there was a thrown\n\n643\n00:32:38,757 --> 00:32:41,391\nerror. Okay? That's right, question mark and I'm gonna\n\n644\n00:32:41,393 --> 00:32:43,694\nshow you an example of that in a couple slides. Okay, so\n\n645\n00:32:43,696 --> 00:32:46,930\nthat's throwing errors. You got that. There's not\n\n646\n00:32:46,932 --> 00:32:48,498\na lot of things that throw errors, but\n\n647\n00:32:48,500 --> 00:32:52,536\nyou are gonna run across them. Both in some of the homeworks\n\n648\n00:32:52,538 --> 00:32:56,506\nand also certainly in your final project. Okay, so let's\n\n649\n00:32:56,508 --> 00:33:01,478\nget back to core data here. Now, calling valueForKey and\n\n650\n00:33:01,480 --> 00:33:04,047\nsetValue(forKey:) is pretty ugly. Okay,\n\n651\n00:33:04,049 --> 00:33:06,917\nthere's no type-checking there, because it's any object\n\n652\n00:33:06,919 --> 00:33:08,352\nis the type of the argument. Okay, and\n\n653\n00:33:08,354 --> 00:33:12,255\nyou've got all these literal strings [LAUGH] like text and\n\n654\n00:33:12,257 --> 00:33:16,994\ncreated and id inside your code, which\n\n655\n00:33:16,996 --> 00:33:20,564\nyou probably are gonna put in a struct static let like you\n\n656\n00:33:20,566 --> 00:33:23,000\ndo all your constants. But it's just a mess, okay.\n\n657\n00:33:23,002 --> 00:33:26,370\nWhat you really want is vars. You want these Tweets,\n\n658\n00:33:26,372 --> 00:33:28,638\nyou wanna be able to have a var on there called text.\n\n659\n00:33:28,640 --> 00:33:31,441\nAnd you just wanna say that tweet.text equals,\n\n660\n00:33:31,443 --> 00:33:33,343\nthat's what you want, okay? An object-oriented.\n\n661\n00:33:33,345 --> 00:33:36,747\nSo, of course, we can do that. And the way we do that is\n\n662\n00:33:36,749 --> 00:33:41,118\nwe're gonna create a sub class of ns managed object. Okay? So\n\n663\n00:33:41,120 --> 00:33:43,620\nfor each thing a tweet, Twitter user whatever, we're\n\n664\n00:33:43,622 --> 00:33:46,223\ngonna create a sub class of ns object managed object for\n\n665\n00:33:46,225 --> 00:33:50,193\nit and it's gonna have vars which are all the properties.\n\n666\n00:33:50,195 --> 00:33:52,796\nOkay? Couldn't be easier. Really simply.\n\n667\n00:33:52,798 --> 00:33:56,833\nAnd x code will even generate this sub class for\n\n668\n00:33:56,835 --> 00:33:59,569\nus. Okay, so let's look at how you do that. So I'm\n\n669\n00:33:59,571 --> 00:34:02,239\ngonna select the entities that I wanna generate these little\n\n670\n00:34:02,241 --> 00:34:05,375\nsub classes for. Okay, so I'm selecting both in this case\n\n671\n00:34:05,377 --> 00:34:08,478\nright here. Then I go up to the editor menu and\n\n672\n00:34:08,480 --> 00:34:14,551\nI pick Create NSManagedObject Subclass. When I do\n\n673\n00:34:14,553 --> 00:34:17,254\nthat it's gonna say okay for which of your models do you\n\n674\n00:34:17,256 --> 00:34:19,456\nwant to do that because you might have multiple models,\n\n675\n00:34:19,458 --> 00:34:22,492\nso I'll pick the only model I have here.\n\n676\n00:34:22,494 --> 00:34:24,428\nThen it says okay which entities?\n\n677\n00:34:24,430 --> 00:34:27,164\nWell, I selected both so it's got these both pre-selected.\n\n678\n00:34:27,166 --> 00:34:31,201\nI wanna create a menus managed object subclass for tweet and\n\n679\n00:34:31,203 --> 00:34:34,204\none for twitter users. It can be two different classes.\n\n680\n00:34:34,206 --> 00:34:37,140\nOkay now, it's saying where do you wanna put it, it's also\n\n681\n00:34:37,142 --> 00:34:39,509\nasking what language? Be careful right here sometimes\n\n682\n00:34:39,511 --> 00:34:42,379\nthis comes up Objective-C even if you're in a Swift project.\n\n683\n00:34:42,381 --> 00:34:44,414\nSo make sure that says Swift otherwise you're gonna get an\n\n684\n00:34:44,416 --> 00:34:49,653\nObjective- C class. Which is a subclass of that's a swift.\n\n685\n00:34:49,655 --> 00:34:52,189\nThe other thing is there's this uscaler properties for\n\n686\n00:34:52,191 --> 00:34:55,258\nprimitive data types. Be careful of this one,\n\n687\n00:34:55,260 --> 00:34:56,460\nif you turn this on, then for\n\n688\n00:34:56,462 --> 00:34:59,830\nexample NSDate, the property it creates, or the var,\n\n689\n00:34:59,832 --> 00:35:01,031\nis going to be an NSTime interval.\n\n690\n00:35:01,033 --> 00:35:05,235\nWhich is going to be the number of seconds since 1970,\n\n691\n00:35:05,237 --> 00:35:08,138\nokay. So you probably don't want that most of the time,\n\n692\n00:35:08,140 --> 00:35:11,708\nright, you want it to be an NSDate object. Also you're\n\n693\n00:35:11,710 --> 00:35:14,211\ngonna put it, this is gonna say where you're gonna put it.\n\n694\n00:35:14,213 --> 00:35:16,780\nBy default it usually says to put it at the very top\n\n695\n00:35:16,782 --> 00:35:19,249\nlevel, but you usually actually want it down where\n\n696\n00:35:19,251 --> 00:35:22,853\nall the rest of your files are down here like in core data\n\n697\n00:35:22,855 --> 00:35:23,954\nexample, right?\n\n698\n00:35:23,956 --> 00:35:26,690\nSo make sure you get that right too. So, be,\n\n699\n00:35:26,692 --> 00:35:28,158\npay attention to this thing and\n\n700\n00:35:28,160 --> 00:35:29,926\nanswer all these questions the way you want. Okay?\n\n701\n00:35:29,928 --> 00:35:33,196\nIt's not one that you can just click Create and just move on\n\n702\n00:35:33,198 --> 00:35:35,365\nthrough or you won't get what you want, I don't think.\n\n703\n00:35:35,367 --> 00:35:39,870\nAll right, so it created these things. Here they are,\n\n704\n00:35:39,872 --> 00:35:41,705\nyou can see them on the side here. There's one,\n\n705\n00:35:41,707 --> 00:35:45,675\nTweet.swift, okay? There's TwitterUser.swift.\n\n706\n00:35:45,677 --> 00:35:48,645\nAnd it's just a class tweet as promised.\n\n707\n00:35:48,647 --> 00:35:51,281\nLook at that, it inherits from NSManagedObject, and\n\n708\n00:35:51,283 --> 00:35:54,651\nyou could put any code you want in here to do\n\n709\n00:35:54,653 --> 00:35:57,220\ntweet specific stuff. Because the fact\n\n710\n00:35:57,222 --> 00:35:58,989\nthat the tweet is stored in the database is great but\n\n711\n00:35:58,991 --> 00:36:01,391\nit might also have some other behavior that you want to add.\n\n712\n00:36:01,393 --> 00:36:04,561\nIt's just a class, right, you're using it in your app so\n\n713\n00:36:04,563 --> 00:36:06,863\nyou might want to put some code in there, okay, so\n\n714\n00:36:06,865 --> 00:36:10,734\nit's perfectly good for that. Here's TwitterUser,\n\n715\n00:36:10,736 --> 00:36:15,138\nright Okay, put all your Twitter user stuff here. But\n\n716\n00:36:15,140 --> 00:36:16,873\nwhat about those vars? Okay,\n\n717\n00:36:16,875 --> 00:36:19,876\nI thought there was going to be vars for text and\n\n718\n00:36:19,878 --> 00:36:22,746\ncreated and the screen name for, where are those? Well,\n\n719\n00:36:22,748 --> 00:36:25,549\nit turns out those are put in extensions, you see them right\n\n720\n00:36:25,551 --> 00:36:27,651\nhere, there's two of them, that one and that one, so\n\n721\n00:36:27,653 --> 00:36:30,353\nlet's look at those, okay. This file right here,\n\n722\n00:36:30,355 --> 00:36:34,925\nthis extension. This is creating a property of R for\n\n723\n00:36:34,927 --> 00:36:37,661\neach of the things, the attributes and\n\n724\n00:36:37,663 --> 00:36:40,830\nrelationships to in my Tweet object.\n\n725\n00:36:40,832 --> 00:36:43,867\nNow, why does it put them off in an extension here? Why\n\n726\n00:36:43,869 --> 00:36:46,203\ndidn't it just put it in the other class? Can anyone think\n\n727\n00:36:46,205 --> 00:36:50,340\nof a reason why this would be an extension? It's a good\n\n728\n00:36:50,342 --> 00:36:54,211\nreason actually which is that, you might wanna change these\n\n729\n00:36:54,213 --> 00:36:56,680\nattributes in relationship over time that you're working\n\n730\n00:36:56,682 --> 00:36:58,982\non your app. You decide you need a new property, okay?\n\n731\n00:36:58,984 --> 00:37:02,953\nWell you gonna regenerate this file. When you do that, you\n\n732\n00:37:02,955 --> 00:37:05,689\ndon't wanna blow away in the other code that you wrote for\n\n733\n00:37:05,691 --> 00:37:08,458\ntweet. Right, so it keeps all the stuff that's being\n\n734\n00:37:08,460 --> 00:37:13,296\ngenerated by x code when you do that create subclass,\n\n735\n00:37:13,298 --> 00:37:15,131\nit's keeping it all in one file so it can be constantly\n\n736\n00:37:15,133 --> 00:37:19,502\noverwritten. Make sense? See, that's why we put an extension\n\n737\n00:37:19,504 --> 00:37:22,739\nthere. Now lets look at this wacky extension here,\n\n738\n00:37:22,741 --> 00:37:25,275\nwhat's going on here? Well these are obvious,\n\n739\n00:37:25,277 --> 00:37:29,045\ntext, ID and created, why are they optional? Because they're\n\n740\n00:37:29,047 --> 00:37:31,915\nnil when you first create a tweet it's empty those things\n\n741\n00:37:31,917 --> 00:37:35,452\nare all nil so it has to be an optional, and then look at\n\n742\n00:37:35,454 --> 00:37:39,089\nthis one. Tweeter has promised again twitter users.\n\n743\n00:37:39,091 --> 00:37:41,825\nNow I told you that tweeter since it's a relationship\n\n744\n00:37:41,827 --> 00:37:45,295\nwould be an NS managed object But the system is smart enough\n\n745\n00:37:45,297 --> 00:37:47,530\nto say, well not only is it an NSManaged object,\n\n746\n00:37:47,532 --> 00:37:49,432\nbut I know it's a TwitterUser. Okay,\n\n747\n00:37:49,434 --> 00:37:52,702\nwhich is this other class over here that it created.\n\n748\n00:37:52,704 --> 00:37:54,537\nBy the way, sometimes when you generate a whole\n\n749\n00:37:54,539 --> 00:37:58,742\nbunch of things at once, it will miss that. Okay,\n\n750\n00:37:58,744 --> 00:38:02,145\nit will notice, it will just have this NSManaged object,\n\n751\n00:38:02,147 --> 00:38:06,283\njust regenerate them again if that happens. Okay?\n\n752\n00:38:06,285 --> 00:38:07,384\nIt's just like, cause it's like a one,\n\n753\n00:38:07,386 --> 00:38:10,220\ninstead of being a two phase generation, it's like a one\n\n754\n00:38:10,222 --> 00:38:12,522\nphase generation; if it does one class before the other.\n\n755\n00:38:12,524 --> 00:38:14,758\nIt didn't know that twitter user existed by the time it\n\n756\n00:38:14,760 --> 00:38:18,161\ndid tweet. So, I don't know, hopefully they'll fix that\n\n757\n00:38:18,163 --> 00:38:20,330\nsomeday. Might already be fixed in the latest version,\n\n758\n00:38:20,332 --> 00:38:23,867\nbut just regenerate if you get that problem. So\n\n759\n00:38:23,869 --> 00:38:25,368\nanyway, Tweeter is a Twitter user,\n\n760\n00:38:25,370 --> 00:38:27,404\nthat makes sense, right? That's what a Tweeter is,\n\n761\n00:38:27,406 --> 00:38:29,639\nit's a Twitter user. Let's go look at Tweet,\n\n762\n00:38:29,641 --> 00:38:32,742\nit's the same thing here. Here's the screen name and\n\n763\n00:38:32,744 --> 00:38:35,145\nthe name, those are string. Now look at tweets,\n\n764\n00:38:35,147 --> 00:38:39,716\nit's an NS set and inside this NS set is going to be,\n\n765\n00:38:39,718 --> 00:38:44,921\nwhat? Tweet objects, right because that's what this is,\n\n766\n00:38:44,923 --> 00:38:47,490\nthe Tweets that this Twitter user has Tweeted. So\n\n767\n00:38:47,492 --> 00:38:50,627\nthis NS set is gonna have Tweet, Tweet objects.\n\n768\n00:38:50,629 --> 00:38:54,264\nSee this class right up here. Okay,\n\n769\n00:38:54,266 --> 00:38:58,868\nnow what about this @NSManaged thing? What the heck,\n\n770\n00:38:58,870 --> 00:39:00,737\nwe never seen that before. What is that?\n\n771\n00:39:00,739 --> 00:39:04,174\nOkay, well, that's basically just some magic that says\n\n772\n00:39:04,176 --> 00:39:07,644\nthe system is gonna take of that, of this bar, okay?\n\n773\n00:39:07,646 --> 00:39:10,547\nBecause otherwise, where is this bar stored?\n\n774\n00:39:10,549 --> 00:39:13,149\nIt can't just be a normal stored property because\n\n775\n00:39:13,151 --> 00:39:15,985\nwhen it changes, it needs to change in the database, so\n\n776\n00:39:15,987 --> 00:39:18,254\nit's got to be code going on there.\n\n777\n00:39:18,256 --> 00:39:21,191\nIt kind of could be a computer property but you certainly\n\n778\n00:39:21,193 --> 00:39:24,027\ndon't want the computer property code in here. So,\n\n779\n00:39:24,029 --> 00:39:28,698\nthis NSManage basically says that it's a dynamic, bar and\n\n780\n00:39:28,700 --> 00:39:33,603\nwhen it gets accessed it causes other code in core data\n\n781\n00:39:33,605 --> 00:39:33,837\nto be executed.\n\n782\n00:39:33,839 --> 00:39:37,107\nAnd that's basically going to do value and value for key and\n\n783\n00:39:37,109 --> 00:39:40,210\nset value for key for you. Yeah.\n\n784\n00:39:40,212 --> 00:39:43,480\n>> A name like \"TwitterUser\",\n\n785\n00:39:43,482 --> 00:39:45,982\nwould it change every time >> [INAUDIBLE] Yeah, so\n\n786\n00:39:45,984 --> 00:39:49,018\nthe question is what if I change the key like like\n\n787\n00:39:49,020 --> 00:39:52,122\nif I rename screen name to be an ampersand name or\n\n788\n00:39:52,124 --> 00:39:54,624\nsomething like that. No, you have to go back and\n\n789\n00:39:54,626 --> 00:39:57,227\nregenerate them okay they will always have to regenerate.\n\n790\n00:39:57,229 --> 00:40:00,196\nThis is not captain sync with the visual map you have to\n\n791\n00:40:00,198 --> 00:40:04,067\nregenerate all the time. Again that's why you want this to be\n\n792\n00:40:04,069 --> 00:40:05,902\na separate file from the other thing.\n\n793\n00:40:05,904 --> 00:40:09,539\nOkay, so ns manage is just magic that core data uses.\n\n794\n00:40:09,541 --> 00:40:13,410\nYou don't even have to worry about it, you're never gonna\n\n795\n00:40:13,412 --> 00:40:14,811\nhave to actually type this in or anything.\n\n796\n00:40:14,813 --> 00:40:19,883\nIt's always just in this generated thing. Okay, so,\n\n797\n00:40:19,885 --> 00:40:25,155\nhow do I access these entities using these sub classes and\n\n798\n00:40:25,157 --> 00:40:28,458\nget the properties. Okay, so, it's pretty simple.\n\n799\n00:40:28,460 --> 00:40:30,160\nLet's say I get my manage of the context.\n\n800\n00:40:30,162 --> 00:40:32,362\nHere, I'm getting it from my UI managed document,\n\n801\n00:40:32,364 --> 00:40:35,165\nbut I could have got it from my app delegate, whatever,\n\n802\n00:40:35,167 --> 00:40:35,932\nI got my context.\n\n803\n00:40:35,934 --> 00:40:39,002\nI'm gonna create one by saying insert new object for\n\n804\n00:40:39,004 --> 00:40:41,204\na different name, same as before. Except for\n\n805\n00:40:41,206 --> 00:40:46,142\nlook at the yellow text, I'm gonna cast it, downcast it\n\n806\n00:40:46,144 --> 00:40:50,246\nto be a tweet. Because I know that these tweet entities have\n\n807\n00:40:50,248 --> 00:40:55,118\nthis associated subclass with them. Got it? So that's\n\n808\n00:40:55,120 --> 00:40:59,122\nthe magic right there. That's the thing that turns this\n\n809\n00:40:59,124 --> 00:41:01,491\nTweet that you're creating into a tweet so that now\n\n810\n00:41:01,493 --> 00:41:04,961\nthat it's a tweet you can say things like tweet.tweeter = or\n\n811\n00:41:04,963 --> 00:41:09,499\ntweet.created = or tweet.text =, tweet.tweeter.name =,\n\n812\n00:41:09,501 --> 00:41:12,836\nyou can even do. Okay, see what's happened here?\n\n813\n00:41:12,838 --> 00:41:13,937\nTweet.tweeter.name.\n\n814\n00:41:13,939 --> 00:41:17,106\nI'm actually just using properties. To go through,\n\n815\n00:41:17,108 --> 00:41:19,809\nwe know the type of Tweeter is a Twitter user, and\n\n816\n00:41:19,811 --> 00:41:25,915\nwe know the twitter user has a bar which is the name.\n\n817\n00:41:27,085 --> 00:41:30,920\nSo, this is a lot nicer than saying set value, this,\n\n818\n00:41:30,922 --> 00:41:33,957\ncomma, for key, text.\n\n819\n00:41:37,028 --> 00:41:39,996\nSwift code, and also Swift can type check all of this to make\n\n820\n00:41:39,998 --> 00:41:45,535\nsure you're providing the right types, all right? Okay,\n\n821\n00:41:45,537 --> 00:41:48,338\nso now let's talk about deletion briefly.\n\n822\n00:41:48,340 --> 00:41:53,309\nYou can delete objects from the database. It's very easy,\n\n823\n00:41:53,311 --> 00:41:57,514\nit's almost too easy. You just call deleteObject, okay?\n\n824\n00:41:57,516 --> 00:41:59,182\nAnd it will delete from the database.\n\n825\n00:41:59,184 --> 00:42:02,385\nThere's a little bit of a question, if I delete a tweet,\n\n826\n00:42:02,387 --> 00:42:02,919\ndoes it delete the Twitter user who tweeted it?\n\n827\n00:42:02,921 --> 00:42:05,622\nProbably not. If I delete a Twitter user, does it delete\n\n828\n00:42:11,563 --> 00:42:14,831\nall the tweets that the Twitter user tweeted? Maybe\n\n829\n00:42:14,833 --> 00:42:19,836\nso, okay? So you can determine that rule for what happens\n\n830\n00:42:19,838 --> 00:42:23,106\nwhen something is deleted back in the Visual Mapper. You just\n\n831\n00:42:23,108 --> 00:42:26,109\ninspect the relationship and you can put the delete rule in\n\n832\n00:42:26,111 --> 00:42:29,145\nthere. You can read all about what the settings are,\n\n833\n00:42:29,147 --> 00:42:33,316\nin the documentation. But you can basically have cascading\n\n834\n00:42:33,318 --> 00:42:35,218\ndeletes that delete, like that's probably what\n\n835\n00:42:35,220 --> 00:42:37,487\nyou would have if you deleted a Twitter user.\n\n836\n00:42:37,489 --> 00:42:37,620\nIt would cascade and\n\n837\n00:42:37,622 --> 00:42:40,823\ndelete all the tweets. And you can have just a nilling one,\n\n838\n00:42:40,825 --> 00:42:43,960\nwhere if you deleted a certain tweet, it's just going to\n\n839\n00:42:43,962 --> 00:42:47,764\nremove it from the set, and the Twitter user's set will be\n\n840\n00:42:47,766 --> 00:42:52,835\nautomatically updated, okay? One thing, once you delete\n\n841\n00:42:52,837 --> 00:42:55,538\nthis tweet, make sure you don't keep a strong pointer to\n\n842\n00:42:55,540 --> 00:42:58,274\nit because it now points to something that's invalid.\n\n843\n00:42:58,276 --> 00:43:01,044\nCuz you deleted it from the database so you can't set any\n\n844\n00:43:01,046 --> 00:43:03,680\nof its attributes or do anything cuz it's gone.\n\n845\n00:43:03,682 --> 00:43:06,482\nSo it kinda gets into a weird state here [COUGH].\n\n846\n00:43:06,484 --> 00:43:10,753\nJust make sure you don't do anything with that. All right,\n\n847\n00:43:10,755 --> 00:43:14,023\none thing that's kind of fun about deletion here is that\n\n848\n00:43:14,025 --> 00:43:16,893\nyour NsMangedObject subclass like tweet or\n\n849\n00:43:16,895 --> 00:43:21,331\nTwitterUser will be sent this method, prepareForDeletion,\n\n850\n00:43:21,333 --> 00:43:24,901\nwhen someone tries to delete it, and in there you can\n\n851\n00:43:24,903 --> 00:43:28,137\ndo a lot of things. You could decrement some count for\n\n852\n00:43:28,139 --> 00:43:30,239\nexample if you're keeping a track of a count or\n\n853\n00:43:30,241 --> 00:43:33,509\nsomething like that. One thing you don't have to do in here\n\n854\n00:43:33,511 --> 00:43:36,012\nthough is modify in a relationships.\n\n855\n00:43:36,014 --> 00:43:37,614\nThat happens for you automatically.\n\n856\n00:43:37,616 --> 00:43:42,418\nSo if I delete a tweet k? From the database, it automatically\n\n857\n00:43:42,420 --> 00:43:46,456\ngets removed from any ns sets that Twitter users point to,\n\n858\n00:43:46,458 --> 00:43:50,560\neven if I go into an NS set, okay, of tweets and\n\n859\n00:43:50,562 --> 00:43:54,864\nI delete a tweet out of there, it will [INAUDIBLE] you know,\n\n860\n00:43:54,866 --> 00:43:58,267\nany, both sides of every relationship get updated. So\n\n861\n00:43:58,269 --> 00:44:00,703\nyou never have to update either side of a relationship.\n\n862\n00:44:00,705 --> 00:44:03,439\nYou touch one, the other side stays in synch.\n\n863\n00:44:03,441 --> 00:44:05,942\nThat's one of the really cool things about core data. So\n\n864\n00:44:05,944 --> 00:44:07,343\nyou don't have to do that in a prepare for\n\n865\n00:44:07,345 --> 00:44:10,113\ndeletion. Prepare for deletion lets you do other things,\n\n866\n00:44:10,115 --> 00:44:12,649\nother things you might be counting or\n\n867\n00:44:12,651 --> 00:44:15,785\ndoing other things.\n\n868\n00:44:15,787 --> 00:44:19,288\nSo now we know how to create our database, set all the data\n\n869\n00:44:19,290 --> 00:44:22,925\nin there, it's awesome. Now we get to the real value of\n\n870\n00:44:22,927 --> 00:44:25,762\nhaving the data in there which is querying, okay. So\n\n871\n00:44:25,764 --> 00:44:28,064\nnow we wanna go and look in the database and\n\n872\n00:44:28,066 --> 00:44:32,769\nget the objects we want based on certain criteria, okay. And\n\n873\n00:44:32,771 --> 00:44:37,140\nhow do we do that? The main\n\n874\n00:44:37,142 --> 00:44:40,943\nPiece of this is this class called NSFETCH request,\n\n875\n00:44:40,945 --> 00:44:44,380\nokay? And in NSFETCH request we're going to specify\n\n876\n00:44:44,382 --> 00:44:46,349\nwhich objects we want out of the database, and\n\n877\n00:44:46,351 --> 00:44:49,018\nthey're going to come back in an array, it's as simple as\n\n878\n00:44:49,020 --> 00:44:52,855\nthat, okay? So, how do we create an NSFETCH request?\n\n879\n00:44:52,857 --> 00:44:56,259\nWe need four things. One, the entity to fetch.\n\n880\n00:44:56,261 --> 00:44:58,995\nThis is very important to understand. Okay. You can only\n\n881\n00:44:58,997 --> 00:45:02,732\nfetch one kind of thing with a fetch request. There's no\n\n882\n00:45:02,734 --> 00:45:05,835\nfetch request in the world that's gonna give you an array\n\n883\n00:45:05,837 --> 00:45:08,738\nof some tweets and some Twitter users.\n\n884\n00:45:08,740 --> 00:45:11,674\nIt's always gonna give you an array of all the same thing,\n\n885\n00:45:11,676 --> 00:45:14,877\nall tweets, or all Twitter users. Okay?\n\n886\n00:45:14,879 --> 00:45:18,648\nSo, you specify the entity, the one entity that's going to\n\n887\n00:45:18,650 --> 00:45:22,418\nbe in this fetch request. All right? Second thing is\n\n888\n00:45:22,420 --> 00:45:26,255\nhow many objects you want to limit your fetch to,\n\n889\n00:45:26,257 --> 00:45:28,224\nlike maybe you only want to fetch 100 or\n\n890\n00:45:28,226 --> 00:45:30,793\nyou want to fetch them in groups of 20 or 40 or\n\n891\n00:45:30,795 --> 00:45:34,831\nsomething like that. You can specify that in the request.\n\n892\n00:45:34,833 --> 00:45:37,700\nYou can specify how to sort the result because I told you\n\n893\n00:45:37,702 --> 00:45:41,738\nthe result comes back as an array, arrays are ordered. So\n\n894\n00:45:41,740 --> 00:45:44,874\nyou can specify what order the things you're fetching come\n\n895\n00:45:44,876 --> 00:45:48,578\nback in. All right? And then lastly and most importantly,\n\n896\n00:45:48,580 --> 00:45:50,079\nyou're gonna specify the predicate.\n\n897\n00:45:50,081 --> 00:45:55,818\nThis is the description of which objects you want. Okay?\n\n898\n00:45:55,820 --> 00:45:59,088\nSo, let's look at all of this things. Here's what the code\n\n899\n00:45:59,090 --> 00:46:01,157\nlooks like. Basically to create a request right here.\n\n900\n00:46:01,159 --> 00:46:02,458\nSo, let's look at all parts of this.\n\n901\n00:46:02,460 --> 00:46:03,559\nSo, we're creating a request for\n\n902\n00:46:03,561 --> 00:46:06,562\nthe certain entity. Here I'm saying the BatchSize and\n\n903\n00:46:06,564 --> 00:46:08,664\nfetchLimits and then the sortDescriptors and\n\n904\n00:46:08,666 --> 00:46:10,299\npredicate, we'll talk about it in the next slide.\n\n905\n00:46:10,301 --> 00:46:15,171\nSo the batch size of 20 here, just means that when I fetch\n\n906\n00:46:15,173 --> 00:46:18,040\nit's gonna look like it returns all the objects, but\n\n907\n00:46:18,042 --> 00:46:21,444\nit's actually only fetch them at 20 at a time.\n\n908\n00:46:21,446 --> 00:46:23,679\nThis is really great for things like table views,\n\n909\n00:46:23,681 --> 00:46:26,883\nwhere you know the person's scrolling through it, so\n\n910\n00:46:26,885 --> 00:46:28,451\nyou don't wanna fetch all million item.\n\n911\n00:46:28,453 --> 00:46:30,586\nYou know that you can fetch them in batches as they go\n\n912\n00:46:30,588 --> 00:46:33,289\nalong. Okay. We're gonna talk a little bit about another\n\n913\n00:46:33,291 --> 00:46:35,458\nimportant thing called faulting, which it so you can\n\n914\n00:46:35,460 --> 00:46:37,560\nhave a million items on the table and it's still pretty\n\n915\n00:46:37,562 --> 00:46:41,430\nlightweight even if you don't set a batch limit but you can.\n\n916\n00:46:41,432 --> 00:46:43,499\nAlso you might have something where there's thousands of\n\n917\n00:46:43,501 --> 00:46:46,035\nobjects but maybe your UI can only show a hundred,\n\n918\n00:46:46,037 --> 00:46:47,603\nit's just the maximum you can show.\n\n919\n00:46:47,605 --> 00:46:50,807\nWell then you can say only give me the first hundred.\n\n920\n00:46:50,809 --> 00:46:54,544\nOkay that's also Allowed. Alright so\n\n921\n00:46:54,546 --> 00:46:56,179\nlet's talk about the two most important ones,\n\n922\n00:46:56,181 --> 00:46:58,447\nyou don't really use these very much, but\n\n923\n00:46:58,449 --> 00:46:59,115\nthe sortdescriptor and\n\n924\n00:46:59,117 --> 00:47:00,483\nthe predicate you are going to use a lot.\n\n925\n00:47:00,485 --> 00:47:04,287\nLet's talk about those in detail. The sortdescriptor is,\n\n926\n00:47:04,289 --> 00:47:09,492\nis an array of descriptions of things to sort by.\n\n927\n00:47:09,494 --> 00:47:12,428\nOkay? And it's gonna use those sort by things\n\n928\n00:47:12,430 --> 00:47:14,831\nto sort the things that come out of the array, or\n\n929\n00:47:14,833 --> 00:47:16,299\ncome out of the database when it puts them\n\n930\n00:47:16,301 --> 00:47:19,168\nin the array. Okay? So here's what it's like to create\n\n931\n00:47:19,170 --> 00:47:22,705\na sort descriptor. It has a few different initializers,\n\n932\n00:47:22,707 --> 00:47:26,576\nbut here's kind of one of it's most, verbose ones.\n\n933\n00:47:26,578 --> 00:47:30,413\nFirst is the key that you're going to be sorting by. So\n\n934\n00:47:30,415 --> 00:47:33,216\nif I'm looking for Twitter users, I might want the array\n\n935\n00:47:33,218 --> 00:47:36,819\nto come back sorted by the screen name, okay, at sign,\n\n936\n00:47:36,821 --> 00:47:38,020\nwhatever. Okay, I wanna sort it so\n\n937\n00:47:38,022 --> 00:47:41,224\nI would create a descriptor where the key is screenName,\n\n938\n00:47:41,226 --> 00:47:42,725\ncuz that's what I want it to sort by.\n\n939\n00:47:42,727 --> 00:47:45,494\nAscending is whether it's you know the @ sign\n\n940\n00:47:45,496 --> 00:47:48,531\nA people come first or the @ sign Z people come first\n\n941\n00:47:48,533 --> 00:47:52,235\nright? So [INAUDIBLE] is it an ascending list or a descending\n\n942\n00:47:52,237 --> 00:47:55,571\nlist? And then this selector which is usually optional,\n\n943\n00:47:55,573 --> 00:47:57,773\nyou don't usually need it, is interesting.\n\n944\n00:47:57,775 --> 00:48:02,044\nIt's basically something that just says, how do I sort?\n\n945\n00:48:02,046 --> 00:48:05,348\nThese strings, okay? Do I just sort them alphabetically?\n\n946\n00:48:05,350 --> 00:48:08,684\nWell, what does it mean to sort alphabetically? Okay,\n\n947\n00:48:08,686 --> 00:48:10,820\nthis localized standard compare means\n\n948\n00:48:10,822 --> 00:48:13,689\nalphabetically in the way that people are used to seeing it\n\n949\n00:48:13,691 --> 00:48:16,726\nin the finder on the Mac, basically, so it's kind of\n\n950\n00:48:16,728 --> 00:48:20,963\nlike user-sensible alphabetical order.\n\n951\n00:48:20,965 --> 00:48:23,866\nOkay, there's other alphabetical orders that\n\n952\n00:48:23,868 --> 00:48:26,068\nare more like strict alphabet order.\n\n953\n00:48:26,070 --> 00:48:28,938\nBut maybe they don't deal with diacritics, you know?\n\n954\n00:48:28,940 --> 00:48:31,774\nThey don't look, they don't sort diacritics properly,\n\n955\n00:48:31,776 --> 00:48:35,211\nthings like, or capitalization they might not do right. So\n\n956\n00:48:35,213 --> 00:48:37,113\nthis is a good one. And this is the default, so\n\n957\n00:48:37,115 --> 00:48:39,282\nyou probably don't need to put this in here. But\n\n958\n00:48:39,284 --> 00:48:41,350\nthis can basically be, if this is a string, okay,\n\n959\n00:48:41,352 --> 00:48:44,754\nif screenName is a string, which it is, then this can be,\n\n960\n00:48:44,756 --> 00:48:48,357\nany string method. Now there are some string methods that\n\n961\n00:48:48,359 --> 00:48:51,894\nare magic and are actually done on the database side.\n\n962\n00:48:51,896 --> 00:48:53,229\nSo they're super efficient, okay. And\n\n963\n00:48:53,231 --> 00:48:55,598\nyou can read the documentation to find out which ones.\n\n964\n00:48:55,600 --> 00:48:58,434\nThis is definitely one of them. Okay, so\n\n965\n00:48:58,436 --> 00:49:01,504\nthis method is not actually being called on every single\n\n966\n00:49:01,506 --> 00:49:04,407\nscreen name in the database. You know, in other words, it,\n\n967\n00:49:04,409 --> 00:49:06,142\nit's not fetching them calling that method,\n\n968\n00:49:06,144 --> 00:49:07,977\nfetching the next one, calling it, comparing them,\n\n969\n00:49:07,979 --> 00:49:11,948\ntrying to sort it. No, this is happening in the database.\n\n970\n00:49:11,950 --> 00:49:15,351\nOkay, the database knows how to do the sort. All right, so\n\n971\n00:49:15,353 --> 00:49:19,322\nthat's the sort descriptor. Now, notice that, we,\n\n972\n00:49:19,324 --> 00:49:21,791\nwhen we create our fetch request,\n\n973\n00:49:21,793 --> 00:49:25,728\nwe actually provide an array of sort descriptors.\n\n974\n00:49:25,730 --> 00:49:28,831\nWe don't just give one sort descriptor, we do an array.\n\n975\n00:49:28,833 --> 00:49:29,498\nWhy would we need an array?\n\n976\n00:49:29,500 --> 00:49:32,001\nWell, sometimes you, maybe you're searching for names,\n\n977\n00:49:32,003 --> 00:49:35,538\npeople by name, and you wanna search by last name first and\n\n978\n00:49:35,540 --> 00:49:40,409\nthen by first name, right, the common thing to do. So\n\n979\n00:49:40,411 --> 00:49:42,278\nyou can give an array of sort descriptors.\n\n980\n00:49:42,280 --> 00:49:45,114\nThe first sort descriptor is the last name sort descriptor,\n\n981\n00:49:45,116 --> 00:49:48,617\nand the second one is the first name sort descriptor,\n\n982\n00:49:48,820 --> 00:49:53,089\nokay? That's why it's an array. All right, now,\n\n983\n00:49:53,091 --> 00:49:56,592\nNSPredicate, the real gut of how we do all this.\n\n984\n00:49:56,594 --> 00:50:00,529\nThe predicate is a really flexible object, okay, you,\n\n985\n00:50:00,531 --> 00:50:03,165\nthis is one where you really have to go read NSPredicate\n\n986\n00:50:03,167 --> 00:50:05,968\ndocumentation. Okay, it would take me, I could have a whole\n\n987\n00:50:05,970 --> 00:50:08,304\nlecture on all of the things NSPredicate can do.\n\n988\n00:50:08,306 --> 00:50:12,408\nThe format of NSPredicate is NSPredicate is basically you\n\n989\n00:50:12,410 --> 00:50:15,011\nhave a constructor here, an initializer,\n\n990\n00:50:15,013 --> 00:50:19,281\nwhich takes a format string, like this, with little percent\n\n991\n00:50:19,283 --> 00:50:21,784\nat signs in it that you put then at the end.\n\n992\n00:50:21,786 --> 00:50:24,687\nSee, here's two %@ signs, you put them at the end, joe and\n\n993\n00:50:24,689 --> 00:50:29,258\naDate, right? And these values get put into this spot.\n\n994\n00:50:29,260 --> 00:50:32,628\nIt's like printdef, okay, you all know printdef.\n\n995\n00:50:32,630 --> 00:50:34,764\nIt's, who, who doesn't, does everyone know, who,\n\n996\n00:50:34,766 --> 00:50:36,232\nif you don't know what printdef is,\n\n997\n00:50:36,234 --> 00:50:37,366\nraise your hand. Okay, so\n\n998\n00:50:37,368 --> 00:50:39,802\neveryone knows what printdef is, just like printdef,\n\n999\n00:50:39,804 --> 00:50:43,839\nin that way. But of course, this is, has meaning, okay,\n\n1000\n00:50:43,841 --> 00:50:46,642\nmeaning in terms of what you can search in the database.\n\n1001\n00:50:46,644 --> 00:50:49,111\nSo, here's just some examples. Here, for example,\n\n1002\n00:50:49,113 --> 00:50:51,580\nI'm searching the database to find all the tweet,\n\n1003\n00:50:51,582 --> 00:50:54,216\nthese are all searches for tweets by the way,\n\n1004\n00:50:54,218 --> 00:50:55,351\nall these things you're seeing right here,\n\n1005\n00:50:55,353 --> 00:50:57,887\nsearches for tweets. So here I'm trying to find a tweet\n\n1006\n00:50:57,889 --> 00:51:00,790\nwhose text contains case insensitively,\n\n1007\n00:51:00,792 --> 00:51:03,993\nthat's what that square bracket [c] means, this text,\n\n1008\n00:51:03,995 --> 00:51:07,663\nand the text is the search string, okay? So I have some\n\n1009\n00:51:07,665 --> 00:51:11,600\nsearch string, I'm trying to find all the tweets, that,\n\n1010\n00:51:11,602 --> 00:51:16,472\ncontain that text, okay? Or here's another one down here,\n\n1011\n00:51:16,474 --> 00:51:20,276\nI wanna find all the tweets that were tweeted by Joe and\n\n1012\n00:51:20,278 --> 00:51:24,847\nwere created before or after some date, aDate right there.\n\n1013\n00:51:24,849 --> 00:51:30,286\nSee that? And then here is, an interesting one,\n\n1014\n00:51:30,288 --> 00:51:34,256\nI'm saying give me all the tweets, not Twitter users,\n\n1015\n00:51:34,258 --> 00:51:39,829\ntweets whose Twitter screen name is CS193p. So\n\n1016\n00:51:39,831 --> 00:51:43,199\nthis is all of CS19 p's tweets,\n\n1017\n00:51:43,201 --> 00:51:47,336\nokay? So even though this says tweeter.screenName,\n\n1018\n00:51:47,338 --> 00:51:51,407\nthis is a tweet query. You see that?\n\n1019\n00:51:51,409 --> 00:51:55,277\nOkay, now here's interesting, th, this is only the tip of\n\n1020\n00:51:55,279 --> 00:51:58,147\nthe iceberg, you can do some pretty powerful things. Here,\n\n1021\n00:51:58,149 --> 00:51:58,948\nfor example, I'm doing a tweet u,\n\n1022\n00:51:58,950 --> 00:52:02,318\nTwitterUser request down here at the bottom, and\n\n1023\n00:52:02,320 --> 00:52:06,088\nI'm trying to find all the Twitter users that have tweets\n\n1024\n00:52:06,090 --> 00:52:10,893\nthat contain the search string, okay? So\n\n1025\n00:52:10,895 --> 00:52:13,696\nthat's pretty powerful, since tweets is a too many\n\n1026\n00:52:13,698 --> 00:52:18,834\nrelationship, but it can do that. All right, so you gotta\n\n1027\n00:52:18,836 --> 00:52:21,537\nread up on NSPredicate to know what you can do.\n\n1028\n00:52:21,539 --> 00:52:23,339\nIn your homework, I'm gonna ask you to do something\n\n1029\n00:52:23,341 --> 00:52:25,641\npretty straightforward. So don't worry too much,\n\n1030\n00:52:25,643 --> 00:52:28,911\nbut you're gonna need to not skip the step of going and\n\n1031\n00:52:28,913 --> 00:52:32,748\nreading this. You can also make compound predicates.\n\n1032\n00:52:32,750 --> 00:52:35,050\nBasically, you have this NSCompoundPredicate.\n\n1033\n00:52:35,052 --> 00:52:37,786\nYou can make an AND predicate or an OR predicate. And\n\n1034\n00:52:37,788 --> 00:52:41,423\nyou just give it an alid, an array of other predicates,\n\n1035\n00:52:41,425 --> 00:52:41,957\nand you'll AND them together.\n\n1036\n00:52:41,959 --> 00:52:44,860\nNow you don't need to do that because you could put OR and\n\n1037\n00:52:44,862 --> 00:52:47,863\nAND in the predicate string. But sometimes,\n\n1038\n00:52:47,865 --> 00:52:51,333\nyou wanna like calculate which ones you want, okay,\n\n1039\n00:52:51,335 --> 00:52:54,370\nyou will by some if thens or something, you wanna decide\n\n1040\n00:52:54,372 --> 00:52:56,839\nwhich ones are there, and so this is a good way to AND\n\n1041\n00:52:56,841 --> 00:53:02,011\nthem together. All right, or and or or. Okay, I'm\n\n1042\n00:53:02,013 --> 00:53:04,480\nnot really gonna talk about this whole slide actually,\n\n1043\n00:53:04,482 --> 00:53:10,920\nadvanced querying, but there are some kind of weird little,\n\n1044\n00:53:10,922 --> 00:53:14,523\nthings you can put in your predicate, like @average,\n\n1045\n00:53:14,525 --> 00:53:18,794\nwhich will assume that this is returning an array, and it'll\n\n1046\n00:53:18,796 --> 00:53:23,699\naverage all of these keys in that array. Okay, so here for\n\n1047\n00:53:23,701 --> 00:53:28,404\nexample, I have tweets.tweet, I'm basically looking at all\n\n1048\n00:53:28,406 --> 00:53:32,274\nof the tweets that this Twitter user has tweeted.\n\n1049\n00:53:32,276 --> 00:53:33,876\nAnd I'm averaging the latitude,\n\n1050\n00:53:33,878 --> 00:53:37,580\nassuming they had a latitude and longitude on the tweet.\n\n1051\n00:53:37,582 --> 00:53:40,549\nI'm averaging the latitude to find the average latitude at\n\n1052\n00:53:40,551 --> 00:53:42,885\nwhich someone tweets. Okay, that's kinda weird,\n\n1053\n00:53:42,887 --> 00:53:46,355\nbut you can do that. So same thing with counts, okay?\n\n1054\n00:53:46,357 --> 00:53:49,391\nNow you're seeing counts here, but in, in your homework,\n\n1055\n00:53:49,393 --> 00:53:52,761\nyou're gonna be asked to do a count, but not with this.\n\n1056\n00:53:52,763 --> 00:53:53,462\nOkay, this won't work for\n\n1057\n00:53:53,464 --> 00:53:54,897\nthe kind of counting I'm asking you to do.\n\n1058\n00:53:54,899 --> 00:53:58,000\nYou're just gonna have to have code that counts for that.\n\n1059\n00:53:58,002 --> 00:53:59,268\nOkay, so don't get confused by this.\n\n1060\n00:53:59,270 --> 00:54:03,272\nDo not use @count in your homework, all right. And\n\n1061\n00:54:03,274 --> 00:54:06,275\ndown here, it's talking about this class NSExpression,\n\n1062\n00:54:06,277 --> 00:54:09,478\nwhich lets you create these arbitrary expressions to\n\n1063\n00:54:09,480 --> 00:54:13,015\nsearch for. Again, I'm not gonna talk about it,\n\n1064\n00:54:13,017 --> 00:54:14,416\nyou don't need to do it for your homework.\n\n1065\n00:54:14,418 --> 00:54:16,719\nYou can certainly take a look at the class NSExpression.\n\n1066\n00:54:16,721 --> 00:54:21,590\nIt's pretty amazing what's in there. Okay, all right, so\n\n1067\n00:54:21,592 --> 00:54:23,859\nlet's put this all together, all this querying business,\n\n1068\n00:54:23,861 --> 00:54:25,628\nso I'm gonna create this fetch request for\n\n1069\n00:54:25,630 --> 00:54:29,498\na Twitter user. Okay, I wanna have all the tweets\n\n1070\n00:54:29,500 --> 00:54:33,569\nthat this Twitter user has created in the last 24 hours.\n\n1071\n00:54:33,571 --> 00:54:37,473\nSo how do I do that? Okay, I'm gonna fetch into, actually\n\n1072\n00:54:37,475 --> 00:54:40,509\nI know I'm gonna create all the, sorry, be clear here.\n\n1073\n00:54:40,511 --> 00:54:44,079\nI'm fetching all the Twitter users who have tweeted in\n\n1074\n00:54:44,081 --> 00:54:47,049\nthe last 24 hours. Okay, so I'm fetching Twitter users.\n\n1075\n00:54:47,051 --> 00:54:50,886\nSo that's my entity, I'm gonna create the time yesterday,\n\n1076\n00:54:50,888 --> 00:54:54,223\nwhich is just the time interval since now of minus 24\n\n1077\n00:54:54,225 --> 00:54:56,191\nhours. This is in seconds, okay?\n\n1078\n00:54:56,193 --> 00:54:58,560\nThen I'm gonna create the predicate,\n\n1079\n00:54:58,562 --> 00:55:02,364\nwhich is any tweets that were created after yesterday,\n\n1080\n00:55:02,366 --> 00:55:06,935\n24 hours ago, okay? See that predicate? Pretty fun. And\n\n1081\n00:55:06,937 --> 00:55:10,739\nthen I'm gonna sort the result by the name of the Twitter\n\n1082\n00:55:10,741 --> 00:55:14,176\nuser, not a screen name, but the actual name.\n\n1083\n00:55:14,178 --> 00:55:15,411\nAnd ascending is true, so\n\n1084\n00:55:15,413 --> 00:55:19,615\nI want the As at the beginning and the Zs at the end, okay?\n\n1085\n00:55:19,617 --> 00:55:23,285\nSo this, I create this request. Now I have request,\n\n1086\n00:55:23,287 --> 00:55:28,524\nhow do I get the array, which is all of these things, okay?\n\n1087\n00:55:28,526 --> 00:55:31,960\nWe do that with a method in your managedObjectContext.\n\n1088\n00:55:31,962 --> 00:55:33,662\nI told you you need a managedObjectContext for\n\n1089\n00:55:33,664 --> 00:55:35,431\neverything, and you do, creating, and\n\n1090\n00:55:35,433 --> 00:55:38,701\nalso for fetching. You're gonna use this method in your\n\n1091\n00:55:38,703 --> 00:55:40,869\ncontext called executeFetchRequest, and\n\n1092\n00:55:40,871 --> 00:55:43,505\nyou just give it the NSFetchRequest.\n\n1093\n00:55:43,507 --> 00:55:46,408\nIt returns an NSArray, okay, or an array,\n\n1094\n00:55:46,410 --> 00:55:50,646\na bridge to an array, okay, of all the things.\n\n1095\n00:55:50,648 --> 00:55:52,915\nNow if that array is empty, not nil,\n\n1096\n00:55:52,917 --> 00:55:56,752\nbut empty, that means nothing matches your request.\n\n1097\n00:55:56,754 --> 00:55:58,053\nThere's nothing in the database that matched that.\n\n1098\n00:55:58,055 --> 00:56:00,622\nIn other words, in the, using the previous slide, there\n\n1099\n00:56:00,624 --> 00:56:03,459\nare no Twitter users who have tweeted in the last 24 hours.\n\n1100\n00:56:03,461 --> 00:56:07,262\nThat's empty array. Otherwise it's gonna return a sorted\n\n1101\n00:56:07,264 --> 00:56:10,666\narray of all the Twitter users, sorted by their name,\n\n1102\n00:56:10,668 --> 00:56:13,669\nwho have tweeted in the last 24 hours. Okay?\n\n1103\n00:56:13,671 --> 00:56:15,137\nAnd the objects in there, in that array,\n\n1104\n00:56:15,139 --> 00:56:18,507\nwill be Twitter user, instances of Twitter user.\n\n1105\n00:56:18,509 --> 00:56:20,242\nOkay, cuz that's what I searched for.\n\n1106\n00:56:20,244 --> 00:56:24,546\nNow notice that I have to try, okay, context try, okay,\n\n1107\n00:56:24,548 --> 00:56:30,719\nthat's because this method throws. Now, if this throws,\n\n1108\n00:56:30,721 --> 00:56:33,889\nit probably means there£s some problem with your database.\n\n1109\n00:56:33,891 --> 00:56:36,892\nOkay? Like maybe your database is not opened, maybe tried to\n\n1110\n00:56:36,894 --> 00:56:40,729\nsend this to a UI managed object manage documents\n\n1111\n00:56:40,731 --> 00:56:42,731\ncontext and you never opened it, so it£s not open or\n\n1112\n00:56:42,733 --> 00:56:48,570\nsomething like that. You could ignore the throw, by doing\n\n1113\n00:56:48,572 --> 00:56:52,074\ntri question mark. The thing that tri question mark does\n\n1114\n00:56:52,076 --> 00:56:55,077\nthat you have to realize is, it turns whatever this is,\n\n1115\n00:56:55,079 --> 00:56:58,080\nthis method call. Whatever it returns, it turns it into\n\n1116\n00:56:58,082 --> 00:57:03,285\nan optional. So execute fetch request returns an NS array,\n\n1117\n00:57:03,287 --> 00:57:07,189\nor an array. So, by putting tri question mark, it makes\n\n1118\n00:57:07,191 --> 00:57:11,560\nthis now return an optional array. And why is that?\n\n1119\n00:57:11,562 --> 00:57:16,765\nThat's because if it throws it's gonna return nill. Okay?\n\n1120\n00:57:16,767 --> 00:57:19,568\nSo it's a little funky to realize this but\n\n1121\n00:57:19,570 --> 00:57:23,305\nthis just gonna turn this into an optional array, and so\n\n1122\n00:57:23,307 --> 00:57:27,009\nlet users, users right there, is going to be of type,\n\n1123\n00:57:27,011 --> 00:57:31,513\noptional array. Okay optional array of And\n\n1124\n00:57:31,515 --> 00:57:34,650\nhis managed object actually, to be exact. All right so\n\n1125\n00:57:34,652 --> 00:57:38,253\na lot of times we do do try question mark here because we\n\n1126\n00:57:38,255 --> 00:57:42,324\ndon't really know what to do to handle an error so if we do\n\n1127\n00:57:42,326 --> 00:57:46,428\na fetch and it comes back nil, and there was some problem,\n\n1128\n00:57:46,430 --> 00:57:49,498\nit's kind of like [SOUND] we're reporting error\n\n1129\n00:57:49,500 --> 00:57:53,402\nto the user or something but it's not like much we can do.\n\n1130\n00:57:53,404 --> 00:57:57,172\nOkay, so sometimes, this is a case where we might do try\n\n1131\n00:57:57,174 --> 00:58:01,577\nquestion mark there. Okay, so that's it, very simple and\n\n1132\n00:58:01,579 --> 00:58:02,978\nnow you have the array of objects back,\n\n1133\n00:58:02,980 --> 00:58:06,215\nyou can do whatever you want with them.\n\n1134\n00:58:06,217 --> 00:58:09,651\nI want to talk a little about performance. What if you had\n\n1135\n00:58:09,653 --> 00:58:12,321\na million objects and you said show me all the Twitter user,\n\n1136\n00:58:12,323 --> 00:58:15,224\na million tweets or something or a million Twitter users and\n\n1137\n00:58:15,226 --> 00:58:18,894\nyou said, show me all the Twitter users that tweeted in\n\n1138\n00:58:18,896 --> 00:58:22,965\nthe last 24 hours. And there were 750, or 7,000 of them.\n\n1139\n00:58:22,967 --> 00:58:26,168\nAre you really gonna get an array with 7,000 objects\n\n1140\n00:58:26,170 --> 00:58:28,971\nall of, each of which has a screen name and the name and\n\n1141\n00:58:28,973 --> 00:58:32,174\nwhatever else it. I mean, that would be massive, right.\n\n1142\n00:58:32,176 --> 00:58:34,142\nAnd the answer is no, you don't get that.\n\n1143\n00:58:34,144 --> 00:58:38,113\nYou get this kind of magical thing which is an array of\n\n1144\n00:58:38,115 --> 00:58:42,684\nhusks of those objects if you want to think of it that way.\n\n1145\n00:58:42,686 --> 00:58:43,886\nSo they're not really there and\n\n1146\n00:58:43,888 --> 00:58:46,922\nin fact if you tried to print them, if you used print to\n\n1147\n00:58:46,924 --> 00:58:50,025\nprint them, it would just say this is an NS managed object,\n\n1148\n00:58:50,027 --> 00:58:51,994\nit wouldn't show you the screen name or the name or\n\n1149\n00:58:51,996 --> 00:58:55,297\nanything else about it because it doesn't actually pull that\n\n1150\n00:58:55,299 --> 00:59:00,502\ndata Until you ask for it. Until you ask specifically for\n\n1151\n00:59:00,504 --> 00:59:03,705\na Twitter user's name or his screen name.\n\n1152\n00:59:03,707 --> 00:59:05,641\nIt doesn't get that out of the database.\n\n1153\n00:59:05,643 --> 00:59:09,077\nThis is called faulting. The objects live in this kind of\n\n1154\n00:59:09,079 --> 00:59:11,280\nhusk state where they don't actually have their data. And\n\n1155\n00:59:11,282 --> 00:59:14,416\nwhen you ask for them the data gets faulted in. Now when that\n\n1156\n00:59:14,418 --> 00:59:17,185\nfaulting happens, it might be happening in big bunches,\n\n1157\n00:59:17,187 --> 00:59:18,086\nbecause it might be more efficient for\n\n1158\n00:59:18,088 --> 00:59:21,757\nthe database to fault in a hundred at a time. Okay? But\n\n1159\n00:59:21,759 --> 00:59:22,958\nit's all happening behind the scenes.\n\n1160\n00:59:22,960 --> 00:59:25,160\nThe only reason I even mention it is because you might be\n\n1161\n00:59:25,162 --> 00:59:28,497\ntrying to print these things out, and you're like, what?\n\n1162\n00:59:28,499 --> 00:59:31,400\nWhere's my name and screen name? Okay? And you'll know\n\n1163\n00:59:31,402 --> 00:59:34,670\nwhy it's because it's not been faulted yet. Okay? So\n\n1164\n00:59:34,672 --> 00:59:36,371\nif you really want the name or screen name, you want,\n\n1165\n00:59:36,373 --> 00:59:42,210\nyou have to .name so it faults it in, and can see it. Okay?\n\n1166\n00:59:42,646 --> 00:59:45,380\nAll right let's talk about thread safety with core data.\n\n1167\n00:59:45,382 --> 00:59:50,619\nOkay, NSManagedObjectContext is not thread safe. So\n\n1168\n00:59:50,621 --> 00:59:54,289\nyou cannot have a context fork off some\n\n1169\n00:59:54,291 --> 00:59:56,592\nclosure on another thread with dispatch and\n\n1170\n00:59:56,594 --> 01:00:00,195\naccess it. Okay? So that sounds really bad. Because\n\n1171\n01:00:00,197 --> 01:00:03,365\na database you can imagine I'd want to have another thread\n\n1172\n01:00:03,367 --> 01:00:05,500\ndoing some heavy intensive database thing.\n\n1173\n01:00:05,502 --> 01:00:06,802\nLike loading the database up or\n\n1174\n01:00:06,804 --> 01:00:09,404\ndoing some complicated queries or something like that.\n\n1175\n01:00:09,406 --> 01:00:11,506\nAnd you're telling me I can't do it?\n\n1176\n01:00:11,508 --> 01:00:14,543\nBecause it's not thread same? Well no of course you can do\n\n1177\n01:00:14,545 --> 01:00:18,480\nit. And the way you have to do it is ns managed object each\n\n1178\n01:00:18,482 --> 01:00:24,119\nNSManagedObejct instance has to have its own thread. Okay.\n\n1179\n01:00:24,121 --> 01:00:26,622\nNow, the cool thing is you can have multiple\n\n1180\n01:00:26,624 --> 01:00:30,826\nNSManagedObjectContext on the same database. Okay? So, how\n\n1181\n01:00:30,828 --> 01:00:34,062\ndoes that work? So, you have this NSManagedObjectContext.\n\n1182\n01:00:34,064 --> 01:00:35,631\nIt's writing into the database.\n\n1183\n01:00:35,633 --> 01:00:39,201\nWhen you hit save that save goes out to the database and\n\n1184\n01:00:39,203 --> 01:00:43,805\nother ManagedObjectContext will start seeing it. Okay?\n\n1185\n01:00:43,807 --> 01:00:45,774\nWhen they do fetches they'll see it.\n\n1186\n01:00:45,776 --> 01:00:47,743\nSo it basically works through the saves.\n\n1187\n01:00:47,745 --> 01:00:50,912\nWhen you save through one context boom the other ones\n\n1188\n01:00:50,914 --> 01:00:53,749\nstart seeing it. Automatically as soon as they, next time\n\n1189\n01:00:53,751 --> 01:00:56,952\nthey fetch they're gonna automatically see it. Okay, so\n\n1190\n01:00:56,954 --> 01:01:00,355\nit's really kind of cool that it just uses threads,\n\n1191\n01:01:00,357 --> 01:01:02,190\nokay, queues, to do this.\n\n1192\n01:01:02,192 --> 01:01:04,826\nNow that does mean that the cues to use them on, they have\n\n1193\n01:01:04,828 --> 01:01:07,896\nto be serial queues, can't have concurrent queues because\n\n1194\n01:01:07,898 --> 01:01:10,365\nthen you'd have one manage object in different threads,\n\n1195\n01:01:10,367 --> 01:01:13,502\nbecause a concurrent queue can fire off multiple threads to\n\n1196\n01:01:13,504 --> 01:01:15,937\ngo execute its little blocks. All right?\n\n1197\n01:01:15,939 --> 01:01:19,775\nSo it has to be serial queue. Now the kind of,\n\n1198\n01:01:19,777 --> 01:01:23,011\nNSMangedObjectContext that you get by doing that app delegate\n\n1199\n01:01:23,013 --> 01:01:26,615\nthing and the one you get from doing UI manage documents,\n\n1200\n01:01:26,617 --> 01:01:31,086\nthose are both main cue in this managed object context.\n\n1201\n01:01:31,088 --> 01:01:35,023\nIt could only be used in the main cue so don't ever like,\n\n1202\n01:01:35,025 --> 01:01:37,426\nfork those off and start using those on another queue.\n\n1203\n01:01:37,428 --> 01:01:40,195\nNow you can create your own NSManagedObjectContext on\n\n1204\n01:01:40,197 --> 01:01:43,365\nother queues if you want. There's an initializer for it.\n\n1205\n01:01:43,367 --> 01:01:44,266\nI'm not really gonna talk about that.\n\n1206\n01:01:44,268 --> 01:01:46,735\nYou're not gonna need to do that for this class.\n\n1207\n01:01:46,737 --> 01:01:51,306\nBut that's how you would do concurrency, okay?\n\n1208\n01:01:51,308 --> 01:01:53,642\nNow when you have, because of this, because\n\n1209\n01:01:53,644 --> 01:01:56,511\nyou can have this multiple context, you gotta know about\n\n1210\n01:01:56,513 --> 01:01:58,880\nthis method right here, performBlock.\n\n1211\n01:01:58,882 --> 01:02:02,584\nVery important method in manage ManageObjectContext.\n\n1212\n01:02:02,586 --> 01:02:05,987\nAnd it basically takes a closure here. Closure that\n\n1213\n01:02:05,989 --> 01:02:09,925\ntake no arguments, returns nothing, and inside this block\n\n1214\n01:02:09,927 --> 01:02:13,361\nyou always know with 100% certainty whatever code you're\n\n1215\n01:02:13,363 --> 01:02:17,966\nexecuting in here is going to be performed on this context,\n\n1216\n01:02:17,968 --> 01:02:22,871\nsafe queue. Okay, the queue that it was created on,\n\n1217\n01:02:22,873 --> 01:02:24,406\nthe queue that it's running on,\n\n1218\n01:02:24,408 --> 01:02:27,309\nthe queue that won't cause any problems, always.\n\n1219\n01:02:27,311 --> 01:02:31,646\nOkay, so really anytime you do anything with core data\n\n1220\n01:02:31,648 --> 01:02:34,549\nany time you access an NSManagedObjectContext,\n\n1221\n01:02:34,551 --> 01:02:38,153\nor any of the NSManagedObjects you get out of it, you want to\n\n1222\n01:02:38,155 --> 01:02:42,224\ndo it inside a performBlock. Did you hear what I just said?\n\n1223\n01:02:42,226 --> 01:02:45,427\nI'm going to say it again. performBlock wants to be\n\n1224\n01:02:45,429 --> 01:02:50,298\nwrapped around every access to any NSManagedObjectContext or\n\n1225\n01:02:50,300 --> 01:02:54,369\nNSManagedObject of any kind. Okay. Now\n\n1226\n01:02:54,371 --> 01:02:57,405\nin your homework you're only ever gonna have one context or\n\n1227\n01:02:57,407 --> 01:02:59,574\nyou might say what a waste. Why do you put these\n\n1228\n01:02:59,576 --> 01:03:01,109\nstupid perform blocks around everything?\n\n1229\n01:03:01,111 --> 01:03:02,778\nI know everything's in the main context.\n\n1230\n01:03:02,780 --> 01:03:05,080\nWell the answer you'll want to get used to doing this.\n\n1231\n01:03:05,082 --> 01:03:08,683\nOkay? Because maybe down the road you do add another thread\n\n1232\n01:03:08,685 --> 01:03:10,752\nthat loads up the database with more tweets or\n\n1233\n01:03:10,754 --> 01:03:13,922\nsomething like that and also, it starts breaking if\n\n1234\n01:03:13,924 --> 01:03:17,659\nyou're not performing things on the right context, okay.\n\n1235\n01:03:17,661 --> 01:03:18,660\nSo just get in the habit of doing this.\n\n1236\n01:03:18,662 --> 01:03:22,130\nSo you can also perform block and wait, which will cause\n\n1237\n01:03:22,132 --> 01:03:24,566\nthis code to be executed on the safe queue and\n\n1238\n01:03:24,568 --> 01:03:29,104\nwait till it's done and then continue on this queue, okay.\n\n1239\n01:03:29,106 --> 01:03:33,575\nSo you can do that as well. So, always wrap perform block\n\n1240\n01:03:33,577 --> 01:03:39,447\naround anything you do in core data.\n\n1241\n01:03:39,817 --> 01:03:44,753\nAll right? Quick thing on the parent context. Most context,\n\n1242\n01:03:44,755 --> 01:03:48,456\nmost management contexts have a parentContext, all right?\n\n1243\n01:03:48,458 --> 01:03:51,159\nThat parentContext is either the context that actually\n\n1244\n01:03:51,161 --> 01:03:54,296\nwriting it to the database, or in some cases, it's another,\n\n1245\n01:03:54,298 --> 01:03:57,365\nand it's may context. So that when you save, it's actually\n\n1246\n01:03:57,367 --> 01:04:00,302\nsaving to another context, and then that context saves again.\n\n1247\n01:04:00,304 --> 01:04:02,938\nUI manage document works this way.\n\n1248\n01:04:02,940 --> 01:04:06,241\nOkay, and what's kinda cool is that that parent context is\n\n1249\n01:04:06,243 --> 01:04:08,643\nalmost always on a different queue.\n\n1250\n01:04:08,645 --> 01:04:12,247\nSo if you're using UI managed documents you can actually\n\n1251\n01:04:12,249 --> 01:04:15,317\ndo a little trick which is if you wanna run something for\n\n1252\n01:04:15,319 --> 01:04:19,621\nthat database on another queue just performBlock\n\n1253\n01:04:19,623 --> 01:04:20,622\non the parentContext.\n\n1254\n01:04:20,624 --> 01:04:24,359\nParentContext is just a method in ManagedObject context,\n\n1255\n01:04:24,361 --> 01:04:27,829\nright or for a property. Just do performBlock on that.\n\n1256\n01:04:27,831 --> 01:04:30,765\nNow you'll be performing it on a different queue off the main\n\n1257\n01:04:30,767 --> 01:04:33,168\nqueue, okay. And it'll be in that database.\n\n1258\n01:04:33,170 --> 01:04:35,570\nEverything will be fine so it's kind of a trick.\n\n1259\n01:04:35,572 --> 01:04:37,806\nOkay, again, you won't need that for your assignment,\n\n1260\n01:04:37,808 --> 01:04:40,909\nbut just understand that you can do that.\n\n1261\n01:04:41,511 --> 01:04:44,946\nAll right, so there's so much more to Core Data, no wait,\n\n1262\n01:04:44,948 --> 01:04:48,583\nI mean we've already been here an hour so and barely covered\n\n1263\n01:04:48,585 --> 01:04:51,586\nthe basics. So there's optimistic locking in there,\n\n1264\n01:04:51,588 --> 01:04:55,290\nit has full Undo/Redo which is incredible. Specify thing like\n\n1265\n01:04:55,292 --> 01:04:57,859\nstaleness, you know, when I have to refetch this thing,\n\n1266\n01:04:57,861 --> 01:04:59,728\nhow much time goes by before I have to refetch.\n\n1267\n01:04:59,730 --> 01:05:02,731\nAll that stuff. You have to go look at the documentation for\n\n1268\n01:05:02,733 --> 01:05:05,700\nNS Managed Object Context. Okay, that's really the core\n\n1269\n01:05:05,702 --> 01:05:08,069\nof where this stuff is all happening.\n\n1270\n01:05:08,071 --> 01:05:10,605\nEh, to find out more about it. Again,\n\n1271\n01:05:10,607 --> 01:05:11,873\nI'm not gonna ask you to do any of this for\n\n1272\n01:05:11,875 --> 01:05:15,243\nyour homework but you gotta know that it's out there or\n\n1273\n01:05:15,245 --> 01:05:16,111\nwhen you get in the real world and\n\n1274\n01:05:16,113 --> 01:05:18,680\nstart doing this you'll be missing opportunities to do\n\n1275\n01:05:18,682 --> 01:05:22,317\ncool features. All right, the last thing I wanna talk about\n\n1276\n01:05:22,319 --> 01:05:25,654\nis the interrelationship between Core Data and\n\n1277\n01:05:25,656 --> 01:05:27,889\nUITableView. As you can imagine,\n\n1278\n01:05:27,891 --> 01:05:31,092\nif you got this huge database of stuff,\n\n1279\n01:05:31,094 --> 01:05:35,530\na great place to show it is in a TableView. Okay, in fact,\n\n1280\n01:05:35,532 --> 01:05:38,400\n99% of the time, either a TableView or a CollectionView\n\n1281\n01:05:38,402 --> 01:05:42,404\nis how you're gonna show the stuff in a big database, okay.\n\n1282\n01:05:42,406 --> 01:05:47,108\nAnd that's so common that iOS provides this awesome class\n\n1283\n01:05:47,110 --> 01:05:51,680\nNSFetchedResultsController okay, which is a call which\n\n1284\n01:05:51,682 --> 01:05:56,885\nwill hook up an NSFetchRequest to a UITableView.\n\n1285\n01:05:56,887 --> 01:06:00,822\nAnd not just hook it up once but hook it up so that if\n\n1286\n01:06:00,824 --> 01:06:03,458\nthe database changes in any way that the FetchRequest\n\n1287\n01:06:03,460 --> 01:06:08,330\nwould return different results it updates the table. Okay, so\n\n1288\n01:06:08,332 --> 01:06:10,332\nthe database can be changing behind the scenes.\n\n1289\n01:06:10,334 --> 01:06:12,701\nThe table is just always staying in sync with it.\n\n1290\n01:06:12,703 --> 01:06:13,068\nSo that fetch request and\n\n1291\n01:06:13,070 --> 01:06:16,104\nthat table are always in sync, okay, which is really,\n\n1292\n01:06:16,106 --> 01:06:18,273\nreally cool. Okay, it makes it really easy for\n\n1293\n01:06:18,275 --> 01:06:21,276\nyou to implement your table views with stuff\n\n1294\n01:06:21,278 --> 01:06:22,844\nout of the database. Okay, so\n\n1295\n01:06:22,846 --> 01:06:27,048\nhow do you use this NSFetch, FetchedResultsController?\n\n1296\n01:06:27,050 --> 01:06:28,483\nWell, first of all, let's talk about how,\n\n1297\n01:06:28,485 --> 01:06:30,051\nhow FetchResultsController actually works.\n\n1298\n01:06:30,053 --> 01:06:33,788\nIt's very simple. It provides methods to implement all those\n\n1299\n01:06:33,790 --> 01:06:36,458\nUITableView delegate methods like number of sections and\n\n1300\n01:06:36,460 --> 01:06:39,327\ntables, number of rows and sections. The only one it\n\n1301\n01:06:39,329 --> 01:06:41,730\ndoesn't implement is self row and index path.\n\n1302\n01:06:41,732 --> 01:06:43,565\nYou still have to implement that. Because of course,\n\n1303\n01:06:43,567 --> 01:06:47,202\nself row and index path knows about, you know, the custom UI\n\n1304\n01:06:47,204 --> 01:06:50,271\ncells or whatever, so, you have to be the one who's\n\n1305\n01:06:50,273 --> 01:06:53,241\nputting that data on screen in the right way. But in terms of\n\n1306\n01:06:53,243 --> 01:06:56,611\nall the other, things in the UITableView data source\n\n1307\n01:06:56,613 --> 01:06:59,447\neven things like section hea- headers and all that stuff,\n\n1308\n01:06:59,449 --> 01:07:01,850\nNSFetchedResultsController will do all that for you.\n\n1309\n01:07:01,852 --> 01:07:03,418\nIt has methods to implement all those things.\n\n1310\n01:07:03,420 --> 01:07:06,254\nSo here's a couple examples for what it looks like here.\n\n1311\n01:07:06,256 --> 01:07:09,324\nOkay? The other thing you can do, which is kinda cool,\n\n1312\n01:07:09,326 --> 01:07:11,960\nwell, I'll talk about that in a second. Let's talk about\n\n1313\n01:07:11,962 --> 01:07:13,928\ncellForRowAtIndexPath, since you're responsible for\n\n1314\n01:07:13,930 --> 01:07:17,198\nim- implementing that. The key method you need to know from\n\n1315\n01:07:17,200 --> 01:07:19,801\nFetchedResultsController is object and\n\n1316\n01:07:19,803 --> 01:07:22,637\nindex path, okay. This is a method that you can send\n\n1317\n01:07:22,639 --> 01:07:25,673\nto it. You give it an index path into the table and\n\n1318\n01:07:25,675 --> 01:07:30,378\nit will return you the NSManagedObject at that row.\n\n1319\n01:07:30,380 --> 01:07:33,415\nOkay, now this might be a subclass of NSManagedObject\n\n1320\n01:07:33,417 --> 01:07:34,682\nlike Tweet or Twitter User, but\n\n1321\n01:07:34,684 --> 01:07:37,886\nit's gonna return it to you so in your cellForRowAtIndexPath,\n\n1322\n01:07:37,888 --> 01:07:42,824\nyou're gonna call this, okay, of this index path\n\n1323\n01:07:42,826 --> 01:07:45,493\nto get the object that's at that row and then you're gonna\n\n1324\n01:07:45,495 --> 01:07:49,097\nuse that object to fill out the information in that row.\n\n1325\n01:07:49,099 --> 01:07:51,433\nOkay, that's what cellForRowAtIndexPath does.\n\n1326\n01:07:51,435 --> 01:07:54,669\nEveryone understand this? Super important you understand\n\n1327\n01:07:54,671 --> 01:07:56,638\nthis cuz otherwise, you'll be like, how do I, okay,\n\n1328\n01:07:56,640 --> 01:08:00,775\ncellForRowAtIndexPath? This is how you do it. Okay. So\n\n1329\n01:08:00,777 --> 01:08:03,845\nthis FetchedResultsController is probably gonna be a var in\n\n1330\n01:08:03,847 --> 01:08:06,714\nyour UITableViewController. Okay, that you're going to\n\n1331\n01:08:06,716 --> 01:08:09,951\nhave created with a fetched results, with the NS fetched\n\n1332\n01:08:09,953 --> 01:08:13,154\nrequest. And then with your cellForRowAtIndexPath you're\n\n1333\n01:08:13,156 --> 01:08:15,690\ngonna find out each of the things that are in\n\n1334\n01:08:15,692 --> 01:08:19,861\nthe database that match your fetch. One per row, and\n\n1335\n01:08:19,863 --> 01:08:25,533\nthis is gonna return it. Okay? All right, so how do we create\n\n1336\n01:08:25,535 --> 01:08:28,770\nan NSFetchedResultsController by the way? All you do,\n\n1337\n01:08:28,772 --> 01:08:31,706\nreally all you have to do is create that NS fetch request\n\n1338\n01:08:31,708 --> 01:08:34,142\nthat's it, okay? So for example\n\n1339\n01:08:34,144 --> 01:08:36,177\nhere I'm going to create a FetchResultsController.\n\n1340\n01:08:36,179 --> 01:08:38,980\nYou can see that its initializer takes the fetch\n\n1341\n01:08:38,982 --> 01:08:42,383\nrequest. Obviously the context, and\n\n1342\n01:08:42,385 --> 01:08:47,155\nthen this is kind of a cool thing, the sectionNameKeyPath,\n\n1343\n01:08:47,157 --> 01:08:49,691\nif all of the objects in your database, okay,\n\n1344\n01:08:49,693 --> 01:08:53,995\nknow the section they should be in, they have some key in\n\n1345\n01:08:53,997 --> 01:08:55,630\nthere that is the section they're supposed to be in.\n\n1346\n01:08:55,632 --> 01:08:59,334\nThen you can specify that sec that key right here and it'll\n\n1347\n01:08:59,336 --> 01:09:02,604\nautomatically do the sections for you. Okay. The only\n\n1348\n01:09:02,606 --> 01:09:05,673\nthing is you gotta make sure you sort the result of your\n\n1349\n01:09:05,675 --> 01:09:10,245\nfetched sort in the same order as those sections sort. But\n\n1350\n01:09:10,247 --> 01:09:12,914\nit'll do that for you. And then there's cache right here.\n\n1351\n01:09:12,916 --> 01:09:16,451\nIt'll actually cache the results on disk, okay.\n\n1352\n01:09:16,453 --> 01:09:19,053\nSo if you have a really complicated fetch that might\n\n1353\n01:09:19,055 --> 01:09:21,389\ntake a lot of resources, it will cache the result.\n\n1354\n01:09:21,391 --> 01:09:26,394\nThe only thing about this is you cannot change the request.\n\n1355\n01:09:26,396 --> 01:09:28,229\nThe data can be changing all the time but\n\n1356\n01:09:28,231 --> 01:09:29,964\nthe request itself, the predicate and\n\n1357\n01:09:29,966 --> 01:09:32,200\nthe source scrubbers has to be the same.\n\n1358\n01:09:32,202 --> 01:09:32,467\nIf you ever change it,\n\n1359\n01:09:32,469 --> 01:09:35,236\nthen this cache obviously becomes kinda useless. All\n\n1360\n01:09:35,238 --> 01:09:38,573\nright, so how would we create a FetchResultsController doing\n\n1361\n01:09:38,575 --> 01:09:41,075\nthis? I'm gonna create the request. So like I'm gonna\n\n1362\n01:09:41,077 --> 01:09:43,378\nfetch Tweets here. I'm gonna put Tweets in my TableView.\n\n1363\n01:09:43,380 --> 01:09:46,314\nSo each row of my TableView is gonna be a different Tweet.\n\n1364\n01:09:46,316 --> 01:09:48,383\nI'm gonna sort by the created so\n\n1365\n01:09:48,385 --> 01:09:50,952\nthe newer tweets maybe are gonna be at the beginning.\n\n1366\n01:09:50,954 --> 01:09:54,522\nAd then my predicate is going to be all Tweeters who\n\n1367\n01:09:54,524 --> 01:09:56,891\nwhose Tweeter's name equals a certain name.\n\n1368\n01:09:56,893 --> 01:09:59,928\nSo I'm looking for all the tweets by a certain tweeter\n\n1369\n01:09:59,930 --> 01:10:01,162\nwho has a certain name, okay.\n\n1370\n01:10:01,164 --> 01:10:04,265\nAnd when it gets this result, each row in my TableView\n\n1371\n01:10:04,267 --> 01:10:07,802\nis going to be that tweet that matches. Okay? And\n\n1372\n01:10:07,804 --> 01:10:10,672\nFetchResultsController's gonna make sure that's always true,\n\n1373\n01:10:10,674 --> 01:10:13,308\neven if I added in another tweet to the database\n\n1374\n01:10:13,310 --> 01:10:14,576\nthat matched it, the TableView would\n\n1375\n01:10:14,578 --> 01:10:17,111\nadd in another row at the bottom automatically.\n\n1376\n01:10:17,113 --> 01:10:22,684\nOkay, yeah I talked about the cacheName. And yeah, this key\n\n1377\n01:10:22,686 --> 01:10:25,386\nthat says which attribute is the section name has to sort\n\n1378\n01:10:25,388 --> 01:10:30,792\nin the same order as the sort descripter. Sort descripters.\n\n1379\n01:10:30,794 --> 01:10:35,163\nOkay, all right. The FetchResultsController also\n\n1380\n01:10:35,165 --> 01:10:38,866\nwhile it's watching the database, okay, the, well,\n\n1381\n01:10:38,868 --> 01:10:40,568\nI told you it watches the database and\n\n1382\n01:10:40,570 --> 01:10:40,735\nkeeps them in sync.\n\n1383\n01:10:40,737 --> 01:10:42,570\nThe way it does that is it has a delegate,\n\n1384\n01:10:42,572 --> 01:10:45,406\nthe FetchResultsController has a delegate, okay?\n\n1385\n01:10:45,408 --> 01:10:47,609\nSo here's one of its delegate methods.\n\n1386\n01:10:47,611 --> 01:10:49,110\nController did change object and\n\n1387\n01:10:49,112 --> 01:10:52,680\nindex paths forChangeType: newIndexPath. Okay, here,\n\n1388\n01:10:52,682 --> 01:10:55,049\nsee how it's basically noticing the database change,\n\n1389\n01:10:55,051 --> 01:10:58,186\ntelling you what changed, tell you what index paths changed\n\n1390\n01:10:58,188 --> 01:11:00,655\nin the TableView. It's basically telling you exactly\n\n1391\n01:11:00,657 --> 01:11:05,126\nwhat to do cuz the database changed. Now in here you're\n\n1392\n01:11:05,128 --> 01:11:08,329\nsupposed to call all the UI TableView methods that will be\n\n1393\n01:11:08,331 --> 01:11:11,299\nappropriate to cause this to update the table, okay.\n\n1394\n01:11:11,301 --> 01:11:15,570\nInsert a row, put something there, whatever, delete a row,\n\n1395\n01:11:15,572 --> 01:11:15,837\nall that. Well,\n\n1396\n01:11:15,839 --> 01:11:17,939\nnow you're probably starting to think hey I thought\n\n1397\n01:11:17,941 --> 01:11:21,342\nthis NSFetchResultsController was supposed to be easy. But\n\n1398\n01:11:21,344 --> 01:11:23,344\nI gotta implement all this? In here? For\n\n1399\n01:11:23,346 --> 01:11:26,281\nall these delegate methods, eh that's just too hard. Okay,\n\n1400\n01:11:26,283 --> 01:11:29,584\nwell lucky for you, we're gonna provide a class for\n\n1401\n01:11:29,586 --> 01:11:31,819\nyou called CoreDataTableViewController,\n\n1402\n01:11:31,821 --> 01:11:36,991\nsomething we wrote that does all that for you. Okay, this,\n\n1403\n01:11:36,993 --> 01:11:39,827\nall that stuff it does for you, you can actually see all\n\n1404\n01:11:39,829 --> 01:11:43,097\nthat in the documentation for NSFetchResultsController right\n\n1405\n01:11:43,099 --> 01:11:45,366\nat the top. It actually shows you the code\n\n1406\n01:11:45,368 --> 01:11:45,733\nthat you want to use.\n\n1407\n01:11:45,735 --> 01:11:48,069\nUnfortunately it's in Objective-C, so\n\n1408\n01:11:48,071 --> 01:11:49,404\nwe've written it all in Swift for\n\n1409\n01:11:49,406 --> 01:11:52,740\nyou, and provided this class CoreDataTableViewController so\n\n1410\n01:11:52,742 --> 01:11:55,810\nyou're just going to make this TableViewController be your\n\n1411\n01:11:55,812 --> 01:11:59,747\nsubclass or your super class of your TableViewController so\n\n1412\n01:11:59,749 --> 01:12:04,319\nthat you'll inherit all this NSFetchResultsController\n\n1413\n01:12:04,321 --> 01:12:04,819\nfunctionality. And\n\n1414\n01:12:04,821 --> 01:12:08,923\nall you need to do to make it work is, it has a var, this\n\n1415\n01:12:08,925 --> 01:12:12,226\nCoreDataTableViewController only has one public thing\n\n1416\n01:12:12,228 --> 01:12:15,229\nwhich is a var which is a FetchResultsController,\n\n1417\n01:12:15,231 --> 01:12:18,099\nyou just need to create this FetchResultsController\n\n1418\n01:12:18,101 --> 01:12:22,036\nwhich means creating the NSFetchResult fetch request,\n\n1419\n01:12:22,038 --> 01:12:23,304\nand then set this var.\n\n1420\n01:12:23,306 --> 01:12:25,206\nAnd once you set this var, it's automatically going to\n\n1421\n01:12:25,208 --> 01:12:28,309\nstart updating your table. Okay now of course you're\n\n1422\n01:12:28,311 --> 01:12:30,278\ngonna have to implement cellForRowAtIndexPath,\n\n1423\n01:12:30,280 --> 01:12:32,914\nbecause you gotta load up your thing however you're gonna\n\n1424\n01:12:32,916 --> 01:12:35,450\nload it up. But that's all you have to do.\n\n1425\n01:12:35,452 --> 01:12:40,421\ncellForRowAtIndexPath, set this var, you're winning.\n\n1426\n01:12:40,423 --> 01:12:46,894\nOkay. Now that's it for Core Data. Remember that\n\n1427\n01:12:46,896 --> 01:12:50,365\nAssignment Four has nothing to do with Core Data. Okay.\n\n1428\n01:12:50,367 --> 01:12:54,102\nSo do not do anything with Core Data in Assignment Four.\n\n1429\n01:12:54,104 --> 01:12:56,871\nAssignment Five is gonna be a lot of core data.\n\n1430\n01:12:56,873 --> 01:12:59,173\nOkay. So I mean I have to teach you this\n\n1431\n01:12:59,175 --> 01:13:01,209\nstuff before I give it to you, like I did for Assignment\n\n1432\n01:13:01,211 --> 01:13:02,643\nFour, but then I have to teach you the stuff for\n\n1433\n01:13:02,645 --> 01:13:04,912\nthe next thing and sometimes people get confused and they\n\n1434\n01:13:04,914 --> 01:13:07,014\nthink the thing I'm teaching now goes into the assignment\n\n1435\n01:13:07,016 --> 01:13:09,517\nthat went out a couple days ago, but no. Okay so, A4,\n\n1436\n01:13:09,519 --> 01:13:14,589\nAssignment Four, no Core Data. A5, all Core Data basically.\n\n1437\n01:13:14,591 --> 01:13:18,359\nOkay, so next day, week I'll do a demo on this, okay?\n\n1438\n01:13:18,361 --> 01:13:19,994\nOn Monday I'm gonna do a big old demo where\n\n1439\n01:13:19,996 --> 01:13:22,330\nwe're gonna do all of the stuff I talked about today, so\n\n1440\n01:13:22,332 --> 01:13:24,932\nyou can see how it all works in action as always. And\n\n1441\n01:13:24,934 --> 01:13:26,834\nthen you'll have A5 go out that's on Monday, and\n\n1442\n01:13:26,836 --> 01:13:30,772\nthat's gonna be due the next Monday. On Wednesday, I'm\n\n1443\n01:13:30,774 --> 01:13:33,207\ngonna do Auto Layout because I've kind of been hinting at\n\n1444\n01:13:33,209 --> 01:13:35,343\nAuto Layout, showing you a little bit here and\n\n1445\n01:13:35,345 --> 01:13:36,778\nthere but now I'm gonna talk about really how\n\n1446\n01:13:36,780 --> 01:13:40,148\nAuto Layout works to lay out you're, user interface.\n\n1447\n01:13:40,150 --> 01:13:42,583\nYou can use stack view for a lot of things but sometimes\n\n1448\n01:13:42,585 --> 01:13:44,952\nyou need a little bit of extra layout capabilities and\n\n1449\n01:13:44,954 --> 01:13:47,555\nnext week I'm also gonna talk about the requirements for\n\n1450\n01:13:47,557 --> 01:13:51,726\nyour final project, okay? What you are required to do\n\n1451\n01:13:51,728 --> 01:13:53,494\nto have a successful final project.\n\n1452\n01:13:53,496 --> 01:13:56,197\nAnd, so it's time, now, for you to start thinking a little\n\n1453\n01:13:56,199 --> 01:13:59,233\nbit about what you might want to do for a final project. And\n\n1454\n01:13:59,235 --> 01:14:02,203\ncertainly, as soon as I give this lecture next week\n\n1455\n01:14:02,205 --> 01:14:05,273\non final project requirements, right away you're gonna wanna\n\n1456\n01:14:05,275 --> 01:14:07,942\nnail down what you want to do because you only get three\n\n1457\n01:14:07,944 --> 01:14:10,845\nweeks to do it so that only gives you a week or so to\n\n1458\n01:14:10,847 --> 01:14:14,882\nthink of what you want to do. Okay? So be ready to kinda go\n\n1459\n01:14:14,884 --> 01:14:20,054\noutta the gate with that next week. Okay, that's it!\n\n1460\n01:14:20,056 --> 01:14:22,857\nI will see you next week. >> For\n\n1461\n01:14:22,859 --> 01:14:22,890\nmore, please visit us at Stanford.edu.\n\n"
  },
  {
    "path": "subtitles/11. Core Data Demo.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,535\n[MUSIC]\n\n2\n00:00:03,537 --> 00:00:07,373\nStanford University. >> All right.\n\n3\n00:00:07,375 --> 00:00:13,412\nWelcome to Lecture Number 11 of CS193P, the Spring of 2016.\n\n4\n00:00:13,414 --> 00:00:17,783\nToday it's all demo, okay. All demo all the time. We're gonna\n\n5\n00:00:17,785 --> 00:00:22,788\ndo a core data demo. And just to let you know what's coming\n\n6\n00:00:22,790 --> 00:00:26,558\nup since I, cuz I won't come back to the slides obviously.\n\n7\n00:00:26,560 --> 00:00:29,728\nOn Wednesday, we'll be talking about Auto Layout, and also,\n\n8\n00:00:29,730 --> 00:00:31,930\nwe'll be talking about the final project requirements on\n\n9\n00:00:31,932 --> 00:00:35,267\nWednesday, okay? No Friday section this week.\n\n10\n00:00:35,269 --> 00:00:38,637\nAnd then, next week, we'll start talking about animation.\n\n11\n00:00:38,639 --> 00:00:42,975\nYou have an assignment that's out now which is Number Five.\n\n12\n00:00:42,977 --> 00:00:44,343\nWhich is a core data assignment. And\n\n13\n00:00:44,345 --> 00:00:46,512\nthen there will be Assignment Six which will be an animation\n\n14\n00:00:46,514 --> 00:00:50,482\nassignment which will probably go out next Monday and\n\n15\n00:00:50,484 --> 00:00:54,086\ndue the Monday after maybe next Wednesday,\n\n16\n00:00:54,088 --> 00:00:55,054\ndue the Wednesday after. I'm not sure, but\n\n17\n00:00:55,056 --> 00:00:57,222\nprobably next Monday and then that'll be your last\n\n18\n00:00:57,224 --> 00:01:02,428\nassignment before the final project. Okay. All right,\n\n19\n00:01:02,430 --> 00:01:06,532\nso let's talk about this core data demo that we're gonna do.\n\n20\n00:01:06,534 --> 00:01:08,534\nWe're gonna continue with Smashtag,\n\n21\n00:01:08,536 --> 00:01:10,803\nleave off where we were before. Okay so here's\n\n22\n00:01:10,805 --> 00:01:16,141\nthe user interface that we had at the end of Lecture Nine.\n\n23\n00:01:16,143 --> 00:01:19,611\nAnd you're probably very familiar with it because your\n\n24\n00:01:19,613 --> 00:01:21,213\nhomework builds on this. And\n\n25\n00:01:21,215 --> 00:01:24,983\nwe're gonna build on this as well with this core data demo.\n\n26\n00:01:24,985 --> 00:01:28,087\nWhat I'm gonna do is add another, table view\n\n27\n00:01:28,089 --> 00:01:30,522\ncontroller, here. In fact let's just drag it out.\n\n28\n00:01:30,524 --> 00:01:35,861\nSo here it is. And I'm going to segue to this table\n\n29\n00:01:35,863 --> 00:01:40,499\nview controller from a bar button item in this existing\n\n30\n00:01:40,501 --> 00:01:42,334\ntable view controller. Which is a little different,\n\n31\n00:01:42,336 --> 00:01:44,670\nlike in your homework you're segueing from the row.\n\n32\n00:01:44,672 --> 00:01:49,308\nHere I'm actually gonna segue from a little bar button item.\n\n33\n00:01:49,310 --> 00:01:50,275\nNow most of you have figured\n\n34\n00:01:50,277 --> 00:01:52,878\nout that if you wanna add a button to the navigation bar\n\n35\n00:01:52,880 --> 00:01:56,615\nup here you can't use this regular button that's up here.\n\n36\n00:01:56,617 --> 00:01:59,284\nYou have to use these bar buttons that are down towards\n\n37\n00:01:59,286 --> 00:02:02,488\nthe bottom. Here's one right here, a bar button item so\n\n38\n00:02:02,490 --> 00:02:05,657\nyou're just gonna drag it out and see if you drag it up at,\n\n39\n00:02:05,659 --> 00:02:10,229\nup at top of a navigation bar, then it'll jump in there. And,\n\n40\n00:02:10,231 --> 00:02:13,899\nwhat we're gonna have this UI do is, I'm gonna call\n\n41\n00:02:13,901 --> 00:02:17,703\nthis button Tweeters, and we're gonna have this MVC,\n\n42\n00:02:17,705 --> 00:02:19,638\nthis new one we're gonna write today, it's\n\n43\n00:02:19,640 --> 00:02:25,511\ngonna show a list of all the tweeters who tweeted a tweet\n\n44\n00:02:25,513 --> 00:02:29,148\nthat we've ever downloaded with the search term that's in\n\n45\n00:02:29,150 --> 00:02:34,319\nthis MBC. Right? Our main MBC. So we type #Stanford here and\n\n46\n00:02:34,321 --> 00:02:36,588\nsearch for some tweets and then we hit Tweeters.\n\n47\n00:02:36,590 --> 00:02:40,692\nOver here, we would see a list of all the Twitter users who\n\n48\n00:02:40,694 --> 00:02:43,529\ntweeted those tweets with #Stanford in there.\n\n49\n00:02:43,531 --> 00:02:47,432\nOkay, not just in the most, latest search of #Stanford,\n\n50\n00:02:47,434 --> 00:02:49,801\nbut ever. And we're gonna do this by having us\n\n51\n00:02:49,803 --> 00:02:52,371\ncoordinate a database where every time we get a tweet,\n\n52\n00:02:52,373 --> 00:02:54,339\nwe're gonna put it in the database, okay?\n\n53\n00:02:54,341 --> 00:02:57,142\nAnd so, we then, we can query those tweets and\n\n54\n00:02:57,144 --> 00:02:58,010\nget all the information we want,\n\n55\n00:02:58,012 --> 00:03:02,814\nincluding getting a list of the users who have tweeted. So\n\n56\n00:03:02,816 --> 00:03:06,618\nof course we will need a custom subclass of UITableView\n\n57\n00:03:06,620 --> 00:03:10,355\nfor this guy, so let's go ahead and create that. File,\n\n58\n00:03:10,357 --> 00:03:11,623\nNew File as usual, iOS source,\n\n59\n00:03:11,625 --> 00:03:15,394\nit's a Cocoa Touch class. It's a UITableView controller also.\n\n60\n00:03:15,396 --> 00:03:19,064\nWe'll call this our Tweeter's TableView controller,\n\n61\n00:03:19,066 --> 00:03:19,665\ncuz that's what's gonna be in here,\n\n62\n00:03:19,667 --> 00:03:23,001\ntweeters. We'll put it in the same group we put all the rest\n\n63\n00:03:23,003 --> 00:03:25,871\nof our stuff there. Okay, here's our tweeters.\n\n64\n00:03:25,873 --> 00:03:28,340\nWe're not actually going to keep any of this except,\n\n65\n00:03:28,342 --> 00:03:31,510\nactually I'll keep myself a row and index path here. But\n\n66\n00:03:31,512 --> 00:03:36,381\nwe'll get rid of the rest of this boiler plate that we get.\n\n67\n00:03:36,383 --> 00:03:41,520\nOkay, there's our tweeters table view\n\n68\n00:03:41,522 --> 00:03:44,356\ncontroller. And we always want to make sure we go back into\n\n69\n00:03:44,358 --> 00:03:48,026\nour storyboard and set with the identity inspector this to\n\n70\n00:03:48,028 --> 00:03:50,028\nbe our tweeter's table view controller.\n\n71\n00:03:50,030 --> 00:03:50,829\nThis guy right here. And\n\n72\n00:03:50,831 --> 00:03:53,465\nlet's go ahead and wire up this segue right here too.\n\n73\n00:03:53,467 --> 00:03:58,203\nI'm just gonna select this guy and control drag over to here.\n\n74\n00:03:58,205 --> 00:04:00,005\nWe're in a navigation controller so\n\n75\n00:04:00,007 --> 00:04:01,974\nwe won't show if we were in a split view,\n\n76\n00:04:01,976 --> 00:04:03,542\nwe'd be show detail maybe but\n\n77\n00:04:03,544 --> 00:04:05,844\nhere we're in navigation se we're gonna show.\n\n78\n00:04:05,846 --> 00:04:10,315\nHere's our segue, let's give it an identifier, we'll call\n\n79\n00:04:10,317 --> 00:04:16,388\nthis the tweeter's, we'll make this very verbose,\n\n80\n00:04:16,390 --> 00:04:21,159\nTweeters Mentioning Search Term segue. Okay, so\n\n81\n00:04:21,161 --> 00:04:23,629\nthat's what this segue does. When you click tweeters,\n\n82\n00:04:23,631 --> 00:04:27,399\nit shows you all the tweeters that mention this particular\n\n83\n00:04:27,401 --> 00:04:30,202\nsearch term whatever that'll be that be, #Stanford or\n\n84\n00:04:30,204 --> 00:04:35,274\nwhatever. Okay. So that's pretty much setup our UI right\n\n85\n00:04:35,276 --> 00:04:41,713\nthere. One thing that we need here is core data, we wanna be\n\n86\n00:04:41,715 --> 00:04:43,282\nable to access a core data database, so\n\n87\n00:04:43,284 --> 00:04:45,083\nwe need that manage object context,\n\n88\n00:04:45,085 --> 00:04:47,586\nremember that's the hook that let's us in there.\n\n89\n00:04:47,588 --> 00:04:49,588\nAnd I've told you there is two ways to do that,\n\n90\n00:04:49,590 --> 00:04:52,557\none is UI manage document, I'm not gonna demo that,\n\n91\n00:04:52,559 --> 00:04:55,327\nthat's extra credit by the way in Assignment Number Five,\n\n92\n00:04:55,329 --> 00:04:56,461\nif you wanna try and tackle that.\n\n93\n00:04:56,463 --> 00:04:59,231\nOnly thing difficult about that is the asynchronous stuff\n\n94\n00:04:59,233 --> 00:05:01,600\nbut if you're got it comfortable now with\n\n95\n00:05:01,602 --> 00:05:04,670\nasynchrony, it shouldn't be very difficult at all.\n\n96\n00:05:04,672 --> 00:05:07,973\nThe other way was to use code that would get generated for\n\n97\n00:05:07,975 --> 00:05:09,107\nyou when you create a new project and\n\n98\n00:05:09,109 --> 00:05:12,244\nturn on the core data button and that's what I'm gonna use.\n\n99\n00:05:12,246 --> 00:05:16,748\nWe started this project and if we look in our app delegate\n\n100\n00:05:16,750 --> 00:05:20,052\nOkay? This is Smashtags, AppDelegate here.\n\n101\n00:05:20,054 --> 00:05:22,988\nYou can see that it's got some empty methods in here,\n\n102\n00:05:22,990 --> 00:05:25,223\nbasically with some comments about them.\n\n103\n00:05:25,225 --> 00:05:26,391\nWe'll be covering this stuff, by the way.\n\n104\n00:05:26,393 --> 00:05:28,927\nThis is part of what we call the Application Life Cycle,\n\n105\n00:05:28,929 --> 00:05:31,530\nthese methods. But there's nothing in here about core\n\n106\n00:05:31,532 --> 00:05:33,498\ndata because, when we created Smashtag, we didn't\n\n107\n00:05:33,500 --> 00:05:35,534\nthink we were building a core data app at that time,\n\n108\n00:05:35,536 --> 00:05:38,637\nso we didn't switch that button. So no problem though,\n\n109\n00:05:38,639 --> 00:05:41,239\nI'm just gonna create a new project. Go to File, New,\n\n110\n00:05:41,241 --> 00:05:46,078\nProject. Okay, and again, iOS application, single view like\n\n111\n00:05:46,080 --> 00:05:48,647\nwe usually do, and you can call it anything you want.\n\n112\n00:05:48,649 --> 00:05:52,384\nI'm gonna call mine Foo, okay. And just make sure that this\n\n113\n00:05:52,386 --> 00:05:55,220\nbutton right here is switched, Use Core Data, okay, and\n\n114\n00:05:55,222 --> 00:05:58,156\nprobably also wanna make sure it's Swift unless you're\n\n115\n00:05:58,158 --> 00:05:59,458\nbuilding something Objective C.\n\n116\n00:05:59,460 --> 00:06:02,961\nAnd then when you click Next put it anywhere you want.\n\n117\n00:06:02,963 --> 00:06:06,365\nI'll put mine in my same place as always developer here.\n\n118\n00:06:06,367 --> 00:06:09,034\nAnd it makes this Foo, now this Foo is just a blank\n\n119\n00:06:09,036 --> 00:06:12,537\napp right? It's got a blank view controller here.\n\n120\n00:06:12,539 --> 00:06:13,372\nBut we don't care about any of that.\n\n121\n00:06:13,374 --> 00:06:16,241\nAll we care about is in its app delegate, we look\n\n122\n00:06:16,243 --> 00:06:20,612\ndown it's got all those same methods but starting here,\n\n123\n00:06:20,614 --> 00:06:23,148\nCore Data stack it's got a whole bunch of other code,\n\n124\n00:06:23,150 --> 00:06:26,485\nokay. And we just basically want to pick this code up.\n\n125\n00:06:26,487 --> 00:06:29,287\nSo I'm just going to select it all, okay.\n\n126\n00:06:29,289 --> 00:06:32,190\nStarting from this Mark Core Data stack going down to\n\n127\n00:06:32,192 --> 00:06:34,793\nthe end. And I'm just gonna cut it out of here.\n\n128\n00:06:34,795 --> 00:06:38,063\nCopy or cut it. And I'm gonna go to my AppDelegate back in\n\n129\n00:06:38,065 --> 00:06:42,501\nSmashtag here. And I'm just going to paste it in.\n\n130\n00:06:42,503 --> 00:06:45,070\nOkay. Now it's not quite that easy there's two more things\n\n131\n00:06:45,072 --> 00:06:47,472\nwe gotta think about. You can see there are errors here.\n\n132\n00:06:47,474 --> 00:06:49,674\nOkay there's an error there, error here.\n\n133\n00:06:49,676 --> 00:06:53,178\nThat's because Core Data is in a separate framework just like\n\n134\n00:06:53,180 --> 00:06:56,381\nthe Twitter stuff you had is in a separate framework, so\n\n135\n00:06:56,383 --> 00:06:56,915\nis Core Data. So you have to,\n\n136\n00:06:56,917 --> 00:06:59,951\nat the top, anywhere you're going to be using Core Data,\n\n137\n00:06:59,953 --> 00:07:03,922\nsay import CoreData. Okay? So that'll get rid\n\n138\n00:07:03,924 --> 00:07:04,890\nof all of our errors okay,\n\n139\n00:07:04,892 --> 00:07:08,160\nbecause of the types like in this manage object model, and\n\n140\n00:07:08,162 --> 00:07:11,229\nin this persistent core coordinator, things like that.\n\n141\n00:07:11,231 --> 00:07:13,265\nBut there's one more thing we have to be careful of here.\n\n142\n00:07:13,267 --> 00:07:15,534\nAnd, you're really going to want to be careful of this\n\n143\n00:07:15,536 --> 00:07:17,702\nin your homework assignment, which is that,\n\n144\n00:07:17,704 --> 00:07:21,339\nthis code that gets generated, it actually uses the name of\n\n145\n00:07:21,341 --> 00:07:24,709\nthe app as the name of the data model. You know, you know\n\n146\n00:07:24,711 --> 00:07:27,946\nthat visual map we're gonna make with all the entities and\n\n147\n00:07:27,948 --> 00:07:30,081\nattributes? Things I showed you in the slides.\n\n148\n00:07:30,083 --> 00:07:32,684\nIt calls that thing the name of the app so, in this case,\n\n149\n00:07:32,686 --> 00:07:34,653\nFoo, because that's what I called that other app.\n\n150\n00:07:34,655 --> 00:07:37,122\nSo you're gonna wanna change this to whatever you're\n\n151\n00:07:37,124 --> 00:07:38,223\ngonna call your mapping model and\n\n152\n00:07:38,225 --> 00:07:40,759\nyou get to choose, so you can pick anything you want.\n\n153\n00:07:40,761 --> 00:07:44,396\nThe default happens to be Model, okay, but you could\n\n154\n00:07:44,398 --> 00:07:47,199\nalso put the name of your app or whatever you want in here.\n\n155\n00:07:47,201 --> 00:07:50,435\nJust make sure that whatever you put in here Is the same\n\n156\n00:07:50,437 --> 00:07:53,271\nthing as the name you pick when you create the mapping\n\n157\n00:07:53,273 --> 00:07:55,907\nokay, which we're gonna do next. Okay, so that's it.\n\n158\n00:07:55,909 --> 00:07:59,711\nSo once you do that you're gonna get a few vars in here\n\n159\n00:07:59,713 --> 00:08:03,315\nbut the main one that's Import here is this one.\n\n160\n00:08:03,317 --> 00:08:05,450\nManage object context, so that's the thing,\n\n161\n00:08:05,452 --> 00:08:08,587\nthat's the hook that you're gonna get into your database,\n\n162\n00:08:08,589 --> 00:08:13,225\nright. Okay, so let's go ahead and create the schema for\n\n163\n00:08:13,227 --> 00:08:18,330\nthat database. And we do that with File > New > File. But\n\n164\n00:08:18,332 --> 00:08:20,398\nhere instead of doing iOS source,\n\n165\n00:08:20,400 --> 00:08:23,768\nwe're gonna go down to iOS Core Data. Okay? And\n\n166\n00:08:23,770 --> 00:08:27,205\nin here there's three things. And this is the one you want,\n\n167\n00:08:27,207 --> 00:08:28,607\nData Model, cuz that's what we're gonna be doing,\n\n168\n00:08:28,609 --> 00:08:31,810\nthat's our description of raw enti, entities and attributes,\n\n169\n00:08:31,812 --> 00:08:33,578\nour Data Model. Don't accidentally pick\n\n170\n00:08:33,580 --> 00:08:37,215\nMapping Model. It sounds similar, but it's different,\n\n171\n00:08:37,217 --> 00:08:38,617\nokay? So Data Model's what you want.\n\n172\n00:08:38,619 --> 00:08:41,453\nSo we'll double-click on that. Okay, you're gonna get this,\n\n173\n00:08:41,455 --> 00:08:44,122\nso you can see the default is Model. Just make sure this is\n\n174\n00:08:44,124 --> 00:08:46,491\nthe same as whatever you put in your app delegate,\n\n175\n00:08:46,493 --> 00:08:49,160\nthat code that you copied in and, make sure you put it\n\n176\n00:08:49,162 --> 00:08:52,097\nwhere you want. Like, I really don't want this in supporting\n\n177\n00:08:52,099 --> 00:08:54,533\nfiles or I don't want it down here in supporting files,\n\n178\n00:08:54,535 --> 00:08:57,202\nI want it up at a higher level here at the smash tag level,\n\n179\n00:08:57,204 --> 00:09:00,305\nokay? So let me put that there, hit Create and\n\n180\n00:09:00,307 --> 00:09:03,775\nit creates this empty map, okay. It has no entities yet,\n\n181\n00:09:03,777 --> 00:09:08,780\nno attributes. Now our app is going to have some Twitter\n\n182\n00:09:08,782 --> 00:09:10,782\nusers. It's gonna show Twitter users for,\n\n183\n00:09:10,784 --> 00:09:13,785\nthat have tweeted a certain mention in a bunch of tweets.\n\n184\n00:09:13,787 --> 00:09:17,589\nSo clearly we're gonna need an entity which is a Twitter user\n\n185\n00:09:17,591 --> 00:09:19,758\nand we're probably gonna need an entity which is a tweet.\n\n186\n00:09:19,760 --> 00:09:22,861\nSo let's create our entities and see where it takes us.\n\n187\n00:09:22,863 --> 00:09:23,995\nSo I clicked this button down here,\n\n188\n00:09:23,997 --> 00:09:28,199\nAdd Entity, and I added this entity called, Entity. And\n\n189\n00:09:28,201 --> 00:09:29,434\nI'm gonna double-click on it to rename it.\n\n190\n00:09:29,436 --> 00:09:33,238\nI'm gonna call it TwitterUser. Okay, so this is gonna be\n\n191\n00:09:33,240 --> 00:09:36,708\nthe entity that represents a Twitter user in my database.\n\n192\n00:09:36,710 --> 00:09:39,110\nOkay, gonna add another entity, clicking down here,\n\n193\n00:09:39,112 --> 00:09:42,647\nokay? This one I'm gonna call Tweet, so it's gonna represent\n\n194\n00:09:42,649 --> 00:09:46,184\na tweet. Now, once we have these entities,\n\n195\n00:09:46,186 --> 00:09:49,721\nwe obviously need attributes on them. So Tweet, we're going\n\n196\n00:09:49,723 --> 00:09:53,491\nto add text, which is, every tweet has a text, 140\n\n197\n00:09:53,493 --> 00:09:57,095\ncharacters worth. You can see I have an error right up here.\n\n198\n00:09:57,097 --> 00:09:59,598\nIt says, Tweet text must have a defined type.\n\n199\n00:09:59,600 --> 00:10:02,667\nAnd it's right now undefined. So I'm gonna pick it to be\n\n200\n00:10:02,669 --> 00:10:05,103\na string and I could add other things here.\n\n201\n00:10:05,105 --> 00:10:08,974\nMaybe one thing that'd be really important with tweet,\n\n202\n00:10:08,976 --> 00:10:11,109\nwith a tweet, when I'm fetching these tweets,\n\n203\n00:10:11,111 --> 00:10:14,045\nif I typed #Stanford and fetched 100 tweets, and\n\n204\n00:10:14,047 --> 00:10:16,548\nthen I typed #Stanford and fetched another 100 tweets,\n\n205\n00:10:16,550 --> 00:10:19,317\nit would probably be mostly the same tweets, maybe one or\n\n206\n00:10:19,319 --> 00:10:22,320\ntwo new ones. So I need some kind of unique identifier in\n\n207\n00:10:22,322 --> 00:10:24,255\nthe database to identify a tweet so\n\n208\n00:10:24,257 --> 00:10:26,257\nI don't get all kinds of duplicates. I don't want,\n\n209\n00:10:26,259 --> 00:10:28,426\nyou know, the same Tweet in there tons of times.\n\n210\n00:10:28,428 --> 00:10:32,163\nSo I'm gonna call it Unique. Luckily, we're gonna find that\n\n211\n00:10:32,165 --> 00:10:35,433\nthe Twitter, framework provides a nice unique ID that\n\n212\n00:10:35,435 --> 00:10:38,336\nwe can use to be, to uni, to unique our tweets so\n\n213\n00:10:38,338 --> 00:10:40,872\nthat's good. And I can put other things in here, like,\n\n214\n00:10:40,874 --> 00:10:44,309\nmaybe, you know, the created date of the tweet,\n\n215\n00:10:44,311 --> 00:10:46,845\nmaybe I would call that posted and you see I'm making\n\n216\n00:10:46,847 --> 00:10:50,515\nthe type here be date. These names don't have to match\n\n217\n00:10:50,517 --> 00:10:51,783\nthe names in the Twitter framework at all.\n\n218\n00:10:51,785 --> 00:10:54,319\nIn fact, the Twitter framework is completely separate.\n\n219\n00:10:54,321 --> 00:10:55,987\nIt has nothing to do with core data.\n\n220\n00:10:55,989 --> 00:10:57,756\nIt just gets the data from Twitter. Okay,\n\n221\n00:10:57,758 --> 00:11:00,392\nit's our responsibility to take that data from Twitter\n\n222\n00:11:00,394 --> 00:11:02,927\nand put it into this database with whatever attributes and\n\n223\n00:11:02,929 --> 00:11:06,431\nentities we want. Okay, now we happen to call this tweet and\n\n224\n00:11:06,433 --> 00:11:09,634\nwe also have a class in our Twitter framework called tweet\n\n225\n00:11:09,636 --> 00:11:12,704\nalso and we're gonna have to be careful about that. But\n\n226\n00:11:12,706 --> 00:11:13,772\nthey're totally different. Okay,\n\n227\n00:11:13,774 --> 00:11:15,607\nthey represent the same thing conceptually, a tweet,\n\n228\n00:11:15,609 --> 00:11:19,377\nbut they're different classes. All right, our Twitter user,\n\n229\n00:11:19,379 --> 00:11:21,846\nwhat does a Twitter user have? Well, a screen name,\n\n230\n00:11:21,848 --> 00:11:23,948\nobviously, that's the most important thing,\n\n231\n00:11:23,950 --> 00:11:26,484\nthat's your Twitter handle, you know, @whatever,\n\n232\n00:11:26,486 --> 00:11:30,055\nthat's a string. You know, the, we don't really need much\n\n233\n00:11:30,057 --> 00:11:33,224\nelse for our app here, but maybe there's the actual name,\n\n234\n00:11:33,226 --> 00:11:36,027\nwe could have other attributes of a user, put whatever we\n\n235\n00:11:36,029 --> 00:11:40,365\nwant in here. Okay? Now, as time goes by, as you enhance\n\n236\n00:11:40,367 --> 00:11:42,600\nyour app, you're gonna be adding more attribute,\n\n237\n00:11:42,602 --> 00:11:44,769\nmore entities, and that's perfectly fine.\n\n238\n00:11:44,771 --> 00:11:47,372\nThe only thing to notice is every time you change your\n\n239\n00:11:47,374 --> 00:11:50,842\nmodel here, okay? The database that's on your simulator or\n\n240\n00:11:50,844 --> 00:11:55,146\non your device is now invalid, okay? Now, there is a way to\n\n241\n00:11:55,148 --> 00:11:57,982\nmake compatible changes, I'm not really gonna talk about\n\n242\n00:11:57,984 --> 00:12:01,286\nthat. But there is a way to do that. Once you, if you started\n\n243\n00:12:01,288 --> 00:12:03,021\nshipping an app on the app store, then that would start\n\n244\n00:12:03,023 --> 00:12:05,623\nto matter to you because you wanna ship a new version.\n\n245\n00:12:05,625 --> 00:12:06,858\nMaybe it has some new attributes, you\n\n246\n00:12:06,860 --> 00:12:10,595\nwant all the data the user's created to still be good. But\n\n247\n00:12:10,597 --> 00:12:12,430\nwhen you're in development and you're changing things,\n\n248\n00:12:12,432 --> 00:12:15,500\nwhat you can do is just go on to your device, or\n\n249\n00:12:15,502 --> 00:12:16,234\nyour, simulator, and\n\n250\n00:12:16,236 --> 00:12:20,004\ndelete your app. Okay, every time you change your schema,\n\n251\n00:12:20,006 --> 00:12:22,073\nyou're gonna have to delete your app and then run again.\n\n252\n00:12:22,075 --> 00:12:24,576\nOf course, you'll lose all your data in the database too,\n\n253\n00:12:24,578 --> 00:12:27,912\nbut, that's just, you're doing development cycles anyway, so\n\n254\n00:12:27,914 --> 00:12:31,182\nit shouldn't, probably shouldn't matter. Okay.\n\n255\n00:12:31,184 --> 00:12:33,184\nAll right, so we have this great thing.\n\n256\n00:12:33,186 --> 00:12:35,253\nLet's take a look at it in the graphical view,\n\n257\n00:12:35,255 --> 00:12:36,888\nclicking this little button down here, and\n\n258\n00:12:36,890 --> 00:12:39,457\nyou can see here's our two things. Notice if I move one,\n\n259\n00:12:39,459 --> 00:12:42,961\nthe other one kind of moves around to keep it all,\n\n260\n00:12:42,963 --> 00:12:43,795\nin a nice space here.\n\n261\n00:12:43,797 --> 00:12:46,364\nAnd you can see here's my attributes, the name,\n\n262\n00:12:46,366 --> 00:12:49,434\nthe screen name, you can see that the inspector over here\n\n263\n00:12:49,436 --> 00:12:52,570\nis showing us things like the type of it. All right?\n\n264\n00:12:52,572 --> 00:12:55,774\nClick on this one, type. You can even set some things like\n\n265\n00:12:55,776 --> 00:12:58,243\nminimum and maximums for dates and things like that.\n\n266\n00:12:58,245 --> 00:13:00,712\nI'm not really gonna talk about this inspector. You can\n\n267\n00:13:00,714 --> 00:13:03,047\nplay around with it, certainly read the documentation and\n\n268\n00:13:03,049 --> 00:13:06,384\nfind out all the things you can do over here. But\n\n269\n00:13:06,386 --> 00:13:09,420\nwhat I'm interested now is the relationship between Twitter\n\n270\n00:13:09,422 --> 00:13:10,789\nusers and Tweets, okay. And\n\n271\n00:13:10,791 --> 00:13:14,459\nwe know that a Twitter user Tweets and creates a bunch of\n\n272\n00:13:14,461 --> 00:13:16,161\nthese things, okay, creates a bunch of Tweets.\n\n273\n00:13:16,163 --> 00:13:18,897\nSo there's a relationship between these two, and anytime\n\n274\n00:13:18,899 --> 00:13:21,599\nthere's a relationship between entities in your data model,\n\n275\n00:13:21,601 --> 00:13:25,270\nyou just go to this graphical view, hold down Ctrl, and\n\n276\n00:13:25,272 --> 00:13:28,740\ndrag between them, okay? When you let go, you're gonna get\n\n277\n00:13:28,742 --> 00:13:31,609\nthese new things. These are also gonna be vars ju-, in\n\n278\n00:13:31,611 --> 00:13:35,213\nyour code, just like these are vars, which is a relationship\n\n279\n00:13:35,215 --> 00:13:38,950\nbetween the two. And each side has a relationship, okay? And\n\n280\n00:13:38,952 --> 00:13:40,552\nyou'll, first thing you'll want to do\n\n281\n00:13:40,554 --> 00:13:42,887\nis rename these to be more meaningful names than\n\n282\n00:13:42,889 --> 00:13:44,889\nnewRelationship. So a Twitter user,\n\n283\n00:13:44,891 --> 00:13:48,827\nTwitter user's relationship to their tweets is probably gonna\n\n284\n00:13:48,829 --> 00:13:51,529\nbe called tweets. It's the tweets that they've tweeted,\n\n285\n00:13:51,531 --> 00:13:54,599\nright? And similarly a tweet, the relationship it has\n\n286\n00:13:54,601 --> 00:13:57,402\nto the Twitter user who tweeted it is probably,\n\n287\n00:13:57,404 --> 00:13:59,237\nyou could call it user, or poster, or\n\n288\n00:13:59,239 --> 00:14:02,607\nI'm gonna call it tweeter, but it doesn't really matter,\n\n289\n00:14:02,609 --> 00:14:06,044\nit's just the name of a var, that we're gonna have in our\n\n290\n00:14:06,046 --> 00:14:09,447\ncode, that represents the relationship between the two.\n\n291\n00:14:09,449 --> 00:14:12,784\nNow, as we talked about in the slides about core data,\n\n292\n00:14:12,786 --> 00:14:15,987\nthere's something special about this relationship,\n\n293\n00:14:15,989 --> 00:14:19,624\nthis tweet's relationship to tweet, which is that a Twitter\n\n294\n00:14:19,626 --> 00:14:23,394\nuser can have multiple tweets, could have hundreds of tweets\n\n295\n00:14:23,396 --> 00:14:27,899\npossibly, okay? A given tweet only has one tweeter. But\n\n296\n00:14:27,901 --> 00:14:31,236\na good, a twitter user could have hundreds of tweets. So\n\n297\n00:14:31,238 --> 00:14:32,403\nthis relationship's a little different. So\n\n298\n00:14:32,405 --> 00:14:36,207\nwhen we click on it here and look at it in the inspector,\n\n299\n00:14:36,209 --> 00:14:37,876\nand see the inspector is pretty smart.\n\n300\n00:14:37,878 --> 00:14:40,478\nIt knows there's an inverse relationship tweeter\n\n301\n00:14:40,480 --> 00:14:42,914\nover here. That's the inverse of tweets. And\n\n302\n00:14:42,916 --> 00:14:45,817\nit also knows the type of connection here is To one and\n\n303\n00:14:45,819 --> 00:14:49,754\nwe want to tell it no. This is a To many, To many connection,\n\n304\n00:14:49,756 --> 00:14:54,125\nokay, meaning there are many tweets per Twitter user. And\n\n305\n00:14:54,127 --> 00:14:57,262\nwhen we do that to To many, you can see that the arrow\n\n306\n00:14:57,264 --> 00:14:59,931\nhere gets double arrowed in this direction. Only this\n\n307\n00:14:59,933 --> 00:15:02,901\ndirection, it's still single To one in that direction, but\n\n308\n00:15:02,903 --> 00:15:05,536\nit's To many in this direction. Okay, and\n\n309\n00:15:05,538 --> 00:15:07,505\nthat's perfectly fine for one to be a To one and\n\n310\n00:15:07,507 --> 00:15:10,074\none to be a To many, as you can see here. You can also\n\n311\n00:15:10,076 --> 00:15:13,645\nhave both of them be To many. That's legal as well.\n\n312\n00:15:13,647 --> 00:15:17,048\nAll right, and we also know from the slides that what this\n\n313\n00:15:17,050 --> 00:15:21,352\nmeans is that tweets var, okay, on our Twitter user,\n\n314\n00:15:21,354 --> 00:15:23,187\nis gonna be an ns set. And\n\n315\n00:15:23,189 --> 00:15:25,823\nin that ns set are gonna be ns managed objects.\n\n316\n00:15:25,825 --> 00:15:29,594\nThis is an ns managed object. This is an ns managed object.\n\n317\n00:15:29,596 --> 00:15:33,698\nThis var, that points this way in Tweet, is gonna be an ns\n\n318\n00:15:33,700 --> 00:15:37,835\nmanaged object, okay, because it's only a single one.\n\n319\n00:15:37,837 --> 00:15:40,705\nEvery single entity in the database is represented by\n\n320\n00:15:40,707 --> 00:15:43,875\nan ns managed object. Now, that's a little bit kind\n\n321\n00:15:43,877 --> 00:15:46,377\nof hard to use, to have every single thing,\n\n322\n00:15:46,379 --> 00:15:49,147\nTwitter users and tweets be NS managed object.\n\n323\n00:15:49,149 --> 00:15:50,782\nBecause the only way we can set the attributes\n\n324\n00:15:50,784 --> 00:15:53,685\nis using that set value for key. And get the attributes\n\n325\n00:15:53,687 --> 00:15:57,055\nwith value for key. It's a little unwieldy. So of course,\n\n326\n00:15:57,057 --> 00:15:59,791\nwe want to have subclasses of NS managed object for\n\n327\n00:15:59,793 --> 00:16:02,427\neach of our entities. So a class called tweet, which\n\n328\n00:16:02,429 --> 00:16:05,063\nis a subclass of NS managed object that represents these\n\n329\n00:16:05,065 --> 00:16:07,932\nthings, and has vars for all this. And the same thing for\n\n330\n00:16:07,934 --> 00:16:12,070\nTwitter user. Okay. And again, remember from the slides we\n\n331\n00:16:12,072 --> 00:16:14,539\ncan go up here and have, in the editor menu,\n\n332\n00:16:14,541 --> 00:16:17,709\nXcode generate those sub classes for us. One thing I'll\n\n333\n00:16:17,711 --> 00:16:20,578\nremind you if you're gonna do this, see where it says model\n\n334\n00:16:20,580 --> 00:16:23,948\ndot x c model. Do you see how that's selected? This menu,\n\n335\n00:16:23,950 --> 00:16:26,184\nthe editor menu is contact sensitive,\n\n336\n00:16:26,186 --> 00:16:28,486\nit depends on what thing you have selected.\n\n337\n00:16:28,488 --> 00:16:29,087\nSo for example if I go over here and\n\n338\n00:16:29,089 --> 00:16:32,390\npick Story Board, look this menu£s completely different,\n\n339\n00:16:32,392 --> 00:16:34,292\nit£s doing Story Board things over here,\n\n340\n00:16:34,294 --> 00:16:36,094\nokay like embedding and stuff like that. So\n\n341\n00:16:36,096 --> 00:16:38,730\nyou wanna make sure you have this data model selected so\n\n342\n00:16:38,732 --> 00:16:41,466\nthat you get the data model editor menu.\n\n343\n00:16:41,468 --> 00:16:45,737\nSo we're gonna pick Create NS managed sub class here.\n\n344\n00:16:45,739 --> 00:16:46,170\nSo NS Managed sub class,\n\n345\n00:16:46,172 --> 00:16:49,007\nit's saying which of these do you wanna create it for?\n\n346\n00:16:49,009 --> 00:16:51,876\nWe only have one okay, so it's obviously selected.\n\n347\n00:16:51,878 --> 00:16:54,345\nBut you can actually have multiple of these mappings and\n\n348\n00:16:54,347 --> 00:16:57,281\nhave multiple databases. Here it's saying which of\n\n349\n00:16:57,283 --> 00:16:59,817\nthe entities do you wanna generate sub classes for and\n\n350\n00:16:59,819 --> 00:17:03,388\nI'm gonna click them both. Okay? I want both of these.\n\n351\n00:17:03,390 --> 00:17:06,557\nClick next. And be very careful of this one, okay?\n\n352\n00:17:06,559 --> 00:17:09,260\nThis is asking you where you want to put these things.\n\n353\n00:17:09,262 --> 00:17:10,661\nWell, look where it wanted to put it.\n\n354\n00:17:10,663 --> 00:17:13,564\nRight at the very top of my work space.\n\n355\n00:17:13,566 --> 00:17:14,632\nI definitely don't want it there.\n\n356\n00:17:14,634 --> 00:17:17,335\nI definitely want it somewhere in my Smash Tag project.\n\n357\n00:17:17,337 --> 00:17:20,204\nProbably right at this level. Not in supporting files, but\n\n358\n00:17:20,206 --> 00:17:23,608\nright here. Make sure you set this you'll be unhappy if you\n\n359\n00:17:23,610 --> 00:17:25,977\nput it up in your top work space level,\n\n360\n00:17:25,979 --> 00:17:29,547\nfiles won't be in the right place it'll be bad.\n\n361\n00:17:29,549 --> 00:17:31,682\nAlso make sure you're language is right of course.\n\n362\n00:17:31,684 --> 00:17:35,286\nThis scaler remember that's, all the things that,\n\n363\n00:17:35,288 --> 00:17:38,056\nintegers and doubles are represented as NS numbers,\n\n364\n00:17:38,058 --> 00:17:40,892\nokay? And if you do the use scalers the Vars\n\n365\n00:17:40,894 --> 00:17:41,692\nthat it will create will be\n\n366\n00:17:41,694 --> 00:17:44,228\nnot be NS numbers will be instant doubles. And\n\n367\n00:17:44,230 --> 00:17:49,300\nfortunately, in this time intervals. I don't want that.\n\n368\n00:17:49,302 --> 00:17:51,969\nI have it in this date right here posted. So\n\n369\n00:17:51,971 --> 00:17:54,539\nI'm not going to switch this, but if you change your mind\n\n370\n00:17:54,541 --> 00:17:57,308\non this you can always go back and regenerate these. Okay,\n\n371\n00:17:57,310 --> 00:17:59,243\nit's not like you generate these once and you're done,\n\n372\n00:17:59,245 --> 00:18:01,779\nyou can always go back. All right. So I'm going to\n\n373\n00:18:01,781 --> 00:18:04,515\nhit create to create this thing. We'll see the files\n\n374\n00:18:04,517 --> 00:18:09,120\nare created, okay. You can see right here this first one is\n\n375\n00:18:09,122 --> 00:18:10,421\ntweet okay? Tweet.swift.\n\n376\n00:18:10,423 --> 00:18:13,624\nIt's a sub class of NS managed object as we would expect. And\n\n377\n00:18:13,626 --> 00:18:15,927\nthis is just a place we can put any code we want,\n\n378\n00:18:15,929 --> 00:18:18,796\nokay? Any code that in an object oriented design sense\n\n379\n00:18:18,798 --> 00:18:22,100\nwould make sense to be in the tweet, class.\n\n380\n00:18:22,102 --> 00:18:24,936\nOkay this is a bizarre place to do thing. If we go back and\n\n381\n00:18:24,938 --> 00:18:30,174\nregenerate these this file will not get changed. Okay? So\n\n382\n00:18:30,176 --> 00:18:33,578\nit won't stomp our, whatever code we put in here. Okay,\n\n383\n00:18:33,580 --> 00:18:39,016\nsimilar we have TwitterUser, okay, right here. Same thing,\n\n384\n00:18:39,018 --> 00:18:40,284\nokay? Just a place to put a TwitterUser.\n\n385\n00:18:40,286 --> 00:18:41,953\nIt's a sub-class of NSManagedObject. And\n\n386\n00:18:41,955 --> 00:18:45,323\nthen there are these, these two really cool extensions\n\n387\n00:18:45,325 --> 00:18:47,959\nthat were created for us, okay, one for TwitterUser and\n\n388\n00:18:47,961 --> 00:18:51,896\none for Tweet that have vars that represent each of our\n\n389\n00:18:51,898 --> 00:18:53,564\nattributes, so we don't have to use set value for\n\n390\n00:18:53,566 --> 00:18:56,167\na key, okay? You can see its screenName is a string,\n\n391\n00:18:56,169 --> 00:18:59,403\nname is a string, tweet, as promised, is an NSSet.\n\n392\n00:18:59,405 --> 00:19:02,373\nAnd in that NSSet, we NSManage objects, in fact,\n\n393\n00:19:02,375 --> 00:19:06,644\nthey'll be tweets, okay? A subclass of NSManagedObject.\n\n394\n00:19:06,646 --> 00:19:07,912\nNotice that they are all optional,\n\n395\n00:19:07,914 --> 00:19:10,948\nthat's because when we create a twitter user in this\n\n396\n00:19:10,950 --> 00:19:14,285\ncase in the database all the. Okay,\n\n397\n00:19:14,287 --> 00:19:19,490\nwe can set them to whatever we want and similar for tweet.\n\n398\n00:19:19,492 --> 00:19:23,127\nOkay, it's got an extension as well as you can see, and\n\n399\n00:19:23,129 --> 00:19:25,463\nnotice it's tweeter relationship\n\n400\n00:19:25,465 --> 00:19:30,134\nis a pointer to a TwitterUser If you do this, and\n\n401\n00:19:30,136 --> 00:19:34,605\nyou find this to be managed object, okay? It could be\n\n402\n00:19:34,607 --> 00:19:37,341\nbecause your Tweet and Twitter user files got generated\n\n403\n00:19:37,343 --> 00:19:39,810\nin the wrong order, so that twitter user hadn't been\n\n404\n00:19:39,812 --> 00:19:43,147\ngenerated at the time tweet was, and so it gets object.\n\n405\n00:19:43,149 --> 00:19:46,484\nThe fix is just go back and regenerate them again, okay?\n\n406\n00:19:46,486 --> 00:19:50,755\nCuz it takes into account what is generated in the past.\n\n407\n00:19:50,757 --> 00:19:53,591\nOkay? Otherwise this is all pretty straightforward.\n\n408\n00:19:53,593 --> 00:19:54,792\nNow these files you never edit.\n\n409\n00:19:54,794 --> 00:19:57,929\nThese files get regenerated every time you go into that\n\n410\n00:19:57,931 --> 00:20:01,632\ncreate ns manage object thing. So as you change your schema\n\n411\n00:20:01,634 --> 00:20:06,003\nthese might change. All right now I like to take all of\n\n412\n00:20:06,005 --> 00:20:10,041\nthese core data things, okay, including my model file and\n\n413\n00:20:10,043 --> 00:20:11,275\nI like to put them in their own groups.\n\n414\n00:20:11,277 --> 00:20:14,445\nI'll select them all and say new group from selection and\n\n415\n00:20:14,447 --> 00:20:18,482\ncall it core data. So this is my core data group.\n\n416\n00:20:18,484 --> 00:20:18,549\nInside this group,\n\n417\n00:20:18,551 --> 00:20:21,452\nI've got all my stuff that has to do with core data, and\n\n418\n00:20:21,454 --> 00:20:25,156\nwe're going to add a little bit more to that in a minute.\n\n419\n00:20:26,192 --> 00:20:29,594\nAlright, so back to our app and\n\n420\n00:20:29,596 --> 00:20:31,195\nwhat we're trying to accomplish here.\n\n421\n00:20:31,197 --> 00:20:32,630\nAll right, so here's what our app looks like,\n\n422\n00:20:32,632 --> 00:20:34,599\nright? Just got this thing that's gonna segue,\n\n423\n00:20:34,601 --> 00:20:39,003\nthere's really two parts to making this new NVC work.\n\n424\n00:20:39,005 --> 00:20:41,339\nOne is we have to put data in the database,\n\n425\n00:20:41,341 --> 00:20:44,242\nthat's actually something this NVC does, cuz it's the thing\n\n426\n00:20:44,244 --> 00:20:46,510\nthat does the fetching. When we type #Stanford,\n\n427\n00:20:46,512 --> 00:20:48,145\nit's the thing that goes out and gets them.\n\n428\n00:20:48,147 --> 00:20:51,816\nSo this is going to load up the database with Tweet and\n\n429\n00:20:51,818 --> 00:20:52,283\ntweeter users. And\n\n430\n00:20:52,285 --> 00:20:55,286\nthen this one is going to look in the database, okay,\n\n431\n00:20:55,288 --> 00:20:57,488\nto find things out. So let's do this part first,\n\n432\n00:20:57,490 --> 00:21:00,124\nlet's go to our existing tweet table view controller and\n\n433\n00:21:00,126 --> 00:21:03,828\nhave it update the database every time we do a fetch.\n\n434\n00:21:03,830 --> 00:21:05,696\nAll right, so here's our code for\n\n435\n00:21:05,698 --> 00:21:08,733\nour tweet table view hopefully your you i remember this where\n\n436\n00:21:08,735 --> 00:21:11,369\nyou intimately famil, familiar with it as our search text.\n\n437\n00:21:11,371 --> 00:21:14,238\nHere's where we're doing our search for tweets, right.\n\n438\n00:21:14,240 --> 00:21:16,040\nHere's where we find new tweets and\n\n439\n00:21:16,042 --> 00:21:18,509\ninsert them in the table. So I'm just gonna,\n\n440\n00:21:18,511 --> 00:21:20,144\nin addition here to putting them in the table,\n\n441\n00:21:20,146 --> 00:21:24,682\nI'm gonna call some method, let's say updateDatabase and\n\n442\n00:21:24,684 --> 00:21:29,954\npass along these new tweets to go put them in the database,\n\n443\n00:21:29,956 --> 00:21:34,191\nall right. Now, we're gonna be doing CoreData here, so\n\n444\n00:21:34,193 --> 00:21:37,828\nI wanna make sure I import CoreData up at the top here,\n\n445\n00:21:37,830 --> 00:21:43,467\nokay? And then I have to write this method here, private func\n\n446\n00:21:43,469 --> 00:21:48,372\nupdateDatabase, okay? It takes the new tweets that it got,\n\n447\n00:21:48,374 --> 00:21:50,741\nwhich is an array of tweet, but\n\n448\n00:21:50,743 --> 00:21:52,810\nnow I have to be careful here, okay?\n\n449\n00:21:52,812 --> 00:21:56,614\nCuz which tweet is this? Is that the tweet in the Twitter\n\n450\n00:21:56,616 --> 00:22:00,785\nframework, or is that this tweet right here that's an ns\n\n451\n00:22:00,787 --> 00:22:05,089\nmanaged object? Hm, okay we have to be careful here. And\n\n452\n00:22:05,091 --> 00:22:07,591\nthe way we distinguish the two is by putting the framework\n\n453\n00:22:07,593 --> 00:22:11,929\nname in front. So this update database takes Twitter tweets\n\n454\n00:22:11,931 --> 00:22:15,399\nand we're gonna put them, turn them into, in [INAUDIBLE]\n\n455\n00:22:15,401 --> 00:22:17,902\ntweets and put ' in the database so be careful if you\n\n456\n00:22:17,904 --> 00:22:20,905\ndo that. Now when you do your homework, you're welcome to\n\n457\n00:22:20,907 --> 00:22:24,575\nnot call this thing in your database tweet.\n\n458\n00:22:24,577 --> 00:22:27,111\nIf you don't wanna have to deal with twitter.tweet.\n\n459\n00:22:27,113 --> 00:22:30,881\nOkay you can call it something else. But it, if you do call\n\n460\n00:22:30,883 --> 00:22:33,751\nit tweet, then you wanna make sure to distinguish which ones\n\n461\n00:22:33,753 --> 00:22:37,555\nyou're talking about at any given time. All right? Now,\n\n462\n00:22:37,557 --> 00:22:40,091\nto update our database, here's where we need that\n\n463\n00:22:40,093 --> 00:22:43,227\nobject context, right? That little hook that lets us put\n\n464\n00:22:43,229 --> 00:22:45,262\nthings in the database, search through the database, etc ect.\n\n465\n00:22:45,264 --> 00:22:50,067\nI'm actually gonna make that part of the model of this NVC,\n\n466\n00:22:50,069 --> 00:22:52,169\nbecause if you think about what this NVC does, yeah,\n\n467\n00:22:52,171 --> 00:22:55,306\nit lets you search, but it also updates that database.\n\n468\n00:22:55,308 --> 00:22:58,442\nWhich database it updates is really part of\n\n469\n00:22:58,444 --> 00:23:00,111\ndescribing its model. Okay, so\n\n470\n00:23:00,113 --> 00:23:04,014\nI'm gonna have a var here called managedObjectContext.\n\n471\n00:23:04,016 --> 00:23:07,451\nIt's gonna be an NSManagedObjectContext, and\n\n472\n00:23:07,453 --> 00:23:09,587\nit'll be optional. And if this is nil,\n\n473\n00:23:09,589 --> 00:23:12,556\nthis is not set to anything, then I just won't update any\n\n474\n00:23:12,558 --> 00:23:15,192\ndatabase. Okay, so I'm gonna write my code, so if this is\n\n475\n00:23:15,194 --> 00:23:17,862\nnil I'm not gonna update it. I'll still do my searching,\n\n476\n00:23:17,864 --> 00:23:19,797\nbut I'm not gonna update any database. So\n\n477\n00:23:19,799 --> 00:23:24,101\nif anyone wants me to update a database they better set this,\n\n478\n00:23:24,103 --> 00:23:26,237\nokay, to the database they want me to update.\n\n479\n00:23:26,239 --> 00:23:28,939\nNow especially for demo purposes, I'm actually gonna\n\n480\n00:23:28,941 --> 00:23:32,176\nhave this have a default which is that App delegate thing.\n\n481\n00:23:32,178 --> 00:23:35,146\nRemember that code that we just copied over into app\n\n482\n00:23:35,148 --> 00:23:37,915\ndelegate over here? This manage object context?\n\n483\n00:23:37,917 --> 00:23:42,620\nI wanna call this property, access this property on my\n\n484\n00:23:42,622 --> 00:23:45,489\napp delegate, to get the managed object context. Again,\n\n485\n00:23:45,491 --> 00:23:48,292\nif you're using a UI managed document, you'd be doing this\n\n486\n00:23:48,294 --> 00:23:50,828\ndifferently. Okay? So I got a call then.\n\n487\n00:23:50,830 --> 00:23:53,764\nIf you remember how that code goes, we're gonna get\n\n488\n00:23:53,766 --> 00:23:56,167\nUI applications, shared applications.\n\n489\n00:23:56,169 --> 00:23:58,836\nSo this is just an instance of UI application that's shared.\n\n490\n00:23:58,838 --> 00:24:01,739\nSo outta your whole app, it's the only one you're ever\n\n491\n00:24:01,741 --> 00:24:04,308\ngonna use. Now I'm gonna get its delegate.\n\n492\n00:24:04,310 --> 00:24:08,712\nOkay, now its delegate is of type UI application delegate.\n\n493\n00:24:08,714 --> 00:24:11,182\nRight, it's a protocol. You know how delegates work,\n\n494\n00:24:11,184 --> 00:24:13,517\nit's always a protocol. And we don't want that, okay?\n\n495\n00:24:13,519 --> 00:24:17,188\nWe want it to be this particular app delegate class\n\n496\n00:24:17,190 --> 00:24:21,358\nright here. Okay. This app class app delegate, kind of\n\n497\n00:24:21,360 --> 00:24:24,628\na generic name app delegate. It happens to implement the UI\n\n498\n00:24:24,630 --> 00:24:27,364\napplication delegate protocol so that's good. Okay. So\n\n499\n00:24:27,366 --> 00:24:32,770\nthat means I can go over here and say as AppDelegate, okay?\n\n500\n00:24:32,772 --> 00:24:35,606\nSo now I have a hold of that AppDelegate\n\n501\n00:24:35,608 --> 00:24:39,043\ninstance, all right? And all I need to do now is send it\n\n502\n00:24:39,045 --> 00:24:41,145\nManagedObjectContext. So let's go ahead and do that.\n\n503\n00:24:41,147 --> 00:24:42,746\nI had to put a parentheses around here.\n\n504\n00:24:42,748 --> 00:24:46,317\nNow this might be nil, okay? What if the delegate is for\n\n505\n00:24:46,319 --> 00:24:49,253\nsome reason not set, or what if it isn't this class\n\n506\n00:24:49,255 --> 00:24:52,823\nAppDelegate for some reason? You change it mid-flight,\n\n507\n00:24:52,825 --> 00:24:57,027\nokay? Then I'm gonna optional chain here and get the managed\n\n508\n00:24:57,029 --> 00:25:01,699\nobject content. Okay. So this all might come out nil,\n\n509\n00:25:01,701 --> 00:25:05,436\nthat's okay because this is an optional. We just won't do,\n\n510\n00:25:05,438 --> 00:25:07,571\nput in anything in the database in that case.\n\n511\n00:25:07,573 --> 00:25:11,175\nAll right, now it's a little weird to have this default.\n\n512\n00:25:11,177 --> 00:25:13,644\nMore likely you would just have this be nil and\n\n513\n00:25:13,646 --> 00:25:15,846\nsomeone would have to explicitly set it, but\n\n514\n00:25:15,848 --> 00:25:19,116\nthat would require probably to create a little subclass of\n\n515\n00:25:19,118 --> 00:25:22,119\ntweet table view called root tweet table view, and\n\n516\n00:25:22,121 --> 00:25:23,621\nit would do this line of code, and\n\n517\n00:25:23,623 --> 00:25:26,757\nthen call super.manage.object context equals this.\n\n518\n00:25:26,759 --> 00:25:28,826\nOkay, and then we would go in our storyboard and\n\n519\n00:25:28,828 --> 00:25:31,562\nwe would set the identity inspector for this table view\n\n520\n00:25:31,564 --> 00:25:33,631\nto be root table, Tweet table view controller.\n\n521\n00:25:33,633 --> 00:25:35,866\nSo that's a little more than I wanna go through in the demo\n\n522\n00:25:35,868 --> 00:25:38,669\nhere, so we're just going to kinda go cheap mode here and\n\n523\n00:25:38,671 --> 00:25:43,007\njust make it default to be this managedObjectContext. All\n\n524\n00:25:43,009 --> 00:25:45,743\nright, so this is where we're gonna store our database when\n\n525\n00:25:45,745 --> 00:25:48,846\nwe, or our information when we do this update database.\n\n526\n00:25:48,848 --> 00:25:51,849\nOkay. Now remember, any time we access the database,\n\n527\n00:25:51,851 --> 00:25:54,685\nwe have to do it with that perform block because these\n\n528\n00:25:54,687 --> 00:25:57,254\ndatabase, these managedObjectContext, are only\n\n529\n00:25:57,256 --> 00:26:00,024\nthread safe within the thread they were created on.\n\n530\n00:26:00,026 --> 00:26:02,359\nAnd I'm gonna write all my code in this demo as\n\n531\n00:26:02,361 --> 00:26:05,462\nif I don't know what thread these managedObjectContexts\n\n532\n00:26:05,464 --> 00:26:09,233\nare created on. Even though we know that that AppDelegate one\n\n533\n00:26:09,235 --> 00:26:12,136\nis always a main queue one. But I'm not gonna write my\n\n534\n00:26:12,138 --> 00:26:15,105\ncode assuming that, just so you can see what it looks like\n\n535\n00:26:15,107 --> 00:26:18,809\nto write multi-threaded managedObject, code, okay? So,\n\n536\n00:26:18,811 --> 00:26:22,846\nthat means we always have to have our managedObjectContext\n\n537\n00:26:22,848 --> 00:26:27,017\nand do performBlock, okay? Now if this is nil,\n\n538\n00:26:27,019 --> 00:26:31,021\nwhat happens here? Nothing, good, that's what I want.\n\n539\n00:26:31,023 --> 00:26:33,924\nOkay, I, I've, if I don't have a managedObjectContext,\n\n540\n00:26:33,926 --> 00:26:34,992\nI don't wanna update the database.\n\n541\n00:26:34,994 --> 00:26:36,894\nSo this is perfect so far, all right?\n\n542\n00:26:36,896 --> 00:26:39,697\nSo we're gonna perform a block here. Inside this block,\n\n543\n00:26:39,699 --> 00:26:42,499\nall we gotta do is put these newTweets, okay,\n\n544\n00:26:42,501 --> 00:26:45,869\ninto the database. So, that's pretty straightforward.\n\n545\n00:26:45,871 --> 00:26:46,570\nI'm just gonna have a little for\n\n546\n00:26:46,572 --> 00:26:49,807\nloop that goes through those tweets. Let's say for\n\n547\n00:26:49,809 --> 00:26:55,446\ntwitterInfo in the newTweets. And then here,\n\n548\n00:26:55,448 --> 00:27:00,818\nI have to, you know, create a new but unique Tweet,\n\n549\n00:27:00,820 --> 00:27:06,023\nin the N-S managed objects sense. With that, you know,\n\n550\n00:27:06,025 --> 00:27:10,060\nTwitter info. Okay, so that's what I need to do in here. So\n\n551\n00:27:10,062 --> 00:27:13,297\nI need a method to do that. Now that method doesn't really\n\n552\n00:27:13,299 --> 00:27:16,367\nwant to go in this Tweet table view controller,\n\n553\n00:27:16,369 --> 00:27:19,903\nokay. That's really something that wants to go in the Tweet\n\n554\n00:27:19,905 --> 00:27:25,242\nclass. Okay. A tweet class is one stop shop for\n\n555\n00:27:25,244 --> 00:27:27,611\neverything tweet when it comes to the database. So\n\n556\n00:27:27,613 --> 00:27:30,614\nif you had a method that takes Twitter info from the network\n\n557\n00:27:30,616 --> 00:27:32,082\nand turns it into a tweet in the database,\n\n558\n00:27:32,084 --> 00:27:35,753\nthat needs to believe, live in the one stop shop. Okay.\n\n559\n00:27:35,755 --> 00:27:40,090\nSo we're gonna actually put that code some method that\n\n560\n00:27:40,092 --> 00:27:41,258\ndoes this in tweet.\n\n561\n00:27:41,260 --> 00:27:43,927\nOkay, remember Tweet is this subclass of NSObject, so\n\n562\n00:27:43,929 --> 00:27:46,664\nwe're gonna do exactly what that comment just said and\n\n563\n00:27:46,666 --> 00:27:50,234\ninsert the code we want in here. Now this code,\n\n564\n00:27:50,236 --> 00:27:53,470\nwhat is this method gonna do? Well, this method is going to\n\n565\n00:27:53,472 --> 00:27:56,774\nlook in the database and if there's already a tweet there\n\n566\n00:27:56,776 --> 00:28:00,978\nwith that unique ID, then it's just gonna just return that.\n\n567\n00:28:00,980 --> 00:28:03,514\nIf not, it's gonna create one and load it up with\n\n568\n00:28:03,516 --> 00:28:06,316\nthe Twitter information, okay that it got from from,\n\n569\n00:28:06,318 --> 00:28:10,120\nfrom over the network and then, it's gonna return that.\n\n570\n00:28:10,122 --> 00:28:12,356\nSo, it either looks it up and returns it or\n\n571\n00:28:12,358 --> 00:28:15,859\ncreate it if necessary. Okay. I'm gonna call this thing,\n\n572\n00:28:15,861 --> 00:28:18,095\nfirst of all, it's gonna be a class function,\n\n573\n00:28:18,097 --> 00:28:20,698\nmeaning I'm gonna send this to the tweet class\n\n574\n00:28:20,700 --> 00:28:22,199\nbecause I'm creating an instance here,\n\n575\n00:28:22,201 --> 00:28:23,701\nI can't really send it to an instance yet,\n\n576\n00:28:23,703 --> 00:28:26,470\nI haven't created one. I'm gonna call this thing\n\n577\n00:28:26,472 --> 00:28:31,942\ntweetWithTwitterInfo and it's gonna take some Twitter info\n\n578\n00:28:31,944 --> 00:28:37,047\nwhich is gonna be a Twitter.Tweet, okay? So I have\n\n579\n00:28:37,049 --> 00:28:41,051\nto import Twitter here. So then making a Twitter.Tweet.\n\n580\n00:28:41,053 --> 00:28:44,455\nAnd the other thing I gotta have if I'm gonna create\n\n581\n00:28:44,457 --> 00:28:48,125\nsomething in the database is inManagedObjectContext.\n\n582\n00:28:48,127 --> 00:28:51,762\nOkay, I have to have the NS ManagedObjectContext that you\n\n583\n00:28:51,764 --> 00:28:53,997\nwant to create this thing in, or, or\n\n584\n00:28:53,999 --> 00:28:56,200\nit just can't create it, okay.\n\n585\n00:28:56,202 --> 00:29:00,104\nAnd this thing is gonna return a tweet. Okay, it's either\n\n586\n00:29:00,106 --> 00:29:02,973\ngonna return the tweet that it found in the database by\n\n587\n00:29:02,975 --> 00:29:05,576\nlooking at the unique ID of this Twitter.Tweet, or\n\n588\n00:29:05,578 --> 00:29:08,378\nit's gonna create one in the database and return that.\n\n589\n00:29:08,380 --> 00:29:13,150\nOkay, so let's have it return nil. Actually, let's just make\n\n590\n00:29:13,152 --> 00:29:15,419\nit so it returns an optional tweet in case for\n\n591\n00:29:15,421 --> 00:29:16,987\nsome reason we can't create one.\n\n592\n00:29:16,989 --> 00:29:21,058\nWe'll have it return nil by default. Okay, we'll get back\n\n593\n00:29:21,060 --> 00:29:23,761\nto how we're going to implement this in a second. I,\n\n594\n00:29:23,763 --> 00:29:26,430\nI want to go back to the code that calls this,\n\n595\n00:29:26,432 --> 00:29:29,633\nwhich is here. Okay, this update database. And use it\n\n596\n00:29:29,635 --> 00:29:32,903\nhere. And so you just call, you know how you call class\n\n597\n00:29:32,905 --> 00:29:36,440\nfunctions, you just have the name of the class, tweet, and\n\n598\n00:29:36,442 --> 00:29:42,446\nthen this is tweet, what's it called? TweetWithTwitterInfo,\n\n599\n00:29:42,448 --> 00:29:45,649\nand we're gonna pass the Twitter info along.\n\n600\n00:29:45,651 --> 00:29:49,119\nOkay, this is the Twitter info that we're pulling out of this\n\n601\n00:29:49,121 --> 00:29:53,257\narray of Twitter.Tweets, right? In a for loop here.\n\n602\n00:29:53,259 --> 00:29:58,028\nAnd ininManagedObjectContext, we're gonna pass our own\n\n603\n00:29:58,030 --> 00:30:02,332\nmanaged object context. And we can go ahead and unwrap it,\n\n604\n00:30:02,334 --> 00:30:04,868\nbecause we know we wouldn't, have made it into this block\n\n605\n00:30:04,870 --> 00:30:08,872\nif this were not nil. All right? And notice that it's\n\n606\n00:30:08,874 --> 00:30:12,409\ncomplaining here about you gotta put self in, sorry,\n\n607\n00:30:12,411 --> 00:30:16,180\nyou've gotta put self in front of this because this right\n\n608\n00:30:16,182 --> 00:30:20,651\nhere is a block, okay? So we gotta make sure we avoid any\n\n609\n00:30:20,653 --> 00:30:25,289\nloops, you know, any any memory cycles and\n\n610\n00:30:25,291 --> 00:30:29,326\nwhat else is it complaining about here? Cannot,\n\n611\n00:30:29,328 --> 00:30:36,033\nI must have typed that wrong. Let's go back here. All right,\n\n612\n00:30:36,035 --> 00:30:41,505\ngo back here to tweet. I must have, yes,\n\n613\n00:30:41,507 --> 00:30:46,109\nI forgot to put context okay in this iManagedObjectContext\n\n614\n00:30:46,111 --> 00:30:49,847\nthere. All right, back. All right, so we got this,\n\n615\n00:30:49,849 --> 00:30:52,649\nso this, now one thing that's interesting about this\n\n616\n00:30:52,651 --> 00:30:55,552\ntweetWithTwitterInfo, it returns a value, right,\n\n617\n00:30:55,554 --> 00:30:57,888\nit returns a tweet. Now I don't care.\n\n618\n00:30:57,890 --> 00:31:00,724\nI don't want the tweet here, I'm just creating it, I'm just\n\n619\n00:31:00,726 --> 00:31:03,460\nthe guy loading the database, so I don't want that tweet. So\n\n620\n00:31:03,462 --> 00:31:06,029\nnotice that swift doesn't complain, even though I'm\n\n621\n00:31:06,031 --> 00:31:10,634\nignoring it. But some would say it's pretty good code to\n\n622\n00:31:10,636 --> 00:31:15,105\nsay_ = here, okay. That tells someone reading this code,\n\n623\n00:31:15,107 --> 00:31:18,275\nyeah, I understand that this returns to a value but\n\n624\n00:31:18,277 --> 00:31:19,276\nI'm not interested in it.\n\n625\n00:31:19,278 --> 00:31:22,246\nRemember the underbar in Swift is the universal,\n\n626\n00:31:22,248 --> 00:31:25,749\nI don't care about this thing, okay. So, looks a little odd\n\n627\n00:31:25,751 --> 00:31:28,318\nto do this but, some would say this is a little bit better\n\n628\n00:31:28,320 --> 00:31:31,121\ncoding style, it's just looks, it makes it a little clearer\n\n629\n00:31:31,123 --> 00:31:35,125\nto people reading your code that this is what you intend.\n\n630\n00:31:35,294 --> 00:31:39,229\nOkay? Now this will, once we implement this,\n\n631\n00:31:39,231 --> 00:31:42,232\nthis'll load up the database with these tweets, but it's\n\n632\n00:31:42,234 --> 00:31:46,203\nnot gonna save that database. Okay, now if we're using a UI\n\n633\n00:31:46,205 --> 00:31:49,706\nmanaged document, okay, then it would all be autosaving,\n\n634\n00:31:49,708 --> 00:31:51,942\nfine. But here we use an app delegate one and\n\n635\n00:31:51,944 --> 00:31:55,012\neven if we're not sure which one we're using, it can't hurt\n\n636\n00:31:55,014 --> 00:31:58,548\nto save, okay, the context in the UI managed document case.\n\n637\n00:31:58,550 --> 00:32:00,817\nSo how do we save? Well, it's simple.\n\n638\n00:32:00,819 --> 00:32:03,854\nWe just say inManagedObjectContext, save.\n\n639\n00:32:03,856 --> 00:32:07,090\nOkay? But of course, we're gonna have an error here,\n\n640\n00:32:07,092 --> 00:32:09,526\nbecause it's gonna say hold on a second, well,\n\n641\n00:32:09,528 --> 00:32:12,629\nfirst it's saying we're inside a block so we have to do self,\n\n642\n00:32:12,631 --> 00:32:16,366\nso we'll do that. And we still have another error, which it\n\n643\n00:32:16,368 --> 00:32:21,204\nsays this call can throw, but it's not marked with try. So\n\n644\n00:32:21,206 --> 00:32:23,941\nit's to say hey, pay attention, this can throw.\n\n645\n00:32:23,943 --> 00:32:26,643\nSo we need to put try in front And of course if we're going\n\n646\n00:32:26,645 --> 00:32:30,080\nto try something we need to put it inside of a do loop.\n\n647\n00:32:30,082 --> 00:32:33,750\nAnd catch any errors that come out. Okay, and\n\n648\n00:32:33,752 --> 00:32:35,652\nwe'll put it in a local variable we'll call error.\n\n649\n00:32:35,654 --> 00:32:38,088\nThis is going to be an N-S error instance,\n\n650\n00:32:38,090 --> 00:32:40,724\nokay. We could look at the error code etcetera.\n\n651\n00:32:40,726 --> 00:32:42,192\nI'm just going to go ahead and print it out.\n\n652\n00:32:42,194 --> 00:32:46,463\nI'm going to say core data error. Error,\n\n653\n00:32:46,465 --> 00:32:47,664\nsomething like that. This is bad,\n\n654\n00:32:47,666 --> 00:32:49,333\nyou wouldn't want to do this in your real code, okay.\n\n655\n00:32:49,335 --> 00:32:53,003\nThis is just demo ware here, you would want to decide what\n\n656\n00:32:53,005 --> 00:32:55,472\nyou wanted to do if you tried to save and it failed for\n\n657\n00:32:55,474 --> 00:33:01,378\nsome reason. Okay? So, anyway, so this is gonna save it.\n\n658\n00:33:01,380 --> 00:33:03,547\nSo this will work again, even if you were in an autosave and\n\n659\n00:33:03,549 --> 00:33:07,184\nyou iManage document, it's gonna work just fine. Okay?\n\n660\n00:33:07,186 --> 00:33:11,888\nAll right, let's jump back to where we were over here.\n\n661\n00:33:11,890 --> 00:33:17,361\nTweet. And implement this thing, TweetWithTwitterInfo.\n\n662\n00:33:17,363 --> 00:33:20,030\nSo I said that what TweetWithTwitterInfo's gonna\n\n663\n00:33:20,032 --> 00:33:22,165\ndo is first it's gonna look in the database and\n\n664\n00:33:22,167 --> 00:33:25,402\nsee if it can find this Twitter.Tweet. Okay.\n\n665\n00:33:25,404 --> 00:33:28,005\nIn the database already and if so it's gonna return it. So,\n\n666\n00:33:28,007 --> 00:33:31,575\nhow do we look in the database and find something? Well,\n\n667\n00:33:31,577 --> 00:33:34,845\nwe use this NSFetchRequest thing. Okay?\n\n668\n00:33:34,847 --> 00:33:37,881\nSo, we're gonna make a Fetch Request, okay? It always wants\n\n669\n00:33:37,883 --> 00:33:42,119\nto know the entity name. So, here we're looking for Tweet\n\n670\n00:33:42,121 --> 00:33:45,222\nin the database. Okay. So we've got this fetch request.\n\n671\n00:33:45,224 --> 00:33:47,090\nI am going to sign that to a local variable here.\n\n672\n00:33:47,092 --> 00:33:51,461\nLet request equal. And this request needs a predicate\n\n673\n00:33:51,463 --> 00:33:55,032\nthat says which tweet do you want. So I am gonna say okay,\n\n674\n00:33:55,034 --> 00:33:59,536\nmy predicate is NSPredicate with a format.\n\n675\n00:33:59,538 --> 00:34:03,740\nAnd I am gonna say that the unique ID of this tweet\n\n676\n00:34:03,742 --> 00:34:06,676\nequals something And what is that something?\n\n677\n00:34:06,678 --> 00:34:11,314\nWell, it's the whatever the unique ID is in twitter.tweet.\n\n678\n00:34:11,316 --> 00:34:13,450\nK? Which happens to be called ID. So\n\n679\n00:34:13,452 --> 00:34:18,155\nI'm going to get my twitter info.id. K? So that, this\n\n680\n00:34:18,157 --> 00:34:22,459\nis just a property and you might have used it with your\n\n681\n00:34:22,461 --> 00:34:25,562\nhomework number four but it's just a property that uniquely\n\n682\n00:34:25,564 --> 00:34:28,131\nidentifies this tweet. Okay, so i'm gonna go look in\n\n683\n00:34:28,133 --> 00:34:32,469\nthe database and see if i can find that, and the way we look\n\n684\n00:34:32,471 --> 00:34:37,741\nin the database is we say, let query results.\n\n685\n00:34:37,743 --> 00:34:38,942\nJust a local variable,\n\n686\n00:34:38,944 --> 00:34:42,679\nequal the context that we are supposed to look in here,\n\n687\n00:34:42,681 --> 00:34:48,185\nthat's this context up here dot execute fetch request.\n\n688\n00:34:48,187 --> 00:34:50,754\nAnd then, you give it that request, okay?\n\n689\n00:34:50,756 --> 00:34:52,089\nSo that's how we look in the database,\n\n690\n00:34:52,091 --> 00:34:54,791\nbut there's some problems with this. As you can see,\n\n691\n00:34:54,793 --> 00:34:59,830\nlittle errors over here. One is that this thing throws,\n\n692\n00:34:59,832 --> 00:35:03,300\nokay? Execute fetch request throws. So I need to say, try,\n\n693\n00:35:03,302 --> 00:35:06,870\nokay? So that's problem number one of this. And\n\n694\n00:35:06,872 --> 00:35:09,172\nif I'm going to try, then of course, I need to.\n\n695\n00:35:09,174 --> 00:35:14,344\nDo a little do loop here and catch any errors.\n\n696\n00:35:14,346 --> 00:35:17,948\nNow, if I'm actually getting this fetch request to look for\n\n697\n00:35:17,950 --> 00:35:21,785\nthis tweet and it's not there, what am I gonna Gonna do?\n\n698\n00:35:21,787 --> 00:35:23,320\nThere really nothing I can do.\n\n699\n00:35:23,322 --> 00:35:25,355\nI just continue and try to create it.\n\n700\n00:35:25,357 --> 00:35:27,891\nI'm gonna assume it's not there. Right if I search for\n\n701\n00:35:27,893 --> 00:35:29,993\nit and I don't find it, I'm gonna assume it's not there.\n\n702\n00:35:29,995 --> 00:35:33,063\nSo basically when I catch an error I'm just gonna ignore\n\n703\n00:35:33,065 --> 00:35:37,901\nthe error and move on down here to keep trying to\n\n704\n00:35:37,903 --> 00:35:42,739\ncreate it. But if I am able to find it right here, okay,\n\n705\n00:35:42,741 --> 00:35:45,175\nif I do get a result there from,\n\n706\n00:35:45,177 --> 00:35:48,879\nfrom doing this fetch. Then I'm going to say if I can let\n\n707\n00:35:48,881 --> 00:35:52,682\nthe tweet that's in there equal the query results,\n\n708\n00:35:52,684 --> 00:35:55,585\nnow remember the query results are an array of tweets.\n\n709\n00:35:55,587 --> 00:35:58,855\nAll the tweets that match my predicate My predicate is\n\n710\n00:35:58,857 --> 00:36:02,359\nunique, so there should only be one in there. Either one or\n\n711\n00:36:02,361 --> 00:36:04,628\nzero, okay? There's one in there if it found it.\n\n712\n00:36:04,630 --> 00:36:08,465\nThere's zero of them in there if it didn't find it, right?\n\n713\n00:36:08,467 --> 00:36:14,704\nSo, I'm gonna go use this method in array called first.\n\n714\n00:36:14,706 --> 00:36:18,341\nOkay, that returned to the first item in the array,\n\n715\n00:36:18,343 --> 00:36:19,676\nor nil, if the array is empty.\n\n716\n00:36:19,678 --> 00:36:22,345\nSo it never does array index out of bounds, so it's kind of\n\n717\n00:36:22,347 --> 00:36:25,649\na cool, there's also last, but first is kind of a cool one.\n\n718\n00:36:25,651 --> 00:36:27,250\nAnd when I pull it out of there, of course,\n\n719\n00:36:27,252 --> 00:36:29,519\nit needs to be a tweet. Okay, so\n\n720\n00:36:29,521 --> 00:36:33,456\nif I can pull the first thing out of this result array and\n\n721\n00:36:33,458 --> 00:36:37,394\nit's a tweet, I'm good to go. I can just return that tweet.\n\n722\n00:36:37,396 --> 00:36:40,030\nOkay? Otherwise, I couldn't find the thing in there.\n\n723\n00:36:40,032 --> 00:36:42,232\nI got to go create it in the data base.\n\n724\n00:36:42,234 --> 00:36:44,935\nEverybody cool with this code? Now this is unfortunate\n\n725\n00:36:44,937 --> 00:36:47,671\na lot of code, okay? Seven lines of code here.\n\n726\n00:36:47,673 --> 00:36:50,707\nThis can all be done in one line. LIne of code, okay?\n\n727\n00:36:50,709 --> 00:36:53,343\nSo let's look at that. How can we do that? And in this is,\n\n728\n00:36:53,345 --> 00:36:55,645\nrequires you to start getting more and more familiar\n\n729\n00:36:55,647 --> 00:36:58,181\nwith optional chaining, okay. >> Cuz we got a lot of things\n\n730\n00:36:58,183 --> 00:37:00,217\nthat can go wrong here, okay? Things can be nil,\n\n731\n00:37:00,219 --> 00:37:03,420\nall kinds of things happening right here. So believe it or\n\n732\n00:37:03,422 --> 00:37:05,889\nnot we can do this just by doing this.\n\n733\n00:37:05,891 --> 00:37:10,760\nIf let tweet = we're gonna try,\n\n734\n00:37:10,762 --> 00:37:14,531\nand if we fail, return nill. Try? means try it, and if it\n\n735\n00:37:14,533 --> 00:37:18,969\nfails return nill. To ask our context to execute this fetch\n\n736\n00:37:18,971 --> 00:37:23,440\nrequest. Okay, this same fetch request we just did, okay.\n\n737\n00:37:23,442 --> 00:37:27,811\nIf that is successful, then go on to get the first thing in\n\n738\n00:37:27,813 --> 00:37:34,517\nthe array. And see if you can cast it to a tweet, okay.\n\n739\n00:37:35,721 --> 00:37:40,090\nThat is identical to this, okay. And\n\n740\n00:37:40,092 --> 00:37:43,326\nit reads a little more simply a little more like English,\n\n741\n00:37:43,328 --> 00:37:47,464\nokay. Try to use the context to execute this Fetch request.\n\n742\n00:37:47,466 --> 00:37:49,399\nGet the first thing, a-and if you can get this\n\n743\n00:37:49,401 --> 00:37:53,670\nfirst thing as a tweet, Then return it. Okay? So\n\n744\n00:37:53,672 --> 00:37:57,007\nit's actually better code, I believe more readable than\n\n745\n00:37:57,009 --> 00:37:57,574\nthe other. Yeah? >> So\n\n746\n00:37:57,576 --> 00:38:01,478\nwhere would we link the catch? >> Yeah, so\n\n747\n00:38:01,480 --> 00:38:03,880\nwe can't do this if we're gonna catch.\n\n748\n00:38:03,882 --> 00:38:06,650\nIf we're gonna catch and do something we ignore so,\n\n749\n00:38:06,652 --> 00:38:08,318\nwe didn't do that, but if we're gonna catch and\n\n750\n00:38:08,320 --> 00:38:11,755\ndo something then we would have to use this more verbose\n\n751\n00:38:12,190 --> 00:38:13,957\nGood question there.\n\n752\n00:38:13,959 --> 00:38:18,828\nAlright, so we got that, okay. So, what if we can't? Okay?\n\n753\n00:38:18,830 --> 00:38:22,265\nWhat if we could not find the tweet in the database?\n\n754\n00:38:22,267 --> 00:38:24,567\nNow we need to create the tweet, okay?\n\n755\n00:38:24,569 --> 00:38:27,270\nSo here I'm gonna say, okay I couldnt it so\n\n756\n00:38:27,272 --> 00:38:30,740\nI couldn't look it up. So if I can create it which is,\n\n757\n00:38:30,742 --> 00:38:34,144\nif you'll remember from the slide, NS entity\n\n758\n00:38:34,146 --> 00:38:40,350\ndescription.insert, insert new object for\n\n759\n00:38:40,352 --> 00:38:43,286\nentity for name, okay? We're creating a tweet.\n\n760\n00:38:43,288 --> 00:38:47,590\nThe manage object context is context, okay, and\n\n761\n00:38:47,592 --> 00:38:53,697\nwe obviously want it to be a tweet. Okay?\n\n762\n00:38:53,932 --> 00:38:55,832\nSo here we've created the tweet.\n\n763\n00:38:55,834 --> 00:38:59,302\nIf we£re able to, okay if let, so we£re gonna see if we can\n\n764\n00:38:59,304 --> 00:39:02,372\ncreate it by inserting something in the database.\n\n765\n00:39:02,374 --> 00:39:06,242\nEverybody cool with that line of code.\n\n766\n00:39:06,244 --> 00:39:09,746\nAll right, now we've created a tweet, but it£s empty, okay.\n\n767\n00:39:09,748 --> 00:39:10,914\nIt£s all everything£s nill in there,\n\n768\n00:39:10,916 --> 00:39:13,416\nso we need to start setting some of the values like really\n\n769\n00:39:13,418 --> 00:39:16,019\nimportantly we better set that unique equal to the Twitter\n\n770\n00:39:16,021 --> 00:39:19,956\ninfo£s ID. Okay, make sure it's unique, we also wanna set\n\n771\n00:39:19,958 --> 00:39:26,196\nthe tweets text equal to the Twitter info's text. I think\n\n772\n00:39:26,198 --> 00:39:29,499\nwe also had the tweet posted which would be the Twitter\n\n773\n00:39:29,501 --> 00:39:33,870\ninfo's created, okay? So we just wanna go through here and\n\n774\n00:39:33,872 --> 00:39:36,506\ngrab the information that we got from it network, and\n\n775\n00:39:36,508 --> 00:39:38,675\nput it in the database that's basically what we're doing\n\n776\n00:39:38,677 --> 00:39:41,311\nhere. Okay? Now, what about this one,\n\n777\n00:39:41,313 --> 00:39:47,917\ntweet.tweeter =? Ooh, what do we, how do we do that?\n\n778\n00:39:47,919 --> 00:39:50,820\nGotta set up that relationship between [LAUGH] tweeter and\n\n779\n00:39:50,822 --> 00:39:52,789\ntweets, okay? Well, to do that,\n\n780\n00:39:52,791 --> 00:39:56,092\nwe have to create the Twitter user. That goes for this,\n\n781\n00:39:56,094 --> 00:39:59,796\nokay, and by that I mean this Twitter user right here.\n\n782\n00:39:59,798 --> 00:40:04,000\nThis managed object Twitter user. Okay. And to create\n\n783\n00:40:04,002 --> 00:40:07,103\na twitter user, I'm going to use the exact same kind of\n\n784\n00:40:07,105 --> 00:40:10,440\ncode that I just was in the middle of typing and tweet.\n\n785\n00:40:10,442 --> 00:40:12,942\nI'm going to type it in really fast because\n\n786\n00:40:12,944 --> 00:40:17,447\nit's exactly the same, okay. So I'll go through it here but\n\n787\n00:40:17,449 --> 00:40:17,781\nit's exactly the same.\n\n788\n00:40:17,783 --> 00:40:20,984\nSo I need to import twitter, just like I did in that one.\n\n789\n00:40:20,986 --> 00:40:24,354\nSo here we're in twitter user. Okay? And this one's called\n\n790\n00:40:24,356 --> 00:40:27,157\nTwitter user with Twitter info. This time the Twitter\n\n791\n00:40:27,159 --> 00:40:30,760\ninfo is not a Twitter, tweet, it's a Twitter.user. Okay,\n\n792\n00:40:30,762 --> 00:40:32,829\nand we still have to pass the the manage object context.\n\n793\n00:40:32,831 --> 00:40:36,833\nAnd it returns a Twitter user if it can find one or create.\n\n794\n00:40:36,835 --> 00:40:40,537\nOkay, now for Twitter user the unique is the screen name.\n\n795\n00:40:40,539 --> 00:40:43,239\nEvery Twitter user has their own unique screen name, so\n\n796\n00:40:43,241 --> 00:40:43,673\nwe don't have a unique\n\n797\n00:40:43,675 --> 00:40:46,009\nwe just use the screen name as the unique thing. Here,\n\n798\n00:40:46,011 --> 00:40:48,678\nwe're doing that try to see if we can find it, if we can, we\n\n799\n00:40:48,680 --> 00:40:52,882\nreturn it. If we can't, we're inserting a new one, okay, and\n\n800\n00:40:52,884 --> 00:40:56,686\nsetting the screen name and the name, and returning it.\n\n801\n00:40:56,688 --> 00:41:01,157\nOkay? Now, notice that I'm not setting the tweet's NS set.\n\n802\n00:41:01,159 --> 00:41:05,161\nI'm not adding anything to the tweet NS set here. Okay,\n\n803\n00:41:05,163 --> 00:41:05,261\nat this point I don't know any tweets that are in a set.\n\n804\n00:41:05,263 --> 00:41:08,598\nthat's because I,\n\n805\n00:41:08,600 --> 00:41:10,233\nSo I'm just creating a twitter user that so\n\n806\n00:41:10,235 --> 00:41:16,005\nfar, has no tweets in the database, okay, when I create.\n\n807\n00:41:16,608 --> 00:41:19,275\nAlright? Now let's go back here to where we're creating\n\n808\n00:41:19,277 --> 00:41:22,946\nthe tweet, and now to set this tweet.tweeter all we need to\n\n809\n00:41:22,948 --> 00:41:29,152\ndo is say twitter user Twitter user with Twitter info.\n\n810\n00:41:29,154 --> 00:41:35,925\nAnd now we pass the user, which is the Twitterinfo.user\n\n811\n00:41:35,927 --> 00:41:40,163\nin inManagedObjectContext.\n\n812\n00:41:40,165 --> 00:41:45,835\nThe context, okay? This creates that Twitter user.\n\n813\n00:41:45,837 --> 00:41:50,173\nOkay, and sets it to this bar which is that relationship.\n\n814\n00:41:50,175 --> 00:41:53,576\nThe NS Set in the Twitter user, will have this tweet\n\n815\n00:41:53,578 --> 00:41:56,246\nauto, tweet automatically added to it, okay.\n\n816\n00:41:56,248 --> 00:41:58,481\nYou don't have to do both sides, if you do one side,\n\n817\n00:41:58,483 --> 00:42:01,184\nit does the other, if I'd put a tweet in the Twitter user\n\n818\n00:42:01,186 --> 00:42:05,588\nNS Set, the Twitter would have been set to it. Okay? If you\n\n819\n00:42:05,590 --> 00:42:08,791\ndo, if you touch one side, the other side gets kept in sync,\n\n820\n00:42:08,793 --> 00:42:10,493\nthat's the awesome thing about Core Data. So\n\n821\n00:42:10,495 --> 00:42:12,428\nyou never have to worry about database integrity,\n\n822\n00:42:12,430 --> 00:42:15,465\nit manages the integrity all the time for you, okay?\n\n823\n00:42:15,467 --> 00:42:19,569\nVery important to understand. All right, so we got it.\n\n824\n00:42:19,571 --> 00:42:21,437\nSo as long as we were able to do,\n\n825\n00:42:21,439 --> 00:42:25,208\neither look it up or create it, we can return it okay?\n\n826\n00:42:25,210 --> 00:42:29,212\nWhoops. Return the tweet, otherwise if we couldn£t do\n\n827\n00:42:29,214 --> 00:42:32,282\neither of those things then we£ll just return nill.\n\n828\n00:42:32,984 --> 00:42:36,185\nOkay very unlikely cuz this almost never fails. Inserting\n\n829\n00:42:36,187 --> 00:42:42,091\na new object, it£s gonna work for G1 100% of the time. Okay?\n\n830\n00:42:42,093 --> 00:42:47,664\nGot that? All right. So back to where we were calling this.\n\n831\n00:42:48,099 --> 00:42:49,299\nRight here. Everybody cool with this?\n\n832\n00:42:49,301 --> 00:42:53,937\nYou can see how this is going to put this array of tweets,\n\n833\n00:42:53,939 --> 00:43:00,043\nokay, into the database. All right.\n\n834\n00:43:00,045 --> 00:43:07,016\nNow, let's go ahead and before we do our new mvc\n\n835\n00:43:07,018 --> 00:43:08,851\nlet's just make sure this is working okay?\n\n836\n00:43:08,853 --> 00:43:12,088\nI'm gonna write a little function here that prints out\n\n837\n00:43:12,090 --> 00:43:12,689\nwhat's in the database.\n\n838\n00:43:12,691 --> 00:43:14,624\nHow many Twitter users, how many tweets.\n\n839\n00:43:14,626 --> 00:43:17,493\nLet's just see if this working okay? So let's write,\n\n840\n00:43:17,495 --> 00:43:19,429\nlet's write that function, see what that would look like.\n\n841\n00:43:19,431 --> 00:43:22,098\nSo I'm gonna have a private funk. I'm gonna call\n\n842\n00:43:22,100 --> 00:43:26,402\nit PrintDatabaseStatistics cuz it's basically going just\n\n843\n00:43:26,404 --> 00:43:31,608\nprint how many, Twitter users are and how many, of the,\n\n844\n00:43:31,610 --> 00:43:36,179\nhow many tweets and how many Twitter users, so of course we\n\n845\n00:43:36,181 --> 00:43:42,619\nhave to perform this in a block Okay, cuz we always\n\n846\n00:43:42,621 --> 00:43:47,857\nhave to do that when we're doing manage object context\n\n847\n00:43:47,859 --> 00:43:50,927\nstuff and I'm going to watch this,\n\n848\n00:43:50,929 --> 00:43:55,865\nif let results equal try to execute on our context and\n\n849\n00:43:55,867 --> 00:44:00,403\nactually we can exclamation point that.\n\n850\n00:44:00,405 --> 00:44:01,671\nExecute fetch request. Now watch.\n\n851\n00:44:01,673 --> 00:44:04,207\nI'm going to create a fetch request on the fly here.\n\n852\n00:44:04,209 --> 00:44:07,710\nFetch request with an entity name and what am I looking for\n\n853\n00:44:07,712 --> 00:44:10,380\nhere? Okay, let's count the Twitter users first. So\n\n854\n00:44:10,382 --> 00:44:14,250\nTwitter user. Now, notice I have a fetch request here with\n\n855\n00:44:14,252 --> 00:44:17,186\nnow predicate. I just created an quest\n\n856\n00:44:17,188 --> 00:44:20,890\nwith no predicate set on it. That gets all twitter users.\n\n857\n00:44:20,892 --> 00:44:23,693\nIf you have a without a predicate, that means give me\n\n858\n00:44:23,695 --> 00:44:26,529\nall of them, all of whatever the entity is\n\n859\n00:44:26,531 --> 00:44:31,200\nthat you're looking for. Okay, so if I'm able to do that and\n\n860\n00:44:31,202 --> 00:44:34,337\nget the results, then I'm just going to print that we have\n\n861\n00:44:34,339 --> 00:44:40,376\nResult.count how ever many we go here.\n\n862\n00:44:40,378 --> 00:44:44,847\nTwitter users. Okay so, that£s this little code right\n\n863\n00:44:44,849 --> 00:44:47,450\nhere, we£ll print out how many Twitter users are in\n\n864\n00:44:47,452 --> 00:44:50,720\nthe database. Alright, now there£s actually a better\n\n865\n00:44:50,722 --> 00:44:53,589\nway to do this because this is a bit of a problem, when I\n\n866\n00:44:53,591 --> 00:44:56,259\nexecute that vet request it gives me every single\n\n867\n00:44:56,261 --> 00:44:58,094\nTwitter user out of the database and\n\n868\n00:44:58,096 --> 00:45:01,764\ninto my memory. Now, there just husks because remember I\n\n869\n00:45:01,766 --> 00:45:05,535\ntalked about the faulting thing. So, the attributes like\n\n870\n00:45:05,537 --> 00:45:08,504\nthe Twitter user screen name and name those aren't pulled\n\n871\n00:45:08,506 --> 00:45:11,941\nfrom the database. But, like a little husk is there and\n\n872\n00:45:11,943 --> 00:45:13,509\nif I had thousands thousands of Twitter users,\n\n873\n00:45:13,511 --> 00:45:16,112\nthat would be unnecessarily thousands of bytes\n\n874\n00:45:16,114 --> 00:45:18,715\nbeing pulled into my memory. Okay. So there's a better way\n\n875\n00:45:18,717 --> 00:45:22,318\nto do this. There's actually an execute equivalent, which\n\n876\n00:45:22,320 --> 00:45:24,921\nonly counts how many things there are, and it counts it on\n\n877\n00:45:24,923 --> 00:45:27,356\nthe database side without pulling everything over and\n\n878\n00:45:27,358 --> 00:45:31,794\ncounting it in an array. So for the tweets I'll use that\n\n879\n00:45:31,796 --> 00:45:36,999\nway of doing it and that looks like this. I'm gonna let tweet\n\n880\n00:45:37,001 --> 00:45:41,971\ncount equal our context-managed object,\n\n881\n00:45:41,973 --> 00:45:46,075\ncountForFetchRequest, it's called. Okay? Instead of\n\n882\n00:45:46,077 --> 00:45:48,511\nexecute fetch request it calls count for fetch request.\n\n883\n00:45:48,513 --> 00:45:51,814\nI'm still gonna create a fetch request on the fly here, and\n\n884\n00:45:51,816 --> 00:45:57,353\nthis time, I am, In this fetch request entity name.\n\n885\n00:45:57,355 --> 00:46:01,124\nThis time I'm searching for tweets, not Twitter users.\n\n886\n00:46:01,126 --> 00:46:02,792\nNotice there's this little error pointer right here.\n\n887\n00:46:02,794 --> 00:46:06,496\nYou see this error pointer? This is an interesting method.\n\n888\n00:46:06,498 --> 00:46:06,896\nI'm not sure why it does\n\n889\n00:46:06,898 --> 00:46:08,564\nit this way. But instead of throwing the error,\n\n890\n00:46:08,566 --> 00:46:10,633\nit actually returns it through a pointer.\n\n891\n00:46:10,635 --> 00:46:13,669\nAnd if you're not interested, you can just say, nil. Say,\n\n892\n00:46:13,671 --> 00:46:17,373\nI don't want any error information. Okay?\n\n893\n00:46:17,375 --> 00:46:20,710\nSo it's kind of an odd little method in that way.\n\n894\n00:46:20,712 --> 00:46:22,278\nThat's going to return the tweet count.\n\n895\n00:46:22,280 --> 00:46:26,983\nAnd now, I can just print. The tweetCount,\n\n896\n00:46:26,985 --> 00:46:32,221\nTweets. So this is better code right here than this, okay?\n\n897\n00:46:32,223 --> 00:46:33,456\nIt's gonna be much more efficient.\n\n898\n00:46:33,458 --> 00:46:36,492\nI'll leave them both in here so that when I post the demo,\n\n899\n00:46:36,494 --> 00:46:37,360\nyou can see the difference.\n\n900\n00:46:37,362 --> 00:46:41,664\nHere, I'll even put a comment in here. A more efficient way\n\n901\n00:46:41,666 --> 00:46:47,436\nto count objects. Okay, but they're both just counting.\n\n902\n00:46:47,438 --> 00:46:48,638\nThis is counting the number of Twitter users,\n\n903\n00:46:48,640 --> 00:46:51,808\nthis is counting the number of tweets. Okay, so\n\n904\n00:46:51,810 --> 00:46:55,578\nlet's call this print every time we update the database,\n\n905\n00:46:55,580 --> 00:46:55,745\nlet's go ahead and\n\n906\n00:46:55,747 --> 00:46:58,414\ncall this print database statistics thing, and I'm\n\n907\n00:46:58,416 --> 00:47:02,385\nactually gonna put a little print in here saying, done\n\n908\n00:47:02,387 --> 00:47:06,255\nprinting database statistics. Okay, I'm gonna put\n\n909\n00:47:06,257 --> 00:47:09,258\nthis in here because something interesting is going to happen\n\n910\n00:47:09,260 --> 00:47:14,130\nwith that print. Okay? All right,\n\n911\n00:47:14,132 --> 00:47:16,199\nlet's go ahead and run. Now we should be\n\n912\n00:47:16,201 --> 00:47:19,168\nloading up the database with Twitter users and tweets every\n\n913\n00:47:19,170 --> 00:47:21,204\ntime we search for something, hashtag Stanford.\n\n914\n00:47:21,206 --> 00:47:24,407\nWe're not showing any of it but hopefully we'll be loading\n\n915\n00:47:24,409 --> 00:47:30,346\nup the database. Okay, we have to,\n\n916\n00:47:30,348 --> 00:47:32,682\nwe'll set our prototypes here when we get to that.\n\n917\n00:47:32,684 --> 00:47:36,085\nSo, here's our segue. You can see our table here is empty.\n\n918\n00:47:36,087 --> 00:47:38,154\nWe haven't done anything to implement that MVC, so\n\n919\n00:47:38,156 --> 00:47:43,192\nit's just a blank MVC. But if we do #stanford,\n\n920\n00:47:43,194 --> 00:47:48,064\nokay, it searches and we'll see down here in our console\n\n921\n00:47:48,466 --> 00:47:51,100\nthat it had a hundred tweets, which is right,\n\n922\n00:47:51,102 --> 00:47:53,502\nbecause remember here in our code,\n\n923\n00:47:53,504 --> 00:47:55,771\nwe fetch a hundred tweets, okay?\n\n924\n00:47:55,773 --> 00:47:59,375\nSo, that's doing that properly and it's only 75 users,\n\n925\n00:47:59,377 --> 00:48:02,712\nwhy is that? Well, probably there are people in here who\n\n926\n00:48:02,714 --> 00:48:04,080\nare tweeting more than ones, okay?\n\n927\n00:48:04,082 --> 00:48:07,016\nNumerous fill like here, this guy, I am not the clone. Okay?\n\n928\n00:48:07,018 --> 00:48:10,152\nHe tweeted twice right there, so you only count it once.\n\n929\n00:48:10,154 --> 00:48:12,688\nSo that sounds right that there's something,\n\n930\n00:48:12,690 --> 00:48:15,725\n75 and 100. Now, here's a very important test\n\n931\n00:48:15,727 --> 00:48:16,559\nto make sure things are working.\n\n932\n00:48:16,561 --> 00:48:19,629\nI'm gonna look for hashtag Stanford again and\n\n933\n00:48:19,631 --> 00:48:25,201\nI better not get 200 tweets. There it is, only 100.\n\n934\n00:48:25,203 --> 00:48:27,803\nSo nobody even tweeted to Stanford,\n\n935\n00:48:27,805 --> 00:48:32,875\none of you maybe tweeted, make it work for us here. Okay,\n\n936\n00:48:32,877 --> 00:48:34,443\nlet me try something else.\n\n937\n00:48:34,445 --> 00:48:38,080\nHow about #SFGiants, believe they're playing right now.\n\n938\n00:48:38,082 --> 00:48:40,883\nOkay, now we have 200 tweets because we searched for\n\n939\n00:48:40,885 --> 00:48:44,654\nsomething different, okay. So we've got the 100 tweets from\n\n940\n00:48:44,656 --> 00:48:46,322\nStanford, and hundreds of tweets from Giants, so\n\n941\n00:48:46,324 --> 00:48:49,926\nI'm gonna do Giants again. Still nobody tweeting.\n\n942\n00:48:49,928 --> 00:48:51,260\nNobody's interested in the Giants or\n\n943\n00:48:51,262 --> 00:48:56,432\nin Stanford currently, I guess. There we go.\n\n944\n00:48:56,434 --> 00:48:59,402\nSomebody finally tweeted something new for the Giants.\n\n945\n00:48:59,404 --> 00:49:00,503\nOkay. So now, we have 201 tweets,\n\n946\n00:49:00,505 --> 00:49:04,573\nokay. Doesn't sound like things are going well for\n\n947\n00:49:04,575 --> 00:49:09,011\nthe Giants. Hope I didn't spoil it for anybody. Okay.\n\n948\n00:49:09,013 --> 00:49:11,247\nSo, we got our thing working right here.\n\n949\n00:49:11,249 --> 00:49:14,884\nLook at this though, dome printing database statistics,\n\n950\n00:49:14,886 --> 00:49:20,256\nthat's printing out before it prints, isn't that weird?\n\n951\n00:49:20,258 --> 00:49:23,659\nThis print is definitely after print database statistics, so\n\n952\n00:49:23,661 --> 00:49:28,130\nwhy is this printing out before? Anyone have an idea?\n\n953\n00:49:30,101 --> 00:49:34,103\nIt begins with an A. Asynchronous,\n\n954\n00:49:34,105 --> 00:49:37,940\nyeah. Okay, this stuff, these performed blocks both this\n\n955\n00:49:37,942 --> 00:49:40,476\nperformed block right here, and also this performed block\n\n956\n00:49:40,478 --> 00:49:44,013\nup here happen asynchronously. These blocks just get put onto\n\n957\n00:49:44,015 --> 00:49:46,015\ntheir queue, and in this case it's the main queue, but\n\n958\n00:49:46,017 --> 00:49:48,217\nthat doesn't matter, whatever the queue is and\n\n959\n00:49:48,219 --> 00:49:48,751\nthey get put on that.\n\n960\n00:49:48,753 --> 00:49:50,886\nSo, when I do printdatabase for statistics,\n\n961\n00:49:50,888 --> 00:49:54,123\nit does this line of code which returns immediately.\n\n962\n00:49:54,125 --> 00:49:56,993\nIt instantly returns, it puts that block on some queue and\n\n963\n00:49:56,995 --> 00:49:59,562\nreturns immediately. It doesn't wait to execute\n\n964\n00:49:59,564 --> 00:50:02,064\nthis code because this is not perform block and wait, it's\n\n965\n00:50:02,066 --> 00:50:05,634\njust perform block. So this goes, returns immediately, and\n\n966\n00:50:05,636 --> 00:50:08,304\nthen this prints out immediately. Then later, this\n\n967\n00:50:08,306 --> 00:50:11,440\nblock gets pulled off onto the queue, the main queue, and\n\n968\n00:50:11,442 --> 00:50:16,746\nrun does its thing which causes this output. Okay,\n\n969\n00:50:16,748 --> 00:50:17,813\nsee why I put this in here so\n\n970\n00:50:17,815 --> 00:50:20,850\nyou understand that? This is happening asynchronously\n\n971\n00:50:20,852 --> 00:50:23,452\nunless you say perform block and wait. It's asynchronous.\n\n972\n00:50:23,454 --> 00:50:30,359\nAll right, now we got the data in our database. Excellent,\n\n973\n00:50:30,361 --> 00:50:33,562\nnow we can go on back to our storyboard right here.\n\n974\n00:50:33,564 --> 00:50:39,135\nAnd we can implement this NBC, this new NBC of ours.\n\n975\n00:50:39,137 --> 00:50:41,704\nWe need to do some things to do that.\n\n976\n00:50:41,873 --> 00:50:45,007\nWe need to make sure that we have for example,\n\n977\n00:50:45,009 --> 00:50:48,844\nreuse identifier for this cell. So what is that cell?\n\n978\n00:50:48,846 --> 00:50:51,947\nIt's basically a Twitter user, so I'll call it Twitter user\n\n979\n00:50:51,949 --> 00:50:56,285\ncell. We want these probably to be subtitle,\n\n980\n00:50:56,287 --> 00:50:57,053\nokay, instead of custom cell.\n\n981\n00:50:57,055 --> 00:50:59,822\nWe don't need custom cells for any reason.\n\n982\n00:50:59,824 --> 00:51:03,492\nWhoops. We can make sure we have our identities for\n\n983\n00:51:03,494 --> 00:51:05,761\nthe whole table. We do. That's all looking good.\n\n984\n00:51:05,763 --> 00:51:09,098\nWe can make sure we have this set, okay? Which we do. Okay?\n\n985\n00:51:09,100 --> 00:51:12,201\nSo it's all good, all right? So we're all ready to.\n\n986\n00:51:12,203 --> 00:51:16,405\nBasically implement this guy's class his custom sub class.\n\n987\n00:51:16,407 --> 00:51:19,141\nSo let's go take a look at that, that's right here.\n\n988\n00:51:19,143 --> 00:51:22,445\nWhenever we implement a new mvc, a great thing to do\n\n989\n00:51:22,447 --> 00:51:25,014\nI think, it's the fourth time I've said it in this class.\n\n990\n00:51:25,016 --> 00:51:27,983\nCome up with this model first, try to understand what this\n\n991\n00:51:27,985 --> 00:51:31,554\nthing is actually doing by understanding its model. Now,\n\n992\n00:51:31,556 --> 00:51:35,324\nthis is a very simple NVC, it takes some mention,\n\n993\n00:51:35,326 --> 00:51:39,395\nlike hashtag stamper and it searches for all the users,\n\n994\n00:51:39,397 --> 00:51:44,166\nokay, who have tweeted that, okay, in, in our database.\n\n995\n00:51:44,168 --> 00:51:48,838\nSo a clear, very important part is that mention. Okay,\n\n996\n00:51:48,840 --> 00:51:50,639\nwhatever that mention is, hashtag Stanford,\n\n997\n00:51:50,641 --> 00:51:53,209\nthat clearly needs to be part of our model. Okay,\n\n998\n00:51:53,211 --> 00:51:54,944\nwithout that we can't do anything. But\n\n999\n00:51:54,946 --> 00:51:59,115\nanother really important part of the model is that database.\n\n1000\n00:51:59,117 --> 00:52:01,050\nOkay? Without that database I can't look\n\n1001\n00:52:01,052 --> 00:52:03,953\nthis mention up. Okay? So another one is\n\n1002\n00:52:03,955 --> 00:52:07,857\na managed object model just like our other one, actually,\n\n1003\n00:52:07,859 --> 00:52:09,525\nhad part of its model as well. Okay,\n\n1004\n00:52:09,527 --> 00:52:14,263\nthat's an NSManaged not models and NSManagedObjectContext,\n\n1005\n00:52:14,265 --> 00:52:19,235\nNSManagedObjectContext, okay? I'll have that be optional,\n\n1006\n00:52:19,237 --> 00:52:22,471\nbut to be frank, if that's nil I'm not gonna, I'm gonna have\n\n1007\n00:52:22,473 --> 00:52:27,810\nan empty table, okay? Because this time really demands that.\n\n1008\n00:52:27,812 --> 00:52:31,080\nIf either of these change I'm gonna do a did set here and\n\n1009\n00:52:31,082 --> 00:52:33,782\nupdate my ui, which basically means I'm gonna have to reload\n\n1010\n00:52:33,784 --> 00:52:40,089\nmy table, okay? So, I'll do for either of these, and\n\n1011\n00:52:40,091 --> 00:52:41,290\nthen of course I need a private,\n\n1012\n00:52:41,292 --> 00:52:46,529\nprivate funk update ui. Okay,\n\n1013\n00:52:46,531 --> 00:52:49,832\nand in here we're gonna have to use this information. Okay,\n\n1014\n00:52:49,834 --> 00:52:54,336\nit's complaining here because we have to import core data.\n\n1015\n00:52:54,338 --> 00:52:58,807\nOkay. Notice that this particular NBC does not import\n\n1016\n00:52:58,809 --> 00:53:04,346\nTwitter. Okay. Because it's purely using the database,\n\n1017\n00:53:04,815 --> 00:53:07,383\nthe other MVC uses Twitter and the database, this one\n\n1018\n00:53:07,385 --> 00:53:09,685\nonly uses the database, so it doesn't import Twitter,\n\n1019\n00:53:09,687 --> 00:53:12,555\njust core data. All right, so we'll get to\n\n1020\n00:53:12,557 --> 00:53:15,357\nupdate U-I. A second one thing I wanted to do before that is\n\n1021\n00:53:15,359 --> 00:53:18,561\ndo our prepare for Segway and set these two things,\n\n1022\n00:53:18,563 --> 00:53:21,030\nokay, so we have to be prepared for Segway\n\n1023\n00:53:21,032 --> 00:53:25,901\nback in this MVC over here. So let's go back to that NBC,\n\n1024\n00:53:25,903 --> 00:53:28,671\nwe'll put it, right here, prepare for segue this prepare\n\n1025\n00:53:28,673 --> 00:53:33,108\nfor segue, by now prepare for segue should be old\n\n1026\n00:53:33,110 --> 00:53:35,811\nhat for you guys. You've done so many segues, but we're just\n\n1027\n00:53:35,813 --> 00:53:39,415\ngoing to check to see if the segue's identifier is right.\n\n1028\n00:53:39,417 --> 00:53:42,351\nThat's going to be, what did I call that thing?\n\n1029\n00:53:42,353 --> 00:53:42,685\nI can't even remember now,\n\n1030\n00:53:42,687 --> 00:53:47,289\nlet's look in our story board. This was called, copy and\n\n1031\n00:53:47,291 --> 00:53:51,360\npaste. Tweeters mentioning search term, okay?\n\n1032\n00:53:51,362 --> 00:53:53,562\nSo, if it's the tweeters mentioning search term segue,\n\n1033\n00:53:53,564 --> 00:53:58,000\nthen I need to get the destination view controller as\n\n1034\n00:53:58,002 --> 00:54:03,105\na tweeter table u controller. So I'm gonna say if I can let,\n\n1035\n00:54:03,107 --> 00:54:07,176\nthe tweeters TVC we'll call it,\n\n1036\n00:54:07,178 --> 00:54:10,679\nequal the segue.destinationViewContro-\n\n1037\n00:54:10,681 --> 00:54:14,450\nller as a TweetersTableViewController.\n\n1038\n00:54:14,452 --> 00:54:15,384\nOkay, so I've got a hold of it.\n\n1039\n00:54:15,386 --> 00:54:19,521\nNow I can just set the public API the model of this, so\n\n1040\n00:54:19,523 --> 00:54:25,094\nit's got the mention which is just our search text, and\n\n1041\n00:54:25,096 --> 00:54:26,595\nactually don't even need to do that.\n\n1042\n00:54:26,597 --> 00:54:31,800\nThis is our search text and tweeters.tvc.managedobjectsco-\n\n1043\n00:54:31,802 --> 00:54:36,138\nntext is our managed objects context, okay, so\n\n1044\n00:54:36,140 --> 00:54:36,272\nwe just prepare.\n\n1045\n00:54:36,274 --> 00:54:41,543\nThat's all we're doing here is preparing. Now that's okay,\n\n1046\n00:54:41,545 --> 00:54:44,613\nnow back to here. Update U-I. So, how are we going to update\n\n1047\n00:54:44,615 --> 00:54:46,015\nthis U-I? We need to have this table,\n\n1048\n00:54:46,017 --> 00:54:49,885\nand we need to have it full of Twitter users who have Tweeted\n\n1049\n00:54:49,887 --> 00:54:53,289\na Tweet that has this mention hashtag Stanford in there or\n\n1050\n00:54:53,291 --> 00:54:56,358\nwhatever, okay. How are we going to do that? Well,\n\n1051\n00:54:56,360 --> 00:54:59,061\nwe're gonna use an NS fetched results controller,\n\n1052\n00:54:59,063 --> 00:55:01,730\nthat really cool object I told you about the end of the last\n\n1053\n00:55:01,732 --> 00:55:05,267\nlecture. And that is an object that basically just glues\n\n1054\n00:55:05,269 --> 00:55:07,636\nan NS fetch request to a table view,\n\n1055\n00:55:07,638 --> 00:55:09,138\nand that's exactly what we want here.\n\n1056\n00:55:09,140 --> 00:55:10,306\nWe're gonna create an NS fetch request,\n\n1057\n00:55:10,308 --> 00:55:12,875\nwhich fetches the twitterings, we want, then we're\n\n1058\n00:55:12,877 --> 00:55:16,412\ngonna glue it on this table, okay? And in that way, anytime\n\n1059\n00:55:16,414 --> 00:55:19,515\nthe database changes in a way that those users would change,\n\n1060\n00:55:19,517 --> 00:55:21,450\nit's gonna automatically update the table, and\n\n1061\n00:55:21,452 --> 00:55:23,819\nwe don't have to do anything else, okay?\n\n1062\n00:55:23,821 --> 00:55:27,656\nNow, let's remind ourselves how NS Fetch Request,\n\n1063\n00:55:27,658 --> 00:55:32,695\nNS Fetch Request, NS Fetch Request Controller How\n\n1064\n00:55:32,697 --> 00:55:35,864\nit works, okay? It's got two pieces to it, and\n\n1065\n00:55:35,866 --> 00:55:38,334\nI'm gonna have both of those pieces implemented for\n\n1066\n00:55:38,336 --> 00:55:41,470\nyou using this class that you're gonna be able to use\n\n1067\n00:55:41,472 --> 00:55:44,073\nfor your homework, it's right over here,\n\n1068\n00:55:44,075 --> 00:55:46,842\ncalled core data table view controller.\n\n1069\n00:55:46,844 --> 00:55:48,644\nSo let's drag this core data view controller.\n\n1070\n00:55:48,646 --> 00:55:51,480\nI'm gonna put it in my core data group right here and\n\n1071\n00:55:51,482 --> 00:55:56,118\ncopy it in, okay. All right so let's take a look at this\n\n1072\n00:55:56,120 --> 00:56:00,122\nthing and see how ns fetched results controller works.\n\n1073\n00:56:00,124 --> 00:56:02,558\nSo, here's core data table view controller,\n\n1074\n00:56:02,560 --> 00:56:04,727\nit's a sub class of ui table view controller,\n\n1075\n00:56:04,729 --> 00:56:07,863\nyou're gonna make it be a sub class, you're gonna make it\n\n1076\n00:56:07,865 --> 00:56:10,833\nbe the super class of your ui table view controller.\n\n1077\n00:56:10,835 --> 00:56:12,735\nSo back here in our TweetersTableView,\n\n1078\n00:56:12,737 --> 00:56:15,471\ninstead of inheriting from UITableViewController,\n\n1079\n00:56:15,473 --> 00:56:19,007\nI'm going to inherit from CoreDateTableViewController.\n\n1080\n00:56:19,009 --> 00:56:21,944\nThat way, I'll get everything you get from\n\n1081\n00:56:21,946 --> 00:56:22,277\nUITableViewController.\n\n1082\n00:56:22,279 --> 00:56:25,314\nBut I'm also going to get this NS Fetch results controller\n\n1083\n00:56:25,316 --> 00:56:28,317\nstuff, okay? So let's look at that some more. There's two\n\n1084\n00:56:28,319 --> 00:56:32,654\nparts to the NS Fetch results controller. One is that\n\n1085\n00:56:32,656 --> 00:56:37,226\nI can use the [INAUDIBLE] to implement my entire UI table\n\n1086\n00:56:37,228 --> 00:56:39,862\nview data source except for its self erodement index\n\n1087\n00:56:39,864 --> 00:56:42,698\npath, okay? You still have to implement that. But all\n\n1088\n00:56:42,700 --> 00:56:45,567\nthe other ones look numbers of sections in table view,\n\n1089\n00:56:45,569 --> 00:56:46,769\nnumbers of rows in section,\n\n1090\n00:56:46,771 --> 00:56:48,837\neven the section header titers, titles,\n\n1091\n00:56:48,839 --> 00:56:52,741\nright the header titles, and footer titles section indexes.\n\n1092\n00:56:52,743 --> 00:56:54,176\nAll this stuff, it implements all that stuff.\n\n1093\n00:56:54,178 --> 00:56:57,079\nSee how the implementation of these is all using the fetch\n\n1094\n00:56:57,081 --> 00:57:00,649\nresults controller? So that's part A of how the NS\n\n1095\n00:57:00,651 --> 00:57:03,786\nfetch results controller works. Part B is that\n\n1096\n00:57:03,788 --> 00:57:07,823\nthe fetch results controller has a delegate, okay? And\n\n1097\n00:57:07,825 --> 00:57:11,193\nthat delegate can implement these methods.\n\n1098\n00:57:11,195 --> 00:57:14,730\nThat will be called anytime the database changes. So\n\n1099\n00:57:14,732 --> 00:57:17,933\nanytime anything happens in the database that might affect\n\n1100\n00:57:17,935 --> 00:57:20,602\nthis NS fetch request, okay? The delegate,\n\n1101\n00:57:20,604 --> 00:57:24,039\nthe NS Fetch delegate is going to be called and\n\n1102\n00:57:24,041 --> 00:57:27,543\nsent these messages. And look what these things do. They\n\n1103\n00:57:27,545 --> 00:57:30,746\njust update the table view, see? Table view, insert rows,\n\n1104\n00:57:30,748 --> 00:57:34,450\ndelete rows. You know, reload rows, that's because you know,\n\n1105\n00:57:34,452 --> 00:57:36,485\nthis is because something got deleted from the database,\n\n1106\n00:57:36,487 --> 00:57:37,853\nthis is something got inserted in the database,\n\n1107\n00:57:37,855 --> 00:57:42,791\nthis something changed in the database. Okay? So that's part\n\n1108\n00:57:42,793 --> 00:57:46,662\ntwo is this, delegate of the NSFetchedResultsController.\n\n1109\n00:57:46,664 --> 00:57:50,232\nSo I've given you the codes to do both those things. Okay,\n\n1110\n00:57:50,234 --> 00:57:51,300\nto implement this delegate, and\n\n1111\n00:57:51,302 --> 00:57:55,537\nalso to implement all of this UI table view data source.\n\n1112\n00:57:55,539 --> 00:57:57,906\nAll you have to do is set this var\n\n1113\n00:57:57,908 --> 00:57:59,274\nin the CoreDataTableViewController,\n\n1114\n00:57:59,276 --> 00:58:01,577\nwhich is an NSFetchedResultsController.\n\n1115\n00:58:01,579 --> 00:58:06,181\nAnd all that happens when you set this var in didSet is,\n\n1116\n00:58:06,183 --> 00:58:07,850\nit sets itself as the delegate, so\n\n1117\n00:58:07,852 --> 00:58:10,319\nthat all these methods down here at the bottom will work.\n\n1118\n00:58:10,321 --> 00:58:14,490\nOkay, then it tries to perform the fetch. Okay, if it\n\n1119\n00:58:14,492 --> 00:58:17,092\ncatches it, it will report an error if there is any.\n\n1120\n00:58:17,094 --> 00:58:20,028\nAnd then it reloads the table and that's it, okay.\n\n1121\n00:58:20,030 --> 00:58:22,264\nThe fetch results are always going to automatically\n\n1122\n00:58:22,266 --> 00:58:26,068\nbe linked now. So all you have to do to use Core Data table\n\n1123\n00:58:26,070 --> 00:58:28,203\ncontroller is set this fetch results controller.\n\n1124\n00:58:28,205 --> 00:58:31,006\nYou have to create and set one of these and then it will just\n\n1125\n00:58:31,008 --> 00:58:35,978\nwork by magic. Okay. So let's go back here. Do exactly that.\n\n1126\n00:58:35,980 --> 00:58:40,382\nIn our update UI, we need to say self dot fetched results\n\n1127\n00:58:40,384 --> 00:58:43,385\ncontroller equals. We do not actually need to say self\n\n1128\n00:58:43,387 --> 00:58:46,088\ndot, but I just wanted to ehm emphasize that it is something\n\n1129\n00:58:46,090 --> 00:58:49,491\nwe are inheriting from core table core data tableview.\n\n1130\n00:58:49,493 --> 00:58:51,159\nOkay, we can just set our fetch results control or\n\n1131\n00:58:51,161 --> 00:58:54,863\nsomething. So we are going to create a new fetch result\n\n1132\n00:58:54,865 --> 00:58:58,267\ncontroller. Okay.\n\n1133\n00:58:58,269 --> 00:59:02,037\nAnd here are all of what the things in the initializer\n\n1134\n00:59:02,039 --> 00:59:05,207\nlook like. Okay. First, there's the request.\n\n1135\n00:59:05,209 --> 00:59:08,243\nThis is the NSFetchRequest that is going to\n\n1136\n00:59:08,245 --> 00:59:09,344\nglue on to the table view. Okay.\n\n1137\n00:59:09,346 --> 00:59:13,115\nWe'll have to create that in a second. Second is the context.\n\n1138\n00:59:13,117 --> 00:59:15,918\nSo we have to go what context? What database are we looking\n\n1139\n00:59:15,920 --> 00:59:19,888\nin? Next is this section named key path. Okay. N.S.\n\n1140\n00:59:19,890 --> 00:59:23,058\nSpec Controller results will do the section titles,\n\n1141\n00:59:23,060 --> 00:59:26,962\nif you have an attribute in the entities that here in\n\n1142\n00:59:26,964 --> 00:59:30,666\nthe table that you're looking up here which is the section.\n\n1143\n00:59:30,668 --> 00:59:33,135\nOkay? The string the represents the section.\n\n1144\n00:59:33,137 --> 00:59:35,304\nCan I call that actually with anything you want. And\n\n1145\n00:59:35,306 --> 00:59:38,941\nyou put the name of it here, whatever name the section\n\n1146\n00:59:38,943 --> 00:59:41,376\nattributes here. The only thing about this, and\n\n1147\n00:59:41,378 --> 00:59:43,278\nyou can put Neil if you don't section, if we don't.\n\n1148\n00:59:43,280 --> 00:59:46,348\nThe only thing about this is that your table must sort\n\n1149\n00:59:46,350 --> 00:59:50,085\nin the same order as these sections would sort.\n\n1150\n00:59:50,087 --> 00:59:50,485\nWhen you think about it,\n\n1151\n00:59:50,487 --> 00:59:53,121\nif you're going to have them grouped by section\n\n1152\n00:59:53,123 --> 00:59:54,623\nthe things need to be in the same order.\n\n1153\n00:59:54,625 --> 00:59:57,225\nOtherwise you'd have some sec-, things in section here,\n\n1154\n00:59:57,227 --> 00:59:58,961\nsome in a different section, another different section.\n\n1155\n00:59:58,963 --> 01:00:01,597\nYou can't have that, they have to sort in the same order.\n\n1156\n01:00:01,599 --> 01:00:03,532\nOkay, so sometimes you'll have you're sort descriptors of\n\n1157\n01:00:03,534 --> 01:00:06,668\nyour effect request. Maybe sort by the section first and\n\n1158\n01:00:06,670 --> 01:00:08,804\nthen sort by whatever you want to do.\n\n1159\n01:00:08,806 --> 01:00:11,139\nThat's an easy way to make it work. And\n\n1160\n01:00:11,141 --> 01:00:14,743\nthen there's the cash which we're also not using. Okay?\n\n1161\n01:00:14,745 --> 01:00:18,013\nNot just a name. It's a string that it represents it.\n\n1162\n01:00:18,015 --> 01:00:19,748\nSo, I'm even gonna put this so\n\n1163\n01:00:19,750 --> 01:00:24,786\nyou can really see this four arguments right here. Okay.\n\n1164\n01:00:24,788 --> 01:00:29,257\nSo, we need to do a request right here and\n\n1165\n01:00:29,259 --> 01:00:29,858\nwe need to do the context.\n\n1166\n01:00:29,860 --> 01:00:32,160\nWell, the context is easy, that's part of our motto.\n\n1167\n01:00:32,162 --> 01:00:35,530\nSo I'm just going to say if I can let the context equal\n\n1168\n01:00:35,532 --> 01:00:39,835\nmy own managed object context, K? Then this\n\n1169\n01:00:39,837 --> 01:00:43,271\nwill get to go here. Otherwise I'm gonna set my fetch results\n\n1170\n01:00:43,273 --> 01:00:46,308\ncontroller to nil. If you set your fetch results controller\n\n1171\n01:00:46,310 --> 01:00:49,011\nto nil, core data table view control will clear your\n\n1172\n01:00:49,013 --> 01:00:52,381\ntable okay. Which is what I want if I don't have a manage\n\n1173\n01:00:52,383 --> 01:00:55,484\nobject context because I don't know what database to look in.\n\n1174\n01:00:55,486 --> 01:00:58,220\nOkay. So now what we need to do is request, okay?\n\n1175\n01:00:58,222 --> 01:01:03,025\nWe just need to have a request which is an NSFetchRequest.\n\n1176\n01:01:03,293 --> 01:01:04,126\nOkay. It's going to be what?\n\n1177\n01:01:04,128 --> 01:01:08,930\nWhat entity is going to be in this table? What is this NBC\n\n1178\n01:01:08,932 --> 01:01:14,136\nshow What kind of things? Twitter users, right? Showing\n\n1179\n01:01:14,138 --> 01:01:16,505\nall the Twitter users that are mentioned in this tweet.\n\n1180\n01:01:16,507 --> 01:01:22,277\nSo this is twitter user, okay. Now, how about the predicates,\n\n1181\n01:01:22,279 --> 01:01:26,381\nokay. We need a predicate of this for this thing. And so\n\n1182\n01:01:26,383 --> 01:01:30,152\nthat's in this predicate. Predicate with format here.\n\n1183\n01:01:30,154 --> 01:01:32,821\nOkay so what is gonna be our predicate for this?\n\n1184\n01:01:32,823 --> 01:01:35,757\nWell this is a little kind of complicated actually if\n\n1185\n01:01:35,759 --> 01:01:38,860\nyou think about it. We really wanna get all the Twitter\n\n1186\n01:01:38,862 --> 01:01:42,497\nusers who have a tweet that contains that string.\n\n1187\n01:01:42,499 --> 01:01:46,134\nAnd it turns out you can do that very straightforwardly\n\n1188\n01:01:46,136 --> 01:01:48,570\nwithin this predicate, you're just gonna say any\n\n1189\n01:01:48,572 --> 01:01:53,942\nTweets whose text contains, case insensitively, please,\n\n1190\n01:01:53,944 --> 01:01:58,346\nthat mention, okay. Now I have to do %@ whenever\n\n1191\n01:01:58,348 --> 01:02:01,616\nanything that I'm doing here is not a reserved keyword. So\n\n1192\n01:02:01,618 --> 01:02:05,454\nI have to do %@ and then put it here in this VarArgs.\n\n1193\n01:02:05,456 --> 01:02:10,792\nSo this is our mention right there Now that's an optional.\n\n1194\n01:02:10,794 --> 01:02:13,028\nSo I need to exclamation point here.\n\n1195\n01:02:13,030 --> 01:02:16,698\nBut I need to be careful here. What if this mention is nil?\n\n1196\n01:02:16,700 --> 01:02:19,868\nThis is gonna crash. And mention is part of my public\n\n1197\n01:02:19,870 --> 01:02:23,205\nAPI. You should not have objects where people can set\n\n1198\n01:02:23,207 --> 01:02:27,442\nyour public API to something that will crash internally.\n\n1199\n01:02:27,444 --> 01:02:30,979\nOkay, that's a bad API design, so\n\n1200\n01:02:30,981 --> 01:02:35,951\nI wanna check right here, by saying where, this mention and\n\n1201\n01:02:35,953 --> 01:02:40,989\nactually I also don't want to look up if the mention is\n\n1202\n01:02:42,025 --> 01:02:45,327\nempty string. That doesn't make any sense either.\n\n1203\n01:02:45,329 --> 01:02:48,864\nSo I'm gonna say mention?.characters.count > 0.\n\n1204\n01:02:48,866 --> 01:02:52,467\nSo I'm using where here with this if, and this is kind of\n\n1205\n01:02:52,469 --> 01:02:55,303\ninteresting look mention characters count. If mention\n\n1206\n01:02:55,305 --> 01:02:58,540\nis nil this whole thing is gonna be nil and the greater\n\n1207\n01:02:58,542 --> 01:03:03,879\nsign operator knows that nil is never greater than zero.\n\n1208\n01:03:04,181 --> 01:03:06,414\nIt also knows nil is never less than zero nor\n\n1209\n01:03:06,416 --> 01:03:09,985\nif nil equal to zero okay so it knows all those things.\n\n1210\n01:03:09,987 --> 01:03:11,920\nSo it's kind of fun you can put nils.\n\n1211\n01:03:11,922 --> 01:03:13,054\nOn the sides of these greater than's or\n\n1212\n01:03:13,056 --> 01:03:18,093\nless than's really kinda makes your code pretty nicely here.\n\n1213\n01:03:18,095 --> 01:03:21,263\nOkay? Now the thing we need to do is sort. Okay so we\n\n1214\n01:03:21,265 --> 01:03:24,633\nneed our sort descriptors, and remember that's an array of\n\n1215\n01:03:24,635 --> 01:03:27,402\nsort descriptors because we can sort by last name first,\n\n1216\n01:03:27,404 --> 01:03:29,404\nand then first name or by section name and\n\n1217\n01:03:29,406 --> 01:03:30,539\nthen by something else. But\n\n1218\n01:03:30,541 --> 01:03:33,842\nhere we only have one sort descriptor okay.\n\n1219\n01:03:33,844 --> 01:03:38,647\nThe sort descriptor has numerous things that you can\n\n1220\n01:03:38,649 --> 01:03:43,552\nspecify in its initialize. What if you used the simplest\n\n1221\n01:03:43,554 --> 01:03:46,388\none here which is I'm going to search by the key screen\n\n1222\n01:03:46,390 --> 01:03:51,059\nsort by the key screen name. So we're gonna list our users\n\n1223\n01:03:51,061 --> 01:03:53,562\nby their screen name, you know their at sign, whatever.\n\n1224\n01:03:53,564 --> 01:03:56,798\nThat's gonna be the order of this table and\n\n1225\n01:03:56,800 --> 01:03:59,568\nI'm going to have it be ascending true.\n\n1226\n01:03:59,570 --> 01:04:03,271\nSo A capital A will be first always to capital Z\n\n1227\n01:04:03,273 --> 01:04:05,774\nthen all the way to a all the way down from there. Okay?\n\n1228\n01:04:05,776 --> 01:04:10,245\nSo that's the only thing I'm gonna search by, so this one,\n\n1229\n01:04:10,247 --> 01:04:12,714\nor sort by this one sort to script Okay?\n\n1230\n01:04:12,716 --> 01:04:16,651\nSo now, that's it. The only thing I have to do now is\n\n1231\n01:04:16,653 --> 01:04:20,789\nimplement my self row at index path and I'm good to go. Okay?\n\n1232\n01:04:20,791 --> 01:04:24,025\nBecause this is going to always be keeping the Twitter\n\n1233\n01:04:24,027 --> 01:04:27,462\nusers associated with the rows. All right so self for\n\n1234\n01:04:27,464 --> 01:04:29,364\nrow index path of course we need to set\n\n1235\n01:04:29,366 --> 01:04:33,702\nour reuse identifier which I think was Twitter user cell.\n\n1236\n01:04:33,704 --> 01:04:35,837\nAll right. And it says configure the cell.\n\n1237\n01:04:35,839 --> 01:04:38,740\nNow, obviously, to configure the cell in any row,\n\n1238\n01:04:38,742 --> 01:04:42,878\nI need to know what Twitter user is in that row, okay. So,\n\n1239\n01:04:42,880 --> 01:04:47,849\nhow do I do that, let twitterUser equal and\n\n1240\n01:04:47,851 --> 01:04:51,920\nI'm gonna ask my fetched results controller, okay.\n\n1241\n01:04:51,922 --> 01:04:54,856\nI'm gonna say, what is the object that act this\n\n1242\n01:04:54,858 --> 01:04:58,627\nindex path? Okay, remember this is cellForRowAtIndexPath,\n\n1243\n01:04:58,629 --> 01:05:02,397\nso indexPath is what, the row we're talking about here. And\n\n1244\n01:05:02,399 --> 01:05:03,698\nI'm just gonna ask the Twitter, the,\n\n1245\n01:05:03,700 --> 01:05:06,902\nI'm gonna ask my fetchedResultsController\n\n1246\n01:05:06,904 --> 01:05:06,968\nwhat it is.\n\n1247\n01:05:06,970 --> 01:05:09,137\nAnd of course, it better be a TwitterUser. So\n\n1248\n01:05:09,139 --> 01:05:15,243\nI'm gonna put as TwitterUser there and say if let, okay?\n\n1249\n01:05:15,245 --> 01:05:18,113\nSo if I'm able to get to twitterUser here,\n\n1250\n01:05:18,115 --> 01:05:23,485\nthen I can just do for example cell.TextLabel.text\n\n1251\n01:05:23,487 --> 01:05:30,091\n= the twitterUser's screenName let's say. Okay?\n\n1252\n01:05:30,093 --> 01:05:32,727\nNow there's a problem with this line of code right here.\n\n1253\n01:05:32,729 --> 01:05:37,933\nCan anyone guess what this problem is right here? Looks\n\n1254\n01:05:37,935 --> 01:05:44,239\nperfectly fine, right? This is accessing the database,\n\n1255\n01:05:44,241 --> 01:05:47,976\nokay? And we know that anytime we access the database,\n\n1256\n01:05:47,978 --> 01:05:51,246\nwe gotta put it inside performBlock, okay? So\n\n1257\n01:05:51,248 --> 01:05:57,452\nwe actually have to put some context here, performBlock.\n\n1258\n01:05:57,454 --> 01:06:02,524\nOkay, around this code. Now, what context are we gonna\n\n1259\n01:06:02,526 --> 01:06:05,994\nuse here? We could use our manage object context.\n\n1260\n01:06:05,996 --> 01:06:07,495\nThat's true. And that would be fine.\n\n1261\n01:06:07,497 --> 01:06:09,331\nI'm actually gonna use a different context.\n\n1262\n01:06:09,333 --> 01:06:15,704\nI'm gonna use the Twitter user's manage object context.\n\n1263\n01:06:16,540 --> 01:06:20,208\nEvery NS managed object, this is a Twitter user. Okay?\n\n1264\n01:06:20,210 --> 01:06:22,911\nBut we also have Tweet. Every NS managed object\n\n1265\n01:06:22,913 --> 01:06:26,081\nknows the managed object context it's in. And\n\n1266\n01:06:26,083 --> 01:06:29,818\nyou can ask it. That will often keep you from having to\n\n1267\n01:06:29,820 --> 01:06:33,288\nhave var ManagedObjectContext as public var.\n\n1268\n01:06:33,290 --> 01:06:36,658\nBecause you'll have some other var which is a Twitter user or\n\n1269\n01:06:36,660 --> 01:06:40,028\na tweet or something like that and when that gets passed to\n\n1270\n01:06:40,030 --> 01:06:42,430\nyou now you know the managed object context.\n\n1271\n01:06:42,432 --> 01:06:45,533\nGot it? So that makes it so that you don't have to\n\n1272\n01:06:45,535 --> 01:06:48,069\npass both of managed object context and a Twitter user or\n\n1273\n01:06:48,071 --> 01:06:50,939\nsomething. Cuz if you pass in a Twitter user you're passing\n\n1274\n01:06:50,941 --> 01:06:54,542\nthe context along. Okay. So I'm just gonna use that down\n\n1275\n01:06:54,544 --> 01:06:55,944\nin here. I'm doing this intentionally so\n\n1276\n01:06:55,946 --> 01:06:57,612\nthat you know that this method exists.\n\n1277\n01:06:57,614 --> 01:07:01,383\nIt's a really cool var on an ms managed object.\n\n1278\n01:07:01,385 --> 01:07:05,987\nNow this is still no good, okay? What's wrong here?\n\n1279\n01:07:05,989 --> 01:07:12,260\nWhat's going on right there? That's accessing the ui.\n\n1280\n01:07:12,262 --> 01:07:16,297\nThat can only happen on the main queue. Okay? This,\n\n1281\n01:07:16,299 --> 01:07:20,502\nI happen to know, is the main queue, okay? I know, but\n\n1282\n01:07:20,504 --> 01:07:23,805\nwhat if I was writing my code to truly be multi-threaded and\n\n1283\n01:07:23,807 --> 01:07:28,309\nms managed conduct? I couldn't count on that. Okay? So,\n\n1284\n01:07:28,311 --> 01:07:31,212\nI can't do that, so instead, I'm gonna create a little var\n\n1285\n01:07:31,214 --> 01:07:35,583\nhere screen name, okay. Which is going to be a string. And\n\n1286\n01:07:35,585 --> 01:07:38,920\ninside here I'm going to get rid of this and say\n\n1287\n01:07:38,922 --> 01:07:44,025\nscreen name equals that and then out here I'm going to set\n\n1288\n01:07:44,027 --> 01:07:47,395\nthis equal to screen name. Okay. But\n\n1289\n01:07:47,397 --> 01:07:50,598\nthere is still a problem with this. Anyone can guess what\n\n1290\n01:07:50,600 --> 01:07:56,871\nthis problem is? You're a quiet crowd today. This\n\n1291\n01:07:56,873 --> 01:08:00,942\nis a synchronic. Okay, that screen name is going to happen\n\n1292\n01:08:00,944 --> 01:08:06,047\nsome other time. Certainly not in time for this. Okay, so\n\n1293\n01:08:06,049 --> 01:08:10,418\nwe need to perform block and wait here. Okay.\n\n1294\n01:08:10,420 --> 01:08:15,156\nWe have to wait for this to happen before we can do this.\n\n1295\n01:08:16,293 --> 01:08:20,829\nGot it? Okay, so that's it, let's go ahead and run and\n\n1296\n01:08:20,831 --> 01:08:29,904\nsee what this looks like. All right,\n\n1297\n01:08:29,906 --> 01:08:35,143\nlet's look for Stanford again. Okay, we got 206 tweets,\n\n1298\n01:08:35,145 --> 01:08:36,344\nwe got this many Twitter users.\n\n1299\n01:08:36,346 --> 01:08:38,480\n'm going to click this Tweeters right here, and\n\n1300\n01:08:38,482 --> 01:08:42,450\nsure enough, look! Her's all the people who tweeted hashtag\n\n1301\n01:08:42,452 --> 01:08:46,287\nStanford that w've ever seen. Now, this is not\n\n1302\n01:08:46,289 --> 01:08:50,024\nquite exactly what we want. I's close, okay? Notice\n\n1303\n01:08:50,026 --> 01:08:53,795\nour alphabetization. You see, all the capital letters first.\n\n1304\n01:08:53,797 --> 01:08:56,898\nThen [LAUGH] all the lowercase letters. Really,\n\n1305\n01:08:56,900 --> 01:09:01,102\nI want interspersed, right? I want case insensitive.\n\n1306\n01:09:01,104 --> 01:09:03,271\nLowercase. Or, sorry, case insensitive so,\n\n1307\n01:09:03,273 --> 01:09:06,641\nsorting as well. [SOUND] what else is going on here? Also,\n\n1308\n01:09:06,643 --> 01:09:09,911\nmaybe some of these I don't like. Like, look at this guy.\n\n1309\n01:09:09,913 --> 01:09:13,615\nDarksidedub16. Okay, that sounds kind of evil, so\n\n1310\n01:09:13,617 --> 01:09:17,752\nI don't even want Darkside to appear in my results. Okay?\n\n1311\n01:09:17,754 --> 01:09:19,120\nSo, let's fix both of those things,\n\n1312\n01:09:19,122 --> 01:09:19,521\nlet's fix the sorting and\n\n1313\n01:09:19,523 --> 01:09:23,158\nlet's make sure dark side does not appear in our results,\n\n1314\n01:09:23,160 --> 01:09:27,328\nokay? So, how do we do those things? First, the sorting,\n\n1315\n01:09:27,330 --> 01:09:30,165\ncase intensively is quite easy, okay? Here is where our\n\n1316\n01:09:30,167 --> 01:09:32,934\nsort descriptor is right here, here is the key and\n\n1317\n01:09:32,936 --> 01:09:35,370\nhere is the ascending, right there. We can just add\n\n1318\n01:09:35,372 --> 01:09:38,840\nanother argument here, which is the selector. To use, okay?\n\n1319\n01:09:38,842 --> 01:09:43,244\nWe'll use the hashtag selector here. Selector.\n\n1320\n01:09:43,246 --> 01:09:45,980\nAnd the selector I'm going to use is NF strings,\n\n1321\n01:09:45,982 --> 01:09:49,817\nI've got one called localizedcaseinsentivecompare\n\n1322\n01:09:49,819 --> 01:09:56,191\nright here, okay? And so you guys remember this format for\n\n1323\n01:09:56,193 --> 01:09:58,326\nspecifying a selector, right? So\n\n1324\n01:09:58,328 --> 01:10:00,328\nI'm just gonna use this instead of the standard one,\n\n1325\n01:10:00,330 --> 01:10:02,263\nwhich is compare, which is not case insensitive.\n\n1326\n01:10:02,265 --> 01:10:05,733\nSo that's gonna effect our, case insensitive sorting.\n\n1327\n01:10:05,735 --> 01:10:08,603\nOkay, it's just how we specify our sort descriptor.\n\n1328\n01:10:08,605 --> 01:10:11,105\nHow about getting the dark side out of there? Well,\n\n1329\n01:10:11,107 --> 01:10:14,809\nwhat appears in that table is determined by this predicate.\n\n1330\n01:10:14,811 --> 01:10:22,717\nOkay? Any tweets containing this currently, but I can say,\n\n1331\n01:10:22,719 --> 01:10:28,089\nand the screen name does not begin with,\n\n1332\n01:10:28,091 --> 01:10:32,660\ncase insensitivity, the darkside.\n\n1333\n01:10:32,662 --> 01:10:35,730\nOkay, and again I can't put anything but keywords in here,\n\n1334\n01:10:35,732 --> 01:10:40,835\nso I have to put it out here Okay? Like that.\n\n1335\n01:10:40,837 --> 01:10:43,438\nI just wanted to do this to show you that you can update\n\n1336\n01:10:43,440 --> 01:10:45,974\nthis predicate to change what shows up in your table,\n\n1337\n01:10:45,976 --> 01:10:50,979\nthis what controls within the table. So, now when we run.\n\n1338\n01:10:53,950 --> 01:10:57,452\nLet me do #stanford. Okay, and\n\n1339\n01:10:57,454 --> 01:11:01,389\nnow Tweeters, we can see that the sorting is right,\n\n1340\n01:11:01,391 --> 01:11:06,694\nyou see? Capitals and lower case and look, no dark sides.\n\n1341\n01:11:06,696 --> 01:11:11,399\nOkay, this is only a light side query here. All right.\n\n1342\n01:11:11,401 --> 01:11:14,269\nNow I have five minutes left, I'll show you one\n\n1343\n01:11:14,271 --> 01:11:18,439\nlast other fun thing. See this subtitle right here? What if\n\n1344\n01:11:18,441 --> 01:11:22,377\ninstead of saying subtitle I wanted to say how many tweets\n\n1345\n01:11:22,379 --> 01:11:26,014\nthis guys has tweeted, right? So we're show,\n\n1346\n01:11:26,016 --> 01:11:29,050\nthese are all the people who have tweeted #stanford,\n\n1347\n01:11:29,052 --> 01:11:31,286\nyou know, had mentioned #stanford in their tweets.\n\n1348\n01:11:31,288 --> 01:11:34,389\nI wanna know how many, so tell me how many each of these,\n\n1349\n01:11:34,391 --> 01:11:36,958\nhow many tweets this guy does, have done. All right?\n\n1350\n01:11:36,960 --> 01:11:39,727\nSo, to do that, I need another little function, okay?\n\n1351\n01:11:39,729 --> 01:11:43,464\nIt's going to be a private func. I'm going to call it\n\n1352\n01:11:43,466 --> 01:11:47,969\ntweetCountWithMentionByTwitte- rUser.\n\n1353\n01:11:47,971 --> 01:11:51,539\nAnd it's going to take a Twitter user.\n\n1354\n01:11:51,541 --> 01:11:54,709\nAnd it's going to return an int.\n\n1355\n01:11:54,711 --> 01:11:58,146\nOptional with how many times how many tweets, a tweet\n\n1356\n01:11:58,148 --> 01:12:01,015\ncount, where that Twitter user has mentioned that. So it's\n\n1357\n01:12:01,017 --> 01:12:03,785\ngonna return the number that I want to show there. Okay.\n\n1358\n01:12:03,787 --> 01:12:06,454\nSo what is this little guy gonna look like right here?\n\n1359\n01:12:06,456 --> 01:12:08,890\nWell I'm gonna have a local variable which is\n\n1360\n01:12:08,892 --> 01:12:11,993\nthe count which I am going to return at the end, K? It's\n\n1361\n01:12:11,995 --> 01:12:14,729\noptional because maybe I won't be able to find the results,\n\n1362\n01:12:14,731 --> 01:12:18,266\nwe'll see. And I'm going to get the users managed\n\n1363\n01:12:18,268 --> 01:12:21,936\nobject context again and perform black. And\n\n1364\n01:12:21,938 --> 01:12:26,574\nI'd better perform block and wait, k? Because this\n\n1365\n01:12:26,576 --> 01:12:29,177\na method that's being called, it needs to return, it can't,\n\n1366\n01:12:29,179 --> 01:12:32,847\nit's got to do the work and have the result come back. So,\n\n1367\n01:12:32,849 --> 01:12:34,649\nI'm just gonna create a fetch request here,\n\n1368\n01:12:34,651 --> 01:12:38,353\nNSFetchRequest. And this time I'm searching for\n\n1369\n01:12:38,355 --> 01:12:41,956\ntweets. Okay. Even though I'm inside the infiltration of\n\n1370\n01:12:41,958 --> 01:12:44,158\nthe twitter user table, I'm now counting tweets.\n\n1371\n01:12:44,160 --> 01:12:47,295\nSo, when I'm doing a different fetch inside there for tweets.\n\n1372\n01:12:47,297 --> 01:12:49,564\nThis is not the same fetch that's filling the table.\n\n1373\n01:12:49,566 --> 01:12:50,498\nThis is kind of a little side\n\n1374\n01:12:50,500 --> 01:12:54,802\nfetch, that I'm doing and the predicate for that is. And\n\n1375\n01:12:54,804 --> 01:12:59,207\nthen there's predicate, format,\n\n1376\n01:12:59,209 --> 01:13:03,778\nand text. I want the text of the Tweet to contain, case\n\n1377\n01:13:03,780 --> 01:13:08,883\ninsensitively, the mention that we're talking about. And\n\n1378\n01:13:08,885 --> 01:13:13,454\nI want the Tweeter to equal this user. Okay,\n\n1379\n01:13:13,456 --> 01:13:17,191\njust passed in here. So I need to have the mentions.\n\n1380\n01:13:17,193 --> 01:13:20,061\nSo that's our mention. Self.mention we'll need so\n\n1381\n01:13:20,063 --> 01:13:22,864\n.mention. And I'm just gonna go ahead and\n\n1382\n01:13:22,866 --> 01:13:25,333\nunwrap that. I'm pretty sure this is not new\n\n1383\n01:13:25,335 --> 01:13:27,935\nbecause I don't think this method would be called if I\n\n1384\n01:13:27,937 --> 01:13:30,271\nmatch it with milk because we never would've got\n\n1385\n01:13:30,273 --> 01:13:30,571\ninto all the self.\n\n1386\n01:13:30,573 --> 01:13:33,107\nAnd xpath and all this stuff we never would've gotten here.\n\n1387\n01:13:33,109 --> 01:13:34,709\nSome would say protect against this. But,\n\n1388\n01:13:34,711 --> 01:13:37,145\nI actually think it's good to crash here because you'll find\n\n1389\n01:13:37,147 --> 01:13:40,181\nthis bug if you ever call this when mentioned is nil,\n\n1390\n01:13:40,183 --> 01:13:41,816\nwhich it never should be at this point. And\n\n1391\n01:13:41,818 --> 01:13:45,720\nthen the Tweeter is just this argument user. So you Tweeter\n\n1392\n01:13:45,722 --> 01:13:50,558\nequals user and pass a Twitter user, okay? And restrict your\n\n1393\n01:13:50,560 --> 01:13:53,327\nresults to that, so that's our results. So now I'm\n\n1394\n01:13:53,329 --> 01:13:56,097\ngoing to use that count thing that we talked about before.\n\n1395\n01:13:56,099 --> 01:14:01,536\nThat's the user's managed object context. Count for\n\n1396\n01:14:01,538 --> 01:14:05,273\nfetch request. The request. Don't care about errors,it\n\n1397\n01:14:05,275 --> 01:14:06,140\nwill come back zero. That's fine.\n\n1398\n01:14:06,142 --> 01:14:10,678\nAnd I'm going to return the count. Okay? Everyone see what\n\n1399\n01:14:10,680 --> 01:14:14,215\nI did there? Just found the, the request that I wanted.\n\n1400\n01:14:14,217 --> 01:14:16,951\nSo now that I have this nice little guy right here,\n\n1401\n01:14:16,953 --> 01:14:21,422\nI can go here and say that my cell. I can actually say if\n\n1402\n01:14:21,424 --> 01:14:25,927\nlet the count equal the tweet count mentioned by\n\n1403\n01:14:25,929 --> 01:14:29,831\nthis twitter user. Okay? So if I got an account,\n\n1404\n01:14:29,833 --> 01:14:34,535\nthen I'm gonna have the cells detail TextLabel, text= and\n\n1405\n01:14:34,537 --> 01:14:37,371\nlet's even be kinda be cute and say if the count is one.\n\n1406\n01:14:37,373 --> 01:14:42,944\nI'm gonna say 1 tweet otherwise I'm gonna say count\n\n1407\n01:14:42,946 --> 01:14:47,548\ntweets, plural. If I wasn't able to get it then I'm just\n\n1408\n01:14:47,550 --> 01:14:52,453\ngonna say that the cell detail text label text to empty,\n\n1409\n01:14:53,289 --> 01:15:03,097\nokay. Let's run that. All right. Hashtag stanford again.\n\n1410\n01:15:03,099 --> 01:15:07,268\nSeems to be our favorite. Here it is right here.\n\n1411\n01:15:07,270 --> 01:15:12,073\nOkay tweeters and there it is. Okay, a lot of people with one\n\n1412\n01:15:12,075 --> 01:15:14,041\ntweet, but here's someone with three tweets.\n\n1413\n01:15:14,043 --> 01:15:16,244\nOkay there's someone with four tweets right there.\n\n1414\n01:15:16,246 --> 01:15:17,311\nNow there were four tweets.\n\n1415\n01:15:17,313 --> 01:15:19,780\nNow, the next obvious thing is to say,\n\n1416\n01:15:19,782 --> 01:15:23,618\nawesome. I want to sort this table by the people's numbers\n\n1417\n01:15:23,620 --> 01:15:26,254\nof tweets, so the people who tweet a lot are at the top.\n\n1418\n01:15:26,256 --> 01:15:29,724\nWouldn't that be a lot better than alphabetical?\n\n1419\n01:15:29,726 --> 01:15:30,791\nIt sure would. But\n\n1420\n01:15:30,793 --> 01:15:35,563\nto do that, we would need a different schema. Okay.\n\n1421\n01:15:35,565 --> 01:15:37,632\nThis is important because in your homework you're going to\n\n1422\n01:15:37,634 --> 01:15:39,967\nbe sorting by a numb numerical value right here. And\n\n1423\n01:15:39,969 --> 01:15:42,703\nyou gotta make sure you have a schema that supports it.\n\n1424\n01:15:42,705 --> 01:15:44,839\nWhy would we need a different schema to sort\n\n1425\n01:15:44,841 --> 01:15:48,509\nto sort this by the number of tweets? It's because of this.\n\n1426\n01:15:48,511 --> 01:15:50,044\nOkay, if we go back up here and\n\n1427\n01:15:50,046 --> 01:15:55,383\nlook at our sort descriptor. Okay. For this table.\n\n1428\n01:15:55,385 --> 01:16:00,221\nIt's sorting by the screen name. This always has to be\n\n1429\n01:16:00,223 --> 01:16:05,226\nan attribute in this entity. Okay,\n\n1430\n01:16:05,228 --> 01:16:06,994\nthe sort descriptor cannot be anything but\n\n1431\n01:16:06,996 --> 01:16:09,363\nan attribute in this entity. Well, Twitter user\n\n1432\n01:16:09,365 --> 01:16:12,567\ndoes not have an attribute which is that number. So\n\n1433\n01:16:12,569 --> 01:16:16,504\nI cannot sort by it. You see? And not only that.\n\n1434\n01:16:16,506 --> 01:16:19,106\nIt would be very difficult for me to keep a number\n\n1435\n01:16:19,108 --> 01:16:22,476\non my Twitter user that would be that. Because\n\n1436\n01:16:22,478 --> 01:16:25,413\nit depends on the mention. I'd have to have a different\n\n1437\n01:16:25,415 --> 01:16:26,447\nTwitter user for every mention.\n\n1438\n01:16:26,449 --> 01:16:31,152\nSo this schema that we've designed right here,\n\n1439\n01:16:31,154 --> 01:16:35,690\nwhich I will show you this schema, is insufficient.\n\n1440\n01:16:35,692 --> 01:16:38,626\nTo have that table sorted by a number, you need\n\n1441\n01:16:38,628 --> 01:16:41,929\na different schema. A slightly more powerful schema and\n\n1442\n01:16:41,931 --> 01:16:44,899\nreally the hardest thing about semi five for you is probably\n\n1443\n01:16:44,901 --> 01:16:47,234\ndesign that schema. Once you design that schema,\n\n1444\n01:16:47,236 --> 01:16:49,837\nlook how incredibly it is easy to load these tables over\n\n1445\n01:16:49,839 --> 01:16:53,074\nthat coordinated table it's just like, it's trivial. Okay?\n\n1446\n01:16:53,076 --> 01:16:56,410\nSo, make sure you spend your brainpower on assignment five,\n\n1447\n01:16:56,412 --> 01:16:57,011\ngetting a good schema,\n\n1448\n01:16:57,013 --> 01:16:58,412\nunderstanding what you're being asked to do,\n\n1449\n01:16:58,414 --> 01:17:03,150\nand then getting a good schema that supports that, okay?\n\n1450\n01:17:03,152 --> 01:17:05,620\nYou'll, you'll find the rest of assignment five is very,\n\n1451\n01:17:05,622 --> 01:17:10,324\nis straightforward, okay? All right, that's it.\n\n1452\n01:17:10,326 --> 01:17:13,461\nI will see you on Wednesday we'll talk about the final\n\n1453\n01:17:13,463 --> 01:17:16,197\nproject requirements among other things.\n\n1454\n01:17:17,667 --> 01:17:17,932\n>> For more,\n\n1455\n01:17:17,934 --> 01:17:17,965\nplease visit us at stanford.edu.\n\n"
  },
  {
    "path": "subtitles/12. AutoLayout.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,702\n[MUSIC]\n\n2\n00:00:03,704 --> 00:00:07,973\nStanford University. >> Welcome to\n\n3\n00:00:07,975 --> 00:00:12,945\nLecture 12 of Stanford CS193P, spring of 2016. Today\n\n4\n00:00:12,947 --> 00:00:15,647\nwe have Autolayout, which we've actually been doing\n\n5\n00:00:15,649 --> 00:00:18,550\nquite a bit of Autolayout, so far, but we're gonna talk\n\n6\n00:00:18,552 --> 00:00:21,353\na lot more in detail about the concepts of Autolayout and\n\n7\n00:00:21,355 --> 00:00:25,491\nthings like that. And we're gonna introduce an important\n\n8\n00:00:25,493 --> 00:00:28,460\nAutolayout feature called Size Classes, okay?\n\n9\n00:00:28,462 --> 00:00:30,129\nAll right, so let's dive in to Autolayout.\n\n10\n00:00:30,131 --> 00:00:32,798\nSo you already know a lot about Autolayout, right? For\n\n11\n00:00:32,800 --> 00:00:36,235\nexample, you know you can use those dashed blue lines when\n\n12\n00:00:36,237 --> 00:00:38,871\nyou drag things in and move things around to kinda tell\n\n13\n00:00:38,873 --> 00:00:42,441\nXcode what you intend about how things are laid out, okay?\n\n14\n00:00:42,443 --> 00:00:45,444\nBut you know that those blue lines are really only just\n\n15\n00:00:45,446 --> 00:00:48,247\nkind of a hint, right? But you can say reset to\n\n16\n00:00:48,249 --> 00:00:51,016\nsuggest a constraints. And it'll use the dashed blue line\n\n17\n00:00:51,018 --> 00:00:54,753\ninformation to try and guess, what constraints you want.\n\n18\n00:00:54,755 --> 00:00:58,590\nAnd sometimes that's what you want, sometimes not. Really\n\n19\n00:00:58,592 --> 00:01:03,228\nthat's just minimal help from the system to do Autolayout.\n\n20\n00:01:03,230 --> 00:01:04,663\nIt's kinda maybe to get you started,\n\n21\n00:01:04,665 --> 00:01:06,865\nor to get some initial constraints or\n\n22\n00:01:06,867 --> 00:01:08,200\nsomething like that, okay? And\n\n23\n00:01:08,202 --> 00:01:11,136\nyou know that you can look in the Size Inspector, okay?\n\n24\n00:01:11,138 --> 00:01:12,304\nYou can click, click on any view and\n\n25\n00:01:12,306 --> 00:01:13,505\nlook in the Size Inspector, and now,\n\n26\n00:01:13,507 --> 00:01:16,075\nnow, down there you'll see all of the constraints.\n\n27\n00:01:16,077 --> 00:01:20,612\nWe've looked at those before that are on a particular view.\n\n28\n00:01:20,614 --> 00:01:24,716\nOkay, you also know that you can click on a constraint\n\n29\n00:01:24,718 --> 00:01:27,619\nitself and look at it in the Attributes Inspector.\n\n30\n00:01:27,621 --> 00:01:29,988\nSo just like we click on a view and inspect that,\n\n31\n00:01:29,990 --> 00:01:31,757\nyou can click on any constraint,\n\n32\n00:01:31,759 --> 00:01:33,692\nlike a little i-beam or, you know, some bar,\n\n33\n00:01:33,694 --> 00:01:36,628\nsomething that's connecting something to an edge or\n\n34\n00:01:36,630 --> 00:01:38,630\nsomething. You can click on those things.\n\n35\n00:01:38,632 --> 00:01:40,099\nYou can even double-click on them and\n\n36\n00:01:40,101 --> 00:01:41,733\nedit them kind of in a little window.\n\n37\n00:01:41,735 --> 00:01:42,768\nBut you can single-click on them and\n\n38\n00:01:42,770 --> 00:01:46,271\nthen edit them in the Attributes Inspector as well.\n\n39\n00:01:47,108 --> 00:01:50,509\nNow we know that the other way, another way we can set,\n\n40\n00:01:50,511 --> 00:01:53,212\nconstraints is to control drag like we control drag to\n\n41\n00:01:53,214 --> 00:01:56,515\nthe edge and say, you know, make it be a certain distance\n\n42\n00:01:56,517 --> 00:01:58,750\nfrom this edge. Okay, we saw that quite a bit.\n\n43\n00:01:58,752 --> 00:02:01,720\nThat Ctrl-dragging can also be done between views.\n\n44\n00:02:01,722 --> 00:02:04,123\nSo you can Ctrl-drag between two views and then say,\n\n45\n00:02:04,125 --> 00:02:08,227\nmake these two be the same with, okay? Things like that.\n\n46\n00:02:08,229 --> 00:02:10,529\nAnd we'll see a little bit of that today in the demo. So\n\n47\n00:02:10,531 --> 00:02:14,299\nthat Ctrl-dragging is probably the number one way you do\n\n48\n00:02:14,301 --> 00:02:18,036\nAutolayout, okay? But there's also a couple of menus down in\n\n49\n00:02:18,038 --> 00:02:21,106\nthe bottom right corner where that menu that you bring up\n\n50\n00:02:21,108 --> 00:02:25,110\nthat says reset to suggested constraints or update frames.\n\n51\n00:02:25,112 --> 00:02:25,244\nYou know that thing,\n\n52\n00:02:25,246 --> 00:02:27,846\nthere's two other little menus right by it. Okay the pin and\n\n53\n00:02:27,848 --> 00:02:31,717\narrange menus, and they also let you say things like\n\n54\n00:02:31,719 --> 00:02:34,720\nmake these. You can select five views, and then bring up\n\n55\n00:02:34,722 --> 00:02:37,990\nthe arrange menu and say, make all of these equal widths.\n\n56\n00:02:37,992 --> 00:02:39,992\nAnd now we have a constraint on all five of the views to\n\n57\n00:02:39,994 --> 00:02:44,830\nmake them equal widths. So, those menus, frankly\n\n58\n00:02:44,832 --> 00:02:47,833\nyou don't use them that much because the Ctrl-drag is so\n\n59\n00:02:47,835 --> 00:02:49,968\nincredibly convenient for doing that, but\n\n60\n00:02:49,970 --> 00:02:56,241\nsometimes we will. You can look at your constraints by\n\n61\n00:02:56,243 --> 00:02:59,378\ninspecting things, but really the way to see a big picture\n\n62\n00:02:59,380 --> 00:03:02,648\nof all of the constraints is in the document outline, okay?\n\n63\n00:03:02,650 --> 00:03:04,950\nRemember the document outline? That's the thing on the left\n\n64\n00:03:04,952 --> 00:03:06,251\nin the storyboard that you can kinda\n\n65\n00:03:06,253 --> 00:03:07,953\nbring out with the little button on the bottom and\n\n66\n00:03:07,955 --> 00:03:11,123\nit shows you all your views and the hierarchy of it and\n\n67\n00:03:11,125 --> 00:03:11,156\nall that stuff.\n\n68\n00:03:11,158 --> 00:03:14,059\nWell it'll also show all your constraints in there. Okay,\n\n69\n00:03:14,061 --> 00:03:15,994\na big long list of your constraints.\n\n70\n00:03:15,996 --> 00:03:19,331\nAnd, that's a good place where you can go to see them.\n\n71\n00:03:19,333 --> 00:03:22,734\nIt also has a constraint resolution\n\n72\n00:03:22,736 --> 00:03:25,337\nUI which I might have brief, briefly shown but\n\n73\n00:03:25,339 --> 00:03:28,340\nI'll certainly show today. Where it'll actually tell you\n\n74\n00:03:28,342 --> 00:03:30,642\nall the constraints that are conflicting or\n\n75\n00:03:30,644 --> 00:03:33,378\nnot fully specifying things, that kind of stuff.\n\n76\n00:03:33,380 --> 00:03:36,148\nSo it's kind of, Document Outline is your constraint\n\n77\n00:03:36,150 --> 00:03:39,484\nheadquarters to go try and fix things with constraints and\n\n78\n00:03:39,486 --> 00:03:42,454\nunderstand what's going on with your constraints. Now\n\n79\n00:03:42,456 --> 00:03:45,624\nmastering Autolayout requires experience. I can tell you all\n\n80\n00:03:45,626 --> 00:03:49,194\nthese things what the, what the things you can do are, but\n\n81\n00:03:49,196 --> 00:03:52,231\nuntil you get in there and start trying to lay things out\n\n82\n00:03:52,233 --> 00:03:55,801\nand make things line up, and do things like that,\n\n83\n00:03:55,803 --> 00:03:57,536\nyou really won't be able to master it, okay?\n\n84\n00:03:57,538 --> 00:03:59,571\nSo it requires experience. So hopefully in your final\n\n85\n00:03:59,573 --> 00:04:02,241\nproject you'll have some UIs that require quite a bit of\n\n86\n00:04:02,243 --> 00:04:04,977\nAutolayout. You know the UIs we've had so far have not\n\n87\n00:04:04,979 --> 00:04:07,079\nrequired that much Autolayout because I haven't gotten to\n\n88\n00:04:07,081 --> 00:04:09,781\nthis lecture yet. So you know we've been using StatView\n\n89\n00:04:09,783 --> 00:04:12,317\na lot, okay? We're heavily relying on StatView to make it\n\n90\n00:04:12,319 --> 00:04:15,187\nso we don't have to do so much Autolayout, cuz StatView kind\n\n91\n00:04:15,189 --> 00:04:18,457\nof is a thing for doing Autolayout in a very simple\n\n92\n00:04:18,459 --> 00:04:22,361\nway when you want to line things up in grids, okay? So\n\n93\n00:04:22,363 --> 00:04:26,498\nthere's no, no substitute for experience in Autolayout. It\n\n94\n00:04:26,500 --> 00:04:29,868\nis possible to do Autolayout constraints from code, okay?\n\n95\n00:04:29,870 --> 00:04:33,272\nThere is a class called ns layout constraint. And\n\n96\n00:04:33,274 --> 00:04:36,041\nit does all the things you can do in the storyboard and\n\n97\n00:04:36,043 --> 00:04:38,277\npossibly even a little bit more.\n\n98\n00:04:38,279 --> 00:04:40,078\nActually definitely a little bit more.\n\n99\n00:04:40,080 --> 00:04:41,913\nI'm not gonna teach that in this course.\n\n100\n00:04:41,915 --> 00:04:44,549\nIf you wanna learn about it, you might think about trying\n\n101\n00:04:44,551 --> 00:04:48,987\nto do something in your final project, maybe. It requires\n\n102\n00:04:48,989 --> 00:04:51,923\na certain understanding of mathematics and\n\n103\n00:04:51,925 --> 00:04:54,259\nreally understanding relationships between things,\n\n104\n00:04:54,261 --> 00:04:56,962\nto really set things up and make things work. It's a heck\n\n105\n00:04:56,964 --> 00:04:59,631\nof a lot easier just to do it all in the story board. So\n\n106\n00:04:59,633 --> 00:05:02,067\nunless you wanna kinda make that one of your investigative\n\n107\n00:05:02,069 --> 00:05:04,303\nthings for your final project, which you're gonna see\n\n108\n00:05:04,305 --> 00:05:06,104\nis required that you go investigate something that I\n\n109\n00:05:06,106 --> 00:05:09,541\ndon't teach in lecture. You're probably gonna wanna try and\n\n110\n00:05:09,543 --> 00:05:12,711\ndo Autolayout from the story board, okay. And\n\n111\n00:05:12,713 --> 00:05:15,814\nyou can certainly do everything you need to do\n\n112\n00:05:15,816 --> 00:05:19,251\nalmost all the time in your story board. Okay,\n\n113\n00:05:19,253 --> 00:05:24,656\nso, let's see what's next here. Let's talk about,\n\n114\n00:05:24,658 --> 00:05:30,195\nrotation, okay? So sometimes, when you rotate your UI,\n\n115\n00:05:30,197 --> 00:05:33,098\nthe geometry of it changes so drastically that\n\n116\n00:05:33,100 --> 00:05:36,668\nAutolayout is not enough to reposition everything, okay?\n\n117\n00:05:36,670 --> 00:05:39,738\nA great example of this is our calculator, okay? Our\n\n118\n00:05:39,740 --> 00:05:43,775\ncalculator had five across, five buttons across and\n\n119\n00:05:43,777 --> 00:05:47,913\nfour buttons down, I think, okay? And that looked fine.\n\n120\n00:05:47,915 --> 00:05:49,948\nOr it was four across and five down, I guess.\n\n121\n00:05:49,950 --> 00:05:50,982\nAnd that looks fine in portrait.\n\n122\n00:05:50,984 --> 00:05:53,552\nAll the buttons were almost square. They were rectangular,\n\n123\n00:05:53,554 --> 00:05:55,420\nbut they were close to being square. But\n\n124\n00:05:55,422 --> 00:05:56,121\nwhen we went into landscape,\n\n125\n00:05:56,123 --> 00:05:58,390\nall of our buttons got really squished down, okay.\n\n126\n00:05:58,392 --> 00:06:01,393\nThey're really wide and really short. Okay, and really, it\n\n127\n00:06:01,395 --> 00:06:04,363\nwould have been a lot better if we had gone five across and\n\n128\n00:06:04,365 --> 00:06:06,832\nfour down. Because we'd have more space\n\n129\n00:06:06,834 --> 00:06:09,735\nacross than we do have down in landscape. Okay, well there's\n\n130\n00:06:09,737 --> 00:06:13,238\nno way to do Autolayout. No way so that that would happen.\n\n131\n00:06:13,240 --> 00:06:16,675\nOkay, there's no way to put any relationships between them\n\n132\n00:06:16,677 --> 00:06:18,210\nso that they would just somehow flip over.\n\n133\n00:06:18,212 --> 00:06:20,979\nSome of the buttons would flip over from being along the top,\n\n134\n00:06:20,981 --> 00:06:23,448\nfor example, to being along the left, okay? So you can't\n\n135\n00:06:23,450 --> 00:06:26,051\ndo it that way. So what would you do if you wanted to build\n\n136\n00:06:26,053 --> 00:06:29,588\na calculator that repositioned the buttons when you flipped\n\n137\n00:06:29,590 --> 00:06:32,424\nit over? Because it's not just the calculate,\n\n138\n00:06:32,426 --> 00:06:35,327\nthe calculator that might want to do this. For\n\n139\n00:06:35,329 --> 00:06:39,297\nyou example you know when you're in the master of\n\n140\n00:06:39,299 --> 00:06:43,101\na split view okay it's not you're not in portrait.\n\n141\n00:06:43,103 --> 00:06:44,236\nYou're probably on an iPad or\n\n142\n00:06:44,238 --> 00:06:47,973\nat least you might be on an iPhone 6+. In that master,\n\n143\n00:06:47,975 --> 00:06:51,309\nyou also want it to be the right arrangement of buttons.\n\n144\n00:06:51,311 --> 00:06:54,513\nOkay, more like iPhone portrait, okay, than iPad.\n\n145\n00:06:54,515 --> 00:06:58,784\nOkay, so the solution to doing this is called size classes.\n\n146\n00:06:58,786 --> 00:07:00,685\nOkay, so your view controllers,\n\n147\n00:07:00,687 --> 00:07:02,020\nany view controller that you're doing,\n\n148\n00:07:02,022 --> 00:07:02,988\nlike the calculator view controller,\n\n149\n00:07:02,990 --> 00:07:06,691\nalways lives in a size class environment, okay, for\n\n150\n00:07:06,693 --> 00:07:10,896\nits width and its height. Okay, and that size class is\n\n151\n00:07:10,898 --> 00:07:14,466\neither compact or regular. Regular means\n\n152\n00:07:14,468 --> 00:07:18,270\nit's not compact, okay? So your view controller for each,\n\n153\n00:07:18,272 --> 00:07:21,206\nfor horizontally and vertically, will get something\n\n154\n00:07:21,208 --> 00:07:25,177\ntold to it, okay you are in a compact vertical environment,\n\n155\n00:07:25,179 --> 00:07:28,680\nor you are in a compact horizontal environment. And\n\n156\n00:07:28,682 --> 00:07:31,983\nyou can react to that, okay? So in the calculator's case,\n\n157\n00:07:31,985 --> 00:07:34,352\nif we're in a compact vertical environment,\n\n158\n00:07:34,354 --> 00:07:38,256\nlet's put five across and four down, because we're squi,\n\n159\n00:07:38,258 --> 00:07:40,192\nyou know, squished down vertically so\n\n160\n00:07:40,194 --> 00:07:43,228\nwe'll spread them out a little bit. And if we're not,\n\n161\n00:07:43,230 --> 00:07:46,498\nthen we'll go ahead and use the vertical space and make it\n\n162\n00:07:46,500 --> 00:07:50,001\nbe four across and five down, okay? So getting all this,\n\n163\n00:07:50,003 --> 00:07:53,405\nkind of all the different kinds of aspect ratios, and\n\n164\n00:07:53,407 --> 00:07:56,942\nthings for all the devices to fit into this compact in\n\n165\n00:07:56,944 --> 00:07:59,277\nregular. You know it's not a perfect fit, but\n\n166\n00:07:59,279 --> 00:08:02,380\nhere's a kind of general idea of how these fit, all right?\n\n167\n00:08:02,382 --> 00:08:06,651\nSo the iPhone 6 Plus in Portrait, right when it's,\n\n168\n00:08:06,653 --> 00:08:09,855\nit's stand, standing upright basically.\n\n169\n00:08:09,857 --> 00:08:14,025\nThat is compact width, regular height. Makes perfect sense,\n\n170\n00:08:14,027 --> 00:08:15,894\nright? Okay, compact width, regular height.\n\n171\n00:08:15,896 --> 00:08:18,697\nWhen you go to Landscape, now it's compact height,\n\n172\n00:08:18,699 --> 00:08:22,801\nregular width. Okay. So iPhone 6 Plus makes the most sense of\n\n173\n00:08:22,803 --> 00:08:28,240\nall of the devices. Okay? Now iPhone non-plus,\n\n174\n00:08:28,242 --> 00:08:32,944\nokay, is compact, in width.\n\n175\n00:08:32,946 --> 00:08:35,413\nSorry, in Portrait, it's compact in width and\n\n176\n00:08:35,415 --> 00:08:37,649\nregular in height. But in Landscaped, okay,\n\n177\n00:08:37,651 --> 00:08:39,885\nnon 6 Plus now I'm talking about here, it's\n\n178\n00:08:39,887 --> 00:08:44,422\ncompact in both directions. So on a normal iPhone, non plus\n\n179\n00:08:44,424 --> 00:08:47,726\niPhone, in width, you would think it would be regular\n\n180\n00:08:47,728 --> 00:08:50,495\ncuz it was regular when it was in Portrait in height, but no,\n\n181\n00:08:50,497 --> 00:08:53,431\nit's compact. So you can actually tell the difference\n\n182\n00:08:53,433 --> 00:08:57,736\nbetween whether you're on a 6 Plus or a regular iPhone 4 or\n\n183\n00:08:57,738 --> 00:09:00,705\nS or 5 or 6 or whatever, non Plus because you'll\n\n184\n00:09:00,707 --> 00:09:03,241\nbe compact in both directions in Landscape. Okay?\n\n185\n00:09:03,243 --> 00:09:06,011\nSo it's just kinda weird gotta be used to that.\n\n186\n00:09:06,013 --> 00:09:10,015\niPad is always regular in both directions. Cuz it£s so big,\n\n187\n00:09:10,017 --> 00:09:13,351\nit£s not compact in any way, in any direction. However,\n\n188\n00:09:13,353 --> 00:09:16,821\nif you£re an MVC that is in the master of a split view,\n\n189\n00:09:16,823 --> 00:09:21,226\nyou£ll be compact in width. Okay, understandably right cuz\n\n190\n00:09:21,228 --> 00:09:27,265\nyou're kinda, jammed in there. This whole system,\n\n191\n00:09:27,267 --> 00:09:31,136\nby the way, is extensible. It's not just rock solid,\n\n192\n00:09:31,138 --> 00:09:34,372\nyou know, hooked up to whether you're on a 6 Plus or\n\n193\n00:09:34,374 --> 00:09:36,474\nan iPhone or in a split view master or\n\n194\n00:09:36,476 --> 00:09:38,476\na whatever. It has a whole mechanism for\n\n195\n00:09:38,478 --> 00:09:42,781\nan MVC to find out what size class it's in. It can even say\n\n196\n00:09:42,783 --> 00:09:45,650\nbased on its environment I wanna be in this size class.\n\n197\n00:09:45,652 --> 00:09:48,687\nAnd then if it has MVCs inside of it like it's a navigation\n\n198\n00:09:48,689 --> 00:09:49,354\ncontroller or something like that.\n\n199\n00:09:49,356 --> 00:09:52,724\nThen they would inherit that size class information, okay.\n\n200\n00:09:52,726 --> 00:09:56,328\nNow I'm not gonna talk about that all the code side of it.\n\n201\n00:09:56,330 --> 00:09:59,097\nThe only code you're probably gonna be interested\n\n202\n00:09:59,099 --> 00:10:01,232\nin is this method here in view controller,\n\n203\n00:10:01,234 --> 00:10:04,736\nSelf traitCollection. Horizontal size class and\n\n204\n00:10:04,738 --> 00:10:05,503\nvertical size class and\n\n205\n00:10:05,505 --> 00:10:07,672\nit's gonna give you back compact irregular.\n\n206\n00:10:07,674 --> 00:10:09,641\nOkay? So that's how you'll know if you're compact\n\n207\n00:10:09,643 --> 00:10:12,844\nirregular. Now, that's only if you wanted to react\n\n208\n00:10:12,846 --> 00:10:15,947\nto your compactness in code. A lot of times we're gonna\n\n209\n00:10:15,949 --> 00:10:19,217\nbe doing this in our story board. Okay? And I'm gonna\n\n210\n00:10:19,219 --> 00:10:21,686\nshow you how in the story board we'll react to that. So\n\n211\n00:10:21,688 --> 00:10:24,589\nin summary it looks like this, okay? You got compact width\n\n212\n00:10:24,591 --> 00:10:26,491\nand regular width. Compact height and regular height.\n\n213\n00:10:26,493 --> 00:10:30,462\nSo, iPhones (non-Plus) in Landscape are here. Compact,\n\n214\n00:10:30,464 --> 00:10:35,567\ncompact. Regular width compact is iPhone 6 Plus in Landscape.\n\n215\n00:10:35,569 --> 00:10:36,234\nRegular height and\n\n216\n00:10:36,236 --> 00:10:38,470\ncompact width is iPhones in Portrait or\n\n217\n00:10:38,472 --> 00:10:40,772\nyou're the Master of the Split View. And\n\n218\n00:10:40,774 --> 00:10:44,009\nthen iPads are regular in both. Okay. So,\n\n219\n00:10:44,011 --> 00:10:45,443\nif you want to look at the calculator, for example,\n\n220\n00:10:45,445 --> 00:10:49,180\nit would look something like this, all right. Now here is,\n\n221\n00:10:49,182 --> 00:10:53,718\nI'm drawing my UI here as if I've adapted to this. In\n\n222\n00:10:53,720 --> 00:10:57,255\nin this case right here, I've decided to go four across and\n\n223\n00:10:57,257 --> 00:11:00,191\nfive down because I gotta lot of down, a lot of vertical\n\n224\n00:11:00,193 --> 00:11:02,761\nspace. Whereas here I've gone five across and\n\n225\n00:11:02,763 --> 00:11:04,663\nfour down cuz I'm kinda compact in height,\n\n226\n00:11:04,665 --> 00:11:07,699\nyou see. Even here I've done the same thing.\n\n227\n00:11:07,701 --> 00:11:09,200\nI've decided here, compact and\n\n228\n00:11:09,202 --> 00:11:11,970\nregular width to go five across and four down. And\n\n229\n00:11:11,972 --> 00:11:14,539\ndown here, in regular both directions I decided it\n\n230\n00:11:14,541 --> 00:11:19,244\nlooks a little better to have the four across and five down.\n\n231\n00:11:19,246 --> 00:11:24,015\nOkay? Now you would imagine if I wanted my calculator to work\n\n232\n00:11:24,017 --> 00:11:27,318\nthis way I might have to build fi, four different UIs, one,\n\n233\n00:11:27,320 --> 00:11:30,321\ntwo, three, four. For all four of these. Okay, and\n\n234\n00:11:30,323 --> 00:11:32,657\nthat would normally be the way it is.\n\n235\n00:11:32,659 --> 00:11:35,760\nExcept for that, we actually do size classes with a little\n\n236\n00:11:35,762 --> 00:11:38,797\nmore subtlety than that. Because if you look here,\n\n237\n00:11:38,799 --> 00:11:41,866\ncompact height always is five across and\n\n238\n00:11:41,868 --> 00:11:43,968\nfour down. Whether it's compact width or\n\n239\n00:11:43,970 --> 00:11:45,303\nregular width, doesn't matter. And\n\n240\n00:11:45,305 --> 00:11:48,573\nhere, in regular height, it's always four across,\n\n241\n00:11:48,575 --> 00:11:50,542\nfive down, no matter what the width. So\n\n242\n00:11:50,544 --> 00:11:52,343\nreally I should only have to do two things here,\n\n243\n00:11:52,345 --> 00:11:55,413\nokay, based on the height. I shouldn't have to do anything\n\n244\n00:11:55,415 --> 00:11:59,851\ndifferent based on the width. And that's why the whole size\n\n245\n00:11:59,853 --> 00:12:03,388\nclass thing is actually treated as a grid like this.\n\n246\n00:12:03,390 --> 00:12:05,790\nWith nine things in it and in the middle you\n\n247\n00:12:05,792 --> 00:12:09,894\nhave this special width and height called any. Okay. So\n\n248\n00:12:09,896 --> 00:12:11,996\nnow if I want what I had on the previous screen,\n\n249\n00:12:11,998 --> 00:12:15,900\nall I have to do is two UIs. One for regular height,\n\n250\n00:12:15,902 --> 00:12:19,571\nany width, and one for compact height, any width. And\n\n251\n00:12:19,573 --> 00:12:23,842\neven better than that, I can actually put some of my UI\n\n252\n00:12:23,844 --> 00:12:27,312\nhere in the middle, any height, any width. And\n\n253\n00:12:27,314 --> 00:12:31,483\nonly put the differences out here in these other two. So\n\n254\n00:12:31,485 --> 00:12:34,352\nthis the part of the UI that's the same on both right,\n\n255\n00:12:34,354 --> 00:12:36,855\nI got the display and I've got this part of the keypad.\n\n256\n00:12:36,857 --> 00:12:39,424\nIt's the same on both. And it's only that piece that's\n\n257\n00:12:39,426 --> 00:12:42,527\neither gonna be here or here okay that is different.\n\n258\n00:12:42,529 --> 00:12:45,864\nAnd that's all I'm gonna have to do in these two things. All\n\n259\n00:12:45,866 --> 00:12:49,434\nright? So, we just add this idea of this any width and\n\n260\n00:12:49,436 --> 00:12:53,738\nany height to make a nine way thing. And I, in your story\n\n261\n00:12:53,740 --> 00:12:56,908\nboard, you can actually go to any of these nine squares and\n\n262\n00:12:56,910 --> 00:13:00,411\nedit the UI. Okay? And that's what we're gonna show in our\n\n263\n00:13:00,413 --> 00:13:03,148\ndemo here. Okay? So, I'm gonna do this calculator thing,\n\n264\n00:13:03,150 --> 00:13:05,850\nexactly what I just showed there. And\n\n265\n00:13:05,852 --> 00:13:09,521\nwe'll see what it looks like to the size class business\n\n266\n00:13:09,523 --> 00:13:12,857\nin Xcode. Okay so here we are in calculator.\n\n267\n00:13:12,859 --> 00:13:15,326\nThis is how we left off in calculator.\n\n268\n00:13:15,328 --> 00:13:16,761\nActually it's a little different cuz I this is\n\n269\n00:13:16,763 --> 00:13:18,863\nthe version before we did that save restore. So\n\n270\n00:13:18,865 --> 00:13:21,733\nI don't have save restore. So otherwise it's just a normal\n\n271\n00:13:21,735 --> 00:13:24,702\ncalculator thing here. I'm gonna start right off\n\n272\n00:13:24,704 --> 00:13:28,173\nby noticing that I have this warning up here. You see this,\n\n273\n00:13:28,175 --> 00:13:30,708\nthis yellow triangle that's all over the place here.\n\n274\n00:13:30,710 --> 00:13:32,977\nTelling me about warnings. What are this warnings?\n\n275\n00:13:32,979 --> 00:13:36,181\nIf I click them, it's the old frame will be different at\n\n276\n00:13:36,183 --> 00:13:40,018\nrun time. You guys, I'm sure, are well acquainted with that.\n\n277\n00:13:40,020 --> 00:13:43,188\nThat you get it all the time, when you're doing auto layout\n\n278\n00:13:43,190 --> 00:13:45,824\nstuff. And you know the fix to this? Anyone wanna tell me\n\n279\n00:13:45,826 --> 00:13:50,461\nwhat the fix for this is? What do I do? Go down here,\n\n280\n00:13:50,463 --> 00:13:54,899\nright. Select this view controller. Go down here and\n\n281\n00:13:54,901 --> 00:13:59,637\nsay update frames, right. Okay let's try it.\n\n282\n00:14:00,373 --> 00:14:04,676\nNo. It didn't work. What's going on here? Okay, so\n\n283\n00:14:04,678 --> 00:14:06,978\nhave you seen this? Where you do this update frames and\n\n284\n00:14:06,980 --> 00:14:09,347\nit doesn't work. I'm sure some of you have seen that as well.\n\n285\n00:14:09,349 --> 00:14:12,150\nOkay, well I'm gonna show you another way to fix this, okay,\n\n286\n00:14:12,152 --> 00:14:15,253\nwhich is also not going to work. In the document outline,\n\n287\n00:14:15,255 --> 00:14:16,921\nso here's our document outline right here.\n\n288\n00:14:16,923 --> 00:14:19,524\nYou see this? I told you the document outline is\n\n289\n00:14:19,526 --> 00:14:22,393\nkinda the headquarters for constraints. In fact,\n\n290\n00:14:22,395 --> 00:14:25,396\nhere's all my constraints, okay?\n\n291\n00:14:25,398 --> 00:14:27,966\nLook at this little guy right here, this little button.\n\n292\n00:14:27,968 --> 00:14:31,069\nThis is telling me there's a problem with your constraints.\n\n293\n00:14:31,071 --> 00:14:32,871\nAnd you can actually click on this little button,\n\n294\n00:14:32,873 --> 00:14:36,140\nwhich I'm going to do. And it'll show you all the places,\n\n295\n00:14:36,142 --> 00:14:38,076\nall the misplaced views in this case.\n\n296\n00:14:38,078 --> 00:14:38,810\nIt's going around showing them,\n\n297\n00:14:38,812 --> 00:14:41,813\nI can even highlight them as I mouse over them.\n\n298\n00:14:41,815 --> 00:14:44,582\nAnd you can even fix them, if you click on this little\n\n299\n00:14:44,584 --> 00:14:46,818\ntriangle, right here. It'll come up and\n\n300\n00:14:46,820 --> 00:14:49,787\nyou can do update frames to fix this. You can try and\n\n301\n00:14:49,789 --> 00:14:52,090\nupdate the constraints to match what's here.\n\n302\n00:14:52,092 --> 00:14:55,093\nI recommend against that, generally Because it's gonna\n\n303\n00:14:55,095 --> 00:14:56,728\nput hardwired constraints in there to try and\n\n304\n00:14:56,730 --> 00:14:59,964\nhold that thing in position. That's usually not what you\n\n305\n00:14:59,966 --> 00:15:03,201\nwant. You can also reset to suggested constraints here.\n\n306\n00:15:03,203 --> 00:15:06,070\nThat might be something you want sometimes if you know\n\n307\n00:15:06,072 --> 00:15:07,305\nthat you put it on the blue lines,\n\n308\n00:15:07,307 --> 00:15:09,307\nbut usually you want to try and update frames.\n\n309\n00:15:09,309 --> 00:15:11,309\nAnd you can even apply it too all the views in\n\n310\n00:15:11,311 --> 00:15:14,145\nthe container, cuz we know we got five problems right here.\n\n311\n00:15:14,147 --> 00:15:17,849\nSo, I can click those and hit fix displacement here, and\n\n312\n00:15:17,851 --> 00:15:22,253\nthat should fix it. Nope, it didn't, okay. Now, I'm not\n\n313\n00:15:22,255 --> 00:15:25,723\nexactly sure why those either of those things didn't fix it.\n\n314\n00:15:25,725 --> 00:15:29,027\nIt should've. But I'm gonna show you a tricky way,\n\n315\n00:15:29,029 --> 00:15:31,496\nto fix this misplacement problem.\n\n316\n00:15:31,498 --> 00:15:34,032\nWould you just pick up something, okay,\n\n317\n00:15:34,034 --> 00:15:37,368\nthat's misplaced like this, and just put it back down\n\n318\n00:15:37,370 --> 00:15:42,507\nwhere you think it's supposed to be. Okay? Voila, okay?\n\n319\n00:15:42,509 --> 00:15:42,674\nsome reason that causes the entire constraint system to\n\n320\n00:15:42,676 --> 00:15:45,610\nBecause for\n\n321\n00:15:45,612 --> 00:15:48,746\nreevaluate everything's in the right spot, no issues, see?\n\n322\n00:15:48,748 --> 00:15:52,450\nNo auto layout issues here, no yellow buttons up here. Okay?\n\n323\n00:15:52,452 --> 00:15:55,019\nSo that's a real nice little trick to know, okay?\n\n324\n00:15:55,021 --> 00:15:59,657\nJust pick the thing up and put it back down in the right\n\n325\n00:15:59,659 --> 00:16:03,861\nplace, might fix everything All right, okay.\n\n326\n00:16:03,863 --> 00:16:07,432\nSo let's talk about our calculator here.\n\n327\n00:16:07,434 --> 00:16:10,868\nOur calculator wants to use size classes so that instead\n\n328\n00:16:10,870 --> 00:16:14,072\nof being four across and five down like this, okay, in\n\n329\n00:16:14,074 --> 00:16:18,209\ncompact situations, it's gonna be five across and four down.\n\n330\n00:16:18,211 --> 00:16:21,512\nSo I told you there's those nine little spots?\n\n331\n00:16:21,514 --> 00:16:23,214\nHere they are, right here, right down at the bottom.\n\n332\n00:16:23,216 --> 00:16:27,552\nSee this W Any H Any? That tells you you're editing with\n\n333\n00:16:27,554 --> 00:16:30,455\nany height, any. And if you click on this,\n\n334\n00:16:30,457 --> 00:16:33,524\nit'll show you all nine of those areas, okay?\n\n335\n00:16:33,526 --> 00:16:37,328\nJust mouse over them. So the middle one is any, any, okay.\n\n336\n00:16:37,330 --> 00:16:41,199\nUp here, this is compact height, any width.\n\n337\n00:16:41,201 --> 00:16:45,336\nThis down here is regular height, any width, okay?\n\n338\n00:16:45,338 --> 00:16:48,072\nHere is compact width, compact height.\n\n339\n00:16:48,074 --> 00:16:50,341\nSo if I were to click on this and\n\n340\n00:16:50,343 --> 00:16:56,014\ngo edit that UI, what device would this, that ui be on?\n\n341\n00:16:56,016 --> 00:16:56,781\n>> iPhone 6.\n\n342\n00:16:56,783 --> 00:16:56,848\n>> iPhone 6,\n\n343\n00:16:56,850 --> 00:17:00,852\nin landscape, right? Or iPhone 5 in landscape also, okay?\n\n344\n00:17:00,854 --> 00:17:01,853\nCuz that's the only one that's compact. So\n\n345\n00:17:01,855 --> 00:17:06,557\nthis is actually specifically choosing a non-plus iPhone,\n\n346\n00:17:06,559 --> 00:17:09,527\nokay? So you can pick any of these positions that you want.\n\n347\n00:17:09,529 --> 00:17:13,931\nNow we know in our calculator that the compact height, one,\n\n348\n00:17:13,933 --> 00:17:18,036\nokay, is the one that we wanna move these buttons down to\n\n349\n00:17:18,038 --> 00:17:21,172\nthe side over here. Okay, here's a compact height.\n\n350\n00:17:21,174 --> 00:17:24,409\nNow, I'm gonna show you a feature here that you might\n\n351\n00:17:24,411 --> 00:17:26,577\nbe inclined to use with size classes,\n\n352\n00:17:26,579 --> 00:17:28,079\nbut it's not gonna work for us.\n\n353\n00:17:28,081 --> 00:17:31,215\nOkay, but I wanna show you how it works, which is,\n\n354\n00:17:31,217 --> 00:17:34,786\nI might just start by saying let's at first, at least get\n\n355\n00:17:34,788 --> 00:17:38,856\nrid of these four buttons when we're in this compact version,\n\n356\n00:17:38,858 --> 00:17:41,659\nokay? See here we're in width any, height compact. We're\n\n357\n00:17:41,661 --> 00:17:45,296\nediting this UI. Changes that we make in here are only going\n\n358\n00:17:45,298 --> 00:17:49,700\nto apply to this size class, okay, which is compact height.\n\n359\n00:17:49,702 --> 00:17:51,035\nAny time we're in a compact height.\n\n360\n00:17:51,037 --> 00:17:53,538\nNow, we can only make certain changes in here, like,\n\n361\n00:17:53,540 --> 00:17:56,040\nwe couldn't inspect objects and change their color.\n\n362\n00:17:56,042 --> 00:17:59,143\nThat's not gonna work. But we can remove and add views,\n\n363\n00:17:59,145 --> 00:18:03,247\nand most importantly, we can change constraints, okay?\n\n364\n00:18:03,249 --> 00:18:03,881\nThose are the things we can do.\n\n365\n00:18:03,883 --> 00:18:06,484\nSo I said we can remove and add views, how would we remove\n\n366\n00:18:06,486 --> 00:18:09,320\nthis stack view? Let's say we don't want this x divide plus\n\n367\n00:18:09,322 --> 00:18:11,522\nminus stack here, we just don't want it in there.\n\n368\n00:18:11,524 --> 00:18:13,291\nWell, we can go over to the Inspector, okay, and\n\n369\n00:18:13,293 --> 00:18:16,294\ninspect this thing. And look down at the very bottom, okay?\n\n370\n00:18:16,296 --> 00:18:18,029\nThis is just the Inspector for the stack view.\n\n371\n00:18:18,031 --> 00:18:21,599\nAnd the bottom, it says right here, Installed with a check.\n\n372\n00:18:21,601 --> 00:18:26,070\nThat means it's installed in all size classes.\n\n373\n00:18:26,072 --> 00:18:28,973\nAnd if we didn't want it installed in this one,\n\n374\n00:18:28,975 --> 00:18:31,375\nwe can actually click this little plus, and\n\n375\n00:18:31,377 --> 00:18:34,812\npick this size class, which is with any height compact,\n\n376\n00:18:34,814 --> 00:18:38,549\nor we could actually pick any other one we wanted, okay?\n\n377\n00:18:38,551 --> 00:18:41,185\nSo we can pick any combination we want.\n\n378\n00:18:41,187 --> 00:18:42,687\nSince this is the one we're editing, it's,\n\n379\n00:18:42,689 --> 00:18:44,455\nthe kind of the first choice right here, any width,\n\n380\n00:18:44,457 --> 00:18:47,692\ncompact, height. So I'm gonna pick that. And when I pick\n\n381\n00:18:47,694 --> 00:18:50,795\nthat, it breaks that one out. It's still installed, but\n\n382\n00:18:50,797 --> 00:18:52,830\nit breaks that one out with any height compact.\n\n383\n00:18:52,832 --> 00:18:56,868\nBut if I click this off, it will no longer install this\n\n384\n00:18:56,870 --> 00:19:00,371\nview in this size class. So now anytime I'm running in\n\n385\n00:19:00,373 --> 00:19:03,407\na modern environment where it's compact, that view,\n\n386\n00:19:03,409 --> 00:19:06,444\nthat stack view's not even gonna be there. Okay,\n\n387\n00:19:06,446 --> 00:19:11,015\nif I go back to any any here, it's still there,\n\n388\n00:19:11,017 --> 00:19:15,753\nokay. It's only in this compact height that it's gone.\n\n389\n00:19:15,755 --> 00:19:20,758\nSo let's go run and see if this is working for us.\n\n390\n00:19:26,900 --> 00:19:29,167\nAll right, here we go. It's five high and\n\n391\n00:19:29,169 --> 00:19:32,603\nfour wide in portrait. Looks good, okay. Hopefully,\n\n392\n00:19:32,605 --> 00:19:35,506\nif we go to landscape, which we know is compact height,\n\n393\n00:19:35,508 --> 00:19:39,243\nit should get rid of those four buttons, right? It did!\n\n394\n00:19:39,245 --> 00:19:41,712\nExcellent, see, this size class stuff works.\n\n395\n00:19:41,714 --> 00:19:45,683\nAnd now we'll just go back over to portrait. Oops, okay,\n\n396\n00:19:45,685 --> 00:19:49,720\nlook what happened there. When I went back to portrait,\n\n397\n00:19:49,722 --> 00:19:53,124\nit tried to put that stack view back, but the size class\n\n398\n00:19:53,126 --> 00:19:57,128\nsystem can't put things back into other view hierarchies,\n\n399\n00:19:57,130 --> 00:19:59,430\nyou can only put it back at the top level.\n\n400\n00:19:59,432 --> 00:20:02,934\nSo it couldn't do that, so it decided to put it back, and\n\n401\n00:20:02,936 --> 00:20:05,436\njust put it back as 0,0 up there, okay?\n\n402\n00:20:05,438 --> 00:20:07,338\nSo that's clearly not what we want,\n\n403\n00:20:07,340 --> 00:20:08,673\nthat's clearly not gonna work. So\n\n404\n00:20:08,675 --> 00:20:12,276\nwe need a different strategy, but I just wanted to show you\n\n405\n00:20:12,278 --> 00:20:15,713\nthere is this feature where you can use this mechanism to\n\n406\n00:20:15,715 --> 00:20:19,417\ndecide that certain views exist in certain places, okay?\n\n407\n00:20:19,419 --> 00:20:21,919\nAnd you're gonna see this is gonna automatically happen\n\n408\n00:20:21,921 --> 00:20:24,855\nwhen we start putting views in different kinds of views,\n\n409\n00:20:24,857 --> 00:20:26,591\nvertical stack views and things like that.\n\n410\n00:20:26,593 --> 00:20:29,193\nYou'll see that this will automatically be happening for\n\n411\n00:20:29,195 --> 00:20:32,930\nus. So I'm gonna undo here, get that thing back, okay?\n\n412\n00:20:32,932 --> 00:20:38,302\nSo let's get this back in our width any horizontal compact.\n\n413\n00:20:38,304 --> 00:20:38,769\nSo that's not gonna work.\n\n414\n00:20:38,771 --> 00:20:42,807\nSo what could we do instead? All right, well, since I\n\n415\n00:20:42,809 --> 00:20:46,310\nknow I can't have this thing inside this stack view, right,\n\n416\n00:20:46,312 --> 00:20:49,380\nworking, I'm gonna have to pull it out. I'm gonna have to\n\n417\n00:20:49,382 --> 00:20:51,916\npull all of these things out of the stack view. So let's\n\n418\n00:20:51,918 --> 00:20:55,353\njust do that, okay? I'm just going to move this thing. And\n\n419\n00:20:55,355 --> 00:20:57,588\nactually, you know what? I'm gonna do all this in any any.\n\n420\n00:20:57,590 --> 00:21:01,158\nBecause when I think about it, I can't have this here in any\n\n421\n00:21:01,160 --> 00:21:04,195\nany, otherwise, it's always gonna appear there.\n\n422\n00:21:04,197 --> 00:21:07,531\nOkay, in other ones, and I don't want it there,\n\n423\n00:21:07,533 --> 00:21:08,466\non the top in compact, so\n\n424\n00:21:08,468 --> 00:21:12,036\nI'm gonna take this whole stack view right here, okay?\n\n425\n00:21:12,038 --> 00:21:14,905\nThis one, the one that I don't want here, and\n\n426\n00:21:14,907 --> 00:21:18,976\nI'm going to just delete it, hit cut to delete it. Okay, so\n\n427\n00:21:18,978 --> 00:21:21,779\nnow in the any any, that means on all size classes,\n\n428\n00:21:21,781 --> 00:21:25,616\nthat thing is gone. It's not there. And what's more,\n\n429\n00:21:25,618 --> 00:21:28,252\nI'm going to take this stack view right here, and\n\n430\n00:21:28,254 --> 00:21:29,687\nI'm gonna pull the things out of it.\n\n431\n00:21:29,689 --> 00:21:33,491\nSo for example, I'm gonna pull the display out of it, okay,\n\n432\n00:21:33,493 --> 00:21:36,460\nI'm gonna take this inner stack view right here and\n\n433\n00:21:36,462 --> 00:21:39,897\npull it out, leaving this empty stack view, okay? Which\n\n434\n00:21:39,899 --> 00:21:43,668\nwe don't even need anymore, so I'm gonna delete it, okay?\n\n435\n00:21:43,670 --> 00:21:48,539\nSo now, this is all part of all size classes,\n\n436\n00:21:48,541 --> 00:21:52,643\nright? This is in all size classes. In the compact case,\n\n437\n00:21:52,645 --> 00:21:57,048\nit's this with buttons down here. And in the regular case,\n\n438\n00:21:57,050 --> 00:22:00,851\nit's this with some buttons along here. We all agree with\n\n439\n00:22:00,853 --> 00:22:04,789\nthat? So in any any, we always wanna build as much of the UI\n\n440\n00:22:04,791 --> 00:22:08,859\nas we can that we know applies to all size classes, okay?\n\n441\n00:22:08,861 --> 00:22:11,696\nSo this one, we know that this is gonna go\n\n442\n00:22:11,698 --> 00:22:14,732\nin the corner down here, right? And\n\n443\n00:22:14,734 --> 00:22:19,103\nwe also know that this goes up at the top,\n\n444\n00:22:19,105 --> 00:22:23,107\nright? And we can even do the constraints here, or at\n\n445\n00:22:23,109 --> 00:22:26,877\nleast some of the constraints. I'm gonna go down here and\n\n446\n00:22:26,879 --> 00:22:30,381\nreset all of our constraints by picking Clear Constraints\n\n447\n00:22:30,383 --> 00:22:33,084\nin the same place you Update Frames and all that.\n\n448\n00:22:33,086 --> 00:22:36,120\nI'm gonna Clear Constraints to get all these constraints out\n\n449\n00:22:36,122 --> 00:22:38,656\nof here, and now I'm gonna put new constraints in.\n\n450\n00:22:38,658 --> 00:22:41,258\nNow this part is exactly what you're used to,\n\n451\n00:22:41,260 --> 00:22:44,128\nI'm just going to Ctrl + Drag to the edge here and\n\n452\n00:22:44,130 --> 00:22:47,832\nhook up that trailing space. I'm gonna Ctrl + Drag to\n\n453\n00:22:47,834 --> 00:22:50,801\nthe bottom down here, okay, at the bottom.\n\n454\n00:22:50,803 --> 00:22:55,573\nI'm gonna, for the display up here, Ctrl + Drag to the top,\n\n455\n00:22:55,575 --> 00:22:58,142\nCtrl + Drag to the leading edge, okay?\n\n456\n00:22:58,144 --> 00:23:03,013\nCtrl + Drag to the right edge, okay? So look, no errors,\n\n457\n00:23:03,015 --> 00:23:06,016\nno auto-layout issues over here in my document outline.\n\n458\n00:23:06,018 --> 00:23:08,919\nNo little yellow thing, so everything is perfectly fine.\n\n459\n00:23:08,921 --> 00:23:10,588\nI can even run right now. Let's run and\n\n460\n00:23:10,590 --> 00:23:17,495\nsee what happens. Okay, so here it is in portrait. Okay,\n\n461\n00:23:17,497 --> 00:23:20,398\nit's doing what we want, which is this down in the corner,\n\n462\n00:23:20,400 --> 00:23:20,998\nthis up here. Of course,\n\n463\n00:23:21,000 --> 00:23:23,868\nI haven't added the buttons that I want right here.\n\n464\n00:23:23,870 --> 00:23:26,470\nAnd how about in landscape? It's working here too.\n\n465\n00:23:26,472 --> 00:23:29,140\nOf course, I haven't added the buttons here, all right?\n\n466\n00:23:29,142 --> 00:23:31,275\nSo it's putting the display in the right space.\n\n467\n00:23:31,277 --> 00:23:33,010\nIt's keeping these buttons over in the corner.\n\n468\n00:23:33,012 --> 00:23:37,882\nSo this is great, okay? It's all working fine so far.\n\n469\n00:23:37,884 --> 00:23:41,385\nNow let's go and fix the two size classes. So let's start\n\n470\n00:23:41,387 --> 00:23:44,422\nwith compact height, okay. In compact type, actually let's\n\n471\n00:23:44,424 --> 00:23:46,290\nstart with regular height cuz it's the similar,\n\n472\n00:23:46,292 --> 00:23:47,725\nthe most similar to the other one we have.\n\n473\n00:23:47,727 --> 00:23:50,227\nSo here's regular height. Unfortunately, it's so\n\n474\n00:23:50,229 --> 00:23:52,730\nbig I have to scroll up and down, but in this one,\n\n475\n00:23:52,732 --> 00:23:55,266\nwe basically just want to put, take these things.\n\n476\n00:23:55,268 --> 00:23:57,435\nI just pasted them back, I had cut them before, and\n\n477\n00:23:57,437 --> 00:24:01,972\nwe just to put it right here. Okay, right along the top.\n\n478\n00:24:01,974 --> 00:24:03,274\nNow the problem here though,\n\n479\n00:24:03,276 --> 00:24:06,243\nis that we need to put some constraints to make it be\n\n480\n00:24:06,245 --> 00:24:10,114\nthe same as the rest of those buttons in the stack view.\n\n481\n00:24:10,116 --> 00:24:13,317\nRight? So, how are we gonna do that? Well there's a couple\n\n482\n00:24:13,319 --> 00:24:14,752\nof different ways that we can do it.\n\n483\n00:24:14,754 --> 00:24:16,954\n1. Is with these menus down here I told you about so\n\n484\n00:24:16,956 --> 00:24:22,126\nI'm gonna select this one so these two views are selected,\n\n485\n00:24:22,128 --> 00:24:24,228\nthis whole big stack view here, and\n\n486\n00:24:24,230 --> 00:24:26,163\nthis stack view here. And we're gonna go down here, and\n\n487\n00:24:26,165 --> 00:24:29,967\nwe're gonna look at these alignment and pin menus. So\n\n488\n00:24:29,969 --> 00:24:33,938\nhere's an alignment one. We can do thing here to, for\n\n489\n00:24:33,940 --> 00:24:37,842\nexample, align the edges of these things. So it might make\n\n490\n00:24:37,844 --> 00:24:41,412\na lot of sense to take this guy and have his leading and\n\n491\n00:24:41,414 --> 00:24:44,949\ntrailing edges aligned with this one, right? So\n\n492\n00:24:44,951 --> 00:24:47,284\nlet's try that I'm just going to turn on leading and\n\n493\n00:24:47,286 --> 00:24:48,986\ntrailing edges here to align those.\n\n494\n00:24:48,988 --> 00:24:51,155\nI could also align things like the horizontal center,\n\n495\n00:24:51,157 --> 00:24:55,926\nvertical centers, I could horizontally in the containers\n\n496\n00:24:55,928 --> 00:24:58,929\ncentered in the container etcetera. But I'm going to do\n\n497\n00:24:58,931 --> 00:25:01,799\nit, but also notice it's going to align the leading edges\n\n498\n00:25:01,801 --> 00:25:05,369\nwith no delta. It's just like right along the leading edge.\n\n499\n00:25:05,371 --> 00:25:07,705\nSo I'm going to add those two constraints. Okay.\n\n500\n00:25:07,707 --> 00:25:08,439\nIt's added the constraints.\n\n501\n00:25:08,441 --> 00:25:11,275\nNow what's interesting here is now these\n\n502\n00:25:11,277 --> 00:25:14,545\nconstraint complaints are red not yellow red.\n\n503\n00:25:14,547 --> 00:25:17,381\nAnd why is that? Okay, let's go over here and look at this.\n\n504\n00:25:17,383 --> 00:25:20,217\nAnd it says vertical position is ambiguous for\n\n505\n00:25:20,219 --> 00:25:24,488\nstack view, okay? It says it over here as well in my docu-,\n\n506\n00:25:24,490 --> 00:25:24,655\nno-, outline.\n\n507\n00:25:24,657 --> 00:25:28,125\nIt's saying this guy has no vertical position to find. And\n\n508\n00:25:28,127 --> 00:25:30,995\nin fact, that's true. There, it's just floating there.\n\n509\n00:25:30,997 --> 00:25:33,063\nThere's nothing that says where it is vertically.\n\n510\n00:25:33,065 --> 00:25:34,598\nWe've defined where it is horizontally,\n\n511\n00:25:34,600 --> 00:25:36,834\nbut we haven't defined where it is vertically. So\n\n512\n00:25:36,836 --> 00:25:40,838\nto do that, I'm gonna re-, go back to our Ctrl-drag, okay?\n\n513\n00:25:40,840 --> 00:25:43,107\nSo I'm just gonna Ctrl-drag from this one to this one,\n\n514\n00:25:43,109 --> 00:25:46,977\nand this time, I'm gonna put Vertical spacing, okay?\n\n515\n00:25:46,979 --> 00:25:50,114\nNow he's got vertical spacing, so now his problem's right\n\n516\n00:25:50,116 --> 00:25:53,684\nhere, are just the frames are not, are wrong, okay. And\n\n517\n00:25:53,686 --> 00:25:56,954\nagain, I could pick up this thing right here and try and\n\n518\n00:25:56,956 --> 00:26:00,324\nput it there. I can take this, put it down here, you know,\n\n519\n00:26:00,326 --> 00:26:01,125\ntry and move things back or\n\n520\n00:26:01,127 --> 00:26:04,161\nI could do update frames, but we're not done yet\n\n521\n00:26:04,163 --> 00:26:08,299\neither with this. Because there we fix the width\n\n522\n00:26:08,301 --> 00:26:11,268\nto be the same width as this cuz we align the edges but\n\n523\n00:26:11,270 --> 00:26:14,572\nwhat about the height, okay. We need the height of this row\n\n524\n00:26:14,574 --> 00:26:17,241\nto be exactly the same height as all these rows. And\n\n525\n00:26:17,243 --> 00:26:21,378\nit's perfectly legal for us to do that by going control drag,\n\n526\n00:26:21,380 --> 00:26:24,515\nokay, from this guy down to this guy. And\n\n527\n00:26:24,517 --> 00:26:28,118\nthen saying that we want them to be equal heights.\n\n528\n00:26:28,120 --> 00:26:31,589\nOkay? See that Equal Heights? Okay, so\n\n529\n00:26:31,591 --> 00:26:36,060\nnow they're gonna be equal heights. So you see how we've\n\n530\n00:26:36,062 --> 00:26:38,996\nput this thing basically and really stack view does a very\n\n531\n00:26:38,998 --> 00:26:41,131\nsimilar thing to what we're doing right here, okay,.\n\n532\n00:26:41,133 --> 00:26:43,367\nWhen you said all things like fill and fill equally,\n\n533\n00:26:43,369 --> 00:26:45,502\nit's making equal heights and all that stuff.\n\n534\n00:26:45,504 --> 00:26:45,736\nBut unfortunately,\n\n535\n00:26:45,738 --> 00:26:49,206\nwe had to move this stack view out because it doesn't exist,\n\n536\n00:26:49,208 --> 00:26:52,843\nin some of the size classes. All right, so\n\n537\n00:26:52,845 --> 00:26:53,143\nwe're not quite done,\n\n538\n00:26:53,145 --> 00:26:55,713\nbecause we still want this thing to fill the whole space,\n\n539\n00:26:55,715 --> 00:26:59,116\nright? We want this nice block that we've built to fill this\n\n540\n00:26:59,118 --> 00:27:02,219\nwhole space. So I'm gonna do exact same thing we did\n\n541\n00:27:02,221 --> 00:27:05,389\nbefore which is control drag okay from the edge of this.\n\n542\n00:27:05,391 --> 00:27:08,025\nAnd make it leading space, right be fixed here.\n\n543\n00:27:08,027 --> 00:27:10,728\nI'm gonna double click on it, try to make it standard.\n\n544\n00:27:10,730 --> 00:27:15,332\nThat's not available so I'll go zero. Okay, makes it wide.\n\n545\n00:27:15,334 --> 00:27:15,666\nAnd same thing here.\n\n546\n00:27:15,668 --> 00:27:17,134\nI wanna make the distance between here and\n\n547\n00:27:17,136 --> 00:27:20,838\nhere be a standard distance so let's do that. Control drag.\n\n548\n00:27:20,840 --> 00:27:24,308\nAnd down to here and this is the vertical spacing right\n\n549\n00:27:24,310 --> 00:27:27,544\nhere. Okay, which makes this beam. Double click on that\n\n550\n00:27:27,546 --> 00:27:30,481\nand of course when we click on it it's also showing over here\n\n551\n00:27:30,483 --> 00:27:31,382\nnot just in this little window, but\n\n552\n00:27:31,384 --> 00:27:35,285\nit's over here as well. And here standard is available.\n\n553\n00:27:35,287 --> 00:27:38,689\nOkay, so we can do standard height. Okay, so\n\n554\n00:27:38,691 --> 00:27:42,393\nthis looks pretty good. In the regular height situation,\n\n555\n00:27:42,395 --> 00:27:45,129\nwe've got four wide and five high.\n\n556\n00:27:45,131 --> 00:27:52,703\nSo let's go into run, see if it worked. All right,\n\n557\n00:27:52,705 --> 00:27:54,371\nhere it is, four wide and five high. Okay,\n\n558\n00:27:54,373 --> 00:27:58,208\nlet's go to landscape. Perfect we don't want four wide and\n\n559\n00:27:58,210 --> 00:28:00,844\nfive high there so we're just getting the any any\n\n560\n00:28:00,846 --> 00:28:05,516\nsituation right back to here and is back. Okay so\n\n561\n00:28:05,518 --> 00:28:08,318\nit's working fine. And now, what we need to do is the same\n\n562\n00:28:08,320 --> 00:28:11,488\nthing we just did for regular for compact. Okay so\n\n563\n00:28:11,490 --> 00:28:15,426\nlet's go to that we do that by going to this little nine grid\n\n564\n00:28:15,428 --> 00:28:18,862\nhere we're going up to compact height any width. And\n\n565\n00:28:18,864 --> 00:28:22,099\nhere we want that same thing right here,\n\n566\n00:28:22,101 --> 00:28:24,435\nbut this time this has to be vertical. Okay.\n\n567\n00:28:24,437 --> 00:28:26,870\nSo I'm just gonna go to the stack views inspector.\n\n568\n00:28:26,872 --> 00:28:27,871\nHere's the stack view inspecting it.\n\n569\n00:28:27,873 --> 00:28:31,275\nAnd I'm gonna make it vertical this time. Okay?\n\n570\n00:28:31,277 --> 00:28:34,278\nAnd I want to put it along here. Okay?\n\n571\n00:28:34,280 --> 00:28:36,847\nSo I'm gonna use control drag to do it this time and\n\n572\n00:28:36,849 --> 00:28:40,784\nI can actually set up most of this using shift in here.\n\n573\n00:28:40,786 --> 00:28:43,420\nI think I told you before when this comes up You can actually\n\n574\n00:28:43,422 --> 00:28:47,024\nclick multiple things, okay, with shift. So I can make it,\n\n575\n00:28:47,026 --> 00:28:51,495\nfor example, the horizontal spacing, the top, the bottom.\n\n576\n00:28:51,497 --> 00:28:53,697\nI can line those all up. Okay? Now,\n\n577\n00:28:53,699 --> 00:28:55,899\nI don't actually want this to be equal widths, because I\n\n578\n00:28:55,901 --> 00:28:58,335\ndon't want this to be the same width as this whole thing.\n\n579\n00:28:58,337 --> 00:29:00,170\nSo, I'm going to have to do equal widths,\n\n580\n00:29:00,172 --> 00:29:03,540\nby making this the same width as one of these buttons. Okay.\n\n581\n00:29:03,542 --> 00:29:06,110\nSo we do that to set those. So I'm gonna Control drag\n\n582\n00:29:06,112 --> 00:29:07,711\nfrom here to one of these buttons and\n\n583\n00:29:07,713 --> 00:29:11,181\ndo Equal Widths, okay, so that this will be the same width.\n\n584\n00:29:11,183 --> 00:29:14,718\nOf course, we've got this whole frames are wrong,\n\n585\n00:29:14,720 --> 00:29:16,086\nso this time, just to be different,\n\n586\n00:29:16,088 --> 00:29:17,955\nI'll go up here and click one of these and\n\n587\n00:29:17,957 --> 00:29:22,292\napply to all views in container. Fix it. Okay. So\n\n588\n00:29:22,294 --> 00:29:24,194\nnow, we've got it there where we want it. Again,\n\n589\n00:29:24,196 --> 00:29:28,465\nsame thing here. We want to put a vertical spacing\n\n590\n00:29:28,467 --> 00:29:32,970\nconstraint here. Okay, we'll do standard if available,\n\n591\n00:29:32,972 --> 00:29:37,841\nyep. Okay, and same thing over here. We will put this to\n\n592\n00:29:37,843 --> 00:29:43,113\nthe leading edge and again, no standard. Sorry,\n\n593\n00:29:43,115 --> 00:29:49,186\nso we'll do zero. Okay, there we go. We've got five wide,\n\n594\n00:29:49,188 --> 00:29:53,590\nfour high in this compact situation, all right?\n\n595\n00:29:53,592 --> 00:29:59,596\nSo let's run that. Okay,\n\n596\n00:29:59,598 --> 00:30:02,499\nhere it is, portrait, looking good, landscape,\n\n597\n00:30:02,501 --> 00:30:07,037\nlooking good. Okay,\n\n598\n00:30:07,606 --> 00:30:11,809\nany questions about that? Make sense? All right, now I wanna\n\n599\n00:30:11,811 --> 00:30:15,012\nshow you a couple of things about what we've wrought here.\n\n600\n00:30:15,014 --> 00:30:18,182\nOne thing is let's look at this stack view right here.\n\n601\n00:30:18,184 --> 00:30:21,285\nLook at it's installed state down there. See that?\n\n602\n00:30:21,287 --> 00:30:25,823\nIt's not installed in any any. It's only installed in any\n\n603\n00:30:25,825 --> 00:30:28,559\nwith compact height. That's exactly what we want. So\n\n604\n00:30:28,561 --> 00:30:31,862\nsee how it automatically did this when we pasted this one\n\n605\n00:30:31,864 --> 00:30:35,132\nin? Any time we add a view to the size class, it's going to\n\n606\n00:30:35,134 --> 00:30:39,036\nautomatically do this install magic for you here. Okay?\n\n607\n00:30:39,038 --> 00:30:42,472\nNow another think I told you was that the document outline\n\n608\n00:30:42,474 --> 00:30:44,942\nis kind of your constraint central. Okay?\n\n609\n00:30:44,944 --> 00:30:47,711\nSo let's understand what the document outline is telling us\n\n610\n00:30:47,713 --> 00:30:52,649\nabout constraints here okay? Here's all our constraints and\n\n611\n00:30:52,651 --> 00:30:54,985\nnotice that some of them are grayed out and\n\n612\n00:30:54,987 --> 00:30:57,654\nsome of them are dark blue. See that?\n\n613\n00:30:57,656 --> 00:31:00,157\nWell, as you might imagine the grayed out ones\n\n614\n00:31:00,159 --> 00:31:03,327\nare constraints that only apply in other size classes.\n\n615\n00:31:03,329 --> 00:31:06,363\nThat don't apply here. So since this is any width\n\n616\n00:31:06,365 --> 00:31:09,499\ncompact height, we're not seeing any of the constraints\n\n617\n00:31:09,501 --> 00:31:12,870\nthat have to do with any width regular heigth.\n\n618\n00:31:12,872 --> 00:31:13,136\nif I switch over okay watch these carefully right here.\n\n619\n00:31:13,138 --> 00:31:14,972\nOkay? But,\n\n620\n00:31:14,974 --> 00:31:17,174\nYou're gonna see some of these are gonna go like right and\n\n621\n00:31:17,176 --> 00:31:19,309\nsome of these are gonna go dark blue. Okay.\n\n622\n00:31:19,311 --> 00:31:23,780\nSo I'm gonna switch down here to any width, regular height.\n\n623\n00:31:23,782 --> 00:31:25,215\nWhich has different constraints.\n\n624\n00:31:25,217 --> 00:31:27,651\nYou see how this changed? So you can always tell\n\n625\n00:31:27,653 --> 00:31:31,421\nwhich ones apply to you, okay, by which ones are dark.\n\n626\n00:31:31,423 --> 00:31:35,025\nNow another thing you wanna do when you are using constraints\n\n627\n00:31:35,027 --> 00:31:39,296\nis to go magic number hunting. Okay. You want to look at\n\n628\n00:31:39,298 --> 00:31:41,732\nthese constraints and hunt for magic numbers and\n\n629\n00:31:41,734 --> 00:31:45,802\nget rid of them. Unless you really mean to have one. Okay,\n\n630\n00:31:45,804 --> 00:31:49,640\nvery important. So in here let's find some magic numbers.\n\n631\n00:31:49,642 --> 00:31:53,610\nOkay. Here's one, 8, here's 282, 82,\n\n632\n00:31:53,612 --> 00:31:58,181\n88 and 20. So those are all of our magic numbers right there.\n\n633\n00:31:58,183 --> 00:32:01,118\nFirst thing you wanna do is, only you can only hunt for\n\n634\n00:32:01,120 --> 00:32:04,321\nmagic numbers in the ones that are dark blue. Okay,\n\n635\n00:32:04,323 --> 00:32:08,725\nyou can£t, these 282 is in some other constraint in some\n\n636\n00:32:08,727 --> 00:32:12,396\nother size class, so just ignore it here. It£s like\n\n637\n00:32:12,398 --> 00:32:15,966\nyou£re not even seeing it. But this eight right here, okay?\n\n638\n00:32:15,968 --> 00:32:19,236\nThis is the one we do need to look at, okay? Cuz we just\n\n639\n00:32:19,238 --> 00:32:21,905\ndon't want this magic number here. So what is this one?\n\n640\n00:32:21,907 --> 00:32:25,976\nThis is the display's top to the top layout guide's bottom.\n\n641\n00:32:25,978 --> 00:32:28,812\nIt's this one right here. Okay, so that's eight.\n\n642\n00:32:28,814 --> 00:32:32,783\nOkay, let's go ahead and inspect this. We're inspecting\n\n643\n00:32:32,785 --> 00:32:35,452\nthis constraint. And you can see that it's 8 and\n\n644\n00:32:35,454 --> 00:32:38,522\nreally what you wanna change that to is standard value.\n\n645\n00:32:38,524 --> 00:32:40,590\nAnd when you change that to standard value, look.\n\n646\n00:32:40,592 --> 00:32:43,894\nThe eight's gone, okay? Now you might ask,\n\n647\n00:32:43,896 --> 00:32:45,362\nwhere did that eight come in in the first place?\n\n648\n00:32:45,364 --> 00:32:48,899\nWell probably we dragged that thing to, and used a blue line\n\n649\n00:32:48,901 --> 00:32:52,736\nto do, to put it there. And it was eight points from the top.\n\n650\n00:32:52,738 --> 00:32:54,871\nAnd so when we added constraint,\n\n651\n00:32:54,873 --> 00:32:58,075\nit added it as eight. But what we really wanted was standard\n\n652\n00:32:58,077 --> 00:33:00,510\ndistance. Okay, how about this one right here?\n\n653\n00:33:00,512 --> 00:33:03,313\nThis is the stack view's top to the stack view bottom.\n\n654\n00:33:03,315 --> 00:33:06,984\nThat's this one right here. Okay, uh-oh, [LAUGH] that one\n\n655\n00:33:06,986 --> 00:33:11,655\nis a magic number, but that's the wrong magic number.\n\n656\n00:33:11,657 --> 00:33:14,558\nBecause what is the distance in all these other things.\n\n657\n00:33:14,560 --> 00:33:16,860\nIn this stack view, what's the spacing?\n\n658\n00:33:16,862 --> 00:33:20,464\nIt's ten, remember that? Okay? So, we want the space in\n\n659\n00:33:20,466 --> 00:33:24,001\nbetween these two stack views to also be ten. Okay? So\n\n660\n00:33:24,003 --> 00:33:26,169\nthis constant wants to be a magic number and\n\n661\n00:33:26,171 --> 00:33:29,406\nit wants to be ten, and it truly is a magic number. Okay?\n\n662\n00:33:29,408 --> 00:33:30,140\nSo we want that magic number,\n\n663\n00:33:30,142 --> 00:33:33,377\nbecause we intended it to be a magic number.\n\n664\n00:33:33,379 --> 00:33:36,179\nAll right? How about this one? 20.\n\n665\n00:33:36,181 --> 00:33:38,782\nOkay, stack view bottom right here. That one also,\n\n666\n00:33:38,784 --> 00:33:42,386\nwe probably don't want that to be a non-standard value, so\n\n667\n00:33:42,388 --> 00:33:45,689\nI'm just gonna pick Standard Value, okay?\n\n668\n00:33:45,691 --> 00:33:49,726\nAnd we'll do the same thing in our other size classes,\n\n669\n00:33:49,728 --> 00:33:52,195\nso we'll go here. This one right here has\n\n670\n00:33:52,197 --> 00:33:54,297\nthis Stack View.leading to Stack View.trailing,\n\n671\n00:33:54,299 --> 00:33:56,600\nthat's right here, see it highlighted right there?\n\n672\n00:33:56,602 --> 00:34:00,437\nThat wants to be ten. What else have we got here?\n\n673\n00:34:00,439 --> 00:34:02,773\nAnything else? No? All the rest of these are good?\n\n674\n00:34:02,775 --> 00:34:05,842\nAnd don't forget any any when you do these things.\n\n675\n00:34:05,844 --> 00:34:07,044\nSo go to any any. Now it looks good.\n\n676\n00:34:07,046 --> 00:34:11,248\nThey're all good. Okay, so I have no magic numbers now. So\n\n677\n00:34:11,250 --> 00:34:13,083\nmy UI is all nice and arranged.\n\n678\n00:34:13,085 --> 00:34:15,118\nNow why do we wanna get rid of these magic numbers?\n\n679\n00:34:15,120 --> 00:34:18,889\nBecause the built-in numbers, the standard numbers,\n\n680\n00:34:18,891 --> 00:34:20,090\nare gonna be the same in every single app,\n\n681\n00:34:20,092 --> 00:34:22,492\nnot just your app. So when people are running other apps,\n\n682\n00:34:22,494 --> 00:34:25,028\nthings are gonna look similar, similar spacing, etc. And\n\n683\n00:34:25,030 --> 00:34:27,564\nthat's what you want, cuz you want a consistent experience,\n\n684\n00:34:27,566 --> 00:34:31,001\nnot just inside your own app, but within you know,\n\n685\n00:34:31,003 --> 00:34:36,940\ntwo other apps, as well. What else did I want to show here?\n\n686\n00:34:36,942 --> 00:34:41,945\nWe talked about insufficient constraints,\n\n687\n00:34:41,947 --> 00:34:47,084\nwe talked about, okay. Conflicting constraints.\n\n688\n00:34:47,086 --> 00:34:49,086\nSometimes you'll have conflicting constraints, like\n\n689\n00:34:49,088 --> 00:34:51,488\ntwo different constraints that are trying to constrain the\n\n690\n00:34:51,490 --> 00:34:55,525\nsame two things and they'll be across size classes.\n\n691\n00:34:55,527 --> 00:34:58,061\nThose can be sometimes hard to find. Okay,\n\n692\n00:34:58,063 --> 00:35:00,497\nlet's say I have my calculator app here. Okay,\n\n693\n00:35:00,499 --> 00:35:02,699\nI'm looking at any any here and I go away for\n\n694\n00:35:02,701 --> 00:35:05,268\na few months and I come back and I look at this, and\n\n695\n00:35:05,270 --> 00:35:08,305\nI forget the fact that I had these other side classes over\n\n696\n00:35:08,307 --> 00:35:12,042\nhere. And I look at this and I'm like, my gosh, I forgot to\n\n697\n00:35:12,044 --> 00:35:15,712\ncontrol drag this up to the top. No, I better do that.\n\n698\n00:35:15,714 --> 00:35:18,381\nOkay vertical spacing and I better put this thing over\n\n699\n00:35:18,383 --> 00:35:22,919\nhere my lead spacing. Yeah, well have to fix that let's\n\n700\n00:35:22,921 --> 00:35:27,958\nmake this be zero and we'll fix this and we'll\n\n701\n00:35:27,960 --> 00:35:32,529\nmake this one be a standard. Okay whew, I fixed it. Okay,\n\n702\n00:35:32,531 --> 00:35:36,500\neverything's good. Look I have no conflicting constraints.\n\n703\n00:35:36,502 --> 00:35:38,435\nI must have fixed my app, it's in good shape.\n\n704\n00:35:38,437 --> 00:35:41,805\nSo let's go ahead and run it. I'm sure it looks really good.\n\n705\n00:35:45,844 --> 00:35:49,980\nWhat the, okay, that one's okay but what a mess.\n\n706\n00:35:49,982 --> 00:35:51,014\nWhat the heck happened here? And look,\n\n707\n00:35:51,016 --> 00:35:53,083\nI'm getting all kinds of warnings on my console,\n\n708\n00:35:53,085 --> 00:35:56,853\nconflicting constraints. You know what, so I've totally\n\n709\n00:35:56,855 --> 00:35:59,623\nbroken the world, even though when I go back into my app,\n\n710\n00:35:59,625 --> 00:36:02,726\nit looks like everything fine. That's because when you change\n\n711\n00:36:02,728 --> 00:36:04,861\nconstraints, especially when you change any any,\n\n712\n00:36:04,863 --> 00:36:08,265\nyou wanna go take a look at your other size classes. Now,\n\n713\n00:36:08,267 --> 00:36:11,768\nwhen we look at that. [SOUND] Two views are horizontally\n\n714\n00:36:11,770 --> 00:36:15,739\nambiguous. Three conflicting constraints. If we go down\n\n715\n00:36:15,741 --> 00:36:20,477\nto this one down here, we got four conflicting constraints.\n\n716\n00:36:20,479 --> 00:36:23,580\nWhen you have conflicting constraints, this little\n\n717\n00:36:23,582 --> 00:36:26,616\nyellow thing up here will actually turn red, okay? And\n\n718\n00:36:26,618 --> 00:36:28,952\nthen you can click on that and see all the conflicts.\n\n719\n00:36:28,954 --> 00:36:30,687\nSo these things are all conflicting, and\n\n720\n00:36:30,689 --> 00:36:32,322\nof course these conflict, okay?\n\n721\n00:36:32,324 --> 00:36:33,356\nWe know why these conflict.\n\n722\n00:36:33,358 --> 00:36:37,394\nBecause in any any, we've fixed the edges of this stack\n\n723\n00:36:37,396 --> 00:36:40,797\nview to some things. And in the other size classes, we've\n\n724\n00:36:40,799 --> 00:36:45,468\nalso fixed the edges of these, this thing to other things.\n\n725\n00:36:45,470 --> 00:36:49,272\nOkay, like to this thing over here, for example. So\n\n726\n00:36:49,274 --> 00:36:54,744\nbe careful about that when you have, when you're putting your\n\n727\n00:36:54,746 --> 00:36:57,080\nconstraints in there, it might look like everything's fine,\n\n728\n00:36:57,082 --> 00:36:58,248\nbut you could have conflicts across.\n\n729\n00:36:58,250 --> 00:37:03,186\nSo I'm gonna undo all this. To go back here. All right,\n\n730\n00:37:03,188 --> 00:37:06,590\nanother thing I want to show you is\n\n731\n00:37:06,592 --> 00:37:09,159\njust to kind of prove to you what we were talking\n\n732\n00:37:09,161 --> 00:37:12,229\nabout with the compact width being on some platforms\n\n733\n00:37:12,231 --> 00:37:15,232\nnot others, I'm actually gonna go up here to a different one\n\n734\n00:37:15,234 --> 00:37:18,802\nwhich is this guy right here. This is compact width\n\n735\n00:37:18,804 --> 00:37:21,905\nany height. That's what this square is. I'm gonna click on\n\n736\n00:37:21,907 --> 00:37:23,406\nthat. So here's compact width any height.\n\n737\n00:37:23,408 --> 00:37:25,742\nNotice that it looks like any any because we haven't done\n\n738\n00:37:25,744 --> 00:37:28,845\nanything special in here. And I'm actually gonna drag\n\n739\n00:37:28,847 --> 00:37:32,115\na button out. Okay, here's a button. I'm gonna drag it.\n\n740\n00:37:32,117 --> 00:37:34,384\nI'm gonna call this button, actually, we'll just do it\n\n741\n00:37:34,386 --> 00:37:36,920\nwith a label. We don't need a button, this label here,\n\n742\n00:37:36,922 --> 00:37:40,323\nand we'll call this thing Compact Width.\n\n743\n00:37:40,325 --> 00:37:42,659\nCuz we're putting this in the compact width any,\n\n744\n00:37:42,661 --> 00:37:46,830\nright? Then I'll even put it right here in the middle.\n\n745\n00:37:46,832 --> 00:37:49,032\nI'll do another control drag so you can see constraints.\n\n746\n00:37:49,034 --> 00:37:52,402\nSo, I'm gonna control drag to my super view, okay, and\n\n747\n00:37:52,404 --> 00:37:56,806\nsay center this vertically in the container. So\n\n748\n00:37:56,808 --> 00:37:58,742\nnow it's gonna center this. So now when I run,\n\n749\n00:37:58,744 --> 00:38:03,346\nokay, any time I'm appearing on a compact width situation,\n\n750\n00:38:03,348 --> 00:38:04,547\nit's gonna say compact width. So\n\n751\n00:38:04,549 --> 00:38:07,250\nsure enough, this one, that's compact width, right?\n\n752\n00:38:07,252 --> 00:38:09,452\nWe know iPhone 6 and portrait is compact width.\n\n753\n00:38:09,454 --> 00:38:13,056\nAnd here, this is also compact width cuz this is iPhone 6 not\n\n754\n00:38:13,058 --> 00:38:17,427\n6 Plus, iPhone 6 in landscape is also compact width, okay?\n\n755\n00:38:17,429 --> 00:38:19,329\nNow we know this is compact height, because look,\n\n756\n00:38:19,331 --> 00:38:23,633\nour times divide plus minus are not along the sides so\n\n757\n00:38:23,635 --> 00:38:23,967\nit's compact height. And\n\n758\n00:38:23,969 --> 00:38:26,836\nwe know this is regular height because those things are on\n\n759\n00:38:26,838 --> 00:38:30,440\nthe top. Okay, now let's go look at this on 6 Plus.\n\n760\n00:38:38,583 --> 00:38:42,719\nAll right, so 6 Plus portrait is compact width,\n\n761\n00:38:42,721 --> 00:38:46,089\nokay. In landscape, not compact width.\n\n762\n00:38:46,091 --> 00:38:51,261\nIt's regular width. All right? But this height is the same.\n\n763\n00:38:51,263 --> 00:38:54,397\nThis is compact height because these are not along the top.\n\n764\n00:38:54,399 --> 00:38:58,068\nAnd this is regular height because these are the top.\n\n765\n00:38:58,270 --> 00:39:01,371\nOkay, let's take a look at iPad.\n\n766\n00:39:12,417 --> 00:39:16,186\nAll right, so iPad, not compact width in portrait,\n\n767\n00:39:16,188 --> 00:39:20,423\nalso not compact width in landscape. And it's\n\n768\n00:39:20,425 --> 00:39:24,194\nregular in height because, see these buttons on the top?\n\n769\n00:39:24,196 --> 00:39:27,931\nIn landscape and it's regular in height in portrait as well.\n\n770\n00:39:27,933 --> 00:39:31,134\nSo regular in both directions. Both landscape and portrait.\n\n771\n00:39:31,136 --> 00:39:32,369\nOkay now I'm gonna do something here,\n\n772\n00:39:32,371 --> 00:39:34,971\nI'm gonna go back to the calculator here and\n\n773\n00:39:34,973 --> 00:39:38,575\nI'm gonna put it in a split view. Okay?\n\n774\n00:39:38,577 --> 00:39:40,610\nSo this is my calculator here, I'm gonna pop this thing into\n\n775\n00:39:40,612 --> 00:39:43,613\nsplit view,so let's grab a split view. I'm gonna make\n\n776\n00:39:43,615 --> 00:39:45,915\nthis calculator be the master of the split view.\n\n777\n00:39:45,917 --> 00:39:50,186\nThere is the split view. I'm to, delete this and this.\n\n778\n00:39:50,188 --> 00:39:53,189\nAnd I'm just gonna make this be the entry point, right?\n\n779\n00:39:53,191 --> 00:39:55,325\nThis split view is gonna be the entry point. And then I'll\n\n780\n00:39:55,327 --> 00:39:59,763\nmake this be the master. Okay? So now let's run on iPad and\n\n781\n00:39:59,765 --> 00:40:05,402\nsee what we got. Okay.\n\n782\n00:40:05,404 --> 00:40:08,738\nHere we go. This is portrait. Here's landscape.\n\n783\n00:40:08,740 --> 00:40:12,142\nOkay notice or my calculator is compact width\n\n784\n00:40:12,144 --> 00:40:14,711\nwhen it's even if it's on iPad. But it's still compact\n\n785\n00:40:14,713 --> 00:40:17,180\nwidth because it's in the master here. Here's a really\n\n786\n00:40:17,182 --> 00:40:20,016\ninteresting one. What happens if I'm in portrait and\n\n787\n00:40:20,018 --> 00:40:25,588\nI pull the master out? Not compact width. Okay\n\n788\n00:40:25,590 --> 00:40:29,426\nnot compact width, even though it's the exact same width\n\n789\n00:40:29,428 --> 00:40:32,362\nokay as in landscape. It's not compact width, and that's\n\n790\n00:40:32,364 --> 00:40:34,397\nbecause there's actually API in the split view what when\n\n791\n00:40:34,399 --> 00:40:37,267\nyou put that thing out it can pull out different distances.\n\n792\n00:40:37,269 --> 00:40:40,437\nAnd rather than have them try to be changing the size class\n\n793\n00:40:40,439 --> 00:40:43,706\non the fly, sometimes it's compact, sometimes regular.\n\n794\n00:40:43,708 --> 00:40:45,442\nThey just said, okay,\n\n795\n00:40:45,444 --> 00:40:49,412\nbecause it lets you tell these two different states, okay?\n\n796\n00:40:49,414 --> 00:40:52,682\nWhether you're in the landscape as the master or\n\n797\n00:40:52,684 --> 00:40:55,218\nyou're pulled out as the master, okay?\n\n798\n00:40:55,220 --> 00:41:00,056\nEveryone got that? Okay, so that's it, for size classes,\n\n799\n00:41:00,058 --> 00:41:04,394\nthat's it for auto layout. Again, only experience will\n\n800\n00:41:04,396 --> 00:41:06,362\nreally teach you auto layout in the long run,\n\n801\n00:41:06,364 --> 00:41:08,031\nbut you know where all the pieces of it are now,\n\n802\n00:41:08,033 --> 00:41:10,166\nand you know how to do control drag.\n\n803\n00:41:10,168 --> 00:41:12,735\nThat's probably the main thing you're gonna be doing.\n\n804\n00:41:12,737 --> 00:41:14,270\nAnd maybe you'll be doing these menus down here,\n\n805\n00:41:14,272 --> 00:41:20,477\npossibly. Okay, Friday, no section again on this Friday.\n\n806\n00:41:20,479 --> 00:41:22,912\nMonday your current assignment is coordinate a smash tag\n\n807\n00:41:22,914 --> 00:41:27,116\nis due. There will be another assignment, Assignment 6 going\n\n808\n00:41:27,118 --> 00:41:30,787\nout next week. Not sure, probably gonna go out on\n\n809\n00:41:30,789 --> 00:41:33,756\nWednesday. It might go out on Wednesday, not 100% sure.\n\n810\n00:41:33,758 --> 00:41:36,125\nI'll think about it over the week can't okay but\n\n811\n00:41:36,127 --> 00:41:38,728\nthe topic of that assignment and in the topic of next\n\n812\n00:41:38,730 --> 00:41:41,598\nweek's lectures is gonna be animation. Okay, a very\n\n813\n00:41:41,600 --> 00:41:45,101\nimportant part obviously building an app on iOS and\n\n814\n00:41:45,103 --> 00:41:49,939\nthat's it. So I'll be here I'm here if you have questions as\n\n815\n00:41:49,941 --> 00:41:53,710\nusual, that kind of business. >> For\n\n816\n00:41:53,712 --> 00:41:53,743\nmore please visit us at Stanford.edu.\n\n"
  },
  {
    "path": "subtitles/13. NSTimer and Animation.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,602\n[MUSIC]\n\n2\n00:00:03,604 --> 00:00:08,507\nStanford University. >> Okay, well, welcome\n\n3\n00:00:08,509 --> 00:00:13,946\nto Lecture 13 of Stanford CS193P spring of 2016. Today,\n\n4\n00:00:13,948 --> 00:00:18,117\nwe're gonna be talking about animation,\n\n5\n00:00:18,119 --> 00:00:21,754\nprimarily. I'm actually gonna show you a little class called\n\n6\n00:00:21,756 --> 00:00:25,290\nNSTimer first, which we really don't use for animations. But\n\n7\n00:00:25,292 --> 00:00:28,527\nwhen we're doing animations surprisingly, we end up using\n\n8\n00:00:28,529 --> 00:00:30,896\nNSTimer sometimes. Not for the animation itself,\n\n9\n00:00:30,898 --> 00:00:34,266\nbut just because animation is timing-based thing, and\n\n10\n00:00:34,268 --> 00:00:36,869\nNSTimer obviously is a timing-based class.\n\n11\n00:00:36,871 --> 00:00:38,771\nAnd then we're gonna dive right into animation, and\n\n12\n00:00:38,773 --> 00:00:42,441\nthere's lots and lots of mechanisms for animation\n\n13\n00:00:42,443 --> 00:00:45,244\nin iOS, and I'm only gonna show you, you know, two or\n\n14\n00:00:45,246 --> 00:00:48,614\nthree different ones. I'll talk a little bit about what,\n\n15\n00:00:48,616 --> 00:00:52,184\nwhat things there are, but I'm only gonna dive into a few of\n\n16\n00:00:52,186 --> 00:00:55,687\nthem. And one of them, the simulated physics version,\n\n17\n00:00:55,689 --> 00:00:59,158\nI will get started on the slides today at the end, but\n\n18\n00:00:59,160 --> 00:01:01,393\nI won't make it all the way through, and\n\n19\n00:01:01,395 --> 00:01:04,963\nI'll just continue in the next lecture, okay. All right,\n\n20\n00:01:04,965 --> 00:01:07,566\nso let's take this little detour and talk about NSTimer.\n\n21\n00:01:07,568 --> 00:01:12,471\nNSTimer is a very simple little class that allows\n\n22\n00:01:12,473 --> 00:01:16,909\nyou to call a method periodically, okay.\n\n23\n00:01:16,911 --> 00:01:17,976\nAnd you could either have it\n\n24\n00:01:17,978 --> 00:01:19,645\nrepeating where it's calling it over and\n\n25\n00:01:19,647 --> 00:01:22,548\nover every certain amount of time, or you can actually just\n\n26\n00:01:22,550 --> 00:01:25,417\nhave it call it once sometime in the future. Okay, so\n\n27\n00:01:25,419 --> 00:01:29,121\nit's a way to set up a time or to call a method. It couldn't\n\n28\n00:01:29,123 --> 00:01:31,924\nreally be simpler than that. Again, we're not gonna\n\n29\n00:01:31,926 --> 00:01:34,460\nuse it for animation, you know, things moving around and\n\n30\n00:01:34,462 --> 00:01:35,294\nstuff. There's other mechanisms for\n\n31\n00:01:35,296 --> 00:01:38,630\ndoing that. But you're gonna see from the demo I do today,\n\n32\n00:01:38,632 --> 00:01:41,200\nwha, where NSTimer kind of can come in and be used.\n\n33\n00:01:41,202 --> 00:01:43,702\nIt's actually quite useful in a lot of situations.\n\n34\n00:01:43,704 --> 00:01:48,307\nIt's not a real time timer, you know? This is not a real\n\n35\n00:01:48,309 --> 00:01:52,144\ntime operating system. You got that main queue. Other blocks\n\n36\n00:01:52,146 --> 00:01:54,179\nmight be executing off that main queue, and so\n\n37\n00:01:54,181 --> 00:01:57,549\nthe timer's trying to execute, but it can't cuz it's busy.\n\n38\n00:01:57,551 --> 00:02:00,319\nSo it could be off a little bit but it's generally\n\n39\n00:02:00,321 --> 00:02:05,457\ngoing to try to set this, call this method when you say.\n\n40\n00:02:05,659 --> 00:02:08,227\nThe timer's built on a mechanism in iOS which I'm not\n\n41\n00:02:08,229 --> 00:02:11,296\ngonna talk about at all in this class, called run loops.\n\n42\n00:02:11,298 --> 00:02:14,433\nFor the main queue, there's a run loop set up for you, so\n\n43\n00:02:14,435 --> 00:02:18,570\nNSTimer always works on the main queue. For other queues,\n\n44\n00:02:18,572 --> 00:02:21,106\nyou know, you may or may not have a run loop. You might\n\n45\n00:02:21,108 --> 00:02:24,209\nhave to set up your own run loop, etc, so for the purposes\n\n46\n00:02:24,211 --> 00:02:27,813\nof this class, just assume NSTimer is a main queue thing.\n\n47\n00:02:27,815 --> 00:02:30,082\nOf course, when a timer goes off and calls a method,\n\n48\n00:02:30,084 --> 00:02:33,352\nyou could dispatc_async to another queue in that method,\n\n49\n00:02:33,354 --> 00:02:35,821\nthat's fine. It is just that the actual firing of\n\n50\n00:02:35,823 --> 00:02:39,091\nthe timer, that has to be happening in the main queue,\n\n51\n00:02:39,093 --> 00:02:40,459\nfor the purposes of this class.\n\n52\n00:02:40,461 --> 00:02:42,561\nOkay, so what's the main method\n\n53\n00:02:42,563 --> 00:02:45,831\nlook like in NSTimer that does this? This is it.\n\n54\n00:02:45,833 --> 00:02:47,866\nSay I just scheduled timer with time interval.\n\n55\n00:02:47,868 --> 00:02:49,368\nNotice that it's a class method, right,\n\n56\n00:02:49,370 --> 00:02:52,404\na static method on the class. So you invoke this by saying\n\n57\n00:02:52,406 --> 00:02:56,175\nNSTimer.scheduledTimeWithTime- Interval. And you just specify\n\n58\n00:02:56,177 --> 00:02:58,544\nhow many seconds from now you want this timer to go off for\n\n59\n00:02:58,546 --> 00:03:02,147\nthe first time, and then you specify a target and selector.\n\n60\n00:03:02,149 --> 00:03:04,750\nThat's the method in the object that you want to be\n\n61\n00:03:04,752 --> 00:03:07,352\ncalled. You got this user info, that's basically\n\n62\n00:03:07,354 --> 00:03:10,656\na cookie, right? You can put anything you want in there,\n\n63\n00:03:10,658 --> 00:03:11,590\nsome context, whatever,\n\n64\n00:03:11,592 --> 00:03:12,524\nyou can leave it nil if you want.\n\n65\n00:03:12,526 --> 00:03:16,061\nAnd then repeat is whether it's going to go off again in\n\n66\n00:03:16,063 --> 00:03:18,997\nthis many seconds, at the beginning there, and\n\n67\n00:03:18,999 --> 00:03:22,167\nthen just keep going off, over and over and over.\n\n68\n00:03:22,169 --> 00:03:26,438\nSo it couldn't really be simpler than that. So\n\n69\n00:03:26,440 --> 00:03:28,240\nhere's an example of calling it. All right,\n\n70\n00:03:28,242 --> 00:03:31,810\nI'm calling it for it to go off in two seconds there.\n\n71\n00:03:31,812 --> 00:03:35,747\nYou see? Two seconds and I'm gonna call a method in myself\n\n72\n00:03:35,749 --> 00:03:37,683\ncalled fire. It has one argument.\n\n73\n00:03:37,685 --> 00:03:40,452\nWe'll talk about that what that argument is in a second.\n\n74\n00:03:40,454 --> 00:03:43,322\nAnd then here I'm not passing any context or\n\n75\n00:03:43,324 --> 00:03:44,022\ncookie or whatever right there,\n\n76\n00:03:44,024 --> 00:03:46,792\njust nil. And this one's gonna be re, repeating. So every two\n\n77\n00:03:46,794 --> 00:03:50,195\nseconds this method, fire, is going to be invoked in self.\n\n78\n00:03:50,197 --> 00:03:53,632\nAnd so let's go ahead and look at fire with this argument\n\n79\n00:03:53,634 --> 00:03:55,100\nNSTimer in there. Here it is.\n\n80\n00:03:55,102 --> 00:03:59,571\nYou remember from the selector syntax up here, this hashtag,\n\n81\n00:03:59,573 --> 00:04:02,975\nor pound sign, whatever, hashtag we call it now,\n\n82\n00:04:02,977 --> 00:04:07,212\n[LAUGH] pound sign selector. Fire, see this little\n\n83\n00:04:07,214 --> 00:04:10,115\nunder bar colon right there means it has an argument. And\n\n84\n00:04:10,117 --> 00:04:14,620\nthat argument, for NStimer is always the timer itself, okay?\n\n85\n00:04:14,622 --> 00:04:18,056\nSo that's the timer that is sending you this fire\n\n86\n00:04:18,058 --> 00:04:18,257\nmethod down here. And\n\n87\n00:04:18,259 --> 00:04:21,226\ninside of the implementation of this fire method, you can\n\n88\n00:04:21,228 --> 00:04:24,596\nget this cookie that you gave it up here where it's,\n\n89\n00:04:24,598 --> 00:04:26,498\nnow it's nil but if I put a cookie up there,\n\n90\n00:04:26,500 --> 00:04:31,903\nI can get it back by accessing the userInfo bar on NSTimer,\n\n91\n00:04:31,905 --> 00:04:34,906\nsee? So that's how you get the cookie back. Cuz remember this\n\n92\n00:04:34,908 --> 00:04:36,842\ntimer is going on some number of seconds or\n\n93\n00:04:36,844 --> 00:04:39,811\neven minutes later, and you might want that timer to\n\n94\n00:04:39,813 --> 00:04:42,447\nget that cookie back at that time. Okay,\n\n95\n00:04:42,449 --> 00:04:44,916\nnow what if you have a repeating timer and\n\n96\n00:04:44,918 --> 00:04:48,253\nyou wanna stop it? How do you do that? You call this method\n\n97\n00:04:48,255 --> 00:04:50,922\non the timer called invalidate. Now a little bit\n\n98\n00:04:50,924 --> 00:04:53,625\nof a warning, if you call invalidate on a timer,\n\n99\n00:04:53,627 --> 00:04:55,093\nthat timer is no longer valid, and\n\n100\n00:04:55,095 --> 00:04:57,663\nyou should not do anything with it. You can't restart it,\n\n101\n00:04:57,665 --> 00:04:59,731\nreally. There's nothing you can do with it. And\n\n102\n00:04:59,733 --> 00:05:03,368\nso it's usually a pretty bad idea to have a strong pointer\n\n103\n00:05:03,370 --> 00:05:06,605\nto an NSTimer, okay? Because you've got the strong pointer,\n\n104\n00:05:06,607 --> 00:05:09,708\nyou invalidate it. Now you've got a strong pointer to\n\n105\n00:05:09,710 --> 00:05:10,876\nsomething that's invalid.\n\n106\n00:05:10,878 --> 00:05:13,045\nSo it's much better to make your pointers to NSTimers\n\n107\n00:05:13,047 --> 00:05:16,415\nbe weak. And when you do that, if you hit invalidate,\n\n108\n00:05:16,417 --> 00:05:18,784\nno one will have a strong pointer to it anymore. And\n\n109\n00:05:18,786 --> 00:05:22,988\nit'll leave the heap, and your weak variable will get set\n\n110\n00:05:22,990 --> 00:05:26,625\nto nil. So I recommend using weak pointers to NSTimers. Or\n\n111\n00:05:26,627 --> 00:05:31,630\nnot having any at all because remember every time it fires,\n\n112\n00:05:31,632 --> 00:05:37,069\nyou get this timer passed back to you as the argument if you\n\n113\n00:05:37,071 --> 00:05:40,105\nwant it. Okay, tolerance.\n\n114\n00:05:40,107 --> 00:05:44,509\nSo you can specify in the timer a tolerance, and that's\n\n115\n00:05:44,511 --> 00:05:49,348\nbasically how much you're willing to accept some slop in\n\n116\n00:05:49,350 --> 00:05:52,017\nits calculation of when it goes off,\n\n117\n00:05:52,019 --> 00:05:54,853\nokay? So here I'm talking about an example where you\n\n118\n00:05:54,855 --> 00:05:55,854\nhave a timer goes off once a minute.\n\n119\n00:05:55,856 --> 00:05:58,323\nYou set the tolerance to ten, which is in seconds,\n\n120\n00:05:58,325 --> 00:06:01,927\nand that means if it goes off after a minute, that's fine,\n\n121\n00:06:01,929 --> 00:06:03,662\na minute and three seconds from now.\n\n122\n00:06:03,664 --> 00:06:05,864\nYeah, okay, a minute and 7 seconds, fine, but\n\n123\n00:06:05,866 --> 00:06:08,834\na minute and 20 seconds, that's too long, all right.\n\n124\n00:06:08,836 --> 00:06:10,402\nAnd so why would you want this tolerance?\n\n125\n00:06:10,404 --> 00:06:12,437\nWell, because other things are going on in the system, and\n\n126\n00:06:12,439 --> 00:06:15,273\nif you really don't care about getting it right on time,\n\n127\n00:06:15,275 --> 00:06:17,342\nthen maybe the system can be more efficient about how it's\n\n128\n00:06:17,344 --> 00:06:21,947\nusing its processor and other resources during that time.\n\n129\n00:06:21,949 --> 00:06:25,951\nOkay, and notice that this tolerance does not cause\n\n130\n00:06:25,953 --> 00:06:29,187\ndrift. So if the first time it goes off, it goes off a minute\n\n131\n00:06:29,189 --> 00:06:33,558\nand seven seconds after, the next time it's gonna go off,\n\n132\n00:06:33,560 --> 00:06:36,161\ntry to go off two minutes from the beginning. And\n\n133\n00:06:36,163 --> 00:06:37,729\nthe next time, three minutes from the beginning,\n\n134\n00:06:37,731 --> 00:06:41,133\nyou see what I mean, it's not drifting. If it's late on one,\n\n135\n00:06:41,135 --> 00:06:43,769\nit's doesn't start being late on the next one.\n\n136\n00:06:44,538 --> 00:06:46,037\nAll right, so let's do a demo of this, so\n\n137\n00:06:46,039 --> 00:06:50,075\nyou can see it in action. What I'm gonna do here is I'm gonna\n\n138\n00:06:50,077 --> 00:06:54,112\ntake our old friend FaceIt, okay, remember FaceIt there,\n\n139\n00:06:54,114 --> 00:06:57,883\nand we're gonna make it so his eyes blink, okay, and\n\n140\n00:06:57,885 --> 00:07:01,787\nwe're gonna do that using a timer. So\n\n141\n00:07:01,789 --> 00:07:04,222\nit's pretty straightforward actually to do this.\n\n142\n00:07:04,224 --> 00:07:07,192\nI'm gonna use this opportunity to teach you something else.\n\n143\n00:07:07,194 --> 00:07:09,761\nOkay, I always try to do that. Which is,\n\n144\n00:07:09,763 --> 00:07:13,331\nwhat if I had this MVC right here. If you look at this MVC,\n\n145\n00:07:13,333 --> 00:07:16,067\nif you look at the identity inspector for\n\n146\n00:07:16,069 --> 00:07:19,604\nit, you can see that its class, of course,\n\n147\n00:07:19,606 --> 00:07:20,439\nis FaceViewController.\n\n148\n00:07:20,441 --> 00:07:22,374\nRight, you remember our FaceViewController?\n\n149\n00:07:22,376 --> 00:07:24,176\nIt's got all this stuff our face views.\n\n150\n00:07:24,178 --> 00:07:27,078\nWe got all that those gesture recognizer,\n\n151\n00:07:27,347 --> 00:07:28,079\nall this stuff remember that? So\n\n152\n00:07:28,081 --> 00:07:30,749\nthat makes sense that that's what the controller is for\n\n153\n00:07:30,751 --> 00:07:34,219\nthis. What if I wanted to put all my blinking stuff in\n\n154\n00:07:34,221 --> 00:07:37,456\nanother class? In other words, I didn't want to put blinking\n\n155\n00:07:37,458 --> 00:07:39,624\nin with all this other FaceViewController,\n\n156\n00:07:39,626 --> 00:07:42,127\nokay? In other words, what if I wanted a blinking\n\n157\n00:07:42,129 --> 00:07:45,831\nFaceViewController? Okay, well, you can use inheritance,\n\n158\n00:07:45,833 --> 00:07:48,633\nthis is object-oriented programming. It's not uncommon\n\n159\n00:07:48,635 --> 00:07:52,103\nto create a subclass of another MVC's controller to\n\n160\n00:07:52,105 --> 00:07:54,806\ncreate a controller you want for your MVC.\n\n161\n00:07:54,808 --> 00:07:56,942\nAnd that's exactly what I'm gonna do. Okay,\n\n162\n00:07:56,944 --> 00:07:59,878\nI'm gonna create a new controller here, new File.\n\n163\n00:07:59,880 --> 00:08:03,582\nOkay, to iOS source, it's a Cocoa Touch Class. But\n\n164\n00:08:03,584 --> 00:08:07,252\ninstead of the subclass being of some UI kit class here,\n\n165\n00:08:07,254 --> 00:08:12,390\nit's gonna be a subclass of my class, FaceViewController.\n\n166\n00:08:12,392 --> 00:08:17,329\nOkay, and I'm gonna call it BlinkingFaceViewController,\n\n167\n00:08:17,331 --> 00:08:19,865\nall right? So, here it is, it's creating it,\n\n168\n00:08:19,867 --> 00:08:22,300\nputting in all the regular places where it puts it.\n\n169\n00:08:22,302 --> 00:08:24,402\nHere it is, I don't need any of this stuff, so\n\n170\n00:08:24,404 --> 00:08:26,037\nI'll get out that out of there. So\n\n171\n00:08:26,039 --> 00:08:27,939\nI've got this BlinkingFaceViewController,\n\n172\n00:08:27,941 --> 00:08:30,542\nit's a subclass of FaceViewController. And\n\n173\n00:08:30,544 --> 00:08:33,278\nin my storyboard, if I went to this and\n\n174\n00:08:33,280 --> 00:08:35,046\nchanged in the identity inspector for\n\n175\n00:08:35,048 --> 00:08:38,316\nthis, changed it from being a FaceViewController to being\n\n176\n00:08:38,318 --> 00:08:41,019\na BlinkingFaceViewController. And hit Run,\n\n177\n00:08:41,021 --> 00:08:45,857\ndo you think this would work? Yeah it would work, because\n\n178\n00:08:45,859 --> 00:08:48,393\nBlinkingFaceViewController inherits everything from\n\n179\n00:08:48,395 --> 00:08:51,062\nFaceViewController, so it's gonna work just as well.\n\n180\n00:08:51,064 --> 00:08:53,365\nCuz, full inheritance of it. So, let's go back here and\n\n181\n00:08:53,367 --> 00:08:57,536\nremember what face this emotions app here does. So we\n\n182\n00:08:57,538 --> 00:08:59,437\ncan pick our various emotions. You can see it's working\n\n183\n00:08:59,439 --> 00:09:02,541\njust fine to have this be a BlinkingFaceViewController.\n\n184\n00:09:02,543 --> 00:09:03,074\nOf course, it doesn't blink,\n\n185\n00:09:03,076 --> 00:09:05,644\ncuz I haven't put any blinking code in there, but\n\n186\n00:09:05,646 --> 00:09:08,914\nI am gonna put the blinking code in now. Okay, I'm gonna\n\n187\n00:09:08,916 --> 00:09:12,517\nput all that blinking code up here in this subclass. So,\n\n188\n00:09:12,519 --> 00:09:15,053\nthe, this blinking thing is pretty simple. It basically\n\n189\n00:09:15,055 --> 00:09:19,891\nneeds a Bool here, which is whether it's blinking or not,\n\n190\n00:09:19,893 --> 00:09:22,427\nwe'll start it out as false, it's not blinking, and\n\n191\n00:09:22,429 --> 00:09:24,629\nof course every time this changes, we're need,\n\n192\n00:09:24,631 --> 00:09:28,900\ngoing to, basically need to start blinking, okay?\n\n193\n00:09:28,902 --> 00:09:31,636\nIf someone says that, you know, if someone the,\n\n194\n00:09:31,638 --> 00:09:34,806\nif someone says didSet, changes this blinking thing.\n\n195\n00:09:34,808 --> 00:09:40,045\nSo, I need a little private, oops, private var here,\n\n196\n00:09:40,047 --> 00:09:41,880\nstartBlink, and\n\n197\n00:09:41,882 --> 00:09:44,282\nit's going to just have to start things blinking. And\n\n198\n00:09:44,284 --> 00:09:46,818\nactually, it's gonna want to look at blinking, though, and\n\n199\n00:09:46,820 --> 00:09:50,555\nonly do the blinking if blinking is true. Okay,\n\n200\n00:09:50,557 --> 00:09:53,191\nif blinking is not true, it's not gonna want to do that.\n\n201\n00:09:53,193 --> 00:09:56,227\nPrivate, oops, this is not func. Private func.\n\n202\n00:09:56,229 --> 00:09:59,097\n[LAUGH] Okay, so inside the blinking there it's gonna want\n\n203\n00:09:59,099 --> 00:10:02,300\nto start blinking, we'll talk about how to do startBlink in\n\n204\n00:10:02,302 --> 00:10:06,471\na second. Now sort of for the purposes of demo,\n\n205\n00:10:06,473 --> 00:10:09,307\nbut also to talk a little bit about timers here,\n\n206\n00:10:09,309 --> 00:10:12,877\nI'm actually in my viewDidAppear, okay,\n\n207\n00:10:12,879 --> 00:10:17,649\nsuper.viewDidAppear(animated). I'm gonna\n\n208\n00:10:17,651 --> 00:10:21,186\nstart myself blinking. So I'm gonna say blinking = true.\n\n209\n00:10:21,188 --> 00:10:23,989\nIt's a little bit demoware, because you probably wouldn't\n\n210\n00:10:23,991 --> 00:10:25,824\nwant a blinking face controller to always start\n\n211\n00:10:25,826 --> 00:10:28,693\nblinking as soon as it comes up. You wanna let people, this\n\n212\n00:10:28,695 --> 00:10:31,396\nis a public var and you wanna let them control it with that.\n\n213\n00:10:31,398 --> 00:10:33,965\nBut it's good for the demo here and\n\n214\n00:10:33,967 --> 00:10:37,602\nalso in viewWillDisappear, I'm gonna do the opposite and\n\n215\n00:10:37,604 --> 00:10:41,539\nturn it back off. And we'll talk about why I'm gonna do\n\n216\n00:10:41,541 --> 00:10:46,911\nthat in a second. Blinking = false, okay? All right, so\n\n217\n00:10:46,913 --> 00:10:49,047\nwe got this kind of infrastructure for\n\n218\n00:10:49,049 --> 00:10:49,914\nour blinking right here.\n\n219\n00:10:49,916 --> 00:10:51,683\nHow are we actually gonna do the blinking?\n\n220\n00:10:51,685 --> 00:10:54,119\nBlinking is really easy. We're gonna start blink,\n\n221\n00:10:54,121 --> 00:10:57,455\nhow do we start a blink in real life? We close our eyes,\n\n222\n00:10:57,457 --> 00:11:02,560\nright? So, we're gonna have our faceView.eyesOpen = false.\n\n223\n00:11:02,562 --> 00:11:06,931\nOkay, we just closed our eyes. And now, after a moment,\n\n224\n00:11:06,933 --> 00:11:09,868\nopen them again. That's what we do when we blink, right?\n\n225\n00:11:09,870 --> 00:11:12,604\nWe close them, and then pretty soon after that,\n\n226\n00:11:12,606 --> 00:11:12,971\nwe open them back up again.\n\n227\n00:11:12,973 --> 00:11:16,574\nThat's what a blink is, okay? So that's what we need to do.\n\n228\n00:11:16,576 --> 00:11:18,843\nNow before we talk about how I'm gonna do this,\n\n229\n00:11:18,845 --> 00:11:21,112\nlet's look at faceView right here. This is interesting,\n\n230\n00:11:21,114 --> 00:11:24,249\nfaceView, where does that come from? Anyone know where that\n\n231\n00:11:24,251 --> 00:11:27,886\ncomes from? Yeah, inherited from this guy,\n\n232\n00:11:27,888 --> 00:11:31,389\nfrom faceViewController. If I go back to faceViewController,\n\n233\n00:11:31,391 --> 00:11:32,457\nhere it is right here, faceView.\n\n234\n00:11:32,459 --> 00:11:36,961\nNotice it's not private, okay? Usually, we make our outlets\n\n235\n00:11:36,963 --> 00:11:39,064\nprivate. We didn't happen to make this one private,\n\n236\n00:11:39,066 --> 00:11:41,032\nmight've been an oversight on my part. But\n\n237\n00:11:41,034 --> 00:11:43,868\nwe didn't make it private. One of the interesting things\n\n238\n00:11:43,870 --> 00:11:47,505\nabout Swift is that there's no idea of protected. How many\n\n239\n00:11:47,507 --> 00:11:51,409\npeople know what protected means? Okay, not too many.\n\n240\n00:11:51,411 --> 00:11:53,611\nSo, we know about private and public, right?\n\n241\n00:11:53,613 --> 00:11:56,548\nPrivate means you can only use it in this class, public means\n\n242\n00:11:56,550 --> 00:11:58,983\nyou can use it outside the framework you're in.\n\n243\n00:11:58,985 --> 00:12:00,485\nEverything else in Swift is internal,\n\n244\n00:12:00,487 --> 00:12:02,053\nwhich means you can use anything, anywhere,\n\n245\n00:12:02,055 --> 00:12:04,989\ninside the framework you're in, including your app is kind\n\n246\n00:12:04,991 --> 00:12:07,792\nof like a framework. So this faceView is really available\n\n247\n00:12:07,794 --> 00:12:12,897\nto any class that's inside our app, okay? And, so,\n\n248\n00:12:12,899 --> 00:12:15,033\nthat's nice, but, it would be maybe better if\n\n249\n00:12:15,035 --> 00:12:17,869\nthere were another protection class called protected. And,\n\n250\n00:12:17,871 --> 00:12:22,707\nwhat that would mean is, only subclasses can use this thing.\n\n251\n00:12:22,709 --> 00:12:23,608\nCuz, that's really what I'd like here.\n\n252\n00:12:23,610 --> 00:12:27,412\nFaceView, I really don't want other classes even in my app,\n\n253\n00:12:27,414 --> 00:12:30,014\nthinking they can start mucking with my faceView,\n\n254\n00:12:30,016 --> 00:12:33,752\nokay? But I want to be able to allow people to subclass.\n\n255\n00:12:33,754 --> 00:12:35,153\nSo unfortunately can't do that, so\n\n256\n00:12:35,155 --> 00:12:36,988\nif you want something to be subclassable, and\n\n257\n00:12:36,990 --> 00:12:39,624\nit's used in a subclass, you have to leave it internal,\n\n258\n00:12:39,626 --> 00:12:43,995\nokay? So we're gonna leave that internal, and\n\n259\n00:12:43,997 --> 00:12:46,564\nthat means we can use it here to open the eyes.\n\n260\n00:12:46,566 --> 00:12:49,134\nOr to close the eyes. Okay, so now how are we going to\n\n261\n00:12:49,136 --> 00:12:51,169\ndo this thing where we wait a moment and open them? Well,\n\n262\n00:12:51,171 --> 00:12:54,372\nI'm just gonna use Timer, of course, that's why we're here!\n\n263\n00:12:54,374 --> 00:12:57,509\nSo let's, some space here. NSTimer, it's called\n\n264\n00:12:57,511 --> 00:13:01,513\nScheduledTimerWithTimeInter- val, notice there's two of\n\n265\n00:13:01,515 --> 00:13:04,015\nthem here. See this one and this one.\n\n266\n00:13:04,017 --> 00:13:06,818\nWe don't want to use this one, this one has a NSInvocation\n\n267\n00:13:06,820 --> 00:13:09,320\nwhich is really just a wrapper for a calling a method.\n\n268\n00:13:09,322 --> 00:13:11,756\nBut I'm not gonna show you that, you don't really need to\n\n269\n00:13:11,758 --> 00:13:14,592\nknow it because this one's just as good right here.\n\n270\n00:13:14,594 --> 00:13:16,194\nThis one's target and selector so\n\n271\n00:13:16,196 --> 00:13:18,263\nthis is what we saw on the slides. So here it is.\n\n272\n00:13:18,265 --> 00:13:23,434\nTo make this is a little more easy to see here I'm gonna add\n\n273\n00:13:23,436 --> 00:13:26,838\nsome carat returns here. Okay, so here's our\n\n274\n00:13:26,840 --> 00:13:28,640\nscheduledTimerWithTimeInter- val.\n\n275\n00:13:28,642 --> 00:13:32,143\nSo, we need a time interval. I'm gonna be a good programmer\n\n276\n00:13:32,145 --> 00:13:34,846\nhere and I'm gonna create a little constant struct here.\n\n277\n00:13:34,848 --> 00:13:38,550\nI'm gonna call it my BlinkRate and, so\n\n278\n00:13:38,552 --> 00:13:45,023\nI'll have a static let here which is the ClosedDuration.\n\n279\n00:13:45,025 --> 00:13:46,191\nWhich will have the, I don't know,\n\n280\n00:13:46,193 --> 00:13:48,793\nyou close your eyes for less than half a second.\n\n281\n00:13:48,795 --> 00:13:51,963\nSomething like that. And then we'll have our OpenDuration.\n\n282\n00:13:51,965 --> 00:13:54,766\nNow this really doesn't wanna be a constant. If you think\n\n283\n00:13:54,768 --> 00:13:58,336\nabout how you blink, you don't blink and then exactly five\n\n284\n00:13:58,338 --> 00:14:01,573\nseconds later you blink again. Okay might seem like a robot,\n\n285\n00:14:01,575 --> 00:14:04,509\nunfortunately this is kind of a robot. So this really would\n\n286\n00:14:04,511 --> 00:14:06,444\nprobably would be some sort of function you know,\n\n287\n00:14:06,446 --> 00:14:09,380\nthe kinda I don't know does some statistical distribution\n\n288\n00:14:09,382 --> 00:14:12,150\nof your blinking, but we're just gonna make it every 2.5\n\n289\n00:14:12,152 --> 00:14:14,953\nseconds okay. So we can this guy blinking pretty quick.\n\n290\n00:14:14,955 --> 00:14:16,721\nAll right, so he's gonna keep his eyes open for\n\n291\n00:14:16,723 --> 00:14:20,592\n2.5 seconds, close them for 0.4. So here eyes are closed,\n\n292\n00:14:20,594 --> 00:14:23,361\nso we want the interval that we're keeping it closed before\n\n293\n00:14:23,363 --> 00:14:25,730\nwe open it again. So this is going to be our\n\n294\n00:14:25,732 --> 00:14:30,535\nBlinkRate.ClosedDuration, okay. The target is going to\n\n295\n00:14:30,537 --> 00:14:33,771\nbe our self. Now there's a restriction on this self,\n\n296\n00:14:33,773 --> 00:14:36,074\nthe same restriction we had with the other.\n\n297\n00:14:36,076 --> 00:14:39,310\nA pound sign selector type of APIs,\n\n298\n00:14:39,312 --> 00:14:42,080\nwhich is that this class that's receiving this has to\n\n299\n00:14:42,082 --> 00:14:46,317\nbe available to the Objective C run time, okay? And\n\n300\n00:14:46,319 --> 00:14:49,921\nso that means it essentially has to inherit from MS Object.\n\n301\n00:14:49,923 --> 00:14:52,857\nNow luckily, self, no problem because we inherit from\n\n302\n00:14:52,859 --> 00:14:56,461\nfaceViewController, which inherits from UIViewController\n\n303\n00:14:56,463 --> 00:14:59,397\nwhich inherits eventually from NSObjects. So we're all good\n\n304\n00:14:59,399 --> 00:15:03,067\nto go here, but just don't get too confused if you try and\n\n305\n00:15:03,069 --> 00:15:04,402\ndo this and it's like it doesn't work.\n\n306\n00:15:04,404 --> 00:15:07,405\nBecause the object you send this message to has to be\n\n307\n00:15:07,407 --> 00:15:11,309\nObjective C compatible. So the selector we want here,\n\n308\n00:15:11,311 --> 00:15:13,344\nlet's call it, this is the start of the blink, so\n\n309\n00:15:13,346 --> 00:15:18,016\nI'm gonna call, my selector on the other side end of blink.\n\n310\n00:15:18,018 --> 00:15:21,853\nSo, this is, we're in our BlinkingFaceViewController\n\n311\n00:15:21,855 --> 00:15:26,624\nhere, endBlink I'll call it, the argument on there, okay?\n\n312\n00:15:27,127 --> 00:15:29,193\nOkay, so, that's what we're gonna, we're gonna call. So,\n\n313\n00:15:29,195 --> 00:15:34,299\nwe're gonna need a method down here, private func endBlink.\n\n314\n00:15:34,301 --> 00:15:37,769\nIt's gonna take that timer as an argument, okay.\n\n315\n00:15:37,771 --> 00:15:40,738\nBut we're gonna end our blink there. UserInfo, that's\n\n316\n00:15:40,740 --> 00:15:43,141\na little cookie, I don't really have anything to say.\n\n317\n00:15:43,143 --> 00:15:45,310\nIt's pretty obvious, I open and close my eyes. And\n\n318\n00:15:45,312 --> 00:15:50,448\nrepeat is false. Okay, I can't really have one repeating,\n\n319\n00:15:50,450 --> 00:15:52,784\ntimer, because you don't blink like this.\n\n320\n00:15:52,786 --> 00:15:54,585\nEyes closed for one second, eyes open for one second,\n\n321\n00:15:54,587 --> 00:15:56,587\neyes closed for one second, you know what I mean,\n\n322\n00:15:56,589 --> 00:15:57,221\nthey're two different timers.\n\n323\n00:15:57,223 --> 00:15:59,557\nOne is the closing one, and one is the opening one.\n\n324\n00:15:59,559 --> 00:16:03,294\nSo I really need Two different timers going back and\n\n325\n00:16:03,296 --> 00:16:06,564\nforth rather than one just going repeatedly,\n\n326\n00:16:06,566 --> 00:16:11,135\nokay? Missed that there. Okay, make sense?\n\n327\n00:16:11,137 --> 00:16:13,104\nNow let's take a look here at this error.\n\n328\n00:16:13,106 --> 00:16:15,440\nYou see the error right here? I put this in here, it's like,\n\n329\n00:16:15,442 --> 00:16:18,743\nwhat's the problem here? And it says right here, you have\n\n330\n00:16:18,745 --> 00:16:22,246\nto add a objc to expose this method to Objective-C.\n\n331\n00:16:22,248 --> 00:16:25,650\nSo I said this had to be an Objective-C compatible method.\n\n332\n00:16:25,652 --> 00:16:26,351\nWell, what the heck?\n\n333\n00:16:26,353 --> 00:16:28,653\nWhy is it making me put Objective-C there?\n\n334\n00:16:28,655 --> 00:16:33,057\nAnd the answer is because I made it private. Okay?\n\n335\n00:16:33,059 --> 00:16:37,662\nPrivate methods don't get exposed to Objective-C. So\n\n336\n00:16:37,664 --> 00:16:38,463\nthey inject a C runtime.\n\n337\n00:16:38,465 --> 00:16:42,200\nAs soon as I made that not private, now it worked.\n\n338\n00:16:42,435 --> 00:16:46,671\nOkay so note that as well. It has to be public method,\n\n339\n00:16:46,673 --> 00:16:49,140\nokay, or otherwise exposed to objective C. Which you can\n\n340\n00:16:49,142 --> 00:16:53,544\ndo with that at sign over J C as well. Okay, so that's good.\n\n341\n00:16:53,546 --> 00:16:56,614\nNow another interesting thing about this endBlink here is\n\n342\n00:16:56,616 --> 00:16:58,349\nthat I actually don't need this timer.\n\n343\n00:16:58,351 --> 00:17:00,485\nBecause I don't have any user info,\n\n344\n00:17:00,487 --> 00:17:01,619\nit's not a repeating timer that I\n\n345\n00:17:01,621 --> 00:17:03,921\nwould want to invalidate. Why do I even need that,\n\n346\n00:17:03,923 --> 00:17:05,456\nI don't even need that thing. Get that outta there.\n\n347\n00:17:05,458 --> 00:17:09,227\nAnd if I get that outta there then I don't need this, okay.\n\n348\n00:17:09,229 --> 00:17:13,264\nAnd that's allowed as well. Okay, just like we have\n\n349\n00:17:13,266 --> 00:17:16,134\ntarget action, or sometimes we pass the cinder along,\n\n350\n00:17:16,136 --> 00:17:20,405\nsame thing with the timer. All right, so that's it.\n\n351\n00:17:20,407 --> 00:17:21,873\nWhat are we gonna do in our endBlink?\n\n352\n00:17:21,875 --> 00:17:25,209\nIn our endBlink, what happens when our blinking is ending?\n\n353\n00:17:25,211 --> 00:17:28,112\nWe got our eyes closed. Now, we open them back up again.\n\n354\n00:17:28,114 --> 00:17:28,846\nSo now we're just gonna say,\n\n355\n00:17:28,848 --> 00:17:33,151\nfaceView dot eyesOpen. Equals true.\n\n356\n00:17:33,153 --> 00:17:36,254\nAnd now, we want to queue up another blink.\n\n357\n00:17:36,256 --> 00:17:39,424\n'Cuz we just want to keep on blinking, right? So I'm going\n\n358\n00:17:39,426 --> 00:17:42,427\nto do that with another timer. So we're going to copy and\n\n359\n00:17:42,429 --> 00:17:45,163\npaste this right here. This time, though,\n\n360\n00:17:45,165 --> 00:17:47,999\nit's our open duration. This is how long the ice cream will\n\n361\n00:17:48,001 --> 00:17:50,601\nbe open until we start blinking again. And instead of\n\n362\n00:17:50,603 --> 00:17:55,907\nendBlink here, now we're start blinking again, okay. Again,\n\n363\n00:17:55,909 --> 00:18:00,411\nerror because this needs to be public, okay, cuz now we're\n\n364\n00:18:00,413 --> 00:18:03,848\ncalling this one, these guys are calling each other, okay.\n\n365\n00:18:03,850 --> 00:18:08,853\nThat good, everyone understand all that?\n\n366\n00:18:09,722 --> 00:18:13,724\nOkay, so let's see if that works for us.\n\n367\n00:18:17,397 --> 00:18:20,431\nAll right, here's our guy right here. And sure enough,\n\n368\n00:18:20,433 --> 00:18:25,570\nhe's blinking, okay? And you know, if we go to other ones,\n\n369\n00:18:25,572 --> 00:18:30,808\nthey'll all blink. Got it?\n\n370\n00:18:30,810 --> 00:18:33,945\nOkay so that's it for timer. Hopefully that's a simple\n\n371\n00:18:33,947 --> 00:18:37,215\nexample to show you how we use timer. So the eye blinking is\n\n372\n00:18:37,217 --> 00:18:40,118\nnot really, we wouldn't really necessarily animation but\n\n373\n00:18:40,120 --> 00:18:42,553\nit's kind of involved in the animation,\n\n374\n00:18:42,555 --> 00:18:45,790\nright? And the next demo I show you we're going to\n\n375\n00:18:45,792 --> 00:18:47,758\nactually animate the opening and closing the eyes.\n\n376\n00:18:47,760 --> 00:18:50,027\nBecause right there the eyes are just popping open and\n\n377\n00:18:50,029 --> 00:18:52,997\npopping shut, popping open. That's not really animating\n\n378\n00:18:52,999 --> 00:18:59,070\nthem okay? So we'll show that in our next demo. All right\n\n379\n00:18:59,072 --> 00:19:04,609\nback to our slides here. Okay so\n\n380\n00:19:04,611 --> 00:19:07,979\nlet's do a little overview of the kinds of animation that\n\n381\n00:19:07,981 --> 00:19:10,948\nare available in iOS. Okay this is most of the kinds.\n\n382\n00:19:10,950 --> 00:19:15,520\nOne is there are three UIView properties that you can\n\n383\n00:19:15,522 --> 00:19:19,390\nanimate the changing of okay which is the frame,\n\n384\n00:19:19,392 --> 00:19:21,926\nthe transform which is like that rotation thing and\n\n385\n00:19:21,928 --> 00:19:23,561\nthe alpha which is the transparency so\n\n386\n00:19:23,563 --> 00:19:26,030\nyou can animate those. We'll talk about doing that.\n\n387\n00:19:26,032 --> 00:19:29,367\nYou can also animate view controller transitions.\n\n388\n00:19:29,369 --> 00:19:31,002\nYou noticed that UINavigationController when\n\n389\n00:19:31,004 --> 00:19:34,705\nyou click to another one it slides into another it kinda,\n\n390\n00:19:34,707 --> 00:19:38,876\nit animated, like cards sliding in, right? Or\n\n391\n00:19:38,878 --> 00:19:42,180\nsliding off. So this whole mechanism for building your\n\n392\n00:19:42,182 --> 00:19:46,017\nown UI navigation controller like things, right,\n\n393\n00:19:46,019 --> 00:19:50,888\nthat have little sub UI view controllers that move in and\n\n394\n00:19:50,890 --> 00:19:52,657\nout, and we're not going to talk about that at all,\n\n395\n00:19:52,659 --> 00:19:54,358\nbecause you're not going to be doing that in this class,\n\n396\n00:19:54,360 --> 00:19:57,361\nit's a little bit of advanced design, but when you go out in\n\n397\n00:19:57,363 --> 00:19:58,930\nthe real world, you might figure out some way,\n\n398\n00:19:58,932 --> 00:20:01,832\nyou know. I know the Facebook app has a little tray that\n\n399\n00:20:01,834 --> 00:20:05,269\nslides out from the left. OK? It's something they designed\n\n400\n00:20:05,271 --> 00:20:07,004\nand it's kinda like U I navigation control, but\n\n401\n00:20:07,006 --> 00:20:10,107\nit only slides out part way. Okay? So I'm sure they had to\n\n402\n00:20:10,109 --> 00:20:14,345\nuse this mechanism to make that animation happen.\n\n403\n00:20:14,347 --> 00:20:17,949\nCore animation is a non object oriented,\n\n404\n00:20:17,951 --> 00:20:21,552\nAPI that underlies almost all the animation we're gonna talk\n\n405\n00:20:21,554 --> 00:20:24,589\nabout here. Okay? It's the big beat engine\n\n406\n00:20:24,591 --> 00:20:28,125\nthat's gong on underneath all this, it's making it all work.\n\n407\n00:20:28,127 --> 00:20:29,760\nUnfortunately I don't have time to talk about it,\n\n408\n00:20:29,762 --> 00:20:31,596\nwe're gonna talk about the higher level things that\n\n409\n00:20:31,598 --> 00:20:33,664\nare build on top of core animation But\n\n410\n00:20:33,666 --> 00:20:36,334\nyou should know it's there. And then a lot of people do\n\n411\n00:20:36,336 --> 00:20:39,637\ndo Core Animation stuff in their final projects. Okay?\n\n412\n00:20:39,639 --> 00:20:41,439\nIt's a good not-covered-in-lecture thing,\n\n413\n00:20:41,441 --> 00:20:43,608\nand there's things you can do in Core Animation that you\n\n414\n00:20:43,610 --> 00:20:47,745\ncan't do with UIView level animation. Okay? There's\n\n415\n00:20:47,747 --> 00:20:51,749\na window from your UIView into the Core Animation world,\n\n416\n00:20:51,751 --> 00:20:54,752\nwhich is the layer. If you look and there's a CA layer,\n\n417\n00:20:54,754 --> 00:20:58,422\nCore Animation layer, that's what CA layer stands for And\n\n418\n00:20:58,424 --> 00:20:59,090\nthere's a property in view for\n\n419\n00:20:59,092 --> 00:21:01,659\nthat, and that's how you can kind of get down to the core\n\n420\n00:21:01,661 --> 00:21:04,228\nanimation layer and start doing core animation things.\n\n421\n00:21:04,230 --> 00:21:07,064\nLike core animation can do rounded recs on the edges\n\n422\n00:21:07,066 --> 00:21:09,133\nof your views and things like that. Masks,\n\n423\n00:21:09,135 --> 00:21:14,071\nall kinds of fun stuff. Okay? If you want to do 3-D,\n\n424\n00:21:14,073 --> 00:21:17,275\nthere's OpenGL. OpenGL is bundled with IOS, so,\n\n425\n00:21:17,277 --> 00:21:20,378\nhow many people here have experience with OpenGL or\n\n426\n00:21:20,380 --> 00:21:23,014\ndoing 3-D? Okay, so a few of you. So you can do that,\n\n427\n00:21:23,016 --> 00:21:26,717\nfull OpenGL support in IOS. There's also something called\n\n428\n00:21:26,719 --> 00:21:30,554\nSpriteKit, which is like 2.5D. Okay, this is how,\n\n429\n00:21:30,556 --> 00:21:34,525\nwhen you make an animated thing out of images that kind\n\n430\n00:21:34,527 --> 00:21:37,495\nof are overlapping each other and moving around, right?\n\n431\n00:21:37,497 --> 00:21:40,097\nSome guy walking though a castle and you know,\n\n432\n00:21:40,099 --> 00:21:42,233\nyou find some monster, and he's fighting against it.\n\n433\n00:21:42,235 --> 00:21:45,536\nAnd it's not really being drawn in 3D like OpenGL.\n\n434\n00:21:45,538 --> 00:21:47,505\nIt's being drawn with images overlapping, but\n\n435\n00:21:47,507 --> 00:21:50,007\nthey're kind of 3D looking images. And so,\n\n436\n00:21:50,009 --> 00:21:53,611\nSpriteKit manages not just the overlapping images and\n\n437\n00:21:53,613 --> 00:21:56,080\nhow they all move around each other. But,\n\n438\n00:21:56,082 --> 00:21:57,615\nit also can do particles, so\n\n439\n00:21:57,617 --> 00:22:00,017\nyou can do things like explosions and fire and\n\n440\n00:22:00,019 --> 00:22:01,952\nall kinds of things. So, it's a really great thing for\n\n441\n00:22:01,954 --> 00:22:06,624\nbuilding You know these two and a half D like animated\n\n442\n00:22:06,626 --> 00:22:09,293\nthings, we're not gonna talk anything about that in this\n\n443\n00:22:09,295 --> 00:22:12,263\nclass sorry about it, there's gotta be limits and there's\n\n444\n00:22:12,265 --> 00:22:18,102\none of them. There's also for views dynamic animation and\n\n445\n00:22:18,104 --> 00:22:20,838\nthis is essentially animating using physics so\n\n446\n00:22:20,840 --> 00:22:23,441\nyou assign gravity and collision boundaries and\n\n447\n00:22:23,443 --> 00:22:27,511\nthings like that to views, and then you just say go, and\n\n448\n00:22:27,513 --> 00:22:30,748\ngravity starts pulling on it, and it hits the boundary and\n\n449\n00:22:30,750 --> 00:22:33,084\nit bounces off and things like that, okay?\n\n450\n00:22:33,086 --> 00:22:37,588\nSo it's physics-based animation of views.\n\n451\n00:22:37,590 --> 00:22:38,823\nThat I am going to talk about again.\n\n452\n00:22:38,825 --> 00:22:40,691\nI won't have time to get all the way through that, but\n\n453\n00:22:40,693 --> 00:22:43,527\nI have a big demo on that in the next lecture. But\n\n454\n00:22:43,529 --> 00:22:46,564\ntoday I'm going to focus on the UI View animation.\n\n455\n00:22:46,566 --> 00:22:50,534\nThe first one is this simple one where you can change\n\n456\n00:22:50,536 --> 00:22:53,037\nany of these three properties; frame, transform or\n\n457\n00:22:53,039 --> 00:22:58,042\nalpha. These are the primary ones you can change.\n\n458\n00:22:58,044 --> 00:23:00,678\nIt will animate the change, the from and\n\n459\n00:23:00,680 --> 00:23:04,348\nthe to, of the values of these three properties. So,\n\n460\n00:23:04,350 --> 00:23:06,984\nit's done with UIView class methods.\n\n461\n00:23:06,986 --> 00:23:11,255\nSo you say, UIView, dot, animate duration, okay?\n\n462\n00:23:11,257 --> 00:23:14,625\nAnd, inside there, you're going to provide a block.\n\n463\n00:23:14,627 --> 00:23:15,092\nAnd inside that block,\n\n464\n00:23:15,094 --> 00:23:18,729\nyou're gonna change one of these three things. Okay? And\n\n465\n00:23:18,731 --> 00:23:21,065\nit's going to animate that change over\n\n466\n00:23:21,067 --> 00:23:24,368\ntime. Okay? And it animates in a very configurable\n\n467\n00:23:24,370 --> 00:23:27,304\nway, as you will see. What's interesting, though, is, even\n\n468\n00:23:27,306 --> 00:23:29,807\nthough you're going to give a block to these methods and\n\n469\n00:23:29,809 --> 00:23:31,375\nit's going to animate these changes,\n\n470\n00:23:31,377 --> 00:23:34,912\nit's going to execute that block you give it immediately.\n\n471\n00:23:34,914 --> 00:23:37,548\nSo these values are going to change instantly to the end\n\n472\n00:23:37,550 --> 00:23:40,284\npoint of your animation. So even while the animation is\n\n473\n00:23:40,286 --> 00:23:41,919\nhappening on screen, they're already changed.\n\n474\n00:23:41,921 --> 00:23:44,388\nOkay, that's something really important to understand\n\n475\n00:23:44,390 --> 00:23:47,158\nabout how animation works in general, even core animation.\n\n476\n00:23:47,160 --> 00:23:48,793\nWhen you change things, they change immediately.\n\n477\n00:23:48,795 --> 00:23:52,296\nIt's, on screen is really just taking your time to show\n\n478\n00:23:52,298 --> 00:23:54,532\nthe user what the world looks like okay.\n\n479\n00:23:54,534 --> 00:23:57,201\nYou're not actually, the animation doesn't change\n\n480\n00:23:57,203 --> 00:24:00,404\nthe things over time, it only shows the change over time.\n\n481\n00:24:00,406 --> 00:24:02,306\nOkay, important thing to understand there. So\n\n482\n00:24:02,308 --> 00:24:04,975\nhere's the method, or one of the methods, kind of the one\n\n483\n00:24:04,977 --> 00:24:07,878\nwith the most arguments here, animate with duration right,\n\n484\n00:24:07,880 --> 00:24:12,183\nclass function on UI view. You can see here that it has\n\n485\n00:24:12,185 --> 00:24:14,718\na time interval for how long this animation's gonna take.\n\n486\n00:24:14,720 --> 00:24:17,288\nYou know, is it gonna take two seconds, half a second, or\n\n487\n00:24:17,290 --> 00:24:22,293\nwhatever? Also, you can delay the start of the animation,\n\n488\n00:24:22,295 --> 00:24:24,528\nlike start this animation two seconds from now.\n\n489\n00:24:24,530 --> 00:24:27,198\nWhy would you ever wanna delay that? Because maybe you're\n\n490\n00:24:27,200 --> 00:24:29,633\ngonna have some animation going on during that two\n\n491\n00:24:29,635 --> 00:24:33,037\nseconds, okay? So you might have three or four animations\n\n492\n00:24:33,039 --> 00:24:35,739\nthat you queue up, one of them to start in two seconds,\n\n493\n00:24:35,741 --> 00:24:37,475\none starts right now. It takes two seconds,\n\n494\n00:24:37,477 --> 00:24:39,877\nwhatever. You can do that, so that's why you might\n\n495\n00:24:39,879 --> 00:24:43,047\nwanna delay the start of it, then options we'll talk about\n\n496\n00:24:43,049 --> 00:24:45,282\nlater. Here's that block I'm talking about,\n\n497\n00:24:45,284 --> 00:24:48,886\nanimations this first green one here, takes no arguments,\n\n498\n00:24:48,888 --> 00:24:49,587\nreturns no arguments.\n\n499\n00:24:49,589 --> 00:24:52,289\nYou can put anything in you want in there that changes\n\n500\n00:24:52,291 --> 00:24:56,060\nthe frame, the transform, and the alpha, okay?\n\n501\n00:24:56,062 --> 00:25:00,130\nAnd then completion is another block, it has an argument to\n\n502\n00:25:00,132 --> 00:25:02,633\nthe block which is boolean, whether it finished\n\n503\n00:25:02,635 --> 00:25:06,704\nthis animation, you asked it to change to some end point,\n\n504\n00:25:06,706 --> 00:25:09,607\nif it got there with the animation, then this will be\n\n505\n00:25:09,609 --> 00:25:12,510\ncalled with this true. If it got interrupted somehow, and\n\n506\n00:25:12,512 --> 00:25:13,644\nI'll talk about how that can happen,\n\n507\n00:25:13,646 --> 00:25:16,447\nthen this will get called with this finish being false.\n\n508\n00:25:16,449 --> 00:25:19,683\nIn other words, I wasn't able to complete the animation\n\n509\n00:25:19,685 --> 00:25:22,720\nof those things you changed. All right, so\n\n510\n00:25:22,722 --> 00:25:25,689\nhere's an example of calling this. Let's say I have a view,\n\n511\n00:25:25,691 --> 00:25:28,392\nmy view, and it has an alpha of 1, in other words it's\n\n512\n00:25:28,394 --> 00:25:31,595\nfully opaque. And if I get to this piece of code, and\n\n513\n00:25:31,597 --> 00:25:35,032\nI find that my view is fully opaque, I'm going to make it\n\n514\n00:25:35,034 --> 00:25:37,935\nfully transparent and then remove it from the super,\n\n515\n00:25:37,937 --> 00:25:40,638\nfrom the view hierarchy, remove it from the super view.\n\n516\n00:25:40,640 --> 00:25:42,473\nOkay, take it right out of there. Okay,\n\n517\n00:25:42,475 --> 00:25:45,409\nthat's what I'm gonna do. So, I'm not gonna,\n\n518\n00:25:45,411 --> 00:25:48,479\nit's gonna take three seconds for it to fade away. Okay,\n\n519\n00:25:48,481 --> 00:25:51,315\nI'm gonna be animating Alpha here, but I'm not gonna start\n\n520\n00:25:51,317 --> 00:25:53,817\nfor another two seconds. I don't know why. Okay, and\n\n521\n00:25:53,819 --> 00:25:55,619\nagain, maybe I'm making the view spin around for\n\n522\n00:25:55,621 --> 00:25:59,089\na couple seconds before it animates out, I don't know.\n\n523\n00:25:59,091 --> 00:26:02,026\nHere are some options, for example, here the option I'm\n\n524\n00:26:02,028 --> 00:26:05,262\nusing is curve linear, that means the fade out is going\n\n525\n00:26:05,264 --> 00:26:07,998\nto happen linearly, okay, it's going to fade\n\n526\n00:26:08,000 --> 00:26:09,633\nout from 1.0 down to zero,\n\n527\n00:26:09,635 --> 00:26:12,803\nwhich is where we're going linearly, evenly.\n\n528\n00:26:12,805 --> 00:26:15,539\nOkay? Smoothly. There are other curves that you can do,\n\n529\n00:26:15,541 --> 00:26:19,910\nand I'll talk about that in a second. Here's my block.\n\n530\n00:26:19,912 --> 00:26:22,212\nIn my block, I just set my alpha to 0.\n\n531\n00:26:22,214 --> 00:26:25,649\nThat's where I want it to be eventually, okay? So\n\n532\n00:26:25,651 --> 00:26:27,851\nI set it to 0. Now again, when I call this,\n\n533\n00:26:27,853 --> 00:26:31,589\nit immediately sets alpha to 0. Alpha's not going to be set\n\n534\n00:26:31,591 --> 00:26:33,924\nto 0 in five seconds, it's going to be set to 0 now.\n\n535\n00:26:33,926 --> 00:26:36,694\nIt's just going to appear on screen in five seconds.\n\n536\n00:26:36,696 --> 00:26:39,897\nAnd in the completion here, I'm saying 'if $0', which\n\n537\n00:26:39,899 --> 00:26:43,267\nmeans if it finished, then remove it from the super view.\n\n538\n00:26:43,269 --> 00:26:45,869\nSo if this animation of the alpha got interrupted,\n\n539\n00:26:45,871 --> 00:26:48,872\nby some other animation, then I'm not going to remove myself\n\n540\n00:26:48,874 --> 00:26:50,341\nfrom the super view, I'm only going to do it if\n\n541\n00:26:50,343 --> 00:26:54,979\nI make it all the way down to zero. This block, is going\n\n542\n00:26:54,981 --> 00:26:58,115\nto be executed five seconds from now, or whenever this\n\n543\n00:26:58,117 --> 00:27:00,584\nanimation gets interrupted, if before then. Okay, so\n\n544\n00:27:00,586 --> 00:27:05,289\nthis block is going to be executed later. Notice that\n\n545\n00:27:05,291 --> 00:27:09,026\nI put 'print(\"myView.alpha =\\(myView.alpha)\"' there.\n\n546\n00:27:09,028 --> 00:27:12,262\nThis is going to print 'myView.alpha = 0' because\n\n547\n00:27:12,264 --> 00:27:15,232\nthis 'animateWithDuration' executes this block and\n\n548\n00:27:15,234 --> 00:27:18,202\nreturns immediately. So, myView.alpha is gonna be 0.\n\n549\n00:27:18,204 --> 00:27:22,973\nOkay? And it's gonna stay 0 all the way through this\n\n550\n00:27:22,975 --> 00:27:25,275\nfive seconds that it takes for this animation to happen\n\n551\n00:27:25,277 --> 00:27:27,277\nbecause this animation really has nothing to do,\n\n552\n00:27:27,279 --> 00:27:30,981\nhas no effect on the setting of alpha. It just,\n\n553\n00:27:30,983 --> 00:27:35,152\nis how we're presenting this change to the user. Okay\n\n554\n00:27:35,154 --> 00:27:37,287\nlet's talk about some of those options. There are tons and\n\n555\n00:27:37,289 --> 00:27:39,623\ntons of options. I'm not gonna go over all of them for\n\n556\n00:27:39,625 --> 00:27:43,293\ntime reasons here, but you saw a CurveLinear there.\n\n557\n00:27:43,295 --> 00:27:46,597\nSome other curves like CurveEaseinEaseout,\n\n558\n00:27:46,599 --> 00:27:49,333\nthat means it start off animating it slowly, and\n\n559\n00:27:49,335 --> 00:27:51,769\nthen picks up to a normal speed, and then slows down\n\n560\n00:27:51,771 --> 00:27:55,039\nagain at the end. That's an, curve that we usually use for\n\n561\n00:27:55,041 --> 00:27:57,574\nmoving things. Okay? If you have a view on screen and\n\n562\n00:27:57,576 --> 00:27:59,576\nyou want to move it, so you're changing its frame,\n\n563\n00:27:59,578 --> 00:28:02,112\nyou're animating its frame, you don't really want to go\n\n564\n00:28:02,114 --> 00:28:05,015\n[SOUND], okay? You kinda want it to pick up speed, move,\n\n565\n00:28:05,017 --> 00:28:07,351\nand then slow down at the end. Okay?\n\n566\n00:28:07,353 --> 00:28:10,721\nIt's just less abrupt, turns out, to do it that way.\n\n567\n00:28:10,723 --> 00:28:13,357\nSo you can specify that. Things like begin from current\n\n568\n00:28:13,359 --> 00:28:16,393\nstate that's an interesting one. If you have an animation\n\n569\n00:28:16,395 --> 00:28:18,862\nin motion let's say our animation before, let's say\n\n570\n00:28:18,864 --> 00:28:21,932\nwe're half way through showing the alpha going to zeros so\n\n571\n00:28:21,934 --> 00:28:24,668\nit's half transparent. And then some other animations\n\n572\n00:28:24,670 --> 00:28:27,805\ncomes along and wants to animate it going to full or\n\n573\n00:28:27,807 --> 00:28:31,308\npeak. Okay, if the other animation said begin from\n\n574\n00:28:31,310 --> 00:28:34,945\ncurrent state, then when it starts, it would start at 0.5,\n\n575\n00:28:34,947 --> 00:28:39,083\nalpha of 0.5. Okay, in other words it would grab onto\n\n576\n00:28:39,085 --> 00:28:41,685\nthe alpha of whatever animations and process.\n\n577\n00:28:41,687 --> 00:28:44,888\nYou can think of this as begin from current state means\n\n578\n00:28:44,890 --> 00:28:49,760\nuse the values of these in the animation world,\n\n579\n00:28:49,762 --> 00:28:51,428\nnot in the real world, because in the real world,\n\n580\n00:28:51,430 --> 00:28:55,099\nthe alpha is zero. It was zero as soon as I set it to zero.\n\n581\n00:28:55,101 --> 00:28:56,567\nSo, if you don't have BeginFromCurrentState,\n\n582\n00:28:56,569 --> 00:28:59,203\nthen this new one is gonna use the real world one, and\n\n583\n00:28:59,205 --> 00:29:01,505\nit's gonna be going to half transparent,\n\n584\n00:29:01,507 --> 00:29:04,041\nback to zero, up to one, okay?\n\n585\n00:29:04,043 --> 00:29:06,143\nBecause if you don't put that BeginFromCurrentState,\n\n586\n00:29:06,145 --> 00:29:09,480\nit pays no attention to what's going on in the animation\n\n587\n00:29:09,482 --> 00:29:11,648\nalone. AllowsUserInteraction, exactly what you think.\n\n588\n00:29:11,650 --> 00:29:13,484\nYou need to put gesture, you've got some view flying\n\n589\n00:29:13,486 --> 00:29:16,587\nacross the screen, can you touch on it while it's moving?\n\n590\n00:29:16,589 --> 00:29:18,589\nThat kind of stuff, you know auto reversing,\n\n591\n00:29:18,591 --> 00:29:21,125\ndoes the animation repeat all these things you can go look\n\n592\n00:29:21,127 --> 00:29:25,129\nthis up in the documentation of UIView. Okay.\n\n593\n00:29:25,131 --> 00:29:29,399\nSometimes you wanna make other changes to views, not frame,\n\n594\n00:29:29,401 --> 00:29:33,937\ntransform, or Alpha, okay? And you wanna animate the entire\n\n595\n00:29:33,939 --> 00:29:39,576\nchange in there In, at once with some kind of cool looking\n\n596\n00:29:39,578 --> 00:29:42,546\nthing on screen. For example, dissolve you'd want\n\n597\n00:29:42,548 --> 00:29:46,150\nto change to dissolve in from the old what it looked like\n\n598\n00:29:46,152 --> 00:29:48,185\nbefore to what it's going to look like have it dissolve\n\n599\n00:29:48,187 --> 00:29:50,687\nover time. Or have it flip over, like I'm gonna use\n\n600\n00:29:50,689 --> 00:29:53,524\nan example of a playing card. If you have a playing card and\n\n601\n00:29:53,526 --> 00:29:54,925\nyou change it from face down to face up,\n\n602\n00:29:54,927 --> 00:29:58,629\nyou'd like it to flip. Okay you don't want to just [NOISE]\n\n603\n00:29:58,631 --> 00:30:00,197\nchange to face up, that's very abrupt.\n\n604\n00:30:00,199 --> 00:30:02,800\nYou want it to kind of flip over. Okay. And there's even\n\n605\n00:30:02,802 --> 00:30:05,235\na curl up if you have a view that fills the whole screen,\n\n606\n00:30:05,237 --> 00:30:07,638\nit can curl up from the bottom like it's a piece of\n\n607\n00:30:07,640 --> 00:30:08,572\npaper that someone is looking under.\n\n608\n00:30:08,574 --> 00:30:12,176\nOkay you've probably seen that sometimes. You do this with\n\n609\n00:30:12,178 --> 00:30:16,480\nanother U-I view class method called transition with a view.\n\n610\n00:30:16,482 --> 00:30:21,485\nKay, you specify the view like a playing card view or\n\n611\n00:30:21,487 --> 00:30:27,224\nwhatever, so this is the view that's changing,\n\n612\n00:30:27,226 --> 00:30:30,160\nand this is duration of the animation just like we\n\n613\n00:30:30,162 --> 00:30:31,128\nhave the duration of the previous one,\n\n614\n00:30:31,130 --> 00:30:33,197\nhow long it's gonna take the card to flip over or\n\n615\n00:30:33,199 --> 00:30:36,934\nwhatever. More options the same options as before.\n\n616\n00:30:36,936 --> 00:30:40,437\nHere's the closure okay? This closure this green closure\n\n617\n00:30:40,439 --> 00:30:43,974\nhere it can change anything at once about the view okay?\n\n618\n00:30:43,976 --> 00:30:46,476\nBecause it doesn't have to be restricted to those three that\n\n619\n00:30:46,478 --> 00:30:48,478\nwe know because it's not gonna actually animate any\n\n620\n00:30:48,480 --> 00:30:51,348\nin between states. It's just gonna take the end state and\n\n621\n00:30:51,350 --> 00:30:53,784\nthe beginning state and flip between the two or\n\n622\n00:30:53,786 --> 00:30:56,320\ncross dissolve between the two. You see what I mean?\n\n623\n00:30:56,322 --> 00:30:58,255\nIt's not going to show intermediate positions of\n\n624\n00:30:58,257 --> 00:31:01,558\nthe frame moving around or anything like that, okay? Umm,\n\n625\n00:31:01,560 --> 00:31:05,128\nso this contains anything you want and it also gets executed\n\n626\n00:31:05,130 --> 00:31:09,066\nimmediately, okay, even though the animation will take time\n\n627\n00:31:09,068 --> 00:31:11,368\nto show the flip, the change gets made immediately.\n\n628\n00:31:11,370 --> 00:31:13,904\nAnd then here's completion, the same completion thing that\n\n629\n00:31:13,906 --> 00:31:15,906\nwill let you know whether it finished. This one is almost\n\n630\n00:31:15,908 --> 00:31:19,009\nalways going to finish here, it's hard to interrupt. And\n\n631\n00:31:19,011 --> 00:31:22,312\none like this. All right, so here's the playing card\n\n632\n00:31:22,314 --> 00:31:24,648\nexample. I've got my playing card view up here.\n\n633\n00:31:24,650 --> 00:31:26,950\nI'm gonna take a little less than a second.\n\n634\n00:31:26,952 --> 00:31:29,786\nI'm using the transition flip from left option.\n\n635\n00:31:29,788 --> 00:31:32,489\nSo, it's gonna flip my card over from the left edge being\n\n636\n00:31:32,491 --> 00:31:36,326\nlifted up and over. All I'm doing in my block is changing\n\n637\n00:31:36,328 --> 00:31:39,363\nsome attribute of my playing card view. Card is face up\n\n638\n00:31:39,365 --> 00:31:42,566\nto card is not face up, so I'm toggling card is face up,\n\n639\n00:31:42,568 --> 00:31:45,702\nnow when I do this that's going to change the whole look\n\n640\n00:31:45,704 --> 00:31:48,739\nof my playing card view from the back of the card to one\n\n641\n00:31:48,741 --> 00:31:52,175\nof the front, you know, cards face up. So essentially,\n\n642\n00:31:52,177 --> 00:31:54,578\nthe system's gonna take a snapshot of what it looked\n\n643\n00:31:54,580 --> 00:31:57,614\nlike before, take a snapshot of what it looked like after.\n\n644\n00:31:57,616 --> 00:32:00,517\nAnd then do a flip animation to show the new thing.\n\n645\n00:32:00,519 --> 00:32:04,788\nOr cross dissolve or whatever options teaches,\n\n646\n00:32:04,790 --> 00:32:07,758\nokay. So that's that.\n\n647\n00:32:08,327 --> 00:32:11,595\nNow if you're animating a change to the view hierarchy,\n\n648\n00:32:11,597 --> 00:32:13,230\nwhich is to say you've got a view in there and\n\n649\n00:32:13,232 --> 00:32:14,932\nyou're going to remove it from consumer view and\n\n650\n00:32:14,934 --> 00:32:17,868\nreplace it with another view, okay? You've got a view that\n\n651\n00:32:17,870 --> 00:32:21,338\nyou're gonna hide and unhide some other view in its place.\n\n652\n00:32:21,340 --> 00:32:22,506\nThen you're going to want to use this one,\n\n653\n00:32:22,508 --> 00:32:26,410\ntransitionFromView(toView So, the fromView is the view\n\n654\n00:32:26,412 --> 00:32:30,213\nthat's in the view hierarchy, that's going to leave or be\n\n655\n00:32:30,215 --> 00:32:33,617\nhidden. And the toView is the one that is going to appear.\n\n656\n00:32:33,619 --> 00:32:36,586\nAll right? And here's the time, and here's the options.\n\n657\n00:32:36,588 --> 00:32:38,889\nAnd here's the completion. Okay? Now if you use\n\n658\n00:32:38,891 --> 00:32:40,991\nthe option Show Hide Transition Views,\n\n659\n00:32:40,993 --> 00:32:43,327\nthen instead of removing it from view hierarchy and\n\n660\n00:32:43,329 --> 00:32:44,962\nadding the other one at the same place,\n\n661\n00:32:44,964 --> 00:32:46,863\nit'll actually just set dot hidden. Right?\n\n662\n00:32:46,865 --> 00:32:50,400\nRemember the dot hidden of our on a view, which makes it just\n\n663\n00:32:50,402 --> 00:32:52,002\nnot appear. It's still in the view hierarchy, but\n\n664\n00:32:52,004 --> 00:32:55,772\ndoesn't appear. This will set the .hidden of one, clear\n\n665\n00:32:55,774 --> 00:32:58,475\nthe .hidden of one and, set the .hidden of one to true and\n\n666\n00:32:58,477 --> 00:33:04,114\ntip the other one to false so that it appears. Okay. So,\n\n667\n00:33:04,116 --> 00:33:05,582\nthat's basically View Animation.\n\n668\n00:33:05,584 --> 00:33:07,317\nSo let me show you a demo of that.\n\n669\n00:33:07,319 --> 00:33:08,585\nAnd the demo we're going to do,\n\n670\n00:33:08,587 --> 00:33:09,453\ntwo parts here in Face View.\n\n671\n00:33:09,455 --> 00:33:13,123\nOne, we're gonna make our blinking actually, be smooth.\n\n672\n00:33:13,125 --> 00:33:14,958\nAnd to do that we're gonna use the flip. But\n\n673\n00:33:14,960 --> 00:33:17,527\ninstead of flip from left, I'm gonna do flip from top.\n\n674\n00:33:17,529 --> 00:33:19,429\nAs you can imagine, if you had the eye open and\n\n675\n00:33:19,431 --> 00:33:22,099\nyou flipped from top, it would, you know,\n\n676\n00:33:22,101 --> 00:33:24,968\nmore smoothly look like it's blinking. And\n\n677\n00:33:24,970 --> 00:33:27,571\nthen for the head shake, so I'm gonna have\n\n678\n00:33:27,573 --> 00:33:30,273\nthis face. It's only 2D, so to shake its head it has to turn\n\n679\n00:33:30,275 --> 00:33:34,044\nits head sideways like this. It's gonna shake its head,\n\n680\n00:33:34,046 --> 00:33:34,244\nand to do that,\n\n681\n00:33:34,246 --> 00:33:36,880\nI'm going to use the things where I change the transform,\n\n682\n00:33:36,882 --> 00:33:38,849\nwhich is the rotation of that view. Right,\n\n683\n00:33:38,851 --> 00:33:41,518\nremember transform is scale, rotation, and translation.\n\n684\n00:33:41,520 --> 00:33:43,620\nSo I'm going to change that to make it shake its head,\n\n685\n00:33:43,622 --> 00:33:46,556\nbasically. Okay, now that's an interesting one because\n\n686\n00:33:46,558 --> 00:33:49,159\nthere's actually multiple moves there, and we're going\n\n687\n00:33:49,161 --> 00:33:53,096\nto have to chain them together to make it shakes its head.\n\n688\n00:33:53,332 --> 00:33:58,135\nAll right, so let's go back over to A face view,\n\n689\n00:33:58,137 --> 00:34:01,004\nsame place we were there. Now,\n\n690\n00:34:01,006 --> 00:34:05,675\nto make face view eyes blink, all right, right here.\n\n691\n00:34:05,677 --> 00:34:11,281\nThese eyes need to be views. Okay, because I'm going to use\n\n692\n00:34:11,283 --> 00:34:14,985\nview animation. So if I want them to flip, okay, they're\n\n693\n00:34:14,987 --> 00:34:18,221\ngoing to have to be views. So I have to change my code. It\n\n694\n00:34:18,223 --> 00:34:22,325\nwill turn these eyes into sub views of my face view. Now,\n\n695\n00:34:22,327 --> 00:34:25,395\nit's really not gonna change the face view that much, okay.\n\n696\n00:34:25,397 --> 00:34:27,564\nLet's see what it's really like to do that. So\n\n697\n00:34:27,566 --> 00:34:30,934\nto save a little bit of time, I create an a Eyeview which\n\n698\n00:34:30,936 --> 00:34:33,070\nwe're gonna look at don't worry, okay. So\n\n699\n00:34:33,072 --> 00:34:34,504\nthis is Eyeview. It's just going to be\n\n700\n00:34:34,506 --> 00:34:38,775\na view that represents one of these eyes, okay. So,\n\n701\n00:34:38,777 --> 00:34:42,546\nlet's take a look at the eye view. Here it is right here.\n\n702\n00:34:42,548 --> 00:34:44,781\nThe eye view, this code in eye view is\n\n703\n00:34:44,783 --> 00:34:47,717\nidentical to the code I used to have in face view, or still\n\n704\n00:34:47,719 --> 00:34:49,719\nhave in face view which we're going to have to get rid of,\n\n705\n00:34:49,721 --> 00:34:52,022\nwhich is this path for eye. Remember path for\n\n706\n00:34:52,024 --> 00:34:55,092\neye? We got either a circle, or it was a line, depending\n\n707\n00:34:55,094 --> 00:34:57,694\non whether it was open or closed. If you look at this\n\n708\n00:34:57,696 --> 00:35:01,264\ncode here path for eye, it looks just like this.\n\n709\n00:35:01,266 --> 00:35:04,101\nOkay, now I had to bring over line with color and\n\n710\n00:35:04,103 --> 00:35:07,671\neyes open as VARs in my eye view, which I'll have to set\n\n711\n00:35:07,673 --> 00:35:10,006\nthose from here in my face view. Okay, so\n\n712\n00:35:10,008 --> 00:35:12,609\nI don't need this path for eye anymore, because I'm going to\n\n713\n00:35:12,611 --> 00:35:16,880\nuse subviews to draw my eyes. This is also good, another\n\n714\n00:35:16,882 --> 00:35:20,717\nway to show you using subviews of other views in code and\n\n715\n00:35:20,719 --> 00:35:23,320\nhow we do that. All right, so I don't need path for i,\n\n716\n00:35:23,322 --> 00:35:27,057\nI also don't need to do path for i stroke over here.\n\n717\n00:35:27,059 --> 00:35:30,227\nBecause I'm not drawing my i's in my drawRect anymore,\n\n718\n00:35:30,229 --> 00:35:34,631\nI'm letting a sub-view of mine draw them. Okay? All right, so\n\n719\n00:35:34,633 --> 00:35:38,235\nhow we gonna do this, thing here? So I have a little,\n\n720\n00:35:38,237 --> 00:35:41,471\nagain a little code here. That will, this little piece of\n\n721\n00:35:41,473 --> 00:35:44,341\ncode right here okay this is how we're gonna do this. One,\n\n722\n00:35:44,343 --> 00:35:47,377\nI'm creating a couple of vars one for the left eye one for\n\n723\n00:35:47,379 --> 00:35:52,015\nthe right eye. It's an EyeView right EyeView is just a UIView\n\n724\n00:35:52,017 --> 00:35:55,519\nokay that draws those eyes. So it's an EyeView, and\n\n725\n00:35:55,521 --> 00:35:58,889\nI'm creating it by calling this method create eye\n\n726\n00:35:58,891 --> 00:36:02,159\non myself. Now, I'm gonna take a time out\n\n727\n00:36:02,161 --> 00:36:04,361\nhere to talk about these lazys right here.\n\n728\n00:36:04,363 --> 00:36:07,831\nIf I take these lazys out, this will generate an error.\n\n729\n00:36:07,833 --> 00:36:11,801\nCan anyone tell me why that's an error right there?\n\n730\n00:36:13,639 --> 00:36:17,841\nNobody knows? What? >> [INAUDIBLE]\n\n731\n00:36:17,843 --> 00:36:18,742\n>> Yes. Exactly.\n\n732\n00:36:18,744 --> 00:36:22,012\nWe're in initialization right here. We're initializing these\n\n733\n00:36:22,014 --> 00:36:25,749\nduring initialization, self is not fully initialized.\n\n734\n00:36:25,751 --> 00:36:29,452\nWe can't send it any methods. We can't send create eye to\n\n735\n00:36:29,454 --> 00:36:32,889\nself right here in the middle of initialization. Okay?\n\n736\n00:36:32,891 --> 00:36:34,958\nThis is part of this class being initialized.\n\n737\n00:36:34,960 --> 00:36:36,526\nUntil the class is fully initialized,\n\n738\n00:36:36,528 --> 00:36:39,362\nwe can't call our own method. That's why putting,\n\n739\n00:36:39,364 --> 00:36:42,332\nby the way the error message you get in here\n\n740\n00:36:42,334 --> 00:36:45,001\nis kinda cryptic. So, kinda what it'd look like.\n\n741\n00:36:45,003 --> 00:36:47,804\nSo if you see something like this, all right?\n\n742\n00:36:47,806 --> 00:36:50,774\nThen you might get the idea, maybe it's that thing where\n\n743\n00:36:50,776 --> 00:36:54,377\nI'm trying to call a method on myself while I'm initializing.\n\n744\n00:36:54,379 --> 00:36:59,015\nSo why does putting lazy in here fix it? Because lazy\n\n745\n00:36:59,017 --> 00:37:04,020\nmeans that the initialization here doesn't happen until\n\n746\n00:37:04,022 --> 00:37:08,358\nsomeone asks for this var. Okay, until someone asks for\n\n747\n00:37:08,360 --> 00:37:10,260\nthe leftEye or asks for the rightEye,\n\n748\n00:37:10,262 --> 00:37:13,330\nthese =self.createEye are not gonna happen, and\n\n749\n00:37:13,332 --> 00:37:14,497\nno one is allowed to ask for\n\n750\n00:37:14,499 --> 00:37:20,103\nthese vars until this thing is fully initialized. So,\n\n751\n00:37:20,105 --> 00:37:20,403\nall is well.\n\n752\n00:37:20,405 --> 00:37:23,573\nBecause now we can call this createEye to initialize it. So\n\n753\n00:37:23,575 --> 00:37:27,711\nyou see how lazy gets you out of that little conundrum of,\n\n754\n00:37:27,713 --> 00:37:30,680\ninitializing there? And don't forget also you want to put\n\n755\n00:37:30,682 --> 00:37:34,651\nself dot right here when you're doing a createEye.\n\n756\n00:37:34,653 --> 00:37:36,786\nOkay? If you're gonna say this equals, you need to make it\n\n757\n00:37:36,788 --> 00:37:39,389\nclear in your initialization that you're accessing your\n\n758\n00:37:39,391 --> 00:37:44,394\nself. This creates each of these two eyes.\n\n759\n00:37:44,396 --> 00:37:47,264\nWhat does this create eye look like. Let's just create a new\n\n760\n00:37:47,266 --> 00:37:49,699\neye view. I'm just calling the initializer here.\n\n761\n00:37:49,701 --> 00:37:53,737\nI'm going to set it to be not opaque, because eye view\n\n762\n00:37:53,739 --> 00:37:56,439\ndoesn't draw background or have any background set, so\n\n763\n00:37:56,441 --> 00:37:57,741\nif there was something behind my eye view,\n\n764\n00:37:57,743 --> 00:38:00,510\nmaybe some eye shadow eyeliner or something,\n\n765\n00:38:00,512 --> 00:38:04,648\nit would show through. Also, I got to transfer the color and\n\n766\n00:38:04,650 --> 00:38:06,516\nthe line with on to the eye view, and\n\n767\n00:38:06,518 --> 00:38:09,419\nin fact, I need to do this not only here when I create it,\n\n768\n00:38:09,421 --> 00:38:12,822\nbut I probably want to do up here if someone sets the color\n\n769\n00:38:12,824 --> 00:38:16,393\nright here. In addition to doing set needs display,\n\n770\n00:38:16,395 --> 00:38:17,861\nI probably want to set my left\n\n771\n00:38:17,863 --> 00:38:19,362\neye's color equal to the color and\n\n772\n00:38:19,364 --> 00:38:24,768\nI want to set my right eye's Color equal to the color. And\n\n773\n00:38:24,770 --> 00:38:26,436\nsame thing here with line width,\n\n774\n00:38:26,438 --> 00:38:29,005\nin addition to set needs display left eye dot line\n\n775\n00:38:29,007 --> 00:38:34,177\nwidth goes to the line width. And right eye dot line width\n\n776\n00:38:34,179 --> 00:38:38,548\ngoes to the line width, and interestingly,\n\n777\n00:38:38,550 --> 00:38:42,085\neyes open. Of course, we also want to pass that along,\n\n778\n00:38:42,087 --> 00:38:45,021\nbut we don't actually need set needs display anymore for\n\n779\n00:38:45,023 --> 00:38:50,760\neyes open, do we? Because eyes open is no longer drawn by us.\n\n780\n00:38:50,762 --> 00:38:53,730\nSo if it changed, the eye view is the thing that\n\n781\n00:38:53,732 --> 00:38:53,763\nhere we just need to say lefteye.eyesopen = eyesOpen.\n\n782\n00:38:53,765 --> 00:38:59,102\nneeds to change, so\n\n783\n00:38:59,104 --> 00:39:02,906\nAnd rightEye.eyesOpen = eyesOpen,\n\n784\n00:39:02,908 --> 00:39:08,778\nokay? Since there and don't understand why we don't need\n\n785\n00:39:08,780 --> 00:39:10,914\nsetNeedsDisplay? Because we're not drawing the eyes anymore.\n\n786\n00:39:10,916 --> 00:39:15,151\nWe have a subview that does it for us now. Okay, so\n\n787\n00:39:15,153 --> 00:39:16,286\nhere we've got the eye created.\n\n788\n00:39:16,288 --> 00:39:18,621\nNow after we've set the color and line width,\n\n789\n00:39:18,623 --> 00:39:21,991\nthen we're just going to add it as a subview of ourselves,\n\n790\n00:39:21,993 --> 00:39:22,892\nwhich are great, okay. Now,\n\n791\n00:39:22,894 --> 00:39:27,530\na little bit of a problem here, where is this eye? Okay,\n\n792\n00:39:27,532 --> 00:39:28,932\nwe haven't specified where this eye.\n\n793\n00:39:28,934 --> 00:39:31,735\nWe created it with this initializer which doesn't\n\n794\n00:39:31,737 --> 00:39:35,105\nspecify the frame. So, it's like, we don't even know where\n\n795\n00:39:35,107 --> 00:39:38,041\nthis eye is. It's probably at zero, zero and it's also size\n\n796\n00:39:38,043 --> 00:39:40,677\nzero, zero. So, we obviously need to position and\n\n797\n00:39:40,679 --> 00:39:44,514\nsize each of these two eyes. Okay, to make this work. So\n\n798\n00:39:44,516 --> 00:39:48,218\nI created this little function right here to position an eye\n\n799\n00:39:48,220 --> 00:39:51,588\nokay, and it just takes the eye you want to position and\n\n800\n00:39:51,590 --> 00:39:54,824\nwhere you want the center of the eye to be. Okay, now it\n\n801\n00:39:54,826 --> 00:39:57,794\nknows the size the eye is supposed to be because it has\n\n802\n00:39:57,796 --> 00:39:59,662\nthis skull radius to eye radius thing, so\n\n803\n00:39:59,664 --> 00:40:02,665\nit's setting the size to that. And it creates a rectangle\n\n804\n00:40:02,667 --> 00:40:06,336\nthat's initially in the upper left with the proper size. And\n\n805\n00:40:06,338 --> 00:40:10,206\nthen it sets the eye center to be whatever center you wanted,\n\n806\n00:40:10,208 --> 00:40:13,309\nokay? So, trivial little piece of code that just positions\n\n807\n00:40:13,311 --> 00:40:15,945\nthe eye. So now the question is,\n\n808\n00:40:15,947 --> 00:40:19,482\nwhere do we call this position eye? Okay,\n\n809\n00:40:19,484 --> 00:40:24,120\nwhere do we set the position of these eyes. I can't do it\n\n810\n00:40:24,122 --> 00:40:28,024\nhere, this create eye is could be happening any time.\n\n811\n00:40:28,026 --> 00:40:29,993\nI don't what my bounds are at this point.\n\n812\n00:40:29,995 --> 00:40:32,395\nMight not even be, my bounds might be zero zero also, so\n\n813\n00:40:32,397 --> 00:40:35,665\nI don't even know where my eye goes, so that's no good.\n\n814\n00:40:35,667 --> 00:40:40,437\nThere's no view did layout sub views, okay. This is a UI\n\n815\n00:40:40,439 --> 00:40:44,841\nview, not UI view controller. Okay, so there's no view to,\n\n816\n00:40:44,843 --> 00:40:47,010\nthere's no view controller life cycle. We're in a view,\n\n817\n00:40:47,012 --> 00:40:49,813\nnot a view controller. So, we can't do that. I can't call it\n\n818\n00:40:49,815 --> 00:40:52,015\nfrom my controller. Here's my controller.\n\n819\n00:40:52,017 --> 00:40:55,552\nBecause my controller has no idea that faceView is using\n\n820\n00:40:55,554 --> 00:41:00,190\na subview to draw its eye. If you go look back in face view,\n\n821\n00:41:00,192 --> 00:41:03,493\nall this stuff about the eye, it's all private. Private.\n\n822\n00:41:03,495 --> 00:41:06,162\nPrivate. It's all private. So there's absolutely no way that\n\n823\n00:41:06,164 --> 00:41:10,934\nmy controller can reach down into me and do that. This\n\n824\n00:41:10,936 --> 00:41:14,337\nis going to show you how you find out when your view needs\n\n825\n00:41:14,339 --> 00:41:19,476\nto lay out it's subviews. It's a method called conveniently.\n\n826\n00:41:19,478 --> 00:41:21,711\nlayoutSubviews(). Okay? So,\n\n827\n00:41:21,713 --> 00:41:25,949\nlayoutSubviews() is the method in view that's called whenever\n\n828\n00:41:25,951 --> 00:41:29,686\nthe system wants the view to lay it's subviews out. Okay?\n\n829\n00:41:29,688 --> 00:41:32,255\nAnd those two eyes are subviews of ours. So we get to\n\n830\n00:41:32,257 --> 00:41:36,926\nlay them out. Okay? So, we'll call super.layoutSubviews().\n\n831\n00:41:36,928 --> 00:41:37,961\nAlways nice to do that,\n\n832\n00:41:37,963 --> 00:41:38,528\ndefinitely wanna do that for\n\n833\n00:41:38,530 --> 00:41:41,564\nthat. And then we're gonna position these eyes so\n\n834\n00:41:41,566 --> 00:41:44,367\nwe're just going to call it positionEye with position to\n\n835\n00:41:44,369 --> 00:41:48,771\nleftEye. Where does the leftEye center belong.\n\n836\n00:41:48,773 --> 00:41:51,207\nActually, believe it or not, from our old code,\n\n837\n00:41:51,209 --> 00:41:54,978\nwe have this getEyeCenter method here, okay. So\n\n838\n00:41:54,980 --> 00:41:57,580\nwe'll just use that that tells us the center of the eye.\n\n839\n00:41:57,582 --> 00:42:01,251\nAwesome. So we'll say GetEyeCenter,\n\n840\n00:42:01,253 --> 00:42:04,654\nthe left eye. Okay? And we'll do the same thing for\n\n841\n00:42:04,656 --> 00:42:12,428\nthe right eye. Okay? There we go.\n\n842\n00:42:12,430 --> 00:42:14,030\nSo be don't confused in the difference between layout\n\n843\n00:42:14,032 --> 00:42:16,466\nsubviews and view did layout subviews, okay?\n\n844\n00:42:16,468 --> 00:42:18,701\nIf you did layout subviews as part of the view controller\n\n845\n00:42:18,703 --> 00:42:20,537\nlife cycle, that's a view controller thing.\n\n846\n00:42:20,539 --> 00:42:23,573\nLayout subviews is a view method where a view's\n\n847\n00:42:23,575 --> 00:42:27,377\nbeing asked to actually lay it's subviews out, okay? Now,\n\n848\n00:42:27,379 --> 00:42:31,714\na lot of times your subviews get laid out by auto layout.\n\n849\n00:42:31,716 --> 00:42:34,150\nRight, in that case you don't need to do anything in layout\n\n850\n00:42:34,152 --> 00:42:38,121\nsubviews. But here these eyes, we can't really put an auto\n\n851\n00:42:38,123 --> 00:42:40,690\nlayout for the eyes, maybe we could I'd have to\n\n852\n00:42:40,692 --> 00:42:42,425\nthink about that actually, it might be possible,\n\n853\n00:42:42,427 --> 00:42:44,894\nbelieve it or not, but we're just going to do it in code,\n\n854\n00:42:44,896 --> 00:42:46,863\nso you can learn how to do it in code as well, and so\n\n855\n00:42:46,865 --> 00:42:48,798\nwhen layout subjects happen, we're just always going to be\n\n856\n00:42:48,800 --> 00:42:51,067\nmoving our eyes to the right thing. Layout subjects is\n\n857\n00:42:51,069 --> 00:42:53,503\nalways going to be called if our bounds changed. Because of\n\n858\n00:42:53,505 --> 00:42:55,838\nour balance change, we clearly need to lay our subviews out.\n\n859\n00:42:55,840 --> 00:42:59,075\nThis ads of view right here is gonna call layout subviews,\n\n860\n00:42:59,077 --> 00:43:01,010\nbecause layout subviews to be called. Because anytime you\n\n861\n00:43:01,012 --> 00:43:07,150\nchange your subviews you gotta lay them out again, okay?\n\n862\n00:43:07,152 --> 00:43:12,221\nAll right, so see if anything else we wanna do here.\n\n863\n00:43:12,223 --> 00:43:15,558\nI think that's pretty much everything. Hopefully\n\n864\n00:43:15,560 --> 00:43:19,596\nthis will work. Let's see if this works. I just want to\n\n865\n00:43:19,598 --> 00:43:21,397\nmake sure I haven't broken anything. Obviously,\n\n866\n00:43:21,399 --> 00:43:24,067\nwe haven't done any animation for the eye blinking here.\n\n867\n00:43:24,069 --> 00:43:28,905\nBut hopefully, we've replaced our view. Or our eyes, rather,\n\n868\n00:43:28,907 --> 00:43:32,809\nwith a view. And it looks like it's working, okay? Got these.\n\n869\n00:43:32,811 --> 00:43:33,309\nLet's see if we can rotate. Yep,\n\n870\n00:43:33,311 --> 00:43:37,080\nit's all still working. Okay, so we haven't broken anything.\n\n871\n00:43:37,082 --> 00:43:41,150\nSo now, we want to make these eyes animate closing and\n\n872\n00:43:41,152 --> 00:43:45,254\nopening, okay, by using that transition flip from top,\n\n873\n00:43:45,256 --> 00:43:46,756\nokay? So, how are we going to do that?\n\n874\n00:43:46,758 --> 00:43:48,891\nSo I'm going to do all that in the eye view,\n\n875\n00:43:48,893 --> 00:43:50,460\nI am going to be object oriented here.\n\n876\n00:43:50,462 --> 00:43:53,796\nThe animation of the eye, that's an eye thing so\n\n877\n00:43:53,798 --> 00:43:54,597\nit should be in the eye view,\n\n878\n00:43:54,599 --> 00:43:56,199\nthat shouldn't be in the face view. Okay,\n\n879\n00:43:56,201 --> 00:44:00,203\nto be in the EyeView. So we're gonna animate this thing right\n\n880\n00:44:00,205 --> 00:44:04,941\nhere, this eyesOpening, okay. We want to animate eyesOpen.\n\n881\n00:44:04,943 --> 00:44:06,142\nSo, how are we gonna animate eyesOpen?\n\n882\n00:44:06,144 --> 00:44:10,213\nWell, basically anytime an eyesOpen gets set, okay,\n\n883\n00:44:10,215 --> 00:44:12,815\nwe need to set it in an animated way. So I'd\n\n884\n00:44:12,817 --> 00:44:15,685\nalmost like to put something in didSet, except for\n\n885\n00:44:15,687 --> 00:44:19,322\ndidSet would be too late, because it already got set\n\n886\n00:44:19,324 --> 00:44:21,591\nOkay, I have to animate the setting of it.\n\n887\n00:44:21,593 --> 00:44:23,760\nI have to provide a little closure there, right,\n\n888\n00:44:23,762 --> 00:44:27,063\nto that animate method that does the setting of it. So\n\n889\n00:44:27,065 --> 00:44:28,431\nit did set a little too late.\n\n890\n00:44:28,433 --> 00:44:32,769\nSo I'm really gonna have to have eyesOpen via var\n\n891\n00:44:33,772 --> 00:44:38,341\nthat has its own get and set. So\n\n892\n00:44:38,343 --> 00:44:42,745\nthat in this set right here I can animate the setting, okay.\n\n893\n00:44:42,747 --> 00:44:46,015\nBut I still need storage for the eyes open so here's what\n\n894\n00:44:46,017 --> 00:44:48,351\nI'm gonna do, this trick. If you ever find yourself in\n\n895\n00:44:48,353 --> 00:44:52,221\na situation where you need to do something when something,\n\n896\n00:44:52,223 --> 00:44:55,024\nyou need to animate the setting of something or\n\n897\n00:44:55,026 --> 00:44:57,493\notherwise be Involved in the actual setting.\n\n898\n00:44:57,495 --> 00:45:00,530\nNot the react to the setting, this would didSet is for.\n\n899\n00:45:00,532 --> 00:45:03,800\nBut you actually have to do the setting of it. And you ni,\n\n900\n00:45:03,802 --> 00:45:07,770\nmake a public var like this that's computed. You can take\n\n901\n00:45:07,772 --> 00:45:09,906\nthe storage and put an under bar in front of it.\n\n902\n00:45:09,908 --> 00:45:12,475\nThat's kinda the convention we use to mean this is\n\n903\n00:45:12,477 --> 00:45:16,446\nthe storage for another property that is computed.\n\n904\n00:45:16,448 --> 00:45:20,316\nOkay? We just call underbar. So I still have_eyesOpen.\n\n905\n00:45:20,318 --> 00:45:24,754\nIt's just that I'm gonna set this, in here, animated.\n\n906\n00:45:24,756 --> 00:45:29,759\nRight? I'm gonna, say _eyesOpen = newValue in here.\n\n907\n00:45:29,761 --> 00:45:33,129\nBut I'm gonna have to animate this happening. Now the get is\n\n908\n00:45:33,131 --> 00:45:36,799\njust return_eyesOpen I don't have to animate the getting of\n\n909\n00:45:36,801 --> 00:45:40,970\nthis value. But this I have to animate. Okay, so I'm going to\n\n910\n00:45:40,972 --> 00:45:46,075\nanimate this of course using UI view, transition with view.\n\n911\n00:45:46,077 --> 00:45:48,978\nOkay so here's transition, see there's the with view on and\n\n912\n00:45:48,980 --> 00:45:52,315\nhere's the from view two view. So I'm going to use the with\n\n913\n00:45:52,317 --> 00:45:55,051\nview. And we'll do the same thing You do when there's\n\n914\n00:45:55,053 --> 00:45:58,354\nlots of arguments like this so you can see them all.\n\n915\n00:46:03,194 --> 00:46:07,096\nOkay, so we just have to animate the setting of this.\n\n916\n00:46:07,098 --> 00:46:12,301\nNow, let's start with the actual setting of this. That\n\n917\n00:46:12,303 --> 00:46:15,004\nhappens here in this block. You see this animations block,\n\n918\n00:46:15,006 --> 00:46:17,673\nright here? So I'm just going to double click on this block.\n\n919\n00:46:17,675 --> 00:46:20,843\nHere it is. And I'm gonna put, what I want to happen,\n\n920\n00:46:20,845 --> 00:46:25,481\ninside here. See? So I'm animating this change. Okay.\n\n921\n00:46:25,483 --> 00:46:28,985\nThis is gonna complain that this needs to be self. That's\n\n922\n00:46:28,987 --> 00:46:34,056\nbecause this is a closure. Okay? So we have to be clear.\n\n923\n00:46:34,058 --> 00:46:36,659\nNow, is there any problem with memory cycles here?\n\n924\n00:46:36,661 --> 00:46:40,563\nNo, because this animation's only going to take\n\n925\n00:46:40,565 --> 00:46:42,532\nless than a second and this this closure will be gone,\n\n926\n00:46:42,534 --> 00:46:45,568\nso there's no worries about someone holding onto it and\n\n927\n00:46:45,570 --> 00:46:49,739\nit pointing back to us and keeping a cycle there. So\n\n928\n00:46:49,741 --> 00:46:53,976\nwhat view are we doing this in? We're doing this in self,\n\n929\n00:46:53,978 --> 00:46:57,780\nit's the eye view itself that's being animated,\n\n930\n00:46:57,782 --> 00:47:02,218\nit's being flipped over. And the time interval? Well,\n\n931\n00:47:02,220 --> 00:47:05,521\nwe know that we close our eyes for 0.4, in 0.4 seconds, for\n\n932\n00:47:05,523 --> 00:47:09,192\n0.4 seconds. So, our time of causing the,\n\n933\n00:47:09,194 --> 00:47:11,160\nanimating the change better be less than that.\n\n934\n00:47:11,162 --> 00:47:13,996\nSo, maybe we'll say 0.2 seconds?\n\n935\n00:47:13,998 --> 00:47:16,866\nSomething like that. We could play with these numbers.\n\n936\n00:47:16,868 --> 00:47:18,768\nAgain, I should make a constant for this, but for\n\n937\n00:47:18,770 --> 00:47:22,004\ntime, I won't do it. The animation options here,\n\n938\n00:47:22,006 --> 00:47:26,475\nwe talked about. We want this transition, sure I find out\n\n939\n00:47:26,477 --> 00:47:29,312\nwhat it's called here. Transition flip from top,\n\n940\n00:47:29,314 --> 00:47:35,651\nI think it's called, yes. TransitionFlipFromTop, okay.\n\n941\n00:47:35,987 --> 00:47:38,221\nThe addition, and we could put other ones in here. Maybe we,\n\n942\n00:47:38,223 --> 00:47:43,092\nyou know, dot curve linear, or whatever. Put whatever\n\n943\n00:47:43,094 --> 00:47:48,064\nother options we want in here. And then completion. Once this\n\n944\n00:47:48,066 --> 00:47:51,734\nthing has closed we don't need to do anything. So\n\n945\n00:47:51,736 --> 00:47:57,540\nmy completion here is nil. Everybody cool with that?\n\n946\n00:47:57,542 --> 00:48:04,347\nAll right, let's see it work. All right, there it is.\n\n947\n00:48:04,349 --> 00:48:08,517\nSo you see how the eyes kind of, see how they're kind of\n\n948\n00:48:08,519 --> 00:48:11,787\nsquinching closed instead of jumping closed?\n\n949\n00:48:11,789 --> 00:48:18,461\nYeah? All right. So it's getting better by the second.\n\n950\n00:48:18,463 --> 00:48:20,363\nAll right, now let's do this head shake.\n\n951\n00:48:20,365 --> 00:48:22,131\nSo now I want this little head to, to shake.\n\n952\n00:48:22,133 --> 00:48:24,667\nI don't know, to say, like he's saying no or something.\n\n953\n00:48:24,669 --> 00:48:26,702\nI'm not sure what. But let's do the head shake. So\n\n954\n00:48:26,704 --> 00:48:30,239\nthe head shake, we're going to do by changing one of those\n\n955\n00:48:30,241 --> 00:48:31,274\nthree special properties,\n\n956\n00:48:31,276 --> 00:48:34,110\nnamely the transform. Okay, we're going to have\n\n957\n00:48:34,112 --> 00:48:35,945\nthe transform of that thing changed.\n\n958\n00:48:35,947 --> 00:48:36,779\nAnd I'm gonna do that, mm,\n\n959\n00:48:36,781 --> 00:48:38,481\nI'm gonna do that in my FaceView right here.\n\n960\n00:48:38,483 --> 00:48:40,816\nOkay, it doesn't really have anything to do with blinking,\n\n961\n00:48:40,818 --> 00:48:42,285\nso there's no reason to put it there. So\n\n962\n00:48:42,287 --> 00:48:46,422\nI can put it in my FaceView. And so let's do it so that\n\n963\n00:48:46,424 --> 00:48:50,760\nit shakes its head when we tap on it. Right now, when we tap\n\n964\n00:48:50,762 --> 00:48:54,630\non our FaceView, it does this, toggleEyes, right. If we\n\n965\n00:48:54,632 --> 00:48:56,365\ngo look at our storyboard right here and\n\n966\n00:48:56,367 --> 00:48:59,201\nwe look at this Tap Gesture Recognizer and right-click\n\n967\n00:48:59,203 --> 00:49:01,737\non it, you see that toggleEye is doing toggleEyes in\n\n968\n00:49:01,739 --> 00:49:04,840\nour FaceViewController. So I'm gonna disconnect that and\n\n969\n00:49:04,842 --> 00:49:07,977\ncreate a new thing, which is gonna be a head shake. Okay,\n\n970\n00:49:07,979 --> 00:49:11,881\nso let's do a head shake. Now, I want to put head shake into\n\n971\n00:49:11,883 --> 00:49:14,917\nthe FaceViewController superclass, okay?\n\n972\n00:49:14,919 --> 00:49:17,720\nI do not want head shake in BlinkingFaceViewController,\n\n973\n00:49:17,722 --> 00:49:20,389\nbecause it's not a blinking thing, it's nothing to do with\n\n974\n00:49:20,391 --> 00:49:23,559\nblinking, okay. But when I have this on automatic up\n\n975\n00:49:23,561 --> 00:49:27,763\nhere, okay, it picks the BlinkingFaceViewController.\n\n976\n00:49:27,765 --> 00:49:33,970\nSo how can I Ctrl+drag to put this in the superclass?\n\n977\n00:49:33,972 --> 00:49:36,772\nThe answer is, just go to Manual. Okay,\n\n978\n00:49:36,774 --> 00:49:37,807\nif you go to Manual over here and\n\n979\n00:49:37,809 --> 00:49:41,243\npick the FaceViewController and then you try to Ctrl+drag\n\n980\n00:49:41,245 --> 00:49:44,413\nin here, we'll put it right near toggle eyes, right here,\n\n981\n00:49:44,415 --> 00:49:49,018\nit's going to work. Because Xcode is smart enough to know\n\n982\n00:49:49,020 --> 00:49:51,921\nthat even though this is a BlinkingFaceViewController\n\n983\n00:49:51,923 --> 00:49:56,058\nyou're connecting it to one of its superclasses.\n\n984\n00:49:56,060 --> 00:50:00,129\nOkay, so we'll make a tap gesture action here,\n\n985\n00:50:00,131 --> 00:50:04,100\nwe'll call it headShake. Okay, to tap gesture, right?\n\n986\n00:50:04,102 --> 00:50:08,571\nThere's our tap gesture right there. Let's go ahead and\n\n987\n00:50:08,573 --> 00:50:11,374\nget the wider screen here. So,\n\n988\n00:50:11,376 --> 00:50:14,377\nlike a real wide screen. All right, so here's headShake.\n\n989\n00:50:14,379 --> 00:50:15,778\nThis is going to happen when we tap,\n\n990\n00:50:15,780 --> 00:50:19,448\nokay? So here's where we need to modify our transform,\n\n991\n00:50:19,450 --> 00:50:21,350\nand we want it, we know we want it to be animated,\n\n992\n00:50:21,352 --> 00:50:24,086\nso let's start right off the bat by doing our\n\n993\n00:50:24,088 --> 00:50:25,988\nUIView.animateWithDuration. Now,\n\n994\n00:50:25,990 --> 00:50:29,191\nyou'll notice there's quite a few animateWithDurations here.\n\n995\n00:50:29,193 --> 00:50:34,296\nThere's even one down here that has springiness in it so\n\n996\n00:50:34,298 --> 00:50:36,465\nthat you can animate things springing,\n\n997\n00:50:36,467 --> 00:50:41,103\nthings like that. But we're gonna pick the simplest one,\n\n998\n00:50:41,105 --> 00:50:44,373\nwhich is right here, almost [INAUDIBLE].\n\n999\n00:50:44,375 --> 00:50:49,645\nLet's do the same thing where we put this on separate lines.\n\n1000\n00:50:50,481 --> 00:50:52,381\nAll right, so here's our animateWithDuration.\n\n1001\n00:50:52,383 --> 00:50:56,619\nSo here I am going to make a little private struct, struct,\n\n1002\n00:50:56,621 --> 00:51:01,090\nwhich I'm gonna have be my animation constants. And so\n\n1003\n00:51:01,092 --> 00:51:06,328\nlet's do static let, let's have the ShakeAngle. So that's\n\n1004\n00:51:06,330 --> 00:51:09,398\ngonna be the angle of the head that we're going to shake, and\n\n1005\n00:51:09,400 --> 00:51:13,102\nwe'll go, let's see. It's gonna be a CGFloat. It,\n\n1006\n00:51:13,104 --> 00:51:17,640\nlet's go pi over 6. It's gonna be in radians, so we'll do pi\n\n1007\n00:51:17,642 --> 00:51:20,676\nover 6, which is a little bit of a head shake there.\n\n1008\n00:51:20,678 --> 00:51:24,380\nAnd then I'm also gonna have the shake duration,\n\n1009\n00:51:24,382 --> 00:51:27,616\nhow long it takes to move. And for that one,\n\n1010\n00:51:27,618 --> 00:51:28,851\nlet's do maybe half a second.\n\n1011\n00:51:28,853 --> 00:51:31,187\nSo it's gonna do half a second to move each direction.\n\n1012\n00:51:31,189 --> 00:51:35,191\nSo it'll take about a second a half to do the full shake,\n\n1013\n00:51:35,193 --> 00:51:39,161\nokay. So here, let's use our duration here, which is\n\n1014\n00:51:39,163 --> 00:51:43,032\nAnimation.ShakeDuration. And here's\n\n1015\n00:51:43,034 --> 00:51:45,734\nour animation, okay, so we're gonna put our animation. This\n\n1016\n00:51:45,736 --> 00:51:48,871\nis where we're gonna change one of those three special\n\n1017\n00:51:48,873 --> 00:51:51,474\nthings. And then here's our completion,\n\n1018\n00:51:51,476 --> 00:51:54,610\nwhich is gonna have this finished boolean and\n\n1019\n00:51:54,612 --> 00:51:58,314\nthen some code here when we're finished, okay?\n\n1020\n00:51:58,316 --> 00:52:01,917\nAnd actually, in this case, I'm not going to, well, yeah.\n\n1021\n00:52:01,919 --> 00:52:05,121\nI'm not gonna use closing trailing syntax here.\n\n1022\n00:52:05,123 --> 00:52:07,857\nThis is an interesting thing to talk about. So\n\n1023\n00:52:07,859 --> 00:52:11,527\nthis is one of the few times when I don't like the trailing\n\n1024\n00:52:11,529 --> 00:52:14,730\nclosure syntax here, because there's really nothing special\n\n1025\n00:52:14,732 --> 00:52:16,232\nabout this closure versus this closure,\n\n1026\n00:52:16,234 --> 00:52:19,168\nthey're kinda equal in power, maybe this one's even\n\n1027\n00:52:19,170 --> 00:52:22,138\nmore powerful. So I'm gonna keep them all inside here,\n\n1028\n00:52:22,140 --> 00:52:26,308\njust kinda, to me, I think it reads a little better. But\n\n1029\n00:52:26,310 --> 00:52:26,675\nit's totally a style thing,\n\n1030\n00:52:26,677 --> 00:52:28,944\nwhatever you wanna do. All right, so in here,\n\n1031\n00:52:28,946 --> 00:52:30,446\nwe get to change one of these three things. Well,\n\n1032\n00:52:30,448 --> 00:52:34,917\nI'm gonna change the transform of this, of our FaceView.\n\n1033\n00:52:34,919 --> 00:52:35,518\nSo I'm gonna say face, oops,\n\n1034\n00:52:35,520 --> 00:52:38,120\nand I'm gonna do self because I'm in a closure here.\n\n1035\n00:52:38,122 --> 00:52:42,224\nfaceView.transform, and I'm gonna use this nice,\n\n1036\n00:52:42,226 --> 00:52:47,696\nfunction called CGAffineTransformRotate.\n\n1037\n00:52:47,698 --> 00:52:48,831\nIt takes an existing transform,\n\n1038\n00:52:48,833 --> 00:52:52,568\nwhich I'm gonna take the FaceView's existing transform.\n\n1039\n00:52:52,570 --> 00:52:55,404\nOkay, transform, is, remember, it's just a var in UIView,\n\n1040\n00:52:55,406 --> 00:52:58,641\nthat's all it is is a var, and it encapsulates the rotation,\n\n1041\n00:52:58,643 --> 00:53:01,010\nscaling, and translation, okay. So\n\n1042\n00:53:01,012 --> 00:53:04,346\nwe're gonna be messing with the rotation here. And it's,\n\n1043\n00:53:04,348 --> 00:53:07,950\nwe'll rotate it by this angle which we know is our\n\n1044\n00:53:07,952 --> 00:53:11,554\nAnimation.Head, or, ShakeAngle.\n\n1045\n00:53:13,291 --> 00:53:17,660\nOkay? So that's going to do the rotation there. All right,\n\n1046\n00:53:17,662 --> 00:53:20,329\nlet's see, what do we got here, what are we missing?\n\n1047\n00:53:20,331 --> 00:53:25,434\nCompletion. Yeah, sorry. Completion.\n\n1048\n00:53:25,436 --> 00:53:28,470\nIt's part of that trailing closure syntax, it deleted\n\n1049\n00:53:28,472 --> 00:53:31,774\nthe last keyword. All right, so everyone cool with this?\n\n1050\n00:53:31,776 --> 00:53:35,644\nNow, what to do in here, we'll see later, okay. First we're\n\n1051\n00:53:35,646 --> 00:53:37,913\ngonna see if this is working at all. So we're gonna see,\n\n1052\n00:53:37,915 --> 00:53:40,382\nthis is only doing the first part of the head shake, so\n\n1053\n00:53:40,384 --> 00:53:42,818\nlet's see if that animation works.\n\n1054\n00:53:46,624 --> 00:53:48,257\nOkay, so our eyes, our eyes are still blinking,\n\n1055\n00:53:48,259 --> 00:53:51,527\nthey're still doing the flip from top. And if we click,\n\n1056\n00:53:51,529 --> 00:53:54,830\nsure enough, it rotated it by pi over 6.\n\n1057\n00:53:54,832 --> 00:53:55,331\nIn fact, if we click again,\n\n1058\n00:53:55,333 --> 00:53:58,367\nit'll keep on rotating. Now, notice the other animation\n\n1059\n00:53:58,369 --> 00:54:00,970\nkeeps working completely independently. Okay, all\n\n1060\n00:54:00,972 --> 00:54:04,006\nanimations, they, completely independent. They're only\n\n1061\n00:54:04,008 --> 00:54:06,842\ngonna start interacting with each other if you're animating\n\n1062\n00:54:06,844 --> 00:54:09,278\nthe same thing, the same transform, the same alpha or\n\n1063\n00:54:09,280 --> 00:54:12,147\nwhatever. Here these are completely different views,\n\n1064\n00:54:12,149 --> 00:54:15,217\nokay, and even though that view is being transformed,\n\n1065\n00:54:15,219 --> 00:54:17,319\nit still continued to flip from top, okay,\n\n1066\n00:54:17,321 --> 00:54:20,155\nwhich is kinda cool, it lets you make, lets you build\n\n1067\n00:54:20,157 --> 00:54:22,691\nyour UI animation very object-oriented. Just make\n\n1068\n00:54:22,693 --> 00:54:26,462\neach piece animate however it wants to animate. Okay, but\n\n1069\n00:54:26,464 --> 00:54:29,064\nour head shake, it needs to turn back the other way and\n\n1070\n00:54:29,066 --> 00:54:31,100\nthen back to the middle. So how are we gonna do that?\n\n1071\n00:54:31,102 --> 00:54:35,271\nWell, it can't turn back to the other side until it's\n\n1072\n00:54:35,273 --> 00:54:38,073\nfinished turning to the right. Okay? So\n\n1073\n00:54:38,075 --> 00:54:42,311\nwe're gonna use the completion block to animate it going back\n\n1074\n00:54:42,313 --> 00:54:44,847\nthe other way. So as soon as it's finished, if it's\n\n1075\n00:54:44,849 --> 00:54:50,052\nsuccessfully moved over, if it finished. If it finished,\n\n1076\n00:54:50,054 --> 00:54:51,387\nthen we're gonna animate back.\n\n1077\n00:54:51,389 --> 00:54:53,722\nWell, how the heck are we gonna animate back? Well,\n\n1078\n00:54:53,724 --> 00:54:57,593\nlet's just copy and paste this, because we know this,\n\n1079\n00:54:57,595 --> 00:55:00,162\nright, this whole thing right here does an animation. So\n\n1080\n00:55:00,164 --> 00:55:02,798\nwe wanna do almost the exact same animation. I'm just gonna\n\n1081\n00:55:02,800 --> 00:55:06,368\ncopy and paste it right in there. The only difference is\n\n1082\n00:55:06,370 --> 00:55:08,637\nthat instead of the shake angle going to the right,\n\n1083\n00:55:08,639 --> 00:55:13,108\nnow it wants to go backwards times two. Okay, it wants to\n\n1084\n00:55:13,110 --> 00:55:16,512\ngo all the way back past the middle and to the other side.\n\n1085\n00:55:16,514 --> 00:55:18,981\nAnd then sure enough, when that one's finished,\n\n1086\n00:55:18,983 --> 00:55:21,383\nwe want to do it again and get back to the middle.\n\n1087\n00:55:21,385 --> 00:55:24,486\nSo we're just doing three transforms here, and\n\n1088\n00:55:24,488 --> 00:55:28,457\nwe're just chaining them, okay, in the completion blocks\n\n1089\n00:55:28,459 --> 00:55:32,494\nof each of them, we're just doing the next animation. That\n\n1090\n00:55:32,496 --> 00:55:35,431\nmake sense? Right? So that's how we chain animations.\n\n1091\n00:55:35,433 --> 00:55:40,969\nSo let's see if that works. All right?\n\n1092\n00:55:40,971 --> 00:55:42,638\nSo, here we go, he's blinking, and\n\n1093\n00:55:42,640 --> 00:55:48,143\nhe shakes his head. And again, we could play with this,\n\n1094\n00:55:48,145 --> 00:55:51,313\ndo we want to curve in, ease in, ease out. Do we want to\n\n1095\n00:55:51,315 --> 00:55:53,682\ntake a little longer maybe to swing back over.\n\n1096\n00:55:53,684 --> 00:55:57,186\nAnd so you can play with those numbers really easy in here\n\n1097\n00:55:57,188 --> 00:56:00,489\njust by setting options or Or durations. I didn't use\n\n1098\n00:56:00,491 --> 00:56:03,692\nthe version of animate durations that had the options\n\n1099\n00:56:03,694 --> 00:56:07,296\nas an argument, but you could certainly add that back in,\n\n1100\n00:56:07,298 --> 00:56:10,165\nokay? Any questions about that? You getting a good feel\n\n1101\n00:56:10,167 --> 00:56:15,304\nfor this whole UI view based animation? All right. Okay,\n\n1102\n00:56:15,306 --> 00:56:21,043\nin the time we have remaining here, hopefully I can get\n\n1103\n00:56:21,045 --> 00:56:26,815\nus going on this next kind of animation which is this\n\n1104\n00:56:26,817 --> 00:56:30,119\nphysic based one. So now let's talk more about animation.\n\n1105\n00:56:30,121 --> 00:56:31,954\nWe're gonna talk about dynamic animation,\n\n1106\n00:56:31,956 --> 00:56:35,557\nwhich is this physics based animation and it's a little\n\n1107\n00:56:35,559 --> 00:56:37,626\ndifferent approach than the UIView-based. The\n\n1108\n00:56:37,628 --> 00:56:40,229\nUIView-based, your pretty much directly changing the things\n\n1109\n00:56:40,231 --> 00:56:42,931\nyou wanna change and then animating that change, okay.\n\n1110\n00:56:42,933 --> 00:56:45,868\nHere you're just describing how things interact and\n\n1111\n00:56:45,870 --> 00:56:49,304\nthen letting them go, okay? However they, they wanna go\n\n1112\n00:56:49,306 --> 00:56:53,208\nbased on whatever restrictions and physics you put upon them,\n\n1113\n00:56:53,210 --> 00:56:56,145\nokay? So, here's how you do dynamic animation, here's\n\n1114\n00:56:56,147 --> 00:56:59,348\nthe steps. One, you're gonna create a UIDynamicAnimator.\n\n1115\n00:56:59,350 --> 00:57:01,750\nThis is the thing that does the animation. Very simple\n\n1116\n00:57:01,752 --> 00:57:05,421\nobject to create, it, but very powerful implementation,\n\n1117\n00:57:05,423 --> 00:57:07,890\nit's the thing that actually is doing the animation.\n\n1118\n00:57:07,892 --> 00:57:11,493\nThen you're gonna create UIDynamicBehaviors and\n\n1119\n00:57:11,495 --> 00:57:15,397\nadd them to the animator. Behaviors are things like,\n\n1120\n00:57:15,399 --> 00:57:19,334\ngravity is a behavior. Collisions are a behavior.\n\n1121\n00:57:19,336 --> 00:57:22,438\nPushing things is a behavior, okay?\n\n1122\n00:57:22,440 --> 00:57:25,140\nThen you're gonna add UIDynamicItems, which\n\n1123\n00:57:25,142 --> 00:57:28,911\nare usually UIViews, but not always, but 90% of the time.\n\n1124\n00:57:28,913 --> 00:57:32,047\nYou're gonna add those to the behaviors, and that's gonna\n\n1125\n00:57:32,049 --> 00:57:34,516\nmake those behaviors start acting on those items,\n\n1126\n00:57:34,518 --> 00:57:36,852\nokay? So it's a three way thing there. Items get\n\n1127\n00:57:36,854 --> 00:57:39,721\nadded to behaviors, behaviors get added to the animator and\n\n1128\n00:57:39,723 --> 00:57:41,190\nas soon as those are all hooked up,\n\n1129\n00:57:41,192 --> 00:57:43,225\nthings will just start moving, okay?\n\n1130\n00:57:43,227 --> 00:57:44,393\nNothing else, you don't need to say go.\n\n1131\n00:57:44,395 --> 00:57:46,128\nIt just automatically goes. As soon as you add it,\n\n1132\n00:57:46,130 --> 00:57:50,199\nit starts going. All right, so let's talk about each of those\n\n1133\n00:57:50,201 --> 00:57:52,734\nsteps. First creating the dynamic animator,\n\n1134\n00:57:52,736 --> 00:57:56,605\nthere's only two initializers of it. One takes no arguments,\n\n1135\n00:57:56,607 --> 00:57:58,407\nthat just creates a dynamic animator. But\n\n1136\n00:57:58,409 --> 00:58:02,044\nif you're animating views, if the UIDynamic items you want\n\n1137\n00:58:02,046 --> 00:58:05,447\nto animate are views, then you're going to want to create\n\n1138\n00:58:05,449 --> 00:58:09,084\nit with a referenceView, okay? And that's just gonna be like\n\n1139\n00:58:09,086 --> 00:58:12,521\nyour top level view, usually, where all the animation is\n\n1140\n00:58:12,523 --> 00:58:16,225\nhappening. All right? So that's it.\n\n1141\n00:58:16,227 --> 00:58:16,291\nThat's easy,\n\n1142\n00:58:16,293 --> 00:58:19,127\nit couldn't be easier creating a UIDynamicAnimator.\n\n1143\n00:58:19,129 --> 00:58:21,964\nNext you're gonna create the DynamicBehaviors, okay.\n\n1144\n00:58:21,966 --> 00:58:23,532\nThe behaviors, generally you create,\n\n1145\n00:58:23,534 --> 00:58:27,002\ntheir initializers take no arguments, okay? And so\n\n1146\n00:58:27,004 --> 00:58:30,439\nyou just create them, and add them to the animator here\n\n1147\n00:58:30,441 --> 00:58:32,608\nusing addBehavior, this addBehavior method.\n\n1148\n00:58:32,610 --> 00:58:36,378\nNow, oftentimes, you'll create something like gravity or\n\n1149\n00:58:36,380 --> 00:58:38,647\nthe collider there and you're going to configure it.\n\n1150\n00:58:38,649 --> 00:58:41,350\nBecause the gravity can be strong gravity or light\n\n1151\n00:58:41,352 --> 00:58:43,785\ngravity, like Martian gravity or Earth gravity, okay?\n\n1152\n00:58:43,787 --> 00:58:46,455\nYou can change that. Same thing with collider obviously.\n\n1153\n00:58:46,457 --> 00:58:49,391\nYou've got to decide what's gonna collide with what, okay?\n\n1154\n00:58:49,393 --> 00:58:52,461\nBut once you create them, you're going to just add them\n\n1155\n00:58:52,463 --> 00:58:54,730\nto the animator using addBehavior. And\n\n1156\n00:58:54,732 --> 00:58:58,200\nthen you add the dynamic items to the behavior and you do\n\n1157\n00:58:58,202 --> 00:59:01,703\nthat with addItem on the behavior. So gravity.addItem,\n\n1158\n00:59:01,705 --> 00:59:04,573\ncollider.addItem, gravity.addItem 2. Now if you\n\n1159\n00:59:04,575 --> 00:59:08,010\ndid these three things right here, notice that item1 and\n\n1160\n00:59:08,012 --> 00:59:11,213\nitem2 would both be affected by gravity cuz I added them to\n\n1161\n00:59:11,215 --> 00:59:15,450\nthat. But notice that item2 would not collide with item1.\n\n1162\n00:59:15,452 --> 00:59:18,887\nIf item2 and item1 came, next to each other on screen,\n\n1163\n00:59:18,889 --> 00:59:21,456\nthey'd pass right through because they're not\n\n1164\n00:59:21,458 --> 00:59:25,661\nboth being affected by the same collider, okay?\n\n1165\n00:59:25,663 --> 00:59:26,895\nNow if I said collider add item2,\n\n1166\n00:59:26,897 --> 00:59:29,264\nthen they would smash into each other and\n\n1167\n00:59:29,266 --> 00:59:34,102\nbounce off, okay? So, which, behaviors you add, which\n\n1168\n00:59:34,104 --> 00:59:38,040\nitems to really determines how they're gonna interact.\n\n1169\n00:59:38,042 --> 00:59:40,609\nAll right, so UIDynamicItem, I keep mentioning this.\n\n1170\n00:59:40,611 --> 00:59:43,612\nWhat is this? I said that usually this would be views,\n\n1171\n00:59:43,614 --> 00:59:48,450\nUIViews. But UIDynamicItem is actually a protocol, okay? And\n\n1172\n00:59:48,452 --> 00:59:52,254\nit has these three vars in it, bounds, which is the bounds of\n\n1173\n00:59:52,256 --> 00:59:57,626\nthe thing being animated, notice that that is get only,\n\n1174\n00:59:57,628 --> 01:00:03,699\nokay? You cannot animate the bounds of something\n\n1175\n01:00:03,701 --> 01:00:07,536\nin the animator. However, you can animate the center,\n\n1176\n01:00:07,538 --> 01:00:09,805\nwhich is where it is, because that one is get and\n\n1177\n01:00:09,807 --> 01:00:13,575\nset, okay? So the position of something in the animation\n\n1178\n01:00:13,577 --> 01:00:16,078\nworld is animatable, but not the bounds. In other words,\n\n1179\n01:00:16,080 --> 01:00:21,550\nnot the size, okay? However, the transform which\n\n1180\n01:00:21,552 --> 01:00:26,355\nviews have is settable. So you can rotate things, okay?\n\n1181\n01:00:26,357 --> 01:00:31,293\nAnd scale them, things like that, as part of the animation\n\n1182\n01:00:31,295 --> 01:00:35,464\nas well. So, this like I said, is usually a UIView but\n\n1183\n01:00:35,466 --> 01:00:37,899\nyou could actually animate off screen things or\n\n1184\n01:00:37,901 --> 01:00:40,469\nthings that you draw on screen using sprites or\n\n1185\n01:00:40,471 --> 01:00:45,741\nsomething else, using this whole mechanism as well, okay.\n\n1186\n01:00:45,743 --> 01:00:48,243\nBut in this class you are only gonna do UIViews,\n\n1187\n01:00:48,245 --> 01:00:51,213\nit's the most straightforward obvious way to do it.\n\n1188\n01:00:51,215 --> 01:00:53,248\nNow if you think about these being UIViews, and\n\n1189\n01:00:53,250 --> 01:00:55,250\nthey've been added to all these behaviors. And\n\n1190\n01:00:55,252 --> 01:00:57,719\ngravity is pulling on them, and they're colliding on,\n\n1191\n01:00:57,721 --> 01:01:00,088\noff each other and bouncing and moving all around.\n\n1192\n01:01:00,090 --> 01:01:02,591\nMaybe they're spinning around because they hit a corner or\n\n1193\n01:01:02,593 --> 01:01:05,327\nsomething. Their transform is being changed.\n\n1194\n01:01:05,329 --> 01:01:08,296\nIf you want to change any of those views, if you want to\n\n1195\n01:01:08,298 --> 01:01:12,100\nchange their transform or center, okay. Then you have to\n\n1196\n01:01:12,102 --> 01:01:15,270\nlet the animator know, otherwise, it's gonna be\n\n1197\n01:01:15,272 --> 01:01:17,939\nchanging them to something else. And you do that\n\n1198\n01:01:17,941 --> 01:01:20,442\nby sending this message to the animator which is\n\n1199\n01:01:20,444 --> 01:01:23,578\nupdateItemUsingCurrentState. When you pass the item, this\n\n1200\n01:01:23,580 --> 01:01:27,115\nwould be a UIView, right, cuz UIView implements in protocol.\n\n1201\n01:01:27,117 --> 01:01:30,485\nAnd, then it will pick up whatever the current state is.\n\n1202\n01:01:30,487 --> 01:01:33,622\nSo if you move the view to a certain spot the animator\n\n1203\n01:01:33,624 --> 01:01:36,291\nwhich moved the item to the spot in its world and\n\n1204\n01:01:36,293 --> 01:01:40,395\nthen keep applying all the behaviors to it, okay? But\n\n1205\n01:01:40,397 --> 01:01:41,229\nit you don't do this,\n\n1206\n01:01:41,231 --> 01:01:43,665\nyou're gonna be fighting the animator. Okay,\n\n1207\n01:01:43,667 --> 01:01:46,902\nso don't fight the animator, work with the animator.\n\n1208\n01:01:47,638 --> 01:01:49,471\nOkay, so let's talk about some of these behaviors in\n\n1209\n01:01:49,473 --> 01:01:54,276\ndetail here. Gravity behavior, so gravity isn't always down.\n\n1210\n01:01:54,278 --> 01:01:56,978\nOkay, gravity can mean any direction you want. Okay,\n\n1211\n01:01:56,980 --> 01:02:00,415\nyou specify the direction with this angle right here,\n\n1212\n01:02:00,417 --> 01:02:05,020\nangles in radians, 0 is off to the right. So if you set your\n\n1213\n01:02:05,022 --> 01:02:08,056\ngravity angle to 0 and put some views on there, as long\n\n1214\n01:02:08,058 --> 01:02:10,025\nas your magnitude is greater than 0 everything starts\n\n1215\n01:02:10,027 --> 01:02:13,528\nsliding off, accelerating off, cuz gravity is acceleration.\n\n1216\n01:02:13,530 --> 01:02:14,529\nRight everyone know what gravity is?\n\n1217\n01:02:14,531 --> 01:02:17,432\nIt's acceleration of gravity, 9.8 meters per second squared,\n\n1218\n01:02:17,434 --> 01:02:19,634\nright? So it's gonna start accelerating\n\n1219\n01:02:19,636 --> 01:02:22,237\noff to the right. So if you wanted it going down,\n\n1220\n01:02:22,239 --> 01:02:25,507\nlet's say, down towards the home button,\n\n1221\n01:02:25,509 --> 01:02:29,978\nthen you would want it to be what, three pi over two or\n\n1222\n01:02:29,980 --> 01:02:32,147\nsomething like that? Yeah, three pi over two I guess,\n\n1223\n01:02:32,149 --> 01:02:34,549\nI know my radians. Cuz you want it pointing all the way\n\n1224\n01:02:34,551 --> 01:02:38,653\nto down, okay. We're gonna talk about next week,\n\n1225\n01:02:38,655 --> 01:02:42,090\nwhat if you wanted it pointing where real gravity was. And\n\n1226\n01:02:42,092 --> 01:02:43,792\nonce you know core motion, and you know how to use\n\n1227\n01:02:43,794 --> 01:02:46,061\nthe accelerometer that's in the device you could actually\n\n1228\n01:02:46,063 --> 01:02:49,631\nbe constantly setting this gravity to be actual gravity.\n\n1229\n01:02:49,633 --> 01:02:51,166\nAnd so all your things could fall and\n\n1230\n01:02:51,168 --> 01:02:52,067\nno matter way they turn their phone,\n\n1231\n01:02:52,069 --> 01:02:55,871\nthings could fall down towards the Earth. And then magnitude\n\n1232\n01:02:55,873 --> 01:02:59,574\nis how, how fast the acceleration is happening.\n\n1233\n01:02:59,576 --> 01:03:00,375\nWhat's interesting is 1.0,\n\n1234\n01:03:00,377 --> 01:03:05,580\nthe magnitude of 1.0 is 1000 points per second squared.\n\n1235\n01:03:05,582 --> 01:03:07,883\nOkay, it's accelerating 1000 points a second,\n\n1236\n01:03:07,885 --> 01:03:10,819\nper second, that's how fast it's accelerating.\n\n1237\n01:03:10,821 --> 01:03:15,423\nThis looks amazingly like 9.8 meters per second squared.\n\n1238\n01:03:15,425 --> 01:03:17,959\nOkay, if you put something the top of your screen and\n\n1239\n01:03:17,961 --> 01:03:20,595\nlet it fall at this magnitude, it'll fall\n\n1240\n01:03:20,597 --> 01:03:23,632\nvery similar to how a real object would fall in space.\n\n1241\n01:03:23,634 --> 01:03:26,101\nAnd it's amazing that this round number is so\n\n1242\n01:03:26,103 --> 01:03:30,906\nclose to 9.8 meters per second squared. But it's not,\n\n1243\n01:03:30,908 --> 01:03:34,309\nit's not the same thing, but it's close. All right,\n\n1244\n01:03:34,311 --> 01:03:36,945\nUI attachment behaviors. So what is this behavior?\n\n1245\n01:03:36,947 --> 01:03:40,749\nThis behavior allows you to take two items or an item and\n\n1246\n01:03:40,751 --> 01:03:43,351\na point and attach them. Basically attach\n\n1247\n01:03:43,353 --> 01:03:45,253\nthem with like an iron bar between them. But\n\n1248\n01:03:45,255 --> 01:03:49,157\nthe bar can pivot at either side, either at the point or\n\n1249\n01:03:49,159 --> 01:03:51,793\nat the item or at the two items can pivot.\n\n1250\n01:03:51,795 --> 01:03:53,762\nSo basically if you wanna think about two items,\n\n1251\n01:03:53,764 --> 01:03:56,164\nthose two items will always stay the same distance apart\n\n1252\n01:03:56,166 --> 01:03:59,467\nno matter what's happening to them. Okay? Now, if you had\n\n1253\n01:03:59,469 --> 01:04:02,604\na point, a fixed point, in an item, and this item had\n\n1254\n01:04:02,606 --> 01:04:05,507\ngravity and an attachment behavior going onto it,\n\n1255\n01:04:05,509 --> 01:04:09,511\nit would fall down and swing. See why? Cuz it's always\n\n1256\n01:04:09,513 --> 01:04:11,847\nattached to this point, but gravity is pulling it down,\n\n1257\n01:04:11,849 --> 01:04:15,851\nand eventually it would settle down. That make sense? So\n\n1258\n01:04:15,853 --> 01:04:18,086\nattachment is basically a way to attach two things, or\n\n1259\n01:04:18,088 --> 01:04:19,788\nattach something to a point. Now, what's\n\n1260\n01:04:19,790 --> 01:04:23,558\nreally cool about it is, while things are happening, you can\n\n1261\n01:04:23,560 --> 01:04:26,328\nchange the length of that attachment. Okay?\n\n1262\n01:04:26,330 --> 01:04:29,231\nRight, right in the middle, so it's falling down,\n\n1263\n01:04:29,233 --> 01:04:32,534\nyou could just pull it up in close. Like a yo-yo. Right?\n\n1264\n01:04:32,536 --> 01:04:34,502\nIf you're doing yo-yo, you throw it around, and\n\n1265\n01:04:34,504 --> 01:04:37,772\nyou start pulling in, while it's still turning? Okay.\n\n1266\n01:04:37,774 --> 01:04:38,039\nYou can do the same thing.\n\n1267\n01:04:38,041 --> 01:04:41,977\nYou could build Yoyo quite easily here, by changing\n\n1268\n01:04:41,979 --> 01:04:45,981\nthe length of the attachment. Okay, the anchor point, okay,\n\n1269\n01:04:45,983 --> 01:04:48,083\nif you have a point and an item, that can also change.\n\n1270\n01:04:48,085 --> 01:04:50,085\nIt's like maybe it's attached to the finger,\n\n1271\n01:04:50,087 --> 01:04:52,821\nusing a gesture. And you're moving your finger around and\n\n1272\n01:04:52,823 --> 01:04:55,790\nthe attachment changing, is pulling the thing around with\n\n1273\n01:04:55,792 --> 01:04:57,893\nit. Okay, and I'm actually going to show that.\n\n1274\n01:04:57,895 --> 01:05:00,795\nIn the demo on Wednesday. So there's a lot of power in\n\n1275\n01:05:00,797 --> 01:05:04,232\nan attachment behavior. Collision behaviors.\n\n1276\n01:05:04,234 --> 01:05:06,468\nAnother thing,obviously, that you want. Right?\n\n1277\n01:05:06,470 --> 01:05:09,237\nLet's say you're gonna build your homework six which is\n\n1278\n01:05:09,239 --> 01:05:11,706\na breakout game. Okay? Obviously the breakout game\n\n1279\n01:05:11,708 --> 01:05:14,175\nwants to collide with the bricks and knock them out, and\n\n1280\n01:05:14,177 --> 01:05:16,411\nwants to bounce of the edge and bounce off the paddle.\n\n1281\n01:05:16,413 --> 01:05:19,814\nSo you need these collisions, right? There you can either\n\n1282\n01:05:19,816 --> 01:05:22,317\nhave things colliding off of boundaries so\n\n1283\n01:05:22,319 --> 01:05:25,053\nlike in your breakout game the bricks would probably be these\n\n1284\n01:05:25,055 --> 01:05:27,422\nfixed boundaries. Okay your paddle's probably\n\n1285\n01:05:27,424 --> 01:05:29,791\na boundary that you're moving all right or\n\n1286\n01:05:29,793 --> 01:05:32,427\nit can bounce off other things that are being animated.\n\n1287\n01:05:32,429 --> 01:05:34,996\nAlthough you wouldn't want your bricks to do that because\n\n1288\n01:05:34,998 --> 01:05:36,331\nyour bricks when you hit them they disappear.\n\n1289\n01:05:36,333 --> 01:05:39,467\nThey don't go flying off the screen okay they They despair\n\n1290\n01:05:39,469 --> 01:05:42,270\nwell maybe would have a flat screen, I don't know.\n\n1291\n01:05:42,272 --> 01:05:46,741\nSo collision lets you set up collisions between boundaries\n\n1292\n01:05:46,743 --> 01:05:51,379\nor between items, okay. You can have as many items as you\n\n1293\n01:05:51,381 --> 01:05:52,981\nwant in there, things all bouncing off each other,\n\n1294\n01:05:52,983 --> 01:05:54,582\nthe demo I'm going to do on Wednesday we're gonna have\n\n1295\n01:05:54,584 --> 01:05:57,352\na lot of things colliding with each other.\n\n1296\n01:05:57,354 --> 01:05:58,320\nThere's a nice little var here,\n\n1297\n01:05:58,322 --> 01:06:01,423\na bool translates reference bounce into boundary. And\n\n1298\n01:06:01,425 --> 01:06:04,693\nwhat that'll do it'll make a boundary which is the edge\n\n1299\n01:06:04,695 --> 01:06:06,828\nof your animator's reference view right?\n\n1300\n01:06:06,830 --> 01:06:09,264\nSo the reference view remember at the beginning of this that\n\n1301\n01:06:09,266 --> 01:06:10,899\nkind of contains the whole space.\n\n1302\n01:06:10,901 --> 01:06:13,134\nYou can make it so that it's basically a box. So everything\n\n1303\n01:06:13,136 --> 01:06:16,104\nthat happens in the animation world as long as you add it to\n\n1304\n01:06:16,106 --> 01:06:21,676\nthis collision behavior will stay inside that box okay?\n\n1305\n01:06:22,579 --> 01:06:25,280\nOne thing that's nice to know about the collision is when\n\n1306\n01:06:25,282 --> 01:06:27,882\na collision happens. And the collision behavior has\n\n1307\n01:06:27,884 --> 01:06:31,886\na delegate, okay, which lets you find out when a collision\n\n1308\n01:06:31,888 --> 01:06:34,689\nhappens. So you get this delegate method sent to you\n\n1309\n01:06:34,691 --> 01:06:37,926\ncollision behavior. Here's the behavior that sent me to you.\n\n1310\n01:06:37,928 --> 01:06:41,162\nAnd it'll tell you that contact began or ended for\n\n1311\n01:06:41,164 --> 01:06:45,000\nan item with a boundary, or for an item with another item.\n\n1312\n01:06:45,002 --> 01:06:48,837\nSo there's the thing with item as well. Notice\n\n1313\n01:06:48,839 --> 01:06:54,009\nthe type of this with boundary identifier. NScopying okay.\n\n1314\n01:06:54,011 --> 01:06:59,614\nNScopying is there for historical reasons but\n\n1315\n01:06:59,616 --> 01:07:01,216\nsuffice it to say NSstring and\n\n1316\n01:07:01,218 --> 01:07:05,387\nNSnumber are what's intended to be passed there. And\n\n1317\n01:07:05,389 --> 01:07:07,789\nwe know that those are bridged to string and Int and\n\n1318\n01:07:07,791 --> 01:07:10,892\nDouble, nicely bridged. So you can pass strings and doubles,\n\n1319\n01:07:10,894 --> 01:07:14,829\nthe only tricky thing is that you're gonna have to use as\n\n1320\n01:07:14,831 --> 01:07:18,133\nto cast this to be a string or an Int or a Double okay\n\n1321\n01:07:18,135 --> 01:07:24,139\nbecause it's an NSCopying. Small quirk of the API there.\n\n1322\n01:07:24,141 --> 01:07:27,242\nNext behavior is SnapBehavior. This is how you move something\n\n1323\n01:07:27,244 --> 01:07:29,944\nto a new location. So, you got something sitting there and\n\n1324\n01:07:29,946 --> 01:07:31,813\nyou want it, move it over here, okay.\n\n1325\n01:07:31,815 --> 01:07:35,316\nAnd, it's called SnapBehavior because it moves over there\n\n1326\n01:07:35,318 --> 01:07:38,219\nbut when it gets there it's like it's attached with\n\n1327\n01:07:38,221 --> 01:07:41,022\nfour springs to its corners so that it gets there and\n\n1328\n01:07:41,024 --> 01:07:44,359\ngoes [NOISE]. It vibrates a little bit. It doesn't just\n\n1329\n01:07:44,361 --> 01:07:48,863\nslide up and get stuck. It slides kind of softly.\n\n1330\n01:07:48,865 --> 01:07:51,566\nYou can say how much the springs are dampened,\n\n1331\n01:07:51,568 --> 01:07:53,334\nwhether it really shakes when it gets there, or\n\n1332\n01:07:53,336 --> 01:07:56,738\nif you get a slight shake or whatever. But snap behavior's\n\n1333\n01:07:56,740 --> 01:07:59,741\nkinda the preferred way to move something from one place\n\n1334\n01:07:59,743 --> 01:08:02,811\nto another, okay. Now a lot of things might be moving cuz\n\n1335\n01:08:02,813 --> 01:08:05,213\nthey have gravity and other things bouncing on them. But\n\n1336\n01:08:05,215 --> 01:08:06,714\nsometimes you have a stationary thing that you want\n\n1337\n01:08:06,716 --> 01:08:10,151\nto move and snap behavior is a good way to do that.\n\n1338\n01:08:10,153 --> 01:08:13,588\nThen there's push behavior, okay. Push behavior means push\n\n1339\n01:08:13,590 --> 01:08:16,891\non this thing, okay, and you can either push it once and\n\n1340\n01:08:16,893 --> 01:08:20,829\nsee what happens to it or you can continue to push on it,\n\n1341\n01:08:20,831 --> 01:08:25,633\nokay. So that's continuous versus instantaneous pushing.\n\n1342\n01:08:25,635 --> 01:08:27,502\nAnd you just specify the direction or\n\n1343\n01:08:27,504 --> 01:08:30,472\nyou can do an angle and a magnitude kind of like you\n\n1344\n01:08:30,474 --> 01:08:33,007\ndo with gravity and it's going to push in that direction.\n\n1345\n01:08:33,009 --> 01:08:34,843\nSo, for example, let's say you had a view, and\n\n1346\n01:08:34,845 --> 01:08:36,878\ngravity is working on it, so it's falling down the screen,\n\n1347\n01:08:36,880 --> 01:08:39,447\nand you pushed up on it with a certain amount of force.\n\n1348\n01:08:39,449 --> 01:08:42,684\nIt would fly back up, but then gravity would still be working\n\n1349\n01:08:42,686 --> 01:08:43,585\non it, so it would come back down.\n\n1350\n01:08:43,587 --> 01:08:46,888\nSee what I mean? So pushing imparts a certain\n\n1351\n01:08:46,890 --> 01:08:50,492\nforce to it, but if it's an instantaneous push it's not\n\n1352\n01:08:50,494 --> 01:08:52,694\ngoing to apply that force after the initial push and\n\n1353\n01:08:52,696 --> 01:08:57,065\nother forces are going to continue to work on it. Right.\n\n1354\n01:08:57,067 --> 01:08:57,565\nOkay?\n\n1355\n01:08:57,567 --> 01:09:01,669\nNow it's an interesting about push behaviors is that if\n\n1356\n01:09:01,671 --> 01:09:05,140\nthey're instantaneous once you push on them you kind of want\n\n1357\n01:09:05,142 --> 01:09:07,208\nto remove them as behaviors cuz they're dead.\n\n1358\n01:09:07,210 --> 01:09:09,077\nThey're never gonna push again. And\n\n1359\n01:09:09,079 --> 01:09:10,378\ninstance behavior only and\n\n1360\n01:09:10,380 --> 01:09:12,147\ninstantaneous behavior only pushes one and\n\n1361\n01:09:12,149 --> 01:09:15,650\nthen it's done so you want to really remove that behavior.\n\n1362\n01:09:15,652 --> 01:09:18,887\nAnd doing that you kind of do that in an unusual way.\n\n1363\n01:09:18,889 --> 01:09:20,255\nAnd I'm gonna talk about that in a few slides,\n\n1364\n01:09:20,257 --> 01:09:25,193\nafter I talk about a different method in a second. Then\n\n1365\n01:09:25,195 --> 01:09:27,695\nthere's this behavior. Okay, we're talking about behaviors,\n\n1366\n01:09:27,697 --> 01:09:28,863\nright, for gravity and collisions.\n\n1367\n01:09:28,865 --> 01:09:30,965\nHere's one called UIDynamicItemBehavior.\n\n1368\n01:09:30,967 --> 01:09:33,635\nAnd this is kind of a meta behavior, okay.\n\n1369\n01:09:33,637 --> 01:09:37,038\nThis has a bunch of vars like allowsRotation, friction,\n\n1370\n01:09:37,040 --> 01:09:41,209\nelasticity. These are settings that you make, okay, that, so\n\n1371\n01:09:41,211 --> 01:09:43,845\nall the items that are added to this behavior will kind of\n\n1372\n01:09:43,847 --> 01:09:48,416\nhave these attributes. Okay. They'll be allowed to rotate,\n\n1373\n01:09:48,418 --> 01:09:48,650\nthey'll have a certain friction.\n\n1374\n01:09:48,652 --> 01:09:52,220\nThey'll have a certain elasticity when they bounce of\n\n1375\n01:09:52,222 --> 01:09:56,191\nother things, okay? So these are really kind of effect,\n\n1376\n01:09:56,193 --> 01:10:01,196\naffecting other behaviors. Behaviors.\n\n1377\n01:10:01,198 --> 01:10:04,632\nSo you can think of this as a configuration behavior.\n\n1378\n01:10:04,634 --> 01:10:08,169\nYou really are probably only going to have one.\n\n1379\n01:10:08,171 --> 01:10:10,338\nEach item will in one item behavior.\n\n1380\n01:10:10,340 --> 01:10:12,974\nIt is actually legal to have multiple item\n\n1381\n01:10:12,976 --> 01:10:16,144\nbehaviors on same items. But you better be sure that you\n\n1382\n01:10:16,146 --> 01:10:18,846\nunderstand how they are interacting with each other.\n\n1383\n01:10:18,848 --> 01:10:22,951\nGenerally though we think of them as just settings. For\n\n1384\n01:10:22,953 --> 01:10:25,286\nthe items, how they're gonna behave with collisions and\n\n1385\n01:10:25,288 --> 01:10:28,356\nall these other things. The UIDynamicItemBehavior,\n\n1386\n01:10:28,358 --> 01:10:29,424\nyou almost always have one, by the way,\n\n1387\n01:10:29,426 --> 01:10:32,026\ncuz you want to set these things. It's also really cool,\n\n1388\n01:10:32,028 --> 01:10:34,596\nbecause you can ask the dynamic item behavior for\n\n1389\n01:10:34,598 --> 01:10:36,731\nany item that's added to that behavior.\n\n1390\n01:10:36,733 --> 01:10:40,735\nYou can say, what's its current linear velocity?\n\n1391\n01:10:40,737 --> 01:10:43,671\nI got some viewage bouncing along the screen because it\n\n1392\n01:10:43,673 --> 01:10:46,441\ncollided and gravity's pulling on it and\n\n1393\n01:10:46,443 --> 01:10:47,675\nI want to know what's it's velocity?\n\n1394\n01:10:47,677 --> 01:10:50,278\nRight now at this instant, how fast is it moving and in what\n\n1395\n01:10:50,280 --> 01:10:53,681\ndirection? Okay, so that's really nice to know especially\n\n1396\n01:10:53,683 --> 01:10:56,818\nif you're gonna pause your game. Or pause what's going on\n\n1397\n01:10:56,820 --> 01:11:00,388\nand then continue. You want to grab its linear velocity,\n\n1398\n01:11:00,390 --> 01:11:03,324\nstop the animation and when it starts again set the linear\n\n1399\n01:11:03,326 --> 01:11:06,527\nvelocity back to what it was, cause you can set it as well,\n\n1400\n01:11:06,529 --> 01:11:08,263\nby adding linear velocity back in.\n\n1401\n01:11:08,265 --> 01:11:11,099\nYou can also find angular velocity, if the thing is\n\n1402\n01:11:11,101 --> 01:11:14,269\nspinning, k how fast it's spinning, spinning really fast\n\n1403\n01:11:14,271 --> 01:11:19,274\nor just kind of slowly rotating, whatever okay.\n\n1404\n01:11:20,110 --> 01:11:23,177\nUI dynamic behavior as opposed to UI dynamic\n\n1405\n01:11:23,179 --> 01:11:25,680\nitem behavior the last I was here UI dynamic item behavior.\n\n1406\n01:11:25,682 --> 01:11:28,650\nThis is UI dynamic behavior. This is the super class of all\n\n1407\n01:11:28,652 --> 01:11:33,621\nbehaviors okay? And you can create your own behaviors as\n\n1408\n01:11:33,623 --> 01:11:38,393\na composite of other behaviors by using this addChildBehavior\n\n1409\n01:11:38,395 --> 01:11:40,895\nmethod and UIDynamicBehavior. So you simply\n\n1410\n01:11:40,897 --> 01:11:44,699\nsubclass UIDynamicBehavior, addChildBehavior for\n\n1411\n01:11:44,701 --> 01:11:47,402\nall the composite behaviors you want. The gravity and\n\n1412\n01:11:47,404 --> 01:11:50,605\nthe dynamic item behaviors and collision, whatever.\n\n1413\n01:11:50,607 --> 01:11:51,639\nYou add all those child behaviors.\n\n1414\n01:11:51,641 --> 01:11:55,543\nAnd then add any items to all of those behaviors, and you've\n\n1415\n01:11:55,545 --> 01:11:59,213\ncreated a composite new kind of behavior, which collects\n\n1416\n01:11:59,215 --> 01:12:02,250\nall those into one. And if we have some set of behaviors\n\n1417\n01:12:02,252 --> 01:12:05,119\nthat's operating on a whole bunch of items, we are very\n\n1418\n01:12:05,121 --> 01:12:08,056\noften going to create our own little composite subclass.\n\n1419\n01:12:08,058 --> 01:12:11,159\nAnd I'll do that in the demo cuz it's pretty common, okay?\n\n1420\n01:12:11,161 --> 01:12:14,962\nOne thing that's cool about UIDynamicBehavior is it has\n\n1421\n01:12:14,964 --> 01:12:17,999\na var called DynamicAnimator, which will get you\n\n1422\n01:12:18,001 --> 01:12:21,102\nthe UIDynamicAnimator that this behavior is in.\n\n1423\n01:12:21,104 --> 01:12:23,971\nBecause remember we add behaviors to dynamic animators\n\n1424\n01:12:23,973 --> 01:12:25,773\nas like the second slide I showed you.\n\n1425\n01:12:25,775 --> 01:12:27,342\nSo you can find out what it is. And\n\n1426\n01:12:27,344 --> 01:12:30,311\nin fact it'll even tell you if you move to an animator.\n\n1427\n01:12:30,313 --> 01:12:33,348\nThat's usually you, the animator being taken away from\n\n1428\n01:12:33,350 --> 01:12:35,316\nyou because they wanna stop animation, or\n\n1429\n01:12:35,318 --> 01:12:37,885\nadd it back to you to continue animation, okay? So\n\n1430\n01:12:37,887 --> 01:12:42,090\nthat's a good way to find out that that's happening. Okay,\n\n1431\n01:12:42,092 --> 01:12:46,561\nUIDynamicBehavior also has a really cool var\n\n1432\n01:12:46,563 --> 01:12:50,965\ncalled action which is a closure, okay?\n\n1433\n01:12:50,967 --> 01:12:54,402\nYou can set this closure to anything you want and\n\n1434\n01:12:54,404 --> 01:12:56,671\nevery time this behavior does anything,\n\n1435\n01:12:56,673 --> 01:13:00,575\nit's gonna call this closure. So some behaviors call this\n\n1436\n01:13:00,577 --> 01:13:03,811\nthing all the time cuz they're always acting on\n\n1437\n01:13:03,813 --> 01:13:07,382\nthe particular items, okay? So you wawnna be careful to make\n\n1438\n01:13:07,384 --> 01:13:09,917\nsure whatever's in this closure is really efficient.\n\n1439\n01:13:09,919 --> 01:13:12,787\nThis is one of those cases where you do wanna kinda\n\n1440\n01:13:12,789 --> 01:13:15,990\nthink about optimizing prematurely here because\n\n1441\n01:13:15,992 --> 01:13:16,824\nthis could be called a lot.\n\n1442\n01:13:16,826 --> 01:13:18,960\nSo you don't wanna do anything expensive in here.\n\n1443\n01:13:18,962 --> 01:13:22,296\nOkay, but it's really kinda cool because you can then\n\n1444\n01:13:22,298 --> 01:13:25,433\ndo things as the animation is happening, finding as things\n\n1445\n01:13:25,435 --> 01:13:28,970\nare happening in the animation you can be getting involved.\n\n1446\n01:13:28,972 --> 01:13:31,072\nOkay, so it's really kind of a cool method.\n\n1447\n01:13:31,074 --> 01:13:32,407\nNow one of the uses we can do for\n\n1448\n01:13:32,409 --> 01:13:33,875\nthis is that push behavior conundrum,\n\n1449\n01:13:33,877 --> 01:13:37,011\nyou got an instantaneous push, it's already pushed. Now you\n\n1450\n01:13:37,013 --> 01:13:39,147\nwanna remove it. Well this would be a great way to do it.\n\n1451\n01:13:39,149 --> 01:13:43,017\nJust have an action on that push behavior then set\n\n1452\n01:13:43,019 --> 01:13:46,220\nthe push behavior to remove itself when you're done and\n\n1453\n01:13:46,222 --> 01:13:49,357\nthis is what it would look like. Oops, no, sorry.\n\n1454\n01:13:49,359 --> 01:13:51,826\nOne more thing before I talk about that. This is\n\n1455\n01:13:51,828 --> 01:13:54,962\nthe dynamic animator also has a delegate. And it'll tell\n\n1456\n01:13:54,964 --> 01:13:59,267\nyou when the animator paused or resumed. Now what causes\n\n1457\n01:13:59,269 --> 01:14:03,137\nthe animator to pause? It's when all the objects reach\n\n1458\n01:14:03,139 --> 01:14:06,707\nstasis. In other words, none of the behaviors are causing\n\n1459\n01:14:06,709 --> 01:14:09,410\nany of the objects to change, okay? Then it pauses.\n\n1460\n01:14:09,412 --> 01:14:13,147\nAs soon as a push comes in or something like that,\n\n1461\n01:14:13,149 --> 01:14:16,250\ncauses things to start moving again, it will resume. So you\n\n1462\n01:14:16,252 --> 01:14:20,087\ncan find out when things have reached a steady state and\n\n1463\n01:14:20,089 --> 01:14:23,157\nwhen they resume, using these delegate methods\n\n1464\n01:14:23,159 --> 01:14:26,594\nof the dynamic animator, okay? All right, back to that push\n\n1465\n01:14:26,596 --> 01:14:28,463\nstate that I was talking about. All right, so\n\n1466\n01:14:28,465 --> 01:14:30,631\nhere I've created a push behavior with a certain\n\n1467\n01:14:30,633 --> 01:14:33,267\nmagnitude and angle, right? And look what I've got.\n\n1468\n01:14:33,269 --> 01:14:36,237\nI've set the push behavior's action to be,\n\n1469\n01:14:36,239 --> 01:14:40,241\nremove this pushBehavaior from the dynamic animator.\n\n1470\n01:14:40,243 --> 01:14:45,046\nYou see that? And since it's instantaneous,\n\n1471\n01:14:45,048 --> 01:14:47,748\nsee how its mode is instantaneous? This is fine.\n\n1472\n01:14:47,750 --> 01:14:49,817\nI want this thing removed. I don't want it sitting around\n\n1473\n01:14:49,819 --> 01:14:52,820\nthere collecting dust because it's not gonna fire ever\n\n1474\n01:14:52,822 --> 01:14:56,057\nagain. It fired, the action method got called,\n\n1475\n01:14:56,059 --> 01:14:57,792\nI put this closure method in here to do this. But\n\n1476\n01:14:57,794 --> 01:15:01,963\nof course this has a memory cycle, a really bad one, okay?\n\n1477\n01:15:01,965 --> 01:15:06,534\nBecause, this push behavior has a var\n\n1478\n01:15:06,536 --> 01:15:11,105\naction which is a closure. So, it has a strong pointer to\n\n1479\n01:15:11,107 --> 01:15:13,841\nthis closure. Push behavior's action is a strong pointer to\n\n1480\n01:15:13,843 --> 01:15:17,979\nthis closure. And this closure references the pushBehavior,\n\n1481\n01:15:17,981 --> 01:15:21,282\nso it has a strong pointer back to the pushBehavior. So\n\n1482\n01:15:21,284 --> 01:15:22,583\nthis will happen just fine and\n\n1483\n01:15:22,585 --> 01:15:25,419\nnow the only people pointing to this pushBehavior,\n\n1484\n01:15:25,421 --> 01:15:28,623\nsince it got removed from the dynamicAnimator, the only\n\n1485\n01:15:28,625 --> 01:15:33,361\nthing pointing to it is this closure. And it's pointing to\n\n1486\n01:15:33,363 --> 01:15:36,964\nclosure, so they're keeping each other in the heap, okay?\n\n1487\n01:15:36,966 --> 01:15:39,767\nSo this is our classic memory cycle.\n\n1488\n01:15:39,769 --> 01:15:41,669\nAnd just to remind how we break it here,\n\n1489\n01:15:41,671 --> 01:15:44,872\nwe're just gonna put unowned pushBehavior in here. Cuz we\n\n1490\n01:15:44,874 --> 01:15:48,476\nknow that this can never be out of the heap when action is\n\n1491\n01:15:48,478 --> 01:15:52,013\ncalled by definition. Okay, action is only called when his\n\n1492\n01:15:52,015 --> 01:15:55,216\npushBehavior does anything. So it has to clearly still be in\n\n1493\n01:15:55,218 --> 01:15:57,251\nthe heap [INAUDIBLE] done anything, okay?\n\n1494\n01:15:57,253 --> 01:15:59,420\nSo we can just put out known pushBehavior, boom,\n\n1495\n01:15:59,422 --> 01:16:02,924\nbreaks our cycle. This will be just a refresher course in\n\n1496\n01:16:02,926 --> 01:16:08,262\nbreaking the recycles. Okay, I made it. Okay, so as before,\n\n1497\n01:16:08,264 --> 01:16:10,698\nhere's what we're doing coming up. If you have any\n\n1498\n01:16:10,700 --> 01:16:13,801\nquestions I will be here as usual.\n\n1499\n01:16:14,771 --> 01:16:15,036\n>> For more,\n\n1500\n01:16:15,038 --> 01:16:15,069\nplease visit us at stanford.edu\n\n"
  },
  {
    "path": "subtitles/14. Animation and Core Motion.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,635\n[MUSIC]\n\n2\n00:00:03,637 --> 00:00:08,774\nStanford University. >> Okay well welcome\n\n3\n00:00:08,776 --> 00:00:13,379\nthen to Lecture 14 of CS Stanford CS193P,\n\n4\n00:00:13,381 --> 00:00:18,384\nSpring of 2016. Today, we have two topics. One is,\n\n5\n00:00:18,386 --> 00:00:21,587\nI'm gonna continue the dynamic animation we talked about in\n\n6\n00:00:21,589 --> 00:00:24,456\nthe last lecture and slides with a big ol' demo. Okay,\n\n7\n00:00:24,458 --> 00:00:28,660\nthat really shows a lot of dynamic, animation in action\n\n8\n00:00:28,662 --> 00:00:31,897\nand homework Assignment Six is all about dynamic animation,\n\n9\n00:00:31,899 --> 00:00:34,433\nso be preparing you for that. And then I'm gonna do a new\n\n10\n00:00:34,435 --> 00:00:37,336\ntopic. I had said last time it was probably gonna be Alerts,\n\n11\n00:00:37,338 --> 00:00:40,172\nbut actually I'm gonna do CoreMotion now, okay.\n\n12\n00:00:40,174 --> 00:00:43,842\nAnd we'll, I'm gonna redo some slides on CoreMation,\n\n13\n00:00:43,844 --> 00:00:46,645\nCore Motion, and then I'll also do a demo. Hopefully I'll\n\n14\n00:00:46,647 --> 00:00:50,849\nhave enough time to do all of that today, all right. Okay,\n\n15\n00:00:50,851 --> 00:00:54,386\nso let's dive right into this demo. It's called Dropit. It's\n\n16\n00:00:54,388 --> 00:00:57,756\nbasically as if I were gonna go write a Tetris app, okay,\n\n17\n00:00:57,758 --> 00:01:00,259\nwith the little falling blocks that you put in place and\n\n18\n00:01:00,261 --> 00:01:02,761\nthen you complete a row and the row would disappear and\n\n19\n00:01:02,763 --> 00:01:04,730\nthen more blocks would come down. Kinda like that,\n\n20\n00:01:04,732 --> 00:01:06,732\nbut this is a demo. We're starting from scratch.\n\n21\n00:01:06,734 --> 00:01:08,300\nSo we're just gonna have little individuals\n\n22\n00:01:08,302 --> 00:01:11,070\nblocks come down and when they all make a row then it'll\n\n23\n00:01:11,072 --> 00:01:14,606\ndisappear. So we're not gonna do the L-shaped and T-shaped\n\n24\n00:01:14,608 --> 00:01:17,509\nblocks from Tetris. We're just gonna do squares only. Okay,\n\n25\n00:01:17,511 --> 00:01:20,279\nso it's kind of like we're getting started on Tetris.\n\n26\n00:01:20,281 --> 00:01:23,515\nSo I'm not calling it Tetris because it doesn't look enough\n\n27\n00:01:23,517 --> 00:01:23,782\nlike Tetris for that.\n\n28\n00:01:23,784 --> 00:01:25,984\nI'll call it DropIt because we're gonna dropping,\n\n29\n00:01:25,986 --> 00:01:30,055\nlittle squares. Okay, so I'm gonna create a new project\n\n30\n00:01:30,057 --> 00:01:34,426\nhere. It's an iOS application as always. Single view..\n\n31\n00:01:34,428 --> 00:01:39,531\nI'm gonna call it Dropit. Okay, we don't need core data.\n\n32\n00:01:39,533 --> 00:01:40,766\nOkay it can be universal app,\n\n33\n00:01:40,768 --> 00:01:42,267\nI don't see any reason why this app wouldn't be\n\n34\n00:01:42,269 --> 00:01:45,270\nuniversal as you'll see. Okay. So here's Dropit,\n\n35\n00:01:45,272 --> 00:01:48,640\nwe'll put it where we always put everything. Here it is.\n\n36\n00:01:48,642 --> 00:01:51,009\nNow what's interesting about Dropit is I'm gonna build\n\n37\n00:01:51,011 --> 00:01:55,380\nthe entire user interface in code. So my story board all\n\n38\n00:01:55,382 --> 00:01:58,984\nit's gonna have is one custom view. Okay, and then I'm\n\n39\n00:01:58,986 --> 00:02:01,587\ngonna do all in code because we're gonna use the animator.\n\n40\n00:02:01,589 --> 00:02:03,722\nWe're gonna have a lot of animated views going on.\n\n41\n00:02:03,724 --> 00:02:06,992\nThat's what's gonna be the entire UI. So,um,\n\n42\n00:02:06,994 --> 00:02:09,428\nI don't really want this generic ViewController here.\n\n43\n00:02:09,430 --> 00:02:12,965\nSo I'm just gonna take this generic ViewController and\n\n44\n00:02:12,967 --> 00:02:15,501\ndelete it, okay, move it to the trash. And\n\n45\n00:02:15,503 --> 00:02:18,470\nthen I'm going to do the thing we always do here where we\n\n46\n00:02:18,472 --> 00:02:21,306\ntake these little guys and move them off into supporting\n\n47\n00:02:21,308 --> 00:02:26,111\nfiles because we don't need to do anything, supporting files,\n\n48\n00:02:26,113 --> 00:02:28,914\nbecause we don't really need to do anything with them. And\n\n49\n00:02:28,916 --> 00:02:32,284\nso I'm gonna right off the bat create a custom ViewController\n\n50\n00:02:32,286 --> 00:02:36,522\nfor this view controller that I have here in my storyboard.\n\n51\n00:02:36,524 --> 00:02:38,323\nAnd I'm also gonna create a custom UIView.\n\n52\n00:02:38,325 --> 00:02:41,360\nAnd that UIView is really where the logic of my game is,\n\n53\n00:02:41,362 --> 00:02:43,862\nyou can almost think of it as like a gameView. Right, and\n\n54\n00:02:43,864 --> 00:02:47,099\nI could actually put this view anywhere in any UI and\n\n55\n00:02:47,101 --> 00:02:47,332\nit would play this game,\n\n56\n00:02:47,334 --> 00:02:51,436\nthe Tetris-like game we gonna call DropIt. So let's go and\n\n57\n00:02:51,438 --> 00:02:54,973\ncreate those two classes. The UI view controller and\n\n58\n00:02:54,975 --> 00:02:59,878\nUI view. So here's to UI view, we'll call it DropItView.\n\n59\n00:02:59,880 --> 00:03:00,879\nOkay, it's gonna be the DropItView.\n\n60\n00:03:00,881 --> 00:03:04,650\nI'll put it in the same place here not in supporting files.\n\n61\n00:03:04,652 --> 00:03:09,188\nI'm gonna put where all the rest of the things are. Hey,\n\n62\n00:03:09,190 --> 00:03:09,855\nthere's my DropItView.\n\n63\n00:03:09,857 --> 00:03:13,625\nMy DropItView actually is not gonna implement DrawRect,\n\n64\n00:03:13,627 --> 00:03:15,894\nokay, it's gonna implement its entire existence with\n\n65\n00:03:15,896 --> 00:03:20,098\nsubviews. Okay, so it's not even gonna have, a DrawRect in\n\n66\n00:03:20,100 --> 00:03:24,836\nmy DropItView. And then I also need, my controller, okay.\n\n67\n00:03:24,838 --> 00:03:27,873\nSo same thing here. But this is gonna be UIViewController,\n\n68\n00:03:27,875 --> 00:03:30,909\nand I'm gonna call it my DropItViewController, okay.\n\n69\n00:03:30,911 --> 00:03:35,147\nSame place. Okay, there's my DropItViewController,\n\n70\n00:03:35,149 --> 00:03:40,152\nyou're gonna clear all this stuff out. All right, now that\n\n71\n00:03:40,154 --> 00:03:42,754\nI have these two classes, I'm gonna make my storyboard\n\n72\n00:03:42,756 --> 00:03:46,458\njust make it so that this ViewController that I have,\n\n73\n00:03:46,460 --> 00:03:49,494\nI'm gonna go to the Identity Inspector over here and\n\n74\n00:03:49,496 --> 00:03:51,563\ninstead of having it be just\n\n75\n00:03:51,565 --> 00:03:52,097\nplain ViewController,\n\n76\n00:03:52,099 --> 00:03:54,700\nit's gonna be a DropItViewController.\n\n77\n00:03:54,702 --> 00:03:58,870\nOkay, and same thing inside here I'm just gonna put a view\n\n78\n00:03:58,872 --> 00:04:02,441\na generic UI view, so let's scroll down and find that,\n\n79\n00:04:02,443 --> 00:04:06,044\nwhere that is. Where is that? Right here it is. Okay,\n\n80\n00:04:06,046 --> 00:04:07,746\ngeneric UI view I'm gonna put in here and\n\n81\n00:04:07,748 --> 00:04:13,185\nI'm gonna change its identify to be DropItView. Okay.\n\n82\n00:04:13,187 --> 00:04:16,288\nNow I'm gonna have, use constraints here to have this\n\n83\n00:04:16,290 --> 00:04:20,025\nfill my entire view controller here. You're gonna put\n\n84\n00:04:20,027 --> 00:04:22,694\nit right there. Use the blue lines to put it on the edges\n\n85\n00:04:22,696 --> 00:04:27,399\nthen we'll go down to here, oops, down to here,\n\n86\n00:04:27,401 --> 00:04:29,735\nand we'll say reset to suggested constraints.\n\n87\n00:04:29,737 --> 00:04:32,304\nI always like to look in the Size Inspector, make sure it\n\n88\n00:04:32,306 --> 00:04:36,074\ndid what I wanted, which it looks like it did. Okay. So\n\n89\n00:04:36,076 --> 00:04:38,844\nI've got this DropItView in here inside my\n\n90\n00:04:38,846 --> 00:04:41,880\nDropItViewController. I'm also gonna create an outlet from\n\n91\n00:04:41,882 --> 00:04:45,050\none to the other. Okay? Okay, so I'm just gonna control drag\n\n92\n00:04:45,052 --> 00:04:47,452\ninto my DropItViewController to create this view.\n\n93\n00:04:47,454 --> 00:04:51,323\nI'm gonna call it my gameView. You can see there's of type\n\n94\n00:04:51,325 --> 00:04:54,393\nDropItView, which is good. It's what I want. Okay, so\n\n95\n00:04:54,395 --> 00:04:56,795\nI've got my gameView. So this is my basic setup of\n\n96\n00:04:56,797 --> 00:05:00,132\nmy game, all right. And really all the controller's gonna do,\n\n97\n00:05:00,134 --> 00:05:02,968\nmaybe set up some gestures, possibly a little bit\n\n98\n00:05:02,970 --> 00:05:05,370\nof ViewController life cycle here and there, but most\n\n99\n00:05:05,372 --> 00:05:10,075\nof the logic is going to be inside this DropItView class.\n\n100\n00:05:10,077 --> 00:05:16,148\nOkay. So Let's make our screen bigger here. All right.\n\n101\n00:05:16,150 --> 00:05:19,951\nSo let's dive right in to this DropItView. I'm gonna have my\n\n102\n00:05:19,953 --> 00:05:24,489\nDropItView start by being able to put a little square. Okay,\n\n103\n00:05:24,491 --> 00:05:27,326\nthese things that are gonna fall down like Tetric, Tetris,\n\n104\n00:05:27,328 --> 00:05:28,260\nexcept for there's gonna be squares.\n\n105\n00:05:28,262 --> 00:05:31,063\nI'm gonna have a little method that puts a square there.\n\n106\n00:05:31,065 --> 00:05:33,899\nOkay so I'm gonna need a little bit of some private\n\n107\n00:05:33,901 --> 00:05:39,438\ndata here. How about Private let dropsPerRow = 10.\n\n108\n00:05:39,440 --> 00:05:42,941\nSo this is how many of these little drops that are gonna\n\n109\n00:05:42,943 --> 00:05:45,577\nfall down will fit across the top of my view,\n\n110\n00:05:45,579 --> 00:05:47,846\nthey're falling down from the top, right? So\n\n111\n00:05:47,848 --> 00:05:50,048\nthis is how many. So ten across is a good number,\n\n112\n00:05:50,050 --> 00:05:53,752\nI think. And then I'm gonna have a dropSize, okay,\n\n113\n00:05:53,754 --> 00:05:56,888\nwhich is gonna be a CGSize. That's gonna be the size\n\n114\n00:05:56,890 --> 00:05:58,790\nof each of the little things that falls down.\n\n115\n00:05:58,792 --> 00:06:01,993\nAnd I'm gonna have that be calculated. Kay?\n\n116\n00:06:01,995 --> 00:06:03,628\nAnd I'm gonna calculate it by having the size,\n\n117\n00:06:03,630 --> 00:06:07,232\nhave it be square. And we'll have the size be the width,\n\n118\n00:06:07,234 --> 00:06:10,168\nwhatever our width is at the time we ask this,\n\n119\n00:06:10,170 --> 00:06:13,805\ndivided by the number of drops per row. Right, so\n\n120\n00:06:13,807 --> 00:06:17,242\nI'm gonna have the size be so that they'll fit across\n\n121\n00:06:17,244 --> 00:06:20,011\nthe width of our view. Now, by the way,\n\n122\n00:06:20,013 --> 00:06:22,714\nour app might rotate and this width might change, so\n\n123\n00:06:22,716 --> 00:06:25,317\nthe drops might actually change as we rotate and stuff.\n\n124\n00:06:25,319 --> 00:06:28,453\nBut we can decide if that's what we wanted or not, but\n\n125\n00:06:28,455 --> 00:06:29,421\nthis is perfectly fine.\n\n126\n00:06:29,423 --> 00:06:32,891\nSo, now I'm just gonna create a CG size here whose width\n\n127\n00:06:32,893 --> 00:06:36,328\nis the size and whose height is the size. So it's square,\n\n128\n00:06:36,330 --> 00:06:38,230\nbasically. So this is gonna be the size of a drop,\n\n129\n00:06:38,232 --> 00:06:40,232\na square that fits ten across the top.\n\n130\n00:06:40,234 --> 00:06:44,035\nNow I'm gonna have a function called addDrop, that just\n\n131\n00:06:44,037 --> 00:06:47,305\nadds one of these things. One of these little squares that's\n\n132\n00:06:47,307 --> 00:06:49,975\ngonna fall down from the top to the view. So, of course,\n\n133\n00:06:49,977 --> 00:06:53,078\nwe need the size of this drop, to be put into a frame.\n\n134\n00:06:53,080 --> 00:06:56,782\nSo I'm gonna create a frame which is CGRect. The origin\n\n135\n00:06:56,784 --> 00:07:00,752\nof the frame is gonna be at CGPoint.zero to start.\n\n136\n00:07:00,754 --> 00:07:02,287\nI'm gonna put it up in the upper left hand corner and\n\n137\n00:07:02,289 --> 00:07:05,023\nthen I'm gonna move it over into one of the slots along\n\n138\n00:07:05,025 --> 00:07:08,894\nthe top. And the size of course is the dropSize. So\n\n139\n00:07:08,896 --> 00:07:11,329\nlet's do that frame movement. So I am gonna move\n\n140\n00:07:11,331 --> 00:07:16,435\nthe origin.x = and really what I want here is a random\n\n141\n00:07:16,437 --> 00:07:21,373\nfloat somewhere between 0 and the drops per row. Okay,\n\n142\n00:07:21,375 --> 00:07:24,242\nthat's pretty much where I am going to put it.\n\n143\n00:07:24,244 --> 00:07:27,512\nSo, if I like to sometimes, if I want to have a function on\n\n144\n00:07:27,514 --> 00:07:30,816\nCG float called random I'll actually make extensions and\n\n145\n00:07:30,818 --> 00:07:34,119\nso I've made some extensions, here they are right here,\n\n146\n00:07:34,121 --> 00:07:38,089\nUIKitExtensions.swift which I'm gonna copy in here. And\n\n147\n00:07:38,091 --> 00:07:41,493\nthese extensions are just kinda some convenient things\n\n148\n00:07:41,495 --> 00:07:43,929\nthat I've created that are gonna help my demo go\n\n149\n00:07:43,931 --> 00:07:47,098\nquicker. So you can see I have created this random function\n\n150\n00:07:47,100 --> 00:07:50,302\non CGFloat. I've created a random function on UIColor\n\n151\n00:07:50,304 --> 00:07:54,439\nwhich gives me a random color. Kind of fun, right?\n\n152\n00:07:54,441 --> 00:07:57,476\nAnd then some CGRect things here, other stuff,\n\n153\n00:07:57,478 --> 00:08:01,146\nso you can look through this later at your leisure.\n\n154\n00:08:01,148 --> 00:08:03,849\nBut I'm going to use one of here,\n\n155\n00:08:03,851 --> 00:08:08,253\nwhich is this CGFloat.random That takes an int,\n\n156\n00:08:08,255 --> 00:08:13,325\ndropsPerRow. Okay, and so that's gonna create a random\n\n157\n00:08:13,327 --> 00:08:16,228\nfloat between 0 and dropsPerRow, and\n\n158\n00:08:16,230 --> 00:08:20,599\nthen I'm going to multiply that times our dropSize width.\n\n159\n00:08:20,601 --> 00:08:25,070\nSo I've picked a spot across the top a random spot across\n\n160\n00:08:25,072 --> 00:08:27,539\nthe top there. So now, I'm gonna create the drop.\n\n161\n00:08:27,541 --> 00:08:31,309\nI'm just gonna say it's a UIView a generic UIView\n\n162\n00:08:31,311 --> 00:08:34,646\nwhose frame is frame. Okay, that this frame I just created\n\n163\n00:08:34,648 --> 00:08:39,117\nright here. So I got the drop. And let's set the drops back\n\n164\n00:08:39,119 --> 00:08:42,254\ncolor to a random color equals UIColor, that random.\n\n165\n00:08:42,256 --> 00:08:44,589\nYeah, that's one of my UI kit extensions that I created\n\n166\n00:08:44,591 --> 00:08:48,360\nthere And then we're gonna add sub-view, the drop, okay?\n\n167\n00:08:48,362 --> 00:08:52,330\nJust put it, on screen, okay? Make sense? Now,\n\n168\n00:08:52,332 --> 00:08:56,835\nI'm gonna cause this add drop to happen whenever I tap, so\n\n169\n00:08:56,837 --> 00:08:58,870\nI'm gonna put a gesture recognizer back here at my\n\n170\n00:08:58,872 --> 00:09:01,273\ncontrol. A lot of this, by the way, is review hopefully for\n\n171\n00:09:01,275 --> 00:09:05,544\nyou guys, but I'm going to, when my game view gets set\n\n172\n00:09:05,546 --> 00:09:08,747\nhere I'm gonna add a gesture recognizer. So\n\n173\n00:09:08,749 --> 00:09:12,551\nI'm just gonna say gameView.addGestureRecognizer.\n\n174\n00:09:12,553 --> 00:09:15,620\nIt's gonna be a tap. UITapGestureRecognizer.\n\n175\n00:09:15,622 --> 00:09:19,658\nThe target: is gonna be my self,\n\n176\n00:09:19,660 --> 00:09:22,827\nand the action: will be, let's say a #selector.\n\n177\n00:09:22,829 --> 00:09:25,997\nWe'll call it addDrop. This one has an argument. Okay?\n\n178\n00:09:25,999 --> 00:09:29,434\nCuz it's a gesture recognizer. Okay, so we'll just do that.\n\n179\n00:09:29,436 --> 00:09:33,104\nAnd then, I'm gonna have a little func here. Add drop,\n\n180\n00:09:33,106 --> 00:09:37,876\nwhich takes a recognizer which is a UITapGestureRecognizer.\n\n181\n00:09:37,878 --> 00:09:39,978\nWhat did I do here that's no good? That's good.\n\n182\n00:09:39,980 --> 00:09:43,949\nWe fix that. All right, so when we have TapGesture\n\n183\n00:09:43,951 --> 00:09:47,352\nwe basically wanna check to see if the recognizer state\n\n184\n00:09:47,354 --> 00:09:52,390\nhas moved to ended if it does then there was a tap. And\n\n185\n00:09:52,392 --> 00:09:54,059\nnow, I'm just gonna tell my game view,\n\n186\n00:09:54,061 --> 00:09:58,730\nokay go ahead and add one of those drops. Okay everybody\n\n187\n00:09:58,732 --> 00:10:01,666\nsee what I did there? Just create a little tap gesture,\n\n188\n00:10:01,668 --> 00:10:05,136\njust gonna call this method addDrop over in my drop it\n\n189\n00:10:05,138 --> 00:10:08,273\nview. So let's switch over to the DropItView it again.\n\n190\n00:10:08,275 --> 00:10:11,076\nIt's gonna call it, cause this add drop to happen right here.\n\n191\n00:10:11,078 --> 00:10:13,411\nAll right, so let's go ahead and run,\n\n192\n00:10:13,413 --> 00:10:18,116\nwe'll run on iPhone 6 here. So now, when we tap,\n\n193\n00:10:18,118 --> 00:10:24,422\nit should put a random color block along the top. Okay,\n\n194\n00:10:24,424 --> 00:10:28,293\nso tap, there it is, a green one, purple, okay, excellent.\n\n195\n00:10:28,295 --> 00:10:28,793\nYou see, as I click,\n\n196\n00:10:28,795 --> 00:10:31,463\nit puts more along the top. Now of course, we want these\n\n197\n00:10:31,465 --> 00:10:34,366\nthings to fall down. Okay, we want them to fall down to\n\n198\n00:10:34,368 --> 00:10:36,968\nthe bottom and we know how to do that with Dynamic Animator.\n\n199\n00:10:36,970 --> 00:10:39,104\nWe're just gonna create a gravity behavior, okay, and\n\n200\n00:10:39,106 --> 00:10:42,240\nthe default gravity behavior is downward gravity at 1,000\n\n201\n00:10:42,242 --> 00:10:45,977\npoints per second squared. So that's exactly what we want.\n\n202\n00:10:45,979 --> 00:10:48,913\nSo that's all we need to do is create a gravity behavior and\n\n203\n00:10:48,915 --> 00:10:49,180\nadd it to an animator.\n\n204\n00:10:49,182 --> 00:10:53,518\nSo let's do that. Up here, we're gonna create a private\n\n205\n00:10:53,520 --> 00:10:58,990\nlet gravity equal a ui gravity behavior, okay?\n\n206\n00:10:58,992 --> 00:11:01,760\nAnd of course, I also need an animator so I'm gonna say\n\n207\n00:11:01,762 --> 00:11:06,297\nprivate let animator which is gonna be a ui dynamic\n\n208\n00:11:06,299 --> 00:11:12,037\nanimator. And actually, let's just create one right here.\n\n209\n00:11:12,039 --> 00:11:14,506\nYou and I dynamic animator. And we know that when\n\n210\n00:11:14,508 --> 00:11:16,875\nwe created dynamic animator that's gonna be animating\n\n211\n00:11:16,877 --> 00:11:20,712\nviews. We wanna say what the reference view is. Okay. Which\n\n212\n00:11:20,714 --> 00:11:25,083\nin this case is, self. Okay. Where Drop it view is a view.\n\n213\n00:11:25,085 --> 00:11:28,486\nSo referring to yourself. Now, we have an error here.\n\n214\n00:11:28,488 --> 00:11:33,091\nAnyone know what the problem here is? Okay,\n\n215\n00:11:33,093 --> 00:11:37,328\nwhat are we doing right here? Initializing, right?\n\n216\n00:11:37,330 --> 00:11:40,231\nWe're initializing. Can we refer to self when we're\n\n217\n00:11:40,233 --> 00:11:44,669\ninitializing? No, because self is not fully initialized yet.\n\n218\n00:11:44,671 --> 00:11:47,405\nSo we can get around this though with our favorite\n\n219\n00:11:47,407 --> 00:11:51,943\nlazy var. Okay. So now, it's not gonna initialize this\n\n220\n00:11:51,945 --> 00:11:53,044\nuntil someone ask for the animator.\n\n221\n00:11:53,046 --> 00:11:54,879\nAnd that's not gonna happen until we're finish the slide.\n\n222\n00:11:54,881 --> 00:12:00,485\nSo we're winning, right? Okay. So we got that. Now, I'm gonna\n\n223\n00:12:00,487 --> 00:12:04,589\nactually make a public var called here called animating,\n\n224\n00:12:04,591 --> 00:12:07,258\nwhich is gonna be a boll, and we start it out equal\n\n225\n00:12:07,260 --> 00:12:11,696\nto false. And this is gonna be basically how we turn on and\n\n226\n00:12:11,698 --> 00:12:13,465\noff the animating. If you say, animating = true,\n\n227\n00:12:13,467 --> 00:12:15,934\nthen we're gonna have these blocks animating. If you say,\n\n228\n00:12:15,936 --> 00:12:18,770\nanimating = false, they'll stop animating. Okay, so\n\n229\n00:12:18,772 --> 00:12:22,373\nit's kind of like the on/off switch for our DropItView. So\n\n230\n00:12:22,375 --> 00:12:25,910\nwhat are we gonna do here? I'm gonna say if someone sets\n\n231\n00:12:25,912 --> 00:12:30,982\nthis, then if they set it to true, then I'm going\n\n232\n00:12:30,984 --> 00:12:34,619\nto animate this. Which all I need to do to animate, is\n\n233\n00:12:34,621 --> 00:12:38,423\nto take the animator and add the behavior of the gravity.\n\n234\n00:12:38,425 --> 00:12:40,959\nOkay? As soon as you add the behavior\n\n235\n00:12:40,961 --> 00:12:43,061\nto the animator it's going to start animating it.\n\n236\n00:12:43,063 --> 00:12:47,465\nOkay? And similarly if they turn animating off,\n\n237\n00:12:47,467 --> 00:12:50,135\nthen I'm just going to do the opposite, I'm going to remove\n\n238\n00:12:50,137 --> 00:12:55,373\nThat gravity behaviour. Okay, and that's going to stop\n\n239\n00:12:56,176 --> 00:13:01,446\nit animating. Okay, got that? Let's go ahead and set this.\n\n240\n00:13:01,448 --> 00:13:03,148\nWe're going to set this in our controllers.\n\n241\n00:13:03,150 --> 00:13:05,817\nI'm going to go back to our controller right here, and\n\n242\n00:13:05,819 --> 00:13:07,819\nlet's do this in our view controller live cycle. So\n\n243\n00:13:07,821 --> 00:13:11,556\nhow about in View Did Appear? As soon as View Did Appear\n\n244\n00:13:11,558 --> 00:13:17,996\nhappens, let's go ahead and set this gameView's animating\n\n245\n00:13:18,465 --> 00:13:21,933\nTo true. Okay, so that's gonna start it animating.\n\n246\n00:13:21,935 --> 00:13:28,439\nAnd similarly, on viewWillDissapear, We\n\n247\n00:13:28,441 --> 00:13:31,943\nwill turn the animation off. Cuz we really don't want this\n\n248\n00:13:31,945 --> 00:13:36,114\nthing animating while we're not even on screen. So. It's\n\n249\n00:13:36,116 --> 00:13:40,685\na good place to turn it on and off. Everyone understand that?\n\n250\n00:13:40,687 --> 00:13:42,987\nOkay. If you don't understand anything I'm saying,\n\n251\n00:13:42,989 --> 00:13:45,824\nfeel free to stop me. Okay? All right. So\n\n252\n00:13:45,826 --> 00:13:48,927\nthat turns it on and off. We got this thing going. The only\n\n253\n00:13:48,929 --> 00:13:52,397\nthing we need to do here is this behavior, currently there\n\n254\n00:13:52,399 --> 00:13:54,599\nare no items that have been added to this behavior.\n\n255\n00:13:54,601 --> 00:13:57,268\nSo nothing, this gravity is not affecting anything.\n\n256\n00:13:57,270 --> 00:14:00,572\nSo of course, every time we add a br-, a drop down here,\n\n257\n00:14:00,574 --> 00:14:03,308\nwe're gonna want to add it to the behavior,\n\n258\n00:14:03,310 --> 00:14:06,144\ngravity.addItem this (drop). Okay, and\n\n259\n00:14:06,146 --> 00:14:10,715\nthat makes that gravity start affecting that drop.\n\n260\n00:14:11,184 --> 00:14:13,685\nWe've got all that? So that's, we've seen all the steps now,\n\n261\n00:14:13,687 --> 00:14:15,353\ndynamic animation of making it work, right?\n\n262\n00:14:15,355 --> 00:14:18,156\nWe created the animator, we created our behavior, we added\n\n263\n00:14:18,158 --> 00:14:20,425\nthe behavior to the animator, and then we added items that\n\n264\n00:14:20,427 --> 00:14:22,694\nwe wanted affected by that behavior to the behavior.\n\n265\n00:14:22,696 --> 00:14:26,231\nAll right, so let's go see this work.\n\n266\n00:14:33,440 --> 00:14:35,406\nOkay, so here we go, let's run,\n\n267\n00:14:35,408 --> 00:14:36,307\nlet's try tap this user or\n\n268\n00:14:36,309 --> 00:14:40,111\ntap just just to here, and look they're falling down.\n\n269\n00:14:40,113 --> 00:14:42,680\nSee they all fall and we can click as many as we want and\n\n270\n00:14:42,682 --> 00:14:46,184\nthey all fall. Now the problem with this from a Tetris point\n\n271\n00:14:46,186 --> 00:14:47,819\nof view is they just fall off the bottom and\n\n272\n00:14:47,821 --> 00:14:51,789\nwe really want them to hit the bottom and stop, right? And\n\n273\n00:14:51,791 --> 00:14:53,324\npile up so that they will make rows and\n\n274\n00:14:53,326 --> 00:14:56,427\nwe can clear the rows out. Right? So the next thing we're\n\n275\n00:14:56,429 --> 00:14:58,396\ngoing to do is put a boundary and we're going to put\n\n276\n00:14:58,398 --> 00:15:01,065\nthe boundary all the way around this thing. Okay.\n\n277\n00:15:01,067 --> 00:15:03,801\nIt's a real simple way to create a collision boundary\n\n278\n00:15:03,803 --> 00:15:05,703\nall the way around this reference view right here.\n\n279\n00:15:05,705 --> 00:15:10,742\nSo let's do that. All right? Go back over here.\n\n280\n00:15:10,744 --> 00:15:13,678\nSo do that we need to create another behavior like\n\n281\n00:15:13,680 --> 00:15:17,749\nthe gravity behavior. And this one I'm gonna call my collider\n\n282\n00:15:17,751 --> 00:15:22,420\nand it's gonna be UICollisionBehavior. Okay?\n\n283\n00:15:22,422 --> 00:15:25,290\nNow I could just do that. The problem is I need to\n\n284\n00:15:25,292 --> 00:15:28,092\nconfigure this, cuz I wanna tell this collision behavior,\n\n285\n00:15:28,094 --> 00:15:32,230\nmake the bounds of the reference view be a boundary.\n\n286\n00:15:32,232 --> 00:15:34,599\nSo I'm gonna create this in kind of a cool way,\n\n287\n00:15:34,601 --> 00:15:37,035\nhopefully you'll remember that you can do this.\n\n288\n00:15:37,037 --> 00:15:38,870\nI'm gonna do it with a closure.\n\n289\n00:15:38,872 --> 00:15:42,473\nI'm gonna initialize this variable by executing\n\n290\n00:15:42,475 --> 00:15:47,412\nthis closure right here, and remember that we can do that.\n\n291\n00:15:47,414 --> 00:15:49,614\nSo I'm going to create a little local variable here.\n\n292\n00:15:49,616 --> 00:15:51,015\nHappens to be called the same thing but\n\n293\n00:15:51,017 --> 00:15:54,185\nwouldn't have to be of the same thing as a variable.\n\n294\n00:15:54,187 --> 00:15:56,554\nThis is just a local inside this enclosure. And\n\n295\n00:15:56,556 --> 00:16:02,060\nI'm gonna set the collider to translateReferenceBoundsIntoB-\n\n296\n00:16:02,062 --> 00:16:04,262\noundary = true. And if you do that,\n\n297\n00:16:04,264 --> 00:16:08,132\nthe UICollisionBehavior will automatically have the bounds\n\n298\n00:16:08,134 --> 00:16:11,035\nof the reference view be a collision boundary.\n\n299\n00:16:11,037 --> 00:16:14,706\nThen, we'll return the collider here, okay?\n\n300\n00:16:14,708 --> 00:16:17,041\nMake sense? Now, this collider,\n\n301\n00:16:17,043 --> 00:16:21,412\njust like the gravity, here, sorry. If you do this when you\n\n302\n00:16:21,414 --> 00:16:24,916\nmake a closure, don't forget that you have to explicitly\n\n303\n00:16:24,918 --> 00:16:30,888\ntype the var here, and that's because it wants to be\n\n304\n00:16:30,890 --> 00:16:34,225\nable to check to make sure the return value here matches what\n\n305\n00:16:34,227 --> 00:16:37,729\nyou want it to assign to here. Okay, so\n\n306\n00:16:37,731 --> 00:16:39,197\njust like we added the gravity behavior,\n\n307\n00:16:39,199 --> 00:16:41,132\nwe're gonna have to add the collider as well, so\n\n308\n00:16:41,134 --> 00:16:45,570\njust like, here's the gravity, we're gonna do collider, and\n\n309\n00:16:45,572 --> 00:16:47,538\nsame thing obviously when we stop animating,\n\n310\n00:16:47,540 --> 00:16:50,975\nwe want to remove the collider. Okay, and also down\n\n311\n00:16:50,977 --> 00:16:53,845\nhere, we want gravity to work on the drops, we also want\n\n312\n00:16:53,847 --> 00:16:56,848\nthe collider to work on the drops. If I didn't do this,\n\n313\n00:16:56,850 --> 00:17:00,385\nthen the drops would still keep falling off the end,\n\n314\n00:17:00,387 --> 00:17:03,121\nbecause the collider would not be behaving,\n\n315\n00:17:03,123 --> 00:17:06,557\nthe collider behavior would not apply to them, okay?\n\n316\n00:17:06,559 --> 00:17:13,564\nEverybody got that? So let's see if that works. All right,\n\n317\n00:17:13,566 --> 00:17:15,633\nhere we go, drop, and, sure enough, look,\n\n318\n00:17:15,635 --> 00:17:21,039\nthey're piling up. And here when, no, we're never gonna\n\n319\n00:17:21,041 --> 00:17:24,409\nget a completed row there, how are we gonna do that?\n\n320\n00:17:24,411 --> 00:17:28,546\nAll right, well, we obviously need more behaviors here than\n\n321\n00:17:28,548 --> 00:17:31,349\nwe have. And the next behavior we want to do is a behavior\n\n322\n00:17:31,351 --> 00:17:33,818\nthat makes it so that those things don't rotate like that,\n\n323\n00:17:33,820 --> 00:17:37,021\nokay, they don't tip over and start piling on top of each\n\n324\n00:17:37,023 --> 00:17:40,258\nother right there. We want them to stay in nice rows, so\n\n325\n00:17:40,260 --> 00:17:42,560\nwe want to turn rotation off. And to do that,\n\n326\n00:17:42,562 --> 00:17:45,029\nwe need a dynamic item behavior, which I talked about\n\n327\n00:17:45,031 --> 00:17:47,632\nin lecture. But it's starting to get to a point where I've\n\n328\n00:17:47,634 --> 00:17:50,435\nkinda got a lot of messy code cuz I'm adding behavior,\n\n329\n00:17:50,437 --> 00:17:51,636\nbehavior, behavior, another one.\n\n330\n00:17:51,638 --> 00:17:54,372\nI'm gonna add, add, add, remove, remove, add item,\n\n331\n00:17:54,374 --> 00:17:57,075\nadd item. So, I'm gonna do the thing I talk about in lecture\n\n332\n00:17:57,077 --> 00:17:59,811\nwhere I create a new behavior which is all these other\n\n333\n00:17:59,813 --> 00:18:04,415\nbehaviors combined, like a composite behavior, okay. So\n\n334\n00:18:04,417 --> 00:18:07,652\nlet's go, File > New up here.\n\n335\n00:18:07,654 --> 00:18:11,923\nOkay, it's a Cocoa Touch Class. This one is a subclass\n\n336\n00:18:11,925 --> 00:18:16,861\nof UIDynamicBehavior, okay. And I'm gonna call this\n\n337\n00:18:16,863 --> 00:18:20,264\nthe FallingObjectBehavior, okay, cuz that's what it is,\n\n338\n00:18:20,266 --> 00:18:24,502\nthis is a a thing falling down, a FallingObjectBehavior.\n\n339\n00:18:24,504 --> 00:18:26,671\nOkay, I don't wanna put it in the top level,\n\n340\n00:18:26,673 --> 00:18:28,573\ndrop it here, I wanna put it down here,\n\n341\n00:18:28,575 --> 00:18:30,007\nwhere all the rest of my classes are.\n\n342\n00:18:30,009 --> 00:18:32,510\nI notice some of you sometimes make that mistake in your\n\n343\n00:18:32,512 --> 00:18:36,247\nhomework. Really nice to keep your files together there.\n\n344\n00:18:36,249 --> 00:18:38,116\nOkay, so here's my FallingObjectBehavior,\n\n345\n00:18:38,118 --> 00:18:42,253\nit's a UIDynamicBehavior. And I'm just gonna go and copy and\n\n346\n00:18:42,255 --> 00:18:45,123\npaste those two behaviors I already have,\n\n347\n00:18:45,125 --> 00:18:49,627\nthese two guys right here, out of here, and over into here,\n\n348\n00:18:49,629 --> 00:18:52,763\nokay. Cuz now, cuz I want this falling object behavior to\n\n349\n00:18:52,765 --> 00:18:56,701\nhave these two behaviors right here. The other thing\n\n350\n00:18:56,703 --> 00:18:59,036\nwe do when we create a DynamicBehavior subclass is,\n\n351\n00:18:59,038 --> 00:19:02,607\nwe're obviously going to have an init. So I'm gonna override\n\n352\n00:19:02,609 --> 00:19:05,443\nthe init that comes with UIDynamicBehavior,\n\n353\n00:19:05,445 --> 00:19:08,646\ncall super.init, okay, because I, I need to that, from\n\n354\n00:19:08,648 --> 00:19:10,615\nthe rules of init. We haven't talked a lot about inits,\n\n355\n00:19:10,617 --> 00:19:13,918\nby the way. Again, hopefully you haven't needed them too\n\n356\n00:19:13,920 --> 00:19:17,054\nmuch in your, your homeworks. And hopefully you understood\n\n357\n00:19:17,056 --> 00:19:19,924\nwhat the reading assignment said about inits. But anyway,\n\n358\n00:19:19,926 --> 00:19:22,059\nyou need to call super.init before you can do stuff.\n\n359\n00:19:22,061 --> 00:19:25,062\nSo I'm going to then add a child behavior,\n\n360\n00:19:25,064 --> 00:19:29,867\nwhich is gravity, and I'm gonna add a child behavior,\n\n361\n00:19:29,869 --> 00:19:31,169\nwhich is the collider.\n\n362\n00:19:31,171 --> 00:19:33,971\nOkay, so this is how you build these composites.\n\n363\n00:19:33,973 --> 00:19:37,108\nYou add children behavior, okay. Now,\n\n364\n00:19:37,110 --> 00:19:41,179\nanother nice thing to do is to have a func addItem, okay,\n\n365\n00:19:41,181 --> 00:19:44,815\nwhich takes an item which would be a UIDynamicItem,\n\n366\n00:19:44,817 --> 00:19:47,885\nokay? Remember that UIView implements this protocol.\n\n367\n00:19:47,887 --> 00:19:51,088\nThis is a protocol, okay, UIView implements it.\n\n368\n00:19:51,090 --> 00:19:53,891\nAnd here, I just want to make sure that I add this item to\n\n369\n00:19:53,893 --> 00:19:58,863\nall of my sub, my children, basically, behaviors. So\n\n370\n00:19:58,865 --> 00:20:04,802\nlet's do that. And collider. Okay, and similarly,\n\n371\n00:20:04,804 --> 00:20:07,371\nwe probably, we don't need it for this demo, but\n\n372\n00:20:07,373 --> 00:20:11,709\nto be complete, we probably want a removeItem as well.\n\n373\n00:20:13,379 --> 00:20:16,681\nOkay, so now, we've created this new behavior that\n\n374\n00:20:16,683 --> 00:20:19,884\nwe can add items to and that this behavior can be added\n\n375\n00:20:19,886 --> 00:20:23,854\nto an animator to cause this group of behaviors to happen.\n\n376\n00:20:23,856 --> 00:20:26,657\nSo now let's go back to our DropItView,\n\n377\n00:20:26,659 --> 00:20:30,094\nand instead having these individual behaviors,\n\n378\n00:20:30,096 --> 00:20:34,932\nlet's create a new behavior, we'll call it dropBehavior,\n\n379\n00:20:34,934 --> 00:20:38,436\nwhich is a FallingObjectBehavior.\n\n380\n00:20:38,438 --> 00:20:41,105\nOkay, so this is one behavior encapsulate all those\n\n381\n00:20:41,107 --> 00:20:46,077\nbehaviors. So now we can put that instead of all these\n\n382\n00:20:46,079 --> 00:20:50,348\ndetails. Okay, same thing down here.\n\n383\n00:20:52,218 --> 00:20:55,486\nAll right? So see how this code has gotten so\n\n384\n00:20:55,488 --> 00:20:58,589\nsimple now it fits on one page to do this. And\n\n385\n00:20:58,591 --> 00:21:01,359\nthe actual behavior, the dynamic behavior is now\n\n386\n00:21:01,361 --> 00:21:05,663\nencapsulated over here in this FallingObjectBehavior instead.\n\n387\n00:21:05,965 --> 00:21:08,032\nAll right? Okay, let's run this and\n\n388\n00:21:08,034 --> 00:21:10,301\nmake sure we haven't broken anything by doing that.\n\n389\n00:21:10,303 --> 00:21:12,103\nOkay, haven't really changed anything,\n\n390\n00:21:12,105 --> 00:21:14,939\nI've just moved the code for a different encapsulation.\n\n391\n00:21:14,941 --> 00:21:17,575\nHere it is, we click, hopefully these things will\n\n392\n00:21:17,577 --> 00:21:21,112\nstill hit the bottom, they do, okay? So all is well. Now,\n\n393\n00:21:21,114 --> 00:21:25,249\nthey're still, can be tippy. See there, they're starting to\n\n394\n00:21:25,251 --> 00:21:26,450\ntip over. No, they're tipping over, okay.\n\n395\n00:21:26,452 --> 00:21:29,020\nSo they're still tipping, so we need to fix the tippiness.\n\n396\n00:21:29,022 --> 00:21:31,355\nBut now we're gonna fix this tippiness here in\n\n397\n00:21:31,357 --> 00:21:34,792\nour FallingObjectBehavior. And we're gonna do that by adding\n\n398\n00:21:34,794 --> 00:21:38,296\nanother behavior, okay? This is gonna be the itemBehavior.\n\n399\n00:21:38,298 --> 00:21:41,599\nThis is gonna describe how each of these items behaves\n\n400\n00:21:41,601 --> 00:21:45,870\nwhen it goes in all the other behaviors. And we do that with\n\n401\n00:21:45,872 --> 00:21:48,239\na UIDynamicItemBehavior, okay, and\n\n402\n00:21:48,241 --> 00:21:52,643\nI'm gonna initialize this in the same way that I did here,\n\n403\n00:21:52,645 --> 00:21:57,248\nokay, with a closure. So let's let dib,\n\n404\n00:21:57,250 --> 00:22:03,120\na dynamic item behavior, equal a UIDynamicItemBehavior.\n\n405\n00:22:03,122 --> 00:22:07,024\nAnd now we can set all kinds of things that dib, this dib,\n\n406\n00:22:07,026 --> 00:22:09,026\nUIDynamicItemBehavior, knows how to do.\n\n407\n00:22:09,028 --> 00:22:13,564\nFor example, allows rotation? No, so now, our block won't\n\n408\n00:22:13,566 --> 00:22:17,268\nrotate. We could also do stuff like friction and\n\n409\n00:22:17,270 --> 00:22:21,238\nalso elasticity. So I'm gonna do elasticity of 0.75.\n\n410\n00:22:21,240 --> 00:22:23,407\nElasticity of 1 is perfect elasticity.\n\n411\n00:22:23,409 --> 00:22:26,677\nIn other words, no energy is lost by the collision.\n\n412\n00:22:26,679 --> 00:22:26,977\nThey bounce off each other.\n\n413\n00:22:26,979 --> 00:22:30,281\nSo 0.75 is a little energy lost. But, you know, so\n\n414\n00:22:30,283 --> 00:22:33,417\nI'm not sure what the default elasticity is. But it was low,\n\n415\n00:22:33,419 --> 00:22:34,752\nbecause those things came down to the bottom,\n\n416\n00:22:34,754 --> 00:22:38,155\nthey didn't bounce much. They kind of just sat there.\n\n417\n00:22:38,157 --> 00:22:40,691\nSo I'll do that. And now let's return dib.\n\n418\n00:22:40,693 --> 00:22:44,061\nAnd of course we need to do the same thing here,\n\n419\n00:22:44,063 --> 00:22:48,933\nadd this child behavior or item behavior. And\n\n420\n00:22:48,935 --> 00:22:53,270\nsame thing here, we want to be able to add items to this. And\n\n421\n00:22:53,272 --> 00:23:01,011\nwe want to be able to remove items as well, okay? So\n\n422\n00:23:01,013 --> 00:23:03,581\nwe've just added this behavior now. These things are all\n\n423\n00:23:03,583 --> 00:23:06,751\ngoing to have this kind of behavior as they bounce and\n\n424\n00:23:06,753 --> 00:23:09,453\nare affected by gravity and things like that. And\n\n425\n00:23:09,455 --> 00:23:12,823\nnotice that to add this stuff, we didn't touch DropItView.\n\n426\n00:23:12,825 --> 00:23:15,559\nDropItView has not changed, okay? We didn't change\n\n427\n00:23:15,561 --> 00:23:17,361\nanything there. We're only changing this in\n\n428\n00:23:17,363 --> 00:23:20,498\nthis custom behavior that we've built. Okay, so let's go\n\n429\n00:23:20,500 --> 00:23:24,301\nahead and run. See what those changes did, what having no\n\n430\n00:23:24,303 --> 00:23:26,771\nrotation elasticity did. So here it comes like this, so\n\n431\n00:23:26,773 --> 00:23:29,407\nhere we go. Look, they're much bouncier. And\n\n432\n00:23:29,409 --> 00:23:31,742\nnotice how they'll bounce into each other, okay?\n\n433\n00:23:31,744 --> 00:23:33,978\nThey behave like real objects in the real world.\n\n434\n00:23:33,980 --> 00:23:36,747\nThey're bouncing, and they're not rotating, so they're not\n\n435\n00:23:36,749 --> 00:23:39,016\ntipping over anymore. They're still bouncing up and down,\n\n436\n00:23:39,018 --> 00:23:41,619\nthough, see? When something lands on a row, it causes them\n\n437\n00:23:41,621 --> 00:23:45,489\nto bounce up a little bit. But now we're on track for Tetris,\n\n438\n00:23:45,491 --> 00:23:49,527\nbecause now we're getting completed rows that we can\n\n439\n00:23:49,529 --> 00:23:51,529\nhave them, have the rows remove.\n\n440\n00:23:51,531 --> 00:23:54,732\nNow, the code for removing, for kind of removing a row,\n\n441\n00:23:54,734 --> 00:23:57,802\nit's a little tedious for a demo here. I'm really just\n\n442\n00:23:57,804 --> 00:24:01,005\ngonna go across the row and do what's called a hit test.\n\n443\n00:24:01,007 --> 00:24:02,940\nIn UI view, it has a hit test, which basically I'm\n\n444\n00:24:02,942 --> 00:24:04,375\njust looking to see if there's a view there.\n\n445\n00:24:04,377 --> 00:24:07,077\nSo I'm gonna go all the way across each row looking to see\n\n446\n00:24:07,079 --> 00:24:09,547\nif they're view. And if there's a view in every single\n\n447\n00:24:09,549 --> 00:24:12,149\nspot, then I'm gonna assume that row is complete and\n\n448\n00:24:12,151 --> 00:24:14,752\nI'm gonna remove all those views. Okay, so\n\n449\n00:24:14,754 --> 00:24:18,889\nI wrote that code outside, let's go take a look at it.\n\n450\n00:24:18,891 --> 00:24:22,827\nWe'll put it, let's put it right here. Okay,\n\n451\n00:24:22,829 --> 00:24:24,128\nit's called removeCompletedRow.\n\n452\n00:24:24,130 --> 00:24:28,232\nIt's just this one method right here, okay?\n\n453\n00:24:28,234 --> 00:24:30,801\nYou can see it goes through, it's doing this hit testing,\n\n454\n00:24:30,803 --> 00:24:33,571\nit's trying to find the drops to remove. If it finds\n\n455\n00:24:33,573 --> 00:24:36,974\nthe whole row, then it goes through each of the drops and\n\n456\n00:24:36,976 --> 00:24:37,441\nthe drops removed, and\n\n457\n00:24:37,443 --> 00:24:41,378\nlook what it does. It removes it from the drop behavior and\n\n458\n00:24:41,380 --> 00:24:42,413\nthen removes it from superview, so\n\n459\n00:24:42,415 --> 00:24:44,748\nit just takes that drop right out of there. Okay?\n\n460\n00:24:44,750 --> 00:24:48,652\nSo we're literally just throwing it away, okay? Now,\n\n461\n00:24:48,654 --> 00:24:52,857\nthe question is, when do we call remove completed row?\n\n462\n00:24:53,426 --> 00:24:56,760\nOkay, do we just kind of call it randomly with an NS timer\n\n463\n00:24:56,762 --> 00:25:00,831\nor something? No, we're gonna call remove completed row\n\n464\n00:25:00,833 --> 00:25:06,103\nwhen all the bouncing stops. Okay, when our\n\n465\n00:25:06,105 --> 00:25:09,807\ndynamic animation engine pauses, then we're gonna try\n\n466\n00:25:09,809 --> 00:25:12,376\nto remove a row. Cuz if things are still bouncing, you can't\n\n467\n00:25:12,378 --> 00:25:14,478\nreally be removing rows while things are still bouncing.\n\n468\n00:25:14,480 --> 00:25:15,145\nSo when things have settled down,\n\n469\n00:25:15,147 --> 00:25:18,148\nthen we'll try and remove a complete row if we can.\n\n470\n00:25:18,150 --> 00:25:19,517\nSo, if you remember from lecture,\n\n471\n00:25:19,519 --> 00:25:21,952\nhow do we find out the things have stopped?\n\n472\n00:25:21,954 --> 00:25:25,656\nWe use a dynamic animators delegate, the dynamic animator\n\n473\n00:25:25,658 --> 00:25:27,858\nwill tell it's delegate when things have paused.\n\n474\n00:25:27,860 --> 00:25:30,928\nWhen things have stasis, okay? So we're gonna have to do\n\n475\n00:25:30,930 --> 00:25:34,298\nthe same trick here that we did with these other ones, and\n\n476\n00:25:34,300 --> 00:25:37,001\nuse a closure Create this because we just have\n\n477\n00:25:37,003 --> 00:25:39,670\nthe delegates of it. So let's go here and\n\n478\n00:25:39,672 --> 00:25:43,607\nwe'll create a little let animator equal this thing.\n\n479\n00:25:43,609 --> 00:25:48,846\nAnd we are just going to set the animator's delegate\n\n480\n00:25:48,848 --> 00:25:51,916\nto self and return animator.\n\n481\n00:25:53,686 --> 00:25:56,353\nOkay, and we can use self in here because this is lazy.\n\n482\n00:25:56,355 --> 00:26:00,190\nOkay. Eh, right? You do that but there is as error here.\n\n483\n00:26:00,192 --> 00:26:03,527\nWhat's this error? Can't assign the DropItView to\n\n484\n00:26:03,529 --> 00:26:06,630\nUIDynamicDeleg eh,DynamicAnimatorDelegate so\n\n485\n00:26:06,632 --> 00:26:09,366\nwe need to go here and say we are a UIDynamic.\n\n486\n00:26:09,368 --> 00:26:13,504\nAnimator delegate, okay? Say we implement this\n\n487\n00:26:13,506 --> 00:26:16,440\nprotocol. Now they're all optional so we don't have to\n\n488\n00:26:16,442 --> 00:26:18,776\nactually implement any, there's no errors here, but\n\n489\n00:26:18,778 --> 00:26:21,045\nthe one we want is that it will pause.\n\n490\n00:26:21,047 --> 00:26:23,781\nAnd that we'll just start typing dynamicAnimator, and\n\n491\n00:26:23,783 --> 00:26:25,182\nyou can se it's actually the very first one.\n\n492\n00:26:25,184 --> 00:26:27,585\nHere's resume and here's pause. So let's go ahead and\n\n493\n00:26:27,587 --> 00:26:30,120\ndo the pause. So this gets called whenever everything\n\n494\n00:26:30,122 --> 00:26:33,123\nreach stasis and I'm just going to removeCompletedRow.\n\n495\n00:26:33,125 --> 00:26:36,026\nIf there are no completed rows removeCompletedRow does\n\n496\n00:26:36,028 --> 00:26:37,828\nnothing, it only removes completed rows\n\n497\n00:26:37,830 --> 00:26:42,333\nif there are some. Okay, so let's try it see if it works.\n\n498\n00:26:42,335 --> 00:26:47,371\nCould it really be that easy? Yes. All right here we go.\n\n499\n00:26:47,373 --> 00:26:49,306\nDrops them down here. Okay, we'll let it\n\n500\n00:26:49,308 --> 00:26:53,811\nreach stasis where there's no completed row. Okay,\n\n501\n00:26:53,813 --> 00:26:57,448\nnothing removed, okay, let's add a whole bunch more,\n\n502\n00:26:57,450 --> 00:27:03,253\nbad enough so that something becomes complete here. Okay,\n\n503\n00:27:03,255 --> 00:27:05,522\noops, nope, still need one more,\n\n504\n00:27:05,524 --> 00:27:05,889\nthis column right here, so\n\n505\n00:27:05,891 --> 00:27:08,926\nwe'll keep clicking until we get something in that column.\n\n506\n00:27:09,261 --> 00:27:12,162\nThere it is. Okay, here we go.\n\n507\n00:27:13,666 --> 00:27:18,402\nCross your fingers. Boom. Now, notice that\n\n508\n00:27:18,404 --> 00:27:21,839\nwhen I remove those views, the animator leapt into action\n\n509\n00:27:21,841 --> 00:27:24,908\nagain. Because it noticed, woah, gravity can now work on\n\n510\n00:27:24,910 --> 00:27:26,944\nthese ones that are not blocked by the other ones.\n\n511\n00:27:26,946 --> 00:27:29,947\nOkay? And same thing here. And this will happen repeatedly.\n\n512\n00:27:29,949 --> 00:27:34,518\nYeah, question. >> Yeah, so the last row or so\n\n513\n00:27:34,520 --> 00:27:37,755\nsometimes the bottom squares are like a little bit\n\n514\n00:27:37,757 --> 00:27:38,689\noff the ground. >> Mm-hm.\n\n515\n00:27:38,691 --> 00:27:39,390\n>> What's going on there?\n\n516\n00:27:39,392 --> 00:27:39,957\n>> Yeah, you see a little\n\n517\n00:27:39,959 --> 00:27:40,391\n>> Little bit of white in\n\n518\n00:27:40,393 --> 00:27:45,095\nthere. I'm not 100% sure what that is, but I think\n\n519\n00:27:45,097 --> 00:27:48,866\nit's just an artifact that all this animation stuff happened,\n\n520\n00:27:48,868 --> 00:27:52,603\nis happening, in CGFloat space, right?\n\n521\n00:27:52,605 --> 00:27:54,538\nIt's not happening on integer boundaries. And so\n\n522\n00:27:54,540 --> 00:27:57,675\nit might be that these things landing, maybe they're 0.01,\n\n523\n00:27:57,677 --> 00:28:00,711\nand so the, it's up enough, round enough so\n\n524\n00:28:00,713 --> 00:28:01,712\nthat it shows the one pixel there.\n\n525\n00:28:01,714 --> 00:28:04,415\nI'm not really 100% sure why it's not exactly on there.\n\n526\n00:28:04,417 --> 00:28:06,917\nRemember that, you know, the physics you got a lot\n\n527\n00:28:06,919 --> 00:28:09,086\nof things bouncing here, off of each other.\n\n528\n00:28:09,088 --> 00:28:10,954\nDifferent, amounts and stuff like that.\n\n529\n00:28:10,956 --> 00:28:12,356\nAnd these things, and when they could rotate,\n\n530\n00:28:12,358 --> 00:28:14,958\nyou saw, they started tipping over even, and nicking into\n\n531\n00:28:14,960 --> 00:28:17,895\neach other. So this stuff is not all happening on integer\n\n532\n00:28:17,897 --> 00:28:20,864\nboundaries, I think that's the bottom line on that.\n\n533\n00:28:20,866 --> 00:28:23,634\nBut I'm not 100% certain. All right, so anyway, this\n\n534\n00:28:23,636 --> 00:28:27,871\nis working great, okay? We got our tetris engine really\n\n535\n00:28:27,873 --> 00:28:30,774\nready to go here, if we just made these not be squares.\n\n536\n00:28:30,776 --> 00:28:35,245\nAnd I don't have time to make them be actual you know,\n\n537\n00:28:35,247 --> 00:28:35,713\nL shapes and all that stuff.\n\n538\n00:28:35,715 --> 00:28:38,515\nBut you get the idea. And you understand how this works.\n\n539\n00:28:38,517 --> 00:28:42,953\nSo, I'm going to Let's turn the rotation back on.\n\n540\n00:28:42,955 --> 00:28:46,423\nI want to show you something fun here.\n\n541\n00:28:46,425 --> 00:28:51,495\nLet's make the rotation be true again. Run.\n\n542\n00:28:54,834 --> 00:28:59,269\nOkay, so put it in here. And these things are gonna bounce\n\n543\n00:28:59,271 --> 00:29:00,537\noff each other. Uhp! No! No!. No! But, let's\n\n544\n00:29:00,539 --> 00:29:02,840\nsee if removeCompletedRow can work here. Because, actually,\n\n545\n00:29:02,842 --> 00:29:05,843\nsome of these rows still might have a in every slot.\n\n546\n00:29:05,845 --> 00:29:09,513\nLet's see. There we go! Remove that row. So\n\n547\n00:29:09,515 --> 00:29:16,186\nit doesn't work quite as well, but it can kind of work.\n\n548\n00:29:16,188 --> 00:29:19,857\nThere we go. Okay? All right.\n\n549\n00:29:19,859 --> 00:29:23,060\nWhat's next? Next I'm gonna make it so\n\n550\n00:29:23,062 --> 00:29:26,463\nthat just to show you how the collide, collisions work cuz w\n\n551\n00:29:26,465 --> 00:29:27,698\nonly have collisions with the edges.\n\n552\n00:29:27,700 --> 00:29:31,401\nI'm gonna put a little round thing in the middle, okay?\n\n553\n00:29:31,403 --> 00:29:34,838\nThat this squares are gonna collide against. Just a little\n\n554\n00:29:34,840 --> 00:29:36,940\nround circles. So the bottom, there's squeezing him down and\n\n555\n00:29:36,942 --> 00:29:39,710\nboop bounce of a bit. With just a little round boundary,\n\n556\n00:29:39,712 --> 00:29:42,279\nokay? Cuz you can put, with these, with the collision\n\n557\n00:29:42,281 --> 00:29:45,883\nbehavior you can put any arbitrary Bezier path as a,\n\n558\n00:29:45,885 --> 00:29:46,617\nas a boundary anywhere.\n\n559\n00:29:46,619 --> 00:29:47,551\nAnd when you're doing your breakout game.\n\n560\n00:29:47,553 --> 00:29:49,486\nYou know, you're probably gonna use those boundaries for\n\n561\n00:29:49,488 --> 00:29:52,923\nthe bricks, for example, okay? And maybe for your paddle\n\n562\n00:29:52,925 --> 00:29:54,424\neven. You'll be moving the boundary constantly,\n\n563\n00:29:54,426 --> 00:29:56,593\nbecause the bricks and the paddle, they don't go flying\n\n564\n00:29:56,595 --> 00:29:58,896\naround when you hit them they disappear or whatever and\n\n565\n00:29:58,898 --> 00:30:00,998\nthe paddle, when you hit it nothing happens to it,\n\n566\n00:30:01,000 --> 00:30:04,067\nit stays perfectly the same. Okay, so let's go ahead and\n\n567\n00:30:04,069 --> 00:30:06,069\ndo that. We're just going to put a little round circle\n\n568\n00:30:06,071 --> 00:30:10,374\nhere that is a collision. So, to do that I'm going to go\n\n569\n00:30:10,376 --> 00:30:12,676\nin my Falling Object behavior here.\n\n570\n00:30:12,678 --> 00:30:13,644\nAnd I'm going to make this,\n\n571\n00:30:13,646 --> 00:30:16,547\nunfortunately my collider is private. And I actually like\n\n572\n00:30:16,549 --> 00:30:19,683\nto keep it private in my little dynamic behavior here.\n\n573\n00:30:19,685 --> 00:30:21,985\nBut I am going to allow people to add a barrier.\n\n574\n00:30:21,987 --> 00:30:25,756\nSo, I'm gonna create a public function addBarrier. And\n\n575\n00:30:25,758 --> 00:30:29,126\nyou can specify any path you want, a UIBezierPath, that you\n\n576\n00:30:29,128 --> 00:30:32,296\nwant to be the barrier. And let's go ahead and you can\n\n577\n00:30:32,298 --> 00:30:35,866\nname it as well. So, it will let you give it a name.\n\n578\n00:30:35,868 --> 00:30:39,236\nAnd that's because when you put these barriers into\n\n579\n00:30:39,238 --> 00:30:41,238\nthe collider, you name them there as well.\n\n580\n00:30:41,240 --> 00:30:44,141\nThat's how you know which Barrier got hit, okay, and\n\n581\n00:30:44,143 --> 00:30:47,077\nwhich barrier you're gonna add or remove or change. So those\n\n582\n00:30:47,079 --> 00:30:51,982\nare all named. And you just do this with a collider, method.\n\n583\n00:30:51,984 --> 00:30:57,788\nAddBoundaryWithIdentifier. Okay, here it is, and\n\n584\n00:30:57,790 --> 00:31:00,757\nso the identifier is the name, and the path is the path that\n\n585\n00:31:00,759 --> 00:31:03,660\nwas passed along in here. If someone calls us, by the way,\n\n586\n00:31:03,662 --> 00:31:08,665\nI'm also going to conveniently remove any old boundary with\n\n587\n00:31:08,667 --> 00:31:12,769\nthat name. Okay? So if you call this repeatedly,\n\n588\n00:31:12,771 --> 00:31:17,174\nit'll move the barrier around, just for convenience here.\n\n589\n00:31:17,810 --> 00:31:19,743\nOkay? So this is a nice public function for\n\n590\n00:31:19,745 --> 00:31:23,113\nadding a barrier. Let's use that in our drop it view to\n\n591\n00:31:23,115 --> 00:31:28,518\nadd a little barrier in the middle. Now, Where do I\n\n592\n00:31:28,520 --> 00:31:31,455\nwant to put the code that adds that little thing? Well, I\n\n593\n00:31:31,457 --> 00:31:34,224\ndon't know where the middle of my bounds are until my bounds\n\n594\n00:31:34,226 --> 00:31:37,494\nis set, so I certainly have to wait until my bounds are set,\n\n595\n00:31:37,496 --> 00:31:39,863\nand actually my bounds could change, right?\n\n596\n00:31:39,865 --> 00:31:42,432\nThey could get rotated. Now my middle is in a different\n\n597\n00:31:42,434 --> 00:31:45,702\nplace, and I want the barrier to always be in the middle. So\n\n598\n00:31:45,704 --> 00:31:46,737\nyou'll remember from our last\n\n599\n00:31:46,739 --> 00:31:50,540\ndemo That when a UI views bounds change,\n\n600\n00:31:50,542 --> 00:31:53,543\nwhat gets called? Layout subviews.\n\n601\n00:31:53,545 --> 00:31:55,846\nAll right, it doesn't have a view did layout subviews, it\n\n602\n00:31:55,848 --> 00:31:58,248\nhas the actual layout subviews that lays the subviews out.\n\n603\n00:31:58,250 --> 00:32:00,517\nSo that's a good place to put this thing in the middle.\n\n604\n00:32:00,519 --> 00:32:03,553\nBecause layout subviews gonna get called every single time.\n\n605\n00:32:03,555 --> 00:32:06,490\nThe bounds change. So, that's layoutSubviews.\n\n606\n00:32:06,492 --> 00:32:11,161\nI'm just gonna subclass else. Super.layoutSubviews. And\n\n607\n00:32:11,163 --> 00:32:14,298\nall I'm gonna do here in layoutSubviews is to\n\n608\n00:32:14,300 --> 00:32:18,302\ncreate a round path, so let path equal UIBezierPath.\n\n609\n00:32:18,304 --> 00:32:22,739\nAnd there happens to be a BezierPath ovalInRect\n\n610\n00:32:22,741 --> 00:32:24,975\nthing to create them. And so\n\n611\n00:32:24,977 --> 00:32:28,712\nlet's have this rect be a CGRect whose center,\n\n612\n00:32:28,714 --> 00:32:32,582\nthis is one of my little UI kit extensions is a,\n\n613\n00:32:32,584 --> 00:32:35,552\nis a CGRect has a center initializer\n\n614\n00:32:35,554 --> 00:32:39,022\nwill be bounds.mid. That's my mid point of my bounds,\n\n615\n00:32:39,024 --> 00:32:42,159\nthat's also a little extension that I did there. And\n\n616\n00:32:42,161 --> 00:32:45,929\nwe'll have the size of it be the dropSize. Okay so\n\n617\n00:32:45,931 --> 00:32:47,164\nwe're gonna put a little round circle,\n\n618\n00:32:47,166 --> 00:32:50,367\nthe same size as a drop right in the middle. So we have that\n\n619\n00:32:50,369 --> 00:32:53,737\npath. Let's just call on our drop behavior. We'll add\n\n620\n00:32:53,739 --> 00:32:57,841\nthis barrier with this path. We need to give it a name.\n\n621\n00:32:57,843 --> 00:33:00,043\nSo let's be good programmers here and\n\n622\n00:33:00,045 --> 00:33:03,046\ndo private struct pathNames, we'll call it.\n\n623\n00:33:03,048 --> 00:33:06,883\nStatic let this one we'll call our MiddleBarrier and\n\n624\n00:33:06,885 --> 00:33:11,121\nwe can use any string we want here, just has to be unique so\n\n625\n00:33:11,123 --> 00:33:15,325\nwe'll call it MiddleBarrier. Okay, so\n\n626\n00:33:15,327 --> 00:33:19,930\nthis is PathNames.MiddleBarrier. Okay,\n\n627\n00:33:19,932 --> 00:33:25,202\nso I'm just adding this named barrier here, to my\n\n628\n00:33:25,204 --> 00:33:30,507\nto my collision behavior in my drop behavior. All right,\n\n629\n00:33:30,509 --> 00:33:36,980\nso let's go try it, see what this looks like. All right,\n\n630\n00:33:36,982 --> 00:33:40,751\nwe're dropping them here. Whoop! See that? If we drop\n\n631\n00:33:40,753 --> 00:33:45,022\none in the middle, right? Aah, give me a middle one.\n\n632\n00:33:45,024 --> 00:33:47,224\nThere one, see? They're hitting off the middle.\n\n633\n00:33:47,226 --> 00:33:49,593\nNow this is a little hard to see. See,\n\n634\n00:33:49,595 --> 00:33:51,228\nyou see that it's hitting the barrier, but\n\n635\n00:33:51,230 --> 00:33:53,096\nyou can't actually see the barrier. So\n\n636\n00:33:53,098 --> 00:33:56,099\nhow could we draw that barrier there? Well,\n\n637\n00:33:56,101 --> 00:34:00,070\nwe could implement DrawRect, okay? Our own DrawRect and\n\n638\n00:34:00,072 --> 00:34:03,573\ndraw it, okay, just using just stroke, stroking the thing.\n\n639\n00:34:03,575 --> 00:34:05,675\nBut actually, I'm gonna do something kinda fun. And\n\n640\n00:34:05,677 --> 00:34:09,012\nthis is, really I'm doing it this way to show you, always\n\n641\n00:34:09,014 --> 00:34:12,215\nthink object-oriented when you're building an iOS, okay?\n\n642\n00:34:12,217 --> 00:34:14,985\nWhat I'm gonna do instead to draw all that little circle,\n\n643\n00:34:14,987 --> 00:34:17,854\nis I'm gonna create a new UIView okay,\n\n644\n00:34:17,856 --> 00:34:22,025\na new UIView subclass. And all this UIView subclass I'm gonna\n\n645\n00:34:22,027 --> 00:34:26,663\ncreate does is it knows how to draw a Bezier Path in itself.\n\n646\n00:34:26,665 --> 00:34:29,800\nIt's just a generic Bezier path-drawing view. And\n\n647\n00:34:29,802 --> 00:34:33,970\nI'm gonna call it what did I call it? NamedBezierPathsView,\n\n648\n00:34:33,972 --> 00:34:37,507\nokay, cuz that's what it does. It's gonna have\n\n649\n00:34:37,509 --> 00:34:40,210\na dictionary of Bezier paths and it just draws them.\n\n650\n00:34:40,212 --> 00:34:42,979\nIt's really generic. It has nothing to do with DropIt.\n\n651\n00:34:42,981 --> 00:34:45,849\nI could well end up using this in some other app. Okay, and\n\n652\n00:34:45,851 --> 00:34:49,686\nthis is what this Named BezierPathsView is gonna have.\n\n653\n00:34:49,688 --> 00:34:54,357\nIt's gonna have public var called bezierPaths, okay,\n\n654\n00:34:54,359 --> 00:34:56,660\nwhich is going to be a dictionary,\n\n655\n00:34:56,662 --> 00:35:00,931\nwhich is String as the key, which is an arbitrary name,\n\n656\n00:35:00,933 --> 00:35:06,369\nand a UIBezierPath as the value, okay? And that's public\n\n657\n00:35:06,371 --> 00:35:09,272\nand anybody who wants to use this can just add something to\n\n658\n00:35:09,274 --> 00:35:13,610\nthat, and when they do I'm gonna watch didSet and\n\n659\n00:35:13,612 --> 00:35:17,114\ndo setNeedsDisplay, okay?\n\n660\n00:35:17,116 --> 00:35:19,249\nSo if anyone adds a Bezier path to this,\n\n661\n00:35:19,251 --> 00:35:22,252\nthen I'm going to NeedsDisplay and in my drawRect I'm gonna\n\n662\n00:35:22,254 --> 00:35:25,689\ndraw all these Bezier paths that are in this dictionary.\n\n663\n00:35:25,691 --> 00:35:29,159\nWhich is super simple to do, okay? I'm just gonna say for\n\n664\n00:35:29,161 --> 00:35:32,863\n_, path) because I don't really care what the names of\n\n665\n00:35:32,865 --> 00:35:35,298\nthem are where I'm drawing them. That's\n\n666\n00:35:35,300 --> 00:35:38,034\nonly w, if someone who's using it wants to replace one that's\n\n667\n00:35:38,036 --> 00:35:41,938\nalready there, they can use the same name. In bezierPaths,\n\n668\n00:35:41,940 --> 00:35:44,608\nso I'm just enumerating my bezierPath keys and\n\n669\n00:35:44,610 --> 00:35:47,377\nvalues, and I don't care about the keys. And I'm just gonna\n\n670\n00:35:47,379 --> 00:35:51,281\nsay path.stroke. So here I've created the world's simplest\n\n671\n00:35:51,283 --> 00:35:54,084\nlittle class but it's very powerful drawing class, okay,\n\n672\n00:35:54,086 --> 00:35:57,287\ncuz it, it, it draws arbitrary Bezier paths. Now if I really\n\n673\n00:35:57,289 --> 00:35:59,589\nwere creating this, I'd probably maybe let you\n\n674\n00:35:59,591 --> 00:36:02,926\nset the line width and color and other kinds of things, but\n\n675\n00:36:02,928 --> 00:36:05,061\nhere we're just gonna do the, the bar,\n\n676\n00:36:05,063 --> 00:36:09,065\nbare bones of it here. Okay, now how can I use this\n\n677\n00:36:09,067 --> 00:36:13,270\nin my DropIt? Anyone have an idea how I could really easily\n\n678\n00:36:13,272 --> 00:36:17,374\nuse this UIView to draw that circle in my DropIt?\n\n679\n00:36:20,512 --> 00:36:26,449\nHow's about if we make DropItView inherit from it?\n\n680\n00:36:27,853 --> 00:36:31,521\nNow all of a sudden, DropItView has a new instance\n\n681\n00:36:31,523 --> 00:36:35,225\nvariable called BezierPaths which it can set to any\n\n682\n00:36:35,227 --> 00:36:39,896\nBezierPaths it wants and it'll be drawn in itself, okay?\n\n683\n00:36:39,898 --> 00:36:42,999\nEveryone got that? So let's do that, okay?\n\n684\n00:36:43,001 --> 00:36:46,503\nWhen we set this barrier, let's go ahead and\n\n685\n00:36:46,505 --> 00:36:49,439\nset our own Bezier paths okay? This Bezier path is,\n\n686\n00:36:49,441 --> 00:36:53,143\nthis is the dictionary that we inherited from that class we\n\n687\n00:36:53,145 --> 00:36:56,980\njust created. And let's call it middle barrier again.\n\n688\n00:36:56,982 --> 00:37:01,117\nPathNames.MiddleBarrier, okay, we can give any name we want.\n\n689\n00:37:01,119 --> 00:37:06,456\nAnd it's equal to that path we just created. Let's go\n\n690\n00:37:06,458 --> 00:37:14,064\ntake a look at this. And sure enough, there it is. Okay,\n\n691\n00:37:14,066 --> 00:37:17,767\nnow it's stroked with line with one black color fine, but\n\n692\n00:37:17,769 --> 00:37:19,569\nthere it is. And we drop things now,\n\n693\n00:37:19,571 --> 00:37:23,139\nit's easier to see the things banging off of it.\n\n694\n00:37:24,009 --> 00:37:27,143\nOkay, and this barrier, of course, if we pile up enough\n\n695\n00:37:27,145 --> 00:37:30,780\nstuff, the things will start piling up around this barrier,\n\n696\n00:37:30,782 --> 00:37:33,817\nbecause everything bounces off of this barrier.\n\n697\n00:37:33,819 --> 00:37:35,885\nIt's causes collision. By the way,\n\n698\n00:37:35,887 --> 00:37:37,721\nif we put something inside that barrier, okay,\n\n699\n00:37:37,723 --> 00:37:42,993\nit would bounce around in the inside of the barrier. Okay,\n\n700\n00:37:42,995 --> 00:37:46,363\nyou got that? No remove completed?\n\n701\n00:37:46,365 --> 00:37:49,766\nRuh, okay, there we go. There we go.\n\n702\n00:37:49,768 --> 00:37:52,535\nAll right, so that's showing you a little bit there.\n\n703\n00:37:52,537 --> 00:37:56,640\nOkay the next one I'm gonna do is an attachment behavior. So\n\n704\n00:37:56,642 --> 00:38:00,677\nI'm gonna allow myself, when a thing drops here,\n\n705\n00:38:00,679 --> 00:38:03,747\nto grab onto a drop, okay, with my mouse,\n\n706\n00:38:03,749 --> 00:38:07,317\nor with my finger, if it was on a device and I'd make\n\n707\n00:38:07,319 --> 00:38:09,886\nan attachment to it. And remember an attachment is like\n\n708\n00:38:09,888 --> 00:38:13,990\nan iron bar that hooks up from either a point to an item or\n\n709\n00:38:13,992 --> 00:38:16,092\nbetween two items. In this case it's gonna be a point,\n\n710\n00:38:16,094 --> 00:38:19,796\nto point my finger is. And what also cool is, as my, I'm\n\n711\n00:38:19,798 --> 00:38:22,632\ngonna do a pan gesture and, as my finger moves around,\n\n712\n00:38:22,634 --> 00:38:24,934\nI'm gonna keep moving that attachment point. And\n\n713\n00:38:24,936 --> 00:38:28,638\nthat bar is gonna be dragged around with it and\n\n714\n00:38:28,640 --> 00:38:30,507\nthe item too, okay?\n\n715\n00:38:30,509 --> 00:38:33,343\nSo that's what we're gonna do. Let's do that attachment\n\n716\n00:38:33,345 --> 00:38:36,179\nbehavior. So, to do the attachment behavior,\n\n717\n00:38:36,181 --> 00:38:38,748\nI certainly need an attachment behavior.\n\n718\n00:38:38,750 --> 00:38:43,453\nSo I'm gonna create a private var, which is attachment,\n\n719\n00:38:43,455 --> 00:38:47,624\nUIAttachmentBehavior, okay? Actually we'll have it be\n\n720\n00:38:47,626 --> 00:38:50,827\nan optional, because we might not have an attachment yet. We\n\n721\n00:38:50,829 --> 00:38:54,698\ndon't have an attachment until we put our finger down on it,\n\n722\n00:38:54,700 --> 00:39:00,103\nto grab onto it. And when this attachment behavior\n\n723\n00:39:00,105 --> 00:39:04,674\ngets set to something we need to obviously add\n\n724\n00:39:04,676 --> 00:39:08,678\nthe behavior to our animator, otherwise this attachment\n\n725\n00:39:08,680 --> 00:39:12,382\nwon't do anything, okay? So what do we need to do that?\n\n726\n00:39:12,384 --> 00:39:16,319\nI'm just going to say if this attachment is not nil, okay,\n\n727\n00:39:16,321 --> 00:39:19,222\nif someone has set the attachment to be something\n\n728\n00:39:19,224 --> 00:39:24,728\nother than nil, then animator, addBehavior this attachment.\n\n729\n00:39:25,464 --> 00:39:27,230\nOkay, everyone understand that? Now, one thing,\n\n730\n00:39:27,232 --> 00:39:30,500\nby the way, I also am gonna do something we haven't done in\n\n731\n00:39:30,502 --> 00:39:34,437\na demo, which is willSet. And willSet happens before the new\n\n732\n00:39:34,439 --> 00:39:36,973\nvalue gets set. And what do I wanna do here?\n\n733\n00:39:36,975 --> 00:39:40,143\nHere I wanna say if my current attachment,\n\n734\n00:39:40,145 --> 00:39:46,116\nbefore I've set it, is not nil, then I want to remove it.\n\n735\n00:39:48,787 --> 00:39:50,186\nOkay, you see why I'm doing this?\n\n736\n00:39:50,188 --> 00:39:52,789\nRight, if someone sets the attachment to something new,\n\n737\n00:39:52,791 --> 00:39:55,625\nif there was an old attachment I wanna remove it, okay? So,\n\n738\n00:39:55,627 --> 00:39:58,828\nhere I'm just making sure that every time I set attachment,\n\n739\n00:39:58,830 --> 00:40:00,997\nthe old one gets removed, a new one gets added.\n\n740\n00:40:00,999 --> 00:40:04,701\nAll right with that. Okay, so we've got this attachment,how\n\n741\n00:40:04,703 --> 00:40:05,969\nare we gonna set this attachment?\n\n742\n00:40:05,971 --> 00:40:09,706\nWe gonna set it to something. I am only gonna allow you to\n\n743\n00:40:09,708 --> 00:40:12,442\ngrab onto the last drop that was dropped.\n\n744\n00:40:12,444 --> 00:40:15,278\nThis cause that you can drop a lot of drops,only the last one\n\n745\n00:40:15,280 --> 00:40:18,681\nyou dropped can you drag grab onto with this pan gesture.\n\n746\n00:40:18,683 --> 00:40:21,151\nSo I'm gonna need a var for the last drop.\n\n747\n00:40:21,153 --> 00:40:23,853\nSo let's go ahead and put a var, I don't know,\n\n748\n00:40:23,855 --> 00:40:29,692\nwe'll put it down here. private var lastDrop, okay,\n\n749\n00:40:30,061 --> 00:40:33,930\nwhich is a UIView, okay, and it also could be null,\n\n750\n00:40:33,932 --> 00:40:35,465\nit might not have dropped anything. And\n\n751\n00:40:35,467 --> 00:40:39,869\nevery time we add a drop, I'm just gonna set the lastDrop\n\n752\n00:40:39,871 --> 00:40:44,207\nequal to the drop. [INAUDIBLE] understand there, that's just\n\n753\n00:40:44,209 --> 00:40:47,143\ngrabbing the last drop. So, now, I have the last drop,\n\n754\n00:40:47,145 --> 00:40:51,848\nokay? And I get my finger down, I need to grab onto it,\n\n755\n00:40:51,850 --> 00:40:52,949\nokay? And create this attachment behavior.\n\n756\n00:40:52,951 --> 00:40:56,252\nSo, how am I gonna do that? All right, let's go here and\n\n757\n00:40:56,254 --> 00:41:00,557\ncreate a function called grabDrop which is going to be\n\n758\n00:41:00,559 --> 00:41:05,795\na hand gesture Handler, okay. Cuz we're gonna have a pan\n\n759\n00:41:05,797 --> 00:41:10,967\ngesture be how we grab onto this following drop. Okay,\n\n760\n00:41:10,969 --> 00:41:13,937\nso first I'm just gonna get the point of the gesture, or\n\n761\n00:41:13,939 --> 00:41:19,042\ngesturePoint, that's the recognizer locationInView, or\n\n762\n00:41:19,044 --> 00:41:22,679\nself. Okay, so now we know where that hand gesture is,\n\n763\n00:41:22,681 --> 00:41:25,415\neither at the start or as we're moving around we know\n\n764\n00:41:25,417 --> 00:41:28,418\nwhere it is. So now let's handle these pan\n\n765\n00:41:28,420 --> 00:41:32,388\ngesture states, okay, recognizer.state.\n\n766\n00:41:32,390 --> 00:41:36,593\nIf it's Began, right, if this thing just began,\n\n767\n00:41:36,595 --> 00:41:41,197\nthen we need to, you know, create the attachment. Okay,\n\n768\n00:41:41,199 --> 00:41:44,767\nif it's C=changed, okay, person moved the attachment\n\n769\n00:41:44,769 --> 00:41:49,205\naround, now we need to change the attachments Anchor point.\n\n770\n00:41:49,207 --> 00:41:51,708\nOkay, cuz remember I said the attachment is gonna attach\n\n771\n00:41:51,710 --> 00:41:55,645\na point to that drop and so as we pan around. We're gonna\n\n772\n00:41:55,647 --> 00:41:58,214\nkeep moving the point that it's attached to and that's\n\n773\n00:41:58,216 --> 00:42:02,051\ngonna drag the trop around with it by the iron bar, okay,\n\n774\n00:42:02,053 --> 00:42:06,489\nby the stiff bar. Otherwise, I'm just gonna set\n\n775\n00:42:06,491 --> 00:42:11,327\nthe attachment to nil. Okay, because if it's not begin or\n\n776\n00:42:11,329 --> 00:42:13,263\nchange, then it's either ended or some failure,\n\n777\n00:42:13,265 --> 00:42:16,232\nsomething like that, I want this attachment to go away.\n\n778\n00:42:16,234 --> 00:42:16,933\nOkay. If there is an attachment,\n\n779\n00:42:16,935 --> 00:42:18,801\nI want it to go away so that's the end of the line.\n\n780\n00:42:18,803 --> 00:42:24,440\nAll right. This one's easy, okay. Create the attachment's\n\n781\n00:42:24,442 --> 00:42:28,211\nanchor point. That's super easy. That's just attachments.\n\n782\n00:42:28,213 --> 00:42:32,849\nIf we have one. AnchorPoint = gesturePoint, okay?\n\n783\n00:42:32,851 --> 00:42:36,452\nThat's it. Okay? Remember, the attachment is just a behavior,\n\n784\n00:42:36,454 --> 00:42:38,388\nit's an object. It's got a var on it,\n\n785\n00:42:38,390 --> 00:42:41,524\nwhich is the anchor point. If it's a point to,\n\n786\n00:42:41,526 --> 00:42:43,993\na point connection to a item, it's got an anchor point.\n\n787\n00:42:43,995 --> 00:42:45,795\nAnd then we're just gonna change, as you drag around\n\n788\n00:42:45,797 --> 00:42:47,730\nwith the pan, we're just gonna keep changing that. And\n\n789\n00:42:47,732 --> 00:42:49,933\nthe animation system's automatically gonna react to\n\n790\n00:42:49,935 --> 00:42:50,833\nthat. We don't have to do anything.\n\n791\n00:42:50,835 --> 00:42:53,636\nJust automatically it's going to notice that change and\n\n792\n00:42:53,638 --> 00:42:57,507\ndeal with it. How about creating the attachment? Well,\n\n793\n00:42:57,509 --> 00:43:01,044\nhere we better make sure we have a drop to attach to.\n\n794\n00:43:01,046 --> 00:43:05,915\nSo I'm gonna say if the drop to drop To\n\n795\n00:43:05,917 --> 00:43:09,886\nattachTo equals the lastDrop. Okay, so in other words,\n\n796\n00:43:09,888 --> 00:43:12,822\nif we have a lastDrop, cuz we might've just started and\n\n797\n00:43:12,824 --> 00:43:14,290\nobviously if we start panning when\n\n798\n00:43:14,292 --> 00:43:16,492\nthere's nothing dropping, we can't do it. And\n\n799\n00:43:16,494 --> 00:43:22,999\nalso wanna make sure that that dropToAttachTo is in the view\n\n800\n00:43:23,001 --> 00:43:29,205\nhierarchy. Okay? So I want to make sure it hasn't\n\n801\n00:43:29,207 --> 00:43:33,242\nbeen removed from super view by, remove completed row or\n\n802\n00:43:33,244 --> 00:43:37,013\nany other way. So if I got a draft drop, I'm just gonna\n\n803\n00:43:37,015 --> 00:43:42,285\ncreate an attachment by saying it equals a UI attachment.\n\n804\n00:43:44,155 --> 00:43:46,856\nAttachment behavior Oops,\n\n805\n00:43:46,858 --> 00:43:51,594\nwe forget attach. Attachment,\n\n806\n00:43:51,596 --> 00:43:53,896\nUIAttachmentBehavior. And you can see,\n\n807\n00:43:53,898 --> 00:43:56,332\nhere's the different kinds of attachments you can create,\n\n808\n00:43:56,334 --> 00:43:59,736\nattach to an anchor, an item attached to another item.\n\n809\n00:43:59,738 --> 00:44:01,671\nYou can even attach items to anchors or\n\n810\n00:44:01,673 --> 00:44:03,606\nother items offsetFromCenter. In other words,\n\n811\n00:44:03,608 --> 00:44:05,875\nthe attachment doesn't have to be in the center of the thing,\n\n812\n00:44:05,877 --> 00:44:08,645\nit could be on a corner. If you do that Then as you pull\n\n813\n00:44:08,647 --> 00:44:10,880\nit around that thing's gonna be spinning around because,\n\n814\n00:44:10,882 --> 00:44:12,849\nyou know if you have the corner of a rectangle and you\n\n815\n00:44:12,851 --> 00:44:16,185\npull on it its gonna rotate as long as you allow rotation.\n\n816\n00:44:16,187 --> 00:44:18,755\nOkay? But here I want attached to anchor obviously. I'm\n\n817\n00:44:18,757 --> 00:44:21,724\ngonna attach it to the anchor which is the pan. The item\n\n818\n00:44:21,726 --> 00:44:27,730\nis the droptoattachto and the anchor is the gesturePoint.\n\n819\n00:44:27,732 --> 00:44:30,667\nOkay where the pan gesture went on.\n\n820\n00:44:30,669 --> 00:44:33,836\nBy the way I'm gonna make my game so that once you drab,\n\n821\n00:44:33,838 --> 00:44:36,706\ngrab onto this thing, you can't grab onto it again.\n\n822\n00:44:36,708 --> 00:44:38,074\nIf you grab on and you let it go,\n\n823\n00:44:38,076 --> 00:44:41,644\nyou can't grab it again. So last drop to nil in the case\n\n824\n00:44:41,646 --> 00:44:46,482\nwhere I create an attachment. Okay? We have to obviously\n\n825\n00:44:46,484 --> 00:44:50,286\nadd the GestureRecognizer that call this handler, so\n\n826\n00:44:50,288 --> 00:44:53,256\nwe were gonna do that obviously in our controller.\n\n827\n00:44:53,258 --> 00:44:55,892\nOkay, just like we added this TapGesture, let's go\n\n828\n00:44:55,894 --> 00:45:01,731\ngameView.addGestureRecognizer, UIPanGesture this time.\n\n829\n00:45:01,733 --> 00:45:04,634\nThe target this time is the gameView.\n\n830\n00:45:04,636 --> 00:45:11,607\nOkay, and the action is a selector which is\n\n831\n00:45:11,609 --> 00:45:18,881\nthe DropItView.grabDrop with an argument.\n\n832\n00:45:18,883 --> 00:45:23,986\nOkay, everybody got that? All right, we'll go back here so\n\n833\n00:45:23,988 --> 00:45:26,422\nyou can see this code on the screen at the same time.\n\n834\n00:45:26,424 --> 00:45:32,695\nTo run that. All right, so here we drop it.\n\n835\n00:45:32,697 --> 00:45:34,997\nI didn't grab it. Okay. We're gonna drop another one.\n\n836\n00:45:34,999 --> 00:45:38,768\nI grabbed it. Okay, do you see what's happening? It's kind of\n\n837\n00:45:38,770 --> 00:45:42,004\nhard to see. Watch this. Boing! Okay? So this thing is\n\n838\n00:45:42,006 --> 00:45:46,776\nbouncing around. I'm dragging it around, ok, with my finger.\n\n839\n00:45:46,778 --> 00:45:49,579\nLook. I can even it bounce it on the iron bar.\n\n840\n00:45:49,581 --> 00:45:51,881\nWooo. Now, it's kind of hard to see this.\n\n841\n00:45:51,883 --> 00:45:55,852\nWouldn't it be cool if we could draw a line there?\n\n842\n00:45:55,854 --> 00:45:58,755\nOkay? So that we could see this iron bar,\n\n843\n00:45:58,757 --> 00:46:01,724\nthat this attachment behavior is creating. And, of course,\n\n844\n00:46:01,726 --> 00:46:04,660\nwe can do that because we inherit from a class that\n\n845\n00:46:04,662 --> 00:46:07,196\nknows how to draw arbitrary path. So\n\n846\n00:46:07,198 --> 00:46:09,766\njust like we drew this little one, let's draw that bar.\n\n847\n00:46:09,768 --> 00:46:13,269\nBut it's a little tricky cuz that bar is always changing as\n\n848\n00:46:13,271 --> 00:46:16,205\nI drag it around with the pen, right? That think is always\n\n849\n00:46:16,207 --> 00:46:19,542\nchanging. So how are we going to have a hook\n\n850\n00:46:19,544 --> 00:46:22,578\nto know when to draw it? This is where that really cool\n\n851\n00:46:22,580 --> 00:46:28,050\nUI dynamic behavior mechanism I was talking about is action.\n\n852\n00:46:28,052 --> 00:46:30,553\nAll right. Action is a closure that you can set.\n\n853\n00:46:30,555 --> 00:46:34,323\nIt could get called every time that behavior acts. Perfect.\n\n854\n00:46:34,325 --> 00:46:37,960\nSo I'm gonna put that behavior on that attachment, so that\n\n855\n00:46:37,962 --> 00:46:41,664\nevery time that attachment has any affect on something,\n\n856\n00:46:41,666 --> 00:46:44,066\nI'm gonna re-draw my line.\n\n857\n00:46:44,068 --> 00:46:47,136\nOkay. Perfect opportunity to do that. All right. So\n\n858\n00:46:47,138 --> 00:46:52,108\nI'm gonna do that. Where is a good place to put that?\n\n859\n00:46:52,110 --> 00:46:59,248\nLet's put it down in where we create the attachment I guess.\n\n860\n00:46:59,250 --> 00:47:00,183\nOr is that here it is.\n\n861\n00:47:00,185 --> 00:47:02,285\nHere is where we create the attachment.\n\n862\n00:47:02,287 --> 00:47:04,387\nThis is where we are adding the behavior.\n\n863\n00:47:04,389 --> 00:47:07,323\nSo I'm als, in addition to adding the behavior here, I'm\n\n864\n00:47:07,325 --> 00:47:12,328\ngoing to say the attachments. Attachment, I have trouble\n\n865\n00:47:12,330 --> 00:47:16,833\ntyping that. The attachment to action equals some closure.\n\n866\n00:47:16,835 --> 00:47:21,270\nSo in here this is where we wanna draw that line, okay. So\n\n867\n00:47:21,272 --> 00:47:23,506\nhow are we gonna draw this line in here?\n\n868\n00:47:23,508 --> 00:47:26,409\nHow about let's get the attach drop. Okay?\n\n869\n00:47:26,411 --> 00:47:29,779\nCuz I wanna draw a line between the point, okay,\n\n870\n00:47:29,781 --> 00:47:33,482\nthat the gestures out and where the attached drop is.\n\n871\n00:47:33,484 --> 00:47:35,518\nSo I need to find that attached drop. So\n\n872\n00:47:35,520 --> 00:47:38,354\nhow can I find the attached drop from the attachment.\n\n873\n00:47:38,356 --> 00:47:42,191\nWell, here' how we do that. We can get the attachments. Oops,\n\n874\n00:47:42,193 --> 00:47:47,697\nequals. Get the attach, attachments items.\n\n875\n00:47:47,699 --> 00:47:49,999\nOkay, that's all the items that it's attaching.\n\n876\n00:47:50,001 --> 00:47:52,835\nNow it's only gonna be having this one drop attached,\n\n877\n00:47:52,837 --> 00:47:55,905\nokay it only attaches one drop. But, so this is an array\n\n878\n00:47:55,907 --> 00:47:59,108\nof items, so I'm gonna get the first one out of there cuz\n\n879\n00:47:59,110 --> 00:48:02,378\nI know there's only gonna be one. So I've got this first\n\n880\n00:48:02,380 --> 00:48:05,281\nthing, and I'm gonna make sure it's a UIView, okay?\n\n881\n00:48:05,283 --> 00:48:08,651\nI just wanna be 100% sure it's a UIView, and I want this var\n\n882\n00:48:08,653 --> 00:48:11,754\nright here to be of type UIView. Here it's complaining\n\n883\n00:48:11,756 --> 00:48:14,390\nbecause this is a closure, and so we have to have self,\n\n884\n00:48:14,392 --> 00:48:16,092\nexplicit self, cuz we're capturing self,\n\n885\n00:48:16,094 --> 00:48:18,828\nwhich is actually gonna be a huge problem here, by the way,\n\n886\n00:48:18,830 --> 00:48:21,330\nto capture self, we'll talk about that in a second,\n\n887\n00:48:21,332 --> 00:48:24,267\nall right? So now I've got the attached drop,\n\n888\n00:48:24,269 --> 00:48:30,907\nI just need to create a Bézier path, okay, UIBezierPath.\n\n889\n00:48:32,377 --> 00:48:36,812\nAnd I've got a nice lineFrom. Okay,\n\n890\n00:48:36,814 --> 00:48:42,184\na UIBezierPath.lineFrom the attachment's anchor point.\n\n891\n00:48:42,186 --> 00:48:45,121\nOops, not replacement,\n\n892\n00:48:45,123 --> 00:48:51,761\nanchorPoint to the attachedDrop.center.\n\n893\n00:48:52,797 --> 00:48:56,299\nOkay? See what I'm doing there? Okay, we also need some\n\n894\n00:48:56,301 --> 00:49:00,236\nself dot going on in here. We can do that,\n\n895\n00:49:00,238 --> 00:49:05,174\ncuz we know we're good on the attachment. What else do\n\n896\n00:49:05,176 --> 00:49:09,478\nwe got here okay, and so we need to give this a name,\n\n897\n00:49:09,480 --> 00:49:11,247\nright, cuz bezierPath is a dictionary, so\n\n898\n00:49:11,249 --> 00:49:13,215\nwe need give it a name. So let's go back down here and\n\n899\n00:49:13,217 --> 00:49:16,252\ncreate another named path, this one we'll call\n\n900\n00:49:16,254 --> 00:49:21,324\nAttachment. All right, so this is gonna be our\n\n901\n00:49:21,326 --> 00:49:25,795\nbezierPath[PathNames.Attachme- nt]. Maybe for\n\n902\n00:49:25,797 --> 00:49:28,631\nreadability here, I'll put this on the next line.\n\n903\n00:49:28,633 --> 00:49:31,467\nOkay? So there, we've created the Bezier path\n\n904\n00:49:31,469 --> 00:49:35,438\nto show this attachment. Everybody cool with that? Now,\n\n905\n00:49:35,440 --> 00:49:37,306\nthe other thing is, when we remove it,\n\n906\n00:49:37,308 --> 00:49:39,275\nwe better remove that thing. So self dot,\n\n907\n00:49:39,277 --> 00:49:42,345\nwe don't even need self here. We're not inside a closure.\n\n908\n00:49:42,347 --> 00:49:47,850\nBezierPaths[PathNames.Attachm- ent] = nil.\n\n909\n00:49:47,852 --> 00:49:51,153\nThat's a way to remove something from a dictionary,\n\n910\n00:49:51,155 --> 00:49:52,989\nby the way, just set it to nil. Okay,\n\n911\n00:49:52,991 --> 00:49:57,593\npretty cool with that? Now, as I mentioned we have a serious\n\n912\n00:49:57,595 --> 00:50:02,732\nproblem here with self being captured. Okay, because this\n\n913\n00:50:02,734 --> 00:50:06,435\ncell, okay, this closure keeps self in the heap. And\n\n914\n00:50:06,437 --> 00:50:08,204\nself keeps the closure in the heap,\n\n915\n00:50:08,206 --> 00:50:12,108\nbecause self.attachment.action equals this closure. So\n\n916\n00:50:12,110 --> 00:50:13,676\nthey each have strong pointers to each other,\n\n917\n00:50:13,678 --> 00:50:17,313\nthey can never leave the heap. Now, this one we can fix with\n\n918\n00:50:17,315 --> 00:50:21,951\nunowned self. Because we know that this behavior\n\n919\n00:50:21,953 --> 00:50:26,022\nis gonna leave the heap as soon as self leaves the heap,\n\n920\n00:50:26,024 --> 00:50:29,759\nso it's perfectly safe here to say, unowned self to\n\n921\n00:50:29,761 --> 00:50:33,696\nbreak that loop. Okay, self will never be around when this\n\n922\n00:50:33,698 --> 00:50:39,068\nattachment behavior's around, still around. Okay, so\n\n923\n00:50:39,070 --> 00:50:44,340\nlet's see if that works. All right,\n\n924\n00:50:44,342 --> 00:50:47,376\nlet's drop a few down. Now I'm gonna grab the next one.\n\n925\n00:50:47,378 --> 00:50:48,677\nThere it is. Okay, so\n\n926\n00:50:48,679 --> 00:50:52,281\nnow we can see a lot better what we're doing here. So\n\n927\n00:50:52,283 --> 00:50:58,554\nwe balance it. Okay? Got it. Make sense?\n\n928\n00:50:59,390 --> 00:51:03,659\nAll right, so that is all I wanted to show you for\n\n929\n00:51:03,661 --> 00:51:06,529\nbehaviors. Any questions about that stuff? I showed you\n\n930\n00:51:06,531 --> 00:51:08,564\na lot of behaviors there, attachments, colliders,\n\n931\n00:51:08,566 --> 00:51:12,601\nitem behaviors, gravity, okay, so that's plenty of stuff to\n\n932\n00:51:12,603 --> 00:51:17,106\nhelp you get started on your homework there. All right,\n\n933\n00:51:17,108 --> 00:51:20,676\nlet's go back and look at some slides here. So\n\n934\n00:51:20,678 --> 00:51:24,480\nnow I'm gonna talk about Core Motion, okay? Core Motion\n\n935\n00:51:24,482 --> 00:51:27,917\nis an object-oriented API to get at the motion\n\n936\n00:51:27,919 --> 00:51:29,285\nsensing hardware on your device.\n\n937\n00:51:29,287 --> 00:51:32,221\nSo that's accelerometer, the gyro, magnetometer,\n\n938\n00:51:32,223 --> 00:51:36,025\nthose kinds of things, all right? Not all devices have\n\n939\n00:51:36,027 --> 00:51:40,262\nall of this hardware, although in recent years they all do.\n\n940\n00:51:40,264 --> 00:51:43,499\nBut if your app wants to run back on iPhone 4 or\n\n941\n00:51:43,501 --> 00:51:46,202\nsomething like that, it doesn't have a gyro, for\n\n942\n00:51:46,204 --> 00:51:49,839\nexample, we kind of, for good programming technique,\n\n943\n00:51:49,841 --> 00:51:52,741\nwanna check to make sure that we have the hardware, and\n\n944\n00:51:52,743 --> 00:51:56,946\nyou'll see that in a second. You get at all this stuff\n\n945\n00:51:56,948 --> 00:51:59,682\nvia an instance of CMMotionManager.\n\n946\n00:51:59,684 --> 00:52:03,719\nNow, you really only wanna have one CMMotionManager in\n\n947\n00:52:03,721 --> 00:52:04,253\nyour entire app,\n\n948\n00:52:04,255 --> 00:52:06,789\nbecause there's only one gyro in your entire\n\n949\n00:52:06,791 --> 00:52:09,792\ndevice, right? So it really makes no sense to have two\n\n950\n00:52:09,794 --> 00:52:12,228\nmotion managers trying to, you know, cross over each\n\n951\n00:52:12,230 --> 00:52:14,930\nother. You need to coordinate it, so if you really had two\n\n952\n00:52:14,932 --> 00:52:18,300\ndifferent places in your app where you were accessing\n\n953\n00:52:18,302 --> 00:52:21,871\nthis hardware, then you would need to have a shared motion\n\n954\n00:52:21,873 --> 00:52:24,440\nmanager either as a static on some class\n\n955\n00:52:24,442 --> 00:52:26,942\nsomewhere or maybe part of your app delegate or something\n\n956\n00:52:26,944 --> 00:52:29,712\nlike that, that is, you know, dealing with the fact that two\n\n957\n00:52:29,714 --> 00:52:33,315\ndifferent people wanna look at the the hardware the same\n\n958\n00:52:33,317 --> 00:52:34,416\ntime, okay?\n\n959\n00:52:34,418 --> 00:52:36,285\nSo how do you use this motion manager to get this\n\n960\n00:52:36,287 --> 00:52:40,556\ninformation? Well, first it was two ways really, okay. One\n\n961\n00:52:40,558 --> 00:52:44,326\nway is by polling, and one way is by getting constant updates\n\n962\n00:52:44,328 --> 00:52:46,829\nabout what's going on, okay. But in either case, first\n\n963\n00:52:46,831 --> 00:52:49,165\nyou're gonna check to see if the hardware's available, and\n\n964\n00:52:49,167 --> 00:52:51,600\nI'll talk about how you do that. In the polling case,\n\n965\n00:52:51,602 --> 00:52:55,404\nyou're then going to tell the motion manager, okay, I want\n\n966\n00:52:55,406 --> 00:52:59,275\naccelerometer updates. Okay, and that'll turn that on. And\n\n967\n00:52:59,277 --> 00:53:02,178\nthen you just ask it, what's the current accelerometer,\n\n968\n00:53:02,180 --> 00:53:03,746\nwhat's the current accelerometer?\n\n969\n00:53:03,748 --> 00:53:04,680\nAny time, you can ask it, you want,\n\n970\n00:53:04,682 --> 00:53:08,117\nyou're polling it, basically, asking it. So that's one way,\n\n971\n00:53:08,119 --> 00:53:11,453\nrare that you would do that way. The second way, again,\n\n972\n00:53:11,455 --> 00:53:13,088\nyou check to see that hardware's available,\n\n973\n00:53:13,090 --> 00:53:15,758\nthen you're gonna set the rate at which you want\n\n974\n00:53:15,760 --> 00:53:18,194\nthe system to tell you about accelerometer or\n\n975\n00:53:18,196 --> 00:53:23,265\ngyro or magnetometer updates, okay. So five times a second,\n\n976\n00:53:23,267 --> 00:53:26,001\n30 times a second, probably not much more than that.\n\n977\n00:53:26,003 --> 00:53:28,771\nI mean, you can only draw it maybe 60 frames a second,\n\n978\n00:53:28,773 --> 00:53:31,974\nso you're probably not gonna need information much\n\n979\n00:53:31,976 --> 00:53:32,141\nBut you're gonna tell it how often you want it, okay?\n\n980\n00:53:32,143 --> 00:53:34,910\nmore than that.\n\n981\n00:53:34,912 --> 00:53:36,612\nThen you're gonna give it a closure, okay,\n\n982\n00:53:36,614 --> 00:53:39,381\na block of code. And it's going to execute that closure\n\n983\n00:53:39,383 --> 00:53:42,017\nthat many times. Five times a second, 30 times a second. And\n\n984\n00:53:42,019 --> 00:53:44,887\nthat closure, the arguments to it are the current state of\n\n985\n00:53:44,889 --> 00:53:48,257\nthe accelerometer or the current state of the gyro.\n\n986\n00:53:48,259 --> 00:53:51,794\nOkay, so those are the two ways to do it. So, let's fix,\n\n987\n00:53:51,796 --> 00:53:54,797\nsee how all this works. Checking the availability. You\n\n988\n00:53:54,799 --> 00:53:58,367\njust ask the CMMotionManager accelerometer Available.\n\n989\n00:53:58,369 --> 00:54:00,736\nThat's a Bool, okay, and it'll tell you yes or no,\n\n990\n00:54:00,738 --> 00:54:03,839\nor magnetometer available, and that's how you find out. Okay,\n\n991\n00:54:03,841 --> 00:54:06,475\nso it's as simple as that. So you always wanna check that,\n\n992\n00:54:06,477 --> 00:54:08,611\nthough, because if it's not available and\n\n993\n00:54:08,613 --> 00:54:11,080\nyou start asking for things, you're gonna get errors,\n\n994\n00:54:11,082 --> 00:54:14,750\nall right? Now, how do you, if you're doing the polling case,\n\n995\n00:54:14,752 --> 00:54:16,685\nhow do you start this thing up? You just say,\n\n996\n00:54:16,687 --> 00:54:20,422\nstart Accelerometer Updates, start Gyro Updates.\n\n997\n00:54:20,424 --> 00:54:22,424\nAnd it'll start looking at that hardware. Now,\n\n998\n00:54:22,426 --> 00:54:26,762\nthis is not free. Okay, having this thing start listening to\n\n999\n00:54:26,764 --> 00:54:31,367\nthese pieces of hardware costs battery especially, okay, and\n\n1000\n00:54:31,369 --> 00:54:33,068\nsome CPU too, but it costs battery.\n\n1001\n00:54:33,070 --> 00:54:36,005\nSo don't turn this on unless you're really ready to start\n\n1002\n00:54:36,007 --> 00:54:39,041\ngetting the information, okay? You can ask\n\n1003\n00:54:39,043 --> 00:54:42,745\nthe CMMotionManager whether it is currently, has that\n\n1004\n00:54:42,747 --> 00:54:46,015\nhardware fired up, basically, by saying, you know,\n\n1005\n00:54:46,017 --> 00:54:49,184\nAccelerometer active. And that's bool, yes or no. By\n\n1006\n00:54:49,186 --> 00:54:51,420\nthe way, you're noticing all here, you see accelerometer,\n\n1007\n00:54:51,422 --> 00:54:54,623\ngyro, magnetometer. You also see this thing, deviceMotion.\n\n1008\n00:54:54,625 --> 00:54:58,761\nOkay, deviceMotion is kind of a special device.\n\n1009\n00:54:58,763 --> 00:55:01,730\nIt's really a combination of the other three. Okay,\n\n1010\n00:55:01,732 --> 00:55:04,533\nan intelligent combination of the other three, and\n\n1011\n00:55:04,535 --> 00:55:08,437\nwe'll talk about that in a moment here. And\n\n1012\n00:55:08,439 --> 00:55:09,338\nthen to stop the hardware,\n\n1013\n00:55:09,340 --> 00:55:12,174\nto turn off the accelerometer, turn off the gyro, you just\n\n1014\n00:55:12,176 --> 00:55:16,845\nsay stop whatever updates, okay, and that'll stop it. And\n\n1015\n00:55:16,847 --> 00:55:20,215\nyou wanna do this as soon as you realize, I don't need it,\n\n1016\n00:55:20,217 --> 00:55:22,451\neven if you only don't need it for a little while and\n\n1017\n00:55:22,453 --> 00:55:24,887\nyou're gonna go back and turn it back on, fine. But\n\n1018\n00:55:24,889 --> 00:55:26,755\nany time you don't need it, turn it off, okay,\n\n1019\n00:55:26,757 --> 00:55:29,258\ndon't waste the user's battery by having this thing\n\n1020\n00:55:29,260 --> 00:55:32,861\nworking when you're not actually using the data. Okay,\n\n1021\n00:55:32,863 --> 00:55:36,065\nso that's how you kind of control the hardware.\n\n1022\n00:55:36,067 --> 00:55:39,134\nNow, again, we're talking about polling here,\n\n1023\n00:55:39,136 --> 00:55:40,669\nhow do I then say, okay, well,\n\n1024\n00:55:40,671 --> 00:55:42,371\nyou got the accelerometer turned on,\n\n1025\n00:55:42,373 --> 00:55:45,474\nwhat is the current value of the accelerometer? And you\n\n1026\n00:55:45,476 --> 00:55:49,311\njust use this CMMotionManager var accelerometer data.\n\n1027\n00:55:49,313 --> 00:55:53,982\nAnd it gives you this struct, CMAccelerometerData struct,\n\n1028\n00:55:53,984 --> 00:55:57,219\nand it's got the acceleration data in x, y, and z, okay?\n\n1029\n00:55:57,221 --> 00:56:01,824\nSo what is this x, y, and z? So here I have a device, okay,\n\n1030\n00:56:01,826 --> 00:56:05,561\nso, y Okay, y is this axis right here,\n\n1031\n00:56:05,563 --> 00:56:10,099\npointing down through the home button, okay?\n\n1032\n00:56:10,101 --> 00:56:14,236\nSo this is the y, okay? It's this vertical axis, okay?\n\n1033\n00:56:14,238 --> 00:56:18,440\nX is perpendicular to that, cross the device this way.\n\n1034\n00:56:18,442 --> 00:56:22,878\nSo this is y, with the home button being down. This is x.\n\n1035\n00:56:22,880 --> 00:56:28,951\nZ is out the back. Okay, so if I put this on a table,\n\n1036\n00:56:28,953 --> 00:56:33,689\nz, what do, what do you think z value would be?\n\n1037\n00:56:33,691 --> 00:56:37,693\n1.0. Okay, why 1.0? Because x, y, and\n\n1038\n00:56:37,695 --> 00:56:41,029\nz here are in g. Everyone know what g is, right? 9.8 meters\n\n1039\n00:56:41,031 --> 00:56:43,966\nper second squared. That's what g is. So z would be 1\n\n1040\n00:56:43,968 --> 00:56:47,603\ng if I sit it right there, okay? Because the acceleration\n\n1041\n00:56:47,605 --> 00:56:51,407\ndue to gravity is operating on it. And it does tell you\n\n1042\n00:56:51,409 --> 00:56:52,741\nthe acceleration is due to gravity,\n\n1043\n00:56:52,743 --> 00:56:54,610\nin addition to the acceleration due to the user\n\n1044\n00:56:54,612 --> 00:56:56,845\nmoving the thing around, okay. Acceleration going all\n\n1045\n00:56:56,847 --> 00:56:59,882\nover the place, okay? But the acceleration due to gravity\n\n1046\n00:56:59,884 --> 00:57:04,853\nalso counts, so that would be x and y 0, z 1.0.\n\n1047\n00:57:04,855 --> 00:57:08,157\nSimilarly if I do this, this would be y 1.0, x and\n\n1048\n00:57:08,159 --> 00:57:13,529\nz zero. Okay, so that's the acceleration there.\n\n1049\n00:57:13,898 --> 00:57:16,298\nYou get similar information for gyro, okay.\n\n1050\n00:57:16,300 --> 00:57:21,870\nThe gyro is the rotation of the device, okay. What, what,\n\n1051\n00:57:21,872 --> 00:57:26,141\nhow it's rotating, okay. And this is gonna tell you this in\n\n1052\n00:57:26,143 --> 00:57:29,378\nradians per second, same axes, okay, radians per second,\n\n1053\n00:57:29,380 --> 00:57:32,414\nhow this thing is rotating. Now there's a bias in here.\n\n1054\n00:57:32,416 --> 00:57:35,083\nI don't know if people know what a gyro bias is, but\n\n1055\n00:57:35,085 --> 00:57:36,385\none simple way to think about it is,\n\n1056\n00:57:36,387 --> 00:57:40,088\nif I'm moving like this, what if I'm also moving like this?\n\n1057\n00:57:40,090 --> 00:57:42,658\nOkay, you can see how that might make the gyro think this\n\n1058\n00:57:42,660 --> 00:57:45,394\nis moving faster than it is, because it's moving this way\n\n1059\n00:57:45,396 --> 00:57:48,197\nin addition to this. So there's a bias in there. And\n\n1060\n00:57:48,199 --> 00:57:53,769\nalso just the the gyro equipment has a bias built\n\n1061\n00:57:53,771 --> 00:57:55,637\ninto it. Now I'm gonna show you in a way, in a second,\n\n1062\n00:57:55,639 --> 00:57:59,107\na way to get this rotation as pure rotation without\n\n1063\n00:57:59,109 --> 00:58:02,277\nthat bias, okay? And also a way to get the accelerometer\n\n1064\n00:58:02,279 --> 00:58:07,115\ndata without gravity. The magnetometer is measuring\n\n1065\n00:58:07,117 --> 00:58:10,285\nmagnetic field, right? This is a thing that can find, you can\n\n1066\n00:58:10,287 --> 00:58:13,689\nfind true north. You can basically find out which way\n\n1067\n00:58:13,691 --> 00:58:17,526\neach of those axes is pointing relative to true north,\n\n1068\n00:58:17,528 --> 00:58:20,863\nby measuring the magnetic field around your device,\n\n1069\n00:58:20,865 --> 00:58:25,834\nokay. Now, I talked about the bias and acceleration due to\n\n1070\n00:58:25,836 --> 00:58:28,370\ngravity. Here's how you get that out of there.\n\n1071\n00:58:28,372 --> 00:58:31,974\nInstead of using CMAccelerometer, okay, or\n\n1072\n00:58:31,976 --> 00:58:36,645\nCMGyro, you use this device CMDeviceMotion.\n\n1073\n00:58:36,647 --> 00:58:38,313\nAnd that's the one that's the combination of the other\n\n1074\n00:58:38,315 --> 00:58:41,316\nthree. And by combining them and using the data from all of\n\n1075\n00:58:41,318 --> 00:58:44,486\nthem, it can tell you the part of the acceleration that is\n\n1076\n00:58:44,488 --> 00:58:48,123\ngravity, and the part of it is the user moving it. Okay,\n\n1077\n00:58:48,125 --> 00:58:52,928\nbecause it has the gyro, you see? So it knows from the gyro\n\n1078\n00:58:52,930 --> 00:58:57,132\nwhat's going on there. Similar, because it has\n\n1079\n00:58:57,134 --> 00:59:01,670\nthe accelerometer, it can unbias the gyro and\n\n1080\n00:59:01,672 --> 00:59:06,275\nit reports the gyro to you like an airplane. Any of you\n\n1081\n00:59:06,277 --> 00:59:08,810\npilots or anybody flown, piloting, know about it,\n\n1082\n00:59:08,812 --> 00:59:12,614\nokay. So imagine my iPad here is an airplane,\n\n1083\n00:59:12,616 --> 00:59:16,618\nokay. The way an airplane describes its motion is it\n\n1084\n00:59:16,620 --> 00:59:21,123\nhas, roll. Roll is this, okay, this axis in the middle,\n\n1085\n00:59:21,125 --> 00:59:23,225\nhow you're rolling. Okay, this is roll. So\n\n1086\n00:59:23,227 --> 00:59:25,994\nwhen airplanes turn, they roll and that causes them to turn,\n\n1087\n00:59:25,996 --> 00:59:29,765\nokay. Then there's pitch, that's up and down, right,\n\n1088\n00:59:29,767 --> 00:59:31,700\nairplane climbing and descending,\n\n1089\n00:59:31,702 --> 00:59:35,037\nokay. And then there's yaw. Yaw is when an airplane,\n\n1090\n00:59:35,039 --> 00:59:37,472\nlet's say there's a fierce wind coming this way,\n\n1091\n00:59:37,474 --> 00:59:38,640\nthe airplane wants to go that way but\n\n1092\n00:59:38,642 --> 00:59:42,644\nit actually has to turn this way to fight this wind. Okay,\n\n1093\n00:59:42,646 --> 00:59:45,647\nthe amount it's turned along this axis is\n\n1094\n00:59:45,649 --> 00:59:50,552\nthe yaw, okay. So you've got roll, pitch and yaw. Okay,\n\n1095\n00:59:50,554 --> 00:59:54,256\nso that's what we reported to you with CM device motion and\n\n1096\n00:59:54,258 --> 00:59:56,091\nthat is independent of any motion,\n\n1097\n00:59:56,093 --> 00:59:58,460\nwhether the airplane is going fast or sitting still,\n\n1098\n00:59:58,462 --> 01:00:01,129\nwhatever, you're going to get that roll, pitch and yaw,\n\n1099\n01:00:01,131 --> 01:00:05,467\nokay. So that's device motion, really powerful mechanism.\n\n1100\n01:00:05,469 --> 01:00:07,302\nAnd if you're doing anything with a gyro you're probably\n\n1101\n01:00:07,304 --> 01:00:11,306\ngonna be using Device Motion instead of CM Gyro. Okay,\n\n1102\n01:00:11,308 --> 01:00:14,142\nmagnetic field, with the CM Device Motion,\n\n1103\n01:00:14,144 --> 01:00:20,048\nit can tell you the accuracy of the magnetic field, okay.\n\n1104\n01:00:20,684 --> 01:00:23,485\nAll right, so, that, we talked about how to poll.\n\n1105\n01:00:23,487 --> 01:00:25,988\nYou just ask for the information you want.\n\n1106\n01:00:25,990 --> 01:00:28,890\nHow about if you wanna be notified 5 times a second,\n\n1107\n01:00:28,892 --> 01:00:32,594\nor 30 times a second of what's going on, very easy.\n\n1108\n01:00:32,596 --> 01:00:35,230\nYou just call startAccelerometer updates or\n\n1109\n01:00:35,232 --> 01:00:38,667\nstartGyro updates or startdevicemotion updates to\n\n1110\n01:00:38,669 --> 01:00:39,901\nqueue. And you give it a queue,\n\n1111\n01:00:39,903 --> 01:00:43,505\nthis is not a dispatc_queueT, this is an nsoperation queue,\n\n1112\n01:00:43,507 --> 01:00:46,408\nthe object oriented version I talked about. But\n\n1113\n01:00:46,410 --> 01:00:48,910\nprobably you're gonna be passing NSoperationmainqueue,\n\n1114\n01:00:48,912 --> 01:00:51,546\nor maybe you'll use NSoperationcurrentqueue if\n\n1115\n01:00:51,548 --> 01:00:54,383\nyou're on a different queue. You don't really wanna do this\n\n1116\n01:00:54,385 --> 01:00:56,618\non the main queue if you're gonna be doing it at a very\n\n1117\n01:00:56,620 --> 01:00:59,554\nhigh rate, like 30 frames a sec, 30 calls a second unless\n\n1118\n01:00:59,556 --> 01:01:03,258\nyou're doing something really simple. Just think about it,\n\n1119\n01:01:03,260 --> 01:01:05,227\nyou don't want the main queue busy doing that.\n\n1120\n01:01:05,229 --> 01:01:08,296\nBut if you're doing 4 or 5 frames a second, absolutely,\n\n1121\n01:01:08,298 --> 01:01:10,866\ndoing something simple, you can do that.\n\n1122\n01:01:10,868 --> 01:01:13,268\nThen you give it a handler. This is just a block,\n\n1123\n01:01:13,270 --> 01:01:16,271\na closure, and you can see that closure as two arguments.\n\n1124\n01:01:16,273 --> 01:01:18,840\nOne is that same CMAccelerometerData we\n\n1125\n01:01:18,842 --> 01:01:22,811\nsaw from before, the x, y and z, and g, that thing,\n\n1126\n01:01:22,813 --> 01:01:25,480\nokay, and also an error possibly.\n\n1127\n01:01:25,482 --> 01:01:26,448\nOkay, these are optionals,\n\n1128\n01:01:26,450 --> 01:01:29,551\nprobably if one's nil the other one's not, vice-versa.\n\n1129\n01:01:29,553 --> 01:01:31,453\nOkay, so this is just closure and inside that closure,\n\n1130\n01:01:31,455 --> 01:01:34,489\nyou can do anything you want with the AccelerometerData.\n\n1131\n01:01:34,491 --> 01:01:38,427\nAll right, similar with the gyro, startGyroUpdatesToQueue,\n\n1132\n01:01:38,429 --> 01:01:40,495\nyou're gonna get the gyro data.\n\n1133\n01:01:40,497 --> 01:01:43,498\nStartMagnetometerUpdatesToQu- eue, you're gonna get\n\n1134\n01:01:43,500 --> 01:01:45,600\nthe magnetometer data. And of course,\n\n1135\n01:01:45,602 --> 01:01:49,471\nstartDeviceMotionUpdatesToQu- eue, okay. You get the CM,\n\n1136\n01:01:49,473 --> 01:01:53,108\nCM button DeviceMotion, that's that thing that has vars like\n\n1137\n01:01:53,110 --> 01:01:57,713\ngravity and attitude for the roll, pitch and yaw, that kind\n\n1138\n01:01:57,715 --> 01:02:01,316\nof stuff. Just to talk a little bit about the errors,\n\n1139\n01:02:01,318 --> 01:02:03,251\nyou're, of course, gonna want to look in the documentation,\n\n1140\n01:02:03,253 --> 01:02:06,788\nbut some of the errors you can get are like you can't find\n\n1141\n01:02:06,790 --> 01:02:09,991\ntrue north maybe, too much interference.\n\n1142\n01:02:09,993 --> 01:02:12,394\nMaybe this activity's not authorized. Okay,\n\n1143\n01:02:12,396 --> 01:02:15,997\nmaybe user, you're not authorized to actually measure\n\n1144\n01:02:15,999 --> 01:02:17,999\nthe device's motion. Okay, that could be too.\n\n1145\n01:02:18,001 --> 01:02:20,068\nSo you do wanna be able to check for these errors to make\n\n1146\n01:02:20,070 --> 01:02:24,940\nsure you're actually getting good data. All right, so\n\n1147\n01:02:24,942 --> 01:02:28,443\nhow often you get these closures, called, is set with\n\n1148\n01:02:28,445 --> 01:02:31,513\nthese vars in motion manager, okay. Update interval,\n\n1149\n01:02:31,515 --> 01:02:34,149\nthis is just the number of seconds between calls.\n\n1150\n01:02:34,151 --> 01:02:38,854\nSo like 0.25 would be four times a second, okay? It is\n\n1151\n01:02:38,856 --> 01:02:42,724\nokay to, to have multiple, closures registered. You could\n\n1152\n01:02:42,726 --> 01:02:46,328\nsay startAccelerometer updates with handler and then call\n\n1153\n01:02:46,330 --> 01:02:48,029\nit again with another handler. But understand,\n\n1154\n01:02:48,031 --> 01:02:50,766\nthey're all gonna be called at this same interval cuz there's\n\n1155\n01:02:50,768 --> 01:02:53,869\nonly this one motion manager that you're gonna create for\n\n1156\n01:02:53,871 --> 01:02:54,503\nyour whole app, okay.\n\n1157\n01:02:54,505 --> 01:02:56,505\nAll right, so let's take a look at this.\n\n1158\n01:02:56,507 --> 01:02:59,641\nLet's take DropIt, and let's make the gravity that's in\n\n1159\n01:02:59,643 --> 01:03:03,979\nDropIt be real gravity, okay. Right now the gravity just\n\n1160\n01:03:03,981 --> 01:03:06,281\ngoes down towards the home button, but let's make it so\n\n1161\n01:03:06,283 --> 01:03:08,683\nthat it's actual gravity. So as I move my thing around,\n\n1162\n01:03:08,685 --> 01:03:12,921\nthose blocks are gonna start swinging towards real gravity.\n\n1163\n01:03:13,357 --> 01:03:18,760\nAll right, so how are we gonna do that? I'm going to\n\n1164\n01:03:18,762 --> 01:03:25,767\ngo to my DropIt view right here, I'm gonna add a new var,\n\n1165\n01:03:25,769 --> 01:03:31,273\npublic var called realGravity, and it's gonna be a Bool,\n\n1166\n01:03:31,275 --> 01:03:35,410\nokay? I'll start it out being false. And if this is on,\n\n1167\n01:03:35,412 --> 01:03:38,313\nthen I'm gonna use real gravity in my DropIt.\n\n1168\n01:03:38,315 --> 01:03:40,515\nIf it's off, I'm gonna use fake gravity,\n\n1169\n01:03:40,517 --> 01:03:44,452\nthe gravity I already have basically, all right? And so\n\n1170\n01:03:44,454 --> 01:03:47,455\nlet's go back to our controller and\n\n1171\n01:03:47,457 --> 01:03:48,824\nset this to be true, so\n\n1172\n01:03:48,826 --> 01:03:52,394\nI'm just gonna do it here in the didSet here,\n\n1173\n01:03:52,396 --> 01:03:57,599\ngameView.realgravity. Gravity and real,\n\n1174\n01:03:57,601 --> 01:04:01,870\nrealGravity equals true. Okay, so\n\n1175\n01:04:01,872 --> 01:04:05,006\nwe've got realGravity turned on. And how am I gonna make\n\n1176\n01:04:05,008 --> 01:04:08,743\nthis real gravity work? Well anytime someone changes this,\n\n1177\n01:04:08,745 --> 01:04:11,446\nI'm gonna call some method update real gravity or\n\n1178\n01:04:11,448 --> 01:04:14,883\nsomething, and this is the method that's gonna have to\n\n1179\n01:04:14,885 --> 01:04:17,853\nturn the accelerometer on to start using it. Okay?\n\n1180\n01:04:17,855 --> 01:04:22,557\nSo that's a private funk update real gravity.\n\n1181\n01:04:22,559 --> 01:04:23,625\nOkay, so this is going to be the guts.\n\n1182\n01:04:23,627 --> 01:04:26,494\nThis is going to be the thing that's actually doing\n\n1183\n01:04:26,496 --> 01:04:27,729\nthe work here. All right, so\n\n1184\n01:04:27,731 --> 01:04:30,465\nwhat do update real gravity going to do? Well,\n\n1185\n01:04:30,467 --> 01:04:32,434\nit's going to do something with the accelerometer. And\n\n1186\n01:04:32,436 --> 01:04:34,669\nwe to use the accelerometer to get the gravity.\n\n1187\n01:04:34,671 --> 01:04:35,804\nI'm not going to use device motion,\n\n1188\n01:04:35,806 --> 01:04:40,075\nokay, just to make it simple, we'll use the accelerometer.\n\n1189\n01:04:40,077 --> 01:04:43,211\nWe want the real gravity anyway so we'll use that. So I\n\n1190\n01:04:43,213 --> 01:04:46,281\nneed a private var here which is that motion manager. As I\n\n1191\n01:04:46,283 --> 01:04:48,984\ntold you, you need a motion manager to do any of this. So,\n\n1192\n01:04:48,986 --> 01:04:52,087\nwe'll just say that equals CMMotionManager.\n\n1193\n01:04:52,089 --> 01:04:54,122\nI'm not using any of this in\n\n1194\n01:04:54,124 --> 01:04:56,391\nany other part of my app. So I'm putting it here.\n\n1195\n01:04:56,393 --> 01:04:59,227\nAgain, if I was using it in two different places,\n\n1196\n01:04:59,229 --> 01:05:02,964\nI'd have to make this be some sort of shared resource.\n\n1197\n01:05:02,966 --> 01:05:04,699\nNotice it is complaining right here, okay?\n\n1198\n01:05:04,701 --> 01:05:05,934\nDoes never heard of a CMMotionManager and\n\n1199\n01:05:05,936 --> 01:05:08,003\nit doesn't know what the heck we're talking about.\n\n1200\n01:05:08,005 --> 01:05:11,039\nThis is because this is in a different framework,\n\n1201\n01:05:11,041 --> 01:05:15,677\nimport,CcoreMotion, okay? All this CoreMotion stuff you have\n\n1202\n01:05:15,679 --> 01:05:19,848\nto import CoreMotion. All right, so we have our\n\n1203\n01:05:19,850 --> 01:05:22,450\nmotion manager right here. How are we going to use our\n\n1204\n01:05:22,452 --> 01:05:25,987\nmotion manager to grab that accelerometer, information?\n\n1205\n01:05:25,989 --> 01:05:31,226\nSo if we want real gravity, then we're going to do that.\n\n1206\n01:05:31,228 --> 01:05:32,928\nBy the way, if we don't want real gravity,\n\n1207\n01:05:32,930 --> 01:05:35,997\nthen I'm going to tell the motion manager to stop\n\n1208\n01:05:35,999 --> 01:05:40,001\naccelerometer updates. Again, I always want to stop that\n\n1209\n01:05:40,003 --> 01:05:43,939\nupdating happening any time I don't want the updates, okay.\n\n1210\n01:05:43,941 --> 01:05:46,741\nSo we try to keep that off as much as possible. But if we do\n\n1211\n01:05:46,743 --> 01:05:51,579\nwant real gravity, then first I'm gonna check to see, if\n\n1212\n01:05:51,581 --> 01:05:57,886\nthe motionManager accelerometer is available.\n\n1213\n01:05:57,888 --> 01:06:02,257\nOkay, as promised, this is first thing we need to do.\n\n1214\n01:06:02,259 --> 01:06:03,758\nActually I'm also going to see here if\n\n1215\n01:06:03,760 --> 01:06:06,628\nthe accelerometer is already active. Cuz maybe I already\n\n1216\n01:06:06,630 --> 01:06:09,364\ncalled updateRealGravity and it's already running. So\n\n1217\n01:06:09,366 --> 01:06:14,903\nI'm gonna actually say and the motionManager.accelerometerAc-\n\n1218\n01:06:14,905 --> 01:06:19,607\ntive is false. Okay? So if the accelerometer is available and\n\n1219\n01:06:19,609 --> 01:06:20,075\nit's not already running,\n\n1220\n01:06:20,077 --> 01:06:24,079\nthen I need to fire this thing up, okay? So let's fire it up.\n\n1221\n01:06:24,081 --> 01:06:27,949\nLet's start with our update interval. So I'm going to have\n\n1222\n01:06:27,951 --> 01:06:30,919\nthe accelerometer update interval be, I,\n\n1223\n01:06:30,921 --> 01:06:35,090\nmaybe 0.25, 0.2 is probably enough. You know, gravity\n\n1224\n01:06:35,092 --> 01:06:38,193\ndoesn't really need to change that much more often than that\n\n1225\n01:06:38,195 --> 01:06:40,161\nas I am moving my device around. This is a number\n\n1226\n01:06:40,163 --> 01:06:43,031\nI could play with. Again, this should probably, not probably,\n\n1227\n01:06:43,033 --> 01:06:45,600\ndefinitely be a constant but we're time constrained here so\n\n1228\n01:06:45,602 --> 01:06:50,872\nI'm not gonna do that. So now I'm just gonna have the motion\n\n1229\n01:06:50,874 --> 01:06:54,309\nmanager start giving me updates to queue,\n\n1230\n01:06:54,311 --> 01:06:57,612\nokay? So this is how I started updating. Now, what queue am I\n\n1231\n01:06:57,614 --> 01:06:59,581\ngonna use? I'm gonna use the main cue here cuz\n\n1232\n01:06:59,583 --> 01:07:01,916\nI'm only doing it four times a second and I'm only just\n\n1233\n01:07:01,918 --> 01:07:04,052\ngonna set that gravity thing, that's all I'm gonna do, so\n\n1234\n01:07:04,054 --> 01:07:07,222\nthat's really lightweight so I can just use the main queue.\n\n1235\n01:07:07,224 --> 01:07:11,059\nSo, enter operation queue main queue. Okay,\n\n1236\n01:07:11,061 --> 01:07:14,362\nhere's the handler, the CM handler. I always recommend\n\n1237\n01:07:14,364 --> 01:07:17,098\ndouble clicking on these things because it fills\n\n1238\n01:07:17,100 --> 01:07:21,603\nout really nicely. Your arguments and\n\n1239\n01:07:21,605 --> 01:07:25,106\nstuff like that. I'm also going to use the closing or\n\n1240\n01:07:25,108 --> 01:07:29,911\nthe trailing closure syntax here to do this, all right.\n\n1241\n01:07:29,913 --> 01:07:32,747\nSo I'm going to start this accelerometer,\n\n1242\n01:07:32,749 --> 01:07:34,616\nhere is my closure that I have to do,\n\n1243\n01:07:34,618 --> 01:07:39,621\nokay? So, this accelerometer data, I'll call it data. This\n\n1244\n01:07:39,623 --> 01:07:44,459\nerror I'll call error. Okay, so, how am I gonna do this?\n\n1245\n01:07:44,461 --> 01:07:48,630\nWell, this data might be nil, it's an optional. So, I'm\n\n1246\n01:07:48,632 --> 01:07:51,132\ngonna see if I can get the accelerometer data first.\n\n1247\n01:07:51,134 --> 01:07:54,702\nSo, let's say if I can let, we'll call the x,\n\n1248\n01:07:54,704 --> 01:07:57,539\nI'm only caring about x and y. Don't care about z, okay,\n\n1249\n01:07:57,541 --> 01:08:01,242\nbecause I'm gonna have the my little drop it is two\n\n1250\n01:08:01,244 --> 01:08:03,244\ndimensional so it doesn't care about z. So\n\n1251\n01:08:03,246 --> 01:08:07,582\nif I can let dx equal the data acceleration in x, and\n\n1252\n01:08:07,584 --> 01:08:12,020\nalso we can let dy equal the data's acceleration in y so\n\n1253\n01:08:12,022 --> 01:08:16,124\nthen I'm just getting simultaneously getting and\n\n1254\n01:08:16,126 --> 01:08:19,794\nchecking to be sure the data is not nil, so\n\n1255\n01:08:19,796 --> 01:08:21,062\nI've got the dx a new y.\n\n1256\n01:08:21,064 --> 01:08:28,803\nLet's first try to just set the drop behaviors gravity's,\n\n1257\n01:08:28,805 --> 01:08:33,808\ngravity direction, to just be a CG vector\n\n1258\n01:08:33,810 --> 01:08:37,812\nwhich is dx and dy, okay? So we're gonna try this first.\n\n1259\n01:08:37,814 --> 01:08:41,483\nNow, this is not gonna work because gravity is private. So\n\n1260\n01:08:41,485 --> 01:08:44,285\nlet's just go over to our behavior, falling object\n\n1261\n01:08:44,287 --> 01:08:47,655\nbehaviour here. I'm gonna make this not be private. Okay,\n\n1262\n01:08:47,657 --> 01:08:50,191\njust for expediency. Maybe we wanna make some other public\n\n1263\n01:08:50,193 --> 01:08:53,128\nAPI like we did with Glider here. I'm just gonna make this\n\n1264\n01:08:53,130 --> 01:08:57,932\npublic. Make it a little, go a little faster. All right, so\n\n1265\n01:08:57,934 --> 01:09:01,669\nhere we are, we're saving this, gravity here.\n\n1266\n01:09:02,305 --> 01:09:05,206\nYeah good one, that's what, okay got it.\n\n1267\n01:09:05,208 --> 01:09:09,511\nVery good catch, bonus points, all right, so right.\n\n1268\n01:09:09,513 --> 01:09:13,848\nSo there's that, one other thing I wanna be careful of\n\n1269\n01:09:13,850 --> 01:09:17,986\nhere is memory cycle. Okay I've got this accelerometer,\n\n1270\n01:09:17,988 --> 01:09:20,655\ncuz motion manager has accelerometer that that\n\n1271\n01:09:20,657 --> 01:09:23,925\nthing has a hold of this closure, I have a hold of it.\n\n1272\n01:09:23,927 --> 01:09:25,426\nOkay I have a hold the of motion manger. And\n\n1273\n01:09:25,428 --> 01:09:29,597\nMotion manager has a hold of me, okay? So that's not good.\n\n1274\n01:09:29,599 --> 01:09:33,268\nAgain, we can do unowned to solve this one. Oops don't put\n\n1275\n01:09:33,270 --> 01:09:37,505\nit there. Unowned goes over here. We can do unowned\n\n1276\n01:09:37,507 --> 01:09:42,177\nself here because as soon as self leaves the heap,\n\n1277\n01:09:42,179 --> 01:09:44,512\nthis motionManager is gonna leave the heap with it,\n\n1278\n01:09:44,514 --> 01:09:46,915\nwhich means this closure is gonna go out too.\n\n1279\n01:09:46,917 --> 01:09:49,417\nSo this closure will never get executed with self not in\n\n1280\n01:09:49,419 --> 01:09:52,787\nthe heap. Once self leaves the heap, this guy goes with it.\n\n1281\n01:09:52,789 --> 01:09:56,224\nSo we can do unowned here, to do that. The only other\n\n1282\n01:09:56,226 --> 01:10:00,562\nthing I want to do here is if, I, I want to try and turn this\n\n1283\n01:10:00,564 --> 01:10:04,299\naccelerator updates off as much as possible. So another\n\n1284\n01:10:04,301 --> 01:10:08,436\ntime I want to turn it off is if I'm not animating, right?\n\n1285\n01:10:08,438 --> 01:10:11,940\nIf I have my dropBehavior, okay, and it's not currently\n\n1286\n01:10:11,942 --> 01:10:15,243\nanimating, I do not want to be continuing to do this.\n\n1287\n01:10:15,245 --> 01:10:19,814\nSo, I'm gonna say only do this if my dropBehavior,\n\n1288\n01:10:19,816 --> 01:10:24,185\nit's dynamic animator is not nil. That's how you can tell\n\n1289\n01:10:24,187 --> 01:10:25,887\nwhether a behaviour is currently being animated.\n\n1290\n01:10:25,889 --> 01:10:29,490\nIf it has a dynamic animator, it's being animated. If not,\n\n1291\n01:10:29,492 --> 01:10:34,028\nit's not. So, if it's not nil, then we'll do this. Otherwise,\n\n1292\n01:10:34,030 --> 01:10:38,099\nI'm going to stop this motion manager, okay?\n\n1293\n01:10:38,101 --> 01:10:41,703\nStop accelerometer updates in this motion manager. You see\n\n1294\n01:10:41,705 --> 01:10:45,039\nhow I'm trying to stop this thing as much as possible?\n\n1295\n01:10:45,041 --> 01:10:46,407\nThe only thing about this, though,\n\n1296\n01:10:46,409 --> 01:10:49,310\nis if I do stop it because I stop animating, then I better\n\n1297\n01:10:49,312 --> 01:10:51,646\nbe sure that when I start animating up again.\n\n1298\n01:10:51,648 --> 01:10:53,181\nRemember this is that animating bar,\n\n1299\n01:10:53,183 --> 01:10:54,782\nyou set it to true to start animating.\n\n1300\n01:10:54,784 --> 01:10:58,152\nI better update my real gravity here to make sure that\n\n1301\n01:10:58,154 --> 01:11:01,556\nI start the accelerometer back up again, okay? So\n\n1302\n01:11:01,558 --> 01:11:03,124\nthat allows me to start and stop animating.\n\n1303\n01:11:03,126 --> 01:11:06,394\nIt stops the accelerometers, every time I restart it,\n\n1304\n01:11:06,396 --> 01:11:09,264\nit starts them again, okay? So let's try this and\n\n1305\n01:11:09,266 --> 01:11:11,299\nsee if it works. Now, this is the first time in this\n\n1306\n01:11:11,301 --> 01:11:12,200\nclass where I'm having to actually,\n\n1307\n01:11:12,202 --> 01:11:15,903\nI can't do it in a simulator because the simulator has no,\n\n1308\n01:11:15,905 --> 01:11:17,505\naccelerometer or anything like that, so\n\n1309\n01:11:17,507 --> 01:11:21,376\nwe're gonna be doing it here on this other device.\n\n1310\n01:11:21,378 --> 01:11:26,147\nLet me run over here and show you this. All right, so\n\n1311\n01:11:26,149 --> 01:11:30,551\nlet's run this on our device here, here we go,\n\n1312\n01:11:30,553 --> 01:11:33,187\nit's coming up here, there it is, we see our little circle,\n\n1313\n01:11:33,189 --> 01:11:38,793\nif I tap, it's not working. What's going on here?\n\n1314\n01:11:38,795 --> 01:11:41,396\nWhy wouldn't that be working? I got the gravity going on\n\n1315\n01:11:41,398 --> 01:11:46,501\nthere, hm. Maybe if I turn my thing upside down, woah!\n\n1316\n01:11:46,503 --> 01:11:48,703\nThat worked, I turned my iPad upside down, and\n\n1317\n01:11:48,705 --> 01:11:52,874\nall of a sudden gravity seems to be backwards here, okay?\n\n1318\n01:11:52,876 --> 01:11:57,111\nNow why would gravity be backwards? The answer is,\n\n1319\n01:11:57,113 --> 01:12:01,282\nbecause our drawing coordinate system has 0,0 in the upper\n\n1320\n01:12:01,284 --> 01:12:04,752\nleft. So this is working fine, it's falling down toward zero,\n\n1321\n01:12:04,754 --> 01:12:08,022\nit's just that's in the upper left. So we need to add some\n\n1322\n01:12:08,024 --> 01:12:12,126\ncode here that knows what the orientation of our device is,\n\n1323\n01:12:12,128 --> 01:12:16,297\nand adjusts, okay, for the fact that it's upside down,\n\n1324\n01:12:16,299 --> 01:12:19,567\nbasically. Also, when we turn sideways, and\n\n1325\n01:12:19,569 --> 01:12:21,369\nwe're looking at landscape mode,\n\n1326\n01:12:21,371 --> 01:12:24,172\nwe wanna make sure that's doing the right thing as well.\n\n1327\n01:12:24,174 --> 01:12:28,843\nSo let's put that in here. Okay, that goes right, so\n\n1328\n01:12:28,845 --> 01:12:32,613\nlet's put that right in here. Okay, we've got our dx and dy.\n\n1329\n01:12:32,615 --> 01:12:36,751\nAll I'm gonna do here is I'm gonna switch on my device's,\n\n1330\n01:12:36,753 --> 01:12:40,621\nthis is how you get the current device's orientation,\n\n1331\n01:12:40,623 --> 01:12:43,124\nokay. This will return the orientation of the current\n\n1332\n01:12:43,126 --> 01:12:48,196\ndevice. And so for example, in the case of portrait, okay,\n\n1333\n01:12:48,198 --> 01:12:51,666\nwe know that portrait is upside down, so\n\n1334\n01:12:51,668 --> 01:12:54,535\nI'm gonna say dy = -dy in portrait.\n\n1335\n01:12:54,537 --> 01:12:58,639\nIn the case of portrait upside down, everything's fine.\n\n1336\n01:12:58,641 --> 01:13:00,875\nWe know that that works, okay. Portrait upside down,\n\n1337\n01:13:00,877 --> 01:13:03,611\nwe've got the right thing. How about LandscapeLeft,\n\n1338\n01:13:03,613 --> 01:13:07,715\nor LandscapeRight, let's say. In LandscapeRight, x and\n\n1339\n01:13:07,717 --> 01:13:11,819\ny are swapped, right, because I've turned it sideways, so\n\n1340\n01:13:11,821 --> 01:13:14,789\nnow it's the x of my device that's down. So\n\n1341\n01:13:14,791 --> 01:13:17,759\nI need to swap them. There's actually a nice method here or\n\n1342\n01:13:17,761 --> 01:13:21,496\nfunction called swap which will swap two variables, okay.\n\n1343\n01:13:21,498 --> 01:13:29,370\nAnd then in LandscapeLeft, not only are they swapped,\n\n1344\n01:13:29,372 --> 01:13:34,675\nbut also dy has to be -dy, okay?\n\n1345\n01:13:34,677 --> 01:13:38,279\nIn other cases, there are other cases like FaceUp and\n\n1346\n01:13:38,281 --> 01:13:41,816\nFaceDown. Those are orientations. In those cases,\n\n1347\n01:13:41,818 --> 01:13:45,119\nthere should be no gravity going on. So I'm gonna say dx\n\n1348\n01:13:45,121 --> 01:13:49,323\n= 0, dy = 0. Okay, because my thing is flat or whatever.\n\n1349\n01:13:49,325 --> 01:13:52,827\nNow, notice I'm modifying dy and dx in here, but I said\n\n1350\n01:13:52,829 --> 01:13:57,298\nif let, just to remind you all you can change this to var,\n\n1351\n01:13:57,300 --> 01:14:01,502\nif var. Exactly the same as if let, it's just that\n\n1352\n01:14:01,504 --> 01:14:05,640\nthese will now be vars that inside here you can modify.\n\n1353\n01:14:05,642 --> 01:14:10,545\nOkay, everybody got that? Okay, so\n\n1354\n01:14:10,547 --> 01:14:18,119\nlet's try that. All right,\n\n1355\n01:14:18,121 --> 01:14:21,222\nhere we go. Drop it, it's working! Look at this.\n\n1356\n01:14:21,224 --> 01:14:23,691\nDropping some more things, I have my thing face up.\n\n1357\n01:14:23,693 --> 01:14:26,694\nOkay, now I'm going to turn my thing upside down.\n\n1358\n01:14:26,696 --> 01:14:30,531\nLet's see if they all fall down. And they do! Excellent.\n\n1359\n01:14:30,533 --> 01:14:36,003\nOkay, now I'm gonna turn it sideways. Bam. Okay,\n\n1360\n01:14:36,005 --> 01:14:41,042\nsideways around the other way. Okay. Now,\n\n1361\n01:14:41,044 --> 01:14:44,011\none thing that's interesting about this is I actually have\n\n1362\n01:14:44,013 --> 01:14:47,648\nmy rotation locked. If I unlock my rotation,\n\n1363\n01:14:47,650 --> 01:14:49,784\nthen my view is gonna change. Watch this.\n\n1364\n01:14:49,786 --> 01:14:54,555\nSee? So since it switched, all the views moved to the bottom.\n\n1365\n01:14:54,557 --> 01:14:57,291\nSo it didn't actually do much. Now, I can try and\n\n1366\n01:14:57,293 --> 01:15:00,795\nmove it around without changing my orientation, but\n\n1367\n01:15:00,797 --> 01:15:02,997\nas soon as my orientation changes,\n\n1368\n01:15:02,999 --> 01:15:07,368\nit's gonna jump around. Got that?\n\n1369\n01:15:07,370 --> 01:15:11,606\nOkay? All right, that's it for\n\n1370\n01:15:11,608 --> 01:15:14,342\ntoday. You have everything you need to know, I hope,\n\n1371\n01:15:14,344 --> 01:15:18,246\nto do your assignment six. If you have any questions,\n\n1372\n01:15:18,248 --> 01:15:20,781\nI'll be here as usual. >> For\n\n1373\n01:15:20,783 --> 01:15:20,814\nmore, please visit us at Stanford.edu.\n\n"
  },
  {
    "path": "subtitles/15. Application Lifecycle, Alerts, CloudKit.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:08,173\n[SOUND] Stanford University. >> All right,\n\n2\n00:00:08,175 --> 00:00:13,145\nwell welcome to lecture 15 CS193P Spring of 2016.\n\n3\n00:00:13,147 --> 00:00:16,915\nSo today we have three major topics.\n\n4\n00:00:16,917 --> 00:00:18,350\nOne is the Application Life Cycle.\n\n5\n00:00:18,352 --> 00:00:20,786\nRemember we talked about the View Controller Life Cycle.\n\n6\n00:00:20,788 --> 00:00:23,956\nHow View Controller comes into existence and goes on and\n\n7\n00:00:23,958 --> 00:00:25,090\noff screen and all that stuff. Well,\n\n8\n00:00:25,092 --> 00:00:27,726\nan Application goes through a similar sort of life cycle.\n\n9\n00:00:27,728 --> 00:00:30,596\nAnd we're going to talk about that. And along the way I'm\n\n10\n00:00:30,598 --> 00:00:32,998\nalso going to talk about NS Notification, which\n\n11\n00:00:33,000 --> 00:00:35,834\nis that radio station from the NBC that we talked about\n\n12\n00:00:35,836 --> 00:00:37,369\nat the very beginning of the Quarter.\n\n13\n00:00:37,371 --> 00:00:40,239\nAnd we're going to talk about alerts. And I'm going to\n\n14\n00:00:40,241 --> 00:00:41,974\nswitch gears a little from what I had said and\n\n15\n00:00:41,976 --> 00:00:44,977\ntalk today about Cloud Kit. Because quite a few of you\n\n16\n00:00:44,979 --> 00:00:46,645\nhave come up to me in your final projects and said.\n\n17\n00:00:46,647 --> 00:00:50,582\nWell, I want to do a little light weight backend over\n\n18\n00:00:50,584 --> 00:00:50,716\nmaybe something simple like, some sort of messaging or\n\n19\n00:00:50,718 --> 00:00:53,552\nthe network,\n\n20\n00:00:53,554 --> 00:00:57,656\nsomething like that. and cloud kit is a pretty cool way and\n\n21\n00:00:57,658 --> 00:01:00,526\npretty simple way, actually, to do that, especially for\n\n22\n00:01:00,528 --> 00:01:01,493\nsomething like your final project,\n\n23\n00:01:01,495 --> 00:01:07,199\nwhich is a proof of concept vehicle where you\n\n24\n00:01:07,201 --> 00:01:09,868\njust need something simple where you can make it work and\n\n25\n00:01:09,870 --> 00:01:11,103\nyou can always replace it with something much\n\n26\n00:01:11,105 --> 00:01:13,605\nmore powerful networking-wise later. All right.\n\n27\n00:01:13,607 --> 00:01:15,140\nSo I'm gonna talk about those three things today. And\n\n28\n00:01:15,142 --> 00:01:20,579\nthen on Wednesday I will demo all these things. All right?\n\n29\n00:01:20,581 --> 00:01:23,082\nAll right. So let's talk about this in this notification\n\n30\n00:01:23,084 --> 00:01:25,851\nthing. If you remember back to the very first lecture or\n\n31\n00:01:25,853 --> 00:01:28,520\nthe second lecture when I talked about MVC,\n\n32\n00:01:28,522 --> 00:01:31,924\nthere was this little guy here on the model\n\n33\n00:01:31,926 --> 00:01:34,526\nthat looked a little round thing right here.\n\n34\n00:01:34,528 --> 00:01:36,528\nWhich I called a radio station model for\n\n35\n00:01:36,530 --> 00:01:40,499\ncommunication from the model to the controller usually.\n\n36\n00:01:40,501 --> 00:01:43,068\nGuess where it goes and so we're gonna talk about\n\n37\n00:01:43,070 --> 00:01:46,238\nactually how this little radio station works in code,\n\n38\n00:01:46,240 --> 00:01:47,973\nhow we do this thing in code. Okay,\n\n39\n00:01:47,975 --> 00:01:51,376\nit's called NSNotification, all right? It's a radio\n\n40\n00:01:51,378 --> 00:01:54,113\nstation, the radio station by the way is not only good for\n\n41\n00:01:54,115 --> 00:01:55,547\nthe model communicating with the controller,\n\n42\n00:01:55,549 --> 00:01:59,084\nit's also good for the system IOS to communicate with your\n\n43\n00:01:59,086 --> 00:02:03,188\napp. So you'll see a lot of communication from IOS to your\n\n44\n00:02:03,190 --> 00:02:07,292\napp as a whole using these notifications as well. So\n\n45\n00:02:07,294 --> 00:02:09,995\nlet's first of all talk about how you tune into a radio\n\n46\n00:02:09,997 --> 00:02:12,264\nstation. In other words if you want to listen to what's being\n\n47\n00:02:12,266 --> 00:02:14,733\nbroadcast on a radio station, how do you do that? It's\n\n48\n00:02:14,735 --> 00:02:17,970\nactually quite simple, you're gonna get this in instance of\n\n49\n00:02:17,972 --> 00:02:21,273\nthis object right here the NS notification center by saying\n\n50\n00:02:21,275 --> 00:02:23,876\nNSNotificationCenter.defaultC- enter(), okay.\n\n51\n00:02:23,878 --> 00:02:27,379\nAnd this is gonna get to this shared NS notification center,\n\n52\n00:02:27,381 --> 00:02:28,680\nand then you're gonna send that\n\n53\n00:02:28,682 --> 00:02:33,485\nmessage right here addObserverForName, okay. So\n\n54\n00:02:33,487 --> 00:02:38,757\naddObserverForName Takes a string which is the name\n\n55\n00:02:38,759 --> 00:02:43,195\nof the radio station. And it takes a block down here,\n\n56\n00:02:43,197 --> 00:02:46,031\nthe send this notification block which is the block\n\n57\n00:02:46,033 --> 00:02:49,067\nthat's going to be executed when there are broadcasts on\n\n58\n00:02:49,069 --> 00:02:52,004\nthe radio station. So it really couldn't be any\n\n59\n00:02:52,006 --> 00:02:56,642\nsimpler. It returns something that's an NS object protocol.\n\n60\n00:02:56,644 --> 00:02:58,944\nOptional, okay, but basically it's just a cookie.\n\n61\n00:02:58,946 --> 00:03:01,914\nYou can almost think of it as any object. You'll kind of\n\n62\n00:03:01,916 --> 00:03:06,418\nneed the return value of this, so you can stop observing this\n\n63\n00:03:06,420 --> 00:03:08,820\nradio station because you're listening when you,\n\n64\n00:03:08,822 --> 00:03:11,156\nwhen you send this, to this default center there.\n\n65\n00:03:11,158 --> 00:03:12,824\nYou start listening to the radio station, well,\n\n66\n00:03:12,826 --> 00:03:14,059\nyou have to be able to stop listening and\n\n67\n00:03:14,061 --> 00:03:17,229\nto do that, you need this little return value of this\n\n68\n00:03:17,231 --> 00:03:18,163\nadd observer. For\n\n69\n00:03:18,165 --> 00:03:21,767\nname, guy right there. Okay, what are the other two\n\n70\n00:03:21,769 --> 00:03:23,869\narguments here besides the name of the radio station and\n\n71\n00:03:23,871 --> 00:03:28,040\nthe block of code to execute? One is the senders,\n\n72\n00:03:28,042 --> 00:03:30,509\nokay, in other words, the broadcasters that you're\n\n73\n00:03:30,511 --> 00:03:32,911\nYou're interested in. Now you can just specify nil here,\n\n74\n00:03:32,913 --> 00:03:35,714\nthen you'll listen to any radio station with that name.\n\n75\n00:03:35,716 --> 00:03:38,784\nAnybody broadcasting on that radio station you're going to\n\n76\n00:03:38,786 --> 00:03:40,519\nlisten to. But if you put an object here,\n\n77\n00:03:40,521 --> 00:03:43,188\nit would only be if that particular object is\n\n78\n00:03:43,190 --> 00:03:45,924\nbroadcasting on that radio station.\n\n79\n00:03:45,926 --> 00:03:48,560\nOkay? So, it depends on the kind\n\n80\n00:03:48,562 --> 00:03:51,363\nof environment that you're listening here as to whether\n\n81\n00:03:51,365 --> 00:03:52,664\nit makes sense to put something there.\n\n82\n00:03:52,666 --> 00:03:53,799\nAnd I'll show you some examples.\n\n83\n00:03:53,801 --> 00:03:57,135\nIt'll make more sense. Then there's this queue right here.\n\n84\n00:03:57,137 --> 00:03:59,137\nThis queue is gonna be the queue,\n\n85\n00:03:59,139 --> 00:04:03,976\nthat this closure is going to be executed on. Okay? So\n\n86\n00:04:03,978 --> 00:04:07,079\noften times if you're doing UI stuff in here you'll obviously\n\n87\n00:04:07,081 --> 00:04:09,982\nwant to say NSOperationQueue.MainQueue.\n\n88\n00:04:09,984 --> 00:04:13,785\nOkay? You can also pass nil here. You can see the question\n\n89\n00:04:13,787 --> 00:04:16,355\nmark there, so this could be nil. If you pass mail here,\n\n90\n00:04:16,357 --> 00:04:20,058\nthen it will execute this closure on the same queue\n\n91\n00:04:20,060 --> 00:04:23,061\nas the radio station broadcaster,\n\n92\n00:04:23,063 --> 00:04:24,062\nwhich is a little bit odd, okay,\n\n93\n00:04:24,064 --> 00:04:26,231\nbecause sometimes the radio station's broadcasting and\n\n94\n00:04:26,233 --> 00:04:28,767\nyou're not really sure what queue they're on, but\n\n95\n00:04:28,769 --> 00:04:31,336\nthat's what meant, so usually we're going to have NS\n\n96\n00:04:31,338 --> 00:04:34,806\noperation main queue in here when you're listening. Now,\n\n97\n00:04:34,808 --> 00:04:37,843\ninside this closure, you can see there is one argument.\n\n98\n00:04:37,845 --> 00:04:39,544\nThe argument is an NSNotification. So,\n\n99\n00:04:39,546 --> 00:04:43,148\nan NSNotification encapsulates the data that's coming across\n\n100\n00:04:43,150 --> 00:04:46,418\nin a radio station broadcast. And, there's really only one\n\n101\n00:04:46,420 --> 00:04:48,620\ninteresting thing inside, there's a few in here you\n\n102\n00:04:48,622 --> 00:04:51,356\ncan look in the documentation, but the main interesting thing\n\n103\n00:04:51,358 --> 00:04:54,960\nin this notification, is this thing called it's userInfo,\n\n104\n00:04:54,962 --> 00:04:58,330\nnotification.userInfo. That's a dictionary, okay,\n\n105\n00:04:58,332 --> 00:05:02,668\nkeys are NSObjects the values are AnyObject, okay. And\n\n106\n00:05:02,670 --> 00:05:05,137\nin that dictionary is any information that the radio\n\n107\n00:05:05,139 --> 00:05:07,806\nstation broadcaster wants you to have, okay. So they're\n\n108\n00:05:07,808 --> 00:05:10,609\ngonna have to let you know what the keys of this are so\n\n109\n00:05:10,611 --> 00:05:13,645\nyou can look in there and then you can get certain values.\n\n110\n00:05:13,647 --> 00:05:16,181\nSo everybody who broadcasts. On a radio station,\n\n111\n00:05:16,183 --> 00:05:17,983\nit's going to tell you the name of the radio station.\n\n112\n00:05:17,985 --> 00:05:20,819\nThis string right here, addObserverForName(String.\n\n113\n00:05:20,821 --> 00:05:23,789\nAnd then they're going to tell you the keys that you can use\n\n114\n00:05:23,791 --> 00:05:27,225\nto look inside this notification.userinfo. Okay,\n\n115\n00:05:27,227 --> 00:05:29,394\nthose are all things that the radio station broadcaster has\n\n116\n00:05:29,396 --> 00:05:32,564\nto tell you if you want to listen to that broadcast and\n\n117\n00:05:32,566 --> 00:05:36,068\nmake any sense of it, okay. All right, so\n\n118\n00:05:36,070 --> 00:05:40,272\nhere's an example of listening to a radio station. So\n\n119\n00:05:40,274 --> 00:05:43,775\nthere happens to be a radio station that broadcasts\n\n120\n00:05:43,777 --> 00:05:46,712\nwhenever the user goes into their setting and\n\n121\n00:05:46,714 --> 00:05:50,482\nsets their font size. This is, did you see on the right,\n\n122\n00:05:50,484 --> 00:05:52,484\nthere's a screen in the general settings\n\n123\n00:05:52,486 --> 00:05:54,086\napp that's under accessibility I think,\n\n124\n00:05:54,088 --> 00:05:56,655\nfont sizes or something like that. And you can see there's\n\n125\n00:05:56,657 --> 00:05:58,824\nthis slider down here. You can make your fonts bigger or\n\n126\n00:05:58,826 --> 00:06:02,260\nsmaller. Okay, well when you change this a radio station\n\n127\n00:06:02,262 --> 00:06:05,197\nbroadcast goes out to all the apps saying the,\n\n128\n00:06:05,199 --> 00:06:08,734\nwhat's called, content size category did change.\n\n129\n00:06:08,736 --> 00:06:11,036\nSo this is the name of the radio station,\n\n130\n00:06:11,038 --> 00:06:14,573\nUIContentSizeCategoryDidChang- eNotification. Okay,\n\n131\n00:06:14,575 --> 00:06:18,944\nthat's a constant somewhere in IOS. And it is\n\n132\n00:06:18,946 --> 00:06:21,880\na string that just finds the name of this radio station.\n\n133\n00:06:21,882 --> 00:06:24,983\nSo if you wanted to find out when the user changes\n\n134\n00:06:24,985 --> 00:06:29,354\ntheir font size you would just do defaultcenter here,\n\n135\n00:06:29,356 --> 00:06:31,990\naddObserverForName listen to that radio station.\n\n136\n00:06:31,992 --> 00:06:35,260\nThe sender is going to be the UI application when the system\n\n137\n00:06:35,262 --> 00:06:37,929\ntalks to you it usually talks to you from UI application,\n\n138\n00:06:37,931 --> 00:06:41,266\nbut you might put nill right here because if anybody wants\n\n139\n00:06:41,268 --> 00:06:43,969\nto tell you that the content size category did change,\n\n140\n00:06:43,971 --> 00:06:45,837\nyou're probably interested so you might say nill for\n\n141\n00:06:45,839 --> 00:06:48,807\nthe object there. And then main queue you're almost\n\n142\n00:06:48,809 --> 00:06:49,941\ncertainly gonna be listening for\n\n143\n00:06:49,943 --> 00:06:52,778\nbroadcast of this radio station, on your main queue,\n\n144\n00:06:52,780 --> 00:06:55,680\nbecause when the font size changes we are gonna do\n\n145\n00:06:55,682 --> 00:06:57,416\nsome UI thing. You're gonna react to it and\n\n146\n00:06:57,418 --> 00:07:01,586\nof course we know you can only do UI on the main queue. Okay?\n\n147\n00:07:01,588 --> 00:07:04,656\nSo here's my closure, and right here I see I'm getting\n\n148\n00:07:04,658 --> 00:07:08,093\nthe notification user info, inside there is a key, again,\n\n149\n00:07:08,095 --> 00:07:12,297\nthis broadcast that's, you know, in some IOS place there.\n\n150\n00:07:12,299 --> 00:07:15,767\nUI content size category new value key, and it'll tell you\n\n151\n00:07:15,769 --> 00:07:19,738\nthe new value of this size category of the font,\n\n152\n00:07:19,740 --> 00:07:24,943\nokay? It could be for example, UIContentSizeCategorySmall.\n\n153\n00:07:24,945 --> 00:07:27,012\nThat's one of the size categories. And\n\n154\n00:07:27,014 --> 00:07:29,548\nonce you get that new category, then you can react\n\n155\n00:07:29,550 --> 00:07:33,952\nto it, okay. Redraw something, whatever you wanna do.\n\n156\n00:07:33,954 --> 00:07:35,854\nBy the way, if you're using preferred font,\n\n157\n00:07:35,856 --> 00:07:39,391\nremember we switched to using system font in our early apps?\n\n158\n00:07:39,393 --> 00:07:42,294\nWe started using preferred fonts like the body font and\n\n159\n00:07:42,296 --> 00:07:42,360\nYou remember all that? Those fonts are really cool because\n\n160\n00:07:42,362 --> 00:07:45,096\nthe headline font.\n\n161\n00:07:45,098 --> 00:07:48,900\nthey automatically are going to adjust to this size change.\n\n162\n00:07:48,902 --> 00:07:50,802\nSo if you have a UI label somewhere, and\n\n163\n00:07:50,804 --> 00:07:54,406\nyou used a prefered body font, and the person cranks up their\n\n164\n00:07:54,408 --> 00:07:57,709\nsize really big, cuz maybe their eyes are getting old,\n\n165\n00:07:57,711 --> 00:08:00,612\nage is getting up with, catching up with them Then\n\n166\n00:08:00,614 --> 00:08:03,949\nit's automatically going to change those for you.\n\n167\n00:08:03,951 --> 00:08:06,518\nSo that's kind of cool feature. Okay, but\n\n168\n00:08:06,520 --> 00:08:08,820\nsometimes you might have something else that some other\n\n169\n00:08:08,822 --> 00:08:11,122\npart of the UI that depends on the size of font that you have\n\n170\n00:08:11,124 --> 00:08:13,825\nto adjust as well. And maybe I'll show that in a little bit\n\n171\n00:08:13,827 --> 00:08:18,864\nin my demo on Wednesday. Okay, now, what about broadcasting.\n\n172\n00:08:18,866 --> 00:08:21,500\nWhat if you want to be a radio station broadcaster?\n\n173\n00:08:21,502 --> 00:08:24,002\nHow do youd do that? That's very easy too.\n\n174\n00:08:24,004 --> 00:08:26,238\nYou just create one of these NSNotifications,\n\n175\n00:08:26,240 --> 00:08:29,307\nthe same thing that is given to your closure when you're\n\n176\n00:08:29,309 --> 00:08:31,843\na listener. You just create one of these things and\n\n177\n00:08:31,845 --> 00:08:34,513\nthen you're gonna ask the NSNotification default center\n\n178\n00:08:34,515 --> 00:08:38,116\nto post that notification. Okay, and then it's going to\n\n179\n00:08:38,118 --> 00:08:40,585\nbroadcast on that radio station. And the notification\n\n180\n00:08:40,587 --> 00:08:43,455\nof course has to have the name of the radio station. And\n\n181\n00:08:43,457 --> 00:08:44,823\nalso, the object that is sending it.\n\n182\n00:08:44,825 --> 00:08:47,659\nThat's usually gonna be self, right. Your post notification,\n\n183\n00:08:47,661 --> 00:08:49,427\nyou're gonna usually have the self be the center.\n\n184\n00:08:49,429 --> 00:08:51,630\nAnd then here's that user info you get to provide,\n\n185\n00:08:51,632 --> 00:08:55,500\nokay. This is the information that's gonna go to people\n\n186\n00:08:55,502 --> 00:08:57,536\nwho listen to your broadcast. Okay,\n\n187\n00:08:57,538 --> 00:08:58,904\nyou just post this notification and\n\n188\n00:08:58,906 --> 00:09:02,007\nall the listeners will have their closures executed\n\n189\n00:09:02,009 --> 00:09:06,211\nwith this notification object as the argument. Okay,\n\n190\n00:09:06,213 --> 00:09:09,180\npretty simple, all right. Okay, so\n\n191\n00:09:09,182 --> 00:09:12,350\nthat's it for notifications, now I'm gonna move on to, and\n\n192\n00:09:12,352 --> 00:09:14,152\nI'm gonna talk about notification more like in when\n\n193\n00:09:14,154 --> 00:09:15,554\nwe talk about Cloud Kit a little later,\n\n194\n00:09:15,556 --> 00:09:17,589\nthere's notifications involved there, so we'll talk about\n\n195\n00:09:17,591 --> 00:09:20,859\nthis more that and then in the day we'll talk about this too\n\n196\n00:09:20,861 --> 00:09:22,460\nSo now we're gonna do a little different topic here which\n\n197\n00:09:22,462 --> 00:09:26,698\nis the application lifecycle, okay. So this is what happens\n\n198\n00:09:26,700 --> 00:09:29,734\nto your application as it goes through its life, okay.\n\n199\n00:09:29,736 --> 00:09:32,737\nAnd it's really encapsulated in these boxes right here.\n\n200\n00:09:32,739 --> 00:09:37,642\nThis green box right here is the kind of your application\n\n201\n00:09:37,644 --> 00:09:41,212\nwhen it's the user's focus of attention when they're running\n\n202\n00:09:41,214 --> 00:09:44,783\nyour app. The blue box is your app is still around and\n\n203\n00:09:44,785 --> 00:09:47,352\nrunning but it's not the one the user's interacting with\n\n204\n00:09:47,354 --> 00:09:51,690\nright now. And then these other spaces are not that,\n\n205\n00:09:51,692 --> 00:09:54,859\nokay. It's not either of those cases. So let's look at this\n\n206\n00:09:54,861 --> 00:09:58,229\ngreen box this foreground box. Inside that green box there's\n\n207\n00:09:58,231 --> 00:10:00,932\nactually a little state here called inactive.\n\n208\n00:10:00,934 --> 00:10:05,036\nOkay that's when your app is running, it's the foreground,\n\n209\n00:10:05,038 --> 00:10:06,972\nbut it's not receiving any UI events, okay.\n\n210\n00:10:06,974 --> 00:10:10,408\nSo this is kind of like when it's just getting started up,\n\n211\n00:10:10,410 --> 00:10:13,411\nokay. And then it moves from there into this state\n\n212\n00:10:13,413 --> 00:10:17,215\nactive where it's running and receiving events. Okay so\n\n213\n00:10:17,217 --> 00:10:19,751\nthere are just two distinct states there, and you'll see\n\n214\n00:10:19,753 --> 00:10:23,855\nwhy we have those in a moment. And then down here, okay,\n\n215\n00:10:23,857 --> 00:10:26,891\nwhen you're in this background area, at the bottom,\n\n216\n00:10:26,893 --> 00:10:30,428\nyour code might be running, for a short amount of time.\n\n217\n00:10:30,430 --> 00:10:33,565\nYou don't usually run in the background for very long. Now,\n\n218\n00:10:33,567 --> 00:10:37,135\nthere's a misconception that iOS, at least until recently,\n\n219\n00:10:37,137 --> 00:10:38,570\nis not a multitasking system. Because,\n\n220\n00:10:38,572 --> 00:10:41,306\nit seems like you only have one app running at a time.\n\n221\n00:10:41,308 --> 00:10:41,539\nin iOS nine, they introduced the ability to have two apps\n\n222\n00:10:41,541 --> 00:10:44,409\nWell of course,\n\n223\n00:10:44,411 --> 00:10:44,809\nrunning at the same time,\n\n224\n00:10:44,811 --> 00:10:47,979\non the same screen at the same time. In on iPad,\n\n225\n00:10:47,981 --> 00:10:52,884\nside by side. But even before that, apps could run\n\n226\n00:10:52,886 --> 00:10:55,654\nat the same time. It just one would be or two or three would\n\n227\n00:10:55,656 --> 00:10:57,956\nbe in the background and one would be in the foreground.\n\n228\n00:10:57,958 --> 00:11:00,759\nOf course, we know that iOS is just UNIX underneath and\n\n229\n00:11:00,761 --> 00:11:03,461\nUNIX is a complete multitasking operating\n\n230\n00:11:03,463 --> 00:11:03,528\nsystem so\n\n231\n00:11:03,530 --> 00:11:08,466\nThe single tasking nature that it would appear that IOS had,\n\n232\n00:11:08,468 --> 00:11:12,504\nwas more a UI decision for the user. The user could\n\n233\n00:11:12,506 --> 00:11:14,539\nconcentrate on the one thing they're doing at the time and\n\n234\n00:11:14,541 --> 00:11:17,442\nI have a cluttered, trying to figure out what's going on,\n\n235\n00:11:17,444 --> 00:11:18,643\nwhich apps are running all the time.\n\n236\n00:11:18,645 --> 00:11:21,312\nSo it's kind of a simplification of the UI.\n\n237\n00:11:21,314 --> 00:11:24,549\nOkay, but even then, apps were running in the background.\n\n238\n00:11:24,551 --> 00:11:27,152\nAnd we'll talk about why apps run in the back,\n\n239\n00:11:27,154 --> 00:11:30,388\nbackground and when and all that in a moment here,\n\n240\n00:11:30,390 --> 00:11:32,624\nokay. When you go down to the state\n\n241\n00:11:32,626 --> 00:11:36,127\nat the bottom, okay, your code, you are not running.\n\n242\n00:11:36,129 --> 00:11:39,664\nNone of your, no code is being executed in your app at all.\n\n243\n00:11:39,666 --> 00:11:43,001\nYou're in the suspended state. So your process still exists,\n\n244\n00:11:43,003 --> 00:11:44,369\nbut it's not getting any cycles from the CPU.\n\n245\n00:11:44,371 --> 00:11:47,806\nIt's just sitting there. So spend it. At any time in here,\n\n246\n00:11:47,808 --> 00:11:50,742\nyou could be killed, okay, and you could be killed\n\n247\n00:11:50,744 --> 00:11:53,578\nwithout ever having a chance to run again. So\n\n248\n00:11:53,580 --> 00:11:54,279\nwhen you get into this state,\n\n249\n00:11:54,281 --> 00:11:57,949\nyou wanna make sure you're ready to be killed, okay?\n\n250\n00:11:57,951 --> 00:12:00,585\nSo that you don't have any data that's half written or\n\n251\n00:12:00,587 --> 00:12:03,555\nany kind of weird state, you have to be ready to be killed\n\n252\n00:12:03,557 --> 00:12:08,493\ndown in this suspended state. Okay? And then of course,\n\n253\n00:12:08,495 --> 00:12:11,229\ny- you have the not running state at the top, and\n\n254\n00:12:11,231 --> 00:12:12,964\nhow do we get out of this not running state?\n\n255\n00:12:12,966 --> 00:12:13,598\nSo, the not running state, there's,\n\n256\n00:12:13,600 --> 00:12:16,534\nthere's no process that's run in your app, and how do we get\n\n257\n00:12:16,536 --> 00:12:18,803\nout of that? Well, we getting out of it by launching.\n\n258\n00:12:18,805 --> 00:12:21,506\nAnd the launching process takes you from not running\n\n259\n00:12:21,508 --> 00:12:25,376\ninto the foreground Thorough this inactive state and\n\n260\n00:12:25,378 --> 00:12:26,377\nthen into active state.\n\n261\n00:12:26,379 --> 00:12:29,214\nNow it's also possible for you to be launched directly into\n\n262\n00:12:29,216 --> 00:12:32,517\nthe background. Not really sure I am here but that's\n\n263\n00:12:32,519 --> 00:12:37,388\npossible as well. When you switch to another application.\n\n264\n00:12:37,390 --> 00:12:38,623\nSo you are the primary application.\n\n265\n00:12:38,625 --> 00:12:40,592\nThe user goes and switches to some other application.\n\n266\n00:12:40,594 --> 00:12:42,994\nMaybe by double clicking the home button or something like\n\n267\n00:12:42,996 --> 00:12:45,263\nthat. Going back and picking something else.\n\n268\n00:12:45,265 --> 00:12:47,098\nWhat happens here is you go from the active state to\n\n269\n00:12:47,100 --> 00:12:50,568\nthe inactive state and around to the background state. And\n\n270\n00:12:50,570 --> 00:12:53,905\nthen after a little while, you moved to suspended, okay,\n\n271\n00:12:53,907 --> 00:12:56,374\nwhile this other app is running. Okay, so\n\n272\n00:12:56,376 --> 00:12:59,043\nif they go back to you, then you're gonna go back, okay,\n\n273\n00:12:59,045 --> 00:13:04,482\nthe reverse here. Yes. I have mentioned this already.\n\n274\n00:13:04,484 --> 00:13:04,682\nWhen you're killed,\n\n275\n00:13:04,684 --> 00:13:06,217\nwhen you go through Suspended to Not running,\n\n276\n00:13:06,219 --> 00:13:09,387\nno code gets run in your app. So any preparation you have to\n\n277\n00:13:09,389 --> 00:13:11,990\ndo for being killed has to happen before that. Now,\n\n278\n00:13:11,992 --> 00:13:14,692\nat each of these transitions happen, all these arrows,\n\n279\n00:13:14,694 --> 00:13:18,363\nokay, code gets executed in your application. Most notably\n\n280\n00:13:18,365 --> 00:13:21,366\nin your AppDelegate, okay? We know that AppDelegate file,\n\n281\n00:13:21,368 --> 00:13:24,469\na file I always Move out of the way into supporting files\n\n282\n00:13:24,471 --> 00:13:28,339\nplace that record data, and manage up the contexting was.\n\n283\n00:13:28,341 --> 00:13:30,875\nOkay, well, there's a bunch of methods in there since it is\n\n284\n00:13:30,877 --> 00:13:34,279\nthe delegates UIApplication object not much methods\n\n285\n00:13:34,281 --> 00:13:36,481\nin there they're called as we transition through all\n\n286\n00:13:36,483 --> 00:13:38,783\nthese states. So, we'll talk about those. So,\n\n287\n00:13:38,785 --> 00:13:42,453\nwhen you're going from not running to inactive, okay, or\n\n288\n00:13:42,455 --> 00:13:46,291\nthis all time from not running into the background.\n\n289\n00:13:46,293 --> 00:13:49,060\nOkay, you could do this little path here\n\n290\n00:13:49,062 --> 00:13:53,198\nnot running Inactive into the background. You get this\n\n291\n00:13:53,200 --> 00:13:55,066\nmethod right called in your AppDelegate called\n\n292\n00:13:55,068 --> 00:13:58,803\nApplicationDidFinishLaunching- WithOption, okay, and\n\n293\n00:13:58,805 --> 00:14:01,840\nit's exactly what its sound. It's saying okay you have\n\n294\n00:14:01,842 --> 00:14:04,576\nlaunch, you're in the Inactive state, okay.\n\n295\n00:14:04,578 --> 00:14:08,079\nAnd here are some options and these options is a dictionary.\n\n296\n00:14:08,081 --> 00:14:09,380\nOkay and we'll talk about what's in the dictionary in\n\n297\n00:14:09,382 --> 00:14:12,951\na second. You also are gonna get an NSNotification for\n\n298\n00:14:12,953 --> 00:14:15,820\nradio station broadcast on this radio station the\n\n299\n00:14:15,822 --> 00:14:19,057\nUIApplicationDidFinishLaunchi- ngNotification radio station.\n\n300\n00:14:19,059 --> 00:14:22,927\nAnd so if you observe on that you'll get your closer called\n\n301\n00:14:22,929 --> 00:14:26,397\nwhen the app reaches this inactive state right here.\n\n302\n00:14:26,399 --> 00:14:29,334\nOkay. Now, what's this dictionary all about right\n\n303\n00:14:29,336 --> 00:14:32,337\nhere? Okay. So this dictionary is passed to you and\n\n304\n00:14:32,339 --> 00:14:34,939\nit tells you basically why you were launched.\n\n305\n00:14:34,941 --> 00:14:37,308\nNow, you always think of I get launched because someone\n\n306\n00:14:37,310 --> 00:14:40,311\nclicked on my icon. That's true. That's one way to get\n\n307\n00:14:40,313 --> 00:14:42,447\nlaunched but there's a lot other way to get launched. For\n\n308\n00:14:42,449 --> 00:14:45,950\nexample, someone might want you to open URL. You might be\n\n309\n00:14:45,952 --> 00:14:50,421\nan app Like you're the Keynote app, okay, on iOS. And\n\n310\n00:14:50,423 --> 00:14:53,258\nyou know how to open Keynote files. So when someone says,\n\n311\n00:14:53,260 --> 00:14:55,927\nI wanna open this Keynote file, the app is gonna launch\n\n312\n00:14:55,929 --> 00:14:59,264\nKeynote, okay. And so this is going to tell them\n\n313\n00:14:59,266 --> 00:15:03,601\nthat that's why Keynote got launched. You might\n\n314\n00:15:03,603 --> 00:15:06,638\ndo this because you enter a certain place in the world.\n\n315\n00:15:06,640 --> 00:15:06,871\nThere's a way,\n\n316\n00:15:06,873 --> 00:15:09,607\nwith core location which we haven't talked about,\n\n317\n00:15:09,609 --> 00:15:09,741\nto say hey,\n\n318\n00:15:09,743 --> 00:15:13,044\nif this person walks in this little area of the world,\n\n319\n00:15:13,046 --> 00:15:17,348\nthese GPS coordinates, then wake my app up. Launch me,\n\n320\n00:15:17,350 --> 00:15:20,518\nbecause I want to do something when they walk into that area.\n\n321\n00:15:20,520 --> 00:15:23,154\nOkay? So you might get launched because of that. You\n\n322\n00:15:23,156 --> 00:15:25,957\nmight be continuing activities started on another device.\n\n323\n00:15:25,959 --> 00:15:28,026\nHow many people have used Da app\n\n324\n00:15:28,028 --> 00:15:30,828\ncontinuation where you start using an app like Safari or\n\n325\n00:15:30,830 --> 00:15:32,730\nsomething on your iPhone or something and\n\n326\n00:15:32,732 --> 00:15:34,632\nthen you go over to your iPad and you just continue,\n\n327\n00:15:34,634 --> 00:15:36,401\nthere's a little thing in the corner, okay,\n\n328\n00:15:36,403 --> 00:15:38,269\nonly a couple of you are nodding your heads but\n\n329\n00:15:38,271 --> 00:15:40,438\nit's kind of a cool feature but if you go and\n\n330\n00:15:40,440 --> 00:15:43,074\npress that little continuation icon on your IOS and\n\n331\n00:15:43,076 --> 00:15:45,343\nof course it's going to launch you to continue what you were\n\n332\n00:15:45,345 --> 00:15:49,414\ndoing on the device. Also a notification might have\n\n333\n00:15:49,416 --> 00:15:51,382\narrived for you. Like push notification.\n\n334\n00:15:51,384 --> 00:15:54,652\nWho doesn't know what a push notification is?\n\n335\n00:15:54,654 --> 00:15:55,853\nOkay, so, everybody knows what that is.\n\n336\n00:15:55,855 --> 00:15:58,556\nIt's little things that make the badges on your icon,\n\n337\n00:15:58,558 --> 00:16:01,059\njust basically when communication's coming from\n\n338\n00:16:01,061 --> 00:16:03,695\nservers out there in the world, things like that.\n\n339\n00:16:03,697 --> 00:16:07,065\nWell of course that might launch you. Maybe you have\n\n340\n00:16:07,067 --> 00:16:10,368\nsome Bluetooth devi, Bluetooth device that is attached to\n\n341\n00:16:10,370 --> 00:16:13,771\nyour computer and it wants to do something with your app,\n\n342\n00:16:13,773 --> 00:16:14,772\nit might launch your app to do that.\n\n343\n00:16:14,774 --> 00:16:17,408\nSo you can see there's tons of examples and these,\n\n344\n00:16:17,410 --> 00:16:19,777\nthis dictionary is gonna contain the information that\n\n345\n00:16:19,779 --> 00:16:23,915\ntells you For example, the URL it wants to open or that,\n\n346\n00:16:23,917 --> 00:16:26,718\nyou know, that, you entered a certain place in the world or\n\n347\n00:16:26,720 --> 00:16:28,286\nthings like that. So it's gonna give you information\n\n348\n00:16:28,288 --> 00:16:32,724\nabout what happened that caused you to launch, okay.\n\n349\n00:16:33,893 --> 00:16:35,560\nOne thing about this application to finish\n\n350\n00:16:35,562 --> 00:16:37,395\nlaunching with options. It used to be\n\n351\n00:16:37,397 --> 00:16:41,332\nthat you actually built you UI here. Okay your primary UI.\n\n352\n00:16:41,334 --> 00:16:44,268\nLike a split view controller with a navigation controller\n\n353\n00:16:44,270 --> 00:16:46,471\nin the master with this view controller in it. And you\n\n354\n00:16:46,473 --> 00:16:50,942\nwould actually build that in code inside of this. A method,\n\n355\n00:16:50,944 --> 00:16:54,145\nwe no longer do that anymore, we use storyboards. But,\n\n356\n00:16:54,147 --> 00:16:55,913\nwhen you are doing your final project you are going to be\n\n357\n00:16:55,915 --> 00:16:59,417\nout searching on the internet for things and you are going\n\n358\n00:16:59,419 --> 00:17:01,152\nto find something and someone is going to say, Yeah,\n\n359\n00:17:01,154 --> 00:17:03,454\nyou do this by putting code in your application to finish\n\n360\n00:17:03,456 --> 00:17:05,289\nlaunching with options. You create your split view there\n\n361\n00:17:05,291 --> 00:17:08,826\nand you set the delegates. Whoa don't do that That's old.\n\n362\n00:17:08,828 --> 00:17:12,063\nThat's old IOS 7 kind of behavior but\n\n363\n00:17:12,065 --> 00:17:13,598\nyou know sometimes on the internet when you're searching\n\n364\n00:17:13,600 --> 00:17:16,000\nyou can't tell what's new and what's old. The good thing for\n\n365\n00:17:16,002 --> 00:17:19,370\nyou guys is, if you search for Swift stuff, you're likely\n\n366\n00:17:19,372 --> 00:17:21,973\ngonna get new stuff. Swift's only been around since IOS 8 I\n\n367\n00:17:21,975 --> 00:17:27,045\nguess, maybe it was 9 I guess. I was eight,\n\n368\n00:17:27,047 --> 00:17:30,014\nI don't remember, whichever. So, so, it's new.\n\n369\n00:17:30,016 --> 00:17:32,717\nSo you're not likely to see this stuff when you're looking\n\n370\n00:17:32,719 --> 00:17:37,255\nfor Swift-based code. So that's good. Okay. All right,\n\n371\n00:17:37,257 --> 00:17:40,491\nso what about this transition right here? Okay. So you\n\n372\n00:17:40,493 --> 00:17:45,897\nare going out of the inactive of this, Active state into\n\n373\n00:17:45,899 --> 00:17:49,700\ninactive. So you were active, user was interacting with you.\n\n374\n00:17:49,702 --> 00:17:52,703\nAnd now you have been moved into the inactive state.\n\n375\n00:17:52,705 --> 00:17:55,239\nNow why is it important to know this state.\n\n376\n00:17:55,241 --> 00:18:01,245\nThis I like to talk, about as the 'app is paused' state.\n\n377\n00:18:01,247 --> 00:18:04,082\nOkay? So for example, let's imagine a match in breakout.\n\n378\n00:18:04,084 --> 00:18:07,919\nOkay? This would be the you want to\n\n379\n00:18:07,921 --> 00:18:09,120\npause the motion of the ball.\n\n380\n00:18:09,122 --> 00:18:12,757\nRemember it's Linear Velocity and Stop it. Okay,\n\n381\n00:18:12,759 --> 00:18:16,861\nin here. Now, you haven't gone to any of this other state,\n\n382\n00:18:16,863 --> 00:18:19,730\nyou just move from Active to Inactive. Now,\n\n383\n00:18:19,732 --> 00:18:22,800\nwhy might you move from Active to Inactive? Well, you might\n\n384\n00:18:22,802 --> 00:18:25,670\nbe in your way to being thrown in to the background and\n\n385\n00:18:25,672 --> 00:18:28,639\nthen suspend it but maybe just a phone call came in.,\n\n386\n00:18:28,641 --> 00:18:31,242\nOkay,if a phone call comes in you move to\n\n387\n00:18:31,244 --> 00:18:34,846\nthe inactive foreground state. The phone call gets possessed.\n\n388\n00:18:34,848 --> 00:18:37,682\nWhen the person hangs up you go back to active. So,\n\n389\n00:18:37,684 --> 00:18:39,383\nif you had the bouncing ball in Breakout and\n\n390\n00:18:39,385 --> 00:18:41,719\na phone call comes in, you wanna stop the ball.\n\n391\n00:18:41,721 --> 00:18:44,021\nWhen the call's over you wanna continue the ball right?\n\n392\n00:18:44,023 --> 00:18:46,757\nSo this is the pause. Think about it as pause.\n\n393\n00:18:46,759 --> 00:18:50,027\nSo, that's what you're gonna do in will resign active. And\n\n394\n00:18:50,029 --> 00:18:53,464\nagain, there's a, radio station for it as well, okay,\n\n395\n00:18:53,466 --> 00:18:56,033\nas you can find out. The radio station is nice because\n\n396\n00:18:56,035 --> 00:18:59,137\nyou can find out anywhere in your application if you just\n\n397\n00:18:59,139 --> 00:19:00,471\nwent to this resign, okay?\n\n398\n00:19:00,473 --> 00:19:03,241\nYou don't have to implement some method in app delegate,\n\n399\n00:19:03,243 --> 00:19:04,976\nyou can find out anywhere in any view controller,\n\n400\n00:19:04,978 --> 00:19:10,915\njust sign up to listen to this radio station, okay. Now,\n\n401\n00:19:10,917 --> 00:19:13,050\nwhen you come back active again, okay,\n\n402\n00:19:13,052 --> 00:19:16,120\nmaybe the phone call was over or maybe you're launching and\n\n403\n00:19:16,122 --> 00:19:19,457\ngot to here. Okay or maybe you came out of the background.\n\n404\n00:19:19,459 --> 00:19:21,225\nFor whatever reason when you come back here,\n\n405\n00:19:21,227 --> 00:19:21,926\nthat's kind of the unpause.\n\n406\n00:19:21,928 --> 00:19:24,695\nOkay, that's where you're gonna put the ball back and\n\n407\n00:19:24,697 --> 00:19:29,000\nresume it's linear velocity to what it was. Okay? So this is\n\n408\n00:19:29,002 --> 00:19:32,069\nthe pause and unpause capping between these two states right\n\n409\n00:19:32,071 --> 00:19:35,473\nhere. And the great thing is, if you paused the ball and\n\n410\n00:19:35,475 --> 00:19:38,876\nyou went to background, that's fine, it would be paused. And\n\n411\n00:19:38,878 --> 00:19:38,910\nwhen you come back,\n\n412\n00:19:38,912 --> 00:19:41,279\nwhether it's come back from background or whatever reason,\n\n413\n00:19:41,281 --> 00:19:45,149\nyou unpause and move the ball again. That's fine too.\n\n414\n00:19:45,151 --> 00:19:48,986\nAll right? Now what about this state right here. Okay,\n\n415\n00:19:48,988 --> 00:19:51,189\nso here you were in the inactive state and\n\n416\n00:19:51,191 --> 00:19:53,090\nnow you're moved into the background. Okay,\n\n417\n00:19:53,092 --> 00:19:55,826\nthis is an important one right here, because when you move\n\n418\n00:19:55,828 --> 00:19:58,362\ninto the background, you're only gonna get to run for\n\n419\n00:19:58,364 --> 00:20:00,398\na short amount of time, about 30 seconds or so,\n\n420\n00:20:00,400 --> 00:20:02,767\nit's not actually guaranteed how long you get to run,\n\n421\n00:20:02,769 --> 00:20:06,304\nbut practical matter, it's around 30 seconds. and\n\n422\n00:20:06,306 --> 00:20:08,606\nyou'd better, in 30 seconds, you'd better hurry up,\n\n423\n00:20:08,608 --> 00:20:11,075\nand clean up. Because, after this,\n\n424\n00:20:11,077 --> 00:20:13,144\nyou're probably gonna move down to the state suspended,\n\n425\n00:20:13,146 --> 00:20:16,714\nand then you can be killed at any time, okay? So, background\n\n426\n00:20:16,716 --> 00:20:19,550\nis really where you wanna batten down the hatches, okay?\n\n427\n00:20:19,552 --> 00:20:24,956\nClose files, you know, get rid of any stuff you're not using.\n\n428\n00:20:24,958 --> 00:20:28,926\nThings like that. Get your network state into the state\n\n429\n00:20:28,928 --> 00:20:31,162\nyou want things like that because you might be,\n\n430\n00:20:31,164 --> 00:20:33,197\nthis might be a prelude to being killed.\n\n431\n00:20:33,199 --> 00:20:34,098\nMaybe not but it might be so\n\n432\n00:20:34,100 --> 00:20:37,868\nyou really wanna ask that here. Now it's possible to ask\n\n433\n00:20:37,870 --> 00:20:41,339\nthe system for more time more if 30 seconds is not quite\n\n434\n00:20:41,341 --> 00:20:43,174\nenough, you can ask for a little bit more time but\n\n435\n00:20:43,176 --> 00:20:45,109\neventually the system will get tired of you asking for\n\n436\n00:20:45,111 --> 00:20:48,613\nmore time and they'll stop giving you more time. Okay.\n\n437\n00:20:48,615 --> 00:20:53,918\nNow, other applications, run in the background as well.\n\n438\n00:20:54,120 --> 00:20:56,988\nIf not coming into this situation from here.\n\n439\n00:20:56,990 --> 00:20:59,890\nWhereas, user went to a different app or whatever. But\n\n440\n00:20:59,892 --> 00:21:02,026\nyou can actually do things in the background.\n\n441\n00:21:02,028 --> 00:21:05,997\nAnd we'll talk about that in a second too. Okay.\n\n442\n00:21:05,999 --> 00:21:09,033\nNow when you come back okay, so you were in the background\n\n443\n00:21:09,035 --> 00:21:10,868\nokay or even suspended and then you went back\n\n444\n00:21:10,870 --> 00:21:13,070\nto the background and then the user made you active again.\n\n445\n00:21:13,072 --> 00:21:15,873\nOf course you come back up around here and you find out\n\n446\n00:21:15,875 --> 00:21:18,476\nhere that application will enter foreground. You see\n\n447\n00:21:18,478 --> 00:21:20,945\nhow you're coming out of the background into the green box\n\n448\n00:21:20,947 --> 00:21:24,382\nforeground there. Will tell you that you're back alive.\n\n449\n00:21:24,384 --> 00:21:26,150\nAnd now you can un-batten down the hatchets.\n\n450\n00:21:26,152 --> 00:21:29,453\nUndo what you did when you got into the background here.\n\n451\n00:21:29,455 --> 00:21:31,722\nYou can open things back up.\n\n452\n00:21:32,258 --> 00:21:36,627\nAll right, now, what other things can you do in\n\n453\n00:21:36,629 --> 00:21:40,064\nthe AppDelegate besides these lifecycle methods? Tons of\n\n454\n00:21:40,066 --> 00:21:43,734\nthings, okay. So not only can you handle push notifications\n\n455\n00:21:43,736 --> 00:21:46,771\nhere, okay. You also have a local notification, which\n\n456\n00:21:46,773 --> 00:21:50,541\nare notification that you set to go up at a certain time.\n\n457\n00:21:50,543 --> 00:21:54,445\nLike reminders, okay, it's at 10:00pm every day,\n\n458\n00:21:54,447 --> 00:21:57,581\nhave this local notification go up and wake my app up, and\n\n459\n00:21:57,583 --> 00:22:03,354\ngo do something. Well, all that handled through the Also,\n\n460\n00:22:03,356 --> 00:22:05,589\ndata protection, okay.\n\n461\n00:22:05,591 --> 00:22:09,593\nWhen your, when your app or your device is locked,\n\n462\n00:22:09,595 --> 00:22:12,663\nthen a lot of the data, pretty much by default,\n\n463\n00:22:12,665 --> 00:22:15,166\nall of the data on your phone is encrypted. Okay.\n\n464\n00:22:15,168 --> 00:22:18,302\nThat's why a locked phone, no one can get in there to your\n\n465\n00:22:18,304 --> 00:22:20,671\ndata cuz it's encrypted, okay? And so\n\n466\n00:22:20,673 --> 00:22:24,208\nall the locking and unlocking and giving you access of files\n\n467\n00:22:24,210 --> 00:22:26,677\nwhere they're not encrypted when you're unlocked and\n\n468\n00:22:26,679 --> 00:22:27,611\nencrypted when they're locked,\n\n469\n00:22:27,613 --> 00:22:31,982\nthat's all the AppDelegate. The AppDelegate also would get\n\n470\n00:22:31,984 --> 00:22:33,351\ncalled if you were already running and\n\n471\n00:22:33,353 --> 00:22:35,386\nsomeone said open this URL, like your keynote,\n\n472\n00:22:35,388 --> 00:22:38,589\nand someone said open this keynote file. You can also do\n\n473\n00:22:38,591 --> 00:22:41,359\nwhat's called background fetching which is kinda cool.\n\n474\n00:22:41,361 --> 00:22:41,592\nLet's say your some\n\n475\n00:22:41,594 --> 00:22:43,260\nsocial media app or something like that.\n\n476\n00:22:43,262 --> 00:22:47,832\nA news app and you want to kinda through out the day,\n\n477\n00:22:47,834 --> 00:22:49,433\ngo often fetch the latest news.\n\n478\n00:22:49,435 --> 00:22:51,902\nSo when the app runs you got the latest news right there.\n\n479\n00:22:51,904 --> 00:22:54,972\nYou don't have to go fetch on the network at that time. And\n\n480\n00:22:54,974 --> 00:22:56,207\nyou are actually allowed to do that,\n\n481\n00:22:56,209 --> 00:22:59,677\nso this background fetching Let your app launch and\n\n482\n00:22:59,679 --> 00:23:02,713\nrun in the background for the little while again not too\n\n483\n00:23:02,715 --> 00:23:05,783\nlong okay this is another one too many apps stealing cycles\n\n484\n00:23:05,785 --> 00:23:08,753\nfrom the foreground app but it will run in the background and\n\n485\n00:23:08,755 --> 00:23:10,020\nyou can go do some network activity.\n\n486\n00:23:10,022 --> 00:23:10,855\nPull down your data or whatever and\n\n487\n00:23:10,857 --> 00:23:14,525\nthen go back to sleep and the system manages that and\n\n488\n00:23:14,527 --> 00:23:15,659\nyou can go look at the documentation for\n\n489\n00:23:15,661 --> 00:23:19,597\nUI application to find out how you set this up. You have to\n\n490\n00:23:19,599 --> 00:23:22,533\nenable something in the capabilities of your app.\n\n491\n00:23:22,535 --> 00:23:22,900\nYou set this up and\n\n492\n00:23:22,902 --> 00:23:25,369\nyou can say kinda how often you wanna be woken up and\n\n493\n00:23:25,371 --> 00:23:28,873\nall those kinda things. If you abuse this, of course this so\n\n494\n00:23:28,875 --> 00:23:32,243\nwe'll stop waking you up in the background. Other Other\n\n495\n00:23:32,245 --> 00:23:34,245\nreasons that you might wake up in the background.\n\n496\n00:23:34,247 --> 00:23:38,416\nYou might be a VOIP app, right. A voice over IP app and\n\n497\n00:23:38,418 --> 00:23:41,218\nso you're using some other application in the foreground,\n\n498\n00:23:41,220 --> 00:23:43,954\nbut you're talking on over VOIP to someone else.\n\n499\n00:23:43,956 --> 00:23:45,956\nOr you're a music playing app, okay.\n\n500\n00:23:45,958 --> 00:23:47,324\nAnd the person's got their headphones on, they're\n\n501\n00:23:47,326 --> 00:23:49,693\nlistening to your music while they're using some other app.\n\n502\n00:23:49,695 --> 00:23:51,529\nOf course you're of course running in the background in\n\n503\n00:23:51,531 --> 00:23:53,864\nthat case. So there are a lot of cases where you can run in\n\n504\n00:23:53,866 --> 00:23:56,100\nthe background and you can look it all this up in your UI\n\n505\n00:23:56,102 --> 00:23:59,503\napplication. Unfortunately, again from time constraints,\n\n506\n00:23:59,505 --> 00:24:00,538\nI don't have time to go thru and\n\n507\n00:24:00,540 --> 00:24:03,674\nshow you all the Cool thing to know in the background but\n\n508\n00:24:03,676 --> 00:24:04,475\nthese are some of them, and\n\n509\n00:24:04,477 --> 00:24:08,012\nalmost all of this stuff happens with your AppDelegate.\n\n510\n00:24:08,014 --> 00:24:10,448\nOkay the methods in the AppDelegate.\n\n511\n00:24:11,117 --> 00:24:14,518\nAll right, let's talk about UIApplication. The actual\n\n512\n00:24:14,520 --> 00:24:16,754\nobject UIApplication is only one instance,\n\n513\n00:24:16,756 --> 00:24:19,957\nobviously in your app. You get it by calling this method\n\n514\n00:24:19,959 --> 00:24:24,328\nUIApplication.sharedapplica- tion Right there. Okay.\n\n515\n00:24:24,330 --> 00:24:28,666\nAnd it manages all the global behavior in your app. Mostly\n\n516\n00:24:28,668 --> 00:24:31,302\nit delegates things to its delegate, the app delegate,\n\n517\n00:24:31,304 --> 00:24:34,071\nso that's good, that's why we see so much behavior there.\n\n518\n00:24:34,073 --> 00:24:36,841\nBut it does have some useful functionality of it's own.\n\n519\n00:24:36,843 --> 00:24:39,376\nFor example, it has a method called openURL.\n\n520\n00:24:39,378 --> 00:24:41,645\nYou saw this in your smashtag. Right,\n\n521\n00:24:41,647 --> 00:24:44,181\nthis is how you could click on a URL and open it up.\n\n522\n00:24:44,183 --> 00:24:47,618\nYou call this application method openURL okay.\n\n523\n00:24:47,620 --> 00:24:51,121\nYou can register here for scheduling these\n\n524\n00:24:51,123 --> 00:24:53,591\nnotifications. These local notifications, right, those\n\n525\n00:24:53,593 --> 00:24:56,427\nthings I was telling you wake up every day at 10 o'clock and\n\n526\n00:24:56,429 --> 00:24:59,296\nrun my app kind of things. You actually register and\n\n527\n00:24:59,298 --> 00:25:02,800\nschedule them here in UIApplication If\n\n528\n00:25:02,802 --> 00:25:05,202\nyou are doing the background fetching thing I talked about.\n\n529\n00:25:05,204 --> 00:25:08,672\nYou can set the minimum fetch interval. Okay,\n\n530\n00:25:08,674 --> 00:25:09,607\nso how often your background,\n\n531\n00:25:09,609 --> 00:25:12,243\nthings gonna open up in the background in run? Here is\n\n532\n00:25:12,245 --> 00:25:15,713\nhow you ask for more time if you're in the background.\n\n533\n00:25:15,715 --> 00:25:20,251\nBackground task with expiration handler. Okay,\n\n534\n00:25:20,253 --> 00:25:23,153\nthere's a little spinning wheel on the upper left\n\n535\n00:25:23,155 --> 00:25:26,023\ncorner in the status bar of your iOS device.\n\n536\n00:25:26,025 --> 00:25:26,624\nI'm sure you've seen it, right,\n\n537\n00:25:26,626 --> 00:25:29,159\nthat's supposed to represent network activity. You can turn\n\n538\n00:25:29,161 --> 00:25:32,563\nthat on and off with this bool right here in UIApplication.\n\n539\n00:25:32,565 --> 00:25:34,798\nnetworkActivityIndicatorVis- ible equals true and\n\n540\n00:25:34,800 --> 00:25:38,702\nit'll on start spinning. Say false, it'll turn off.\n\n541\n00:25:38,704 --> 00:25:41,539\nOkay, and you generally should do this anytime you're\n\n542\n00:25:41,541 --> 00:25:45,009\ndoing any network activity so that the user knows, app is\n\n543\n00:25:45,011 --> 00:25:49,046\naccessing the network right now. You can also find out\n\n544\n00:25:49,048 --> 00:25:51,582\na lot of things, like remember that content sides category,\n\n545\n00:25:51,584 --> 00:25:54,051\nthe fonts, big fonts on, you can find that out,\n\n546\n00:25:54,053 --> 00:25:55,786\nyou can poll it, of course, you could also listen\n\n547\n00:25:55,788 --> 00:25:57,821\nto the radio station that tells you when it changes, but\n\n548\n00:25:57,823 --> 00:26:00,224\nyou can poll it. You can also find out how much time\n\n549\n00:26:00,226 --> 00:26:03,160\nyou've got remaining until you're gonna be suspended\n\n550\n00:26:03,162 --> 00:26:06,497\nfrom the background state. And you can even find out\n\n551\n00:26:06,499 --> 00:26:07,998\nwhat state you're in. Am I in the foreground?\n\n552\n00:26:08,000 --> 00:26:11,835\nAm I in the background etc. With this guy right there.\n\n553\n00:26:12,305 --> 00:26:15,639\nOkay? Now let's talk about Info.plist.\n\n554\n00:26:15,641 --> 00:26:16,941\nWe've actually seen Info.plist.\n\n555\n00:26:16,943 --> 00:26:21,345\nRemember, that's where we went when we tried to access URLs,\n\n556\n00:26:21,347 --> 00:26:23,948\nand they were HTTP not HTTPS, right? And\n\n557\n00:26:23,950 --> 00:26:27,384\nwe had to go in here and add something to our Info.plist\n\n558\n00:26:27,386 --> 00:26:32,957\nthat allowed us to kind of unsecurely access URLs and\n\n559\n00:26:32,959 --> 00:26:35,593\nin general Info.plist is for things like that.\n\n560\n00:26:35,595 --> 00:26:38,262\nLittle settings that you're gonna set to do things like\n\n561\n00:26:38,264 --> 00:26:41,599\nthat. You can see that there's an, kind of a property list\n\n562\n00:26:41,601 --> 00:26:45,536\neditor right here. Lets you go through and edit values and\n\n563\n00:26:45,538 --> 00:26:48,973\neven you know, if the values are arrays okay, you can\n\n564\n00:26:48,975 --> 00:26:52,409\nedit that in there. You can also right-click on it and\n\n565\n00:26:52,411 --> 00:26:56,246\nchange it to be an XML view, okay? I don't really recommend\n\n566\n00:26:56,248 --> 00:26:58,849\nthis, cuz it's easy to make a syntax error in here, and\n\n567\n00:26:58,851 --> 00:27:00,050\nnow your Info.plist can't be read.\n\n568\n00:27:00,052 --> 00:27:02,720\nSo I'd stick with the other view. But actually, most of\n\n569\n00:27:02,722 --> 00:27:06,924\nthe things in Info.plist you set In the general settings of\n\n570\n00:27:06,926 --> 00:27:09,994\nyour project. Right? All these places where we said\n\n571\n00:27:09,996 --> 00:27:13,931\nthings like, portrait upside down or landscape left.\n\n572\n00:27:13,933 --> 00:27:14,431\nWhich one of those are allowed?\n\n573\n00:27:14,433 --> 00:27:17,301\nThose are info.p list things but we edit them here.\n\n574\n00:27:17,303 --> 00:27:21,805\nIt's just nicer. And most of the common ones we can find in\n\n575\n00:27:22,241 --> 00:27:27,678\nhere. Okay? Now, in addition to all, all the settings there\n\n576\n00:27:27,680 --> 00:27:31,982\nthere's also some capabilities in your app that you have to\n\n577\n00:27:31,984 --> 00:27:35,719\nexplicitly enable if you wanna use them, okay? And you do\n\n578\n00:27:35,721 --> 00:27:38,622\nthis in the Capabilities tab in your Project Setting,\n\n579\n00:27:38,624 --> 00:27:39,690\nit looks like this. Okay.\n\n580\n00:27:39,692 --> 00:27:41,425\nThis list is always always changing. But\n\n581\n00:27:41,427 --> 00:27:43,961\nyou can see a lot of cool features in here like iCloud,\n\n582\n00:27:43,963 --> 00:27:47,031\nwich I'm gonna talk about a little later in this lecture,\n\n583\n00:27:47,033 --> 00:27:47,598\nand the Game Centre,\n\n584\n00:27:47,600 --> 00:27:51,201\nApple Pay, here the background fetching thing,\n\n585\n00:27:51,203 --> 00:27:55,873\nright here, Data Protection down here, Home Kit and\n\n586\n00:27:55,875 --> 00:27:58,909\nHealth Kit down at the bottom. If you wanna use any of these,\n\n587\n00:27:58,911 --> 00:28:01,812\nyou have to turn it on by just going to this capabilities\n\n588\n00:28:01,814 --> 00:28:04,181\ntab in your project settings. And just clicking this\n\n589\n00:28:04,183 --> 00:28:07,184\nfrom off to on. And when you click it to on, there's going\n\n590\n00:28:07,186 --> 00:28:08,986\nto be various settings for that thing. Okay and\n\n591\n00:28:08,988 --> 00:28:12,222\nwe'll see this all in detail when we do Cloud Kit. Okay,\n\n592\n00:28:12,224 --> 00:28:15,092\nyou can also see from this how much stuff I just can't cover\n\n593\n00:28:15,094 --> 00:28:17,094\nin this class. In fact, of this whole list.\n\n594\n00:28:17,096 --> 00:28:19,863\nOnly thing I'm gonna cover is the first one, I cloud.\n\n595\n00:28:19,865 --> 00:28:22,499\nOkay? The rest of the stuff, I just don't have time to get to\n\n596\n00:28:22,501 --> 00:28:25,803\nit all. When you go start looking through the doc and\n\n597\n00:28:25,805 --> 00:28:27,371\nyou start looking at some of the things you might do,\n\n598\n00:28:27,373 --> 00:28:29,940\nyou can know that you have to go here to turn things on.\n\n599\n00:28:29,942 --> 00:28:33,877\nOkay? All right, so\n\n600\n00:28:33,879 --> 00:28:36,580\nthat's pretty much it for your application lifestyle,\n\n601\n00:28:36,582 --> 00:28:40,050\nlife cycle, and kind of overall settings in your app.\n\n602\n00:28:40,052 --> 00:28:44,722\nThe next topic I'm gonna do is alerts and action sheets okay.\n\n603\n00:28:44,724 --> 00:28:46,056\nSo these are the pop up and\n\n604\n00:28:46,058 --> 00:28:49,793\nask the user something UI okay. And they're very,\n\n605\n00:28:49,795 --> 00:28:54,965\nvery similar the API for them is almost identical okay but\n\n606\n00:28:54,967 --> 00:28:56,066\ntheir UI is slightly different so\n\n607\n00:28:56,068 --> 00:28:58,702\nlet's take a look at these alerts and action sheets. So\n\n608\n00:28:58,704 --> 00:29:01,138\nalerts, always pop up in the middle of the screen.\n\n609\n00:29:01,140 --> 00:29:03,474\nThey grey out everything else behind it. Okay.\n\n610\n00:29:03,476 --> 00:29:05,476\nOn this little screen. Both an iPad and iPhone.\n\n611\n00:29:05,478 --> 00:29:10,748\n*swallow* And, it usually asks a question that has\n\n612\n00:29:10,750 --> 00:29:11,582\nusually one or two answers.\n\n613\n00:29:11,584 --> 00:29:15,219\nEither you just click 'okay' or maybe 'okay, cancel' or\n\n614\n00:29:15,221 --> 00:29:19,156\n'yes, no'. Possibly a third answer. But usually it's only\n\n615\n00:29:19,158 --> 00:29:23,494\ntwo. Answers. This thing is very modal,\n\n616\n00:29:23,496 --> 00:29:24,995\nit kind of takes over your whole UI and\n\n617\n00:29:24,997 --> 00:29:26,430\njust puts up this little box, so you know,\n\n618\n00:29:26,432 --> 00:29:29,066\nyou don't wanna use it unless you really can't proceed\n\n619\n00:29:29,068 --> 00:29:33,704\nwithout the user acknowledging this information or whatever.\n\n620\n00:29:33,706 --> 00:29:36,206\nUsually it's used when there are asynchronous problems,\n\n621\n00:29:36,208 --> 00:29:40,878\nsome network connection fails. There's no place in the UI to\n\n622\n00:29:40,880 --> 00:29:43,347\ntell them that, so you kinda have to Take over for\n\n623\n00:29:43,349 --> 00:29:47,017\na moment and say the network connection failed click OK or\n\n624\n00:29:47,019 --> 00:29:51,288\nclick here to retry or whatever. Okay, this alerts\n\n625\n00:29:51,290 --> 00:29:56,293\ncan have text fields in it as well. Okay, and the condition\n\n626\n00:29:56,295 --> 00:29:57,895\njust OK or cancel or whatever you cannot type full.\n\n627\n00:29:57,897 --> 00:30:01,899\nSo you could use it for you know, access tonight. Enter\n\n628\n00:30:01,901 --> 00:30:05,903\npassword Okay, you can use it for things like that. Okay?\n\n629\n00:30:05,905 --> 00:30:10,674\nI wouldn't use it as a general text of obtaining UI, however.\n\n630\n00:30:10,676 --> 00:30:13,677\nOkay? Again, it's only for exceptional circumstances.\n\n631\n00:30:13,679 --> 00:30:16,747\nNow an action sheet is very similar to an alert, but\n\n632\n00:30:16,749 --> 00:30:19,183\nit has more than two choices, usually three or\n\n633\n00:30:19,185 --> 00:30:22,886\nfour choices. Okay? Instead of appearing in the middle,\n\n634\n00:30:22,888 --> 00:30:25,689\nit slides up from the bottom, on an iPhone, or\n\n635\n00:30:25,691 --> 00:30:30,994\nit appears in a popover on an iPad, okay? And you kind of\n\n636\n00:30:30,996 --> 00:30:34,798\nwould think of, action sheet as a branching decision UI.\n\n637\n00:30:34,800 --> 00:30:37,968\nOkay, the user has reached a place in there Point in their\n\n638\n00:30:37,970 --> 00:30:41,004\nuse of the UI where they have to branch and go do a certain\n\n639\n00:30:41,006 --> 00:30:42,673\ntask, and go a different direction, they have two,\n\n640\n00:30:42,675 --> 00:30:46,877\nor three, or four different ways that they can go. Okay?\n\n641\n00:30:46,879 --> 00:30:50,047\nNow you've seen all these UI, these things in your app,\n\n642\n00:30:50,049 --> 00:30:51,515\nso I don't want to go too much into it,\n\n643\n00:30:51,517 --> 00:30:54,418\nbut let's look a little bit about how we\n\n644\n00:30:54,420 --> 00:30:57,621\ndo the code behind it. So Here is what they look like.\n\n645\n00:30:57,623 --> 00:30:59,923\nAn action sheet comes up from the bottom. right.\n\n646\n00:30:59,925 --> 00:31:03,560\nIt's got a tile right here and then also a little commentary\n\n647\n00:31:03,562 --> 00:31:06,997\nin there some explanation. And then it's got the buttons.\n\n648\n00:31:06,999 --> 00:31:11,602\nAnd alert is, comes up in the middle of the screen.\n\n649\n00:31:11,604 --> 00:31:13,670\nIt's, you got one or two buttons usually and\n\n650\n00:31:13,672 --> 00:31:16,974\npossibly. Text, so here for example I've got\n\n651\n00:31:16,976 --> 00:31:21,178\na Login Required to control my Cassini I guess here and\n\n652\n00:31:21,180 --> 00:31:23,881\nyou got to type your guided system password to\n\n653\n00:31:23,883 --> 00:31:25,883\nbe able to get control of Cassini.\n\n654\n00:31:25,885 --> 00:31:28,485\nWhile over in the Action Sheet I'm kind of\n\n655\n00:31:28,487 --> 00:31:31,288\nCassini wants to go somewhere and we're picking a branch in\n\n656\n00:31:31,290 --> 00:31:33,190\ndecision whether we're gonna Orbit Saturn or\n\n657\n00:31:33,192 --> 00:31:36,293\nE=xplore Titan, get a Closeup of the Sun. Or just cancel\n\n658\n00:31:36,295 --> 00:31:40,264\nthat branching decision. Okay? So, how's the code for\n\n659\n00:31:40,266 --> 00:31:45,535\nthis look? Well these things, like action sheet, are just\n\n660\n00:31:45,537 --> 00:31:48,572\nUI view controllers. Okay? They're presented motilly,\n\n661\n00:31:48,574 --> 00:31:50,974\nthey just instead of taking over the whole screen,\n\n662\n00:31:50,976 --> 00:31:52,342\nthey just get drawn like this, or\n\n663\n00:31:52,344 --> 00:31:53,777\nas a little square in the middle.\n\n664\n00:31:53,779 --> 00:31:55,379\nBut they're basically just UI view controllers\n\n665\n00:31:55,381 --> 00:31:57,681\npresented motilly. I haven't really talked about motile\n\n666\n00:31:57,683 --> 00:32:00,484\npresentation. I hope to get that on Wednesday, but\n\n667\n00:32:00,486 --> 00:32:03,520\nmodal just means you can't do anything else in that app\n\n668\n00:32:03,522 --> 00:32:07,391\nuntil you deal with this view controller. K, so these\n\n669\n00:32:07,393 --> 00:32:09,293\nare modal view controllers so you create them but\n\n670\n00:32:09,295 --> 00:32:11,828\nthey are initially initialized to UI alert controller,\n\n671\n00:32:11,830 --> 00:32:14,131\ngonna create you one of these UI view controllers.\n\n672\n00:32:14,133 --> 00:32:16,600\nIt's a sub class of UI view controller. All you need to\n\n673\n00:32:16,602 --> 00:32:19,770\nspecify is this title right here like Redeploy Cassini.\n\n674\n00:32:19,772 --> 00:32:21,972\nAnd the message that goes in here\n\n675\n00:32:21,974 --> 00:32:24,107\nIssue commands to Cassini's guidance system.\n\n676\n00:32:24,109 --> 00:32:26,176\nRight here. And then, the style you want,\n\n677\n00:32:26,178 --> 00:32:29,646\neither action sheet or alert. Okay, so that's it,\n\n678\n00:32:29,648 --> 00:32:32,182\nthat's how you create one of these view controllers.\n\n679\n00:32:32,184 --> 00:32:34,318\nThe next step is we're gonna configure it and\n\n680\n00:32:34,320 --> 00:32:35,919\nthen we're going to present it modally.\n\n681\n00:32:35,921 --> 00:32:38,355\nSo let's do the configuration part.\n\n682\n00:32:38,357 --> 00:32:42,726\nObviously configuring it, we need to add actions to it,\n\n683\n00:32:42,728 --> 00:32:45,295\nokay, these various buttons and we do that by sending\n\n684\n00:32:45,297 --> 00:32:50,033\nthe method addAction, okay, to the alert and the addAction\n\n685\n00:32:50,035 --> 00:32:54,805\ntakes one argument which is a UIAlertAction, okay.\n\n686\n00:32:54,807 --> 00:32:57,341\nThey UIAlertAction has the following\n\n687\n00:32:57,343 --> 00:33:00,110\ninitializer arguments The title that's gonna be\n\n688\n00:33:00,112 --> 00:33:02,713\nthe title on the button okay like Orbit Saturn or\n\n689\n00:33:02,715 --> 00:33:05,449\nExplore Titan whatever. The style we'll talk about what\n\n690\n00:33:05,451 --> 00:33:08,118\nthat style is in a second and then a handler and\n\n691\n00:33:08,120 --> 00:33:11,054\nthis is just a closure that's gonna get executed when\n\n692\n00:33:11,056 --> 00:33:15,392\nthis button gets pressed. Got it? So could be simpler. Okay\n\n693\n00:33:15,394 --> 00:33:18,662\nthat's all there is. So let's look at some examples of this.\n\n694\n00:33:18,664 --> 00:33:19,997\nHere's orbit Saturn right here.\n\n695\n00:33:19,999 --> 00:33:23,433\nThe title is Orbit Saturn, the style is the default style,\n\n696\n00:33:23,435 --> 00:33:26,370\norbit Saturn explore Titan or default style buttons. We'll\n\n697\n00:33:26,372 --> 00:33:29,373\ntalk about the other styles in a second. And in the closure,\n\n698\n00:33:29,375 --> 00:33:32,209\nobviously we're going to go into orbit around Saturn.\n\n699\n00:33:32,211 --> 00:33:33,010\nThat's what we're going to do and\n\n700\n00:33:33,012 --> 00:33:36,446\nwe'll do whatever code is necessary to do that there.\n\n701\n00:33:36,448 --> 00:33:38,048\nOkay, so here is Explore TItan,\n\n702\n00:33:38,050 --> 00:33:42,686\nalmost exactly the same. Okay. Just that the, closure here is\n\n703\n00:33:42,688 --> 00:33:45,789\na little different. Notice this closure says, okay,\n\n704\n00:33:45,791 --> 00:33:48,759\nif I'm going to Explorer TItan that's not part of Cassini's\n\n705\n00:33:48,761 --> 00:33:50,427\nmission, then, so I'm going to log,\n\n706\n00:33:50,429 --> 00:33:53,230\nmake the person log in. Okay you can send him to Saturn,\n\n707\n00:33:53,232 --> 00:33:56,299\nsend Cassini to Saturn evidently without a password.\n\n708\n00:33:56,301 --> 00:33:58,668\nBut you need to enter a password for Titan.\n\n709\n00:33:58,670 --> 00:34:01,705\nSo just has a little different action there, that's all.\n\n710\n00:34:01,707 --> 00:34:06,243\nOkay and these are both normal default style buttons.\n\n711\n00:34:06,245 --> 00:34:09,713\nNow let's take a look at closing, closer, go closeup to\n\n712\n00:34:09,715 --> 00:34:12,482\nthe sun here, okay. Closeup to the sun's a little different.\n\n713\n00:34:12,484 --> 00:34:17,821\nIts style is not default, it's Destructive. So if you have a,\n\n714\n00:34:17,823 --> 00:34:20,924\naction sheet button that is of style of destructive,\n\n715\n00:34:20,926 --> 00:34:24,227\nit's gonna appear red, okay. Now you should always\n\n716\n00:34:24,229 --> 00:34:27,064\npick destructive if the thing the users gonna do with this\n\n717\n00:34:27,066 --> 00:34:30,167\nbutton is going to do something permanent like\n\n718\n00:34:30,169 --> 00:34:30,500\ndelete something,\n\n719\n00:34:30,502 --> 00:34:33,303\ndelete an entry from a database that can't be undone,\n\n720\n00:34:33,305 --> 00:34:36,606\nor something like that. Okay so that is a destructive here.\n\n721\n00:34:36,608 --> 00:34:39,743\nA close up of the sun is probably destroy Cassini so\n\n722\n00:34:39,745 --> 00:34:41,978\nwe made that destructive, alright but\n\n723\n00:34:41,980 --> 00:34:46,583\notherwise it is still going to perform this action. Okay,\n\n724\n00:34:46,585 --> 00:34:50,020\nand what about cancel so cancel you notice it looks\n\n725\n00:34:50,022 --> 00:34:52,756\na little different it is kind of separated. You see that?\n\n726\n00:34:52,758 --> 00:34:57,360\nOtherwise it looks the same. Maybe the font might be bold?\n\n727\n00:34:57,362 --> 00:35:01,331\nHard to tell there, I think so. But otherwise, it's just\n\n728\n00:35:01,333 --> 00:35:03,934\na normal button, okay? But it's of style cancel.\n\n729\n00:35:03,936 --> 00:35:06,369\nWhen we get to iPad, you're gonna see why it's very\n\n730\n00:35:06,371 --> 00:35:09,706\nimportant that we make our Cancel button be style. Cancel\n\n731\n00:35:09,708 --> 00:35:14,478\nbe a different style than the other thing. Okay. So you add\n\n732\n00:35:14,480 --> 00:35:18,215\nall your actions there to do all the things you want to do.\n\n733\n00:35:18,217 --> 00:35:21,351\nAnd then you simply call this view controller method,\n\n734\n00:35:21,353 --> 00:35:23,854\npresent view controller. Present view controller is\n\n735\n00:35:23,856 --> 00:35:27,757\nthe Normal modal presentation method in view controller.\n\n736\n00:35:27,759 --> 00:35:30,594\nWhen I get talk, give you the lecture on mobile view\n\n737\n00:35:30,596 --> 00:35:32,529\ncontrollers, this is the method I'm gonna talk about.\n\n738\n00:35:32,531 --> 00:35:35,198\nYou call this method, it takes a view controller, that's what\n\n739\n00:35:35,200 --> 00:35:38,335\nan alert is, right? Alert is alert controller which is\n\n740\n00:35:38,337 --> 00:35:39,202\nsubclass UIController.\n\n741\n00:35:39,204 --> 00:35:42,639\nTakes one of these and it presents is modally. Okay,\n\n742\n00:35:42,641 --> 00:35:46,276\nthis is whether it's going to animate the presentation. And\n\n743\n00:35:46,278 --> 00:35:48,044\nthis is just a completion handler, they call it,\n\n744\n00:35:48,046 --> 00:35:51,381\nit gets called when it has finished presenting it.\n\n745\n00:35:51,383 --> 00:35:54,284\nNow when it goes away but when it finishes presenting so it's\n\n746\n00:35:54,286 --> 00:35:57,154\non screen. Okay, we almost never use that, by the way.\n\n747\n00:35:57,156 --> 00:36:00,223\nAll right, so the view controller, you do that, okay.\n\n748\n00:36:00,225 --> 00:36:03,426\nIt puts the thing up, now when these buttons get pressed,\n\n749\n00:36:03,428 --> 00:36:05,262\ntheir closures get called. Okay,\n\n750\n00:36:05,264 --> 00:36:09,466\nwhen cancel gets pressed, it goes away, it dismisses.\n\n751\n00:36:10,102 --> 00:36:13,637\nThat's it, that's how you use the Action sheet. Alright,\n\n752\n00:36:13,639 --> 00:36:18,608\nnow, let's talk a little bit about iPad, okay. Because,\n\n753\n00:36:18,610 --> 00:36:22,679\nan iPad, this thing would look ridiculous if it came up from\n\n754\n00:36:22,681 --> 00:36:25,115\nthe bottom. Either it would just be a tiny thing here, or\n\n755\n00:36:25,117 --> 00:36:28,151\nif it was as wide as the whole screen It will be gigantic,\n\n756\n00:36:28,153 --> 00:36:32,556\nokay? So we don't have these things come up from the bottom\n\n757\n00:36:32,558 --> 00:36:37,093\non an iPad, instead we have them come up as pop-overs,\n\n758\n00:36:37,095 --> 00:36:40,197\nokay. See how this is the same thing, but it's over pop-over.\n\n759\n00:36:40,199 --> 00:36:43,733\nNotice, no cancel button, okay? Why do we\n\n760\n00:36:43,735 --> 00:36:45,302\nhave no cancel button on iPad?\n\n761\n00:36:45,304 --> 00:36:48,572\nBecause when a pop-over comes up, you click anywhere else,\n\n762\n00:36:48,574 --> 00:36:53,176\nit dismisses it. That's just like hitting cancel, okay.\n\n763\n00:36:53,178 --> 00:36:58,181\nIn fact your cancel closure will get there, okay. So what\n\n764\n00:36:58,183 --> 00:37:03,353\ndo we need to do to make this appear in a pop over, on iPad,\n\n765\n00:37:03,355 --> 00:37:05,522\nokay. Well we do need to do a little bit different code.\n\n766\n00:37:05,524 --> 00:37:08,024\nSo here's our code from the iPhone. Okay.\n\n767\n00:37:08,026 --> 00:37:11,628\nFirst we're gonna add a little thing in here, which is,\n\n768\n00:37:11,630 --> 00:37:12,162\nwe're gonna set the,\n\n769\n00:37:12,164 --> 00:37:16,700\na View Controller's modal Presentation Style to Popover.\n\n770\n00:37:16,702 --> 00:37:18,368\nOkay, that says present this modally,\n\n771\n00:37:18,370 --> 00:37:22,639\nbut in a Popover style, instead of up from the bottom\n\n772\n00:37:22,641 --> 00:37:27,177\nthere. Okay? Then we just need to get the popover\n\n773\n00:37:27,179 --> 00:37:30,447\nPresentation Controller, which is just It's a class.\n\n774\n00:37:30,449 --> 00:37:31,681\nWe're not gonna talk too much about it,\n\n775\n00:37:31,683 --> 00:37:34,718\nbut it's the thing that controls presentation.\n\n776\n00:37:34,720 --> 00:37:37,554\nOkay? All view controllers, when they're presented,\n\n777\n00:37:37,556 --> 00:37:39,856\nhave a presentation controller that presents them.\n\n778\n00:37:39,858 --> 00:37:42,559\nWell, pop-over ones have one called pop-over presentation\n\n779\n00:37:42,561 --> 00:37:45,295\ncontroller. You're just gonna get this thing if you look for\n\n780\n00:37:45,297 --> 00:37:47,364\nthe UI for a pop-over presentation controller,\n\n781\n00:37:47,366 --> 00:37:50,767\nyou'll see that it has. An argument bar button item,\n\n782\n00:37:50,769 --> 00:37:52,902\nit also has another argument wrecked.\n\n783\n00:37:52,904 --> 00:37:56,706\nOkay, and if you set the bar button item this just tells\n\n784\n00:37:56,708 --> 00:38:02,112\nthe system where this pop over pops up from. So\n\n785\n00:38:02,114 --> 00:38:05,115\nhere this redeploy bar button item is this little bar button\n\n786\n00:38:05,117 --> 00:38:07,651\nitem in the upper right. And so we're just telling\n\n787\n00:38:07,653 --> 00:38:09,786\nthe presentation controller that's gonna pop over,\n\n788\n00:38:09,788 --> 00:38:12,455\npop this thing over, that this is the button that it\n\n789\n00:38:12,457 --> 00:38:15,759\npops over from. And that's how it knows to put it up near it,\n\n790\n00:38:15,761 --> 00:38:17,460\nand to put that little triangle up there,\n\n791\n00:38:17,462 --> 00:38:20,196\nyou see the triangle pointing to, to redeploy. We could of\n\n792\n00:38:20,198 --> 00:38:24,868\nsaid PPC question mark dot wrecked equals whatever.\n\n793\n00:38:24,870 --> 00:38:25,802\nAnd view equals whatever and\n\n794\n00:38:25,804 --> 00:38:28,204\nthen it could pop over from any arbitrary rectangle,\n\n795\n00:38:28,206 --> 00:38:31,875\nanywhere in a view, okay. So you can do that as well.\n\n796\n00:38:31,877 --> 00:38:33,143\nSo that's all we're doing here.\n\n797\n00:38:33,145 --> 00:38:36,880\nAll we've added to this whole thing for pop over's just\n\n798\n00:38:36,882 --> 00:38:38,548\nmade our presentation saw a pop over and\n\n799\n00:38:38,550 --> 00:38:42,252\ntold the control, the pop over presentation controller, where\n\n800\n00:38:42,254 --> 00:38:45,322\nwe want it to pop over from. That's all we've done. Okay,\n\n801\n00:38:45,324 --> 00:38:49,959\nnow cool thing about this is this will work on iPhone 2.\n\n802\n00:38:49,961 --> 00:38:53,830\nSo you can put this code in here. It will do this but\n\n803\n00:38:53,832 --> 00:38:55,799\niPhone will continue to do this. And\n\n804\n00:38:55,801 --> 00:38:59,636\nwhy is that? That because of this adaptive presentation\n\n805\n00:38:59,638 --> 00:39:01,571\nstyle mechanism we talk about early in the core.\n\n806\n00:39:01,573 --> 00:39:04,341\nYou might have forgot it by now. But it's the mechanism\n\n807\n00:39:04,343 --> 00:39:06,943\nthat says if I try to put something up as a pop-over\n\n808\n00:39:06,945 --> 00:39:10,280\non an iPhone, it says op, can't, we don't do pop-overs\n\n809\n00:39:10,282 --> 00:39:12,916\non an iPhone so we're gonna present this thing modally.\n\n810\n00:39:12,918 --> 00:39:15,652\nSo it presents it modally and this is what an action sheet\n\n811\n00:39:15,654 --> 00:39:18,288\nlooks like, one presented modally, okay, versus\n\n812\n00:39:18,290 --> 00:39:22,792\npop-over style So it's back to presenting the same way. Now,\n\n813\n00:39:22,794 --> 00:39:24,494\nof course, it doesn't even look at\n\n814\n00:39:24,496 --> 00:39:26,429\nthis pop over presentation controller because\n\n815\n00:39:26,431 --> 00:39:29,432\nit didn't end up presenting it with the pop over style.\n\n816\n00:39:29,434 --> 00:39:31,901\nIt adapted and presented it with a normal modal style.\n\n817\n00:39:31,903 --> 00:39:35,038\nSo this is great. You can write this one code and\n\n818\n00:39:35,040 --> 00:39:37,841\nit'll work on both devices. Okay.\n\n819\n00:39:37,843 --> 00:39:42,412\nAll right, what about alerts? Okay,\n\n820\n00:39:42,414 --> 00:39:45,181\nso alerts are almost exactly the same as Action Cheat. You\n\n821\n00:39:45,183 --> 00:39:49,152\njust say the style is Alert here instead of Action Cheat.\n\n822\n00:39:49,154 --> 00:39:53,590\nYou still do all the same thing with Add Action, okay,\n\n823\n00:39:53,592 --> 00:39:56,659\nyour Cancel Button and Add Action for\n\n824\n00:39:56,661 --> 00:39:57,861\nthe login button. Okay?\n\n825\n00:39:57,863 --> 00:40:00,530\nSo just like same thing we did with the cl, closures and\n\n826\n00:40:00,532 --> 00:40:03,166\nall that stuff right here. One thing that's different about\n\n827\n00:40:03,168 --> 00:40:05,802\nthe alert, of course, you've got this text field. So how do\n\n828\n00:40:05,804 --> 00:40:08,371\nyou deal with the fact there's text fields in an alert but\n\n829\n00:40:08,373 --> 00:40:11,174\nnot an action sheet? And the answer is\n\n830\n00:40:11,176 --> 00:40:15,011\nAlertController has a method addTextFieldWithConfiguration-\n\n831\n00:40:15,013 --> 00:40:18,047\nHandler. This only does something on alerts,\n\n832\n00:40:18,049 --> 00:40:19,916\nit doesn't do anything if it's an action sheet. And\n\n833\n00:40:19,918 --> 00:40:23,787\nthis closure will be called with the text field that\n\n834\n00:40:23,789 --> 00:40:27,457\nyou're adding, and allow you to configure it in here.\n\n835\n00:40:27,459 --> 00:40:28,825\nSo that's all this little closure does,\n\n836\n00:40:28,827 --> 00:40:31,027\nis just configuring the text field. So for example,\n\n837\n00:40:31,029 --> 00:40:34,097\nI want guidance system password as my placeholder\n\n838\n00:40:34,099 --> 00:40:36,766\ntext in this text field, so I've just set textfield's\n\n839\n00:40:36,768 --> 00:40:40,804\nplaceholder to be Guidance System Password there, okay.\n\n840\n00:40:40,806 --> 00:40:43,940\nSo this adds a text field to the alert, and\n\n841\n00:40:43,942 --> 00:40:46,075\nthis closure just lets you configure it.\n\n842\n00:40:46,077 --> 00:40:49,345\nNow, what happens when someone types in here? How do you get\n\n843\n00:40:49,347 --> 00:40:53,283\nthe text out of there? Well in the action, like for\n\n844\n00:40:53,285 --> 00:40:56,352\ncancel, we went away, we, we don't even look at the text.\n\n845\n00:40:56,354 --> 00:40:58,955\nBut for log in, I wanna look at this password.\n\n846\n00:40:58,957 --> 00:41:00,523\nSo in the action closure here for\n\n847\n00:41:00,525 --> 00:41:03,092\nlogin, you see that right there, the action closure?\n\n848\n00:41:03,094 --> 00:41:09,232\nI'm going to say, if I can let tf = self.alert.textFields?,\n\n849\n00:41:09,234 --> 00:41:12,435\nis option because you don't always have text field .first.\n\n850\n00:41:12,437 --> 00:41:15,004\nOkay, I only have one text field so I want the first one.\n\n851\n00:41:15,006 --> 00:41:17,807\nThen, I've got the text field and I could, for example,\n\n852\n00:41:17,809 --> 00:41:21,044\nlog in with the password tf.text. Okay, so\n\n853\n00:41:21,046 --> 00:41:24,380\nthe answer is I use this text field's bar which is an array\n\n854\n00:41:24,382 --> 00:41:29,018\nof all the text fields that are in this alert. Okay,\n\n855\n00:41:29,020 --> 00:41:32,655\nso that's it, that's it for action alert.\n\n856\n00:41:32,657 --> 00:41:32,922\nPretty easy to use,\n\n857\n00:41:32,924 --> 00:41:35,425\nyou're almost certain to use them in your final project.\n\n858\n00:41:35,427 --> 00:41:38,394\nThat's why I'm covering them early in the final project\n\n859\n00:41:38,396 --> 00:41:43,233\nperiod here. So hopefully that gives you all the things,\n\n860\n00:41:43,235 --> 00:41:48,104\neverything you need to know to do that. All right, and\n\n861\n00:41:48,106 --> 00:41:51,975\nof course, we present this thing exact same way,\n\n862\n00:41:51,977 --> 00:41:53,209\npresentViewController, okay.\n\n863\n00:41:53,211 --> 00:41:55,778\nIt's just modally presented, happens to draw in this way,\n\n864\n00:41:55,780 --> 00:41:58,648\nbut it's still just modally presented, so we use the same\n\n865\n00:41:58,650 --> 00:42:02,752\npresentViewController there, okay. And\n\n866\n00:42:02,754 --> 00:42:08,124\nit looks the same both on iPad and iPhone. All right, so\n\n867\n00:42:08,126 --> 00:42:10,593\nCloud Kit. So I'm covering Cloud Kit,\n\n868\n00:42:10,595 --> 00:42:12,128\nagain I don't usually cover Cloud Kit. But\n\n869\n00:42:12,130 --> 00:42:14,330\nI'm covering it this quarter because I think it's gonna be\n\n870\n00:42:14,332 --> 00:42:17,767\nsomething really cool and powerful for you to use for\n\n871\n00:42:17,769 --> 00:42:21,271\nyour final projects, okay. So what is Cloud Kit?\n\n872\n00:42:21,273 --> 00:42:24,340\nCloud Kit is a database in the cloud, okay.\n\n873\n00:42:24,342 --> 00:42:28,545\nIt's a feature of iCloud and it's very simple to use, okay.\n\n874\n00:42:28,547 --> 00:42:31,614\nAnd it has very basic database operations,\n\n875\n00:42:31,616 --> 00:42:34,751\nokay. It's over the network, so everything that you're\n\n876\n00:42:34,753 --> 00:42:36,719\ndoing is happening real time on the network, so\n\n877\n00:42:36,721 --> 00:42:40,189\nit's all asynchronous, of course. Because the network\n\n878\n00:42:40,191 --> 00:42:42,258\ncould be slow or even not available, okay.\n\n879\n00:42:42,260 --> 00:42:44,794\nThat requires you to do some thoughtful programing,\n\n880\n00:42:44,796 --> 00:42:47,363\nas you have learned with everything is asynchronous,\n\n881\n00:42:47,365 --> 00:42:49,766\nyou kinda have to like, think about what it means for\n\n882\n00:42:49,768 --> 00:42:52,869\nthese methods to, not call you back until much later, okay.\n\n883\n00:42:52,871 --> 00:42:56,272\nSo, otherwise, it's really nice simple, database\n\n884\n00:42:56,274 --> 00:42:59,075\nmechanism to use. Here are the important concepts,\n\n885\n00:42:59,077 --> 00:43:02,745\nokay, that you need to know. One is record type.\n\n886\n00:43:02,747 --> 00:43:05,448\nRecord type is like an entity in core data.\n\n887\n00:43:05,450 --> 00:43:07,517\nWe're gonna do a lot of parallels to core data,\n\n888\n00:43:07,519 --> 00:43:11,387\ncuz you know core data so well so know that terminology, so\n\n889\n00:43:11,389 --> 00:43:14,023\nrecord type is kind of like entity.\n\n890\n00:43:14,025 --> 00:43:17,994\nFields are like attributes. Okay, so fields\n\n891\n00:43:17,996 --> 00:43:21,497\nare the data that's stored in a record, type record.\n\n892\n00:43:21,499 --> 00:43:26,603\nA record is an instance of a record type. So I've got,\n\n893\n00:43:26,605 --> 00:43:31,207\njust like, it's like, sort of like NSManageObject in,\n\n894\n00:43:31,209 --> 00:43:34,377\ncore data. But of course it's so much more lightweight,\n\n895\n00:43:34,379 --> 00:43:36,179\nthere isn't any of that infrastructure.\n\n896\n00:43:36,181 --> 00:43:36,579\nBut it's kind of like that, so\n\n897\n00:43:36,581 --> 00:43:40,283\nit's an instance of a certain record. A reference is kinda\n\n898\n00:43:40,285 --> 00:43:45,588\nlike a relationship to another entity or another record type\n\n899\n00:43:45,590 --> 00:43:48,725\nthere, okay reference. A database is a place where you\n\n900\n00:43:48,727 --> 00:43:53,529\nstore your records. A zone is a sub-area of a database.\n\n901\n00:43:53,531 --> 00:43:54,864\nI'm not gonna talk about zones, but\n\n902\n00:43:54,866 --> 00:43:58,067\nif you divide your database up into zones you can do cool\n\n903\n00:43:58,069 --> 00:43:59,602\nthings like, do efficient queries,\n\n904\n00:43:59,604 --> 00:44:02,171\nwhere you're only querying over a subset of your data,\n\n905\n00:44:02,173 --> 00:44:05,141\nlike this in-sum zone. Okay, I'm not gonna talk about that,\n\n906\n00:44:05,143 --> 00:44:06,309\nbut that's what a zone is all about,\n\n907\n00:44:06,311 --> 00:44:08,277\nit's a subarea of a database for searching and\n\n908\n00:44:08,279 --> 00:44:12,582\nstuff. A container is a collection of databases, we'll\n\n909\n00:44:12,584 --> 00:44:17,420\ntalk about that. A query, is a NSPredicate based search.\n\n910\n00:44:17,422 --> 00:44:20,123\nOf course, NSPredicates can be quite a bit simpler,\n\n911\n00:44:20,125 --> 00:44:21,424\nbecause it's a simpler database,\n\n912\n00:44:21,426 --> 00:44:24,627\nbut, it's still, similar to core data. You're gonna use,\n\n913\n00:44:24,629 --> 00:44:27,130\nactually use the class and its predicate to make '.\n\n914\n00:44:27,132 --> 00:44:31,734\nAnd then a subscription is a standing query, okay.\n\n915\n00:44:31,736 --> 00:44:34,837\nIt's, basically an NSPredicate, you can upload to\n\n916\n00:44:34,839 --> 00:44:37,674\nthe database, and any time it changes it will send you\n\n917\n00:44:37,676 --> 00:44:41,844\na push notification, which is fantastic. This is the coolest\n\n918\n00:44:41,846 --> 00:44:45,014\nfeature of all in Cloud Kit, is that it will send you push\n\n919\n00:44:45,016 --> 00:44:46,949\nnotifications when the database changes, okay.\n\n920\n00:44:46,951 --> 00:44:49,786\nAnd then all you need to do is just, give it a standing\n\n921\n00:44:49,788 --> 00:44:52,855\nquery, called a subscription, and it'll do that, okay.\n\n922\n00:44:52,857 --> 00:44:55,858\nAll right, so let's talk about how all this works,\n\n923\n00:44:55,860 --> 00:44:59,562\nhow do we make this Cloud Kit thing happen. First thing you\n\n924\n00:44:59,564 --> 00:45:02,298\nhave to understand about Cloud Kit is a very important thing\n\n925\n00:45:02,300 --> 00:45:05,902\nhere called the Cloud Kit Dashboard. This is a website,\n\n926\n00:45:05,904 --> 00:45:09,672\nokay. You get to it by going to your project, okay,\n\n927\n00:45:09,674 --> 00:45:11,541\nclick on your project. Actually,\n\n928\n00:45:11,543 --> 00:45:13,476\nI'll show in a second how you can get to this. But\n\n929\n00:45:13,478 --> 00:45:14,844\nyou can click somewhere in your project, and\n\n930\n00:45:14,846 --> 00:45:16,379\nit's gonna take you to this website.\n\n931\n00:45:16,381 --> 00:45:18,848\nThis is gonna have all your record types,\n\n932\n00:45:18,850 --> 00:45:19,882\nall your entities, and\n\n933\n00:45:19,884 --> 00:45:22,118\nall of their fields, all their attributes.\n\n934\n00:45:22,120 --> 00:45:25,722\nSo here's an entity called QandA, it's a question and\n\n935\n00:45:25,724 --> 00:45:27,824\nanswer thing. Here's, it's got answers,\n\n936\n00:45:27,826 --> 00:45:30,526\nwhich is a list of strings, an array of strings,\n\n937\n00:45:30,528 --> 00:45:33,463\nand it's got a question, which is a single string. And\n\n938\n00:45:33,465 --> 00:45:36,766\nthese are all indexed, both for querying and searching and\n\n939\n00:45:36,768 --> 00:45:39,769\neven sorting, okay. Here's another one,\n\n940\n00:45:39,771 --> 00:45:42,538\nresponse, it's got some things. Over here, okay,\n\n941\n00:45:42,540 --> 00:45:46,209\nyou can actually go to default zone right here, you'll\n\n942\n00:45:46,211 --> 00:45:50,213\nbe able to actually see the data stored in these records,\n\n943\n00:45:50,215 --> 00:45:53,883\nwhich is kinda cool. And then it's got some other\n\n944\n00:45:53,885 --> 00:45:57,153\nthings here like the subscriptions that you have\n\n945\n00:45:57,155 --> 00:45:58,921\noutstanding out there.\n\n946\n00:45:58,923 --> 00:46:01,324\nMaybe any users that are using the database etc.\n\n947\n00:46:01,326 --> 00:46:03,960\nSo this is kind of your place where you're gonna go to find\n\n948\n00:46:03,962 --> 00:46:06,729\nout everything that's going on in your database in real time,\n\n949\n00:46:06,731 --> 00:46:11,934\n'kay. The dashboard also has interesting\n\n950\n00:46:11,936 --> 00:46:14,837\nmetadata indexes, and I'm putting a slide on this,\n\n951\n00:46:14,839 --> 00:46:18,274\ncuz this is easy to forget. Okay, because, of course,\n\n952\n00:46:18,276 --> 00:46:21,210\nthe QandA thing has answers and question fields, but\n\n953\n00:46:21,212 --> 00:46:24,380\nit also has these fields like the record ID which is\n\n954\n00:46:24,382 --> 00:46:28,785\na unique ID for this QandA record. Also, created by,\n\n955\n00:46:28,787 --> 00:46:32,421\nthat's the user who created it, that's very interesting.\n\n956\n00:46:32,423 --> 00:46:33,689\nThe date it was created.\n\n957\n00:46:33,691 --> 00:46:36,392\nSo these are all kind of fields you always get, and\n\n958\n00:46:36,394 --> 00:46:39,529\nby default none of them are index however. So if you\n\n959\n00:46:39,531 --> 00:46:42,732\nwanted to search and say show me all the QandA's that were\n\n960\n00:46:42,734 --> 00:46:45,668\ncreated by a certain user, that wouldn't work, unless you\n\n961\n00:46:45,670 --> 00:46:50,439\ngo in here in the dashboard and turn on query index for\n\n962\n00:46:50,441 --> 00:46:53,142\ncreated by. Okay, so don't forget about this. This is\n\n963\n00:46:53,144 --> 00:46:56,045\nsomething easy to forget to do cuz they're automatic off and\n\n964\n00:46:56,047 --> 00:46:59,882\nyou're like how come that they won't show me all the QandA's\n\n965\n00:46:59,884 --> 00:47:00,683\nby this user,\n\n966\n00:47:00,685 --> 00:47:04,187\nit's because it's not indexed, okay. So that,\n\n967\n00:47:04,189 --> 00:47:05,721\nyou need to click on this little guy here,\n\n968\n00:47:05,723 --> 00:47:09,425\nmetadata indexes, to show this. Okay now,\n\n969\n00:47:09,427 --> 00:47:14,130\nthat schema that we're talking about there, the entities and\n\n970\n00:47:14,132 --> 00:47:16,566\nthe attributes okay, the record types and the fields,\n\n971\n00:47:16,568 --> 00:47:20,536\nyou can create it all in the dashboard if you want, but\n\n972\n00:47:20,538 --> 00:47:21,204\nyou don't have to.\n\n973\n00:47:21,206 --> 00:47:23,940\nYou can just start creating them in your code and\n\n974\n00:47:23,942 --> 00:47:26,209\nit'll automatically create the schema for you. Every time\n\n975\n00:47:26,211 --> 00:47:28,644\nyou will reference an entity that wasn't there before,\n\n976\n00:47:28,646 --> 00:47:31,347\nit's gonna create a new entity for it. Every time you access\n\n977\n00:47:31,349 --> 00:47:35,051\na field on a certain entity, you know, record type,\n\n978\n00:47:35,053 --> 00:47:37,720\nit's gonna create an attribute automatically. Now,\n\n979\n00:47:37,722 --> 00:47:40,122\nyou're still gonna have to go to dashboard and turn on or\n\n980\n00:47:40,124 --> 00:47:43,159\noff any indexes and things like that, but\n\n981\n00:47:43,161 --> 00:47:45,761\nit's just gonna create it all for you on the fly.\n\n982\n00:47:45,763 --> 00:47:48,231\nThat only happens though during development,\n\n983\n00:47:48,233 --> 00:47:50,867\nonce you deploy your app over at the app store,\n\n984\n00:47:50,869 --> 00:47:52,535\nnow that's not true anymore, okay.\n\n985\n00:47:52,537 --> 00:47:56,572\nSo your app has to have its schema built in development\n\n986\n00:47:56,574 --> 00:48:00,476\nand then you export that schema. When you run in\n\n987\n00:48:00,478 --> 00:48:05,214\ndeployment environment, okay? So this is really cool for\n\n988\n00:48:05,216 --> 00:48:07,884\ndevelopment because you don't have to do a lot of tedious\n\n989\n00:48:07,886 --> 00:48:12,154\ncreating of things in your in your dashboard.\n\n990\n00:48:12,156 --> 00:48:14,657\nAnd you can always go in the dashboard and delete things.\n\n991\n00:48:14,659 --> 00:48:18,060\nAnd it's really actually quite flexible and cool.\n\n992\n00:48:18,062 --> 00:48:22,031\nNow none of this will work until you unable Cloud Kit\n\n993\n00:48:22,033 --> 00:48:24,800\nin your capabilities. Remember I'd show you the capabilities\n\n994\n00:48:24,802 --> 00:48:28,337\nearlier. You go to the very top one here iCloud and\n\n995\n00:48:28,339 --> 00:48:30,072\nyou're gonna click this from off to on.\n\n996\n00:48:30,074 --> 00:48:32,975\nOkay if you don't do that none of this works. So\n\n997\n00:48:32,977 --> 00:48:36,746\nwhen you click it to on. You get this settings right here.\n\n998\n00:48:36,748 --> 00:48:40,316\nYou're gonna wanna click this switch right here Cloud Kit.\n\n999\n00:48:40,318 --> 00:48:41,884\nThat's all this stuff I'm gonna be talking about here in\n\n1000\n00:48:41,886 --> 00:48:45,454\nthis lecture, okay? Cloud Kit. There's also Key Value Storage\n\n1001\n00:48:45,456 --> 00:48:49,125\nwhich is kind of cool, you can store like an NS user defaults\n\n1002\n00:48:49,127 --> 00:48:50,893\non the Cloud. That's kind of cool features.\n\n1003\n00:48:50,895 --> 00:48:53,262\nWell, I'm not gonna talk about that. It's there if you wanna\n\n1004\n00:48:53,264 --> 00:48:56,766\ndo it and of course you can store documents in the Cloud.\n\n1005\n00:48:56,768 --> 00:48:59,268\nManage document Remember that from core data?\n\n1006\n00:48:59,270 --> 00:49:02,905\nIt stores all the core data stuff in the cloud, okay?\n\n1007\n00:49:02,907 --> 00:49:04,440\nSo, so you could have that as well.\n\n1008\n00:49:04,442 --> 00:49:08,644\nBut today, we're talking about this Cloud Kit right here,\n\n1009\n00:49:08,646 --> 00:49:11,047\nall right? This button right here,\n\n1010\n00:49:11,049 --> 00:49:12,715\nis how you get to that Cloud Kit dashboard.\n\n1011\n00:49:12,717 --> 00:49:16,786\nThis will open up your browser and take you to that thing,\n\n1012\n00:49:16,788 --> 00:49:22,725\nfor you. Kay? This right here is the containers. Remember I\n\n1013\n00:49:22,727 --> 00:49:25,895\nsaid a container is a thing that contains databases.\n\n1014\n00:49:25,897 --> 00:49:29,198\nWe're only gonna talk about use default container here.\n\n1015\n00:49:29,200 --> 00:49:32,201\nBut you're gonna actually create your custom containers.\n\n1016\n00:49:32,203 --> 00:49:35,771\nAnd what's cool about these containers is these containers\n\n1017\n00:49:35,773 --> 00:49:39,809\ncan be used across different kinds of apps. Okay?\n\n1018\n00:49:39,811 --> 00:49:41,544\nIn other words, you might be a company in\n\n1019\n00:49:41,546 --> 00:49:43,779\nyour shipment four different apps, and\n\n1020\n00:49:43,781 --> 00:49:45,314\nthey wanted to share data.\n\n1021\n00:49:45,316 --> 00:49:49,085\nThey can do that by creating a shared container, okay?\n\n1022\n00:49:49,087 --> 00:49:52,521\nThe default container is just to use by your one app, okay?\n\n1023\n00:49:52,523 --> 00:49:56,225\nI'm shipping to my app, all my users of that one app can use\n\n1024\n00:49:56,227 --> 00:49:59,295\nthis default container. Okay, and that's what I'm gonna\n\n1025\n00:49:59,297 --> 00:50:01,764\ntalk about today, but you can just know that this custom\n\n1026\n00:50:01,766 --> 00:50:04,900\ncontainer feature is available for your final project,\n\n1027\n00:50:04,902 --> 00:50:07,103\nthe default container's gonna be plenty, okay?\n\n1028\n00:50:07,105 --> 00:50:10,339\nAll right, so let's talk about these containers and\n\n1029\n00:50:10,341 --> 00:50:13,542\nwhat's in them, okay? And because we need to know that,\n\n1030\n00:50:13,544 --> 00:50:15,411\nso we can create records in the database,\n\n1031\n00:50:15,413 --> 00:50:19,115\nokay? So we get a database from the container.\n\n1032\n00:50:19,117 --> 00:50:21,884\nRemember, I said container contains databases.\n\n1033\n00:50:21,886 --> 00:50:25,855\nAnd the default container actually has two databases,\n\n1034\n00:50:25,857 --> 00:50:28,858\na public database and a private database.\n\n1035\n00:50:28,860 --> 00:50:31,260\nThe difference between these two is that the private\n\n1036\n00:50:31,262 --> 00:50:35,564\ndatabase can only be looked at by the currently logged in\n\n1037\n00:50:35,566 --> 00:50:39,902\niCloud user. Okay, so you know how on your phone, hopefully,\n\n1038\n00:50:39,904 --> 00:50:42,338\nyou're logged into iCloud, right? Okay, so,\n\n1039\n00:50:42,340 --> 00:50:46,409\nwhatever that login is, only the person logged in as that\n\n1040\n00:50:46,411 --> 00:50:49,612\niCloud can see the private database for that iCloud view.\n\n1041\n00:50:49,614 --> 00:50:50,346\nSo, it is exactly what it sounds like,\n\n1042\n00:50:50,348 --> 00:50:53,449\nit is private information. The public database can be seen by\n\n1043\n00:50:53,451 --> 00:50:58,988\nanybody, okay, anybody who is running your app. Can see\n\n1044\n00:50:58,990 --> 00:51:02,324\nthis public database. Got the difference between public and\n\n1045\n00:51:02,326 --> 00:51:05,094\nprivate? So public is where you're gonna have data that's\n\n1046\n00:51:05,096 --> 00:51:08,130\nshared between your users, private data is where you're\n\n1047\n00:51:08,132 --> 00:51:11,200\ngonna have data that the user sees on all their devices but\n\n1048\n00:51:11,202 --> 00:51:15,404\nthe other users can't see. All right. So that's how you\n\n1049\n00:51:15,406 --> 00:51:17,406\nget the database. Once you have the database.\n\n1050\n00:51:17,408 --> 00:51:18,441\nYou can do all kinds of things.\n\n1051\n00:51:18,443 --> 00:51:20,609\nCreate records query all kinds of stuff.\n\n1052\n00:51:20,611 --> 00:51:24,180\nSo let's starts with how to create record on the database.\n\n1053\n00:51:24,182 --> 00:51:27,583\nOkay. You create a record first of all by distributing\n\n1054\n00:51:27,585 --> 00:51:31,320\nCKRecord, Cloud Kit record and all you do is specified\n\n1055\n00:51:31,322 --> 00:51:34,190\nthe record type. Okay, that's like the entity name,\n\n1056\n00:51:34,192 --> 00:51:37,560\nlike tweet or Twitter user, whatever, it's just a string,\n\n1057\n00:51:37,562 --> 00:51:40,396\nokay. If that entity doesn't exist in the database when you\n\n1058\n00:51:40,398 --> 00:51:45,301\nsave this record, it'll create that entity, okay? Make sense?\n\n1059\n00:51:45,303 --> 00:51:48,170\nAll right, so now you have this record, okay?\n\n1060\n00:51:48,172 --> 00:51:51,474\nHow do you put information into the record? Well, you use\n\n1061\n00:51:51,476 --> 00:51:55,177\na dictionary-like syntax. So here I've got a record,\n\n1062\n00:51:55,179 --> 00:52:00,015\nright here. And I'm adding some fields to it by saying,\n\n1063\n00:52:00,017 --> 00:52:03,219\nrecords of text equals something, records of created\n\n1064\n00:52:03,221 --> 00:52:05,754\nequals something, records of items equals something, So,\n\n1065\n00:52:05,756 --> 00:52:07,490\nyou see how ithat looks a dictionary? It looks like\n\n1066\n00:52:07,492 --> 00:52:10,526\nrecords is almost a dictionary right there And so\n\n1067\n00:52:10,528 --> 00:52:13,462\nthat's actually use it, now what are these values,\n\n1068\n00:52:13,464 --> 00:52:15,564\nthese things that I have dot, dot, dot right here,\n\n1069\n00:52:15,566 --> 00:52:18,267\nwhat are these? Well, these can only be things\n\n1070\n00:52:18,269 --> 00:52:22,338\nthat implement the protocol CKRecordValue, okay? And\n\n1071\n00:52:22,340 --> 00:52:24,874\nthe only things the implement that protocol are these seven\n\n1072\n00:52:24,876 --> 00:52:29,178\nthings in green. Strings, numbers, arrays and dates.\n\n1073\n00:52:29,180 --> 00:52:32,148\nAnd of course, we get the bridged Swift types, so\n\n1074\n00:52:32,150 --> 00:52:36,352\nthat means doubles, ints, string, array, okay? And\n\n1075\n00:52:36,354 --> 00:52:39,989\nthen also these three special things, CKReference,\n\n1076\n00:52:39,991 --> 00:52:42,758\nCKAssett and CLLocation, okay?\n\n1077\n00:52:42,760 --> 00:52:47,930\nNow array can be array of any of the other types. Okay?\n\n1078\n00:52:47,932 --> 00:52:49,865\nThe array of any of these other green things.\n\n1079\n00:52:49,867 --> 00:52:52,268\nSo you can have an array of numbers, array of strings,\n\n1080\n00:52:52,270 --> 00:52:56,305\narray of dates,\n\n1081\n00:52:56,307 --> 00:53:00,643\nCKReference is a reference to another record. Okay, so this\n\n1082\n00:53:00,645 --> 00:53:03,712\nis how you do relationships, okay? So you have a record.\n\n1083\n00:53:03,714 --> 00:53:09,318\nSo again, if you had tweeter, and the tweets, okay?\n\n1084\n00:53:09,320 --> 00:53:12,955\nThe tweet record type would have a field\n\n1085\n00:53:12,957 --> 00:53:18,861\nthat is a CKReference to a Twitter user, okay?\n\n1086\n00:53:18,863 --> 00:53:23,599\nCKAsset is for storing big things, like images, sounds,\n\n1087\n00:53:23,601 --> 00:53:28,370\nvideo, okay, files basically. Now, This cloud kit does\n\n1088\n00:53:28,372 --> 00:53:31,507\na really cool job of when you put something in the cloud it\n\n1089\n00:53:31,509 --> 00:53:34,376\ndoesn't immediately just start cranking on the network piling\n\n1090\n00:53:34,378 --> 00:53:37,813\nthat thing up on the net, it stores it locally and\n\n1091\n00:53:37,815 --> 00:53:40,182\nwhen it wants to, when there's good network connection,\n\n1092\n00:53:40,184 --> 00:53:44,386\nwhatever, it's uploading it to the cloud. And vice versa. So\n\n1093\n00:53:44,388 --> 00:53:46,021\nIt's doing all this behind the scenes and\n\n1094\n00:53:46,023 --> 00:53:46,388\nbeing very efficient and\n\n1095\n00:53:46,390 --> 00:53:50,092\ncaching it etc. CL location, we're gonna talk about next\n\n1096\n00:53:50,094 --> 00:53:52,394\nweek when we talk about maps and locations.\n\n1097\n00:53:52,396 --> 00:53:55,831\nIt's just a GPS coordinate, okay, someplace on earth,\n\n1098\n00:53:55,833 --> 00:54:00,102\nso you can store something as a GPS coordinate. Okay, so\n\n1099\n00:54:00,104 --> 00:54:02,938\nthat's it, it's super. Easy to create these records. Again as\n\n1100\n00:54:02,940 --> 00:54:05,608\nyou put these field names in here if that doesn't exist in\n\n1101\n00:54:05,610 --> 00:54:08,677\nthe schema it's just gonna add that field okay as soon as you\n\n1102\n00:54:08,679 --> 00:54:11,614\nstore this to the database. So here we've created the record\n\n1103\n00:54:11,616 --> 00:54:13,749\nbut we haven't stored it yet okay it's not it hasn't been\n\n1104\n00:54:13,751 --> 00:54:16,585\nuploaded to the network we've only created it locally.\n\n1105\n00:54:16,587 --> 00:54:21,590\nSo how do we get the information. So we\n\n1106\n00:54:21,592 --> 00:54:24,927\nsaw how to put the information record how do we get it out\n\n1107\n00:54:24,929 --> 00:54:26,395\nYou again use dictionary syntax,\n\n1108\n00:54:26,397 --> 00:54:29,965\nso recor|\"text| to get the text out of the record. But\n\n1109\n00:54:29,967 --> 00:54:34,737\nyou have to cast, because all of these things come back as\n\n1110\n00:54:34,739 --> 00:54:38,274\nCKRecordValues. Okay? Cuz I told you, the only things that\n\n1111\n00:54:38,276 --> 00:54:40,943\ncan go in are things that implement that protocol.\n\n1112\n00:54:40,945 --> 00:54:42,511\nSo when you get it out, it comes out,\n\n1113\n00:54:42,513 --> 00:54:44,346\nit's a thing that implements that protocol.\n\n1114\n00:54:44,348 --> 00:54:45,180\nSo you have to cast it.\n\n1115\n00:54:45,182 --> 00:54:49,251\nTo the thing it actually is, okay. Make sense? That's why\n\n1116\n00:54:49,253 --> 00:54:52,254\neven like records of items. That's an array of strings.\n\n1117\n00:54:52,256 --> 00:54:56,292\nYou have to say as array of string, okay, got it.\n\n1118\n00:54:56,294 --> 00:54:58,827\nAnd of course, these all will be optional because as\n\n1119\n00:54:58,829 --> 00:55:03,432\nquestion mark. So I might wanna say if let on all these.\n\n1120\n00:55:03,434 --> 00:55:08,070\nOkay. Now, I've got the record creator, how do I put it into\n\n1121\n00:55:08,072 --> 00:55:11,707\nthe database? It's, actually, the real answer is, or\n\n1122\n00:55:11,709 --> 00:55:15,010\nthe full answer is you're gonna create an NSOperation,\n\n1123\n00:55:15,012 --> 00:55:17,680\nokay? Do you remember NSOperation, NSOperationQueue?\n\n1124\n00:55:17,682 --> 00:55:21,450\nThat's the object-oriented version of the GCD, right?\n\n1125\n00:55:21,452 --> 00:55:22,251\nDispatch async and\n\n1126\n00:55:22,253 --> 00:55:26,155\nall that stuff So the way you actually create\n\n1127\n00:55:26,157 --> 00:55:28,757\nrecords in the database is you create a special kind of\n\n1128\n00:55:28,759 --> 00:55:33,529\nNS operation called CKModifyRecordsOperation and\n\n1129\n00:55:33,531 --> 00:55:36,365\nyou can give it a bunch of records and you create and\n\n1130\n00:55:36,367 --> 00:55:40,369\nNS or operation cue, okay. You could use the main cue, okay,\n\n1131\n00:55:40,371 --> 00:55:43,405\nor you can create you're own cue. Those cues are just like\n\n1132\n00:55:43,407 --> 00:55:45,774\nthreads, okay, they're like Not like threads,\n\n1133\n00:55:45,776 --> 00:55:48,010\nthey're cues, just like dispatch under bar cue,\n\n1134\n00:55:48,012 --> 00:55:51,847\nunder bar tee things. And then you just tell that, if you put\n\n1135\n00:55:51,849 --> 00:55:55,617\nthis ModifyRecordsOperation on a cue it'll go and\n\n1136\n00:55:55,619 --> 00:55:56,318\nexecute it and\n\n1137\n00:55:56,320 --> 00:55:57,219\nupdate the database. But\n\n1138\n00:55:57,221 --> 00:56:00,422\nthat's a little bit of a pain in the neck to go do all that,\n\n1139\n00:56:00,424 --> 00:56:04,159\nokay. So there's a nice little convenience method right in\n\n1140\n00:56:04,161 --> 00:56:08,397\ndatabase called save record. And it just takes a record and\n\n1141\n00:56:08,399 --> 00:56:10,666\na completion handler. And it saves the record and\n\n1142\n00:56:10,668 --> 00:56:12,935\ncalls your completion handler when it's done. Okay, and\n\n1143\n00:56:12,937 --> 00:56:15,571\nremember that can be quite a ways later because this is\n\n1144\n00:56:15,573 --> 00:56:17,506\nhappening over the network. Your network might be slow,\n\n1145\n00:56:17,508 --> 00:56:19,942\nyou might be out of range of network, whatever. So\n\n1146\n00:56:19,944 --> 00:56:22,745\nit can take a very, very long time for this to come back.\n\n1147\n00:56:22,747 --> 00:56:27,116\nIt could even possibly time out but this is how it works.\n\n1148\n00:56:27,118 --> 00:56:28,283\nS this is on the database.\n\n1149\n00:56:28,285 --> 00:56:29,051\nRemember the public database or\n\n1150\n00:56:29,053 --> 00:56:32,087\nthe private database that you got from the container?\n\n1151\n00:56:32,089 --> 00:56:34,556\nThat's where you send this method. Okay?\n\n1152\n00:56:34,558 --> 00:56:37,292\nNow this thing cant do everything that this whole\n\n1153\n00:56:37,294 --> 00:56:42,765\nNSoperationQ can write multiple records at once.\n\n1154\n00:56:42,767 --> 00:56:45,200\nIt also knows how to overwrite a newer version.\n\n1155\n00:56:45,202 --> 00:56:47,703\nOkay, this does optimistic locking right here, the save\n\n1156\n00:56:47,705 --> 00:56:50,906\nrecord one. So if it tries to write something and there's\n\n1157\n00:56:50,908 --> 00:56:54,076\na newer version of that thing it's just gonna fail.\n\n1158\n00:56:54,078 --> 00:56:54,510\nReport an error.\n\n1159\n00:56:54,512 --> 00:56:58,747\nIt'll come back with an error here in the handler whereas\n\n1160\n00:56:58,749 --> 00:57:01,683\nthe modify records operation knows how to\n\n1161\n00:57:01,685 --> 00:57:05,421\noverwrite what's in there. But save record for\n\n1162\n00:57:05,423 --> 00:57:07,923\nthe most part does what you want most of the time. And for\n\n1163\n00:57:07,925 --> 00:57:10,559\nyour final project this is gonna be plenty probably.\n\n1164\n00:57:10,561 --> 00:57:13,996\nOkay, but you're not gonna need this operation thing.\n\n1165\n00:57:14,365 --> 00:57:16,999\nAll right, this happens all asychronously.\n\n1166\n00:57:17,001 --> 00:57:19,768\nBe very careful specially be careful with the fact\n\n1167\n00:57:19,770 --> 00:57:23,439\nthat your closure they gets cold when they save record is\n\n1168\n00:57:23,441 --> 00:57:27,109\nfinished Happens on another thread besides the main queue.\n\n1169\n00:57:27,111 --> 00:57:28,510\nOkay, it's not in the main queue.\n\n1170\n00:57:28,512 --> 00:57:31,413\nSo you need to dispatch async back to the main queue from\n\n1171\n00:57:31,415 --> 00:57:33,849\nthere if you want to do some UI stuff when\n\n1172\n00:57:33,851 --> 00:57:37,486\nthat record is saved. It make sense? Okay, and\n\n1173\n00:57:37,488 --> 00:57:39,388\nyou also just need an architecture code properly.\n\n1174\n00:57:39,390 --> 00:57:42,524\nYou need to think about the whole design of your app\n\n1175\n00:57:42,526 --> 00:57:45,093\nwhen the data that's appearing in it\n\n1176\n00:57:45,095 --> 00:57:46,962\nmight be coming asychronously. So\n\n1177\n00:57:46,964 --> 00:57:50,098\nyou need to know how to have apps that have basically blank\n\n1178\n00:57:50,100 --> 00:57:52,935\nUIs with either spinning wheels or Loading or\n\n1179\n00:57:52,937 --> 00:57:55,471\nsomething on there, so the user knows what's going on.\n\n1180\n00:57:55,473 --> 00:57:57,673\nAnd, when the data comes, it populates it. Okay?\n\n1181\n00:57:57,675 --> 00:58:00,008\nIt's very similar to, you do the smash tag where\n\n1182\n00:58:00,010 --> 00:58:02,544\nyou have the little profile images, and they come up and\n\n1183\n00:58:02,546 --> 00:58:06,148\nthey were blank. And then they just started filling in. Same\n\n1184\n00:58:06,150 --> 00:58:08,517\nkind of thing here, you have data in your database that\n\n1185\n00:58:08,519 --> 00:58:11,119\nstarts out, you don't have it and then it starts filling in.\n\n1186\n00:58:11,121 --> 00:58:14,389\nAnd what does that mean for the user? Means things should\n\n1187\n00:58:14,391 --> 00:58:17,259\nstart appearing over time. So you gotta think about how to\n\n1188\n00:58:17,261 --> 00:58:21,730\narchitect your app to use asyncronity. All right, so\n\n1189\n00:58:21,732 --> 00:58:22,664\nhere's what it looks like to create\n\n1190\n00:58:22,666 --> 00:58:24,867\na record in the database all put together here.\n\n1191\n00:58:24,869 --> 00:58:26,435\nSo I'm going to create a tweet right here.\n\n1192\n00:58:26,437 --> 00:58:29,404\nSo here I'm letting tweet equal ckrecord.\n\n1193\n00:58:29,406 --> 00:58:29,972\nJust created a record.\n\n1194\n00:58:29,974 --> 00:58:32,908\nI'm gonna have the Tweets text to be 140 characters of pure\n\n1195\n00:58:32,910 --> 00:58:35,811\njoy. Then I'm gonna get my database by saying\n\n1196\n00:58:35,813 --> 00:58:38,380\nCKContainer.defaultContainer publicCloudDatabase. So I'm\n\n1197\n00:58:38,382 --> 00:58:40,949\ngonna put this in the public database that all users of my\n\n1198\n00:58:40,951 --> 00:58:44,219\napp can see. Then I'm just gonna ask the database to save\n\n1199\n00:58:44,221 --> 00:58:47,322\nthe record Tweet, right. Here's that record Tweet and\n\n1200\n00:58:47,324 --> 00:58:49,591\nit's gonna call this closure, this big thing,\n\n1201\n00:58:49,593 --> 00:58:53,195\nwhen it's done. And this closure test two arguments,\n\n1202\n00:58:53,197 --> 00:58:55,264\nthe record that it saved or\n\n1203\n00:58:55,266 --> 00:59:00,068\nnil if it failed to save it and an error, okay.\n\n1204\n00:59:00,070 --> 00:59:05,073\nAgain, nil if it saved it, not nil if it failed to save it,\n\n1205\n00:59:05,075 --> 00:59:07,476\nokay. It doesn't return anything and so here's why\n\n1206\n00:59:07,478 --> 00:59:10,345\ndoing my closure almost all of the time first I'm gonna say,\n\n1207\n00:59:10,347 --> 00:59:12,748\nif the error equals nil Hooray okay,\n\n1208\n00:59:12,750 --> 00:59:15,684\nit saved it successfully, so now I do whatever I do when\n\n1209\n00:59:15,686 --> 00:59:19,421\nit was successfully saved. Maybe nothing okay? Maybe I do\n\n1210\n00:59:19,423 --> 00:59:23,592\nsomething else, I don't know, but here's success. Sometimes\n\n1211\n00:59:23,594 --> 00:59:27,362\nthere are 29 different errors in ck error code, so\n\n1212\n00:59:27,364 --> 00:59:31,300\na lot of things can go wrong. Network unavailable, all kinds\n\n1213\n00:59:31,302 --> 00:59:35,003\nof things I just showed you how you handle these by\n\n1214\n00:59:35,005 --> 00:59:37,439\npicking one at random, which is not authenticated.\n\n1215\n00:59:37,441 --> 00:59:40,008\nOkay? Let's say the person is not logged into iCloud.\n\n1216\n00:59:40,010 --> 00:59:42,578\nKay? They just never went to their settings and\n\n1217\n00:59:42,580 --> 00:59:43,545\nlogged into iCloud. Okay? So\n\n1218\n00:59:43,547 --> 00:59:46,515\nyou're gonna get this error, CKErrorCode.NotAuthenticated.\n\n1219\n00:59:46,517 --> 00:59:49,017\nDon't forget put, to put .rawValue so you get it as\n\n1220\n00:59:49,019 --> 00:59:51,753\nan integer because this error code is an integer. And\n\n1221\n00:59:51,755 --> 00:59:54,456\nso if there's that then I'm gonna maybe put up an alert\n\n1222\n00:59:54,458 --> 00:59:58,360\ncode that \"Please log in to iCloud\" or something, right?\n\n1223\n00:59:58,362 --> 01:00:02,664\nAnd there's 29 other errors and so doing this programming\n\n1224\n01:00:02,666 --> 01:00:07,336\nreally right, is a lot of error handling code. Okay, so\n\n1225\n01:00:07,338 --> 01:00:10,472\nin your final project You know the more you do of\n\n1226\n01:00:10,474 --> 01:00:13,275\nthis the more it's kind of like you can get forming\n\n1227\n01:00:13,277 --> 01:00:15,877\na one-point use of Cloud kit to a two-point use if you\n\n1228\n01:00:15,879 --> 01:00:18,413\nactually handle the error, you see what I'm saying?\n\n1229\n01:00:18,415 --> 01:00:20,983\nI don't expect you to handle every single error and\n\n1230\n01:00:20,985 --> 01:00:23,485\nuh-uh you get zero points, okay. Of course not, okay,\n\n1231\n01:00:23,487 --> 01:00:26,521\nthe more error you handle, the more robust you are,\n\n1232\n01:00:26,523 --> 01:00:27,723\nthe better you're a synchronize use,\n\n1233\n01:00:27,725 --> 01:00:30,859\nthe more depth point you might get working in Cloud,\n\n1234\n01:00:30,861 --> 01:00:34,062\nCloud kit Okay, but there's lots of other errors here.\n\n1235\n01:00:34,064 --> 01:00:35,597\nI'll show you some other errors that were going to\n\n1236\n01:00:35,599 --> 01:00:38,033\nhandle in some other, ones in a second here.\n\n1237\n01:00:38,035 --> 01:00:39,868\nBut this is how you're going to do it. Else if, else if,\n\n1238\n01:00:39,870 --> 01:00:43,572\nelse if, or you could just switch on the error code,\n\n1239\n01:00:43,574 --> 01:00:46,375\nto go to handling errors. Okay.\n\n1240\n01:00:46,377 --> 01:00:49,945\nI mean, at worst, you could just either put an alert up,\n\n1241\n01:00:49,947 --> 01:00:52,748\nbecause the user is saying unknown error or something, or\n\n1242\n01:00:52,750 --> 01:00:55,150\nyou could print something on the console. I don't know.\n\n1243\n01:00:55,152 --> 01:00:58,120\nBut it's usually you want to try and collect\n\n1244\n01:00:58,122 --> 01:01:01,990\nall the errors that you can do something about, okay?\n\n1245\n01:01:01,992 --> 01:01:06,361\nNow again if tweet the entity doesn't exist in the database\n\n1246\n01:01:06,363 --> 01:01:10,265\nit's gonna create it, okay? If text field doesn't exist on\n\n1247\n01:01:10,267 --> 01:01:12,834\nthis it's gonna create that attribute automatically for\n\n1248\n01:01:12,836 --> 01:01:16,405\nme. Okay, so that's it. That's how you put a record in\n\n1249\n01:01:16,407 --> 01:01:20,909\nthe database real easy. Okay? Now, there's\n\n1250\n01:01:20,911 --> 01:01:24,613\na special kind of error, that you can get sometimes,\n\n1251\n01:01:24,615 --> 01:01:30,318\nwhere, it will actually give you a retry time interval. So,\n\n1252\n01:01:30,320 --> 01:01:34,790\nnot all errors have this, but some errors when you get them,\n\n1253\n01:01:34,792 --> 01:01:35,724\nCloud Kit is basically saying hey,\n\n1254\n01:01:35,726 --> 01:01:38,627\nyou know this is the kinda area you probably wanna retry,\n\n1255\n01:01:38,629 --> 01:01:41,329\nand here's a good amount of time to try, okay.\n\n1256\n01:01:41,331 --> 01:01:44,866\nSo it's basically telling you what an appropriate retry\n\n1257\n01:01:44,868 --> 01:01:45,300\ninterval would be.\n\n1258\n01:01:45,302 --> 01:01:49,171\nAnd I believe if things continue to fail it, you know,\n\n1259\n01:01:49,173 --> 01:01:51,473\nadds, makes the retry interval a little bit longer,\n\n1260\n01:01:51,475 --> 01:01:54,242\nuntil it just gives up and says don't retry anymore.\n\n1261\n01:01:54,244 --> 01:01:55,944\nMore, but here is how you get it.\n\n1262\n01:01:55,946 --> 01:01:59,114\nError the NSError that you get back here in addition I have\n\n1263\n01:01:59,116 --> 01:02:02,284\nan error it also has a user info dictionary and\n\n1264\n01:02:02,286 --> 01:02:07,055\nin that dictionary is a key CKError retry after key and\n\n1265\n01:02:07,057 --> 01:02:10,559\nit's an NS time interval okay it's actually an NS number but\n\n1266\n01:02:10,561 --> 01:02:13,328\nyou're gonna cast it to an NS time interval there And\n\n1267\n01:02:13,330 --> 01:02:16,298\nthen you gonna wanna dispatch back to the main queue because\n\n1268\n01:02:16,300 --> 01:02:17,365\nyou gonna wanna have do a timer and\n\n1269\n01:02:17,367 --> 01:02:20,102\nwe know that we do our timers on the main queue. And so I'm\n\n1270\n01:02:20,104 --> 01:02:23,505\ngonna schedule a timer with that retry interval I'm just\n\n1271\n01:02:23,507 --> 01:02:27,609\ngonna call some method but will probably try this again.\n\n1272\n01:02:27,611 --> 01:02:30,846\nOkay maybe calls a method that this is in in fact.\n\n1273\n01:02:31,081 --> 01:02:35,817\nOkay I found So basically something might put in\n\n1274\n01:02:35,819 --> 01:02:38,453\nany kind of error that you'd be willing to retry.\n\n1275\n01:02:38,455 --> 01:02:41,590\nJust check to see if there's a retry interval, there's is.\n\n1276\n01:02:41,592 --> 01:02:43,992\nGive it a go. Try it again. Okay,\n\n1277\n01:02:43,994 --> 01:02:46,762\nand if there is no retry interval then of course,\n\n1278\n01:02:46,764 --> 01:02:51,266\nthis won't happen. You won't be doing this timer thing.\n\n1279\n01:02:51,268 --> 01:02:55,403\nGot it? Okay, now we've got the records stored.\n\n1280\n01:02:55,405 --> 01:02:58,406\nNow we want to get them, okay? So we basically want a query\n\n1281\n01:02:58,408 --> 01:03:02,577\nto get them. And querying is also super, super simple here.\n\n1282\n01:03:02,579 --> 01:03:05,347\nYou're just gonna do performQuery on the database.\n\n1283\n01:03:05,349 --> 01:03:07,549\nJust like you did saveRecord on the database you're gonna\n\n1284\n01:03:07,551 --> 01:03:09,184\ndo performQuery and give it a query.\n\n1285\n01:03:09,186 --> 01:03:11,920\nI'll talk about in a second. This inZoneWithID,\n\n1286\n01:03:11,922 --> 01:03:15,724\nremember I've told you there were zones, subdatabase zones,\n\n1287\n01:03:15,726 --> 01:03:19,161\nokay. So you can specify a zone there, or nil, actually\n\n1288\n01:03:19,163 --> 01:03:24,232\nthat's an optional string, so that could be nil. But if you\n\n1289\n01:03:24,234 --> 01:03:27,068\nspecify a zone, it will put, it will search only in zone,\n\n1290\n01:03:27,070 --> 01:03:29,971\nso you can limit your search and be more efficient, okay,\n\n1291\n01:03:29,973 --> 01:03:33,408\nif you can sensibly Divide your database into little\n\n1292\n01:03:33,410 --> 01:03:36,678\nzones. To keep your searches smaller it's a good idea.\n\n1293\n01:03:36,680 --> 01:03:38,180\nThat's what that inZoneWithID is.\n\n1294\n01:03:38,182 --> 01:03:40,115\nFor your final project, again you could say nil and\n\n1295\n01:03:40,117 --> 01:03:43,752\njust put everything in one big zone, default zone. And\n\n1296\n01:03:43,754 --> 01:03:46,121\nthen of course you're gonna call a completion handler, and\n\n1297\n01:03:46,123 --> 01:03:47,789\nlook what the completion handler has.\n\n1298\n01:03:47,791 --> 01:03:51,126\nAn array of the records that you searched for, couldn't be\n\n1299\n01:03:51,128 --> 01:03:55,330\nsimpler. Okay? Possibly an error. Okay, so this is just\n\n1300\n01:03:55,332 --> 01:03:57,732\nreally straightforward. You give it a query.\n\n1301\n01:03:57,734 --> 01:04:00,802\nIt just calls your handler with the records that matched.\n\n1302\n01:04:00,804 --> 01:04:03,638\nOr nil if there was an error, okay?\n\n1303\n01:04:03,640 --> 01:04:07,309\nNow what about this CKQuery, that's also trivial.\n\n1304\n01:04:07,311 --> 01:04:10,078\nIt's initializer is just the entity, okay?\n\n1305\n01:04:10,080 --> 01:04:14,549\nSo you wanna search for tweets and then an NSPredicate, okay?\n\n1306\n01:04:14,551 --> 01:04:17,719\nAnd so this NSPredicate is gonna specify which things you\n\n1307\n01:04:17,721 --> 01:04:21,423\nwant in your database. And this NSPredicate is\n\n1308\n01:04:21,425 --> 01:04:24,726\nobviously much simpler than Core Data because there\n\n1309\n01:04:24,728 --> 01:04:28,430\nare just fewer things that you can do, fewer data type,\n\n1310\n01:04:28,432 --> 01:04:31,900\nfewer, the relationships aren't as complicated,\n\n1311\n01:04:31,902 --> 01:04:35,604\nthere's just that reference thing etc. But\n\n1312\n01:04:35,606 --> 01:04:37,672\nyou can look in the documentation for CKQuery,\n\n1313\n01:04:37,674 --> 01:04:40,976\nit has a very good description of all the things you can do\n\n1314\n01:04:40,978 --> 01:04:43,278\nwith NSPredicate for CKQuery. It's, you know,\n\n1315\n01:04:43,280 --> 01:04:46,114\nall the things you might think like equals equals.\n\n1316\n01:04:46,116 --> 01:04:48,650\nBut also it has some cool things like in, okay?\n\n1317\n01:04:48,652 --> 01:04:50,352\nWhere you check whether something is in and\n\n1318\n01:04:50,354 --> 01:04:53,588\narray of other things for example. And so like that,\n\n1319\n01:04:53,590 --> 01:04:56,725\nit also has a special field name by the way, self, and\n\n1320\n01:04:56,727 --> 01:04:59,327\nyou know, cuz you should, could have a field name like\n\n1321\n01:04:59,329 --> 01:05:03,265\ntext if there's a tweet, text contains some word.\n\n1322\n01:05:03,267 --> 01:05:05,834\nThat's perfectly valid predicate. But you can also\n\n1323\n01:05:05,836 --> 01:05:09,604\nhave self as a keyword, not just tech, but self. And if I\n\n1324\n01:05:09,606 --> 01:05:13,541\nsay self contains whatever, it'll look in all the fields,\n\n1325\n01:05:13,543 --> 01:05:16,978\nokay, that are index, not just text but all the tweets.\n\n1326\n01:05:16,980 --> 01:05:20,248\nSo maybe you have a tweet that has text, it has hashtags,\n\n1327\n01:05:20,250 --> 01:05:23,952\nit has you know URLs as different fields. If you'd say\n\n1328\n01:05:23,954 --> 01:05:26,922\nself-contained something, it'll look in all the fields,\n\n1329\n01:05:26,924 --> 01:05:28,523\nall the indexed fields to find it, okay?\n\n1330\n01:05:28,525 --> 01:05:33,528\nSo it's kind of a search text over all the index field,\n\n1331\n01:05:33,530 --> 01:05:35,730\nokay? So this is really, couldn't be simpler,\n\n1332\n01:05:35,732 --> 01:05:38,333\nthey couldn't have made this any simpler. This is as simple\n\n1333\n01:05:38,335 --> 01:05:41,136\na kind of queries you can possibly imagine. Okay, so\n\n1334\n01:05:41,138 --> 01:05:43,371\nhere's an example. Here I'm looking for\n\n1335\n01:05:43,373 --> 01:05:46,741\na tweet that's text contains some search string so\n\n1336\n01:05:46,743 --> 01:05:47,742\nI've a predicate which is\n\n1337\n01:05:47,744 --> 01:05:51,479\ntext contains %@ which is the search string there.\n\n1338\n01:05:51,481 --> 01:05:54,549\nOtherwise, it looks just like NSPredicate of core data.\n\n1339\n01:05:54,551 --> 01:05:57,018\nOkay, I'm gonna create this query which is looking for\n\n1340\n01:05:57,020 --> 01:06:00,422\nTweets without predicate. I'm gonna perform the query\n\n1341\n01:06:00,424 --> 01:06:04,159\nsome time later. It's gonna call my closure right here.\n\n1342\n01:06:04,161 --> 01:06:07,629\nIt's gonna give me a list of all the Tweets, okay,\n\n1343\n01:06:07,631 --> 01:06:10,598\nthat contain that. That's what this records thing is right\n\n1344\n01:06:10,600 --> 01:06:13,969\nhere. Again, I'm checking for errors. Here, I've checked for\n\n1345\n01:06:13,971 --> 01:06:17,939\nthat not authenticated error again. But,\n\n1346\n01:06:17,941 --> 01:06:22,143\nit's as simple as that, okay? Now,\n\n1347\n01:06:22,145 --> 01:06:25,146\none thing, if you're gonna search on any of these things,\n\n1348\n01:06:25,148 --> 01:06:28,116\nany field that you're gonna search on, make sure you go to\n\n1349\n01:06:28,118 --> 01:06:30,986\nyour dashboard and make sure that the checkbox query for\n\n1350\n01:06:30,988 --> 01:06:34,856\nindexes is set, otherwise you can't query on it. Okay,\n\n1351\n01:06:34,858 --> 01:06:38,159\nnow when you create new fields automatically on\n\n1352\n01:06:38,161 --> 01:06:40,128\nthe fly like this, it automatically sets those.\n\n1353\n01:06:40,130 --> 01:06:42,430\nit automatically turns on indexes for all of them.\n\n1354\n01:06:42,432 --> 01:06:44,966\nIt doesn't turn on the indexes for created by and\n\n1355\n01:06:44,968 --> 01:06:47,736\ncreated date and all that, but it does do it for\n\n1356\n01:06:47,738 --> 01:06:51,106\nthe new field that you add. And in fact,\n\n1357\n01:06:51,108 --> 01:06:52,440\nwhen you go to deploy, you probably wanna turn\n\n1358\n01:06:52,442 --> 01:06:54,843\nsome of those off if you know you never search on it.\n\n1359\n01:06:54,845 --> 01:06:59,047\nDon't waste the database's time creating indexes that\n\n1360\n01:06:59,049 --> 01:07:03,018\nit doesn't use. Now, there's a special kind of record\n\n1361\n01:07:03,020 --> 01:07:06,354\nthough that you get with the special method here which\n\n1362\n01:07:06,356 --> 01:07:10,392\nis the recordID of the user, okay, the currently logged in\n\n1363\n01:07:10,394 --> 01:07:12,460\niCloud user. Now why would you ever want this?\n\n1364\n01:07:12,462 --> 01:07:14,662\nWell, because you might wanna look in the database and\n\n1365\n01:07:14,664 --> 01:07:17,632\nfind records created by that user. And to do that,\n\n1366\n01:07:17,634 --> 01:07:21,169\nyou need the user. You need the user's RecordID so\n\n1367\n01:07:21,171 --> 01:07:24,706\nthat you can make a query that says user, or\n\n1368\n01:07:24,708 --> 01:07:28,309\ncreatedBy, let's say, which is a built in one. User, creator,\n\n1369\n01:07:28,311 --> 01:07:30,445\nsomething. Actually I'll talk about in the next slide. You\n\n1370\n01:07:30,447 --> 01:07:32,881\nwant to be able to set that. Well, to do that, you need it.\n\n1371\n01:07:32,883 --> 01:07:35,216\nAnd you do this with a fetchUserRecordIDWithCompleti-\n\n1372\n01:07:35,218 --> 01:07:38,520\nonHandler. That is not sent to the database, though.\n\n1373\n01:07:38,522 --> 01:07:40,488\nThat is sent to the container. Okay,\n\n1374\n01:07:40,490 --> 01:07:43,691\nbecause the container, all the databases in the container,\n\n1375\n01:07:43,693 --> 01:07:46,528\nthe, I currently logged in iCloud user, is the user for\n\n1376\n01:07:46,530 --> 01:07:50,498\nthem. So you actually go up to CKContainer to do this,\n\n1377\n01:07:50,500 --> 01:07:51,699\nCKContainer default container,\n\n1378\n01:07:51,701 --> 01:07:54,736\nfetch record user record with completion handler, and\n\n1379\n01:07:54,738 --> 01:07:57,372\nit just returns you the RecordID of the user.\n\n1380\n01:07:57,374 --> 01:08:00,842\nNow, notice this is the RecordID, not the CKRecord,\n\n1381\n01:08:00,844 --> 01:08:03,912\nyou almost never need the actual record of the user.\n\n1382\n01:08:03,914 --> 01:08:05,380\nYou could get the record of the user, and\n\n1383\n01:08:05,382 --> 01:08:07,348\nyou could even add fields to it if you wanted,\n\n1384\n01:08:07,350 --> 01:08:10,485\nbut it's rare to do that. Usually, you just need\n\n1385\n01:08:10,487 --> 01:08:13,621\nthe RecordID because you're going to be querying on it,\n\n1386\n01:08:13,623 --> 01:08:17,125\nyou're gonna be making queries to find out if this user was\n\n1387\n01:08:17,127 --> 01:08:19,828\nthe person who created it or whatever, okay?\n\n1388\n01:08:19,830 --> 01:08:22,797\nThe RecordID has a property record name,\n\n1389\n01:08:22,799 --> 01:08:26,935\nwhich is just some randomly created string that you\n\n1390\n01:08:26,937 --> 01:08:29,270\ncan use as kind of a blind username.\n\n1391\n01:08:29,272 --> 01:08:31,973\nIt's not gonna be the person's actual iCloud name, it's just\n\n1392\n01:08:31,975 --> 01:08:35,877\nsome gobbledygook. But inside of your implementation,\n\n1393\n01:08:35,879 --> 01:08:40,048\nyou can use it as a string key that means this user if you\n\n1394\n01:08:40,050 --> 01:08:43,818\nwant, okay? I'm gonna combine the two things,\n\n1395\n01:08:43,820 --> 01:08:48,356\nthe fetchUserRecord with the query here. I'm gonna find all\n\n1396\n01:08:48,358 --> 01:08:51,493\nthe tweets that were created by the currently logged in\n\n1397\n01:08:51,495 --> 01:08:55,630\nuser. Okay, so first I get the container,\n\n1398\n01:08:55,632 --> 01:08:58,800\nI fetch the user in the completion handler for\n\n1399\n01:08:58,802 --> 01:09:01,903\nthat right here. I have the user. Now I'm gonna create\n\n1400\n01:09:01,905 --> 01:09:05,540\na new predicate which is the creatorUserRecordID.\n\n1401\n01:09:05,542 --> 01:09:09,711\nWhich is a built in field on all record types.\n\n1402\n01:09:09,713 --> 01:09:14,616\nEquals the UserRecordID, a thing I got from fetchRecord.\n\n1403\n01:09:14,618 --> 01:09:15,416\nSee that thing right there.\n\n1404\n01:09:15,418 --> 01:09:17,619\nAnd them I'm gonna create a query which is for\n\n1405\n01:09:17,621 --> 01:09:20,155\ntweets that uses that predicate. Now I'm gonna\n\n1406\n01:09:20,157 --> 01:09:22,991\nget the public database and perform the query, okay?\n\n1407\n01:09:22,993 --> 01:09:26,761\nIn zone nil, and I'm gonna get the record in error as\n\n1408\n01:09:26,763 --> 01:09:29,764\na return value. And so now I have this records containing\n\n1409\n01:09:29,766 --> 01:09:32,767\nall the tweets created by the currently logged in user.\n\n1410\n01:09:32,769 --> 01:09:34,602\nSee how I chained those two? And\n\n1411\n01:09:34,604 --> 01:09:37,872\nremember, this fetch record, UserRecordID,\n\n1412\n01:09:37,874 --> 01:09:38,606\nthat's gonna take a little while.\n\n1413\n01:09:38,608 --> 01:09:41,109\nAnd when it returns, it's gonna do another query.\n\n1414\n01:09:41,111 --> 01:09:44,045\nThat's gonna take a little while, so it's gonna chain.\n\n1415\n01:09:44,047 --> 01:09:47,549\nBut since this call is inside of this other closure,\n\n1416\n01:09:47,551 --> 01:09:52,253\nit chains them nicely there. Okay, again\n\n1417\n01:09:52,255 --> 01:09:55,423\nyou have to create, turn that Created By metadata index on\n\n1418\n01:09:55,425 --> 01:09:57,792\nthat I showed you right at the beginning for this to work or\n\n1419\n01:09:57,794 --> 01:10:03,198\nyou can't search on user. Okay, by the way,\n\n1420\n01:10:03,200 --> 01:10:06,901\nif you ever have a RecordID and you wanna get the record,\n\n1421\n01:10:06,903 --> 01:10:09,637\nokay, the CKRecord, you can use databases\n\n1422\n01:10:09,639 --> 01:10:12,240\nfetchRecordWithID and that will search and\n\n1423\n01:10:12,242 --> 01:10:16,311\nget the actual record, okay? The RecordID, though,\n\n1424\n01:10:16,313 --> 01:10:18,846\non its own has some interesting things\n\n1425\n01:10:18,848 --> 01:10:22,850\nlike the creator, the creation date, the record type,\n\n1426\n01:10:22,852 --> 01:10:26,321\nand all that stuff, so that's kind of fun. All right,\n\n1427\n01:10:26,323 --> 01:10:30,158\ndeleting records from the database couldn't be easier.\n\n1428\n01:10:30,160 --> 01:10:30,658\nJust say to the database,\n\n1429\n01:10:30,660 --> 01:10:33,361\ndeleteRecordWithID. You have to have the record ID, you can\n\n1430\n01:10:33,363 --> 01:10:35,230\nof course get the record ID from a record easily,\n\n1431\n01:10:35,232 --> 01:10:38,066\nthere's a bar for it. And then completionHandler when it's\n\n1432\n01:10:38,068 --> 01:10:42,237\ndone, okay? Okay, now let's talk about references, okay?\n\n1433\n01:10:42,239 --> 01:10:44,038\nI wanna, I want to store a reference. So this is\n\n1434\n01:10:44,040 --> 01:10:46,908\nlike the Twitter user as the tweeter for a tweet.\n\n1435\n01:10:46,910 --> 01:10:50,278\nYou cannot do this code right here. twitterUser equals\n\n1436\n01:10:50,280 --> 01:10:54,549\na recordType TwitterUser. Tweet equals a record Tweet.\n\n1437\n01:10:54,551 --> 01:10:58,052\nTweet, subTweeter equals TwitterUser. [SOUND] Okay,\n\n1438\n01:10:58,054 --> 01:11:02,490\ncan't do it. This thing has to be a CKReference.\n\n1439\n01:11:02,492 --> 01:11:04,993\nSo you just have to say TweetSubTweeter equals\n\n1440\n01:11:04,995 --> 01:11:07,996\nCKReference with the record. And then you specify this\n\n1441\n01:11:07,998 --> 01:11:10,431\naction which is interesting, it's either deletes itself or\n\n1442\n01:11:10,433 --> 01:11:16,504\nnot. This action says what to do if this thing is deleted.\n\n1443\n01:11:16,506 --> 01:11:20,308\nOkay, when we cascade. So if I say the action is DeleteSelf,\n\n1444\n01:11:20,310 --> 01:11:23,811\nthis reference to twitterUser is DeleteSelf reference.\n\n1445\n01:11:23,813 --> 01:11:26,948\nThen if the twitterUser is deleted, then the Tweet is\n\n1446\n01:11:26,950 --> 01:11:29,984\ndeleted as well. It cascades the delete. That's why it's\n\n1447\n01:11:29,986 --> 01:11:35,089\nsaying delete myself, okay, if this reference gets deleted.\n\n1448\n01:11:35,091 --> 01:11:37,525\nNone means don't do it. When you delete,\n\n1449\n01:11:37,527 --> 01:11:41,829\ndon't do any cascading, just delete this one thing, okay?\n\n1450\n01:11:41,831 --> 01:11:44,399\nBy the way, when you're creating a predicate,\n\n1451\n01:11:44,401 --> 01:11:45,900\nyou don't have to do that CKReference thing.\n\n1452\n01:11:45,902 --> 01:11:47,969\nIf I wanna create a predicate which is tweeter equals\n\n1453\n01:11:47,971 --> 01:11:50,938\nsomething, I can actually pass the twitterUser, I don't have\n\n1454\n01:11:50,940 --> 01:11:56,978\nto say CKReference twitterUser there. Okay, standing queries,\n\n1455\n01:11:56,980 --> 01:12:00,315\nthe last thing we're talking about, subscriptions, okay? So\n\n1456\n01:12:00,317 --> 01:12:02,950\nsometimes it's nice to not have to be constantly\n\n1457\n01:12:02,952 --> 01:12:06,454\nquerying, you just want iCloud to tell you when a new Thing\n\n1458\n01:12:06,456 --> 01:12:09,657\nappears in the database that you're interested in.\n\n1459\n01:12:09,659 --> 01:12:12,794\nAnd that's really, really easy to do. So for\n\n1460\n01:12:12,796 --> 01:12:15,596\nan example here, I'm going to set up a subscription so\n\n1461\n01:12:15,598 --> 01:12:18,866\nthat I get notified by a push notification any time that\n\n1462\n01:12:18,868 --> 01:12:19,600\na Tweet is created or\n\n1463\n01:12:19,602 --> 01:12:22,737\ndeleted. So I'm gonna create a predicate which is\n\n1464\n01:12:22,739 --> 01:12:25,373\ntrue predicate which means all Tweets. Okay,\n\n1465\n01:12:25,375 --> 01:12:28,009\nthis is a special predicate, that means all.\n\n1466\n01:12:28,011 --> 01:12:31,145\nAnd in core dating, you have the predicate nil, means all.\n\n1467\n01:12:31,147 --> 01:12:32,814\nHere you have to create a predicate,\n\n1468\n01:12:32,816 --> 01:12:33,147\nit's true predicate.\n\n1469\n01:12:33,149 --> 01:12:36,084\nAnd then you create this thing called a CKSubscription\n\n1470\n01:12:36,086 --> 01:12:39,120\nwith the record type that you're interested in, Tweets,\n\n1471\n01:12:39,122 --> 01:12:42,657\nthe predicate you want, all of the them. A subscriptionID,\n\n1472\n01:12:42,659 --> 01:12:45,893\nthis is an English language string that should\n\n1473\n01:12:45,895 --> 01:12:48,996\nvery uniquely describe what you're looking for. Okay,\n\n1474\n01:12:48,998 --> 01:12:51,833\nbecause this is gonna identify this subscription in\n\n1475\n01:12:51,835 --> 01:12:54,335\nthe database so you can delete it later for an example.\n\n1476\n01:12:54,337 --> 01:12:57,939\nOkay so here I called it \"All Tweet Creation and Deletion\".\n\n1477\n01:12:57,941 --> 01:13:02,510\nAnd then options is what kinds of actions of those tweets,\n\n1478\n01:13:02,512 --> 01:13:05,446\nfor example, do you wanna know when the tweets are created?\n\n1479\n01:13:05,448 --> 01:13:07,115\nDo you wanna know when tweets are deleted?\n\n1480\n01:13:07,117 --> 01:13:08,883\nYou can also find out when tweets are updated,\n\n1481\n01:13:08,885 --> 01:13:12,019\ntheir fields change. And you can also have FiresOnce\n\n1482\n01:13:12,021 --> 01:13:15,289\nin here which means that this subscription only works once.\n\n1483\n01:13:15,291 --> 01:13:16,391\nIt sends you one push notification and\n\n1484\n01:13:16,393 --> 01:13:20,128\nthen gets deleted. Okay, so it's like a one time standing\n\n1485\n01:13:20,130 --> 01:13:23,564\nquery. It also has this thing called a notifcationInfo.\n\n1486\n01:13:23,566 --> 01:13:25,466\nOkay, this is gonna send a push notification.\n\n1487\n01:13:25,468 --> 01:13:28,536\nSo this can help you configure that push notification right\n\n1488\n01:13:28,538 --> 01:13:32,039\nhere. And then you just say, database.saveSubscription.\n\n1489\n01:13:32,041 --> 01:13:34,208\nOkay, and it'll call you back when it's done.\n\n1490\n01:13:34,210 --> 01:13:36,110\nAnd that puts this subscription in the database.\n\n1491\n01:13:36,112 --> 01:13:39,580\nAnd now the database is gonna send you a push notification\n\n1492\n01:13:39,582 --> 01:13:42,884\nwhenever this is changing. Okay, creation or deletion of\n\n1493\n01:13:42,886 --> 01:13:46,254\ntweets, in this case. Okay, now I have to tell you how to\n\n1494\n01:13:46,256 --> 01:13:49,624\ndeal with push notifications, okay. How to turn them on,\n\n1495\n01:13:49,626 --> 01:13:53,761\nand how to get them. So, to turn on a push notification,\n\n1496\n01:13:53,763 --> 01:13:56,030\nyou actually need to in your application,\n\n1497\n01:13:56,032 --> 01:13:59,333\ndidFinishLaunchingWithOptions is usually where you would put\n\n1498\n01:13:59,335 --> 01:14:02,003\nthis code, you have to put these yellow lines here.\n\n1499\n01:14:02,005 --> 01:14:04,939\nWhich is, you have to call this method\n\n1500\n01:14:04,941 --> 01:14:06,908\nregisterUserNotificationSetti- ngs.\n\n1501\n01:14:06,910 --> 01:14:09,844\nOkay, the user notification settings just say what kind\n\n1502\n01:14:09,846 --> 01:14:13,714\nof push notifications you're willing to receive like,\n\n1503\n01:14:13,716 --> 01:14:16,150\nalerts, badges, or sounds.\n\n1504\n01:14:16,152 --> 01:14:19,220\nIf you're just alerting to let the code know, you don't have\n\n1505\n01:14:19,222 --> 01:14:21,989\nto send off any of those three, okay? Alert badge and\n\n1506\n01:14:21,991 --> 01:14:24,425\nsound means it's gonna put an alert up when things come,\n\n1507\n01:14:24,427 --> 01:14:27,562\nokay, or a badge. It's gonna put a little red badge\n\n1508\n01:14:27,564 --> 01:14:30,331\non your icon, your app icon which is kinda cool maybe,\n\n1509\n01:14:30,333 --> 01:14:32,033\nyou might want that actually.\n\n1510\n01:14:32,035 --> 01:14:36,270\nYou get to specify the, what happens when the push\n\n1511\n01:14:36,272 --> 01:14:39,073\nnotification comes from Cloud Kit back in that notification\n\n1512\n01:14:39,075 --> 01:14:41,776\ninfo thing that I was telling you about in the previous\n\n1513\n01:14:41,778 --> 01:14:43,644\nslide. Subscription.notificationInfo,\n\n1514\n01:14:43,646 --> 01:14:46,981\none of the things in there is whether to alert badge or\n\n1515\n01:14:46,983 --> 01:14:51,052\nsound when the subscription fires. Okay. So\n\n1516\n01:14:51,054 --> 01:14:54,622\nanyway you register what your kind of settings you want, and\n\n1517\n01:14:54,624 --> 01:14:56,791\nthen you have to register for remote notifications.\n\n1518\n01:14:56,793 --> 01:14:59,327\nThat means I wanna hear about remote notifications.\n\n1519\n01:14:59,329 --> 01:15:00,728\nIf you don't do this, you won't get any push\n\n1520\n01:15:00,730 --> 01:15:04,298\nnotifications of any kind, let alone these Cloud Kit ones.\n\n1521\n01:15:04,300 --> 01:15:06,634\nOkay. So now once you've done that okay,\n\n1522\n01:15:06,636 --> 01:15:08,936\nyou need to receive them. And you do that with this\n\n1523\n01:15:08,938 --> 01:15:12,673\napplication delegate method didReceiveRemoteNotification.\n\n1524\n01:15:12,675 --> 01:15:15,376\nSo this will get called any time a push notification comes\n\n1525\n01:15:15,378 --> 01:15:19,380\nto your app, okay. When you get it there's user info\n\n1526\n01:15:19,382 --> 01:15:22,950\nright here, okay. And inside that userInfo is a dictionary\n\n1527\n01:15:22,952 --> 01:15:26,587\nthat Cloud Kit's gonna send. And you're gonna use this\n\n1528\n01:15:26,589 --> 01:15:30,658\nCKNotification class, right here, call it initializer,\n\n1529\n01:15:30,660 --> 01:15:34,195\nwith that dictionary to create a CKNotification.\n\n1530\n01:15:34,197 --> 01:15:37,532\nThat CKNotification, Cloud Kit notification, represents\n\n1531\n01:15:37,534 --> 01:15:40,001\nthe push notification that was sent to you. It's got all the\n\n1532\n01:15:40,003 --> 01:15:43,104\ninformation you need to know about the push notification\n\n1533\n01:15:43,106 --> 01:15:46,574\nthat got sent because you're subscription. Okay? And\n\n1534\n01:15:46,576 --> 01:15:49,176\nit's got things in there like the recordID that change\n\n1535\n01:15:49,178 --> 01:15:53,748\nthat cause it. Why the notification is happening s\n\n1536\n01:15:53,750 --> 01:15:54,782\nit because something was created,\n\n1537\n01:15:54,784 --> 01:15:56,717\nor something was deleted, or something was updated?\n\n1538\n01:15:56,719 --> 01:15:59,687\nOkay, will tell you which of those things went on that\n\n1539\n01:15:59,689 --> 01:16:02,790\ncaused this notification to be sent to you and\n\n1540\n01:16:02,792 --> 01:16:04,258\nwhich record was affected by it.\n\n1541\n01:16:04,260 --> 01:16:07,094\nYou can even, in the subscription notificationInfo,\n\n1542\n01:16:07,096 --> 01:16:10,031\nyou can set certain fields to be prefetched and\n\n1543\n01:16:10,033 --> 01:16:12,733\ncome along with. Okay, cuz normally it only sends you\n\n1544\n01:16:12,735 --> 01:16:15,269\nthe recordID of what changed in the database.\n\n1545\n01:16:15,271 --> 01:16:16,938\nYou might wanna actually sum of the fields, so\n\n1546\n01:16:16,940 --> 01:16:20,675\nyou don't have to go get, fetch the record itself, okay?\n\n1547\n01:16:20,677 --> 01:16:23,477\nSo that's great. Now that you've got this notification,\n\n1548\n01:16:23,479 --> 01:16:27,181\nwhat do you do with it. Okay, you really need to get it\n\n1549\n01:16:27,183 --> 01:16:29,750\nto the part of your UI, if you control it or\n\n1550\n01:16:29,752 --> 01:16:33,287\nwhatever, that's going to do something with this data\n\n1551\n01:16:33,289 --> 01:16:35,756\nthat has changed, okay. And the best way,\n\n1552\n01:16:35,758 --> 01:16:37,425\nthis is all coming to your AppDelegate, right?\n\n1553\n01:16:37,427 --> 01:16:39,694\nIs your AppDelegate getting this push notification?\n\n1554\n01:16:39,696 --> 01:16:41,829\nThat's not that useful because usually it's some view\n\n1555\n01:16:41,831 --> 01:16:44,265\ncontroller somewhere that really wants the information.\n\n1556\n01:16:44,267 --> 01:16:46,734\nSo what we're gonna do is we're gonna forward it\n\n1557\n01:16:46,736 --> 01:16:49,770\nusing the radio station model, okay?\n\n1558\n01:16:49,772 --> 01:16:52,106\nThat's is real simple way to get this thing to came to\n\n1559\n01:16:52,108 --> 01:16:54,809\nAppDelegate and get it out to who really wants it. So\n\n1560\n01:16:54,811 --> 01:16:57,078\nI'm just gonna create a local notification here I'm gonna\n\n1561\n01:16:57,080 --> 01:16:59,880\nbecome a radio station broadcaster see in this\n\n1562\n01:16:59,882 --> 01:17:00,047\nnotification.\n\n1563\n01:17:00,049 --> 01:17:03,417\nHere's my radio station name MyCloudKitNotificationName or\n\n1564\n01:17:03,419 --> 01:17:07,388\nwhatever. Self is this is in AppDelegate so self is gonna\n\n1565\n01:17:07,390 --> 01:17:09,790\nbe my AppDelegate but it probably doesn't matter what I\n\n1566\n01:17:09,792 --> 01:17:12,393\npass here as the sender of the radio station. And\n\n1567\n01:17:12,395 --> 01:17:15,863\nthen here in the userInfo, I'm gonna put that ckn,\n\n1568\n01:17:15,865 --> 01:17:18,666\nthis notification right here that I created, okay,\n\n1569\n01:17:18,668 --> 01:17:21,335\nfrom the dictionary that came in the push notification.\n\n1570\n01:17:21,337 --> 01:17:23,704\nI'm gonna put that in the dictionary\n\n1571\n01:17:23,706 --> 01:17:25,873\nunder some key name, ckn or\n\n1572\n01:17:25,875 --> 01:17:30,011\nwhatever, CKNKey, so that the people who are listening to my\n\n1573\n01:17:30,013 --> 01:17:33,080\nradio station can get this CKNotification. By the way,\n\n1574\n01:17:33,082 --> 01:17:36,517\nthese two strings wanna be global constant somewhere.\n\n1575\n01:17:36,519 --> 01:17:40,254\nSo that the listeners and the sender are using the same keys\n\n1576\n01:17:40,256 --> 01:17:46,394\nand radio station names, okay? And then I just post it, okay.\n\n1577\n01:17:46,396 --> 01:17:48,329\nDefaultCenter postNotification disNotification.\n\n1578\n01:17:48,331 --> 01:17:51,098\nAnd now everybody's listening to this radio station gonna\n\n1579\n01:17:51,100 --> 01:17:52,967\nfind out about all the push notifications coming\n\n1580\n01:17:52,969 --> 01:17:56,737\nfrom Cloud Kit. Cause they're getting forwarded out to them.\n\n1581\n01:17:56,739 --> 01:18:00,708\nOkay, now, if I'm an observer, what do I do? I just\n\n1582\n01:18:00,710 --> 01:18:04,111\ndo this addObserverForName, okay. So now I'm some view\n\n1583\n01:18:04,113 --> 01:18:06,380\ncontroller that wants to hear this push notification, so\n\n1584\n01:18:06,382 --> 01:18:09,784\nI do addObserveForName, I use the radio station name there,\n\n1585\n01:18:09,786 --> 01:18:12,319\nI don't care who sends it to me, I'm going to do it on\n\n1586\n01:18:12,321 --> 01:18:14,889\nthe same queue because I know my AppDelegate runs on\n\n1587\n01:18:14,891 --> 01:18:18,926\nthe main queue, but I could put main queue here also. And\n\n1588\n01:18:18,928 --> 01:18:20,027\nthen using block right here.\n\n1589\n01:18:20,029 --> 01:18:20,995\nThis is the block that gets called.\n\n1590\n01:18:20,997 --> 01:18:24,432\nHere's the notification that came over the radio station.\n\n1591\n01:18:24,434 --> 01:18:26,467\nI'm gonna look in the notification look at that\n\n1592\n01:18:26,469 --> 01:18:30,905\nuser interface, user info, get that key and cast it\n\n1593\n01:18:30,907 --> 01:18:34,608\nto be a CKQueryNotification by the way. There's another kind\n\n1594\n01:18:34,610 --> 01:18:39,113\nof thing it could be which is a zone oriented notification,\n\n1595\n01:18:39,115 --> 01:18:41,115\nI'm not talking about zones but most of the times it's\n\n1596\n01:18:41,117 --> 01:18:43,651\ngonna be a query notification cuz it's a subscription.\n\n1597\n01:18:43,653 --> 01:18:45,886\nSo you can do this as query notification.\n\n1598\n01:18:45,888 --> 01:18:50,591\nNow you're gonna check to see if the subscriptionID of this\n\n1599\n01:18:50,593 --> 01:18:54,862\nquery notification is the same as your subscriptionID because\n\n1600\n01:18:54,864 --> 01:18:56,230\nthere might be other view controllers\n\n1601\n01:18:56,232 --> 01:18:57,698\nwho have subscriptions in Cloud Kit and\n\n1602\n01:18:57,700 --> 01:18:59,700\nthey're getting notified by push notifications.\n\n1603\n01:18:59,702 --> 01:19:02,002\nYou don't want theirs, you want yours. And\n\n1604\n01:19:02,004 --> 01:19:04,839\nyou can tell it's yours because you can look in this\n\n1605\n01:19:04,841 --> 01:19:08,275\nCKQueryNotification and find the subscriptionID that caused\n\n1606\n01:19:08,277 --> 01:19:12,046\nthis push notification to get pushed, got it? And\n\n1607\n01:19:12,048 --> 01:19:15,249\nonce I'm sure it's for me now I can go react to it.\n\n1608\n01:19:15,251 --> 01:19:15,416\nThe data's available.\n\n1609\n01:19:15,418 --> 01:19:18,519\nMaybe I'll put it in my table view or whatever I do with\n\n1610\n01:19:18,521 --> 01:19:20,921\nit cuz the data is here, okay? Maybe I'll query for\n\n1611\n01:19:20,923 --> 01:19:24,959\nmore information, whatever. But now I can get going.\n\n1612\n01:19:24,961 --> 01:19:28,262\nMake sense? By the way, notice that when did out observe for\n\n1613\n01:19:28,264 --> 01:19:31,198\nname I grabbed the return value that cookie I told you\n\n1614\n01:19:31,200 --> 01:19:34,468\nand in this object protocol thing we did and why do I want\n\n1615\n01:19:34,470 --> 01:19:37,271\nthat, because later on when I'm done listening\n\n1616\n01:19:37,273 --> 01:19:40,641\nto further push notifications via this radio station.\n\n1617\n01:19:40,643 --> 01:19:44,278\nI'm gonna call removeObserver to remove this observer so\n\n1618\n01:19:44,280 --> 01:19:46,947\nI no longer get these local notifications.\n\n1619\n01:19:46,949 --> 01:19:51,051\nSo this is something might do in our view did disappear.\n\n1620\n01:19:51,053 --> 01:19:54,922\nAnd we might do this in our view will appear or view did\n\n1621\n01:19:54,924 --> 01:19:58,192\nappear. Right, cuz only when we're on screen do we maybe\n\n1622\n01:19:58,194 --> 01:20:00,528\nwant these notifications. When we go off we don't\n\n1623\n01:20:00,530 --> 01:20:01,796\nwant them any more. When we come back on we wanna\n\n1624\n01:20:01,798 --> 01:20:06,500\nkeep getting them again. Okay? You definitely wanna do this,\n\n1625\n01:20:06,502 --> 01:20:11,005\nby the way you never want your view controller to go away and\n\n1626\n01:20:11,007 --> 01:20:16,143\nstill be here because this closure will keep your\n\n1627\n01:20:16,145 --> 01:20:18,746\nview controller in memory. And you don't wanna really do\n\n1628\n01:20:18,748 --> 01:20:21,282\nweakSelf and all that because you actually wanna explicitly\n\n1629\n01:20:21,284 --> 01:20:23,350\nremove it otherwise the NotificationCenter's gonna\n\n1630\n01:20:23,352 --> 01:20:27,555\nalways be holding onto you, okay?\n\n1631\n01:20:27,557 --> 01:20:31,158\nSo, make sure you do this, somewhere, removeObserver\n\n1632\n01:20:31,160 --> 01:20:33,828\nsomewhere. Okay, that's it for Cloud Kit. Now you know\n\n1633\n01:20:33,830 --> 01:20:36,096\neverything about how to create records, query for\n\n1634\n01:20:36,098 --> 01:20:38,399\nthem, and even sign up to get notified.\n\n1635\n01:20:38,401 --> 01:20:40,434\nI'm gonna do a big demo on this on Wednesday, so you can\n\n1636\n01:20:40,436 --> 01:20:45,172\nsee it all in action. Friday, No Section again. Next week,\n\n1637\n01:20:45,174 --> 01:20:48,876\nstill kinda deciding how or what works to do things.\n\n1638\n01:20:48,878 --> 01:20:49,743\nI really wanna make to sure you get\n\n1639\n01:20:49,745 --> 01:20:54,215\nthis Segues covered right here but maps are also really cool.\n\n1640\n01:20:54,217 --> 01:20:56,450\nI won't get to all of these next week but I'll do as much\n\n1641\n01:20:56,452 --> 01:20:59,353\nas I can. Okay, if you have by the way something you really\n\n1642\n01:20:59,355 --> 01:21:01,355\nlike to see me do because you find a project wants to\n\n1643\n01:21:01,357 --> 01:21:06,794\ndo it. Like Cloud Kit was, let me know. Okay, that's it.\n\n1644\n01:21:06,796 --> 01:21:08,696\nSee you next time. >> For\n\n1645\n01:21:08,698 --> 01:21:08,729\nmore please visit us at stanford.edu.\n\n"
  },
  {
    "path": "subtitles/16. Notifications and CloudKit.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,702\n[MUSIC]\n\n2\n00:00:03,704 --> 00:00:08,340\nStanford University. >> All right, well,\n\n3\n00:00:08,342 --> 00:00:12,711\nwelcome to C, Stanford CS193P spring of 2016\n\n4\n00:00:12,713 --> 00:00:15,881\nlecture number 16. And today it's all demo.\n\n5\n00:00:15,883 --> 00:00:18,817\nI'm gonna do a big demo on CloudKit to show you how,\n\n6\n00:00:18,819 --> 00:00:21,286\nhow that works. I'm also gonna take a brief little\n\n7\n00:00:21,288 --> 00:00:24,023\nthing at the beginning to show you about notifications, that\n\n8\n00:00:24,025 --> 00:00:27,092\nlittle radio station thing. We talked about how you can find\n\n9\n00:00:27,094 --> 00:00:28,427\nout about size changes happening and\n\n10\n00:00:28,429 --> 00:00:31,630\nI'm gonna show you how that works. And that's pretty much\n\n11\n00:00:31,632 --> 00:00:34,366\nit for today. It's kinda all demo today.\n\n12\n00:00:34,368 --> 00:00:37,870\nComing up Friday we're not doing sections anymore.\n\n13\n00:00:37,872 --> 00:00:40,606\nPeople weren't that interested in sections this quarter,\n\n14\n00:00:40,608 --> 00:00:42,074\nthat's fine. And then next week,\n\n15\n00:00:42,076 --> 00:00:44,977\nI'm gonna be covering maps some more segues, and\n\n16\n00:00:44,979 --> 00:00:48,680\nthen just some miscellaneous topics, not quite sure yet\n\n17\n00:00:48,682 --> 00:00:52,317\nwhat I'm gonna do there. All right, so,\n\n18\n00:00:52,319 --> 00:00:57,356\nlet's dive right into this demo. Going to launch Xcode\n\n19\n00:00:57,358 --> 00:01:02,127\nhere. We're going to make a new project.\n\n20\n00:01:02,129 --> 00:01:04,630\nIt's gonna be our standard stuff here. So\n\n21\n00:01:04,632 --> 00:01:08,667\nwhat I'm gonna do is an app that is a question asking app.\n\n22\n00:01:08,669 --> 00:01:12,604\nSo it lets you author questions with answers, and\n\n23\n00:01:12,606 --> 00:01:14,807\nthen they're out on the cloud, in iCloud,\n\n24\n00:01:14,809 --> 00:01:16,108\nand people can answer the questions,\n\n25\n00:01:16,110 --> 00:01:18,243\nokay, and then it keeps track of how many answers people had\n\n26\n00:01:18,245 --> 00:01:20,946\nand all that stuff. So today we're just gonna kinda do\n\n27\n00:01:20,948 --> 00:01:23,082\nthe start of it, which is, we'll have some UI to make\n\n28\n00:01:23,084 --> 00:01:25,584\nthe question and we'll upload the questions to the cloud,\n\n29\n00:01:25,586 --> 00:01:28,020\nand then we'll have another view controller which shows\n\n30\n00:01:28,022 --> 00:01:30,122\na list of all the questions that you can choose on.\n\n31\n00:01:30,124 --> 00:01:33,325\nAnd you can click, some UI to make a new question or\n\n32\n00:01:33,327 --> 00:01:35,961\ndelete old questions. So we're gonna be able to do all\n\n33\n00:01:35,963 --> 00:01:37,262\nkinds of iCloud stuff there. Deleting,\n\n34\n00:01:37,264 --> 00:01:39,998\nwe're gonna do subscriptions with push notifications,\n\n35\n00:01:40,000 --> 00:01:45,070\nall that stuff. Okay, so we're gonna call this app Pollster.\n\n36\n00:01:45,072 --> 00:01:48,640\nI'm also gonna change my unique thing here just to be\n\n37\n00:01:48,642 --> 00:01:52,945\nsomething different, how about teacher instead of instructor.\n\n38\n00:01:52,947 --> 00:01:55,147\nSo Pollster, because you could use it to poll,\n\n39\n00:01:55,149 --> 00:01:57,783\nask people questions, and get polls. No Core Data,\n\n40\n00:01:57,785 --> 00:02:00,819\nit's gonna be an iPhone-only application. We're just gonna\n\n41\n00:02:00,821 --> 00:02:04,189\nhave a couple table views is all. And we'll put it in our\n\n42\n00:02:04,191 --> 00:02:09,128\nstandard location here. So here we are in Pollster, and\n\n43\n00:02:09,130 --> 00:02:14,433\nI'm going to kind of clear out my storyboard to start. So\n\n44\n00:02:14,435 --> 00:02:18,637\nlet's take this little view controller that it\n\n45\n00:02:18,639 --> 00:02:22,941\ncomes with, let's delete its code right here.\n\n46\n00:02:22,943 --> 00:02:26,445\nSo I'll do Delete. Move that to the trash.\n\n47\n00:02:26,447 --> 00:02:29,948\nLet's go ahead and put these little guys into a little\n\n48\n00:02:29,950 --> 00:02:33,852\nsupporting files thing again, Supporting Files. And notice\n\n49\n00:02:33,854 --> 00:02:36,054\nI'm gonna leave AppDelegate out of the Supporting Files,\n\n50\n00:02:36,056 --> 00:02:38,190\nbecause of course, we're gonna do push notifications.\n\n51\n00:02:38,192 --> 00:02:40,893\nThat involves our AppDelegate, so it's not really\n\n52\n00:02:40,895 --> 00:02:43,862\na supporting file, it's kind of a main thing this time.\n\n53\n00:02:43,864 --> 00:02:47,833\nAnd back in the storyboard we can just get rid of this view\n\n54\n00:02:47,835 --> 00:02:51,069\ncontroller, we don't need it at all, okay.\n\n55\n00:02:51,071 --> 00:02:52,905\nNow, I also have some other files\n\n56\n00:02:52,907 --> 00:02:55,307\nhere that are gonna be supporting files for\n\n57\n00:02:55,309 --> 00:02:58,410\nthis demo, so I'm gonna drag those in right here.\n\n58\n00:02:58,412 --> 00:03:00,979\nIn fact, I'm gonna put them in Supporting Files.\n\n59\n00:03:00,981 --> 00:03:05,317\nCopy them in, let's take a quick look at those.\n\n60\n00:03:05,319 --> 00:03:08,687\nAll right, so one is, I just wanted all my structs, with,\n\n61\n00:03:08,689 --> 00:03:11,456\nyou know, my constants in there to be pre-typed in so\n\n62\n00:03:11,458 --> 00:03:14,593\nI don't have to type them in all the time. And basically,\n\n63\n00:03:14,595 --> 00:03:18,397\nthese constants are gonna be for the push or actually for\n\n64\n00:03:18,399 --> 00:03:21,300\nthe local notification, the radio station stuff,\n\n65\n00:03:21,302 --> 00:03:24,436\nthis is gonna be the name of our radio station and\n\n66\n00:03:24,438 --> 00:03:25,537\nthe key in the dictionary.\n\n67\n00:03:25,539 --> 00:03:27,406\nAnd then these are the names of the entities and\n\n68\n00:03:27,408 --> 00:03:29,675\nattributes that I'm gonna create in CloudKit, okay?\n\n69\n00:03:29,677 --> 00:03:32,311\nSo we're doing QandA, here are questions and answers, and\n\n70\n00:03:32,313 --> 00:03:35,547\nhere's a Response to a QandA, and then we've got questions,\n\n71\n00:03:35,549 --> 00:03:36,982\nanswers, we got a chosenAnswer, and\n\n72\n00:03:36,984 --> 00:03:40,886\nthen we've got a reference qanda. So we got all that.\n\n73\n00:03:40,888 --> 00:03:43,388\nAnd then I added this little wasCreatedByThisUser.\n\n74\n00:03:43,390 --> 00:03:46,225\nIt's a bool on a CKRecord, a CloudKit record, that just\n\n75\n00:03:46,227 --> 00:03:49,027\nsays whether this record was created by the currently\n\n76\n00:03:49,029 --> 00:03:52,097\nlogged in iCloud user, okay. So that's that.\n\n77\n00:03:52,099 --> 00:03:55,300\nThen, over here, I have this nice class here,\n\n78\n00:03:55,302 --> 00:03:57,236\nQandATableViewController.\n\n79\n00:03:57,238 --> 00:04:00,205\nIt is, has nothing to do with iCloud. It's just a table view\n\n80\n00:04:00,207 --> 00:04:03,775\ncontroller that shows a question, okay, a question and\n\n81\n00:04:03,777 --> 00:04:06,778\nas many answers as you want. Okay, notice that it inherits\n\n82\n00:04:06,780 --> 00:04:09,281\nfrom TextTableViewController. That's a generic\n\n83\n00:04:09,283 --> 00:04:12,284\nview controller that just shows a table view where all\n\n84\n00:04:12,286 --> 00:04:14,753\nthe rows are editable text. Okay, that's all that is.\n\n85\n00:04:14,755 --> 00:04:17,055\nIt doesn't know anything about questions and answers,\n\n86\n00:04:17,057 --> 00:04:17,856\nit's just rows of editable text,\n\n87\n00:04:17,858 --> 00:04:21,226\nnothing more. We're not even gonna be accessing this API,\n\n88\n00:04:21,228 --> 00:04:24,129\nwe're gonna be focusing totally at this MVC's level.\n\n89\n00:04:24,131 --> 00:04:27,432\nAnd here's the public API for that, super simple. Okay,\n\n90\n00:04:27,434 --> 00:04:30,736\nit's got this var qanda, which is basically its model,\n\n91\n00:04:30,738 --> 00:04:33,305\nwhich is of type QandA, that's this struct, and\n\n92\n00:04:33,307 --> 00:04:35,874\nit's a question, which is a String, and answers,\n\n93\n00:04:35,876 --> 00:04:39,011\nwhich are Strings. Okay, so it couldn't be any simpler,\n\n94\n00:04:39,013 --> 00:04:41,313\nit's the simplest possible data structure for\n\n95\n00:04:41,315 --> 00:04:43,982\na Q&A. It's got, these other vars here is just whether\n\n96\n00:04:43,984 --> 00:04:46,685\nyou're asking the question or answering the question.\n\n97\n00:04:46,687 --> 00:04:47,886\nThat's cuz if you're asking the question,\n\n98\n00:04:47,888 --> 00:04:50,289\nyou can edit the question, right? You're asking it, so\n\n99\n00:04:50,291 --> 00:04:52,291\nyou can add more answers and stuff like that.\n\n100\n00:04:52,293 --> 00:04:53,525\nWhereas, if you're answering the question,\n\n101\n00:04:53,527 --> 00:04:55,627\nyou can only choose an answer, okay? And\n\n102\n00:04:55,629 --> 00:04:57,829\nthen if you do choose an answer, here's the answer.\n\n103\n00:04:57,831 --> 00:05:01,700\nSo you can just get the answer as a string, okay? It might be\n\n104\n00:05:01,702 --> 00:05:03,568\na nil, because maybe they haven't answered yet.\n\n105\n00:05:03,570 --> 00:05:06,405\nSo that's it, that's the entire public API of this, and\n\n106\n00:05:06,407 --> 00:05:09,007\nthis is the only API we're gonna use in our cloud one.\n\n107\n00:05:09,009 --> 00:05:12,210\nAnd our cloud one is just gonna be a subclass of this,\n\n108\n00:05:12,212 --> 00:05:13,979\nbecause it's gonna be a QandA, but\n\n109\n00:05:13,981 --> 00:05:16,548\nit's a QandA that's stored in the cloud, okay.\n\n110\n00:05:16,550 --> 00:05:19,851\nSo let's go ahead and create that subclass of this guy, so\n\n111\n00:05:19,853 --> 00:05:23,255\nI'm just gonna do File > New, okay, > Cocoa Touch Class.\n\n112\n00:05:23,257 --> 00:05:28,827\nIt's gonna be a subclass of our QandATableViewController,\n\n113\n00:05:28,829 --> 00:05:33,398\nokay. And we're gonna call it CloudQand, whoops,\n\n114\n00:05:34,601 --> 00:05:36,068\nQandATableViewController, okay?\n\n115\n00:05:36,070 --> 00:05:39,004\nCuz it's basically just a QandATableViewController that\n\n116\n00:05:39,006 --> 00:05:42,040\nstores its question and answer on the cloud. All right, so\n\n117\n00:05:42,042 --> 00:05:45,644\nhere it is. Let's go ahead and blast all this, just so\n\n118\n00:05:45,646 --> 00:05:49,147\nyou can clearly see what new stuff we're adding here. So\n\n119\n00:05:49,149 --> 00:05:52,351\nthere's our super class being a QandATableViewController.\n\n120\n00:05:52,353 --> 00:05:54,753\nLet's, of course, go to our storyboard and\n\n121\n00:05:54,755 --> 00:05:56,722\ndrag out a Table View Controller, okay.\n\n122\n00:05:56,724 --> 00:05:59,958\nAnd we're gonna set its identity to be one of these\n\n123\n00:05:59,960 --> 00:06:02,160\nCloudQandATableViewControll- ers.\n\n124\n00:06:02,162 --> 00:06:05,197\nWhat's interesting about the QandATableViewController is,\n\n125\n00:06:05,199 --> 00:06:07,566\nyou don't need any prototype cells at all.\n\n126\n00:06:07,568 --> 00:06:09,601\nIt creates its prototype cells in code.\n\n127\n00:06:09,603 --> 00:06:11,503\nAnd so, if you're interested in how to do that for your\n\n128\n00:06:11,505 --> 00:06:13,705\nfinal project or whatever, you could take a look at that\n\n129\n00:06:13,707 --> 00:06:15,207\nQandATableViewController, actually,\n\n130\n00:06:15,209 --> 00:06:17,142\nyou would wanna look at the TextTableViewController,\n\n131\n00:06:17,144 --> 00:06:20,712\nthe superclass one for how you might have a table view that\n\n132\n00:06:20,714 --> 00:06:23,348\ncreates its cells that way instead of using prototypes.\n\n133\n00:06:23,350 --> 00:06:24,983\nAnd you can see why it don't use prototypes,\n\n134\n00:06:24,985 --> 00:06:26,518\nbecause it's such a simple cell,\n\n135\n00:06:26,520 --> 00:06:28,120\nits just has a text view in there, that's it.\n\n136\n00:06:28,122 --> 00:06:30,555\nThe entire cell is just a text view, nothing more.\n\n137\n00:06:30,557 --> 00:06:32,290\nSo it didn't really need a prototype to do that,\n\n138\n00:06:32,292 --> 00:06:33,558\nand it makes it easier for subclasser too,\n\n139\n00:06:33,560 --> 00:06:37,028\nthey don't have to worry about that. All right, so\n\n140\n00:06:37,030 --> 00:06:37,295\nwe've got our thing here.\n\n141\n00:06:37,297 --> 00:06:40,365\nLet's also make sure that it's the Initial View Controller,\n\n142\n00:06:40,367 --> 00:06:43,402\nright here, where we have the arrow coming in. And in fact,\n\n143\n00:06:43,404 --> 00:06:48,140\nI'm gonna put this thing into a Navigation Controller, okay?\n\n144\n00:06:48,142 --> 00:06:52,077\nThat way I can have titles on things and stuff like that.\n\n145\n00:06:52,079 --> 00:06:54,246\nOkay, so this is our UI to start. And\n\n146\n00:06:54,248 --> 00:06:57,716\nwe're gonna start by just having a question up here in\n\n147\n00:06:57,718 --> 00:07:01,720\nthis cloud TableViewController right here. So I'm gonna go to\n\n148\n00:07:01,722 --> 00:07:04,322\nthe cloud TableViewController. Where did I put that?\n\n149\n00:07:04,324 --> 00:07:06,391\nRight here. I'm gonna take that out of Supporting Files,\n\n150\n00:07:06,393 --> 00:07:09,661\nactually. So I'm gonna go to the cloud TableViewController,\n\n151\n00:07:09,663 --> 00:07:11,129\nand I'm just gonna, in its viewDidLoad,\n\n152\n00:07:11,131 --> 00:07:12,931\nI'm just gonna give it a question. Okay, so,\n\n153\n00:07:12,933 --> 00:07:15,467\nsuper.viewDidLoad, just so you can see how this thing works.\n\n154\n00:07:15,469 --> 00:07:20,839\nSo qanda = a QandA, and here's the constructor for it.\n\n155\n00:07:20,841 --> 00:07:21,239\nIt takes a question, you know,\n\n156\n00:07:21,241 --> 00:07:26,144\n\"What is your favorite color?\" or something like that. And\n\n157\n00:07:26,146 --> 00:07:29,915\nthe answer is [\"Blue\", \"Black\", \"Red\"],\n\n158\n00:07:29,917 --> 00:07:34,753\nokay, or however many we want, okay? So let's just run and\n\n159\n00:07:34,755 --> 00:07:37,689\nsee what that looks like. We'll go ahead and run I think\n\n160\n00:07:37,691 --> 00:07:42,027\nwe'll run this on the device, actually. Let's try that.\n\n161\n00:07:50,804 --> 00:07:54,873\nOkay, so this is an iPad, but it's running here in iPhone\n\n162\n00:07:54,875 --> 00:07:58,043\nCompatibility mode, I'm still sharing an iPad.\n\n163\n00:07:58,045 --> 00:07:59,644\nSo here you go, what is your favorite color?\n\n164\n00:07:59,646 --> 00:08:01,179\nIt shows to you, you can scroll up and\n\n165\n00:08:01,181 --> 00:08:03,348\ndown and you can choose an answer, okay? Now,\n\n166\n00:08:03,350 --> 00:08:06,318\nthat's because we're in answering mode, okay? But\n\n167\n00:08:06,320 --> 00:08:11,590\nif we go back to our code over here and say asking = oops,\n\n168\n00:08:11,592 --> 00:08:14,559\nasking = true, okay, and then run,\n\n169\n00:08:14,561 --> 00:08:18,263\nyou'll get very similar UI. The only difference being,\n\n170\n00:08:18,265 --> 00:08:20,966\nwe can edit it. We can add more answers and\n\n171\n00:08:20,968 --> 00:08:22,667\nmove our answers around. Okay, so here we go.\n\n172\n00:08:22,669 --> 00:08:26,371\nNotice that we can reposition them, okay, so if we want one\n\n173\n00:08:26,373 --> 00:08:29,307\nanswer to be after another, we could add another answer here,\n\n174\n00:08:29,309 --> 00:08:34,145\nmaybe white. Okay, something like that. We can delete\n\n175\n00:08:34,147 --> 00:08:38,416\nan answer just by backspacing out of it. Gets rid of it.\n\n176\n00:08:38,418 --> 00:08:41,653\nOkay, we can change the question too if wanted. Okay,\n\n177\n00:08:41,655 --> 00:08:43,955\nso everyone understand what this QandATableViewController\n\n178\n00:08:43,957 --> 00:08:46,525\nwe just inherited from does? That it. That's all it does.\n\n179\n00:08:46,527 --> 00:08:48,226\nOkay, now, it knows nothing about the cloud.\n\n180\n00:08:48,228 --> 00:08:51,530\nAnd what we're gonna make this Q&A thing here be\n\n181\n00:08:51,532 --> 00:08:53,298\nstored on the cloud. All right, so\n\n182\n00:08:53,300 --> 00:08:56,268\nnow we're back in the CloudQandATableViewController.\n\n183\n00:08:56,270 --> 00:08:59,304\nAnd we want to make this thing work with the cloud. So\n\n184\n00:08:59,306 --> 00:09:02,807\nit's gonna have a different model than its superclass.\n\n185\n00:09:02,809 --> 00:09:06,578\nIts superclass's model is a question and answer, which is\n\n186\n00:09:06,580 --> 00:09:11,016\ngood, but our model here is going to be a CKRecord, okay,\n\n187\n00:09:11,018 --> 00:09:11,917\na CloudKit record.\n\n188\n00:09:11,919 --> 00:09:15,053\nSo I'm gonna call this thing CKQandA,\n\n189\n00:09:15,055 --> 00:09:18,957\nokay, called that because it's CloudKit Q&A.\n\n190\n00:09:18,959 --> 00:09:22,327\nActually, maybe we can even call it CloudKitQandARecord so\n\n191\n00:09:22,329 --> 00:09:26,097\nwe're clear that it's a record in CloudKit. And\n\n192\n00:09:26,099 --> 00:09:29,234\nit's gonna be a CKRecord, is all. And of course,\n\n193\n00:09:29,236 --> 00:09:32,470\nif anyone sets it, just like with almost all of our MVC's,\n\n194\n00:09:32,472 --> 00:09:34,372\nwhen someone sets our model to something,\n\n195\n00:09:34,374 --> 00:09:36,942\nif it's public and we allow people to set it, when we\n\n196\n00:09:36,944 --> 00:09:39,644\nset it, we want to react to that. And what we want to do\n\n197\n00:09:39,646 --> 00:09:42,047\nwhen someone sets our record is call our superclass,\n\n198\n00:09:42,049 --> 00:09:45,317\nset up our superclass's model, right, that QandA. We're gonna\n\n199\n00:09:45,319 --> 00:09:47,485\nget the question and answer out of the record and put,\n\n200\n00:09:47,487 --> 00:09:52,023\nset it up in our superclass. So we'll just let the question\n\n201\n00:09:52,025 --> 00:09:56,194\nequal the record's, and remember that we access\n\n202\n00:09:56,196 --> 00:10:00,465\nthe records just using dictionary-like notation.\n\n203\n00:10:00,467 --> 00:10:04,836\nSo I'm gonna use one of those constants that I had there,\n\n204\n00:10:04,838 --> 00:10:06,972\nAttribute.Question. Okay?\n\n205\n00:10:06,974 --> 00:10:10,342\nThat's over here, remember, in the CloudKit extensions.\n\n206\n00:10:10,344 --> 00:10:15,180\nSo Cloud.Attribute.Question is this key, so that's gonna\n\n207\n00:10:15,182 --> 00:10:19,084\nbe a key into my QandA entity right here. Okay, and notice\n\n208\n00:10:19,086 --> 00:10:21,720\nhow I'm not going and creating this scheme anywhere first,\n\n209\n00:10:21,722 --> 00:10:24,222\nI'm just writing my code on the fly, and it's just gonna\n\n210\n00:10:24,224 --> 00:10:26,558\nautomatically create these things in the database for\n\n211\n00:10:26,560 --> 00:10:30,161\nme as I go. Now, we also know that this ckQandARecord,\n\n212\n00:10:30,163 --> 00:10:31,863\nwhen you use this dictionary notation,\n\n213\n00:10:31,865 --> 00:10:35,734\nit always returns this type that you have to cast, right.\n\n214\n00:10:35,736 --> 00:10:39,671\nIt returns a CKRecord type or something like that.\n\n215\n00:10:39,673 --> 00:10:41,906\nSo I'm gonna have to say as a String, cuz I know\n\n216\n00:10:41,908 --> 00:10:44,376\nthe question is a string. And by the way, if that's nil,\n\n217\n00:10:44,378 --> 00:10:48,313\nI'm just gonna use an empty string as my question, okay?\n\n218\n00:10:48,315 --> 00:10:50,248\nSo that way my question's never nil here.\n\n219\n00:10:50,250 --> 00:10:52,217\nAnd then it's similar with the answers,\n\n220\n00:10:52,219 --> 00:10:54,886\nthat's the QandARecord, using the attribute for\n\n221\n00:10:54,888 --> 00:10:57,455\nthe answers, except for, that's not a string,\n\n222\n00:10:57,457 --> 00:11:00,592\nit's an array of strings. And if that's nil, then we'll\n\n223\n00:11:00,594 --> 00:11:03,762\nuse an empty array. So now I've gotten my question and\n\n224\n00:11:03,764 --> 00:11:06,731\nmy answers out of this record that was given to me.\n\n225\n00:11:06,733 --> 00:11:10,402\nOkay, this is didSet on my public API right here. So now\n\n226\n00:11:10,404 --> 00:11:14,606\nI'm gonna have my superclass qanda equal a QandA, okay,\n\n227\n00:11:14,608 --> 00:11:18,576\nwhere the question is that question and the answers is\n\n228\n00:11:18,578 --> 00:11:24,049\nthat answers. Okay? Now, what about the asking,\n\n229\n00:11:24,051 --> 00:11:25,917\nokay, what about whether I'm asking or not?\n\n230\n00:11:25,919 --> 00:11:28,086\nOkay, this thing of whether it's gonna be editable or\n\n231\n00:11:28,088 --> 00:11:30,822\nnot. Well, that depends on whether this record they just\n\n232\n00:11:30,824 --> 00:11:33,491\ngave me was created by me. If it was created by me, them I'm\n\n233\n00:11:33,493 --> 00:11:35,326\nclearly editing it. It was created by someone else,\n\n234\n00:11:35,328 --> 00:11:39,731\nthen I'm just choosing it. So I'm just gonna say that that\n\n235\n00:11:39,733 --> 00:11:45,270\nis ckQandARecord.wasCreated, what did I call it,\n\n236\n00:11:45,272 --> 00:11:50,909\nwasCreatedByThisUser, okay? So I'm just using that thing\n\n237\n00:11:50,911 --> 00:11:55,313\nI showed you in that, that little extension over here,\n\n238\n00:11:55,315 --> 00:11:56,915\nokay? So we've got this record, now,\n\n239\n00:11:56,917 --> 00:12:00,885\na couple of problems here, okay? One thing is right here.\n\n240\n00:12:00,887 --> 00:12:05,590\nUse of undeclared type CKRecord. Why is that? import\n\n241\n00:12:05,592 --> 00:12:09,327\nCloudKit. Okay? CloudKit is a different framework.\n\n242\n00:12:09,329 --> 00:12:10,962\nIf you want to use it in any of your files,\n\n243\n00:12:10,964 --> 00:12:13,765\nyou have to import CloudKit, okay? Still have an error\n\n244\n00:12:13,767 --> 00:12:16,334\nhere. What's this? The old no initializers.\n\n245\n00:12:16,336 --> 00:12:20,105\nWhy? Because this is never initialized. Okay, well,\n\n246\n00:12:20,107 --> 00:12:22,974\nthis is kind of an interesting case, because I could just,\n\n247\n00:12:22,976 --> 00:12:25,610\nfor example, make this be an optional.\n\n248\n00:12:25,612 --> 00:12:29,380\nThen it would start out nil, that's great, but really,\n\n249\n00:12:29,382 --> 00:12:34,018\nI don't want any external person to be giving me\n\n250\n00:12:34,020 --> 00:12:36,721\nan empty record, you know, a nil record. So,\n\n251\n00:12:36,723 --> 00:12:38,890\nI'm gonna do something kind of interesting here that you can\n\n252\n00:12:38,892 --> 00:12:42,927\ndo when you want your public API to be non-optional but\n\n253\n00:12:42,929 --> 00:12:44,596\nyou still going to allow,\n\n254\n00:12:44,598 --> 00:12:48,166\ninternally, the thing to be optional or nil.\n\n255\n00:12:48,168 --> 00:12:50,435\nOkay, what I'm gonna do is, I'm gonna leave this public\n\n256\n00:12:50,437 --> 00:12:54,105\none to be optional, non-optional, rather. And\n\n257\n00:12:54,107 --> 00:12:59,911\nI'm gonna turn it into a get and set, okay, a computed one.\n\n258\n00:12:59,913 --> 00:13:04,315\nWhere it's going to be implementing its get and\n\n259\n00:13:04,317 --> 00:13:09,387\nset by using a private var _ckQandARecord, and this\n\n260\n00:13:09,389 --> 00:13:13,057\none's going to be optional. Okay, it's gonna do all\n\n261\n00:13:13,059 --> 00:13:15,627\nthe same things that it did, it's just gonna be optional.\n\n262\n00:13:15,629 --> 00:13:18,396\nAnd in the get and set here, the set here is just going to\n\n263\n00:13:18,398 --> 00:13:23,968\nset the ckQandARecord private one to be the new value.\n\n264\n00:13:23,970 --> 00:13:25,270\nOkay, this is always gonna be non-optional,\n\n265\n00:13:25,272 --> 00:13:27,806\nthat's going to be great, that's gonna set it there. And\n\n266\n00:13:27,808 --> 00:13:31,342\nhere, if someone tries to get the ckQandARecord,\n\n267\n00:13:31,344 --> 00:13:36,214\nokay I'm gonna check to see if my private one is nil.\n\n268\n00:13:36,216 --> 00:13:40,185\nAnd if it is, I'm gonna set my private one to just be a blank\n\n269\n00:13:40,187 --> 00:13:46,558\none. Okay, and here I'm gonna use this Entity.QandA.\n\n270\n00:13:46,560 --> 00:13:47,659\nOkay, so I'm gonna create a blank one.\n\n271\n00:13:47,661 --> 00:13:50,862\nAnd then I can return _ckQandA unwrapped,\n\n272\n00:13:50,864 --> 00:13:53,298\ncuz I know I always at least create it.\n\n273\n00:13:53,300 --> 00:13:56,201\nSo this is kind of a little tricky thing here to make sure\n\n274\n00:13:56,203 --> 00:13:59,737\nthat it's always this way. And another good thing about this\n\n275\n00:13:59,739 --> 00:14:02,473\nis, sorry, you had a question? >> Could you use\n\n276\n00:14:02,475 --> 00:14:05,710\na lazy initializer here? >> Yeah, so the question is,\n\n277\n00:14:05,712 --> 00:14:07,045\ncan I use a lazy initializer here?\n\n278\n00:14:07,047 --> 00:14:09,414\nLike, could I have said ckQandARecord =\n\n279\n00:14:09,416 --> 00:14:12,050\nCKRecord whatever, or even a lazy one, I wouldn't even have\n\n280\n00:14:12,052 --> 00:14:15,453\nto be lazy. The reason I'm not doing that is the old problem\n\n281\n00:14:15,455 --> 00:14:16,554\nwhere didSet doesn't\n\n282\n00:14:16,556 --> 00:14:21,092\nget called with the initializer, right? And\n\n283\n00:14:21,094 --> 00:14:22,827\nI want didSet to always get called, and\n\n284\n00:14:22,829 --> 00:14:25,263\nthis is gonna cause didSet to always get called.\n\n285\n00:14:25,265 --> 00:14:28,233\nSo it's a little bit of a trick there. Okay?\n\n286\n00:14:28,235 --> 00:14:31,502\nAll right, so we've got this all set up for\n\n287\n00:14:31,504 --> 00:14:35,240\nour public API here. What do we want to do next?\n\n288\n00:14:35,242 --> 00:14:38,109\nWell, let's go ahead and change our viewDidLoad,\n\n289\n00:14:38,111 --> 00:14:40,245\ninstead of setting our superclass thing,\n\n290\n00:14:40,247 --> 00:14:42,780\nlet's just test and make sure we're working. So\n\n291\n00:14:42,782 --> 00:14:46,784\nI'm gonna set my ckQandARecord equal to an empty record,\n\n292\n00:14:46,786 --> 00:14:55,393\njust as a test here. Okay? So we're just gonna do that.\n\n293\n00:14:55,395 --> 00:15:00,231\nI just wanna see if this is working. So let's run.\n\n294\n00:15:00,233 --> 00:15:02,500\nAnd it should come up an empty question, but\n\n295\n00:15:02,502 --> 00:15:05,837\nit should be editable, because I created this CKRecord.\n\n296\n00:15:05,839 --> 00:15:08,640\nRight? So here it is. It's empty, empty question.\n\n297\n00:15:08,642 --> 00:15:12,277\nI could type here, you know, I could say something, you know,\n\n298\n00:15:12,279 --> 00:15:18,416\nlike, When, we'll just say When, okay. Answers, Today.\n\n299\n00:15:18,418 --> 00:15:22,654\nMaybe Never, okay.\n\n300\n00:15:22,656 --> 00:15:27,659\nAnd then Tomorrow. Okay, so I've created this question.\n\n301\n00:15:27,661 --> 00:15:29,994\nNow, as I edit all this stuff, of course,\n\n302\n00:15:29,996 --> 00:15:31,763\nnone of this is going on the cloud yet.\n\n303\n00:15:31,765 --> 00:15:34,565\nAnd in fact, none of it's even going into the CKRecord.\n\n304\n00:15:34,567 --> 00:15:37,535\nIt's all just being held in that Q and A, okay. So\n\n305\n00:15:37,537 --> 00:15:40,004\nthe next step we need to do is to have this thing\n\n306\n00:15:40,006 --> 00:15:43,374\nwrite to the cloud. Now, when to write to the cloud is\n\n307\n00:15:43,376 --> 00:15:46,344\nthe question here, okay? We could add a button,\n\n308\n00:15:46,346 --> 00:15:48,746\nmaybe a bar button item up there that says,\n\n309\n00:15:48,748 --> 00:15:51,416\nSave to Cloud, okay? Or just Save or something like that.\n\n310\n00:15:51,418 --> 00:15:54,986\nSo that, that would be one way of it. But I'm actually kind\n\n311\n00:15:54,988 --> 00:15:58,489\nof a fan of UIs that the user doesn't have to take extra\n\n312\n00:15:58,491 --> 00:16:01,960\nsteps unnecessarily. So wouldn't it be cool if we just\n\n313\n00:16:01,962 --> 00:16:05,697\nsaved this to the cloud every time someone finishes\n\n314\n00:16:05,699 --> 00:16:06,397\nediting one of these fields.\n\n315\n00:16:06,399 --> 00:16:09,133\nNow as soon as the keyboard goes away, any of these times,\n\n316\n00:16:09,135 --> 00:16:11,569\nboom, we'll just save whatever we got to the cloud.\n\n317\n00:16:11,571 --> 00:16:15,239\nNow we might also want another UI which is published,\n\n318\n00:16:15,241 --> 00:16:16,341\nso that it shows it to other users.\n\n319\n00:16:16,343 --> 00:16:19,243\nBut for now users can see things in progress, okay,\n\n320\n00:16:19,245 --> 00:16:21,212\njust because we're starting out our app.\n\n321\n00:16:21,214 --> 00:16:23,715\nSo that's what I'm gonna do, I'm gonna have it every time\n\n322\n00:16:23,717 --> 00:16:26,751\nthat this first responder gets taken away from a text field,\n\n323\n00:16:26,753 --> 00:16:28,319\nI'm gonna have it update the cloud.\n\n324\n00:16:28,321 --> 00:16:31,189\nSo how can we find out when a first responder's taken away\n\n325\n00:16:31,191 --> 00:16:33,691\nfrom the text view? We gonna use the text view's delegate,\n\n326\n00:16:33,693 --> 00:16:36,160\nit's almost identical to the text field delegate\n\n327\n00:16:36,162 --> 00:16:39,630\nthat we talked about before. And our super classes, okay,\n\n328\n00:16:39,632 --> 00:16:43,101\nthe QandATableViewController, right here.\n\n329\n00:16:43,103 --> 00:16:46,237\nIt's super class is the text TableViewController and\n\n330\n00:16:46,239 --> 00:16:50,108\nthe text TableViewController already and not surprisingly,\n\n331\n00:16:50,110 --> 00:16:54,012\nis a UITextViewDelegate. So it's already receiving\n\n332\n00:16:54,014 --> 00:16:56,848\nUITextViewDelegate message whenever any of its text\n\n333\n00:16:56,850 --> 00:16:59,717\nviews are edited. Okay, so that's great. So all we need\n\n334\n00:16:59,719 --> 00:17:02,553\nto do here is implement a UITextViewDelegate, so\n\n335\n00:17:02,555 --> 00:17:05,990\nI'm gonna implement the one which is DidEndEditing.\n\n336\n00:17:05,992 --> 00:17:08,593\nOkay, TextViewDidEndEditing. Whoops,\n\n337\n00:17:08,595 --> 00:17:13,431\nnot did change. DidEndEditing,\n\n338\n00:17:13,433 --> 00:17:18,603\nthis one. Okay, and let my super class. He might well be\n\n339\n00:17:18,605 --> 00:17:23,608\ndoing something there so, we'll let him do his thing.\n\n340\n00:17:23,610 --> 00:17:27,245\nAnd now what I'm going to do with just update the Cloud, so\n\n341\n00:17:27,247 --> 00:17:30,448\nI'm going to have some method iCloud update, okay?\n\n342\n00:17:30,450 --> 00:17:33,584\nAnd it's complaining here because I overrode this so\n\n343\n00:17:33,586 --> 00:17:38,056\nI need to say override. Okay, so this iCloud update is going\n\n344\n00:17:38,058 --> 00:17:40,958\nto take our Q&A, ship it up to the iCloud,\n\n345\n00:17:40,960 --> 00:17:44,495\nto the cloud kit database up there. So let's go ahead and\n\n346\n00:17:44,497 --> 00:17:50,635\ndo that. That's private func iCloud update.\n\n347\n00:17:50,637 --> 00:17:53,504\nOkay, so what do we need to do, to write this thing,\n\n348\n00:17:53,506 --> 00:17:55,406\nto the cloud? It's actually really simple.\n\n349\n00:17:55,408 --> 00:17:58,342\nThe first thing we're gonna do is get the stuff out of our\n\n350\n00:17:58,344 --> 00:18:02,246\nQnA into our record. Then we're gonna save our record,\n\n351\n00:18:02,248 --> 00:18:05,450\nokay? So let's do the first part of that first.\n\n352\n00:18:05,452 --> 00:18:10,555\nWhich is let's take our ckQandARecord, and set,\n\n353\n00:18:10,557 --> 00:18:13,191\nfor example, its Question, and\n\n354\n00:18:13,193 --> 00:18:18,596\nwe'll set this question equal to be the Q&A question.\n\n355\n00:18:18,598 --> 00:18:23,301\nSo we're just grabbing it out of our super\n\n356\n00:18:23,303 --> 00:18:28,639\nclasses thing and similarly here the Q&A for\n\n357\n00:18:28,641 --> 00:18:32,577\nthe answers equals qanda.answers.\n\n358\n00:18:32,579 --> 00:18:35,980\nOne thing, I'd probably don't wanna be polluting the cloud\n\n359\n00:18:35,982 --> 00:18:37,281\nwith empty question and answers.\n\n360\n00:18:37,283 --> 00:18:40,551\nSo I'm gonna put a little if around this just to say.\n\n361\n00:18:40,553 --> 00:18:44,856\nif my qanda, qanda.question,\n\n362\n00:18:44,858 --> 00:18:48,426\noops, question.isEmpty and\n\n363\n00:18:48,428 --> 00:18:54,932\nI'm also goinna make sure that my answers, Q and\n\n364\n00:18:54,934 --> 00:18:59,637\nA answers isn't empty either, okay?\n\n365\n00:18:59,639 --> 00:19:02,507\nSo, in other words, if I don't have an empty question or\n\n366\n00:19:02,509 --> 00:19:05,843\nanswer, then I'll go ahead and do this. Okay, so now that\n\n367\n00:19:05,845 --> 00:19:09,547\nI've updated this record. I need to save it to the cloud.\n\n368\n00:19:09,549 --> 00:19:11,682\nSo I'm gonna actually have a different function for that.\n\n369\n00:19:11,684 --> 00:19:14,285\nICloudSaveRecord I'm gonna call it.\n\n370\n00:19:14,287 --> 00:19:18,089\nI'm gonna pass my CKQandARecord along. Okay,\n\n371\n00:19:18,091 --> 00:19:21,526\nwe're gonna have this little function that's going to save\n\n372\n00:19:21,528 --> 00:19:27,198\nthings to the cloud. So, private func iCloudSaveRecord,\n\n373\n00:19:27,200 --> 00:19:32,370\ntakes a recordToSave, which is a CKRecord. Okay,\n\n374\n00:19:32,372 --> 00:19:35,907\nnow what's this guy gonna do? This one also surprisingly\n\n375\n00:19:35,909 --> 00:19:38,576\nstraightforward, as you saw from the slides. One thing\n\n376\n00:19:38,578 --> 00:19:41,279\nis any time we're gonna save something into the Cloud,\n\n377\n00:19:41,281 --> 00:19:42,947\nwe need a database to work with. So\n\n378\n00:19:42,949 --> 00:19:48,085\nI'm gonna say private let the database equal CKcontainer,\n\n379\n00:19:48,087 --> 00:19:52,423\nremember? Container, whoops, [LAUGH] CKcontainer,\n\n380\n00:19:52,425 --> 00:19:56,060\ndefaultContainer public. So we're gonna put this in\n\n381\n00:19:56,062 --> 00:19:58,129\nthe public cloud because I want everyone to\n\n382\n00:19:58,131 --> 00:19:59,697\nsee everyone else's questions, okay?\n\n383\n00:19:59,699 --> 00:20:02,133\nSo if I put it in the private database I'd only be able to\n\n384\n00:20:02,135 --> 00:20:04,702\nsee my own questions, so this way I can see everybody's,\n\n385\n00:20:04,704 --> 00:20:08,606\nokay? So we got that. So I'm gonna ask the database here,\n\n386\n00:20:08,608 --> 00:20:14,712\njust to save this record. Okay, the record to save. And\n\n387\n00:20:14,714 --> 00:20:17,515\nhere's the completion handler right here. And in this\n\n388\n00:20:17,517 --> 00:20:21,519\ncompletions handler, we have the saved record basically.\n\n389\n00:20:21,521 --> 00:20:25,723\nWhich should be the same thing or nil and the error, okay?\n\n390\n00:20:25,725 --> 00:20:28,526\nAnd this is asynchronous. Okay, this closure is gonna\n\n391\n00:20:28,528 --> 00:20:31,362\nbe called sometime later when this thing is saved.\n\n392\n00:20:31,364 --> 00:20:33,564\nNow, this is a demo so I don't have time for\n\n393\n00:20:33,566 --> 00:20:36,300\nus to go and analyze every realistic error that could\n\n394\n00:20:36,302 --> 00:20:38,669\nhappen every single time we do something with the cloud.\n\n395\n00:20:38,671 --> 00:20:40,838\nBut I'm gonna show you a few of them just so\n\n396\n00:20:40,840 --> 00:20:43,574\nyou kind of get an idea how to handle errors, what kind of\n\n397\n00:20:43,576 --> 00:20:46,210\nerrors will come along. So let's look at an interesting\n\n398\n00:20:46,212 --> 00:20:49,313\nerror that might happen when you're saving a record, okay.\n\n399\n00:20:49,315 --> 00:20:52,617\nSo this error code equals\n\n400\n00:20:52,619 --> 00:20:59,790\nCKErrorCode.ServerRecordChan- ged.\n\n401\n00:20:59,792 --> 00:21:03,060\nOkay, don't forget .rawValue at the end because we're\n\n402\n00:21:03,062 --> 00:21:06,163\nlooking at this as an right here.\n\n403\n00:21:06,165 --> 00:21:09,133\nSo what is this error? This error means we tried to save\n\n404\n00:21:09,135 --> 00:21:12,303\na record but that record had already been saved newer\n\n405\n00:21:12,305 --> 00:21:16,007\nby someone else, okay. So now I've got old data that I'm\n\n406\n00:21:16,009 --> 00:21:18,376\ntrying to write on top of somebody who wrote newer data.\n\n407\n00:21:18,378 --> 00:21:20,811\nMaybe it was one of my other devices. Maybe it's even me.\n\n408\n00:21:20,813 --> 00:21:24,115\nMaybe I'm writing so fast. I saved three of four records in\n\n409\n00:21:24,117 --> 00:21:25,883\na row, okay. They all got queued up and\n\n410\n00:21:25,885 --> 00:21:29,053\none of them got through the network faster than the other,\n\n411\n00:21:29,055 --> 00:21:32,490\ncould be. This kind of approach of writing things and\n\n412\n00:21:32,492 --> 00:21:34,892\njust checking when you write them to see\n\n413\n00:21:34,894 --> 00:21:37,194\nif it's newer is called optimistic locking.\n\n414\n00:21:37,196 --> 00:21:40,097\nOkay, it's basically you don't check first before you write,\n\n415\n00:21:40,099 --> 00:21:43,234\nyou just try to write and it's newer you fail. Okay?\n\n416\n00:21:43,236 --> 00:21:47,204\nSo save record which is this convenous method on database,\n\n417\n00:21:47,206 --> 00:21:50,775\nreally has no way to make it overwrite,\n\n418\n00:21:50,777 --> 00:21:52,209\nhave an older thing overwrite a newer thing.\n\n419\n00:21:52,211 --> 00:21:53,878\nIt's not even clear that's what I'd want here.\n\n420\n00:21:53,880 --> 00:21:57,048\nI probably do want the newer thing, to be what what gets\n\n421\n00:21:57,050 --> 00:22:01,786\nthrough. If I did wanna do do overwriting of newer things,\n\n422\n00:22:01,788 --> 00:22:02,353\nthen I can use that whole\n\n423\n00:22:02,355 --> 00:22:04,388\noperation-based thing I was telling you about in\n\n424\n00:22:04,390 --> 00:22:06,757\nthe slides. Much more complicated that this\n\n425\n00:22:06,759 --> 00:22:09,794\nconvenience method but it can be done. But anyway for server\n\n426\n00:22:09,796 --> 00:22:13,164\nrecord change happens there is really nothing we can do or\n\n427\n00:22:13,166 --> 00:22:16,600\nwe would want to do. So you know we can just ignore this,\n\n428\n00:22:16,602 --> 00:22:21,072\nokay. We just assume that the newer ones is what we wanted.\n\n429\n00:22:21,074 --> 00:22:22,707\nOkay, what are the kind of stuff going to happen for\n\n430\n00:22:22,709 --> 00:22:28,379\nwriting here? How about, let's say if our error is not Nil.\n\n431\n00:22:28,381 --> 00:22:28,579\nWell in other words,\n\n432\n00:22:28,581 --> 00:22:31,315\nwe got some other kinds of error. Let's check to see\n\n433\n00:22:31,317 --> 00:22:34,485\nif that error may be has a retry in there for us. Okay,\n\n434\n00:22:34,487 --> 00:22:37,988\nsomething we can go and retry what we' re doing. Okay? Now,\n\n435\n00:22:37,990 --> 00:22:41,892\nmaybe why does that happen? Net, network let, latencies,\n\n436\n00:22:41,894 --> 00:22:44,862\nsomething like that. Some network problem that might\n\n437\n00:22:44,864 --> 00:22:47,631\nrecover with a little bit of time, that kind of thing.\n\n438\n00:22:47,633 --> 00:22:51,469\nSo, how do we do this? So, I am just going to call another\n\n439\n00:22:51,471 --> 00:22:56,540\nfunction to handle this. I am gonna call it retry after\n\n440\n00:22:56,542 --> 00:23:00,444\nerror. It's goinna take the error whatever happened and\n\n441\n00:23:00,446 --> 00:23:03,414\nI am just going to give it a selector to call to retry.\n\n442\n00:23:03,416 --> 00:23:06,016\nOkay, and the selector here is going to be in this case since\n\n443\n00:23:06,018 --> 00:23:09,253\nwe are saving record. I'm gonna have iCloud update,\n\n444\n00:23:09,255 --> 00:23:14,024\nokay, this thing up here that updates, try to do this again.\n\n445\n00:23:14,026 --> 00:23:17,928\nOkay? Now let's go and put this t retry in there and\n\n446\n00:23:17,930 --> 00:23:20,765\nwe'll see what some of these errors that are.\n\n447\n00:23:20,767 --> 00:23:25,102\nSo this is a private func retryAfterError,\n\n448\n00:23:25,104 --> 00:23:27,671\ntakes an error, do an NSError.\n\n449\n00:23:27,673 --> 00:23:31,409\nAnd then it takes with selector. We'll have a nice\n\n450\n00:23:31,411 --> 00:23:35,379\nlocal name for that and this is a selector, okay.\n\n451\n00:23:35,381 --> 00:23:38,716\nSo we have errors here, so what is this error. It says,\n\n452\n00:23:38,718 --> 00:23:38,816\nselector refers to\n\n453\n00:23:38,818 --> 00:23:42,219\na method that does not expose to objective C. That's iCloud.\n\n454\n00:23:42,221 --> 00:23:45,723\nNow why is this iCloud update not exposed to objective C?\n\n455\n00:23:45,725 --> 00:23:47,758\nWell, it's because it's private, okay.\n\n456\n00:23:47,760 --> 00:23:50,394\nThis is a class that inherits from in it' s objects, so\n\n457\n00:23:50,396 --> 00:23:52,763\nthat's not the problem. The problem is that we have\n\n458\n00:23:52,765 --> 00:23:54,565\na private method here. So we can expose it\n\n459\n00:23:54,567 --> 00:23:57,668\neither by making it not private or just saying OBJC.\n\n460\n00:23:57,670 --> 00:24:01,672\nThat mean, hey, expose this to Objective-C run time. Okay?\n\n461\n00:24:01,674 --> 00:24:06,610\nMake sense? All right, here is now saying the call\n\n462\n00:24:06,612 --> 00:24:12,016\nto the method iCloud update requires explicit self, okay?\n\n463\n00:24:12,018 --> 00:24:15,019\nSo that it knows, in our self because we happen to be\n\n464\n00:24:15,021 --> 00:24:17,888\nin a closure right here, okay? All references to\n\n465\n00:24:17,890 --> 00:24:21,792\nthings in our selves Have to be explicit. Okay, so\n\n466\n00:24:21,794 --> 00:24:24,862\nthat's good. All right, now, retry after or how we gonna\n\n467\n00:24:24,864 --> 00:24:29,233\nretry after. Well, if we can't get that retry interval magic\n\n468\n00:24:29,235 --> 00:24:32,269\nout of the error structure then we cannot do it so\n\n469\n00:24:32,271 --> 00:24:33,103\nthat's the first thing we're gonna do.\n\n470\n00:24:33,105 --> 00:24:36,607\nWe're gonna say if we can let retry interval\n\n471\n00:24:37,276 --> 00:24:41,011\nequal the errors. User info, okay so\n\n472\n00:24:41,013 --> 00:24:44,582\nuser info is this dictionary that comes with an error that\n\n473\n00:24:44,584 --> 00:24:46,317\ngives you kind of interesting info.\n\n474\n00:24:46,319 --> 00:24:51,989\nAnd, the thing we want is ck error,\n\n475\n00:24:51,991 --> 00:24:55,359\nretry after key, okay? So\n\n476\n00:24:55,361 --> 00:25:00,664\nthat should be an ns time interval. So if we're able to\n\n477\n00:25:00,666 --> 00:25:05,135\nget that retry interval, then hey, let's go ahead and retry.\n\n478\n00:25:05,471 --> 00:25:09,340\nAnd how are we going to retry here? Well I'm just going to\n\n479\n00:25:09,342 --> 00:25:13,777\ndo an NSTimer, scheduled timer with time interval,\n\n480\n00:25:13,779 --> 00:25:18,282\nI want this one, let's go ahead and make this\n\n481\n00:25:19,819 --> 00:25:24,054\nhave different lines here so you can see little better what\n\n482\n00:25:24,056 --> 00:25:28,359\nwe're doing with the timer. Okay, so the time interval\n\n483\n00:25:28,361 --> 00:25:31,829\nhere is that retry interval that we got out of the error.\n\n484\n00:25:31,831 --> 00:25:34,532\nThe target is going to be our self.\n\n485\n00:25:34,534 --> 00:25:39,270\nThe selector is the selector we passed on Here, okay?\n\n486\n00:25:39,272 --> 00:25:42,606\nUser info, eh, we don't have any, we're just retrying, so\n\n487\n00:25:42,608 --> 00:25:48,779\nwe don't have any extra data, and it does not repeat. Okay,\n\n488\n00:25:48,781 --> 00:25:51,181\nnow the problem here we gotta be careful of,\n\n489\n00:25:51,183 --> 00:25:54,051\nwe're calling retry after error in this closure,\n\n490\n00:25:54,053 --> 00:25:57,922\nwhich is executing off the main thread. Okay, so\n\n491\n00:25:57,924 --> 00:26:00,958\nwe cannot do NSTimers on other threads. So\n\n492\n00:26:00,960 --> 00:26:08,399\nwe need to dispatc_async, to the main queue.\n\n493\n00:26:08,401 --> 00:26:13,103\nDispatc_Ge_mai_queue.\n\n494\n00:26:13,105 --> 00:26:18,042\nWe'll do this, like that. Okay,\n\n495\n00:26:18,044 --> 00:26:23,047\nyou got that? Cool, all right so\n\n496\n00:26:23,049 --> 00:26:27,184\nthat's just a couple of the errors that we can do.\n\n497\n00:26:27,186 --> 00:26:29,787\nIf it succeeds, we actually don't need to do anything.\n\n498\n00:26:29,789 --> 00:26:30,554\nIt saved it, we're happy,\n\n499\n00:26:30,556 --> 00:26:35,793\nwe can just move on, okay. All right, so let's try and\n\n500\n00:26:35,795 --> 00:26:37,027\nrun this, let's just see if it happens,\n\n501\n00:26:37,029 --> 00:26:40,030\nlet's see if it can save this thing to the database. So\n\n502\n00:26:40,032 --> 00:26:46,971\nI'm gonna run, all right, here we crashed,\n\n503\n00:26:46,973 --> 00:26:50,874\nnow why'd we crash? The first place I'm always gonna\n\n504\n00:26:50,876 --> 00:26:53,611\nlook is the console down here. So let's go take a look at\n\n505\n00:26:53,613 --> 00:26:57,948\nthe console and see if it has a reason that it crashed and\n\n506\n00:26:57,950 --> 00:26:59,249\nit does have a reason. And the reason is,\n\n507\n00:26:59,251 --> 00:27:02,853\nthis application is missing the required entitlement for\n\n508\n00:27:02,855 --> 00:27:03,253\niCloud services.\n\n509\n00:27:03,255 --> 00:27:05,356\nSo this is that thing I was telling you about.\n\n510\n00:27:05,358 --> 00:27:06,523\nWe have to go enable iCloud,\n\n511\n00:27:06,525 --> 00:27:09,627\nall right. Because iCloud is server technology. Gee,\n\n512\n00:27:09,629 --> 00:27:11,862\nthings are gonna have to be created on a server side for\n\n513\n00:27:11,864 --> 00:27:14,732\nthis app, etcetera. So they don't want to create that for\n\n514\n00:27:14,734 --> 00:27:16,967\nevery app, only for apps that are actually gonna use it.\n\n515\n00:27:16,969 --> 00:27:20,804\nSo how do we do that? We go up here, okay, to our inspector,\n\n516\n00:27:20,806 --> 00:27:23,040\ninspect our project settings here and\n\n517\n00:27:23,042 --> 00:27:24,642\nwe'll go to capabilities.\n\n518\n00:27:24,644 --> 00:27:27,578\nAnd we click iCloud here, okay? So you have to make sure\n\n519\n00:27:27,580 --> 00:27:30,748\nyou pick a team, okay, cuz it needs to know who you are so\n\n520\n00:27:30,750 --> 00:27:33,550\nwe can set up this iCloud stuff for you, okay?\n\n521\n00:27:33,552 --> 00:27:37,855\nYour, account, your developer account up there. So\n\n522\n00:27:37,857 --> 00:27:40,824\nhere we have iCloud enabled, we are going to pick cloud kit\n\n523\n00:27:40,826 --> 00:27:45,963\nas that's the service that we want, we can pick these other\n\n524\n00:27:45,965 --> 00:27:48,899\nones as well but we're going to focus on CloudKit today.\n\n525\n00:27:48,901 --> 00:27:52,169\nAnd we'll be looking at the dashboard in a little bit,\n\n526\n00:27:52,171 --> 00:27:55,005\nactually let's go take a look at our dashboard now.\n\n527\n00:27:55,007 --> 00:27:58,409\nOnce your at dashboard, of course you have to log in.\n\n528\n00:27:58,711 --> 00:28:00,611\nHere we are, nothing has been created yet and\n\n529\n00:28:00,613 --> 00:28:03,714\nthat's because we haven't done any iCloud where we have\n\n530\n00:28:03,716 --> 00:28:08,652\ntried to create any entities, okay? All right, so\n\n531\n00:28:08,654 --> 00:28:10,587\nnow that we've done that. Now let's go back and\n\n532\n00:28:10,589 --> 00:28:14,091\nrun, and do that. And actually create some entities. So let's\n\n533\n00:28:14,093 --> 00:28:19,063\nget our code back up here so you can see that. And run.\n\n534\n00:28:23,769 --> 00:28:28,105\nAll right. So here we go. Blank question and answer.\n\n535\n00:28:28,107 --> 00:28:35,813\nLet's go ahead a put a question answer here again,\n\n536\n00:28:35,815 --> 00:28:40,884\nlet's try how about what is your\n\n537\n00:28:40,886 --> 00:28:46,056\nfavorite team? Okay,\n\n538\n00:28:46,058 --> 00:28:52,396\nwe'll say, maybe the Sharks. Whoops. Sharks,\n\n539\n00:28:52,398 --> 00:28:59,903\nor maybe the Warriors, or maybe it's the Giants. Okay,\n\n540\n00:29:00,106 --> 00:29:02,473\nthere are a lot of teams to choose from in the Bay area.\n\n541\n00:29:02,475 --> 00:29:07,377\nAll right? So hopefully this is creating on the server\n\n542\n00:29:07,379 --> 00:29:12,116\nbecause remember every time we went to a new field,\n\n543\n00:29:12,118 --> 00:29:13,884\nit should be riding something up to the Cloud.\n\n544\n00:29:13,886 --> 00:29:18,722\nSo let's go back and take a look at our dashboard here, so\n\n545\n00:29:18,724 --> 00:29:23,460\nlet's reload, Here it is, look at that,\n\n546\n00:29:23,462 --> 00:29:26,363\nQandA entity got created with answers and questions.\n\n547\n00:29:26,365 --> 00:29:28,732\nSo that's great. So that's the entity side of it.\n\n548\n00:29:28,734 --> 00:29:30,400\nAnd we can actually look at the data,\n\n549\n00:29:30,402 --> 00:29:33,270\nnot just the entity, but the data that's been stored by\n\n550\n00:29:33,272 --> 00:29:34,872\ngoing down here to this Default Zone.\n\n551\n00:29:34,874 --> 00:29:36,840\nNow, we'll notice when we try to look in here for\n\n552\n00:29:36,842 --> 00:29:39,409\nthings, it says, records can't be shown because there's no\n\n553\n00:29:39,411 --> 00:29:42,446\nindex on the Record ID field. So you can't look at things\n\n554\n00:29:42,448 --> 00:29:46,517\nthat aren't indexed. And so let me show you where that is.\n\n555\n00:29:46,519 --> 00:29:49,486\nIf you go back here you see metadata indexes,\n\n556\n00:29:49,488 --> 00:29:52,856\nrecord ID not being indexed. Same thing created by.\n\n557\n00:29:52,858 --> 00:29:55,225\nIn fact I want both of those to be searchable.\n\n558\n00:29:55,227 --> 00:29:58,862\nI need created by so I know which Q&As were created by me,\n\n559\n00:29:58,864 --> 00:30:00,297\nand I want record ID so\n\n560\n00:30:00,299 --> 00:30:02,166\nI can go find all the ones out there. And\n\n561\n00:30:02,168 --> 00:30:04,635\nyou can actually see here I'm gonna go ahead and save this.\n\n562\n00:30:04,637 --> 00:30:06,703\nI'll show you something real quick here. So\n\n563\n00:30:06,705 --> 00:30:08,772\nI've changed this to have these indexes.\n\n564\n00:30:08,774 --> 00:30:11,275\nNow I can go to the default zone. It can find things and\n\n565\n00:30:11,277 --> 00:30:13,610\nsure enough. What is your favorite team? Sharks and\n\n566\n00:30:13,612 --> 00:30:19,016\nWarriors. I guess we didn't save the Giants one here. When\n\n567\n00:30:19,018 --> 00:30:21,919\nwe reload, we'll see that. One thing about the car I\n\n568\n00:30:21,921 --> 00:30:26,690\nwanted to show you the costs thing, which is down here.\n\n569\n00:30:26,692 --> 00:30:31,028\nIf you look at uhs where is that uhs\n\n570\n00:30:31,931 --> 00:30:34,865\nusage? If you look at usage right here it is going to show\n\n571\n00:30:34,867 --> 00:30:37,668\nyou how much you using how many active users you have,\n\n572\n00:30:37,670 --> 00:30:40,070\nhow many request per second, how much transfers you\n\n573\n00:30:40,072 --> 00:30:42,906\nare doing of large files. How much storage you're using. All\n\n574\n00:30:42,908 --> 00:30:46,210\nthat stuff. And these things if you go above these lines,\n\n575\n00:30:46,212 --> 00:30:48,478\nstart costing you money. See these red lines.\n\n576\n00:30:48,480 --> 00:30:52,416\nOkay, the limits? Usage? So, I'm way, way below everything.\n\n577\n00:30:52,418 --> 00:30:53,917\n[LAUGH] Obviously. But, you know.\n\n578\n00:30:53,919 --> 00:30:58,622\nSo, this is basically how you get charged for it, okay?\n\n579\n00:30:58,624 --> 00:31:03,193\nThat good? All right. So we've got our nice database is being\n\n580\n00:31:03,195 --> 00:31:06,129\nloaded up, it's excellent, okay? The next thing we're\n\n581\n00:31:06,131 --> 00:31:11,168\ngonna do in our UI here is we are going to have another\n\n582\n00:31:11,170 --> 00:31:15,038\nview controller that has a list of all the question,\n\n583\n00:31:15,040 --> 00:31:16,773\nthe Q&A's that are in the database, okay?\n\n584\n00:31:16,775 --> 00:31:20,277\nThat we can choose from, and take a look at the Q&A's Okay,\n\n585\n00:31:20,279 --> 00:31:23,513\nso it's just gonna be a simple table view with a list of\n\n586\n00:31:23,515 --> 00:31:26,316\nthe QNAs. All right, so how we gonna do that,\n\n587\n00:31:26,318 --> 00:31:29,820\nwe gonna have to create a new MVC. So lets go ahead and\n\n588\n00:31:29,822 --> 00:31:34,091\ndo that, go file, new, go touch, this one is just going\n\n589\n00:31:34,093 --> 00:31:36,860\nto be a regular UI table view controller,\n\n590\n00:31:36,862 --> 00:31:41,031\nam gonna call it my AllQandAsTableViewController,\n\n591\n00:31:41,033 --> 00:31:42,866\ncuz that's what it's gonna do.\n\n592\n00:31:42,868 --> 00:31:45,402\nIt's gonna be the table view controller, shows all my Q and\n\n593\n00:31:45,404 --> 00:31:49,139\nAs in it, okay? And we'll put it in the same place\n\n594\n00:31:49,141 --> 00:31:53,777\nas usual here. Here's all Q and As. Let's go ahead and\n\n595\n00:31:53,779 --> 00:32:02,953\nget rid of all of this stuff. Okay,\n\n596\n00:32:02,955 --> 00:32:06,990\nso as always, what's gonna be the model of our new MVC?\n\n597\n00:32:06,992 --> 00:32:10,661\nWell, it shows all Q and A's, so that's gonna be my model,\n\n598\n00:32:10,663 --> 00:32:13,897\nall the Q and A's. And that's just going to be an array of\n\n599\n00:32:13,899 --> 00:32:19,436\nCKRecord, okay. And of course, when that changes,\n\n600\n00:32:19,438 --> 00:32:22,339\nif someone changes that array of records, then I'm going to\n\n601\n00:32:22,341 --> 00:32:26,376\nhave the table view reload its data. Hopefully you're all\n\n602\n00:32:26,378 --> 00:32:30,047\nfamiliar with that after Smashtag experiences. Okay, so\n\n603\n00:32:30,049 --> 00:32:35,285\nit's as simple as that. So how do we get all these Q and A's?\n\n604\n00:32:35,287 --> 00:32:39,489\nImport CloudKit. How do we get them all? Well,\n\n605\n00:32:39,491 --> 00:32:43,327\nin my view, let's do it in viewWillAppear, okay,\n\n606\n00:32:43,329 --> 00:32:48,498\nwhen I know I'm gonna come on screen. I'm\n\n607\n00:32:48,500 --> 00:32:52,035\ngoing to call some method to fetchAllQandAs, okay, and\n\n608\n00:32:52,037 --> 00:32:56,440\nthat's gonna go out to CloudKit and find them all. So\n\n609\n00:32:56,442 --> 00:33:01,478\nthat's private method called fetchAllQAndAs.\n\n610\n00:33:01,480 --> 00:33:06,883\nOops. Okay, and how's this thing gonna work? Well,\n\n611\n00:33:06,885 --> 00:33:09,853\nthis is gonna turn out to be very, very simple. Of course,\n\n612\n00:33:09,855 --> 00:33:12,022\nwe need our database here, so let's get that.\n\n613\n00:33:12,024 --> 00:33:15,258\nCKContainer.defaultContainer, again, we're looking in\n\n614\n00:33:15,260 --> 00:33:18,662\nthe public database there. All right, we have a database. So\n\n615\n00:33:18,664 --> 00:33:22,332\nfetching all the QandAs really just requires doing a CKQuery.\n\n616\n00:33:22,334 --> 00:33:24,468\nYou remember that from the slide CKQuery?\n\n617\n00:33:24,470 --> 00:33:27,871\nSo for CKQuery, we need a predicate, okay?\n\n618\n00:33:27,873 --> 00:33:30,974\nAnd since I'm getting all of the QandA's,\n\n619\n00:33:30,976 --> 00:33:34,845\nevery single one, I'm not searching for anything,\n\n620\n00:33:34,847 --> 00:33:38,982\nI'm gonna use the predicate TRUEPREDICATE. Okay, this\n\n621\n00:33:38,984 --> 00:33:42,753\nis a special predicate that means, get them all. Okay,\n\n622\n00:33:42,755 --> 00:33:45,856\nremember, in Core Data, we have nil means get them all,\n\n623\n00:33:45,858 --> 00:33:48,191\nbut here, you can't have predicate be nil, so\n\n624\n00:33:48,193 --> 00:33:52,529\nTRUEPREDICATE. It means get them all. Okay? Next,\n\n625\n00:33:52,531 --> 00:33:58,268\nwe can just create the query itself. That's a CKQuery,\n\n626\n00:33:58,270 --> 00:34:03,673\nokay? And we'll get its initializer here. So it\n\n627\n00:34:03,675 --> 00:34:05,876\njust wants to know what kind of things are you querying.\n\n628\n00:34:05,878 --> 00:34:08,211\nIt's just like when you're doing NSFetchRequest in\n\n629\n00:34:08,213 --> 00:34:10,847\nCore Data. You can only query one kind of thing at a time,\n\n630\n00:34:10,849 --> 00:34:15,819\none entity at a time. So here we're gonna have Cloud.Entity,\n\n631\n00:34:15,821 --> 00:34:20,390\nEntity.QandA, cuz that's what we're searching for,\n\n632\n00:34:20,392 --> 00:34:22,759\nthese QandA entities, entities.\n\n633\n00:34:22,761 --> 00:34:25,162\nAnd here's the predicate we're gonna use. Now,\n\n634\n00:34:25,164 --> 00:34:28,065\none thing I forgot to show you in the slides, very important,\n\n635\n00:34:28,067 --> 00:34:30,934\nis sorting. Just like in NSFetchRequest, you can\n\n636\n00:34:30,936 --> 00:34:35,272\ndo this here as well. I can say query.sortDescriptors, and\n\n637\n00:34:35,274 --> 00:34:37,340\nI can specify how I want to sort\n\n638\n00:34:37,342 --> 00:34:40,677\nthis query that I'm doing. Okay? So I'll have a sort,\n\n639\n00:34:40,679 --> 00:34:42,813\nwe'll sort this by the name of the,\n\n640\n00:34:42,815 --> 00:34:44,614\nby the question name, okay. So\n\n641\n00:34:44,616 --> 00:34:49,719\nkey is Cloud.Attribute.Question, and\n\n642\n00:34:49,721 --> 00:34:54,524\nwe'll have it be ascending. Okay, and of course,\n\n643\n00:34:54,526 --> 00:34:57,260\nthis is an array just like it is with fetch request,\n\n644\n00:34:57,262 --> 00:34:59,963\nyou can search last name first, then by first name,\n\n645\n00:34:59,965 --> 00:35:04,067\net cetera. Okay, so that's it. We've created our carry,\n\n646\n00:35:04,069 --> 00:35:07,137\nquery, how we wanna sort it, what the predicate is.\n\n647\n00:35:07,139 --> 00:35:11,775\nNow we just ask the database to perform this query.\n\n648\n00:35:11,777 --> 00:35:16,012\nOkay? And the query is query. Now, this inZoneWithID,\n\n649\n00:35:16,014 --> 00:35:18,849\nI told you that there's these zones, that are like subareas\n\n650\n00:35:18,851 --> 00:35:21,618\nof databases. By dividing your database into zone,\n\n651\n00:35:21,620 --> 00:35:23,386\nyou can make your queries a lot more efficient.\n\n652\n00:35:23,388 --> 00:35:26,223\nYou can see why already, if I only am searching a small part\n\n653\n00:35:26,225 --> 00:35:29,159\nof my database, it makes it a lot faster to search.\n\n654\n00:35:29,161 --> 00:35:32,329\nHere we're not using zones, okay, so we're just\n\n655\n00:35:32,331 --> 00:35:35,565\nputting nil as our zone. But if you have a huge data set,\n\n656\n00:35:35,567 --> 00:35:39,569\nyou can look into the zones feature. Okay, so here's my\n\n657\n00:35:39,571 --> 00:35:42,772\nclosure, when the results come back sometime later.\n\n658\n00:35:42,774 --> 00:35:46,743\nThis is the array of records that it found with that query.\n\n659\n00:35:46,745 --> 00:35:50,680\nAnd here's the error if any that it found. Okay? Now,\n\n660\n00:35:50,682 --> 00:35:54,951\nwhat am I gonna do with these records that came back? Well,\n\n661\n00:35:54,953 --> 00:35:58,822\nif the records is not nil, in other words,\n\n662\n00:35:58,824 --> 00:36:03,426\nif it found any records, then I just need to set my\n\n663\n00:36:03,428 --> 00:36:07,631\nallQandAs equal to those records. All right?\n\n664\n00:36:07,633 --> 00:36:12,602\nBut be careful. This is not happening on the main queue.\n\n665\n00:36:12,604 --> 00:36:16,206\nSo, if we're gonna do this, which is gonna cause this,\n\n666\n00:36:16,208 --> 00:36:20,877\nreloadData to happen, means we have to dispatc_async onto\n\n667\n00:36:20,879 --> 00:36:25,782\nthe main queue. Okay?\n\n668\n00:36:25,784 --> 00:36:27,584\nSo don't forget that dispatching back to the main\n\n669\n00:36:27,586 --> 00:36:32,889\nqueue when you're gonna do UI stuff as a response. Okay? So\n\n670\n00:36:32,891 --> 00:36:34,591\nthat's it. Okay, super easy.\n\n671\n00:36:34,593 --> 00:36:38,528\nThe only thing we have left to do in this TableViewController\n\n672\n00:36:38,530 --> 00:36:40,697\nis our UITableViewDataSource. So\n\n673\n00:36:40,699 --> 00:36:45,769\nlet's mark UITableViewDataSource.\n\n674\n00:36:45,771 --> 00:36:48,205\nOkay, we don't have any sections in this table, okay,\n\n675\n00:36:48,207 --> 00:36:52,943\nit's just all just one big section. The number of rows,\n\n676\n00:36:52,945 --> 00:36:56,413\nokay, let's do the number of rows.\n\n677\n00:36:56,415 --> 00:37:00,116\nThat's just the number of things in our array,\n\n678\n00:37:00,118 --> 00:37:04,688\nAllQandAs.count. That's how many rows we have, obviously.\n\n679\n00:37:04,690 --> 00:37:07,157\nAnd then we also obviously need cellForRowAtIndexPath.\n\n680\n00:37:07,159 --> 00:37:11,561\ncellForRowAtIndexPath. So cellForRowAtIndexPath, which\n\n681\n00:37:11,563 --> 00:37:14,831\nwe have, well, here, let's make it a little wider here.\n\n682\n00:37:14,833 --> 00:37:15,799\nOkay, cellForRowAtIndexPath.\n\n683\n00:37:15,801 --> 00:37:22,038\nI'm gonna get the cell by using the tableViews.dequeue,\n\n684\n00:37:22,040 --> 00:37:26,276\nwhoops, view's dequeue with identifier.\n\n685\n00:37:26,278 --> 00:37:30,180\nSo what identifier should we use? Let's say a QandA Cell.\n\n686\n00:37:30,182 --> 00:37:35,318\nSo let's go back to our storyboard. And\n\n687\n00:37:35,320 --> 00:37:39,789\nhave the cells of this. First of all, let's put our table\n\n688\n00:37:39,791 --> 00:37:42,892\nview in here. How about that? So here's a table view.\n\n689\n00:37:42,894 --> 00:37:45,595\nThis is gonna be in between these two. All right.\n\n690\n00:37:45,597 --> 00:37:48,131\nThis one is going to be the root view controller, and we\n\n691\n00:37:48,133 --> 00:37:51,101\nare going to be segueing from this one to this one which\n\n692\n00:37:51,103 --> 00:37:54,170\nshows them. Let's make sure we set our identity of this to be\n\n693\n00:37:54,172 --> 00:37:58,642\nour new allQandAs table here. Here's our cells right here.\n\n694\n00:37:58,644 --> 00:38:01,378\nSo these cells, we're gonna have them be basic style,\n\n695\n00:38:01,380 --> 00:38:03,013\ncuz they just have the question.\n\n696\n00:38:03,015 --> 00:38:04,114\nWe're just gonna put the question, so\n\n697\n00:38:04,116 --> 00:38:04,714\nthey don't have any subtitle.\n\n698\n00:38:04,716 --> 00:38:07,083\nThey don't need any custom stuff. And\n\n699\n00:38:07,085 --> 00:38:12,122\nthe identifier is the QandA Cell. Okay,\n\n700\n00:38:12,124 --> 00:38:15,058\nhey, while were here, let's go ahead do the segues for this.\n\n701\n00:38:15,060 --> 00:38:17,861\nIt's really simple. We're gonna segue from these rows.\n\n702\n00:38:17,863 --> 00:38:19,863\nOkay, anytime someone clicks on these rows,\n\n703\n00:38:19,865 --> 00:38:22,098\nwe're gonna segue over to here and do a show segue.\n\n704\n00:38:22,100 --> 00:38:25,969\nAnd we also want to be able to create new questions as well,\n\n705\n00:38:25,971 --> 00:38:28,271\nright? We're gonna click on questions we got,\n\n706\n00:38:28,273 --> 00:38:29,205\nbut we want to create new ones.\n\n707\n00:38:29,207 --> 00:38:31,741\nSo I'm gonna do that with some UI in here.\n\n708\n00:38:31,743 --> 00:38:36,446\nI'm gonna create a Bar Button Item right here. And\n\n709\n00:38:36,448 --> 00:38:38,982\nI'll use the standard plus one, which is add, okay,\n\n710\n00:38:38,984 --> 00:38:41,017\ncuz we're gonna add something, this is plus.\n\n711\n00:38:41,019 --> 00:38:43,219\nAnd then we're just gonna Ctrl+drag from here and\n\n712\n00:38:43,221 --> 00:38:47,223\nmake that show. Okay, so this is gonna do a segue, if fact,\n\n713\n00:38:47,225 --> 00:38:48,124\nthey can do the same segue,\n\n714\n00:38:48,126 --> 00:38:50,126\ncuz they pretty much do the same thing.\n\n715\n00:38:50,128 --> 00:38:51,227\nThey show a Q and A, it's just,\n\n716\n00:38:51,229 --> 00:38:53,863\none of them shows whatever row is selected and\n\n717\n00:38:53,865 --> 00:38:55,432\nthe other one creates a new one. So\n\n718\n00:38:55,434 --> 00:38:58,468\nwe'll call this Show QandA. That's a good name for\n\n719\n00:38:58,470 --> 00:39:03,506\nthat. And we'll call this one also Show QandA. Now,\n\n720\n00:39:03,508 --> 00:39:05,475\nin our prepare for segue, we're gonna have to be,\n\n721\n00:39:05,477 --> 00:39:08,044\ndo a little bit different thing, in those two cases,\n\n722\n00:39:08,046 --> 00:39:11,481\nbut that's basically what we're doing. Okay? So\n\n723\n00:39:11,483 --> 00:39:16,586\nlet's go back to our code here. allQandAs.\n\n724\n00:39:16,588 --> 00:39:21,391\nSo here's our cell index path there. Let's\n\n725\n00:39:21,393 --> 00:39:26,629\njust have our cell's textLabel?.text equal what?\n\n726\n00:39:26,631 --> 00:39:30,233\nallQandAs sub indexPath.row.\n\n727\n00:39:30,235 --> 00:39:34,371\nThat's giving me the CKRecord. Now, out of that CKRecord,\n\n728\n00:39:34,373 --> 00:39:37,974\nI've gotta get the Cloud.Attribute.Question,\n\n729\n00:39:37,976 --> 00:39:40,543\ncuz that's what I'm gonna show,\n\n730\n00:39:40,545 --> 00:39:41,811\ninside that row. And of course,\n\n731\n00:39:41,813 --> 00:39:44,080\nwe know that comes back as a CKRecord value, so\n\n732\n00:39:44,082 --> 00:39:50,153\nI have to say, as a String. Okay? And then we will\n\n733\n00:39:50,155 --> 00:39:55,392\nreturn the cell. Okay? Also super simple.\n\n734\n00:39:55,394 --> 00:39:57,660\nAll right, make sense? And now let's prepare for segue.\n\n735\n00:39:57,662 --> 00:40:02,332\nSo that's mark our Navigation. Prepare for\n\n736\n00:40:02,334 --> 00:40:06,403\nsegue. This is also gonna be pretty straightforward. First,\n\n737\n00:40:06,405 --> 00:40:11,141\nwe're gonna see if the identifier is our\n\n738\n00:40:11,143 --> 00:40:15,845\nShow QandA. If it is, let's get that MVC.\n\n739\n00:40:15,847 --> 00:40:20,049\nSo we'll say, if we can let the cloud Q and, QandA,\n\n740\n00:40:20,051 --> 00:40:24,788\noops, CloudKit Q and A table view controller equal our\n\n741\n00:40:24,790 --> 00:40:28,224\nsegue's destinationViewController as\n\n742\n00:40:28,226 --> 00:40:31,060\na CloudQandATableViewController,\n\n743\n00:40:31,062 --> 00:40:34,898\nokay, so we're segueing into one of those, so\n\n744\n00:40:34,900 --> 00:40:39,235\nthat better be on the other end. If that's true,\n\n745\n00:40:39,237 --> 00:40:41,971\nthen we need the cell, if we're segueing from a row,\n\n746\n00:40:41,973 --> 00:40:45,475\nwe need the cell, so let's try that. So if we can let cell\n\n747\n00:40:45,477 --> 00:40:49,846\nequal the sender as a UITableViewCell, okay,\n\n748\n00:40:49,848 --> 00:40:52,549\nhopefully you guys are used to doing this, again, from your\n\n749\n00:40:52,551 --> 00:40:56,553\nhomework assignment. And then we can let the indexPath equal\n\n750\n00:40:56,555 --> 00:41:01,324\nthe tableView's method cell for, or sorry, index path,\n\n751\n00:41:01,326 --> 00:41:05,995\nPathForCell, this cell.\n\n752\n00:41:05,997 --> 00:41:09,232\nOkay, so here is kind of a one-liner that gets the index\n\n753\n00:41:09,234 --> 00:41:14,237\npath of the row that was chosen. And if that works,\n\n754\n00:41:14,239 --> 00:41:19,342\nthen we can just say that the CloudQandA, oops,\n\n755\n00:41:19,344 --> 00:41:22,178\nI guess I called it ckQandATVC,\n\n756\n00:41:22,180 --> 00:41:27,550\nwe'll set its public API, which is ckQandARecord,\n\n757\n00:41:27,552 --> 00:41:32,288\nokay, equal to allQandAs sub indexPath.row.\n\n758\n00:41:32,290 --> 00:41:36,259\nAll right? That's what's, that's the record that\n\n759\n00:41:36,261 --> 00:41:38,962\nwas chosen there, obviously. If we can't get the cell,\n\n760\n00:41:38,964 --> 00:41:42,031\nif we can't get the table view cell, that must be because we\n\n761\n00:41:42,033 --> 00:41:45,201\npressed the + button, right? Because the plus button's not\n\n762\n00:41:45,203 --> 00:41:47,170\na row in a table. So in that case,\n\n763\n00:41:47,172 --> 00:41:51,608\nI'm just going to set the ckQandARecord equal to a new\n\n764\n00:41:51,610 --> 00:41:56,646\nrecord, because that's what we want. Creating a new\n\n765\n00:41:56,648 --> 00:42:01,718\nthing here, so that's Cloud.Entity.QandA.\n\n766\n00:42:01,720 --> 00:42:05,989\nOkay, everyone understand that prepareForSegue?\n\n767\n00:42:05,991 --> 00:42:07,724\nOkay, so let's do that.\n\n768\n00:42:17,035 --> 00:42:18,701\nAll right, so here's it showing all the ones, and\n\n769\n00:42:18,703 --> 00:42:20,937\nlook, it's even showing, what is your favorite team,\n\n770\n00:42:20,939 --> 00:42:22,005\nthat we already had from before.\n\n771\n00:42:22,007 --> 00:42:26,109\nI'm gonna touch on that, and it's not showing it to us.\n\n772\n00:42:26,111 --> 00:42:31,247\nOkay. Why is it not showing it to us? When we click on this,\n\n773\n00:42:31,249 --> 00:42:33,483\nit shows a blank one. Why does it show a blank one?\n\n774\n00:42:33,485 --> 00:42:37,153\nBecause over here, in our CloudTableViewController,\n\n775\n00:42:37,155 --> 00:42:40,223\nlook what we do in our viewDidLoad.\n\n776\n00:42:40,225 --> 00:42:42,458\nNo! We always set the record to be nil.\n\n777\n00:42:42,460 --> 00:42:47,397\nSo, let's get rid of that. And allow the segue to actually\n\n778\n00:42:47,399 --> 00:42:51,901\nset it. That's a tricky little bug.\n\n779\n00:43:00,812 --> 00:43:02,378\nOkay, so now, when we click on this,\n\n780\n00:43:02,380 --> 00:43:08,084\nwe get to see the question out of the database. Okay? And\n\n781\n00:43:08,086 --> 00:43:14,691\nwe can hit + and create a new one,\n\n782\n00:43:14,693 --> 00:43:19,462\nmaybe like, what is your\n\n783\n00:43:19,464 --> 00:43:24,367\nfavorite Stanford class?\n\n784\n00:43:24,369 --> 00:43:29,572\nOkay, and we'll have some answers here,\n\n785\n00:43:29,574 --> 00:43:34,110\nhow about CS193p, or if not that,\n\n786\n00:43:34,112 --> 00:43:40,283\nhow about iOS development. Okay,\n\n787\n00:43:40,285 --> 00:43:47,223\nthat's a great class too. And how about the iPhone and\n\n788\n00:43:47,225 --> 00:43:52,228\niPad programming course.\n\n789\n00:43:52,230 --> 00:43:54,063\nYou can pick whatever Stanford class you'd like.\n\n790\n00:43:54,065 --> 00:43:59,302\nOkay? So that, when we go back now, it's gonna ask for all of\n\n791\n00:43:59,304 --> 00:44:02,805\nthose Q&As and it's gonna show that one as well. Okay? So\n\n792\n00:44:02,807 --> 00:44:05,842\nthat you can see, very little code we had to write here to\n\n793\n00:44:05,844 --> 00:44:09,779\nhave it so that we're creating these things and editing them.\n\n794\n00:44:09,781 --> 00:44:14,317\nWhat about deleting them? Okay? What if I said, eh,\n\n795\n00:44:14,319 --> 00:44:15,752\nI don't want this one anymore, I wanna delete it.\n\n796\n00:44:15,754 --> 00:44:18,788\nWhat would be really cool is if I could just swipe on this\n\n797\n00:44:18,790 --> 00:44:20,490\nto delete. You've seen that in table views, right?\n\n798\n00:44:20,492 --> 00:44:23,459\nWhere you can swipe to delete, okay? How do we do swipe,\n\n799\n00:44:23,461 --> 00:44:26,095\nswipe to delete? We have never covered that in class.\n\n800\n00:44:26,097 --> 00:44:27,463\nThis is a great opportunity to do that.\n\n801\n00:44:27,465 --> 00:44:28,798\nSo if you want to do swipe to delete,\n\n802\n00:44:28,800 --> 00:44:32,135\nyou have to implement two of your UITableViewDataSource\n\n803\n00:44:32,137 --> 00:44:35,371\nmethods. One is, you have to answer whether a row\n\n804\n00:44:35,373 --> 00:44:37,807\ncan be deleted or not. Okay? That one is called\n\n805\n00:44:37,809 --> 00:44:42,912\ncanEditRowAtIndexPath. Okay, canEditRowAtIndexPath.\n\n806\n00:44:42,914 --> 00:44:46,649\nNow, in our case, as long as we created this, then we can\n\n807\n00:44:46,651 --> 00:44:49,152\nallow it to delete it, but if we didn't create it, we can't.\n\n808\n00:44:49,154 --> 00:44:55,058\nSo here I'm gonna return all Q&As at the indexPath.row was\n\n809\n00:44:55,060 --> 00:44:58,828\ncreated by this user. So if it was created by this user,\n\n810\n00:44:58,830 --> 00:45:02,632\nthen I'll allow you to delete it. Okay? The other method you\n\n811\n00:45:02,634 --> 00:45:05,001\nneed is the thing that actually commits the delete,\n\n812\n00:45:05,003 --> 00:45:09,338\nthat does the delete. That's called commitEditingStyle.\n\n813\n00:45:09,340 --> 00:45:11,407\nOkay, commitEditingStyle right here,\n\n814\n00:45:11,409 --> 00:45:14,477\nTableView.commitEditingStyle. And so here,\n\n815\n00:45:14,479 --> 00:45:17,246\nthere's actually two editing styles that you can have.\n\n816\n00:45:17,248 --> 00:45:18,715\nOne is deleting and one is inserting.\n\n817\n00:45:18,717 --> 00:45:21,417\nWell, we do our inserting with that plus, so we don't need\n\n818\n00:45:21,419 --> 00:45:25,021\nthe inserting style there. We only want the deleting, so\n\n819\n00:45:25,023 --> 00:45:27,957\nI'm gonna say, if the editingStyle == .Delete.\n\n820\n00:45:27,959 --> 00:45:32,895\nOkay, so if the person wants to delete my row or whatever,\n\n821\n00:45:32,897 --> 00:45:36,532\nthen all I need to do is delete it from the table. But\n\n822\n00:45:36,534 --> 00:45:40,436\nI also wanna delete it from the database as well, right,\n\n823\n00:45:40,438 --> 00:45:44,107\nboth of those. So what's that look like? So let's say,\n\n824\n00:45:44,109 --> 00:45:47,376\nif we're deleting, then I'm gonna let the record to delete\n\n825\n00:45:47,378 --> 00:45:51,948\nequal, my allQandAs indexPath.row.\n\n826\n00:45:51,950 --> 00:45:56,686\nOkay. Then I'm gonna save the database. Please delete this\n\n827\n00:45:56,688 --> 00:46:02,191\nrecord with an ID, and the ID is the record's recordID,\n\n828\n00:46:02,193 --> 00:46:05,428\nokay. Completion handler here to handle errors.\n\n829\n00:46:05,430 --> 00:46:09,999\nThis is the deleted record, if it happened,\n\n830\n00:46:10,001 --> 00:46:14,070\nor error if it didn't. And so, handle errors. I'm, again,\n\n831\n00:46:14,072 --> 00:46:18,908\nshort on time. So we're not going to do that. And\n\n832\n00:46:18,910 --> 00:46:21,744\nin either case, even if it didn't, you know,\n\n833\n00:46:21,746 --> 00:46:25,081\neven if it failed to delete, I'm still gonna go ahead and\n\n834\n00:46:25,083 --> 00:46:29,952\ndelete it out of allQandAs. So to do that, I just say\n\n835\n00:46:29,954 --> 00:46:36,225\nallQandAs.removeAtIndex the indexPath.row.\n\n836\n00:46:36,227 --> 00:46:38,728\nOkay, so it's just gonna delete it from the thing. Now,\n\n837\n00:46:38,730 --> 00:46:42,131\nhopefully, this was successful and it won't come back later,\n\n838\n00:46:42,133 --> 00:46:45,802\nbut it's gonna delete here. So let's take a look at this.\n\n839\n00:46:53,645 --> 00:46:55,845\nAll right, so we created both of these, so\n\n840\n00:46:55,847 --> 00:46:58,881\nI can swipe to delete, right, either one I wanted.\n\n841\n00:46:58,883 --> 00:47:01,284\nSo let's delete, let's delete this one.\n\n842\n00:47:01,286 --> 00:47:04,687\nIt's gone. Okay, and we can make sure it actually deleted\n\n843\n00:47:04,689 --> 00:47:06,322\nit in the database by going away and coming back,\n\n844\n00:47:06,324 --> 00:47:09,225\ncuz it reloads when it does that. It didn't come back, so\n\n845\n00:47:09,227 --> 00:47:10,693\nit actually deleted that from the database.\n\n846\n00:47:10,695 --> 00:47:13,663\nWe could also go over and look in our database right here,\n\n847\n00:47:13,665 --> 00:47:15,598\nin our default zone. And we can see, we only have,\n\n848\n00:47:15,600 --> 00:47:19,836\nwhat is your favorite team. We could reload just to be 100%\n\n849\n00:47:19,838 --> 00:47:22,238\nsure. Default zone. Sure enough, we only have,\n\n850\n00:47:22,240 --> 00:47:26,008\nwhat is your favorite team? It deleted it. Okay? All right,\n\n851\n00:47:26,010 --> 00:47:29,178\nso that's great. All right. One bad thing about our UI,\n\n852\n00:47:29,180 --> 00:47:32,415\nthough is, you see this nice little table view? If I'm just\n\n853\n00:47:32,417 --> 00:47:36,085\nsitting here and someone else creates something, it doesn't\n\n854\n00:47:36,087 --> 00:47:40,790\nshow me. So let's go over here on iPhone simulator here,\n\n855\n00:47:40,792 --> 00:47:42,992\nand I'm gonna create a new one.\n\n856\n00:47:42,994 --> 00:47:48,197\nI'm gonna see what happens. Okay, so it's showing,\n\n857\n00:47:48,199 --> 00:47:51,634\nwhat is your favorite team? So I'll create a new one here,\n\n858\n00:47:51,636 --> 00:47:54,270\nI'll say, what is your favorite color?\n\n859\n00:47:54,272 --> 00:48:00,142\nThat's our kind of our favorite one. Red and Blue.\n\n860\n00:48:00,144 --> 00:48:04,213\nAnd black, okay? Now, I've created this but it's not\n\n861\n00:48:04,215 --> 00:48:07,049\nshowing up over here, right? And it's not showing up there\n\n862\n00:48:07,051 --> 00:48:10,286\nbecause I'm not subscribing to that change. I'm not watching\n\n863\n00:48:10,288 --> 00:48:14,523\nthe database. Now, if I go away from this and come back,\n\n864\n00:48:14,525 --> 00:48:16,726\nit is gonna show it. Because when we viewWillAppear,\n\n865\n00:48:16,728 --> 00:48:19,495\nwe reload from the database. But it's really annoying for\n\n866\n00:48:19,497 --> 00:48:21,364\nthe user to always to have to go away and\n\n867\n00:48:21,366 --> 00:48:23,566\ncome back to the see the latest, thing. So,\n\n868\n00:48:23,568 --> 00:48:27,136\nwe need to do a subscription, okay? Perfect opportunity to\n\n869\n00:48:27,138 --> 00:48:29,705\ndo a subscription. So let's do that.\n\n870\n00:48:29,707 --> 00:48:34,243\nSo, how do we do the subscription? Pretty simple,\n\n871\n00:48:34,245 --> 00:48:36,746\nit's two parts really, three parts to doing it.\n\n872\n00:48:36,748 --> 00:48:39,181\nThe first one is we need to actually subscribe.\n\n873\n00:48:39,183 --> 00:48:40,549\nSo let's do the subscription first.\n\n874\n00:48:40,551 --> 00:48:45,922\nI'll even put this in a little MARK: Subscription place here.\n\n875\n00:48:45,924 --> 00:48:50,159\nOne thing is we need to have an ID for our subscription.\n\n876\n00:48:50,161 --> 00:48:51,193\nSo, I'm gonna say subscriptionID.\n\n877\n00:48:51,195 --> 00:48:54,430\nAnd this is just an English language description of what\n\n878\n00:48:54,432 --> 00:48:57,400\nwe're gonna subscribe to. And so I'm gonna say,\n\n879\n00:48:57,402 --> 00:49:00,603\nwe're gonna get All QandA Creations and Deletions.\n\n880\n00:49:00,605 --> 00:49:04,407\nAnd this has gotta uniquely identify this subscription in\n\n881\n00:49:04,409 --> 00:49:04,540\nthe database and\n\n882\n00:49:04,542 --> 00:49:07,777\nI think that pretty uniquely identifies what we're doing\n\n883\n00:49:07,779 --> 00:49:12,515\nhere. So, let me create a private func here\n\n884\n00:49:12,517 --> 00:49:16,652\ncalled iCloudSubscribeToQandAs, okay?\n\n885\n00:49:16,654 --> 00:49:19,622\nAnd this thing is going to do the subscription. So\n\n886\n00:49:19,624 --> 00:49:22,858\nwhen you do a subscription you need a predicate that says,\n\n887\n00:49:22,860 --> 00:49:23,993\nwhat you're looking for, okay?\n\n888\n00:49:23,995 --> 00:49:27,430\nWhat you're trying to find out when it changes. So again,\n\n889\n00:49:27,432 --> 00:49:31,233\nwe're gonna use pretty much the same one we used before\n\n890\n00:49:31,235 --> 00:49:34,337\nwhich is true predicate, TRUEPREDICATE, yeah.\n\n891\n00:49:34,339 --> 00:49:37,239\nBecause, we are looking for any additions or\n\n892\n00:49:37,241 --> 00:49:40,543\ndeletions of Q and A, not, not just the ones we created, or\n\n893\n00:49:40,545 --> 00:49:42,645\nnot just ones with certain questions but\n\n894\n00:49:42,647 --> 00:49:42,812\nany of them, so\n\n895\n00:49:42,814 --> 00:49:45,314\nthat's why we're using the same predicate. And then,\n\n896\n00:49:45,316 --> 00:49:50,286\nwe just create the subscription. Okay,\n\n897\n00:49:50,288 --> 00:49:57,126\nCKSubscription. And, it's, this one right here.\n\n898\n00:49:57,128 --> 00:49:59,528\nAnd let's go ahead and put this on separate lines,\n\n899\n00:49:59,530 --> 00:50:03,833\nas I am wont to do when there are lots of arguments so\n\n900\n00:50:03,835 --> 00:50:07,136\nyou can see what's going on, okay? So the recordType is,\n\n901\n00:50:07,138 --> 00:50:09,872\nwhat kind of thing we're watching, and of course here,\n\n902\n00:50:09,874 --> 00:50:13,075\nwe are watching Entity.QandA. That's what we're looking for\n\n903\n00:50:13,077 --> 00:50:18,447\nsearches for. predicate: is our predicate, okay.\n\n904\n00:50:18,449 --> 00:50:20,483\nsubscriptionID: is our subscriptionID.\n\n905\n00:50:20,485 --> 00:50:23,452\nI'm putting self in there just to emphasize that\n\n906\n00:50:23,454 --> 00:50:24,353\nit's my subscription ID,\n\n907\n00:50:24,355 --> 00:50:26,789\nokay? And then, the subscription options: are what\n\n908\n00:50:26,791 --> 00:50:29,658\nkind of changes are we looking for? So we want ones that\n\n909\n00:50:29,660 --> 00:50:34,263\nfire when one's created, and we also want to find out when\n\n910\n00:50:34,265 --> 00:50:37,867\none's deleted. Cuz we're showing a list of the suf,\n\n911\n00:50:37,869 --> 00:50:40,403\nof the Q and As, so we don't care if one gets\n\n912\n00:50:40,405 --> 00:50:43,339\nupdated. Although, we might care if it's updated because\n\n913\n00:50:43,341 --> 00:50:44,573\nmaybe it changed the question and\n\n914\n00:50:44,575 --> 00:50:45,474\nnow the list should change there.\n\n915\n00:50:45,476 --> 00:50:48,544\nBut I'm just gonna do creation and deletion here, to show you\n\n916\n00:50:48,546 --> 00:50:51,981\nthat. Now, one thing here that I'm not gonna do, but\n\n917\n00:50:51,983 --> 00:50:56,552\nthat you can do here, is there is a notification info\n\n918\n00:50:56,554 --> 00:51:00,089\nargument, or, var on subscription that you can use\n\n919\n00:51:00,091 --> 00:51:04,460\nto say, what happens when the push notification comes, when\n\n920\n00:51:04,462 --> 00:51:06,662\nthis changes. Does it put up an alert? Does it put a badge?\n\n921\n00:51:06,664 --> 00:51:10,533\nDoes it increase the badge, right? On your app icon, okay?\n\n922\n00:51:10,535 --> 00:51:13,169\nDoes it play a sound? Bloop, things arrived. Okay, you can\n\n923\n00:51:13,171 --> 00:51:16,138\nset that here. I'm gonna have none of those things happening\n\n924\n00:51:16,140 --> 00:51:18,674\nI'm just going to behind the scenes fix up the table.\n\n925\n00:51:18,676 --> 00:51:20,309\nI'm not gonna put any alerts up or whatever.\n\n926\n00:51:20,311 --> 00:51:23,746\nBut I just wanna let you know, you can do that here, okay?\n\n927\n00:51:23,748 --> 00:51:27,349\nSo, we got that, so let's just go to our database and\n\n928\n00:51:27,351 --> 00:51:29,652\ntell it to save this subscription, okay.\n\n929\n00:51:29,654 --> 00:51:33,322\nSave our subscription with our completion handler right here,\n\n930\n00:51:33,324 --> 00:51:36,292\nokay. Here is the savedSubscription,\n\n931\n00:51:36,294 --> 00:51:39,695\nif it succeeded, and here's an error if not.\n\n932\n00:51:39,697 --> 00:51:42,698\nI'm gonna take a second to show you an error here because\n\n933\n00:51:42,700 --> 00:51:48,137\nthere's a common one that happens. error?.code ==\n\n934\n00:51:48,139 --> 00:51:55,010\nCKErrorCode.ServerRejectedReq- uest,\n\n935\n00:51:55,012 --> 00:51:58,581\nokay? And what happens here sometimes is,\n\n936\n00:51:58,583 --> 00:52:01,417\nif this subscription by its unique name is already on\n\n937\n00:52:01,419 --> 00:52:05,054\nthe server, then it will reject your request, okay?\n\n938\n00:52:05,056 --> 00:52:08,157\nSo, this usually means that you ran your program,\n\n939\n00:52:08,159 --> 00:52:10,626\nyou were developing, you, this code ran,\n\n940\n00:52:10,628 --> 00:52:13,162\nand then you hit stop in the debugger, okay?\n\n941\n00:52:13,164 --> 00:52:15,664\nIt killed your app. And then you ran it again, and\n\n942\n00:52:15,666 --> 00:52:18,434\nit tried to do it, it's still there. Okay, the subscriptions\n\n943\n00:52:18,436 --> 00:52:21,637\nlive forever, until you actually remove them, okay?\n\n944\n00:52:21,639 --> 00:52:24,773\nSo quitting your app has no effect on the subscriptions.\n\n945\n00:52:24,775 --> 00:52:27,843\nSo, this is one where usually you'll ignore that\n\n946\n00:52:27,845 --> 00:52:29,979\nServerRejectedRequest figuring eh, somehow,\n\n947\n00:52:29,981 --> 00:52:33,549\nthis thing got got already put in there. That's fine,\n\n948\n00:52:33,551 --> 00:52:36,218\nwe'll just use it, okay, it'll continue to work just fine.\n\n949\n00:52:36,220 --> 00:52:39,522\nOkay and else, you know, if there's some error,\n\n950\n00:52:39,524 --> 00:52:40,823\nother kind of error, you know,\n\n951\n00:52:40,825 --> 00:52:44,226\nreport that error or whatever you feel like you need to do.\n\n952\n00:52:44,228 --> 00:52:48,597\nOkay, so that's it, that's all that's necessary to get iCloud\n\n953\n00:52:48,599 --> 00:52:53,102\nto start, you know, sending us push notifications when,\n\n954\n00:52:53,104 --> 00:52:56,839\nany of these creations and deletions happen to any Q and\n\n955\n00:52:56,841 --> 00:52:59,208\nA. Now, one thing is we're subscribing here.\n\n956\n00:52:59,210 --> 00:53:02,578\nWe also are probably want to unsubscribed and\n\n957\n00:53:02,580 --> 00:53:04,547\nwhen would we want to do those two things.\n\n958\n00:53:04,549 --> 00:53:08,918\nSo I'm gonna have an unsubscribe as well,\n\n959\n00:53:08,920 --> 00:53:12,087\nUnsubscribe. And when do we wanna do this?\n\n960\n00:53:12,089 --> 00:53:14,790\nProbably, we'll want to, when viewWillAppear,\n\n961\n00:53:14,792 --> 00:53:16,825\nwe wanna subscribe and when viewDisappears,\n\n962\n00:53:16,827 --> 00:53:19,762\nwe unsubscribe. Okay, because it's no use sending these push\n\n963\n00:53:19,764 --> 00:53:21,163\nnotifications if we're not even on screen.\n\n964\n00:53:21,165 --> 00:53:24,233\nOkay, especially since when we reappear we reload ourselves\n\n965\n00:53:24,235 --> 00:53:28,070\nanyway. Okay, so there's no reason to do that. So,\n\n966\n00:53:28,072 --> 00:53:31,473\nin viewWillAppear right here,\n\n967\n00:53:31,475 --> 00:53:36,645\nI'm gonna say, iCloudSubscribeToQandAs,\n\n968\n00:53:36,647 --> 00:53:41,784\nand in viewDidDisappear, I'm gonna say,\n\n969\n00:53:41,786 --> 00:53:45,821\niCloudUnsubscribe, okay? Now,\n\n970\n00:53:45,823 --> 00:53:48,991\niCloudUnsubscribe, what do we need to do to unsubscribe?\n\n971\n00:53:48,993 --> 00:53:53,295\nVery easy, I'm just gonna say to my database, please\n\n972\n00:53:53,297 --> 00:53:57,199\ndeleteSubscriptionWithID, my subscriptionID,\n\n973\n00:53:57,201 --> 00:54:01,537\nokay? Completion handler to handle errors here. So\n\n974\n00:54:01,539 --> 00:54:05,407\nthis is, the subscription that we tried to delete.\n\n975\n00:54:05,409 --> 00:54:08,344\nThere's an error. We will not handle errors cuz we're\n\n976\n00:54:08,346 --> 00:54:11,947\nrunning out of time. Handle it, okay? So, we'll just\n\n977\n00:54:11,949 --> 00:54:16,518\ndelete those, descriptions there and that's it. Okay, so\n\n978\n00:54:16,520 --> 00:54:20,489\nnow we've set up our table here to get those updates but\n\n979\n00:54:20,491 --> 00:54:23,158\nof course, we have to be able to receive push notifications\n\n980\n00:54:23,160 --> 00:54:26,762\nfor this to work, okay? And we do that, over in our app\n\n981\n00:54:26,764 --> 00:54:29,898\ndelegate. So lets go back to our app delegate right here,\n\n982\n00:54:29,900 --> 00:54:32,067\nand look at that code that we covered in lecture.\n\n983\n00:54:32,069 --> 00:54:34,436\nOne, in did finish launching with options,\n\n984\n00:54:34,438 --> 00:54:36,171\nwe need to register for\n\n985\n00:54:36,173 --> 00:54:38,307\nthe kinds of notifications\n\n986\n00:54:38,309 --> 00:54:40,242\nwe're willing to present to our user, okay?\n\n987\n00:54:40,244 --> 00:54:43,112\nAnd the user actually can choose in settings,\n\n988\n00:54:43,114 --> 00:54:46,248\nthe general settings, whether they want alerts or badges or\n\n989\n00:54:46,250 --> 00:54:48,917\nsounds or whatever, but we're going to explain here\n\n990\n00:54:48,919 --> 00:54:52,454\nwhich ones we think we want to give them, okay? So,\n\n991\n00:54:52,456 --> 00:54:56,859\nwe do that by just creating the settings, by that's\n\n992\n00:54:56,861 --> 00:55:01,430\na UIUserNotificationSettings, and for\n\n993\n00:55:01,432 --> 00:55:04,733\nthe types that we want. And this can be like alerts,\n\n994\n00:55:04,735 --> 00:55:09,405\nbadges, sounds, okay? And I'll go ahead and register for\n\n995\n00:55:09,407 --> 00:55:11,874\nall of them, although, I'm not gonna use any of them cuz I,\n\n996\n00:55:11,876 --> 00:55:14,043\nthat subscription.notification info, remember that?\n\n997\n00:55:14,045 --> 00:55:16,912\nI didn't put that line in, so it's not gonna do any of these\n\n998\n00:55:16,914 --> 00:55:20,215\nthings. But, I, I'm gonna tell the user, hey, I wanna do all\n\n999\n00:55:20,217 --> 00:55:22,818\nthese things cuz maybe some of my other push notifications\n\n1000\n00:55:22,820 --> 00:55:25,854\nwanted to do it or whatever. But I wouldn't sign up for\n\n1001\n00:55:25,856 --> 00:55:28,490\nthese actually if you're not gonna use them cuz it just\n\n1002\n00:55:28,492 --> 00:55:32,861\ncreates unnecessary stuff for your user, all right?\n\n1003\n00:55:32,863 --> 00:55:35,297\nSo there's the settings, so now I have to register\n\n1004\n00:55:35,299 --> 00:55:39,068\nthose settings, so I just say application.registerUserNotif-\n\n1005\n00:55:39,070 --> 00:55:40,669\nicationSettings, those settings.\n\n1006\n00:55:40,671 --> 00:55:44,807\nAnd now, I need to turn on push notifications, okay?\n\n1007\n00:55:44,809 --> 00:55:47,810\nregisterForRemoteNotificati- ons, okay?\n\n1008\n00:55:47,812 --> 00:55:51,013\nPush notifications are called remote notifications, okay?\n\n1009\n00:55:51,015 --> 00:55:53,449\nBoom, so now I've turned on push notifications,\n\n1010\n00:55:53,451 --> 00:55:54,850\nthey're gonna start coming, okay?\n\n1011\n00:55:54,852 --> 00:55:58,187\nFrom Cloudkit, or whatever else ones that I set up.\n\n1012\n00:55:58,189 --> 00:56:02,191\nSo now I have to handle them when they arrive, and I do\n\n1013\n00:56:02,193 --> 00:56:06,595\nthat with this thing called the remote notification,\n\n1014\n00:56:06,597 --> 00:56:09,498\ndidReceiveRemoteNotification, okay?\n\n1015\n00:56:09,500 --> 00:56:12,301\nA remote notification came in, what am I gonna do with it?\n\n1016\n00:56:12,303 --> 00:56:15,671\nWell, I'm gonna assume that it's a CloudKit one here.\n\n1017\n00:56:15,673 --> 00:56:17,740\nI don't have any other ones that I'm expecting, so\n\n1018\n00:56:17,742 --> 00:56:19,641\nthat should be fine. If I had other ones,\n\n1019\n00:56:19,643 --> 00:56:23,011\nI'd have to do more code here. But I'm just gonna say,\n\n1020\n00:56:23,013 --> 00:56:27,383\nif I can, or actually, I mean, yeah, if I'm gonna let CQ,\n\n1021\n00:56:27,385 --> 00:56:31,453\nckqn, that's short for CloudKit query notification,\n\n1022\n00:56:31,455 --> 00:56:35,357\nequals CKQueryNotification, CKQueryNotification,\n\n1023\n00:56:35,359 --> 00:56:40,996\nokay, that's not completing because, import CloudKit.\n\n1024\n00:56:41,866 --> 00:56:43,699\nOkay, so I'm gonna create a query notification.\n\n1025\n00:56:43,701 --> 00:56:47,169\nThe only way to create one of these things is to hand\n\n1026\n00:56:47,171 --> 00:56:51,707\nthe dictionary that comes with the push notification off to\n\n1027\n00:56:51,709 --> 00:56:55,444\nthis constructor, okay, this initializer.\n\n1028\n00:56:55,446 --> 00:56:56,178\nSo I'm gonna give it that.\n\n1029\n00:56:56,180 --> 00:56:58,914\nOne thing that's unfortunate about that is that it wants\n\n1030\n00:56:58,916 --> 00:57:03,952\nthat to be a dictionary where Strings are the keys and\n\n1031\n00:57:03,954 --> 00:57:05,387\nNSObjects are the values,\n\n1032\n00:57:05,389 --> 00:57:09,258\ninstead of NSObjects as the keys, AnyObject as the value.\n\n1033\n00:57:09,260 --> 00:57:12,995\nOkay? So, you just have to do this. All right, so\n\n1034\n00:57:12,997 --> 00:57:17,132\nI've got my query notification that came from CloudKit.\n\n1035\n00:57:17,134 --> 00:57:20,369\nAwesome. Now I need to hand it out to all my view controllers\n\n1036\n00:57:20,371 --> 00:57:22,104\nthat might be interested. And as we said in lecture,\n\n1037\n00:57:22,106 --> 00:57:24,273\nwe're gonna do this with a radio station. Okay, so\n\n1038\n00:57:24,275 --> 00:57:30,612\nlet's create a radio station. notification = NSNotification,\n\n1039\n00:57:30,614 --> 00:57:35,984\nall right, we're gonna use this one right here. Again,\n\n1040\n00:57:35,986 --> 00:57:41,323\nI will help you out a little bit. See what's going on.\n\n1041\n00:57:42,159 --> 00:57:44,993\nAll right, so name is the name of the radio station, and\n\n1042\n00:57:44,995 --> 00:57:47,062\nas I told you, in that CloudKit extensions,\n\n1043\n00:57:47,064 --> 00:57:50,365\nI created something for that. So I called that\n\n1044\n00:57:50,367 --> 00:57:54,803\nCloudKitNotifications.notific- ation,\n\n1045\n00:57:54,805 --> 00:57:58,440\nwhat did I call it? So I have to go back and look here.\n\n1046\n00:57:58,442 --> 00:58:02,444\nSupporting Files, extension, CloudKitNotification.\n\n1047\n00:58:02,446 --> 00:58:05,848\nNotificationReceived. That's the name of my radio station,\n\n1048\n00:58:05,850 --> 00:58:09,017\nNotificationReceived. Sorry.\n\n1049\n00:58:13,724 --> 00:58:17,926\nNotificationReceived. Okay, so that's the name. AnyObject,\n\n1050\n00:58:17,928 --> 00:58:19,928\nthis object is the sender. Ha, that's self,\n\n1051\n00:58:19,930 --> 00:58:22,064\nthat's my AppDelegate. Doesn't really matter too much,\n\n1052\n00:58:22,066 --> 00:58:24,299\ncuz I'm not gonna look at it in the other end. And\n\n1053\n00:58:24,301 --> 00:58:28,337\nthen the userInfo, I need to pass this ckqn on.\n\n1054\n00:58:28,339 --> 00:58:30,839\nSo I'm gonna create a little dictionary on the fly here.\n\n1055\n00:58:30,841 --> 00:58:35,143\nAnd the key is gonna be my CloudKitNotifications.Notific-\n\n1056\n00:58:35,145 --> 00:58:41,216\nationKey. And the value is gonna be that ckqn. Okay?\n\n1057\n00:58:41,218 --> 00:58:44,753\nSo this is the thing I'm gonna pass out onto, this is\n\n1058\n00:58:44,755 --> 00:58:48,957\nReceived, this is the thing I'm gonna pass out on my radio\n\n1059\n00:58:48,959 --> 00:58:53,462\nstation. So let's go ahead and broadcast it by saying\n\n1060\n00:58:53,464 --> 00:58:59,935\nNSNotificationCenter.defaultC- enter, post this notification,\n\n1061\n00:58:59,937 --> 00:59:03,705\nthat means broadcast on this radio station.\n\n1062\n00:59:03,707 --> 00:59:06,875\nOkay, now everybody who is signed up to listen is going\n\n1063\n00:59:06,877 --> 00:59:11,013\nto get this push notification forwarded onto them. Okay?\n\n1064\n00:59:11,015 --> 00:59:15,484\nSo now let's go back and sign up over here to get that.\n\n1065\n00:59:15,486 --> 00:59:16,718\nAnd I'm gonna do it in my subscribe,\n\n1066\n00:59:16,720 --> 00:59:19,054\nwhen I subscribe to the Q and A's, I'm gonna then go and\n\n1067\n00:59:19,056 --> 00:59:22,925\nsign up for that radio station so I can hear the results. And\n\n1068\n00:59:22,927 --> 00:59:26,061\nto do that, I need that little, cookie. So\n\n1069\n00:59:26,063 --> 00:59:31,066\nprivate var, we'll call it cloudKitObserver. It's gonna\n\n1070\n00:59:31,068 --> 00:59:34,369\nbe an NSObjectProtocol optional right there.\n\n1071\n00:59:34,371 --> 00:59:38,040\nOkay, I'm gonna say cloudKitObserver = and\n\n1072\n00:59:38,042 --> 00:59:42,311\nI'm just gonna ask the notification center if I can\n\n1073\n00:59:42,313 --> 00:59:46,181\nplease listen to that radio station by saying,\n\n1074\n00:59:46,183 --> 00:59:52,921\naddObserverForName. It's this one. Okay, again.\n\n1075\n00:59:55,826 --> 00:59:58,427\nI'd love if there was a nice little single key to do that\n\n1076\n00:59:58,429 --> 01:00:01,330\nfor me. So here's the radio station that I wanna listen\n\n1077\n01:00:01,332 --> 01:00:04,900\nto, which is CloudKitNotifications.Notific-\n\n1078\n01:00:04,902 --> 01:00:08,203\nationReceived, that's the name of the radio station.\n\n1079\n01:00:08,205 --> 01:00:10,939\nAnyObject, I don't care. And if anybody sends me that, I'm\n\n1080\n01:00:10,941 --> 01:00:12,975\ngonna listen, okay? I could put the AppDelegate here, but\n\n1081\n01:00:12,977 --> 01:00:15,677\nI'm just gonna say anybody. And I'm gonna do some UI here,\n\n1082\n01:00:15,679 --> 01:00:19,715\nso I'd better say [INAUDIBLE] NSOperationQueue.mainQueue,\n\n1083\n01:00:19,717 --> 01:00:21,850\nokay, send me this on the main queue. And\n\n1084\n01:00:21,852 --> 01:00:24,186\nthen here's the block, okay? This argument is\n\n1085\n01:00:24,188 --> 01:00:28,490\nthe notification that's coming along in the radio station.\n\n1086\n01:00:28,492 --> 01:00:33,662\nAnd I need to get the ck, ckqn out of the user info\n\n1087\n01:00:33,664 --> 01:00:37,466\nin that notification. Okay, so what does that look like?\n\n1088\n01:00:37,468 --> 01:00:40,168\nActually, I'm gonna do all that in a different method.\n\n1089\n01:00:40,170 --> 01:00:44,673\nI'm gonna have iCloudHandleSubscriptionNotif-\n\n1090\n01:00:44,675 --> 01:00:50,212\nication, and I'm just gonna pass ckqn on to that.\n\n1091\n01:00:50,214 --> 01:00:52,648\nSo the cq, ckqn here, we can say,\n\n1092\n01:00:52,650 --> 01:00:57,085\nif we can let ckqn equal the notification's userInfo,\n\n1093\n01:00:57,087 --> 01:01:01,456\nwhich might be nil, you have to be careful about that,\n\n1094\n01:01:01,458 --> 01:01:06,194\nand I'm gonna get the CloudKit notification key here,\n\n1095\n01:01:06,196 --> 01:01:09,698\nnotification's NotificationKey, okay.\n\n1096\n01:01:09,700 --> 01:01:13,702\nAnd that better be a CKQuery notification, or\n\n1097\n01:01:13,704 --> 01:01:15,904\nI don't know what to do with it,\n\n1098\n01:01:15,906 --> 01:01:19,708\nokay? So if I can get that out of the little radio station\n\n1099\n01:01:19,710 --> 01:01:23,712\nbroadcast, then I'm gonna handle it. Okay, so\n\n1100\n01:01:23,714 --> 01:01:30,285\nhow do I handle it? private func this thing,\n\n1101\n01:01:30,287 --> 01:01:34,723\nokay. And, there, we have a syntax\n\n1102\n01:01:34,725 --> 01:01:39,528\nerror right here, this should be NotificationKey,\n\n1103\n01:01:39,530 --> 01:01:42,864\nNotificationKey. So handling it is pretty simple,\n\n1104\n01:01:42,866 --> 01:01:47,636\nactually. First, when handling it, I'm gonna make sure that\n\n1105\n01:01:47,638 --> 01:01:52,441\nthis is for me. I'm gonna look at the subscription,\n\n1106\n01:01:52,443 --> 01:01:55,644\nsorry, ckqn is a CKQueryNotification.\n\n1107\n01:01:55,646 --> 01:01:58,480\nOkay, I'm gonna make sure that this thing is for me,\n\n1108\n01:01:58,482 --> 01:02:02,184\nto make sure its subscription ID equals my subscription ID.\n\n1109\n01:02:02,186 --> 01:02:04,386\nBecause, remember, you might have lots of different view\n\n1110\n01:02:04,388 --> 01:02:07,122\ncontrollers getting push notifications from CloudKit,\n\n1111\n01:02:07,124 --> 01:02:09,758\nokay, doing different things. So here I want to make sure\n\n1112\n01:02:09,760 --> 01:02:14,329\nit's this one that I'm getting the answer back from.\n\n1113\n01:02:14,331 --> 01:02:16,832\nAll right, so now that I have that, I'm just gonna get\n\n1114\n01:02:16,834 --> 01:02:19,835\nthe record that changed, okay, the recordID that changed\n\n1115\n01:02:19,837 --> 01:02:24,473\nis ckqn.recordID, okay, so hopefully some record changed,\n\n1116\n01:02:24,475 --> 01:02:27,976\ndeleted or created here, otherwise I wouldn't be here.\n\n1117\n01:02:27,978 --> 01:02:32,013\nI can also find out what changed. So I can say,\n\n1118\n01:02:32,015 --> 01:02:36,084\nwhat is the reason that I got this notification? And\n\n1119\n01:02:36,086 --> 01:02:38,120\none reason could be because a record\n\n1120\n01:02:38,122 --> 01:02:42,657\nwas created. Another reason might be cuz a record was\n\n1121\n01:02:42,659 --> 01:02:46,361\ndeleted, okay? Otherwise, I don't care,\n\n1122\n01:02:46,363 --> 01:02:48,196\ncuz I only handle creations and deletions,\n\n1123\n01:02:48,198 --> 01:02:53,502\nall right? Let's do deletion first. It's a pretty easy one.\n\n1124\n01:02:53,504 --> 01:02:56,705\nOkay, so what happens, if something was deleted? Well,\n\n1125\n01:02:56,707 --> 01:03:00,208\nI'm just gonna dispatc_async back the the main queue and\n\n1126\n01:03:00,210 --> 01:03:02,344\nremove it from my all QAs thing. So\n\n1127\n01:03:02,346 --> 01:03:08,350\ndispatc_ge_mai_queue. And I'm just gonna say,\n\n1128\n01:03:08,352 --> 01:03:14,055\nself.allQandAs equals self.allQandAs,\n\n1129\n01:03:14,057 --> 01:03:18,927\nand I'm just gonna filter out any records\n\n1130\n01:03:18,929 --> 01:03:23,598\nwhere the $0.recordID does not equal\n\n1131\n01:03:23,600 --> 01:03:27,669\nthis recordID that was just deleted.\n\n1132\n01:03:27,671 --> 01:03:30,739\nOkay, so filter goes through all the things in the array,\n\n1133\n01:03:30,741 --> 01:03:31,673\n$0 is each thing in the array,\n\n1134\n01:03:31,675 --> 01:03:34,543\nI'm gonna get the recordID of the thing that's in there.\n\n1135\n01:03:34,545 --> 01:03:35,844\nAnd if it's not equal to the recordID,\n\n1136\n01:03:35,846 --> 01:03:38,480\nthen I'm gonna filter it, if it is equal to the record ID,\n\n1137\n01:03:38,482 --> 01:03:41,516\nthen it's not gonna get through the filter.\n\n1138\n01:03:41,718 --> 01:03:44,920\nEverybody got that? Super simple. Created,\n\n1139\n01:03:44,922 --> 01:03:47,155\nslightly more difficult, although only slightly.\n\n1140\n01:03:47,157 --> 01:03:50,625\nSo, here, I'm gonna check if I have a record,\n\n1141\n01:03:50,627 --> 01:03:53,795\nif the record okay, let's, first of all,\n\n1142\n01:03:53,797 --> 01:03:57,699\nwe have the record ID here. To show this record in our,\n\n1143\n01:03:57,701 --> 01:04:01,236\nin our table, we actually need the record,\n\n1144\n01:04:01,238 --> 01:04:01,670\nnot the record ID.\n\n1145\n01:04:01,672 --> 01:04:05,373\nBy the way, it is possible in our subscription to have said,\n\n1146\n01:04:05,375 --> 01:04:08,910\nhey when you give this thing, also give me the question.\n\n1147\n01:04:08,912 --> 01:04:11,213\nIn other words, you can ask for certain fields so\n\n1148\n01:04:11,215 --> 01:04:13,448\nthat I don't have to do what I'm doing right now,\n\n1149\n01:04:13,450 --> 01:04:16,384\nwhich is I'm going back to my database and\n\n1150\n01:04:16,386 --> 01:04:21,790\nfetching that record. Database. fetchRecordWithID.\n\n1151\n01:04:21,792 --> 01:04:24,626\nWhich is kind of unfortunate that I have this record ID and\n\n1152\n01:04:24,628 --> 01:04:27,395\nI'm having to turn around and go back and fetch it.\n\n1153\n01:04:27,397 --> 01:04:29,497\nSo, you don't have to do that if you,\n\n1154\n01:04:29,499 --> 01:04:30,665\nin your description say just give me\n\n1155\n01:04:30,667 --> 01:04:34,502\nthat right off the bat, okay? You just specify which fields\n\n1156\n01:04:34,504 --> 01:04:37,272\nyou want. Okay. So here's the record coming back, hopefully,\n\n1157\n01:04:37,274 --> 01:04:42,510\nnot nil, and here's the error. Okay. So, if the record\n\n1158\n01:04:42,512 --> 01:04:46,815\nis not nil, I got it back. Now I need to add it to my Q and\n\n1159\n01:04:46,817 --> 01:04:49,784\nAs, now, a slight complication here is when I put it in my\n\n1160\n01:04:49,786 --> 01:04:53,321\nlist of Q and As, I obviously need to sort it. Because my\n\n1161\n01:04:53,323 --> 01:04:55,423\nlist of Q and As was sorted by the database, but now I'm\n\n1162\n01:04:55,425 --> 01:04:58,593\ngetting this one record that I have to put in the list.\n\n1163\n01:04:58,595 --> 01:04:59,060\nSo, I have to do sorting.\n\n1164\n01:04:59,062 --> 01:05:00,362\nSo, I'll show you a little bit how to do, ahh,\n\n1165\n01:05:00,364 --> 01:05:05,400\nsorting in here. Ahh, so, I'm gonna dispatc_async back to\n\n1166\n01:05:05,402 --> 01:05:10,639\nthe main queue. Okay.\n\n1167\n01:05:10,641 --> 01:05:13,808\nAnd on here, I'm gonna say self.allQandAs, okay?\n\n1168\n01:05:13,810 --> 01:05:18,146\nGet ready for this, equals the self.allQandAs we got so far,\n\n1169\n01:05:18,148 --> 01:05:22,784\nplus this record. Okay. So now, this is the new thing\n\n1170\n01:05:22,786 --> 01:05:25,320\nwith it appended on to the end, but the end is no good so\n\n1171\n01:05:25,322 --> 01:05:29,257\nI'm gonna sort. Okay? And when I sort, sort is\n\n1172\n01:05:29,259 --> 01:05:32,727\ngonna pass me dollar zero and dollar one. And I have to say,\n\n1173\n01:05:32,729 --> 01:05:35,297\nif dollar zero is less than or eq, or greater than dollar\n\n1174\n01:05:35,299 --> 01:05:38,667\none. And that's how it's gonna sort everything. So, let's go\n\n1175\n01:05:38,669 --> 01:05:44,339\nahead and return here. Dollar zero, which is a record,\n\n1176\n01:05:44,341 --> 01:05:48,043\na ck record, so I'm gonna get the, Cloud.Attribute.Question,\n\n1177\n01:05:48,045 --> 01:05:52,113\ncuz I'm comparing the questions, quest- question,\n\n1178\n01:05:52,115 --> 01:05:55,750\nall right. But of course, I have to do it as a string,\n\n1179\n01:05:55,752 --> 01:05:59,387\nand I'm gonna see if that's less than $1,\n\n1180\n01:05:59,389 --> 01:06:07,228\nCloud.Attribute.Question, also as a String.\n\n1181\n01:06:07,230 --> 01:06:10,832\nOkay. So, this is nice but\n\n1182\n01:06:10,834 --> 01:06:14,602\nthis is really messy code, it looks absolutely awesome,\n\n1183\n01:06:14,604 --> 01:06:16,905\nawful here. Wouldn't it be cool if in,\n\n1184\n01:06:16,907 --> 01:06:17,872\nlike we had in core data,\n\n1185\n01:06:17,874 --> 01:06:19,641\nwhere we could have the subclass and\n\n1186\n01:06:19,643 --> 01:06:22,344\nwe just use vars for these things? Well,\n\n1187\n01:06:22,346 --> 01:06:25,413\nwe can't quite do that, but watch this little trick.\n\n1188\n01:06:25,415 --> 01:06:27,682\nI'm going to go back to my supporting files,\n\n1189\n01:06:27,684 --> 01:06:30,618\nthis CloudKit extensions thing that I did over here, okay?\n\n1190\n01:06:30,620 --> 01:06:36,124\nAnd I'm going to do this extension to CKRecord\n\n1191\n01:06:36,426 --> 01:06:43,431\nvar question is a String, okay. I'm gonna return self\n\n1192\n01:06:43,433 --> 01:06:50,205\nsub Cloud.Attribute.Question as a String. And\n\n1193\n01:06:50,207 --> 01:06:53,708\nin fact, I want this to not be an optional. So I'm gonna say,\n\n1194\n01:06:53,710 --> 01:06:59,481\n??, empty. So, you see I've added a var question,\n\n1195\n01:06:59,483 --> 01:07:02,617\nto CkRecord that returns this thing.\n\n1196\n01:07:02,619 --> 01:07:07,188\nSo now back in my other code over here, all this gunk just\n\n1197\n01:07:07,190 --> 01:07:11,860\nbecomes .question. Okay, get rid of all this,\n\n1198\n01:07:11,862 --> 01:07:18,767\n.question. Okay, looks a lot nicer, doesn't it, okay?\n\n1199\n01:07:18,769 --> 01:07:21,236\nAnd in fact, we could use this .question in other places,\n\n1200\n01:07:21,238 --> 01:07:23,004\nlike down here, in cell for row at indexPath,\n\n1201\n01:07:23,006 --> 01:07:27,342\nwe do the same. A big mess right here, ,question.\n\n1202\n01:07:27,344 --> 01:07:30,311\nOkay. Now, okay, all your attributes would have to\n\n1203\n01:07:30,313 --> 01:07:32,947\nbe unique across all of your entities or you would have to\n\n1204\n01:07:32,949 --> 01:07:35,750\nstart putting the entity names somehow, in, in this name in\n\n1205\n01:07:35,752 --> 01:07:38,853\nthis bar, but you know, something to consider,\n\n1206\n01:07:38,855 --> 01:07:40,755\ncleans up your code quite a bit.\n\n1207\n01:07:40,757 --> 01:07:44,526\nAll right. Everyone, make sense what I did right there?\n\n1208\n01:07:44,528 --> 01:07:47,729\nBy the way, if this record couldn't be fetched,\n\n1209\n01:07:47,731 --> 01:07:52,167\nthen I'm kind of like, what the heck am I gonna do here?\n\n1210\n01:07:52,169 --> 01:07:53,701\nSo, I might wanna do something here like,\n\n1211\n01:07:53,703 --> 01:07:57,005\ngo reload my whole table, you know, do a fetch all q and\n\n1212\n01:07:57,007 --> 01:07:58,940\na's, call fetch, dispatch, async, and all that, but\n\n1213\n01:07:58,942 --> 01:08:02,177\nI'm not gonna do it cuz we're out of time. Ahm, but, that's,\n\n1214\n01:08:02,179 --> 01:08:07,649\nI might want to react to this error somehow here. Okay?\n\n1215\n01:08:07,651 --> 01:08:09,851\nAll right, so let's go back and\n\n1216\n01:08:09,853 --> 01:08:17,459\nlet's run it on iPhone. And we'll run it on our device.\n\n1217\n01:08:26,570 --> 01:08:33,741\nAll right. Okay. So let's go and create a new one here.\n\n1218\n01:08:33,743 --> 01:08:39,647\nLet's try, how do you greet people?\n\n1219\n01:08:40,050 --> 01:08:44,886\nAnd the answer is you say Hello, or maybe you say Aloha,\n\n1220\n01:08:44,888 --> 01:08:47,489\nand you can see as soon as I typed enough to get this thing\n\n1221\n01:08:47,491 --> 01:08:51,025\nto upload, it appeared here because it got noti, notified\n\n1222\n01:08:51,027 --> 01:08:54,629\nvia the push notification. And in fact, I can look at it,\n\n1223\n01:08:54,631 --> 01:08:57,765\nlet's see how do you greet people? Here we got hello,\n\n1224\n01:08:57,767 --> 01:09:00,568\nthe Aloha has not even, been uploaded yet, so\n\n1225\n01:09:00,570 --> 01:09:05,240\nlet's go ahead and hit the Aloha, then we get the Aloha.\n\n1226\n01:09:06,776 --> 01:09:09,110\nOkay? And same thing with delete, if we go back here and\n\n1227\n01:09:09,112 --> 01:09:10,845\nsay, well we don't want this to greet people,\n\n1228\n01:09:10,847 --> 01:09:13,248\nhit delete. And it deleted on our iPhone,\n\n1229\n01:09:13,250 --> 01:09:16,818\nwe don't have to wait back and forth. Okay,\n\n1230\n01:09:16,820 --> 01:09:21,156\nI will see you next time. >> For more,\n\n1231\n01:09:21,158 --> 01:09:21,189\nplease visit us at stanford.edu.\n\n"
  },
  {
    "path": "subtitles/17. Segues, Core Location, and MapKit.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,802\n[MUSIC]\n\n2\n00:00:03,804 --> 00:00:08,440\nStanford University. >> Okay, well,\n\n3\n00:00:08,442 --> 00:00:14,146\nwelcome to Lecture 17 of Stanford CS193P\n\n4\n00:00:14,148 --> 00:00:19,518\nspring of 2016. This is our penultimate lecture that\n\n5\n00:00:19,520 --> 00:00:23,822\nactually has content. Next week we have Memorial Day, and\n\n6\n00:00:23,824 --> 00:00:27,760\nthen we'll have our alternate final on Wednesday.\n\n7\n00:00:27,762 --> 00:00:28,861\nSo what are we gonna talk about today?\n\n8\n00:00:28,863 --> 00:00:31,130\nToday we're gonna talk about segues, okay?\n\n9\n00:00:31,132 --> 00:00:32,398\nWe've talked a lot about segues, but\n\n10\n00:00:32,400 --> 00:00:36,602\nthere's still quite a few more segues to be talked about. And\n\n11\n00:00:36,604 --> 00:00:39,738\nthen we're gonna talk about core location and MapKit,\n\n12\n00:00:39,740 --> 00:00:43,876\nwhich is kind of where is the device in the world. And then\n\n13\n00:00:43,878 --> 00:00:46,812\nI'm gonna do a demo, I'll do as much as the demo as I can,\n\n14\n00:00:46,814 --> 00:00:48,247\nand we'll just continue it on Wednesday.\n\n15\n00:00:48,249 --> 00:00:50,616\nThe demo's gonna be about maps and segues, obviously,\n\n16\n00:00:50,618 --> 00:00:53,719\nthat's what we're talking about today. All right? So\n\n17\n00:00:53,721 --> 00:00:55,220\nlet's dive right in here to segues.\n\n18\n00:00:55,222 --> 00:00:59,792\nThe first segue I'm gonna talk about is the modal segue. So,\n\n19\n00:00:59,794 --> 00:01:03,095\nthis modal segue is the segue to an MVC that is gonna\n\n20\n00:01:03,097 --> 00:01:05,697\ncompletely take over your screen, okay?\n\n21\n00:01:05,699 --> 00:01:08,834\nYou are fully responsible if you put a modal segue up for\n\n22\n00:01:08,836 --> 00:01:11,670\nproviding a way for a user to get out of it, okay.\n\n23\n00:01:11,672 --> 00:01:15,307\nBecause that MVC is completely in control.\n\n24\n00:01:15,309 --> 00:01:18,977\nThis kind of UI should be used with care, okay, because you\n\n25\n00:01:18,979 --> 00:01:22,214\nreally are locking down the UI, there's nothing else\n\n26\n00:01:22,216 --> 00:01:24,817\nthe user can do. They can't. If they change their mind,\n\n27\n00:01:24,819 --> 00:01:27,653\nthey can't go to another tab cuz it's not a tab bar thing.\n\n28\n00:01:27,655 --> 00:01:30,022\nThey can't just hit back in a navigation controller,\n\n29\n00:01:30,024 --> 00:01:32,224\nthey can't go to the other side of their split view or\n\n30\n00:01:32,226 --> 00:01:35,494\nwhatever. They're pretty much stuck here until you let them,\n\n31\n00:01:35,496 --> 00:01:39,598\nout of it. And so, I don't even show you this until late\n\n32\n00:01:39,600 --> 00:01:40,466\nin the quarter because\n\n33\n00:01:40,468 --> 00:01:43,802\nI really don't want you to think of this as a go to way\n\n34\n00:01:43,804 --> 00:01:47,406\nto present an MVC on screen, okay? But it does have its\n\n35\n00:01:47,408 --> 00:01:50,242\nuses, okay? Here's an example, perhaps. Okay,\n\n36\n00:01:50,244 --> 00:01:54,746\nthis is a contacts app, or an app that has contacts in it.\n\n37\n00:01:54,748 --> 00:01:56,281\nAnd we're showing the contacts and\n\n38\n00:01:56,283 --> 00:01:59,585\nthe little plus button in the corner here, let's say that,\n\n39\n00:01:59,587 --> 00:02:02,521\nthat button's going to allow us to enter a new contact.\n\n40\n00:02:02,523 --> 00:02:05,691\nNow, you could argue if the user has chosen to enter a new\n\n41\n00:02:05,693 --> 00:02:09,428\ncontact. They don't wanna do anything else except for\n\n42\n00:02:09,430 --> 00:02:10,028\nthat right now, and so\n\n43\n00:02:10,030 --> 00:02:13,298\nit's okay to present this adding contact view controller\n\n44\n00:02:13,300 --> 00:02:17,436\nmodally. Modally just means in a mode where you can't\n\n45\n00:02:17,438 --> 00:02:19,605\ndo anything else but this. Yeah,\n\n46\n00:02:19,607 --> 00:02:21,573\none could argue there might be other ways to do this,\n\n47\n00:02:21,575 --> 00:02:24,209\nbut let's, let's say that we're gonna do it this way.\n\n48\n00:02:24,211 --> 00:02:27,913\nSo we tap on this plus sign, and from the bottom slides up\n\n49\n00:02:27,915 --> 00:02:30,916\nthis new MVC. Now, this new MVC is completely controlling\n\n50\n00:02:30,918 --> 00:02:34,253\nthe screen. It doesn't have a back button that cancel button\n\n51\n00:02:34,255 --> 00:02:37,256\nthat you see right there. Is a button that this MVC is\n\n52\n00:02:37,258 --> 00:02:40,893\nputting in that bar, okay, it happens to cancel and\n\n53\n00:02:40,895 --> 00:02:42,995\nnot add a new contact in this case.\n\n54\n00:02:42,997 --> 00:02:45,564\nCuz it's not a push segue, it's a modal segue,\n\n55\n00:02:45,566 --> 00:02:48,901\ndifferent kind of segue. And the thing about modal, as you\n\n56\n00:02:48,903 --> 00:02:52,137\ncan actually have embedded modal inside modal, okay? So,\n\n57\n00:02:52,139 --> 00:02:55,541\nfor example here, I am adding my contact, let's say now,\n\n58\n00:02:55,543 --> 00:02:58,010\nI wanna choose the photo for my contact, okay?\n\n59\n00:02:58,012 --> 00:03:01,280\nThat's, also going to put up a modal MVC to get that. So\n\n60\n00:03:01,282 --> 00:03:05,117\nI click on that, another MVC slides off in the bottom so\n\n61\n00:03:05,119 --> 00:03:06,451\nnow, I have two modal ones.\n\n62\n00:03:06,453 --> 00:03:08,554\nAnd you might think of this as a little bit like,\n\n63\n00:03:08,556 --> 00:03:08,787\nnavigation control but\n\n64\n00:03:08,789 --> 00:03:10,756\nthey're on a stack, but that's really not the way it is.\n\n65\n00:03:10,758 --> 00:03:14,393\nIt's just the ad contact MVC took over the entire world and\n\n66\n00:03:14,395 --> 00:03:18,096\nthen, it gave it to the photos one and it completely took\n\n67\n00:03:18,098 --> 00:03:20,599\nover the world. And until it's dismissed,\n\n68\n00:03:20,601 --> 00:03:22,234\nthe other ones don't even really matter,\n\n69\n00:03:22,236 --> 00:03:26,872\nokay. Now, again notice no back button here. Also notice\n\n70\n00:03:26,874 --> 00:03:30,042\nby the way that cancel button has moved over from the right,\n\n71\n00:03:30,044 --> 00:03:32,110\nwhereas on previous MVC had it on the left.\n\n72\n00:03:32,112 --> 00:03:35,113\nI'm not a big fun of this kind of UI, by the way.\n\n73\n00:03:35,115 --> 00:03:36,181\nI think, things like cancel,\n\n74\n00:03:36,183 --> 00:03:38,784\nif they're conceptually the same thing in two MVCs.\n\n75\n00:03:38,786 --> 00:03:41,753\nEspecially, two MVCs that appear back to back like this,\n\n76\n00:03:41,755 --> 00:03:43,088\nshould probably be in the same place.\n\n77\n00:03:43,090 --> 00:03:47,292\nSo I would have put the cancel buttons both on the left here.\n\n78\n00:03:47,294 --> 00:03:51,430\nBut whatever app this is or from where these contacts\n\n79\n00:03:51,432 --> 00:03:55,100\ncame from, I decided to do that. But in any case,\n\n80\n00:03:55,102 --> 00:03:59,538\nno back button here. Right? Make sense? Okay,\n\n81\n00:03:59,540 --> 00:04:04,243\nso, let's cancel this and we'll see what happens to this\n\n82\n00:04:04,245 --> 00:04:07,112\nmodal MVC. This cancel is a way to get out of it.\n\n83\n00:04:07,114 --> 00:04:07,579\nAnd when we cancel it,\n\n84\n00:04:07,581 --> 00:04:10,549\nof course, it slides back out. And the other MVC is still\n\n85\n00:04:10,551 --> 00:04:14,720\nthere. Okay? Nothing has changed. And here, of course,\n\n86\n00:04:14,722 --> 00:04:17,789\nif we cancel this one, then we'll go back to where we were\n\n87\n00:04:17,791 --> 00:04:21,193\nbefore. And this MVC goes away. So that's modal, right?\n\n88\n00:04:21,195 --> 00:04:24,029\nYou press the MVC. It lives, it does whatever it does.\n\n89\n00:04:24,031 --> 00:04:26,265\nIt completely takes over the app and then somehow,\n\n90\n00:04:26,267 --> 00:04:29,167\nyou press something to get out of it. Cancel or done, or\n\n91\n00:04:29,169 --> 00:04:33,605\nwhatever, but that's totally up to that MVC. Right? So,\n\n92\n00:04:33,607 --> 00:04:37,109\nbe careful is all I say about this. Don't go to modal first.\n\n93\n00:04:37,111 --> 00:04:39,845\nThink about whether there's a way to put it in a tab or\n\n94\n00:04:39,847 --> 00:04:43,348\nin your navigation stack, or something like that. Before\n\n95\n00:04:43,350 --> 00:04:46,752\nyou jump right to choosing modal. All right, so how do we\n\n96\n00:04:46,754 --> 00:04:49,154\nset up a modal segue? How do we do one of these?\n\n97\n00:04:49,156 --> 00:04:51,957\nJust like all the other segues we've been doing,\n\n98\n00:04:51,959 --> 00:04:55,927\nyou just CTRL+drag, from the thing that's going to cause\n\n99\n00:04:55,929 --> 00:04:59,331\nthe modal segue to happen, to the MVC that's going to take\n\n100\n00:04:59,333 --> 00:05:02,601\nover the world. When you do that by the way, an important\n\n101\n00:05:02,603 --> 00:05:05,137\nthing to notice is that you can inspect the segue, and\n\n102\n00:05:05,139 --> 00:05:07,939\na modal segue has different kinda things you can choose.\n\n103\n00:05:07,941 --> 00:05:10,709\nWhich I'm gonna talk about, like how the modal segue is\n\n104\n00:05:10,711 --> 00:05:12,511\npresented. Does it slide up from the bottom or\n\n105\n00:05:12,513 --> 00:05:15,013\ndo something else? And also, what does the modal segue\n\n106\n00:05:15,015 --> 00:05:18,216\nlook like when it's there? Is it a take over the full screen\n\n107\n00:05:18,218 --> 00:05:20,319\nkind, okay, or is it some other kind.\n\n108\n00:05:20,321 --> 00:05:23,822\nWe'll talk about what those other kinds can be. All right?\n\n109\n00:05:23,824 --> 00:05:28,727\nIf you wanna present a modal MVC not from a button, okay or\n\n110\n00:05:28,729 --> 00:05:30,062\nfrom a bar button item.\n\n111\n00:05:30,064 --> 00:05:31,496\nYou wanna do it from something else. Of course,\n\n112\n00:05:31,498 --> 00:05:33,865\nyou can present it using the normal form segue with\n\n113\n00:05:33,867 --> 00:05:35,934\nidentifier from your code. We've seen a couple of\n\n114\n00:05:35,936 --> 00:05:39,705\nexamples of that in the demos and of course, modal, you can\n\n115\n00:05:39,707 --> 00:05:42,741\ndo that as well. You also, if you have a view controller in\n\n116\n00:05:42,743 --> 00:05:44,710\nyour hand, you actually have an instance of a view\n\n117\n00:05:44,712 --> 00:05:47,212\ncontroller like remember alert view controller, right?\n\n118\n00:05:47,214 --> 00:05:49,681\nYou say new alert view controller and you get one,\n\n119\n00:05:49,683 --> 00:05:53,118\nnow you have one. You can put it up using this method right\n\n120\n00:05:53,120 --> 00:05:56,455\nhere, which we actually saw in one of the other demos,\n\n121\n00:05:56,457 --> 00:05:59,257\nalert demo there. Actually I don't know if I demoed it,\n\n122\n00:05:59,259 --> 00:06:01,660\nbut we talked about it in alerts, which is present\n\n123\n00:06:01,662 --> 00:06:03,628\nview controller. And you just give it the view controller\n\n124\n00:06:03,630 --> 00:06:06,264\nthat you have in your hand and whether you want it\n\n125\n00:06:06,266 --> 00:06:09,668\nto be an animated transition, which usually you do. And\n\n126\n00:06:09,670 --> 00:06:12,070\nthen you just got a little handler here at the end,\n\n127\n00:06:12,072 --> 00:06:15,440\nthat will get called when it has finished being presented.\n\n128\n00:06:15,442 --> 00:06:18,009\nYou usually don't need that, but just in case, you do.\n\n129\n00:06:18,011 --> 00:06:20,178\nAll right. So this is how you present something modally.\n\n130\n00:06:20,180 --> 00:06:23,115\nThis is only for modalPresentations, all right?\n\n131\n00:06:23,117 --> 00:06:24,516\nIf you have the view controller in your hand,\n\n132\n00:06:24,518 --> 00:06:28,453\nwhich is rare. Generally, it's things you got from iOS,\n\n133\n00:06:28,455 --> 00:06:30,922\nlike maybe the camera view controller, or\n\n134\n00:06:30,924 --> 00:06:34,059\nthe alert view controller, some things like that.\n\n135\n00:06:34,061 --> 00:06:37,462\nNotice that in horizontally regular environment,\n\n136\n00:06:37,464 --> 00:06:40,732\nhorizontally regular, not compact. You there's\n\n137\n00:06:40,734 --> 00:06:44,169\na modalPresentationStyle var in a view controller, that'll,\n\n138\n00:06:44,171 --> 00:06:47,305\nthat'll specify basically how this view controller gets\n\n139\n00:06:47,307 --> 00:06:50,175\npresented when it gets presented modally. Does it get\n\n140\n00:06:50,177 --> 00:06:53,512\npresented full screen where it takes the whole full screen?\n\n141\n00:06:53,514 --> 00:06:57,382\nOverFullScreen which means, it goes over the whole screen but\n\n142\n00:06:57,384 --> 00:06:58,283\nit, the one behind,\n\n143\n00:06:58,285 --> 00:07:01,286\nwhatever is existing on this screen is visible. So\n\n144\n00:07:01,288 --> 00:07:03,288\nif you had a clear view controller,\n\n145\n00:07:03,290 --> 00:07:03,989\nyou'd be able to see through it.\n\n146\n00:07:03,991 --> 00:07:07,592\nSo you have things underneath. Pop over, of course you guys\n\n147\n00:07:07,594 --> 00:07:10,462\nknow what a pop over is. A pop over is just a modal,\n\n148\n00:07:10,464 --> 00:07:15,033\na modal MVC, but it's kinda got some special presentation\n\n149\n00:07:15,035 --> 00:07:18,136\ncharacteristics. There's also form sheet and page sheet,\n\n150\n00:07:18,138 --> 00:07:21,339\nthings like that, which kinda present in different ways.\n\n151\n00:07:21,341 --> 00:07:24,242\nYou can play with those, by inspecting the segue in\n\n152\n00:07:24,244 --> 00:07:27,712\nthe storyboard and choosing different presentation styles.\n\n153\n00:07:27,714 --> 00:07:31,283\nNote that in horizontally compact environments, however,\n\n154\n00:07:31,285 --> 00:07:35,754\nit's basically the iPhone in portrait. The system, when you\n\n155\n00:07:35,756 --> 00:07:40,091\ndo the presentViewController will by default,\n\n156\n00:07:40,093 --> 00:07:42,327\nadapt to be full screen, okay?\n\n157\n00:07:42,329 --> 00:07:46,164\nSo if you try to present something in form sheet mode,\n\n158\n00:07:46,166 --> 00:07:50,101\nokay? On an iPhone, it'll come up as full screen, cuz it'll\n\n159\n00:07:50,103 --> 00:07:54,406\nadapt to the fact that it's on the phone. It doesn't really\n\n160\n00:07:54,408 --> 00:07:58,844\nhave enough width to do a form sheet for you, okay?\n\n161\n00:07:58,846 --> 00:08:02,047\nHow do you prepare for a Modal segue? Nothing to see here,\n\n162\n00:08:02,049 --> 00:08:04,616\nokay? It's just like any other segue you've ever done.\n\n163\n00:08:04,618 --> 00:08:06,751\nNothing special about it. Just check the identifier,\n\n164\n00:08:06,753 --> 00:08:09,321\nget the destination view controller and prepare it.\n\n165\n00:08:09,323 --> 00:08:12,958\nHow do you hear back from a modal view controller?\n\n166\n00:08:12,960 --> 00:08:15,460\nYou put something some up modally and it does something,\n\n167\n00:08:15,462 --> 00:08:18,230\nokay? You add to new contact, how do you hear back\n\n168\n00:08:18,232 --> 00:08:21,166\nwith the results of what it did? Okay? Well,\n\n169\n00:08:21,168 --> 00:08:26,271\nthere's a couple of ways to do this. One is that the add\n\n170\n00:08:26,273 --> 00:08:29,674\ncontact thing might be putting the contact in a database,\n\n171\n00:08:29,676 --> 00:08:32,644\nsome modal that is shared by the guy who put it up.\n\n172\n00:08:32,646 --> 00:08:35,113\nSo then you don't need to do anything, okay. When the modal\n\n173\n00:08:35,115 --> 00:08:36,715\nthing gets dismissed, you'll come back and there'll be\n\n174\n00:08:36,717 --> 00:08:39,384\nsomething else in the database that wasn't there before.\n\n175\n00:08:39,386 --> 00:08:42,988\nAnother way is using an unwind segue which I'm gonna talk\n\n176\n00:08:42,990 --> 00:08:45,891\nabout in few slides here. And then another way is\n\n177\n00:08:45,893 --> 00:08:48,660\ndelegation. And the reason we have to use delegation or\n\n178\n00:08:48,662 --> 00:08:51,396\nunwind or something like that is because when you present\n\n179\n00:08:51,398 --> 00:08:53,932\na view controller modally, it's part of your view.\n\n180\n00:08:53,934 --> 00:08:56,701\nIt's part of the presenting view controller's view.\n\n181\n00:08:56,703 --> 00:09:00,472\nSo that thing can't talk back in any way, except for\n\n182\n00:09:00,474 --> 00:09:02,240\nthose blind structured ways we talked about,\n\n183\n00:09:02,242 --> 00:09:07,245\nlike delegation, okay? How do you dismiss a view controller,\n\n184\n00:09:07,247 --> 00:09:10,115\nright? So a view controller's up, and it's collecting\n\n185\n00:09:10,117 --> 00:09:12,584\nthe new contact, and then the user puts Cancel or\n\n186\n00:09:12,586 --> 00:09:16,154\nDone, how do we make it go away? The answer is you ask\n\n187\n00:09:16,156 --> 00:09:19,424\nthe presenting view controller to dismiss you, always\n\n188\n00:09:19,426 --> 00:09:22,928\nthe presenting view controller dismisses you. All right? And\n\n189\n00:09:22,930 --> 00:09:26,164\nyou send it the message dismissViewControllerAnimated\n\n190\n00:09:26,166 --> 00:09:27,432\nto the presenting view controller and\n\n191\n00:09:27,434 --> 00:09:31,069\nit's going to dismiss whatever modal view controller it has\n\n192\n00:09:31,071 --> 00:09:34,973\npresented, okay? So that's sent to the presenting.\n\n193\n00:09:34,975 --> 00:09:38,143\nI can't emphasize that enough. Now, in the old days,\n\n194\n00:09:38,145 --> 00:09:40,312\npeople used to send it to the presented.\n\n195\n00:09:40,314 --> 00:09:41,846\nThe API was a little bit different, okay?\n\n196\n00:09:41,848 --> 00:09:44,215\nAnd then sent it to the presented view controller,\n\n197\n00:09:44,217 --> 00:09:46,084\nthe one that's actually up, okay?\n\n198\n00:09:46,086 --> 00:09:49,287\nAnd, that's wrong. For backwards compatibility,\n\n199\n00:09:49,289 --> 00:09:50,622\nif you sent it to the presented one,\n\n200\n00:09:50,624 --> 00:09:53,892\nand the presented one had not presented another one,\n\n201\n00:09:53,894 --> 00:09:56,561\nthen it would dismiss it. But don't write your code to\n\n202\n00:09:56,563 --> 00:09:59,464\ndepend on that kind of backwards compatibility mode.\n\n203\n00:09:59,466 --> 00:10:02,534\nWhen you wanna dismiss it, you send it to the presenting.\n\n204\n00:10:02,536 --> 00:10:05,937\nNow the great thing is that the presented has a var\n\n205\n00:10:05,939 --> 00:10:08,640\ncalled presenting view controller, which is the view\n\n206\n00:10:08,642 --> 00:10:11,009\ncontroller that presented it. So it's very easy for\n\n207\n00:10:11,011 --> 00:10:13,778\nthe presented one to dismiss itself by asking\n\n208\n00:10:13,780 --> 00:10:17,682\nits presenting view controller to dismiss it. You see.\n\n209\n00:10:17,684 --> 00:10:20,251\nBut that's the way you wanna write that code.\n\n210\n00:10:20,253 --> 00:10:22,420\nOkay, if you do an unwind segue,\n\n211\n00:10:22,422 --> 00:10:24,322\nagain, which I'm gonna talk about in a few slides,\n\n212\n00:10:24,324 --> 00:10:26,791\nit automatically dismisses. So when you unwind,\n\n213\n00:10:26,793 --> 00:10:29,094\nyou don't have to call dismissViewController.\n\n214\n00:10:29,096 --> 00:10:30,195\nJust automatically dismisses. So\n\n215\n00:10:30,197 --> 00:10:33,031\nwe're talking about unwinding in a second. All right,\n\n216\n00:10:33,033 --> 00:10:37,902\nso in addition to how the modal view controller appears,\n\n217\n00:10:37,904 --> 00:10:39,704\nlike form sheet or popover or whatever,\n\n218\n00:10:39,706 --> 00:10:42,440\nthere's also how it gets transitioned onto the screen,\n\n219\n00:10:42,442 --> 00:10:45,977\nwhat animation gets used. Okay, so, CoverVertical is\n\n220\n00:10:45,979 --> 00:10:48,313\nthe slides up from the bottom, FlipHorizontal,\n\n221\n00:10:48,315 --> 00:10:50,248\nexactly what you would think, the presented and\n\n222\n00:10:50,250 --> 00:10:53,952\nthe presenting flip, are on like two sides of a card and\n\n223\n00:10:53,954 --> 00:10:54,319\nit flips over.\n\n224\n00:10:54,321 --> 00:10:56,955\nYou got CrossDissolve which is all between the two.\n\n225\n00:10:56,957 --> 00:11:00,792\nEven PartialCurl which will partially curl a presenting\n\n226\n00:11:00,794 --> 00:11:05,263\none up showing the presented behind it. Kind of just at\n\n227\n00:11:05,265 --> 00:11:06,731\nthe bottom. It's kind of looks really cool.\n\n228\n00:11:06,733 --> 00:11:08,466\nYou see it sometimes with map applications and\n\n229\n00:11:08,468 --> 00:11:13,071\nstuff you curl the map up and there's something underneath.\n\n230\n00:11:14,274 --> 00:11:17,275\nAll right, let's talk about that wi, unwind segue.\n\n231\n00:11:17,277 --> 00:11:18,243\nRight, you have these MVCs,\n\n232\n00:11:18,245 --> 00:11:21,012\nthey wanna communicate back, or they wanna jump back.\n\n233\n00:11:21,014 --> 00:11:23,248\nMaybe, something's on a navigation stack and\n\n234\n00:11:23,250 --> 00:11:26,317\nwants to jump back farther than just one pop, okay?\n\n235\n00:11:26,319 --> 00:11:27,752\nYou can do all this with an unwind.\n\n236\n00:11:27,754 --> 00:11:31,423\nNow, unwind segues are weird because they violate the thing\n\n237\n00:11:31,425 --> 00:11:32,924\nI told you would never violate it,\n\n238\n00:11:32,926 --> 00:11:37,062\nwhich is that segues always create a new MVC. Okay, and\n\n239\n00:11:37,064 --> 00:11:41,132\nthat's generally true if you modally segue or show segue or\n\n240\n00:11:41,134 --> 00:11:42,701\nany of these other kinds of segues,\n\n241\n00:11:42,703 --> 00:11:46,604\nit creates a new MVC every time except unwind. Because\n\n242\n00:11:46,606 --> 00:11:50,375\nunwind is gonna segue back to somebody who presented you,\n\n243\n00:11:50,377 --> 00:11:52,844\nmaybe not the guy who immediately presented to you,\n\n244\n00:11:52,846 --> 00:11:54,279\nmaybe somebody who presented to the guy\n\n245\n00:11:54,281 --> 00:11:54,779\nwho presented to you but\n\n246\n00:11:54,781 --> 00:11:57,282\nyou're gonna be going back to an existing view controller.\n\n247\n00:11:57,284 --> 00:12:01,786\nYou're gonna unwind. Okay, your view controllers.\n\n248\n00:12:01,788 --> 00:12:03,822\nWhat's it good for? Like I said, good for\n\n249\n00:12:03,824 --> 00:12:06,925\ncommunicating back information after a modal one is done,\n\n250\n00:12:06,927 --> 00:12:09,561\nand also good for jumping back up the stack of cards in\n\n251\n00:12:09,563 --> 00:12:13,498\nthe navigation controller more than one step, okay?\n\n252\n00:12:13,500 --> 00:12:15,767\nBecause it can go back to guys, who presented guys,\n\n253\n00:12:15,769 --> 00:12:18,470\nwho presented guys so it can jump all the way back.\n\n254\n00:12:18,472 --> 00:12:20,805\nHow does it work? Okay, so instead of\n\n255\n00:12:20,807 --> 00:12:24,709\nCtrl+dragging to another MVC to set up this segue which is\n\n256\n00:12:24,711 --> 00:12:27,545\nwhat you usually do, you actually Ctrl+drag to this\n\n257\n00:12:27,547 --> 00:12:30,181\nlittle button at the top. It's kinda reddish.\n\n258\n00:12:30,183 --> 00:12:34,185\nThe Exit button. Okay, so if I have this row in this table\n\n259\n00:12:34,187 --> 00:12:37,622\nright here and when you click on it, it wants to unwind and\n\n260\n00:12:37,624 --> 00:12:41,025\ngo back to one of the MVCs that presented this MVC,\n\n261\n00:12:41,027 --> 00:12:45,163\nyou just Ctrl+drag up to this little exit. Now when you do\n\n262\n00:12:45,165 --> 00:12:49,501\nthat, it's gonna show you a list of methods that\n\n263\n00:12:49,503 --> 00:12:53,805\nare implemented by other MVCs in your app, okay? They're\n\n264\n00:12:53,807 --> 00:12:57,342\nspecial, and I'll show you what makes them special but\n\n265\n00:12:57,344 --> 00:13:00,879\nthese special things will appear in this list.\n\n266\n00:13:00,881 --> 00:13:04,549\nAnd all you do is pick which one you want. Then when you do\n\n267\n00:13:04,551 --> 00:13:07,685\nthe segue, it will start looking up the list of MVC's\n\n268\n00:13:07,687 --> 00:13:09,354\nthat presented you, and the one that presented that, and\n\n269\n00:13:09,356 --> 00:13:11,523\nthe one that presented that until it finds that method.\n\n270\n00:13:11,525 --> 00:13:14,359\nAnd it will dismiss all the way back to that one and\n\n271\n00:13:14,361 --> 00:13:19,330\ncall this method, okay? So let me show you some more\n\n272\n00:13:19,332 --> 00:13:22,801\npictures to make this a little bit clearer right here.\n\n273\n00:13:22,803 --> 00:13:26,104\nSo this go back method right here, okay,\n\n274\n00:13:26,106 --> 00:13:28,306\nI want, I connected to exit and\n\n275\n00:13:28,308 --> 00:13:28,740\nI have to go back.\n\n276\n00:13:28,742 --> 00:13:32,110\nGo back let's say is in the guy who directly presented me.\n\n277\n00:13:32,112 --> 00:13:34,712\nHe could be farther up the stack but let's say he's right\n\n278\n00:13:34,714 --> 00:13:37,282\nhere. And here's this go back method right here. Now,\n\n279\n00:13:37,284 --> 00:13:40,552\nwhat's special about this go back method in this presenter?\n\n280\n00:13:40,554 --> 00:13:44,355\nWell, one thing is it has to be marked IBAction, okay?\n\n281\n00:13:44,357 --> 00:13:47,292\nSo if it has IBAction. And the second thing is,\n\n282\n00:13:47,294 --> 00:13:51,162\nthe argument has to be a UIStoryboardSegue. So\n\n283\n00:13:51,164 --> 00:13:53,731\nany method that's, is marked IBAction and\n\n284\n00:13:53,733 --> 00:13:57,802\nhas UIStoryboardSegue as the argument is gonna appear in\n\n285\n00:13:57,804 --> 00:14:02,240\nthis list. Okay, now this IBAction,\n\n286\n00:14:02,242 --> 00:14:06,377\nonce you kind of pick the one you want.\n\n287\n00:14:06,379 --> 00:14:09,314\nThis segue is gonna happen and it's still gonna be a normal\n\n288\n00:14:09,316 --> 00:14:10,982\nsegue and then it's gonna have prepare.\n\n289\n00:14:10,984 --> 00:14:13,985\nNow the prepare, okay, here's the prepare for segue.\n\n290\n00:14:13,987 --> 00:14:17,689\nIt's going to be in the aah MVC that you wired the exit\n\n291\n00:14:17,691 --> 00:14:20,725\nbutton up to, the one on the right here. Okay,\n\n292\n00:14:20,727 --> 00:14:23,027\nso it lives down in there. And it gets to prepare for\n\n293\n00:14:23,029 --> 00:14:26,564\nthis segue. The segue is gonna come back to this presenter.\n\n294\n00:14:26,566 --> 00:14:28,967\nSo, the destination view controller,\n\n295\n00:14:28,969 --> 00:14:33,872\nhere, is the presenter. The source view controller,\n\n296\n00:14:33,874 --> 00:14:34,906\nwhich you haven't seen yet,\n\n297\n00:14:34,908 --> 00:14:38,710\nin previous segues, is the thing on the right, okay?\n\n298\n00:14:38,712 --> 00:14:42,180\nThe thing it's segueing from. That's the source,\n\n299\n00:14:42,182 --> 00:14:46,351\nthis is the destination, okay? Make sense? And\n\n300\n00:14:46,353 --> 00:14:49,220\nwhen this happens, okay, when the segue happens,\n\n301\n00:14:49,222 --> 00:14:52,156\nyou'll be dismissed, right? The source one\n\n302\n00:14:52,158 --> 00:14:55,226\nwill be dismissed. And again, it doesn't just have to\n\n303\n00:14:55,228 --> 00:14:57,829\ngo one level up, it could go up the stack of the navigation\n\n304\n00:14:57,831 --> 00:15:00,431\ncontroller things. Or if you had four or five modals in\n\n305\n00:15:00,433 --> 00:15:02,634\na row, it could jump all the way back, it's perfectly fine.\n\n306\n00:15:02,636 --> 00:15:07,038\nIt's just whoever implements the method. All right?\n\n307\n00:15:07,040 --> 00:15:10,341\nNow let's talk another kind of segue, popovers, okay?\n\n308\n00:15:10,343 --> 00:15:11,009\nYou've all seen the popover.\n\n309\n00:15:11,011 --> 00:15:13,544\nHere's an example of popover here on the right.\n\n310\n00:15:13,546 --> 00:15:16,247\nThis is probably some kind of Search for Appointment to\n\n311\n00:15:16,249 --> 00:15:21,486\npopover, okay? So this MVC just leaves in here.\n\n312\n00:15:21,488 --> 00:15:23,721\nAnd it's being presented modally, okay?\n\n313\n00:15:23,723 --> 00:15:26,958\nIt's just that it presents in a way that looks like this,\n\n314\n00:15:26,960 --> 00:15:29,961\nlike it's in a pop-over. And the popover of course has\n\n315\n00:15:29,963 --> 00:15:32,196\na little arrow at the top, a little white arrow,\n\n316\n00:15:32,198 --> 00:15:35,767\nyou can see it, that points to the thing, the UI element that\n\n317\n00:15:35,769 --> 00:15:40,405\ncaused it to pop up. Usually that's a bar button item, but\n\n318\n00:15:40,407 --> 00:15:43,341\nit could also just be an arbitrary rectangle inside\n\n319\n00:15:43,343 --> 00:15:47,712\nsome view somewhere, okay? This area out here, okay,\n\n320\n00:15:47,714 --> 00:15:51,015\neverywhere else except for this popover and\n\n321\n00:15:51,017 --> 00:15:54,652\nthe keyboard is grayed out. If you click there,\n\n322\n00:15:54,654 --> 00:15:58,556\nit will dismiss this popover. So the one difference between\n\n323\n00:15:58,558 --> 00:16:02,293\npopover and other kinda modal one is that popovers are easy\n\n324\n00:16:02,295 --> 00:16:05,964\nto dismiss. Just click outside of them, you'll dismiss, so\n\n325\n00:16:05,966 --> 00:16:08,633\nyou don't need a cancel button in a popover or\n\n326\n00:16:08,635 --> 00:16:11,502\nmodal popover. But it's still modal in that obviously you\n\n327\n00:16:11,504 --> 00:16:13,738\ncan't do anything in that grayed out area.\n\n328\n00:16:13,740 --> 00:16:16,007\nYou can only do what this search for\n\n329\n00:16:16,009 --> 00:16:18,409\nappointment MBC wants to do right now.\n\n330\n00:16:18,411 --> 00:16:21,112\nOkay, so it's still a modal, it just looks different.\n\n331\n00:16:21,114 --> 00:16:26,317\nPopover is just a presentation style basically for modal. So\n\n332\n00:16:26,319 --> 00:16:29,320\npopovers, you think of a popover's kind of like\n\n333\n00:16:29,322 --> 00:16:32,824\na navigational controller or split view controller, a tab\n\n334\n00:16:32,826 --> 00:16:36,294\nbar because it's putting a view controller inside another\n\n335\n00:16:36,296 --> 00:16:39,497\nanother view controller, but it's not. You should think of\n\n336\n00:16:39,499 --> 00:16:44,569\npopover just as a presentation style. Dial for modal, okay?\n\n337\n00:16:44,571 --> 00:16:48,373\nSo segue into a popover is setup the same way that you\n\n338\n00:16:48,375 --> 00:16:51,642\nsetup a oni modal one, it's just that when you drag over,\n\n339\n00:16:51,644 --> 00:16:56,080\nyou're gonna pick popover instead of modal, okay? When\n\n340\n00:16:56,082 --> 00:16:59,350\nyou're in the storyboard you drag over. Now, an important\n\n341\n00:16:59,352 --> 00:17:02,253\nthing to note when you prepare for a popover segue,\n\n342\n00:17:02,255 --> 00:17:04,455\nthis is what's different between a popover and\n\n343\n00:17:04,457 --> 00:17:10,461\nimmodal encode, okay? When you prepare all presentations of\n\n344\n00:17:10,463 --> 00:17:14,265\nany kind of segue are done by a UI presentation controller.\n\n345\n00:17:14,267 --> 00:17:17,335\nYou don't see this, I'm not really talking about this\n\n346\n00:17:17,337 --> 00:17:20,071\nin this class, it's not really kind of a introductory\n\n347\n00:17:20,073 --> 00:17:24,342\nmaterial. But, the popover one has a sub class of that called\n\n348\n00:17:24,344 --> 00:17:26,244\nUI popover presentation controller,\n\n349\n00:17:26,246 --> 00:17:27,278\nand it's in the thing that knows\n\n350\n00:17:27,280 --> 00:17:28,613\nhow to present it as a popover.\n\n351\n00:17:28,615 --> 00:17:31,516\nSo it's the thing that knows, for example, where to have\n\n352\n00:17:31,518 --> 00:17:35,053\nthe little popover thing point, okay. That's something\n\n353\n00:17:35,055 --> 00:17:39,123\nthat that popover presentation controller knows about. So in\n\n354\n00:17:39,125 --> 00:17:42,360\nyour prepare for segue, you're gonna get this UI popover\n\n355\n00:17:42,362 --> 00:17:44,462\npresentation controller and I'll show you how to do that.\n\n356\n00:17:44,464 --> 00:17:47,398\nAnd you're going to use it to configure how the popover\n\n357\n00:17:47,400 --> 00:17:51,869\npresents, okay? Now in addition to setting things\n\n358\n00:17:51,871 --> 00:17:53,805\nlike where the popover's arrow can point,\n\n359\n00:17:53,807 --> 00:17:57,008\nyou can also control things like how the popover adapts\n\n360\n00:17:57,010 --> 00:18:00,912\nto different size classes, okay? And we'll talk about\n\n361\n00:18:00,914 --> 00:18:04,615\nthat in a second too. So here's the prepare for segue,\n\n362\n00:18:04,617 --> 00:18:06,384\nthe prepare for a popover, okay?\n\n363\n00:18:06,386 --> 00:18:09,954\nAll the green, except for what's in this yellow if\n\n364\n00:18:09,956 --> 00:18:13,524\nstatement right here is the same as any other prepare. But\n\n365\n00:18:13,526 --> 00:18:14,592\nwhen we get down to the bottom here,\n\n366\n00:18:14,594 --> 00:18:17,295\nwe're gonna get that popover presentation controller by\n\n367\n00:18:17,297 --> 00:18:20,698\nasking the view controller that we're putting up modally.\n\n368\n00:18:20,700 --> 00:18:24,402\nPlease give me your popover presentation controller,\n\n369\n00:18:24,404 --> 00:18:27,271\nokay? So that view controller has the popover presentation\n\n370\n00:18:27,273 --> 00:18:30,475\ngoing. We get it. Once we have it, we can do things like\n\n371\n00:18:30,477 --> 00:18:33,044\nconfigure it like the permitted arrow directions.\n\n372\n00:18:33,046 --> 00:18:35,980\nWhich direction we want the arrow to be? We can also\n\n373\n00:18:35,982 --> 00:18:40,118\nspecify things like where the arrows are pointing,\n\n374\n00:18:40,120 --> 00:18:40,852\nall that kind of stuff.\n\n375\n00:18:40,854 --> 00:18:44,021\nOkay, everything you would imagine a popover needs to be\n\n376\n00:18:44,023 --> 00:18:47,158\nconfigured with. All right, now also importantly,\n\n377\n00:18:47,160 --> 00:18:51,863\nwe can set that presentation controllers delegate, okay?\n\n378\n00:18:51,865 --> 00:18:54,365\nAnd with that delegate we control a little bit more\n\n379\n00:18:54,367 --> 00:18:56,701\nabout how the popover works. So let's talk about that.\n\n380\n00:18:56,703 --> 00:19:00,004\nWhat can we do with the delegate? One thing we can do\n\n381\n00:19:00,006 --> 00:19:04,942\nis find out when that popover was dismissed, okay? So\n\n382\n00:19:04,944 --> 00:19:06,144\nthe delegate will be sent this message,\n\n383\n00:19:06,146 --> 00:19:08,946\npopoverPresentationController- DidDismissPopover.\n\n384\n00:19:08,948 --> 00:19:11,782\nDid dismiss popover. Okay, so that's nice to be able to\n\n385\n00:19:11,784 --> 00:19:14,919\nknow when that popover was dismissed. Another thing is we\n\n386\n00:19:14,921 --> 00:19:18,623\ncan control the adaptation behavior when we're in\n\n387\n00:19:18,625 --> 00:19:22,193\ndifferent size classes like horizontally compact,\n\n388\n00:19:22,195 --> 00:19:25,029\nokay? So when a popover comes up, as you can\n\n389\n00:19:25,031 --> 00:19:28,032\nimagine, maybe it wouldn't fit in a horizontally compact\n\n390\n00:19:28,034 --> 00:19:30,535\nenvironment unless it's kind of the small popover.\n\n391\n00:19:30,537 --> 00:19:34,839\nSo by default, the system adapts to full screen.\n\n392\n00:19:34,841 --> 00:19:37,642\nSo if you have a popover segue and it's on horizontally\n\n393\n00:19:37,644 --> 00:19:41,812\ncompact, it gets changed to modal full screen. So it'll\n\n394\n00:19:41,814 --> 00:19:44,182\ntake over the whole screen, slide up from the bottom.\n\n395\n00:19:44,184 --> 00:19:46,751\nOkay, now you might now want that. Maybe it is a small\n\n396\n00:19:46,753 --> 00:19:49,687\nlittle popover and you do want it to be a pop over on iPhone\n\n397\n00:19:49,689 --> 00:19:52,590\nand you can control that. And here's how you do that.\n\n398\n00:19:52,592 --> 00:19:55,526\nThere is a method. Okay, this is a popover. This is actually\n\n399\n00:19:55,528 --> 00:19:59,397\na presentation controller delegate method. And\n\n400\n00:19:59,399 --> 00:20:01,832\nyou can see it just sends you the controller here and\n\n401\n00:20:01,834 --> 00:20:05,903\na traitCollection. So that's the size class is right here\n\n402\n00:20:05,905 --> 00:20:07,905\nand you're gonna return a presentation style.\n\n403\n00:20:07,907 --> 00:20:10,975\nNow, if you don't implement this delegation method, then\n\n404\n00:20:10,977 --> 00:20:14,278\nin horizontally compact, it returns full screen otherwise,\n\n405\n00:20:14,280 --> 00:20:16,714\nit returns whatever it was setup in the storyboard,\n\n406\n00:20:16,716 --> 00:20:19,217\npopover or form sheet or whatever. But\n\n407\n00:20:19,219 --> 00:20:21,919\nif you do implement it, you could return for example UI\n\n408\n00:20:21,921 --> 00:20:25,823\nmodal presentation style none which means don't adapt.\n\n409\n00:20:25,825 --> 00:20:29,093\nThis is asking for, how do I adapt to this trait\n\n410\n00:20:29,095 --> 00:20:31,796\ncollection. If you say none, that means don't adapt.\n\n411\n00:20:31,798 --> 00:20:34,031\nJust do the same thing on every single platform.\n\n412\n00:20:34,033 --> 00:20:37,068\nOkay, and so if you do this, then your popover will appear\n\n413\n00:20:37,070 --> 00:20:40,071\nas a popover on your iPhone. Look just like on an iPad but\n\n414\n00:20:40,073 --> 00:20:43,140\nit better be small coz it didn't have a lot of room.\n\n415\n00:20:43,142 --> 00:20:47,178\nSo this is how you can control that adaptation behavior,\n\n416\n00:20:47,180 --> 00:20:49,747\nokay. But here's a problem, let's say you\n\n417\n00:20:49,749 --> 00:20:52,316\ndo that, okay, let's say you don't do that. Let's say\n\n418\n00:20:52,318 --> 00:20:54,885\nthe popover is too big and it comes up full screen,\n\n419\n00:20:54,887 --> 00:20:59,624\nhow do you dismiss that popover, okay? Because it used\n\n420\n00:20:59,626 --> 00:21:01,592\nto be a popover I could click somewhere else and\n\n421\n00:21:01,594 --> 00:21:03,494\nit will disappear. But now it's full screen.\n\n422\n00:21:03,496 --> 00:21:06,464\nI can't click anywhere else. How do I dismiss it? Okay,\n\n423\n00:21:06,466 --> 00:21:08,599\nthat's a problem. What would be really cool,\n\n424\n00:21:08,601 --> 00:21:11,335\nis if you could put it inside a navigation controller and\n\n425\n00:21:11,337 --> 00:21:15,740\nthen add a little done button, right at the top? And\n\n426\n00:21:15,742 --> 00:21:18,242\nthis method is how you do that. So, if you implement\n\n427\n00:21:18,244 --> 00:21:20,911\nthe delegate of the popover presentation controller, and\n\n428\n00:21:20,913 --> 00:21:22,713\nyou implement this thing, view controller for\n\n429\n00:21:22,715 --> 00:21:25,650\nadapter presentation style, it allows you to return\n\n430\n00:21:25,652 --> 00:21:30,655\na different view controller to present. For example,\n\n431\n00:21:30,657 --> 00:21:33,057\nyou might, preser, present, return a navigation\n\n432\n00:21:33,059 --> 00:21:36,994\ncontroller. Whose visible view controller is, the actual view\n\n433\n00:21:36,996 --> 00:21:39,897\ncontroller that was inside the popover, you see. And\n\n434\n00:21:39,899 --> 00:21:42,633\nyou could add a done button to it or whatever you want. So\n\n435\n00:21:42,635 --> 00:21:44,435\nhere you can return, if you return nil here\n\n436\n00:21:44,437 --> 00:21:47,338\nit's going to just return the thing that was inside,\n\n437\n00:21:47,340 --> 00:21:48,339\ngonna be inside the popover.\n\n438\n00:21:48,341 --> 00:21:50,374\nBut if you return the navigation controller or\n\n439\n00:21:50,376 --> 00:21:53,311\nwhatever, it'll put that up In the modal adapted. And this is\n\n440\n00:21:53,313 --> 00:21:56,280\nonly happening in the adapted case, right? View control for\n\n441\n00:21:56,282 --> 00:22:01,652\nadapted presentation style, okay? All right,\n\n442\n00:22:01,654 --> 00:22:04,789\nvery important issue about popover is its size, okay?\n\n443\n00:22:04,791 --> 00:22:07,625\niOS implements its size in a very object-jointed way,\n\n444\n00:22:07,627 --> 00:22:10,828\nwhich is that when you have an MVC that's gonna be put up as\n\n445\n00:22:10,830 --> 00:22:14,131\na popover, the system asks that MVC what size would\n\n446\n00:22:14,133 --> 00:22:15,466\nyou prefer it to be?\n\n447\n00:22:15,468 --> 00:22:18,102\nOkay, because that MVC obviously knows what the best\n\n448\n00:22:18,104 --> 00:22:22,139\nsize for it to be is, and it does that via this var\n\n449\n00:22:22,141 --> 00:22:25,643\npreferredContentSize is a CGSize and you can either\n\n450\n00:22:25,645 --> 00:22:29,947\nset this preferredContectSize. The MVC can set its\n\n451\n00:22:29,949 --> 00:22:32,550\nown preferredContectSize to something reasonable or\n\n452\n00:22:32,552 --> 00:22:34,652\nyou could actually even override it. And\n\n453\n00:22:34,654 --> 00:22:38,789\nhave it return its correct size, its prefered size.\n\n454\n00:22:38,791 --> 00:22:42,059\nIt's called preferred by the way because, obviously\n\n455\n00:22:42,061 --> 00:22:44,395\nthe system will try to fit it on screen but if, for\n\n456\n00:22:44,397 --> 00:22:47,298\nexample, it's on horizontally compact and the adaptive thing\n\n457\n00:22:47,300 --> 00:22:49,734\nis turned off then it might have to jam it in there,\n\n458\n00:22:49,736 --> 00:22:51,769\nit might have to be a little smaller than preferred wants\n\n459\n00:22:51,771 --> 00:22:55,973\nit to be, kay? So this is not guaranteed to be this size,\n\n460\n00:22:55,975 --> 00:23:00,878\nthis size is preferred. Okay, the last segue I'm gonna talk\n\n461\n00:23:00,880 --> 00:23:03,781\nabout is embed segues, okay? These are really,\n\n462\n00:23:03,783 --> 00:23:07,785\nreally cool segues. Basically you could take an MVC,\n\n463\n00:23:07,787 --> 00:23:10,321\ntake its view, you know, the top level view, and\n\n464\n00:23:10,323 --> 00:23:14,225\nput it as a view inside the view hierarchy of another MVC.\n\n465\n00:23:14,227 --> 00:23:17,061\nOkay it'll look just a view in another MVC, it's just that,\n\n466\n00:23:17,063 --> 00:23:19,130\nit's completely controlled by an MVC,\n\n467\n00:23:19,132 --> 00:23:21,699\nokay? Really cool that's why it's called embedded.\n\n468\n00:23:21,701 --> 00:23:24,301\nYou're embedding an MVC inside of another one.\n\n469\n00:23:24,303 --> 00:23:25,736\nXcode makes it really easy to do this.\n\n470\n00:23:25,738 --> 00:23:30,174\nJust go down to your little object pallet down there where\n\n471\n00:23:30,176 --> 00:23:31,809\nyou get your buttons and stuff. And look for\n\n472\n00:23:31,811 --> 00:23:35,646\ncontainer view and drag that into the place that you want\n\n473\n00:23:35,648 --> 00:23:38,215\nthis thing to be embedded. It will look just like a view,\n\n474\n00:23:38,217 --> 00:23:40,184\nyou can do auto layout constraints on it.\n\n475\n00:23:40,186 --> 00:23:42,653\nYou can put it as a sub-view of anything else you want.\n\n476\n00:23:42,655 --> 00:23:45,656\nIt's just a view, okay. And when you do it,\n\n477\n00:23:45,658 --> 00:23:50,060\nyou're gonna see this kind of cool look where it puts what\n\n478\n00:23:50,062 --> 00:23:51,529\nlooks like a Segue way thing.\n\n479\n00:23:51,531 --> 00:23:53,998\nOkay, here's the thing in the container, what I dragged out.\n\n480\n00:23:54,000 --> 00:23:57,535\nThis segue right here and here's the NVC. Okay so\n\n481\n00:23:57,537 --> 00:24:00,905\nhere's the normal NVC like in your storyboard anywhere else,\n\n482\n00:24:00,907 --> 00:24:03,874\nand it's got this little segue here, so kinda seem like\n\n483\n00:24:03,876 --> 00:24:06,177\na segue and it is in the sense kinda segue to it.\n\n484\n00:24:06,179 --> 00:24:09,380\nIt's just that instead of doing it modelly or something\n\n485\n00:24:09,382 --> 00:24:12,383\nthat, it's just going to put its view right in here.\n\n486\n00:24:12,385 --> 00:24:16,320\nOkay, make sense and you can prepare for that segue,\n\n487\n00:24:16,322 --> 00:24:20,224\nit's a perfectly normal segue. One thing to be careful\n\n488\n00:24:20,226 --> 00:24:22,660\nabout this though is the View Loading Timing.\n\n489\n00:24:22,662 --> 00:24:24,662\nRemember that when you're in prepare for segue,\n\n490\n00:24:24,664 --> 00:24:27,431\nnone of the outlets of the MVC are set. And that's true with\n\n491\n00:24:27,433 --> 00:24:30,067\nembed as well, all right? So might have this embed segue,\n\n492\n00:24:30,069 --> 00:24:33,003\nhas all this cool UI but none of its outlets are set up. So\n\n493\n00:24:33,005 --> 00:24:35,606\na lot of times in the embed, when you're preparing for\n\n494\n00:24:35,608 --> 00:24:38,509\nan embed segue, you're just grabbing the MVC and\n\n495\n00:24:38,511 --> 00:24:40,377\nholding onto it with a pointer. And\n\n496\n00:24:40,379 --> 00:24:42,613\nthen later like in your own viewDidLoad,\n\n497\n00:24:42,615 --> 00:24:46,283\nokay your MVC will be loaded by then, then you can go and\n\n498\n00:24:46,285 --> 00:24:49,153\nset whatever you want to the embayed, the embedded thing to\n\n499\n00:24:49,155 --> 00:24:52,189\nlook like okay. So just be careful of that.\n\n500\n00:24:52,191 --> 00:24:55,259\nIt's just standard thing here that prepare for\n\n501\n00:24:55,261 --> 00:24:59,230\nsegue outlets aren't set in the destination MVC but for\n\n502\n00:24:59,232 --> 00:25:02,566\nembed it comes, it's even more obvious, kinda,\n\n503\n00:25:02,568 --> 00:25:07,571\nit bites you more often. Okay, so that's segues. Okay,\n\n504\n00:25:07,573 --> 00:25:10,741\nthat's all the segues there are. Okay, Ben, now you can\n\n505\n00:25:10,743 --> 00:25:14,011\ncover. Yeah, question? >> So, so in, in that segues,\n\n506\n00:25:14,013 --> 00:25:16,814\nif you have an existing view controller,\n\n507\n00:25:16,816 --> 00:25:18,816\ncan you connect into the inside or\n\n508\n00:25:18,818 --> 00:25:21,852\ndoes it have to look funny like, you know?\n\n509\n00:25:21,854 --> 00:25:22,887\n>> Yeah so the question is can\n\n510\n00:25:22,889 --> 00:25:26,190\nI connect just a regular mvc from somewhere like maybe my\n\n511\n00:25:26,192 --> 00:25:29,059\nCassini image view controller for example. It's just\n\n512\n00:25:29,061 --> 00:25:31,328\nsitting around there. Could I embed it? And the answer is\n\n513\n00:25:31,330 --> 00:25:35,199\nyes you can. Okay the mvc has embedded nothing special about\n\n514\n00:25:35,201 --> 00:25:39,803\nit whatsoever okay it can be embedded just as easily.\n\n515\n00:25:40,206 --> 00:25:43,774\nAll right. Core Location is my next topic.\n\n516\n00:25:43,776 --> 00:25:45,309\nOkay we're done with segues now we're moving on to\n\n517\n00:25:45,311 --> 00:25:49,413\nCore Location and map kit here. So Core Location and map\n\n518\n00:25:49,415 --> 00:25:53,417\nkit are really two part pieces of the same puzzle here.\n\n519\n00:25:53,419 --> 00:25:57,121\nCore Location is the non-UI way to find out about your\n\n520\n00:25:57,123 --> 00:26:01,258\nlocation. Okay? And then map kit is the bunch of UI to show\n\n521\n00:26:01,260 --> 00:26:04,028\nyour location on maps and stuff. So when you talk about\n\n522\n00:26:04,030 --> 00:26:06,297\ncorrelation first because it has a lot of the intrinsic\n\n523\n00:26:06,299 --> 00:26:09,099\nstuff that you need to understand the map kit stuff.\n\n524\n00:26:09,101 --> 00:26:13,537\nAll right. The basic object in core location is called\n\n525\n00:26:13,539 --> 00:26:17,641\na CLLocation. Core location, location. CLLocation has\n\n526\n00:26:17,643 --> 00:26:21,145\nthe coordinate latitude and longitude, altitude,\n\n527\n00:26:21,147 --> 00:26:24,481\nthe horizontal and vertical accuracy of this location,\n\n528\n00:26:24,483 --> 00:26:27,551\nbecause sometimes depending on how you got this location,\n\n529\n00:26:27,553 --> 00:26:28,552\nit might be highly accurate,\n\n530\n00:26:28,554 --> 00:26:29,887\nyou know, within a meter or so, or\n\n531\n00:26:29,889 --> 00:26:32,222\nmight be very inaccurate, maybe it's a kilometer.\n\n532\n00:26:32,224 --> 00:26:35,459\nOkay? Timestamp, when was this thing was taken, you'll see\n\n533\n00:26:35,461 --> 00:26:39,029\nthat that's really important. A speed if the system detected\n\n534\n00:26:39,031 --> 00:26:42,266\nthat you were moving at this time that this thing was\n\n535\n00:26:42,268 --> 00:26:45,970\ntaken, and a course will tell you what direction you were\n\n536\n00:26:45,972 --> 00:26:50,007\nheaded in if it detects that you were moving at this point.\n\n537\n00:26:50,009 --> 00:26:55,179\nSo that's the basic collection of stuff is in CLLocation.\n\n538\n00:26:55,181 --> 00:26:58,248\nThe CL, coordinate, this coordinate thing right here is\n\n539\n00:26:58,250 --> 00:27:02,019\na CLLocationCOordinate2D which is just a latitude and\n\n540\n00:27:02,021 --> 00:27:03,253\na longitude struct.\n\n541\n00:27:03,255 --> 00:27:06,023\nThe altitude is a CLLocationDistance,\n\n542\n00:27:06,025 --> 00:27:10,594\nwhich is meters. Okay? Now let's talk about\n\n543\n00:27:10,596 --> 00:27:14,932\nthe accuracy thing, okay? When you are asking for\n\n544\n00:27:14,934 --> 00:27:18,302\na location and when you get a location, in both cases,\n\n545\n00:27:18,304 --> 00:27:20,471\nyou're gonna specify an accuracy, okay?\n\n546\n00:27:20,473 --> 00:27:23,240\nSpecifying the accuracy is going to determine what\n\n547\n00:27:23,242 --> 00:27:25,976\nmechanism your device uses to get the accuracy. And\n\n548\n00:27:25,978 --> 00:27:29,380\nthen when you get the accuracy back It tells you, kind of,\n\n549\n00:27:29,382 --> 00:27:32,416\nhow it got it, somewhat. Okay, so, we're a little bit\n\n550\n00:27:32,418 --> 00:27:35,486\nabstracting the hardware away from the concept of\n\n551\n00:27:35,488 --> 00:27:38,889\nan accurate measurement of location. Here\n\n552\n00:27:38,891 --> 00:27:41,892\nare the different accuracies that it can have here,\n\n553\n00:27:41,894 --> 00:27:42,393\nbest for navigation,\n\n554\n00:27:42,395 --> 00:27:45,129\nbest nearest ten meters, hundred meters, kilometer,\n\n555\n00:27:45,131 --> 00:27:49,266\nor three kilometers and as you can imagine best for\n\n556\n00:27:49,268 --> 00:27:51,535\nnavigation. It's really really really really accurate.\n\n557\n00:27:51,537 --> 00:27:55,639\nIt's also really really really uses a lot of battery, okay.\n\n558\n00:27:55,641 --> 00:27:58,809\nAnd basically you can almost rename these things as\n\n559\n00:27:58,811 --> 00:27:59,810\nlots of battery usage,\n\n560\n00:27:59,812 --> 00:28:02,813\na little bit less, medium battery usage, not so\n\n561\n00:28:02,815 --> 00:28:05,883\nmuch battery usage, very very battery efficient by the time\n\n562\n00:28:05,885 --> 00:28:09,453\nyou get to the bottom. Okay? It's really batteries are big\n\n563\n00:28:09,455 --> 00:28:12,322\ndeal when it comes to getting your location. Now,\n\n564\n00:28:12,324 --> 00:28:15,926\nhow does the system get these different accuracy locations?\n\n565\n00:28:15,928 --> 00:28:19,129\nWell, there's three different ways really at least for\n\n566\n00:28:19,131 --> 00:28:21,331\nnow that the system could get location and\n\n567\n00:28:21,333 --> 00:28:23,333\nyou don't know which one is using. Okay,\n\n568\n00:28:23,335 --> 00:28:25,836\nall you get to do is specify the accuracy you want and\n\n569\n00:28:25,838 --> 00:28:28,472\nit will get the locations as best it can and re-tell you\n\n570\n00:28:28,474 --> 00:28:32,710\nwhat accuracy it got. But the three ways it knows how to do\n\n571\n00:28:32,712 --> 00:28:37,981\nare GPS which is very accurate and uses a lot of power.\n\n572\n00:28:37,983 --> 00:28:42,519\nOkay, then there's WiFi nodes. Believe it or not your phone\n\n573\n00:28:42,521 --> 00:28:45,689\ncan, as you walk around, see what WiFi nodes are around.\n\n574\n00:28:45,691 --> 00:28:48,358\nIt's got a huge database on the network of all the WiFi\n\n575\n00:28:48,360 --> 00:28:50,828\nnodes and where they are. And so based on which ones\n\n576\n00:28:50,830 --> 00:28:54,031\nare close to you, which ones you're getting good signal,\n\n577\n00:28:54,033 --> 00:28:56,266\nit can figure our generally where you are.\n\n578\n00:28:56,268 --> 00:28:57,701\nWhich is kind of a cool feature, right?\n\n579\n00:28:57,703 --> 00:29:00,571\nPretty low power, WiFi is fairly low power not as\n\n580\n00:29:00,573 --> 00:29:04,074\nlow-power as cellular towers which is the next one, and,\n\n581\n00:29:04,076 --> 00:29:07,544\nbut certainly a lot less power than doing GPS. And so,\n\n582\n00:29:07,546 --> 00:29:10,380\nit can find, you know, these kind of medium accuracies\n\n583\n00:29:10,382 --> 00:29:12,616\nby doing that. And in fact, if you walk around at Stanford,\n\n584\n00:29:12,618 --> 00:29:15,352\nit can be very accurate because there's an incredible\n\n585\n00:29:15,354 --> 00:29:17,688\nnumber of WiFi nodes around Stanford campus. You\n\n586\n00:29:17,690 --> 00:29:20,758\nare probably in range of 50 of them at almost given time.\n\n587\n00:29:20,760 --> 00:29:23,761\nCertainly 20 so, we pretty much know almost exactly where\n\n588\n00:29:23,763 --> 00:29:27,297\nyou are. And then last one is cell tower triangulation. So\n\n589\n00:29:27,299 --> 00:29:30,134\nsame way with the WiFi nodes it can look around to the cell\n\n590\n00:29:30,136 --> 00:29:33,403\ntowers. Now there's fewer cell towers than there are WiFi\n\n591\n00:29:33,405 --> 00:29:36,073\nnodes okay, and they tend to be farther away from you.\n\n592\n00:29:36,075 --> 00:29:39,843\nOkay, so triangulating them is a little more iffy okay.\n\n593\n00:29:39,845 --> 00:29:41,211\nAnd sometimes there's not one for\n\n594\n00:29:41,213 --> 00:29:44,748\nvery very far distance from you, a kilometer or more. So\n\n595\n00:29:44,750 --> 00:29:47,417\nthat's why you start getting these really low accuracies\n\n596\n00:29:47,419 --> 00:29:51,355\nout here but the cellular radio is incredibly low power.\n\n597\n00:29:51,357 --> 00:29:53,323\nSuper super low power, okay. And\n\n598\n00:29:53,325 --> 00:29:56,460\nyour cellular radio is also automatically being turned on\n\n599\n00:29:56,462 --> 00:29:58,896\nand off and used as, you know you walk around and\n\n600\n00:29:58,898 --> 00:30:01,565\nyou're making phone calls, or receiving phone calls etc. So\n\n601\n00:30:01,567 --> 00:30:03,934\nthe cellular infrastructure's very low power but\n\n602\n00:30:03,936 --> 00:30:08,939\nlow accuracy. Okay? Got all of that? All right\n\n603\n00:30:08,941 --> 00:30:10,974\nthere's other things you can find out in the core location,\n\n604\n00:30:10,976 --> 00:30:13,377\nyour speed, your course, that timestamp.\n\n605\n00:30:13,379 --> 00:30:16,113\nThe reason the time stamp is important is that there\n\n606\n00:30:16,115 --> 00:30:18,115\nare a lot of ways to ask the system to give you\n\n607\n00:30:18,117 --> 00:30:21,051\nCLLocations, not in real time. In other words it's not going\n\n608\n00:30:21,053 --> 00:30:23,554\nto give you the location right now. Like you might be going\n\n609\n00:30:23,556 --> 00:30:25,789\nout for a run and you put your phone in your pocket and\n\n610\n00:30:25,791 --> 00:30:28,559\nit goes to sleep it can still collect locations. And\n\n611\n00:30:28,561 --> 00:30:31,562\nthen when it wake back up it will send them all to you. And\n\n612\n00:30:31,564 --> 00:30:33,997\nwhen it does you're going to want to know the timestamps so\n\n613\n00:30:33,999 --> 00:30:35,065\nyou knew where you were at the time.\n\n614\n00:30:35,067 --> 00:30:39,002\nSo time stamp is an important part of the CLLocation.\n\n615\n00:30:39,004 --> 00:30:42,339\nAll right. So how do we get a CLLocation? Well, you get it\n\n616\n00:30:42,341 --> 00:30:45,676\nfrom a CLLocationManager usually. Just like we had\n\n617\n00:30:45,678 --> 00:30:47,611\na core motion, we have the CM motion manager. Well,\n\n618\n00:30:47,613 --> 00:30:51,381\nin the core location, we have the CLLocationManager. And\n\n619\n00:30:51,383 --> 00:30:53,917\nit has a delegate that's going to generally give you,\n\n620\n00:30:53,919 --> 00:30:57,387\nlocations. What's really cool about it is you can actually\n\n621\n00:30:57,389 --> 00:31:00,490\ntest in the simulator by simulating yourself being in\n\n622\n00:31:00,492 --> 00:31:03,227\ndifferent locations. If you go down near the debugger bar,\n\n623\n00:31:03,229 --> 00:31:06,830\nthere's a little guy there and that you can even upload\n\n624\n00:31:06,832 --> 00:31:09,333\nwith the GPX file. The GPX file is just\n\n625\n00:31:09,335 --> 00:31:11,235\na file with a bunch of waypoints in it, okay.\n\n626\n00:31:11,237 --> 00:31:14,438\nGPS locations can have other stuff in there like actually\n\n627\n00:31:14,440 --> 00:31:17,875\nURLs for photos taken at the location, stuff like that. But\n\n628\n00:31:17,877 --> 00:31:20,510\nit can have these location you can upload it and\n\n629\n00:31:20,512 --> 00:31:25,782\nhave whatever testing you want in here okay. So\n\n630\n00:31:25,784 --> 00:31:26,250\nthe CLLocationManager.\n\n631\n00:31:26,252 --> 00:31:29,086\nHow do you use it? Similar to the CMMotion manager. First\n\n632\n00:31:29,088 --> 00:31:31,722\nyou're going to check like to see what hardware's available.\n\n633\n00:31:31,724 --> 00:31:34,858\nOkay and then you're going to create a CLLocationManager and\n\n634\n00:31:34,860 --> 00:31:37,628\nset as delegate so that you can receive updates.\n\n635\n00:31:37,630 --> 00:31:41,198\nThen you're going to configure the manager to say what kind\n\n636\n00:31:41,200 --> 00:31:43,934\nof location you want. And we'll talk about what that\n\n637\n00:31:43,936 --> 00:31:45,836\nmeans and then you're going to start it going.\n\n638\n00:31:45,838 --> 00:31:49,006\nAnd once you start it going it's going to start sending\n\n639\n00:31:49,008 --> 00:31:52,042\nyour locations based on how you, what you asked for,\n\n640\n00:31:52,044 --> 00:31:55,112\nall right. How, what kind of location monitoring is\n\n641\n00:31:55,114 --> 00:31:58,515\navailable in the system? Well one is accuracy based\n\n642\n00:31:58,517 --> 00:32:02,452\ncontinual updates. This is what you would normally think.\n\n643\n00:32:02,454 --> 00:32:04,988\nYou set an accuracy that you want. Okay, I want\n\n644\n00:32:04,990 --> 00:32:08,525\nhighly accurate best for navigation or low accuracy and\n\n645\n00:32:08,527 --> 00:32:11,395\nthe system will start sending you locations based on that\n\n646\n00:32:11,397 --> 00:32:13,630\naccuracy. So if you ask for best for navigation it's\n\n647\n00:32:13,632 --> 00:32:15,265\ngonna be sending you locations all the time and\n\n648\n00:32:15,267 --> 00:32:17,701\nthey're gonna be highly accurate. If you ask for\n\n649\n00:32:17,703 --> 00:32:19,569\nevery three kilometers. You could walk for\n\n650\n00:32:19,571 --> 00:32:22,205\n20 minutes before it sends you another location because it\n\n651\n00:32:22,207 --> 00:32:25,742\nnotices another cell tower and can figure out its location.\n\n652\n00:32:25,744 --> 00:32:30,480\nOkay? So that's one way to do it. Another way is you can\n\n653\n00:32:30,482 --> 00:32:34,084\nget notified only when a significant location change\n\n654\n00:32:34,086 --> 00:32:37,321\nhappens, okay. This is basically, I'm not talking\n\n655\n00:32:37,323 --> 00:32:40,190\nabout how it's implemented here but I kinda am.\n\n656\n00:32:40,192 --> 00:32:44,594\nBut it's basically when it sees a new cell tower. Okay.\n\n657\n00:32:44,596 --> 00:32:47,931\nSo that's a significant enough change that it'll probably\n\n658\n00:32:47,933 --> 00:32:48,098\nsend you one. So\n\n659\n00:32:48,100 --> 00:32:54,237\nthis is not highly accurate locations necessarily. Okay.\n\n660\n00:32:54,239 --> 00:32:57,441\nThe other one is region based updates so you can define\n\n661\n00:32:57,443 --> 00:33:01,979\nthese regions either little circular areas in the world or\n\n662\n00:33:01,981 --> 00:33:06,083\neven where beacons live. Okay? Little bluetooth beacons and\n\n663\n00:33:06,085 --> 00:33:09,252\nyou can get notified when you get close to that beacon or\n\n664\n00:33:09,254 --> 00:33:10,387\nyou get real close to the beacon or\n\n665\n00:33:10,389 --> 00:33:14,157\nwhen you walk inside the circular area. Okay? And\n\n666\n00:33:14,159 --> 00:33:16,360\nthen you also can have your heading monitored if\n\n667\n00:33:16,362 --> 00:33:20,497\nyou change direction, it can send you a new location.\n\n668\n00:33:20,799 --> 00:33:23,133\nAll right, so let's talk about how we use CLO,\n\n669\n00:33:23,135 --> 00:33:26,036\nCL location manager, and then we'll talk about how to make\n\n670\n00:33:26,038 --> 00:33:28,672\neach of those things work. First we want to find out what\n\n671\n00:33:28,674 --> 00:33:32,376\nour, hardware can do. One of the most important things\n\n672\n00:33:32,378 --> 00:33:35,846\nto find out about hardware is whether you're authorized to\n\n673\n00:33:35,848 --> 00:33:38,982\nget the user's location. As you can imagine, users might\n\n674\n00:33:38,984 --> 00:33:41,518\nnot want you to know where they are, tracking their every\n\n675\n00:33:41,520 --> 00:33:45,188\nmove out there. It's kind of a sensitive subject, okay. So\n\n676\n00:33:45,190 --> 00:33:48,658\nyou have to make sure you're authorized to receive it.\n\n677\n00:33:48,660 --> 00:33:52,029\nAnd you can do this with these various things I'll talk about\n\n678\n00:33:52,031 --> 00:33:52,129\nauthorization, on the next page. By the way, anytime you\n\n679\n00:33:52,131 --> 00:33:54,831\nin detail,\n\n680\n00:33:54,833 --> 00:33:57,234\nhave an authorization status of any kind, not just for\n\n681\n00:33:57,236 --> 00:34:00,737\nlocation, you notice there's the states Authorized, Denied,\n\n682\n00:34:00,739 --> 00:34:04,641\nor Restricted. What Restricted means right there is,\n\n683\n00:34:04,643 --> 00:34:08,045\nit's denied, and the user can't change it.\n\n684\n00:34:08,047 --> 00:34:11,615\nSo don't put up an alert that says, you, I'm not authorized\n\n685\n00:34:11,617 --> 00:34:14,918\nto get your location. Please go to Settings and change it.\n\n686\n00:34:14,920 --> 00:34:16,820\nOkay because they're not allowed to. There are ways\n\n687\n00:34:16,822 --> 00:34:19,723\nin enterprises inside companies where companies can\n\n688\n00:34:19,725 --> 00:34:23,193\nconfigure the phones of their employees. So for example,\n\n689\n00:34:23,195 --> 00:34:26,396\nthey can't do this location service or other services.\n\n690\n00:34:26,398 --> 00:34:28,331\nOkay so be careful about the restricted state.\n\n691\n00:34:28,333 --> 00:34:32,102\nIt's restricted just accept the fact you can't do it.\n\n692\n00:34:32,104 --> 00:34:35,272\nAll right. And then you can also check for certain\n\n693\n00:34:35,274 --> 00:34:38,308\nkinds of monitoring like can you monitor for beacons or\n\n694\n00:34:38,310 --> 00:34:41,778\ncan you monitor for circular regions? Most new hardware can\n\n695\n00:34:41,780 --> 00:34:44,548\ndo all of these stuff or if you have an older phone maybe\n\n696\n00:34:44,550 --> 00:34:47,617\nit doesn't have the same capabilities to do that.\n\n697\n00:34:47,619 --> 00:34:50,387\nAlright? So let's talk about\n\n698\n00:34:50,389 --> 00:34:52,255\nthis authorization piece though because it is\n\n699\n00:34:52,257 --> 00:34:54,458\nvery important interesting piece to do it.\n\n700\n00:34:54,460 --> 00:34:57,160\nThere's couple of steps you have to do to make it work.\n\n701\n00:34:57,162 --> 00:35:00,797\nOne is you have to request authorization, okay.\n\n702\n00:35:00,799 --> 00:35:03,400\nThis is ASynchronous, okay. You send this to the CL\n\n703\n00:35:03,402 --> 00:35:06,336\nlocation manager and you're gonna request one of\n\n704\n00:35:06,338 --> 00:35:08,371\nthese two different kinds of authorizations.\n\n705\n00:35:08,373 --> 00:35:11,842\nIn Use Authorization or Always Authorization. So\n\n706\n00:35:11,844 --> 00:35:14,578\nInUseAuthorization means you only wanna be allowed to\n\n707\n00:35:14,580 --> 00:35:18,148\nget the location when it's the foreground app the user is\n\n708\n00:35:18,150 --> 00:35:20,784\nusing. Okay? When the user is in the background or\n\n709\n00:35:20,786 --> 00:35:22,652\nanything else, you can't find this location.\n\n710\n00:35:22,654 --> 00:35:24,287\nUsers are fairly comfortable with that level\n\n711\n00:35:24,289 --> 00:35:26,756\nof authorization cuz they know when you're getting their,\n\n712\n00:35:26,758 --> 00:35:29,860\ntheir location. AlwaysAuthorization is you can\n\n713\n00:35:29,862 --> 00:35:32,429\nget their location anytime even the background and\n\n714\n00:35:32,431 --> 00:35:35,999\nthat's very invasive of their privacy. So\n\n715\n00:35:36,001 --> 00:35:39,736\nyou know a lot of people, users won't do this.\n\n716\n00:35:39,738 --> 00:35:42,672\nThey won't give you that authorization, okay? So\n\n717\n00:35:42,674 --> 00:35:45,809\nthe system might be putting up an alert asking the user if\n\n718\n00:35:45,811 --> 00:35:48,912\nit's okay, they're checking in their settings to see what\n\n719\n00:35:48,914 --> 00:35:51,781\nsettings are there, things like that to find so\n\n720\n00:35:51,783 --> 00:35:54,651\nthat's what its asynchronous. Eventually a delegate method\n\n721\n00:35:54,653 --> 00:35:56,520\nwill be called in your CL location saying,\n\n722\n00:35:56,522 --> 00:35:58,054\nokay, here's your authorization task.\n\n723\n00:35:58,056 --> 00:36:01,925\nIt was denied or it was accept, it was allowed. Okay?\n\n724\n00:36:01,927 --> 00:36:05,729\nNow, when you go off to request this authorization,\n\n725\n00:36:05,731 --> 00:36:09,766\nyou have to have the user in their setting,\n\n726\n00:36:09,768 --> 00:36:10,433\nif they go into settings and\n\n727\n00:36:10,435 --> 00:36:13,370\nlook at location services, your app will be there,\n\n728\n00:36:13,372 --> 00:36:15,739\nthere has to be a switch they can click that says,\n\n729\n00:36:15,741 --> 00:36:20,644\nyes I'll allow my, this app to have always authorization or\n\n730\n00:36:20,646 --> 00:36:25,448\nin use authorization. To put that UI in the settings,\n\n731\n00:36:25,450 --> 00:36:28,752\nyou have to put something in your info P list. Okay?\n\n732\n00:36:28,754 --> 00:36:31,388\nWhich is this key right here NSLocation when\n\n733\n00:36:31,390 --> 00:36:32,789\nin use description or\n\n734\n00:36:32,791 --> 00:36:35,492\nNSLocation always use a description. This is a string\n\n735\n00:36:35,494 --> 00:36:41,231\nexplaining why you want this particular authorization.\n\n736\n00:36:41,233 --> 00:36:45,235\nAnd if this key exists then, in settings,\n\n737\n00:36:45,237 --> 00:36:47,837\nthe user will be able to have a switch to turn this on or\n\n738\n00:36:47,839 --> 00:36:51,007\noff. So if you don't put these in here, these things on top,\n\n739\n00:36:51,009 --> 00:36:54,344\nthese funcs will always fail. Because there's no way for\n\n740\n00:36:54,346 --> 00:36:56,479\nthe user to set that in their settings, so\n\n741\n00:36:56,481 --> 00:36:58,882\nthey'll all just always fail. Okay? And\n\n742\n00:36:58,884 --> 00:37:02,118\nthe system can't put up an alert even asking if it's okay\n\n743\n00:37:02,120 --> 00:37:03,920\nbecause if they said yes there's no way,\n\n744\n00:37:03,922 --> 00:37:06,189\nthere's no switch for the system to turn on.\n\n745\n00:37:06,191 --> 00:37:07,891\nSo you'd just be always denied, so\n\n746\n00:37:07,893 --> 00:37:13,296\nyou need these two steps to get authorization. All right.\n\n747\n00:37:13,298 --> 00:37:17,167\nNow, how do you then get the CL location from the location\n\n748\n00:37:17,169 --> 00:37:19,002\nmanager? Of course you can pull, but\n\n749\n00:37:19,004 --> 00:37:21,705\nlike with motion manager we say that's not a good idea.\n\n750\n00:37:21,707 --> 00:37:24,341\nBut what you can do you can just ask the location manager\n\n751\n00:37:24,343 --> 00:37:25,075\nplease give me the current location. And\n\n752\n00:37:25,077 --> 00:37:28,178\nit will give you the location with whatever accuracy it has.\n\n753\n00:37:28,180 --> 00:37:31,648\nOkay but really the way we do it is we set this var\n\n754\n00:37:31,650 --> 00:37:34,384\nin the location manager called desired accuracy.\n\n755\n00:37:34,386 --> 00:37:36,620\nThat's one of those accuracies like best for navigation and\n\n756\n00:37:36,622 --> 00:37:39,723\nall those things. And then also a distance filter which\n\n757\n00:37:39,725 --> 00:37:43,360\nis how far the user has to move before we're gonna give\n\n758\n00:37:43,362 --> 00:37:46,863\na new location. Okay? So, if you take ten meters,\n\n759\n00:37:46,865 --> 00:37:50,033\nyou just gotta walk ten meters down the way before another\n\n760\n00:37:50,035 --> 00:37:50,867\nlocation will come. And\n\n761\n00:37:50,869 --> 00:37:53,970\nthose two things together will give the system a good idea of\n\n762\n00:37:53,972 --> 00:37:57,807\nhow hard it has to work to get the users location. Okay. So\n\n763\n00:37:57,809 --> 00:38:01,611\nyou set those and then you say start updating the location.\n\n764\n00:38:01,613 --> 00:38:04,481\nAnd as soon as you say start updating location, as long as\n\n765\n00:38:04,483 --> 00:38:07,250\nyou've set these, you're going to start getting locations\n\n766\n00:38:07,252 --> 00:38:11,588\nappropriate to these settings up here. Now, be sure,\n\n767\n00:38:11,590 --> 00:38:12,455\njust like with the motion manager,\n\n768\n00:38:12,457 --> 00:38:14,924\nin fact even more importantly than the motion manager,\n\n769\n00:38:14,926 --> 00:38:17,627\nto stop them when you're not gonna do anything with\n\n770\n00:38:17,629 --> 00:38:20,430\nthe results. If locations are coming, and you're ignoring\n\n771\n00:38:20,432 --> 00:38:23,967\nthem, you should have stopped it because this is basically\n\n772\n00:38:23,969 --> 00:38:26,102\nturn on battery save. [LAUGH] Okay. If you turn, turn,\n\n773\n00:38:26,104 --> 00:38:29,072\nif you don't stop updating location and\n\n774\n00:38:29,074 --> 00:38:31,141\nyou're not using it, you're just draining your battery for\n\n775\n00:38:31,143 --> 00:38:33,043\nnothing, it's probably the number one way to drain\n\n776\n00:38:33,045 --> 00:38:37,480\ntheir battery, actually. Okay. And you people will rapidly,\n\n777\n00:38:37,482 --> 00:38:40,550\nyou'll get it on your app store thing on the comments\n\n778\n00:38:40,552 --> 00:38:42,886\nit'll say drained your battery don't buy this thing.\n\n779\n00:38:42,888 --> 00:38:46,890\nOkay? So you want to be really careful not to do that. Okay.\n\n780\n00:38:46,892 --> 00:38:50,160\nSo once you turn it on you're gonna start getting this\n\n781\n00:38:50,162 --> 00:38:54,698\ndelegate method sent to you. Did update locations is plural\n\n782\n00:38:54,700 --> 00:38:56,333\nwhich in a, within array of locations.\n\n783\n00:38:56,335 --> 00:38:58,535\nNow, why is that an array of locations instead of\n\n784\n00:38:58,537 --> 00:39:00,170\njust sending you each location one by one.\n\n785\n00:39:00,172 --> 00:39:03,073\nWell, it's that running example, you got for a run,\n\n786\n00:39:03,075 --> 00:39:06,343\nyour phone goes to sleep, it collects a bunch of locations\n\n787\n00:39:06,345 --> 00:39:09,312\nand I'm not gonna talk about how you'd set that up but\n\n788\n00:39:09,314 --> 00:39:11,781\nyou can look in the documentation. And when you're\n\n789\n00:39:11,783 --> 00:39:14,317\npick your phone up and then and say, how was my run. Boom!\n\n790\n00:39:14,319 --> 00:39:16,619\nYou're gonna get all these locations as an array here.\n\n791\n00:39:16,621 --> 00:39:19,289\nOkay, with time stamps and all that, so you'll be able to\n\n792\n00:39:19,291 --> 00:39:23,727\nreconstruct the run. Okay, similar APIs this, for\n\n793\n00:39:23,729 --> 00:39:27,797\nheading, if you wanna just monitor the user's heading.\n\n794\n00:39:28,333 --> 00:39:29,799\nError reporting is important and\n\n795\n00:39:29,801 --> 00:39:32,669\neasy to miss because you have to implement another delegate\n\n796\n00:39:32,671 --> 00:39:35,171\nmethod here, which is locationManagerDidFailWithEr-\n\n797\n00:39:35,173 --> 00:39:38,908\nror. But you definitely do want to be looking at this.\n\n798\n00:39:38,910 --> 00:39:39,142\nOkay if you have,\n\n799\n00:39:39,144 --> 00:39:41,478\nif you are using a location you have to implement this.\n\n800\n00:39:41,480 --> 00:39:45,148\nBecause for example the user could at any time go to their\n\n801\n00:39:45,150 --> 00:39:45,215\nsay no I don't want this guy using my location.\n\n802\n00:39:45,217 --> 00:39:46,916\nsettings and\n\n803\n00:39:46,918 --> 00:39:50,420\nIn which case you're gonna start getting this denied.\n\n804\n00:39:50,422 --> 00:39:53,289\nAnd if you don't look for this, your output's just gonna\n\n805\n00:39:53,291 --> 00:39:55,792\ngo into some wacky state because it's not gonna know\n\n806\n00:39:55,794 --> 00:39:57,861\nwhat's happening. Okay you need to what's happening.\n\n807\n00:39:57,863 --> 00:40:01,598\nAlso, error location unknown. If from some reason, it,\n\n808\n00:40:01,600 --> 00:40:04,300\nwe can't find the location. Maybe you asked for best for\n\n809\n00:40:04,302 --> 00:40:07,404\nnavigation, it just can't find any, thing to give you your\n\n810\n00:40:07,406 --> 00:40:10,273\nlocation, so you wanna know that as well, okay?\n\n811\n00:40:10,275 --> 00:40:11,808\nSo definitely wanna look at this thing.\n\n812\n00:40:11,810 --> 00:40:14,978\nIf you're doing location manager in your final project,\n\n813\n00:40:14,980 --> 00:40:19,482\nyou got to implement this, okay? All right,\n\n814\n00:40:19,484 --> 00:40:21,718\nlets talk about getting your location in the background,\n\n815\n00:40:21,720 --> 00:40:24,487\nverses about getting your location in the foreground.\n\n816\n00:40:24,489 --> 00:40:26,723\nOkay, so when you get in the foreground it's all\n\n817\n00:40:26,725 --> 00:40:29,225\nthe things we just talked about.\n\n818\n00:40:29,227 --> 00:40:31,628\nThere's a bird in here with it.\n\n819\n00:40:31,630 --> 00:40:32,929\nWhen you're in the background, though,\n\n820\n00:40:32,931 --> 00:40:34,764\nthings are a little different because you know that\n\n821\n00:40:34,766 --> 00:40:36,800\ngenerally you're not allowed to run in the background.\n\n822\n00:40:36,802 --> 00:40:40,170\nYou kind of go quiet, and then you get in those cycles. But\n\n823\n00:40:40,172 --> 00:40:42,439\nthere are ways you, you remember when we went and\n\n824\n00:40:42,441 --> 00:40:45,408\nenabled iCloud in that capabilities thing? Well,\n\n825\n00:40:45,410 --> 00:40:48,478\nthere's things in there where you can enable backgrounding\n\n826\n00:40:48,480 --> 00:40:52,015\nfor locations, okay? Now if you do this\n\n827\n00:40:52,017 --> 00:40:53,883\nyou will continue to get stuff in the background.\n\n828\n00:40:53,885 --> 00:40:56,653\nYou can imagine it's even more important to be sure you're\n\n829\n00:40:56,655 --> 00:40:58,188\nnot sucking the battery at this,\n\n830\n00:40:58,190 --> 00:41:01,090\nin this situation, okay? And this is the kind of thing,\n\n831\n00:41:01,092 --> 00:41:03,326\nif you're sucking the battery in the background there,\n\n832\n00:41:03,328 --> 00:41:06,162\nyour App Store app might not get approved, okay?\n\n833\n00:41:06,164 --> 00:41:07,764\nThat's how important it is not to be sitting there\n\n834\n00:41:07,766 --> 00:41:10,633\nsucking the battery in the background, okay? Now,\n\n835\n00:41:10,635 --> 00:41:14,304\nthere are other ways though, very battery-efficient ways,\n\n836\n00:41:14,306 --> 00:41:15,738\nto get your location in the background, so\n\n837\n00:41:15,740 --> 00:41:19,476\nlet's talk about those. One is that significant monitoring I\n\n838\n00:41:19,478 --> 00:41:22,779\nthing I was telling you about where you're walking around,\n\n839\n00:41:22,781 --> 00:41:24,814\nand it notices a new cell tower so\n\n840\n00:41:24,816 --> 00:41:27,183\nit's very kind of large grained.\n\n841\n00:41:27,185 --> 00:41:29,953\nThat's an awesome way to get locations for\n\n842\n00:41:29,955 --> 00:41:33,289\nvery low battery, uses almost no battery to do this. And\n\n843\n00:41:33,291 --> 00:41:35,959\nwhat's more and really cool about it, if you're app is in\n\n844\n00:41:35,961 --> 00:41:39,662\nthe background. You'll get the notification if it's not even\n\n845\n00:41:39,664 --> 00:41:44,234\nrunning, it will get launched and told this information. So\n\n846\n00:41:44,236 --> 00:41:49,472\nthis a very powerful telling you where the location is.\n\n847\n00:41:49,474 --> 00:41:51,074\nAnd when it gets launched, by the way, if,\n\n848\n00:41:51,076 --> 00:41:53,776\nif they're using some other app, it will launch it and\n\n849\n00:41:53,778 --> 00:41:54,844\nlaunch you in the background.\n\n850\n00:41:54,846 --> 00:41:56,513\nSo you can figure out where you are and\n\n851\n00:41:56,515 --> 00:41:57,747\ndecide if you need to do something.\n\n852\n00:41:57,749 --> 00:42:00,416\nOkay, so this one is really cool, really low power,\n\n853\n00:42:00,418 --> 00:42:03,520\nthe only problem with it, it's large grained. Now,\n\n854\n00:42:03,522 --> 00:42:06,823\nonce you get woken up, that you've significantly changed,\n\n855\n00:42:06,825 --> 00:42:10,793\nyou could start doing more close location, KGPS location,\n\n856\n00:42:10,795 --> 00:42:12,662\ntry and find out a little bit exactly where you are,\n\n857\n00:42:12,664 --> 00:42:16,666\nif you want. Although be careful not to take too long,\n\n858\n00:42:16,668 --> 00:42:17,133\nwhen you get launched for\n\n859\n00:42:17,135 --> 00:42:19,802\nthis in the background because the system will stop doing\n\n860\n00:42:19,804 --> 00:42:24,674\nthis. If you, you know starts consuming a lot of resources\n\n861\n00:42:24,676 --> 00:42:29,779\nin the background there, okay? So be careful with that.\n\n862\n00:42:29,781 --> 00:42:32,615\nSimilarly is the region base monitoring, okay?\n\n863\n00:42:32,617 --> 00:42:34,551\nWhere you specify a circle or beacons,\n\n864\n00:42:34,553 --> 00:42:38,254\nokay? That also will wake you up and even launch your\n\n865\n00:42:38,256 --> 00:42:41,991\napplication if it notices you going into that region. Okay,\n\n866\n00:42:41,993 --> 00:42:45,862\nand run you in the background. Also low power, you know,\n\n867\n00:42:45,864 --> 00:42:48,798\nreally nice way to do it. So if that will meet your needs\n\n868\n00:42:48,800 --> 00:42:52,535\nas well, that's a good one to do, okay.\n\n869\n00:42:52,537 --> 00:42:56,039\nWhen you enter a region, either beacon or\n\n870\n00:42:56,041 --> 00:42:59,576\ncircular region, you're gonna get these delegate methods.\n\n871\n00:42:59,578 --> 00:43:01,244\ndidEnterRegion, didExitRegion, and\n\n872\n00:43:01,246 --> 00:43:05,114\nmonitoringDidFailForRegion. Also here's the error handler\n\n873\n00:43:05,116 --> 00:43:09,118\nfor that one, okay? So that's kind of a fun one.\n\n874\n00:43:09,120 --> 00:43:12,355\nRegion-monitoring works when you're not running because all\n\n875\n00:43:12,357 --> 00:43:15,592\nyour regions are named, okay? They all have to have unique\n\n876\n00:43:15,594 --> 00:43:18,695\nnames, and so when you get launched you'll know which one\n\n877\n00:43:18,697 --> 00:43:23,600\nfired by its name. You also, there is by the way a maximum\n\n878\n00:43:23,602 --> 00:43:26,269\nlimit to the circular region called maximum region\n\n879\n00:43:26,271 --> 00:43:28,504\nmonitoring distance, you want to look at that.\n\n880\n00:43:28,506 --> 00:43:30,940\nYou can't say when I enter the United States,\n\n881\n00:43:30,942 --> 00:43:33,009\nokay that won't take that big of a region.\n\n882\n00:43:33,011 --> 00:43:36,546\nIt has to be much much smaller,and this will tell you\n\n883\n00:43:36,548 --> 00:43:41,084\nhow big it can be, okay? This is the beacon thing.\n\n884\n00:43:41,086 --> 00:43:42,518\nWhen you're looking for beacons,\n\n885\n00:43:42,520 --> 00:43:45,288\nwhat you're really interested in is how far from the beacon\n\n886\n00:43:45,290 --> 00:43:48,858\nam I? Okay, am I close to it, like really, really next to\n\n887\n00:43:48,860 --> 00:43:51,294\nit? Or a little bit far away or across the ways. So\n\n888\n00:43:51,296 --> 00:43:54,364\nbeacons are used for things like, you're going to a coffee\n\n889\n00:43:54,366 --> 00:43:56,599\nshop and when you get right up to the register.\n\n890\n00:43:56,601 --> 00:43:58,701\nMaybe it offers you a coupon or something like that,\n\n891\n00:43:58,703 --> 00:44:00,803\nwell it needs to know you're right near the register.\n\n892\n00:44:00,805 --> 00:44:03,773\nBut maybe when you just walk in the store it just gives you\n\n893\n00:44:03,775 --> 00:44:07,010\nan advertisement or directs you to some display, okay?\n\n894\n00:44:07,012 --> 00:44:09,679\nSo the beacon would be sitting maybe near the register and\n\n895\n00:44:09,681 --> 00:44:12,515\nso this thing is telling you. That's why we call it ranging,\n\n896\n00:44:12,517 --> 00:44:15,652\nstart ranging these beacons. Now these beacons could be\n\n897\n00:44:15,654 --> 00:44:19,055\nother iOS devices, could serve as a beacon, okay? Or\n\n898\n00:44:19,057 --> 00:44:23,159\nyou could even buy these third party stand alone eye beacons\n\n899\n00:44:23,161 --> 00:44:26,963\nbasically that will act as beacons. If you wanted to be\n\n900\n00:44:26,965 --> 00:44:30,033\na beacon, okay, that's beyond the scope of this class.\n\n901\n00:44:30,035 --> 00:44:32,135\nI can't really tell you how to do that, okay.\n\n902\n00:44:32,137 --> 00:44:35,471\nYou need to get the Core Bluetooth Framework involved\n\n903\n00:44:35,473 --> 00:44:37,940\nhere and check out CBPeripheralManager.\n\n904\n00:44:37,942 --> 00:44:41,344\nIt will show you how to do it but it's a little more\n\n905\n00:44:41,346 --> 00:44:44,747\ncomplicated than I can show in a couple slides so.\n\n906\n00:44:44,749 --> 00:44:48,084\nSo that's it for core location. Let's now talk about\n\n907\n00:44:48,086 --> 00:44:50,687\nMap Kit which is the UI way of showing location.\n\n908\n00:44:50,689 --> 00:44:55,191\nMKMapView is a UI view that displays a map, okay?\n\n909\n00:44:55,193 --> 00:44:59,862\nLooks just like the maps app, on iOS.\n\n910\n00:44:59,864 --> 00:45:03,533\nA map can have annotations, like this little red pin\n\n911\n00:45:03,535 --> 00:45:07,570\ndown there, okay? Each annotation has a coordinate,\n\n912\n00:45:07,572 --> 00:45:11,140\nobviously the GPS location where that thing is, and also\n\n913\n00:45:11,142 --> 00:45:15,545\na title. And a subtitle, okay, there's no subtitle shown\n\n914\n00:45:15,547 --> 00:45:16,412\nin this one right here,\n\n915\n00:45:16,414 --> 00:45:21,451\nokay? The annotations though can also have this call out,\n\n916\n00:45:21,453 --> 00:45:24,587\nthis white area. That's not part of the annotation view,\n\n917\n00:45:24,589 --> 00:45:29,625\nthat's a call out that the annotation view brings up. So\n\n918\n00:45:29,627 --> 00:45:32,595\nwe're going to talk about the components of this callout\n\n919\n00:45:32,597 --> 00:45:35,431\nin a second as well. Actually it's talking right now.\n\n920\n00:45:35,433 --> 00:45:38,301\n[COUGH] It's got a left accessory view and\n\n921\n00:45:38,303 --> 00:45:39,335\na right accessory view.\n\n922\n00:45:39,337 --> 00:45:42,505\nAnd these are usually things like UI image views or\n\n923\n00:45:42,507 --> 00:45:46,843\nmaybe UI buttons things like that, okay. So this is how\n\n924\n00:45:46,845 --> 00:45:51,047\nwe're going to build our map UIs out of these components.\n\n925\n00:45:51,049 --> 00:45:52,281\nSo how do you create with MapView?\n\n926\n00:45:52,283 --> 00:45:55,852\nReally easy. MKMapView or MKMapView with a frame,\n\n927\n00:45:55,854 --> 00:45:59,388\ninitializer, or you can drag it out in your storyboard,\n\n928\n00:45:59,390 --> 00:46:02,759\nwhich is what we'll do in the demo. And MapView, what\n\n929\n00:46:02,761 --> 00:46:06,129\ndoes it, how does it basically work? It's got an array,\n\n930\n00:46:06,131 --> 00:46:09,932\nthis var annotations which is an array of MKAnnotation,\n\n931\n00:46:09,934 --> 00:46:15,271\nokay. MKAnnotation is not a class, it's a protocol. So\n\n932\n00:46:15,273 --> 00:46:18,074\nanything could be an annotation on a map as long as\n\n933\n00:46:18,076 --> 00:46:21,577\nit implements this protocol. What is that protocol?\n\n934\n00:46:21,579 --> 00:46:26,048\nIt has coordinate, title, and subtitle,\n\n935\n00:46:26,050 --> 00:46:29,085\nokay? If you implement those three bars, boom,\n\n936\n00:46:29,087 --> 00:46:32,655\nyou can be thrown onto a map. You will be an MKAnnotation.\n\n937\n00:46:32,657 --> 00:46:36,626\nThey're all get, see? Var title is an optional string by\n\n938\n00:46:36,628 --> 00:46:38,528\nthe way but it's really expected to be implemented.\n\n939\n00:46:38,530 --> 00:46:41,998\nDon't ever leave this nil or system does not like that,\n\n940\n00:46:42,000 --> 00:46:45,201\nokay? I'm not sure why, it's optional, should be and then\n\n941\n00:46:45,203 --> 00:46:47,937\nthe core location coordination coordinate remember that's\n\n942\n00:46:47,939 --> 00:46:53,643\ncllocation coordinate 2D, latitude and longitude Ok,\n\n943\n00:46:53,645 --> 00:46:56,445\nso that's it. So it's got this array of annotations but\n\n944\n00:46:56,447 --> 00:47:00,550\nyou notice this array is read only. So to add annotations or\n\n945\n00:47:00,552 --> 00:47:03,719\nremove annotations you have to use these methods, add or\n\n946\n00:47:03,721 --> 00:47:05,087\nremove annotations.\n\n947\n00:47:06,825 --> 00:47:08,991\nIt's generally a good idea from a performance perspective\n\n948\n00:47:08,993 --> 00:47:13,229\nto add all of your annotations that you know about up front.\n\n949\n00:47:13,231 --> 00:47:14,564\nAnd that's because the annotation views,\n\n950\n00:47:14,566 --> 00:47:19,101\nthose little pins. Get reused just like in a table view,\n\n951\n00:47:19,103 --> 00:47:21,671\nokay? So you might as well add them all upfront and\n\n952\n00:47:21,673 --> 00:47:24,974\nlet the system reuse the pins as you scroll,\n\n953\n00:47:24,976 --> 00:47:30,246\nscroll around the world. Okay, can reuse them. What do\n\n954\n00:47:30,248 --> 00:47:32,782\nannotations look like on the map? Well we saw it before,\n\n955\n00:47:32,784 --> 00:47:37,453\nright? If you use an MKPinAnnotationView, which is\n\n956\n00:47:37,455 --> 00:47:40,890\na subclass of MKAnnotationView you get a little pin.\n\n957\n00:47:40,892 --> 00:47:44,126\nIt can be red or purple I think or maybe another\n\n958\n00:47:44,128 --> 00:47:47,063\ncolor. But it does allow you to even change this image. If\n\n959\n00:47:47,065 --> 00:47:49,599\nyou don't like a pin, you can change it to something else.\n\n960\n00:47:49,601 --> 00:47:51,934\nAnd when you click on the PinAnnotationView,\n\n961\n00:47:51,936 --> 00:47:52,568\nyou get this call out. And\n\n962\n00:47:52,570 --> 00:47:56,973\nthat's what the call out looks like, okay? So what happens\n\n963\n00:47:56,975 --> 00:48:00,509\nwhen you press the pin besides this call-out coming out? And\n\n964\n00:48:00,511 --> 00:48:05,214\nby the way, this call-out only comes out if canShowCallout is\n\n965\n00:48:05,216 --> 00:48:08,551\ntrue on the MK annotation pin annotation view.\n\n966\n00:48:08,553 --> 00:48:11,520\nSo you have to have that be true. So this will come up,\n\n967\n00:48:11,522 --> 00:48:14,690\nbut in addition to this appearing, a delegate method\n\n968\n00:48:14,692 --> 00:48:17,994\nwill be sent to the map views delegate. It's called\n\n969\n00:48:17,996 --> 00:48:22,999\nMap view did select annotation view, okay? And so this\n\n970\n00:48:23,001 --> 00:48:25,601\nis important little method right here because if you're\n\n971\n00:48:25,603 --> 00:48:30,039\ngonna show anything expensive in your call out, like so\n\n972\n00:48:30,041 --> 00:48:32,008\nyou're gonna go over their network and grab an image or\n\n973\n00:48:32,010 --> 00:48:34,777\nsomething like that. You're gonna wanna wait to do it\n\n974\n00:48:34,779 --> 00:48:37,580\nuntil didSelectAnnotationView. Because if the user never\n\n975\n00:48:37,582 --> 00:48:40,549\nclicks on this pin, he's never gonna see that image. So you\n\n976\n00:48:40,551 --> 00:48:43,552\ndon't wanna waste your time fetching it. Okay? So this\n\n977\n00:48:43,554 --> 00:48:45,821\nis a place where you're gonna do expensive stuff that's\n\n978\n00:48:45,823 --> 00:48:48,291\ngonna show in the call out. You also, though,\n\n979\n00:48:48,293 --> 00:48:51,027\nmight segue out of this. When someone clicks on a pin,\n\n980\n00:48:51,029 --> 00:48:54,463\nmaybe you wanna go segue to some other view, I don't know.\n\n981\n00:48:54,465 --> 00:48:58,868\nOkay, but this is the target action of MKAnnotations.\n\n982\n00:48:59,003 --> 00:49:01,671\nAll right, so how are these AnnotationViews, these little\n\n983\n00:49:01,673 --> 00:49:04,440\npins created and associated with those annotations?\n\n984\n00:49:04,442 --> 00:49:07,610\nBecause we know MKMap View only has this array of\n\n985\n00:49:07,612 --> 00:49:11,347\nannotations. So how do those pins get there to show them?\n\n986\n00:49:11,349 --> 00:49:14,550\nAnd the answer is from this delegate method right here,\n\n987\n00:49:14,552 --> 00:49:15,651\nMapView, viewForAnnotation.\n\n988\n00:49:15,653 --> 00:49:18,888\nThis is very much like self or roll in index path in table\n\n989\n00:49:18,890 --> 00:49:22,091\nview. Okay? So in there, you're creating a cell which\n\n990\n00:49:22,093 --> 00:49:25,361\nis a view. Okay, UI table view cell. Here you're creating\n\n991\n00:49:25,363 --> 00:49:28,864\nan MK annotation view like the Pin annotation view. Okay. So\n\n992\n00:49:28,866 --> 00:49:31,600\nlet's go through this and see how we do it. First we're\n\n993\n00:49:31,602 --> 00:49:36,505\ngonna dq a reusable one using some identifier but\n\n994\n00:49:36,507 --> 00:49:40,876\nif that fail, okay and view is nil if we can't dq one\n\n995\n00:49:40,878 --> 00:49:44,914\nthen there's no prototype like there is in the table view so\n\n996\n00:49:44,916 --> 00:49:47,717\nwe have to create the prototype in code. So\n\n997\n00:49:47,719 --> 00:49:49,185\nhere I'm creating the prototype by saying,\n\n998\n00:49:49,187 --> 00:49:52,955\nview equals MK pin Annotation view, okay? But I'm specifying\n\n999\n00:49:52,957 --> 00:49:56,559\nthat sam reuse identifier that later I might come back and do\n\n1000\n00:49:56,561 --> 00:49:59,595\nthis reuseable with, you see? So that's how they get done.\n\n1001\n00:49:59,597 --> 00:50:02,665\nAnd then can't show call out either set to true or false,\n\n1002\n00:50:02,667 --> 00:50:05,768\nwhichever one you want. Okay.\n\n1003\n00:50:05,770 --> 00:50:07,570\nThen we're gonna whether we created the view or\n\n1004\n00:50:07,572 --> 00:50:10,206\nnot, we're gonna wanna set the view's annotation to be\n\n1005\n00:50:10,208 --> 00:50:15,044\nthe annotation we're creating, this view for. And then,\n\n1006\n00:50:15,046 --> 00:50:18,881\nwe're gonna wanna prepare this view with anything else.\n\n1007\n00:50:18,883 --> 00:50:21,817\nLike if it's gonna have a left call out accessor view,\n\n1008\n00:50:21,819 --> 00:50:22,318\nwhich is an image view,\n\n1009\n00:50:22,320 --> 00:50:25,354\nthis is the time we would add the image view. This might not\n\n1010\n00:50:25,356 --> 00:50:28,624\nbe the time we actually go fetch the image to put there,\n\n1011\n00:50:28,626 --> 00:50:31,427\nyou might wait until didSelectAnnotationView for\n\n1012\n00:50:31,429 --> 00:50:34,630\nyou to do that but we're not gonna wanna put the UI image\n\n1013\n00:50:34,632 --> 00:50:37,867\nview in there so that it's ready to go in the call out.\n\n1014\n00:50:37,869 --> 00:50:41,537\nOkay, and then we're gonna return the view then\n\n1015\n00:50:41,539 --> 00:50:45,141\nthe system gonna use this view to show that pin.\n\n1016\n00:50:45,143 --> 00:50:47,777\nOkay, interesting properties on UIAnnotationView,\n\n1017\n00:50:47,779 --> 00:50:49,078\nwe already talked about the left and\n\n1018\n00:50:49,080 --> 00:50:51,514\nright CallOutAccessoryViews, which are just views.\n\n1019\n00:50:51,516 --> 00:50:55,317\nThere's also whether it's enabled or not. This image is\n\n1020\n00:50:55,319 --> 00:50:58,087\nthe image of the pin, not the image that's in the callout,\n\n1021\n00:50:58,089 --> 00:51:00,656\nit's the image of the pin. Also you can\n\n1022\n00:51:00,658 --> 00:51:03,359\nmake it draggable, setting draggable to true. If you do\n\n1023\n00:51:03,361 --> 00:51:06,529\nthat your MKAnnotations, the coordinate property would have\n\n1024\n00:51:06,531 --> 00:51:09,465\nto be get and set. Obviously if you're gonna drag it around\n\n1025\n00:51:09,467 --> 00:51:12,268\nyou have to be able to set the property as well.\n\n1026\n00:51:12,870 --> 00:51:16,605\nOkay. This cool property or\n\n1027\n00:51:16,607 --> 00:51:19,642\ndelegate method right here calloutAccessoryControlTapped\n\n1028\n00:51:19,644 --> 00:51:23,813\nwill get sent to your map view delegates If your left or\n\n1029\n00:51:23,815 --> 00:51:27,049\nright call out accessory is a ui control.\n\n1030\n00:51:27,051 --> 00:51:29,852\nBasically a ui button okay? So if you put a button\n\n1031\n00:51:29,854 --> 00:51:32,455\nat your left or right call out accessory when it gets touched\n\n1032\n00:51:32,457 --> 00:51:36,459\nyou're gonna get this call out accessory control tapped\n\n1033\n00:51:36,861 --> 00:51:39,695\nmethod which is pretty cool.\n\n1034\n00:51:39,697 --> 00:51:42,631\nIn did select annotation view we talked about the fact\n\n1035\n00:51:42,633 --> 00:51:46,268\nthat this is where you might want to create your image or\n\n1036\n00:51:46,270 --> 00:51:50,706\neven fire off a thread or q, on a different q, fire off\n\n1037\n00:51:50,708 --> 00:51:53,509\na request to go get the image. When it comes back later\n\n1038\n00:51:53,511 --> 00:51:57,813\nyou'll have to load it up into the accessory view. Okay?\n\n1039\n00:51:57,815 --> 00:51:59,982\nJust like when you're scrolling around in a table\n\n1040\n00:51:59,984 --> 00:52:02,685\nview, realize that if you're scrolling around on the map\n\n1041\n00:52:02,687 --> 00:52:06,455\nyou might fire off a dispatch async here to go get this\n\n1042\n00:52:06,457 --> 00:52:09,758\nimage, and when it comes back that image is no longer being\n\n1043\n00:52:09,760 --> 00:52:12,761\ndisplayed in this call accessory view because it gets\n\n1044\n00:52:12,763 --> 00:52:17,566\nreused, reused right by other ones. So be careful about\n\n1045\n00:52:17,568 --> 00:52:21,537\nthat. The map you can configure the way it displays.\n\n1046\n00:52:21,539 --> 00:52:24,673\nThis is a var on MKMapView. You can do standard,\n\n1047\n00:52:24,675 --> 00:52:27,710\nsatellite, or hybrid. So standard is like streets and\n\n1048\n00:52:27,712 --> 00:52:31,447\nthings like that, satellite is like Google Earth type thing.\n\n1049\n00:52:31,449 --> 00:52:35,251\nAnd then hybrid is a mix, an overlay of those two things.\n\n1050\n00:52:35,253 --> 00:52:39,155\nYou can also show the user's current location. On the map\n\n1051\n00:52:39,157 --> 00:52:40,923\njust by saying this Bool to true and it will show it.\n\n1052\n00:52:40,925 --> 00:52:43,659\nI think the users current location is blue or maybe it's\n\n1053\n00:52:43,661 --> 00:52:46,128\npurple, I don't know. But it will just show in there.\n\n1054\n00:52:46,130 --> 00:52:48,864\nYou can also get the users location as well.\n\n1055\n00:52:48,866 --> 00:52:51,500\nAs MKUserLocation which is just thing that implements\n\n1056\n00:52:51,502 --> 00:52:56,472\nthe MKAnnotation protocol. You can also restrict scrolling.\n\n1057\n00:52:56,474 --> 00:52:59,008\nOkay, maybe you don't want. The 3D mode.\n\n1058\n00:52:59,010 --> 00:53:01,544\nIf you don't want 3D mode, set pitch enable to false and\n\n1059\n00:53:01,546 --> 00:53:06,248\nit won't pitch up to show you 3D maps. You can control\n\n1060\n00:53:06,250 --> 00:53:08,851\nthe camera if you do allow 3D you can control\n\n1061\n00:53:08,853 --> 00:53:12,254\nwhere the camera is pointing using this, API right here,\n\n1062\n00:53:12,256 --> 00:53:16,025\nthat's kind of fun. You can also say what part of\n\n1063\n00:53:16,027 --> 00:53:19,094\nthe world is being shown with the MP coordinate region which\n\n1064\n00:53:19,096 --> 00:53:22,998\nis just a latitude longitude and a span okay which is\n\n1065\n00:53:23,000 --> 00:53:28,370\nnumber of meters. Okay? So it shows that will show that part\n\n1066\n00:53:28,372 --> 00:53:32,208\nof the Earth. Actually it's not it's not even meters.\n\n1067\n00:53:32,210 --> 00:53:35,044\nThe span is a delta of latitude and longitude.\n\n1068\n00:53:35,046 --> 00:53:36,078\nHow many degrees of latitude and\n\n1069\n00:53:36,080 --> 00:53:38,581\nhow many degrees of longitude to show.\n\n1070\n00:53:39,217 --> 00:53:43,886\nOkay? What else we can do here?\n\n1071\n00:53:43,888 --> 00:53:46,722\nI just want you to note that there's a whole bunch of\n\n1072\n00:53:46,724 --> 00:53:49,892\nC-like functions, they're swift global functions,\n\n1073\n00:53:49,894 --> 00:53:52,494\nthey're not methods, that you can do to convert\n\n1074\n00:53:52,496 --> 00:53:55,064\nlike from map coordinates to view coordinates and\n\n1075\n00:53:55,066 --> 00:53:58,300\nthings like that. So make sure you take a look at these and\n\n1076\n00:53:58,302 --> 00:54:01,270\nunderstand all of these. There's probably about 15 or\n\n1077\n00:54:01,272 --> 00:54:03,906\n20 of them that will help you do conversions.\n\n1078\n00:54:03,908 --> 00:54:08,110\nThere's also some methods that will do it, as well,\n\n1079\n00:54:08,112 --> 00:54:13,415\nin MKMapView. There's a cool method in MKMapView called\n\n1080\n00:54:13,417 --> 00:54:15,618\ndidChangeRegionAnimated.\n\n1081\n00:54:15,620 --> 00:54:18,087\nOkay? So, if you tell the mapview to\n\n1082\n00:54:18,089 --> 00:54:21,257\nshow a different part of the world like New York, okay.\n\n1083\n00:54:21,259 --> 00:54:23,559\nIt's going to animate going there. It's going to\n\n1084\n00:54:23,561 --> 00:54:26,695\nscroll over there. But if I'm in San Francisco and I say,\n\n1085\n00:54:26,697 --> 00:54:29,999\nshow New York it's gonna go whoo, okay, you're not even\n\n1086\n00:54:30,001 --> 00:54:32,534\ngonna see it. Nebraska, you'll never see it okay.\n\n1087\n00:54:32,536 --> 00:54:35,337\nIn Nebraska, you can go by so fast. You'll never see it.\n\n1088\n00:54:35,339 --> 00:54:36,905\nWhat would be really cool is if you said,\n\n1089\n00:54:36,907 --> 00:54:39,408\nI'm in San Francisco, show New York, first you said\n\n1090\n00:54:39,410 --> 00:54:42,678\nshow the whole United States then show New York.\n\n1091\n00:54:42,680 --> 00:54:45,681\nRight then you get this cool animation. San Francisco to\n\n1092\n00:54:45,683 --> 00:54:47,249\nthe whole United States down to New York.\n\n1093\n00:54:47,251 --> 00:54:49,318\nWouldn't that be cool? Yes it would. And so\n\n1094\n00:54:49,320 --> 00:54:52,621\nthe way you do that is you first of all set your location\n\n1095\n00:54:52,623 --> 00:54:53,489\nto the whole United States or\n\n1096\n00:54:53,491 --> 00:54:56,358\nmiddle of the United States with a large span and it will\n\n1097\n00:54:56,360 --> 00:54:59,695\ngo up to there and as soon as the animation of that finishes\n\n1098\n00:54:59,697 --> 00:55:04,166\nyou'll get sent this. Okay cuz it's a did change region.\n\n1099\n00:55:04,168 --> 00:55:04,533\nIt finished the change region.\n\n1100\n00:55:04,535 --> 00:55:08,537\nAs soon as it sends you this now you animate to New York.\n\n1101\n00:55:08,706 --> 00:55:10,005\nSo essentially chaining you see.\n\n1102\n00:55:10,007 --> 00:55:11,907\nAnd now it will [INAUDIBLE] New York. So this is the way\n\n1103\n00:55:11,909 --> 00:55:14,276\nyou can chain animations to make the animations kind of\n\n1104\n00:55:14,278 --> 00:55:18,480\nfly around the world nicely. MKLocalSearch I'm not going to\n\n1105\n00:55:18,482 --> 00:55:21,750\nreally talk about it but it's a way that you can put normal\n\n1106\n00:55:21,752 --> 00:55:25,321\nEnglish language descriptions of places like Ike's, and\n\n1107\n00:55:25,323 --> 00:55:27,423\nit'll go and search. This is asynchronous,\n\n1108\n00:55:27,425 --> 00:55:30,626\ncuz it's gonna go out on the internet to look this up. But\n\n1109\n00:55:30,628 --> 00:55:32,961\nit'll come back and give you a bunch of,\n\n1110\n00:55:32,963 --> 00:55:38,734\nlocations that might match this search. Okay? Okay.\n\n1111\n00:55:38,903 --> 00:55:41,470\nSimilarly you can asked for the directions you can\n\n1112\n00:55:41,472 --> 00:55:44,273\nsay I wanna go from here to here and I'm gonna drive,\n\n1113\n00:55:44,275 --> 00:55:46,942\ngive me directions, and it will give you this thing\n\n1114\n00:55:46,944 --> 00:55:49,845\ncalled MKRoute with also have turn by turn directions.\n\n1115\n00:55:49,847 --> 00:55:53,982\nAnd also have an MKPolyline which is an object which will\n\n1116\n00:55:53,984 --> 00:55:56,652\ndraw this blue line right here Okay, and\n\n1117\n00:55:56,654 --> 00:55:59,888\nhow do you get this blue line showing on here?\n\n1118\n00:55:59,890 --> 00:56:02,624\nYou're gonna use another feature called overlays, okay.\n\n1119\n00:56:02,626 --> 00:56:05,728\nOverlays are very much like annotations, but instead of\n\n1120\n00:56:05,730 --> 00:56:09,064\nyou have view for annotation, you have overlay view for\n\n1121\n00:56:09,066 --> 00:56:11,734\nannotation or renderer for annotation.\n\n1122\n00:56:11,736 --> 00:56:15,137\nOkay, and this renderer could be something like a polyline\n\n1123\n00:56:15,139 --> 00:56:17,506\nrenderer, and if you have a polyline renderer, and\n\n1124\n00:56:17,508 --> 00:56:21,643\nyou give it an MKPolyline that comes from that root thing,\n\n1125\n00:56:21,645 --> 00:56:24,146\nyou can draw that root, okay?\n\n1126\n00:56:24,148 --> 00:56:26,148\nYou also use overlays for your on own thing,\n\n1127\n00:56:26,150 --> 00:56:29,785\nif you wanna draw a bounding area around something, or\n\n1128\n00:56:29,787 --> 00:56:33,255\nyou wanna draw your own path of where you went, you can do\n\n1129\n00:56:33,257 --> 00:56:36,492\nall that with overlays. Okay if you wanna do that in your\n\n1130\n00:56:36,494 --> 00:56:38,761\nfinal project, it'll count as not covered in lecture,\n\n1131\n00:56:38,763 --> 00:56:39,728\ncuz I'm not really covering it,\n\n1132\n00:56:39,730 --> 00:56:41,130\nI'm just telling you it's there, okay?\n\n1133\n00:56:41,132 --> 00:56:42,431\nSame thing as local search and\n\n1134\n00:56:42,433 --> 00:56:46,268\nall these things I've kind of glossed over here, okay?\n\n1135\n00:56:46,270 --> 00:56:49,104\nThese are some of the built-in renderers, polyline,\n\n1136\n00:56:49,106 --> 00:56:54,076\nalso circles, polygons, tiling, etc. Okay,\n\n1137\n00:56:54,078 --> 00:56:56,945\nso that's it. Now we're gonna start a demo that's gonna last\n\n1138\n00:56:56,947 --> 00:57:01,650\nacross both lectures here, and we're gonna start by just\n\n1139\n00:57:01,652 --> 00:57:05,721\ndoing a simple app that takes some waypoints and throws them\n\n1140\n00:57:05,723 --> 00:57:09,291\non a map, so we can see how to do that. Also on Wednesday, in\n\n1141\n00:57:09,293 --> 00:57:12,394\naddition to finishing up this demo I'm gonna cover the last\n\n1142\n00:57:12,396 --> 00:57:13,996\ntopic of the quarter which is persistence,\n\n1143\n00:57:13,998 --> 00:57:15,798\nwhich is basically how to store things in the file\n\n1144\n00:57:15,800 --> 00:57:21,537\nsystem, right? Opening files and all that business. Okay,\n\n1145\n00:57:21,539 --> 00:57:24,873\nso let's go start a new app here.\n\n1146\n00:57:24,875 --> 00:57:29,044\nWe're gonna create a brand new one. We'll create on iOS app,\n\n1147\n00:57:29,046 --> 00:57:33,015\nSingle View, as usual. We'll call this one Trax, okay?\n\n1148\n00:57:33,017 --> 00:57:37,052\nCuz it's gonna keep track of where you have been.\n\n1149\n00:57:37,054 --> 00:57:40,923\nWe'll make it a Universal app, so it works on iPhone and\n\n1150\n00:57:40,925 --> 00:57:46,595\niPad. There we go, we'll put it in our standard location.\n\n1151\n00:57:46,831 --> 00:57:50,265\nAll right, so here's Trax. In the storyboard right here\n\n1152\n00:57:50,267 --> 00:57:54,303\nI'm going to, do my standard thing. We're gonna move,\n\n1153\n00:57:54,305 --> 00:57:58,373\nsome of these things off to Supporting Files here.\n\n1154\n00:57:58,375 --> 00:57:58,740\nSupporting Files.\n\n1155\n00:57:58,742 --> 00:58:01,844\nWe're not gonna be needing to do anything in AppDelegate, so\n\n1156\n00:58:01,846 --> 00:58:04,513\nI'll move it off to Supporting flies, Files here.\n\n1157\n00:58:04,515 --> 00:58:07,883\nIn my storyboard, I actually don't want my ViewController\n\n1158\n00:58:07,885 --> 00:58:10,319\nhere to be called generic View Controller.\n\n1159\n00:58:10,321 --> 00:58:13,856\nSo I'm gonna rename it to be GPXViewController,\n\n1160\n00:58:13,858 --> 00:58:16,492\ncuz what we're gonna do is take a GPX file which,\n\n1161\n00:58:16,494 --> 00:58:19,194\nlike I said before, is just a file that contains a bunch\n\n1162\n00:58:19,196 --> 00:58:21,597\nof GPS coordinates, and we're gonna put it on our map.\n\n1163\n00:58:21,599 --> 00:58:26,034\nSo we're gonna call this our GPXViewController, so\n\n1164\n00:58:26,036 --> 00:58:28,537\nI'm gonna rename it here as well,\n\n1165\n00:58:28,539 --> 00:58:31,206\nand also in my storyboard and go here to\n\n1166\n00:58:31,208 --> 00:58:35,978\nthe Identity Inspector change this to GPXViewController.\n\n1167\n00:58:35,980 --> 00:58:40,782\nOkay, now let's also go ahead and build our UI here.\n\n1168\n00:58:40,784 --> 00:58:44,019\nOur UI is gonna be all map, all the time. Okay, our entire\n\n1169\n00:58:44,021 --> 00:58:48,390\nUI is just gonna be a gigantic map. So I'm gonna go down to\n\n1170\n00:58:48,392 --> 00:58:50,592\nmy object palette down here and try and find map,\n\n1171\n00:58:50,594 --> 00:58:53,262\nactually, I'm gonna search for it by just typing map.\n\n1172\n00:58:53,264 --> 00:58:56,265\nHere it is, a Map Kit View, and you drag that out and\n\n1173\n00:58:56,267 --> 00:59:00,836\nput it here. Make it fill the entire MVC scene.\n\n1174\n00:59:00,838 --> 00:59:03,705\nOf course, we'll do Reset to Suggested Constraints, and\n\n1175\n00:59:03,707 --> 00:59:06,441\nwe'll jump over here to our size inspector and make sure\n\n1176\n00:59:06,443 --> 00:59:09,411\nit did the right thing. Sure looks like it did. Let's go\n\n1177\n00:59:09,413 --> 00:59:12,748\nahead and make an outlet to this from our controller. So\n\n1178\n00:59:12,750 --> 00:59:17,052\nI'm just gonna Ctrl+drag in here. I'll call it my mapView.\n\n1179\n00:59:17,054 --> 00:59:20,756\nOkay, you can see that it's a type MKMapView right there. So\n\n1180\n00:59:20,758 --> 00:59:25,961\nwe have our Map View. Let's go ahead and when our mapView\n\n1181\n00:59:25,963 --> 00:59:29,197\nis set, let's go ahead and configure our mapView what we\n\n1182\n00:59:29,199 --> 00:59:35,337\nwant it to look like. So how about the mapView's, mapType.\n\n1183\n00:59:35,806 --> 00:59:38,206\nAnd see it's not doing escape completion here.\n\n1184\n00:59:38,208 --> 00:59:40,842\nWhy not? Import MapKit.\n\n1185\n00:59:40,844 --> 00:59:44,012\nOkay, just like CloudKit, it's a separate framework.\n\n1186\n00:59:44,014 --> 00:59:45,981\nWe need it, or it's not gonna know any of these types.\n\n1187\n00:59:45,983 --> 00:59:49,885\nSo we'll set our mapType to be Satellite, okay,\n\n1188\n00:59:49,887 --> 00:59:54,890\nsatellite images. Let's set our delegate,\n\n1189\n00:59:54,892 --> 00:59:59,361\nof course. Nothing works in a mapView without a delegate, so\n\n1190\n00:59:59,363 --> 01:00:02,030\nwe absolutely have to use delegate, and\n\n1191\n01:00:02,032 --> 01:00:05,267\nthat means we'll have to be an MKMapViewDelegate.\n\n1192\n01:00:05,269 --> 01:00:09,171\nAll right, so we have our mapview set up here nicely,\n\n1193\n01:00:09,173 --> 01:00:14,876\noops. Okay, so now we need our model.\n\n1194\n01:00:14,878 --> 01:00:17,279\nWhat's gonna be our model to this thing?\n\n1195\n01:00:17,281 --> 01:00:22,284\nIt's going to be a gpxURL. Okay, so this is gonna be\n\n1196\n01:00:22,286 --> 01:00:26,054\nthe URL to a GPX file, a file that contains coordinates.\n\n1197\n01:00:26,056 --> 01:00:27,823\nAnd we're just gonna open that file,\n\n1198\n01:00:27,825 --> 01:00:30,592\nlook at all the GPX coordinates and display them.\n\n1199\n01:00:30,594 --> 01:00:35,097\nAnd in fact, let's go ahead and in our viewDidLoad here\n\n1200\n01:00:35,099 --> 01:00:40,369\njust load one up. So let's see, gpxURL equals,\n\n1201\n01:00:40,371 --> 01:00:45,674\nhow about this one right here, a string, which is\n\n1202\n01:00:45,676 --> 01:00:51,246\nhttp://cs193p.stanford.edu/Va- cation,\n\n1203\n01:00:51,248 --> 01:00:55,951\noops, Vacation.gpx. Okay, so that's just a,\n\n1204\n01:00:55,953 --> 01:01:01,390\na URL I have around there that we can look at. Now this\n\n1205\n01:01:01,392 --> 01:01:05,560\nis an http, so we'd better go over to our info.plist,\n\n1206\n01:01:05,562 --> 01:01:10,232\nright here, and do the thing we always do here where we add\n\n1207\n01:01:10,234 --> 01:01:13,535\nour App Transport settings right here.\n\n1208\n01:01:13,537 --> 01:01:18,507\nLet's add Arbitrary Loads allowed, and we will\n\n1209\n01:01:18,509 --> 01:01:21,977\nsay YES. Everyone understand why we're doing that,\n\n1210\n01:01:21,979 --> 01:01:26,281\nsame thing we had to do with smash tag there. All right, so\n\n1211\n01:01:26,283 --> 01:01:29,918\nwe're all set up here, what are we gonna do when this is\n\n1212\n01:01:29,920 --> 01:01:35,323\nset? Okay, so when our model is set, when this URL is set,\n\n1213\n01:01:35,325 --> 01:01:40,529\nwhat are we gonna need to do here to make this work? Well,\n\n1214\n01:01:40,531 --> 01:01:43,265\nif they set the URL equal to something, so\n\n1215\n01:01:43,267 --> 01:01:48,236\nthey didn't set it to be nil let's say. Then really what\n\n1216\n01:01:48,238 --> 01:01:52,841\nI need to do is parse this file, this URL somehow. And\n\n1217\n01:01:52,843 --> 01:01:56,545\nto do that, I'm going to introduce a little class that\n\n1218\n01:01:56,547 --> 01:02:00,849\nI wrote called GPX, which will parse a GPX file and then give\n\n1219\n01:02:00,851 --> 01:02:03,618\nyou all the waypoints. Okay, so let's go ahead and\n\n1220\n01:02:03,620 --> 01:02:08,090\ngrab that file. It's right here, it's called GPX.swift.\n\n1221\n01:02:08,092 --> 01:02:10,492\nCopy it in. Take a brief look at this thing,\n\n1222\n01:02:10,494 --> 01:02:15,163\nwhat it does. All right, here's GPX, let's go ahead and\n\n1223\n01:02:15,165 --> 01:02:18,133\nlook at it just at its generated interface\n\n1224\n01:02:18,135 --> 01:02:23,371\nhere. No need to look at the code there.\n\n1225\n01:02:23,373 --> 01:02:26,208\nAll right, so here's the GPX, this class. And\n\n1226\n01:02:26,210 --> 01:02:30,545\nthe main thing it has is this, this var waypoints,\n\n1227\n01:02:30,547 --> 01:02:34,249\nwhich is a array of GPX.Waypoint.\n\n1228\n01:02:34,251 --> 01:02:36,952\nLet's go look at the GPX waypoint, that's right here.\n\n1229\n01:02:36,954 --> 01:02:40,756\nSo, the Waypoint is latitude and longitude, of course,\n\n1230\n01:02:40,758 --> 01:02:44,659\nkind of some information about this waypoint, the date\n\n1231\n01:02:44,661 --> 01:02:48,497\nthe waypoint was captured. And it's also an entry,\n\n1232\n01:02:48,499 --> 01:02:51,233\nthis Waypoint is also an entry, which is this thing.\n\n1233\n01:02:51,235 --> 01:02:54,603\nThe entry can have any number of hyperlinks. So these would\n\n1234\n01:02:54,605 --> 01:02:58,240\nbe like URLs to photos or video that I might have taken\n\n1235\n01:02:58,242 --> 01:03:02,611\nat this location when I was on my trek or whatever. Also it\n\n1236\n01:03:02,613 --> 01:03:06,381\nhas a name, which is the name of this waypoint, okay? May or\n\n1237\n01:03:06,383 --> 01:03:11,686\nmay not have a name, but if it does this is the name. Okay,\n\n1238\n01:03:11,688 --> 01:03:14,623\nthese links by the way, these GPX links is right here.\n\n1239\n01:03:14,625 --> 01:03:18,593\nIt's basically just URLs, hrefs, here,\n\n1240\n01:03:18,595 --> 01:03:21,797\nokay. All right, so that's it. That's all this thing does is,\n\n1241\n01:03:21,799 --> 01:03:25,333\nmain thing is this, this array of waypoints, okay? So let's\n\n1242\n01:03:25,335 --> 01:03:29,704\ngo back to our controller here. So we do this GPX.parse.\n\n1243\n01:03:29,706 --> 01:03:34,576\nNotice that this parse method in GPX is asynchronous.\n\n1244\n01:03:34,578 --> 01:03:37,112\nIt parses that file, and then later it calls you back.\n\n1245\n01:03:37,114 --> 01:03:40,682\nIt's a very nice asynchronous method in that it always calls\n\n1246\n01:03:40,684 --> 01:03:42,284\nyou back on the main queue, okay, so\n\n1247\n01:03:42,286 --> 01:03:45,187\nwe don't have to dispatch async or anything here. And\n\n1248\n01:03:45,189 --> 01:03:50,025\nthe only argument that's given when you do it is a GPX, which\n\n1249\n01:03:50,027 --> 01:03:54,596\nis an instance of this class, and it has those waypoints.\n\n1250\n01:03:54,598 --> 01:03:57,632\nSo, what are we gonna do with these waypoints when they come\n\n1251\n01:03:57,634 --> 01:04:01,937\nback? Well, if the, if it was able to parse it, basically if\n\n1252\n01:04:01,939 --> 01:04:06,241\nthis thing came back and it wasn't nil, then we're going\n\n1253\n01:04:06,243 --> 01:04:11,546\nto add these waypoints to ourself. Waypoints,\n\n1254\n01:04:11,548 --> 01:04:14,583\nokay, so we're gonna have to add, do this method here.\n\n1255\n01:04:14,585 --> 01:04:17,252\nAlso every time someone said that I'm also gonna clear any\n\n1256\n01:04:17,254 --> 01:04:20,522\nwaypoints that I already have. So I'm gonna implement these\n\n1257\n01:04:20,524 --> 01:04:24,292\ntwo methods right here. Okay everybody cool with that? So\n\n1258\n01:04:24,294 --> 01:04:27,262\nwe're just getting those GPS waypoints out of this GPX\n\n1259\n01:04:27,264 --> 01:04:29,397\nfile. So we're gonna implement these two methods. So\n\n1260\n01:04:29,399 --> 01:04:34,035\nlet's do private func clearWaypoints. Okay, so for\n\n1261\n01:04:34,037 --> 01:04:37,072\nclearWaypoints I just wanna remove all the annotations off\n\n1262\n01:04:37,074 --> 01:04:40,375\nmy map, remember the map just shows annotations? So\n\n1263\n01:04:40,377 --> 01:04:40,842\nI'm gonna remove them all.\n\n1264\n01:04:40,844 --> 01:04:44,713\nI'm gonna say mapView removeAnnotations which is\n\n1265\n01:04:44,715 --> 01:04:47,816\nthe mapView's current annotations, okay,\n\n1266\n01:04:47,818 --> 01:04:52,187\nwhatever the mapView currently has. Notice I'm doing this\n\n1267\n01:04:52,189 --> 01:04:55,824\nMapView question mark here, that's because if this happens\n\n1268\n01:04:55,826 --> 01:04:59,828\nin like a perform, prepare for segue or something like that,\n\n1269\n01:04:59,830 --> 01:05:02,030\nthen my mapView wouldn't be wired up yet.\n\n1270\n01:05:02,032 --> 01:05:04,799\nSo I don't want this to fail, I just want you to do nothing.\n\n1271\n01:05:04,801 --> 01:05:08,436\nSo that's why I'm doing MapView?. Okay and\n\n1272\n01:05:08,438 --> 01:05:13,775\nthen we have the addWaypoints, private func addWaypoints and\n\n1273\n01:05:13,777 --> 01:05:18,146\nthis one is going to take an array. Waypoints,\n\n1274\n01:05:18,148 --> 01:05:23,618\nwhich is an array of these GPX.Waypoint objects. Okay,\n\n1275\n01:05:23,620 --> 01:05:25,720\nso what do we wanna do in addWaypoints?\n\n1276\n01:05:25,722 --> 01:05:28,990\nWell, we just want to add them as annotations. So I'm just\n\n1277\n01:05:28,992 --> 01:05:33,228\ngonna say addAnnotations, these waypoints, right?\n\n1278\n01:05:33,230 --> 01:05:37,532\nMapView, the other thing I'm gonna do is there's a way in\n\n1279\n01:05:37,534 --> 01:05:41,369\nthe MapView to say, show me all of these annotations.\n\n1280\n01:05:41,371 --> 01:05:46,474\nYou say showAnnotations, showAnnotations, and\n\n1281\n01:05:46,476 --> 01:05:47,342\nit takes some annotations, and\n\n1282\n01:05:47,344 --> 01:05:49,978\nI'll just give those same waypoints. And\n\n1283\n01:05:49,980 --> 01:05:50,645\nI'll say animated true, and\n\n1284\n01:05:50,647 --> 01:05:54,582\nwhat this will do is zoom the map to show these annotations,\n\n1285\n01:05:54,584 --> 01:06:00,255\nokay. Now, a couple errors here. What are these errors?\n\n1286\n01:06:00,257 --> 01:06:03,758\nCannot convert value of array of GPS Waypoint to\n\n1287\n01:06:03,760 --> 01:06:07,862\nexpected argument which is array of MKAnnotation.\n\n1288\n01:06:07,864 --> 01:06:11,866\nHa! Right I said that the mapView takes MKAnnotations,\n\n1289\n01:06:11,868 --> 01:06:15,670\nand these are GPS Waypoints. They're not MKAnnotations. But\n\n1290\n01:06:15,672 --> 01:06:20,208\nwe can easily turn a GPX Waypoint into an MKAnnotation\n\n1291\n01:06:20,210 --> 01:06:23,011\nas long as we get it to implement those three methods,\n\n1292\n01:06:23,013 --> 01:06:25,880\nright? So how are we gonna do that? Well let's create\n\n1293\n01:06:25,882 --> 01:06:29,050\nanother little file and we're just gonna add protocol\n\n1294\n01:06:29,052 --> 01:06:33,121\nconformance via an extension which I talked about earlier\n\n1295\n01:06:33,123 --> 01:06:35,991\nin the quarter but we haven't seen it actually happen. So\n\n1296\n01:06:35,993 --> 01:06:36,925\nhere I'm gonna create a Swift file.\n\n1297\n01:06:36,927 --> 01:06:41,096\nI'm gonna call it mkgpx because it's MK annotated,\n\n1298\n01:06:41,098 --> 01:06:45,000\nmap kit stuff having to do with this GPX class right\n\n1299\n01:06:45,002 --> 01:06:49,938\nhere. And I'm going to import MapKit, MK, yeah MapKit.\n\n1300\n01:06:49,940 --> 01:06:51,740\nAll right, and what am I gonna do,\n\n1301\n01:06:51,742 --> 01:06:55,043\nI'm gonna create an extension to GPX.Waypoint, and\n\n1302\n01:06:55,045 --> 01:06:58,480\nit's going to implement the protocol MKAnnotation.\n\n1303\n01:06:58,482 --> 01:07:00,382\nThat's what this extension is going to do. So\n\n1304\n01:07:00,384 --> 01:07:05,453\nthis is how we can implement a protocol via an extension.\n\n1305\n01:07:05,455 --> 01:07:07,288\nOkay now all you need to do is implement these things.\n\n1306\n01:07:07,290 --> 01:07:12,594\nRemember there's coordinates that we have to do which is\n\n1307\n01:07:12,596 --> 01:07:17,665\na CLLocationCoordinate2D. We have to implement title, which\n\n1308\n01:07:17,667 --> 01:07:20,902\nis a String, optional but we have to implement it and\n\n1309\n01:07:20,904 --> 01:07:23,805\nthen there's subtitle which can be any subtitle\n\n1310\n01:07:23,807 --> 01:07:27,075\ninformation we want, okay, which is also a String.\n\n1311\n01:07:27,077 --> 01:07:29,644\nSo we just have to implement these three things and\n\n1312\n01:07:29,646 --> 01:07:32,113\nthen we will have successfully,\n\n1313\n01:07:32,282 --> 01:07:36,951\nadded the MKAnnotation conformant to Waypoint.\n\n1314\n01:07:36,953 --> 01:07:38,486\nSo how are we going to implement these things?\n\n1315\n01:07:38,488 --> 01:07:41,189\nOkay well coordinate this is not coordination this is\n\n1316\n01:07:41,191 --> 01:07:44,459\ncoordinate okay? The coordinate is easy to\n\n1317\n01:07:44,461 --> 01:07:47,662\nimplement because the GPXWaypoint knows latitude and\n\n1318\n01:07:47,664 --> 01:07:48,029\nSo I'm just gonna create a new LocationCoordinate2D okay, and\n\n1319\n01:07:48,031 --> 01:07:51,599\nlongitude.\n\n1320\n01:07:51,601 --> 01:07:54,803\nit's gonna have latitude which is the latitude,\n\n1321\n01:07:54,805 --> 01:07:58,306\nit's green there, you see? Because it's a var,\n\n1322\n01:07:58,308 --> 01:08:03,244\nin this class, and then longitude. Okay, so\n\n1323\n01:08:03,246 --> 01:08:05,346\nthat was easy. How about the title?\n\n1324\n01:08:05,348 --> 01:08:07,916\nWell, all these GPX Waypoints have that name, so\n\n1325\n01:08:07,918 --> 01:08:11,853\nI'm just gonna return the name of the GPX Waypoint and\n\n1326\n01:08:11,855 --> 01:08:16,357\nthen they also have this thing called info, which is just\n\n1327\n01:08:16,359 --> 01:08:17,992\nkind of information about the Waypoint.\n\n1328\n01:08:17,994 --> 01:08:22,263\nThat would be a good subtitle, okay? So just like that I've\n\n1329\n01:08:22,265 --> 01:08:25,834\nturned GPX Waypoints into MKAnnotations and\n\n1330\n01:08:25,836 --> 01:08:28,636\nthis is how you use the map. You take usually something\n\n1331\n01:08:28,638 --> 01:08:30,905\nyou already have and make it implement this.\n\n1332\n01:08:30,907 --> 01:08:33,374\nNow you could create a new class that all it does\n\n1333\n01:08:33,376 --> 01:08:35,710\nis implement MKAnnotation that's fine too, but\n\n1334\n01:08:35,712 --> 01:08:38,480\ngenerally, usually have something lying around that\n\n1335\n01:08:38,482 --> 01:08:40,248\nyou can turn into an MKAnnotation. And\n\n1336\n01:08:40,250 --> 01:08:44,419\nnotice as soon as I do that, no more errors here, okay,\n\n1337\n01:08:44,421 --> 01:08:48,456\nbecause this is now an array of MKAnnotation, okay,\n\n1338\n01:08:48,458 --> 01:08:53,027\nall right. So let's go ahead and run this,\n\n1339\n01:08:53,029 --> 01:08:56,698\nsee what happens, lets go here, iPhone6, run,\n\n1340\n01:08:56,700 --> 01:08:58,967\nsee if it can open this GPX file up and\n\n1341\n01:08:58,969 --> 01:09:05,874\nshow us these waypoints. Up, sure enough there it is,\n\n1342\n01:09:05,876 --> 01:09:08,510\nand it even did that showAnnotations right here,\n\n1343\n01:09:08,512 --> 01:09:10,378\nokay. That zoomed to where it is so\n\n1344\n01:09:10,380 --> 01:09:11,146\nit's showing all the annotations\n\n1345\n01:09:11,148 --> 01:09:13,915\nit found in that GPX file. Let's see if we can see where\n\n1346\n01:09:13,917 --> 01:09:19,387\nwe are here. Zoom out. Looks like we are in what, what is,\n\n1347\n01:09:19,389 --> 01:09:25,960\nanyone know where that is? Recognize that coastline?\n\n1348\n01:09:25,962 --> 01:09:29,497\nCanada! Yeah, there's the United States, here's Canada.\n\n1349\n01:09:29,499 --> 01:09:32,333\nOkay? So here we are, we got these things in Canada. Now,\n\n1350\n01:09:32,335 --> 01:09:35,170\nif we click on some of these. Let's click on some,\n\n1351\n01:09:35,172 --> 01:09:38,540\nsee what happens. So I click, notice we get the name and\n\n1352\n01:09:38,542 --> 01:09:42,544\nthe info right. The title and the subtitle got it.\n\n1353\n01:09:42,546 --> 01:09:47,615\nNow I happen to know that this GPX file has URLs of photos\n\n1354\n01:09:47,617 --> 01:09:52,020\nthat were taken at all of these locations, okay?\n\n1355\n01:09:52,022 --> 01:09:55,056\nSo the next thing we'd like to do is see those. Okay and\n\n1356\n01:09:55,058 --> 01:09:58,226\nwhat I'm gonna try to do is put them as a thumbnail image\n\n1357\n01:09:58,228 --> 01:10:02,297\ninside my left accessory view of these call outs.\n\n1358\n01:10:02,299 --> 01:10:06,534\nNow to do that we're going to need to override or implement\n\n1359\n01:10:06,536 --> 01:10:09,270\nthat method viewForAnnotation. Notice we didn't implement\n\n1360\n01:10:09,272 --> 01:10:11,940\nviewForAnnotation which is like self erode index path,\n\n1361\n01:10:11,942 --> 01:10:14,642\nand when you don't you get this really simple call\n\n1362\n01:10:14,644 --> 01:10:16,611\nout that has no left or right accessory view,\n\n1363\n01:10:16,613 --> 01:10:18,479\njust has the title or subtitle, okay.\n\n1364\n01:10:18,481 --> 01:10:21,382\nBut we need to implement it so we can put a left accessory\n\n1365\n01:10:21,384 --> 01:10:23,785\nview which is going to be a button. I'm gonna have it be a\n\n1366\n01:10:23,787 --> 01:10:25,920\nbutton because I'm gonna want to be able to click on it in\n\n1367\n01:10:25,922 --> 01:10:29,824\nand segue to show me the image later in the demo probably\n\n1368\n01:10:29,826 --> 01:10:33,261\nnext lecture. All right, so how are we gonna do this?\n\n1369\n01:10:33,263 --> 01:10:36,264\nWell we have to implement that method viewForAnnotations.\n\n1370\n01:10:36,266 --> 01:10:38,566\nSo let's see if we can find it. There it is, okay.\n\n1371\n01:10:38,568 --> 01:10:42,904\nMKMap viewForAnnotation, okay? It's asking us to provide\n\n1372\n01:10:42,906 --> 01:10:47,141\nan annotation view for this annotation. So first, I'm\n\n1373\n01:10:47,143 --> 01:10:49,644\ngoing to see if I can get it, and I'm actually gonna do\n\n1374\n01:10:49,646 --> 01:10:53,414\nsomething kind of interesting here. I'm going to type this.\n\n1375\n01:10:53,416 --> 01:10:56,084\nNow, normally you would say why are you putting a type\n\n1376\n01:10:56,086 --> 01:10:58,886\nhere. Because you could just say view equals something and\n\n1377\n01:10:58,888 --> 01:11:01,489\nit would automatically infer the type. Well the reason is\n\n1378\n01:11:01,491 --> 01:11:05,727\ncuz I want it to be implicitly unwrapped. Okay if I didn't\n\n1379\n01:11:05,729 --> 01:11:08,396\nput this here, okay, then it would be an optional\n\n1380\n01:11:08,398 --> 01:11:10,965\nbecause the thing I'm going to call returns an optional, but\n\n1381\n01:11:10,967 --> 01:11:12,767\nI want it implicitly unwrapped so\n\n1382\n01:11:12,769 --> 01:11:14,035\nthe rest of my method method looks like.\n\n1383\n01:11:14,037 --> 01:11:16,838\nThe code and the rest of my method. Okay so\n\n1384\n01:11:16,840 --> 01:11:20,174\nI'm gonna do here. I'm gonna ask the MapView to dequeue\n\n1385\n01:11:20,176 --> 01:11:22,710\na reusable annotationView with an identifier.\n\n1386\n01:11:22,712 --> 01:11:24,779\nNow to be nice I have some constants, so\n\n1387\n01:11:24,781 --> 01:11:28,182\nlet's put them on the bottom here. Okay so\n\n1388\n01:11:28,184 --> 01:11:32,120\nhere's my constants that I have and I have a constant for\n\n1389\n01:11:32,122 --> 01:11:36,357\nthe reuse identifier here. Call it waypoint and say\n\n1390\n01:11:36,359 --> 01:11:42,297\nConstants.AnnotationViewReuse- Identifier.\n\n1391\n01:11:42,299 --> 01:11:43,498\nOkay, so that's de-queueing it.\n\n1392\n01:11:43,500 --> 01:11:46,934\nNow what if this is the first pin it's ever doing? It's not\n\n1393\n01:11:46,936 --> 01:11:49,871\ngoing to be able to de-queue. There's no pins to reuse.\n\n1394\n01:11:49,873 --> 01:11:51,139\nThere's none that were used and\n\n1395\n01:11:51,141 --> 01:11:53,841\nare now left over. So now we're gonna have to say if\n\n1396\n01:11:53,843 --> 01:11:57,078\nthe view Equals nil we have to create this thing because\n\n1397\n01:11:57,080 --> 01:12:00,081\nthere's no prototypes like table view. So I'm going\n\n1398\n01:12:00,083 --> 01:12:04,185\nto create the thing by saying I want an MKPinAnnotationView.\n\n1399\n01:12:04,187 --> 01:12:06,954\nAnd the arguments to initialize here\n\n1400\n01:12:06,956 --> 01:12:10,158\nare the annotation which is this annotation right here.\n\n1401\n01:12:10,160 --> 01:12:13,394\nThat's the annotation we're creating a view for. And\n\n1402\n01:12:13,396 --> 01:12:15,630\nwe wanna use the same ReuseIdentifier right here,\n\n1403\n01:12:15,632 --> 01:12:19,367\nbecause in future, we want this one that we're creating\n\n1404\n01:12:19,369 --> 01:12:23,004\nto be in the reuse queue, okay? And\n\n1405\n01:12:23,006 --> 01:12:26,874\nI'm also gonna say that we can show callouts.\n\n1406\n01:12:27,210 --> 01:12:28,843\nOkay, because by default, I believe,\n\n1407\n01:12:28,845 --> 01:12:30,611\nif you create an MKPinAnnotationView,\n\n1408\n01:12:30,613 --> 01:12:32,447\nit won't show the callouts when you click on it.\n\n1409\n01:12:32,449 --> 01:12:33,948\nSo I wanna make sure it does show the callouts,\n\n1410\n01:12:33,950 --> 01:12:36,684\ncuz that's where my left accessory view is gonna be.\n\n1411\n01:12:36,686 --> 01:12:40,154\nOtherwise, if I was able to dequeue one here then I need\n\n1412\n01:12:40,156 --> 01:12:45,259\nto change the annotation in it to be this annotation here.\n\n1413\n01:12:46,296 --> 01:12:48,062\nOkay? All right,\n\n1414\n01:12:48,064 --> 01:12:51,032\nnow we've got this view, this is basically exactly what's\n\n1415\n01:12:51,034 --> 01:12:53,568\nhappening if we don't implement this method. Okay?\n\n1416\n01:12:53,570 --> 01:12:56,471\nAnd in fact, if I run this, if I just return this view and\n\n1417\n01:12:56,473 --> 01:12:58,840\nrun it, you're gonna see it looks exactly the same,\n\n1418\n01:12:58,842 --> 01:13:03,911\nokay the system basically will do exactly this for you. See?\n\n1419\n01:13:03,913 --> 01:13:07,515\nIf you don't implement it okay? So it's doing exactly\n\n1420\n01:13:07,517 --> 01:13:12,353\nthe same thing. So now,let's add this left annotation view\n\n1421\n01:13:12,355 --> 01:13:16,858\nwhich wants to be a ui button. So how are we gonna do that?\n\n1422\n01:13:16,860 --> 01:13:20,795\nOkay well, let's just first of all let's set the left\n\n1423\n01:13:20,797 --> 01:13:24,899\nleftCalloutAccessoryView to be nil. I'm just going to put\n\n1424\n01:13:24,901 --> 01:13:29,570\nthis little button in there if the GPS point has a photo.\n\n1425\n01:13:29,572 --> 01:13:31,305\nIf it doesn't have a thumbnail image,\n\n1426\n01:13:31,307 --> 01:13:32,607\nI don't want that button to\n\n1427\n01:13:32,609 --> 01:13:34,509\nbe there empty. So, first of all,\n\n1428\n01:13:34,511 --> 01:13:35,376\nI'm going to clear it out.\n\n1429\n01:13:35,378 --> 01:13:39,514\nThen I'm going to say if I can get the waypoint, which I\n\n1430\n01:13:39,516 --> 01:13:42,683\nshould be able to because it's just the annotation\n\n1431\n01:13:42,685 --> 01:13:47,755\nAs a GPX waypoint, right? That's what the waypoint is.\n\n1432\n01:13:47,757 --> 01:13:50,658\nThis annotation, all of our annotations are that. So\n\n1433\n01:13:50,660 --> 01:13:51,826\nas long I'm able to get that waypoint,\n\n1434\n01:13:51,828 --> 01:13:55,029\nwhich I should be able to, then if the waypoint has\n\n1435\n01:13:55,031 --> 01:14:01,636\na thumbnail URL, if that doesn't equal\n\n1436\n01:14:01,638 --> 01:14:05,440\nnil Now this is something I'm gonna have to implement okay.\n\n1437\n01:14:05,442 --> 01:14:06,941\nBecause it doesn't have that method, so\n\n1438\n01:14:06,943 --> 01:14:08,543\nI'm going to have to implement that method.\n\n1439\n01:14:08,545 --> 01:14:11,512\nThen, I'm gonna set my left column so AccessoryView\n\n1440\n01:14:11,514 --> 01:14:15,783\nto be a UI button. Whose frame is this constant.\n\n1441\n01:14:15,785 --> 01:14:18,453\nUnfortunately I have to do a constant here for\n\n1442\n01:14:18,455 --> 01:14:21,956\nthis and I'll show that in a second. The constant for\n\n1443\n01:14:21,958 --> 01:14:25,593\nthis is 59 by 59. This is one of the few cases\n\n1444\n01:14:25,595 --> 01:14:28,329\nin IOS where you're gonna use a magic number. But\n\n1445\n01:14:28,331 --> 01:14:30,498\nunfortunately, they're just doesn't seem to be anyway,\n\n1446\n01:14:30,500 --> 01:14:34,135\nat least that I've ever found, to ask the map views and\n\n1447\n01:14:34,137 --> 01:14:38,239\nnotation view how big is your call-out so that I can make\n\n1448\n01:14:38,241 --> 01:14:41,375\nthe thing the right size. So, I just Know that 59 by\n\n1449\n01:14:41,377 --> 01:14:43,978\n59 works. I hope Apple doesn't change the size of that\n\n1450\n01:14:43,980 --> 01:14:46,380\ncallout in the future, cuz it might break this code.\n\n1451\n01:14:46,382 --> 01:14:47,715\nThat's why you never want magic numbers,\n\n1452\n01:14:47,717 --> 01:14:50,985\nbut unfortunately, we're kind of stuck with one here.\n\n1453\n01:14:50,987 --> 01:14:53,488\nSo, we have this error because thumbnailURL is not\n\n1454\n01:14:53,490 --> 01:14:56,557\nimplemented. So, how are we gonna implement thumbnailURL?\n\n1455\n01:14:56,559 --> 01:14:59,827\nWell, I told you that every GPX waypoint can have\n\n1456\n01:14:59,829 --> 01:15:02,630\na number of links associated with one of them,\n\n1457\n01:15:02,632 --> 01:15:04,632\none of my view thumbnailURL. So\n\n1458\n01:15:04,634 --> 01:15:08,803\nI'm gonna go back to my MKGPX right here and\n\n1459\n01:15:08,805 --> 01:15:11,806\nI'm gonna add this var thumbnailURL, which\n\n1460\n01:15:11,808 --> 01:15:15,776\nis gonna be an NSURL. And this is gonna be optional because,\n\n1461\n01:15:15,778 --> 01:15:18,546\nit might be that it doesn't have one. Which is fine,\n\n1462\n01:15:18,548 --> 01:15:21,215\nnow I just want to show this little side button. And\n\n1463\n01:15:21,217 --> 01:15:24,352\nto implement this, I'm gonna implement a little method\n\n1464\n01:15:24,354 --> 01:15:28,422\nhere, a private func, which goes through the links and\n\n1465\n01:15:28,424 --> 01:15:31,425\ntries to find one of the type thumbnail. So it's gonna be\n\n1466\n01:15:31,427 --> 01:15:36,464\ncalled getImageURLofType. It's gonna take a certain type,\n\n1467\n01:15:36,466 --> 01:15:39,367\nwhich is just a string like thumbnail or something like\n\n1468\n01:15:39,369 --> 01:15:45,640\nthat. And it's going to return an NSURL possibly if\n\n1469\n01:15:45,642 --> 01:15:46,474\nyou can find such a thing, and\n\n1470\n01:15:46,476 --> 01:15:51,345\nI'm just gonna go through the links in the GPXWayPoint. And\n\n1471\n01:15:51,347 --> 01:15:55,082\nif the links type equals the type am asking for then am\n\n1472\n01:15:55,084 --> 01:15:58,619\njust gonna return the links URL, and if I can't do any of\n\n1473\n01:15:58,621 --> 01:16:02,924\nthat I'll return nil. Okay? So this gets an ImageURLofType,\n\n1474\n01:16:02,926 --> 01:16:07,662\nso here I'm gonna get the ImageURLofTyp.\n\n1475\n01:16:07,664 --> 01:16:10,231\nSo if it's able to get a thumbnail image, woo hoo,\n\n1476\n01:16:10,233 --> 01:16:13,568\nwe're good to go, otherwise it'll be returning nil here.\n\n1477\n01:16:13,570 --> 01:16:17,738\nWhile I'm here I'm gonna have another one called imageURL\n\n1478\n01:16:17,740 --> 01:16:20,708\nwhich gets the URL of the image large.\n\n1479\n01:16:20,710 --> 01:16:23,578\nOkay, not a thumbnail of it, but a big, large image of it.\n\n1480\n01:16:23,580 --> 01:16:28,316\nAnd so, that's the type large. Okay, so these are just types\n\n1481\n01:16:28,318 --> 01:16:33,321\nassociated with that link in the GPX file, okay? So\n\n1482\n01:16:33,323 --> 01:16:38,659\nnow we have these, we can go back here, and do this now.\n\n1483\n01:16:38,661 --> 01:16:40,428\nNotice that we, Sorry.\n\n1484\n01:16:40,430 --> 01:16:43,364\n[LAUGH] Create this leftCalloutAccessoryView here.\n\n1485\n01:16:43,366 --> 01:16:44,732\nI'm actually gonna give this some space, but\n\n1486\n01:16:44,734 --> 01:16:47,401\nwe don't actually set the button's image. And\n\n1487\n01:16:47,403 --> 01:16:51,305\nI'm not gonna set that image until the user clicks on me.\n\n1488\n01:16:51,307 --> 01:16:54,675\nOkay? Soon as they click on my pin annotation view,\n\n1489\n01:16:54,677 --> 01:16:55,376\nit makes our callout accessory\n\n1490\n01:16:55,378 --> 01:16:57,345\nis gonna come up. Then I'm gonna go get the image.\n\n1491\n01:16:57,347 --> 01:16:58,646\nCuz getting the image is gonna be expensive.\n\n1492\n01:16:58,648 --> 01:17:01,616\nCuz I'm gonna go get it off the internet somewhere. Okay?\n\n1493\n01:17:01,618 --> 01:17:06,420\nSo let's do that and we do that in this method here\n\n1494\n01:17:06,422 --> 01:17:12,026\ncalled did select annotation view.\n\n1495\n01:17:12,028 --> 01:17:14,895\nOkay, so mapview delegate method here tells us when this\n\n1496\n01:17:14,897 --> 01:17:18,065\nannotation view was selected. And so I'm gonna have to\n\n1497\n01:17:18,067 --> 01:17:21,469\nextract some things here, like I need to get that thumbnail\n\n1498\n01:17:21,471 --> 01:17:24,972\nimage button from the left accessory view. That's just my\n\n1499\n01:17:24,974 --> 01:17:28,776\nleft call out accessory view and it better be a ui button.\n\n1500\n01:17:28,778 --> 01:17:31,112\nSo I'll that's what I'm doing if let here.\n\n1501\n01:17:31,114 --> 01:17:36,984\nI'm also going to get the url which is the gpx waypoint\n\n1502\n01:17:36,986 --> 01:17:42,690\nwhich is the annotation as a gpx waypoint okay?\n\n1503\n01:17:42,692 --> 01:17:47,028\nIt's it's thumbnail URL that method we just implemented.\n\n1504\n01:17:47,030 --> 01:17:49,764\nOkay, I also need to get the image data.\n\n1505\n01:17:49,766 --> 01:17:54,835\nNow I'm gonna be a really bad man here and I'm going\n\n1506\n01:17:54,837 --> 01:18:00,708\nto do this on the main queue okay. Blocks main queue.\n\n1507\n01:18:00,710 --> 01:18:03,944\nYou would never do this in your final projects for\n\n1508\n01:18:03,946 --> 01:18:09,050\nexample okay. And now, I'm going to get the UI image that\n\n1509\n01:18:09,052 --> 01:18:18,592\ncorresponds to that data. All right?\n\n1510\n01:18:18,594 --> 01:18:22,596\nSo now I've run the gauntlet of all of these if lets and\n\n1511\n01:18:22,598 --> 01:18:24,899\nI have the image and I have the thumbnail image button,\n\n1512\n01:18:24,901 --> 01:18:28,602\nso I'm just gonna say thumbnail image button.\n\n1513\n01:18:28,604 --> 01:18:33,274\nSetImage to be that image for the State. Remember\n\n1514\n01:18:33,276 --> 01:18:35,376\nbuttons have different states like highlight and state and\n\n1515\n01:18:35,378 --> 01:18:37,645\nwhatever so I don't want the normal state which is kinda\n\n1516\n01:18:37,647 --> 01:18:42,817\nthe default state, okay. So let's go and run that.\n\n1517\n01:18:47,690 --> 01:18:52,126\nRight, here we go, a click on it and sure enough now we're\n\n1518\n01:18:52,128 --> 01:18:56,363\ngetting this thumbnail in here To that, okay? So\n\n1519\n01:18:56,365 --> 01:18:57,131\nthat's all we have time for today.\n\n1520\n01:18:57,133 --> 01:18:59,667\nWhat we're gonna do next time is I'm gonna click on this\n\n1521\n01:18:59,669 --> 01:19:03,671\nbutton, and we're gonna Segway to the image view controller\n\n1522\n01:19:03,673 --> 01:19:05,806\nwe have in Kissimmee. It's gonna Segway and\n\n1523\n01:19:05,808 --> 01:19:09,777\nshow us the full size image, the large image of that thing.\n\n1524\n01:19:09,779 --> 01:19:12,646\nSo once you have segue. Then, we'll go on and do some more\n\n1525\n01:19:12,648 --> 01:19:17,251\nstuff to show off some other little features. All right?\n\n1526\n01:19:17,253 --> 01:19:20,087\nSo, see you next time. >> For\n\n1527\n01:19:20,089 --> 01:19:20,120\nmore, please visit us at stanford.edu.\n\n"
  },
  {
    "path": "subtitles/18. Persistence.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,469\n[MUSIC]\n\n2\n00:00:03,471 --> 00:00:07,806\nStanford University. >> Okay, well,\n\n3\n00:00:07,808 --> 00:00:12,711\nwelcome to Stanford CSI93P Spring of 2016.\n\n4\n00:00:12,713 --> 00:00:14,947\nThis is our last normal lecture.\n\n5\n00:00:14,949 --> 00:00:18,217\nThe only lecture we have left is our alternate final, next\n\n6\n00:00:18,219 --> 00:00:23,088\nweek. Today we are going to have a demo of all the stuff I\n\n7\n00:00:23,090 --> 00:00:27,760\ntalked about on Monday. So, mostly that's segues.\n\n8\n00:00:27,762 --> 00:00:33,298\nIncluding ma, modal segue, popover segue, unwind segue.\n\n9\n00:00:33,300 --> 00:00:35,868\nAnd even we'll talk about the adaptive presentation,\n\n10\n00:00:35,870 --> 00:00:39,671\nhow we adapt to horizontally compact, all that stuff. And\n\n11\n00:00:39,673 --> 00:00:40,672\nI'll throw a little bit of bonus in there.\n\n12\n00:00:40,674 --> 00:00:43,442\nWe'll talk a little about visual effects, like Blur.\n\n13\n00:00:43,444 --> 00:00:47,513\nYou'll see a lot of Blur in the UI occasionally and\n\n14\n00:00:47,515 --> 00:00:50,682\nI'll show you how to basically do that. And\n\n15\n00:00:50,684 --> 00:00:53,952\nI think that's gonna take most of the time but\n\n16\n00:00:53,954 --> 00:00:55,854\nif I have any time left like maybe five or\n\n17\n00:00:55,856 --> 00:00:58,590\nten minutes left I'll try to do a quick tour through\n\n18\n00:00:58,592 --> 00:01:01,393\npersistence because creating files in the file system,\n\n19\n00:01:01,395 --> 00:01:03,962\nstuff like that is something a lot of people are gonna wanna\n\n20\n00:01:03,964 --> 00:01:06,031\ndo in their final project. So I'll try and cover that. No\n\n21\n00:01:06,033 --> 00:01:08,901\ndemo for that unfortunately, but at least maybe I can get\n\n22\n00:01:08,903 --> 00:01:14,006\nthrough the slides if the demo goes on a good pace, okay?\n\n23\n00:01:14,008 --> 00:01:17,443\nSo here's our demo those all the things we're gonna cover.\n\n24\n00:01:17,445 --> 00:01:20,345\nSo it's quite a quick demo, it, it, or\n\n25\n00:01:20,347 --> 00:01:24,850\nquite a involved demo. It's gonna be an extension of Trax,\n\n26\n00:01:24,852 --> 00:01:27,920\nokay, the thing that we left off with last time.\n\n27\n00:01:27,922 --> 00:01:29,655\nI'll run that really quick just to remind yourself,\n\n28\n00:01:29,657 --> 00:01:34,693\nin the last two days, what it did. So, remember that it went\n\n29\n00:01:34,695 --> 00:01:37,162\nout on the Internet, it grabbed a GPX file, which is\n\n30\n00:01:37,164 --> 00:01:40,099\njust basically a file that contains a bunch of waypoints\n\n31\n00:01:40,101 --> 00:01:43,035\nand possibly hyperlinks attached to the waypoints.\n\n32\n00:01:43,037 --> 00:01:44,670\nAnd it puts them on the map here so\n\n33\n00:01:44,672 --> 00:01:48,207\nwe can scroll around and zoom in and out on them. And\n\n34\n00:01:48,209 --> 00:01:49,675\nwe made it so that if we clicked on them,\n\n35\n00:01:49,677 --> 00:01:52,678\nthe callout had a left accessory callout\n\n36\n00:01:52,680 --> 00:01:55,114\nview right here, this left accessory callout view.\n\n37\n00:01:55,116 --> 00:01:59,785\nAnd put a thumbnail that it found in the GPX file for\n\n38\n00:01:59,787 --> 00:02:03,455\neach waypoint, okay? So now, what we'll do today,\n\n39\n00:02:03,457 --> 00:02:06,024\nthe next thing we're gonna do is learn how to segue from\n\n40\n00:02:06,026 --> 00:02:08,660\na map, because it's a little unusual trying to segue from\n\n41\n00:02:08,662 --> 00:02:12,131\na map because when you look at it in the storyboard it's\n\n42\n00:02:12,133 --> 00:02:13,899\njust blank, this big blank map view,\n\n43\n00:02:13,901 --> 00:02:15,868\nso that you can't, it's not like a table view where you\n\n44\n00:02:15,870 --> 00:02:18,670\ngot a row you can Ctrl+drag from or something. So\n\n45\n00:02:18,672 --> 00:02:21,540\nwe're gonna have to do this segueing from a map in code.\n\n46\n00:02:21,542 --> 00:02:23,809\nAnd what we're gonna do is make it so that when we\n\n47\n00:02:23,811 --> 00:02:27,079\nclick on this little thumbnail button right here, it segues,\n\n48\n00:02:27,081 --> 00:02:31,083\nokay. And puts an image view controller that will show you\n\n49\n00:02:31,085 --> 00:02:36,088\nthe full large image of this. And we're gonna get the UI for\n\n50\n00:02:36,090 --> 00:02:36,455\ndoing that imagery control,\n\n51\n00:02:36,457 --> 00:02:38,357\nwe're just gonna steal that right out of Cassini. I mean,\n\n52\n00:02:38,359 --> 00:02:41,026\nyou're gonna see the advantage of building these MVCs that\n\n53\n00:02:41,028 --> 00:02:44,530\nhave very clear public models. It makes them quite reuseable.\n\n54\n00:02:44,532 --> 00:02:47,833\nSo we can reuse that MVC we made in Cassini with\n\n55\n00:02:47,835 --> 00:02:50,235\nabsolutely no changes. Gonna just drag it in and\n\n56\n00:02:50,237 --> 00:02:53,205\nset up its public API and it'll work perfectly. So\n\n57\n00:02:53,207 --> 00:02:56,441\nlet's go do that right now, let's go over to Cassini.\n\n58\n00:02:56,443 --> 00:03:02,147\nAnd where is Cassini? It's here in Developer > Cassini.\n\n59\n00:03:02,149 --> 00:03:04,683\nWe open Cassi, Cassini here. So remember, you'll\n\n60\n00:03:04,685 --> 00:03:07,853\nremember Cassini here. And we, it's the one that showed the,\n\n61\n00:03:07,855 --> 00:03:10,155\nthe image of Cassini, what it was doing. So\n\n62\n00:03:10,157 --> 00:03:12,457\nI'm just gonna grab this ImageViewController,\n\n63\n00:03:12,459 --> 00:03:15,127\nright here, this class ImageViewController. And\n\n64\n00:03:15,129 --> 00:03:18,664\nI'm gonna pick it up and drag it into my app over here and\n\n65\n00:03:18,666 --> 00:03:22,034\nI'm gonna copy it in, okay? But I can do actually more\n\n66\n00:03:22,036 --> 00:03:24,169\nthan that, more than just grabbing that MVC,\n\n67\n00:03:24,171 --> 00:03:26,738\nI can actually go to the storyboard and find the place\n\n68\n00:03:26,740 --> 00:03:29,441\nin the storyboard, down here actually, where Casini is\n\n69\n00:03:29,443 --> 00:03:33,512\nusing the ImageViewController. And I can copy that scene from\n\n70\n00:03:33,514 --> 00:03:39,184\nCasini and then bring it on over to our storyboard here.\n\n71\n00:03:39,186 --> 00:03:43,589\nWe'll zoom out so you can see this. Okay, and we can paste.\n\n72\n00:03:43,591 --> 00:03:46,024\nAnd that actually dropped an ImageViewController there,\n\n73\n00:03:46,026 --> 00:03:49,328\nwith the scroll view already in it and wired up. And\n\n74\n00:03:49,330 --> 00:03:52,364\nit has the proper identity, right, ImageViewController, so\n\n75\n00:03:52,366 --> 00:03:55,367\nit's all really nice. So don't forget that, in storyboards\n\n76\n00:03:55,369 --> 00:03:58,170\nyou can copy and paste scenes between storyboards and\n\n77\n00:03:58,172 --> 00:03:58,604\nit'll bring it all.\n\n78\n00:03:58,606 --> 00:04:00,439\nAnd it brings it all by name, remember, so\n\n79\n00:04:00,441 --> 00:04:02,441\nyou have to have the classes with the same name or\n\n80\n00:04:02,443 --> 00:04:07,012\noutlets with the same name for it all to work. Okay, so let's\n\n81\n00:04:07,014 --> 00:04:10,649\ngo ahead and build the rest of our UI that we have here.\n\n82\n00:04:10,651 --> 00:04:14,186\nWe want to segue from this map view over to this scroll\n\n83\n00:04:14,188 --> 00:04:17,322\nview, but we don't really anything to Ctrl+drag from\n\n84\n00:04:17,324 --> 00:04:20,092\nhere cuz of the callouts and things like that are all come\n\n85\n00:04:20,094 --> 00:04:22,995\nup from programmatically. So we're gonna do a manual\n\n86\n00:04:22,997 --> 00:04:25,631\nsegue, which we've already seen and the way we do that is\n\n87\n00:04:25,633 --> 00:04:28,433\nwe Ctrl+drag from the View Controller itself just to\n\n88\n00:04:28,435 --> 00:04:31,370\ncreate a segue with a certain identifier, okay, between\n\n89\n00:04:31,372 --> 00:04:36,074\nthe two MVCs. So let's just get these both on screen here.\n\n90\n00:04:36,076 --> 00:04:39,578\nAnd I'm gonna Ctrl+drag from here over to here.\n\n91\n00:04:39,580 --> 00:04:41,780\nWe're gonna put this inside the navigation controller.\n\n92\n00:04:41,782 --> 00:04:45,083\nSo this is gonna be a show segue right here.\n\n93\n00:04:45,085 --> 00:04:48,620\nAnd we'll give it a name. This is gonna show an image, so\n\n94\n00:04:48,622 --> 00:04:51,957\nwe'll call this Show Image segue. Let's be sure to go\n\n95\n00:04:51,959 --> 00:04:57,462\nahead and embed this in a Navigation Controller. Okay,\n\n96\n00:04:57,464 --> 00:05:00,899\noops, so let's zoom out and take a look at our UI. So\n\n97\n00:05:00,901 --> 00:05:03,735\nhere's our UI. We could even do some other things like here\n\n98\n00:05:03,737 --> 00:05:06,505\nI'd maybe this, we wanna give it a title, we'll call it\n\n99\n00:05:06,507 --> 00:05:09,541\nTrax, or something like that. And this title we'll set\n\n100\n00:05:09,543 --> 00:05:11,943\nprogrammatically depending on which waypoint we're\n\n101\n00:05:11,945 --> 00:05:15,447\nlooking at, we'll put whatever the name of that waypoint is\n\n102\n00:05:15,449 --> 00:05:15,714\nso we'll do that in the code. All right, so how are we gonna\n\n103\n00:05:15,716 --> 00:05:20,052\nin at the top,\n\n104\n00:05:20,054 --> 00:05:23,455\nfire off this segue right here from the code?\n\n105\n00:05:23,457 --> 00:05:24,823\nWhere's a good place to do it in the code? Well,\n\n106\n00:05:24,825 --> 00:05:29,728\nwe know we wanna do it when we click on that left accessory\n\n107\n00:05:29,730 --> 00:05:32,764\nview button right there. And if you'll remember from\n\n108\n00:05:32,766 --> 00:05:36,702\nlecture, there's a really cool map view, MKMapViewDelegate\n\n109\n00:05:36,704 --> 00:05:39,571\nmethod, I'm just back here in GPXViewController\n\n110\n00:05:39,573 --> 00:05:42,174\nhere. So this is a really cool MapViewDelegate method\n\n111\n00:05:42,176 --> 00:05:45,844\nthat will get called when an accessory view is tapped on\n\n112\n00:05:45,846 --> 00:05:48,513\nand that accessory view is a UI control like\n\n113\n00:05:48,515 --> 00:05:51,249\na UI button, for example. All right, so let's put that in\n\n114\n00:05:51,251 --> 00:05:54,986\nhere. That thing is called a callout accessory, there it\n\n115\n00:05:54,988 --> 00:06:00,258\nis, MapView, annotationView, calloutAccessory view Tapped,\n\n116\n00:06:00,260 --> 00:06:02,961\nokay? Let's give ourselves a lot more room here.\n\n117\n00:06:02,963 --> 00:06:06,331\nThis is this method. And all we need to do here is look at\n\n118\n00:06:06,333 --> 00:06:09,368\nthe control that was tapped, and see if it's our left\n\n119\n00:06:09,370 --> 00:06:13,105\nAccessoryView, okay? So if the control == our views,\n\n120\n00:06:13,107 --> 00:06:17,609\nleftCalloutAccessoryView, okay, then we know someone\n\n121\n00:06:17,611 --> 00:06:21,580\ntapped on that left side. And we wanna do this segue, and\n\n122\n00:06:21,582 --> 00:06:24,383\nwe know how to perform a segue from clo, from code.\n\n123\n00:06:24,385 --> 00:06:27,686\nWe just do performSegueWithIdentifier.\n\n124\n00:06:27,688 --> 00:06:30,288\nOkay, the identifier is that \"Show Image\", I actually\n\n125\n00:06:30,290 --> 00:06:32,691\ncreated a constant for that right here, okay just so\n\n126\n00:06:32,693 --> 00:06:37,863\nmy code would be nice. So constants.ShowImageSegue.\n\n127\n00:06:37,865 --> 00:06:40,766\nAnd what about the sender? Well, when this segue happens,\n\n128\n00:06:40,768 --> 00:06:44,236\nwe're gonna need to know which of our many waypoints we wanna\n\n129\n00:06:44,238 --> 00:06:47,973\nshow the image of, okay. So we need to pass a sender on\n\n130\n00:06:47,975 --> 00:06:50,809\nto prepareForSegue that can identify it.\n\n131\n00:06:50,811 --> 00:06:53,945\nAnd a simple thing to do here, okay, this argument\n\n132\n00:06:53,947 --> 00:06:57,282\nthat we get right here is the annotationView. Okay,\n\n133\n00:06:57,284 --> 00:07:01,286\nthat was, that this callout has a left accessory view\n\n134\n00:07:01,288 --> 00:07:02,554\nfor, so we'll just pass that along.\n\n135\n00:07:02,556 --> 00:07:05,090\nSo we'll just pass that as the sender, which makes sense,\n\n136\n00:07:05,092 --> 00:07:05,991\nthe annotationView is the sender.\n\n137\n00:07:05,993 --> 00:07:08,727\nAnd from the annotationView, we're gonna be able to get\n\n138\n00:07:08,729 --> 00:07:11,463\nthe waypoint that we want. Okay, so that couldn't\n\n139\n00:07:11,465 --> 00:07:15,300\nbe simpler right there. Now what about the navigation? So\n\n140\n00:07:15,302 --> 00:07:18,103\nlet's put in some navigation here, the prepareForSegue.\n\n141\n00:07:18,105 --> 00:07:20,372\nBecause any segue needs to be prepared. In this case,\n\n142\n00:07:20,374 --> 00:07:23,608\nwe're going to have to prepare that ImageViewController with\n\n143\n00:07:23,610 --> 00:07:25,610\nits public API, which, if you'll remember,\n\n144\n00:07:25,612 --> 00:07:29,247\nis an image URL. We have to give it the URL of an image,\n\n145\n00:07:29,249 --> 00:07:32,150\nokay? So prepareForSegue, let's do that,\n\n146\n00:07:32,152 --> 00:07:36,288\nprepareForSegue. And what do we need for prepareForSegue?\n\n147\n00:07:36,290 --> 00:07:38,623\nWell, first of all, let's collect some information here,\n\n148\n00:07:38,625 --> 00:07:40,525\nlike, let's get the destinationViewController.\n\n149\n00:07:40,527 --> 00:07:43,762\nThat's the segue's destinationViewController.\n\n150\n00:07:43,764 --> 00:07:47,165\nAnd actually, I'm gonna do that contentViewController\n\n151\n00:07:47,167 --> 00:07:50,802\ntrick that we did where we have a little extension,\n\n152\n00:07:50,804 --> 00:07:52,437\ncontentViewController here,\n\n153\n00:07:52,439 --> 00:07:54,739\na little extension to UIViewController.\n\n154\n00:07:54,741 --> 00:07:57,108\nSo that if the thing is in a Navigation Controller,\n\n155\n00:07:57,110 --> 00:07:58,443\nwe return the visibleViewController,\n\n156\n00:07:58,445 --> 00:08:01,112\notherwise we just return self. You remember this from From\n\n157\n00:08:01,114 --> 00:08:03,648\nbefore, this is so that if we're in a split view and\n\n158\n00:08:03,650 --> 00:08:05,717\nwe happen to put the detail, for example,\n\n159\n00:08:05,719 --> 00:08:06,985\ninside a navigation controller,\n\n160\n00:08:06,987 --> 00:08:09,955\nwe can get the thing that's inside. All right, so\n\n161\n00:08:09,957 --> 00:08:13,625\nwe'll do the content view controller. Here, so\n\n162\n00:08:13,627 --> 00:08:17,195\nthat's the destination of, this, segue.\n\n163\n00:08:17,197 --> 00:08:19,931\nLet's get the annotation view, which is the sender,\n\n164\n00:08:19,933 --> 00:08:23,301\nokay this sender any object, should be an annotation view,\n\n165\n00:08:23,303 --> 00:08:24,469\nso let's go ahead and get that.\n\n166\n00:08:24,471 --> 00:08:29,541\nBy saying the sender as an MKAnnotationView. Okay.\n\n167\n00:08:29,543 --> 00:08:33,078\nLet's also get the waypoint that we're talking about here.\n\n168\n00:08:33,080 --> 00:08:35,981\nOkay, all these segues are gonna be segueing from\n\n169\n00:08:35,983 --> 00:08:38,517\nsomething that has a waypoint. So what is that?\n\n170\n00:08:38,519 --> 00:08:43,355\nThat's gonna be the annotationViews annotation.\n\n171\n00:08:43,557 --> 00:08:45,924\nAnd it has to be a gpx waypoint, which they all\n\n172\n00:08:45,926 --> 00:08:50,028\nshould be. All the annotations that we add to our map view\n\n173\n00:08:50,030 --> 00:08:53,665\nimplement the MK protocol, so they're all gpx waypoint.\n\n174\n00:08:53,667 --> 00:08:55,667\nSo this should always come out true.\n\n175\n00:08:55,669 --> 00:08:58,537\nSo we kinda got these little things that we need.\n\n176\n00:08:58,539 --> 00:09:03,241\nSo now lets just say if the segway identifier equals\n\n177\n00:09:03,243 --> 00:09:08,079\nthe Constants.ShowSegue, ShowImageSegue, okay?\n\n178\n00:09:08,081 --> 00:09:11,850\nSo we know we're going the show image. Then if we can get\n\n179\n00:09:11,852 --> 00:09:14,886\nan ImageViewController as the destination, so\n\n180\n00:09:14,888 --> 00:09:18,290\nif the destination is an ImageViewController,\n\n181\n00:09:18,525 --> 00:09:23,028\nthen we can just load it up by saying it's imageURL equals\n\n182\n00:09:23,030 --> 00:09:24,829\nthe waypoints.\n\n183\n00:09:25,766 --> 00:09:29,301\nImage URL, right remember image URL,\n\n184\n00:09:29,303 --> 00:09:32,671\nwe added that when we put this little extension on here that\n\n185\n00:09:32,673 --> 00:09:36,107\ndid the thumbnail URL we also added the image URL. Its just\n\n186\n00:09:36,109 --> 00:09:40,045\ngonna look in the gpx file information to find an image\n\n187\n00:09:40,047 --> 00:09:44,282\nurl that's got the type large verse the type thumbnail.\n\n188\n00:09:44,284 --> 00:09:46,885\nOkay? Cuz we obviously wanna show the large image,\n\n189\n00:09:46,887 --> 00:09:50,522\nwhen we segue to it. All right? All right, so\n\n190\n00:09:50,524 --> 00:09:52,290\nthat's good. While we're here, let's go ahead and\n\n191\n00:09:52,292 --> 00:09:57,662\nset the title of this, thing to be the waypoint's name. So\n\n192\n00:09:57,664 --> 00:10:00,031\nthat'll give us a nice title at the top,\n\n193\n00:10:00,033 --> 00:10:06,571\nof our MVC. Okay? Makes sense? All right so\n\n194\n00:10:06,573 --> 00:10:11,476\nlet's go to run see what this does. See if it works for us?\n\n195\n00:10:17,017 --> 00:10:20,218\nAll right, so here is all of our little waypoints here. So\n\n196\n00:10:20,220 --> 00:10:24,422\nlet's click on waypoint, like this one, still working okay,\n\n197\n00:10:24,424 --> 00:10:26,524\nwe got the picture in here but now hopefully if we click on\n\n198\n00:10:26,526 --> 00:10:30,729\nthis, we'll seque. Sure enough here we go. My image view\n\n199\n00:10:30,731 --> 00:10:32,130\ncontroller is not quite as nice as the one you did in\n\n200\n00:10:32,132 --> 00:10:35,233\nyour homework in terms of the white space management but\n\n201\n00:10:35,235 --> 00:10:37,636\nit works. Notice it's got the title up here as well.\n\n202\n00:10:37,638 --> 00:10:39,471\nThe title of this thing, Panorama,\n\n203\n00:10:39,473 --> 00:10:45,377\ngot passed along there. Okay, so that was pretty easy.\n\n204\n00:10:45,746 --> 00:10:47,679\nThe next thing we're gonna do is make it so\n\n205\n00:10:47,681 --> 00:10:51,816\nthat in our map here, we can add a waypoint.\n\n206\n00:10:51,818 --> 00:10:54,719\nNow, this is a demo, I'm not gonna go so far as to actually\n\n207\n00:10:54,721 --> 00:10:58,356\nrewrite the gpx file to add this waypoint to it, but I'm\n\n208\n00:10:58,358 --> 00:11:02,260\ngonna show you how to at least add the waypoint to the map.\n\n209\n00:11:02,262 --> 00:11:05,563\nNow, the UI I'm gonna use here is long press.\n\n210\n00:11:05,565 --> 00:11:08,166\nI don't know if you've seen a long press gesture, but\n\n211\n00:11:08,168 --> 00:11:10,368\nbasically if you just press with your finger and\n\n212\n00:11:10,370 --> 00:11:11,169\nyou hold it down long enough,\n\n213\n00:11:11,171 --> 00:11:14,839\nit'll start looking like a long press, to iOS.\n\n214\n00:11:14,841 --> 00:11:17,442\nAnd when you long press, I'm gonna drop another pin there.\n\n215\n00:11:17,444 --> 00:11:21,780\nA new pin. It's gonna be a new we, new waypoint. All right so\n\n216\n00:11:21,782 --> 00:11:23,348\nlet's put that in our UI first,\n\n217\n00:11:23,350 --> 00:11:26,851\nlet's go, back here to our story board and\n\n218\n00:11:26,853 --> 00:11:30,221\nwe're just gonna add a long press gesture to this map, so\n\n219\n00:11:30,223 --> 00:11:34,092\ni'm gonna go over here down to this, I'll even search for it\n\n220\n00:11:34,094 --> 00:11:36,594\nand make it even easier, long press. Here it is right here,\n\n221\n00:11:36,596 --> 00:11:39,497\nso I'm gonna add this long press the map view is the one\n\n222\n00:11:39,499 --> 00:11:44,102\nthat is gonna recognize it right there, to it.\n\n223\n00:11:44,104 --> 00:11:48,373\nAnd now we're go ahead and make this long press send\n\n224\n00:11:48,375 --> 00:11:51,009\naction to our con, view controller. So let's get them\n\n225\n00:11:51,011 --> 00:11:55,780\non the screen at the same time here. All right go automatic.\n\n226\n00:11:56,049 --> 00:12:01,119\nOkay we'll put it let's put it right down here. Okay? So\n\n227\n00:12:01,121 --> 00:12:03,755\nI'm just gonna Ctrl+drag from the long press gesture\n\n228\n00:12:03,757 --> 00:12:07,792\ninto here. Its going to be an action, we will call this Add\n\n229\n00:12:07,794 --> 00:12:10,829\nwayPoint because that is what this gesture is going to do,\n\n230\n00:12:10,831 --> 00:12:15,166\nits going to add a waypoint. OK, lets go ahead and\n\n231\n00:12:15,168 --> 00:12:19,871\ngo back here. All right, so we have got Add waypoint right\n\n232\n00:12:19,873 --> 00:12:22,674\nhere. What do we need to do when we add a waypoint?\n\n233\n00:12:22,676 --> 00:12:27,712\nWell, first we're going to do it as soon as we\n\n234\n00:12:27,714 --> 00:12:32,484\nrecognize the long press. So soon as it\n\n235\n00:12:32,486 --> 00:12:35,019\nstarts recognizing this long press, we're going to do it.\n\n236\n00:12:35,021 --> 00:12:37,622\nNow a long press is actually a continuous gesture.\n\n237\n00:12:37,624 --> 00:12:39,157\nIf you hold the long town press down,\n\n238\n00:12:39,159 --> 00:12:41,693\nit'll keep firing. Okay fire over and over and\n\n239\n00:12:41,695 --> 00:12:43,027\nover. We don't want that we don't want to add\n\n240\n00:12:43,029 --> 00:12:44,662\na whole bunch of waypoints we just want the first one.\n\n241\n00:12:44,664 --> 00:12:46,898\nSo as soon as we recognize that it's a long press\n\n242\n00:12:46,900 --> 00:12:48,900\nwe're gonna drop the waypoint and we don't care what happens\n\n243\n00:12:48,902 --> 00:12:52,637\nwith the press after that we're ignoring. Okay?\n\n244\n00:12:52,639 --> 00:12:54,472\nSo we've got to get the coordinate\n\n245\n00:12:54,474 --> 00:12:57,408\nokay that CL coordinate 2d right the latitude and\n\n246\n00:12:57,410 --> 00:13:01,246\nlongitude of this thing that's dropped. And to do that,\n\n247\n00:13:01,248 --> 00:13:03,648\nwe're gonna have to take the coordinate from the gesture,\n\n248\n00:13:03,650 --> 00:13:06,751\nwhich is a view coordinate, and turn it into longitude and\n\n249\n00:13:06,753 --> 00:13:09,621\nlatitude. Well luckily Mapview knows how to do that,\n\n250\n00:13:09,623 --> 00:13:13,024\nMapview has a method called convertPoint,\n\n251\n00:13:13,026 --> 00:13:14,793\ntwo coordinate from view, you see it right there,\n\n252\n00:13:14,795 --> 00:13:17,762\nthe first one, Convert point to coordinate from view. So\n\n253\n00:13:17,764 --> 00:13:22,767\nthe point it wants to convert is the gesture recognizers\n\n254\n00:13:22,769 --> 00:13:27,172\nlocation in view, okay. And what view?\n\n255\n00:13:27,174 --> 00:13:28,373\nThe map view itself. So\n\n256\n00:13:28,375 --> 00:13:30,708\nwe're gonna get the location to gesture in the map view and\n\n257\n00:13:30,710 --> 00:13:34,712\nwe're going to turn it into a coordinate and the coordinates\n\n258\n00:13:34,714 --> 00:13:40,084\nwe're, converting from is the map view also. Okay.\n\n259\n00:13:40,086 --> 00:13:43,454\nSo now we've got the latitude and longitude that the long\n\n260\n00:13:43,456 --> 00:13:46,457\npress happened at. So now let's create a wave point, and\n\n261\n00:13:46,459 --> 00:13:50,628\nwe're going to do that by just saying GPX.wavepoint, latitude\n\n262\n00:13:50,630 --> 00:13:53,832\nand longitude. Right? So the latitude is the coordinates\n\n263\n00:13:53,834 --> 00:13:59,304\nlatitude, and longitude is the coordinates longitude. Right?\n\n264\n00:13:59,306 --> 00:13:59,704\nThis coordinate right here,\n\n265\n00:13:59,706 --> 00:14:02,807\nthat's this coordinate we just created. All right. So we got\n\n266\n00:14:02,809 --> 00:14:06,211\na waypoint and we can give the waypoint a name, let's give it\n\n267\n00:14:06,213 --> 00:14:08,847\na default name. We'll call it Dropped since we just dropped\n\n268\n00:14:08,849 --> 00:14:12,417\nthis waypoint onto of the map. Now let's go and add that as\n\n269\n00:14:12,419 --> 00:14:17,355\nan annotation, to the map, and we know that this is legal for\n\n270\n00:14:17,357 --> 00:14:21,025\nus to do because addAnnotation takes an MKAnnotation and\n\n271\n00:14:21,027 --> 00:14:22,160\nwe know that GPS. Way,\n\n272\n00:14:22,162 --> 00:14:25,230\nGPX.Waypoint implements the MKAnnotation protocol, so\n\n273\n00:14:25,232 --> 00:14:29,868\nthis is perfectly legal for us to do, right? All right, so\n\n274\n00:14:29,870 --> 00:14:37,542\nlet's go take a look see if this works. All right,\n\n275\n00:14:37,544 --> 00:14:40,645\nso here we are. I'm just going to let's say right up here is\n\n276\n00:14:40,647 --> 00:14:43,514\na little airport here, so let's hold it down and\n\n277\n00:14:43,516 --> 00:14:45,216\ndrop and sure enough, it dropped a pin there, okay.\n\n278\n00:14:45,218 --> 00:14:48,219\nWe drop another one over here, another one over here. Now,\n\n279\n00:14:48,221 --> 00:14:51,923\nif I click on this, I'm just gonna get dropped. Okay?\n\n280\n00:14:51,925 --> 00:14:54,425\nAlso, what if I put this in the wrong spot and\n\n281\n00:14:54,427 --> 00:14:57,061\nI wanted to pick it up? 'Kay, there's no way to pick it up\n\n282\n00:14:57,063 --> 00:15:02,100\nand move it and that's because these pins are not \"dragable.\"\n\n283\n00:15:02,102 --> 00:15:04,669\nAnd if you remember from the, la a, slides,\n\n284\n00:15:04,671 --> 00:15:07,438\nto make a pin dragable you have to take that coordinate,\n\n285\n00:15:07,440 --> 00:15:10,608\nma, var, you know we have this coordinate var that we added\n\n286\n00:15:10,610 --> 00:15:13,912\nwhen we were implementing MKannotation we added this.\n\n287\n00:15:13,914 --> 00:15:16,948\nThis has to be read and write. To make these things\n\n288\n00:15:16,950 --> 00:15:19,183\nobviously dragable if they're going to be dragable when they\n\n289\n00:15:19,185 --> 00:15:21,653\ndrop into a new place we need to set the new coordinates.\n\n290\n00:15:21,655 --> 00:15:24,722\nSo we need to have a editable or\n\n291\n00:15:24,724 --> 00:15:27,225\none of these that has a get and a set. So\n\n292\n00:15:27,227 --> 00:15:30,995\nI'm actually going to do that by creating a subclass of\n\n293\n00:15:30,997 --> 00:15:36,601\nGPX Waypoint called editable ed it a ble waypoint,\n\n294\n00:15:36,603 --> 00:15:40,905\nokay. It's just gonna sub class GPX.waypoint and\n\n295\n00:15:40,907 --> 00:15:43,508\nin that sub class I'm gonna make coordinate.\n\n296\n00:15:43,510 --> 00:15:48,680\nB read right VAR. So coordinate, CL location,\n\n297\n00:15:48,682 --> 00:15:50,882\ncoordinate 2D is gonna have a get and\n\n298\n00:15:50,884 --> 00:15:54,152\nit's also gonna have the set. Now for the get, I'm just\n\n299\n00:15:54,154 --> 00:15:58,022\ngonna do super. coordinate. Okay? We should note\n\n300\n00:15:58,024 --> 00:16:02,527\nthat we are overriding this bar from gpx waypoint, okay.\n\n301\n00:16:02,529 --> 00:16:05,830\nAnd for the set, we've got this new value which is\n\n302\n00:16:05,832 --> 00:16:09,400\na coordinate and I need to put that into the GPXs data\n\n303\n00:16:09,402 --> 00:16:13,137\nstructure which is latitude and longitude right?\n\n304\n00:16:13,139 --> 00:16:15,807\nSo, I'm just gonna say here that,\n\n305\n00:16:15,809 --> 00:16:19,978\nour latitude equals the new value's latitude and\n\n306\n00:16:19,980 --> 00:16:24,082\nour longitude equals the new value's longitude.\n\n307\n00:16:24,084 --> 00:16:27,585\nOkay, so we're setting the latitude and the longitude in\n\n308\n00:16:27,587 --> 00:16:31,622\nthe GPX waypoint from this new coordinate value that we got.\n\n309\n00:16:31,624 --> 00:16:35,526\nOkay. So, we'll do that. Everybody get that.\n\n310\n00:16:35,528 --> 00:16:36,627\nEveryone understand what I what I did there?\n\n311\n00:16:36,629 --> 00:16:38,930\nSo, I have this new class now, EditableWaypoint.\n\n312\n00:16:38,932 --> 00:16:41,165\nYeah, I probably could have done that here,\n\n313\n00:16:41,167 --> 00:16:44,002\nput in the extension but it's actually nice as you're\n\n314\n00:16:44,004 --> 00:16:46,771\ngonna see to have a whole class that we know that this\n\n315\n00:16:46,773 --> 00:16:49,140\nis an editable waypoint by looking at its class,\n\n316\n00:16:49,142 --> 00:16:53,745\nactually. All right? Okay, so let's go back now to here, and\n\n317\n00:16:53,747 --> 00:16:57,148\ninstead of creating a GPX waypoint here now when we add\n\n318\n00:16:57,150 --> 00:17:02,086\nwaypoint, I'm gonna create an editable waypoint. Okay.\n\n319\n00:17:02,088 --> 00:17:04,389\nSo that, so that it can be moved around.\n\n320\n00:17:04,391 --> 00:17:07,892\nNow, the other thing I need to do to make it an draggable\n\n321\n00:17:07,894 --> 00:17:11,629\nis to go here to where I create my annotation view for\n\n322\n00:17:11,631 --> 00:17:13,131\nannotation which remember,\n\n323\n00:17:13,133 --> 00:17:15,900\nis kind of self row index path for map view.\n\n324\n00:17:15,902 --> 00:17:17,602\nHere's where I create the left call it accessory.\n\n325\n00:17:17,604 --> 00:17:21,806\nI also need to say whether it's draggable. Okay?\n\n326\n00:17:21,808 --> 00:17:25,643\nAnd that's just going to be, whether or not the annotation\n\n327\n00:17:25,645 --> 00:17:29,647\nthat we passed on here is an editable waypoint. Okay?\n\n328\n00:17:29,649 --> 00:17:31,783\nIf annotation is of class editable waypoint,\n\n329\n00:17:31,785 --> 00:17:34,352\nthen we know it's editable, and so it's dragable.\n\n330\n00:17:34,354 --> 00:17:37,188\nSee how giving that in a separate class was kind of\n\n331\n00:17:37,190 --> 00:17:39,724\ncool? Makes our code read kind of nice there.\n\n332\n00:17:39,726 --> 00:17:42,527\nAll right, so we should be able to drag this around, so\n\n333\n00:17:42,529 --> 00:17:49,801\nlet's see if it works. All right,\n\n334\n00:17:49,803 --> 00:17:51,836\nso you going to drop one right here, here it is,\n\n335\n00:17:51,838 --> 00:17:54,338\nwe can see this is dropped. Can we pick it up and drag it?\n\n336\n00:17:54,340 --> 00:17:59,377\nLet's see. Yes, we can put it somewhere else pick it\n\n337\n00:17:59,379 --> 00:18:02,947\nup again put it over here. Okay so\n\n338\n00:18:02,949 --> 00:18:06,050\nthat's kind of cool. So, now what are we gonna do? Well,\n\n339\n00:18:06,052 --> 00:18:09,353\nit's kind of annoying that this just says dropped, okay.\n\n340\n00:18:09,355 --> 00:18:10,788\nWe don't want it to say dropped,\n\n341\n00:18:10,790 --> 00:18:11,923\nwe wanna actually edit it and so,\n\n342\n00:18:11,925 --> 00:18:13,891\nyou know if I put it over here on top of this little\n\n343\n00:18:13,893 --> 00:18:17,328\nairport right here, I probably wanna put airport in there.\n\n344\n00:18:17,330 --> 00:18:20,431\nOkay? And so how are we gonna do that? Well,\n\n345\n00:18:20,433 --> 00:18:23,334\nthis is a good opportunity to show you a modal segue.\n\n346\n00:18:23,336 --> 00:18:27,138\nOkay, cuz what we're gonna do is we're gonna create a little\n\n347\n00:18:27,140 --> 00:18:29,807\nMVC to edit the name and the description there of\n\n348\n00:18:29,809 --> 00:18:33,244\nthe waypoint and we're going to modally present that MVC,\n\n349\n00:18:33,246 --> 00:18:37,448\nokay? So, how we're gonna do that? Pretty straightforward.\n\n350\n00:18:37,450 --> 00:18:40,985\nLet's start here by figuring out how we're gonna get\n\n351\n00:18:40,987 --> 00:18:42,120\nthat modal MVC to appear and\n\n352\n00:18:42,122 --> 00:18:44,956\nwhat I'm gonna do is you see how I'm using over here\n\n353\n00:18:44,958 --> 00:18:48,326\nat the left accessory view. Now, I'm gonna use the right\n\n354\n00:18:48,328 --> 00:18:50,928\naccessory view on these and I'm gonna put a detail\n\n355\n00:18:50,930 --> 00:18:54,132\ndisclosure button in there. That's the little blue kinda\n\n356\n00:18:54,134 --> 00:18:57,101\nlooks like a blue round circle with a carrot in it. So,\n\n357\n00:18:57,103 --> 00:18:59,804\nI'm gonna put that kind of button in here and only on\n\n358\n00:18:59,806 --> 00:19:02,173\nthat editable way points will I put it there. And\n\n359\n00:19:02,175 --> 00:19:05,309\nwhen you click on that, it's going to bring up this modal\n\n360\n00:19:05,311 --> 00:19:09,714\npanel that lets you edit the name and info. Okay. So, let's\n\n361\n00:19:09,716 --> 00:19:15,219\ngo ahead and do that, let's change our UI to make our UI,\n\n362\n00:19:15,221 --> 00:19:17,822\nthat's how we gonna do that.\n\n363\n00:19:17,824 --> 00:19:20,358\nWe're gonna have to add a RightCalloutAccessoryView.\n\n364\n00:19:20,360 --> 00:19:22,760\nJust like we added a leftCalloutAccessoryView here,\n\n365\n00:19:22,762 --> 00:19:25,329\nso I'm gonna do the same thing where I clear it out first\n\n366\n00:19:25,331 --> 00:19:27,698\nbecause if it's not at an editable waypoint we don't\n\n367\n00:19:27,700 --> 00:19:30,301\nwant it in there. And remember we're reusing these things,\n\n368\n00:19:30,303 --> 00:19:33,538\nright? DQ reusable. So, we have to clear it out from\n\n369\n00:19:33,540 --> 00:19:37,141\nprevious uses. And so, here I'm just gonna say,\n\n370\n00:19:37,143 --> 00:19:41,479\nif the waypoint is an EditableWaypoint,then I need\n\n371\n00:19:41,481 --> 00:19:46,017\nto add this rightCallout AccessoryView which is just\n\n372\n00:19:46,019 --> 00:19:51,022\ngoing to be a UIButton(type: .DetailDisclosure).\n\n373\n00:19:51,024 --> 00:19:51,923\nOkay, so I'm just going to put it on.\n\n374\n00:19:51,925 --> 00:19:54,792\nThis is only going to appear on editable ones which is\n\n375\n00:19:54,794 --> 00:19:58,196\nexactly what we want. Now, how do we make it so that it's\n\n376\n00:19:58,198 --> 00:20:01,866\ngoing to Do this modal segue whenever we're gonna do it.\n\n377\n00:20:01,868 --> 00:20:03,801\nWe're gonna do the exact same way that we did for\n\n378\n00:20:03,803 --> 00:20:06,637\nthe left call-out accessory, which is what we're gonna do\n\n379\n00:20:06,639 --> 00:20:08,639\nit in this call-out accessory control tapped.\n\n380\n00:20:08,641 --> 00:20:11,375\nOkay, cuz now this the right side one. So, I'm gonna say\n\n381\n00:20:11,377 --> 00:20:15,813\nelse if the control equals the right call-out accessory view.\n\n382\n00:20:15,815 --> 00:20:21,552\nOkay? Then, I need to perform a segue, the different one.\n\n383\n00:20:22,121 --> 00:20:25,756\nThis one's gonna be called, let's see what I call down\n\n384\n00:20:25,758 --> 00:20:28,759\nhere in the constance. I call it edit way points,\n\n385\n00:20:28,761 --> 00:20:32,830\nthe Edit user way points segway, right? Edit user way\n\n386\n00:20:32,832 --> 00:20:36,000\npoints and the sender still gonna be the view because we\n\n387\n00:20:36,002 --> 00:20:39,003\nstill wanna know which way point we're editing, okay? And\n\n388\n00:20:39,005 --> 00:20:42,540\nof course, we have to fix or prepare for segway to do that\n\n389\n00:20:42,542 --> 00:20:47,311\nas well. Let's take a time out from doing our prepare for\n\n390\n00:20:47,313 --> 00:20:51,315\nsegue and go into our storyboard and add that new\n\n391\n00:20:51,317 --> 00:20:54,552\nMVC. All right, so here we are, I'm going to make this\n\n392\n00:20:54,554 --> 00:20:56,053\na little zoomed out a little bit. So,\n\n393\n00:20:56,055 --> 00:20:58,823\nI'm going to put this new view controller just by dragging\n\n394\n00:20:58,825 --> 00:21:01,158\nout an empty view controller on to the top up here.\n\n395\n00:21:01,160 --> 00:21:02,226\nThis is where we're going to put this thing.\n\n396\n00:21:02,228 --> 00:21:05,896\nIt's of course, going to need it's own Custom Class so lets\n\n397\n00:21:05,898 --> 00:21:10,635\ngo file New. Create a subclass of UI View Controller. Okay.\n\n398\n00:21:10,637 --> 00:21:13,371\nWe'll call this our Edit Waypoint View Controller\n\n399\n00:21:13,373 --> 00:21:16,674\nbecause that's what it does. Edit a waypoint.\n\n400\n00:21:16,676 --> 00:21:19,343\nI'll put it same place as everything as usual.\n\n401\n00:21:19,345 --> 00:21:22,980\nHere it is, we'll go ahead and get rid of all this stuff.\n\n402\n00:21:23,950 --> 00:21:26,484\nYeah, so that's clean. Let's go ahead and build the ui of\n\n403\n00:21:26,486 --> 00:21:30,321\nit, okay what's the ui of this thing gonna look like here?\n\n404\n00:21:30,323 --> 00:21:32,290\nWell, it's gonna be a pretty simple UI,\n\n405\n00:21:32,292 --> 00:21:33,591\nit's gonna have two fields, one for\n\n406\n00:21:33,593 --> 00:21:36,527\nthe name of the waypoint and one for like the info, right,\n\n407\n00:21:36,529 --> 00:21:38,429\nthe little description of the waypoint. So,\n\n408\n00:21:38,431 --> 00:21:41,565\nthat's gonna be easy to build, let's just go down here and\n\n409\n00:21:41,567 --> 00:21:44,068\ngrab a text field or two, there's one text field,\n\n410\n00:21:44,070 --> 00:21:47,471\nthere's another one, let's grab a couple labels okay for\n\n411\n00:21:47,473 --> 00:21:50,141\nour name and description. So, all right so\n\n412\n00:21:50,143 --> 00:21:51,442\nthis is the name of the waypoint.\n\n413\n00:21:51,444 --> 00:21:56,347\nThis is the description of it which is called the info field\n\n414\n00:21:56,349 --> 00:22:00,084\nin the GPX structure. So, we'll right align these\n\n415\n00:22:00,086 --> 00:22:02,887\nbecause they're gonna be names. We'll go ahead and\n\n416\n00:22:02,889 --> 00:22:06,724\nput these in a stack view here. So, let's embed these in\n\n417\n00:22:06,726 --> 00:22:08,893\na stack view. Hopefully it'll figure out it's horizontal.\n\n418\n00:22:08,895 --> 00:22:11,495\nIt does. We'll put a little spacing in there,\n\n419\n00:22:11,497 --> 00:22:13,264\nmaybe eight or something like that.\n\n420\n00:22:13,266 --> 00:22:16,534\nSame thing here, let's put those in. Okay.\n\n421\n00:22:16,536 --> 00:22:22,973\nAlso, eight. Now, let's put these in vertical stack view.\n\n422\n00:22:26,079 --> 00:22:29,113\nOkay, maybe we'll also do 8 here as well.\n\n423\n00:22:29,115 --> 00:22:32,783\nOkay. Now, these aren't quite looking like what we want,\n\n424\n00:22:32,785 --> 00:22:35,152\nthis, this kind of, this is in the center.\n\n425\n00:22:35,154 --> 00:22:37,421\nWe don't really want center alignment here,\n\n426\n00:22:37,423 --> 00:22:39,490\nwe'd like it to fill the entire space. Also,\n\n427\n00:22:39,492 --> 00:22:42,560\nwe'd really want this and this lined up, which really means\n\n428\n00:22:42,562 --> 00:22:45,296\nwe want Name and Description to be the same width. So,\n\n429\n00:22:45,298 --> 00:22:48,966\nI'm actually going to control drag between these two and\n\n430\n00:22:48,968 --> 00:22:52,069\nmake them be equal widths, okay? Make name and\n\n431\n00:22:52,071 --> 00:22:55,973\ndescription be equal widths and also it's gonna,\n\n432\n00:22:55,975 --> 00:22:59,477\nlet me take it back in a second here I think.\n\n433\n00:22:59,479 --> 00:23:00,911\nLet's also put it in position.\n\n434\n00:23:00,913 --> 00:23:05,282\nWe're gonna put this leading edge, we're gonna put this\n\n435\n00:23:05,284 --> 00:23:09,253\nthe top edge, we'll put this to the trailing edge and\n\n436\n00:23:09,255 --> 00:23:13,924\nwe'll put this to the bottom edge. Okay? Now, where we\n\n437\n00:23:13,926 --> 00:23:17,995\nput these is a little weird. Okay, this one is our standard\n\n438\n00:23:17,997 --> 00:23:21,899\nthing here where we want this to be zero or standard value.\n\n439\n00:23:21,901 --> 00:23:23,701\nSo, there's no standard value so we'll make it zero.\n\n440\n00:23:23,703 --> 00:23:27,138\nThat makes it nice and wide. That's good. This one right\n\n441\n00:23:27,140 --> 00:23:30,374\nhere, I actually don't want this one to be zero cuz\n\n442\n00:23:30,376 --> 00:23:33,244\nI really want name and description to sit at the top.\n\n443\n00:23:33,246 --> 00:23:35,746\nSo, you might argue I don't even need a constraint on\n\n444\n00:23:35,748 --> 00:23:38,716\nthe bottom here, but here's the thing when I put this\n\n445\n00:23:38,718 --> 00:23:41,952\non screen, okay the size is gonna change I always wanna\n\n446\n00:23:41,954 --> 00:23:45,122\nmake sure there's at least the standard issue thing from\n\n447\n00:23:45,124 --> 00:23:47,391\nthe bottom. Get a standard space from the bottom and\n\n448\n00:23:47,393 --> 00:23:49,527\nyou'll see why that is a little bit later. So,\n\n449\n00:23:49,529 --> 00:23:53,197\nI'm actually have the constant here be greater than or\n\n450\n00:23:53,199 --> 00:23:54,932\nequal to the standard value. Okay,\n\n451\n00:23:54,934 --> 00:23:57,535\nso just remember that I put a constraint on the bottom to\n\n452\n00:23:57,537 --> 00:24:00,971\nmake sure it's greater than or equal to the standard value.\n\n453\n00:24:00,973 --> 00:24:03,641\nWe we'll see that later. So,\n\n454\n00:24:03,643 --> 00:24:08,078\nequal widths. Thought I had done that. Okay, anyway, so\n\n455\n00:24:08,080 --> 00:24:12,850\nthis looks pretty good for our UI, okay? Using the space,\n\n456\n00:24:12,852 --> 00:24:15,853\netc. It's kind of lining things up nicely. So\n\n457\n00:24:15,855 --> 00:24:18,456\nlet's go ahead and create a couple of outlets to pl,\n\n458\n00:24:18,458 --> 00:24:23,494\nplug into these two things, all right. Let's\n\n459\n00:24:23,496 --> 00:24:26,730\nmake sure we set the right class for this. We don't want\n\n460\n00:24:26,732 --> 00:24:29,567\nto be in GPS Waypoint view controller, we wanted to be in\n\n461\n00:24:29,569 --> 00:24:32,536\nEdit Waypoint view controller. That's why we're not getting\n\n462\n00:24:32,538 --> 00:24:36,240\nthe right class here when we try to do our list.\n\n463\n00:24:36,242 --> 00:24:37,575\nLet us drag our outlay here.\n\n464\n00:24:37,577 --> 00:24:41,979\nThis outlay is going to be NameTextField. And\n\n465\n00:24:41,981 --> 00:24:47,017\nthis one is going to be, call this the infoTextField.\n\n466\n00:24:47,854 --> 00:24:53,457\nAll right? And so we kinda set up our UI here how we want it.\n\n467\n00:24:53,459 --> 00:24:58,128\nWhat do we wanna do here in terms of a let's\n\n468\n00:24:58,130 --> 00:25:01,932\nmake this over here. Let's look at our edit wave.\n\n469\n00:25:01,934 --> 00:25:05,402\nOkay, what do we want to do in terms of a public model here,\n\n470\n00:25:05,404 --> 00:25:05,703\nso that people can set it?\n\n471\n00:25:05,705 --> 00:25:09,507\nWell, that's obvious, we want the a- waypoint to edit. 'Kay?\n\n472\n00:25:09,509 --> 00:25:14,478\nGPX, sorry, editable waypoint. Let it be optional.\n\n473\n00:25:14,480 --> 00:25:17,214\nSo that's the public API. If someone sets this waypoint\n\n474\n00:25:17,216 --> 00:25:20,017\nthen obviously we're going to have our UI show it. And when\n\n475\n00:25:20,019 --> 00:25:23,487\nthe UI is changing, it's going to be changing this way point.\n\n476\n00:25:23,489 --> 00:25:26,524\nSo, when it gets set, we're gonna have to update your,\n\n477\n00:25:26,526 --> 00:25:29,693\nour UI. So we'll call updateUI and make a method that does\n\n478\n00:25:29,695 --> 00:25:34,765\nthat. Probably here when these well we'll talk about\n\n479\n00:25:34,767 --> 00:25:40,204\nthat in a second, so let's get our private funk update ui.\n\n480\n00:25:40,640 --> 00:25:41,939\nSo what do we do to update the ui?\n\n481\n00:25:41,941 --> 00:25:47,478\nI'm just gonna have the name, text fields, text equal\n\n482\n00:25:47,480 --> 00:25:52,116\nthe waypoint to edit name.\n\n483\n00:25:52,818 --> 00:25:57,187\nAnd similarly the info text field Text equals\n\n484\n00:25:57,189 --> 00:26:02,226\nthe Way PointTo Edit info. Okay. So\n\n485\n00:26:02,228 --> 00:26:05,996\nthat's updating that. Probably also we should View Did Load.\n\n486\n00:26:05,998 --> 00:26:12,403\nAnd View Did Load will also update our UI.\n\n487\n00:26:12,405 --> 00:26:14,805\nThat way when we're sequeway to it or\n\n488\n00:26:14,807 --> 00:26:18,442\nsomething if we set this before our outlets are set,\n\n489\n00:26:18,444 --> 00:26:23,714\nlater on or. Now this is great for transferring information\n\n490\n00:26:23,716 --> 00:26:26,183\nfrom the waypoint to our text fields.\n\n491\n00:26:26,185 --> 00:26:28,986\nWhat about the other way? We edit in the text fields,\n\n492\n00:26:28,988 --> 00:26:31,956\nwe have to edit our waypoint. So how are we going to that?\n\n493\n00:26:31,958 --> 00:26:33,591\nWell, there's actually a number of ways\n\n494\n00:26:33,593 --> 00:26:34,558\nto do that. I already showed you\n\n495\n00:26:34,560 --> 00:26:36,961\nin textfield how to do that with delegate messages.\n\n496\n00:26:36,963 --> 00:26:40,064\nI'm gonna show you how to do it now with radio stations.\n\n497\n00:26:40,066 --> 00:26:43,000\nOkay? Text fields actually broadcast on a radio station,\n\n498\n00:26:43,002 --> 00:26:46,236\nand one of the things they'll broadcast is my text changed.\n\n499\n00:26:46,238 --> 00:26:48,172\nSo you can listen to that radio station, and\n\n500\n00:26:48,174 --> 00:26:51,108\nevery time the text changes you can update whatever\n\n501\n00:26:51,110 --> 00:26:55,946\nthing you want to update. Now, before we do that, we\n\n502\n00:26:55,948 --> 00:26:58,616\nalso need some things from the text fields delegate, however.\n\n503\n00:26:58,618 --> 00:27:01,218\nLike, I'd like to control the keyboard a little bit.\n\n504\n00:27:01,220 --> 00:27:03,954\nSo, every time you press return in the keyboard,\n\n505\n00:27:03,956 --> 00:27:05,255\nI'd like to remove the keyboard,\n\n506\n00:27:05,257 --> 00:27:07,858\njust to clear it out of your way. So, how may I do that?\n\n507\n00:27:07,860 --> 00:27:13,831\nI'm gonna make sure that I am the main text fields delegate.\n\n508\n00:27:15,301 --> 00:27:15,933\nOkay so let's go ahead and\n\n509\n00:27:15,935 --> 00:27:19,903\nmake sure we are a UI text field delegate.\n\n510\n00:27:20,673 --> 00:27:25,509\nDo the same thing with the info text field here.\n\n511\n00:27:25,511 --> 00:27:29,213\nAll right, so now with the delegate.\n\n512\n00:27:29,215 --> 00:27:32,016\nWhat are we going to do here on that famous text\n\n513\n00:27:32,018 --> 00:27:35,586\nfield should return target method right here.\n\n514\n00:27:35,588 --> 00:27:39,857\nI'm just gonna say text field, resign your first responder.\n\n515\n00:27:39,859 --> 00:27:43,360\n'Kay. And I'll return true,\n\n516\n00:27:43,362 --> 00:27:45,229\n'cause it can do whatever it wants there.\n\n517\n00:27:45,231 --> 00:27:47,064\nWe don't have, you're not gonna have any action setups.\n\n518\n00:27:47,066 --> 00:27:49,433\nThat's not gonna matter anyway. And, in fact,\n\n519\n00:27:49,435 --> 00:27:52,469\nanother thing I'd like is when this NDC first appears,\n\n520\n00:27:52,471 --> 00:27:55,606\nI'd like to keyboard to appear. Okay I wanted it to\n\n521\n00:27:55,608 --> 00:27:58,842\ncome up don't want to make the person touch in there.\n\n522\n00:27:58,844 --> 00:28:03,547\nSo I'm gonna say let's do the name text field. Become\n\n523\n00:28:03,549 --> 00:28:07,851\nfirst response responder. Okay so that means when we reload,\n\n524\n00:28:07,853 --> 00:28:09,620\nwe're gonna become the first responders.\n\n525\n00:28:09,622 --> 00:28:11,121\nQuestion. >> Sir,\n\n526\n00:28:11,123 --> 00:28:12,523\ndid you say that the textfield should\n\n527\n00:28:12,525 --> 00:28:15,025\nreturn because this one said the textfieldShouldReturn?\n\n528\n00:28:15,027 --> 00:28:15,359\n>> Good catch, okay so\n\n529\n00:28:15,361 --> 00:28:17,161\nthis is not supposed to be textfieldShouldClear,\n\n530\n00:28:17,163 --> 00:28:18,395\nthis should be textfieldShouldReturn.\n\n531\n00:28:18,397 --> 00:28:23,100\nOkay, good catch, that's why you guys are here to catch\n\n532\n00:28:23,102 --> 00:28:27,671\nthese mistakes. Yeah, so there we go, textfieldShouldReturn.\n\n533\n00:28:28,741 --> 00:28:31,809\nAll right, so that's gonna manage our keyboard, but\n\n534\n00:28:31,811 --> 00:28:35,345\nnow what about those radio stations? So let's go ahead,\n\n535\n00:28:35,347 --> 00:28:39,650\nand when, our view appears on screen, okay?\n\n536\n00:28:39,652 --> 00:28:40,184\nWhen we get viewDisappear,\n\n537\n00:28:40,186 --> 00:28:42,386\nwe're gonna start listening to those radio stations. And\n\n538\n00:28:42,388 --> 00:28:45,856\nwhen we get viewWillDisappear, then we'll stop listening, all\n\n539\n00:28:45,858 --> 00:28:50,594\nright? So viewWillappear, or else you can do viewDidappear.\n\n540\n00:28:50,596 --> 00:29:00,704\nSuper.viewDidAppear(animated).\n\n541\n00:29:00,706 --> 00:29:04,908\nAll right. So we got viewDidAppear,\n\n542\n00:29:04,910 --> 00:29:09,279\nand so I am just going to say listenToTextFields Okay,\n\n543\n00:29:09,281 --> 00:29:17,321\nwe'll make a little private func that does that. Okay,\n\n544\n00:29:17,323 --> 00:29:20,257\nso how we gonna listen to the text fields? Let's go ahead\n\n545\n00:29:20,259 --> 00:29:24,361\nand get ourselves the center, okay, the NSNotification,\n\n546\n00:29:24,363 --> 00:29:29,633\nNotificationCenter.defaultCen- ter. And\n\n547\n00:29:29,635 --> 00:29:31,802\nlet's get the q that we want, we're going to do all of this\n\n548\n00:29:31,804 --> 00:29:36,774\non the main Q. So ns operation q dot main q. All right now\n\n549\n00:29:36,776 --> 00:29:39,810\nthat we have those two things, two little variables here,\n\n550\n00:29:39,812 --> 00:29:43,046\nI'm going to ask the center to listen to this radio station.\n\n551\n00:29:43,048 --> 00:29:47,584\nSo I'm going to add observer for name. Return here, so\n\n552\n00:29:47,586 --> 00:29:50,854\nyou can see this again, this is what we did last time.\n\n553\n00:29:50,856 --> 00:29:54,758\nAll right, what's the name of the radio station?\n\n554\n00:29:54,760 --> 00:29:59,797\nIt's UITextFieldTextDidChange, you can see it's got a couple\n\n555\n00:29:59,799 --> 00:30:03,367\nof other radio stations there too for begin end editing, but\n\n556\n00:30:03,369 --> 00:30:05,969\nI'm gonna get the one where every time the text change.\n\n557\n00:30:05,971 --> 00:30:08,338\nEvery single character It's going to update.\n\n558\n00:30:08,340 --> 00:30:12,276\nThe object here okay this one I'm gonna be listening to\n\n559\n00:30:12,278 --> 00:30:13,911\nthe Name text field. Okay, and\n\n560\n00:30:13,913 --> 00:30:18,882\nwe'll do it on the main queue. And here's the block.\n\n561\n00:30:18,884 --> 00:30:23,387\nSo what's our block going to do here? We actually don't\n\n562\n00:30:23,389 --> 00:30:25,322\neven need to look at the notification, because we know\n\n563\n00:30:25,324 --> 00:30:28,325\nthis is the Name text field right here this change. So\n\n564\n00:30:28,327 --> 00:30:32,563\nI'm just gonna say here, if I can let waypoint equal our\n\n565\n00:30:32,565 --> 00:30:36,667\nwaypointToEdit, so if our waypointToEdit is not nil,\n\n566\n00:30:36,669 --> 00:30:38,101\nbasically, then let's go ahead and\n\n567\n00:30:38,103 --> 00:30:43,874\nhave the waypoint's name equal the nameTextFields.text,\n\n568\n00:30:43,876 --> 00:30:48,412\nall right? So every time this nameTextField changes,\n\n569\n00:30:48,414 --> 00:30:52,282\nwe're going to update, our name. Okay. And\n\n570\n00:30:52,284 --> 00:30:56,320\nthis needs to be self, because we're inside of closure here.\n\n571\n00:30:56,322 --> 00:31:00,424\nOkay, we'll do the exact same thing for the info text field.\n\n572\n00:31:00,426 --> 00:31:03,961\nOne thing we could have done by the way, is have the object\n\n573\n00:31:03,963 --> 00:31:07,464\nwe're listening to be nil and get all UI text and\n\n574\n00:31:07,466 --> 00:31:10,167\nthen look at the text field that is sending it to us and\n\n575\n00:31:10,169 --> 00:31:13,170\nfind out which one it is. But, what if we had other text\n\n576\n00:31:13,172 --> 00:31:15,505\nfields, other places in our UI that were listening, and\n\n577\n00:31:15,507 --> 00:31:18,075\nmaybe they weren't good and that they kept listening even\n\n578\n00:31:18,077 --> 00:31:21,645\nwhen they were off screen, and all that getting all these.\n\n579\n00:31:21,647 --> 00:31:24,381\nThis is a little bit more code in terms of alliance\n\n580\n00:31:24,383 --> 00:31:26,750\nright here, but it makes these closers really,\n\n581\n00:31:26,752 --> 00:31:30,320\nreally, really simple. Okay? So, this is gonna be\n\n582\n00:31:30,322 --> 00:31:35,292\nthe inform text field, update, now in viewDidAppear here,\n\n583\n00:31:35,294 --> 00:31:41,164\nwe're listing the textfields, in viewWillDisappear,\n\n584\n00:31:43,302 --> 00:31:47,204\nWe need to stop listening to these, okay so how do we do\n\n585\n00:31:47,206 --> 00:31:50,874\nthat, okay we just ask the notification center.\n\n586\n00:31:50,876 --> 00:31:55,412\nDefaultCenter() to remove the Observer,\n\n587\n00:31:55,414 --> 00:31:58,615\nokay, that is this guy right here.\n\n588\n00:31:58,617 --> 00:32:01,551\nAnd same thing, we'll have to do another one for this.\n\n589\n00:32:01,553 --> 00:32:04,821\nSo this is where we have to use the return value of this\n\n590\n00:32:04,823 --> 00:32:07,891\naddObserverForName. It actually returns something.\n\n591\n00:32:07,893 --> 00:32:09,793\nWe'll call this one ntfObserver.\n\n592\n00:32:09,795 --> 00:32:12,829\nAnd this is just basically a cookie that represents\n\n593\n00:32:12,831 --> 00:32:14,298\nthis radio station going here. So\n\n594\n00:32:14,300 --> 00:32:18,201\nwe'll need a couple of private vars here. ntfObserver.\n\n595\n00:32:18,203 --> 00:32:21,505\nThese things are of type NSObjectProtocol. Which\n\n596\n00:32:21,507 --> 00:32:25,008\nbasically just means they're Objective-C compatible things,\n\n597\n00:32:25,010 --> 00:32:28,779\nthey're part, they're visible to the Objective-C runtime.\n\n598\n00:32:28,781 --> 00:32:33,317\nOkay, and so we'll have info text field observer also.\n\n599\n00:32:35,955 --> 00:32:38,922\nOkay, so we'll let the ntfObserver equal that,\n\n600\n00:32:38,924 --> 00:32:41,892\nwe'll have the itfObserver equal this. Okay, now\n\n601\n00:32:41,894 --> 00:32:45,495\nthat we have these cookies, we, we wanna remove them here,\n\n602\n00:32:45,497 --> 00:32:48,098\nokay? We can just put them in here. But we wanna make sure\n\n603\n00:32:48,100 --> 00:32:51,034\nthey're not nil, so I'm gonna say if I can let observer\n\n604\n00:32:51,036 --> 00:32:58,442\nequal the ntfObserver, then I will remove that observer.\n\n605\n00:32:58,811 --> 00:33:04,781\nAnd same thing down here. If I can let observer\n\n606\n00:33:04,783 --> 00:33:08,919\nequal to itfObserver,\n\n607\n00:33:08,921 --> 00:33:12,990\nthen I will move that. Probably\n\n608\n00:33:12,992 --> 00:33:14,725\ncould have made a nice little function that did this, so\n\n609\n00:33:14,727 --> 00:33:19,096\nthat I don't have this kind of same repeated code style here.\n\n610\n00:33:19,098 --> 00:33:21,898\nAlso, actually probably want to put these in another\n\n611\n00:33:21,900 --> 00:33:25,936\nprivate func. Maybe call it private func\n\n612\n00:33:25,938 --> 00:33:31,008\nstopListeningToTextFields. Put that in there, and\n\n613\n00:33:31,010 --> 00:33:37,047\nwe'll call that from here. Okay? Arrange this\n\n614\n00:33:37,049 --> 00:33:41,685\na little bit better. Put this down here. Okay, so basically,\n\n615\n00:33:41,687 --> 00:33:44,021\nlistening and stop listening. So everyone understand that?\n\n616\n00:33:44,023 --> 00:33:46,323\nSee how we're using radio stations to find out what's\n\n617\n00:33:46,325 --> 00:33:46,990\nhappening in the text fields?\n\n618\n00:33:46,992 --> 00:33:50,627\nSo it's kind of a, a fun way to do that. All right,\n\n619\n00:33:50,629 --> 00:33:54,331\nso the last thing we need to do here is our prepare for\n\n620\n00:33:54,333 --> 00:33:57,901\nsegue, right? Over here, we, when we do this other segue,\n\n621\n00:33:57,903 --> 00:34:02,472\nthis segue, this modal segue, we need to prepare for it. So\n\n622\n00:34:02,474 --> 00:34:09,713\nlet's do that. Say else if segue.identifier ==\n\n623\n00:34:09,715 --> 00:34:15,919\nEditUserWaypoint. Okay, that's the name of that, identifier.\n\n624\n00:34:15,921 --> 00:34:19,056\nThen in here we just wanna get that editable waypoint.\n\n625\n00:34:19,058 --> 00:34:20,057\nSo I'm gonna see if I can\n\n626\n00:34:20,059 --> 00:34:22,592\nlet the editableWaypoint equal the waypoint as\n\n627\n00:34:22,594 --> 00:34:26,063\nan EditableWaypoint, so make sure it's editable. It always\n\n628\n00:34:26,065 --> 00:34:29,866\nshould be or we wouldn't be here. Let's put a comma here.\n\n629\n00:34:29,868 --> 00:34:33,336\nThen we can let our editable Waypoint view controller\n\n630\n00:34:33,338 --> 00:34:38,675\nequal the destination as EditWaypointViewController.\n\n631\n00:34:38,677 --> 00:34:43,447\nOkay, then we just set the EWVC's waypointToEdit, which\n\n632\n00:34:43,449 --> 00:34:50,420\nis its public model there, to the editableWaypoint, okay?\n\n633\n00:34:50,422 --> 00:34:52,022\nNow let's go back to our storyboard here and\n\n634\n00:34:52,024 --> 00:34:54,658\ntake a look at how we're going to create the segue\n\n635\n00:34:54,660 --> 00:34:56,493\nright here. Because right now, there's no segue,\n\n636\n00:34:56,495 --> 00:35:00,997\nthis thing is free as a bird out here flying around, okay?\n\n637\n00:35:00,999 --> 00:35:04,201\nSo we want to edit it, so we're gonna do the same thing\n\n638\n00:35:04,203 --> 00:35:07,304\nwe did here when we created this one, which is,\n\n639\n00:35:07,306 --> 00:35:11,875\nto drag from the, view controller, oops,\n\n640\n00:35:11,877 --> 00:35:15,479\nnot that one, from this view controller right here.\n\n641\n00:35:15,481 --> 00:35:20,717\nWe're gonna drag from this guy up to our new MVC.\n\n642\n00:35:20,719 --> 00:35:23,620\nSo let's do that. Ctrl+drag up here. Now, this time though,\n\n643\n00:35:23,622 --> 00:35:26,890\nwe're gonna do something new. This one's gonna be presented\n\n644\n00:35:26,892 --> 00:35:28,859\nmodally. So instead of saying show and\n\n645\n00:35:28,861 --> 00:35:31,261\nhaving it appear inside this navigation controller,\n\n646\n00:35:31,263 --> 00:35:33,463\nwe're gonna do present modally and it's gonna take over\n\n647\n00:35:33,465 --> 00:35:35,932\nthe whole screen while we're editing the waypoint.\n\n648\n00:35:35,934 --> 00:35:38,135\nSo we do present modally. Now let's go ahead and\n\n649\n00:35:38,137 --> 00:35:40,737\ntake a look at this, sorry, let's make this a little\n\n650\n00:35:40,739 --> 00:35:45,442\neasier to see here. Okay. Let's go ahead and take a look\n\n651\n00:35:45,444 --> 00:35:48,645\nat this segue that was just created in the inspector.\n\n652\n00:35:48,647 --> 00:35:52,282\nOkay, so you obviously will need an identifier.\n\n653\n00:35:52,284 --> 00:35:55,919\nI think I called this one Edit Waypoint.\n\n654\n00:35:55,921 --> 00:35:59,523\nI hope that's what I called it. Let's go take a quick\n\n655\n00:35:59,525 --> 00:36:02,292\nlook, make sure we get it right in our constants. Yes,\n\n656\n00:36:02,294 --> 00:36:05,962\nEdit Waypoint. That's what we called this segue right there.\n\n657\n00:36:06,732 --> 00:36:09,599\nAnd you can see it's got Present Modally here,\n\n658\n00:36:09,601 --> 00:36:13,570\nokay? And we'll take a look at these presentation styles down\n\n659\n00:36:13,572 --> 00:36:17,207\nhere a little bit later. Okay? But for right now,\n\n660\n00:36:17,209 --> 00:36:19,209\nwe just wanna present modally. So let's go ahead and\n\n661\n00:36:19,211 --> 00:36:26,082\nsee what this does. All right, so\n\n662\n00:36:26,084 --> 00:36:29,052\nhere we go, we're gonna drop an editable waypoint, okay?\n\n663\n00:36:29,054 --> 00:36:33,089\nIt says Dropped, we can pick it up and move it, okay,\n\n664\n00:36:33,091 --> 00:36:35,892\nto anywhere we want, like to that airport again. And\n\n665\n00:36:35,894 --> 00:36:38,328\nhopefully, we press this i, we're gonna get this\n\n666\n00:36:38,330 --> 00:36:42,032\nmodal segue to this new MVC. So hit the i, there we go,\n\n667\n00:36:42,034 --> 00:36:44,100\nmodal segue. Now, we've got some problems here.\n\n668\n00:36:44,102 --> 00:36:46,736\nLooks like we've got a little problem with our\n\n669\n00:36:46,738 --> 00:36:49,973\nauto layout there. We'll have to take a look at that. And\n\n670\n00:36:49,975 --> 00:36:54,511\nin fact, we've gotta fix that, or we're not gonna be able to,\n\n671\n00:36:54,513 --> 00:36:57,714\nto edit this. So let's go back to our storyboard here and\n\n672\n00:36:57,716 --> 00:36:58,715\ntake a look at what the problem,\n\n673\n00:36:58,717 --> 00:37:01,184\nprobably was that thing where I said same width.\n\n674\n00:37:01,186 --> 00:37:04,821\nSomebody has the same width who shouldn't, I believe.\n\n675\n00:37:04,823 --> 00:37:06,823\nMaybe one of these stack views.\n\n676\n00:37:06,825 --> 00:37:09,559\nLet's take a look at this guy. So I'm just gonna,\n\n677\n00:37:09,561 --> 00:37:12,362\nwhen you get a problem with your auto layout,\n\n678\n00:37:12,364 --> 00:37:16,132\nit's kind of a good idea to make a little tour through\n\n679\n00:37:16,134 --> 00:37:16,733\nyour various things.\n\n680\n00:37:16,735 --> 00:37:19,769\nYou can even see, I've got red here, conflicting constraints,\n\n681\n00:37:19,771 --> 00:37:22,405\nso we know there's problems. And sure enough, look at this.\n\n682\n00:37:22,407 --> 00:37:26,109\nWhen I said, tried to make the description equal to the name,\n\n683\n00:37:26,111 --> 00:37:28,612\nI made this whole stack view equal to the name.\n\n684\n00:37:28,614 --> 00:37:31,615\nYou see that? Equal width to name, this whole stack view,\n\n685\n00:37:31,617 --> 00:37:35,185\nso that's not good. So I don't want this, so I'm just gonna\n\n686\n00:37:35,187 --> 00:37:38,288\ndelete that constraint. And now this has probably fixed\n\n687\n00:37:38,290 --> 00:37:40,357\nthe problem, because you see I have no more warning\n\n688\n00:37:40,359 --> 00:37:44,227\nof conflicting constraints. Okay? So let's go try again,\n\n689\n00:37:44,229 --> 00:37:50,800\nsee if that makes our UI look a little better. All right.\n\n690\n00:37:50,802 --> 00:37:56,172\nWe'll drop here. Edit. That looks a lot better.\n\n691\n00:37:56,174 --> 00:37:59,743\nOkay. And you can see that it passed from the prepare for\n\n692\n00:37:59,745 --> 00:38:02,279\nsegue, it passed our existing name and info,\n\n693\n00:38:02,281 --> 00:38:04,981\nwhich is just dropped with no info, into here. And\n\n694\n00:38:04,983 --> 00:38:07,784\nit also put the keyboard up, was nice. And if I get rid of,\n\n695\n00:38:07,786 --> 00:38:10,020\nhit return, it makes the keyboard go away. And\n\n696\n00:38:10,022 --> 00:38:13,290\nif I make one of these first responder, it comes back.\n\n697\n00:38:13,292 --> 00:38:14,891\nAll right. And I can edit this.\n\n698\n00:38:14,893 --> 00:38:21,231\nLet's say, I'll say, I love it when people, do something,\n\n699\n00:38:21,233 --> 00:38:27,437\nokay. And how about, the fact is your name.\n\n700\n00:38:27,439 --> 00:38:31,408\nOkay, so here's our basically name of our waypoint and\n\n701\n00:38:31,410 --> 00:38:34,678\nthe description. And so, uh-oh, how do we get out of\n\n702\n00:38:34,680 --> 00:38:38,615\nhere? It's like, we can't get out. So this is a problem I\n\n703\n00:38:38,617 --> 00:38:41,818\nwas telling you about. Modal, you have to provide a way for\n\n704\n00:38:41,820 --> 00:38:44,621\nyour user to escape once they've edited whatever they\n\n705\n00:38:44,623 --> 00:38:47,757\nwant to edit. Okay? So how are we gonna do that? Let's go\n\n706\n00:38:47,759 --> 00:38:49,993\nback to our storyboard. The simple way to do it\n\n707\n00:38:49,995 --> 00:38:53,029\nis to put this inside a navigation controller and\n\n708\n00:38:53,031 --> 00:38:57,000\nput a done button up there like we saw in the slides.\n\n709\n00:38:57,002 --> 00:38:58,201\nSo let's do that. Let's go here,\n\n710\n00:38:58,203 --> 00:39:00,270\nEdit > Embed In > Navigation Controller,\n\n711\n00:39:00,272 --> 00:39:03,440\nit puts it in a navigation controller right here. And\n\n712\n00:39:03,442 --> 00:39:04,741\nwe're just gonna put a Done button right there.\n\n713\n00:39:04,743 --> 00:39:09,145\nSo let's go down here. We'll search for bar button item.\n\n714\n00:39:09,147 --> 00:39:11,815\nHere it is, a Bar Button Item. We'll put it right up here.\n\n715\n00:39:11,817 --> 00:39:15,919\nI think there's even a standard system one for that,\n\n716\n00:39:15,921 --> 00:39:20,824\nmaybe. Yeah, there's a Done button right there, okay, for\n\n717\n00:39:20,826 --> 00:39:21,124\nclicking Done.\n\n718\n00:39:21,126 --> 00:39:24,594\nAnd then we'll just make this done button call a method\n\n719\n00:39:24,596 --> 00:39:26,229\nin this view controller, by the way, so\n\n720\n00:39:26,231 --> 00:39:29,165\nyou can see our stack view frames are a little off now.\n\n721\n00:39:29,167 --> 00:39:32,235\nWe can fix that clicking on here and\n\n722\n00:39:32,237 --> 00:39:35,372\ndoing a update frames, moves that down. But\n\n723\n00:39:35,374 --> 00:39:38,875\nlet's make this so that it sends a message to ourselves,\n\n724\n00:39:38,877 --> 00:39:41,578\nand then we'll dismiss ourselves. Okay, so\n\n725\n00:39:41,580 --> 00:39:46,149\nlet's do that. We get here, we'll put this.\n\n726\n00:39:46,151 --> 00:39:48,585\nLet's make it a little more space for you there. Okay,\n\n727\n00:39:48,587 --> 00:39:52,856\nwe'll put that dismiss, how about, I don't know,\n\n728\n00:39:52,858 --> 00:39:56,259\nright up after our view controller lifecycle here.\n\n729\n00:39:56,261 --> 00:39:59,062\nOkay? So I'm just gonna Ctrl+drag right in here. This\n\n730\n00:39:59,064 --> 00:40:02,932\nis gonna be an action. This is my done action, I'll call it.\n\n731\n00:40:02,934 --> 00:40:07,137\nOkay, BarButtonitem is gonna be the argument. Here it is.\n\n732\n00:40:07,139 --> 00:40:08,972\nNow remember, again,\n\n733\n00:40:08,974 --> 00:40:13,943\nlet's go twofold width here. Remember, here,\n\n734\n00:40:13,945 --> 00:40:18,214\nwe don't want to say just dismissViewControllerAnimated.\n\n735\n00:40:18,216 --> 00:40:23,353\nWe want to get our presentingViewController.\n\n736\n00:40:23,355 --> 00:40:28,091\nThat's the view controller that presented us and\n\n737\n00:40:28,093 --> 00:40:32,195\nask it to dismiss us, okay. And we don't care when that\n\n738\n00:40:32,197 --> 00:40:34,864\nhappens. Okay, so don't forget that.\n\n739\n00:40:34,866 --> 00:40:38,301\nI'm kind of putting this self here just to let you know I'm\n\n740\n00:40:38,303 --> 00:40:41,805\ntalking about my self's presentingViewController but\n\n741\n00:40:41,807 --> 00:40:43,773\nyou don't need self there obviously,\n\n742\n00:40:43,775 --> 00:40:46,810\nokay? Understand that? All right, so let's see that.\n\n743\n00:40:46,812 --> 00:40:54,150\nSee how that makes this work. All right,\n\n744\n00:40:54,152 --> 00:40:58,922\nso we'll drop this. Go here, we'll edit it. Comes up,\n\n745\n00:40:58,924 --> 00:41:00,623\nwe've got our Navigation Controller, it's there.\n\n746\n00:41:00,625 --> 00:41:03,460\nWe probably should have put a title called edit waypoint or\n\n747\n00:41:03,462 --> 00:41:06,696\nsomething like that. So let's go ahead and edit this again.\n\n748\n00:41:06,698 --> 00:41:12,235\nSo let's say the best thing. Okay, that's what our name is.\n\n749\n00:41:12,237 --> 00:41:17,740\nAnd the description is, the only way. All right, so we got\n\n750\n00:41:17,742 --> 00:41:21,177\nthe best thing and the only way there. And we hit Done.\n\n751\n00:41:21,179 --> 00:41:25,048\nAnd it still says, Dropped, okay? Now why is that?\n\n752\n00:41:25,050 --> 00:41:27,851\nWell, that's because that callout was put up, and\n\n753\n00:41:27,853 --> 00:41:30,954\nwhen it's put up, it's loaded up with the waypoint's\n\n754\n00:41:30,956 --> 00:41:34,090\ninformation. And it stays that way all the time,\n\n755\n00:41:34,092 --> 00:41:37,894\nokay? The only time it changes is if it goes away and\n\n756\n00:41:37,896 --> 00:41:42,232\ncomes back. When it comes back, it came back, okay?\n\n757\n00:41:42,234 --> 00:41:45,201\nNow we got a bug somewhere in our code cuz it should have\n\n758\n00:41:45,203 --> 00:41:49,706\nour subtitle there. But that was really annoying for\n\n759\n00:41:49,708 --> 00:41:51,474\nour user that they went and edited this and\n\n760\n00:41:51,476 --> 00:41:54,244\nwhen they came back it still said Dropped, okay.\n\n761\n00:41:54,246 --> 00:41:56,479\nSo let's fix the bug so that this the only way,\n\n762\n00:41:56,481 --> 00:42:01,684\nwhich I think was the info was yeah, so here we go.\n\n763\n00:42:01,686 --> 00:42:05,755\nThis should be info = the infoTextField,\n\n764\n00:42:05,757 --> 00:42:10,360\nokay? So how are we gonna fix that? Well, one thing about it\n\n765\n00:42:10,362 --> 00:42:16,165\nright off the bat is that when we click on this little i,\n\n766\n00:42:16,167 --> 00:42:19,402\nI'm gonna take this callout off the screen. Because I know\n\n767\n00:42:19,404 --> 00:42:22,572\nit's pretty much invalid right away because if I go over here\n\n768\n00:42:22,574 --> 00:42:23,673\nand change this to anything else,\n\n769\n00:42:23,675 --> 00:42:26,576\nthat thing is no good anymore. So let's do that as step one.\n\n770\n00:42:26,578 --> 00:42:29,646\nLet's just take that callout away when we do this\n\n771\n00:42:29,648 --> 00:42:31,948\nperformForSeg, performSegue. So\n\n772\n00:42:31,950 --> 00:42:33,516\nlet's find where we do that performSegue,\n\n773\n00:42:33,518 --> 00:42:38,588\nit's in this funny little calloutAccessoryTapped, right?\n\n774\n00:42:38,590 --> 00:42:40,089\nHere's where we perform that segue.\n\n775\n00:42:40,091 --> 00:42:41,558\nAnd when we perform that segue,\n\n776\n00:42:41,560 --> 00:42:45,128\nwe're going to remove that callout when we do that. And\n\n777\n00:42:45,130 --> 00:42:50,099\nso, we do that by saying mapView.deselectAnnotation\n\n778\n00:42:50,101 --> 00:42:52,735\nbecause the reason that callout is up is because this\n\n779\n00:42:52,737 --> 00:42:55,805\nannotation is selected. So, if we deselect this annotation,\n\n780\n00:42:55,807 --> 00:42:59,042\nit will remove that callout. And what do we wanna do?\n\n781\n00:42:59,044 --> 00:43:02,078\nWe wanna remove the annotation in the view that our\n\n782\n00:43:02,080 --> 00:43:05,348\ncallout is currently accessory control tapping.\n\n783\n00:43:05,350 --> 00:43:07,550\nAnd sure, we'll, we'll animate it, although it probably\n\n784\n00:43:07,552 --> 00:43:09,752\ndoesn't matter that it's animated because we're gonna\n\n785\n00:43:09,754 --> 00:43:10,853\nput a modal thing right on top of it. But\n\n786\n00:43:10,855 --> 00:43:13,756\nmaybe it'll be fading out as that's sliding in, that might\n\n787\n00:43:13,758 --> 00:43:18,428\nbe kinda nice. Okay, so let's see if that fixes our problem.\n\n788\n00:43:22,233 --> 00:43:25,068\nAll right, here we go. Put this on the airport here.\n\n789\n00:43:25,070 --> 00:43:27,704\nWe'll click there, there's Dropped. We click.\n\n790\n00:43:27,706 --> 00:43:31,341\nOkay, we go to Dropped. And we'll put something in here.\n\n791\n00:43:31,343 --> 00:43:36,412\nSay I'm so excited, that's good.\n\n792\n00:43:36,414 --> 00:43:40,083\nDescription, the fact is. Okay, and\n\n793\n00:43:40,085 --> 00:43:44,253\nwe'll hit Done and hopefully, it's not showing it.\n\n794\n00:43:44,255 --> 00:43:45,855\nSo at least it's not saying dropped, so\n\n795\n00:43:45,857 --> 00:43:49,192\nthat's the improvement, right? But if we click on it, it's\n\n796\n00:43:49,194 --> 00:43:52,829\nshowing it. So really what we'd like is when we come back\n\n797\n00:43:52,831 --> 00:43:55,732\nfrom that modal segue, we'd like it to put this thing back\n\n798\n00:43:55,734 --> 00:43:58,968\nup with the new information. Okay, so how are we gonna do\n\n799\n00:43:58,970 --> 00:44:02,839\nthat, cuz we don't know when that modal thing goes away,\n\n800\n00:44:02,841 --> 00:44:05,708\nokay. It's just getting dismissed, right? So this is\n\n801\n00:44:05,710 --> 00:44:09,679\na good opportunity to show you unwind. Okay, so we're gonna,\n\n802\n00:44:09,681 --> 00:44:12,915\ninstead of hitting Done and having it dismiss ourselves,\n\n803\n00:44:12,917 --> 00:44:14,917\nwe're going to do an unwind segue back to\n\n804\n00:44:14,919 --> 00:44:17,387\nour GPXController. And when it gets that message,\n\n805\n00:44:17,389 --> 00:44:20,657\nthat special message, it'll know I'm gonna put this thing\n\n806\n00:44:20,659 --> 00:44:23,826\nback up, okay. So let's do that, so how do we do that?\n\n807\n00:44:23,828 --> 00:44:27,330\nWe know that when we unwind, we always wanna create one of\n\n808\n00:44:27,332 --> 00:44:31,401\nthis special methods, okay? And those special methods,\n\n809\n00:44:31,403 --> 00:44:34,904\nfirst of all, they're always IBActions, okay?\n\n810\n00:44:34,906 --> 00:44:38,141\nThey can have any name that we want, so we'll call ours\n\n811\n00:44:38,143 --> 00:44:42,045\nupdatedUserWaypoint because that's what happened, okay?\n\n812\n00:44:42,047 --> 00:44:44,414\nWhen the unwind happens, the user update waypoint\n\n813\n00:44:44,416 --> 00:44:48,785\ngot updated. And the other thing that's special about it,\n\n814\n00:44:48,787 --> 00:44:52,288\nthe argument has to be a UIStoryboardSegue, okay?\n\n815\n00:44:52,290 --> 00:44:54,957\nSo this is the special method and this is all we need to do\n\n816\n00:44:54,959 --> 00:44:57,794\nto create one of these special message, methods.\n\n817\n00:44:57,796 --> 00:44:59,829\nWe'll call it a func. All right, and\n\n818\n00:44:59,831 --> 00:45:03,599\nso now anybody can unwind to this as long as there's\n\n819\n00:45:03,601 --> 00:45:06,669\nsomething we presented. Any MVC that we've presented or\n\n820\n00:45:06,671 --> 00:45:09,672\nthat was presented by somebody we presented,\n\n821\n00:45:09,674 --> 00:45:12,408\netc., can now unwind back to us here.\n\n822\n00:45:12,410 --> 00:45:14,644\nNow what are we gonna do when we unbind back to here?\n\n823\n00:45:14,646 --> 00:45:18,314\nWell, we're gonna reselect that annotation that we\n\n824\n00:45:18,316 --> 00:45:22,452\ndeselected when we left. So let's do that.\n\n825\n00:45:22,454 --> 00:45:25,054\nI'll create a little function to do that called sec,\n\n826\n00:45:25,056 --> 00:45:31,094\nselectWaypoint. Okay, and selectWaypoint, we gotta get\n\n827\n00:45:31,096 --> 00:45:34,030\nthe waypoint we selected, it's a little tricky, watch this.\n\n828\n00:45:34,032 --> 00:45:38,668\nI'm gonna get the segue's sourceViewController. That's\n\n829\n00:45:38,670 --> 00:45:41,237\nthe view controller that is sending us this unwind.\n\n830\n00:45:41,239 --> 00:45:43,272\nSo that's gonna be the modal segue, right?\n\n831\n00:45:43,274 --> 00:45:45,274\nThat's the source of the unwind. So\n\n832\n00:45:45,276 --> 00:45:46,776\nwe're gonna get that sourceViewController.\n\n833\n00:45:46,778 --> 00:45:49,479\nAnd actually we'll get its contentViewController,\n\n834\n00:45:49,481 --> 00:45:55,451\nokay? And it has to be an EditWaypointViewController.\n\n835\n00:45:55,453 --> 00:45:57,253\nAnd if we're able to find that,\n\n836\n00:45:57,255 --> 00:46:00,223\nthen we'll just get its waypointToEdit. Okay,\n\n837\n00:46:00,225 --> 00:46:03,659\nthat's obviously the waypoint that we want to select.\n\n838\n00:46:03,661 --> 00:46:07,463\nSo we need to, this method selectWaypoint. Let's do that.\n\n839\n00:46:07,465 --> 00:46:12,502\nfunc selectWaypoint takes a waypoint\n\n840\n00:46:12,504 --> 00:46:17,240\nwhich is at GPX.Waypoint, point. We'll\n\n841\n00:46:17,242 --> 00:46:19,675\neven make it optional if you wanna pass it in there. And\n\n842\n00:46:19,677 --> 00:46:24,614\nwe'll just say if the waypoint != nil then we are gonna go\n\n843\n00:46:24,616 --> 00:46:29,786\nto the mapView and tell it to select an annotation, which is\n\n844\n00:46:29,788 --> 00:46:34,991\nthe waypoint. Okay, remember that all of our waypoints\n\n845\n00:46:34,993 --> 00:46:37,827\nare annotations, so we can directly ask the mapView. This\n\n846\n00:46:37,829 --> 00:46:40,797\nis what's really nice about having some data structure\n\n847\n00:46:40,799 --> 00:46:43,866\nthat we already have in our app, like a GPX waypoint,\n\n848\n00:46:43,868 --> 00:46:45,735\nimplement that MK annotation protocol.\n\n849\n00:46:45,737 --> 00:46:48,704\nBecause we're not having to constantly create these other\n\n850\n00:46:48,706 --> 00:46:51,774\nlittle things that contain all the waypoint in you know,\n\n851\n00:46:51,776 --> 00:46:54,777\nthe MK notation information, we just get it directly from\n\n852\n00:46:54,779 --> 00:46:57,346\nour waypoints. Okay, so this is gonna select it.\n\n853\n00:46:57,348 --> 00:47:01,017\nSo now we have to unwind to this instead of doing Done.\n\n854\n00:47:01,019 --> 00:47:03,653\nSo let's go back to our storyboard here. Okay,\n\n855\n00:47:03,655 --> 00:47:06,622\nwe've got this Done. I'm gonna disconnect Done\n\n856\n00:47:06,624 --> 00:47:09,525\nfrom this done method, right. So I'm just going here and\n\n857\n00:47:09,527 --> 00:47:12,395\ndisconnecting it. So now it's not gonna send Done. And\n\n858\n00:47:12,397 --> 00:47:16,065\nin fact, if we go back to our EditWaypointViewController,\n\n859\n00:47:16,067 --> 00:47:19,368\nwe can just delete this done method entirely whenever it\n\n860\n00:47:19,370 --> 00:47:22,905\nis, oops, there it is. Okay, we're not even gonna use that\n\n861\n00:47:22,907 --> 00:47:25,808\nanymore. Instead of doing that, we are going to unwind.\n\n862\n00:47:25,810 --> 00:47:28,878\nSo let's go back here and unwind. So, how do we unwind?\n\n863\n00:47:28,880 --> 00:47:33,583\nEveryone remember? Ctrl+drag to this Exit button. Okay,\n\n864\n00:47:33,585 --> 00:47:36,519\nthis is how you unwind. This is saying I want this Done\n\n865\n00:47:36,521 --> 00:47:39,021\nbutton to unwind, okay? To exit this MVC and\n\n866\n00:47:39,023 --> 00:47:41,624\ngo back to one of its presenters. And look, when we\n\n867\n00:47:41,626 --> 00:47:44,861\nclick, look what we see in the list! updatedUserWaypoint.\n\n868\n00:47:44,863 --> 00:47:46,796\nThat method we put there with the special\n\n869\n00:47:46,798 --> 00:47:49,065\nIBAction in this segue as an argument,\n\n870\n00:47:49,067 --> 00:47:51,601\nokay? And every method in every MVC we ever\n\n871\n00:47:51,603 --> 00:47:54,203\nwould've put in our entire app that was like that would\n\n872\n00:47:54,205 --> 00:47:57,173\nappear here. Yeah, question. >> Does the unwind only work\n\n873\n00:47:57,175 --> 00:47:59,342\nin a Navigation Controller? >> So the question,\n\n874\n00:47:59,344 --> 00:48:01,844\ndoes unwind only work inside a Navigation Controller?\n\n875\n00:48:01,846 --> 00:48:03,379\nAnd the answer is no, it works anywhere.\n\n876\n00:48:03,381 --> 00:48:06,616\nSo you could have just a non-navigation controller MBC\n\n877\n00:48:06,618 --> 00:48:09,719\npresent another one modally which presents another one\n\n878\n00:48:09,721 --> 00:48:13,055\nmodally, and then you unwind back to either of those two.\n\n879\n00:48:13,057 --> 00:48:15,358\nSo it has nothing to do with navigation controller.\n\n880\n00:48:15,360 --> 00:48:17,860\nThis is not pop you now back or anything.\n\n881\n00:48:17,862 --> 00:48:21,664\nThis is really just take this MBCs off until you get back to\n\n882\n00:48:21,666 --> 00:48:24,166\nthe guy who implements this method, okay?\n\n883\n00:48:24,168 --> 00:48:26,535\nNow it would work in a navigation controller as well.\n\n884\n00:48:26,537 --> 00:48:29,772\nIt would pop back from that as well, but it works in any\n\n885\n00:48:29,774 --> 00:48:33,476\nany environment basically. All right so I'm gonna click that\n\n886\n00:48:33,478 --> 00:48:37,113\nand that's gonna make the done button unwind to that method.\n\n887\n00:48:37,115 --> 00:48:42,618\nOkay so that method is gonna get called. So let's ugh. We\n\n888\n00:48:42,620 --> 00:48:47,256\nlooking at this method when it happens. Let's go over here.\n\n889\n00:48:51,529 --> 00:48:55,665\nAll right so drop the pin right here gonna click.\n\n890\n00:48:55,667 --> 00:48:59,435\nIt says dropped right here. We're gonna go edit it.\n\n891\n00:48:59,437 --> 00:49:03,339\nChange it to something here,\n\n892\n00:49:03,341 --> 00:49:08,511\nhow about the fact that you have to,\n\n893\n00:49:08,513 --> 00:49:11,747\nand we'll call this I'm so\n\n894\n00:49:11,749 --> 00:49:15,785\nhappy, okay? So we're gonna hit done here and hopefully,\n\n895\n00:49:15,787 --> 00:49:18,187\nwe're gonna see that call out, show up,\n\n896\n00:49:18,189 --> 00:49:20,056\nwithout having to click on anything and, sure enough,\n\n897\n00:49:20,058 --> 00:49:24,226\nit does. Okay because it unwind back, called this code\n\n898\n00:49:24,228 --> 00:49:26,529\nright here which selected that annotation.\n\n899\n00:49:26,531 --> 00:49:31,667\nThis is back in our TPX view controller here, see? Okay,\n\n900\n00:49:31,669 --> 00:49:34,036\neverybody got the unwind there? All right,\n\n901\n00:49:34,038 --> 00:49:37,974\nthe next segue we're gonna look at is popovers. Okay,\n\n902\n00:49:37,976 --> 00:49:41,110\nlet's take a look at our app on iPad. And\n\n903\n00:49:41,112 --> 00:49:44,280\nto do this I'm actually gonna do it on my device over here.\n\n904\n00:49:44,282 --> 00:49:49,819\nSo let's go up here, this is device and run this.\n\n905\n00:49:54,559 --> 00:49:57,760\nWe made this to a universal app so it should work fine\n\n906\n00:49:57,762 --> 00:50:01,097\nover here. Sure enough there it is, zooming in to where we\n\n907\n00:50:01,099 --> 00:50:05,167\nare, okay. Here's our stuff we can zoom in here and\n\n908\n00:50:05,169 --> 00:50:08,304\nwe can click on these things just like we could before. And\n\n909\n00:50:08,306 --> 00:50:14,643\nwe can segue to see this. Okay all that stuff is nice.\n\n910\n00:50:14,645 --> 00:50:18,314\nAnd we can also add new pins, so I'm just long pressing.\n\n911\n00:50:18,316 --> 00:50:21,684\nThere's a pin. Okay, let's click there, okay dropped.\n\n912\n00:50:21,686 --> 00:50:27,390\nWe're going to edit it. Whoa. Okay this is pretty ugly UI.\n\n913\n00:50:27,392 --> 00:50:29,325\nOkay do not do this in your final project.\n\n914\n00:50:29,327 --> 00:50:31,660\nI cannot tell you how many final projects\n\n915\n00:50:31,662 --> 00:50:35,031\nthink I've made it work on the iPad with this kind of UI.\n\n916\n00:50:35,033 --> 00:50:37,099\nOkay, this kind of UI looks ridiculous.\n\n917\n00:50:37,101 --> 00:50:39,568\nYou're never going to have the name and description be that\n\n918\n00:50:39,570 --> 00:50:43,506\nlong, okay. So you don't want that. There are other ways of\n\n919\n00:50:43,508 --> 00:50:45,608\npresenting modal NBC's that look a lot\n\n920\n00:50:45,610 --> 00:50:49,345\nbetter on iPad. So let's go pick one of them, let's go\n\n921\n00:50:49,347 --> 00:50:53,482\nback to our storyboard here, oops. Let's go back to our\n\n922\n00:50:53,484 --> 00:50:57,553\nstoryboard and we're just gonna change our segue here,\n\n923\n00:50:57,555 --> 00:51:00,890\nthis is the modal segue okay. That puts this thing up,\n\n924\n00:51:00,892 --> 00:51:03,893\nokay we're gonna inspect it and I'm gonna try a different\n\n925\n00:51:03,895 --> 00:51:07,396\npresentation like for example form sheet. So form sheet is\n\n926\n00:51:07,398 --> 00:51:10,399\nmuch more appropriate for the iPad. So let's go ahead and\n\n927\n00:51:10,401 --> 00:51:12,935\nrun this. See what form sheet looks like. The form sheet\n\n928\n00:51:12,937 --> 00:51:16,472\nmodal presentation. It's just a different presentation than\n\n929\n00:51:16,474 --> 00:51:17,540\ntake over the whole screen.\n\n930\n00:51:17,542 --> 00:51:18,574\nIt still takes over the whole screen,\n\n931\n00:51:18,576 --> 00:51:21,877\nit just does it a little more space efficiently here.\n\n932\n00:51:21,879 --> 00:51:24,013\nAll right, so I'm dropping a pin there and\n\n933\n00:51:24,015 --> 00:51:24,580\nwe're gonna edit it. And\n\n934\n00:51:24,582 --> 00:51:28,617\nyou can see this gives a much more sensible looking space.\n\n935\n00:51:28,619 --> 00:51:32,154\nNow the background here on the side, the grey on the side,\n\n936\n00:51:32,156 --> 00:51:34,423\nokay, is not active. I can't do anything with it so\n\n937\n00:51:34,425 --> 00:51:36,525\nit's still modal, it's still completely taking over,\n\n938\n00:51:36,527 --> 00:51:40,029\nit just presenting it a little nicer here. Okay, and I can\n\n939\n00:51:40,031 --> 00:51:44,767\nstill do all the things that I would do here. Ya know, hello.\n\n940\n00:51:44,769 --> 00:51:49,271\nOkay so, that's nice but, really on the iPad, what would\n\n941\n00:51:49,273 --> 00:51:53,776\nbe really cool is to do it in a little pop over right there.\n\n942\n00:51:53,778 --> 00:51:57,179\nOkay to have the name, and info just be in that small,\n\n943\n00:51:57,181 --> 00:52:00,249\nlittle pop over pointing right at that little pin,\n\n944\n00:52:00,251 --> 00:52:03,352\nthat would be a much better UI. And so it's great because\n\n945\n00:52:03,354 --> 00:52:06,222\nwe can learn how to do pop overs. So lets do that, how\n\n946\n00:52:06,224 --> 00:52:11,393\nare we gonna do popovers? So a, and when we have a popover\n\n947\n00:52:11,395 --> 00:52:14,630\nwe're not gonna want this Navigation Controller in here,\n\n948\n00:52:14,632 --> 00:52:17,032\nokay? We'll zoom out so you can see it.\n\n949\n00:52:17,034 --> 00:52:20,069\nOkay if when we have a popover to do this we wanna get\n\n950\n00:52:20,071 --> 00:52:21,303\nrid of this Navigation Controller here.\n\n951\n00:52:21,305 --> 00:52:24,140\nSo I'm gonna delete that. So we have this, okay?\n\n952\n00:52:24,142 --> 00:52:27,276\nNow, I'm just gonnato create a popover in the same way,\n\n953\n00:52:27,278 --> 00:52:28,677\nas we created all the other ones, okay?\n\n954\n00:52:28,679 --> 00:52:32,781\nWhich is control drag from here up to here. But\n\n955\n00:52:32,783 --> 00:52:36,285\nthis time, I'm gonna choose present as popover. Okay and\n\n956\n00:52:36,287 --> 00:52:40,422\nthis creates this right here and you can see here's the pop\n\n957\n00:52:40,424 --> 00:52:43,659\nover segue. Now we of course need an identifier for it.\n\n958\n00:52:43,661 --> 00:52:45,728\nWe're going to do the same identifier cause we're\n\n959\n00:52:45,730 --> 00:52:47,630\ngoing to have the same prepare segue as we have for\n\n960\n00:52:47,632 --> 00:52:52,168\nthe mog modal one which was edit waypoint. All right.\n\n961\n00:52:52,170 --> 00:52:55,771\nNotice popover has some extra things down here. Okay, and\n\n962\n00:52:55,773 --> 00:52:58,741\nthis mostly has to do with when I put this popover up,\n\n963\n00:52:58,743 --> 00:53:01,911\nokay, where do you want it to appear? And part of where\n\n964\n00:53:01,913 --> 00:53:04,380\nit wants to appear is where you are going to allow\n\n965\n00:53:04,382 --> 00:53:07,583\nthe Popovers little arrow to point, point up, or left, or\n\n966\n00:53:07,585 --> 00:53:10,920\ndown, or right that's gonna to kind of position it a little\n\n967\n00:53:10,922 --> 00:53:13,689\nbit. In our case we'll let it point any direction.\n\n968\n00:53:13,691 --> 00:53:17,526\nSo, depending on whether your weight point is up in the left\n\n969\n00:53:17,528 --> 00:53:18,761\ncorner, in the right corner,\n\n970\n00:53:18,763 --> 00:53:20,362\nwe'll let the pop over be above it, below it,\n\n971\n00:53:20,364 --> 00:53:24,300\nwhatever the system thinks is best. But the popover also\n\n972\n00:53:24,302 --> 00:53:26,936\nneeds needs an anchor, which is when I come up I've gotta\n\n973\n00:53:26,938 --> 00:53:29,471\npoint at something. And we're not bringing this up with\n\n974\n00:53:29,473 --> 00:53:32,308\na bar button, or something we can point to. We're bringing\n\n975\n00:53:32,310 --> 00:53:35,311\nit up by clicking on this little annotation thing. So,\n\n976\n00:53:35,313 --> 00:53:39,748\nwe really want the anchor to be those pins. Okay so\n\n977\n00:53:39,750 --> 00:53:42,218\nthose pins are in the map view so\n\n978\n00:53:42,220 --> 00:53:45,754\nI'm going to have the anchor right here be the map view and\n\n979\n00:53:45,756 --> 00:53:48,591\nthen in code I'm going to specify a rectangle in the map\n\n980\n00:53:48,593 --> 00:53:51,794\nview which contains that little annotation view. So\n\n981\n00:53:51,796 --> 00:53:55,731\nthe way I make the map view be anchor is I Ctrl+Drag\n\n982\n00:53:55,733 --> 00:53:59,168\nover to this. Okay, from the little circle. Like that and\n\n983\n00:53:59,170 --> 00:54:01,070\nyou can see it puts the map view in there.\n\n984\n00:54:01,072 --> 00:54:03,272\nSo now it's saying okay, I understand that\n\n985\n00:54:03,274 --> 00:54:06,342\nI'm gonna point up pointing to somewhere in the map view.\n\n986\n00:54:06,344 --> 00:54:08,010\nIn your code you better tell me where and\n\n987\n00:54:08,012 --> 00:54:11,480\nwe're gonna tell you, tell it where, okay?\n\n988\n00:54:13,551 --> 00:54:16,785\nOkay, okay, all right.\n\n989\n00:54:16,787 --> 00:54:20,022\nSo where are we gonna set that little rectangle, okay?\n\n990\n00:54:20,024 --> 00:54:23,659\nWe're gonna set that in our prepareforsegue, for\n\n991\n00:54:23,661 --> 00:54:26,862\nthis segue, that's where you set up all your popover stuff,\n\n992\n00:54:26,864 --> 00:54:28,831\nis in the prepareforsegue for that segue.\n\n993\n00:54:28,833 --> 00:54:32,635\nSo here is that part of this prepareforsegue,\n\n994\n00:54:32,637 --> 00:54:35,871\nwrite the edit user waypoint, part of the prepareforsegue.\n\n995\n00:54:35,873 --> 00:54:39,241\nAll we're gonna do here is get the popover presentation\n\n996\n00:54:39,243 --> 00:54:43,178\ncontroller. So if we can get that, we get it from the MBC\n\n997\n00:54:43,180 --> 00:54:47,983\nwe're presenting. So in this case it's the EWVC, the edit\n\n998\n00:54:47,985 --> 00:54:50,719\nwavepoint view controller. We get it from that.\n\n999\n00:54:50,721 --> 00:54:51,720\nAnd we get it from this method,\n\n1000\n00:54:51,722 --> 00:54:55,257\npop over presentation controller. Now if we're now\n\n1001\n00:54:55,259 --> 00:54:58,427\npopping over this would be null. This code won't execute,\n\n1002\n00:54:58,429 --> 00:55:01,230\nexcellent, okay? But if we're doing a popover, then it will\n\n1003\n00:55:01,232 --> 00:55:04,800\nnot be null. So in here we configure the popover\n\n1004\n00:55:04,802 --> 00:55:06,535\npresentation controller and you can go look at the doc,\n\n1005\n00:55:06,537 --> 00:55:10,506\nbut one of the things you can do is the source rectangle\n\n1006\n00:55:10,508 --> 00:55:14,710\nthat it's gonna point to in your anchor view, okay? And\n\n1007\n00:55:14,712 --> 00:55:16,278\nwhat is this gonna be? Well that's easy for\n\n1008\n00:55:16,280 --> 00:55:20,683\nus, that's just gonna be the annotation view's frame. Okay,\n\n1009\n00:55:20,685 --> 00:55:21,650\nthe frame of the little pin,\n\n1010\n00:55:21,652 --> 00:55:26,355\nthat's where we want the popover to point. Make sense?\n\n1011\n00:55:26,357 --> 00:55:29,091\nAll right so, so, let's run this, see what it looks like.\n\n1012\n00:55:39,270 --> 00:55:43,939\nAll right? So, we'll drop this here, click on it and\n\n1013\n00:55:43,941 --> 00:55:47,710\nwhoa! Well, hm, okay we're makin progress but I\n\n1014\n00:55:47,712 --> 00:55:52,581\ndon't think we're quite there. So what's wrong with this?\n\n1015\n00:55:52,583 --> 00:55:54,883\nWell, one thing is that thing is huge!\n\n1016\n00:55:54,885 --> 00:55:57,753\nWay bigger than it needs to be! Why is it so big?\n\n1017\n00:55:57,755 --> 00:56:00,456\nThe answer is because no one told it what size it was\n\n1018\n00:56:00,458 --> 00:56:03,826\nsupposed to be. Okay, and you remember from the slides,\n\n1019\n00:56:03,828 --> 00:56:05,594\nwe do this in an object-oriented way.\n\n1020\n00:56:05,596 --> 00:56:09,164\nThe system wants the MVC that's being put up to say,\n\n1021\n00:56:09,166 --> 00:56:13,669\nwhat size do you want to be? Now, what's really cool is,\n\n1022\n00:56:13,671 --> 00:56:18,207\nI'm gonna calculate that size using Auto Layout, okay?\n\n1023\n00:56:18,209 --> 00:56:21,110\nI'm basically gonna say, make yourself as small as you can\n\n1024\n00:56:21,112 --> 00:56:23,746\nand still obey the Auto Layout rules, okay? And you can do\n\n1025\n00:56:23,748 --> 00:56:26,482\nthat with one line of code. So it's really cool. All right,\n\n1026\n00:56:26,484 --> 00:56:28,884\nso where am I gonna do that? So I'm gonna do that in my\n\n1027\n00:56:28,886 --> 00:56:30,185\nEditWaypointViewController. Okay,\n\n1028\n00:56:30,187 --> 00:56:32,955\nthis is the view controller that's coming up there. So\n\n1029\n00:56:32,957 --> 00:56:33,655\nit's the one responsible for\n\n1030\n00:56:33,657 --> 00:56:37,159\nsetting its preferred size. And I'm gonna do it in\n\n1031\n00:56:37,161 --> 00:56:42,231\nthe view controller life cycle method viewWillLayoutSubviews.\n\n1032\n00:56:42,233 --> 00:56:45,334\nOkay, so, I know that in viewWillLayOutSubviews,\n\n1033\n00:56:45,336 --> 00:56:49,071\nmy balance is gonna be set to whatever the latest thing is.\n\n1034\n00:56:49,073 --> 00:56:53,375\nSo I know I'm gonna have some good, bounds situation.\n\n1035\n00:56:53,377 --> 00:56:55,677\nSo I'm just gonna, in here, I'm gonna set my,\n\n1036\n00:56:55,679 --> 00:57:02,151\npreferred content size, that's the size that I prefer to be,\n\n1037\n00:57:02,153 --> 00:57:04,119\nto be the following thing,\n\n1038\n00:57:04,121 --> 00:57:09,825\nview dot, okay, and all views implement this cool method,\n\n1039\n00:57:09,827 --> 00:57:17,299\nsystemLayoutSizeFittingSize, okay.\n\n1040\n00:57:17,301 --> 00:57:20,402\nSo that's basically saying, use Auto Layout and\n\n1041\n00:57:20,404 --> 00:57:20,803\ntell me what size will\n\n1042\n00:57:20,805 --> 00:57:25,407\nfit in this size the best. And there's a really cool size,\n\n1043\n00:57:25,409 --> 00:57:29,845\npredefined size, called the UILayoutFittingSize.\n\n1044\n00:57:29,847 --> 00:57:33,282\nThere's a ExpandedSize, which means, make me as big as you\n\n1045\n00:57:33,284 --> 00:57:36,852\ncan and obey Auto Layout, and then there's CompressedSize,\n\n1046\n00:57:36,854 --> 00:57:40,389\nwhich is, make me as small as you can. Okay, so, I'm gonna\n\n1047\n00:57:40,391 --> 00:57:43,559\ngo for CompressedSize, okay, and it's going to give me\n\n1048\n00:57:43,561 --> 00:57:46,962\na size that fits as small as possible using Auto Layout.\n\n1049\n00:57:46,964 --> 00:57:48,931\nOkay, so this is a really cool little method,\n\n1050\n00:57:48,933 --> 00:57:52,534\nit's how you get Auto Layout to calculate a size for you.\n\n1051\n00:57:52,536 --> 00:57:55,637\nAll right, so let's see, now that the size is right,\n\n1052\n00:57:55,639 --> 00:57:58,974\nlet's go see if that's going to fix things. I don't think\n\n1053\n00:57:58,976 --> 00:58:02,544\nit's gonna be quite right, but it's gonna be close.\n\n1054\n00:58:07,485 --> 00:58:11,854\nAll right, here we go, drop a pin. We're gonna click on it,\n\n1055\n00:58:11,856 --> 00:58:16,658\noops, I clicked on the side of it. Okay, and edit it. Okay,\n\n1056\n00:58:16,660 --> 00:58:19,828\nnow, this is really close. Okay, it's really nice.\n\n1057\n00:58:19,830 --> 00:58:22,364\nSee how it's making it just the right size?\n\n1058\n00:58:22,366 --> 00:58:25,868\nThe problem is, the text editing part is pretty small.\n\n1059\n00:58:25,870 --> 00:58:29,972\nBecause look what it did, it sized it to the word Dropped.\n\n1060\n00:58:29,974 --> 00:58:33,175\nOkay, and why did it do that? Because in our Auto Layout,\n\n1061\n00:58:33,177 --> 00:58:36,111\nwe didn't tell anything else about what size it should be.\n\n1062\n00:58:36,113 --> 00:58:37,346\nSo it put the contents in there, and\n\n1063\n00:58:37,348 --> 00:58:39,882\nit made it as small as possible and fit the contents.\n\n1064\n00:58:39,884 --> 00:58:43,886\nSo we actually wanna go back to our storyboard and put\n\n1065\n00:58:43,888 --> 00:58:47,289\na minimum, reasonable minimum size for those text fields so\n\n1066\n00:58:47,291 --> 00:58:50,459\nthat they will give the person room to type something in.\n\n1067\n00:58:50,461 --> 00:58:53,729\nOkay? The other thing is, the background is white.\n\n1068\n00:58:53,731 --> 00:58:56,698\nThis may be hard for you to see on that screen. But if you\n\n1069\n00:58:56,700 --> 00:59:00,769\nlook where the little arrow is pointing next to the word\n\n1070\n00:59:00,771 --> 00:59:04,540\ndescription there, that's actually semitransparent.\n\n1071\n00:59:04,542 --> 00:59:06,041\nAnd then also where the name and\n\n1072\n00:59:06,043 --> 00:59:09,077\ndescription is is a white box. Okay, so it's actually\n\n1073\n00:59:09,079 --> 00:59:12,781\npossible to have the whole thing be this semitransparent,\n\n1074\n00:59:12,783 --> 00:59:15,284\nso that we can kind of see that we're on top of a map.\n\n1075\n00:59:15,286 --> 00:59:19,221\nIt won't feel so kind of obnoxious, this white box. And\n\n1076\n00:59:19,223 --> 00:59:21,657\nthe way to do that is just to make this MVC have\n\n1077\n00:59:21,659 --> 00:59:25,894\na background of clear. Okay, then it's just going to appear\n\n1078\n00:59:25,896 --> 00:59:28,730\nclear on top of the popover's background,\n\n1079\n00:59:28,732 --> 00:59:30,399\nwhich is semitransparent.\n\n1080\n00:59:30,401 --> 00:59:32,034\nOkay, so we're gonna fix both those things at once.\n\n1081\n00:59:32,036 --> 00:59:35,370\nSo we're going back to our storyboard here. Okay, so\n\n1082\n00:59:35,372 --> 00:59:38,674\nwe're gonna make it so that these text fields right here,\n\n1083\n00:59:38,676 --> 00:59:41,343\nokay, are a reasonable minimal, minimum size.\n\n1084\n00:59:41,345 --> 00:59:43,645\nSo what would be a reasonable minimum size?\n\n1085\n00:59:43,647 --> 00:59:48,483\nLet's go here to our width here and height. And so\n\n1086\n00:59:48,485 --> 00:59:52,354\nwe could say a width of maybe, I don't know, 250 points?\n\n1087\n00:59:52,356 --> 00:59:54,289\nThis is something that you could play with in your UI.\n\n1088\n00:59:54,291 --> 00:59:57,025\nI really only need to set one of these, because these\n\n1089\n00:59:57,027 --> 00:59:59,194\nare already gonna be the same width. And so\n\n1090\n00:59:59,196 --> 01:00:02,130\nthat's gonna force these to be the same width. But actually,\n\n1091\n01:00:02,132 --> 01:00:06,835\nI don't want it to be exactly 250. I want it to be at least\n\n1092\n01:00:06,837 --> 01:00:11,106\n250, okay. Because if the name is really long, and\n\n1093\n01:00:11,108 --> 01:00:14,176\nit'll fit without going off the edge of the screen, sure,\n\n1094\n01:00:14,178 --> 01:00:18,714\nyou can do it. So I add the constraint here to be 250.\n\n1095\n01:00:18,716 --> 01:00:21,149\nAnd you can see that it makes it exactly 250, but\n\n1096\n01:00:21,151 --> 01:00:23,785\nI don't want that. So I'm gonna go over here to my\n\n1097\n01:00:23,787 --> 01:00:27,889\ndimensions inspector and look at this width 250. I'm gonna\n\n1098\n01:00:27,891 --> 01:00:32,427\nedit it and change it to greater than or equal to 250,\n\n1099\n01:00:32,429 --> 01:00:38,266\nokay? So understand that Auto Layout is pretty configurable.\n\n1100\n01:00:38,268 --> 01:00:40,836\nYou don't have to make things always be exactly certain\n\n1101\n01:00:40,838 --> 01:00:47,109\nsizes, okay? So we'll go ahead and adjust our frames here.\n\n1102\n01:00:47,111 --> 01:00:52,147\nOkay, got that? Okay, now what about the clear? That's really\n\n1103\n01:00:52,149 --> 01:00:54,616\nsimple. I'm just gonna click the background view here,\n\n1104\n01:00:54,618 --> 01:00:56,451\nand instead of having it be white, okay,\n\n1105\n01:00:56,453 --> 01:00:58,987\nthis background view, I'm gonna have it be the default,\n\n1106\n01:00:58,989 --> 01:01:04,192\nwhich is clear. Okay? So let's run it again.\n\n1107\n01:01:13,671 --> 01:01:14,870\nOkay, yes, so that's working.\n\n1108\n01:01:14,872 --> 01:01:16,938\nAll right, so let's drop a pin. Okay.\n\n1109\n01:01:16,940 --> 01:01:22,310\nWe're gonna edit it, here we go. Boom. Perfect. Okay,\n\n1110\n01:01:22,312 --> 01:01:24,680\ngive us a little extra space to work with.\n\n1111\n01:01:24,682 --> 01:01:25,614\nWe can see, can you see that?\n\n1112\n01:01:25,616 --> 01:01:26,648\nYeah, you can see it's kind of a little bit see through.\n\n1113\n01:01:26,650 --> 01:01:30,318\nYou can see it's a little bit green behind that, looks a,\n\n1114\n01:01:30,320 --> 01:01:34,189\na lot nicer. Okay so, excellent.\n\n1115\n01:01:34,191 --> 01:01:37,659\nWow, popovers are great. I'm sure this didn't do any damage\n\n1116\n01:01:37,661 --> 01:01:40,896\non the iPhone side. Let's go take a look, okay?\n\n1117\n01:01:40,898 --> 01:01:47,436\niPhone. Sure the iPhone looks just great.\n\n1118\n01:01:50,307 --> 01:01:53,709\nAll right, here it is. We'll drop a pin.\n\n1119\n01:01:53,711 --> 01:01:56,912\nAll right, there it is, all right, here we go. Oops.\n\n1120\n01:01:56,914 --> 01:02:00,215\nUgh. Okay, well, clearly we totally broke, and\n\n1121\n01:02:00,217 --> 01:02:03,118\nunderstandably, broke our iPhone side of this.\n\n1122\n01:02:03,120 --> 01:02:05,787\nSo what's wrong here, what's going on? Well, first of all,\n\n1123\n01:02:05,789 --> 01:02:07,456\nwe took it out of the navigation controller, so\n\n1124\n01:02:07,458 --> 01:02:09,925\nwe lost our done button, okay? So we're done, okay?\n\n1125\n01:02:09,927 --> 01:02:13,261\n[LAUGH] Second one is, we made the background clear, so\n\n1126\n01:02:13,263 --> 01:02:17,065\nit's looking into the void. Because, we know that when\n\n1127\n01:02:17,067 --> 01:02:20,502\nit adapts, okay, first of all, why is it coming up this way?\n\n1128\n01:02:20,504 --> 01:02:23,338\nWell, the system knows this is horizontally compact, so\n\n1129\n01:02:23,340 --> 01:02:26,074\nit adapted from popover to full screen modal, okay.\n\n1130\n01:02:26,076 --> 01:02:30,245\nFull screen modal completely covers\n\n1131\n01:02:30,247 --> 01:02:32,514\nthe thing underneath it, doesn't show anything,\n\n1132\n01:02:32,516 --> 01:02:34,616\ndoesn't show through, it completely covers it.\n\n1133\n01:02:34,618 --> 01:02:38,420\nAnd it covers it with the void, the great void, okay.\n\n1134\n01:02:38,422 --> 01:02:41,656\nAnd since we're looking clear into the void, it's black,\n\n1135\n01:02:41,658 --> 01:02:44,126\nokay, the void happens to be black. All right, so that's\n\n1136\n01:02:44,128 --> 01:02:47,028\nwhy this looks so terrible. So what are we gonna do about\n\n1137\n01:02:47,030 --> 01:02:51,066\nthis, okay? There's a number of things that we can do\n\n1138\n01:02:51,068 --> 01:02:55,704\nto make this a lot better. So, actually, before we do this,\n\n1139\n01:02:55,706 --> 01:02:58,907\nlet's do one other quick thing. I wanna show you one\n\n1140\n01:02:58,909 --> 01:03:01,910\nother quick thing. Let's go back over to our,\n\n1141\n01:03:01,912 --> 01:03:07,215\nlook at our iPad here, okay? We're back on the iPad there.\n\n1142\n01:03:07,217 --> 01:03:11,319\nOkay, so when I change this, let's say I change something\n\n1143\n01:03:11,321 --> 01:03:15,857\nhere, like, you know, let's change it to, I'm not going,\n\n1144\n01:03:15,859 --> 01:03:19,194\nokay, I'm not going, and I hit return. And now,\n\n1145\n01:03:19,196 --> 01:03:22,397\nhow do we dismiss a popover? We just hit somewhere else,\n\n1146\n01:03:22,399 --> 01:03:26,535\nright? So here we go, tap. Look at that. It didn't\n\n1147\n01:03:26,537 --> 01:03:29,838\nshow it to us. Remember, when we had it on the iPhone,\n\n1148\n01:03:29,840 --> 01:03:33,008\nwhen I clicked Done, it showed it. Now it's not showing.\n\n1149\n01:03:33,010 --> 01:03:36,511\nNow, if I click on it, okay, it worked, that's great. But\n\n1150\n01:03:36,513 --> 01:03:39,815\nno, we want it to show just like it did on the iPhone.\n\n1151\n01:03:39,817 --> 01:03:44,085\nSo how are we gonna fix that? That's pretty easy to fix.\n\n1152\n01:03:44,087 --> 01:03:47,455\nWe're gonna use, over here in our GPX controller,\n\n1153\n01:03:47,457 --> 01:03:50,625\nthis same popover presentation controller.\n\n1154\n01:03:50,627 --> 01:03:53,595\nWe're going to implement one of its delegate methods.\n\n1155\n01:03:53,597 --> 01:03:55,931\nOkay, so we're going to set ourself as the delegate\n\n1156\n01:03:55,933 --> 01:03:58,767\nof this pop-over presentation controller, which means,\n\n1157\n01:03:58,769 --> 01:04:02,370\nof course, we have to go up here. And say that we\n\n1158\n01:04:02,372 --> 01:04:07,475\nare a UIPopoverPresentationControll-\n\n1159\n01:04:07,477 --> 01:04:11,880\nerDeligate, okay? And that, all right. So we're\n\n1160\n01:04:11,882 --> 01:04:14,216\nPopoverPresentationController- Deligate. Which\n\n1161\n01:04:14,218 --> 01:04:16,685\nPopoverPresentationController- Deligate method are we gonna\n\n1162\n01:04:16,687 --> 01:04:20,522\nimplement here? We're gonna implement the one where we\n\n1163\n01:04:20,524 --> 01:04:26,595\nfind out that it dismissed, dismiss pop over.\n\n1164\n01:04:26,597 --> 01:04:28,096\nOkay, so this message gets sent to\n\n1165\n01:04:28,098 --> 01:04:29,898\nthe pop over presentation controller's delegate,\n\n1166\n01:04:29,900 --> 01:04:31,933\nwhen the pop over is dismissed. A perfect time for\n\n1167\n01:04:31,935 --> 01:04:35,370\nus to reselect that waypoint. Okay, we have that method\n\n1168\n01:04:35,372 --> 01:04:37,539\nstill, stay select waypoint, so let's go ahead and\n\n1169\n01:04:37,541 --> 01:04:39,774\ndo it. How do we get it this time? Well, we're going to\n\n1170\n01:04:39,776 --> 01:04:42,777\nget this from the pop over presentation controller. Okay?\n\n1171\n01:04:42,779 --> 01:04:46,648\nWe're gonna get it's presented ViewController, okay?\n\n1172\n01:04:46,650 --> 01:04:48,917\nThat's the controller its presenting which is our\n\n1173\n01:04:48,919 --> 01:04:52,220\neditable view, waypoint view controller. And it better be\n\n1174\n01:04:52,222 --> 01:04:56,291\nan EditWaypointViewController, okay? And if it is,\n\n1175\n01:04:56,293 --> 01:05:01,363\nthen we can just get the waypoint to edit, okay? So\n\n1176\n01:05:01,365 --> 01:05:07,736\nnow, we're on this. Okay. So we'll drop,\n\n1177\n01:05:07,871 --> 01:05:15,043\nclick, go up here, change this to something, random words.\n\n1178\n01:05:15,879 --> 01:05:20,048\nThe only thing is tip away, and we got it. Okay.\n\n1179\n01:05:20,050 --> 01:05:22,317\nSo that's a great use of that little delegate. But\n\n1180\n01:05:22,319 --> 01:05:25,620\nthere are even better uses of that little delegate.\n\n1181\n01:05:25,622 --> 01:05:28,256\nAnd a lot of them have to do with this adaptation\n\n1182\n01:05:28,258 --> 01:05:31,526\nbehavior, okay? The way that the system is adopting to that\n\n1183\n01:05:31,528 --> 01:05:33,962\nhorizontally compact environment and\n\n1184\n01:05:33,964 --> 01:05:38,199\nputting that thing up on our iPhone\n\n1185\n01:05:38,201 --> 01:05:42,037\nin this really obnoxious way. Okay so let's go and\n\n1186\n01:05:42,039 --> 01:05:45,707\nfix some of these things. One thing we could do to fix this\n\n1187\n01:05:45,709 --> 01:05:50,478\nis we could make it not adapt. Okay? We can make it just so\n\n1188\n01:05:50,480 --> 01:05:53,081\nthat it uses popover on iPhone. It doesn't do this\n\n1189\n01:05:53,083 --> 01:05:55,850\nwhole putting a modal one up instead. Okay so\n\n1190\n01:05:55,852 --> 01:05:59,321\nhow would we do that? All right, that one we're gonna\n\n1191\n01:05:59,323 --> 01:06:01,790\nimplement a different delegate method here.\n\n1192\n01:06:01,792 --> 01:06:06,461\nPopover delegate. This one is called the,\n\n1193\n01:06:06,463 --> 01:06:11,066\nnote here, adaptivePresentationStyleforP-\n\n1194\n01:06:11,068 --> 01:06:15,870\nresentationController. Okay, this guy right here. Okay,\n\n1195\n01:06:15,872 --> 01:06:19,040\nadapt to presentation style for presentation controller,\n\n1196\n01:06:19,042 --> 01:06:20,208\nactually we want a different one,\n\n1197\n01:06:20,210 --> 01:06:23,645\nwe want the one that gives us the trade collection.\n\n1198\n01:06:24,781 --> 01:06:29,951\nAdaptivePresentationStyle, it's this one. Okay?\n\n1199\n01:06:29,953 --> 01:06:32,954\nSo this one is basically asking us, let me make it so\n\n1200\n01:06:32,956 --> 01:06:36,324\nyou can see it a little better here. Okay?\n\n1201\n01:06:36,326 --> 01:06:39,494\nIt has two arguments here and it returns\n\n1202\n01:06:39,496 --> 01:06:42,230\na ModalPresentationStyle. So this is saying, for\n\n1203\n01:06:42,232 --> 01:06:45,533\na given trait collection like horizontally compact or\n\n1204\n01:06:45,535 --> 01:06:49,404\nwhatever how do you want to present this\n\n1205\n01:06:49,406 --> 01:06:52,607\nthing in when you're adapting. Now if I don't implement this,\n\n1206\n01:06:52,609 --> 01:06:55,276\nwhat it does is, it looks at this tray collection, says,\n\n1207\n01:06:55,278 --> 01:06:59,748\nis it horizontally compact? Yes? Then return full screen.\n\n1208\n01:06:59,750 --> 01:07:01,916\nThat's how this whole adaptation thing works.\n\n1209\n01:07:01,918 --> 01:07:05,387\nWell, I can fix that by just saying return none. Okay,\n\n1210\n01:07:05,389 --> 01:07:10,191\nthat means don't adapt, okay? So now we will never adapt,\n\n1211\n01:07:10,193 --> 01:07:12,327\nnow if I run on the iPhone,\n\n1212\n01:07:12,329 --> 01:07:16,898\nyou'll see that it's not going to adapt because I set\n\n1213\n01:07:16,900 --> 01:07:20,702\nthe presentation style for, adapting style, to be none so\n\n1214\n01:07:20,704 --> 01:07:24,406\nit's never going to adapt. Go here, you click this.\n\n1215\n01:07:24,408 --> 01:07:27,809\nSure enough we get that. Now look how terrible this looks.\n\n1216\n01:07:27,811 --> 01:07:31,346\nOkay? Clearly horizontally compact is not wide enough to\n\n1217\n01:07:31,348 --> 01:07:34,849\nshow this popover. Okay? It's, smashed it in there,\n\n1218\n01:07:34,851 --> 01:07:37,986\ntried to obey the 250 point wide for the text field.\n\n1219\n01:07:37,988 --> 01:07:40,855\nThe name and description got cut off. It just not you\n\n1220\n01:07:40,857 --> 01:07:44,025\nknow couldn't quite point to the [LAUGH] the pin prob\n\n1221\n01:07:44,027 --> 01:07:46,661\nis a big mess. So this is not the solution to this problem.\n\n1222\n01:07:46,663 --> 01:07:48,797\nIt seemed like it would be a good solution to this problem.\n\n1223\n01:07:48,799 --> 01:07:52,834\nBut it's not. So, lets go try and solve some of those other\n\n1224\n01:07:52,836 --> 01:07:57,405\nproblems we had. Okay, one is, we had no done button, okay?\n\n1225\n01:07:57,407 --> 01:07:59,074\nSo how can we get the done button back? Well,\n\n1226\n01:07:59,076 --> 01:08:01,876\nwe need to put that thing back in a navigation controller,\n\n1227\n01:08:01,878 --> 01:08:06,614\nbut only when we're adapting. So, first of all,\n\n1228\n01:08:06,616 --> 01:08:07,749\nI'm going to comment this out so\n\n1229\n01:08:07,751 --> 01:08:10,418\nthat we're back to adapting. And I'm gonna input another\n\n1230\n01:08:10,420 --> 01:08:15,423\ndelegate method here which is called view controller for\n\n1231\n01:08:15,425 --> 01:08:20,462\nadaptive presentation style. Here it is. Okay,\n\n1232\n01:08:20,464 --> 01:08:26,801\nagain I'll show you the arguments here. Okay, now look\n\n1233\n01:08:26,803 --> 01:08:30,505\nwhat this one returns. This one returns a view controller.\n\n1234\n01:08:30,507 --> 01:08:33,274\nThis is basically saying, okay, I'm trying to adapt\n\n1235\n01:08:33,276 --> 01:08:36,144\nto a certain style, that's gonna be the full screen style\n\n1236\n01:08:36,146 --> 01:08:38,880\nhere give me a View Controller to show\n\n1237\n01:08:38,882 --> 01:08:41,916\nwhen I adapt. Now if I don't implement this, it's just\n\n1238\n01:08:41,918 --> 01:08:44,452\ngoing to use the edit waypoint view controller, okay.\n\n1239\n01:08:44,454 --> 01:08:47,422\nBut I'm going to fix this to return a navigational control\n\n1240\n01:08:47,424 --> 01:08:50,325\nthat has an edit waypoint controller in it. Okay. So\n\n1241\n01:08:50,327 --> 01:08:53,194\nlet's do that. I'm going to say, first I'm gonna let,\n\n1242\n01:08:53,196 --> 01:08:56,831\nwell first I'm gonna say, if the style that we're adapting\n\n1243\n01:08:56,833 --> 01:09:01,569\nto is full screen. Okay, then I'm going to create\n\n1244\n01:09:01,571 --> 01:09:05,907\na navigation controller, let navcon equal a UINavigation.\n\n1245\n01:09:05,909 --> 01:09:09,144\nI'm just creating it with its constructor, right,\n\n1246\n01:09:09,146 --> 01:09:12,614\nits initializer. And the rootViewController of it is\n\n1247\n01:09:12,616 --> 01:09:19,187\ngoing to be the controllers. PresentedViewController,\n\n1248\n01:09:19,189 --> 01:09:21,723\nremember we used that in the other one, okay,\n\n1249\n01:09:21,725 --> 01:09:22,423\nthat is the EditWaypoint,\n\n1250\n01:09:22,425 --> 01:09:25,293\nEditWaypointViewController that we're trying to present,\n\n1251\n01:09:25,295 --> 01:09:28,129\nthat's what it is. And so now I'm just gonna return this\n\n1252\n01:09:28,131 --> 01:09:31,266\nnavigation controller instead. So it's gonna use\n\n1253\n01:09:31,268 --> 01:09:34,369\nthe navigation controller instead of this. If we're not\n\n1254\n01:09:34,371 --> 01:09:36,671\nadapting to full screen then I'm gonna return nil and\n\n1255\n01:09:36,673 --> 01:09:39,507\nlet it do whatever it does by default which is you know\n\n1256\n01:09:39,509 --> 01:09:43,144\nuse the popover or it's not adapting so it doesn't matter.\n\n1257\n01:09:43,146 --> 01:09:46,214\nAll right let's see if that fixes anything here.\n\n1258\n01:09:51,388 --> 01:09:54,656\nAll right here we go. Drop it. Click on it,\n\n1259\n01:09:54,658 --> 01:09:58,459\nboom. Wahoo! Look at that we have a done button back.\n\n1260\n01:09:58,461 --> 01:10:00,528\nNow that done button, by the way, you might say,\n\n1261\n01:10:00,530 --> 01:10:00,762\nwhere'd that come from?\n\n1262\n01:10:00,764 --> 01:10:03,598\nOkay, well that's because we put the done button into that\n\n1263\n01:10:03,600 --> 01:10:06,167\nNBC back when it used to be a navigation controller.\n\n1264\n01:10:06,169 --> 01:10:09,003\nWhen we removed the navigation controller it kept the done\n\n1265\n01:10:09,005 --> 01:10:11,472\nbutton. It wasn't able to display it because it wasn't\n\n1266\n01:10:11,474 --> 01:10:14,475\nin a navigation controller until now. Again, but it kept\n\n1267\n01:10:14,477 --> 01:10:17,412\nthe Done button. Remember that all the things that appear\n\n1268\n01:10:17,414 --> 01:10:19,647\nin a navigation controllers title bar, the buttons and\n\n1269\n01:10:19,649 --> 01:10:23,384\nstuff are associated with the NBC inside, okay. And\n\n1270\n01:10:23,386 --> 01:10:25,920\nwhen you remove, put something in, embed in, or\n\n1271\n01:10:25,922 --> 01:10:28,056\ntake out of a navigational controller in NBC,\n\n1272\n01:10:28,058 --> 01:10:30,892\nit keeps all it's things so that's why we kept the Done\n\n1273\n01:10:30,894 --> 01:10:33,228\nbutton. Okay, not only kept the Done button there,\n\n1274\n01:10:33,230 --> 01:10:34,829\nit's still going to unwind. Okay?\n\n1275\n01:10:34,831 --> 01:10:37,565\nCuz it's still hooked up to that to unwind there. Now,\n\n1276\n01:10:37,567 --> 01:10:40,702\nwe still have this black background. That's not so\n\n1277\n01:10:40,704 --> 01:10:43,137\ngood. Okay? How are we gonna fix that? Well,\n\n1278\n01:10:43,139 --> 01:10:46,174\nI'm gonna do that in a cool way, which is to stop\n\n1279\n01:10:46,176 --> 01:10:51,079\nhaving it basically cover up the the thing underneath, and\n\n1280\n01:10:51,081 --> 01:10:52,747\nlet it show through. Okay?\n\n1281\n01:10:52,749 --> 01:10:56,451\nI'm gonna have this modal view controller come up. But\n\n1282\n01:10:56,453 --> 01:10:59,220\nnot cover up what's behind, okay, and\n\n1283\n01:10:59,222 --> 01:11:01,756\nthat's really simple to do. Actually,\n\n1284\n01:11:01,758 --> 01:11:04,959\nwe're going to use the same method we did back here, okay,\n\n1285\n01:11:04,961 --> 01:11:07,929\nbut instead of saying return none, okay,\n\n1286\n01:11:07,931 --> 01:11:12,700\nwe're just going to say let's just return. If the trace\n\n1287\n01:11:12,702 --> 01:11:18,139\ncollection here collection, okay trait selection,\n\n1288\n01:11:18,141 --> 01:11:22,644\nhorizontal size class, equals compact, then we're gonna\n\n1289\n01:11:22,646 --> 01:11:26,881\nreturn this new style which is over full screen.\n\n1290\n01:11:26,883 --> 01:11:28,549\nSo over full screen is like full screen but\n\n1291\n01:11:28,551 --> 01:11:31,919\nit's over the things so the things shines through. Okay\n\n1292\n01:11:31,921 --> 01:11:33,588\nthat's the only difference between full screen and\n\n1293\n01:11:33,590 --> 01:11:38,126\nover full screen. Otherwise, we're just going to not adapt.\n\n1294\n01:11:38,128 --> 01:11:40,762\nOkay, we're only gonna adapt in the horizontalSizeClass\n\n1295\n01:11:40,764 --> 01:11:45,466\nCompact. Okay, so let's see what that looks like.\n\n1296\n01:11:51,074 --> 01:11:56,044\nAll right, here it is. Drop one, click, bring it up.\n\n1297\n01:11:56,046 --> 01:12:00,114\nAll right! Okay, it brought it up. But, it's kinda weird that\n\n1298\n01:12:00,116 --> 01:12:02,950\nwe can see all the way through it kinda makes it think that\n\n1299\n01:12:02,952 --> 01:12:06,521\nwe could click on this things. Also having the word\n\n1300\n01:12:06,523 --> 01:12:09,123\ndescription be on the dark background makes it hard to\n\n1301\n01:12:09,125 --> 01:12:13,895\nsee it. Okay. I also noticed that maybe our 250 is a little\n\n1302\n01:12:13,897 --> 01:12:17,598\ntoo wide of a minimum. Maybe we wanna go down to 200.\n\n1303\n01:12:17,600 --> 01:12:19,734\nBut, what were really cool is if we could actually show\n\n1304\n01:12:19,736 --> 01:12:23,137\nwhat's behind slightly blurred. Just like the popover\n\n1305\n01:12:23,139 --> 01:12:26,641\none does. Right? The popover one it showed the name and\n\n1306\n01:12:26,643 --> 01:12:29,844\ndescription, but it was only kinda the slightly see-through\n\n1307\n01:12:29,846 --> 01:12:31,612\nsemi-transparent blurred thing.\n\n1308\n01:12:31,614 --> 01:12:34,449\nWell we can do that ourselves. Okay? There's a view, okay,\n\n1309\n01:12:34,451 --> 01:12:37,418\nwe can talk about in the slides. But there's a view\n\n1310\n01:12:37,420 --> 01:12:42,457\nwhich essentially presents whatever's behind it blurred\n\n1311\n01:12:42,459 --> 01:12:45,626\nokay, tha's what the view does. so were gonna poke one\n\n1312\n01:12:45,628 --> 01:12:49,764\nof this views right at the top of the navigation controllers\n\n1313\n01:12:49,766 --> 01:12:52,533\nview hierarchy okay. Even behind the things\n\n1314\n01:12:52,535 --> 01:12:55,036\nlike this bar at the top of the navigation control\n\n1315\n01:12:55,038 --> 01:12:57,705\neverything. Okay, we're gonna be really right at the top, so\n\n1316\n01:12:57,707 --> 01:12:58,773\nit's gonna blur everything behind. And\n\n1317\n01:12:58,775 --> 01:13:01,109\nthe navigation controller's gonna be on top of this nice,\n\n1318\n01:13:01,111 --> 01:13:04,746\nblurred thing. Okay? So, how do we do that? Well,\n\n1319\n01:13:04,748 --> 01:13:07,281\nwe create that navigation controller right here. So\n\n1320\n01:13:07,283 --> 01:13:10,218\nall we need to do is to create this little blurring view\n\n1321\n01:13:10,220 --> 01:13:15,890\ndoohickey, which is called a visual effects view. And\n\n1322\n01:13:15,892 --> 01:13:19,594\nalso, by the way, we're gonna wanna put here if the style\n\n1323\n01:13:19,596 --> 01:13:24,365\nis OverFullScreen so that we can do it in both cases there.\n\n1324\n01:13:24,768 --> 01:13:27,068\nSo, we're gonna create a visual effects view,\n\n1325\n01:13:27,070 --> 01:13:30,938\nvisualEffectsView, we'll call it and\n\n1326\n01:13:30,940 --> 01:13:31,973\nit's UIVisualEffectView.\n\n1327\n01:13:31,975 --> 01:13:38,246\nThat's the name of the class. VisualEffectView. I guess\n\n1328\n01:13:38,248 --> 01:13:42,083\nit would be VisualEffectView cuz it's a single effect. And\n\n1329\n01:13:42,085 --> 01:13:46,587\nyou just specify what kind of effect you want. Effect, and\n\n1330\n01:13:46,589 --> 01:13:51,392\nI want a UIBlurEffect. And the style of\n\n1331\n01:13:51,394 --> 01:13:54,695\nit is I want a ExtraLight okay which is a really\n\n1332\n01:13:54,697 --> 01:13:57,965\nextra light ver, blur. And the reason I want extra light is\n\n1333\n01:13:57,967 --> 01:13:59,801\ncuz I'm gonna be putting black text on top of it and\n\n1334\n01:13:59,803 --> 01:14:02,670\nthings like that so I really want that to stand out. So\n\n1335\n01:14:02,672 --> 01:14:05,139\nthere's extra light blurring.\n\n1336\n01:14:05,141 --> 01:14:10,445\nNow I'm going to set the visual effects views frame\n\n1337\n01:14:11,247 --> 01:14:14,482\nto equal the navCon bounds. Okay.\n\n1338\n01:14:14,484 --> 01:14:16,150\nSo navCon is a view controller. It's just\n\n1339\n01:14:16,152 --> 01:14:17,919\na regular view controller like any other view controller.\n\n1340\n01:14:17,921 --> 01:14:20,621\nIt's got a view which is it's top level view. So I'm gonna\n\n1341\n01:14:20,623 --> 01:14:23,991\nput my visual effects right at the top of its hierarchy, so\n\n1342\n01:14:23,993 --> 01:14:25,893\nI'm gonna have it fill the entire thing. Now,\n\n1343\n01:14:25,895 --> 01:14:28,296\nI'm also gonna do a little bit of magic here which we didn't\n\n1344\n01:14:28,298 --> 01:14:30,164\ntalk about at all, which is, there's\n\n1345\n01:14:30,166 --> 01:14:33,734\na really kind of an old style way of doing auto layout where\n\n1346\n01:14:33,736 --> 01:14:36,604\nyou can specify just a couple of things.\n\n1347\n01:14:36,606 --> 01:14:40,608\nAnd, I'm going to have this visual effect view\n\n1348\n01:14:40,610 --> 01:14:44,445\nalways stick to the same size as the nab cons bounds.\n\n1349\n01:14:44,447 --> 01:14:47,315\nAnd the way I'm gonna do it, is by using these old style\n\n1350\n01:14:47,317 --> 01:14:51,018\nconstraints where I basically say that the width and height\n\n1351\n01:14:51,020 --> 01:14:55,122\nof my visual effects view is flexible. So, as things change\n\n1352\n01:14:55,124 --> 01:14:57,859\nit tries to stick to its super view. Okay? Don't worry\n\n1353\n01:14:57,861 --> 01:15:00,628\ntoo much about this magic It's just a little easier way than\n\n1354\n01:15:00,630 --> 01:15:03,965\ndoing this than trying to show you how to do it with\n\n1355\n01:15:03,967 --> 01:15:05,166\nthe new way.\n\n1356\n01:15:05,168 --> 01:15:08,870\nSo I just basically say that's auto resizing math is flexible\n\n1357\n01:15:08,872 --> 01:15:09,203\nwidth and flexible height.\n\n1358\n01:15:09,205 --> 01:15:13,374\nIf it's superview changes it's size than it sizes with it,\n\n1359\n01:15:13,376 --> 01:15:15,443\nusing the rules keep your width and\n\n1360\n01:15:15,445 --> 01:15:16,544\nheight flexible. Okay?\n\n1361\n01:15:16,546 --> 01:15:20,815\nSo now I'm just going to take that navcon top level view and\n\n1362\n01:15:20,817 --> 01:15:23,551\ninsert a subview, which is a visual effects view.\n\n1363\n01:15:23,553 --> 01:15:28,189\nAnd I'm gonna put it at index zero, which is all the way at\n\n1364\n01:15:28,191 --> 01:15:31,359\nthe back. Remember subviews is ordered int he subview list.\n\n1365\n01:15:31,361 --> 01:15:34,762\nAll right, so let's take a look at that.\n\n1366\n01:15:39,936 --> 01:15:45,473\nAll right. Drop it here. Up. There we go.\n\n1367\n01:15:45,475 --> 01:15:48,209\nOkay, see how it, you can kinda see the,\n\n1368\n01:15:48,211 --> 01:15:51,012\nI don't know how, how good the projection there is, but\n\n1369\n01:15:51,014 --> 01:15:52,513\nyou can kinda almost see the valleys here.\n\n1370\n01:15:52,515 --> 01:15:55,783\nThe mountains and the valleys. In there. When you get this\n\n1371\n01:15:55,785 --> 01:16:01,455\nwe'll go run it at home you'll see it a lot clearer. Okay? So\n\n1372\n01:16:01,457 --> 01:16:03,024\nthat's it we only have three minutes so\n\n1373\n01:16:03,026 --> 01:16:08,963\nI'm not going to the slides on that. I will post on\n\n1374\n01:16:08,965 --> 01:16:12,533\nhow you can learn a little more about that. And\n\n1375\n01:16:12,535 --> 01:16:14,435\nthat's it. So, that's everything there.\n\n1376\n01:16:14,437 --> 01:16:15,903\nYou learned a lot about map view and\n\n1377\n01:16:15,905 --> 01:16:17,572\nabout all kinds of segways there, so\n\n1378\n01:16:17,574 --> 01:16:18,773\nhopefully that will prepare you for\n\n1379\n01:16:18,775 --> 01:16:20,708\nyour final presentation. So,\n\n1380\n01:16:20,710 --> 01:16:22,343\nnext week is just the alternate final,\n\n1381\n01:16:22,345 --> 01:16:24,445\nthere's a holiday on Monday, so there's no class then,\n\n1382\n01:16:24,447 --> 01:16:26,747\nand Wednesday is the alternate final. And,\n\n1383\n01:16:26,749 --> 01:16:30,718\nif you have any questions I'll help you here as usual. For\n\n1384\n01:16:30,720 --> 01:16:30,751\nmore, please visit us at stanford.edu.\n\n"
  },
  {
    "path": "subtitles/2. Applying MVC.srt",
    "content": "1\n00:00:00,001 --> 00:00:03,402\n[MUSIC]\n\n2\n00:00:03,404 --> 00:00:07,739\nStanford University. >> Okay, well, welcome\n斯坦福大学. >> 欢迎\n\n3\n00:00:07,741 --> 00:00:12,276\nto Stanford CS193P. This is spring quarter of 2016, and\n参加斯坦福大学的 CS193P 课程.这是2016年的春季教程的\n\n4\n00:00:12,278 --> 00:00:16,013\nthis is lecture number 2. And today, we are going to talk\n第二个课时.今天我们将要聊聊\n\n5\n00:00:16,015 --> 00:00:19,950\nabout MVC, okay, I'm gonna try and really briefly cover that\n关于 MVC 的知识.接下来我将尝试简短的描述一下 MVC.\n\n6\n00:00:19,952 --> 00:00:23,553\nbecause I know only about half of you know what MVC is, and\n因为我知道你们中大概只有一半知道MVC 是什么.\n\n7\n00:00:23,555 --> 00:00:27,257\nit's a very important part of doing any iOS development.\nMVC 是 iOS 开发过程中非常重要的一部分.\n\n8\n00:00:27,259 --> 00:00:30,126\nAnd then after I'm done with that, I'm gonna continue\n我将在上次代码的基础上完成计算器的功能\n\n9\n00:00:30,128 --> 00:00:32,795\nthe demo from last time, we'll use MVC and learn yet\n我们将使用 MVC 以及之前学过的\n\n10\n00:00:32,797 --> 00:00:36,565\nsome more things about Swift and Objective C, all right?\nSwift 和 Objective C 的知识,准备好了吗?\n\n11\n00:00:36,567 --> 00:00:40,535\nAll right, so MVC, what is it? As I mentioned last time, it's\n那么什么是 MVC 呢?就像我上次提到过的,\n\n12\n00:00:40,537 --> 00:00:44,172\nessentially a way of dividing up your application or\n从本质上来说它是将你应用或代码\n\n13\n00:00:44,174 --> 00:00:47,975\nyour source code into three different camps,\n分割成三个不同的\"阵营\".\n\n14\n00:00:47,977 --> 00:00:52,980\nokay? The three camps pictured here are the model camp.\n就如图片所展示的.而左下角就是模型的\"阵营\".\n\n15\n00:00:52,982 --> 00:00:57,484\nThe model camp is what your application does. Okay,\n所谓模型的\"阵营\"指的是你应用是做什么的.\n\n16\n00:00:57,486 --> 00:00:58,952\nnothing about how it's drawn on screen or\n而跟你界面上如何绘制以及展示\n\n17\n00:00:58,954 --> 00:01:01,221\nanything like that, okay. It's not how it's displayed,\n什么毫无关系.不是关于它如何展示\n\n18\n00:01:01,223 --> 00:01:03,856\nit's just what it is. So for a calculator app,\n而是关于应用是什么.那么对于一个计算器的应用来说\n\n19\n00:01:03,858 --> 00:01:06,926\nwhat it is it's a calculator, so the model is probably gonna\nModel \"阵营\"就是计算器,也就是说 Model 将会被\n\n20\n00:01:06,928 --> 00:01:08,827\nbe the part that does calculating,\n划分为一些计算的部分\n\n21\n00:01:08,829 --> 00:01:11,930\nokay. Next piece is the controller.\n那么接下来我们说说 Controller. \n\n22\n00:01:11,932 --> 00:01:17,369\nThe controller is how your model is displayed on screen.\nController 就是控制你的模型如何在界面上进行展示的工具\n\n23\n00:01:17,371 --> 00:01:20,138\nOkay, it's kind of the how. This is basically all your\n关键点就在于如何进行展示.它主要是包含\n\n24\n00:01:20,140 --> 00:01:23,708\nUI logic, goes into your controller, all right? And\n你的界面逻辑以及界面的跳转.\n\n25\n00:01:23,710 --> 00:01:27,778\nthe view, you can think of as your controller's minions,\nView 你可以把它当做是 Controller 的仆从\n\n26\n00:01:27,780 --> 00:01:30,547\nokay, the things that the controller's gonna use to put\n那些 Controller 想要展示\n\n27\n00:01:30,549 --> 00:01:33,283\nthings on screen. So that's buttons and labels and\n在屏幕上的东西. 所以那些按钮,标签,\n\n28\n00:01:33,285 --> 00:01:36,419\ntables and all those kinda things that the controller\n列表以及一些 Controller 希望在界面上展示的控件的控件\n\n29\n00:01:36,421 --> 00:01:38,688\nneeds to display what's in the model and\n用于展示 Model 的信息,\n\n30\n00:01:38,690 --> 00:01:41,924\nto get input from the user to update the model as well,\n用户的输入和更新 Model 的内容\n\n31\n00:01:41,926 --> 00:01:44,126\nokay? So those are the three camps.\n这就是三个\"阵营\"的大体概念.\n\n32\n00:01:44,128 --> 00:01:46,628\nNow it's one thing to decide where things go\n接下来根据之前提到的\"阵营\"概念\n\n33\n00:01:46,630 --> 00:01:49,197\nbased on the description of the camp, but a really\n来说说决定整套机制的运转的机制,\n\n34\n00:01:49,199 --> 00:01:52,333\nimportant piece of it is the communication between camps,\n三个\"阵营\"交互的关键部分,\n\n35\n00:01:52,335 --> 00:01:54,435\nwhat's allowed, what's allowed, what's not.\n哪些行为是允许的,哪些是不允许的.\n\n36\n00:01:54,437 --> 00:01:57,204\nAnd when communication is allowed, how do you do it,\n以及什么时候进行交互,如何在 iOS 中实现,\n\n37\n00:01:57,206 --> 00:02:00,607\nokay, in iOS? How, how is that communication facilitated?\n如何促进各\"阵营\"的交流.\n\n38\n00:02:00,609 --> 00:02:04,944\nSo, to help with this, I've kind of, drew, drawn here this\n为了帮助理解,我在中心绘制了一个\n\n39\n00:02:04,946 --> 00:02:08,114\nlittle Y in the middle. It's kinda like road signs, okay?\nY 字的图案.有点类似马路标志.\n\n40\n00:02:08,116 --> 00:02:10,916\nIt's like double yellow at the bottom there is don't cross.\n在 'Y' 的下方有两条黄色的线条表示两边是不相通的\n\n41\n00:02:10,918 --> 00:02:13,752\nAnd then solid white is yeah, you can cross, but\n上方两条白色的线表示两边是可以相通的.\n\n42\n00:02:13,754 --> 00:02:17,088\nyou're not really supposed to generally do this without\n你应该在编程时尽可能\n\n43\n00:02:17,090 --> 00:02:20,358\nbeing very careful.\n的小心这方面.\n\n44\n00:02:20,360 --> 00:02:22,193\nthe traffic is going in the same direction, so\n三个\"阵营\"交互的方向总是固定的\n\n45\n00:02:22,195 --> 00:02:23,627\nyou can pretty much crossover.\n所以你只要关注一下大体的\"交互\"方向.\n\n46\n00:02:23,629 --> 00:02:24,828\nProbably wanna put your turn indicator on,\n也许你想打破规定\n\n47\n00:02:24,830 --> 00:02:28,732\nbut off you go. Okay, so let's talk about how that works for\n那你就那样做吧. 那么我们先来谈谈 MVC\n\n48\n00:02:28,734 --> 00:02:32,301\nthese three camps. First let's talk about controller talking\n是如何工作的吧.首先我们先聊聊 Controller 和\n\n49\n00:02:32,303 --> 00:02:35,905\nto the model. The controller can talk to the model all it\nModel 之间的交互吧. Controller 能调用 Model 的方法. \n\n50\n00:02:35,907 --> 00:02:37,940\nwants. It knows everything about the model.\n它能知道 Model 的所有.\n\n51\n00:02:37,942 --> 00:02:39,708\nIt can send any message it wants to the model.\n它能调用所有 Model 所有方法.\n\n52\n00:02:39,710 --> 00:02:42,477\nThe controller is in complete control of the model. Okay,\nController 能完全控制 Model,\n\n53\n00:02:42,479 --> 00:02:44,679\nand the controller needs that because the controller's\n它也需要这样,因为 Controller 的任务就是\n\n54\n00:02:44,681 --> 00:02:48,149\njob is to present what's in the model to the user or\n展示给用户看 Model 的信息,或者\n\n55\n00:02:48,151 --> 00:02:49,950\nto get information from the user and update the model.\n从用户处获得信息以及更新 Model 的信息.\n\n56\n00:02:49,952 --> 00:02:52,352\nSo it needs full control, so that's a full green arrow,\n所以 Controller 需要完全控制 Model ,因此图中有一个绿色箭头\n\n57\n00:02:52,354 --> 00:02:56,556\ndashed white road sign, road line there can do anything at\n以及白色虚线表示可以完全控制 Model.\n\n58\n00:02:56,558 --> 00:02:59,992\nonce. Same thing on the other side, the controller obviously\n相同地,在另一边 Controller 明显地\n\n59\n00:02:59,994 --> 00:03:02,795\nneeds to be able to use its minions however it wants to\n需要使用到它的\"仆从\"( View ),无论 Controller 希望如何展示\n\n60\n00:03:02,797 --> 00:03:06,265\ndisplay the model. And most of the time, the connection\nModel 的信息.大部分情况下, Controller 和 View 之间的链接\n\n61\n00:03:06,267 --> 00:03:09,968\nbetween the controller and its minions is via an outlet.\n都是通过 Outlet 来实现的.\n\n62\n00:03:09,970 --> 00:03:13,104\nAnd you remember we had an outlet on Monday, right?\n所以你们还记得周一提到的 Outlet 吗?\n\n63\n00:03:13,106 --> 00:03:13,871\nIt was the display?\n在之前的 Demo 中的展示.\n\n64\n00:03:13,873 --> 00:03:16,007\nYou remember that, it was a var instance variable.\n你需要记得它是一个实例变量和\n\n65\n00:03:16,009 --> 00:03:20,477\nDisplay with an optional UI label. And that connection is\n展示中 UILabel 的链接.这种链接方式就是\n\n66\n00:03:20,479 --> 00:03:22,679\nhow the controller was talking to it's view.\nController 和 View 之间的交互方式.\n\n67\n00:03:22,681 --> 00:03:25,715\nThat label, that UI label was part of it's view.\n那个Label, UILabel 就是那个 View 中的一部分.\n\n68\n00:03:25,717 --> 00:03:28,317\nIt was a minion in it's view. So that's\n就是那个仆从—— View .所以这里\n\n69\n00:03:28,319 --> 00:03:30,753\nfull green communication, kind of do whatever it wants,\n对 Controller 来说能完全\n\n70\n00:03:30,755 --> 00:03:32,588\ncontroller knows everything about both sides.\n控制它的两边的 View 和 Model.\n\n71\n00:03:32,590 --> 00:03:36,191\nIt has to. Let's talk about the model in the view.\n实际情况也要求这样设计. 接下来我们说说 Model 和 View 之间.\n\n72\n00:03:36,193 --> 00:03:40,795\nThose never speak to each other. Why is that? Simple,\n这二者之间不会产生交互,为什么呢?很简单,\n\n73\n00:03:40,797 --> 00:03:41,963\nthe model is UI independent,\nModel 和界面是相互独立的.\n\n74\n00:03:41,965 --> 00:03:45,366\nso there's absolutely nothing it has to say to the view,\n因此 Model 和 View 之间完全不可能产生直接交互.\n\n75\n00:03:45,368 --> 00:03:46,567\nwhich is completely UI dependent,\n特别对于那些完全和界面独立的\n\n76\n00:03:46,569 --> 00:03:49,236\nthat's all the view is. The view is just the minions\nModel 来说. View 只是 Controller\n\n77\n00:03:49,238 --> 00:03:52,639\nof the controller. And so, you know, it makes no sense for\n的仆从. 由此可知 View 和 Model 之间的交互\n\n78\n00:03:52,641 --> 00:03:55,408\nthese two to talk to each other. So that fire, that's\n是完全没有意义的.这就是为什么\n\n79\n00:03:55,410 --> 00:03:58,911\ndouble yellow line, don't ever do that in this class, okay?\n这里采用两条黄线表示,别在具体实现中这样做.\n\n80\n00:03:58,913 --> 00:04:02,014\nNo communication there at all. Okay, all communication in\n重申一次, Model 和 View 之间完全没有交互.所有的交互\n\n81\n00:04:02,016 --> 00:04:04,950\nthe model, in the view goes through the controller.\n都是通过 Controller 进行传递的.\n\n82\n00:04:04,952 --> 00:04:07,419\nAll right, what about from the view to the controller?\n那么关于从 View 到 Controller 有交互吗?\n\n83\n00:04:07,421 --> 00:04:10,254\nCan the view, like a label and stuff like that,\n那么 View (例如Label 等控件)能访问\n\n84\n00:04:10,256 --> 00:04:12,923\ntalk to its controller? Well, yes and\nController 吗?答案是:既可以也不可以.\n\n85\n00:04:12,925 --> 00:04:15,893\nno. The problem with the view is all the minions\n问题在于所有的控件\n\n86\n00:04:15,895 --> 00:04:19,296\nin there are generic objects like UIButton or UILabel.\n都是一个通用的类型,例如UIButton 或UILabel.\n\n87\n00:04:19,298 --> 00:04:21,297\nThose were written by Apple years ago.\n这些都是由苹果官方在多年前进行封装的.\n\n88\n00:04:21,299 --> 00:04:23,199\nThey know absolutely nothing about a calculator.\n对于这些控件来说,他们对计算器毫不知情.\n\n89\n00:04:23,201 --> 00:04:26,168\nSo there's way to kind of for them to talk to a calculator\n因此一定存在一种方法让它们与计算器交互\n\n90\n00:04:26,170 --> 00:04:28,804\nand know it's a calculator. Okay, so there's limited\n以及知道它是一个计算器.因此对于 Controller 和 View 来说\n\n91\n00:04:28,806 --> 00:04:31,239\ncommunication between the view and the controller. But\n它们之间的交互是有限制的.但是从另一方面来说\n\n92\n00:04:31,241 --> 00:04:33,441\noff course the view needs to talk to the controller because\nView 是需要访问 Controller 的,因为他是 Controller 的\"仆从\"\n\n93\n00:04:33,443 --> 00:04:36,177\nit's the controller's minions and things happen in the U.I.\n并且也需要通知 Controller 在界面上的事件,\n\n94\n00:04:36,179 --> 00:04:38,279\nand need to tell the controller what's going on so.\n同时也需要告诉 Controller 具体在界面上发生了什么.\n\n95\n00:04:38,281 --> 00:04:42,516\nThe kind of communication we have there has to be blind and\n类似这种的交互方式,我们必须做到适当屏蔽以及\n\n96\n00:04:42,518 --> 00:04:42,549\nstructured.\n结构化.\n\n97\n00:04:42,551 --> 00:04:47,087\nBlind meaning the objects in the view don't know what class\n所谓的屏蔽是指 View 不需要知道\n\n98\n00:04:47,089 --> 00:04:47,720\nthey're talking to. 'Kay?\n和什么对象进行交互.\n\n99\n00:04:47,722 --> 00:04:50,589\nCause view, buttons don't know anything about calculator view\n因为对于 View (例如按钮)来说完全不知道他在跟一个计算器的 Controller 进行交互\n\n100\n00:04:50,591 --> 00:04:53,225\ncontrollers. And it's structured because\n而结构化的原因在于\n\n101\n00:04:53,227 --> 00:04:57,262\nsince there is no knowledge of the Objects on either end.\n它对于要交互的对象一无所知. \n\n102\n00:04:57,264 --> 00:05:00,432\nThey have to communicate in a well-defined, pre-defined way,\n它们之间是通过之先定好的方法进行交互,\n\n103\n00:05:00,434 --> 00:05:03,301\nokay. So let's talk about some of those structured ways that\n那么我们就来说说\n\n104\n00:05:03,303 --> 00:05:06,737\nthe view minions talk to the controller. One of them\nView 通知 Controller 的方法.其中一种\n\n105\n00:05:06,739 --> 00:05:09,707\nyou learned last time is target action, okay. So\n我们在上节课讲到过,就是采用 Target-Action 模式实现.\n\n106\n00:05:09,709 --> 00:05:12,843\ntarget action's very simple, the controller hangs a target\n这种方法非常简单,只需 Controller 将自己设置成 target\n\n107\n00:05:12,845 --> 00:05:17,714\non itself by defining a method with at sign ib action on it,\n并且定义一个与 IBAction 的方法\n\n108\n00:05:17,716 --> 00:05:18,381\nusually, in Xcode, so\n通常在 Xcode 内,\n\n109\n00:05:18,383 --> 00:05:20,316\nthat little dot will work, okay. And\n如果有一个小的实心远点,说明它就生效了.\n\n110\n00:05:20,318 --> 00:05:23,585\nthen the view when it wants to talk to the controller simply\n当 View 希望通知 Controller 时,只需简单地\n\n111\n00:05:23,587 --> 00:05:26,388\ncalls that method and that connection. Okay.\n调用该方法即可.\n\n112\n00:05:26,390 --> 00:05:29,257\nThe action being sent, from the view controller,\n只需通过 Ctrl +左键拖拉\n\n113\n00:05:29,259 --> 00:05:31,926\nis wired up usually with control drag. You saw us do\n的方式建立对应的 Action.\n\n114\n00:05:31,928 --> 00:05:35,296\nthat. It can be done in code. But 99% of the time we control\n虽然我们可以通过代码来实现,但是99%的情况下,我们通过\n\n115\n00:05:35,298 --> 00:05:37,531\ndrag to create this target action connection.\nCtrl +左键拖来来创建对应的 Target-Action 的链接.\n\n116\n00:05:37,533 --> 00:05:40,500\nSo there's an example. Very simple communication between.\n最简单的例子就是\n\n117\n00:05:40,502 --> 00:05:44,771\nMenu in the View like the UI button and the Controller,\n菜单里的视图(如按钮)和 Controller 之间的链接就是 Target-Action 模式.\n\n118\n00:05:44,773 --> 00:05:49,208\nthe other method. Okay? Simple one. All right, what else,\n非常简单的方法.那么\n\n119\n00:05:49,210 --> 00:05:50,209\nwhat other kind of communication we had\n除此之外,还有什么其他 View 通知 Controller 的方式吗?\n\n120\n00:05:50,211 --> 00:05:53,412\nbesides Target action? Well, sometimes the View needs to\n当然,有些时候 View 需要\n\n121\n00:05:53,414 --> 00:05:56,348\ncommunicate something a little more complicated than just\n通知 Controller 一些复杂的事件\n\n122\n00:05:56,350 --> 00:05:59,918\nI was touched or something like that. Okay. For example,\n如点击的详情等.\n\n123\n00:05:59,920 --> 00:06:03,554\nit might be a scroll view, that's a generic view minion.\n例如一个通用的滚动视图,\n\n124\n00:06:03,556 --> 00:06:05,956\nAnd it might need to tell the controller,\n有时候需要通知 Controller\n\n125\n00:06:05,958 --> 00:06:09,093\nhey, this guy just started scrolling. Okay.\n我(滚动视图)开始滚动的事件了.\n\n126\n00:06:09,095 --> 00:06:12,929\nOr the person zoomed into this zoom scale. All right.\n或者是一个人缩放了一个缩放视图.\n\n127\n00:06:12,931 --> 00:06:15,498\nSo let's notify the controller cuz the controller might need\n那么这时候就需要通知 Controller 了,因为也许 Controller\n\n128\n00:06:15,500 --> 00:06:17,834\nto know that and react to that, okay.\n需要知道这些事件发生的时候,并且在这些事件发生时与View进行交互,\n\n129\n00:06:17,836 --> 00:06:20,936\nMaybe it effects the model when you zoom in or out.\n也许是在放大或缩小的过程中会影响到 Model,\n\n130\n00:06:20,938 --> 00:06:23,605\nAlso maybe the view like the scroll view needs to make sure\n也许一些视图(如滚动视图)需要知道其是否能\n\n131\n00:06:23,607 --> 00:06:26,875\nit's okay to do something, like if the scroll view says\n做一些操作,如一个滚动视图需要知道\n\n132\n00:06:26,877 --> 00:06:29,377\nshould I allow vertical scrolling right now?\n是否能在垂直方向上滚动?\n\n133\n00:06:29,379 --> 00:06:31,913\nMaybe it wants to ask the controller that. So you have\n有时候就是希望通过 Controller 来知道一些的信息.因此在\n\n134\n00:06:31,915 --> 00:06:35,483\na lot of messages that have words in them like should,\n方法设计过程中,很多方法都包含 should, \n\n135\n00:06:35,485 --> 00:06:40,187\nwill, and did, okay? That the minions wanna ask\nwill, did 等关键字.有些时候 View 希望通过\n\n136\n00:06:40,189 --> 00:06:42,589\nquestions of the controller involved with controller.\nController 获得一些信息,因此需要调用一些方法来获得.\n\n137\n00:06:42,591 --> 00:06:46,292\nOkay? So, [COUGH] This is done via what's called\n上面所说的那么多种情况都是通过一种叫\n\n138\n00:06:46,294 --> 00:06:48,795\na delegate. And we're gonna talk about delegation next\n委托的方式进行实现的.我们将在下周讲述委托的课程.\n\n139\n00:06:48,797 --> 00:06:51,897\nweek. And the word delegate is appropriate here because\n这里用委托这个词语是非常恰当的,\n\n140\n00:06:51,899 --> 00:06:53,899\nit's essentially the view's minions are delegating\n因为本质上来说 View 的\"仆从\"就是将\n\n141\n00:06:53,901 --> 00:06:57,803\nsome responsibility to the controller Okay. The way this\n一些职责交给 Controller 来实现.这种实现方式\n\n142\n00:06:57,805 --> 00:07:01,906\nis implemented is very simple. Delegate, the delegate is just\n也非常简单.委托通常是\n\n143\n00:07:01,908 --> 00:07:05,243\na property in the view and that property,\nView 的一个属性\n\n144\n00:07:05,245 --> 00:07:07,778\nyou might ask, what's the class of that property,\n也许你会问这个属性是什么类型(Class)的,\n\n145\n00:07:07,780 --> 00:07:12,616\nbecause the view doesn't know anything about the calculator\n因为 View 对计算器 Controller 一无所知.\n\n146\n00:07:12,618 --> 00:07:15,852\nview controller. The answer is, it's not gonna be a class.\n答案就是委托不是一个类型(Class),\n\n147\n00:07:15,854 --> 00:07:19,055\nIt's going to be what's called a protocol. Okay, and\n更恰当的说法是叫做协议.\n\n148\n00:07:19,057 --> 00:07:20,089\nwe're gonna talk about what protocols are.\n我们来说说什么叫协议.\n\n149\n00:07:20,091 --> 00:07:22,491\nProtocols are basically just a description of a bunch of\n协议就是一系列\n\n150\n00:07:22,493 --> 00:07:27,229\nmethods that the other guy promises to implement. Okay,\n希望别人来实现的方法的描述.\n\n151\n00:07:27,231 --> 00:07:28,864\nand so if you can imagine if the controller\n因此你可以设想一下如果一个 Controller\n\n152\n00:07:28,866 --> 00:07:31,299\nwould promise to implement these will, should, and did\n实现了带有 will, should,did 等关键字的方法后,\n\n153\n00:07:31,301 --> 00:07:33,768\nthings, then the viewer could talk to it even if the view\nView 就可以通过委托通知 Controller,即使 View\n\n154\n00:07:33,770 --> 00:07:37,705\ndoesn't know what class it is. Okay, no similarly There's\n不知道委托具体是什么类型(Class).\n\n155\n00:07:37,707 --> 00:07:40,741\nan important aspect of MVC which is the views,\n还有一个MVC中非常重要的方面,\n\n156\n00:07:40,743 --> 00:07:45,545\nokay, the view can not own the data they are displaying. Now,\n就是任何视图都不能包含他们所展示的数据(Model).\n\n157\n00:07:45,547 --> 00:07:47,881\nhow are they going to display it if they don't own it?\n那么在没有拥有 Model 的情况下, View 是如何进行展现的?\n\n158\n00:07:47,883 --> 00:07:50,650\nWell, they're going to ask for it from the controller all\n它们总是通过询问 Controller\n\n159\n00:07:50,652 --> 00:07:52,885\nthe time and the controller is going to get it from\n而 Controller 从 Model 中获得数据.\n\n160\n00:07:52,887 --> 00:07:56,689\nthe model. Okay, so that's another kind of protocol but\n除了上面所述的协议外,还有另一种\n\n161\n00:07:56,691 --> 00:07:57,422\ninstead of will did and\n不含有关键字 will, did, 和 should\n\n162\n00:07:57,424 --> 00:08:00,525\nshould you've got messages in that protocol like give\n关键字的协议, 主要是通过协议来获得\n\n163\n00:08:00,527 --> 00:08:03,594\nme the data at this location and how many pieces of data\n某个位置的数据或者是数据的总数等.\n\n164\n00:08:03,596 --> 00:08:06,997\nare there, okay? Things that are asking about the data so\n通过这些协议 View 可以\n\n165\n00:08:06,999 --> 00:08:09,366\nthe viewer can figure out what's going on and\n获得需要显示的数据以及\n\n166\n00:08:09,368 --> 00:08:13,103\ndisplay it, okay. And that's also done with delegation,\n根据数据来决定如何显示, 而这也是通过委托的方式来实现\n\n167\n00:08:13,105 --> 00:08:16,706\nalthough we call that Delegate the Data Source. Okay, so\n但是我们称这些委托为数据源(Data Source).\n\n168\n00:08:16,708 --> 00:08:19,308\nthere'd be another property on some views called\n因此在一些View中也存在着\n\n169\n00:08:19,310 --> 00:08:22,878\nthe Data Source, which is this protocol based pointer,\n数据源的属性,并且是该数据类型的指针.\n\n170\n00:08:22,880 --> 00:08:23,812\nbasically, to another object and\n通过设置其他对象或\n\n171\n00:08:23,814 --> 00:08:27,849\nthe controller sets itself as that so it can get involved.\nController 为数据源, 这样 View 就能调用该数据源的方法.\n\n172\n00:08:27,851 --> 00:08:29,784\nAnd providing the data for the view.\n这样同时也就能为 View 提供显示的数据.\n\n173\n00:08:29,786 --> 00:08:32,320\nKay? So those are the ways that the view can communicate\n因此这就是我们所说的 View 到 Controller 的交互.\n\n174\n00:08:32,322 --> 00:08:34,588\nto the controller. You can see they're all pretty defined,\n你可以看到他们都是定义好的方法\n\n175\n00:08:34,590 --> 00:08:37,524\nwell-defined ways they're not just open ended.\n而不是完全开放随便定义的.\n\n176\n00:08:37,526 --> 00:08:40,827\nMkay? Now, this leads to a situation where\n这就导致了 Controller 的任务可以\n\n177\n00:08:40,829 --> 00:08:45,165\nthe controller's job can be described as interpreting and\n描述为\"为了 View 解释和\n\n178\n00:08:45,167 --> 00:08:49,335\nformatting the model data for the view. Okay.\n格式化 Model 的数据\"\n\n179\n00:08:49,337 --> 00:08:52,538\nIt also interprets view input for the model. So\n同时也可以为了 Model 而处理通过 View 的输入.\n\n180\n00:08:52,540 --> 00:08:53,939\nit's an interpreter between both. That it,\n因此 Controller 是一个类似 Model 和 View 的翻译人员一样.\n\n181\n00:08:53,941 --> 00:08:56,942\ncontroller job so that's really where all your UI logic\n因此可以看出 Controller 的任务主要处理界面上的逻辑\n\n182\n00:08:56,944 --> 00:09:00,211\nis in there. Okay, how bout the model?\n那么对于 Model 到 Controller 的交互呢?\n\n183\n00:09:00,213 --> 00:09:02,847\nCan it talk directly to the controller?\n它能直接调用 Controller 的方法吗?\n\n184\n00:09:02,849 --> 00:09:07,084\nAbsolutely not because the controller is\n当然不可以!因为 Controller 是用来处理\n\n185\n00:09:07,086 --> 00:09:08,252\nyour UI logic.\n你界面上的逻辑的.\n\n186\n00:09:08,254 --> 00:09:11,421\nThe model is UI independent. So there's absolutely no way\n而 Model 是相对于界面完全独立的.因此 Model 不能\n\n187\n00:09:11,423 --> 00:09:13,957\nthe model could have anything to say to the controller.\n直接调用Controller里面的行为和变量.\n\n188\n00:09:13,959 --> 00:09:17,126\nHowever, what happens if the model,\n那么当Model的数据变化的时候,\n\n189\n00:09:17,128 --> 00:09:20,830\nwhich is UI independent, has some data that changes,\n如何通知界面数据以及修改了?\n\n190\n00:09:20,832 --> 00:09:24,133\nokay? So it's maybe the model is representing data on\n例如 Model 里面是用来表现网络上的数据.\n\n191\n00:09:24,135 --> 00:09:26,435\na network. In some ways change is gonna be on the network and\n有时候通过网络得知数据变化了.\n\n192\n00:09:26,437 --> 00:09:29,471\nit's changing. How does the model let the controller know?\n那么如何通知 Controller ?\n\n193\n00:09:29,473 --> 00:09:33,808\nWell, to do this we use what we call a radio station model,\n为了实现这个,我们采用广播的形式\n\n194\n00:09:33,810 --> 00:09:37,111\nokay? So the radio station is just a thing that\n而广播就是通过\n\n195\n00:09:37,113 --> 00:09:38,512\nthe model can set up,\nModel 自己来完成广播的机制\n\n196\n00:09:38,514 --> 00:09:39,546\nset up its own radio station.\n将 Model 自己设立为广播中心.\n\n197\n00:09:39,548 --> 00:09:41,915\nAnd it broadcasts on that radio station whenever,\n然后通过发送广播,通知那些对数据变化\n\n198\n00:09:41,917 --> 00:09:43,883\nwhenever anything interesting happens. Okay,\n有监听的广播站.\n\n199\n00:09:43,885 --> 00:09:47,987\nand then the controller just tunes in to that station. So\n然后将 Controller 设置成接收广播的设备.\n\n200\n00:09:47,989 --> 00:09:49,755\nthe model is not really talking to the controller.\n因此可以看出 Model 并不会直接对 Controller 进行通知.\n\n201\n00:09:49,757 --> 00:09:52,190\nIt's just talking to anyone who wants to know.\n它只是告诉那些想知道的对象.\n\n202\n00:09:52,192 --> 00:09:54,826\nWhat's going on in the model. Now all that communication on\n那么 Model 的\"广播\"是如何实现的呢? 所有通过广播中心\n\n203\n00:09:54,828 --> 00:09:57,762\nthat rad, radio station since it's done by the model has\n的形式,而不直接与界面打交道.\n\n204\n00:09:57,764 --> 00:10:00,931\nnothing to do with UI. It's about the data in the model.\n而所有的广播都是建立在Model的数据基础上,\n\n205\n00:10:00,933 --> 00:10:03,701\nI have new data, my data changed, those kind of\n例如我有一个新的数据,我的数据修改了, 这些事件\n\n206\n00:10:03,703 --> 00:10:07,070\nmessages are going out on this radio station, okay?\n都是通过广播中心发送出去.\n\n207\n00:10:07,072 --> 00:10:11,474\nNow other greater stations can be worked between other camps\n或许有人想是否可以在非 Model 和 Controller 的\n\n208\n00:10:11,476 --> 00:10:12,942\nbesides the model and the controller, and\n其他\"阵营\"之间\n\n209\n00:10:12,944 --> 00:10:15,678\nsome have asked, hey, can I just create a view that tunes\n建立通知机制,例如在 View 与 Model之间\n\n210\n00:10:15,680 --> 00:10:18,213\ninto the model directly, and short circuit the controller?\n直接建立广播的机制, 或者是直接绕过 Controller 的形式?\n\n211\n00:10:18,215 --> 00:10:20,849\nAnd the answer is no, you don't wanna do it that way.\n当然是不行, 不建议这样做.\n\n212\n00:10:20,851 --> 00:10:23,018\nOkay? You would want to have the controller tuning in\n你最好在 Controller 和 Model 之间建立管道.\n\n213\n00:10:23,020 --> 00:10:24,719\nto the model. And having the controller set up\n然后通过 Controller 来控制 View \n\n214\n00:10:24,721 --> 00:10:26,487\nthis generic view thing to display the data.\n是如何展示数据的.\n\n215\n00:10:26,489 --> 00:10:28,989\nQuestion? [INAUDIBLE] Standpoint, it's easy to\n提问:关于什么是\n\n216\n00:10:28,991 --> 00:10:33,126\nunderstand the controller view log model just like your idea\nController 和 View很容易理解, 而对于 Model 只是一个概念,\n\n217\n00:10:33,128 --> 00:10:36,696\nof how this things implemented in the software?\n那么如何在软件中实现 Model ?\n\n218\n00:10:36,698 --> 00:10:37,930\n>> So the question is, so\n这位同学提的问题是:\n\n219\n00:10:37,932 --> 00:10:40,666\nit's easy to understand what the controller and\n关于 Controller 和 View\n\n220\n00:10:40,668 --> 00:10:42,835\nview are, they're displaying the UI.\n是什么很容易理解,因为他们是直接展示在界面上的.\n\n221\n00:10:42,837 --> 00:10:45,537\nThe model is less easy to kinda conceptualize,\n而 Model 却更像是一个概念性的东西,\n\n222\n00:10:45,539 --> 00:10:49,040\nwhat that is, so what is the model? Really the model\n那么具体什么是 Model呢?\n\n223\n00:10:49,042 --> 00:10:51,976\nit takes a little more design but to design the model you\n关于 Model 你需要进行一些设计, 但是设计 Model\n\n224\n00:10:51,978 --> 00:10:56,080\nhave to think about what is it my app does fundamentally,\n需要你想清楚你的程序在本质上是关于什么的,\n\n225\n00:10:56,082 --> 00:10:58,549\nindependent of how it would be displayed. Like imagine I\n而不是关于你的程序在界面上该如何展示. 例如想想\n\n226\n00:10:58,551 --> 00:11:01,785\nwanted a calculator and had a command line interface where I\n我希望完成一个计算器, 而计算器通过命令行来实现,\n\n227\n00:11:01,787 --> 00:11:03,420\ncould type five times three equals and\n当如输入5 乘以 3 等于的时候,\n\n228\n00:11:03,422 --> 00:11:07,290\nit would work. Okay, well that's a user interface but\nModel 就发挥作用了. 它更偏向于计算器的接口\n\n229\n00:11:07,292 --> 00:11:09,458\nthe calculation, the actual multiplication and stuff,\n并且所有的计算和运算符都\n\n230\n00:11:09,460 --> 00:11:12,428\nthat would be in the model. So the model is more about\n将存储在这个 Model. 所以 Model 更像是\n\n231\n00:11:12,430 --> 00:11:14,363\ntrying to understand what it is your application does,\n让我们知道程序是做什么的, \n\n232\n00:11:14,365 --> 00:11:17,332\nnot how it's displayed. That's the separation that we have to\n而不是它是如何进行展示的. 这就是为什么我们必须\n\n233\n00:11:17,334 --> 00:11:18,800\ndo in this design. >> So it's\n将进行划分模块的原因.\n\n234\n00:11:18,802 --> 00:11:20,167\nkind of like an algorithm? >> Yeah,\n这个是不是有点像算法?\n\n235\n00:11:20,169 --> 00:11:23,303\nit's more of the algorithms, the data, the databases and\n那些算法,数据,数据库以及其他的一些\n\n236\n00:11:23,305 --> 00:11:25,505\nstuff like that are more in the model. And you'll see it\n都讲存储在 Model 中. 你也能根据之前的\n\n237\n00:11:25,507 --> 00:11:27,841\nby experience. we'll deal with the calculator today and\n经验来了解这一点. 我们今天将做一个计算器\n\n238\n00:11:27,843 --> 00:11:32,545\nyou'll get an example how that plays out. Okay.\n并且你们也将了解如何进行完成.\n\n239\n00:11:32,547 --> 00:11:37,249\nNow, this all only builds one MVC, okay? One MVC,\n接下来我们将写一个 MVC 的例子.\n\n240\n00:11:37,251 --> 00:11:42,154\ngenerally an iOS, controls one iPhone screen or\n一个通用的 iOS 的程序,\n\n241\n00:11:42,156 --> 00:11:44,923\nmaybe on an iPad it's two pieces or\n无论是在 iPhone, iPad\n\n242\n00:11:44,925 --> 00:11:47,859\nthree different pieces on the iPad screen. In other words\n或者是其他的设备, 都是有多个 MVC 部分构成的. 换一句话来说\n\n243\n00:11:47,861 --> 00:11:50,161\nthis is only controlling a little part of your app.\n一个 MVC 只是完成了一个程序的一部分.\n\n244\n00:11:50,163 --> 00:11:53,030\nTo build a real app we have to take these MVCs,\n为了完成一个程序,我们需要构建非常多的 MVC\n\n245\n00:11:53,032 --> 00:11:56,300\nmake a whole bunch of them and then combine them, okay?\n似的这些 MVC 完成我们的工作.\n\n246\n00:11:56,302 --> 00:12:00,103\nThat's how we make a big app, all right? Now, when we do\n这就是如何制作一个大的程序.当我们\n\n247\n00:12:00,105 --> 00:12:03,873\nthat, it, it's still important that the communication is well\n制作一个程序的时候, 在 MVC 之间定义一个良好的交互\n\n248\n00:12:03,875 --> 00:12:09,178\ndefined and basically the MVC, an MVC can only serve as\n是非常重要的, 并且有的时候一个 MVC 是为了\n\n249\n00:12:09,180 --> 00:12:12,882\npart of the view of another MVC, okay?\n另外一个 MVC 服务的.\n\n250\n00:12:12,884 --> 00:12:14,616\nDo you see how this is arranged up here?\n大家看看上图中的是如何进行排列的.\n\n251\n00:12:14,618 --> 00:12:17,219\nIf you look at any of the purple controllers up there\n如果你看到图中紫色的 Controller 的,\n\n252\n00:12:17,221 --> 00:12:20,221\nyou notice that any arrow they have to another MVC\n你将会注意到有很多绿色的线条指向其他的 MVC,\n\n253\n00:12:20,223 --> 00:12:24,225\ngoes out that view side, okay? So we always wanna\n代表着跳转到其他视图.  我们可以认为\n\n254\n00:12:24,227 --> 00:12:26,961\nthink of these MVCs as part of the view of another MVC.\n这些 MVC 是另外一些 MVC 的一部分.\n\n255\n00:12:26,963 --> 00:12:30,397\nAnd there are some MVCs like tab bar controller that's\n例如像苹果官方提供一个典型的 MVC —— UITabBarController.\n\n256\n00:12:30,399 --> 00:12:33,533\nan MVC that's provider iOS. Where you might have three or\n它将会将3-4个 MVC 作为自己的子视图.\n\n257\n00:12:33,535 --> 00:12:37,570\nfour other MVCs as part of its view. And those are the things\n这些视图会\n\n258\n00:12:37,572 --> 00:12:39,872\nwhen you press on the tabs at the bottom,\n在你点击下方的按钮时,\n\n259\n00:12:39,874 --> 00:12:41,374\nyou see a different MVC, right.\n进行切换不同的 MVC.\n\n260\n00:12:41,376 --> 00:12:45,344\nSo, that's what we built app at four MVCs let say,\n当我们为用整个 MVC 时,将会有4个 MVC,\n\n261\n00:12:45,346 --> 00:12:47,546\none of them is the top level tab bar controller.\n而且中一个会显示在界面上,\n\n262\n00:12:47,548 --> 00:12:49,748\nAnd then we have let say, three other MVCs.\n而其他三个将不会展示在界面上.\n\n263\n00:12:49,750 --> 00:12:52,850\nAnd those three MVCs might do completely independent things\n而这些 MVC 可能作者完全没有关联的事情,\n\n264\n00:12:52,852 --> 00:12:56,754\nand as we build this we really want each MVC to be completely\n当我们这样做时,我们希望每一个 MVC 都能完全完成自己部分的功能.\n\n265\n00:12:56,756 --> 00:12:58,355\nself-contained, just like when we design\n就如我们设计一个对象,\n\n266\n00:12:58,357 --> 00:13:00,624\nobjects we want them to be completely self-contained. We\n我们希望他能完成他自己部分的功能一样,\n\n267\n00:13:00,626 --> 00:13:02,959\ndon't want them reaching into the internal implementations\n我们不希望这些对象能深入了解其他对象的内部实现.\n\n268\n00:13:02,961 --> 00:13:06,295\nof other objects, right? So and sometimes we're building\n就如同我们设计\n\n269\n00:13:06,297 --> 00:13:09,665\nan object orient system here out of MVCs as well.\n面向对象系统一样,我们提出了 MVC 的概念.\n\n270\n00:13:09,667 --> 00:13:11,867\nOkay, now you'll see how all this works in week three.\n我们将在第三周展示这些事如何进行工作的,\n\n271\n00:13:11,869 --> 00:13:15,404\nWe'll start doing multiple MVCs and it'll all make sense.\n并且我们将开始使用一些 MVC 完成我们的程序.\n\n272\n00:13:15,539 --> 00:13:18,006\nOkay, one thing we don't wanna do of course is\n而我们当然不希望所完成的\n\n273\n00:13:18,008 --> 00:13:20,374\nbuild something when MVCs are [LAUGH] not working together.\nMVC 没办法很好的完成我们的程序.\n\n274\n00:13:20,376 --> 00:13:21,875\nIf these arrows start going in every which\n如果这些线条指向各个\n\n275\n00:13:21,877 --> 00:13:24,044\nway direction then there's gonna be now way to understand\n方向,并且一旦指向的方向变得复杂\n\n276\n00:13:24,046 --> 00:13:26,513\nhow your app works once it gets to a certain complexity.\n那么我们就不可能理解你的程序是如何进行工作的.\n\n277\n00:13:26,515 --> 00:13:28,614\nIt's just gonna be beyond your comprehension.\n那么它将超出你的理解能力.\n\n278\n00:13:28,616 --> 00:13:32,918\nOkay, so, we don't want this. This is bad. All right,\n这并不是我们想要的,这也是不好的设计.\n\n279\n00:13:32,920 --> 00:13:35,721\nso the demo I'm gonna dive right into here.\n所以我们深入写出一个 Demo.\n\n280\n00:13:35,723 --> 00:13:37,155\nAgain, this is a slide you can look at later,\n这个幻灯片你可以之后再回来查看,\n\n281\n00:13:37,157 --> 00:13:39,891\nimportant things that I'm gonna cover in this demo.\n重要的是我们将要开始封装这个 Demo.\n\n282\n00:13:39,893 --> 00:13:42,727\nCuz I'm not coming back to the slide so let me summarize,\n而之后也不在返回这张幻灯片,所以让我们来大概总结一下\n\n283\n00:13:42,729 --> 00:13:46,764\nwhat's coming up? On Friday, we do have this debugging,\n幻灯片里面的内容. 在周五, 我们将会有调试的课程.\n\n284\n00:13:46,766 --> 00:13:49,667\nsession. It's at 1:30 in this room,\n周五下午一点半,在这间教室.\n\n285\n00:13:49,669 --> 00:13:52,235\nokay? I highly recommend you go to that,\n我强烈建议你们来听.\n\n286\n00:13:52,237 --> 00:13:54,437\nespecially if you've never done debugging in Xcode,\n特别是针对那些没有使用过 Xcode 进行调试的同学,\n\n287\n00:13:54,439 --> 00:13:57,640\ncuz you'll kinda be wondering how the heck it all works\n因为你可能想要了解它是如何进行工作的.\n\n288\n00:13:57,642 --> 00:14:00,910\notherwise. Next Monday we'll be talking about more Swift,\n另一方面,下周一我们将会深入了解 Swift\n\n289\n00:14:00,912 --> 00:14:03,012\nthat's when your first reading assignment is due and\n你的第一个阅读作业即将到期,\n\n290\n00:14:03,014 --> 00:14:04,212\nyour second reading assignment will go out.\n而在你的第二次阅读作业也将要开始了.\n\n291\n00:14:04,214 --> 00:14:07,282\nAnd then next Wednesday we're gonna start about talking\n并且在下周三,我们将开始了解\n\n292\n00:14:07,284 --> 00:14:08,116\nabout custom drawing in iOS.\n如何在iOS中自定义绘图.\n\n293\n00:14:08,118 --> 00:14:11,585\nWhat if we wanna not just use a button and a, and a label,\n例如我们不想用系统自带的按钮或者标签\n\n294\n00:14:11,587 --> 00:14:14,188\nbut we wanna draw our own stuff? And that's when\n而是希望自己绘制出自己想要的控件.\n\n295\n00:14:14,190 --> 00:14:16,957\nprogramming assignment one will be due before lecture and\n当我们编程作业也即将在课程结束前到期,\n\n296\n00:14:16,959 --> 00:14:21,061\nprogramming assignment two will go out after lecture.\n而我们的第二次编程作业也将在课程结束后布置.\n\n297\n00:14:21,063 --> 00:14:22,395\nOkay? Any questions,\n还有什么问题吗?\n\n298\n00:14:22,397 --> 00:14:26,899\nyou all ready to jump in this demo? All righty, here we go,\n你们准备好开始今天的 Demo 了吗?那我们开始吧.\n\n299\n00:14:26,901 --> 00:14:32,271\nI'm just gonna pick up right where we left off with\n我们将在上次开发的基础上\n\n300\n00:14:32,273 --> 00:14:35,240\nI'm gonna go to developer here as our calculator, all right.\n继续完成我们的计算器开发.\n\n301\n00:14:35,242 --> 00:14:36,741\nI'm gonna, when I wanna relaunch it,\n首先,当我想重新运行它时,\n\n302\n00:14:36,743 --> 00:14:41,212\nI could just launch and get the splash screen here. And\n我可以通过 Xcode 的启动页来启动.\n\n303\n00:14:41,214 --> 00:14:44,648\nthen, click on this to open it and here it is and\n点击我们的项目来打开.\n\n304\n00:14:44,650 --> 00:14:47,618\nthe, before, if you remember where we were, we only had\n如果你还记得我们上节讲到哪, 应该记得我们上节\n\n305\n00:14:47,620 --> 00:14:52,155\na pi button and then the keypad. That was great and now\n有了一个π的按钮和一个数字键盘. 我们接下来\n\n306\n00:14:52,157 --> 00:14:54,624\nwe wanna add more buttons, and that's what we're going to do.\n将添加更多的按钮, 将完成更多的功能.\n\n307\n00:14:54,626 --> 00:14:56,259\nWe're gonna add more operations and\n我们将添加更多的功能,\n\n308\n00:14:56,261 --> 00:14:59,161\nmore sophisticated operations, like multiplying and\n一些复杂的计算, 如乘法\n\n309\n00:14:59,163 --> 00:14:59,895\nthings like that.\n等操作.\n\n310\n00:14:59,897 --> 00:15:02,731\nBefore I do that I wanna talk a little bit about a feature\n在开始之前,我先说一个 Swift 的特性,\n\n311\n00:15:02,733 --> 00:15:06,368\nin Swift that can really make your code read a lot better.\n一个能让你的代码可读性更好的特性.\n\n312\n00:15:06,370 --> 00:15:09,537\nYou notice here that we have this type conversion.\n你可能注意到了这里有一个类型转换,\n\n313\n00:15:09,539 --> 00:15:12,373\nString and pi, right? Where when the pi button gets\n讲一个π的数值转换成 String 类型.\n\n314\n00:15:12,375 --> 00:15:15,909\npressed, we have to convert pi to a double which is a string.\n当我们点击π按钮时,我们将一个 Double 类型的π转换成 String 类型\n\n315\n00:15:15,911 --> 00:15:18,879\nWell if I think ahead about all the operations I'm gonna\n那么如果我考虑到将来对于计算器来说,所有的操作数\n\n316\n00:15:18,881 --> 00:15:21,915\nwanna add to my calculator there all doubles,\n我们都讲采用 Double\n\n317\n00:15:21,917 --> 00:15:24,217\neverything is doubles, not strings, okay?\n所有都用 Double 的数值,而不是 String 的类型.\n\n318\n00:15:24,219 --> 00:15:26,585\nSo am I really gonna have for all these operations,\n那么我们有必要将这些操作符\n\n319\n00:15:26,587 --> 00:15:29,054\nall kinds of converting back and forth between strings and\n在 Double 和 String 之间转来转去吗?\n\n320\n00:15:29,056 --> 00:15:32,457\ndoubles as I try to put the results into the display or\n例如将结果展示在界面上或者\n\n321\n00:15:32,459 --> 00:15:34,259\nget the number out of the display?\n从界面上获得数值?\n\n322\n00:15:34,261 --> 00:15:36,127\nThat is gonna end up being really tedious,\n如果不断这样做的话,那么将会有非常多冗余的代码.\n\n323\n00:15:36,129 --> 00:15:38,696\nokay, and it's gonna make my code kind of a mess,\n它会让我的代码看起来很混乱,\n\n324\n00:15:38,698 --> 00:15:40,330\nlots of type conversions back and forth.\n因为有非常多的类型转换的代码.\n\n325\n00:15:40,332 --> 00:15:45,168\nWouldn't it be cool if I had a var called Display Value which\n如果有一个叫做 displayValue 的属性,\n\n326\n00:15:45,170 --> 00:15:50,073\nwas a double, and this bar automatically tracked what was\n一个 Double 类型的属性,并且会监控到界面上的变化.\n\n327\n00:15:50,075 --> 00:15:52,608\nin that display? In other words if I ever got\n也就是说,如果我希望获得属性的值\n\n328\n00:15:52,610 --> 00:15:55,177\nthe value of this, it would be the value of the display\n我将通过界面上的字符串转换成一个\n\n329\n00:15:55,179 --> 00:15:57,746\nas a double. And if I ever set the value of this, it would\nDouble 类型的数值.而当我改变该变量的数值时,\n\n330\n00:15:57,748 --> 00:16:00,649\nset the display. Wouldn't that be cool? Right, that would\n界面也会跟着变化. 这不是非常便利吗? 这样会\n\n331\n00:16:00,651 --> 00:16:02,951\nmake all the rest of my code a lot easier because I would\n使我其余的代码更加容易读懂, 因为我总是在跟\n\n332\n00:16:02,953 --> 00:16:03,718\nbe all in double land and\n一个 Double 类型的数值打交道.\n\n333\n00:16:03,720 --> 00:16:05,653\nIs not having to be doing this string version?\n并且不用一个处理 String 的代码.\n\n334\n00:16:05,655 --> 00:16:08,188\nAnd the answer is we can absolutely do that kind of\n那么问题就是我们能不能有这样的属性,\n\n335\n00:16:08,190 --> 00:16:10,824\nvar, a var that tracks something else, okay? This\n一个可以监控某一值变化的属性?\n\n336\n00:16:10,826 --> 00:16:13,393\nvar, our user is in the middle of typing, is just stored.\n我们之前学的都是存储属性,\n\n337\n00:16:13,395 --> 00:16:15,828\nThat true false value is stored somewhere with this\n例如之前学过布尔类型的存储属性.\n\n338\n00:16:15,830 --> 00:16:19,265\nobject. This one, instead of being stored, it's going to be\n而今天说的是一个不同于存储属性,\n\n339\n00:16:19,267 --> 00:16:23,802\ncalculated, okay? And we call this a computed property. And\n而是一个通过计算获得的属性.我们通常都称其为计算属性.\n\n340\n00:16:23,804 --> 00:16:27,072\nwe do it by just putting curly braces after it, okay.\n我们只需要在属性后面添加一个花括号.\n\n341\n00:16:27,074 --> 00:16:28,006\nAnd inside this curly braces,\n并且在花括号内,\n\n342\n00:16:28,008 --> 00:16:29,974\nwe're gonna put some code to calculate\n我们添加对应的计算该属性值的代码,\n\n343\n00:16:29,976 --> 00:16:35,680\nthe value of this property. Both when we get it, okay. And\n当我们希望获得该属性值时,添加get关键字\n\n344\n00:16:35,682 --> 00:16:37,881\nwhen we set it. So, we have this get and\n当我们希望获得改变属性值时,添加 set 关键字.\n\n345\n00:16:37,883 --> 00:16:41,985\nset, keywords here. And inside here, we just put code to get\n在这里,我们只需要获得显示的值即可.\n\n346\n00:16:41,987 --> 00:16:45,021\nthe value of display value. And set is the code that gets\n而set的代码\n\n347\n00:16:45,023 --> 00:16:48,624\nexecuted when someone tries to set the value of this var.\n是用户想要改变该属性值时调用的代码.\n\n348\n00:16:48,626 --> 00:16:51,927\nOkay? Super simple. So, what's the implementation of this?\n非常简单吧. 那么这里的 get 方法该如何实现呢?\n\n349\n00:16:51,929 --> 00:16:55,164\nReally easy when someone tries to get the display value\n非常简单,只需要返回显示在界面上的数值,\n\n350\n00:16:55,166 --> 00:16:58,734\nI'm just going to return the display's text. Okay?\n首先我只返回界面上显示的文本\n\n351\n00:16:58,736 --> 00:17:03,938\nUnwrapped, but of course, this is a string. Right? Okay? And\n然后unwarp它,但是这是一个 String 类型. 对吧?\n\n352\n00:17:03,940 --> 00:17:06,307\nthis is supposed to be returning a double. So,\n但是这里需要返回一个 Double 的数值.\n\n353\n00:17:06,309 --> 00:17:09,210\nI need to convert this string to a double. So, I'm gonna say\n所以我需要将 String 转换成 Double.\n\n354\n00:17:09,212 --> 00:17:15,416\ndouble. That, okay, now this is still not gonna work,\n那么我这里进行类型转换成 Double , 但是这里还是有错误.\n\n355\n00:17:15,418 --> 00:17:18,218\nokay? Why is that? Let's look at our error. It says\n为什么呢? 让我们看看错误信息.\n\n356\n00:17:18,220 --> 00:17:21,087\nthe value of optional double is not unwrapped. Look it's\n一个 Optional Double 并没有unwarp.  \n\n357\n00:17:21,089 --> 00:17:24,691\ntrying to unwrap this. Okay, that's really weird. See it's\n从界面可以看得出来,这里试图unwarp它.这个看起来非常奇怪.\n\n358\n00:17:24,693 --> 00:17:27,426\npointing an exclamation point at the end of this double.\n这里在强制转换后自动添加了一个感叹号.\n\n359\n00:17:27,428 --> 00:17:28,560\nI didn't have to do that down here.\n其实我完全没必要这么做.\n\n360\n00:17:28,562 --> 00:17:31,697\nWhen I converted from this Double to a string, I didn't\n这里当我将 Double 转换成 String 时,我没有\n\n361\n00:17:31,699 --> 00:17:36,134\nunwrap it. Why is this? I'm trying to create a double\n进行unwarp. 那么上面这里当我从一个 String 生成一个 Double 类型时\n\n362\n00:17:36,136 --> 00:17:37,168\nhere using this string.\n为什么需要unwarp?\n\n363\n00:17:37,170 --> 00:17:40,037\nWhy do you think this is returning an optional double\n为什么这里返回一个 Optional Double ,而不是\n\n364\n00:17:40,039 --> 00:17:44,641\ninstead of a double? >> Because it might not be\n一个 Double 类型? [学生回答:] 因为字符串\n\n365\n00:17:44,643 --> 00:17:45,275\nconvertible. >> Correct.\n可能不是一个数字. [白老头:] 答对了.\n\n366\n00:17:45,277 --> 00:17:48,878\nIt might not be convertible. Right? If I press hello in\n这里的值可能不是一个可以转换成 Double 类型的 String . 例如我这里输入 'Hello' .\n\n367\n00:17:48,880 --> 00:17:54,951\nthere as the string. Double of hello, eh, I don't know. Okay,\n将'hello'转换成Double, 不知道具体转换成什么.\n\n368\n00:17:54,953 --> 00:17:57,086\nnow again it could return zero or something else but\n如果出现这种情况,我们可以返回0或者其他的数值.\n\n369\n00:17:57,088 --> 00:17:59,755\nreally it wants to say, I don't know. I can't do it.\n这就代表着我不知道具体的数值是多少.\n\n370\n00:17:59,757 --> 00:18:02,591\nAnd the best way to do that is with an optional. So, some\n最好的方式就是返回一个 Optional 的类型.\n\n371\n00:18:02,593 --> 00:18:05,860\nconstructors. Okay? Some of these initializers for various\n对于一些构造器来说,\n\n372\n00:18:05,862 --> 00:18:10,431\nclasses can return optional versions of the thing.\n在创建实例的过程中可能会返回 Optianal 的类型.\n\n373\n00:18:10,433 --> 00:18:13,067\nIn the case where they can't necessarily create one for\n也就是说,他们却好必要参数来创建一个对象.\n\n374\n00:18:13,069 --> 00:18:14,935\nyou. Okay? So that's really kind of awesome.\n这是一个非常好的的特性.\n\n375\n00:18:14,937 --> 00:18:17,871\nSo let's go ahead and unwrap that. Okay now this would,\n我们继续,并且unwarp它.\n\n376\n00:18:17,873 --> 00:18:20,607\nagain, this would crash if we ever put hello in here, it's\n当我们在界面上显示 'hello' 时,这里就会产生奔溃.\n\n377\n00:18:20,609 --> 00:18:23,009\ngonna crash. So, we're kinda designing our codes assuming\n所以我们需要设计好我们的代码,\n\n378\n00:18:23,011 --> 00:18:26,679\nthis is always going to have a number. How about setting it?\n并且假设界面上总是显示数值. 那么如何进行设置它?\n\n379\n00:18:26,681 --> 00:18:30,115\nOkay? Here we want to set the display's text\n这里我们只需设置文本框的显示\n\n380\n00:18:30,117 --> 00:18:33,819\nequal to what the person is setting the display value to.\n设置成我们想要设置的值即可.\n\n381\n00:18:33,821 --> 00:18:36,755\nOkay? When someone sets the display values they're\n当我们设置 displayValue 的值为5后,\n\n382\n00:18:36,757 --> 00:18:39,924\ngoing to say in their code display value equals five,\n也就等于设置了文本框显示为5.\n\n383\n00:18:39,926 --> 00:18:44,295\nright? So, how do I get the five in here, in this set?\n那么我们如何设置文本框的数值为5呢?\n\n384\n00:18:44,297 --> 00:18:47,498\nAnd the answer is there's a special key word called new\n答案是使用一个叫做 newValue 的关键字.\n\n385\n00:18:47,500 --> 00:18:51,635\nvalue. Okay? This new value is going to be the double that\n这里的 newValue 是一个用户设置 Double类型\n\n386\n00:18:51,637 --> 00:18:56,973\nsomebody set. Okay? Display value equals something. Now,\ndisplayValue 的值也将 newValue.\n\n387\n00:18:56,975 --> 00:18:58,841\nI want to put this in display text, but, of course,\n接下来 newValue 传递 display 控件的文本,\n\n388\n00:18:58,843 --> 00:19:03,145\nthis what type is this right here? The double, right?\n那么这里的 newValue 是什么类型呢? Double 类型.\n\n389\n00:19:03,147 --> 00:19:05,047\nBecause they said display value equals something and\n因为他们想要设置 displayValue\n\n390\n00:19:05,049 --> 00:19:07,315\nit's a double. And this has got to be a string. So\n所以 newValue 就是一个 Double 类型. 而这里 display.text 需要传递一个 String 类型.\n\n391\n00:19:07,317 --> 00:19:11,986\nI've got to convert this to a string. Just like I did below.\n所以我需要将其转化为 String 类型.就像我下面所实现的.\n\n392\n00:19:11,988 --> 00:19:15,223\nThat, okay, can always convert a double to a string so\n因为总是能将 Double 转换成 String,\n\n393\n00:19:15,225 --> 00:19:17,324\nthere's no optional, stuff going on.\n所以这里就不会出现Optional的类型.\n\n394\n00:19:17,326 --> 00:19:22,129\nAnd that's it, okay. I've now invented a new property,\n这就是计算属性. 到这里我就新建了一个计算属性.\n\n395\n00:19:22,131 --> 00:19:25,065\nthat is calculated. And every time I ask for\n这样当我每次请求它的值的时候\n\n396\n00:19:25,067 --> 00:19:26,966\nits value I'm gonna get what's in the display's double.\n我讲从界面展示的文本框内获得一个 Double 的值.\n\n397\n00:19:26,968 --> 00:19:30,169\nAnd every time I set it, it's gonna set the display. Pretty\n而当我每次设置它的时候, 它将会将其显示在界面上.\n\n398\n00:19:30,171 --> 00:19:33,439\ncool? And it makes our code like down here a lot better.\n有了它能使我们的代码更简单.\n\n399\n00:19:33,441 --> 00:19:36,041\nInstead of having this go down here, we're just gonna say\n接下来替换这里的代码,只需\n\n400\n00:19:36,043 --> 00:19:41,113\ndisplayValue = Pi, okay? We don't need to do this\n改成 displayValue = M_PI 即可. 我们不在需要\n\n401\n00:19:41,115 --> 00:19:44,449\ntype conversion in reference displayed text, okay?\n进行类型的转换了.\n\n402\n00:19:44,684 --> 00:19:47,985\nEveryone understand that? And, this is going to make it a lot\n大家都明白了吗? 通过添加计算属性, 让我们的代码更简单了.\n\n403\n00:19:47,987 --> 00:19:50,888\neasier to add new things. Let's add another property, or\n接下来让我们xib上添加一个新的\n\n404\n00:19:50,890 --> 00:19:55,125\na another, operation here. I'm gonna add square root, okay?\n按钮.添加一个根号操作.\n\n405\n00:19:55,127 --> 00:19:56,159\nSo let's go here into square root.\n让我们找找根号的字符.\n\n406\n00:19:56,161 --> 00:19:59,395\nThe square root symbol I'm gonna get from the edit.\n根号的字符我们能从Edit菜单下找到.\n\n407\n00:19:59,397 --> 00:20:02,431\nIf you go into edit menu of most Mac apps you'll see this\n在大部分Mac的程序里,你都能在 Edit 菜单下找到\n\n408\n00:20:02,433 --> 00:20:03,999\nemoji and symbols thing at the bottom,\nEmoji & Symbols 的子菜单.\n\n409\n00:20:04,001 --> 00:20:07,569\nbrings up this, window or you can have a lot of emoji, but\n这个子菜单会弹出一个弹出框,里面包含 Emoji 表情\n\n410\n00:20:07,571 --> 00:20:11,840\nyou can also have math symbols and, down here here's square\n当然你也可以在这里找到数学符号, 当然包括了根号.\n\n411\n00:20:11,842 --> 00:20:13,574\nroot. Just the square root symbol, okay.\n这里就选中这个根号即可.\n\n412\n00:20:13,576 --> 00:20:17,545\nSo I'm gonna put the square root symbol on this button.\n并且将这个根号字符显示到按钮上.\n\n413\n00:20:17,747 --> 00:20:22,883\nSquare root. Okay? And, then it's already wired\n并且当我鼠标放在\n\n414\n00:20:22,885 --> 00:20:25,719\nup if I hold over here you can see it's hooked up because I\n这个\"+\"号这里, 你会发现新的按钮已经和代码绑定了.\n\n415\n00:20:25,721 --> 00:20:29,155\ncopy and pasted the pi button. We can see it's okay here\n因为我是通过拷贝π按钮的.同时你可以看到它并没有\n\n416\n00:20:29,157 --> 00:20:31,457\nbecause I didn't copy and paste the digit button.\n跟数字按钮绑定在一起,因为复制数字按钮产生的.\n\n417\n00:20:31,459 --> 00:20:34,159\nIf I right-click on it we can see that it's only gonna send\n当我在这里点击右键,我们能看到它和哪个\n\n418\n00:20:34,161 --> 00:20:37,362\nperform operation, right, so that's all good. And\n方法管理在一起了.\n\n419\n00:20:37,364 --> 00:20:40,765\nall I need to do here is say if the mathematical\n我这里所要做的就是\n\n420\n00:20:40,767 --> 00:20:45,536\nsymbol equals, that square root thing then the display\n点击了根号按钮的时候, 界面显示\n\n421\n00:20:45,538 --> 00:20:50,741\nvalue equals the square root of the display value.\n数值变成其根号的数值.\n\n422\n00:20:52,078 --> 00:20:54,678\nOkay? So, you can see that this code is really nice.\n可以看得出来, 代码方面更加简洁了.\n\n423\n00:20:54,680 --> 00:20:57,247\nIf I didn't have that I would have had to get the display\n如果没有计算变量, 我就需要\n\n424\n00:20:57,249 --> 00:21:00,950\ntext, convert it to a double, do the square root, convert it\n将界面显示转换成 Double, 然后计算出根号值\n\n425\n00:21:00,952 --> 00:21:03,786\nback to a string, and put it back into display text.\n然后转换成 String 后, 再显示回界面.\n\n426\n00:21:03,788 --> 00:21:05,287\nSee how that would have been a mess? Okay?\n可以想象一下多麻烦.\n\n427\n00:21:05,289 --> 00:21:08,690\nAnd, this is only just the very first one I added.\n这只是我添加的第一个计算属性.\n\n428\n00:21:08,692 --> 00:21:11,793\nIf we add a whole bunch more it's gonna be even more and\n如果我们有一堆的计算按钮,\n\n429\n00:21:11,795 --> 00:21:13,394\nmore leverage to have this thing. But\n它会提高非常多的效率\n\n430\n00:21:13,396 --> 00:21:15,996\nmostly I'm showing you this because I want you to see what\n但是这里我主要是为了给你们介绍\n\n431\n00:21:15,998 --> 00:21:16,864\ncomputed properties look like.\n什么叫做计算属性.\n\n432\n00:21:16,866 --> 00:21:19,733\nWe use them all the time in Swift, and we're going to use\n我们在用 Swift 的过程中经常用到它, 我们也将在这个例子\n\n433\n00:21:19,735 --> 00:21:22,335\nthem yet again in this demo, and you should get comfortable\n中不断的用到它, 你应该明白\n\n434\n00:21:22,337 --> 00:21:24,837\nwith the fact that not all your properties are stored\n并不是所有的属性都是存储属性\n\n435\n00:21:24,839 --> 00:21:28,240\nsome of them might be computed like this. All right.\n有一些属性是计算属性.\n\n436\n00:21:28,242 --> 00:21:33,212\nI want to add more operations now, but I have to be careful\n接下来我想添加更多的操作, 但是需要注意的是\n\n437\n00:21:33,214 --> 00:21:37,182\nhere because this code really does not belong in my\n这些所有的计算的代码不应该属于 Controller\n\n438\n00:21:37,184 --> 00:21:42,220\ncontroller, okay? Because this is the code of what my app is.\n因为这些运算的代码正是我程序所完成的事情.\n\n439\n00:21:42,222 --> 00:21:45,456\nIt's a calculator and I'm doing calculations here. So,\n这个程序完成的是一个计算器,而这里所完成的就是计算的功能.\n\n440\n00:21:45,458 --> 00:21:48,759\nthis needs to move into a model class.\n所以需要将这些代码移到 Model 的类中.\n\n441\n00:21:48,761 --> 00:21:51,395\nOkay? So now, it's time to do MBC here and\n那么是时候来开始用 MVC 了, \n\n442\n00:21:51,397 --> 00:21:54,531\nmove this stuff into a model class. So,\n并且将这里的运算的代码移到一个 Model 的类中.\n\n443\n00:21:54,533 --> 00:21:57,934\nwhat's our model class gonna look like? Let's create it and\n那么 Model 的类该如何实现呢?  首先先创建它,\n\n444\n00:21:57,936 --> 00:22:01,237\nkinda design in an API for it and then we'll get back and\n然后像设计 API 一样, 最后我们在这里使用它.\n\n445\n00:22:01,239 --> 00:22:04,106\nuse it here. Okay? So, to create it, okay, in\n那么我们开始创建它吧.\n\n446\n00:22:04,108 --> 00:22:07,376\nfact to create any new file in x code, you're gonna go file,\n为了在 Xcode 中创建一个新的文件, 我们可以通过\n\n447\n00:22:07,378 --> 00:22:10,846\nnew File. Okay? File, new file. And when you go here,\nFile 菜单下的 New 子菜单下的 File来创建. 当你点击后,\n\n448\n00:22:10,848 --> 00:22:12,981\nit's going to say, what kind of file do you want to create?\n将会弹出一个弹出框询问想要创建什么文件类型.\n\n449\n00:22:12,983 --> 00:22:16,784\nAnd of course, we want to create an iOS Source file.\n这里我们当然是创建一个 iOS 的源文件.\n\n450\n00:22:16,786 --> 00:22:18,819\nOkay? Not watch OS or something.\n而不是 watch OS 或者是其他的文件.\n\n451\n00:22:18,821 --> 00:22:21,388\nAnd here we're going to create a Swift file. If we were\n然后选择源文件中的 Swift 文件. 如果想要\n\n452\n00:22:21,390 --> 00:22:24,658\ncreating a Cocoa Touch Class, like a new view controller,\n创建 UIViewController 之类的文件时,我们可以选 Cocoa Touch Class.\n\n453\n00:22:24,660 --> 00:22:27,394\nwe would go here. But if we're going to create just a model\n但是我们只想建一个 Model,\n\n454\n00:22:27,396 --> 00:22:29,896\nclass, we go here. So I'm going to double-click.\n所以我们这里选择 Swift 文件. 双击 Swift 文件 \n\n455\n00:22:29,898 --> 00:22:31,764\nIt's going to say where do you want to put this?\n接下来就是选择要将文件存在哪?\n\n456\n00:22:31,766 --> 00:22:34,099\nI'm going to put it in the same group, calculator,\n这里我存在同一个 Group 里, Calculator 的 Group\n\n457\n00:22:34,101 --> 00:22:36,034\nthat all my other swift files are in.\n所有的 Swift 文件都存在这里.\n\n458\n00:22:36,036 --> 00:22:37,602\nYou see, ViewController.swift there.\n可以看到 ViewController.swift 也存在着.\n\n459\n00:22:37,604 --> 00:22:40,805\nI'm going to call it calculator brain because it's\n命名文件为 CalculatorBrain\n\n460\n00:22:40,807 --> 00:22:42,573\ngoing to be the brain of our calculator.\n因为这将是所有运算的代码所在文件\n\n461\n00:22:42,575 --> 00:22:45,743\nIt's going to be the model for our calculator.\n并且是它就是我们计算器的 Model.\n\n462\n00:22:45,745 --> 00:22:49,546\nThen click create. Here it is right here. You can see that\n然后点击创建. 然后就展示创建的文件.\n\n463\n00:22:49,548 --> 00:22:51,948\nthe very first thing, it imports Foundation,\n你能看到文件中最开始就引入了 Foundation,\n\n464\n00:22:51,950 --> 00:22:56,686\nnot UI Kit. Never import UI Kit in a model file because\n而不是 UIKit. 永远不要在 Model 中引入UIKit,\n\n465\n00:22:56,688 --> 00:22:59,488\nthe model is UI independent. So it would never do that.\n因为 Model 是相对于界面独立的. 所以永远不要这样做.\n\n466\n00:22:59,490 --> 00:23:02,324\nIf you find yourself importing UI Kit, you're doing it wrong.\n如果你发现你引入的 UIKit, 那么肯定是错误的.\n\n467\n00:23:02,326 --> 00:23:05,527\nOkay? So, Foundation is what we want. Foundation is that\nFoundation 正是我们所需要的. Foundation 是\n\n468\n00:23:05,529 --> 00:23:07,962\ncore services layer, kind of the basic stuff,\n基础的服务层, 提供基础的数据功能,\n\n469\n00:23:07,964 --> 00:23:11,032\nnon-UI. Base stuff. By the way, let\n而跟界面完全没关系. 顺带说一句,\n\n470\n00:23:11,034 --> 00:23:13,401\nme show you how you can put different things on each side.\n如何通过 Xcode 查看不同内容的文件呢?\n\n471\n00:23:13,403 --> 00:23:15,102\nSo I've got calculator running over here,\n在左边显示 Calculator 的 Model,\n\n472\n00:23:15,104 --> 00:23:17,804\nwhat if I wanna have my controller still be over here?\n那如何在右边显示 Controller 的内容呢?\n\n473\n00:23:17,806 --> 00:23:19,639\nAnd you do that with these things at the top. Okay?\n你只需要点击上边的这里.\n\n474\n00:23:19,641 --> 00:23:23,343\nThe top line here is actually changeable. You can pick\n上面的导航栏是可以变化. 你可以选择\n\n475\n00:23:23,345 --> 00:23:26,679\nother things to show. So, for example, I can go show my\n其他的内容来显示. 例如, 我可以显示我的\n\n476\n00:23:26,681 --> 00:23:29,515\ncontroller here. Okay, now I can have them both on\nController 的内容. 这样我就可以在同一屏幕里\n\n477\n00:23:29,517 --> 00:23:32,084\nscreen at the same. Which is kind of convenient, especially\n显示 Model 和 Controller 了. 非常的方便, \n\n478\n00:23:32,086 --> 00:23:34,619\nif I have a class that I'm using in another class. I can\n特别是那些我引用了其他类的情况下.\n\n479\n00:23:34,621 --> 00:23:37,989\nsee its API here, and use it over here. All right, so\n我能通过这种方法查看他的 API, 并且调用正确的方法.\n\n480\n00:23:37,991 --> 00:23:40,157\nI'm going to create a new class called Calculator Brain,\n因此我在这里创建一个新的 Class 取名为 CalculatorBrain,\n\n481\n00:23:40,159 --> 00:23:43,627\nand we know how to do that. Right? We know how to do that.\n就如同我们所熟悉的方式. \n\n482\n00:23:43,629 --> 00:23:48,131\nOkay, class Calculator Brain. What's its super class?\n通过使用 class 后面跟着 CalculatorBrain 即可. 那么它的父类是什么呢?\n\n483\n00:23:50,369 --> 00:23:53,002\nNo superclass, right? CalculatorBrain, this model,\n没有父类. CalculatorBrain 并没有\n\n484\n00:23:53,004 --> 00:23:54,136\nit doesn't inherit from anything.\n从任何类上继承.\n\n485\n00:23:54,138 --> 00:23:55,971\nIt doesn't need to inherit from anything, okay?\n它不需要继承任何一个类.\n\n486\n00:23:55,973 --> 00:23:58,440\nSo it's just a base class. All right, now let's\n它只是一个基础类. 那么我们现在来考虑考虑\n\n487\n00:23:58,442 --> 00:24:00,942\ntalk about what its API is. Everyone knows the phrase\n它的API吧. 大家都知道API的语法.\n\n488\n00:24:00,944 --> 00:24:03,611\nAPI, I hope. That means the interface through which we're\n这就意味着我们对于 CalculatorBrain 将跟着这些\n\n489\n00:24:03,613 --> 00:24:06,881\ngoing to be programming, using this, CalculatorBrain.\nAPI 来进行编程, 并且使用它.\n\n490\n00:24:06,883 --> 00:24:10,017\nIt's all the methods and properties in it.\n所有的方法和属性都在保存在这里. \n\n491\n00:24:10,019 --> 00:24:14,488\nSo, I'm gonna do a little function called setOperand,\n这里我先加一个名为 setOperand 的方法,\n\n492\n00:24:14,490 --> 00:24:18,191\nokay, which just takes a Double, okay? That's gonna be\n它的参数是 Double 类型.  这将是它的\n\n493\n00:24:18,193 --> 00:24:21,094\npart of it. So if I'm using my CalculatorBrain, I'm gonna set\n一部分. 当我使用 CalculatorBrain, 我需要设置一个\n\n494\n00:24:21,096 --> 00:24:24,330\nan operand. Then I'm gonna have another function in here,\n操作数. 这里再添加另一个方法,\n\n495\n00:24:24,332 --> 00:24:27,066\ncalled performOperation, which is gonna operate on\n命名为 performOperation, 用来计算操作数的.\n\n496\n00:24:27,068 --> 00:24:30,302\nthat operand. And the argument there is gonna be a String,\n该方法将接收一个 String 的参数,\n\n497\n00:24:30,304 --> 00:24:33,405\nwhich is the mathematical symbol, okay? And then lastly,\n一个用来数学操作符的参数. \n\n498\n00:24:33,407 --> 00:24:38,242\nI'm gonna have a var, which is the result of the operation,\n最后还有一个属性, 用来保存结果的操作数.\n\n499\n00:24:38,244 --> 00:24:39,677\nwhich is gonna be a Double.\n一个为 Double 类型的属性.\n\n500\n00:24:39,679 --> 00:24:43,681\nAnd I'm gonna do something interesting here, instead of\n我将在这里做一件有趣的事\n\n501\n00:24:43,683 --> 00:24:47,384\njust having this be a public var that could be set and got.\n我不会让这个公有变量同时拥有 get 和 set 方法\n\n502\n00:24:47,386 --> 00:24:49,953\nBecause the setting of this doesn't really make sense for\n因为对于使用 CalculatorBrain 的人来说\n\n503\n00:24:49,955 --> 00:24:51,854\nanyone using my CalculatorBrain to set this.\nset 方法实在没有什么意义\n\n504\n00:24:51,856 --> 00:24:55,558\nI set it internally, okay, because of performOperation.\n因为我只在 performOperation 的内部 set 它\n\n505\n00:24:55,560 --> 00:24:58,494\nSo I'm actually gonna make this computed and\n所以我会实际的去做运算，并\n\n506\n00:24:58,496 --> 00:25:01,229\nonly implement the get side of it, okay?\n实现在它的 get 方法里面\n\n507\n00:25:01,231 --> 00:25:02,864\nI'm not gonna implement this set, so\n我不会实现它的 set 方法\n\n508\n00:25:02,866 --> 00:25:05,833\nnow this becomes a read-only property. Do you, do you all\n所以现在它变成了一个只读属性\n\n509\n00:25:05,835 --> 00:25:09,637\nremember another a read-only property we used last time?\n你们还记得我们上次使用的另一个只读属性吗？\n\n510\n00:25:09,639 --> 00:25:12,940\nCurrent title in button, okay? So current title in button is\nButton 的 currentTitle\n\n511\n00:25:12,942 --> 00:25:16,476\na computed read-only property in button. That title, that\n它是 Button 中的一个可计算的只读属性\n\n512\n00:25:16,478 --> 00:25:18,545\ncurrent title, is probably gotten from a UI label or\ncurrentTitle 可能来自于一个 UI Label\n\n513\n00:25:18,547 --> 00:25:21,080\nsomething that the button is using to draw its title, okay?\n或者被 Button 用来绘制它的 title 的东西\n\n514\n00:25:21,082 --> 00:25:24,150\nIt comes from somewhere else, that's why it's computed,\n它是其它地方获取到的，所以它是一个可计算的属性\n\n515\n00:25:24,152 --> 00:25:27,019\nokay? So I'm gonna do the same thing here. So this is how you\n我在这里也将做同样的事情\n\n516\n00:25:27,021 --> 00:25:29,321\ncan make a property be read-only to the callers,\n你们也可以使用类似的方法来把属性设置成只读的\n\n517\n00:25:29,323 --> 00:25:33,692\nokay? Yeah. >> So can we use the get for\n[学生提问]\n\n518\n00:25:33,694 --> 00:25:35,893\ncomparison, not just for assignments,\n[学生提问]\n\n519\n00:25:35,895 --> 00:25:37,795\nlike with equal equal sign? >> Okay, so\n[学生提问]\n\n520\n00:25:37,797 --> 00:25:40,998\nthe question is, is the get used for comparison?\n问题是，在做比较的时候，会调用 get 方法吗？\n\n521\n00:25:41,000 --> 00:25:45,135\nWell, comparison is actually quite interesting in Swift.\nSwift 中的比较还是挺有趣的\n\n522\n00:25:45,137 --> 00:25:48,038\nThe equals equals operator is like a function, and\n== 运算符像一个函数\n\n523\n00:25:48,040 --> 00:25:50,139\nit takes those two sides as arguments.\n它把两边的东西当作参数\n\n524\n00:25:50,141 --> 00:25:53,342\nAnd those two sides have to implement certain methods\n如果两边的东西想要被比较\n\n525\n00:25:53,344 --> 00:25:54,843\nif they wanna be comparable, okay?\n就需要实现某些待定的方法\n\n526\n00:25:54,845 --> 00:25:57,979\nNow, we're not, we're not far enough along in terms of our\n现在我们还没有学习的那么深\n\n527\n00:25:57,981 --> 00:26:01,282\nunderstanding of Swift to see exactly how that works. But\n还没有理解到那种程度\n\n528\n00:26:01,284 --> 00:26:03,518\nthe answer to your question succinctly is no,\n但是你的问题的答案是不会\n\n529\n00:26:03,520 --> 00:26:06,053\nthe get really doesn't have anything to do with equality.\nget 方法与比较（==）无关\n\n530\n00:26:06,055 --> 00:26:09,590\nEquality is just a function that is different,\n比较是一个方法，这两者是不同的\n\n531\n00:26:09,592 --> 00:26:14,594\nokay? All right, so, I'm gonna return 0 for\n这里先 return 0\n\n532\n00:26:14,596 --> 00:26:18,832\nright now, okay? Just to get rid of my little, error there.\n先把这个错误提示给躲掉\n\n533\n00:26:18,834 --> 00:26:21,934\nBut eventually, we're gonna have to implement this,\n不过最终我们还是会实现这里\n\n534\n00:26:21,936 --> 00:26:22,735\ninternally and make it work.\n让它正确工作\n\n535\n00:26:22,737 --> 00:26:26,972\nNow, I wanna talk a little bit about APIs right here, okay?\n我想再谈论一些有关 API 的东西\n\n536\n00:26:26,974 --> 00:26:29,675\nSo far, every method and property we've done\n到目前为止，这个类中的每个方法和属性\n\n537\n00:26:29,677 --> 00:26:33,078\nin this whole class has been essentially public. Meaning,\n都是 public（公有） 的，意味着\n\n538\n00:26:33,080 --> 00:26:36,447\nany class can call any of the methods in any of the classes\n我们类中的所有方法都可以被其他类调用\n\n539\n00:26:36,449 --> 00:26:40,484\nwe created. For example, all of our controller vars,\n举个例子，controller 中的所有变量\n\n540\n00:26:40,486 --> 00:26:44,722\nokay, and functions could all be called by some other class.\n还有函数，都可以被其它类调用\n\n541\n00:26:44,724 --> 00:26:46,723\nNow, that's bad, okay, that's bad.\n这样处理不是太好\n\n542\n00:26:46,725 --> 00:26:47,891\nFor example, displayValue,\n例如 displayValue\n\n543\n00:26:47,893 --> 00:26:50,760\nwe wouldn't want some other class setting the displayValue\n我们不想让应用中的其它类通过这个 controller\n\n544\n00:26:50,762 --> 00:26:53,429\nin the calculators through this controller. Because we\n来修改 displayValue 的值\n\n545\n00:26:53,431 --> 00:26:56,832\nmanaged that displayValue by what our model calculates,\n因为我们通过我们的 model 计算的值来管理 displayValue\n\n546\n00:26:56,834 --> 00:26:59,067\nright? So this is internal implementation.\n所以这是内部的实现\n\n547\n00:26:59,069 --> 00:27:01,770\nIn fact, all of this is internal implementation or\n事实上，所有这些都是内部实现或控制的\n\n548\n00:27:01,772 --> 00:27:05,506\ncontrol. We do not want other classes to be able to call it,\n我们不想让其它类调用它\n\n549\n00:27:05,508 --> 00:27:09,944\nunlike these three, which are external, okay? They're, they,\n不像这里的三个，是外部的\n\n550\n00:27:09,946 --> 00:27:12,146\nwe want people calling these in CalculatorBrain.\n我们希望其它人在 CalculatorBrain 中调用它们\n\n551\n00:27:12,148 --> 00:27:13,747\nThat's how our CalculatorBrain works.\n因为 CalculatorBrain 就是这么工作的\n\n552\n00:27:13,749 --> 00:27:14,481\nIf people couldn't call this,\n如果不调用这几个方法\n\n553\n00:27:14,483 --> 00:27:16,315\nthey couldn't even use the CalculatorBrain.\nCalculatorBrain 就一点用都没有了\n\n554\n00:27:16,317 --> 00:27:19,051\nSo how do we specify that difference between something\n所以我们怎么来控制其他人\n\n555\n00:27:19,053 --> 00:27:21,887\nthat should be called by other people or not? We do that with\n能不能调用指定的方法呢？\n\n556\n00:27:21,889 --> 00:27:26,091\nthe private keyword. So I'm gonna add private, okay,\n可以通过 private（私有的）关键字\n\n557\n00:27:26,093 --> 00:27:28,193\nthis private keyword right here,\n就是这个 private\n\n558\n00:27:28,195 --> 00:27:31,329\nto all of my functions and methods over here.\n把这所有的方法都标记为 private \n\n559\n00:27:31,331 --> 00:27:33,564\nI don't, this is not really part of Swift again,\n再说一次，这不是 Swift 中的关键字\n\n560\n00:27:33,566 --> 00:27:34,865\nthis is kind of an Xcode thing, so\n这是 Xcode 相关的东西\n\n561\n00:27:34,867 --> 00:27:36,533\nI put it after that. But otherwise,\n所以要放到它的后面\n\n562\n00:27:36,535 --> 00:27:38,568\nyou put it there, and we're gonna put it for all of these.\n把它们都标记成 private 的\n\n563\n00:27:38,570 --> 00:27:40,403\nWe're gonna make all of these be private.\n它们都是\n\n564\n00:27:40,405 --> 00:27:43,305\nAnd as you program, okay, you're gonna see that one of\n当你写程序的时候\n\n565\n00:27:43,307 --> 00:27:45,908\nthe evaluation criteria on your homework is that you\n也就是在你们的作业中你们会使用这种判断标准\n\n566\n00:27:45,910 --> 00:27:48,610\nproperly make things private when they should be private.\n当它们应该是 private 的时候，才把它们设置成 private 的\n\n567\n00:27:48,612 --> 00:27:51,680\nAnd I generally would err on the side of making it private.\n但我不建议你们这样做\n\n568\n00:27:51,682 --> 00:27:53,881\nIt's a lot easier to make something private and\n我还是建议你们先设置成 private 的\n\n569\n00:27:53,883 --> 00:27:53,981\ndecide to make it public, than to use something public,\n当你决定让它们成为 public 的时候\n\n570\n00:27:53,983 --> 00:27:56,083\ngo back later and\n再调整为 public 的\n\n571\n00:27:56,085 --> 00:27:57,851\nhave a whole bunch of coders start using it, and\n如果有很多人调用了你开发的类\n\n572\n00:27:57,853 --> 00:27:59,853\nthen decide, no, no, I want that to be private.\n然后你又决定把某个方法变成 private 的\n\n573\n00:27:59,855 --> 00:28:02,789\nThen you break all those other people. So err on the side of\n那么所有其他人的程序都会出现问题\n\n574\n00:28:02,791 --> 00:28:06,125\nprivate first, and then making things public, okay?\n所以还是先把方法设置为 private 的，需要的时候再改成 public\n\n575\n00:28:06,127 --> 00:28:10,129\nNow, it's actually possible to look at something and see what\n现在可以通过\n\n576\n00:28:10,131 --> 00:28:13,699\nits public interface is by going up here to the top and\n点击上方的这里，选择 Generated Interface\n\n577\n00:28:13,701 --> 00:28:16,568\npicking Generated Interface. This will show you the public\n来看所有的公共接口\n\n578\n00:28:16,570 --> 00:28:20,438\nAPI of the class in the main window on the left there.\n它会显示左边窗口的类的所有公共的 API\n\n579\n00:28:20,440 --> 00:28:23,341\nSo we're gonna look at the public API of CalculatorBrain.\n让我们看看 CalculatorBrain 公共的 API\n\n580\n00:28:23,343 --> 00:28:25,676\nYou can see that it has that setOperand, performOperation,\n可以看到有 setOperand, performOperation 和 result\n\n581\n00:28:25,678 --> 00:28:28,211\nand result. Notice this looks just like current title,\n注意，这个 result 看起来和 currentTitle 一样\n\n582\n00:28:28,213 --> 00:28:30,914\nright, where it's saying this is a read-only thing.\n这表明它是一个只读的\n\n583\n00:28:30,916 --> 00:28:32,715\nWe don't see any implementation here,\n我们在这里看不到实现\n\n584\n00:28:32,717 --> 00:28:35,918\nthis is purely the API, okay? So\n只能看到 API\n\n585\n00:28:35,920 --> 00:28:38,787\nno implementation here. Also notice this says internal,\n这里没有实现。还需要注意这里的 internal\n\n586\n00:28:38,789 --> 00:28:41,490\nyou would think this might say public, okay? But there's\n你可能会认为这里是 public\n\n587\n00:28:41,492 --> 00:28:44,392\nactually a slight difference between internal and public.\n但是 public 和 internal 还是有点区别的\n\n588\n00:28:44,394 --> 00:28:47,695\nInternal means it's public within your module.\ninternal 代表，它只在你的 module 中是 public 的\n\n589\n00:28:47,697 --> 00:28:51,565\nPublic would mean it's public to everyone in other modules,\npublic 代表它在其它的 module 中也是 public 的（全局 public）\n\n590\n00:28:51,567 --> 00:28:52,199\nso consider UIkit.\n想想 UIKit\n\n591\n00:28:52,201 --> 00:28:55,736\nUIkit has hundreds of public methods that we can call.\nUIKit 有许多我们可以调用的公有方法\n\n592\n00:28:55,738 --> 00:28:58,271\nBut it also has hundreds, if not thousands of internal\n但还有许多 internal 方法\n\n593\n00:28:58,273 --> 00:29:01,007\nmethods that only other UIkit classes can call between\n是只有在 UIKit 中的类才可以相互调用的\n\n594\n00:29:01,009 --> 00:29:05,111\nthemselves. We don't even know what they are, okay? So, but\n我们连它们是什么叫什么都不知道\n\n595\n00:29:05,113 --> 00:29:05,244\nfor your purposes,\n但对于你来说\n\n596\n00:29:05,246 --> 00:29:07,145\nsince you're always gonna be working in the module,\n因为你总是只在你的 module 里工作\n\n597\n00:29:07,147 --> 00:29:09,781\nwhich is your app, internal means public,\n所以在你的 APP 里 internal 就代表着 public\n\n598\n00:29:09,783 --> 00:29:13,117\nbasically. Let's go look at our controller now, and\n看一眼 controller\n\n599\n00:29:13,119 --> 00:29:16,554\nlet's look at its public API, okay? So here I selected it,\n看看它的 public API\n\n600\n00:29:16,556 --> 00:29:19,423\nlook over here. And it says, there's only one public thing,\n它只有一个东西是 public 的\n\n601\n00:29:19,425 --> 00:29:22,526\nuserIsInTheMiddleOfTyping. I didn't mean that to be public.\nuserIsInTheMiddleOfTyping，我不想让它是 public 的\n\n602\n00:29:22,528 --> 00:29:24,661\nI wanted that to be private, too, I just forgot to put\n我想让它也变成 private 的\n\n603\n00:29:24,663 --> 00:29:26,996\nthe private on there. So if I go back over here and\n我刚刚只是忘了在这加 private\n\n604\n00:29:26,998 --> 00:29:30,966\nsay private, okay, then you'll see it goes away. So now we\n回到这里，加上 private，你会发现它已经消失了\n\n605\n00:29:30,968 --> 00:29:35,204\nhave no public API here. Now, it's still completely usable,\n现在它已经没有 public API 了，但它仍然是可用的\n\n606\n00:29:35,206 --> 00:29:38,707\nbecause in Interface Builder, we can wire up to this\n因为在 Interface Builder 中，可以连线到这个 controller \n\n607\n00:29:38,709 --> 00:29:40,775\ncontroller and make it appear in a tab bar controller,\n让它出现在一个 tab bar controller 中\n\n608\n00:29:40,777 --> 00:29:43,778\nall those things. We can do all that without having any of\n我们可以不把 internal 改成 public \n\n609\n00:29:43,780 --> 00:29:45,246\nthe internal methods here be public.\n就可以实现这些\n\n610\n00:29:45,248 --> 00:29:49,383\nOkay, so we're gonna go back to my, oops, sorry.\n返回我们的\n\n611\n00:29:49,385 --> 00:29:54,588\nI'll go back to my brain over here, it's got my controller\nCalculatorBrain\n\n612\n00:29:54,590 --> 00:29:59,259\nover here. All right, so we've got brain and\n这里放 ViewController\n\n613\n00:29:59,261 --> 00:30:02,195\ncontroller. So let's think about how we're can use this\n现在来想想怎么使用这个 model\n\n614\n00:30:02,197 --> 00:30:06,132\nmodel over here, okay? We haven't implemented this yet,\n我们还没有实现这个\n\n615\n00:30:06,134 --> 00:30:07,700\nbut we've defined its public API. So\n但已经完成了它的 public API\n\n616\n00:30:07,702 --> 00:30:11,136\nhow can we use that over here? Well, we really wanna replace\n所以我们怎么在这里使用呢？\n\n617\n00:30:11,138 --> 00:30:14,673\nall of this business with using our model, right? Cuz\n把这里的业务逻辑都用 model 来完成\n\n618\n00:30:14,675 --> 00:30:18,376\nthis is where we were doing model things, calculations.\nmode 是我们完成计算的地方\n\n619\n00:30:18,378 --> 00:30:20,411\nSo we don't want that, okay? We wanna get rid of that, and\n把这里删掉\n\n620\n00:30:20,413 --> 00:30:23,113\nwe want to start using our model here. Well, to have\n开始使用我们的 model\n\n621\n00:30:23,115 --> 00:30:26,550\na model in our controller, we need to be able to talk to it,\n为了在 controller 中使用 model，也就是与 model 交互\n\n622\n00:30:26,552 --> 00:30:28,051\nthat big green arrow, okay?\n正如那个绿箭头所表示的那样\n\n623\n00:30:28,053 --> 00:30:32,922\nSo we need a private var, which I'll call brain,\n我们需要创建一个 private 的变量，命名为 brain\n\n624\n00:30:32,924 --> 00:30:36,625\nwhich is gonna be a CalculatorBrain, okay?\n它的类型是 CalculatorBrain\n\n625\n00:30:36,627 --> 00:30:38,961\nAnd this is the var that we're, it's gonna create our,\n所以我们创建一个\n\n626\n00:30:38,963 --> 00:30:40,195\nwe're gonna create our CalculatorBrain.\nCalculatorBrain 的实例\n\n627\n00:30:40,197 --> 00:30:43,365\nAnd we're gonna talk to it to do all the calculations, okay?\n然后我们通过它来实现所有的计算\n\n628\n00:30:43,367 --> 00:30:46,501\nSo this is just that big green arrow I showed you on that,\n这就是我在之前幻灯片里给你们展示过的\n\n629\n00:30:46,503 --> 00:30:49,804\nthose previous slides, where the controller talks through\n大的绿色箭头\n\n630\n00:30:49,806 --> 00:30:54,375\nthis to get to the model. Now, how about creating this thing?\ncontroller 可以通过它来调用 model\n\n631\n00:30:54,377 --> 00:30:55,175\nWhere do we create this?\n什么时候把它初始化呢？\n\n632\n00:30:55,177 --> 00:30:58,011\nWell, you can see that we have an error up here,\n这里有一个错误\n\n633\n00:30:58,013 --> 00:30:59,645\nno initializers again.\n没有被初始化\n\n634\n00:30:59,647 --> 00:31:00,446\nThat's because this var,\n因为这个 var 跟其它的一样\n\n635\n00:31:00,448 --> 00:31:02,981\nlike any other, has to be initialized. And\n需要被初始化\n\n636\n00:31:02,983 --> 00:31:06,218\nI'm gonna create a CalculatorBrain here. And\n我在这里创建 CalculatorBrain\n\n637\n00:31:06,220 --> 00:31:11,389\nto do that, I have to call one of its initializers. And every\n并调用它的其中一个初始化函数\n\n638\n00:31:11,391 --> 00:31:15,360\ntime you create a new class, you get one free initializer,\n每一次你新创建的类都会有一个自带的初始化函数\n\n639\n00:31:15,362 --> 00:31:19,897\nwhich is an initializer that takes no arguments, okay,\n这个函数是没有参数的\n\n640\n00:31:19,899 --> 00:31:21,532\nkinda the basic initializer. So\n它就是最基本的初始化函数\n\n641\n00:31:21,534 --> 00:31:25,268\nI'm using that CalculatorBrain initializer, it came for free.\n我调用了那个自带的初始化函数\n\n642\n00:31:25,270 --> 00:31:27,937\nI don't have anything that I need to initialize anyway.\n我不需要在初始化它的时候初始化其它东西\n\n643\n00:31:27,939 --> 00:31:33,109\nSo, that's perfectly fine, okay, so I've created it. Now,\n所以这么做是没问题的\n\n644\n00:31:33,111 --> 00:31:38,180\nnotice that this right here, do we need this?\n我们需要这个吗？\n\n645\n00:31:38,182 --> 00:31:40,382\nNo, because Swift can infer that\n不需要，因为 Swift 可以推断出来\n\n646\n00:31:40,384 --> 00:31:45,087\nbrain is a CalculatorBrain from that = right there, okay?\n从等号的右边可以推断出它的类型是 CalculatorBrain\n\n647\n00:31:45,089 --> 00:31:49,724\nSo we do not wanna put colon CalculatorBrain. All right, so\n所以不用在这里放 :CalculatorBrain\n\n648\n00:31:49,726 --> 00:31:53,227\nnow that we have this brain, kay, and it's created here, we\n现在已经在这里创建好了 brain \n\n649\n00:31:53,229 --> 00:31:56,530\ncan use it to public API right here, to make things work.\n我们就可以调用它的 public API 了\n\n650\n00:31:56,532 --> 00:31:59,166\nWell, one thing we know is that when the mathematical\n当数学符号进到这里的时候\n\n651\n00:31:59,168 --> 00:32:02,636\nsymbol comes through here, we wanna ask the brain to perform\n我们想让 brain 来执行对应的操作\n\n652\n00:32:02,638 --> 00:32:05,805\nthat operation. Okay, so we're gonna pass that mathematical\n所以要把这个数学符号\n\n653\n00:32:05,807 --> 00:32:08,241\nsymbol as the operation, we know that. We also\n当作参数传进来\n\n654\n00:32:08,243 --> 00:32:11,544\nprobably know that after it's done performing the operation,\n当它执行完操作以后\n\n655\n00:32:11,546 --> 00:32:15,247\nwe probably wanna put in the display the result,\n要把 result 放到 displayValue 中显示\n\n656\n00:32:15,249 --> 00:32:19,818\nthe brain's result, this thing right here. Right? And\n是 brain  计算的结果\n\n657\n00:32:19,820 --> 00:32:22,620\nalso at the beginning of the perform operation,\n在做运算之前\n\n658\n00:32:22,622 --> 00:32:24,789\nif we're in the middle of typing a number,\n如果我们正在输入数字\n\n659\n00:32:24,791 --> 00:32:27,191\nwe better set that number at the operand for\n最好把这个数字设置为 brain 的 operand\n\n660\n00:32:27,193 --> 00:32:30,561\nthe calculator to work on it. If we go 235 square root,\n如果我们计算根号235\n\n661\n00:32:30,563 --> 00:32:34,464\nwe got to put that 235 in as the operand for the brain.\n要把235设置为 brain 的 operand\n\n662\n00:32:34,466 --> 00:32:37,233\nSo we better say if the user is in the middle of typing\nif userIsInTheMiddleOfTyping\n\n663\n00:32:37,235 --> 00:32:41,804\na number then brain.set operand to be whatever's\n把显示的数字设置为\n\n664\n00:32:41,806 --> 00:32:45,508\nin the display. You can see even here, having this display\nbrain.operand\n\n665\n00:32:45,510 --> 00:32:49,378\nvalue thing makes our code read really beautifully.\n即使这里有 displayValue，代码的可读性也是非常高的\n\n666\n00:32:49,380 --> 00:32:52,914\nOkay. We can probably put this inside this if, because\n可以把它放进这个 if 里\n\n667\n00:32:52,916 --> 00:32:57,886\nno need to set it false if it's already true. Okay, so\n如果它已经是 false 了，就没有把它设置成 false 的必要了（这里 Paul 口误了）\n\n668\n00:32:57,888 --> 00:33:01,589\nthat's it! That's all we need to do to hook our model up\n好了，这样就把 model 和 controller 连接起来了\n\n669\n00:33:01,591 --> 00:33:04,759\nto our controller. Okay. And we've removed everything\n并且也把实际计算的代码\n\n670\n00:33:04,761 --> 00:33:07,027\nin our controller that has to do with actually calculating.\n都从 controller 里移除了\n\n671\n00:33:07,029 --> 00:33:12,833\nWe've basically given it all off to the model to do.\n已经让 model 来做这件事了\n\n672\n00:33:13,068 --> 00:33:14,367\nSo now we have to implement this, okay?\n现在得实现这个了\n\n673\n00:33:14,369 --> 00:33:16,168\nWe've gotta implement this brain over here.\n我们得实现 brain 的逻辑\n\n674\n00:33:16,170 --> 00:33:19,638\nI'm gonna make that be the main window here.\n让它占满整个窗口\n\n675\n00:33:19,640 --> 00:33:20,172\nAnd how are we gonna do that?\n该怎么实现呢？\n\n676\n00:33:20,174 --> 00:33:24,743\nWell, I'm gonna have a data structure here for my brain\n先创建一个变量\n\n677\n00:33:24,745 --> 00:33:27,311\nwhich makes pretty much sense, which is gonna be private,\n当然要是 private 的\n\n678\n00:33:27,313 --> 00:33:30,114\nwhich is gonna be called accumulator. It's gonna be\n起名为 accumulator，类型是 Double\n\n679\n00:33:30,116 --> 00:33:34,318\na Double and it's going to accumulate the results, okay.\n用它来保存结果\n\n680\n00:33:34,320 --> 00:33:37,521\nAs operations are performed, it's accumulating the result.\n计算完毕后，把结果存起来\n\n681\n00:33:37,523 --> 00:33:40,090\nOkay, anyone who knows how calculator's built,\n知道怎么实现计算器的人\n\n682\n00:33:40,092 --> 00:33:43,226\nit has internal calc, accumulator. So,\n都应该知道它有个内部的存储器\n\n683\n00:33:43,228 --> 00:33:45,594\nthis is our accumulator. Notice that I,\n这就是 accumulator\n\n684\n00:33:45,596 --> 00:33:47,696\nas soon as I put this in here I get this error.\n看这里，写完了以后就出现了一个错误\n\n685\n00:33:47,698 --> 00:33:51,233\nAgain, calculator brain has no initializers, that's because\n同样地 calculatorBrain 没有初始化函数\n\n686\n00:33:51,235 --> 00:33:54,402\nI don't initialize this. So, I'm gonna say this equals 0.0.\n因为我还没有初始化它。我会把它设置为 0.0\n\n687\n00:33:54,404 --> 00:33:59,874\nOnce I do that I do not need this because 0.0,\n这样做了就不再需要这里的 Double\n\n688\n00:33:59,876 --> 00:34:04,311\nSwift always infers that. Or any something dot something,\n因为 Swift 可以从0.0推断出它是 Double 类型的\n\n689\n00:34:04,313 --> 00:34:07,548\nit always infers it to be a Double, okay. So that makes\n它可以推断出来\n\n690\n00:34:07,550 --> 00:34:12,019\nthis be a Double. You see? If I made this no dots just zero,\n所以它就是一个 Double 类型的\n\n691\n00:34:12,021 --> 00:34:14,888\nthen it's gonna infer this as an int, okay.\n如果这里只是0，Swift 就会认为它是 int 类型\n\n692\n00:34:14,890 --> 00:34:19,092\nSo, good thing to know there. So now that I have my\n了解这一点还是不错的\n\n693\n00:34:19,094 --> 00:34:22,628\naccumulator, the result is always just the current state\n现在已经有了 accumulator\n\n694\n00:34:22,630 --> 00:34:25,798\nof my accumulator. So that's easy, open my result. And\nresult 返回的一直是 accumulator 当前的值\n\n695\n00:34:25,800 --> 00:34:28,433\nsame thing when someone says the operand, that kinda\n如果有人调用了 setOperand\n\n696\n00:34:28,435 --> 00:34:33,271\nresets my accumulator to be whatever that operand is.\n就会改变 accumulator 的值\n\n697\n00:34:33,840 --> 00:34:37,241\nOkay. So those are all easy to implement. So that just leaves\n实现这些很容易\n\n698\n00:34:37,243 --> 00:34:40,844\nthis guy, perform operation. That's the heart of my model.\n还剩下 performOperation，这是这个 model 的核心\n\n699\n00:34:40,846 --> 00:34:44,014\nThat's the thing that's really gonna do some calculation.\n它是做计算的地方\n\n700\n00:34:44,016 --> 00:34:47,450\nNow I could right here go back to what I was doing in my\n这里可以像之前在 controller 里实现的那样\n\n701\n00:34:47,452 --> 00:34:51,387\ncontroller which is to have some, if there is an essence\n执行一些 if else 操作\n\n702\n00:34:51,389 --> 00:34:55,725\nis here, well actually I'm gonna use switch. So\n但在这里我用一下 switch\n\n703\n00:34:55,727 --> 00:34:57,993\nswitch is the same as another language but\nswitch 和其它语言的功能类似\n\n704\n00:34:57,995 --> 00:34:59,661\nmuch more powerful in Swift and\n但是在 Swift 中更加强大\n\n705\n00:34:59,663 --> 00:35:02,764\nalso much more important in Swift as you will see. Okay.\n你们也会看到它在 Swift 中更重要\n\n706\n00:35:02,766 --> 00:35:04,799\nSwitch It's very important thing is Swift.\nswitch 在 Swift 中非常重要\n\n707\n00:35:04,801 --> 00:35:07,134\nSo, I can switch on this symbol that's legal.\n我可以对这个符号做 switch 操作\n\n708\n00:35:07,136 --> 00:35:10,637\nThe switch on a String. Okay. And I just put the cases that\n是对 String 进行的 switch 操作\n\n709\n00:35:10,639 --> 00:35:15,542\nI wanna try. So, we have for example pi. And if pi happens,\n首先把 pi 当作其中的一个 case\n\n710\n00:35:15,544 --> 00:35:19,779\nI wanna set my accumulator equal to pi,\n如果是 pi，就把 accumulator 设置为 pi\n\n711\n00:35:19,781 --> 00:35:24,017\nokay. If it was for example, square root,\n如果是 根号\n\n712\n00:35:24,019 --> 00:35:28,354\nlet's go do that. My square root symbol back, here it is.\n我们先把根号调出来\n\n713\n00:35:28,356 --> 00:35:31,790\nSo if we get square root, then I'm just gonna say that my\n如果它是根号\n\n714\n00:35:31,792 --> 00:35:36,461\naccumulator equals the square root of the accumulator. Okay?\naccumulator 就等于根号 accumulator\n\n715\n00:35:36,463 --> 00:35:40,331\nSo, this is basically getting us back to exactly where we\n这和之前做的事情一样\n\n716\n00:35:40,333 --> 00:35:43,067\nwere before but now we have a model.\n只不过现在我们是在 model 里做\n\n717\n00:35:43,069 --> 00:35:43,968\nNotice we have an error here.\n注意，这里有个 error\n\n718\n00:35:43,970 --> 00:35:47,171\nThat's because one thing about switch, you must consider\n这是由 switch 引发的\n\n719\n00:35:47,173 --> 00:35:51,241\nevery possible value of this thing you're switching on.\n你必须考虑到 switch 的所有可能的情形\n\n720\n00:35:51,243 --> 00:35:55,011\nNow, this is a String, so it has infinite possibilities,\n它的类型是 String，所以它有无限多种可能\n\n721\n00:35:55,013 --> 00:35:59,682\nokay? Now, we could spend the next few years saying case A,\n我们可以花几天的时间 switch 所有的情形\n\n722\n00:35:59,684 --> 00:36:02,184\nno, we don't wanna do that. Instead, we're gonna put\n但我们不会那样做\n\n723\n00:36:02,186 --> 00:36:06,155\ndefault break, so default means, if you can't match any\n我们只需要写上 default break\n\n724\n00:36:06,157 --> 00:36:10,392\nof these other ones than just break out of this, okay? Now\n它的意思是如果每一个 case 都匹配不上，就跳出这个 switch\n\n725\n00:36:10,394 --> 00:36:13,528\nnotice my indentations gotten a little wonky here, I'm gonna\n这里的缩进有一些问题\n\n726\n00:36:13,530 --> 00:36:16,931\nteach you something fun. If you select a curly braced\n教你们一个小技巧吧，选中\n\n727\n00:36:16,933 --> 00:36:20,968\nregion including your whole file, and hit Ctrl+I.\n文件中的花括号部分，按下 Ctrl+I\n\n728\n00:36:20,970 --> 00:36:23,637\nIt'll reformat it, okay? Re-lay it out. And\n这部分的缩进就会变成正确的状态\n\n729\n00:36:23,639 --> 00:36:26,540\nI strongly recommend that when you turn your homework in,\n我强烈建议你们在交作业之前这么做\n\n730\n00:36:26,542 --> 00:36:29,142\nyou select all and do Ctrl+I. Okay?\n选择代码，然后按下 Ctrl+I\n\n731\n00:36:29,144 --> 00:36:32,211\nThat way you'll be using the default indentation, even if\n这样就会把代码变成默认缩进的格式\n\n732\n00:36:32,213 --> 00:36:35,681\nyou prefer something else, use the default one because people\n即使你偏好其它类型的缩进\n\n733\n00:36:35,683 --> 00:36:38,017\nreading your code are gonna be able to understand it better.\n默认缩进会让其它人更好地理解你的代码\n\n734\n00:36:38,019 --> 00:36:41,720\nOkay. And believe me, you'll adjust to whatever indentaki,\n相信我，你应当适应\n\n735\n00:36:41,722 --> 00:36:44,522\nindentation style this thing enforces on you, okay?\nXcode 为你调节的这种缩进方式\n\n736\n00:36:44,524 --> 00:36:46,891\nIf you start getting, if you are a computer scientist and\n如果你是一个计算机科学家\n\n737\n00:36:46,893 --> 00:36:49,794\nyou start getting religious about things like indentation,\n如果你在类似于缩进的事情上有了某些信仰\n\n738\n00:36:49,796 --> 00:36:51,328\nyou're heading down a pretty rocky road,\n那你前行的道路可能就很崎岖了\n\n739\n00:36:51,330 --> 00:36:53,930\nokay. Because when you wanna work in the real world you're\n当你在真实的环境中工作\n\n740\n00:36:53,932 --> 00:36:56,966\ngonna have companies that say this is the way we do it,\n你的公司可能会使用你不偏好的那种缩进风格\n\n741\n00:36:56,968 --> 00:36:57,033\nget used to it.\n并且让你适应这种风格\n\n742\n00:36:57,035 --> 00:36:59,135\nAnd if you sit there whining I don't like to do it that way,\n如果你坐在那抱怨：我不想用那种风格\n\n743\n00:36:59,137 --> 00:37:02,104\nwell, you'll probably get fired. Okay? So don't do that.\n你可能会被开除的，所以还是适应吧\n\n744\n00:37:02,106 --> 00:37:05,340\nSo here we're just gonna let the Xcode do our indentation\n这里我们让 Xcode 来调整缩进\n\n745\n00:37:05,342 --> 00:37:08,843\nfor us. So this is all we need to do right here, okay.\n目前为止要做的已经完成了\n\n746\n00:37:08,845 --> 00:37:10,812\nThis is full implementation. We can go back and\n这就是完整的实现\n\n747\n00:37:10,814 --> 00:37:13,781\nrun our app and it's exactly the way it was before,\n运行一下 app，和以前还是一样\n\n748\n00:37:13,783 --> 00:37:17,985\nbut now we're using a model. Okay. So\n但是现在，我们使用了 model\n\n749\n00:37:17,987 --> 00:37:21,321\nhere we go, let's try 4-5, that's working square root.\n试试根号45\n\n750\n00:37:21,323 --> 00:37:24,090\nThat looks like it's working. We'll just be sure by picking\n看起来代码起作用了\n\n751\n00:37:24,092 --> 00:37:26,626\na number we know the square root of, pi seems to work,\n根号9的值是3，也没问题\n\n752\n00:37:26,628 --> 00:37:28,728\nsquare root. Okay, so we're back to where we were,\npi，根号 pi 都没问题，又回到了之前的状态\n\n753\n00:37:28,730 --> 00:37:33,132\nthat's nice. Now, they'll, thing about this now is I'm\n很不错\n\n754\n00:37:33,134 --> 00:37:37,336\nabout to go add a whole bunch more operations here. And\n不过还要添加更多的操作符在这里\n\n755\n00:37:37,338 --> 00:37:42,273\nif for every single one I have to do the math, do the math,\n对于每一个操作符，我都要做计算\n\n756\n00:37:42,275 --> 00:37:43,341\ndo the math each one,\n每一个都要做计算\n\n757\n00:37:43,343 --> 00:37:45,176\nthis is gonna be a lot of duplicated code\n这将会有很多的重复代码\n\n758\n00:37:45,178 --> 00:37:47,978\nin here. Because every time I have a unary operation like\n当它是一元操作符的时候，比如根号\n\n759\n00:37:47,980 --> 00:37:51,281\nsquare root, it's exactly the same. If I have cosign or\n它们的操作都是相同的\n\n760\n00:37:51,283 --> 00:37:53,049\nsquare root or anything it's exactly the same.\n如果这里是 cos 或者根号，这里的操作都是想同的\n\n761\n00:37:53,051 --> 00:37:56,786\nThe only difference is these four characters. Square root,\n唯一的区别是这四个字母\n\n762\n00:37:56,788 --> 00:38:00,423\nor cosign or whatever. Same thing for these constants,\n是 sqrt 还是 cos。这里的常量也是类似的\n\n763\n00:38:00,425 --> 00:38:02,558\nonly this part will be different on every line,\n唯一的区别是这一点地方\n\n764\n00:38:02,560 --> 00:38:05,193\neven for binary, like multiplier, whatever.\n对于二元操作符也是一样的\n\n765\n00:38:05,195 --> 00:38:06,561\nIt's probably only the function that does\n唯一的区别是\n\n766\n00:38:06,563 --> 00:38:08,563\nthe calculation that's gonna be different. So I'm gonna\n进行计算的函数\n\n767\n00:38:08,565 --> 00:38:12,733\nfactor this stuff out, so that all of these things,\n所以我要重构这部分代码\n\n768\n00:38:12,735 --> 00:38:17,805\nlike pi and square root and multiply are in a table, okay?\n把如 pi，根号，乘号之类的符号都放进一个表中\n\n769\n00:38:17,807 --> 00:38:21,441\nAnd I'm just going to have this only be doing the generic\n然后在这里只需要进行通用的计算\n\n770\n00:38:21,443 --> 00:38:22,742\ncalculations, generic constants,\n通用的常量\n\n771\n00:38:22,744 --> 00:38:25,611\ngeneric numeral operations, generic binary operations.\n还有通用的一元操作和二元操作\n\n772\n00:38:25,613 --> 00:38:28,447\nAnd it's gonna look in the table to find out what to do.\n它会到表里查找，应该做什么操作\n\n773\n00:38:28,449 --> 00:38:30,115\nDoesn't that seem like a much better design,\n不觉得这是一种更好的设计吗？\n\n774\n00:38:30,117 --> 00:38:31,483\nmore extensible, less code, etc? So\n更少的代码，更好的扩展性\n\n775\n00:38:31,485 --> 00:38:35,053\nthat's what were gonna do. So let's create that table, okay?\n所有让我们先创建这张表\n\n776\n00:38:35,055 --> 00:38:37,488\nAnd were gonna call that table operations. And\n起名为 operations\n\n777\n00:38:37,490 --> 00:38:40,524\nit's going to be the class, it's actually not a class.\n它的类是 Dictionary，实际上 Dictionary 不是一个类\n\n778\n00:38:40,526 --> 00:38:44,228\nDictionary, okay, so Dictionary is a Swift thing.\n它是一个 Swift 中的东西\n\n779\n00:38:44,230 --> 00:38:48,331\nIt is a generic type. You're probably used to that in Java.\n它是一个通用的类型，你可能在 Java 中用过\n\n780\n00:38:48,333 --> 00:38:51,601\nSo you specify right here when you're declaring this\n你得在这里声明它\n\n781\n00:38:51,603 --> 00:38:55,038\nwhat the keys and values are, what type? And so I want one,\nkey 和 value 的类型\n\n782\n00:38:55,040 --> 00:38:57,039\nI'm gonna start out just doing the constants.\n先从常量开始\n\n783\n00:38:57,041 --> 00:38:59,108\nLet's have this table only do constants, okay,\n先让这个表只放 pi 之类的常量\n\n784\n00:38:59,110 --> 00:39:02,377\nlike pi. Okay? So I'm gonna have my keys be String.\nkey 的类型是 String\n\n785\n00:39:02,379 --> 00:39:06,281\nThat'll be the name of the constant, like the pi\nkey 是常量的名字，例如 pi\n\n786\n00:39:06,283 --> 00:39:09,350\ncharacter or whatever. And the value's gonna be a Double.\nvalue 的类型是 Double\n\n787\n00:39:09,352 --> 00:39:14,055\nSo that'll be like M under bar pi or whatever. Okay? So,\n它就是 pi 的值 M_PI 之类的东西\n\n788\n00:39:14,057 --> 00:39:16,690\nI've declared it here. Now I'm actually gonna initialize\n我在这里声明了它，也在这里初始化它\n\n789\n00:39:16,692 --> 00:39:19,026\nit because remember I have to initialize all my vars.\n因为必须要初始化所有 var\n\n790\n00:39:19,028 --> 00:39:21,895\nYou can initialize a Dictionary right on the fly\n你可以在创建 Dictionary 的时候就初始化它\n\n791\n00:39:21,897 --> 00:39:25,898\njust by using the open square bracket. Notation and\n只需要使用方括号\n\n792\n00:39:25,900 --> 00:39:26,732\nyou just put like for\n你可以放\n\n793\n00:39:26,734 --> 00:39:32,971\nexample pi cuz key colon m under bar pi the value.\n\"pi\" : M_PI\n\n794\n00:39:32,973 --> 00:39:36,174\nOkay so I'm basically filling up the Dictionary here.\n现在我要继续填充这个字典\n\n795\n00:39:36,176 --> 00:39:39,210\nLet's do another constant how about E that's M under bar e\n继续添加另一个常量，\"e\" : M_E\n\n796\n00:39:39,212 --> 00:39:42,714\neveryone know what e is 2.71 or whatever it is. Okay?\n大家都知道 e 是2.71\n\n797\n00:39:42,716 --> 00:39:45,983\nSo, we could add a whole bunch more of these things into our\n还可以向这张表中添加其它的东西\n\n798\n00:39:45,985 --> 00:39:47,885\ntable. Again, we're only doing constants right now,\n现在只添加常量\n\n799\n00:39:47,887 --> 00:39:50,420\nwe're not doing square root and those kinds of things.\n先不添加根号之类的东西\n\n800\n00:39:50,422 --> 00:39:52,122\nSo, that changes my code over here.\n所以这里的代码就得改了\n\n801\n00:39:52,124 --> 00:39:54,657\nInstead of having all that stuff right there,\n把这些删掉\n\n802\n00:39:54,659 --> 00:40:01,364\nI'm just going to let Constant equal Operations sub symbol.\n换成 let constant = operation[symbol]\n\n803\n00:40:01,366 --> 00:40:05,701\nSo,this is how you look something up in a Dictionary.\n这就是从 Dictionary 中查东西的方式\n\n804\n00:40:05,703 --> 00:40:08,603\nOkay? Here's the name of the Dictionary, right here, and\n这是 Dictionary 的名字\n\n805\n00:40:08,605 --> 00:40:11,272\nyou look it up with square brackets and the thing to look\n通过 [] 来查询\n\n806\n00:40:11,274 --> 00:40:14,575\nup. Okay? And now, I could just say my accumulator equals\n然后把 constant 赋值给 accumulator\n\n807\n00:40:14,577 --> 00:40:19,380\nthat constant. Okay? But, this is not gonna work. Why? Let's\n但这不会有效的\n\n808\n00:40:19,382 --> 00:40:24,084\nfind out. Error, it says, value of optional Double?\n有错误，值是一个 optional 的 Double\n\n809\n00:40:24,086 --> 00:40:27,120\nnot unwrapped. Uh-oh, it's optionals again.\n还没有解包，又是 optional\n\n810\n00:40:27,122 --> 00:40:30,590\nOkay, what's happening here? It wants to unwrap constant.\n发生了什么？\n\n811\n00:40:30,592 --> 00:40:33,993\nIn other words, it's saying this is an optional Double.\n它说这是个 optional 的 Double\n\n812\n00:40:33,995 --> 00:40:34,760\nWhy would the thing,\n为什么会这样呢？\n\n813\n00:40:34,762 --> 00:40:37,463\nthis Dictionary does not contain optional Doubles,\n这个 Dictionary 包含的是 Double\n\n814\n00:40:37,465 --> 00:40:41,033\nit contains Doubles? So, why would looking this symbol up\n而不是 optional Double 啊\n\n815\n00:40:41,035 --> 00:40:43,068\nin that Dictionary return an optional Double?\n为什么从中查询数据的时候它就返回了个 optioal 了呢？\n\n816\n00:40:43,070 --> 00:40:46,371\nAnybody have an idea? Someone besides you, cuz you got it\n有人有什么想法吗？\n\n817\n00:40:46,373 --> 00:40:48,572\nright before. [INAUDIBLE]. >> Yeah?\n那个同学\n\n818\n00:40:48,574 --> 00:40:49,373\n>> I think their Dictionary\n字典里可能没有那个 key\n\n819\n00:40:49,375 --> 00:40:50,707\nmight not have that key? >> Correct!\n正确\n\n820\n00:40:50,709 --> 00:40:53,043\nExactly the same thing as before, okay? This Dictionary\n和之前一样对吧？\n\n821\n00:40:53,045 --> 00:40:57,013\nmight not contain that key that we're looking up. So,\nDictionary 中没有我们查询的那个 key\n\n822\n00:40:57,015 --> 00:40:59,882\nit's gonna return nil to say I couldn't find it.\n没找到，它就会返回 nil\n\n823\n00:40:59,884 --> 00:41:04,086\nSo, we simply need to unwrap it. Now, this is dangerous,\n如果只是简单地把它 unwrap，是很危险的\n\n824\n00:41:04,088 --> 00:41:06,221\nbecause maybe somebody's using my API, and\n因为如果有人调用了我的 API\n\n825\n00:41:06,223 --> 00:41:08,623\nthey perform an operation that I don't understand,\nperformOperation 的参数在这里没有的话\n\n826\n00:41:08,625 --> 00:41:11,359\nnow I'm gonna crash. That's not very friendly. So,\n程序就会崩溃，这很不友好\n\n827\n00:41:11,361 --> 00:41:16,764\nhere I'm gonna use if, the if let and set my accumulator,\n这里我会使用 if let\n\n828\n00:41:16,766 --> 00:41:20,134\nand I'm just gonna ignore any operation that I don't\n如果没有的话，就直接忽略这次操作\n\n829\n00:41:20,136 --> 00:41:21,968\nunderstand. I'm not going to affect my accumulator.\n我不会修改 accumulator 的值\n\n830\n00:41:21,970 --> 00:41:26,840\nJust leave it. Okay? All right, so let's run, make sure\n让我们运行程序，看看是否还正常工作\n\n831\n00:41:26,842 --> 00:41:33,346\nthis works. All right. So, the square root's not gonna work,\n根号已经不好用了\n\n832\n00:41:33,348 --> 00:41:35,715\ncuz we don't have square roots in our table here,\n因为表中没有根号\n\n833\n00:41:35,717 --> 00:41:36,315\nwe only have constants.\n只有常量\n\n834\n00:41:36,317 --> 00:41:38,183\nBut, we have these are still working, and\n但是这些还有效\n\n835\n00:41:38,185 --> 00:41:41,219\npi is still working. Okay. So that's good. So\npi 也可以正常工作，还不错\n\n836\n00:41:41,221 --> 00:41:43,755\nwe didn't break pi, at least. And if we had an e key,\n至少 pi 还有用\n\n837\n00:41:43,757 --> 00:41:47,992\nthen the e key would work as well. All right. Now,\n如果有 e 的 key 值，那它也会起作用的\n\n838\n00:41:47,994 --> 00:41:52,229\nwe want to extend this to do square root. Okay.\n现在我们来扩展，实现根号计算\n\n839\n00:41:52,231 --> 00:41:52,729\nHow the heck we going to do that?\n应该怎么实现呢？\n\n840\n00:41:52,731 --> 00:41:55,865\nI mean, really, all we want to do is just say square roots,\n我们想做的只是根号\n\n841\n00:41:55,867 --> 00:41:58,368\nwhoops, I shouldn't have done that. Square roots,\n不小心打错了\n\n842\n00:41:58,370 --> 00:42:01,103\nlets get our friendly neighborhood symbol for\n把根号调出来\n\n843\n00:42:01,105 --> 00:42:06,342\nsquare root here. Okay? Square root we really want to\n我们想把 sqrt 这个函数\n\n844\n00:42:06,344 --> 00:42:08,577\nput square root [LAUGH] right here.\n放到这里\n\n845\n00:42:08,579 --> 00:42:10,011\nOkay? The square root function.\nsqrt 这个函数\n\n846\n00:42:10,013 --> 00:42:11,479\nThat's really what I want, what I want to do.\n我就想这么做\n\n847\n00:42:11,481 --> 00:42:14,849\nAnd, like, If I had cosine I'd really want to put the cosine\n如果有 cos，那我也想把 cos 函数放到这里\n\n848\n00:42:14,851 --> 00:42:18,919\nfunction here. Okay? Now this is obviously not a Double.\n它显然不是一个 Double\n\n849\n00:42:18,921 --> 00:42:20,320\n[LAUGH] That's not going to work.\n它不会起作用的\n\n850\n00:42:20,322 --> 00:42:24,357\nSo, this can't be a Double. This has to be something else.\n它不是 Double，它应该是别的类型的\n\n851\n00:42:24,359 --> 00:42:27,694\nOkay? It has to be something that would work for a Double,\n它应该对于 Double 和 function 类型\n\n852\n00:42:27,696 --> 00:42:31,630\nand would also work for a function. Okay? How are we\n同时起作用\n\n853\n00:42:31,632 --> 00:42:35,567\ngonna do that? Well, we're gonna implement a new type,\n该怎么做呢？我们要实现一种新的类型 enum（枚举）\n\n854\n00:42:35,569 --> 00:42:41,406\nokay, and it's similar to class. It's called enum. Okay?\n它与 class 很相似\n\n855\n00:42:41,408 --> 00:42:44,642\nI'm gonna call this enum operation, and\n把它起名为 Operation\n\n856\n00:42:44,644 --> 00:42:47,445\ninside this enum, I'm gonna have all the different kinds\n在 enum 中，有不同的计算方式\n\n857\n00:42:47,447 --> 00:42:50,214\nof operations I know how to do. Now, you're probably used\n你们可能使用过 enum\n\n858\n00:42:50,216 --> 00:42:52,683\nto enum in other languages. What is enum in\n在其它语言中\n\n859\n00:42:52,685 --> 00:42:56,286\nIn most languages it is a discrete set of values, right?\n在大多数语言中，它把集合中的值进行分类\n\n860\n00:42:56,288 --> 00:42:59,322\nAn enum has to have discrete values. Same thing in Swift.\nSwift 中也是这样做的\n\n861\n00:42:59,324 --> 00:43:02,258\nIt has a discrete value. So, for example, it might\n它把值进行分类\n\n862\n00:43:02,260 --> 00:43:06,262\nbe a constant, or maybe it's a unary operation. Or it might\n它可能是常量，一元操作\n\n863\n00:43:06,264 --> 00:43:10,466\nbe a binary operation, or many it's equals, the equal sign,\n二元操作，也许是等号\n\n864\n00:43:10,468 --> 00:43:12,367\nwhich is kind of a special operation, okay.\n等号是一种特殊的操作\n\n865\n00:43:12,369 --> 00:43:15,970\nSo, enums are the same. What's different about enums in Swift\nSwift 与其它语言不同的地方\n\n866\n00:43:15,972 --> 00:43:20,074\nis that they're like classes in that they can have methods.\n是它可以像 class 一样，拥有方法\n\n867\n00:43:20,076 --> 00:43:22,610\nOkay? So, I can go down here and say func,\n我可以在这里定义函数\n\n868\n00:43:22,612 --> 00:43:25,679\nyou know, something, take some arguments, return something.\n设置参数或返回值\n\n869\n00:43:25,681 --> 00:43:29,916\nI can do that down here. Okay? Enums are allowed to have\n在 Swift 中，enum 有函数是合法的\n\n870\n00:43:29,918 --> 00:43:34,454\nmethods. Now, they can't have any vars. Okay? They can have\n它不能有 var，但是它可以有\n\n871\n00:43:34,456 --> 00:43:37,290\ncomputed vars, but they can't have any storage vars because\ncomputed var（计算属性），但是它不能存储变量\n\n872\n00:43:37,292 --> 00:43:39,125\nthis is essentially their storage. Okay? The enum.\n因为这些本质是它们的空间\n\n873\n00:43:39,127 --> 00:43:44,363\nThe other thing about them is they can not have inheritance,\nenum 也不能继承\n\n874\n00:43:44,365 --> 00:43:46,431\nso you can't have an enum that inherits\n一个 enum 不能继承于另一个 enum\n\n875\n00:43:46,433 --> 00:43:49,100\nfrom another enum, which probably would be weird\n这看起来很奇怪\n\n876\n00:43:49,102 --> 00:43:51,903\nanyway. So that is not much of a restriction. Okay?\n其实这些约束也没什么的\n\n877\n00:43:51,905 --> 00:43:54,372\nThe other thing about enums is they're pass by\nenum 是通过值传递的\n\n878\n00:43:54,374 --> 00:43:57,107\nvalue and I am just going to post while I talk about that\n之后我会给你们介绍 struct\n\n879\n00:43:57,109 --> 00:43:59,876\nuntil I show you struct, which is another pass by value\n它也是通过值传递的数据结构\n\n880\n00:43:59,878 --> 00:44:03,513\ndata structure, in a moment. Okay? So, here is operation,\n这是 Operation 枚举\n\n881\n00:44:03,515 --> 00:44:07,150\nthat's great. So, now I can change pi, that's an operation\n现在可以把 pi 改成 Operation.Constant\n\n882\n00:44:07,152 --> 00:44:12,555\ndot constant. Okay? Comment that out for a second.\n先把这里注释\n\n883\n00:44:12,557 --> 00:44:17,226\nThis is also an operation of constant. This is\n这里也是 Operation.Constant\n\n884\n00:44:17,228 --> 00:44:21,797\nan operation dot unary operation. Okay?\nOperation.UnaryOperation\n\n885\n00:44:21,799 --> 00:44:26,634\nAnd this is also an operation dot uniary operation. Okay,\n这也是 Operation.UnaryOperation\n\n886\n00:44:26,636 --> 00:44:31,839\ncool. So, we can now change this Double to the type\n现在可以把 Double 改成 Operation 了\n\n887\n00:44:31,841 --> 00:44:37,311\noperation. Okay? And errors go away. These are all operations\n没有错误了。这就是 Operation\n\n888\n00:44:37,313 --> 00:44:40,848\nand it all works. Now, small problem here is that,\n这有个小问题\n\n889\n00:44:40,850 --> 00:44:45,452\nwe've lost track of the actual constants and, functions, and\n我们现在丢掉了真正的 constant 和 function\n\n890\n00:44:45,454 --> 00:44:49,322\nwe've commented them out. They're not even involved\n我们把它注释掉了，它们没有参与其中\n\n891\n00:44:49,324 --> 00:44:51,691\nhere. So, this obviously had not solved the problem.\n这显然没有解决问题\n\n892\n00:44:51,693 --> 00:44:53,793\nIt's a step on the way to solving the problem, but\n这只是解决问题中的一步\n\n893\n00:44:53,795 --> 00:44:57,496\nit has not solved the problem. All right, the other thing is,\n问题还在，还没解决\n\n894\n00:44:57,498 --> 00:45:01,767\nobviously down here, looking up constants like this and\n在这里，查询 constant\n\n895\n00:45:01,769 --> 00:45:02,834\nmaking the cumulative, this doesn't work,\n给 accumulator 赋值，都没用了\n\n896\n00:45:02,836 --> 00:45:05,636\nthis only works for constants, so we're not gonna do that.\n它只对 constant 有效，我们就不那么做了\n\n897\n00:45:05,638 --> 00:45:08,472\nSo, how do we look things up now for operations?\n所以我们怎样查找 operations 呢？\n\n898\n00:45:08,474 --> 00:45:11,241\nWell, we're gonna do a similar thing here, okay,\n这里我们做件相似的事情\n\n899\n00:45:11,243 --> 00:45:13,643\nwe're gonna say. Let, we can if,\n对 operations[symbol]\n\n900\n00:45:13,645 --> 00:45:17,414\nif let operation equal operations sub-symbol.\n进行 if let 操作\n\n901\n00:45:17,416 --> 00:45:21,250\nOkay? But, now this operation is going to be one of these.\n但是现在这个操作，将要变成这其中之一\n\n902\n00:45:21,252 --> 00:45:23,252\nOkay? It's going to be one of these enums, right?\n变成这些 enum 中的一个\n\n903\n00:45:23,254 --> 00:45:23,385\nIf I click on it,\n如果我点击它\n\n904\n00:45:23,387 --> 00:45:25,587\nyou see, it's a calculator brain dot operation.\n它是 CalculatorBrain.Operation 类型的\n\n905\n00:45:25,589 --> 00:45:29,824\nYeah, notice also I defined this enum inside this class so\n注意到，我把这个 enum 定义在了类中\n\n906\n00:45:29,826 --> 00:45:33,828\nits full name is calculator brain dot operation.\n所以它的全称是 CalculatorBrain.Operation\n\n907\n00:45:33,830 --> 00:45:35,196\nYou can nest these things.\n你可以嵌套这些东西\n\n908\n00:45:35,198 --> 00:45:38,132\nYou can even put classes inside classes if you want and\n如果你想你可以在一个类中内置另一个类\n\n909\n00:45:38,134 --> 00:45:40,000\nthey'll just, it's just a namespace thing right?\n只是命名空间的区别\n\n910\n00:45:40,002 --> 00:45:44,838\nThe names will be whatever dot whatever dot whatever. Okay?\n它的名字可能是 XXX.XXX.XXX\n\n911\n00:45:44,840 --> 00:45:45,805\nSo, I've got the operation there.\n所以我有了这些操作\n\n912\n00:45:45,807 --> 00:45:48,507\nNow, I'm going to switch on this operation, and\n对它们进行 switch 操作\n\n913\n00:45:48,509 --> 00:45:52,211\nI know that the cases can be constant. Okay?\n我知道这些 case 是常量\n\n914\n00:45:52,213 --> 00:45:54,713\nAnd, I'll just break on all these for now. So,\n我先在这里加一个 break\n\n915\n00:45:54,715 --> 00:45:59,484\nit could be a constant. It could be a unary operation.\n它可能是一个常量，也可能是一元操作\n\n916\n00:45:59,953 --> 00:46:05,356\nIt could be a binary operation. Or\n也可能是二元操作\n\n917\n00:46:05,358 --> 00:46:08,559\nit could be equals. Okay?\n也可能是等号操作\n\n918\n00:46:08,561 --> 00:46:12,029\nAnd remembering switch I have to define every single option,\n还记得我得为每一种可能的情况写 case 吗？\n\n919\n00:46:12,031 --> 00:46:14,664\nbut I don't need default here because there are only\n但这里我不需要写 default\n\n920\n00:46:14,666 --> 00:46:17,767\nfour possible things that an operation could be. So,\n因为这里只有四种可能\n\n921\n00:46:17,769 --> 00:46:21,671\nI've got a case for all of them in my switch.\n我已经在 switch 中全都处理了\n\n922\n00:46:21,673 --> 00:46:23,305\nQuestion? >> Two things.\n有问题吗？>> 两个问题\n\n923\n00:46:23,307 --> 00:46:26,141\nWhy is operation, are we not referring to the same\n为什么是 operation？\n\n924\n00:46:26,143 --> 00:46:28,543\noperation as the enum operation method?\n我们为什么不用跟 enum 中相同的 Operation\n\n925\n00:46:28,545 --> 00:46:32,313\nBecause it's not capitalized. >> Yeah,\n因为它没有大写\n\n926\n00:46:32,315 --> 00:46:33,247\nthis operation? >> Yeah.\n这个 operation 吗？\n\n927\n00:46:33,249 --> 00:46:34,014\n>> Not capitalized makes it\n没有大写是因为它是一个局部变量\n\n928\n00:46:34,016 --> 00:46:36,450\na local variable, we're making it a local variable here yeah.\n我们把它定义为了局部变量\n\n929\n00:46:36,452 --> 00:46:38,251\nAnd, actually, that's a really good opportunity for\n正好是个机会给你们讲讲\n\n930\n00:46:38,253 --> 00:46:41,054\nme to talk about how you capitalize okay?\n什么时候需要大写\n\n931\n00:46:41,056 --> 00:46:45,257\nAll types you want to be capitalized, like Calculator,\n所有的类型都要大写, Calculator\n\n932\n00:46:45,259 --> 00:46:47,459\nBrain, Dictionary, Operation, String, Double.\nBrain, Dictionary, Operation, String, Double.\n\n933\n00:46:47,461 --> 00:46:49,094\nDo you notice they all are capitalized?\n注意到它们都是大写了的吗？\n\n934\n00:46:49,096 --> 00:46:51,663\nOperate, everything, okay, is capitalized.\n类型都是大写的\n\n935\n00:46:51,665 --> 00:46:55,767\nAll local variables and vars are lowercase first letter and\n局部变量和变量的第一个字母都是小写的\n\n936\n00:46:55,769 --> 00:47:00,104\nthen capital letter for all the subsequent words in there.\n后面每一个单词的开头都要大写\n\n937\n00:47:00,106 --> 00:47:01,672\nSo it's called Camel Case, you guys know of,\n这种方式叫作驼峰式命名法\n\n938\n00:47:01,674 --> 00:47:05,909\nhave heard of that before? So, that's how you want to do\n你们之前听说过吗？\n\n939\n00:47:05,911 --> 00:47:06,943\nall your naming. If you don't do that,\n你们最好都这么命名。但如果你不这么做\n\n940\n00:47:06,945 --> 00:47:09,479\nyou're going to get in trouble with me. Okay? So, I know some\n我可能就会找你的麻烦了\n\n941\n00:47:09,481 --> 00:47:11,947\npeople like to use lower case for class names, forget it.\n我知道有些同学喜欢用小写命名类的名字，以后不要这么做了\n\n942\n00:47:11,949 --> 00:47:13,582\nYou can't do it in Swift. Just don't do it, okay.\n你不能在 Swift 中这么做。不要这么做了\n\n943\n00:47:13,584 --> 00:47:15,517\nIt'll be allowed, but you'll get in trouble, so\n你可以不用这种方式，但你会遇到麻烦的\n\n944\n00:47:15,519 --> 00:47:17,519\ndon't do it. Okay? Well,\n所以不要这么做了。好吗？\n\n945\n00:47:17,521 --> 00:47:21,155\nyou had a second question? >> Yeah.\n你还有第二个问题？\n\n946\n00:47:21,157 --> 00:47:21,722\n>> Why are we using the dot in\n为什么在 constants 中使用 . 语法\n\n947\n00:47:21,724 --> 00:47:23,991\nconstants? Are we referring to operation dot,\n我们是在引用 Operation.xx 吗？\n\n948\n00:47:23,993 --> 00:47:26,960\nokay that's my confusion. >> So, why did I say dot\n这就是我的问题\n\n949\n00:47:26,962 --> 00:47:30,096\nconstant here instead of just saying constant?\n为什么要在 Constant 前面加 . 呢？\n\n950\n00:47:30,098 --> 00:47:33,499\nAnd the answer is yeah, really we're doing operation dot\n其实我们做的事情是 Operation.Constant\n\n951\n00:47:33,501 --> 00:47:36,969\nconstant, but Swift can infer that it must be operation\n只不过 Swift 可以推导出来它是 Operation 类型的\n\n952\n00:47:36,971 --> 00:47:40,606\nbecause it knows this is an operation. Okay?\n因为它知道它就是个 Operation\n\n953\n00:47:44,845 --> 00:47:47,946\nIs that because it's within the operation's Dictionary?\n- 是因为它在一个 Operation 的字典中吗？\n\n954\n00:47:47,948 --> 00:47:48,846\n>> Its part of the enum for\n- 它是 Operation 中的一部分\n\n955\n00:47:48,848 --> 00:47:51,615\noperation, you see, operation is not really,\n不......\n\n956\n00:47:51,617 --> 00:47:53,584\nwe're not inside the Dictionary here. We pulled it\n我们现在不在一个字典中\n\n957\n00:47:53,586 --> 00:47:56,853\nalready out of the Dictionary. >> So, how does it know,\n我们把它从字典中取出来了。>>它怎么知道呢？\n\n958\n00:47:56,855 --> 00:47:59,222\nis it intelligent enough Oo distinguish even though you\n它足够智能到可以识别出它是 Operation 类型的吗？\n\n959\n00:47:59,224 --> 00:48:00,590\ncomputed a lowercase operation,\n即使你给它命名为小写的 operation\n\n960\n00:48:00,592 --> 00:48:02,458\nthat it's referring to the enum with\n它和大写的 Operation 之间\n\n961\n00:48:02,460 --> 00:48:03,325\nthe uppercase operation? >> Okay.\n也可以建立关联吗？\n\n962\n00:48:03,327 --> 00:48:06,828\nIt knows that this lowercase operation is a capital\nSwift 知道这个小写的 operation 是大写的 Operation 类型的\n\n963\n00:48:06,830 --> 00:48:10,231\noperation because I pulled it out of this Dictionary, and\n是因为我把它从一个字典中取了出来\n\n964\n00:48:10,233 --> 00:48:13,634\nit knows that that Dictionary has operations as its value.\n并且它知道这个字典是以 Operation 作为 value 的\n\n965\n00:48:13,636 --> 00:48:15,302\nSo, when I pulled out its value, it knew it.\n所以当我取值出来的时候，它知道它的类型\n\n966\n00:48:15,304 --> 00:48:19,907\nOkay? There you go. All right. So this is all going good\n懂了吧？代码很好\n\n967\n00:48:19,909 --> 00:48:23,310\nexcept for, again, we don't have the pi and the e and\n只不过我们还没有把\n\n968\n00:48:23,312 --> 00:48:24,411\nthe square root and the cosine in here.\npi，e，根号，cos 放进来\n\n969\n00:48:24,413 --> 00:48:26,979\nSo how are we gonna get those things in there? And\n我们怎么才能把它们放进来呢？\n\n970\n00:48:26,981 --> 00:48:29,215\nthe answer is, you actually already know it.\n答案是，你们其实已经知道了\n\n971\n00:48:29,217 --> 00:48:34,186\nYou've heard it before. Associated values. Okay?\n你们之前就听过。使用 Associated values（关联值）\n\n972\n00:48:34,188 --> 00:48:37,322\nRemember optional has that associated value. All\n还记得 Optional 也有关联值吗？\n\n973\n00:48:37,324 --> 00:48:41,226\nenums have associated value. In fact, optional is an enum.\nenum 也可以有。实际上 optional 就是个 enum 类型\n\n974\n00:48:41,228 --> 00:48:45,930\nOkay? This is what optional looks like if you were to look\nOptional 就长这个样子\n\n975\n00:48:45,932 --> 00:48:51,902\nat it. Enum Optional, case None, that's the nil case,\n这是 nil 的情况\n\n976\n00:48:51,904 --> 00:48:56,173\ncase Some with associated value, T. And then,\n这是有值的情况\n\n977\n00:48:56,175 --> 00:48:59,576\nthe optional is generic type. Just like Dictionary,\nOptional 支持泛型，就像 Dictionary 一样\n\n978\n00:48:59,578 --> 00:49:03,246\nit has this generic type. So this T could be any type, and\n它也有泛型，T 可以是任何类型的\n\n979\n00:49:03,248 --> 00:49:05,782\nthat's how optional works. Okay?\n这就是 Optional 的原理\n\n980\n00:49:05,784 --> 00:49:08,551\nSo, we can do the same thing down here, we could associate,\n我们也可以在这里做相同的事情\n\n981\n00:49:08,553 --> 00:49:12,521\nfor example, a Double with constants. Okay?\n我们可以把 Double 和 constants 关联起来\n\n982\n00:49:12,523 --> 00:49:14,189\nBecause constants need a Double, M under broad pi,\n因为 Constants 需要 Double 类型的 M_PI\n\n983\n00:49:14,191 --> 00:49:17,459\nwe need that thing. Okay? And so, we're doing the same thing\n在这里和 Optional 做相同的事情\n\n984\n00:49:17,461 --> 00:49:20,828\nthat optional does. Associating a value\n给 Constants 关联上一个值\n\n985\n00:49:20,830 --> 00:49:24,065\nwith our constants. So, we have this constant Double,\n所以我们已经关联上了一个 Double\n\n986\n00:49:24,067 --> 00:49:27,067\nthen here, when we declare the constant we have to provide\n在这里，声明的时候\n\n987\n00:49:27,069 --> 00:49:29,236\nthe associated value which is m under bar pi.\n把这个值和 M_PI 关联起来\n\n988\n00:49:29,238 --> 00:49:32,872\nOkay? Now we can get rid of our comment there.\n现在可以把注释删掉了\n\n989\n00:49:32,874 --> 00:49:35,942\nSame thing here, we can take this M under bar E, and\n这也一样，把 M_E 关联起来\n\n990\n00:49:35,944 --> 00:49:41,814\nassociate it with this constant, oops. Okay,\n和这个 constant\n\n991\n00:49:41,816 --> 00:49:44,883\nsee how we're doing that association? Now,\n这就是关联的方式\n\n992\n00:49:44,885 --> 00:49:48,453\nhow do we get this associated value out when we're\n但是我们怎么把这个关联的值给取出来呢？\n\n993\n00:49:48,455 --> 00:49:51,756\nlooking at a constant down here? Right, here we switched\n在 switch 这里\n\n994\n00:49:51,758 --> 00:49:54,959\non the operation, we know that this is a Constant, right?\n我们已经知道它是一个 Constant 了\n\n995\n00:49:54,961 --> 00:49:57,561\nWe looked it up in the operations Dictionary.\n我们从字典中取到了它\n\n996\n00:49:57,563 --> 00:49:59,163\nAnd we found that it's a constant,\n发现它是一个 constant\n\n997\n00:49:59,165 --> 00:50:01,298\nlet's say, like this one. How do we get it?\n我们怎样获取它的值呢？\n\n998\n00:50:01,300 --> 00:50:07,237\nYou do that by right here saying, let associated,\n你可以在这里，通过 let\n\n999\n00:50:07,239 --> 00:50:10,206\nyou know, constant, value, or whatever you want to call this\n随便起一个名字\n\n1000\n00:50:10,208 --> 00:50:12,708\nis, this is just a local variable, but you can call it\n它只不过是一个局部变量\n\n1001\n00:50:12,710 --> 00:50:17,212\nanything you want. Okay? That will make this local variable\n你可以给它起任何名字，这会让这个局部变量\n\n1002\n00:50:17,214 --> 00:50:21,683\nglom onto this associated value. okay? And\n与这个关联值连接起来\n\n1003\n00:50:21,685 --> 00:50:26,388\nso, now we can say accumulator equals the associated constant\n所以现在我们可以说 accumulator 等于 associated constant\n\n1004\n00:50:26,390 --> 00:50:30,792\nvalue. Okay? So, that's why I said switch is really\n这就是为什么我说swift很强大\n\n1005\n00:50:30,794 --> 00:50:35,596\npowerful it does this kind of pattern matching to get these\n它能够处理这样一些模式匹配的工作\n\n1006\n00:50:35,598 --> 00:50:39,800\nassociated values out, so you do that with switch. Okay.\n来取出关联的值，所以善加利用\n\n1007\n00:50:39,802 --> 00:50:42,469\nNow, associated constant value, it's kinda yucky.\n现在，这个名字有点冗长，我改成 value\n\n1008\n00:50:42,471 --> 00:50:44,838\nI'm just gonna call it value. Okay. I only called it that\n我改成value，只是为了展示\n\n1009\n00:50:44,840 --> 00:50:47,306\nlong thing just to show you it can be called anything and\n它可以被取很多名字\n\n1010\n00:50:47,308 --> 00:50:50,142\nthat it is the associated value, but you can probably\n但是的确是一个关联值，但是你可以叫它value\n\n1011\n00:50:50,144 --> 00:50:54,980\ncall it value. Okay, you got that? All right. Let's run and\n知道了吗？运行一下\n\n1012\n00:50:54,982 --> 00:50:58,050\nsee if this works. It's only going to work for constants,\n看是否工作，但它只对常数有用\n\n1013\n00:50:58,052 --> 00:51:00,819\ncuz that's the only one we're, we've done any associated\n因为我们目前只做了常数这个功能\n\n1014\n00:51:00,821 --> 00:51:03,488\nvalues for yet. But here we go, this is still working,\n看见了吗，它照常工作\n\n1015\n00:51:03,490 --> 00:51:07,692\nPi works, okay, square root, not implemented yet.\nPi起作用了，平方根，我们还没实现\n\n1016\n00:51:07,694 --> 00:51:11,929\nAll right? So, let's do square root, okay? So square root,\n现在我们来做平方根\n\n1017\n00:51:11,931 --> 00:51:13,330\nwhat would be the associated\n那么平方根应该关联于\n\n1018\n00:51:13,332 --> 00:51:19,469\nvalue of a unary operation? Don't be shy. What?\n一个一元操作数？ 不要害羞，什么？\n\n1019\n00:51:21,840 --> 00:51:25,241\nA function yes. It's a function. Okay? So,\n一个函数，对，它是一个函数\n\n1020\n00:51:25,243 --> 00:51:29,144\nhow do we make a function be associated value here? Well,\n那么我们如何让一个函数称为关联值呢？\n\n1021\n00:51:29,146 --> 00:51:30,912\nthe lucky thing is that in Swift,\n在swift种，幸运的是\n\n1022\n00:51:30,914 --> 00:51:35,150\nfunctions are types just like any other type. Okay? There's\n函数类型如同其他类型一样\n\n1023\n00:51:35,152 --> 00:51:38,953\nno differences in Swift's mind between a function type and\n在 swift 脑袋里，函数类型和 Double 类型没有任何区别\n\n1024\n00:51:38,955 --> 00:51:42,223\na Double. Exactly the same. It can be used in all the same\n完全一样，在任何场景下都能这样认为\n\n1025\n00:51:42,225 --> 00:51:45,526\ncircumstances, arguments to functions, associated values,\n函数的参数，关联值\n\n1026\n00:51:45,528 --> 00:51:49,529\nlocal variables, anything can be of type, a function. And\n局部变量，一个函数，任何东西都有类型\n\n1027\n00:51:49,531 --> 00:51:51,898\nnot only that, it's not a generic function,\n不止如此，它不是一个普通函数\n\n1028\n00:51:51,900 --> 00:51:54,967\nit's a function with certain arguments and return values.\n而是一个拥有特性参数类型和返回值类型的函数\n\n1029\n00:51:54,969 --> 00:51:56,268\nAnd how do you declare such a type?\n那么我们如何声明这种类型呢？\n\n1030\n00:51:56,270 --> 00:52:00,072\nHow do you say that that's a type here? You just type it.\n你如何表示这种类型？ 你只需要打出来\n\n1031\n00:52:00,074 --> 00:52:04,009\nSo, this is a function that takes a Double and\n那么这个函数有一个 Double 类型的输入\n\n1032\n00:52:04,011 --> 00:52:05,810\nreturns a Double. Okay?\n和一个 Double 返回值\n\n1033\n00:52:05,812 --> 00:52:08,579\nThat's the associated value of unary operation.\n这就是一元参数的关联值\n\n1034\n00:52:08,581 --> 00:52:12,516\nIt's a function. So, here when we want to associate a value,\n它是个函数，这里我们想要一个关联值\n\n1035\n00:52:12,518 --> 00:52:16,487\nwe have to put In here, just like we put a Double here for\n我把它放在这， 就像我放了一个 Double 在那一样\n\n1036\n00:52:16,489 --> 00:52:20,323\nthis one. All right? Here we have to put a function that\n所以在这里我们放一个函数\n\n1037\n00:52:20,325 --> 00:52:24,561\ntakes a Double and returns a Double like, I don't know,\n有一个 Double 输入， 返回一个 Double，我不知道\n\n1038\n00:52:24,563 --> 00:52:30,266\nsquare root. Okay? Or maybe,\n平方根，或者\n\n1039\n00:52:31,002 --> 00:52:37,506\ncosine. Okay? Everybody got that?\ncos ？大家都懂了吗？\n\n1040\n00:52:37,508 --> 00:52:38,774\nNow, same thing down here.\n现在同样的操作\n\n1041\n00:52:38,776 --> 00:52:41,176\nWe got to grab that associated value.\n我们要取出关联值\n\n1042\n00:52:41,178 --> 00:52:45,446\nSo, here I'm going to say let and again I can say associated\n在这我再 let 一个 asscociatedfuntisn\n\n1043\n00:52:45,448 --> 00:52:50,017\nfunction, but I'm just going to call this function. Okay?\n但我只打算叫它function\n\n1044\n00:52:50,019 --> 00:52:54,321\nNow I have this is a local variable of type function that\n现在我有了这个局部变量\n\n1045\n00:52:54,323 --> 00:52:57,524\ntakes a Double and returns a Double. That's its type. Okay?\n它被输入一个 Double 然后返回一个Double，这就是它的类型\n\n1046\n00:52:57,526 --> 00:52:59,225\nThat's the type of this function. In fact, watch,\n这就是这个函数的类型，事实上\n\n1047\n00:52:59,227 --> 00:53:04,964\nI'll click on it. Look at it's type. It's a function that\n看，我点击一下，看这个类型，就是\n\n1048\n00:53:04,966 --> 00:53:11,103\ntakes a Double and returns a Double.\n输入一个 Double 返回一个 Double 的函数类型\n\n1049\n00:53:11,105 --> 00:53:15,207\nHow do I use a variable like that? Accumulator.\n我怎么使用这个变量呢？  Accumulator\n\n1050\n00:53:15,209 --> 00:53:17,242\nOops, not accessor. Accumulator. Okay?\n搞错了，不是 accessor，是 Accumulator\n\n1051\n00:53:17,244 --> 00:53:21,780\nNow, again this is just a local variable.\n它只是一个局部变量\n\n1052\n00:53:21,782 --> 00:53:24,515\nI could call this foo and then I would put foo here. Okay?\n我可以叫它foo，然后我把foo放在这\n\n1053\n00:53:24,517 --> 00:53:26,717\nIts just a local variable. That's all it is. And\n它就只是一个局部变量\n\n1054\n00:53:26,719 --> 00:53:29,286\nit happens to be, its type is a function that takes\n它也只能是一个局部变量， 这个变量的类型\n\n1055\n00:53:29,288 --> 00:53:32,356\na Double, returns a Double. All right. Everybody cool with\n就是 (Double)->Double，大家都懂了吗\n\n1056\n00:53:32,358 --> 00:53:36,760\nthat? All right, let's run again, see if this is working.\n现在我们再运行一下，看看能否工作\n\n1057\n00:53:39,431 --> 00:53:44,433\nAll right so 81 square root, excellent. Okay?\n81的平方根，太好了\n\n1058\n00:53:44,435 --> 00:53:47,670\nExecuting this associated value, it looked up that\n执行了这个关联值\n\n1059\n00:53:47,672 --> 00:53:52,240\nsquare root, found that it was an Unary Operation with this\n它查询了平方根，发现平方根是对关联值的一元操作\n\n1060\n00:53:52,242 --> 00:53:55,710\nassociated value, went down here and performed operation.\n走下来，执行这个操作\n\n1061\n00:53:55,712 --> 00:53:58,346\nFound it here, grabbed that associated value,\n看这里，提取了关联值 \n\n1062\n00:53:58,348 --> 00:54:02,950\nand then I used it to update my accumulator.\n接着我用它更新了我的 accumulator\n\n1063\n00:54:02,952 --> 00:54:03,784\nQuestion? >> So, so\n什么问题？\n\n1064\n00:54:03,786 --> 00:54:07,888\nyou just specified the types and I'm surprised that you're\n你只是说明了类型，但我惊讶的是\n\n1065\n00:54:07,890 --> 00:54:11,991\nin, operation does not require [INAUDIBLE] because your\noperation不需要 ［听不见］\n\n1066\n00:54:11,993 --> 00:54:15,928\nDictionary could potentially just pull anything,\n因为字典可以提取出任意类型\n\n1067\n00:54:15,930 --> 00:54:18,197\nany kind of- >> [COUGH]\n任意值吗\n\n1068\n00:54:18,199 --> 00:54:18,564\n>> We know that Dictionary can\n我们知道字典里只有一种值\n\n1069\n00:54:18,566 --> 00:54:21,400\nonly have an operation in it, right. You can only have one\n那就是 operation，你只能有一种类型\n\n1070\n00:54:21,402 --> 00:54:25,203\nof these and this only has four possible cases.\n但这种类型有4种可能的情况\n\n1071\n00:54:25,205 --> 00:54:27,939\nEven though any given case might have any associated\n就算在任何情形下，可能有任意的关联值\n\n1072\n00:54:27,941 --> 00:54:30,841\nvalue, it's still the actual case of that operation.\n但它也必定属于这四种基本操作之一\n\n1073\n00:54:30,843 --> 00:54:32,009\nThere's only these four.\n这就四种\n\n1074\n00:54:32,011 --> 00:54:33,443\nSo down here, when I switch on it,\n所以看下来，我用下 switch\n\n1075\n00:54:33,445 --> 00:54:38,281\nI only have to cover those four cases. No more. Okay?\n我只需要搞定这四种情况\n\n1076\n00:54:38,283 --> 00:54:40,950\nAll right, what about binary operation?\n那么二元操作呢？\n\n1077\n00:54:40,952 --> 00:54:45,121\nOkay, well, binary operation, a little more complicated and\n二元操作，更加复杂一点\n\n1078\n00:54:45,123 --> 00:54:48,023\nwhy is it more complicated? Because if you think about\n为什么更复杂？ 因为你想想\n\n1079\n00:54:48,025 --> 00:54:51,893\nthe way a binary operation works like multiply, 3 times\n比如乘法的操作，3*5\n\n1080\n00:54:51,895 --> 00:54:56,331\n5 equals. Okay, when I press times I don't have enough\n等于，okay，当我按下乘号的时候，我没有足够的信息\n\n1081\n00:54:56,333 --> 00:54:59,634\ninformation to update the accumulator yet. I need the 3\n来更新我的 accumulator，我需要那个3\n\n1082\n00:54:59,636 --> 00:55:02,436\nand then the equals, it's only when the equals is hit that I\n然后那个等号，只有当等号被按下\n\n1083\n00:55:02,438 --> 00:55:05,072\nhave enough information to actually do it. So,\n我才有足够的信息来进行运算\n\n1084\n00:55:05,074 --> 00:55:06,106\nin binary operation here,\n那么对二元操作来说\n\n1085\n00:55:06,108 --> 00:55:11,044\nI'm still going to grab that binary function out of there.\n我还是需要取出二元函数\n\n1086\n00:55:11,846 --> 00:55:12,011\nI can't actually perform that function like I can here. So\n我不能像以前那样去实现\n\n1087\n00:55:12,013 --> 00:55:14,346\nOkay? But,\n\n1088\n00:55:14,348 --> 00:55:18,617\nI'm going to have to salt away that function and the operands\n但我仍需要记录下函数和操作数\n\n1089\n00:55:18,619 --> 00:55:22,053\nso far and wait til equals happens then I can do it.\n目前为止，只有按下等号键我们才能开始运算\n\n1090\n00:55:22,055 --> 00:55:24,522\nOkay? But, I still need, just like unary operation,\n但我依然需要，像一元操作一样\n\n1091\n00:55:24,524 --> 00:55:27,491\nI need to have an associated value with a binary operation.\n我需要二元操作的关联值\n\n1092\n00:55:27,493 --> 00:55:32,896\nWhat do you think that looks like? Another function,\n你觉得应该看起来像什么？其他函数形式？\n\n1093\n00:55:32,898 --> 00:55:38,435\nright, that takes two Doubles and returns a Double. Okay?\n对了，接收2个 Double 返回一个 Double\n\n1094\n00:55:38,437 --> 00:55:39,235\nLike multiply.\n就像乘法一样\n\n1095\n00:55:39,237 --> 00:55:42,972\nSo, that's just a different kind of function. Okay?\n不同地方是函数的类型不同\n\n1096\n00:55:42,974 --> 00:55:45,908\nAnd so now I can go up here and add multiply, so\n所以我现在上来添加乘法\n\n1097\n00:55:45,910 --> 00:55:50,412\nlet's go ahead and get the, a, the mathematical symbol for\n让我们继续，从这个 emoji and symbols 中\n\n1098\n00:55:50,414 --> 00:55:52,948\nmultiply out of my emoji and symbols.\n找出我们的乘号\n\n1099\n00:55:52,950 --> 00:55:56,551\nHere it is right here. Multiply, okay? And\n就在这，乘号\n\n1100\n00:55:56,553 --> 00:56:00,755\nthat is an operation tha's BinaryOperation.\n这是一个二元操作\n\n1101\n00:56:00,757 --> 00:56:03,924\nAnd look it wants a function that takes two Doubles and\n它需要一个函数，两个 Double 输入\n\n1102\n00:56:03,926 --> 00:56:07,261\nreturns a Double. So I'm gonna put a function there called\n返回一个 Double，所以我在这放一个函数\n\n1103\n00:56:07,263 --> 00:56:10,864\nmultiply, which doesn't exist in Swift, so I'm gonna have to\n取名 multiply，swift没有自带，所以我打算写在这\n\n1104\n00:56:10,866 --> 00:56:14,901\ngo write that. By the way, we have another thing here\n顺便提一下，这里还有个其他东西\n\n1105\n00:56:14,903 --> 00:56:19,105\nwhich is equals, which is Operation.Equals, okay?\n叫做等式，它也是一种操作\n\n1106\n00:56:19,107 --> 00:56:22,074\nSo i's a kind of a special operation there,\n但是它有点特殊\n\n1107\n00:56:22,076 --> 00:56:25,444\nokay? So, it's complaining here because multiply doesn't\n这里报错是因为 mutiply 并不存在\n\n1108\n00:56:25,446 --> 00:56:28,780\nexist, all right? So, I'm going to write multiply.\n在这，我就写下 multiply 了\n\n1109\n00:56:28,782 --> 00:56:31,016\nHere it is, I'm gonna make it a global function even,\n这里，我打算把它写成全局函数\n\n1110\n00:56:31,018 --> 00:56:32,984\njust like square root. Func multiply,\n就像平方根函数一样，func multiply\n\n1111\n00:56:32,986 --> 00:56:35,753\nokay, takes one argument that is a Double.\n接收一个 Double 参数\n\n1112\n00:56:35,755 --> 00:56:37,721\nTakes another argument tha's a Double.\n再接受另一个 Double 参数\n\n1113\n00:56:37,723 --> 00:56:42,459\nReturns a Double, and it just returns op1* op2,\n返回一个 Double，返回的事 op1*op2\n\n1114\n00:56:42,461 --> 00:56:45,729\nokay? So I've created this new function, multiply,\n所以我写了这个新函数，mutiply\n\n1115\n00:56:45,731 --> 00:56:50,633\nhere it is, and I can now use it right here. Sound good,\n就在这里，放在这我就可以用，很不错\n\n1116\n00:56:50,635 --> 00:56:55,371\nyou understand that? Question? >> Why is that\n你明白了吗？ 什么问题？\n\n1117\n00:56:55,373 --> 00:56:56,972\noutside. >> Yeah, so\n为什么写在外面？\n\n1118\n00:56:56,974 --> 00:56:57,539\nwhy did I put this outside?\n为什么我写在外面？\n\n1119\n00:56:57,541 --> 00:57:00,241\nBecause I wanted it be a function, a global function.\n因为我想要一个函数，全局函数\n\n1120\n00:57:00,243 --> 00:57:04,345\nNot a method in this class, okay? So I just wanted its\n不是类中的一个方法，我希望它的作用范围\n\n1121\n00:57:04,347 --> 00:57:07,048\nscope to be wider. >> So it's more of a style?\n更大一点，那么这是一个编程风格问题？\n\n1122\n00:57:07,050 --> 00:57:07,848\n>> Yeah, it's kind of a style.\n对，是一种风格\n\n1123\n00:57:07,850 --> 00:57:09,850\nA little more of a style thing. All right,\n更多是一种编程风格的事儿\n\n1124\n00:57:09,852 --> 00:57:14,187\nso so now we have this binary operation here,\n那么现在我们有二元操作了\n\n1125\n00:57:14,189 --> 00:57:18,057\nwe have to salt away the binary function like times,\n二元函数需要等待才能执行，比如乘法\n\n1126\n00:57:18,059 --> 00:57:22,561\nand the accumulator so far, the 5, in 5 times 3 equals,\n现在 accumulator 是5，然后把5乘上3\n\n1127\n00:57:22,563 --> 00:57:26,965\nthe 5 and the times we have to wait, salt them away. So\n在“5”和乘号的时候我们必须等待，把它们存起来\n\n1128\n00:57:26,967 --> 00:57:29,768\nI'm gonna salt them away in a data structure, and I'm,\n我打算用一个数据结构来存储\n\n1129\n00:57:29,770 --> 00:57:32,837\ngives me a chance to teach you another data structure.\n我将教你们另一种数据结构\n\n1130\n00:57:32,839 --> 00:57:33,237\nYou know class,\n你们知道类\n\n1131\n00:57:33,239 --> 00:57:37,041\nyou know enum, here's another one called struct. Okay?\n知道枚举，还有一种叫做结构体\n\n1132\n00:57:37,043 --> 00:57:39,309\nNow you know struct from other languages, of course.\n你当然知道其它语言中的结构体\n\n1133\n00:57:39,311 --> 00:57:44,014\nI'm gonna call this struct PendingBinaryOperationInfo,\n我打算把这个结构体叫做 PendingBinaryOperationInfo\n\n1134\n00:57:44,016 --> 00:57:47,150\nokay? And it's just gonna contain these two things I\n他只包含我想要的2个东西\n\n1135\n00:57:47,152 --> 00:57:51,187\nwant. One of them is the binary function that I'm going\n\n1136\n00:57:51,189 --> 00:57:55,124\nto do. What's the type of this? Something that\n它是什么类型？\n\n1137\n00:57:55,126 --> 00:57:58,794\ntakes two Doubles and returns a Double, that's it's type.\n接受2个 Double 返回一个 Double，这就是类型\n\n1138\n00:57:58,796 --> 00:58:00,095\nSee, I'm just declaring, that is a type,\n看，我正在声明它，这就是类型\n\n1139\n00:58:00,097 --> 00:58:03,498\nit's a type like any other type, like int, okay?\n这种类型和其他类型，比如int,没有区别\n\n1140\n00:58:03,500 --> 00:58:06,000\nWe also need to keep track of the firstOperand for\n对这个二元操作来说\n\n1141\n00:58:06,002 --> 00:58:09,403\nthis binary function, which is gonna be the accumulator so\n我们需要记下第一个操作数，把它赋给 accumulator\n\n1142\n00:58:09,405 --> 00:58:12,106\nfar. And that's gonna be of type Double, okay?\n它是 Double 类型的\n\n1143\n00:58:12,108 --> 00:58:16,510\nNow, what is a struct? Okay, we know class, we know enum,\n现在，什么是结构体？我们知道类，枚举\n\n1144\n00:58:16,512 --> 00:58:20,113\nwhat's struct? Okay, struct is very much like class.\n结构体呢？ 结构体非常像类\n\n1145\n00:58:20,115 --> 00:58:24,050\nAlmost identical, okay? It can have vars, stored vars, and\n几乎是一样的，它能有变量，存储变量\n\n1146\n00:58:24,052 --> 00:58:28,888\ncomputed vars, no inheritance, okay? But the big difference\n计算变量，但没有继承，但是\n\n1147\n00:58:28,890 --> 00:58:33,625\nbetween struct and class, is that structs, like enums,\n结构体和类最大的区别是，结构体和枚举一样\n\n1148\n00:58:33,627 --> 00:58:37,729\nare passed by value, whereas classes are passed by\n是按值传递的，类是按引用传递的\n\n1149\n00:58:37,731 --> 00:58:41,333\nreference, okay? What does that mean? All right, so\n这是什么意思？\n\n1150\n00:58:41,335 --> 00:58:45,003\npassing something by reference means that that thing lives in\n按引用传递就是它存储在堆里\n\n1151\n00:58:45,005 --> 00:58:47,972\nthe heap, okay, lives in memory somewhere, and\n内存中的某个地方\n\n1152\n00:58:47,974 --> 00:58:49,707\nwhen you pass it around to methods or\n当你把它传递给某个方法\n\n1153\n00:58:49,709 --> 00:58:52,743\nsomething like that, you're really passing a pointer\n或其他什么的，你实际上传递的是它的指针\n\n1154\n00:58:52,745 --> 00:58:55,345\nto it. And so, when you give it to someone else, they have\n你把指针传递了给去\n\n1155\n00:58:55,347 --> 00:58:58,147\nthe same one you have, because you both just have a pointer\n他们和你有同一个类，因为你们拥有的是同一个指针\n\n1156\n00:58:58,149 --> 00:58:59,849\nto the same thing that lives in the heap.\n都指向堆里存储的这个东西\n\n1157\n00:58:59,851 --> 00:59:02,384\nThat's passing by reference, okay? Hopefully you know that\n这就是按引用传递，希望你有了解过这些计算机知识\n\n1158\n00:59:02,386 --> 00:59:04,853\nmuch of computer science, that that's pass by reference,\n这就是按引用传递\n\n1159\n00:59:04,855 --> 00:59:06,755\nokay, and that's what it means in this scenario. So\n这就是一种按引用传递的场景\n\n1160\n00:59:06,757 --> 00:59:08,322\nif I had a class like calculator brain,\n如果我有一个类，像 calculator brian\n\n1161\n00:59:08,324 --> 00:59:10,858\nand I pass that brain around, I'm talking about the same\n我到处传递它，那么我一直说的是同一个\n\n1162\n00:59:10,860 --> 00:59:14,028\ncalculator brain all the time. Now I can instantiate another\ncalculator brain，现在我可以实例化另一个\n\n1163\n00:59:14,030 --> 00:59:14,861\none in the heap and have a different one,\n存储在堆中的类\n\n1164\n00:59:14,863 --> 00:59:18,665\nbut, but I'm pointing, when I create one I'm pointing to it,\n但当我实例化时，指针指向了它\n\n1165\n00:59:18,667 --> 00:59:21,834\nand I'm passing the pointer to it around. Pass by\n传递时也传递的指针\n\n1166\n00:59:21,836 --> 00:59:26,038\nvalue means that when you pass it, it copies it, okay?\n按值传递的意思就是，当你传递时，它会进行拷贝\n\n1167\n00:59:26,040 --> 00:59:29,074\nSome would think of it as it's being passed on this stack,\n有些人会认为它在栈中被传递\n\n1168\n00:59:29,076 --> 00:59:30,208\nthe call stack of the function.\n执行函数时会调用栈\n\n1169\n00:59:30,210 --> 00:59:32,577\nBut that's not necessarily how Swift implements it.\n但这不是swift的实现方式\n\n1170\n00:59:32,579 --> 00:59:35,413\nBut the semantics of it, are that it is copied.\n从语义上来说，是的它被拷贝了\n\n1171\n00:59:35,415 --> 00:59:38,816\nSo if you have a, let's say an array, which is a struct,\n那么如果你有一个，比如说数组，它是一个结构体\n\n1172\n00:59:38,818 --> 00:59:42,453\nokay? A Double is a struct, it turns out. An int is a struct.\nDouble 是一个结构体，实际上 Int 也是一个结构体\n\n1173\n00:59:42,455 --> 00:59:45,188\nA String is a struct. These are all structs, okay?\nString 也是结构体，它们全是结构体\n\n1174\n00:59:45,190 --> 00:59:48,525\nAnd so if I passed an array to some other method, and\n如果我把一个数组传递给一个方法\n\n1175\n00:59:48,527 --> 00:59:49,992\nthen I added something to that array,\n接着我在数组上添加些什么\n\n1176\n00:59:49,994 --> 00:59:53,262\nit would not be added back in the caller's array. The caller\n它不会添加到原先的数组里\n\n1177\n00:59:53,264 --> 00:59:56,131\nwould have that array without that thing added, okay,\n原先的数组不会被添加任何东西\n\n1178\n00:59:56,133 --> 00:59:59,368\ncuz it would get a copy of it. Now you would think, whoa,\n因为方法得到的是一个拷贝，现在回也许会想\n\n1179\n00:59:59,370 --> 01:00:00,769\nthis is gonna be really low performance,\n哇，这样做真没效率\n\n1180\n01:00:00,771 --> 01:00:03,371\nbecause what if I had an array of 10,000 items and\n因为，如果我有一个10,000长的数组\n\n1181\n01:00:03,373 --> 01:00:06,474\nI passed it, it's gonna copy 10,000 things. My God,\n然后我传递它了，它岂不是要拷贝10,000个元素，我的天哪\n\n1182\n01:00:06,476 --> 01:00:09,877\nmy code is just gonna grind to a halt. No, Swift is really\n我的代码会相当慢了，实际上\n\n1183\n01:00:09,879 --> 01:00:12,646\nsmart about when you pass a bi-valued struct,\n当你按值传递的时候，swift相当聪明\n\n1184\n01:00:12,648 --> 01:00:15,915\nit doesn't actually make a copy of it until you try and\n它不会真的进行拷贝，直到你真的试图使用它为止\n\n1185\n01:00:15,917 --> 01:00:19,452\ntouch it, okay? If you try and mutate it, then it'll make\n如果你试图更改，那么它会进行必要的拷贝\n\n1186\n01:00:19,454 --> 01:00:22,455\na copy as necessary, maybe not even a full copy, but\n甚至不会拷贝全部元素\n\n1187\n01:00:22,457 --> 01:00:26,225\nit'll mutate it. So if you're passing something and\n接着它会被改变，所以如果你传递了某些东西但又不使用\n\n1188\n01:00:26,227 --> 01:00:29,027\nyou don't touch it, then you are gonna be sharing it, okay?\n那么它不会被拷贝的\n\n1189\n01:00:29,029 --> 01:00:32,464\nBut, all of that is behind the scenes performance\n不过，你们的确不知道\n\n1190\n01:00:32,466 --> 01:00:34,232\nenhancement, you don't know anything about it.\n很多场景背后的性能优化\n\n1191\n01:00:34,234 --> 01:00:37,301\nFrom your point of view it copies it. Structs always get\n你们会认为他会拷贝，结构体总是被拷贝\n\n1192\n01:00:37,303 --> 01:00:40,871\ncopied, okay? Understand the difference there?\n知道其中区别了吗\n\n1193\n01:00:40,873 --> 01:00:43,173\nA very important difference between structs and classes.\n结构体和类的这个差别相当重要\n\n1194\n01:00:43,175 --> 01:00:45,141\nAnd enums are like structs. All right, so\n枚举于结构体相似\n\n1195\n01:00:45,143 --> 01:00:49,178\nI've got this right here. Now, notice that I didn't set these\n现在我们看看她，发现，我没有初始化\n\n1196\n01:00:49,180 --> 01:00:52,348\nequal to anything, but I didn't get that warning,\n但也没给我任何警告\n\n1197\n01:00:52,350 --> 01:00:57,553\nno initializers. Now usually if I put a var in a class,\n没有 initializer，通常在类里如果我的一个 var \n\n1198\n01:00:57,555 --> 01:00:58,587\nif I don't put initial, then it says,\n不进行初始化，那么会报错说\n\n1199\n01:00:58,589 --> 01:01:01,423\nno initializers, right? So, why is it not saying here?\n没有 initializer，那么为什么这里没报错？\n\n1200\n01:01:01,425 --> 01:01:05,560\nThat's because for structs, unlike classes, classes we got\n这也是结构体不同于类的一个地方，类里我们有一个\n\n1201\n01:01:05,562 --> 01:01:09,230\na free initializer. What were the arguments to it? Nothing,\n默认 initializer，它有什么参数呢？没有参数\n\n1202\n01:01:09,232 --> 01:01:11,865\nright? Like calculator brain, parenthesis, no arguments. So,\n如同 calculation brian，括号，没有参数\n\n1203\n01:01:11,867 --> 01:01:13,433\nthat's the free initializer you get for classes.\n这就是类里默认的一个 initializer\n\n1204\n01:01:13,435 --> 01:01:16,302\nFor struct, the free initializer you get,\n在结构体中，你的 initializer\n\n1205\n01:01:16,304 --> 01:01:20,940\nis an initializer that, whose arguments are all of its vars,\n的参数是这个结构体里所有的变量\n\n1206\n01:01:20,942 --> 01:01:24,176\nevery one of its vars, okay? So let's go ahead and\n每一个变量，现在我们继续\n\n1207\n01:01:24,178 --> 01:01:26,245\ncall that, because here in BinaryOperation,\n调用他，因为这里是一个二元操作\n1208\n01:01:26,247 --> 01:01:29,348\nI need to create one. So I'm gonna create a private var\n我需要新建一个，所以我新建一个私有变量\n\n1209\n01:01:29,350 --> 01:01:32,951\nhere. I'm gonna call it pending. It's gonna be of type\n我打算叫它 pending，它的类型是\n\n1210\n01:01:32,953 --> 01:01:38,756\nPendingBinaryOperationInfo, and it's gonna be an optional.\nPendingBinaryOperationInfo，并且是一个可选类型\n\n1211\n01:01:38,758 --> 01:01:40,691\nSo here I am creating my first optional.\n那么我建立了第一个可选类型\n\n1212\n01:01:40,693 --> 01:01:45,462\nIt's an optional struct, okay? Why am I making this optional?\n是一个可选结构体，为什么我要让他是可选类型？\n\n1213\n01:01:45,597 --> 01:01:47,997\nBecause this PendingBinaryOperationInfo is\n因为这个 PendingBinaryOperationInfo 只在我执行二元操作\n\n1214\n01:01:47,999 --> 01:01:51,234\nonly there if I have a pending binary operation.\n的时候才有值\n\n1215\n01:01:51,236 --> 01:01:53,502\nIf I haven't typed times or divide or something,\n如果我没有输入乘号或者除号什么的\n\n1216\n01:01:53,504 --> 01:01:56,739\nI don't have one of these, so I want this to be nil, okay?\n我没有这些东西我的话，我希望它是 nil\n\n1217\n01:01:56,741 --> 01:02:00,375\nI want this pending var that's holding this pending stuff,\n我希望这个变量在这个时刻 \n\n1218\n01:02:00,377 --> 01:02:02,677\nto be nil at that point. And then when I have one,\n是 nil 的，来表示一种没有输入的状态\n\n1219\n01:02:02,679 --> 01:02:04,612\nI'll set it to something, okay? And\n当我有了输入后，我希望它被设置成某些值\n\n1220\n01:02:04,614 --> 01:02:06,714\nthat's exactly what I'm gonna do here in BinaryOperation,\n这就是接下来我要做的事\n\n1221\n01:02:06,716 --> 01:02:11,518\nI'm gonna say, pending. That's this thing right here, okay,\n我叫它 pending，就是这个东西\n\n1222\n01:02:11,520 --> 01:02:13,520\n= PendingBinaryOperationInfo.\n等于 PendingBinaryOperationInfo\n\n1223\n01:02:13,522 --> 01:02:19,592\nAnd when I open parentheses, look. I got a constructor for\n当我输入括号，看，我有了构造函数\n\n1224\n01:02:19,594 --> 01:02:23,629\nthis PendingBinaryOperation that has these two things\n这里有两个参数\n\n1225\n01:02:23,631 --> 01:02:26,432\nas its two arguments. See, binaryFunction, and\n看， binaryFunction\n\n1226\n01:02:26,434 --> 01:02:30,736\nfirstOperand. So now I can apply these values, this is\n和 firsyOperand，现在我传入 function\n\n1227\n01:02:30,738 --> 01:02:36,108\nfunction, and the firstOperand is the accumulator. Okay, so\n给 firstOperand 传入 accumulator \n\n1228\n01:02:36,110 --> 01:02:40,478\nnow I've created one of these pending hoo-has right here,\n所以我建立起了这样的功能\n\n1229\n01:02:40,480 --> 01:02:43,014\nand that's all I've done. I pressed time, but\n我就做了这些，我按下乘号\n\n1230\n01:02:43,016 --> 01:02:46,183\nI'm doing 5 times 3 equals, I press the times, all I did was\n我计算5*3，等号，我按下乘号，我所做的\n\n1231\n01:02:46,185 --> 01:02:49,086\ncreate one of these structs, and put the times and\n就是建立了这样一个结构体，按下乘号\n\n1232\n01:02:49,088 --> 01:02:52,889\nthe 5 in there. Now in Equals, right here,\n再按下5，现在看这里的 Equals\n\n1233\n01:02:52,891 --> 01:02:56,926\nI'm gonna say if pending != nil. So\n我想说，如果 pending 不为 nil\n\n1234\n01:02:56,928 --> 01:03:00,963\nif I have a pending operation, then I'm going to evaluate it.\n那么我就在做 pending 操作，接着我再计算\n\n1235\n01:03:00,965 --> 01:03:04,000\nSo 5 times 3 equals works, but if I just say 5 equals, I\n所以5*3起作用，但如果我按下5和等号\n\n1236\n01:03:04,002 --> 01:03:07,903\ndon't have any pending times, so I'm just gonna ignore this.\n我没有输出乘号，那么我就选择忽略它\n\n1237\n01:03:07,905 --> 01:03:10,172\nSo I'm only gonna do this if I have a pending one, and\n所以如果我在 pending 的话\n\n1238\n01:03:10,174 --> 01:03:14,242\nwhat am I gonna do? Well, I'm gonna set my accumulator =,\n我会怎么做呢？我会把 accumulator设置成\n\n1239\n01:03:14,244 --> 01:03:18,813\nevaluating that pending function, which is pending!,\npending 函数的结果，就是给 pending 拆包\n\n1240\n01:03:18,815 --> 01:03:22,283\nbecause it's an optional, .binaryFunction.\n因为它是可选类型，.binaryFunction\n\n1241\n01:03:22,285 --> 01:03:27,921\nCalled with the arguments of the pending!.firstOperand, and\n用 pending!.firstOperand 和\n\n1242\n01:03:27,923 --> 01:03:33,093\nmy current accumulator. Okay,\n和当前 accumulator 作为参数调用\n\n1243\n01:03:33,095 --> 01:03:35,228\nand now pending is nil, because I no longer,\n现在 pending 是nil，因为\n1244\n01:03:35,230 --> 01:03:36,796\nI just handled that pending thing, so\n我不再需要处理接下来的输入\n\n1245\n01:03:36,798 --> 01:03:40,266\nnow I no longer have a pending operation anymore.\n所以我这里不再有 pending 操作了\n\n1246\n01:03:40,901 --> 01:03:44,870\nThat make sense? Okay, so let's go take a look and\n理解吗？ 现在看看它是否工作\n\n1247\n01:03:44,872 --> 01:03:52,811\nsee if this works. All right, here we go. Let's try,\n看，看这里，我们试试\n\n1248\n01:03:52,813 --> 01:03:55,446\nwe don't have a times button. Let's go back to our UI and\n我们还没有乘号按键，回到我们的UI\n\n1249\n01:03:55,448 --> 01:03:59,150\nadd a times button [LAUGH]. In fact, we'll add of our binary\n加上乘号，事实上，我们应该把所有二元操作按键加上\n\n1250\n01:03:59,152 --> 01:04:04,054\noperations here. Okay, so, I'm gonna just copy and paste.\n那么接下来我就是复制粘贴\n\n1251\n01:04:04,056 --> 01:04:08,225\nPut this here, paste another one. Here, we'll put all my\n放在这里，粘贴一个，我打算把所有二元操作\n\n1252\n01:04:08,227 --> 01:04:13,029\nbinary operations across the top here, paste, okay.\n都放在顶上这一栏\n\n1253\n01:04:13,031 --> 01:04:17,300\nGo here, we'll go to our emoji and symbols things.\n在这里，emoji and symbols\n\n1254\n01:04:17,302 --> 01:04:21,904\nHere's times. We'll put divide right next to times.\n这里是乘号，我们把除号放在旁边\n\n1255\n01:04:21,906 --> 01:04:27,443\nWe'll put plus right here. We'll put minus right here.\n加号放在这里，减号放在这里\n\n1256\n01:04:27,445 --> 01:04:30,145\nWe can put some other buttons down here too, like maybe\n下面也可以放一些按键\n\n1257\n01:04:30,147 --> 01:04:34,215\nwe'll put, cosine, yeah, let's put cosine in there.\n比如，放一个 cos，放在那\n\n1258\n01:04:34,217 --> 01:04:39,520\nLet's cosine. Did I have another one? E I guess I had,\n再放一个吧，我觉得应该再放一个 E\n\n1259\n01:04:39,522 --> 01:04:44,592\nright? Put E in there too. E.\n这？ 把 E 也放在这 \n\n1260\n01:04:44,594 --> 01:04:48,696\nLet's also put a equal sign. Gotta have that.\n还要放一个等号\n\n1261\n01:04:48,698 --> 01:04:52,799\nWe'll put it down here. Equal sign. And here, in this empty\n就这里了，等号，在这里\n\n1262\n01:04:52,801 --> 01:04:55,702\nspace is just begging for me to put something there.\n这个空白简直要逼死强迫症\n\n1263\n01:04:55,704 --> 01:04:59,572\nI'm gonna put period. Because in your homework,\n我打算放一个”.”在这，因为在你们的作业里\n\n1264\n01:04:59,574 --> 01:05:01,540\nyou're gonna have to add the capability to be able to\n你们需要给计算器加上使用浮点数\n\n1265\n01:05:01,542 --> 01:05:04,209\nenter floating point numbers. So you'll need this one.\n这个功能，所以你需要它\n\n1266\n01:05:04,211 --> 01:05:07,779\nSo I'll put it there for you. Okay? All right, so here's our\n我就把它放在这了，这就是我们的UI\n\n1267\n01:05:07,781 --> 01:05:12,283\nnice UI. Looks really pretty. And let's run it.\n是挺漂亮的，运行一下\n\n1268\n01:05:16,856 --> 01:05:22,026\nAll right, let's try 4 x 5 =, woo hoo, it works.\n现在我们试试 4 x 5 =，哇，起作用了\n\n1269\n01:05:22,028 --> 01:05:23,660\nA miracle the first time. Okay,\n没有 bug 的奇迹啊\n\n1270\n01:05:23,662 --> 01:05:24,728\nlet's try something a little complicated.\n现在试试更复杂一点的\n\n1271\n01:05:24,730 --> 01:05:26,563\nHow about this? Well, let's do some other things.\n这个怎么样，比如说\n\n1272\n01:05:26,565 --> 01:05:29,065\nThe square root's still working, cosine, let's play pi\n平方根也可以使用，cos，我们算算 pi\n\n1273\n01:05:29,067 --> 01:05:33,803\ncosine. That worked, cool. All right, there's E, 2.71, nice.\n的cos值，也是对的，酷，好的，现在是 E，2.71，漂亮\n\n1274\n01:05:33,805 --> 01:05:36,538\nHere's something that doesn't work though, watch this.\n但是还是有些运算不支持，看\n\n1275\n01:05:36,540 --> 01:05:38,874\n7 x 8 x 2 x 3, uh-oh,\n7 x 8 x 2 x 3，啊哦\n\n1276\n01:05:38,876 --> 01:05:43,244\nthis is not working. And this is not working because it's\n不起作用了，原因是因为\n\n1277\n01:05:43,246 --> 01:05:46,581\nrequiring me to press equals to evaluate minor operations.\n它需要我按下等号键来计算等式\n\n1278\n01:05:46,583 --> 01:05:51,252\nSo I have to go 4 x 7= x3 = x8 =, really, what I want is\n所以我需要这样 4 x 7= x3 = x8 =，我想要的是\n\n1279\n01:05:51,254 --> 01:05:55,823\nan automatic equals anytime I press a binary operation.\n在我做二元运算的任意时刻，它都能自动替我按下等号\n\n1280\n01:05:55,825 --> 01:06:00,927\nSo I can go 4 x 5, and when I go times, it doesn't equals.\n那么我就可以做 4 x 5，接着按乘号，不用按等号\n\n1281\n01:06:00,929 --> 01:06:04,898\nAnd then let me do it. So let's just do that real quick.\n让我来飞快的完成它吧\n\n1282\n01:06:04,900 --> 01:06:09,202\nLet's go back to our brain. I'm just gonna take this\n回到我们的 brain，我打算把一块\n\n1283\n01:06:09,204 --> 01:06:11,070\nlittle thing that equals uses and\nequals的实现，用一个函数来完成\n\n1284\n01:06:11,072 --> 01:06:15,207\nmake it into a function, private func, we'll call it\n并且是私有函数，我们打算叫它\n\n1285\n01:06:15,209 --> 01:06:20,045\nexecutePendingBinaryOperation. It's just gonna,\nexecutePendingBinaryOperation，只是\n\n1286\n01:06:20,047 --> 01:06:21,913\nI'm just pasting in the exact same thing.\n单纯的复制粘贴\n\n1287\n01:06:21,915 --> 01:06:26,084\nI'm gonna call that here, executePendingBinaryOperation.\n我在这调用它，executePendingBinaryOperation.\n\n1288\n01:06:26,086 --> 01:06:33,124\nAnd I'm also gonna call it here. Okay, I personally like,\n也在这调用它，因为我个人习惯\n\n1289\n01:06:33,126 --> 01:06:35,359\nif I have any of my cases that go onto second line,\n如果有任何一个 case 在第二行\n\n1290\n01:06:35,361 --> 01:06:37,928\nI like to put them all there. I just think it looks a little\n我就会把所有 case 都放在第二行，比起全部堆在一行里\n\n1291\n01:06:37,930 --> 01:06:40,630\nnicer than having sum on the end. It doesn't really matter\n更好看，这在swift里没多重要\n\n1292\n01:06:40,632 --> 01:06:44,600\nto SWF, but I just think this looks a little nicer. Okay, so\n我只是觉得好看一些而已\n\n1293\n01:06:44,602 --> 01:06:47,470\nwe did that. So that'll fix that case.\n所以我要更改所有的 case\n\n1294\n01:06:48,739 --> 01:06:53,108\nAll right, the last two things I wanna do,\n最后两件我要做的\n\n1295\n01:06:53,110 --> 01:06:58,747\nokay let's take this 4 x 7 x 8 x 9 = okay.\n就是做 4 x 7 x 8 x 9 =\n\n1296\n01:06:58,749 --> 01:07:01,115\nNow the last thing, two things I wanna do is one,\n最后两件我想要做的事情\n\n1297\n01:07:01,117 --> 01:07:05,453\nI'm gonna show you how to make, divide and plus and\n就是教给你怎么如何实现除法，加法，减法\n\n1298\n01:07:05,455 --> 01:07:08,922\nminus work without creating a whole ton of these little\n甚至不需要一堆\n\n1299\n01:07:08,924 --> 01:07:12,626\nextra functions like multiply cuz that's really gross. And\n像乘法这样的函数，因为这么做很恶心\n\n1300\n01:07:12,628 --> 01:07:15,161\nthen second, I'm gonna make our UI stretchy, so\n第二个，我要让UI更灵活\n\n1301\n01:07:15,163 --> 01:07:16,429\nit works with landscape and portrait.\n让它在横屏和竖屏都能工作\n\n1302\n01:07:16,431 --> 01:07:19,098\nOkay, those are the two things I'm gonna do. All right,\n这就是最后的两件事情\n\n1303\n01:07:19,100 --> 01:07:23,936\nso let's go ahead and make our other four operations here,\n我们继续，实现另外几个操作\n\n1304\n01:07:23,938 --> 01:07:25,270\nwhich is divide, plus and minus.\n除法，加法，和减法\n\n1305\n01:07:25,272 --> 01:07:29,541\nSo I have to bring up our emoji again. Okay, so\n我需要吧 emoji 调出来\n\n1306\n01:07:29,543 --> 01:07:34,412\nthis one will make the divide. We'll make this one be plus.\n这个是除法，这个做成加法\n\n1307\n01:07:34,414 --> 01:07:39,050\nAnd we'll make this one be minus. Okay,\n这一个是减法\n\n1308\n01:07:39,052 --> 01:07:42,686\nnow here I could have a function called divide, and\n现在我可以写一个函数叫做 divide\n\n1309\n01:07:42,688 --> 01:07:46,323\nanother one called add, another one called subtract.\n再写一个叫做 add，再写一个叫做 substract\n\n1310\n01:07:46,325 --> 01:07:49,092\nAnd then, I could go up here and make one of these for\n接着，我可以走上来，实现这几个操作\n\n1311\n01:07:49,094 --> 01:07:51,127\ndivide, and one of these for add and one. Okay, but\n一个除法，一个加法\n\n1312\n01:07:51,129 --> 01:07:54,263\nif I start doing that, what a mess. Okay, I-I've hardly even\n但如果我真的这么做了，一团糟，这样做\n\n1313\n01:07:54,265 --> 01:07:56,799\ngained anything by having this nice table of operations,\n似乎并没有善加利用这张 operations 表\n\n1314\n01:07:56,801 --> 01:07:58,400\nif I also have to have a separate function for\n如果我必须要有不同的函数去实现不同功能\n\n1315\n01:07:58,402 --> 01:08:02,404\neverything I want to do. Well, SWF is gonna take care of us\nswift有办法解决这样的需求\n\n1316\n01:08:02,406 --> 01:08:04,939\non that front because it implements closures.\n因为swift里实现了闭包\n\n1317\n01:08:04,941 --> 01:08:06,340\nHow many people know what closures are,\n你们多少人知道闭包是什么？\n\n1318\n01:08:06,342 --> 01:08:08,842\nthe computer science term closures? Okay,\n计算机科学术语，闭包？\n\n1319\n01:08:08,844 --> 01:08:12,279\nhardly anybody, whoo, okay. So a closure is basically,\n好吧，几乎没有，其实闭包基本上\n\n1320\n01:08:12,281 --> 01:08:15,015\nyou can think of it as an inline function,\n可以被看作是一个内嵌函数\n\n1321\n01:08:15,017 --> 01:08:17,483\nokay? But it's an inline function that captures\n但这个内嵌函数捕捉环境中的状态\n\n1322\n01:08:17,485 --> 01:08:20,319\nthe state of it's environment. And we're gonna see why\n我们会看到\n\n1323\n01:08:20,321 --> 01:08:21,553\nthat's important later in the quarter. But, for\n在课程后期它为什么那么重要\n\n1324\n01:08:21,555 --> 01:08:25,524\nnow, you can just focus on the inlined function part of it.\n现在，我们只关注内嵌函数这部分\n\n1325\n01:08:25,526 --> 01:08:29,527\nSo, I can actually take this multiply function, okay? I'm\n现在我选中 multiply 函数的这部分\n\n1326\n01:08:29,529 --> 01:08:32,964\njust gonna select the function without the word multiply. And\n只是选中它们，除了 multiply\n\n1327\n01:08:32,966 --> 01:08:39,670\nI'm gonna cut, and I'm gonna paste it right in here. Okay?\n然后剪切，然后粘贴在这里\n\n1328\n01:08:39,672 --> 01:08:43,407\nNow, I can't quite do that. I have to do two things. One, I\n实际上我不能直接这样，还有两件事要做\n\n1329\n01:08:43,409 --> 01:08:47,911\nhave to take this curly brace and put it at the beginning so\n第一，我要把大括号放在开头\n\n1330\n01:08:47,913 --> 01:08:51,981\nthat the arguments here is inside the curly brace,\n让参数被包含在大括号里\n\n1331\n01:08:51,983 --> 01:08:56,052\nbecause the whole closure has to have curly braces beginning\n因为闭包是以大括号开始和结束的\n\n1332\n01:08:56,054 --> 01:08:59,021\nto end. And then, since I need to separate this\n接着，为了区分前面和后面\n\n1333\n01:08:59,023 --> 01:09:03,325\nfrom the rest, I also put the word in right there. Okay, so\n我需要在中间放入一个关键词 in\n\n1334\n01:09:03,327 --> 01:09:04,359\nthat's how you make a closure.\n这就是如何使用闭包\n\n1335\n01:09:04,361 --> 01:09:05,727\nIt's exactly the same as a function, except for\n和函数是一样的，除了\n\n1336\n01:09:05,729 --> 01:09:08,596\nthe curly brace starts before the arguments and you put in\n大括号从参数前开始，并且参数后你要放一个 in\n\n1337\n01:09:08,598 --> 01:09:13,701\nafter the arguments. Got that? Now, this doesn't look, so\n知道了吗？所以\n\n1338\n01:09:13,703 --> 01:09:15,402\nthat I don't need function multiply any more.\n我不再需要这个 multiply 函数了\n\n1339\n01:09:15,404 --> 01:09:18,138\nSo this doesn't look that much better. It's still kind\n这个看起来好多了，但还是有点乱\n\n1340\n01:09:18,140 --> 01:09:23,143\nof a mess. But we're gonna use type inference, yeah, to make\n但是我们可以使用类型推断，让它看起来\n\n1341\n01:09:23,145 --> 01:09:27,413\nthis look a lot better. Now, remember that SWF knows that\n更漂亮，记住，swift 知道这个二元操作\n\n1342\n01:09:27,415 --> 01:09:30,883\nthis binary operation takes a Double, two Doubles, and\n需要两个 Double 输入，两个 Double\n\n1343\n01:09:30,885 --> 01:09:36,388\nreturns a Double. So this is all redundant, okay?\n然后返回一个 Double，所以这是多余的\n\n1344\n01:09:36,390 --> 01:09:39,991\nSWF can infer that that's a Double.\nswift能推断这是个 Double\n\n1345\n01:09:39,993 --> 01:09:40,658\nIt can infer that's a Double.\n也能推断它是 Double\n\n1346\n01:09:40,660 --> 01:09:43,728\nAnd it can infer that it re-returns a Double. So\n也能推断返回类型是一个 Double\n\n1347\n01:09:43,730 --> 01:09:47,131\nthis is wow, all of a sudden looking a lot better already,\n那么，哇，突然间看起来好多了\n\n1348\n01:09:47,133 --> 01:09:51,702\nokay? We can make this look all in one line. Okay,\n我们可以写成一行了\n\n1349\n01:09:51,704 --> 01:09:55,272\nthat's looking pretty good. I mean, that alone is probably\n看起来很不错，这看起来\n\n1350\n01:09:55,274 --> 01:09:59,142\nreally, really good. However, it gets better than that,\n依旧相当不错了，但是呢，我们还可以精简\n\n1351\n01:09:59,144 --> 01:10:02,445\nbecause closers also can have default arguments.\n因为闭包拥有默认参数名\n\n1352\n01:10:02,447 --> 01:10:06,682\nThe default argument names are $0, $1, $2,\n默认参数名是，$0，$1，$2\n\n1353\n01:10:06,684 --> 01:10:09,218\n$3, however many arguments it has.\n$3，表示有多少个参数\n\n1354\n01:10:09,220 --> 01:10:12,054\nSo you can put those as the names of the arguments\n比可以把它们当作参数名是用\n\n1355\n01:10:12,056 --> 01:10:15,724\ninstead of having op one or op two whatever you\n而不是 op1 或者 op2\n\n1356\n01:10:15,726 --> 01:10:16,657\nwant to call it. Okay?\n这种你起的名字\n\n1357\n01:10:16,659 --> 01:10:21,028\nAnd if you do this, then you don't even need that. Okay?\n如果你这么做，你甚至不需要它了\n\n1358\n01:10:21,030 --> 01:10:26,200\nIf you use the $0 and $1, and since this is a Double, and\n如果你用 $0 和 $1，因为它们是 Double\n\n1359\n01:10:26,202 --> 01:10:29,469\nSWF can infer that this return's a Double, you don't\nswift能推断它返回了一个 Double\n\n1360\n01:10:29,471 --> 01:10:33,106\nneed return right here. >> [LAUGH]\n你不需要返回了 >>[笑]\n\n1361\n01:10:33,108 --> 01:10:33,673\n>> Okay?\nOkay?\n\n1362\n01:10:33,675 --> 01:10:34,740\n>> [LAUGH]\n[笑]\n\n1363\n01:10:34,742 --> 01:10:34,973\n>> So we've cleaned up our\n我们收拾干净了这代码\n\n1364\n01:10:34,975 --> 01:10:40,912\ncode quite a bit. And in fact, now divide is just this. And\n事实上，除法也如此，加法亦然\n\n1365\n01:10:40,914 --> 01:10:47,118\nadd is just this. And subtract is just this.\n减法也是一样\n\n1366\n01:10:47,253 --> 01:10:51,055\nOkay? So that's closures. Super powerful.\n这就是闭包，非常强大\n\n1367\n01:10:51,057 --> 01:10:53,390\nUsed a lot in the iOS API. You're going to be\niOS API里用了很多，你们以后\n\n1368\n01:10:53,392 --> 01:10:56,893\nable to use it in your code to your heart's content.\n在代码中会把它当做心头好的\n\n1369\n01:10:56,895 --> 01:11:02,799\nIt's very fun. Let's make sure it actually\n非常有趣，验证一下它们是否工作\n\n1370\n01:11:02,801 --> 01:11:07,203\nworks. All right, 7 x 8 = all right,\n7 x 8 = 对的\n\n1371\n01:11:07,205 --> 01:11:12,908\ndivided by 5 equals? Looks good. minus nine equals?\n除以5等于？ 对的，减去9等于？\n\n1372\n01:11:12,910 --> 01:11:17,713\nAll right, so all of our things here are working. Okay?\n对的，所以所有东西都能工作了\n\n1373\n01:11:17,715 --> 01:11:21,483\nWe also could, so we can do that for\n我们也能对一元操作\n\n1374\n01:11:21,485 --> 01:11:23,485\nour UnaryOperations as well. What if we wanted, for\n这样做，如果我们想的话\n\n1375\n01:11:23,487 --> 01:11:27,188\nexample, something like change sign. Let's go find something\n比如，反号，我来找一下这个符号\n\n1376\n01:11:27,190 --> 01:11:30,458\nto be change sign. How about this? That's not really\n这个怎么样，虽然并不是\n\n1377\n01:11:30,460 --> 01:11:33,360\n[LAUGH] a change sign symbol, but I'm gonna use it for that.\n真正的反号，但就这样吧\n\n1378\n01:11:33,362 --> 01:11:36,563\nI could say change sign is Operation.constant, or\n这个反号是 Operation.constant\n\n1379\n01:11:36,565 --> 01:11:39,499\n.UnaryOperation, sorry. UnaryOperation and\n或者.UnaryOperation，不好意思 UnaryOperation\n\n1380\n01:11:39,501 --> 01:11:43,503\nI need a function that takes a Double returns a Double,\n我需要一个函数接受一个 Double，返回一个 Double\n\n1381\n01:11:43,505 --> 01:11:48,574\nhow about -$0. Okay, that changes the sign of\n-$0 如何? 这可以让参数反号\n\n1382\n01:11:48,576 --> 01:11:53,679\nthe one argument. And Swift is smart enough to know that this\nswift 相当聪明，知道这只有一个参数\n\n1383\n01:11:53,681 --> 01:11:58,550\nhas one argument. And that it is returning that argument and\n也知道返回参数，这个一元操作\n\n1384\n01:11:58,552 --> 01:12:00,752\nthat unary operation is Double Double, so\n是一个 Double -> Double\n\n1385\n01:12:00,754 --> 01:12:05,790\nit knows that this must be a Double. It'll even infer that.\n它知道这必然是 Double，能被推断出来\n\n1386\n01:12:05,792 --> 01:12:09,326\nOkay. All right, so that's it for our calculator brain.\n好了，这就是我们的 calculator brain 了\n\n1387\n01:12:09,328 --> 01:12:11,962\nAnd if we look back at our calculator brain and\n回头看看我们的 calculator brain\n\n1388\n01:12:11,964 --> 01:12:13,864\nthe code in it. All the code\n看下它的代码\n\n1389\n01:12:13,866 --> 01:12:15,532\nhere has nothing to do with UI.\n这些代码都与 UI 无关\n\n1390\n01:12:15,534 --> 01:12:19,969\nIt's purely about calculating and it's super-extensible.\n只是单纯地计算，并且非常易扩展\n\n1391\n01:12:19,971 --> 01:12:22,805\nIf you want to add more operations here, all you need\n你如果想加入更多操作\n\n1392\n01:12:22,807 --> 01:12:26,308\nto do is to provide the type of operation and\n只需要提供操作类型\n\n1393\n01:12:26,310 --> 01:12:28,110\nwhat's specific to that operation.\n和操作的一些细节了\n\n1394\n01:12:28,112 --> 01:12:30,845\nAll the calculation is done is this very simple\n这些计算都是非常简单的函数\n\n1395\n01:12:30,847 --> 01:12:33,881\nfunction right here, the only complexity of which is this\n唯一复杂的就是二元操作 pending 这部分\n\n1396\n01:12:33,883 --> 01:12:37,351\npending binary operation thing we have to do. By the way,\n不过它是很必要的，另外\n\n1397\n01:12:37,353 --> 01:12:41,889\nthis right here, this struct, should also be private. Okay,\n这里的 struct，也因该是私有的\n\n1398\n01:12:41,891 --> 01:12:44,458\nthis struct which is calculatorBrain.PendingBinary-\n这个 calculatorBrain.PendingBinaryinfo 结构体\n\n1399\n01:12:44,460 --> 01:12:47,127\nInfo, that's its full name, that should be private as\n它的全名，它该是私有的\n\n1400\n01:12:47,129 --> 01:12:50,063\nwell, because we're only using that internally.\n因为我们只在内部使用\n\n1401\n01:12:50,065 --> 01:12:52,398\nSame thing with this operation.\n这个 Operation 也是一样\n\n1402\n01:12:52,400 --> 01:12:52,664\nIt should be private.\n应该是私有的\n\n1403\n01:12:52,666 --> 01:12:55,634\nCuz we're not using it in our public API and same thing\n因为我们无需公布它的 API，\n\n1404\n01:12:55,636 --> 01:12:59,437\nwith this operation, should be private. Okay, should make\n这个 operations 也是一样，私有的\n\n1405\n01:12:59,439 --> 01:13:01,472\neverything private that you can make private, okay?\n尽量将所有能私有化的东西私有\n\n1406\n01:13:01,474 --> 01:13:04,909\nMake the things public that you intend to support forever\n对于你要永久支持的对象可以公有\n\n1407\n01:13:04,911 --> 01:13:09,513\nin your object. Okay? So let's do that UI thing I was telling\n现在我们来做UI\n\n1408\n01:13:09,515 --> 01:13:12,315\nyou about. Let's go back to our story board here, and\n回到 storyboard\n\n1409\n01:13:12,317 --> 01:13:14,050\nwe want to make this thing so that when we,\n我们想让他变得\n\n1410\n01:13:14,052 --> 01:13:20,490\nlet's see what it looks like now, actually. Okay,\n看看它现在的样子，实际上\n\n1411\n01:13:20,492 --> 01:13:22,224\nso our UI, we know it doesn't look very good,\n我们的 UI 不是很好\n\n1412\n01:13:22,226 --> 01:13:24,927\nthis is not lined up. This is kind of nice right here but\n他们没有连接起来，看起来是不错但\n\n1413\n01:13:24,929 --> 01:13:27,195\nit's not lined up. But what happens if we\n没有连接，如果我们横屏会\n\n1414\n01:13:27,197 --> 01:13:29,898\nrotate to landscape? The way we do that is Hardware,\n发生什么呢？ 我们从 Hardware 里去找\n\n1415\n01:13:29,900 --> 01:13:33,368\nin the simulator, Hardware > Rotate Left and Right, okay?\n在 Simulator，Hardware，Rotate Left 或者 Right\n\n1416\n01:13:33,370 --> 01:13:38,572\nI'm gonna use command keys to do it. Cmd+arrow. That really\n我用 command 键来操作，Cmd+方向键\n\n1417\n01:13:38,574 --> 01:13:43,344\nlooks bad because I can't even say equal six times four.\n看起来很糟，我用 6*4 都找不到等号键\n\n1418\n01:13:43,346 --> 01:13:45,312\nOkay. I can't even use this UI, it's so\n我不能使用这个UI\n\n1419\n01:13:45,314 --> 01:13:48,748\nbad, okay? So, we need to fix this UI so\n太糟糕了，我们需要修改UI\n\n1420\n01:13:48,750 --> 01:13:51,784\nthat when it's in portrait, it's using the whole space.\n当它横屏的时候也能使用整个屏幕空间\n\n1421\n01:13:51,786 --> 01:13:54,653\nLaying the buttons out to make it work and,\n跑到外面去的按键能工作\n\n1422\n01:13:54,655 --> 01:13:57,022\nwhen it's in landscape, it's using the whole space and\n横屏的时候也能使用整个空间\n\n1423\n01:13:57,024 --> 01:13:58,557\nthe buttons are a different shape. Okay,\n只是按键的形状不同\n\n1424\n01:13:58,559 --> 01:14:02,060\nhow are we gonna do that? Well I'm gonna do that by taking\n怎么做呢？我们要把\n\n1425\n01:14:02,062 --> 01:14:05,697\neach of these and putting them in a little stack. And then\n按键们弄成一个小整块\n\n1426\n01:14:05,699 --> 01:14:08,699\nI'm gonna take the five stacks and stack them together.\n再把5个小整块变成一个大整块\n\n1427\n01:14:08,701 --> 01:14:12,503\nAnd then I'm gonna stack this whole thing with this, okay,\n然后把大整块和这个变成一个整块\n\n1428\n01:14:12,505 --> 01:14:16,406\nand create a stack of stacks. And then I'm going to bind\n用整块堆整块，然后\n\n1429\n01:14:16,408 --> 01:14:19,709\nthe left, top, right and bottom edges of that whole\n整块的左边，上面，右边和下面的边缘与 UI\n\n1430\n01:14:19,711 --> 01:14:23,046\nthing to the outer edges of my UI. That way,\n的边缘绑定，这样\n\n1431\n01:14:23,048 --> 01:14:25,781\nwhen the outer edges of my UI change, that thing will\n当 UI 外部边缘改变的时候，它也会改变\n\n1432\n01:14:25,783 --> 01:14:27,616\nchange. And the stacks automatic gonna how to,\n整块会自动知道它如何调整\n\n1433\n01:14:27,618 --> 01:14:30,886\nyou know, reallocate the space. Okay, simple as that.\n你知道的，重新分配空间，就这么简单\n\n1434\n01:14:30,888 --> 01:14:33,154\nSo that's what we're gonna do. So let's make stacks here.\n我们将这么做，现在我们来做一个整块\n\n1435\n01:14:33,156 --> 01:14:35,723\nThe way we do that, we select the things we want to stack.\n做的方法就是，选中我们需要的元素\n1436\n01:14:35,725 --> 01:14:39,460\nWe go to editor Embed In > Stack View. Okay, and that's\n点击 editor Embed > Stack View\n\n1437\n01:14:39,462 --> 01:14:43,263\ngonna put it in a stack view here. Now, we can also go over\n这样就放在了一个 stack view 里面，我们还能\n\n1438\n01:14:43,265 --> 01:14:45,799\nto the inspector and inspect some things about this stack\n在视察窗口里面改变一些 stack view 的设置\n\n1439\n01:14:45,801 --> 01:14:50,036\nview like I want some spacing, 10 points between each one.\n比如我要一些空格，每个之间间隔 10 points\n\n1440\n01:14:50,038 --> 01:14:52,972\nAlso, you see how the cosine one is wider then the dot?\n再有，你看 cos 比其他的更宽\n\n1441\n01:14:52,974 --> 01:14:55,107\nI don't want that, I want them all the same, so\n我不想这个，我要它们看起来都一样\n\n1442\n01:14:55,109 --> 01:15:00,346\nI want it to distribute its space equally. Okay, so\n我希望他们的空间分布相同\n\n1443\n01:15:00,348 --> 01:15:01,947\nnow they're all equal. Okay,\n现在他们一样了\n\n1444\n01:15:01,949 --> 01:15:06,751\nsame thing here. Okay, 10 points, and\n这也是同样，10 points\n\n1445\n01:15:06,753 --> 01:15:10,321\nfill equally. Now, by the way, there is no command key for\nfill equally，现在这个没有快捷键\n\n1446\n01:15:10,323 --> 01:15:13,791\nthis, but you could go to Preferences over here,\n但你可以到 Preferences 里面\n\n1447\n01:15:13,793 --> 01:15:16,126\nXcode > Preferences, and go to the key bindings and\nXcode > Preferences 自定义你的快捷键\n\n1448\n01:15:16,128 --> 01:15:17,260\ngive it a command key if you wanted.\n如果你需要的话\n\n1449\n01:15:17,262 --> 01:15:19,195\nIf you were using stacking a lot, like I am,\n或者你常常使用 stack\n\n1450\n01:15:19,197 --> 01:15:23,166\nyou could do that. So let's put these in here.\n你可以这么做，现在把它们放这\n\n1451\n01:15:23,168 --> 01:15:29,739\n10, fill equally. This one. Oops.\n10，fill equally，这个，Oop\n\n1452\n01:15:32,276 --> 01:15:36,812\n10, fill equally, and this last one. [BLANK\n10，fill equally，最后一个\n\n1453\n01:15:36,814 --> 01:15:42,884\nAUDIO] All right. Now I have these five stacks right here.\n好了，现在我们有5个 stacks 了\n\n1454\n01:15:42,886 --> 01:15:46,254\nOkay, horizontal stacks. Now I'm going to take them and\n水平的 stack 现在我们要把它放\n\n1455\n01:15:46,256 --> 01:15:47,822\nput them in a stack. Okay? So\n在一个更大的 stack 里\n\n1456\n01:15:47,824 --> 01:15:51,558\nI'm going to put them in a vertical stack. [NOISE] Okay?\n这个 stack 是垂直的\n1457\n01:15:51,560 --> 01:15:56,029\nNow, these, I want, here, to all be spread out.\n我想让它们整齐分布\n\n1458\n01:15:56,031 --> 01:15:58,231\nSo right now you see the alignment is leading, so\n这边你可以看见 Alignment 是 leading\n\n1459\n01:15:58,233 --> 01:16:00,600\nit's putting all these things on the leading edge?\n就是把所有东西与最左边的框对其\n\n1460\n01:16:00,602 --> 01:16:05,037\nI want them to fill instead, so they fill the whole width.\n我想让它填充，所以，这样就一个宽度了\n\n1461\n01:16:05,039 --> 01:16:07,906\nOkay? I also want spacing here, okay?\n在这我也想要一些空间\n\n1462\n01:16:07,908 --> 01:16:10,942\n10 between all of them, so I've got kind of a nice\n中间隔开10，现在我有了好看的\n\n1463\n01:16:10,944 --> 01:16:14,045\nlittle key pad. Now let's stack this with this.\n小键盘了，现在把它与这个 stack\n\n1464\n01:16:14,047 --> 01:16:18,449\nSo I'm going to select both of these and stack. Okay,\n选中这两个，然后 stack\n\n1465\n01:16:18,451 --> 01:16:22,086\nput them in a stack together. Again, I want spacing. I want,\n把它们变成一个 stack，这里要隔开\n\n1466\n01:16:22,088 --> 01:16:24,888\ndo definitely do not want fill equally here, because that\n这里不要使用 fill equally\n\n1467\n01:16:24,890 --> 01:16:28,325\nwould make this blue thing the same height as this big stack.\n这样会让蓝色区域和小键盘一样高\n\n1468\n01:16:28,327 --> 01:16:31,561\nSo we don't want that, we just want Fill. That means they're\n我们不需要这样，只是 Fill 就可以了\n\n1469\n01:16:31,563 --> 01:16:35,331\ngonna be their natural size, okay? [COUGH] So for this,\n意味着它是一个合适的尺寸\n\n1470\n01:16:35,333 --> 01:16:38,401\nit's gonna be the size that fits this text and for this,\n这是文本框的尺寸\n\n1471\n01:16:38,403 --> 01:16:39,201\nit's gonna be a size for\n这是所有的 stack\n\n1472\n01:16:39,203 --> 01:16:42,637\nall those stacks to fit their contents. All right,\n会填充的尺寸\n\n1473\n01:16:42,639 --> 01:16:46,841\nnow I'm gonna finally use the blue lines. Okay, because I'm\n最后我终于要用到蓝色线条了\n\n1474\n01:16:46,843 --> 01:16:50,812\ngonna put this thing up in the upper-left corner right here.\n我要把这个放在左上角\n\n1475\n01:16:50,814 --> 01:16:53,581\nOkay? And I'm gonna anchor it to that corner and\n把它定位到这个角落\n\n1476\n01:16:53,583 --> 01:16:55,949\nhere's how we do that. We use the Ctrl key,\n如何做呢？ 使用 Ctrl 键\n\n1477\n01:16:55,951 --> 01:16:58,518\njust like we did when we were dragging to the code.\n就像我们拖动 UI 到代码里一样\n\n1478\n01:16:58,520 --> 01:17:01,287\nWe can also drag between elements in the UI. So,\n在 UI 里也能拖动各种元素\n\n1479\n01:17:01,289 --> 01:17:05,925\nI'm gonna drag between this, stack thing and this\n所以我打算把这个 stack\n\n1480\n01:17:05,927 --> 01:17:09,328\nouter container. So, I'm just dragging up to its top edge.\n拖动到这个 container 边缘，把它拖到顶部边缘\n\n1481\n01:17:09,330 --> 01:17:12,064\nNow when I do, when I Ctrl+drag between things,\n我拖动的时候，要按下 Ctrl 键\n\n1482\n01:17:12,066 --> 01:17:15,233\nI can constrain them to be related in some way.\n这样让 UI 与 container 边缘联系起来\n\n1483\n01:17:15,235 --> 01:17:18,203\nLike I could make them be equal widths. I can make this\n就可以使它们同等宽\n\n1484\n01:17:18,205 --> 01:17:20,705\nthing be the same width as the container view. Or\n可以让 UI 和我的 container 一样宽\n\n1485\n01:17:20,707 --> 01:17:25,209\nI can do what I want, which is constrain the vertical spacing\n或者选择我要的，就是 Vertical Spacing to Top Layout\n\n1486\n01:17:25,211 --> 01:17:27,478\nof this to the top layout. In other words,\n换句话说\n\n1487\n01:17:27,480 --> 01:17:30,514\nkind of attach that to that, so I'm gonna create that.\n像把它们固定在一起，所以我点击它\n\n1488\n01:17:30,516 --> 01:17:32,749\nAnd you can see it creates this little I-beam,\n你看一看见这个小“I”柱\n\n1489\n01:17:32,751 --> 01:17:34,717\nthis little tiny I-beam right there. Okay,\n这里的小“I”柱\n\n1490\n01:17:34,719 --> 01:17:37,520\nI'm gonna do the same thing to this edge, right here.\n同样的，对这条边也是这样\n\n1491\n01:17:37,522 --> 01:17:41,523\nI'm gonna attach the leading space to the container margin,\n我们点击 Leading Space to Container Margin\n\n1492\n01:17:41,525 --> 01:17:43,125\nokay? And I can do the same thing. Now,\n同样的，这条边也是\n\n1493\n01:17:43,127 --> 01:17:46,695\nby the way, when you do this, be careful when you Ctrl+drag,\n提一句，当你这样做的时候一定要小心\n\n1494\n01:17:46,697 --> 01:17:49,630\nyou wanna make sure the thing you're dragging from\n确保你拖住啊的是整块 stack\n\n1495\n01:17:49,632 --> 01:17:52,667\nis the entire stack. Don't be,\n而不是\n1496\n01:17:52,669 --> 01:17:55,436\nyou know, just Ctrl+dragging from this eight or it'll\n你知道的，这个8\n\n1497\n01:17:55,438 --> 01:17:58,238\nactually pin the eight to the edge. Okay, you want to pin\n不然它会把“8”拼在边缘上面\n\n1498\n01:17:58,240 --> 01:18:00,807\nthis whole stack view and I'm going to show you how you can\n我给你展示下，如何选中整块stack\n\n1499\n01:18:00,809 --> 01:18:03,543\nselect the whole stack view in a second here. Let's drag\n在一秒钟之内\n\n1500\n01:18:03,545 --> 01:18:06,278\nthis over, this is going to be the trailing space.\n拖动它，这个选trailing space\n\n1501\n01:18:06,280 --> 01:18:09,314\nOkay. And now, here I'll show you how to, if I click on\n现在我教你们\n\n1502\n01:18:09,316 --> 01:18:12,284\nthis thing right here, it's selecting the two. But I want\n如果我点了这个东西，它选中了“2”\n\n1503\n01:18:12,286 --> 01:18:15,053\nto select the whole thing, so I'm going to do Ctrl+Shift.\n但我想要一整块，按下 Ctrl+Shift\n\n1504\n01:18:15,055 --> 01:18:17,755\nCtrl+Shift, okay, see it down in the lower left there,\nCtrl+Shift，看屏幕下面\n\n1505\n01:18:17,757 --> 01:18:20,658\nCtrl+Shift? Ctrl+Shift-click. When you do that,\nCtrl+Shift，按住 Ctrl+Shift 再点击\n\n1506\n01:18:20,660 --> 01:18:24,294\nit says, what thing under the mouse do you want to select?\n这样的做的时候它会说，你的鼠标想选中什么？\n\n1507\n01:18:24,296 --> 01:18:27,864\nDo you want to select that outer container, the big stack\n你想选中Outer container， stack view\n\n1508\n01:18:27,866 --> 01:18:30,734\nview, or this little, interior stack view? So here, I want\n还是这个小的内部 stack ?\n\n1509\n01:18:30,736 --> 01:18:34,137\nthe big stack view, the one that contains the whole thing.\n在这我选择 stack view，它包含了全部按键\n\n1510\n01:18:34,238 --> 01:18:37,406\nAll right, so and then when I Ctrl+drag, I'm being careful\n所以当我按下 Ctrl 拖拽的时候\n\n1511\n01:18:37,408 --> 01:18:39,474\nnot to Ctrl+drag from one of these buttons.\n要非常小心，不要选择一个按键\n\n1512\n01:18:39,476 --> 01:18:42,110\nAnd here, I'm Ctrl+dragging from one the spaces there,\n现在我把它拖到这里\n\n1513\n01:18:42,112 --> 01:18:45,246\nokay. So this is to vertical space into the bottom.\n这里选 vertical space into the bottom\n\n1514\n01:18:45,248 --> 01:18:48,282\nAnd so now I've tied them to the edges. Unfortunately,\n现在我绑定了它们的边缘，不幸的是\n\n1515\n01:18:48,284 --> 01:18:52,386\nI've tied these two edges too far away from the edges.\n这两条边相隔太远了\n\n1516\n01:18:52,388 --> 01:18:55,489\nOkay. I wanna tie these two edges to right up next to it.\n我想让它们在彼此的旁边\n\n1517\n01:18:55,491 --> 01:18:59,325\nAnd the way I do that is, I can do it via the Inspector\n在视察窗口里就可以做到\n\n1518\n01:18:59,327 --> 01:19:02,462\nright here, by clicking on this I-beam, you see.\n点击这个小”I”柱，你可以看到\n\n1519\n01:19:02,464 --> 01:19:04,030\nThis constant saying how far it is.\n这个常数就是距离\n\n1520\n01:19:04,032 --> 01:19:06,832\nI can also Double-click on this I-beam. And\n我可以双击这个”I”\n\n1521\n01:19:06,834 --> 01:19:09,735\nit puts up a little thing here. So, I don't want her\n这里出现了一些设置\n\n1522\n01:19:09,737 --> 01:19:12,904\nto be 338 points away, I want her to be either some standard\n我不希望它们 338 那么远，想设置成一个标准值\n\n1523\n01:19:12,906 --> 01:19:15,740\nvalue, or if a standard value doesn't make sense here,\n如果标准值不行的话\n\n1524\n01:19:15,742 --> 01:19:17,608\nwhich it doesn't, that's why it's grayed out,\n事实上不能用，这就是为什么它是灰色\n\n1525\n01:19:17,610 --> 01:19:22,413\nthen I'm gonna put it 0 points away. Bam. Okay?\n那么我就在这输入0\n\n1526\n01:19:22,415 --> 01:19:25,582\nSame thing I can do down here. Let's Double-click this one.\n下面这我们可以做相同的事，双击它\n\n1527\n01:19:25,584 --> 01:19:27,817\nHere, a standard value is available, so\n这里标准值可以用\n\n1528\n01:19:27,819 --> 01:19:29,318\nI'm gonna click standard value. And\n所以我点击 standard value\n\n1529\n01:19:29,320 --> 01:19:32,655\nnow it's putting its standard value from the bottom. Okay.\n现在它把距离设置成了标准值\n\n1530\n01:19:32,657 --> 01:19:35,324\nNow, when it's stretched there, it made these tall.\n当设置成功后，这一部分变高了\n\n1531\n01:19:35,326 --> 01:19:38,894\nOkay, so that means we did something bad with our,\n这说明我们之前做错了\n\n1532\n01:19:38,896 --> 01:19:41,730\nyou know, spacing of the things, which is,\n你知道的，设置距离什么的\n\n1533\n01:19:41,732 --> 01:19:45,833\nwhat did we do wrong here? Those are all fill equally.\n我们做错了什么？ 它们 fill equally\n\n1534\n01:19:45,835 --> 01:19:49,837\nYes. How about this guy right here? Maybe this,\n对，是这个小东西吗？可能是这个\n\n1535\n01:19:49,839 --> 01:19:54,008\nthis guy fill equally. Okay we want this internal one.\n这个 fill equally，好了我们想要的就是它\n\n1536\n01:19:54,010 --> 01:19:59,012\nOkay, this internal stack view, to be fill equally.\n中间的整个 stack 就是 fill equally\n\n1537\n01:19:59,014 --> 01:20:00,914\nGlad I made that mistake, so I show you how to do that,\n挺高兴翻了这种错，这样展示给你们看\n\n1538\n01:20:00,916 --> 01:20:04,017\nokay? So, we've got this all equally spaced out. This\n现在整个 UI 分布好了\n\n1539\n01:20:04,019 --> 01:20:06,852\nlooks pretty kind of funny in a square, but I bet it's gonna\n看起来还不错的样子\n\n1540\n01:20:06,854 --> 01:20:08,654\nlook pretty good in portrait and landscape,\n我觉得横屏竖屏下应该都很好看\n\n1541\n01:20:08,656 --> 01:20:17,763\nlet's go take a look. All right here's portrait. Hey,\n我们看一眼，好了，这是竖屏\n\n1542\n01:20:17,765 --> 01:20:22,067\nthat looks pretty darn good. 4 times 8, you know, plus 9\n看起来还不错，4*8，加上9\n\n1543\n01:20:22,069 --> 01:20:27,238\nequals. Square root, okay, cosine, pi, cosine. Excellent,\n等号，根号，好的，cos，pi，cos非常不错\n\n1544\n01:20:27,240 --> 01:20:31,709\nlet's take a look at landscape, woohoo! It worked,\n看看横屏，哇哦，不错哦\n\n1545\n01:20:31,711 --> 01:20:36,213\nokay. So, very little work here. And we can make our UI\n做了点微小的工作，就可以让 UI\n\n1546\n01:20:36,215 --> 01:20:39,349\nstretchable, okay? Now, later in the quarter, we're gonna\n伸缩自如，课程后面我们会学到\n\n1547\n01:20:39,351 --> 01:20:41,751\nhave more sophisticated UIs than just these stack things,\n更多更复杂的 UI 技巧，不仅仅是这种 stack\n\n1548\n01:20:41,753 --> 01:20:45,188\nbut we'll still be using that Ctrl+dragging to the edges.\n但会一直用到 Ctrl 加拖拽\n\n1549\n01:20:45,190 --> 01:20:48,424\nNow, your homework assignment is to reproduce everything\n现在，作业就是重复我\n\n1550\n01:20:48,426 --> 01:20:49,992\nI've done in these two days.\n在过去两节课中的所有工作\n\n1551\n01:20:49,994 --> 01:20:51,493\nAdd that floating point number,\n并且加上浮点数\n\n1552\n01:20:51,495 --> 01:20:54,329\nadd a little text field that shows a history of all\n再加上一个文本框，可以显示所有\n\n1553\n01:20:54,331 --> 01:20:55,963\nthe things that have been typed in, and\n的输入信息的历史\n\n1554\n01:20:55,965 --> 01:20:58,332\nadd some more buttons. So you're gonna be doing outlets,\n添加更多的按键，所以也要做 outlet action\n\n1555\n01:20:58,334 --> 01:21:00,834\nactions, and a little bit more. And that's\n还有\n\n1556\n01:21:00,836 --> 01:21:04,705\nbasically your entire homework okay? It's all posted.\n这基本就是所有作业了，现在都发布了\n\n1557\n01:21:04,707 --> 01:21:06,873\nSee ya next week. >> For\n下个星期再见\n\n1558\n01:21:06,875 --> 01:21:06,906\nmore, please visit us at stanford.edu\n更多信息，请访问 stanford.edu\n"
  },
  {
    "path": "subtitles/3. More Swift and Foundation Framework.srt",
    "content": "1\n00:00:06,000 --> 00:00:09,060\nStanford University. >> Okay,\n斯坦福大学\n\n2\n00:00:09,070 --> 00:00:13,740\nwell welcome to lecture number three of Stanford CS193P.\n欢迎来到斯坦福 CS193P 课程第三讲\n\n3\n00:00:13,740 --> 00:00:17,410\nThis is spring quarter 2016. And today we\n这是 2016 年春季\n\n4\n00:00:17,410 --> 00:00:22,140\nare going to mostly talk about the layer under the UI.\n今天我们主要会介绍UI 层\n\n5\n00:00:22,150 --> 00:00:24,450\nOkay, so we're gonna talk about Swift the language.\n我们会讨论Swift 这门语言\n\n6\n00:00:24,450 --> 00:00:26,950\nWe're gonna talk about this foundation framework that\n我们将会讨论位于核心服务层顶部的foundation 框架\n\n7\n00:00:26,950 --> 00:00:29,550\nlives on top of Core services. So we're not going to be\n所以我们不会讨论一整天非常多关于UI 的内容\n\n8\n00:00:29,550 --> 00:00:32,920\ntalking about the UI very much at all today. I do have a demo\n在接近尾声的时候会有一个demo\n\n9\n00:00:32,920 --> 00:00:36,490\ntowards the end. So I will finish off the slides and\n我会完成这些幻灯片然后我们把这个演示做完\n\n10\n00:00:36,490 --> 00:00:40,090\nthen we'll do the demo to finish. Okay, all right, so\n好的\n\n11\n00:00:40,100 --> 00:00:43,200\nfirst thing I want to talk about is optional's,\n首先我想介绍的是 optional\n\n12\n00:00:43,200 --> 00:00:46,030\nby the way, everything I am talking about today is\n顺便说下 我今天介绍的所有东西\n\n13\n00:00:46,040 --> 00:00:49,340\nin your reading assignments. Okay, I'm just, the things I\n都在你们的阅读作业里。好的\n\n14\n00:00:49,340 --> 00:00:52,040\nam talking about today I want to emphasize. I mean these\n我想强调我今天介绍的东西\n\n15\n00:00:52,040 --> 00:00:54,280\nare things that you really really want to understand.\n我的意思是这些东西你们真的真的需要理解\n\n16\n00:00:54,280 --> 00:00:56,880\nSo if you see me mention it today and then you're reading\n如果你在你的阅读作业里读到我今天提到的东西\n\n17\n00:00:56,880 --> 00:00:59,950\nit in the reading assignment, be sure to pay close attention\n确保密切关注好吗？\n\n18\n00:00:59,950 --> 00:01:02,920\nall right? So as we learned in the last lecture,\n那在我们上节课学的内容中\n\n19\n00:01:02,920 --> 00:01:07,020\noptional is just an enum, okay? It's a generic type kind\noptional 就是一个 enum 是吧？它是一个有点像数组的泛型\n\n20\n00:01:07,020 --> 00:01:09,190\nof like array. It's got this little angle bracket T,\n它有个小尖括号 <T>\n\n21\n00:01:09,190 --> 00:01:11,530\nwhich just means an Optional can be an Optional of any\n这意味着 Optional 可以选择任何类型\n\n22\n00:01:11,530 --> 00:01:14,000\ntype. And we know that to be the case. We can have\n并且我们知道的情况\n\n23\n00:01:14,000 --> 00:01:17,000\nOptional strings or Optional even Optional optionals.\n我们可以有Optional sting 甚至是Optional 的 Optional\n\n24\n00:01:17,000 --> 00:01:19,530\nWe can have any kind of Optional we want. And so\n我们可以选择任何我们想要的 Optional\n\n25\n00:01:19,540 --> 00:01:22,400\nit's an enum with two cases. The None case which is the not\n所以这是一个有两种情况的 enum。\n\n26\n00:01:22,410 --> 00:01:25,710\nset case and then the Some case, which is the set case.\nNone 情况是没有设置东西，其它情况是设置了一些东西的\n\n27\n00:01:25,710 --> 00:01:27,780\nAnd in the Some case it has an associated value. And you\n在一些情况下它有关联值\n\n28\n00:01:27,780 --> 00:01:31,450\nlearned all about enums last time. So this, syntax should\n你们上次学了的关于枚举的内容\n\n29\n00:01:31,450 --> 00:01:37,220\nlook completely, familiar to you. So let's look at some\n所以这个语法对你们来说应该是完全熟悉的\n\n30\n00:01:37,220 --> 00:01:40,250\nof the little question mark, exclamation point stuff. And\n让我们来看看这些小问号，惊叹号\n\n31\n00:01:40,260 --> 00:01:43,060\nwhat that means in terms of optional behind the scenes. So\n在这些场景背后它们和optional 的关系是什么\n\n32\n00:01:43,060 --> 00:01:47,060\nif you had a constant x which was of type optional string,\n如果你有一个常量 x 它的类型是optionl 字符串\n\n33\n00:01:47,060 --> 00:01:48,460\nright, string question mark.\n对，字符串问号\n\n34\n00:01:48,470 --> 00:01:53,330\nAnd I set it to nil, then that's the same as saying that\n然后我把它设置为nil ，这等同于是说 x = Optional<s>.None</s>\n\n35\n00:01:53,340 --> 00:01:58,310\nx = Optional<s>.None, right? Obviously, and same</s>\n对吗？显然， 的情况一样\n\n36\n00:01:58,310 --> 00:02:00,940\nthing if I had an optional string that was set to hello,\n如果我有一个可选字符串设置成hello\n\n37\n00:02:00,940 --> 00:02:04,880\nthat'd be the same as x=Optional<s>.Some</s>\n那就等于x=Optional<s>.Some</s>\n\n38\n00:02:04,880 --> 00:02:07,150\nwith the associated value, hello. Okay,\n关联的值是hello。 好的\n\n39\n00:02:07,150 --> 00:02:10,690\neverybody cool with that? And similarly, if I unwrap,\n大家都觉得这很酷吧？类似的，假如我拆包\n\n40\n00:02:10,690 --> 00:02:15,120\nif I said, var y=x unwrapped, that just means switch x,\n如果我说，var y=x!，就等于switch x\n\n41\n00:02:15,130 --> 00:02:17,390\nbecause we know that the way we unwrap Optionals and\n因为我们知道我们那样子拆包Optionals\n\n42\n00:02:17,390 --> 00:02:19,560\nget their associated value is with switch, so\n所以我会打开x 并用开关得到相关的值\n\n43\n00:02:19,560 --> 00:02:22,400\nI'm gonna switch on x. And in the case of Some, I'm gonna\n在一些情况下，我会用let 值\n\n44\n00:02:22,400 --> 00:02:25,670\ndo that let value thing so I can grab the associated value.\n因为这样我可以抓取相关的值\n\n45\n00:02:25,670 --> 00:02:28,470\nAnd then I'm just gonna set y equal to that value.\n然后我要设置y 等于那个值\n\n46\n00:02:28,470 --> 00:02:30,100\nIn the case None, I'm gonna crash.\n在空的情况下，我的程序会crash\n\n47\n00:02:30,110 --> 00:02:32,740\nI'm gonna raise an exception, okay, because that's what\n我要提出一个列外\n\n48\n00:02:32,740 --> 00:02:35,540\nunwrapping an Optional that's not said is supposed to do,\n因为拆包一个Optional 不意味着它应该这么做\n\n49\n00:02:35,550 --> 00:02:40,450\nit's supposed to crash, okay? And of course, in the case\n它应该让程序崩溃。\n\n50\n00:02:40,450 --> 00:02:44,420\nwhere I'm doing if let, then I'm just gonna switch on x,\n如果我用let 这么做，然后我去switch x\n\n51\n00:02:44,420 --> 00:02:47,190\nand I'm, the case of .Some, I'm gonna grab that y, and\n在 .Some 情况下我用y 拿出 x 的值\n\n52\n00:02:47,190 --> 00:02:49,720\nthen I'm just gonna put some code, whatever my code is in\n然后就会执行我放在下面的代码\n\n53\n00:02:43,731 --> 00:02:46,899\nthere, and if let to happen there. And in the case None,\n然而在None 的情况下\n\n53\n00:02:52,900 --> 00:02:54,660\nI just break out of the switch, I do nothing.\n我会直接跳出switch 什么都不做\n\n54\n00:02:54,660 --> 00:02:59,700\nOkay, sound good? All right, so that's Optionals.\n听起来不错？ 这就是Optionals\n\n55\n00:02:59,700 --> 00:03:01,370\nHopefully Optional now should start feeling very,\n希望现在开始对Optional 的感觉好点了\n\n56\n00:03:01,370 --> 00:03:03,340\nvery comfortable to you cuz, as you found out,\n在这些API 里面\n\n57\n00:03:03,340 --> 00:03:07,640\nit's everywhere in these, in the API. Now Optionals have\n你会发现到处都有舒服的提示\n\n58\n00:03:07,640 --> 00:03:10,710\nsome more syntax, okay. That question mark and exclamation\n现在Optionl 有更多的语法了。你看见的那些问号和感叹号\n\n59\n00:03:10,710 --> 00:03:13,880\npoint stuff, as you're seeing, is just syntactic sugar.\n都是语法糖\n\n60\n00:03:13,880 --> 00:03:16,720\nIt's just to make the, your typing it in easier and\n这是为了让你写起来更舒服并且更好看\n\n61\n00:03:16,720 --> 00:03:20,590\nlook nicer. It has a little bit more syntactic sugar.\n它还有更多的语法糖\n\n62\n00:03:20,590 --> 00:03:24,660\nOne thing is that Optionals can be chained. Okay, so\n比如Optional 可以是链式的\n\n63\n00:03:24,660 --> 00:03:26,460\nthis is the case where, for example,\n如同这个例子的情况\n\n64\n00:03:26,460 --> 00:03:29,530\nin our calculator, we have the display, and\n在我吗的计算器例子里，我们有显示，\n\n65\n00:03:29,530 --> 00:03:34,340\nlets say we want to get the text out of the display. And\n让我们把一些想要得到的文本显示出来\n\n66\n00:03:34,340 --> 00:03:38,070\nthen we want to send another message like hash value which,\n然后我们想传递一些信息，比如哈希值，\n\n67\n00:03:38,070 --> 00:03:40,110\nstrings understand this message hash value,\n这些消息哈希后的字符串\n\n68\n00:03:40,110 --> 00:03:43,380\nhow would we do that? Well of course we would say,\n我们该如何做呢？\n\n69\n00:03:43,380 --> 00:03:47,180\nif let label equal display to unwrap the display. And\n我们会这样，如果让 label 等于 display 这样去拆包 display\n\n70\n00:03:47,180 --> 00:03:50,020\nthey we would say if let text equal the labels text,\n然后我们会让text 等于label 的 text\n\n71\n00:03:50,020 --> 00:03:54,020\nand unwrap that. Then we would say let x equal the text hash\n拆包之后，我们在让x 等于text 哈希后的值\n\n72\n00:03:54,020 --> 00:03:56,820\nvalue, okay? So that is how we would unwrap it.\n所以，这就是我们如何去拆包这些信息\n\n73\n00:03:56,830 --> 00:03:59,730\nWell there is a lot easy way to do it which is this,\n当然还有很多更容的方法来做\n\n74\n00:03:59,730 --> 00:04:02,700\nyou just say display?.text?.hashvalue,\n你可以这样display?.text?.hashvalue\n\n75\n00:04:02,700 --> 00:04:08,540\nokay? So if you use question marks when you're, not when\n如果你在这个时候用 ？ 而不是在声明optional 类型时使用\n\n76\n00:04:08,540 --> 00:04:11,640\nyou're declaring the optional but when you're actually using\n这基本上意味着\n\n77\n00:04:11,640 --> 00:04:14,840\nit, that basically means, try and unwrap this and\n尝试去把它们拆包\n\n78\n00:04:14,840 --> 00:04:18,380\nif you can then use that value to go to the next thing.\n拆包后的值是否可以让你去到下一部分\n\n79\n00:04:18,380 --> 00:04:21,650\nIf you can't, just return nil from this whole expression.\n如果不行，整个表达是就返回nil\n\n80\n00:04:21,650 --> 00:04:23,150\nOkay, this whole display question mark,\n这个dispaly 后面所有的问号，\n\n81\n00:04:23,150 --> 00:04:24,590\nthat typed question mark, that hash value,\n那个哈希值\n\n82\n00:04:24,590 --> 00:04:27,790\nthat whole expression will return nil if at any point\n如果它们当中有任何一点在拆包的时候返回了nil\n\n83\n00:04:27,790 --> 00:04:31,630\nany of these things that were changing unwrap turns out to\n这整个表达式就会返回nil\n\n84\n00:04:31,630 --> 00:04:35,000\nbe nil. So, if the display is nil or if the display's text\n所以，如果display 是空的，或者display 的text 是空的\n\n85\n00:04:35,000 --> 00:04:37,470\nis nil then this whole thing is gonna be nil.\n那这整个就会变成nil\n\n86\n00:04:37,470 --> 00:04:41,870\nSo you see let x equal up there? What type do you think\n所以你看见让x 等于它们\n\n87\n00:04:41,870 --> 00:04:46,970\nx is right there? >> [INAUDIBLE].\n这里的x 是什么类型的 [讨论]\n\n88\n00:04:46,980 --> 00:04:48,780\n>> Int? almost.\nInt? 差不多。\n\n89\n00:04:48,780 --> 00:04:51,780\nOptional int, exactly. It has to be optional int, because\n对，是optional int 类型\n\n90\n00:04:51,780 --> 00:04:54,520\nany of those things could fail and it would return nil.\n因为任何其它东西都可能失败并返回nil\n\n91\n00:04:54,520 --> 00:04:55,520\nSo it has to be able to take nil. So\n所以它可以是nil 值\n\n92\n00:04:55,520 --> 00:04:59,320\nthat would be an optional int, cuz hash value returns an int,\n因为它可以返回一个int 的哈希值，所以它是一个可选int\n\n93\n00:04:59,320 --> 00:05:03,120\nokay. So you're definitely gonna wanna use this,\n你肯定会想用这种链条一样的方式去编程\n\n94\n00:05:03,130 --> 00:05:05,990\nchaining, it really makes your code read beautifully, okay.\n它真的让你的代码看起来漂亮了\n\n95\n00:05:06,000 --> 00:05:09,000\nAnd the starts make Optionals make a lot of sense why we use\n当我们开始使用可选类型的时候会有很多场景去使用它们\n\n96\n00:05:09,000 --> 00:05:11,630\nthem so much. Okay, but there's more.\n好的，但是还有别的用法\n\n97\n00:05:11,630 --> 00:05:14,640\nHere's another Optional syntaxtiture which is ??\n这里是Optional 的另一种用法叫做 ？？\n\n98\n00:05:14,640 --> 00:05:18,970\nOkay, and this is basically providing a default value\n它基本上是在 case 为 nil 的时候提供一个默认的值\n\n99\n00:05:18,980 --> 00:05:22,640\nin case something is nil. Okay, so let's add an optional\n来添加一个可选字符串s\n\n100\n00:05:22,650 --> 00:05:27,380\nstring here s, okay. I could say if s is not nil,\n我可以说，如果s 不是空\n\n101\n00:05:27,380 --> 00:05:30,120\nthen I'm gonna set my display to be s, okay.\n然后我会把我的display 设置成 s\n\n102\n00:05:30,120 --> 00:05:32,920\nSo let's say I'm setting the display in my calculator, and\n这意味我在我的计算器上设置了显示\n\n103\n00:05:32,920 --> 00:05:36,060\nI never want it to be nil. At worst, I want it to be just\n而且我不想让它是空的，最差也得是个空格字符\n\n104\n00:05:36,060 --> 00:05:38,690\na space character. Because you might have noticed,\n因为你可能注意到了\n\n105\n00:05:38,700 --> 00:05:40,490\nsome of you when you're doing your homework,\n当你在做你的一些作业的时候\n\n106\n00:05:40,500 --> 00:05:43,000\nthat if you put nil into a label,\n如果你往 label 里面放了 nil\n\n107\n00:05:43,000 --> 00:05:45,670\nits size will go to zero. Okay,\n它的尺寸会变成0\n\n108\n00:05:45,670 --> 00:05:50,070\ncuz there's no text in there to have a natural size for. So\n因为没有文本它就不会有一个默认的尺寸\n\n109\n00:05:50,070 --> 00:05:52,870\nsometimes you might want to have a code like this where if\n所以有时候你可能想要一些这样的代码\n\n110\n00:05:52,880 --> 00:05:54,310\nyou want to put nothing in the display,\n如果你往display 里面放了空的东西\n\n111\n00:05:54,310 --> 00:05:57,080\nyou put a space character, so at least there's something in\n你就放一个空格字符，因为这样至少这里有东西让 label 有高度\n\n112\n00:05:57,080 --> 00:06:00,920\nthere for it to have a height, okay? Otherwise your display\n否则你设置成nil 的话\n\n113\n00:06:00,920 --> 00:06:03,980\nwould keep disappearing if you kept setting it to nil. So\n你的display 可能会消失\n\n114\n00:06:03,990 --> 00:06:06,890\nwe can do this, if s does not equal nil then display equals\n那么我们可以这样，如果s 不等于nil 就让display 等于s\n\n115\n00:06:06,890 --> 00:06:09,460\ns, that should be s exclamation point right there,\n用 != 表示不等于\n\n116\n00:06:09,460 --> 00:06:12,260\notherwise display equals a space. Okay, well,\n否则就 display 就等于一个空格\n\n117\n00:06:12,260 --> 00:06:15,000\na much simpler way to put that is with this,\n有一个更简单的方法\n\n118\n00:06:15,000 --> 00:06:19,430\ndefaulting operator, which is to say the display.text\n让display.text = s\n\n119\n00:06:19,440 --> 00:06:24,170\n= s Okay? And that means if s is not nil then unwrap it and\n这表示如果s 不为空，就把它拆包\n\n120\n00:06:24,170 --> 00:06:27,680\nuse that value, otherwise use space.\n然后就使用拆包后的值，否则就使用空格\n\n121\n00:06:28,710 --> 00:06:31,850\nGot that? Everyone understand? I don't see any nodding heads\n懂了吗？每个人都懂了吗？我没有看就有人点头\n\n122\n00:06:31,850 --> 00:06:34,680\non that one. Make sense, okay? So this is, again, just\n懂了吗？再说一遍\n\n123\n00:06:34,680 --> 00:06:38,920\na simple way to have a default value in case an optional is\n这是让 optional 在 nil 的情况下有一个默认值的简单的方法\n\n124\n00:06:38,920 --> 00:06:43,490\nnil. All right so let's talk about another thing, tuples.\n继续介绍另一东西，元组。\n\n125\n00:06:43,490 --> 00:06:47,960\nAll right tuples are a type, okay? In Swift they're really,\n元组是一种类型，在 Swift 中它们非常酷\n\n126\n00:06:47,960 --> 00:06:51,670\nreally cool. They're basically a way to build a type out of\n它们是一种构建类型外的类型的基本方法\n\n127\n00:06:51,670 --> 00:06:54,170\nother types by grouping them, okay? And\n好的\n\n128\n00:06:54,170 --> 00:06:56,840\nyou can use it anywhere you can use a type, a tuple can be\n你可以在任何地方用一个类型\n\n129\n00:06:56,840 --> 00:07:01,640\nused anywhere types are valid, okay? So, here's an example.\n一个元组在任何地方使用都是可以的，好的。这里有一个例子\n\n130\n00:07:01,640 --> 00:07:06,010\nI'm going to create x, okay? This let x, x is a constant.\n我要生成一个x 好的。这是let x，x 是一个常量\n\n131\n00:07:06,020 --> 00:07:09,950\nIt's type is a tuple, with a string, int, and\n这是一个元组类型，含有 string, int, 和 double\n\n132\n00:07:09,950 --> 00:07:14,020\ndouble. So, even though tuple has the sound, to, in it,\n尽管元组听起来有 two 的声音\n\n133\n00:07:14,020 --> 00:07:17,190\nit's just not two things. Any number of things can be in\n但并不是他有只有两个东西。一个元组里面可以有任何数量的东西\n\n134\n00:07:17,190 --> 00:07:22,460\na tuple okay? So x there is a tuple with string int and\n好的，所以 x 是一个含有 string int double 的元组\n\n135\n00:07:22,470 --> 00:07:24,700\ndouble. And I'm even setting it to a value,\n我甚至可以往里面设置值\n\n136\n00:07:24,700 --> 00:07:28,240\nwhich is just parenthesis, a string, an int, and a double,\n用括号包起来一个 string 一个 int 和一个 double\n\n137\n00:07:28,240 --> 00:07:33,070\nokay? Now how do I get those values out of the tuple?\n好的。现在我该如何从这个元组里面获得值呢\n\n138\n00:07:33,080 --> 00:07:34,480\nWell there is two ways to do it.\n嗯。有两种方法\n\n139\n00:07:34,480 --> 00:07:38,950\nOne is to say, let and then three, identifiers. These\n一种，分配三个id\n\n140\n00:07:38,950 --> 00:07:41,920\nare basically three local variable names, equals x,\n它们是基于三个本地变量来命名的，等于 x\n\n141\n00:07:41,920 --> 00:07:45,320\nokay? And that's gonna extract the three values and put them,\n好的，然后会取出三个值并保存到它们里面去\n\n142\n00:07:45,320 --> 00:07:48,320\nassign them to word, number, and value, which are gonna\n分别放在 word，number，和 value 里\n\n143\n00:07:48,320 --> 00:07:51,330\nbe local variables in this context, okay? Now, if you\n它们会在这个上下文里得到本地变量。好的，现在\n\n144\n00:07:51,330 --> 00:07:55,730\ntried to say let word, comma, number, closed parentheses,\n如果你尝试 let (word, number) = x\n\n145\n00:07:55,730 --> 00:08:00,170\nequal x, the compiler will complain, because word, comma,\n编译器是会出错的\n\n146\n00:08:00,170 --> 00:08:04,040\nnumber can't match a string in double tuples. Okay? So\n应为 word, number 无法和元组里的 double 关键字匹配。好的\n\n147\n00:08:04,040 --> 00:08:07,610\nthis particular syntax is just putting names on the things in\n这一部分的语法就是把这些东西放到这些命名里面\n\n148\n00:08:07,610 --> 00:08:11,510\nthe Tuple so you can use them, so now you can print them out.\n你可以这样使用元组，所以你现在可以把它们打印出来了\n\n149\n00:08:11,510 --> 00:08:12,580\nPrint word. Print number. Print value.\nPrint word. Print number. Print value.\n\n150\n00:08:12,580 --> 00:08:16,520\nValue would be of type string. Number would be of type int\nword 会是 string 类型，Number 会是 int 类型\n\n151\n00:08:16,520 --> 00:08:18,120\nand value would be of type double. Okay,\n还有 value 会是 double 类型，好的\n\n152\n00:08:18,120 --> 00:08:22,090\nanother way to do it is when you create the tuple, okay,\n另一种这么做的方法是，当你在生成元组时，好的。\n\n153\n00:08:22,090 --> 00:08:24,830\nyou can name each of the things in the tuple. So\n你可以为元组里的每个东西命名。\n\n154\n00:08:24,830 --> 00:08:31,070\nhere I'm letting x, this time be w: String i: Int v: Double.\n这里我对x 的string 命名为w，Int 命名为i，Double 为v\n\n155\n00:08:31,070 --> 00:08:34,640\nI'm giving the names w, i and v to the things inside\n我在元组里面分别起了几个名字叫 w，i 和 v\n\n156\n00:08:34,640 --> 00:08:37,240\nthe tuple. I'm still assigning it, just like I did in\n我继续给它赋值，就好像我在之前做的一样\n\n157\n00:08:37,240 --> 00:08:40,340\nthe version above. But now if I want to get at the values,\n但是现在，如果我想要得到一个值\n\n158\n00:08:40,340 --> 00:08:45,550\nI can just say x.w, x.i, and x.v to get at the tuple\n我可以直接说 x.w，x.i，还有 x.v 来获得元组中的值\n\n159\n00:08:45,550 --> 00:08:48,250\nvalues. See the difference between those two cases?\n看出这两种方法的不同之处了吗?\n\n160\n00:08:48,250 --> 00:08:51,090\nOne, you're kind of naming it when you declare the tuple,\n一种，在你声明元组的时候定义一种命名\n\n161\n00:08:51,090 --> 00:08:53,920\nthe other one is you're taking a tuple that you got and\n另一种是你拿到一个元组\n\n162\n00:08:53,920 --> 00:08:56,620\nyou're just extracting the values. And you can mix them.\n然后你就取出值。并且你可以混合使用它们\n\n163\n00:08:56,630 --> 00:08:59,690\nFor example I could say let = x.\n比如我可以说 let = x\n\n164\n00:08:59,700 --> 00:09:02,100\nEven though I defined it x to have w, i and v,\n尽管我给 x 定义了 w, i 和 v\n\n165\n00:09:02,100 --> 00:09:05,370\nI could ignore the w, i and v and instead just do\n我可以忽略它们\n\n166\n00:09:05,370 --> 00:09:10,800\nthe syntax from the top okay and call it wrd, num and val.\n用 word， number 和 value 执行上面那种语法\n\n167\n00:09:10,810 --> 00:09:15,340\nOkay? So, tuples are cool because you can return\n好的。所以，tuple 是很酷的\n\n168\n00:09:15,340 --> 00:09:18,750\nmultiple values from a function with a tuple. Okay?\n因为你可以从一个 function 中返回一个有多个值的 tuple\n\n169\n00:09:18,750 --> 00:09:22,750\nSo, we know that returned values are arrow and a type.\n所以，我们知道返回的值指向一个类型\n\n170\n00:09:22,750 --> 00:09:25,520\nWell, since a tuple can be a type, you can go arrow and\n好的，当 tuple 可以是一种类型的时候\n\n171\n00:09:25,520 --> 00:09:27,660\na tuple, and return values. Yeah?\n你可以去指向这个类型，并返回它们的值，对吗？\n\n172\n00:09:27,660 --> 00:09:28,260\n>> Can you ignore some of\n[学生提问]\n\n173\n00:09:28,260 --> 00:09:29,320\nthe values? >> So, question,\n所以，问题是\n\n174\n00:09:29,330 --> 00:09:30,560\ncan you ignore some of the values?\n你可以屏蔽这些值中的一部分吗？\n\n175\n00:09:30,560 --> 00:09:33,590\nAbsolutely you can, if you use underbar. Underbar and\n显然是可以的，你可以使用 underbar\n\n176\n00:09:33,600 --> 00:09:37,230\nswift is the universal I'm ignoring this character, okay,\nswift 里的 underbar 是普遍的，在这一章我先不讲，好的\n\n177\n00:09:37,230 --> 00:09:41,670\nso you can put underbar in there. So yeah, so\n所以你可以把值放在这里，\n\n178\n00:09:41,670 --> 00:09:44,070\nhere I'm returning this tuple weight and\n返回一个有宽度和高度的tuple\n\n179\n00:09:44,070 --> 00:09:47,210\nheight, obviously straight forward how we do that.\n显然我们可以直接坐到\n\n180\n00:09:47,210 --> 00:09:50,010\nSo tuples are perfectly valid return values, okay? So\n所以tuple 用来返回值是非常有效的，好的。\n\n181\n00:09:50,010 --> 00:09:52,910\nyou can return multiple things from functions. All right,\n所以你可以从函数返回多个值\n\n182\n00:09:52,920 --> 00:09:56,850\nrange. So range is quite important, actually,\n好的，range 。range 在Swift 里是非常重要的\n\n183\n00:09:56,850 --> 00:10:00,960\nin Swift. It's essentially just two end points,\n它基本上就是两个结束点\n\n184\n00:10:00,960 --> 00:10:05,330\nokay, of anything that can be representative consecutively,\n好的，它可以代表任何连续的东西\n\n185\n00:10:05,330 --> 00:10:10,560\nokay? So range, the type, is generic, like array,\n所以，range ，这种类型是普通的，就好像数组\n\n186\n00:10:10,570 --> 00:10:13,230\nso you can have a range of ints. You can have\n所以你可以有一个 int 的 range。\n\n187\n00:10:13,240 --> 00:10:16,900\na range of indexes into something or whatever it\n你可以有一个某些东西内部的索引范围\n\n188\n00:10:16,910 --> 00:10:20,240\nreally conceptually just has two things, a startIndex and\n或者其它只要有两个东西的连续的东西。有一个起始索引和一个结束索引\n\n189\n00:10:20,240 --> 00:10:25,310\na last index, okay, endIndex. An array's range, okay.\n一个数组的 range，好的\n\n190\n00:10:25,310 --> 00:10:27,950\nIf you wanted to get an array, arrange into an array,\n如果你想要得到一个数组中部分范围的数组\n\n191\n00:10:27,950 --> 00:10:28,880\nit would be a range of ints,\n可以用一个 int 型的 range\n\n192\n00:10:28,880 --> 00:10:30,950\nbecause an array is indexed by ints.\n因为数组的索引是根据int 来的\n\n193\n00:10:30,950 --> 00:10:34,220\nSo you would have a range of ints. In fact you know,\n所以你应该有一个int 的range。\n\n194\n00:10:34,220 --> 00:10:36,720\nyou, there are methods in array where you can say, give\n实际上你知道，在array 里你可以调用一些方法\n\n195\n00:10:36,730 --> 00:10:41,900\nme this range of yourself, and you specify it as a Range.\n提供它们你要指定的范围\n\n196\n00:10:41,900 --> 00:10:47,600\nA string's range is not Int. Okay, if you wanna substring,\n一个字符串的范围不是Int。 好的，若果你想要子字符串\n\n197\n00:10:47,600 --> 00:10:50,440\nyou cannot use a range of Int. It's actually a range of\n你不能使用Int 的range。它实际上是一个String.Index 的range\n\n198\n00:10:50,440 --> 00:10:53,740\nString.Index, which is a different type than Int. And\n它有着和Int 不同的类型\n\n199\n00:10:53,740 --> 00:10:57,680\nyou're gonna need to read all about that in the assignment,\n而且你都会在你的作业里读到这些的\n\n200\n00:10:57,680 --> 00:10:59,310\nokay? One of the section's in assignment is\n好的，作业里面面有一章讲的是\n\n201\n00:10:59,320 --> 00:11:01,720\nindexing into arrays in the ring assignment.\n环形数组中的索引\n\n202\n00:11:01,720 --> 00:11:03,550\nAnd you're gonna wanna understand that, okay?\n你们要去理解那个，好吗\n\n203\n00:11:03,550 --> 00:11:05,790\nIt's a little bit complicated. I'm not gonna spend\n这有一点点复杂。我不能花太多课上的时间\n\n204\n00:11:05,790 --> 00:11:07,420\nlecture time but just I'm pointing it out to you,\n但是我会为你们指出它来\n\n205\n00:11:07,420 --> 00:11:10,820\nso you could go look at it. Okay? Now, there's special,\n所以你们可以去看看，好吗？现在\n\n206\n00:11:10,830 --> 00:11:12,790\njust like with optionals we've got question marks and\n有点特殊，想好像optional 的问号和叹号\n\n207\n00:11:12,800 --> 00:11:16,360\nexclamation points. There's some special syntax for\nrange 有一些特殊的语法\n\n208\n00:11:16,370 --> 00:11:20,070\nranges, okay, which is this ...and ..<.\n比如 ... 和 ..<\n\n209\n00:11:20,070 --> 00:11:24,910\nYou see them right here? Okay the... ..<!--? Okay?\n你们可以看到吧 ... 和 ..<\n\n210\n00:11:24,910 --> 00:11:28,810\nThis means a range right here, okay, that goes from 2 to 3.\n这在这里表示一个 range，那个是从 2 到 3\n\n211\n00:11:28,810 --> 00:11:33,980\nThis is a range that goes from 2 to 3 but does not include 3.\n这是从 2 到 3 但不包含三\n\n212\n00:11:33,980 --> 00:11:37,420\nOkay? So that would be just the number 2, right there.\n好的，所以那里讲会有两个数字\n\n213\n00:11:37,420 --> 00:11:40,050\nOkay? Now, see this 4 right here?\n好的，现在，看这第四行\n\n214\n00:11:40,060 --> 00:11:45,130\n4 loops in swift all are 4 in like this.\nSwift 中的循环都可以向第四行这样\n\n215\n00:11:45,130 --> 00:11:50,500\nSo if you wanted to go for I equals 1, 2, 10 I plus plus or\n如果你想要从 1 加到 2 加到 10 或者加到任何你想要的数值\n\n216\n00:11:50,500 --> 00:11:54,000\nwhatever you would so that with these, ranges like this,\n你就可以这样使用range\n\n217\n00:11:54,000 --> 00:11:58,810\nokay, for IN 27 to 104 or whatever. Okay? And\n好的，从27 遍历到104 或者任何其他范围。好的\n\n218\n00:11:58,810 --> 00:12:03,040\nyou can make ranges that are more powerful than just direct\n比起直接使用range 你可以用更有力的方法起使用range\n\n219\n00:12:03,050 --> 00:12:06,510\nranges. I can't talk about that really on time wise, but\n我不能花太多时间讨论这个\n\n220\n00:12:06,520 --> 00:12:09,080\nagain check the documentation and\n但是在次检查文档的时候你会看到range 的超出\n\n221\n00:12:09,090 --> 00:12:13,050\nyou'll see out of the ranges, okay? So that's when you see\n所以，到那时你就会看到了\n\n222\n00:12:13,060 --> 00:12:17,120\nthat. Okay, let's talk about data structures in Swift.\n好的，来谈一谈Swift 中的结构体\n\n223\n00:12:17,130 --> 00:12:19,160\nI'm talking about classes, structures and enums.\n我在讨论类，结构体，和枚举\n\n224\n00:12:19,160 --> 00:12:22,500\nOkay, you've already seen them in the example. I'm gonna\n好的，你们已经在例子里看到它们了\n\n225\n00:12:22,500 --> 00:12:25,030\ntalk about the similarities and the differences.\n谈一谈它们的相同和不同\n\n226\n00:12:25,030 --> 00:12:27,500\nSo what's similar between class, struct and enum,\n所以，在class，struct 和enum 之间有什么相似之处呢\n\n227\n00:12:27,500 --> 00:12:30,270\nthey're declared the same way, right? Just a keyword,\n它们都用相同的方式声明对吧。\n\n228\n00:12:30,270 --> 00:12:33,270\nthe name of the thing and then curly braces.\n就同这个东西的名字作为关键字，然后收起它们\n\n229\n00:12:33,280 --> 00:12:35,980\nThey all serve like that way. They're also similar and\n它们都提供类似的方法。\n\n230\n00:12:35,980 --> 00:12:37,310\nthat they can also have properties and\n它们也都可以有属性和方法\n\n231\n00:12:37,310 --> 00:12:40,250\nfunctions. Okay? So you can have functions on there,\n所以你可以在这里有方法和属性\n\n232\n00:12:40,250 --> 00:12:43,280\nand you can have properties. Enums cannot have stored\nEnum 不能保存属性\n\n233\n00:12:43,290 --> 00:12:46,150\nproperties. Only structs and classes can have stored\n只有结构体和类可以存储属性\n\n234\n00:12:46,160 --> 00:12:50,160\nproperties but enums can have computed properties. Okay?\n但是枚举可以包含计算属性\n\n235\n00:12:50,160 --> 00:12:52,830\nThe storage of an enum remember is the cases.\nenum 存储的是case\n\n236\n00:12:52,830 --> 00:12:55,730\nIt's a discrete value thing so it's the cases and\n所以它的case 和它们的相关值\n\n237\n00:12:55,730 --> 00:12:58,530\ntheir associated values that's the storage.\n是分开存储的\n\n238\n00:12:58,870 --> 00:13:02,140\nAll right they all can have initializers.\n当然它们都可以初始化\n\n239\n00:13:02,140 --> 00:13:03,940\nOkay, we haven't talked much about initializers yet.\n好的，我们还没讨论很多关于初始化的东西\n\n240\n00:13:03,940 --> 00:13:07,540\nWe're gonna get that today. Eh, so they're all allowed\n我们今天会来说一说。额\n\n241\n00:13:07,540 --> 00:13:09,910\nto have initializers except enum. Okay,\n所以它们除了enum 都可以初始化\n\n242\n00:13:09,910 --> 00:13:12,280\nobviously enum doesn't need an initializer because you just\n显然enum 不需要初始化\n\n243\n00:13:12,280 --> 00:13:16,320\nset it to the discrete value with its associated values.\n应为你是是设置了一些离散的值和它们相关的值\n\n244\n00:13:16,320 --> 00:13:20,450\nOkay? All right. Differences. One, inheritance. Okay?\n好的。当然，不同之处，一：继承\n\n245\n00:13:20,460 --> 00:13:24,860\nWith classes, you can inherit, structs and enum you can't.\n在类中，你可以继承，结构体和枚举不行\n\n246\n00:13:24,860 --> 00:13:27,930\nValue types, I talked about this before, okay? Structs and\n我在这之前介绍过值的类型\n\n247\n00:13:27,930 --> 00:13:30,860\nenum are value types. They're passed around by value.\n结构体和枚举是值的类型。它们通过值来传递\n\n248\n00:13:30,870 --> 00:13:33,970\nClass is a reference type. You pass pointers to it around. It\n类是一种引用类型。通过指针来传递\n\n249\n00:13:33,970 --> 00:13:37,910\nlives in the heap. Okay? Let's talk a little more about value\n它们保存在堆中。好的，来讨论更多关于值和引用\n\n250\n00:13:37,910 --> 00:13:42,780\nversus reference. Value means that it's copied when passed\n值意味着当它作为参数传递个方法是它是个拷贝\n\n251\n00:13:42,780 --> 00:13:45,980\nas argument to a function, that's kind of obvious. But\n这是显而易见的\n\n252\n00:13:45,980 --> 00:13:50,480\nit also copies when you assign it to another variable.\n当你把它分配个另一个变量时它也会拷贝\n\n253\n00:13:50,490 --> 00:13:54,250\nIf I say var x = y if y is a value type,\n如果我说var x = y 如果y 是一个值类型\n\n254\n00:13:54,260 --> 00:13:55,560\nx will be a copy of y.\nx 会是一个y 的拷贝\n\n255\n00:13:55,560 --> 00:14:00,260\nA copy, so if y is an array y might be an array. Okay? And\n所以如果y 是一个array\n\n256\n00:14:00,260 --> 00:14:04,430\nyou say, x equals y. And then you say, x append this thing,\n然后你说x = y 接着用x 拼接一些东西\n\n257\n00:14:04,430 --> 00:14:07,370\nthat thing will not be appended to y. Because x\n这些东西不会被拼接到 y 上去\n\n258\n00:14:07,370 --> 00:14:11,070\nwas a copy of y. You see what I'm talking about there? Okay.\n应为 x 是 y 的一个拷贝。你们明白我在说什么吗？好的\n\n259\n00:14:11,070 --> 00:14:12,910\nSo that's a big difference with value semantics.\n所以这是它们之间的一个特别大的不同\n\n260\n00:14:12,910 --> 00:14:17,880\nEven just assigning them, is a copy of them. A value symantec\n甚至个它们赋值也是对它们的拷贝\n\n261\n00:14:17,880 --> 00:14:22,780\nthing is immutable if it's signed to a let variable.\n一个用let 分配的值是不可变的\n\n262\n00:14:22,790 --> 00:14:24,480\nOkay? So if you have an array okay,\n如果你有一个数组\n\n263\n00:14:24,490 --> 00:14:26,990\nsince that value symmentic cuz an array is a struct.\n因为array 是一个 struct\n\n264\n00:14:26,990 --> 00:14:30,220\nIf you assigned to a let, let x equal an array you cannot\n如果你给一个let 赋值，让let x 等于一个数组\n\n265\n00:14:30,230 --> 00:14:33,930\nappend things on to that array cuz it is immutable. Okay,\n那你就不能往这个数组上面拼接东西，因为 x 是不可变的\n\n266\n00:14:33,930 --> 00:14:38,170\nsame thing with the dictionary or whatever. Okay. Remember\ndictionary 或者其它东西在这一点上也是相同的\n\n267\n00:14:38,170 --> 00:14:40,300\nthe function parameters. All of them are constants so\n记住那些方法的参数，它们都是常量\n\n268\n00:14:40,300 --> 00:14:44,670\nof course you'd copy them into there, you can't modify them.\n所以你得把它们拷贝进来，你不能修改它们\n\n269\n00:14:45,110 --> 00:14:48,580\nBecause of the way copy symmentics work, Swift makes\n由于copy 的工作方式\n\n270\n00:14:48,580 --> 00:14:52,650\nyou when you do have a struct or enum you have to mark all\nSwift 会让你在那些struct 或者enum 里面\n\n271\n00:14:52,650 --> 00:14:55,920\nfunctions that might change that thing. Mutating functions\n把可能会改变的方法标记出来\n\n272\n00:14:55,920 --> 00:15:00,590\nwith the keyword mutating. So like mutating func whatever.\n用mutating 关键字来表示可变方法。\n\n273\n00:15:00,590 --> 00:15:02,820\nOkay? If that function could change that struct.\n如果那个方法可以改变他的结构体\n\n274\n00:15:02,830 --> 00:15:05,790\nAnd the reason for that is when Swift copies it\n当Swift 拷贝它的时候\n\n275\n00:15:05,790 --> 00:15:08,430\nit doesn't want to actually make a copy. Okay?\n它实际上是不会制作一个备份的\n\n276\n00:15:08,430 --> 00:15:11,430\nIt gets another pointer to it but as soon as you try to\n在你试图去改变它的时候\n\n277\n00:15:11,430 --> 00:15:15,370\nmutate it then it's gonna have to copy it. You see? So\n会用一个指针指向它并拷贝这个指针\n\n278\n00:15:15,370 --> 00:15:17,640\nit's kind of a performance enhancement. So\n所以这是一种性能提升\n\n279\n00:15:17,640 --> 00:15:20,310\nany time you have a struct that has a function that\n一旦你的结构体里的方法改变了它的值\n\n280\n00:15:20,310 --> 00:15:22,910\nchanges the values, any of the values of the struct,\n这结构体里的任何一个值\n\n281\n00:15:22,910 --> 00:15:25,580\nyou have to put mutating in front so Swift knows\n你必须在 Swift 知道你这么做之前将它变为可变的\n\n282\n00:15:25,580 --> 00:15:30,220\nthat you're doing that. Okay, reference types, okay.\n好的，引用类型\n\n283\n00:15:30,220 --> 00:15:30,850\nThis is what you're used to,\n可能这就是你所用到的\n\n284\n00:15:30,850 --> 00:15:32,390\nprobably. Things are stored in the heap.\n东西存放在了堆里\n\n285\n00:15:32,390 --> 00:15:35,790\nYou have a reference to them. Those references are counted\n你有一个他们的引用，那些引用会被自动计数\n\n286\n00:15:35,790 --> 00:15:39,730\nautomatically. That means there's no garbage collection\n这意味着在Swift 中是没有垃圾回收机制的\n\n287\n00:15:39,730 --> 00:15:42,430\nin Swift. All right, there's no mark and sweep in\n当然，它们没有标记的时候回从堆里面被清除\n\n288\n00:15:42,430 --> 00:15:45,370\nthe heap. Every single time you create a new pointer to\n每当你创建一个新的指针指向堆里的某个东西时\n\n289\n00:15:45,370 --> 00:15:47,200\nsomething in the heap Swift keeps track of that and\nSwift 会把这个痕迹保存下来增加一个计数值\n\n290\n00:15:47,200 --> 00:15:49,970\nit keeps incrementing a count. And when that count goes down\n然后当计数值成为零的时候\n\n291\n00:15:49,970 --> 00:15:53,070\nto zero because maybe the last pointer that's pointing to it\n可能是最后一个指针不再指向它了\n\n292\n00:15:53,080 --> 00:15:56,140\ngoes out of scope or maybe you assign that last pointer to\n或者这最后的指针指向了其它什么东西\n\n293\n00:15:56,150 --> 00:15:58,910\npoint to something else. Nothing points to it.\n这块内存不再被指向的时候\n\n294\n00:15:58,910 --> 00:16:00,510\nIt immediately removes that from the heap.\n它会立马从堆里面被删除\n\n295\n00:16:00,520 --> 00:16:03,850\nOkay, predictably removed from the heap immediately.\n好的，可以预见会很快的从堆里面移除\n\n296\n00:16:03,850 --> 00:16:06,320\nSo, it's very different than garbage collection, where\n所以，这和垃圾回收机制非常不同\n\n297\n00:16:06,320 --> 00:16:08,960\ngarbage collection is kind of going on in the background,\n垃圾回收是一种在后台运行\n\n298\n00:16:08,960 --> 00:16:10,960\nand it might collect a whole bunch from the heap,\n一次性手机一整串堆里的东西\n\n299\n00:16:10,960 --> 00:16:13,390\nall at once. That's been sitting around for a while.\n那会等上一段时间\n\n300\n00:16:13,400 --> 00:16:13,830\nThis is predictable,\n这是可以预测的\n\n301\n00:16:13,830 --> 00:16:16,460\nmemory management and it's all managed for you. Okay,\n这是你可以管理的内存管理\n\n302\n00:16:16,470 --> 00:16:19,200\nthere's only one way that you participate in that, which is\n你要参与其中只有一种方法\n\n303\n00:16:19,200 --> 00:16:22,740\nthe weak and strong, which I'll be talking about later,\n使用weak 和strong。我过会向你们解释\n\n304\n00:16:24,370 --> 00:16:26,970\nokay? Let's see, constant pointers.\n好的，来看指针常量\n\n305\n00:16:26,980 --> 00:16:28,680\nOkay, if you have a constant pointer to a class,\n如果你在一个类里有一个指针常量\n\n306\n00:16:28,680 --> 00:16:31,680\nobviously it's a pointer, so you're still mutating it,\n显然这是一个指针，所以你依然能修改它\n\n307\n00:16:31,680 --> 00:16:35,520\nright? It's not like a struct where if I say var y = x and\n对吗？ 这不像我说的var y = x 的那种结构\n\n308\n00:16:35,520 --> 00:16:38,190\nthen I add something to y, it doesn't modify x.\n当我想要给 y 加点什么的时候，这并不会修改 x\n\n309\n00:16:38,190 --> 00:16:41,560\nIf I say var y = x and they're classes, then if I send\n若果我说 var y = x 而且它们都是类\n\n310\n00:16:41,560 --> 00:16:44,220\na message to y, it's sending a message to x because they're\n然后如果我想 y 发送消息，这会个 x 发送一个消息，因为它们是同一个东西\n\n311\n00:16:44,230 --> 00:16:46,630\nthe same thing. Right they, that same thing lives in\n同一个在堆里保存的东西\n\n312\n00:16:46,630 --> 00:16:50,700\nthe heat. There's no copying, so let, all let means is that\n没有拷贝，所以let\n\n313\n00:16:50,700 --> 00:16:53,430\npointer's not going to change. It doesn't\n所有的let 意味着那个指针是无法被修改的\n\n314\n00:16:53,440 --> 00:16:56,370\nmean what the pointer points to won't change.\n这不意味着指针指向的东西无法被修改\n\n315\n00:16:56,810 --> 00:17:01,380\nOkay obviously so when you pass a pointer to a class\n显然，当你把指针当做一个参数传递给类的时候\n\n316\n00:17:01,380 --> 00:17:04,440\nas an argument, then it does not make a copy, it's just\n它不会产生一个拷贝\n\n317\n00:17:04,450 --> 00:17:08,580\npassing a pointer. Okay. Now how do you know which to use?\n它就传递了一个指针。好的，现在你知道该怎么用了吗？\n\n318\n00:17:08,580 --> 00:17:10,120\nStruct versus class, specially.\n特别的，结构和类\n\n319\n00:17:10,120 --> 00:17:13,890\nOkay, enum is pretty obvious. But struct versus class well.\nenum 是很明显的。除了结构和类\n\n320\n00:17:13,890 --> 00:17:15,890\nUsually you're gonna choose class over struct.\n通常你会在类和结构中选一个\n\n321\n00:17:15,890 --> 00:17:17,790\nOkay. Because this is object oriented program.\n因为这是面向对象编程\n\n322\n00:17:17,790 --> 00:17:19,630\nYou use to do it and that's going to be fine.\n你这样使用会更好一点\n\n323\n00:17:19,630 --> 00:17:22,360\nStruct is gonna be used for more fundamental types.\nStruct 更多被用作基础类型\n\n324\n00:17:22,360 --> 00:17:25,370\nOkay, things like strings and doubles, and ints and arrays\n向是string 和double ，int 和array 在diction 里\n\n325\n00:17:25,370 --> 00:17:28,500\nin dictionaries, and also for drawing, points, rectangles.\n也会为了绘图有点，矩形\n\n326\n00:17:28,500 --> 00:17:30,740\nDo you see what I'm saying, smaller things that\n你知道我在时候什么，一个更小的独立的东西\n\n327\n00:17:30,740 --> 00:17:33,840\nare self-contained, that it makes sense to copy by value.\n用在需要复制值的场景上\n\n328\n00:17:33,840 --> 00:17:36,340\nYou want the value semantic, that's gonna be your primary\n你要这值的语言。当你在传递这值的时候\n\n329\n00:17:36,350 --> 00:17:38,110\nreason for choosing struct as you want values\n你想要这些值的语义\n\n330\n00:17:38,110 --> 00:17:41,950\nsemantics when you're passing this thing around. Otherwise,\n会成为你选在struct 的主要原因\n\n331\n00:17:41,950 --> 00:17:45,090\nyou're gonna choose classes, okay? Anything big is almost\n否则你就选类\n\n332\n00:17:45,090 --> 00:17:50,660\ncertainly gonna use the class, all right? Okay.\n任何大型的东西肯定会使用类，对吗？\n\n333\n00:17:50,660 --> 00:17:53,730\nOn the methods. So now we are gonna talk about the syntax\n好的。在这些方法里，我们要来说说这些方法的语法\n\n334\n00:17:53,730 --> 00:17:57,360\nof methods. Okay, I showed you this in class a little bit but\n在这个类里我会展示一点\n\n335\n00:17:57,370 --> 00:18:00,370\nI'm gonna talk about the full semantics here of it.\n我还会介绍它在这里的完整的语义\n\n336\n00:18:00,370 --> 00:18:04,140\nSo interesting about the naming of functions, so\n这些方法的命名挺有趣的\n\n337\n00:18:04,140 --> 00:18:06,870\nhere is someone defining a method and here is someone\n这里定义了一个方法\n\n338\n00:18:06,880 --> 00:18:10,440\ncalling this method. Okay? Okay, so watch this colored\n这里调用了这个方法。好的？好，在我讨论这几种东西的时候\n\n339\n00:18:10,450 --> 00:18:15,280\nstuff going on as I talk about these various things going on.\n注意这些高亮的部分\n\n340\n00:18:15,280 --> 00:18:19,650\nSo all parameters to functions have an internal name and\n所有方法的参数都有一个内部的名字和一个外部的名字\n\n341\n00:18:19,660 --> 00:18:21,620\nan external name, every single parameter.\n是每一个参数都有\n\n342\n00:18:21,620 --> 00:18:24,590\nSo here's the first parameter, here's the second parameter,\n那么这里是第一个参数，这里是第二个参数\n\n343\n00:18:24,590 --> 00:18:28,300\nthey both have an external name and an internal name.\n它们都有一个外部的名字和一个内部的名字\n\n344\n00:18:28,300 --> 00:18:31,200\nOkay? The external name comes first. Internal name comes\n好的。先说外部名字，在说内部名字\n\n345\n00:18:31,200 --> 00:18:35,640\nsecond. The internal name is the name of the local\n内部名字是在你的方法里面的本地变量的命名\n\n346\n00:18:35,640 --> 00:18:39,770\nvariable that's gonna be used inside your method.\n\n347\n00:18:39,780 --> 00:18:41,540\nAll right? So that's this one right here,\n所以这就是内部命名\n\n348\n00:18:41,540 --> 00:18:44,880\ninternal name. Shows up right before the colon. Okay?\n就是出现在这冒号之前的东西\n\n349\n00:18:44,880 --> 00:18:46,750\nFirst and second. You can see how first and\n第一个和第二个\n\n350\n00:18:46,750 --> 00:18:50,720\nsecond are the names I used for those inside my function.\n你可以看到在我的方法里我是如何给第一个和第二个起名的\n\n351\n00:18:50,720 --> 00:18:53,090\nDon't appear anywhere here. Notice first and\n不要出现在别的地方。\n\n352\n00:18:53,090 --> 00:18:56,660\nsecond do not appear in the funk bar call. Okay,\n注意第一个和第二个不在方法块后面出现\n\n353\n00:18:56,660 --> 00:19:00,190\ncuz those are the internal names. The external name\n因为它们是内部的名字\n\n354\n00:19:00,200 --> 00:19:04,760\nis what the caller uses when they call this method. Okay,\n外部名字是这个方法的调用者使用的。\n\n355\n00:19:04,770 --> 00:19:09,200\nso you can see bar down there. It says externalFirst: 123,\n你可以看到这里有个下划线。这表示 外部第一个参数：123，\n\n356\n00:19:09,200 --> 00:19:14,170\nexternalSecond: 5.5, right? Okay, it's using the external\n外部第二参数：5.5，好的\n\n357\n00:19:14,180 --> 00:19:16,110\nnames. first and second never appear but\nfirst和second并没有出现\n\n358\n00:19:16,110 --> 00:19:19,480\nfirst and second are still used in the implementation,\n但first和second在代码实现中仍然被使用了，\n\n359\n00:19:19,480 --> 00:19:22,850\nthose in the internal names. Okay,\n可以在方法里用它们的内部名字\n\n360\n00:19:22,850 --> 00:19:26,020\nyou can put an under bar if you don't want callers\n如果你不想让你的传递参数使用外部的名字\n\n361\n00:19:26,020 --> 00:19:30,560\nto use an external name at all for a given parameter. Okay,\n你可以使用 _ 来替代它们\n\n362\n00:19:30,560 --> 00:19:34,690\nso if you put underbar as the external name then there will\n所以你要是在外部名字的地方放了一个 _ 那这里有不会有外部参数\n\n363\n00:19:34,700 --> 00:19:39,330\nbe no external parameters. So you see it says foo(123), not\n比如你调用 foo(123)\n\n364\n00:19:39,330 --> 00:19:44,170\nfoo(externalFirst or anything, it's just nothing, 123. And\n不用调用 foo(外部第一个参数名或者其它什么东西，什么都不用，就写123\n\n365\n00:19:44,170 --> 00:19:49,140\nin fact, this is the default for the first parameter.\n实际上，第一个参数默认就是这么做的\n\n366\n00:19:49,140 --> 00:19:51,850\nThe first parameter defaults to under bar, you don't need\n第一个参数默认就是 _\n\n367\n00:19:51,850 --> 00:19:54,510\nto put an under bar there when you're creating a function.\n当你创建一个方法的时候你不需要再在那里放 _\n\n368\n00:19:54,520 --> 00:19:57,850\nJust by default an under bar would be put there for you,\n那里默认就为你放了一个 _\n\n369\n00:19:57,850 --> 00:20:01,790\nokay? Now you could specify an external name for the first,\n现在你指定第一个外部参数的名字，这是合法的\n\n370\n00:20:01,790 --> 00:20:04,820\nit's legal. Okay, I'll show you that in a second. But\n我会展示第二个怎么做\n\n371\n00:20:04,830 --> 00:20:07,730\nby default under bar is the external name for the first\n默认的 _ 只有第一个外部命名才有\n\n372\n00:20:07,730 --> 00:20:11,900\nparameter only. All the other ones. Okay? The default is\n那么所有其它的是什么呢？\n\n373\n00:20:11,900 --> 00:20:15,500\nthe internal name. So, if you don't have an external name,\n它们默认都是内部名字。所以如果你不想要一个外部名字\n\n374\n00:20:15,500 --> 00:20:21,680\nthen it defaults to being the internal name. Got it?\n它们默认会是一个内部的名字。明白了吗？\n\n375\n00:20:21,680 --> 00:20:25,380\nOkay. Any parameter's external name can be changed, okay?\n好的。任何参数的外部名字都是可以修改的\n\n376\n00:20:25,380 --> 00:20:28,580\nYou can change even the second one to be underbar, so\n你甚至可以把第二个改成 _\n\n377\n00:20:28,580 --> 00:20:32,320\nthat the second one has no name, okay?\n这样第二个就没有名字了，对吗？\n\n378\n00:20:32,320 --> 00:20:35,690\nBut don't do this, okay? It's very anti Swift\n但是不要这样做，好吗？\n\n379\n00:20:35,690 --> 00:20:39,890\nto either remove the second parameter name or\n把第二个参数移除或者添加到第一个参数，是很反 Swift 的\n\n380\n00:20:39,900 --> 00:20:43,500\nto add it back to the first. Adding to the first is\n添加到第一个可能不是很反 Swift\n\n381\n00:20:43,500 --> 00:20:46,400\nprobably less anti Swift, there is probably some case\n可能在某些场景里会需要这么做\n\n382\n00:20:46,400 --> 00:20:49,200\nwhere that might actually make some sense. Removing them for\n但是后面要把它们删掉也是非常麻烦的\n\n383\n00:20:49,200 --> 00:20:51,740\nsubsequent ones is probably really bad. Okay,\n\n384\n00:20:51,740 --> 00:20:55,310\nI don't think I've ever had to do that in my entire life of\n在我用 Swift 写程序的时候，我不记得我曾经这么做过\n\n385\n00:20:55,310 --> 00:20:55,680\nwriting swift so.\n\n386\n00:20:55,680 --> 00:21:00,350\nAll right now, methods are obviously overriddeable,\n现在，方法是可以被覆盖的\n\n387\n00:21:00,350 --> 00:21:04,280\nthis is object orientated programming. Right and the way\n因为这是面向对象编程\n\n388\n00:21:04,290 --> 00:21:07,190\nyou do it, you just put the word override in front of\n你只需要在 func 或者 var 前面加 override 关键字\n\n389\n00:21:07,190 --> 00:21:10,120\nthe func or var. Both properties and functions can\n属性和方法都是可以被覆盖的\n\n390\n00:21:10,130 --> 00:21:12,960\nbe overridden right, so you put override in there. It is\n所以你把 override 放在这里\n\n391\n00:21:12,960 --> 00:21:18,200\npossible to mark a method or a property final in which case\n它可以在子类的情况里用来标记方法和属性\n\n392\n00:21:18,200 --> 00:21:21,270\nno one can subclasses. Okay, there won't be a list,\n一个子类不能在类前放 override\n\n393\n00:21:21,270 --> 00:21:24,740\na subclass can't say override that thing. The compiler won't\n编译器不允许这么做\n\n394\n00:21:24,740 --> 00:21:29,110\nlet them. Okay, you can also mark an entire class final,\n你也可以标记整个类为final\n\n395\n00:21:29,110 --> 00:21:33,980\nand then the whole thing is not subclassable. All right?\n然后整个类就不能有子类了\n\n396\n00:21:33,980 --> 00:21:39,090\nNow, both types and instances can have methods and\n现在类和对象都可以有方法和属性\n\n397\n00:21:39,090 --> 00:21:42,060\nproperties. What does that mean? So, so\n这意味着什么呢\n\n398\n00:21:42,060 --> 00:21:43,560\nfar in all the demos we've done,\n现在我们已经完成了所有的演示\n\n399\n00:21:43,560 --> 00:21:45,990\nall you've seen is instance methods and\n你看到的都是对象方法和对象属性\n\n400\n00:21:45,990 --> 00:21:47,330\ninstance properties. In other words,\n换言之\n\n401\n00:21:47,330 --> 00:21:50,530\nthey are properties that you get from an instance of\n它们是你从一个对象中拿出来的属性\n\n402\n00:21:50,530 --> 00:21:53,100\nthe thing. Okay, an instance of the calculator brain.\n好的，一个计算器大脑的对象\n\n403\n00:21:53,100 --> 00:21:58,070\nSomeone actually created a calculator brain in the heap\n实际上你已经在堆里创建了一个计算器的大脑并且给它发送消息\n\n404\n00:21:58,070 --> 00:22:01,510\nand you send it messages, okay. Those are instances\n那些事对象消息\n\n405\n00:22:01,510 --> 00:22:05,910\nmessages, Instances methods and instances properties. But\n对象方法和对象属性\n\n406\n00:22:05,910 --> 00:22:07,180\nit is possible to have methods and\n然而在它的类里它还能有自己的方法和属性\n\n407\n00:22:07,180 --> 00:22:10,420\nproperties on the type itself, so calculator brain,\n所以在计算器大脑这个类里面它可以有方法，对吗\n\n408\n00:22:10,420 --> 00:22:14,250\nthe type can have functions, okay? And here's what\n这里是调用他们时的样子\n\n409\n00:22:14,260 --> 00:22:17,620\nit looks like to call them. So here I have a little example.\n我这里有一个小例子\n\n410\n00:22:17,630 --> 00:22:20,890\nHere I have a var d which is a double, okay?\n我这里有有一个 double 的变量 b\n\n411\n00:22:20,900 --> 00:22:24,460\nAnd it's set to some value. So this d is an instance of\n然和我给它设置一些值，所以这个d 是一个double 的实例\n\n412\n00:22:24,470 --> 00:22:26,830\na double. It is an actual double that has some value,\n这个double 实际上有一些值\n\n413\n00:22:26,840 --> 00:22:30,740\nall right? And here I'm checking by sending a message,\n我通过发送一个消息来检查这一点\n\n414\n00:22:30,740 --> 00:22:34,240\nan instance method right here. Or probably a property\n它是一个对象的方法，也可能是一个属性\n\n415\n00:22:34,240 --> 00:22:38,380\nactually. Instance property on D, where I'm asking\n对象的 D 属性如果是负数的\n\n416\n00:22:38,380 --> 00:22:41,380\nif it's signed is the minus sign, I'm just making this up,\n我就把它变成正数\n\n417\n00:22:41,380 --> 00:22:43,820\nthere's probably not even such a method on double.\n在double 里面可能没有这样一个方法\n\n418\n00:22:43,820 --> 00:22:47,920\nBut that would be an instance property or method and\n这会是属性或对象\n\n419\n00:22:47,920 --> 00:22:48,760\nI would be sending it to D,\n并且我会把它发给D\n\n420\n00:22:48,760 --> 00:22:52,260\nwhich is an instance. If it does have a minus sign,\n如果它没有负号\n\n421\n00:22:52,260 --> 00:22:55,700\nI'm going to use a type property. Or type function,\n我会使用一个类属性\n\n422\n00:22:55,700 --> 00:23:00,970\nrather, of double here, to change its probably absolute\n或者在 double 里的这个类方法里会把它变成绝对值\n\n423\n00:23:00,970 --> 00:23:03,800\nvalue, so it'd probably change its sign there. Okay.\n所以我可能在这里改变它的符号\n\n424\n00:23:03,810 --> 00:23:07,140\nNotice the syntax here, Double.abs, okay.\n好的。注意这里的语法 Double.abs\n\n425\n00:23:07,140 --> 00:23:09,640\nThis is the name of the function abs, okay, and\n这个方法的名字叫 abs\n\n426\n00:23:09,640 --> 00:23:13,080\nI'm accessing it by saying Double. So in other words, I'm\n然后我通过向 Double 发消息来访问它\n\n427\n00:23:13,080 --> 00:23:17,320\nputting the name of the class. Not an instance of a class,\n换句话说，我把这个类名放在这里。不是一个类的对象\n\n428\n00:23:17,320 --> 00:23:19,850\nnot a variable of that class, but the actual name of\n也不是一个类的变量，而是一个类的名字\n\n429\n00:23:19,860 --> 00:23:24,460\nthe class, dot abs. Okay, that's it's gonna be defined,\n.abs 好的。那个 abs 会被定义\n\n430\n00:23:24,460 --> 00:23:29,700\nthat abs, will be defined like this. Static func abs.\n会用这种方法定义 Static func abs\n\n431\n00:23:29,700 --> 00:23:32,800\nThis would be in the class double. And you put this word\n这会在 double 类的里面\n\n432\n00:23:32,800 --> 00:23:37,270\nstatic and that says that you don't send this to double\n在这里放关键字 static 意味着你不会把它发送给 double 对象\n\n433\n00:23:37,270 --> 00:23:41,040\ninstances. You send it to the Double class by saying capital\n你会用大写的 D ，Double 点，发送给 Double 这个类\n\n434\n00:23:41,040 --> 00:23:45,680\nD Double dot. Okay? Why do we have these things? Okay these\n为什么我们会有这些东西？\n\n435\n00:23:45,680 --> 00:23:49,880\nare usually utility functions kind of global functions but\n我们经常会需要一些全局的功能函数\n\n436\n00:23:49,890 --> 00:23:52,820\nthey're really strongly associated with the class. So\n但是他们和这些类有很强的关联的\n\n437\n00:23:52,820 --> 00:23:54,350\nwe put them as class methods, okay?\n所以我们把它们放到类方法里面，好吗？\n\n438\n00:23:54,360 --> 00:23:58,090\nThat's what they're for, mostly. Maybe you have a class\n这是它们存在的主要原因\n\n439\n00:23:58,090 --> 00:24:02,530\nmethod that creates Shared instances of a class, okay.\n或许你会有个类方法来创建一个类的共享对象\n\n440\n00:24:02,530 --> 00:24:05,630\nSomething like that, we'll see a few of these.\n像这样，我们会看到这些\n\n441\n00:24:05,630 --> 00:24:06,530\nOnce you start to see them in action,\n一旦你在实践中看见他们\n\n442\n00:24:06,540 --> 00:24:08,270\nyou'll start to understand. But I just wanna make sure you\n你就会明白的。\n\n443\n00:24:08,270 --> 00:24:10,800\nunderstand that there is a difference between these two\n但是我想确保你们理解这两者之间是不同的\n\n444\n00:24:10,810 --> 00:24:13,470\nand this static that makes a difference on declaration,\n这个static 在声明的时候是不同的\n\n445\n00:24:13,480 --> 00:24:16,380\nokay. That's also in the reading assignment, make sure\n好的。那些也在阅读作业里面\n\n446\n00:24:16,380 --> 00:24:19,180\nyou read that carefully. In the homework assignment,\n确保你仔细的阅读过了\n\n447\n00:24:19,180 --> 00:24:23,120\nI even say be careful to read this carefully. All right,\n在作业里面我甚至也说了仔细阅读\n\n448\n00:24:23,120 --> 00:24:25,420\nproperties, okay. Properties are really cool.\n好的。属性是很酷的\n\n449\n00:24:25,420 --> 00:24:27,890\nIn Swift we're only just scratching the surface so\n在Swift 里我们才刚刚揭开它的表面远不及它所能做的\n\n450\n00:24:27,890 --> 00:24:31,220\nfar of what they can do. But one really cool thing about\n但是有一件关于它的很酷的是\n\n451\n00:24:31,230 --> 00:24:35,830\nthem is that you can observe changes to a property, okay.\n你可以观察一个属性的改变\n\n452\n00:24:35,830 --> 00:24:39,430\nAnd you need to do that by, here's your var, okay. This is\n而且你需要这样做，这是你的变量。\n\n453\n00:24:39,430 --> 00:24:41,570\na stored property, this is not a computed property,\n这是存储的属性，这不是一个计算的属性而是用来存储的\n\n454\n00:24:41,570 --> 00:24:45,310\nit's stored, okay. It stores in ints, its value is 42. But\n它存在int 里，这个值是 42。\n\n455\n00:24:45,310 --> 00:24:47,970\nI'm putting the curly braces after it, not because I'm\n我把大括号放在它的后面，我要去得到和设置它\n\n456\n00:24:47,980 --> 00:24:51,010\ngonna do get and set, I'm not computing it. But\n我不去计算它\n\n457\n00:24:51,010 --> 00:24:56,150\nI'm gonna add willSet and/or didSet, okay. So willSet and\n但是我会使用willSet 和didSet。好的\n\n458\n00:24:56,150 --> 00:24:59,050\ndidSet, this is just code in here that's gonna get called\nwillSet 和didSet，当调用get 和set 时就会调用者两个方法\n\n459\n00:24:59,050 --> 00:25:04,260\nwhenever this thing gets set. Okay, before and after. Before\n好的，在这之前或在这之后。\n\n460\n00:25:04,260 --> 00:25:08,230\nit gets set, after it's been set, okay. And inside there\n这get 之前和set 之后，好的\n\n461\n00:25:08,230 --> 00:25:11,100\nnewValue is going to be the value it's going to be set to\n在设置到willset 的时候newValue 就是要设置的值\n\n462\n00:25:11,100 --> 00:25:14,500\nin willSet. And oldValue is this value it used to have in\n当你执行didSet，oldValue 就是已经存储着的值\n\n463\n00:25:14,500 --> 00:25:19,770\ndid, when you're executing in didSet, okay. So, pretty cool.\n好的，非常酷\n\n464\n00:25:19,770 --> 00:25:23,280\nAnd you can do that for stored properties, you can do it for\n你可以这样来存储属性，你也可以对继承的属性这么做\n\n465\n00:25:23,280 --> 00:25:25,880\ninherited properties, properties you inherit even,\n你甚至可以继承属性\n\n466\n00:25:25,880 --> 00:25:29,550\nokay. And you can do it for computed properties as well,\n你也可以用它来计算属性\n\n467\n00:25:29,550 --> 00:25:33,720\nokay. Also here, this will be,\n好的\n\n468\n00:25:33,720 --> 00:25:37,420\none thing to note about this is these willSets and didSets,\n这些 willSet 和 didSet 要注意的是\n\n469\n00:25:37,430 --> 00:25:41,660\nif you mutate a value type they will get called,\n如果你改变一个值的类型 get 会被调用\n\n470\n00:25:41,660 --> 00:25:45,600\nokay. So, operations here from our calculator brain,\n所以我们对计算器大脑的操作放在这里\n\n471\n00:25:45,600 --> 00:25:49,100\ndictionary string operation that is a value type,\n字典字符串操作是一个值类型\n\n472\n00:25:49,100 --> 00:25:51,740\ndictionary is a value type, right. So\n字典是一个值类型\n\n473\n00:25:51,740 --> 00:25:54,010\nif you add something to this dictionary,\n所以如果你往字典里加了什么\n\n474\n00:25:54,010 --> 00:25:57,580\nthis will get called. willSet and didSet will get called,\n会调用 get。willSet 和 didSet 会被调用\n\n475\n00:25:57,580 --> 00:26:00,310\nokay. That's not true if it's a reference type, okay.\n如果它是一个引用类型的话这么做是无效的\n\n476\n00:26:00,320 --> 00:26:03,180\nIf that if this property isn't a class and\n如果这属性不是类而且你修改了类的某个地方\n\n477\n00:26:03,180 --> 00:26:06,120\nyou change the class somehow, it can't detect that, so\n它是不会检测到的\n\n478\n00:26:06,120 --> 00:26:08,390\nit doesn't do willSet and didSet, okay.\n所以它不会执行 willSet 和 didSet\n\n479\n00:26:08,390 --> 00:26:13,930\nYou have to change the pointer itself. All right, okay.\n你必须改变指针本身\n\n480\n00:26:13,930 --> 00:26:17,100\nOne very common thing to do in these willSets and didSets is\n通常 willSet 和 didiSet 的用途是更新 UI\n\n481\n00:26:17,100 --> 00:26:20,700\nupdate the UI. You got a method in your controller.\n你在你的控制器里得到一个方法\n\n482\n00:26:20,700 --> 00:26:22,440\nYou set some value in controller that changes\n你改变了控制器某处的值就会在 UI 上显示出来\n\n483\n00:26:22,440 --> 00:26:25,170\nthe way the UI would look. You ask your view to\n你要求你的 View 重绘\n\n484\n00:26:25,170 --> 00:26:27,370\ndraw itself again, okay. Very, very common.\n好的。非常非常常见\n\n485\n00:26:27,380 --> 00:26:30,180\nWe're gonna be doing that up the wazoo in the next lecture,\n我们会在下一节使用它们\n\n486\n00:26:30,180 --> 00:26:35,050\nokay. All right. Lazy initialization. So, this is\n好的。懒加载\n\n487\n00:26:35,050 --> 00:26:38,480\na little bit of a cheat code of Swift right here.\n这是 swift 种有点欺骗性的代码\n\n488\n00:26:38,490 --> 00:26:43,590\nYou can declare vars to be lazily instantiated.\n你可以声明一个懒加载的变量\n\n489\n00:26:43,590 --> 00:26:47,690\nWhich means that, their value, this equals calculator brain,\n这意味它们等于计算器的大脑实际上不会执行\n\n490\n00:26:47,700 --> 00:26:51,430\nwill not actually happen. That assignment will not happen\n知道有些地方需要调用它了才会执行分配\n\n491\n00:26:51,430 --> 00:26:53,700\nuntil someone asks for the brain, okay.\n好的\n\n492\n00:26:53,700 --> 00:26:56,640\nIf someone tries to send a message to this brain or\n若果有什么动向想个这个大脑发一个信息\n\n493\n00:26:56,640 --> 00:26:57,970\nget a property to this brain,\n或者从这个大脑里拿到一个信息\n\n494\n00:26:57,970 --> 00:26:58,870\nthen it's gonna get initialized.\n然后它就会被初始化\n\n495\n00:26:58,870 --> 00:27:01,370\nSo in other words, it's lazily instantiated, okay.\n换句话说，这就是懒加载\n\n496\n00:27:01,380 --> 00:27:04,810\nAnd you can do it like that, okay. Just lazy var brain,\n而且你可以像这样做。就 lazy var brain\n\n497\n00:27:04,810 --> 00:27:08,150\ncalculatorbrain. You can do down here, okay.\n你可以在这里做\n\n498\n00:27:08,150 --> 00:27:12,250\nLazy var myProperty = self.initializedMyProperty.\nLazy var myProperty = self.initializedMyProperty.\n\n499\n00:27:12,250 --> 00:27:16,220\nSo, I'm calling a method on myself to initialize one of my\n所以我告诉我自己去初始化我的一个属性\n\n500\n00:27:16,220 --> 00:27:20,030\nproperties. Normally, this would be illegal\n\n501\n00:27:20,030 --> 00:27:22,730\nwithout the lazy. The reason this would be illegal\n\n502\n00:27:22,730 --> 00:27:25,500\nwithout the lazy is that you cannot send any messages to\n\n503\n00:27:25,500 --> 00:27:28,800\nyourself or access any of your properties until you're fully\n\n504\n00:27:28,800 --> 00:27:32,840\ninitialized, okay. And this is part of your initialization,\n\n505\n00:27:32,840 --> 00:27:34,710\nso it's a catch 22, you can't do it. But\n\n506\n00:27:34,710 --> 00:27:38,780\nif you make this lazy, now you can. Because it's not actually\n\n507\n00:27:38,780 --> 00:27:41,150\ngoing to happen until after you're fully initialized and\n\n508\n00:27:41,150 --> 00:27:44,680\nsomeone comes along and tries to access myProperty, okay. No\n\n509\n00:27:44,690 --> 00:27:47,750\none can access myProperty for your initialize anyway. So,\n\n510\n00:27:47,760 --> 00:27:50,590\nonce you're fully initialized, I'm gonna access myProperty,\n\n511\n00:27:50,590 --> 00:27:54,830\nlazy, boom. This method will get called to initialize you,\n\n512\n00:27:54,830 --> 00:27:57,460\ngot it? And how about this one in the middle here,\n\n513\n00:27:57,470 --> 00:28:02,570\nsome property of this given type equals a closure\n\n514\n00:28:03,040 --> 00:28:04,340\nwith open parentheses,\n\n515\n00:28:04,340 --> 00:28:07,640\nclosed parentheses on the end. This just means,\n\n516\n00:28:07,640 --> 00:28:13,080\ninitialize this by executing the code inside this closure,\n\n517\n00:28:13,080 --> 00:28:15,420\nokay. It's very similar to doing\n\n518\n00:28:15,420 --> 00:28:18,080\nself.initializeMyProperty but you're putting the code\n\n519\n00:28:18,090 --> 00:28:20,320\nin this closure instead of putting it in initialize\n\n520\n00:28:20,320 --> 00:28:24,060\nmyProperty, whatever that method is, okay. Now,\n\n521\n00:28:24,060 --> 00:28:28,330\nnormally inside here, okay. If this weren't lazy,\n\n522\n00:28:28,330 --> 00:28:31,600\nyou would not be able to access self in here.\n\n523\n00:28:31,600 --> 00:28:35,070\nBecause again, this is a part of initialization, you can't\n\n524\n00:28:35,070 --> 00:28:37,970\ndo anything with self until you're fully initialized. So\n\n525\n00:28:37,970 --> 00:28:38,940\nif you tried to put self in here,\n\n526\n00:28:38,940 --> 00:28:42,210\nthe compiler will complain. But if you make it lazy,\n\n527\n00:28:42,210 --> 00:28:46,250\nnow you can access self in here. Got it?\n\n528\n00:28:46,250 --> 00:28:49,080\nCall your own methods or whatever you wanna do, okay.\n\n529\n00:28:49,080 --> 00:28:52,690\nSo that's lazy. The reason this is kind of a cheat code\n\n530\n00:28:52,690 --> 00:28:57,120\nis that this lazy business satisfies the requirement\n\n531\n00:28:57,130 --> 00:29:00,690\nthat all your vars have to be initialized, okay. So even\n\n532\n00:29:00,700 --> 00:29:03,860\nthese, though these things are being initialized lazily,\n\n533\n00:29:03,870 --> 00:29:05,570\nthey're still being initialized for\n\n534\n00:29:05,570 --> 00:29:08,130\nthe purposes of that rule that all your vars have to be\n\n535\n00:29:08,140 --> 00:29:11,200\ninitialized. This kind of will often keep you from having to\n\n536\n00:29:11,210 --> 00:29:13,210\nwrite an initializer. You won't need an init,\n\n537\n00:29:13,210 --> 00:29:16,010\nbecause of this lazily do it, okay.\n\n538\n00:29:16,010 --> 00:29:19,180\nThat's why I say it's kind of a cheat code a little bit,\n\n539\n00:29:19,180 --> 00:29:22,220\nokay. One thing about lazy, they always have to be var.\n\n540\n00:29:22,220 --> 00:29:26,120\nSo there's no such thing as lazy let, okay. Lazy var\n\n541\n00:29:26,120 --> 00:29:30,760\nonly, okay. You can also use laziness to get around some\n\n542\n00:29:30,760 --> 00:29:34,090\ndependency issues, if you have one var depends on another. If\n\n543\n00:29:34,100 --> 00:29:36,960\nyou can make one of them lazy, then that'll be fine, right.\n\n544\n00:29:36,970 --> 00:29:40,400\nCuz the lazy one will call the one that gets pre-initialized,\n\n545\n00:29:40,400 --> 00:29:45,270\nokay. All right, let's talk about array.\n\n546\n00:29:45,270 --> 00:29:48,240\nOkay, I'm not gonna spend much time on this cuz array you're\n\n547\n00:29:48,240 --> 00:29:49,640\nused to array, you know what array is.\n\n548\n00:29:49,640 --> 00:29:52,040\nIn other languages, it's pretty much the same in Swift.\n\n549\n00:29:52,050 --> 00:29:54,910\nSo I'm just gonna try and cover the syntax a little bit.\n\n550\n00:29:54,920 --> 00:29:57,550\nOne thing is we've been using this kind of syntax for\n\n551\n00:29:57,550 --> 00:30:01,790\ndictionary, right, dictionary angle, extreme colon\n\n552\n00:30:01,790 --> 00:30:06,090\noperation, remember that? This is the formal\n\n553\n00:30:07,200 --> 00:30:10,400\nsyntax for an array but this square bracket,\n\n554\n00:30:10,400 --> 00:30:13,130\nstring closed square bracket is more informal and\n\n555\n00:30:13,130 --> 00:30:17,900\nit's the one we use, okay. So as we go forward, we're gonna\n\n556\n00:30:17,910 --> 00:30:23,010\nuse [string] to mean the type array of string, okay.\n\n557\n00:30:23,010 --> 00:30:28,710\nAnd similarly for dictionary, [key:value]. That is\n\n558\n00:30:28,720 --> 00:30:34,690\ndictionary with keys of this and values of that type, okay.\n\n559\n00:30:34,690 --> 00:30:35,960\nNow, this is the type,\n\n560\n00:30:35,960 --> 00:30:38,690\nso the open parenthesis close parenthesis on the end just\n\n561\n00:30:38,690 --> 00:30:41,590\nmeans that I'm calling the initializer with no arguments.\n\n562\n00:30:41,600 --> 00:30:44,600\nSame as up here. So don't get confused by that, okay.\n\n563\n00:30:44,600 --> 00:30:46,530\nSo that just means I'm initializing,\n\n564\n00:30:46,530 --> 00:30:50,140\nI'm creating an instance of an array of string, okay. That's\n\n565\n00:30:50,140 --> 00:30:54,270\nwhat both of those mean. So, I can also create arrays and\n\n566\n00:30:54,280 --> 00:30:58,240\ninitialize them by just saying some variable like animals\n\n567\n00:30:58,250 --> 00:31:02,110\nthere which is constant let animals = [ list a bunch of\n\n568\n00:31:02,120 --> 00:31:05,320\nthings ]. That creates an array of those things.\n\n569\n00:31:05,320 --> 00:31:08,420\nAnd notice I don't specify any type here.\n\n570\n00:31:08,420 --> 00:31:10,790\nWhy, why do I get away with that? What does Swift do?\n\n571\n00:31:10,790 --> 00:31:15,900\nIt infers type. So, we would look at this and say string,\n\n572\n00:31:15,900 --> 00:31:16,960\nstring, string, string all right.\n\n573\n00:31:16,970 --> 00:31:20,430\nThis is an array of string. Now if I went giraffe, cow,\n\n574\n00:31:20,440 --> 00:31:24,970\nthree, bird, then Swift would complain, can't infer the type\n\n575\n00:31:24,970 --> 00:31:28,010\nof that array, because it's not all the same type.\n\n576\n00:31:28,010 --> 00:31:30,910\nOkay, so we'd infer it here. Now, notice this\n\n577\n00:31:30,910 --> 00:31:34,380\nanimals.append(\"Ostrich\"), if I put an Ostrich in here,\n\n578\n00:31:34,380 --> 00:31:37,520\nthis will not compile, okay. Compiler will say no,\n\n579\n00:31:37,520 --> 00:31:41,420\nthat's because animals is let, it's a constant.\n\n580\n00:31:41,420 --> 00:31:45,020\nSo this is a constant array, it can not be modified.\n\n581\n00:31:45,030 --> 00:31:50,460\nIf I put var right here, no problem, it would work, okay.\n\n582\n00:31:50,470 --> 00:31:53,670\nNow, if I say let animal = animals[5].\n\n583\n00:31:53,670 --> 00:31:57,440\nThat's gonna crash my program. Array index out of bounds,\n\n584\n00:31:57,440 --> 00:31:59,910\njust like most Programming systems do. It's one\n\n585\n00:31:59,910 --> 00:32:03,210\nof the few cases that you can crash your program in Swift.\n\n586\n00:32:03,210 --> 00:32:06,880\nWe know unwrapping optionals is one, this is another one.\n\n587\n00:32:06,880 --> 00:32:08,010\nIf you array index out of bounds,\n\n588\n00:32:08,020 --> 00:32:13,250\nit will crash, okay? How do you enumerate array?\n\n589\n00:32:13,250 --> 00:32:16,020\nI wanna look at everything in an array. Yeah, I could do for\n\n590\n00:32:16,020 --> 00:32:19,990\nwith a range 0.., the length of the array, right?\n\n591\n00:32:19,990 --> 00:32:22,400\n0.., less than sign, length of the array. But\n\n592\n00:32:22,400 --> 00:32:24,260\nthat's not how you would do it, you would just say, for\n\n593\n00:32:24,270 --> 00:32:28,900\nanimal in animals, okay? This is gonna loop through, and\n\n594\n00:32:28,900 --> 00:32:30,970\nthis local variable is gonna be assigned each\n\n595\n00:32:30,970 --> 00:32:35,840\nof the animals, okay? That's how you enumerate an array.\n\n596\n00:32:36,210 --> 00:32:38,280\nAll right, interesting Array<T> methods.\n\n597\n00:32:38,280 --> 00:32:40,550\nOkay, I'm not gonna spend a lot of time on this slide.\n\n598\n00:32:40,550 --> 00:32:43,050\nBut I really want you to understand that these methods\n\n599\n00:32:43,050 --> 00:32:45,580\nare here, okay, and you're gonna wanna use them.\n\n600\n00:32:45,590 --> 00:32:46,490\nThey will really clean up your code.\n\n601\n00:32:46,490 --> 00:32:49,590\nThey'll keep you from doing a lot of code, this like for\n\n602\n00:32:49,590 --> 00:32:52,960\nenumerate through my array, do this, if then, this then,\n\n603\n00:32:52,960 --> 00:32:56,200\ncollect it in another array, all that kinda stuff you can\n\n604\n00:32:56,200 --> 00:32:59,000\nput in one liners, okay? So what do these things do?\n\n605\n00:32:59,000 --> 00:33:04,070\nThese things use closures to operate on arrays. So filter,\n\n606\n00:33:04,070 --> 00:33:06,710\nokay, is a method in Array. You send it to it.\n\n607\n00:33:06,710 --> 00:33:11,710\nYou provide a closure, which takes whatever type is in the,\n\n608\n00:33:11,710 --> 00:33:14,510\nin the array and returns a bool. And it just\n\n609\n00:33:14,520 --> 00:33:18,920\nexecutes that closure on every single element of the array,\n\n610\n00:33:18,920 --> 00:33:19,820\nand it includes the ones\n\n611\n00:33:19,820 --> 00:33:23,390\nwhere you return true from your closure. And it excludes\n\n612\n00:33:23,390 --> 00:33:26,590\nthe ones you don't, until filter returns a new array,\n\n613\n00:33:26,590 --> 00:33:30,800\nwhich is only the things that match your closure, okay? So\n\n614\n00:33:30,800 --> 00:33:33,670\nhere for example, let bigNumbers = this\n\n615\n00:33:33,670 --> 00:33:36,840\narray.filter, here's my closure,\n\n616\n00:33:36,840 --> 00:33:40,640\n$0 is this thing that's gonna be for each of these,\n\n617\n00:33:40,640 --> 00:33:42,880\ncalled on each of these. If $0 is greater than 20,\n\n618\n00:33:42,880 --> 00:33:47,280\nI'm gonna return true. So this returns an array, bigNumbers,\n\n619\n00:33:47,280 --> 00:33:51,380\nthat only has 47 and 118, cuz those are the only\n\n620\n00:33:51,390 --> 00:33:54,550\ntwo things greater than 20, got it? Okay,\n\n621\n00:33:54,560 --> 00:33:57,520\nthere's another one simpler, similar, which is map.\n\n622\n00:33:57,530 --> 00:34:01,890\nMap takes your closure and your closure converts each\n\n623\n00:34:01,900 --> 00:34:04,860\nelement in the array to something else.\n\n624\n00:34:04,870 --> 00:34:07,400\nSo if you had an array of ints and you wanted it\n\n625\n00:34:07,400 --> 00:34:10,370\nto be an array of strings, you could do it with this,\n\n626\n00:34:10,370 --> 00:34:14,470\nokay map, closure. Notice, by the way,\n\n627\n00:34:14,480 --> 00:34:16,880\nno parentheses here. You see, map, okay,\n\n628\n00:34:16,880 --> 00:34:21,050\nmap takes an argument, which is a closure there. But I have\n\n629\n00:34:21,050 --> 00:34:23,980\nno parentheses after map around the curly braces like I\n\n630\n00:34:23,990 --> 00:34:27,690\nhad up here with filter. I put this in here to show you that\n\n631\n00:34:27,690 --> 00:34:30,720\nthose parentheses are optional when a closure\n\n632\n00:34:30,730 --> 00:34:33,290\nis the last argument to a function, okay?\n\n633\n00:34:33,290 --> 00:34:36,230\nWhen a closure is the last argument to the function,\n\n634\n00:34:36,230 --> 00:34:40,000\nit can be outside of the function's parentheses, okay,\n\n635\n00:34:40,000 --> 00:34:41,230\nand live on its own out here.\n\n636\n00:34:41,240 --> 00:34:45,140\nOkay, here's another function, okay, called reduce.\n\n637\n00:34:45,140 --> 00:34:49,680\nThis reduces the array to a single result. Okay, so\n\n638\n00:34:49,680 --> 00:34:52,810\nthis particular one, you can convince yourself of it later,\n\n639\n00:34:52,810 --> 00:34:55,180\nit adds up the numbers, okay. It just reduces,\n\n640\n00:34:55,180 --> 00:34:58,620\nstarts with zero, and for each one it takes the amount so\n\n641\n00:34:58,620 --> 00:35:01,620\nfar and adds it to the next thing in there, so\n\n642\n00:35:01,620 --> 00:35:03,260\nit adds up the numbers.\n\n643\n00:35:03,260 --> 00:35:05,120\nNotice this one has two arguments,\n\n644\n00:35:05,130 --> 00:35:09,500\nan initial and a closure. Okay, see this closure here,\n\n645\n00:35:09,500 --> 00:35:12,800\nan initial? And notice the closure also is still living\n\n646\n00:35:12,800 --> 00:35:16,070\noutside of the parentheses. The first argument is inside\n\n647\n00:35:16,070 --> 00:35:19,210\nthe parentheses, but the closure is living outside.\n\n648\n00:35:19,210 --> 00:35:20,370\nThis one had no first argument.\n\n649\n00:35:20,370 --> 00:35:23,440\nIt only had the closure, so it has no parentheses here. This\n\n650\n00:35:23,440 --> 00:35:28,180\none does, okay? This is called trailing closure syntax, and\n\n651\n00:35:28,180 --> 00:35:31,180\nyou almost always wanna use it, it looks really cool,\n\n652\n00:35:31,190 --> 00:35:35,890\nreads really nicely. Okay, dictionary.\n\n653\n00:35:35,890 --> 00:35:38,460\nAll right, so dictionary, similar to array,\n\n654\n00:35:38,460 --> 00:35:40,530\nit's just looking up keys and values.\n\n655\n00:35:40,530 --> 00:35:44,230\nAgain, we're gonna use this more informal kind of syntax,\n\n656\n00:35:44,230 --> 00:35:48,630\nokay? [String:Int] means the type dictionary where\n\n657\n00:35:48,640 --> 00:35:53,110\nthe strings are keys and ints are values, all right?\n\n658\n00:35:53,110 --> 00:35:55,570\nSo if I have pac10teamRankings here, and\n\n659\n00:35:55,580 --> 00:35:59,580\nI had Stanford at number 1, Cal number 10, and I let the,\n\n660\n00:35:59,580 --> 00:36:02,750\nI guess it's Pac-12 now. I should update this,\n\n661\n00:36:02,750 --> 00:36:07,020\nshould't I? So, okay, Cal 12 and so if I say here, let\n\n662\n00:36:07,020 --> 00:36:10,890\nranking = pac10teamRankings [\"Ohio State\"],\n\n663\n00:36:10,890 --> 00:36:14,590\nthat's obviously, no Ohio State in the Pac-12.\n\n664\n00:36:14,600 --> 00:36:17,930\nSo the ranking here has to be an Int?, right, it's\n\n665\n00:36:17,930 --> 00:36:22,970\nan optional Int, we already saw that in our, calculator.\n\n666\n00:36:22,970 --> 00:36:26,370\nOkay, anytime you dereference a dictionary,\n\n667\n00:36:26,370 --> 00:36:29,980\nit's gonna return an optional of whatever type is\n\n668\n00:36:29,980 --> 00:36:34,750\nthe dictionary's values are, okay? The way you enumerate\n\n669\n00:36:34,750 --> 00:36:38,920\nthrough a dictionary is using a tuple, okay, for (key,\n\n670\n00:36:38,920 --> 00:36:42,620\nvalue) in pac10teamRankings, inside here, key is\n\n671\n00:36:42,620 --> 00:36:45,320\ngonna be the key. And here is gonna be the value for each of\n\n672\n00:36:45,330 --> 00:36:49,860\nthe things in the dictionary, okay? Pretty cool. And again,\n\n673\n00:36:49,860 --> 00:36:52,230\nyou could put under bar here if you just wanted the keys,\n\n674\n00:36:52,230 --> 00:36:57,100\nor under bar here if you just wanted the values. All right,\n\n675\n00:36:57,100 --> 00:37:02,170\nString. String is a little complicated in Swift because\n\n676\n00:37:02,180 --> 00:37:03,210\nit's full Unicode.\n\n677\n00:37:03,210 --> 00:37:06,010\nAnd I mean full Unicode. All right so,\n\n678\n00:37:06,010 --> 00:37:09,350\nit supports all kinds of languages. Languages where\n\n679\n00:37:09,350 --> 00:37:13,590\none character might be many, many different codes, okay.\n\n680\n00:37:13,590 --> 00:37:18,620\nSo characters are no longer single codes anymore. Okay,\n\n681\n00:37:18,630 --> 00:37:20,790\nso, that's why, when you index into a string,\n\n682\n00:37:20,800 --> 00:37:24,230\nyou're not indexing by ints. You're indexing by\n\n683\n00:37:24,230 --> 00:37:28,470\nindexes that know how to move along in a string past things\n\n684\n00:37:28,470 --> 00:37:32,240\nlike emojis that might have multiple codes, okay?\n\n685\n00:37:32,240 --> 00:37:34,240\nSo you're gonna wanna read about this, so\n\n686\n00:37:34,240 --> 00:37:36,910\nI'm not gonna cover it all in lecture here. But\n\n687\n00:37:36,910 --> 00:37:39,880\none interesting way to look at a string is by calling\n\n688\n00:37:39,880 --> 00:37:43,920\nthis, String.CharacterView, okay? If you call character\n\n689\n00:37:43,920 --> 00:37:46,820\nview on a string, you'll get the characters\n\n690\n00:37:46,820 --> 00:37:50,590\nin what looks like an array of character, okay? It looks like\n\n691\n00:37:50,590 --> 00:37:53,090\nan array of characters, not actually array of character.\n\n692\n00:37:53,090 --> 00:37:57,130\nIt's a character view. But it can be indexed with ints,\n\n693\n00:37:57,130 --> 00:38:00,100\nokay, and you can get at the characters. So that's one way.\n\n694\n00:38:00,100 --> 00:38:03,000\nAnother way, you can actually create an array,\n\n695\n00:38:03,000 --> 00:38:06,710\none of the initializers that array will take is a string,\n\n696\n00:38:06,710 --> 00:38:09,340\nokay. And then it'll be an array of characters.\n\n697\n00:38:09,340 --> 00:38:11,940\nOkay, not quite as efficient as this character view, but\n\n698\n00:38:11,950 --> 00:38:14,510\nyou could do it that way, especially with a long string,\n\n699\n00:38:14,520 --> 00:38:17,150\nyou probably might not wanna do that. Okay, but that's\n\n700\n00:38:17,150 --> 00:38:19,720\na little easier way to get at it, otherwise you have to\n\n701\n00:38:19,720 --> 00:38:23,220\nunderstand what it says in the reading about string indexes,\n\n702\n00:38:23,220 --> 00:38:25,860\nokay. String.index that class and\n\n703\n00:38:25,860 --> 00:38:29,060\nhow to use it to get things out of a string,\n\n704\n00:38:29,060 --> 00:38:34,130\nokay? There are a lot of other cool methods in String,\n\n705\n00:38:34,140 --> 00:38:36,700\nthough, like hasPrefix will tell you whether one string\n\n706\n00:38:36,700 --> 00:38:40,040\nhas the prefix of another string. You can capitalize and\n\n707\n00:38:40,040 --> 00:38:43,110\nlowercase and uppercase these strings.\n\n708\n00:38:43,110 --> 00:38:45,080\nYou can even do sophisticated things like,\n\n709\n00:38:45,080 --> 00:38:48,950\nget me all the components in this string separated by\n\n710\n00:38:48,950 --> 00:38:48,980\nthis other string. So\n\n711\n00:38:48,980 --> 00:38:52,550\nthis is a method you send to a string. This might be a comma,\n\n712\n00:38:52,550 --> 00:38:56,460\nlet's say, and this, right here like this, and it will\n\n713\n00:38:56,460 --> 00:39:00,130\nextract all the strings that are separated by a comma.\n\n714\n00:39:00,130 --> 00:39:03,360\nOkay, kinda fun. So make sure you familiarize yourself with\n\n715\n00:39:03,360 --> 00:39:06,300\na lot of the methods in String so that you don't waste your\n\n716\n00:39:06,300 --> 00:39:09,230\ntime writing this method which already exists, okay, or\n\n717\n00:39:09,240 --> 00:39:14,070\nsimilar methods like it. All right, other classes that\n\n718\n00:39:14,080 --> 00:39:18,310\nare here that you have to think about. One is NSObject.\n\n719\n00:39:18,310 --> 00:39:23,250\nThis is the base class of all Objective-C classes, okay.\n\n720\n00:39:23,250 --> 00:39:26,850\nNow, we know, in Swift, it doesn't have a mandatory base\n\n721\n00:39:26,850 --> 00:39:30,660\nclass, like CalculatorBrain, no superclass, okay.\n\n722\n00:39:30,660 --> 00:39:31,820\nPerfectly legal in Swift. But\n\n723\n00:39:31,830 --> 00:39:35,890\nall Objective-C ones have to be subclasses of NSObject.\n\n724\n00:39:35,900 --> 00:39:38,560\nNow, there are some APIs, they're fairly rare and\n\n725\n00:39:38,570 --> 00:39:41,830\nI'll tell you which ones they are when we get to them later\n\n726\n00:39:41,840 --> 00:39:45,300\nin the quarter, that are Objective-C APIs, okay.\n\n727\n00:39:45,310 --> 00:39:46,670\nAnd when you use them in Swift,\n\n728\n00:39:46,670 --> 00:39:50,180\nyou need to have a class that subclasses from NSObject. So\n\n729\n00:39:50,180 --> 00:39:53,550\nin Swift, it's perfectly legal to subclass from NSObject,\n\n730\n00:39:53,550 --> 00:39:56,620\nnot required except for in these few cases I'm gonna talk\n\n731\n00:39:56,620 --> 00:39:59,690\nabout later in the quarter. But legal and it really won't\n\n732\n00:39:59,690 --> 00:40:02,650\nhurt anything, so you could do it if you want. Some people\n\n733\n00:40:02,660 --> 00:40:04,620\njust get in the habit of always sub-classing for\n\n734\n00:40:04,630 --> 00:40:07,130\nNSObjects in Swift, if they're not sub-classing from\n\n735\n00:40:07,130 --> 00:40:10,400\nsomething else, because why not, okay. Then their classes\n\n736\n00:40:10,400 --> 00:40:14,870\nare always ready for whatever these weird old APIs are,\n\n737\n00:40:14,870 --> 00:40:19,140\nokay? NSNumber, okay in Objective-C,\n\n738\n00:40:19,140 --> 00:40:23,110\nthere's no such things as well structs\n\n739\n00:40:23,110 --> 00:40:28,110\nin Objective-C are not like structs in Swift.\n\n740\n00:40:28,120 --> 00:40:30,920\nThey're not this nice value type semantic thing.\n\n741\n00:40:30,920 --> 00:40:36,190\nOkay, structs are more like C structs okay, so double and\n\n742\n00:40:36,190 --> 00:40:38,290\nint, string, array,\n\n743\n00:40:38,290 --> 00:40:41,090\ndictionary. In Objective-C these are classes.\n\n744\n00:40:41,100 --> 00:40:45,530\nOkay, sorry, array and diction are classes.\n\n745\n00:40:45,530 --> 00:40:51,040\nDouble and int are C-double and int. Not even objects,\n\n746\n00:40:51,040 --> 00:40:53,540\nokay? So that brings a problem in Objective-C,\n\n747\n00:40:53,540 --> 00:40:56,910\nwhat if I wanna put a bunch of numbers into an array? Okay,\n\n748\n00:40:56,910 --> 00:40:59,710\nyou can't do it, because an array is an array of objects.\n\n749\n00:40:59,710 --> 00:41:03,020\nAnd doubles and ints are C primitive types,\n\n750\n00:41:03,020 --> 00:41:05,420\nin Objective-C. So this class NSNumber,\n\n751\n00:41:05,420 --> 00:41:09,050\nis how you wrap a primitive type into an object.\n\n752\n00:41:09,060 --> 00:41:09,350\nSo you can put it in an array.\n\n753\n00:41:09,360 --> 00:41:12,860\nNow in Swift we don't need that, because in Swift arrays\n\n754\n00:41:12,860 --> 00:41:16,090\nand dictionaries will accept structs, and double and\n\n755\n00:41:16,100 --> 00:41:20,570\nint is a struct. Okay, so this NSNumber not necessary for\n\n756\n00:41:20,570 --> 00:41:26,040\nthat, okay. Now there are iOS APIs that take,\n\n757\n00:41:26,040 --> 00:41:29,710\nfor example, arrays of ints. And\n\n758\n00:41:29,710 --> 00:41:33,280\nin Objective-C, they're gonna be arrays of NSNumber and\n\n759\n00:41:33,280 --> 00:41:37,520\nin Swift, they're going to be Swift arrays of Swift Ints.\n\n760\n00:41:37,520 --> 00:41:39,450\nAnd you might ask, how is that ever gonna work?\n\n761\n00:41:39,450 --> 00:41:41,920\nCuz you're talking about a struct filled with struct\n\n762\n00:41:41,920 --> 00:41:46,890\nversus an array class filled with these NSNumber classes.\n\n763\n00:41:46,890 --> 00:41:49,830\nWell the answer is, those things, array, dictionary,\n\n764\n00:41:49,830 --> 00:41:54,770\nthen int double, and NSNumber are all bridged, magically and\n\n765\n00:41:54,770 --> 00:41:58,070\nautomatically, okay? As you call functions that require\n\n766\n00:41:58,070 --> 00:42:00,410\none to be one way or the other. It just automatically\n\n767\n00:42:00,410 --> 00:42:03,840\nworks. Okay, there's a lot of magic going on in Objective-C\n\n768\n00:42:03,840 --> 00:42:06,140\nruntime to make that work. Okay, and we're gonna take\n\n769\n00:42:06,150 --> 00:42:10,180\nadvantage of that bridging in a couple of slides here.\n\n770\n00:42:10,180 --> 00:42:13,720\nNSDate, brilliant important class to know about. If\n\n771\n00:42:13,720 --> 00:42:17,020\nyou wanna put a date in your UI, you need be very careful.\n\n772\n00:42:17,020 --> 00:42:19,660\nBecause dates are represented in a different way all over\n\n773\n00:42:19,660 --> 00:42:25,300\nthe Earth. Date date class knows all about those ways and\n\n774\n00:42:25,300 --> 00:42:28,670\nit has a lot of companion classes like NSCalendar,\n\n775\n00:42:28,670 --> 00:42:31,670\nNSDateFormatter, NSDateComponents to help you\n\n776\n00:42:31,670 --> 00:42:35,040\nput dates on screen in a way that's gonna work when you\n\n777\n00:42:35,040 --> 00:42:39,580\ntranslate your app to Chinese. So NSDate is an important\n\n778\n00:42:39,580 --> 00:42:43,050\nclass to get familiar with and understand what it can do.\n\n779\n00:42:43,050 --> 00:42:45,320\nOkay, if you're ever gonna put a date in your UI,\n\n780\n00:42:45,320 --> 00:42:48,550\nyou're gonna need to know about NSDate. NSDate can also\n\n781\n00:42:48,560 --> 00:42:52,790\ntell you the current date and time. All right NSData,\n\n782\n00:42:52,790 --> 00:42:57,530\nthat's a bag of bits. Okay just unstructured bag o' bits.\n\n783\n00:42:57,530 --> 00:42:59,600\nWe use it to pass things around,\n\n784\n00:42:59,600 --> 00:43:01,930\nsometimes over the network like image data,\n\n785\n00:43:01,940 --> 00:43:04,700\nthings like that. It's pretty self explanatory,\n\n786\n00:43:04,710 --> 00:43:06,200\nbag of bits doesn't have a lot of methods on it.\n\n787\n00:43:06,210 --> 00:43:09,980\nIt's basically just give me the bits and here's some bits.\n\n788\n00:43:10,210 --> 00:43:13,110\nOkay, now let's talk about initialization, I'm gonna kind\n\n789\n00:43:13,110 --> 00:43:16,250\nof blast through this pretty quick. There's a really\n\n790\n00:43:16,250 --> 00:43:19,120\ngood explanation of this in your homework in your reading\n\n791\n00:43:19,120 --> 00:43:23,090\nassignment. For this coming week but I'm gonna try and\n\n792\n00:43:23,090 --> 00:43:25,720\ngive you the 50,000 foot overview of it quickly so\n\n793\n00:43:25,730 --> 00:43:28,290\nthat you kind of have an idea what's going on as you go and\n\n794\n00:43:28,300 --> 00:43:31,400\nread that very detailed description, okay?\n\n795\n00:43:31,400 --> 00:43:35,330\nSo when is an init method needed? We're talking about\n\n796\n00:43:35,340 --> 00:43:39,840\ninitializing structs and classes okay? They're\n\n797\n00:43:39,840 --> 00:43:42,370\nnot needed that often because of course we can say equal\n\n798\n00:43:42,380 --> 00:43:45,410\nsomething in the var. We coud use those lazy instantiation\n\n799\n00:43:45,410 --> 00:43:49,010\nthings to get around it. Properties might be optional,\n\n800\n00:43:49,020 --> 00:43:50,780\nso, and they can just start off being not set.\n\n801\n00:43:50,780 --> 00:43:53,850\nSo there's a lot of reasons you don't need an init, okay?\n\n802\n00:43:53,850 --> 00:43:56,720\nAnd frankly, most people try to design their classes and\n\n803\n00:43:56,720 --> 00:43:59,790\nstructs so they don't need an init, okay? So you can just\n\n804\n00:43:59,790 --> 00:44:01,690\ncreate them with an init with no arguments, right,\n\n805\n00:44:01,700 --> 00:44:05,160\nwhich you get for free. Or a string in a struct case maybe\n\n806\n00:44:05,170 --> 00:44:08,370\nyou just do what we did in demo where you just init it\n\n807\n00:44:08,370 --> 00:44:11,870\nwith the values of all the things in the struct, okay?\n\n808\n00:44:11,870 --> 00:44:15,110\nSo but sometimes you might find yourself needing an init\n\n809\n00:44:15,110 --> 00:44:18,140\nbecause you just can initialize things using those\n\n810\n00:44:18,150 --> 00:44:21,710\nmechanisms, all right? Now, you do get some free inits,\n\n811\n00:44:21,720 --> 00:44:24,220\nokay? We know about in classes you get the init with no\n\n812\n00:44:24,220 --> 00:44:27,450\narguments for free. That's how CalculatorBrain got an init,\n\n813\n00:44:27,450 --> 00:44:29,190\nso we could create one. And\n\n814\n00:44:29,190 --> 00:44:30,560\nwe also know that structs have a free\n\n815\n00:44:30,560 --> 00:44:33,130\ninitializer to let you initialize all of the,\n\n816\n00:44:33,130 --> 00:44:38,500\nall of its vars. Now, One thing to know about,\n\n817\n00:44:38,500 --> 00:44:41,230\n[COUGH] both of those cases is that you,\n\n818\n00:44:41,240 --> 00:44:44,740\nif you start providing your own initializers,\n\n819\n00:44:44,740 --> 00:44:47,740\nthen you stop getting the free one, okay?\n\n820\n00:44:47,740 --> 00:44:50,840\nIf you provide even one initializer for your struct\n\n821\n00:44:50,840 --> 00:44:54,450\nyou no longer get this free one, the one that does both,\n\n822\n00:44:54,450 --> 00:44:58,920\nokay? All right, what can you do inside of init?\n\n823\n00:44:58,920 --> 00:45:02,820\nWhat is legal to do? You can set any property's value,\n\n824\n00:45:02,820 --> 00:45:05,490\neven one's that already have default values.\n\n825\n00:45:05,490 --> 00:45:06,490\nOnes that you said equal something,\n\n826\n00:45:06,490 --> 00:45:08,630\nyou can reset them to something else if you want.\n\n827\n00:45:08,630 --> 00:45:09,590\nYou can set any property's value,\n\n828\n00:45:09,600 --> 00:45:13,670\nokay. You can even set constant properties, okay.\n\n829\n00:45:13,670 --> 00:45:16,970\nSo if you have let something, so you have a constant in your\n\n830\n00:45:16,970 --> 00:45:20,070\nclass, like a constant instance variable basically.\n\n831\n00:45:20,070 --> 00:45:22,410\nYou can set that in, even though it's let,\n\n832\n00:45:22,410 --> 00:45:24,980\nyou can set it in the initializer. Constant\n\n833\n00:45:24,980 --> 00:45:27,850\nproperties are fairly rare. You know, why would you have\n\n834\n00:45:27,850 --> 00:45:30,550\nsomething that's constant? You might, though, you might have\n\n835\n00:45:30,550 --> 00:45:33,550\nsomething that's determined in initialization. And\n\n836\n00:45:33,550 --> 00:45:33,990\nthen it never changes,\n\n837\n00:45:33,990 --> 00:45:38,560\nokay? You can call other init methods from your init,\n\n838\n00:45:38,560 --> 00:45:42,830\nyou actually can call one other init method from n init,\n\n839\n00:45:42,830 --> 00:45:47,600\nokay? And you can call superclass inits, okay.\n\n840\n00:45:47,600 --> 00:45:50,000\nYou can call your superclass initializers, but\n\n841\n00:45:50,000 --> 00:45:52,740\nthere are rules for calling inits and they are rather\n\n842\n00:45:52,740 --> 00:45:54,970\ncomplicated. And I'm gonna go through them quick and\n\n843\n00:45:54,980 --> 00:45:56,110\nyou're gonna read the documentations,\n\n844\n00:45:56,110 --> 00:45:58,110\nit's gonna give you all the details, okay? So\n\n845\n00:45:58,110 --> 00:46:01,880\nthere are requirements inside of init, things you must do.\n\n846\n00:46:01,880 --> 00:46:03,750\nThe previous slide was things you are allowed to do,\n\n847\n00:46:03,750 --> 00:46:07,550\nhere's the things you must do, okay? By the time any init is\n\n848\n00:46:07,550 --> 00:46:10,420\ndone, okay? By the time the init is finished,\n\n849\n00:46:10,420 --> 00:46:13,590\nall properties must have values. We know this, right?\n\n850\n00:46:13,590 --> 00:46:16,630\nBut in Swift, all, by the time initialization is done,\n\n851\n00:46:16,630 --> 00:46:19,300\nall properties have to have values, and again,\n\n852\n00:46:19,300 --> 00:46:20,870\noptionals must have a value too, but\n\n853\n00:46:20,870 --> 00:46:25,340\nit could be the value not set. That's fine, okay? Now,\n\n854\n00:46:25,340 --> 00:46:30,180\nthere are two types of init methods in a class.\n\n855\n00:46:30,180 --> 00:46:34,110\nConvenience methods and, convenience initializers and\n\n856\n00:46:34,110 --> 00:46:37,280\ndesignated initializers. Designated initializers\n\n857\n00:46:37,280 --> 00:46:40,590\nare not marked with the word convenience. Okay,\n\n858\n00:46:40,590 --> 00:46:43,390\nconvenience initializers say convenience init whatever,\n\n859\n00:46:43,390 --> 00:46:48,890\nokay, in their declaration. A designated initializer must,\n\n860\n00:46:48,900 --> 00:46:52,130\nand can only, call a designated initializers\n\n861\n00:46:52,130 --> 00:46:55,270\nin it's superclass, its immediate superclass, okay?\n\n862\n00:46:55,270 --> 00:46:57,900\nSo a designated initializer can't call a convenience\n\n863\n00:46:57,910 --> 00:46:59,810\ninitializer in its superclass, and it can't\n\n864\n00:46:59,810 --> 00:47:02,740\ncall a convenience super, initializers in its own class.\n\n865\n00:47:02,740 --> 00:47:05,980\nIt must call a superclass's designated initializer. Okay,\n\n866\n00:47:05,980 --> 00:47:10,880\nyou must initialize all the properties that you introduce\n\n867\n00:47:10,880 --> 00:47:16,090\nin your class, before calling a superclass's init.\n\n868\n00:47:16,090 --> 00:47:19,760\nOkay, so by the time you call super init to let your super\n\n869\n00:47:19,760 --> 00:47:22,460\nclass initialize you must have all your properties\n\n870\n00:47:22,460 --> 00:47:27,700\ninitialized, all right? You must call a superclass's init\n\n871\n00:47:27,700 --> 00:47:32,370\nbefore you can touch any of your superclass's properties.\n\n872\n00:47:32,370 --> 00:47:35,270\nSee the order there? You do yours, call the super,\n\n873\n00:47:35,280 --> 00:47:37,740\nnow you can touch theirs, okay? That makes sense.\n\n874\n00:47:37,740 --> 00:47:40,380\nYou gotta let them initialize theirs before you can touch it\n\n875\n00:47:40,380 --> 00:47:42,880\nand you want yours initialized before they come along and\n\n876\n00:47:42,880 --> 00:47:46,850\nstart doing their stuff. A convenience initializer must\n\n877\n00:47:46,850 --> 00:47:52,260\nand can only call an init, either can be user designated,\n\n878\n00:47:52,260 --> 00:47:55,730\nin its own class, cannot call super. Okay,\n\n879\n00:47:55,730 --> 00:47:58,130\na convenience initializer cannot call super initializer.\n\n880\n00:47:58,130 --> 00:48:03,030\nA convenience initializer must call that in it, before it can\n\n881\n00:48:03,040 --> 00:48:07,970\nset any property values. It's own, or it's super classes.\n\n882\n00:48:07,980 --> 00:48:11,840\nOkay, in other words, it must let a designated initializer\n\n883\n00:48:11,850 --> 00:48:14,550\ninitialize your own properties first.\n\n884\n00:48:14,550 --> 00:48:16,080\nAnd that thing is gonna call supern,\n\n885\n00:48:16,080 --> 00:48:18,820\nit's gonna initialize it, so by the time a convenience\n\n886\n00:48:18,820 --> 00:48:21,990\nintializer gets back from the emit, all the property values\n\n887\n00:48:21,990 --> 00:48:24,590\nwill be set and it can reset them to something else,\n\n888\n00:48:24,590 --> 00:48:29,730\nokay. It's just a convenience. Calling other inits\n\n889\n00:48:29,730 --> 00:48:33,470\nhas to be complete before you can access any properties.\n\n890\n00:48:33,470 --> 00:48:36,700\nAccess I'm talking about, not set. Access any properties or\n\n891\n00:48:36,700 --> 00:48:40,810\nmethods in yourself. So you can't say self.anything.\n\n892\n00:48:40,810 --> 00:48:43,440\nYou know, you can't access any of the properties or\n\n893\n00:48:43,440 --> 00:48:45,980\nmethods in yourself until you're fully initialized.\n\n894\n00:48:45,980 --> 00:48:49,110\nOkay, so you'll have to have called the other inits first.\n\n895\n00:48:49,120 --> 00:48:51,920\nYeah? >> If you're building\n\n896\n00:48:52,620 --> 00:48:53,820\nan imperative class why would you\n\n897\n00:48:53,820 --> 00:48:54,890\never need convenience inits? >> So\n\n898\n00:48:54,890 --> 00:48:57,690\nthe question is why would I ever use a convenience init?\n\n899\n00:48:57,690 --> 00:49:02,190\nThe answer is I have a reasonable default for\n\n900\n00:49:02,200 --> 00:49:06,560\nsome of the arguments to a designated initializer, and\n\n901\n00:49:06,570 --> 00:49:08,800\nit's actually possible to default things in swift.\n\n902\n00:49:08,800 --> 00:49:12,040\nYou can basically say, equal something. But let's say you\n\n903\n00:49:12,040 --> 00:49:15,010\nwanna default into some calculative value, maybe based\n\n904\n00:49:15,010 --> 00:49:17,080\non the other argument. A community initialize,\n\n905\n00:49:17,080 --> 00:49:20,150\ninitializer you could create would have fewer arguments and\n\n906\n00:49:20,150 --> 00:49:22,510\nthen turn around and call the designated one.\n\n907\n00:49:22,520 --> 00:49:24,420\nOkay, it's truly for convenience,\n\n908\n00:49:24,420 --> 00:49:26,950\nthat's all these are for, phew is right, okay.\n\n909\n00:49:26,950 --> 00:49:29,790\nThere's a lot of rules there. And it's a lot to think about.\n\n910\n00:49:29,790 --> 00:49:31,620\nAnd when you start writing your own initializers you're\n\n911\n00:49:31,630 --> 00:49:33,060\ngonna bump up against these all the time.\n\n912\n00:49:33,060 --> 00:49:36,190\nYou're gonna be like I can't, I can't access that one until\n\n913\n00:49:36,200 --> 00:49:38,900\nI do, yeah, I gotta call supren, okay, believe me.\n\n914\n00:49:38,900 --> 00:49:41,030\nSo try to stay away from doing your own inits,\n\n915\n00:49:41,030 --> 00:49:45,040\nis my advice to you. Okay, inheriting init.\n\n916\n00:49:45,040 --> 00:49:48,440\nNow, if you don't implement any designated inits,\n\n917\n00:49:48,440 --> 00:49:51,280\nyou'll inherit all of your superclass's designated inits.\n\n918\n00:49:51,280 --> 00:49:53,980\nBut if you in, if you implement even one designated\n\n919\n00:49:53,980 --> 00:49:56,510\ninit, you don't get any of your superclass's designated\n\n920\n00:49:56,520 --> 00:50:01,950\ninitializers, okay. If you override all of your desig,\n\n921\n00:50:01,960 --> 00:50:04,360\nclass, superclass's designated inits, or\n\n922\n00:50:04,360 --> 00:50:07,130\ndon't implement any of them, then you will inherit all of\n\n923\n00:50:07,130 --> 00:50:12,100\nthe convenience initializers from your superclass, okay. In\n\n924\n00:50:12,100 --> 00:50:13,870\nother words, the convenience superv, initializers in your\n\n925\n00:50:13,870 --> 00:50:17,570\nsuperclass are all kinda dependent on the designated\n\n926\n00:50:17,570 --> 00:50:19,840\ninitializer in your superclass being sensible and\n\n927\n00:50:19,840 --> 00:50:23,380\nmaking sense together. So you have to get them all\n\n928\n00:50:23,380 --> 00:50:27,410\nby overriding them all, or by overriding none of them. For\n\n929\n00:50:27,410 --> 00:50:29,010\nthe convenience one to inherit,\n\n930\n00:50:29,020 --> 00:50:33,280\nto make, for sure make sense, okay. If you omit no inits,\n\n931\n00:50:33,290 --> 00:50:36,220\nyou get all of your superclasses inits,\n\n932\n00:50:36,220 --> 00:50:40,030\nconvenience and designated, okay. Any in it that\n\n933\n00:50:40,030 --> 00:50:44,260\nyou inherit by these rules count on the previous slide.\n\n934\n00:50:44,260 --> 00:50:47,730\nAll right, the previous slide says things like you have to,\n\n935\n00:50:47,730 --> 00:50:50,870\nconvenience has to call a designated in your own class,\n\n936\n00:50:50,870 --> 00:50:53,270\nblah, blah, blah. Well, if you inherit it,\n\n937\n00:50:53,270 --> 00:50:56,810\nthen it is in your own class. Okay, so\n\n938\n00:50:56,810 --> 00:51:03,010\nchew on that okay. Required init, different topic.\n\n939\n00:51:03,020 --> 00:51:06,580\nIt is possible to mark an init with the keyword required.\n\n940\n00:51:06,590 --> 00:51:12,360\nThat means that a subclass must implement this init.\n\n941\n00:51:12,360 --> 00:51:14,460\nOkay, it is not optional for it, it must.\n\n942\n00:51:14,460 --> 00:51:18,960\nAnd it can inherit if it follows these rules above.\n\n943\n00:51:18,970 --> 00:51:23,570\nBut it must implement it, it's required, okay. UI view, for\n\n944\n00:51:23,570 --> 00:51:25,540\nexample, which we're gonna do on Wednesday.\n\n945\n00:51:25,540 --> 00:51:26,100\nIt has a required init.\n\n946\n00:51:26,110 --> 00:51:29,340\nOkay, and we're gonna see that. All right,\n\n947\n00:51:29,340 --> 00:51:32,440\nfailable initializers, it is possible for init to fail.\n\n948\n00:51:32,450 --> 00:51:36,180\nWe saw this double if you pass a string to the initialize,\n\n949\n00:51:36,180 --> 00:51:38,720\nif a double has an initializer it takes a string.\n\n950\n00:51:38,720 --> 00:51:41,590\nIf you pass a string. That's not a double,\n\n951\n00:51:41,590 --> 00:51:44,060\nthen it will fail, then return nil, okay.\n\n952\n00:51:44,060 --> 00:51:47,730\nSo failable initializers cause optional versions of the thing\n\n953\n00:51:47,730 --> 00:51:50,760\nto be returned and you specify them with this little question\n\n954\n00:51:50,760 --> 00:51:54,330\nmark. You put in a question mark in there, that turns\n\n955\n00:51:54,330 --> 00:51:57,670\nthis ititializer into the kind of initializer that will turn\n\n956\n00:51:57,670 --> 00:52:02,840\nan optional of this class whatever it is. Okay? And\n\n957\n00:52:02,840 --> 00:52:06,280\nto fail, you just return nil. Inside this initializer,\n\n958\n00:52:06,280 --> 00:52:09,480\nif something goes wrong, return nil, and nil will come\n\n959\n00:52:09,480 --> 00:52:13,890\nback to whoever's trying to get this thing. Make sense?\n\n960\n00:52:13,890 --> 00:52:17,690\nOkay, failable initializers are pretty rare. Images, for\n\n961\n00:52:17,690 --> 00:52:18,090\nexample, UI image,\n\n962\n00:52:18,090 --> 00:52:20,860\nimage named, if it can't find an image with this name,\n\n963\n00:52:20,860 --> 00:52:23,960\nit returns nil. Okay. So that's why this image right\n\n964\n00:52:23,960 --> 00:52:28,900\nhere Let image. This image is an Optional UIimage. And\n\n965\n00:52:28,900 --> 00:52:31,700\nwe probably use if-let here, if let image if we can like\n\n966\n00:52:31,710 --> 00:52:35,840\nthis image equal to UIimage name foo, then whatever.\n\n967\n00:52:36,940 --> 00:52:41,350\nOkay? All right. Creating Objects All right,\n\n968\n00:52:41,350 --> 00:52:45,120\nusually you create an object by calling its initializer\n\n969\n00:52:45,120 --> 00:52:49,250\nwith the appropriate arguments using the type name. So\n\n970\n00:52:49,260 --> 00:52:50,920\nCalculatorBrain, we've seen that,\n\n971\n00:52:50,920 --> 00:52:54,590\nComplicatedObject with a bunch of arguments to create it.\n\n972\n00:52:54,590 --> 00:53:00,670\nOr here's let z = the type array of String initializer.\n\n973\n00:53:00,670 --> 00:53:03,000\nOkay, that creates an empty array of string.\n\n974\n00:53:03,000 --> 00:53:08,210\nIt's constant, so it's gonna be empty forever, okay? But\n\n975\n00:53:08,210 --> 00:53:11,240\nsometimes other objects will create objects for you.\n\n976\n00:53:11,240 --> 00:53:14,180\nThey can call a method and it will create an object for you,\n\n977\n00:53:14,180 --> 00:53:14,810\ngive it to you, right? But\n\n978\n00:53:14,810 --> 00:53:18,980\nwhen you're creating objects from scratch, this is the.\n\n979\n00:53:18,990 --> 00:53:20,590\nSyntax you're using, you're used to that, right?\n\n980\n00:53:20,590 --> 00:53:25,990\nNo questions about that, it's a kind of obvious slide. Okay,\n\n981\n00:53:25,990 --> 00:53:28,990\nnow AnyObject, little more complicated here.\n\n982\n00:53:29,000 --> 00:53:32,630\nAnyObject is a special type, it's actually a protocol, but\n\n983\n00:53:32,630 --> 00:53:33,900\nwe haven't talked about it yet, but anyway,\n\n984\n00:53:33,900 --> 00:53:36,100\nit's a special type. You can leave it as a type.\n\n985\n00:53:36,100 --> 00:53:40,610\nProtocols are types, I guess. It is used Commonly, or used,\n\n986\n00:53:40,610 --> 00:53:43,910\nused to be, for compatibility with Objective-C APIs,\n\n987\n00:53:43,910 --> 00:53:47,450\nbecause Objective-C, for those of you who are trying to learn\n\n988\n00:53:47,450 --> 00:53:50,520\nsome Objective-C along the way here, Objective-C has a very\n\n989\n00:53:50,520 --> 00:53:54,720\nimportant type called ID. Okay, the type ID.\n\n990\n00:53:54,720 --> 00:54:00,560\nWhich means pointer to a object of unknown class.\n\n991\n00:54:00,560 --> 00:54:04,200\nOkay. So that's a very open-ended type. [LAUGH] Okay,\n\n992\n00:54:04,200 --> 00:54:07,400\nSwift doesn't do things that way. Swift is strongly typed.\n\n993\n00:54:07,400 --> 00:54:12,140\nOkay, it infers types but it's strongly typed. However,\n\n994\n00:54:12,140 --> 00:54:15,310\nSwift has to work with all those IOSAPIs, so\n\n995\n00:54:15,310 --> 00:54:17,080\nit introduced this type called AnyObject.\n\n996\n00:54:17,080 --> 00:54:21,680\nSo AnyObject in Swift means A point or two an object of\n\n997\n00:54:21,680 --> 00:54:24,680\nunknown class, okay? It only works for objects for\n\n998\n00:54:24,680 --> 00:54:29,350\nclasses not for structs. So it means the same thing as objective C.\n\n999\n00:54:29,360 --> 00:54:33,560\nIN iOS 9 they fixed objective C. So it has almost none of\n\n1000\n00:54:33,560 --> 00:54:38,530\nthese, okay? They're still a few but very very few. So\n移除了旧的实现。 但是在少数代码中还是存在的。\n\n1001\n00:54:38,530 --> 00:54:42,630\nnowadays It is more used as an opaque type. Okay?\n现在 AnyObject 主要用于需要隐藏具体细节的类型的场景。\n\n1002\n00:54:42,640 --> 00:54:43,400\nWhen you want to have a point or\n当你希望有一个指针指向\n\n1003\n00:54:43,400 --> 00:54:45,970\ntwo in the object and you are not sure what it is or\n一个对象，并且你不确定这个对象是什么你不希望让别人知道\n\n1004\n00:54:45,970 --> 00:54:48,370\nyou don't want anyone to know what it is okay?\n这个对象具体是什么的时候，可以考虑用 AnyObject\n\n1005\n00:54:48,380 --> 00:54:52,510\nSo let's talk about how we can do this okay? So classes only\n那么我们可以如何使用 AnyObject 这个类型呢？它只能用于 Class 类型的\n\n1006\n00:54:52,510 --> 00:54:55,680\nand no structs. There is another type by the way. It is\n对象，而不能使用在 Struct 的对象上。 这里顺带提一句， 还有另外一种类型。\n\n1007\n00:54:55,680 --> 00:55:00,080\nwhat is called any, which is anything. Could be a struct,\n叫做 Any， 他能指向任何类型的对象， 可以指向 Struct、\n\n1008\n00:55:00,090 --> 00:55:02,990\ncould be a class, anything. We almost, in fact, this class we\nClass 以及其他所有类型的对象。 事实上，我们基本上\n\n1009\n00:55:02,990 --> 00:55:06,220\nwill never use Any, okay? You probably never wanna use it.\n不会用到 Any 这个类型。 你也不会想要使用它。\n\n1010\n00:55:06,230 --> 00:55:08,930\nIt's in there, I think, for just language completeness.\n它存在的意义就在于保证语法的完整性。\n\n1011\n00:55:08,930 --> 00:55:12,130\nBut I can't even think of a good explanation of why you\n但是我完全无法想到你能使用到它的场景。\n\n1012\n00:55:12,130 --> 00:55:15,170\nwould wanna use it. So we're not even gonna talk about Any.\n所以我们这就不讨论 Any 。\n\n1013\n00:55:15,170 --> 00:55:17,040\nBut we are gonna talk about AnyObject, okay?\n我们还是继续讨论 AnyObject 吧。\n\n1014\n00:55:17,040 --> 00:55:19,270\nSo where will you see AnyObject? You'll sometimes\n想想你们都在哪见过 AnyObject ？\n\n1015\n00:55:19,270 --> 00:55:23,640\nsee it in a method where one of the arguments Truly can be\n你应该在在一些参数可能是多种类型的\n\n1016\n00:55:23,640 --> 00:55:26,340\nmore than one different kinds of class, mm kay? For\n方法中看到它对吧？\n\n1017\n00:55:26,350 --> 00:55:29,310\nexample, you'll see on Wednesday, prepare for segue\n例如将在下周三的课上才讲到的在MVC\n\n1018\n00:55:29,320 --> 00:55:33,120\nwhich is a thing that prepares for transitions from one NVC\n跳转前会调用 prepareForSegue 方法中含有 AnyObject 的参数。\n\n1019\n00:55:33,120 --> 00:55:36,590\nto another, okay? We're gonna have multiple NVCs someday.\n我们会在一个项目中含有非常多的 MVC 。\n\n1020\n00:55:36,590 --> 00:55:38,690\nWe're gonna wanna transition from one to the other, prepare\n我们经常会从一个跳转到另一个过程，\n\n1021\n00:55:38,690 --> 00:55:41,660\nfor segue prepares for that transition. Well the sender,\n而 prepareForSegue 则是为了这种跳转而存在的。 至于该方法的参数 sender，\n\n1022\n00:55:41,660 --> 00:55:45,100\nin other words the object that initiated the transition could\n换句话来说，这个对象用来初始化跳转，并且它包含\n\n1023\n00:55:45,100 --> 00:55:47,100\nbe lots of different kinds of objects.\n许多不同的类型的对象。\n\n1024\n00:55:47,100 --> 00:55:48,430\nIt might be a button you collect on,\n他可能是一个按钮\n\n1025\n00:55:48,440 --> 00:55:51,200\nit might be a roll in a table, it might be some custom code\n他可能是一个一个在列表中的滚动条， 它可能是一段在你的 Controller 中自定义的代码。\n\n1026\n00:55:51,200 --> 00:55:55,240\ninside of your controller. Okay? So this sender has to be\n所以这个 sender 参数必须使用 AnyObject 类型。\n\n1027\n00:55:55,240 --> 00:55:59,840\nany object. Okay, cuz we don't know what it is. We\n因为我们不知道具体情况下，它是什么？\n\n1028\n00:55:59,850 --> 00:56:03,410\ndon't know if it is a button or table row or what it is.\n我们不知道它是否是一个按钮、列表或者是其他什么东西。\n\n1029\n00:56:03,420 --> 00:56:06,580\nSo AnyObject. Okay. So this is a case where he is an object,\n因此最好使用 AnyObject。 这就是一个对象使用 AnyObject 的例子，\n\n1030\n00:56:06,590 --> 00:56:09,650\nit could be many things we don't know what it is.\n他可能是非常多类型的对象， 而我们不知道它具体是什么。\n\n1031\n00:56:09,660 --> 00:56:12,060\nSo we have to type this as AnyObject.\n所以我们这里必须使用 AnyObject 类型。\n\n1032\n00:56:12,060 --> 00:56:15,930\nOkay? Another example of that is touch digit. If we haven't,\n另外一个例子就是之前用到的 touchDigit 方法。\n\n1033\n00:56:15,930 --> 00:56:16,630\nwhen we control dragged,\n如果在我们拖拽链接中，\n\n1034\n00:56:16,630 --> 00:56:19,630\nremember when we changed it from any object to UI button,\n忘记了从 AnyObject 改成 UIButton 的情况下。\n\n1035\n00:56:19,630 --> 00:56:22,200\nOkay. If we hadn't done that, it would have created a touch\n如果我们忘记了修改， 他将会创建一个 touchDigit 方法，\n\n1036\n00:56:22,200 --> 00:56:25,170\ndigit with sender AnyObject and then touch digit could've\n该方法带有一个 AnyObject 类型的 sender 参数， 这样 touchDigit 方法\n\n1037\n00:56:25,170 --> 00:56:29,140\nbeen sent by a UI button or maybe by UI slider. Okay. Or\n可能由一个 UIButton 触发或者是 UISlider 触发。\n\n1038\n00:56:29,140 --> 00:56:32,710\nsomething else. And we didn't do that because the inside\n当时我们当时并没有用 AnyObject 类型的参数是因为\n\n1039\n00:56:32,710 --> 00:56:34,910\ntouch digit we wanted sender to be a UI button so\n我们希望触发 touchDigit 放的的对象是 UIButton 的类型。\n\n1040\n00:56:34,910 --> 00:56:38,920\nwe just send it current title and other button things, but\n这样我们就可以获得他的内容以及一些其他按钮的属性或方法，\n\n1041\n00:56:38,920 --> 00:56:43,820\nit could have been AnyObject, all right? So, another use for\n但是其实它还是可以改成 AnyObject。\n\n1042\n00:56:43,820 --> 00:56:46,690\nAnyObject is when you wanna return essentially a cookie,\n当时想要用一个密封的 Cookie 的时候， 你也可以用 AnyObject 类型。\n\n1043\n00:56:46,690 --> 00:56:49,290\nokay? A cookie is something\nCookie 是一个\n\n1044\n00:56:49,300 --> 00:56:52,230\nyou give back where you're giving it to someone,\n你给一个指定的人\n\n1045\n00:56:52,230 --> 00:56:53,360\nthey don't know what's inside of it,\n但是他们不需要知道它里面的内容，\n\n1046\n00:56:53,370 --> 00:56:56,100\nyou're not gonna tell them, the only thing they can do\n你也不希望告诉他们， 他们所要做的就是将它\n\n1047\n00:56:56,100 --> 00:57:00,340\nis give it back to you, okay? So the cookie just saves some\n再传递给你。 所有 Cookie 只是保存了一些\n\n1048\n00:57:00,340 --> 00:57:03,510\nstate, remembers something and you can give it back. So\n状态， 或者是一些你能知道内部实现的东西。\n\n1049\n00:57:03,510 --> 00:57:06,540\nbrowsers have cookies, right? You go visit a browser site,\n因此浏览器有对应的 Cookie， 当你访问一个网站，\n\n1050\n00:57:06,550 --> 00:57:10,480\nthe site stores some stuff about itself and about you in\n该网站会存储很多关于它的信息以及保存一些关于你信息\n\n1051\n00:57:10,480 --> 00:57:13,180\ntheir cookie. When you go away and come back to that site,\n的 Cookie。 当你离开这个网站的时候，这些 Cookie 会传回该网站，\n\n1052\n00:57:13,190 --> 00:57:15,590\nit looks in the cookie and it can interpret it, okay?\n如此看来的话， 该网站对 Cookie 应该是可理解的。\n\n1053\n00:57:15,590 --> 00:57:16,890\nBut it gives the cookie to the browser.\n但是当将这个 Cookie 给浏览器时，\n\n1054\n00:57:16,890 --> 00:57:19,120\nThe browser has no idea what's in there. Okay.\n浏览器完全无法知道它具体是什么内容。\n\n1055\n00:57:19,130 --> 00:57:23,530\nTo pick with AnyObject as far as the browser is concerned.\n因此用 AnyObject 是浏览器最好的选择。\n\n1056\n00:57:23,530 --> 00:57:27,870\nAll right. So how do we use a variable type AnyObject when\n那么我们如何使用一个 AnyObject 类型的对象， 并且\n\n1057\n00:57:27,870 --> 00:57:30,940\nwe don't know what the heck it is? Okay. And the answer is we\n我们不知道它具体的内容？ 答案是\n\n1058\n00:57:30,940 --> 00:57:33,640\nhave to convert it to a type that we do know what it is.\n我们必须将其转换成一个我们知道的类型。\n\n1059\n00:57:33,640 --> 00:57:36,970\nOkay. Now this conversion might not be possible.\n当然， 这种换换过程可能会失败，\n\n1060\n00:57:36,980 --> 00:57:40,310\nAll right, because that thing might not be of that type\n因为在我们转换的过程中，\n\n1061\n00:57:40,310 --> 00:57:41,350\nwhen we try to convert it. So\n我们所转换的对象可能不是那种类型。\n\n1062\n00:57:41,350 --> 00:57:46,820\nwe use this as keyword in Swift to try to convert it to\n因此我们在 Swift 中用一个关键字 as 尝试去\n\n1063\n00:57:46,820 --> 00:57:50,150\nthe other type. Okay. In other words, try to treat that\n转换成其他类型。 也就是说， 你尝试将 AnyObject\n\n1064\n00:57:50,160 --> 00:57:54,990\nAnyObject as something else, optionally. So this is an op,\n转换成其他东西。 转换后\n\n1065\n00:57:54,990 --> 00:57:59,000\nthis returns an optional. Okay, we usually, usually use\n返回的是 Optional 的类型。 我们经常用 if let 的方式\n\n1066\n00:57:59,000 --> 00:58:01,970\nit with if let, this as thing because it ensure an optional,\n因为用这个中法获得的一定是 Optaional 的类型。\n\n1067\n00:58:01,970 --> 00:58:04,670\nright? So if I have this local variable here,\n例如我这里有一个变量，\n\n1068\n00:58:04,670 --> 00:58:08,870\nAO which is in AnyObject and I was tying it to something,\nao 是一个 AnyObject 类型， 并且我尝试将它转换成\n\n1069\n00:58:08,880 --> 00:58:12,280\nsome class I don't know what it is, okay? But I wanna try\n其他类型, 并且我们不知道 ao 具体是什么类型。 但是这里我希望将其\n\n1070\n00:58:12,280 --> 00:58:17,420\nand use AO as if it were of class SomeClass, okay,\n换换成 SomeClass 这种类型。\n\n1071\n00:58:17,420 --> 00:58:20,180\nAO might be of SomeClass, and I'm gonna see if it is, and\nao 可能是 SomeClass 这种类型， 那么如果它是的话，\n\n1072\n00:58:20,190 --> 00:58:23,890\nif it is I'm gonna use it as some class, I say if I can let\n我们将其转换成 SomeClass 并且使用它， 也就是说如果我能让 foo\n\n1073\n00:58:23,890 --> 00:58:28,990\nfoo equal AO as SomeClass, then in here there's gonna be\n等于 ao 转换成 SomeClass 的对象不为空的话， 那么我这里将会等一个\n\n1074\n00:58:29,000 --> 00:58:32,530\na local variable foo, which is not gonna be AnyObject, it's\n名为 foo 的本地变量， 并且 foo 将不再是 AnyObject 类型， 应该\n\n1075\n00:58:32,530 --> 00:58:38,240\ngonna be of type SomeClass. Got it? Just to that symbol\n是 SomeClass 类型。 明白了吗？ 使用这种方式\n\n1076\n00:58:38,240 --> 00:58:42,840\nessentially casting if you wanna use that terminology?\n将其转换成想要的类型。\n\n1077\n00:58:42,840 --> 00:58:46,940\nCasting any object to be some class conditionally, okay?\n使用 let if 这种方式将 AnyObject 转换成想要转换的类型即可。\n\n1078\n00:58:46,950 --> 00:58:51,420\nSo that's how we use something of AnyObject either that or\n这就是我们如何使用 AnyObject 对象的方式， 或者是在我们\n\n1079\n00:58:51,420 --> 00:58:54,650\nwe don't know what's in there we just pass it around. Okay,\n不青春它具体的内容是，而只是传递它时使用。\n\n1080\n00:58:54,650 --> 00:58:57,960\njust pass it around to people who know what to do with it.\n将其传递给真正知道它是什么内容的人。\n\n1081\n00:58:57,960 --> 00:59:02,660\nWe don't know what to do with it if it's a cookie, okay? So,\n我们不知道一个 Cookie 具体能做什么。\n\n1082\n00:59:02,660 --> 00:59:05,400\nwhat would code look like let's say on touchDigit.\n那么如果 touchDigit 方法使用 AnyObject 参数该如何写？\n\n1083\n00:59:05,400 --> 00:59:08,870\nIf we had touchDigit and we had any object instead.\n如果我们有一个 touchDigit 带有 AnyObject 的参数的话。\n\n1084\n00:59:08,870 --> 00:59:13,340\nWe probably say if we can let sendingButton equal the sender\n我们可能会使用如果 sendingButton 等于 sender 转换成\n\n1085\n00:59:13,340 --> 00:59:16,240\nas a UIbutton, then we'll treat it as a button,\nUIButton 并且 sendingButton 不为空的话， 我们将其转换成，\n\n1086\n00:59:16,240 --> 00:59:19,410\nget its currentTitle and go. Other wise else if\n然后获得他的内容以及调用它的方法等。 另一方面， 如果\n\n1087\n00:59:19,410 --> 00:59:23,510\nwe can let sending slider equal to sender as UI slider,\n能将其转换成 UISlider 并且不为空的话，\n\n1088\n00:59:23,520 --> 00:59:26,720\nthen we'll let the digit equal the sending sliders value\n那么数字就等于 Slider 的值。\n\n1089\n00:59:26,720 --> 00:59:28,820\nwhich is a double, we'll convert it to an int and\n但是由于其实 Double 类型，所以我们需要将其转换成 Int\n\n1090\n00:59:28,820 --> 00:59:31,790\nwe'll convert that to a string, okay? That's how we\n然后再转换成 String 类型。 这就是如何获得具体\n\n1091\n00:59:31,790 --> 00:59:35,660\nget the digit. Did you see how we're doing kinda if let else,\n数值的方式。 大家看清楚 if let 的方式\n\n1092\n00:59:35,660 --> 00:59:39,060\nif let else? With this optional thing, that's how we\n该如何操作了吗？ 这就是我们处理 AnyObject 的方式。\n\n1093\n00:59:39,070 --> 00:59:43,700\nwould use that AnyObject. All right, another use\n还有一种使用 AnyOject 的场景就是\n\n1094\n00:59:43,700 --> 00:59:49,140\nof AnyObject is Property List, okay? So Property Lists are,\n用在 Property List 中。 因为 Property List 中可能包含\n\n1095\n00:59:49,140 --> 00:59:53,080\nessentially any combination of array, dictionary, string,\n数组、 字典、 字符串\n\n1096\n00:59:53,080 --> 00:59:57,080\ndouble, int, NSData, and NSDate. Kay, if you build\nDouble、 Int、 NSData 甚至是 NSDate 类型的数据。\n\n1097\n00:59:57,080 --> 00:59:59,520\nany data structure out of only those classes,\n如果你使用这些类型来存储数据的话，\n\n1098\n00:59:59,520 --> 01:00:02,220\nyou got a property list. So it's just a word. It's just\n那么你就能获得一个 Property List。 这就是我们\n\n1099\n01:00:02,220 --> 01:00:06,160\na term we use to mean that. Kay, that's what it means.\n想要的类型。 这就是它的含义。\n\n1100\n01:00:06,160 --> 01:00:10,130\nAnd you might feel like, wait a second. Array,\n等等，或许你会想：\n\n1101\n01:00:10,130 --> 01:00:13,160\nAnyObject has to be a class, it cannot be a structs.\nAnyObject 是一个Class类型， 而不是 Struct 类型。\n\n1102\n01:00:13,170 --> 01:00:16,000\nBut string, array, dictionary, double, those are structs.\n但是 String、 Array、 Dictionary、 Double 这些都是 Struct 类型。\n\n1103\n01:00:16,000 --> 01:00:18,740\nSo how could this ever be in a property list. How could it\n那么他们如何包含在一个 Property List 中呢？\n\n1104\n01:00:18,740 --> 01:00:23,210\never be any object. And the answer is the bridging, kay?\n他们是如何转换成 AnyObject 类型呢？ 答案是桥接。\n\n1105\n01:00:23,210 --> 01:00:26,110\nWe got this automatic bridging to Objective-C, kay?\n它们能自动转换成Objective C。\n\n1106\n01:00:26,110 --> 01:00:30,310\nIt automatically treats them like NSDictionary, NSArray,\n它们会自动转换成 NSDictionary、 NSArray、\n\n1107\n01:00:30,320 --> 01:00:34,890\nNSNumber, which are all classes. And allows them to be\nNSNumber 或者是任何它们的封装类型。 这样就允许他们转换成 AnyObject了。\n\n1108\n01:00:34,890 --> 01:00:39,820\nAnyObject, kay? Now these property lists\n那么通过这种方式\n\n1109\n01:00:39,830 --> 01:00:43,560\nare passed around blindly. The people who are looking in them\nProperty List 就在传递过程中可以不让人知道具体内容。 那么及时有人破解它的话，\n\n1110\n01:00:43,560 --> 01:00:46,730\nare only knowing that their dictionaries and\n他们也只能知道字典、数组\n\n1111\n01:00:46,730 --> 01:00:47,900\narrays of strings and dates and stuff.\n字符串、日期以及一些其他的东西。\n\n1112\n01:00:47,900 --> 01:00:50,800\nThey don't know anything about what that data means, okay.\n但是他们却不知道具体数据的含义。\n\n1113\n01:00:50,800 --> 01:00:52,600\nThey're just being passed around, so\n那么它就可以被传递了。\n\n1114\n01:00:52,610 --> 01:00:55,010\nlet's look at an API and iOS that uses a property\n那么让我们看看 iOS 中的一个 API， 一个便于\n\n1115\n01:00:55,010 --> 01:00:58,610\nlist to understand it better. It's called NSUserDefaults.\n我们理解 Property List 的API。 那就是 NSUserDefaults。\n\n1116\n01:00:58,610 --> 01:01:02,110\nWhat NSUserDefaults does, is it takes a property list and\n那么 NSUserDefaults 是拿来干嘛的呢？ 它是用来缓存 Property List\n\n1117\n01:01:02,120 --> 01:01:05,550\nmakes it persistent on disk. So when your app quits and\n并且将其保存到磁盘上的。 那么当你 App 退出重启后，\n\n1118\n01:01:05,550 --> 01:01:08,190\nruns again and you look it up again, it's there.\n你能从新查询到保存的数据， 因为它保存在磁盘了。\n\n1119\n01:01:08,190 --> 01:01:10,660\nSo it's basically a database of property lists,\n它有点类似一个 Property List 的基础数据库，\n\n1120\n01:01:10,660 --> 01:01:14,830\na database of structures with dictionaries, arrays, dates,\n一个包含字典，数组，日期的数据库。\n\n1121\n01:01:14,830 --> 01:01:17,060\nokay, that's what it is.\n这就是N SUserDefaults。\n\n1122\n01:01:17,060 --> 01:01:19,430\nIt's a small database so don't use it for big things.\n由于它是一个微型数据库，所以我们一般用它来保存大的数据。\n\n1123\n01:01:19,430 --> 01:01:21,700\nYou wouldn't wanna store like a dictionary of the entire\n例如你绝对不会想用它来保存\n\n1124\n01:01:21,700 --> 01:01:23,330\nEnglish language in there. It's for\n所以英语的字典。\n\n1125\n01:01:23,340 --> 01:01:26,870\nsmall things like settings and things like that. The API on\n他只是用来存一些小东西，例如设置、配置等一些小的东西。\n\n1126\n01:01:26,870 --> 01:01:30,810\nit is very simply just say, setObject, property list here,\n并且它的接口也非常简单， 只需要调用 setObject 用来存 Property List,\n\n1127\n01:01:30,810 --> 01:01:33,710\nforKey, string. And then you can look it up and\n用 String 来存 Key。 这样你就可以通过\n\n1128\n01:01:33,710 --> 01:01:36,280\nget the property list back. So here you can see how you're\nget 方法重新获得具体的 Property List。 你可以看得出，这里你\n\n1129\n01:01:36,280 --> 01:01:39,450\njust passing it around. You're storing it as a cookie and\n只是负责传递给NSUserDefaults。 你想保存 Cookie 一样保存它，\n\n1130\n01:01:39,450 --> 01:01:41,750\nit's user defaults has no idea what's inside there.\n并且 NSUserDefaults 对于里面具体是什么完全不了解。\n\n1131\n01:01:41,750 --> 01:01:44,290\nIt just knows it's only array is dictionary strings,\n它只知道他可能是数组、 字典、 字符串\n\n1132\n01:01:44,290 --> 01:01:48,830\nints, etc, okay. It can also restore smaller things.\n数值等一些数据。 并且能通过它重新获得这些小数据。\n\n1133\n01:01:48,830 --> 01:01:51,130\nLike as I said a double, and it will make a little property\n例如我告诉它保存一个 Double， 那么他就会创建一个小的 Property List\n\n1134\n01:01:51,130 --> 01:01:54,300\nlist out of a double because a double by itself Is a property\n用来保存 Double， 因为 Double 会是一个 Property List 类型。\n\n1135\n01:01:54,300 --> 01:01:58,200\nlist, right? Because it's one of those classes, okay?\n它是一个 Class 的类型。\n\n1136\n01:01:58,200 --> 01:02:01,710\nJust like array is. How do you use user defaults?\n就像一个数组一样。 那么你是如何使用 NSUserDefaults 的呢？\n\n1137\n01:02:01,710 --> 01:02:06,810\nYou create a shared one using this class or type method,\n你只需调用它的类方法，\n\n1138\n01:02:06,810 --> 01:02:08,980\nNSUserDefaults.standardUserDe- faults().\n一个叫 NSUserDefaults.standardUserDefaults() 的方法。\n\n1139\n01:02:08,980 --> 01:02:12,320\nThis gives you the shared instance of standard, of user\n这个方法将会返回一个共享的 NSUserDefaults 对象。\n\n1140\n01:02:12,320 --> 01:02:17,320\ndefaults. And then you just say To it. Get me a certain\n接下来你只需调用它的方法获得数据，或者\n\n1141\n01:02:17,320 --> 01:02:21,630\nproperty list, write this property list out. The changes\n将一些数据写入即可。\n\n1142\n01:02:21,630 --> 01:02:23,730\nyou make will automatically be saved eventually, but\n这些改变将会自动的保存下来，\n\n1143\n01:02:23,730 --> 01:02:26,200\nif you wanna force them to be saved on disk, you can do\n但是如果你想强制将其保存到磁盘的话， 你可以调用\n\n1144\n01:02:26,200 --> 01:02:29,530\nsynchronize, which returns a bool, which we almost always\nsynchronize 这个方法， 这个方法返回一个布尔类型，\n\n1145\n01:02:29,540 --> 01:02:31,400\nignore because not clear what to do if it fails.\n这个返回值经常被我们忽略， 因为我们并不清楚它做什么，并且是否失败。\n\n1146\n01:02:31,400 --> 01:02:33,900\nIt would probably only fail if your disk were full.\n如果返回时的false的话， 则表示你的磁盘以满。\n\n1147\n01:02:33,910 --> 01:02:36,810\nNot sure what you're gonna do at that point, but any way.\n并且你不确定如果失败了你应该做什么。\n\n1148\n01:02:36,810 --> 01:02:41,710\nWe usually ignore that return value, okay? Another example\n我们经常会忽略这个返回值。\n\n1149\n01:02:41,710 --> 01:02:45,250\nof property list might be in our calculator brain and\n另一个使用 Property List 的例子将会在我们的 CalculatorBrain中使用，\n\n1150\n01:02:45,250 --> 01:02:46,680\nI'm gonna show you a demo of this.\n我将会在接下来的Demo进行展示。\n\n1151\n01:02:46,690 --> 01:02:50,790\nReally quick here, which is, what if we wanted to get\n接下来会讲非常快，关于假如我们希望在计算器中\n\n1152\n01:02:50,790 --> 01:02:53,590\nthe program that it's in the calculator? Right now,\n获得它之前的运算结果。\n\n1153\n01:02:53,590 --> 01:02:55,560\nour calculator could be programmed by saying\n现在的计算能可以计算出类似：\n\n1154\n01:02:55,560 --> 01:02:58,730\nfive times four times three equals, let's put a program\n5 乘以 4 乘以 3 等于什么这种运算， 我们只需将具体\n\n1155\n01:02:58,730 --> 01:03:00,900\nin the calculator, right? Five times four times three.\n操作输入计算器中即可。 输入 5 * 4 * 3.\n\n1156\n01:03:00,900 --> 01:03:03,930\nIt's kinda simple program. It'd be cool if we get\n这个是非常简单的运算， 那么如果计算器能\n\n1157\n01:03:03,940 --> 01:03:05,400\nthat program and the person who got it,\n将这种与运算表达式交给一个完全\n\n1158\n01:03:05,400 --> 01:03:08,570\nit doesn't know anything about our internal data structure.\n不了解运算表达式内部实现的人，那肯定非常溜的功能。\n\n1159\n01:03:08,570 --> 01:03:10,940\nSo it's AnyObject to them. And then later,\n那么这就可以用上 AnyObject了。\n\n1160\n01:03:10,940 --> 01:03:12,280\nthey could come back to the CalculatorBrain and\n只需将重新传递运算表达式给 CalculatorBrain，\n\n1161\n01:03:12,280 --> 01:03:16,810\nsay. Run this program that you gave me earlier, you see? So\n并且告诉它， 运行这些你之前给我的运算表达式， 这样就可以得到答案了。\n\n1162\n01:03:16,820 --> 01:03:19,920\nwe use AnyObject as kind of this opaque program.\n因此我们在这里用 AnyObject 来代表一个不透明的运算表达式。\n\n1163\n01:03:19,920 --> 01:03:22,220\nOkay. Now this doesn't seem very variable right now.\n不过现在看起来好像不可以带参数的。\n\n1164\n01:03:22,220 --> 01:03:24,520\nBut it's gonna be really valuable in assignment two,\n但是我们希望将其做成可带参数的，\n\n1165\n01:03:24,520 --> 01:03:27,730\nwhen you're gonna add variables to your calculator.\n之后只需将参数的具体值告诉给你的计算器即可。\n\n1166\n01:03:27,730 --> 01:03:31,130\nYou're gonna be able to say three times X times five\n也许你希望保存表达式 3 * X * 5这种表达式，\n\n1167\n01:03:31,130 --> 01:03:32,900\nequals, where X is a variable, and\n其中 X 是一个变量，\n\n1168\n01:03:32,900 --> 01:03:36,370\nthen you can run this then you get this program using this\n那么你可以使用我接下来\n\n1169\n01:03:36,370 --> 01:03:40,170\ncode I'm going to show you here, the property list, and\n将要完成的代码， 并且在代码中使用 Property List，这样你\n\n1170\n01:03:40,170 --> 01:03:43,170\nthen later you can, they can set the variable x and\n可以做到了， 你可以设置变量 X 的值，并且重新运行\n\n1171\n01:03:43,180 --> 01:03:45,940\nrun it again. Maybe set the x to something else and\n具体的表达式。 可以设置 X 为任意的一个值，然后\n\n1172\n01:03:45,950 --> 01:03:47,680\nrun the program again and again and again, you see?\n不断的重复运行这个表达式。\n\n1173\n01:03:47,680 --> 01:03:50,650\nSo this would be a good use of AnyObject, because\n那么希望这样的话， 最好使用 AnyObject 类型，\n\n1174\n01:03:50,650 --> 01:03:54,150\nthe calculator brain doesn't wanna give away its internal\n因为 CalculatorBrain 并不想泄露\n\n1175\n01:03:54,150 --> 01:03:57,090\ndata struc for how, structure for how it represents\n他的类型以及它是如何\n\n1176\n01:03:57,090 --> 01:04:00,660\na program. But it's happy to let someone have the program\n重新运算该表达式的。  但是可以让别人拥有该运算表达式，\n\n1177\n01:04:00,660 --> 01:04:04,660\nand give it to them later and they'll run again it later.\n并且将其重新交给计算器， 计算器将会重新计算该运算表达式。\n\n1178\n01:04:04,660 --> 01:04:06,000\nMake sense, see why we want it?\n这样就可以理解为什么使用 AnyObject 了吧？\n\n1179\n01:04:06,000 --> 01:04:07,830\nNow why would we make it a property list?\n那么我们这里为什么要用使用 Property List 呢？\n\n1180\n01:04:07,830 --> 01:04:10,870\nBecause it'd be nice to store it in user defaults, right?\n因为这样方面将其存入到 NSUserDefaults 里。\n\n1181\n01:04:10,870 --> 01:04:13,200\nI've got a program? I'm gonna put it in the user defaults.\n当我获得一个表达式之后， 我将其保存在 NSUserDefaults 中。\n\n1182\n01:04:13,210 --> 01:04:15,440\nNext time my program runs, I can pull it out and\n当下次我的程序运行时， 我能从 NSUserDefaults 重新获得，\n\n1183\n01:04:15,440 --> 01:04:17,340\nask a calculator brain to run it. You see,\n然后让 CalculatorBrain 重新运算它。\n\n1184\n01:04:17,340 --> 01:04:19,280\nit's just more flexible to be a property list.\n由此可以看出 Property List 相对比较灵活。\n\n1185\n01:04:19,280 --> 01:04:21,850\nSo that's what we're gonna do. We're gonna create a var\n我们接下来就按照上面的方法来实现。 首先，我们在 CalculatorBrain 中先创建一个\n\n1186\n01:04:21,850 --> 01:04:23,510\ncalled program in our calculator brain.\n叫做 program 的的属性。\n\n1187\n01:04:23,520 --> 01:04:25,880\nIt's gonna be gettable and settable. When you get it,\n并且给他添加 get 和 set 的方法。 当你获得它的值得时候，\n\n1188\n01:04:25,890 --> 01:04:29,420\nit gets the current program in, that the calculator brain\n他将会给出之前当前表达式， 之前计算过的表达式。\n\n1189\n01:04:29,420 --> 01:04:33,220\nhas just run, and if you set it, it runs the program, okay?\n当时你设置它的值得时候， 该表达式会重新运算一遍。\n\n1190\n01:04:33,230 --> 01:04:35,660\nAll right, so I'm gonna do that as the demo. I'm gonna\n好的，接下来我讲在我们的Demo上添加该功能。\n\n1191\n01:04:35,660 --> 01:04:38,600\nfinish off the slides here first. One thing about this\n不过我们先讲完所有的幻灯片。 首先是关于强制转换的，\n\n1192\n01:04:38,600 --> 01:04:41,800\ncasting, you can cast other things besides any object,\n你可以强制转换任何类型，而不单单是 AnyObject。\n\n1193\n01:04:41,800 --> 01:04:45,270\nokay. So you, for example, you can look at this slide later,\n例如像幻灯片上所展示的，\n\n1194\n01:04:45,270 --> 01:04:48,010\nbut you could have a class that's a subclass of another\n当你有一个子类的对象指向父类的指针的情况下，\n\n1195\n01:04:48,010 --> 01:04:51,740\nclass, okay? And you can try and cast using as to get\n你可以将父类指针强制转换成子类的对象。\n\n1196\n01:04:51,740 --> 01:04:55,550\nthe subclass. You're not sure whether it's a subclass, but\n虽然你没办法确定它是否是子类的对象，\n\n1197\n01:04:55,550 --> 01:04:58,550\nyou can cast and as will tell you whether it is, okay?\n但是你可以通过强制转换的结果告诉你是否是其子类。\n\n1198\n01:04:58,550 --> 01:05:01,220\nIn this case, for example, if I have view controller\n例如，我有一个UIViewController的变量，\n\n1199\n01:05:01,220 --> 01:05:03,720\nthe base class of our view controller, we can't say\n但是我们没办法使用\n\n1200\n01:05:03,720 --> 01:05:06,890\nvc.displayValue cuz this is a CalculatorViewController\nvc.displayValue, 因为这个属性是属于 CalculatorViewController 的属性。\n\n1201\n01:05:06,890 --> 01:05:09,030\nthing. But if I went and as'ed it, okay,\n当时如果我进行强制转换的话，\n\n1202\n01:05:09,030 --> 01:05:12,800\nif I took this VC and as'ed it to CalculatorViewController,\n我将其强制转换成 CalculatorViewController 后，\n\n1203\n01:05:12,800 --> 01:05:16,470\nnow I could use displayValue. Okay, so as is for\n我就可以使用 displayValue 这个属性了。 因此强制转换\n\n1204\n01:05:16,470 --> 01:05:18,400\nmore than just any object.\n不单单是针对 AnyObject。\n\n1205\n01:05:18,400 --> 01:05:20,470\nOkay, and yes, you can force with as!,\n当然你也可以使用关键字 as! 来进行强制转换，\n\n1206\n01:05:20,470 --> 01:05:23,740\nit'll crash if it can't do it. Assertions I'm not gonna talk\n但是如果没办法进行强制转换的话， 你的程序会崩溃。 我不会在这里进行\n\n1207\n01:05:23,740 --> 01:05:26,240\nabout cuz we talked about it in the debugging section.\n讲解断言， 因为我们将在调试的章节进行讲解。\n\n1208\n01:05:26,250 --> 01:05:29,850\nYou can look at the slide or the reading assignment to find\n你可以查看幻灯片或者是阅读作业来查看\n\n1209\n01:05:29,850 --> 01:05:32,780\nout more about assert. And that's it. So coming up on\n更多的关于断言的信息。 记得周三来听\n\n1210\n01:05:32,790 --> 01:05:35,820\nWednesday I'm gonna start talking about custom drawing.\n关于自定义绘制的课程。\n\n1211\n01:05:35,820 --> 01:05:38,160\nOn Friday we don't have a section for this week.\n这周五， 我们没有课程。\n\n1212\n01:05:38,160 --> 01:05:40,960\nAnd next Monday I'm gonna start talking about gestures,\n下周我们我们开始讲解手势，\n\n1213\n01:05:40,960 --> 01:05:43,690\nmulti-touch gestures, okay, pinches and swipes and\n多点触摸手势， 缩放以及滑动手势等，\n\n1214\n01:05:43,700 --> 01:05:45,860\nstuff leading up to your assignment three,\n并且该内容将会在你的第三次作业中用到，\n\n1215\n01:05:45,870 --> 01:05:48,130\nwhich is you're gonna be doing a lot of drawing and\n第三次作业包含了绘制、 多 MVC 以及其他的一些内容。\n\n1216\n01:05:48,130 --> 01:05:50,970\nmultiple MVCs and all that stuff. Your assignment this\n这周的作业是\n\n1217\n01:05:50,970 --> 01:05:53,370\nweek is going to be the variables thing, okay?\n关于变量的题目。\n\n1218\n01:05:53,370 --> 01:05:57,710\nAll right, so let's do that program var, okay?\n接下来我们开始实现 program 属性吧。\n\n1219\n01:05:58,780 --> 01:06:02,110\nJust gonna go back to our calculator here, all right,\n重新回到计算器的程序，\n\n1220\n01:06:02,110 --> 01:06:07,080\nand leave off exactly where we were. All right,\n回到我们之前结束的地方。\n\n1221\n01:06:07,090 --> 01:06:08,690\nso here's my controller, right here.\n屏幕上显示的是我的 Controller。\n\n1222\n01:06:08,690 --> 01:06:10,890\nI'm not gonna change my controller to do this.\n目前我还不打算修改 Controller。\n\n1223\n01:06:10,890 --> 01:06:13,760\nThis is purely a brain thing, okay, here's my brain,\n所需修改的都在 CalculatorBrain 中，\n\n1224\n01:06:13,760 --> 01:06:16,790\ncalculator brain. So I'm gonna add a new var.\n这就是我的 CalculatorBrain 的代码， 我讲为其添加一个新的属性。\n\n1225\n01:06:16,800 --> 01:06:21,430\nLet's put it I don't know, down here, okay?\n我们加在那呢？ 就这里吧。\n\n1226\n01:06:21,430 --> 01:06:25,040\nIt's gonna be called program. It's AnyObject.\n取名为 program， 类型为 AnyObject。\n\n1227\n01:06:25,040 --> 01:06:27,870\nNow I'm gonna make it be AnyObject, but I'm also gonna\n这里虽然我给他的类型为 AnyObject， 但是我同事也可以给他的类型\n\n1228\n01:06:27,870 --> 01:06:30,440\nmake it be a property list, cuz it's more useful.\n为 PropertyList， 因为这个名字更加有可读性。\n\n1229\n01:06:30,440 --> 01:06:32,380\nPeople can put it in as user defaults or whatever.\n其他人可以将其存在 NSUserDefaults 或者是其他的地方。\n\n1230\n01:06:32,380 --> 01:06:35,880\nSo I'm gonna use a cool Swift thing called typealias.\n这里就要用到一个 Swift 的一个特性， 叫做 typealias 。\n\n1231\n01:06:35,880 --> 01:06:38,720\ntypealias lets you create a type, a name type,\ntypealias 让你可以创建一个新的类型， 一个别名的类型，\n\n1232\n01:06:38,720 --> 01:06:41,450\nthat's exactly the same as some other type. So\n它实际上与你绑定的类型是等价的。\n\n1233\n01:06:41,450 --> 01:06:45,890\nI'm gonna create a type called PropertyList which equals\n这里我讲创建一个叫做 PropertyList 的类型，并且它与\n\n1234\n01:06:45,890 --> 01:06:50,330\nAnyObject. So PropertyList is now a type in Swift.\nAnyObject 等价。 那么这样之后， PropertyList 就是一个新的类型了。\n\n1235\n01:06:50,330 --> 01:06:52,100\nIt's exactly the same thing as AnyObject.\n但是其实他是跟 AnyObject 等价的。\n\n1236\n01:06:52,100 --> 01:06:55,000\nNow why would I create this? That's because\n为什么我要创建这个类型呢？\n\n1237\n01:06:55,000 --> 01:06:57,530\nI'm gonna change this to say PropertyList. So\n因为我希望这里的类型名称是 PropertyList。\n\n1238\n01:06:57,540 --> 01:07:00,240\nI'm gonna cha, make the type of my program be PropertyList.\n然后将 program 的类型修改成新的类型 PropertyList。\n\n1239\n01:07:00,240 --> 01:07:03,110\nThis tells anyone using my program that yeah,\n这就等于告诉任何用 program 属性的人，\n\n1240\n01:07:03,110 --> 01:07:06,540\nit's AnyObject but it's also a PropertyList, okay?\n虽然他是一个 AnyObject 类型，但是它同样是 PropertyList 类型。\n\n1241\n01:07:06,550 --> 01:07:09,910\nThis is documentation. I'm essentially documenting here\n这就是文档化， 我本来就是进行文档化\n\n1242\n01:07:09,920 --> 01:07:11,720\nthat this AnyObject is PropertyList.\n即 AnyObject 改名为 PropertyList。\n\n1243\n01:07:11,720 --> 01:07:14,990\nI could have also just put some comments in my code that\n并且我也会将在代码中添加对应的注释\n\n1244\n01:07:14,990 --> 01:07:18,590\nsays it is, but this kind of really hammers home the po,\n这是一个非常好的做法将 program 的\n\n1245\n01:07:18,590 --> 01:07:21,690\nthe point here that this is a PropertyList,\n类型修改成 PropertyList。\n\n1246\n01:07:21,690 --> 01:07:25,860\nokay? Now I'm gonna have my program here be computed,\n现在我将要把我的运算表达式拿来计算。\n\n1247\n01:07:25,870 --> 01:07:29,530\nokay? So I'm gonna do the get set thing, right? And\n因此我要添加 get 和 set 方法。\n\n1248\n01:07:29,540 --> 01:07:33,140\nso now I need to have my program internally,\n因此我需要有一个内部的变量用来存储运算表达式，\n\n1249\n01:07:33,140 --> 01:07:35,870\nI mean, internally store my program, so I'm actually gonna\n我的意思是在该类中存储运算表达式的变量，\n\n1250\n01:07:35,880 --> 01:07:39,240\ngo up to the top and create another private var\n因此我们回到程序的上端，添加一个新的私有属性\n\n1251\n01:07:39,250 --> 01:07:41,780\nwhich is my internalProgram. And\n名叫 internalProgram 的属性。\n\n1252\n01:07:41,780 --> 01:07:44,350\nso I have to think about how I'm gonna store my program,\n因此我需要考虑我应该如何存储我的运算表达式，\n\n1253\n01:07:44,350 --> 01:07:48,250\nyou know, all the operands and operations, internally. And\n而我们知道所有的运算表达式都是有操作数和操作符组成的。\n\n1254\n01:07:48,250 --> 01:07:50,950\nI'm just gonna store it to show you the power of\n因此我只需要存储这些信息，并且用来展示 AnyObject 的强大。\n\n1255\n01:07:50,960 --> 01:07:56,760\nAnyObject. I'm gonna store it as an array of AnyObject,\n因此我这里用一个 AnyObject 的数组来存储这些信息。\n\n1256\n01:07:56,760 --> 01:08:01,530\nokay? And the objects in that array are gonna be a double if\n而数组中的元素可能是 Double 类型，当然是一个操作数的时候，\n\n1257\n01:08:01,530 --> 01:08:05,500\nit's an operand or a string if it's an operation. So\n可能是一个 String 类型，当它是一个操作符的时候。\n\n1258\n01:08:05,500 --> 01:08:08,410\nI'm gonna have an array that has a mix of doubles and\n因此我这里需要一个混合了 Double 和 String 类型的数组，\n\n1259\n01:08:08,410 --> 01:08:11,280\nstrings, okay, and that's gonna store my program.\n用来存储的运算表达式。\n\n1260\n01:08:11,280 --> 01:08:14,010\nI'm just gonna put operands in as doubles and I'm gonna put\n我只需将操作数以 Double 的形式进行存储，\n\n1261\n01:08:14,010 --> 01:08:16,780\noperations as strings. So that's another power of\n将操作符以 String 的形式进行存储。 这里就能展示 AnyObject 的优势之一了。\n\n1262\n01:08:16,780 --> 01:08:20,180\nAnyObject here. So how do I implement my internalProgram?\n那么我应该如何使用 internalProgram 呢？\n\n1263\n01:08:20,190 --> 01:08:24,690\nReal simple, okay. When I set an operand, I'm just gonna\n非常简单， 当我调用 setOperand 的时候，\n\n1264\n01:08:24,690 --> 01:08:29,830\ntell my internalProgram append that operand, oops.\n我只需将对应的操作数添加到 internalProgram 中即可。\n\n1265\n01:08:29,830 --> 01:08:32,430\nOkay, now normally this is AnyObject.\n当时这里使用的是 AnyObject 类型做为数组元素的类型，\n\n1266\n01:08:32,430 --> 01:08:36,900\nOperand is a double, that's a struct. That normally wouldn't\n但是操作数是一个 Double 的类型， 它是一个Struct。 原本应该是没办法\n\n1267\n01:08:36,900 --> 01:08:39,800\nwork, but the bridging, the Objective-C bridging,\n存入数组中的， 但是苹果的桥接技术做到了， 就是与 Objective-C 的桥接技术\n\n1268\n01:08:39,810 --> 01:08:43,340\nwill make this work. Okay, I told you everywhere in the UI\n使的操作数能存入数组中。 我之前在讲 UI 的时候也提到过，\n\n1269\n01:08:43,340 --> 01:08:45,310\nwhere you have this compatibility,\nSwift 与 Objective-C 是具有非常好的兼容性。\n\n1270\n01:08:45,310 --> 01:08:46,840\nit's gonna automatically bridge.\n因为苹果内部已经实现了自动的桥接技术。\n\n1271\n01:08:46,850 --> 01:08:48,980\nI don't, look, I don't have to do anything or say anything.\n而我不需要做任何事情。\n\n1272\n01:08:48,980 --> 01:08:52,150\nIt just automatically always bridges when necessary.\n当它需要兼容的时候，就会自动进行桥接。\n\n1273\n01:08:52,150 --> 01:08:54,220\nOkay, similar down here in my operation.\n当然，下面的操作符也是同样的处理方式。\n\n1274\n01:08:54,220 --> 01:08:57,150\nWhen someone performs an operation, I'm just gonna tell\n当有人调用 performOperation 时， 我只需将它加到\n\n1275\n01:08:57,160 --> 01:09:00,420\nmy internalProgram append the symbol for this operation.\n运算表达式的 internalProgram 变量即可。\n\n1276\n01:09:00,430 --> 01:09:02,990\nOkay, that's a string. Again, a struct but\n但是操作符是一个 String， 同样是一个 Struct 类型，\n\n1277\n01:09:03,000 --> 01:09:06,200\nit's automatically bridged to NSString and\n但是它会自动使用桥接技术， 转换成 NSString 类型，\n\n1278\n01:09:06,200 --> 01:09:09,330\nthus can be an AnyObject. Okay, that's it, that's\n所能能将其转换成 AnyObject 类型。\n\n1279\n01:09:09,340 --> 01:09:11,470\nthe entire implementation of my internalProgram.\n这就是关于所有的 internalProgram 属性的使用。\n\n1280\n01:09:11,470 --> 01:09:14,770\nI'm just remembering every operand and operation.\n我只需记住没有一个操作数和操作符即可。\n\n1281\n01:09:14,770 --> 01:09:19,610\nSo now I'm just gonna return that internalProgram here,\n接着在这里我只需返回 internalProgram 即可，\n\n1282\n01:09:19,610 --> 01:09:20,980\nokay, to be the program.\n用来返回 prgram。\n\n1283\n01:09:20,980 --> 01:09:24,150\nNow you might be freaking out, whoa, you're returning\n也许你会吓到， 为什么你这里\n\n1284\n01:09:24,150 --> 01:09:27,780\nyour internal data structure here to a public caller. But\n要讲私有的数据返回给公用的接口？\n\n1285\n01:09:27,790 --> 01:09:32,560\nwhat kind of type is an array? A value type. And\n但是数组具体是什么类型？ 是一个值传递的类型。\n\n1286\n01:09:32,560 --> 01:09:36,830\nwhat happens when you return a value type? It gets copied.\n那么一个值传递类型的数据作为返回值会出现什么情况？ 会用它的副本进行返回。\n\n1287\n01:09:36,830 --> 01:09:40,360\nOkay, so I'm not returning a pointer to my internal data\n因此我不是返回一个指向内部数据的指针对象，\n\n1288\n01:09:40,370 --> 01:09:44,370\nstructure here, I'm returning a copy. Okay, that's, again,\n而是返回它的一个副本而已。\n\n1289\n01:09:44,370 --> 01:09:47,100\na cool thing about having these things be value types.\n由此可以看出一个值传递类型的优点。\n\n1290\n01:09:47,110 --> 01:09:50,470\nAll right, so now we have to do the set. So someone can now\n那么解析来我们实现一下 set 方法。 目前别人能获得\n\n1291\n01:09:50,480 --> 01:09:53,180\nget my program and they can give it back to me later and\n我的运算表达式， 并且之后会将其重新交给我，\n\n1292\n01:09:53,180 --> 01:09:55,580\nI have to run it. Okay, so how am I gonna do that?\n而我必须重新运算一遍这个表达式。 那么我该如何实现呢？\n\n1293\n01:09:55,580 --> 01:09:59,380\nWell, when someone sets my program, first I'm gonna clear\n首先，当有人需要重新给我运算表达式的时候， 我先要清空\n\n1294\n01:09:59,390 --> 01:10:03,190\nwhatever's in my program. So you, you guys probably\n当前的运算表达式。 而在之后的作业中，\n\n1295\n01:10:03,190 --> 01:10:07,490\nimplemented something like this for your homework, but\n也可能会遇到类似的题目。\n\n1296\n01:10:07,490 --> 01:10:11,660\nI'm gonna, see clear my accumulator. I'm gonna say\n而这里我需要重置操作数， 将\n\n1297\n01:10:11,660 --> 01:10:15,070\nthat I have no pending binary operation. And I'm gonna\npending 属性有置为空并且\n\n1298\n01:10:15,070 --> 01:10:18,640\nclear my internalProgram that I currently have out.\n将当前存储的操作数和操作符都清空。\n\n1299\n01:10:18,640 --> 01:10:22,240\nActually I'll just removeAll items from my internalProgram.\n事实上我只需将数组中的所有元素移除即可。\n\n1300\n01:10:22,240 --> 01:10:25,540\nOkay, so that's clear cuz I'm running a new program, so\n这就是我的清空方法， 然后我需要重新运算新的运算表达式，\n\n1301\n01:10:25,540 --> 01:10:26,880\nI wanna clear all my stuff out.\n但是在此之前我必须重置我的所有属性。\n\n1302\n01:10:26,880 --> 01:10:29,910\nRight, make sense? Now I'm just gonna say if\n而我现在只需判断\n\n1303\n01:10:29,920 --> 01:10:34,180\nthe program they get me, gave me is an array of op,\n他们给我的新的运算表达式是否是一个操作数和操作符的数组，\n\n1304\n01:10:34,190 --> 01:10:37,050\noperands and operations, so I'm gonna\n而我这里只需要\n\n1305\n01:10:37,060 --> 01:10:41,560\nsay if I can let arrayOfOps equal this newValue that they\n通过 if let arrayOfOps = newValue as? [AnyObject]\n\n1306\n01:10:41,560 --> 01:10:46,230\njust gave me as an array of AnyObject, which it has to be.\n的语句进行判断，并且该判断必须要成立。\n\n1307\n01:10:46,230 --> 01:10:48,930\nIf it's not that, I can just ignore this. Someone gave\n如果它不成立的话，我就直接忽视它即可。\n\n1308\n01:10:48,930 --> 01:10:51,600\nme a program which was not one that I gave out, so I'm\n例如有人给了一个运算表达式给我， 但是却不是从我这里给出的，\n\n1309\n01:10:51,600 --> 01:10:54,540\nignoring it, cuz it's gotta be an array of AnyObject or\n那么我讲忽视它， 因此它必须是一个 AnyObject 的数组，\n\n1310\n01:10:54,540 --> 01:10:57,610\nI can't figure out what it is. So if it is, now I'm just\n否则我无法判断里面具体是什么内容。 那么如果它是一个数组的话，\n\n1311\n01:10:57,610 --> 01:10:59,840\ngonna go look through at all the ops in there,\n我只需遍历所有在数组中\n\n1312\n01:10:59,850 --> 01:11:03,550\nall the operations and operands. Okay, an arrayOfOps.\n的操作数和操作符。\n\n1313\n01:11:03,550 --> 01:11:06,620\nOkay, that's how we loop through an array, right, for\n这就是我们常用的遍历数组的方式———— for in 的方式。\n\n1314\n01:11:06,620 --> 01:11:09,950\nin. And for each one I'm gonna check and see what it is.\n对于每一个元素我都进行检查看看它是什么。\n\n1315\n01:11:09,960 --> 01:11:12,460\nNow what type, if I can Alt-click on this,\n那么这里的 op 是什么类型呢？ 如果我通过 Alt + 左键点击op的话，\n\n1316\n01:11:12,460 --> 01:11:16,090\nwhat type is this gonna be? >> AnyObject?\n会显示什么类型呢？ [学生回答] AnyObject ?\n\n1317\n01:11:16,100 --> 01:11:16,930\n>> AnyObject, exactly.\n对的， 就是 AnyObject 类型。\n\n1318\n01:11:16,930 --> 01:11:20,530\nSee, AnyObject. So I can't do anything with AnyObject,\n看见没， 就是 AnyObject 类型。 但是我们还没办法处理 AnyObject 类型，\n\n1319\n01:11:20,530 --> 01:11:23,100\nso I have to try and see if I can make it something else.\n因此我必须尝试看看能否做一些其他的事情。\n\n1320\n01:11:23,100 --> 01:11:27,400\nSo I'm gonna first try and make it be an operand by\n首先我先进行判断它是否是一个 Double 类型的\n\n1321\n01:11:27,410 --> 01:11:32,010\nsaying op as a Double, okay? So if I get to here,\n操作数？ 如果运行到这一行的话，\n\n1322\n01:11:32,010 --> 01:11:32,140\nthen this op,\n那么这个 op 在数组中的变量\n\n1323\n01:11:32,140 --> 01:11:36,380\nthe next thing I looked in the array was a Double. Excellent,\n就是一个 Double 类型的数据。\n\n1324\n01:11:36,380 --> 01:11:39,680\nthen I can just say setOperand to be that operand, okay,\n那么接下来我就可以调用  setOperand 来进行进行处理这个操作数。\n\n1325\n01:11:39,690 --> 01:11:43,090\ncuz I'm running the program. So I'm just gonna replay,\n因为我这里是重新运行运算表达式， 所以我这里只需对\n\n1326\n01:11:43,090 --> 01:11:46,290\nbasically, my operands and operations. Otherwise,\n操作数和操作符进行一遍运算。\n\n1327\n01:11:46,290 --> 01:11:49,990\nif I can let, let's say operation = op as a String,\n另一方面， 我通过 let operation = op as? String 来进行判断是否是操作数，\n\n1328\n01:11:50,000 --> 01:11:54,770\nokay, then I'm going to perform that operation.\n如果是操作数的话， 这里就调用一下 performOperation 的方法。\n\n1329\n01:11:58,540 --> 01:12:03,070\nOkay? Done, okay, very simple, I've done it.\n实现好了，非常简单吧。\n\n1330\n01:12:03,080 --> 01:12:05,810\nNow you're going to have to really make sure you\n那么目前你必须保证你是理解\n\n1331\n01:12:05,810 --> 01:12:09,450\nunderstand this, because you need to enhance this for your\n这些代码的， 因为你需要对该项目进行完善， 在作业中\n\n1332\n01:12:09,450 --> 01:12:12,750\nassignment number two. Because you're gonna have variables,\n用到类似的方法。 例如你将用到变量，\n\n1333\n01:12:12,750 --> 01:12:15,490\nyou're gonna have to deal with here too. You're gonna have\n而你也需要处理这些变量。\n\n1334\n01:12:15,490 --> 01:12:19,020\nvariables in your program, not just operands and operations.\n你需要处理的你的运算表达式， 而不是仅仅的操作数与操作符。\n\n1335\n01:12:19,020 --> 01:12:20,520\nNow, let's see this thing in action.\n那么看我们来实际运行看看。\n\n1336\n01:12:20,530 --> 01:12:22,760\nWe've got this code and we wanna make sure it works, so\n我们写好了这些代码，我们需要确认是否它实现成功了，\n\n1337\n01:12:22,760 --> 01:12:25,930\nlet's put something in our UI that actually checks\n我们需要在界面上添加一些东西来检查这段\n\n1338\n01:12:25,930 --> 01:12:26,700\nthis program business.\n程序的正确性。\n\n1339\n01:12:26,700 --> 01:12:27,800\nSo, I'm gonna go back to my storyboard.\n所以我们先回到我们的 Storyboard。\n\n1340\n01:12:27,800 --> 01:12:31,600\nI'm gonna steal a couple of buttons here. I'm gonna make\n我这里只需要修改一些按钮。\n\n1341\n01:12:31,600 --> 01:12:34,540\nthis be the save button and this be the restore button.\n将这个按钮变成保存的按钮， 而下面一个按钮变成重新运算的按钮。\n\n1342\n01:12:34,540 --> 01:12:37,670\nSo I'm gonna have the save button, save the program, and\n而保存的按钮用来保存之前的运算表达式，\n\n1343\n01:12:37,680 --> 01:12:40,940\nthen I have the restore button, restore the program.\n重新运算的按钮用来重新运算之前的的运算表达式。\n\n1344\n01:12:40,950 --> 01:12:43,980\nOkay, so you can see how it would look like to use that.\n这样你就可以想象我们应该如何使用它了。\n\n1345\n01:12:43,980 --> 01:12:48,120\nSo these are not operation buttons anymore, so\n而这两个按钮不在是操作符的按钮，\n\n1346\n01:12:48,120 --> 01:12:51,990\nI'm gonna disconnect using right-click,\n所以我需要通过右键来断开之前链接的事件，\n\n1347\n01:12:51,990 --> 01:12:54,590\nall these perform operations. Okay,\n所有这两个按钮的事件回调。\n\n1348\n01:12:54,590 --> 01:12:59,760\nthen I'm gonna wire these up. Let's make some room. Wire up,\n解析来我要重新绑定事件的回调。 让我们让 Xcode 多一些控件来进行绑定。\n\n1349\n01:12:59,770 --> 01:13:05,200\ndown here. All right, so I'm gonna wire up save first.\n那么我们先对保存按钮进行绑定事件的回调方法。\n\n1350\n01:13:05,200 --> 01:13:09,440\nPut it right here. I'll call it save. It's an action.\n将其拖拉到这里， 并且给方法取名为 save, 设置它是 Action。\n\n1351\n01:13:09,440 --> 01:13:09,640\nIt doesn't need an arg,\n该方法不需要参数，\n\n1352\n01:13:09,640 --> 01:13:11,980\nI don't need the sender this time, this is the first time\n这次回调方法不需要一个参数， 这是我们第一次遇到不需要\n\n1353\n01:13:11,980 --> 01:13:14,410\nwe've seen where we don't need the sender. Okay,\n参数的回调方法。\n\n1354\n01:13:14,410 --> 01:13:16,810\nat least the first time not in your homework.\n至少不是在你的作业中的第一次遇到。\n\n1355\n01:13:16,820 --> 01:13:22,020\nAnd here's restore. And restore is also an action, and\n同样的方法拉一个 restore 的事件回调， 同样是一个 Action，\n\n1356\n01:13:22,020 --> 01:13:25,260\nit doesn't need an argument either. Here we go, there's\n同样不需要一个参数。 这样就可以了，\n\n1357\n01:13:25,260 --> 01:13:28,530\nsave and restore. Okay, how am I gonna implement this? Well,\n这就是我们的两个按钮的事件回调的方法。 那么我具体该如何实现呢？\n\n1358\n01:13:28,530 --> 01:13:32,100\nI need the saved program, so I'm gonna have a savedProgram.\n我需要保存之前的运算表达式， 所以我需要一个 saveProgram 的属性。\n\n1359\n01:13:32,100 --> 01:13:34,560\nIts type could be any object, but\n它的类型可以是 AnyObject， 但是\n\n1360\n01:13:34,570 --> 01:13:40,000\nI'm actually gonna have it be CalculatorBrain.PropertyList.\n这里更建议使用 CalculatorBrain.PropertyList 的类型。\n\n1361\n01:13:40,010 --> 01:13:42,970\nJust to be clear to myself, this is a property list, and\n首先你的自己清楚， 这是一个 PropertyList，\n\n1362\n01:13:42,980 --> 01:13:45,810\nif I wanted to save this into NFC or default,\n并且如果我我想将其存入 NSUserDefaults 的话，\n\n1363\n01:13:45,810 --> 01:13:49,150\nI could. Okay, but I'm not going to, but I could.\n我也能做到。  但是目前我还没算这样做， 即使我是能做到的。\n\n1364\n01:13:49,150 --> 01:13:51,150\nAll right, so how do I save?\n那么我该如何实现 save 方法呢？\n\n1365\n01:13:51,150 --> 01:13:52,780\nAnd I'm gonna make this optional because,\n在此之前我应该将其变成一个 Optional 的类型，\n\n1366\n01:13:52,790 --> 01:13:54,420\nof course I might not have hit save yet.\n因为我刚开始可能没有保存过预算表达式。\n\n1367\n01:13:54,420 --> 01:13:55,090\nSo it's gonna start out as nil,\n那么它的初始值应该是 nil .\n\n1368\n01:13:55,090 --> 01:13:57,850\nas soon as I hit save it's gonna have a value. All right,\n直到我触发 save 方法之后， 它才会有值。\n\n1369\n01:13:57,860 --> 01:14:02,430\nso how do I save? Well, I'm just gonna say that this\n那么我们该如何实现 save 方法呢？ 我应该\n\n1370\n01:14:02,430 --> 01:14:06,630\nsavedProgram = the calculators brain.program.\n将 CalculatorBrain 中的 program 保存到 savedProgram 即可。\n\n1371\n01:14:06,630 --> 01:14:10,400\nOkay, that's gonna store it in there, really good, you see?\n只需在这里保存即可， 非常简单， 对吧？\n\n1372\n01:14:10,400 --> 01:14:15,910\nHow about restore? Okay, well, if I have a savedProgram\n那么 restore 方法又该如何实现呢？ 如果 savedProgram 不为\n\n1373\n01:14:15,910 --> 01:14:21,080\n!= nil, then I'm just gonna set the brains.program\n空的话， 我将其重新传递给 CalculatorBrain。\n\n1374\n01:14:21,080 --> 01:14:23,710\n= savedProgram. Okay, I have to unwrap it,\n并且我这里需要强制解析它，\n\n1375\n01:14:23,720 --> 01:14:27,350\ncuz it's an optional. And then I'd better update my display\n因为他是一个 Optional 的类型。 然后我需要更新我\n\n1376\n01:14:27,350 --> 01:14:30,390\nvalue now because the brain is gonna have a different result.\n显示的值， 因为 CalculatorBrain 可能重新运算后会有不同的结果。\n\n1377\n01:14:30,390 --> 01:14:34,420\nIt's got a new program, it's gonna have a different result,\n因为它获得了一个新的运算表达式， 所以它可能会运算跟当前显示不同的结果。\n\n1378\n01:14:34,430 --> 01:14:36,230\ngot it? Okay now, this code,\n看明白这段代码了吗？\n\n1379\n01:14:36,230 --> 01:14:38,330\nyou don't need this in your assignment. This is,\n这些代码应该在作业中用不到。\n\n1380\n01:14:38,330 --> 01:14:41,160\nI'm only putting this here just to demonstrate program.\n这只是我放在这里的实例代码而已。\n\n1381\n01:14:41,170 --> 01:14:43,170\nYou will need the other code in CalculatorBrain,\n你需要在 CalculatorBrain 中的其他代码，\n\n1382\n01:14:43,170 --> 01:14:46,340\nbut you will not need this code. Okay, let's go ahead and\n而不需要这段代码。 那么让我重新\n\n1383\n01:14:46,340 --> 01:14:55,310\nrun this. All right,\n运行这个程序。\n\n1384\n01:14:55,310 --> 01:14:57,780\nhere we go, make this a little bigger. All right,\n将模拟器变大一点。\n\n1385\n01:14:57,780 --> 01:15:00,620\nlet's rotate so that our restore button looks better.\n将模拟器进行旋转一下， 这样我们的 restore 按钮看起来更美观一点。\n\n1386\n01:15:00,620 --> 01:15:03,290\nAll right, here we go. So let's put a program in here,\n我们先输入一个表达式，\n\n1387\n01:15:03,290 --> 01:15:10,060\n4 x 5 + 1 =. Okay, that's 21. Okay, let's save that program,\n输入 4 乘以 5 加上 1 等于。 答案是21. 然后点击保存按钮。\n\n1388\n01:15:10,060 --> 01:15:14,930\nnow let's do pi square root. Okay, that's good, + 8 =,\n然后在点击π、 根号、 加号、 8 等一些其他按钮。\n\n1389\n01:15:14,930 --> 01:15:18,740\nsomething like that. Now let's restore. What should happen to\n然后点击 restore 按钮， 那么会发生什么呢？\n\n1390\n01:15:18,740 --> 01:15:21,540\nour display when I restore? >> 21.\n如果我点击 restore 后。 [学生回答] 21.\n\n1391\n01:15:21,540 --> 01:15:22,370\n>> 21 cuz it's gonna rerun\n答案是21， 因为我们重新运算了之前的\n\n1392\n01:15:22,370 --> 01:15:27,440\nthat program. And sure enough, there it is.\n运算表达式。 这个是可以肯定的。\n\n1393\n01:15:27,450 --> 01:15:30,480\nOkay, 14 divided by 7=, restore. Okay, we, we,\n14 除以 7 等于， 点击restore。 看见没？\n\n1394\n01:15:30,480 --> 01:15:34,450\nwe've run that program, and that's the result in there, so\n我们重新运算了之前的表达式， 所以它的结果就展示在这里了。\n\n1395\n01:15:34,450 --> 01:15:38,890\nwe can say x 2 =. Okay, we could save\n而我们可以针对结果继续运算， 如乘以 2 等于之类的。\n\n1396\n01:15:38,890 --> 01:15:42,530\nit again. Okay, 47 divide 8 =, and now when we restore,\n当然我们重新保存新的表达式。 继续输入 47 除以 8 等于， 然后我们在点击 restore 按钮，\n\n1397\n01:15:42,530 --> 01:15:45,300\nwe'll get 42, which is the meaning of life, the universe,\n我们还是能拿到 42，也就是说无论从哪个角度来\n\n1398\n01:15:45,300 --> 01:15:47,900\nand everything, and so we're done, okay. So\n说， 我们都完成了想要的功能。\n\n1399\n01:15:47,900 --> 01:15:52,500\nget that program to code into your app, okay.\n将这部分代码拷贝到你们的程序中，\n\n1400\n01:15:52,500 --> 01:15:55,570\nYou'll need to add that to your assignment one, and then\n你将会在作业一种需要用到这些代码，\n\n1401\n01:15:55,570 --> 01:15:58,610\nI will be publishing, I might actually publish assignment\n当然我会将这些代码发布出来， 我也会将作业二\n\n1402\n01:15:58,610 --> 01:16:01,110\ntwo before Wednesday, okay. It goes out on Wednesday,\n在周三前发布出来。 作业将在周三发布，\n\n1403\n01:16:01,110 --> 01:16:03,280\ndue the next Wednesday. But for those of you who want to\n直到下周三为止。 当然对于那些想先多学一点\n\n1404\n01:16:03,280 --> 01:16:05,580\nstart a little early, cuz you know everything you need to\n的同学们， 因为已经学会了一些\n\n1405\n01:16:05,580 --> 01:16:08,650\nknow now to do assignment two as well, okay. So\n你们也可以提前做作业二。\n\n1406\n01:16:08,650 --> 01:16:13,060\nI'll probably publish that earlier, maybe tomorrow.\n我会尽早将其发布出来，也可能是明天。\n\n1407\n01:16:13,060 --> 01:16:13,520\n>> For more,\n想获得更多信息，\n\n1408\n01:16:13,530 --> 01:16:13,560\nplease visit us at stanford.edu.\n请访问我们的网站 stanford.edu。\n\n"
  },
  {
    "path": "subtitles/4. Views.srt",
    "content": "1\n00:00:00,001 --> 00:00:03,769\n[MUSIC]\n\n2\n00:00:03,771 --> 00:00:07,573\nStanford University. Okay,\n\n3\n00:00:07,575 --> 00:00:11,910\nwell welcome to Lecture four of Stanford's CS193P,\n欢迎来到2016春季Stanford CS193P 第四讲\n\n4\n00:00:11,912 --> 00:00:16,682\nspring of 2016. Today our topic is views. Okay,\n我们今天的主题是Views\n\n5\n00:00:16,684 --> 00:00:19,485\nviews are the rectangular areas on screen that we draw\nview就是我们在屏幕上绘画的矩形区域\n\n6\n00:00:19,487 --> 00:00:22,821\nin. Its also the places where we handle multi-touch,\n它也是我们处理多点触摸的地方\n\n7\n00:00:22,823 --> 00:00:26,392\nwe'll be talking about that next week. So today is,\n我们将在下周讨论这个\n\n8\n00:00:26,394 --> 00:00:28,560\nit's all about the drawing side and I have, of course,\n所以今天我们只讨论绘图方面\n\n9\n00:00:28,562 --> 00:00:32,765\nhave a demo where we're gonna draw a custom view, okay? So\n当然,我们有一个将绘出自定义view的Demo\n\n10\n00:00:32,767 --> 00:00:35,634\nlet's talk about views. The view is that rectangular area,\n所以让我们来讨论一下views,View是一块矩形的区域\n\n11\n00:00:35,636 --> 00:00:39,104\nas I said. It defines a coordinate space, okay?\n正如我所说,它定义了一块坐标空间\n\n12\n00:00:39,106 --> 00:00:42,041\nSo, any time you're drawing or handling input, or whatever,\n所以,任何时候你需要绘图、处理输入或者其他的事情时\n\n13\n00:00:42,043 --> 00:00:45,010\nyou need a coordinate space to be defined for you. And,\n你需要一块定义好的坐标空间\n\n14\n00:00:45,012 --> 00:00:49,581\nuse that space to draw and to handle touch events. This kind\n并且利用这块空间来绘图和处理触摸事件\n\n15\n00:00:49,583 --> 00:00:53,886\nof view setup is hierarchical, as you might imagine, so,\n这种view是分层的，如你所想\n\n16\n00:00:53,888 --> 00:00:58,824\nyou can imagine that you have some view, like maybe this is\n你可以想象你拥有一个view，也许\n\n17\n00:00:58,826 --> 00:01:01,960\nthe view that contains your entire UI for an MVC.\n包含了你的MVC中全部UI的view\n\n18\n00:01:01,962 --> 00:01:05,130\nAnd then, you've got some sub views maybe they're buttons,\n随后你得到了一些子view，比如按钮\n\n19\n00:01:05,132 --> 00:01:08,233\nor whatever, and they might be inside a view,\n或是其他什么东西。他们可能在一个view的内部\n\n20\n00:01:08,235 --> 00:01:10,602\nlike let's say a stack view or something like that.\n比如我们说过的StackView或是其他类似的东西\n\n21\n00:01:10,604 --> 00:01:13,172\nAnd, maybe those are in another view, okay? So,\n这些可能都在另外的一个view之中,okay?\n\n22\n00:01:13,174 --> 00:01:16,075\nyou can see how these things are hierarchical, right?\n你们能够看出这些东西的层级结构吗对吗？\n\n23\n00:01:16,077 --> 00:01:19,311\nYou're building your views in a hierarchy,\n你们将一层一层的来构建你的视图\n\n24\n00:01:19,313 --> 00:01:22,848\na view hierarchy we call it, okay? Now,\n我们称作视图的层级, okay?\n\n25\n00:01:22,850 --> 00:01:26,752\nthese views can overlap, obviously.\n显然，view是可以部分重叠的\n\n26\n00:01:26,754 --> 00:01:30,089\nAnd, they also, even if you have a view inside a view, so\nview也可以在另外的view之中\n\n27\n00:01:30,091 --> 00:01:31,657\na view, let's say in this view right here,\n\n28\n00:01:31,659 --> 00:01:35,427\nif you had another view inside it, it could actually extend\n\n29\n00:01:35,429 --> 00:01:39,665\noutside the bounds of its parent, that's legal. And,\n\n30\n00:01:39,667 --> 00:01:42,134\nyou can set a switch in the view whether it's going to\n\n31\n00:01:42,136 --> 00:01:45,871\nclip, and only show this part, or whether it'll allow this\n\n32\n00:01:45,873 --> 00:01:50,742\nthing to draw outside of its parent, okay? So,\n\n33\n00:01:50,744 --> 00:01:52,478\nthat's how we build our user interface,\n\n34\n00:01:52,480 --> 00:01:54,113\nis by kinda grouping these things together.\n\n35\n00:01:54,115 --> 00:01:57,116\nYou're totally familiar with that in the calculator.\n\n36\n00:01:57,118 --> 00:02:01,553\nAnd, when you build something like this, every view ends up\n\n37\n00:02:01,555 --> 00:02:04,857\nhaving a single super view, right? That's the view that\n\n38\n00:02:04,859 --> 00:02:07,893\nit's inside. And, any given view could have\n\n39\n00:02:07,895 --> 00:02:11,230\nany number of sub-views, okay? Like the stack views could\n\n40\n00:02:11,232 --> 00:02:14,600\nhave any number of things stacked inside of whatever.\n\n41\n00:02:14,602 --> 00:02:18,604\nThe sub-views, you can find them for a view by looking at\n\n42\n00:02:18,606 --> 00:02:21,240\nthis VAR, the CUI view VAR called sub-views.\n\n43\n00:02:21,242 --> 00:02:25,210\nYou see it's an array of UI view there, and,\n\n44\n00:02:25,212 --> 00:02:27,279\nwe'll talk a little later about the order of those\n\n45\n00:02:27,281 --> 00:02:31,450\nsub-views matters. And that's it basically,\n\n46\n00:02:31,452 --> 00:02:35,287\nokay? That's how we represent this new hierarchy.\n\n47\n00:02:35,289 --> 00:02:40,225\nThere is a UI window in iOS, but it almost doesn't matter,\n\n48\n00:02:40,227 --> 00:02:42,027\nokay? You're never gonna interact with it.\n\n49\n00:02:42,029 --> 00:02:45,130\nThere's always only one, per app. Actually, you could have\n\n50\n00:02:45,132 --> 00:02:48,767\nmore than one if you had like an external screen, okay?\n\n51\n00:02:48,769 --> 00:02:53,705\nLike you were doing, what do we call, the, the screen cast,\n\n52\n00:02:53,707 --> 00:02:57,709\nit's not coming to me, where you can, have a second screen.\n\n53\n00:02:57,711 --> 00:03:00,345\nI can't think of it but, like on Apple TV,\n\n54\n00:03:00,347 --> 00:03:01,180\nyou could have a second screen for\n\n55\n00:03:01,182 --> 00:03:05,984\nyour device. Whatever, so then you might have two UI windows,\n\n56\n00:03:05,986 --> 00:03:07,452\nbut it wouldn't matter cuz you're almost never gonna\n\n57\n00:03:07,454 --> 00:03:09,588\ncreate one or send a message to one or whatever. So,\n\n58\n00:03:09,590 --> 00:03:12,925\nit's all about views, it's all about this view hierarchy that\n\n59\n00:03:12,927 --> 00:03:15,694\nwe're gonna build okay, in iOS. It's unlike on the Mac,\n\n60\n00:03:15,696 --> 00:03:17,829\nwhere of course the Mac you've got windows, right,\n\n61\n00:03:17,831 --> 00:03:20,899\nseparate windows. You don't really have that, in iOS,\n\n62\n00:03:20,901 --> 00:03:25,504\nnot enough room really to do that. This hierarchy\n\n63\n00:03:25,506 --> 00:03:28,574\nis most often constructed in Xcode graphically.\n\n64\n00:03:28,576 --> 00:03:31,677\nLike you did with the calculator, okay? But,\n\n65\n00:03:31,679 --> 00:03:33,745\nyou can build this hierarchy in code.\n\n66\n00:03:33,747 --> 00:03:36,181\nThe two methods are add subview, and\n\n67\n00:03:36,183 --> 00:03:38,450\nremove from super view, that's putting them in and\n\n68\n00:03:38,452 --> 00:03:41,186\ntaking them out., Notice that add subview is sent\n\n69\n00:03:41,188 --> 00:03:44,022\nto the future super view of the view saying, hey,\n\n70\n00:03:44,024 --> 00:03:47,059\nor add this sub view to yourself. Remove from subview\n\n71\n00:03:47,061 --> 00:03:50,195\nis actually sent to the view you want to remove, okay?\n\n72\n00:03:50,197 --> 00:03:53,565\nSo, remove from subview from super view rather is kind of\n\n73\n00:03:53,567 --> 00:03:56,668\nlike remove yourself from your super view, okay?\n\n74\n00:03:56,670 --> 00:04:00,839\nWhere does the view hierarchy start? It starts\n\n75\n00:04:00,841 --> 00:04:05,077\nright at the top, in that MVC that we see in the storyboard,\n\n76\n00:04:05,079 --> 00:04:07,446\nthere's a view that fills that whole space.\n\n77\n00:04:07,448 --> 00:04:10,682\nThere is a pointer from your view controller to that top\n\n78\n00:04:10,684 --> 00:04:15,854\nlevel view, okay? That pointer is called view. So,\n\n79\n00:04:15,856 --> 00:04:17,522\nif you look at view controller, right,\n\n80\n00:04:17,524 --> 00:04:18,523\neveryone knows what view controller is?\n\n81\n00:04:18,525 --> 00:04:20,826\nThat's where you put a lot of your code in the calculator,\n\n82\n00:04:20,828 --> 00:04:23,762\nright? Where you wired up all your outlets and actions.\n\n83\n00:04:23,764 --> 00:04:27,032\nThat class, view Controller has a var called view.\n\n84\n00:04:27,034 --> 00:04:28,267\nYou haven't used it yet. But,\n\n85\n00:04:28,269 --> 00:04:32,437\nit is a pointer to the top level UI View. Okay, and\n\n86\n00:04:32,439 --> 00:04:34,573\nthat's an important view to have a pointer to because\n\n87\n00:04:34,575 --> 00:04:36,642\nyou're gonna be adding subviews to it, etcetera,\n\n88\n00:04:36,644 --> 00:04:39,011\nespecially if you're doing it programmatically.\n\n89\n00:04:39,013 --> 00:04:39,578\nYou really need this var so\n\n90\n00:04:39,580 --> 00:04:43,882\nyou can call add subview on it and put some things in there.\n\n91\n00:04:43,884 --> 00:04:45,484\nAnd, this view is automatically hooked up for\n\n92\n00:04:45,486 --> 00:04:48,487\nyou, in your storyboard. So, you don't have to do anything.\n\n93\n00:04:48,489 --> 00:04:51,823\nIt's just automatically hooked up, okay? And,\n\n94\n00:04:51,825 --> 00:04:55,060\nthis top level view is the view whose bounds will change,\n\n95\n00:04:55,062 --> 00:04:57,496\nfor example, when you rotate your device, right?\n\n96\n00:04:57,498 --> 00:05:01,767\nThe bounds go from being tall and thin, to being short and\n\n97\n00:05:01,769 --> 00:05:05,237\nwide, okay? That's the bounds of this top level view.\n\n98\n00:05:05,239 --> 00:05:08,006\nNow, when you change the bounds of this top over view,\n\n99\n00:05:08,008 --> 00:05:09,875\nif you have constrains, like if you put it in\n\n100\n00:05:09,877 --> 00:05:12,944\nthe calculator where we tied the stack view to the edges?\n\n101\n00:05:12,946 --> 00:05:15,714\nWhen those edges change, of course, the stack view gets\n\n102\n00:05:15,716 --> 00:05:18,550\npulled around and stretched. And, the stack view knows how\n\n103\n00:05:18,552 --> 00:05:20,786\nto resize and distribute the things inside of it.\n\n104\n00:05:20,788 --> 00:05:23,088\nThat's part of what the stack view does. That's pretty much\n\n105\n00:05:23,090 --> 00:05:26,258\nall it does actually. So that's why rotating,\n\n106\n00:05:26,260 --> 00:05:29,194\nchanging the bounds of this top view cause a ripple effect\n\n107\n00:05:29,196 --> 00:05:33,765\nwhere everything re-positions inside, okay? Now,\n\n108\n00:05:33,767 --> 00:05:37,002\nlet's talk a little bit about initializing a UI View,\n\n109\n00:05:37,004 --> 00:05:41,306\nokay? As always we want to try to avoid doing an initializer\n\n110\n00:05:41,308 --> 00:05:44,009\nif we can just get away with just saying equals whatever,\n\n111\n00:05:44,011 --> 00:05:46,778\nbut if you have to have an initializer because you just\n\n112\n00:05:46,780 --> 00:05:50,649\nfeel like you just can't initialize a VAR somehow\n\n113\n00:05:50,651 --> 00:05:53,719\nelse. Then you have to be careful with UIView because it\n\n114\n00:05:53,721 --> 00:05:56,922\nactually has two important initializers, okay?\n\n115\n00:05:56,924 --> 00:05:59,391\nOne of them is required, that's the second one,\n\n116\n00:05:59,393 --> 00:06:03,528\ninit with coder. That init is the init that's used to create\n\n117\n00:06:03,530 --> 00:06:07,699\nthe UIView when it's coming out of a storyboard, okay?\n\n118\n00:06:07,701 --> 00:06:09,701\nSo, if you built this view by dragging it out into\n\n119\n00:06:09,703 --> 00:06:13,372\nyour storyboard, when the storyboard gets reconstituted\n\n120\n00:06:13,374 --> 00:06:16,108\nat run time, then this is the init that's gonna get\n\n121\n00:06:16,110 --> 00:06:18,844\ncontrolled, init with coder. The init with frame,\n\n122\n00:06:18,846 --> 00:06:20,746\nthat's the init that you're going to call if you create\n\n123\n00:06:20,748 --> 00:06:24,616\na view in code, okay? And, that frame that you're doing,\n\n124\n00:06:24,618 --> 00:06:28,687\nspecifying is the frame of this view in its super view,\n\n125\n00:06:28,689 --> 00:06:30,455\nin other words where it's going to be, where\n\n126\n00:06:30,457 --> 00:06:35,093\nthis view is going to be. And, it is legal to, to just do\n\n127\n00:06:35,095 --> 00:06:39,731\ninit with no arguments. That's gonna essentially be ZeroRect.\n\n128\n00:06:39,733 --> 00:06:40,799\nYou're just gonna put it, like,\n\n129\n00:06:40,801 --> 00:06:43,468\nup here in the left-hand corner really, really small.\n\n130\n00:06:43,470 --> 00:06:47,139\nYou can set a frame later to move it. Anyway, since you\n\n131\n00:06:47,141 --> 00:06:49,374\nhave two of these things, and one of them is required,\n\n132\n00:06:49,376 --> 00:06:52,644\nthe second one, you're gonna end up implementing both,\n\n133\n00:06:52,646 --> 00:06:55,547\nokay? Because you're gonna want your views to be able to\n\n134\n00:06:55,549 --> 00:06:58,517\nwork from storyboards or you want people to be able to,\n\n135\n00:06:58,519 --> 00:07:01,386\nyou know, instantiate them from code, okay? So,\n\n136\n00:07:01,388 --> 00:07:04,356\nI recommend putting, all your initialization\n\n137\n00:07:04,358 --> 00:07:07,359\ncode in something like a set up function here. And\n\n138\n00:07:07,361 --> 00:07:09,728\nthen, override both of these two and\n\n139\n00:07:09,730 --> 00:07:10,695\ncall set up from both of them.\n\n140\n00:07:10,697 --> 00:07:12,931\nThat way they'll both be doing exactly the same set up,\n\n141\n00:07:12,933 --> 00:07:16,234\nright? Makes sense, kinda obvious. But, I just wanna\n\n142\n00:07:16,236 --> 00:07:18,336\nmake sure you know you gotta do both of these.\n\n143\n00:07:18,338 --> 00:07:22,407\n[COUGH] All right, another initialization mechanism that\n\n144\n00:07:22,409 --> 00:07:24,876\nyou can do for UI view, but only works for\n\n145\n00:07:24,878 --> 00:07:26,378\nviews coming out of storyboards,\n\n146\n00:07:26,380 --> 00:07:29,014\nis to put your code in this method awakeFromNib().\n\n147\n00:07:29,016 --> 00:07:32,217\nOkay, awakeFromNib() is actually called on any object\n\n148\n00:07:32,219 --> 00:07:35,420\nthat comes out of a storyboard, okay? But,\n\n149\n00:07:35,422 --> 00:07:40,692\nnot called at all in you call an object in code. And, so,\n\n150\n00:07:40,694 --> 00:07:43,562\nyou can, you know, put same kind of set up stuff that you\n\n151\n00:07:43,564 --> 00:07:46,064\nwould put in the other one as long as you're fine with your\n\n152\n00:07:46,066 --> 00:07:49,301\nview only working when it's coming from a storyboard,\n\n153\n00:07:49,303 --> 00:07:52,804\nokay? All right. So, now let's talk about the drawing.\n\n154\n00:07:52,806 --> 00:07:55,006\nOkay, I've got this UI view and I wanna draw.\n\n155\n00:07:55,008 --> 00:07:57,843\nWell, before I can show you how to draw, you know,\n\n156\n00:07:57,845 --> 00:08:01,546\ndraw something inside of these Your custom view, and I need\n\n157\n00:08:01,548 --> 00:08:05,083\nto talk about some types, some data types, okay, the first\n\n158\n00:08:05,085 --> 00:08:09,120\none here is CG float. So, we don't use doubles or float,\n\n159\n00:08:09,122 --> 00:08:12,257\nI haven't really talked about the float struct in Swift, but\n\n160\n00:08:12,259 --> 00:08:13,391\nit's just like double. It's just,\n\n161\n00:08:13,393 --> 00:08:16,761\nfloat is single precision, and double is double precisions,\n\n162\n00:08:16,763 --> 00:08:18,230\nthat's why it's called a double.\n\n163\n00:08:18,232 --> 00:08:20,532\nBut we don't use floats or doubles when we're drawing,\n\n164\n00:08:20,534 --> 00:08:23,835\nwe use this special struct called CGFloat,\n\n165\n00:08:23,837 --> 00:08:27,072\nokay? And that means that sometimes, you're going to be\n\n166\n00:08:27,074 --> 00:08:29,908\ndoing calculations in doubles and then you're gonna want to\n\n167\n00:08:29,910 --> 00:08:32,777\ndraw, with the result you're gonna have to convert it\n\n168\n00:08:32,779 --> 00:08:36,948\nto a CGFloat. By doing CGFloat called as initializer,\n\n169\n00:08:36,950 --> 00:08:39,618\nthere's an initializer for CGFloat that takes a double\n\n170\n00:08:39,620 --> 00:08:42,754\nluckily and the other takes a float, okay?\n\n171\n00:08:42,756 --> 00:08:45,790\nSo always using CGFloats and you'll run into some trouble\n\n172\n00:08:45,792 --> 00:08:49,461\nhere and there, because you're trying to pass doubles into\n\n173\n00:08:49,463 --> 00:08:54,266\nAPI that takes CGFloats, cuz it's drawing API, okay?\n\n174\n00:08:54,268 --> 00:08:55,901\nThere's a couple of other obvious structs.\n\n175\n00:08:55,903 --> 00:08:59,471\nThere's CGPoint that just has two bars in it, one is the x,\n\n176\n00:08:59,473 --> 00:09:03,241\nand one is the y, tight? That represents a point and then\n\n177\n00:09:03,243 --> 00:09:06,611\na CGSize, same thing, a struct with two things, a width and\n\n178\n00:09:06,613 --> 00:09:11,182\na height. Okay, those are easy. Then there's CGRect.\n\n179\n00:09:11,184 --> 00:09:15,620\nCGRect gets it's own slide because even though it's\n\n180\n00:09:15,622 --> 00:09:18,323\nobvious, it has an origin which is a CGPoint and\n\n181\n00:09:18,325 --> 00:09:20,525\na size which is a size, right, it's a rectangle,\n\n182\n00:09:20,527 --> 00:09:24,262\nhas an origin and a size. It also has a lot of methods on\n\n183\n00:09:24,264 --> 00:09:27,566\nit, okay? Cool methods you can use or vars and\n\n184\n00:09:27,568 --> 00:09:31,102\nmethods like finding the minimum x value\n\n185\n00:09:31,104 --> 00:09:35,974\nof this rectangle or the mid y point of this thing or\n\n186\n00:09:35,976 --> 00:09:38,510\neven intersect this with another rectangle and\n\n187\n00:09:38,512 --> 00:09:42,013\ngive me the intersecting part like this slashed area here,\n\n188\n00:09:42,015 --> 00:09:46,151\nokay? Or this one intersects which says does this rect\n\n189\n00:09:46,153 --> 00:09:49,788\nintersect this other rect. You can imagine there are a couple\n\n190\n00:09:49,790 --> 00:09:52,123\nof dozen of these kinds of utility methods.\n\n191\n00:09:52,125 --> 00:09:53,491\nSo you want to definitely get to know them so\n\n192\n00:09:53,493 --> 00:09:56,561\nyou don't end up writing these methods yourself when you want\n\n193\n00:09:56,563 --> 00:10:00,365\nto intersect two rects or whatever, okay? So those\n\n194\n00:10:00,367 --> 00:10:03,635\nare the main types that we are going to use when we draw. So\n\n195\n00:10:03,637 --> 00:10:07,172\nyou're gonna be familiar with those types. All right, let's\n\n196\n00:10:07,174 --> 00:10:09,708\ntalk about the coordinate system we're gonna draw in in\n\n197\n00:10:09,710 --> 00:10:15,413\nour view, okay? The origin is in the upper left, upper left,\n\n198\n00:10:15,415 --> 00:10:18,583\nokay. It's not lower left like Cartesian coordinates or\n\n199\n00:10:18,585 --> 00:10:19,250\nlike the Mac okay,\n\n200\n00:10:19,252 --> 00:10:23,822\nwhen you draw on the Mac, if you're building a Mac app,\n\n201\n00:10:23,824 --> 00:10:23,955\nit's in the upper left.\n\n202\n00:10:23,957 --> 00:10:26,424\nThat means increasing y means you're moving down the screen,\n\n203\n00:10:26,426 --> 00:10:30,228\nokay. So if you look at this point I created up here, 535,\n\n204\n00:10:30,230 --> 00:10:35,100\nnotice it's 500 over in x, but only 35 down in y.\n\n205\n00:10:35,102 --> 00:10:37,636\nThat's why it's way over on that side there,\n\n206\n00:10:37,638 --> 00:10:41,706\nokay. The points that we are talking about here in drawing\n\n207\n00:10:41,708 --> 00:10:43,642\nwhen I mention all of this, or\n\n208\n00:10:43,644 --> 00:10:47,312\nthe unit if you will are called points, okay. Now\n\n209\n00:10:47,314 --> 00:10:52,417\na point is not a pixel. Some iOS devices are extremely high\n\n210\n00:10:52,419 --> 00:10:56,354\nresolution like the IPhone Plus, the IPhone 6 Plus, very,\n\n211\n00:10:56,356 --> 00:11:00,692\nvery high resolution. It has three pixels per point, okay.\n\n212\n00:11:00,694 --> 00:11:02,727\nSome of the other devices have two pixels per point,\n\n213\n00:11:02,729 --> 00:11:05,864\nsome have one. Now yo're always drawing in points.\n\n214\n00:11:05,866 --> 00:11:08,266\nUsually, you do't care too much about the pixels.\n\n215\n00:11:08,268 --> 00:11:10,402\nIf you have a lot of pixels, it just means the lines\n\n216\n00:11:10,404 --> 00:11:12,570\nthat you draw are gonna look really smooth or\n\n217\n00:11:12,572 --> 00:11:14,973\nthe images that you have are gonna be really detailed.\n\n218\n00:11:14,975 --> 00:11:17,175\nYou are gonna be able to use a lot of image data\n\n219\n00:11:17,177 --> 00:11:20,245\nto draw them, okay? But if you do care, and\n\n220\n00:11:20,247 --> 00:11:23,682\nactually in assignment three, you are gonna care, so\n\n221\n00:11:23,684 --> 00:11:27,385\npay attention. If you do care, you can find out by asking\n\n222\n00:11:27,387 --> 00:11:30,021\na UIView what is your content scale factor?\n\n223\n00:11:30,023 --> 00:11:35,927\nThat's basically how many pixels per point okay.\n\n224\n00:11:35,929 --> 00:11:38,830\nThe boundaries where you draw in, so this is super important\n\n225\n00:11:38,832 --> 00:11:40,732\nand this is where a lot of confusion comes in,\n\n226\n00:11:40,734 --> 00:11:42,701\nthat's why I spend a lot of time in this even though it's\n\n227\n00:11:42,703 --> 00:11:46,604\nvery simple but people just get these things messed up.\n\n228\n00:11:46,606 --> 00:11:49,808\nLet's talk about the rectangle in which you draw, okay,\n\n229\n00:11:49,810 --> 00:11:51,843\ncuz you're gonna draw inside a rectangle. When you\n\n230\n00:11:51,845 --> 00:11:55,547\nare drawing, you're using this var in your UI view.\n\n231\n00:11:55,549 --> 00:11:58,883\nIt's called bounds. It's a CGRect. That is the rectangle\n\n232\n00:11:58,885 --> 00:12:01,920\nin which you're drawing in your own coordinate system, in\n\n233\n00:12:01,922 --> 00:12:04,956\nthe coordinate system you're drawing in, okay. So any time\n\n234\n00:12:04,958 --> 00:12:10,028\nyou're writing drawing code, you're using this, okay?\n\n235\n00:12:10,030 --> 00:12:14,332\nThere's another thing called frame, which is also CGRect,\n\n236\n00:12:14,334 --> 00:12:18,103\nwhich people confuse between these two. But frame is\n\n237\n00:12:18,105 --> 00:12:21,072\ncompletely different. It has a completely different purpose,\n\n238\n00:12:21,074 --> 00:12:23,975\nand it's in a completely different coordinate system.\n\n239\n00:12:23,977 --> 00:12:27,212\nOkay, so if try to use frame instead of bounds,\n\n240\n00:12:27,214 --> 00:12:28,947\nit might work in certain circumstances but\n\n241\n00:12:28,949 --> 00:12:32,183\nthen be messed up in others. So what's frame about?\n\n242\n00:12:32,185 --> 00:12:36,054\nFrame is about where your view is in it's super view?\n\n243\n00:12:36,056 --> 00:12:39,791\nFrame is a rectangle, a CG rect that completely encloses\n\n244\n00:12:39,793 --> 00:12:44,929\nyou in your super views coordinate system. Okay, so\n\n245\n00:12:44,931 --> 00:12:47,632\nwhen I wanna put some view somewhere,\n\n246\n00:12:47,634 --> 00:12:50,769\nI have to specify where in it's SuperView it goes.\n\n247\n00:12:50,771 --> 00:12:53,238\nI do that by specifying it's frame. And of course,\n\n248\n00:12:53,240 --> 00:12:55,607\nsince I'm talking about putting it into SuperView,\n\n249\n00:12:55,609 --> 00:12:57,375\nthat's in the SuperView's coordinate system,\n\n250\n00:12:57,377 --> 00:13:00,678\nnot in the drawing, coordinate system on the inside there,\n\n251\n00:13:00,680 --> 00:13:05,049\nokay? Similarly, centre, a lot of people think, great,\n\n252\n00:13:05,051 --> 00:13:08,486\nthat's the center of my view. But it's not, okay?\n\n253\n00:13:08,488 --> 00:13:11,489\nThat's the centre of your view in your SuperViews coordinate\n\n254\n00:13:11,491 --> 00:13:13,992\nsystem. So that's positioning you, okay?\n\n255\n00:13:13,994 --> 00:13:15,960\nFrame and center are positioning you.\n\n256\n00:13:15,962 --> 00:13:17,562\nThey have nothing to do with your drawing.\n\n257\n00:13:17,564 --> 00:13:20,865\nWhen you're drawing, you're using your bounds, okay? So\n\n258\n00:13:20,867 --> 00:13:23,735\nI do not want to see you using frame inside your drawing\n\n259\n00:13:23,737 --> 00:13:28,072\ncode, or centre. Got it? And I'll emphasize this again in\n\n260\n00:13:28,074 --> 00:13:33,378\nthe demo. All right, so one thing about frame and\n\n261\n00:13:33,380 --> 00:13:36,414\ncentre, you might think that the size and\n\n262\n00:13:36,416 --> 00:13:38,149\nwidth are going to be the same for the frame and\n\n263\n00:13:38,151 --> 00:13:42,420\ncentre, but they're not because views can be rotated.\n\n264\n00:13:42,422 --> 00:13:44,856\nIf you had a rotated view like view B, okay,\n\n265\n00:13:44,858 --> 00:13:50,128\nit's bounds is 200 wide by 250 high you see that, but\n\n266\n00:13:50,130 --> 00:13:54,432\nlook at his frame 320 by 320 why? Because this is\n\n267\n00:13:54,434 --> 00:13:58,002\nthe smallest rectangle in the super views coordinate system\n\n268\n00:13:58,004 --> 00:14:03,241\nthat will completely contain this rotated view, okay?\n\n269\n00:14:03,243 --> 00:14:06,544\nSo the width and height are not the same, okay?\n\n270\n00:14:06,546 --> 00:14:10,782\nThis is the frame 320 by 320, this is the bounds. When\n\n271\n00:14:10,784 --> 00:14:14,152\nyou're drawing in B, you don't even know you're rotated, so\n\n272\n00:14:14,154 --> 00:14:17,055\nyou want to make sure that you're using\n\n273\n00:14:17,591 --> 00:14:21,726\nthis coordinate system right here, bounds, okay?\n\n274\n00:14:21,728 --> 00:14:26,497\nAll right, creating views, okay, most of the time you're\n\n275\n00:14:26,499 --> 00:14:29,167\ncreating views in your story board by dragging them out.\n\n276\n00:14:29,169 --> 00:14:31,736\nNow if you have a custom view that's drawing something\n\n277\n00:14:31,738 --> 00:14:35,406\ncustom like today we're gonna do a thing where we draw\n\n278\n00:14:35,408 --> 00:14:40,278\na face view, it's gonna be a view Okay.\n\n279\n00:14:40,280 --> 00:14:43,448\nLooks like this, got a couple eyes. Smiley face, okay?\n\n280\n00:14:43,450 --> 00:14:46,985\nI'm drawing, it's got a skull there. When I'm drawing this,\n\n281\n00:14:46,987 --> 00:14:51,155\nthere's no face view in the object palate, right?\n\n282\n00:14:51,157 --> 00:14:52,657\nI can't drag that out into my story board.\n\n283\n00:14:52,659 --> 00:14:55,627\nSo, how do I get my face view to appear somewhere in\n\n284\n00:14:55,629 --> 00:14:56,794\nmy story board. Well, the answer is,\n\n285\n00:14:56,796 --> 00:14:59,697\nI'm going to drag out a generic view, okay,\n\n286\n00:14:59,699 --> 00:15:03,401\na generic UI view, unsubclassed UI view, and then\n\n287\n00:15:03,403 --> 00:15:07,038\nI'm going to change it, edit it in this identity inspector,\n\n288\n00:15:07,040 --> 00:15:09,641\nwhich I'll show you in the demo to change the class of\n\n289\n00:15:09,643 --> 00:15:12,110\nit, so it's a subclass of UI view. And it's in that\n\n290\n00:15:12,112 --> 00:15:14,545\nsubclass of UI view that I'm gonna put all my drawing code,\n\n291\n00:15:14,547 --> 00:15:19,751\nall my face drawing code, okay? Now on rare occasion,\n\n292\n00:15:19,753 --> 00:15:22,854\nyou will create a view in code, okay. You do that just\n\n293\n00:15:22,856 --> 00:15:26,257\nby doing, calling UIView's little constructor here.\n\n294\n00:15:26,259 --> 00:15:29,694\nYou're gonna use the one with frame, not the one with coder,\n\n295\n00:15:29,696 --> 00:15:32,897\nokay. You can also do UIView with no arguments,\n\n296\n00:15:32,899 --> 00:15:35,033\nthat means the tiny little UIView.\n\n297\n00:15:35,035 --> 00:15:36,734\nYou'll have to set it's frame otherwise.\n\n298\n00:15:36,736 --> 00:15:39,671\nSo here's what it looks like to create a view in code.\n\n299\n00:15:39,673 --> 00:15:41,606\nHere I just created a rectangle which is 20/20, 150.\n\n300\n00:15:41,608 --> 00:15:45,877\nSo that's like 20, 20, 150. So this is this rectangle\n\n301\n00:15:47,113 --> 00:15:50,848\nright about there and the, so\n\n302\n00:15:50,850 --> 00:15:54,218\nthen I'm creating a view. This view happens to be a UI label.\n\n303\n00:15:54,220 --> 00:15:56,087\nUI label is just a sub class UI view.\n\n304\n00:15:56,089 --> 00:15:58,756\nSo it' s UI button, so it's UI stack view. All of these\n\n305\n00:15:58,758 --> 00:16:01,492\nthings are just sub classes of UI view. So I'm creating a sub\n\n306\n00:16:01,494 --> 00:16:03,928\ncode view using that frame thing using that frame thing,\n\n307\n00:16:03,930 --> 00:16:06,431\nokay? I'm even setting the elabels text, all right?\n\n308\n00:16:06,433 --> 00:16:10,401\nThen I'm going to say view, let's say this code is\n\n309\n00:16:10,403 --> 00:16:15,473\nin the view controller, say view.addsubvie.\n\n310\n00:16:15,475 --> 00:16:18,109\nThen all the sudden it's gonna appear here,\n\n311\n00:16:18,111 --> 00:16:22,780\nokay? Here's that 20/20. And it's 100 by 50,\n\n312\n00:16:22,782 --> 00:16:27,986\nokay? That's it. Very simple to add views with code,\n\n313\n00:16:27,988 --> 00:16:32,690\nokay? Add subview. All right, custom view. So why do I want\n\n314\n00:16:32,692 --> 00:16:34,759\nto create my own custom view subclass?\n\n315\n00:16:34,761 --> 00:16:37,762\nObviously you want to have a smiley face, okay?\n\n316\n00:16:37,764 --> 00:16:40,698\nSo you need to create your own custom one to do that. And\n\n317\n00:16:40,700 --> 00:16:43,568\nyou might have some pinches or swipes or\n\n318\n00:16:43,570 --> 00:16:46,304\nsomething, which we'll do next week. For your face,\n\n319\n00:16:46,306 --> 00:16:49,040\nyou need a custom view to do those things, okay? So let's\n\n320\n00:16:49,042 --> 00:16:52,944\ntalk about the drawing end of that today. How do I draw?\n\n321\n00:16:52,946 --> 00:16:56,514\nIt's really easy. You're just gonna subclass UI view and\n\n322\n00:16:56,516 --> 00:16:59,150\nyou're gonna override this one method,\n\n323\n00:16:59,152 --> 00:17:02,720\ndrawRect, okay? DrawRect takes one argument,\n\n324\n00:17:02,722 --> 00:17:06,858\nwhich is an optimization only, which is what part of\n\n325\n00:17:06,860 --> 00:17:08,559\nthe view the system wants you to draw.\n\n326\n00:17:08,561 --> 00:17:10,261\nIt might want you to draw the whole thing.\n\n327\n00:17:10,263 --> 00:17:13,631\nBut maybe it just wants you to draw the eyes, okay?\n\n328\n00:17:13,633 --> 00:17:14,399\nNow you can ignore that and\n\n329\n00:17:14,401 --> 00:17:16,868\ndraw the whole thing anyway, and it will work. Or\n\n330\n00:17:16,870 --> 00:17:18,970\nif you can efficiently just draw the eyes,\n\n331\n00:17:18,972 --> 00:17:21,739\nthen you might decide to just draw the eyes, okay. But\n\n332\n00:17:21,741 --> 00:17:24,008\nthis argument right here is purely an optimization.\n\n333\n00:17:24,010 --> 00:17:29,580\nIt can be ignored if you want. Okay, never call this method.\n\n334\n00:17:29,582 --> 00:17:32,717\nIf you ever call this method in the code you submit for\n\n335\n00:17:32,719 --> 00:17:35,286\nhomework, I'll be personally going over and\n\n336\n00:17:35,288 --> 00:17:36,754\nslapping you on the wrist, okay?\n\n337\n00:17:36,756 --> 00:17:40,024\nBecause this, this is never, ever, under any circumstances,\n\n338\n00:17:40,026 --> 00:17:41,859\nno exceptions are you calling this thing.\n\n339\n00:17:41,861 --> 00:17:46,030\nThe system calls drawRect. You never call it. So,\n\n340\n00:17:46,032 --> 00:17:49,767\nhow do you get your face to draw? If you want it drawn.\n\n341\n00:17:49,769 --> 00:17:52,837\nLet's say the eye is closed. And you want to draw the face\n\n342\n00:17:52,839 --> 00:17:55,840\nso the eyes are closed. Well you call this method here set\n\n343\n00:17:55,842 --> 00:17:59,010\nneeds display on your view. And that tells the system,\n\n344\n00:17:59,012 --> 00:18:01,412\nhey this view needs to be redrawn. And\n\n345\n00:18:01,414 --> 00:18:04,782\nthe view at some point in the future when it's appropriate,\n\n346\n00:18:04,784 --> 00:18:08,986\nwill call your drawRect, okay? Now why is it done this way?\n\n347\n00:18:08,988 --> 00:18:10,688\nWell if you think about it. Your view lives in\n\n348\n00:18:10,690 --> 00:18:12,690\nan environment where there might be subviews and\n\n349\n00:18:12,692 --> 00:18:14,792\nyou're in SuperView and they're overlapping.\n\n350\n00:18:14,794 --> 00:18:16,461\nThere's all kinds of things happening. And\n\n351\n00:18:16,463 --> 00:18:19,831\nyou can't just run along and redraw one of those things\n\n352\n00:18:19,833 --> 00:18:21,332\nokay they might be transparent,\n\n353\n00:18:21,334 --> 00:18:25,169\nseeing through to each other, the system has to manage that\n\n354\n00:18:25,171 --> 00:18:27,772\nokay and there's also performance reasons to do it.\n\n355\n00:18:27,774 --> 00:18:31,576\nYou might change, close the eyes, start frowning, etc,\n\n356\n00:18:31,578 --> 00:18:35,279\nthe nose starts running I don't know and all those\n\n357\n00:18:35,281 --> 00:18:35,880\nthings are happening all at once,\n\n358\n00:18:35,882 --> 00:18:38,683\nwe don't wanna redraw it every single time. The, one of them\n\n359\n00:18:38,685 --> 00:18:40,852\nchanges. You wanna wait until all of them have changed and\n\n360\n00:18:40,854 --> 00:18:44,922\nthen draw once your new face, okay? So the system is the one\n\n361\n00:18:44,924 --> 00:18:48,159\nthat decides. Now this is setNeedsDisplay() in Rect.\n\n362\n00:18:48,161 --> 00:18:50,495\nJust lets you set this little rectangle right here.\n\n363\n00:18:50,497 --> 00:18:52,497\nSo this is an optimized version,\n\n364\n00:18:52,499 --> 00:18:54,532\nan optimized version of setNeedsDisplay() in Rect.\n\n365\n00:18:54,534 --> 00:18:56,868\nMaybe just call it with the i's. Okay,\n\n366\n00:18:56,870 --> 00:18:58,336\nif you know that only the eyes have changed.\n\n367\n00:18:58,338 --> 00:19:01,939\nBut this is how you get a view to redraw, okay?\n\n368\n00:19:01,941 --> 00:19:04,976\nAll right, so how do I implement this drawRect thing,\n\n369\n00:19:04,978 --> 00:19:07,678\nokay? I got this drawRect thing, how do I implement it?\n\n370\n00:19:07,680 --> 00:19:10,848\nThere's two ways, really. There is a, kind of a C-like,\n\n371\n00:19:10,850 --> 00:19:14,485\na non-object oriented. In Swift, it's just functions,\n\n372\n00:19:14,487 --> 00:19:17,855\nglobal functions way of doing it called Core Graphics.\n\n373\n00:19:17,857 --> 00:19:21,692\nOkay, Core Graphics and then there's object oriented way\n\n374\n00:19:21,694 --> 00:19:24,762\nusing a class called UIBezierPath, okay? They're\n\n375\n00:19:24,764 --> 00:19:28,466\nboth using Core Graphics underneath the covers so I'm\n\n376\n00:19:28,468 --> 00:19:31,936\ngonna talk a little bit about the Core Graphics Concepts and\n\n377\n00:19:31,938 --> 00:19:35,239\nthey're going to apply to UIBezierPath as you can see.\n\n378\n00:19:35,241 --> 00:19:37,074\nSo what are the concepts of Core Graphics?\n\n379\n00:19:37,076 --> 00:19:39,644\nVery simple. First, you're gonna get a context\n\n380\n00:19:39,646 --> 00:19:42,914\nto draw in. So that context might be drawing on screen.\n\n381\n00:19:42,916 --> 00:19:44,849\nThat's the context you'd want if you're in drawRect.\n\n382\n00:19:44,851 --> 00:19:47,952\nBut you could have other contexts like drawing for\n\n383\n00:19:47,954 --> 00:19:51,522\na printer, drawing into an off screen buffer, okay?\n\n384\n00:19:51,524 --> 00:19:52,523\nThose are all contexts of draw so\n\n385\n00:19:52,525 --> 00:19:56,394\nthat's the first thing you do. In if you're using this\n\n386\n00:19:56,396 --> 00:19:58,963\nkind of like C-like function one you're gonna use this\n\n387\n00:19:58,965 --> 00:20:02,300\nUI graphics to get current context inside of drawRect\n\n388\n00:20:02,302 --> 00:20:03,834\nto get the context that's appropriate for\n\n389\n00:20:03,836 --> 00:20:08,573\ndrawRect, okay? So then number two is you create paths.\n\n390\n00:20:08,575 --> 00:20:12,076\nSo these paths are made of arcs and lines, rectangles,\n\n391\n00:20:12,078 --> 00:20:16,447\ncircles, whatever. You're pu- putting together these Paths,\n\n392\n00:20:16,449 --> 00:20:17,748\nthis path that you're building, okay?\n\n393\n00:20:17,750 --> 00:20:20,051\nAnd that's the thing that's gonna be drawn, okay?\n\n394\n00:20:20,053 --> 00:20:23,888\nSo you build this path. Then you set attributes that you're\n\n395\n00:20:23,890 --> 00:20:28,159\ngonna draw this path with like, the color of the lines.\n\n396\n00:20:28,161 --> 00:20:30,528\nAny fonts if you're doing texts.\n\n397\n00:20:30,530 --> 00:20:32,797\nTextures if you're filling things with textures.\n\n398\n00:20:32,799 --> 00:20:34,765\nLinewidths, linecaps, those kinds of things.\n\n399\n00:20:34,767 --> 00:20:38,402\nYou set all those things up and then you stroke the path\n\n400\n00:20:38,404 --> 00:20:41,372\nwhich means draw a line everywhere the path is or\n\n401\n00:20:41,374 --> 00:20:45,643\nyou fill the path which means fill in the space\n\n402\n00:20:45,645 --> 00:20:49,547\ncontained by the path with some color or texture, okay?\n\n403\n00:20:49,549 --> 00:20:52,450\nThat's it, this is the basic concept of how you draw.\n\n404\n00:20:52,452 --> 00:20:58,122\nThe UIBezierPath does the same okay it's\n\n405\n00:20:58,124 --> 00:21:04,395\njust the UIBezierPath It has methods to draw.\n\n406\n00:21:04,397 --> 00:21:08,799\nLine two, arch two, those kind of things instead of having\n\n407\n00:21:08,801 --> 00:21:11,636\nthese great functions. You know these global functions.\n\n408\n00:21:11,638 --> 00:21:15,439\nYou use UI color to set the stroke and fill colors.\n\n409\n00:21:15,441 --> 00:21:18,709\nThis is a class we'll talk about and then when it comes\n\n410\n00:21:18,711 --> 00:21:22,046\nto stroking in fill, those are methods on UIBezierPath.\n\n411\n00:21:22,048 --> 00:21:23,748\nSo UIBezierPath just encapsulates\n\n412\n00:21:23,750 --> 00:21:25,783\nall that core graphics staff in to a nice class.\n\n413\n00:21:25,785 --> 00:21:28,219\nIt's nice because you can find everything you want.\n\n414\n00:21:28,221 --> 00:21:30,821\nBasically everything you want to do to draw except for\n\n415\n00:21:30,823 --> 00:21:34,225\ncolors, fonts, texts and images. Those four things\n\n416\n00:21:34,227 --> 00:21:38,329\nare not in UIBezierPath but all other drawing is in there.\n\n417\n00:21:38,331 --> 00:21:41,832\nOkay, so how do you do this? Lets, I'm only gonna talk\n\n418\n00:21:41,834 --> 00:21:44,368\nabout the UIBezierPathway cuz it's object oriented,\n\n419\n00:21:44,370 --> 00:21:46,971\nwe love object oriented programming here. So\n\n420\n00:21:46,973 --> 00:21:49,974\nhere's how you would, create a path and draw some.\n\n421\n00:21:49,976 --> 00:21:52,343\nSo we're gonna do a triangle. Okay, so first\n\n422\n00:21:52,345 --> 00:21:56,080\nI create a UIBezierPath, okay theyre are one initializers\n\n423\n00:21:56,082 --> 00:21:58,049\nwith argueness we're gonna use the one we just created,\n\n424\n00:21:58,051 --> 00:22:00,885\na blank, blank path. Then, we're gonna move around.\n\n425\n00:22:00,887 --> 00:22:04,488\nSo, I'm gonna move to 8050, which is like right here.\n\n426\n00:22:04,490 --> 00:22:08,693\nLet's say it's 160 wide and 250 high, or something.\n\n427\n00:22:08,695 --> 00:22:12,630\nSo, 8060s right about there. Then, I'm going to add a line\n\n428\n00:22:12,632 --> 00:22:15,566\nto this point over here, 140, 150. Remember,\n\n429\n00:22:15,568 --> 00:22:19,403\norigin is up here, positive numbers are going down, okay?\n\n430\n00:22:19,405 --> 00:22:22,506\nGonna add another line right here. Okay, to 10150, and\n\n431\n00:22:22,508 --> 00:22:26,877\nthen I'm going to close the path, there's a method called\n\n432\n00:22:26,879 --> 00:22:31,082\nclose path, and that just goes back to the starting point,\n\n433\n00:22:31,084 --> 00:22:31,749\nso that closes it, and boom,\n\n434\n00:22:31,751 --> 00:22:36,087\nI've created a triangle. Now I've misled you a little here,\n\n435\n00:22:36,089 --> 00:22:40,124\nbecause no drawing on screen would actually happen if you\n\n436\n00:22:40,126 --> 00:22:41,359\nput this in your draw rect. Okay,\n\n437\n00:22:41,361 --> 00:22:43,127\nif you put these lines and this code in your draw rect,\n\n438\n00:22:43,129 --> 00:22:46,063\nnothing would happen. Because all you've done here is\n\n439\n00:22:46,065 --> 00:22:49,367\ncreate that path. You have not drawn it on screen.\n\n440\n00:22:49,369 --> 00:22:52,903\nYou haven't stroked it or filled it. So how do we do\n\n441\n00:22:52,905 --> 00:22:56,073\nthat? How do we get it onto screen? Well first of all,\n\n442\n00:22:56,075 --> 00:22:57,942\nwe need to set the colors that we're gonna use to\n\n443\n00:22:57,944 --> 00:23:03,047\nstroke and fill. So I want my triangle to be red lines with\n\n444\n00:23:03,049 --> 00:23:06,283\ngreen fill in the middle. So I'm setting green color\n\n445\n00:23:06,285 --> 00:23:08,919\nas my fill color and red color as my stroke color.\n\n446\n00:23:08,921 --> 00:23:12,857\nNotice that I send these as to a UIColor. I don't send them\n\n447\n00:23:12,859 --> 00:23:15,593\nto the BezierPath. So it's kinda odd that you\n\n448\n00:23:15,595 --> 00:23:18,462\ndo your setting of the colors by sending it to UIColor.\n\n449\n00:23:18,464 --> 00:23:21,899\nSo we'll talk about UIColor green color, what that means\n\n450\n00:23:21,901 --> 00:23:24,902\nin a couple slides. So I'm setting my stroke and fill and\n\n451\n00:23:24,904 --> 00:23:27,938\nthen here I'm saying the line width of my path to\n\n452\n00:23:27,940 --> 00:23:32,443\nthree points, three points wide, okay? Now I can just say\n\n453\n00:23:32,445 --> 00:23:37,615\npath.fill and I get my filled path, see? Filled with green.\n\n454\n00:23:37,617 --> 00:23:41,385\nNotice there's no line around the outside. But then if I say\n\n455\n00:23:41,387 --> 00:23:44,522\npath stroke, now you get a line around the side. And\n\n456\n00:23:44,524 --> 00:23:49,360\nyou can see it's red. And it's line width is three, got it?\n\n457\n00:23:49,362 --> 00:23:51,929\nSo you're going to have code like this in your draw erect.\n\n458\n00:23:51,931 --> 00:23:56,300\nIf you wanted your view to be a view of a triangle.\n\n459\n00:23:56,302 --> 00:24:01,405\nOkay, any questions about that? All right [COUGH].\n\n460\n00:24:01,407 --> 00:24:03,841\nNow, you can use UI Bezier Path to draw more\n\n461\n00:24:03,843 --> 00:24:07,311\ncomplicated things like rounded rects and circles and\n\n462\n00:24:07,313 --> 00:24:10,214\nthings like that, especially by using a lot of\n\n463\n00:24:10,216 --> 00:24:12,349\nthe initializers of UI Bezier Path, but\n\n464\n00:24:12,351 --> 00:24:15,853\nthere's also methods there. So you're going to have to study\n\n465\n00:24:15,855 --> 00:24:17,221\nUI Bezier Path and see what it can do,\n\n466\n00:24:17,223 --> 00:24:20,691\nokay, it can do quite a lot. Another interesting thing\n\n467\n00:24:20,693 --> 00:24:24,528\nabout UIBezierPath is you can set it as a clipping path. So,\n\n468\n00:24:24,530 --> 00:24:26,697\nlet's say you were drawing a playing card, right?\n\n469\n00:24:26,699 --> 00:24:29,533\nPlaying cards have rounded rects. They never have sharp\n\n470\n00:24:29,535 --> 00:24:31,769\ncorners, right? They have rounded rects.\n\n471\n00:24:31,771 --> 00:24:34,839\nWell, you could Could create a UIBezierPath here using this,\n\n472\n00:24:34,841 --> 00:24:38,776\ncreate a rounded rect, set it as the clipping path, and\n\n473\n00:24:38,778 --> 00:24:41,378\nthen just draw your card in the inside.\n\n474\n00:24:41,380 --> 00:24:43,681\nAnd it would never draw in those corners,\n\n475\n00:24:43,683 --> 00:24:46,684\ncuz it would be clipped to the rounded rect. Okay?\n\n476\n00:24:46,686 --> 00:24:50,421\nSo, addClip is kind of a cool Bezier path method.\n\n477\n00:24:50,423 --> 00:24:52,490\nThe Bezier path can also do hit detection. So\n\n478\n00:24:52,492 --> 00:24:56,227\nyou can see whether a point is like inside the triangle,\n\n479\n00:24:56,229 --> 00:24:58,863\nright? If you have that Bezier path that's the triangle, you\n\n480\n00:24:58,865 --> 00:25:01,131\ncan do hit detection on it, whether it contains a point.\n\n481\n00:25:01,133 --> 00:25:03,667\nSo that's kinda cool, too, right, doing some game or\n\n482\n00:25:03,669 --> 00:25:06,504\nsomething and people have to touch on a certain kind of\n\n483\n00:25:06,506 --> 00:25:08,806\nfunny shaped thing, not a rectangular thing.\n\n484\n00:25:08,808 --> 00:25:11,742\nThen it's nice to be able to do hit detection with it.\n\n485\n00:25:11,744 --> 00:25:13,477\nOkay? And there's lots and lots of other stuff,\n\n486\n00:25:13,479 --> 00:25:16,180\nyou need to check the documentation. All right,\n\n487\n00:25:16,182 --> 00:25:19,083\nUIColor. We saw that UIColor, green color thing,\n\n488\n00:25:19,085 --> 00:25:23,120\non the previous slide. This, what kind of method is this?\n\n489\n00:25:23,122 --> 00:25:25,523\nDo you guys remember from last lecture? The green color.\n\n490\n00:25:25,525 --> 00:25:28,025\nWhat kind of method? Type method or\n\n491\n00:25:28,027 --> 00:25:31,128\ninstance method? It's a type method.\n\n492\n00:25:31,130 --> 00:25:33,497\nRight because we're not sending it to a UI color,\n\n493\n00:25:33,499 --> 00:25:35,366\nwe're sending it to the type, UIColor.\n\n494\n00:25:35,368 --> 00:25:38,903\nUIColor's a class and so we're sending this method to it.\n\n495\n00:25:38,905 --> 00:25:41,739\nSo it would be defined as static or\n\n496\n00:25:41,741 --> 00:25:45,976\nclass, funk, green color inside UIColor class.\n\n497\n00:25:45,978 --> 00:25:51,015\nOkay? By the way, you can also create colors, not\n\n498\n00:25:51,017 --> 00:25:54,018\njust picking these well-known colors like green color. But\n\n499\n00:25:54,020 --> 00:25:58,155\nthere are initializers for RGB, red, green, blue. HSB,\n\n500\n00:25:58,157 --> 00:26:00,891\nthat's hue, saturation, and br-brightness. You can even\n代表色相、饱和度和亮度。你甚至可以\n\n501\n00:26:00,893 --> 00:26:05,095\nset, create a color that's a pattern. Okay? It's like some\n设定并创建一个颜色当做模板。了解？这就像\n\n502\n00:26:05,097 --> 00:26:07,097\nimage that you have. You'd make a pattern out of it.\n你有一些图片，你能通过它创建一个模板\n\n503\n00:26:07,099 --> 00:26:09,233\nAnd when it draws, it will be drawing with that pattern.\n并且当它开始画的时候，会以这个模板来画\n\n504\n00:26:09,235 --> 00:26:14,204\nIt's kind of cool. Here we see views have background colors.\n这点挺酷的。这里我们看到 view 有背景颜色\n\n505\n00:26:14,206 --> 00:26:16,574\nSo you've already seen that. We set the background colors\n你已经看到了。我们在 calculator 里\n\n506\n00:26:16,576 --> 00:26:19,677\nof our buttons in the calculator. You noticed that\n设置里按钮的背景颜色。我们在\n\n507\n00:26:19,679 --> 00:26:21,145\nwhen we did that in the attributes inspector,\n属性检查器里处理的时候你已经看到了\n\n508\n00:26:21,147 --> 00:26:23,581\nwe had to scroll down to the bottom because the attribute\n我们需要滑到底下，因为\n\n509\n00:26:23,583 --> 00:26:26,050\ninspector is object oriented and it was showing all\n属性检查器是面向对象的并且它会显示所有\n\n510\n00:26:26,052 --> 00:26:28,886\nthe inherited thing. Well we had to go down to The UIView\n继承的东西。我们需要到 UIView\n\n511\n00:26:28,888 --> 00:26:31,188\nlevel to set the background color of our buttons, okay,\n这一层去设置我们 button 的背景颜色。\n\n512\n00:26:31,190 --> 00:26:36,594\ncuz button inherits that from UIView. Okay? Interesting\n因为这是 button 从 UIView 那里继承来的。没问题？\n\n513\n00:26:36,596 --> 00:26:40,130\nthing about colors, they can have transparency.\n关于颜色有趣的是，它们有透明度。\n\n514\n00:26:40,132 --> 00:26:42,833\nOkay, meaning they kind of show through. That's called\n好的，这意味着他们能够显示背后的东西，这个属性\n\n515\n00:26:42,835 --> 00:26:45,436\nalpha. How many people have heard the term alpha when it\n叫做 alpha，有多少人在碰到绘图的时候\n\n516\n00:26:45,438 --> 00:26:48,639\ncomes to drawing? Okay, so less than half of you.\n听到过 alpha 这个术语？好吧，不到一半\n\n517\n00:26:48,641 --> 00:26:51,208\nSo alpha just means how transparent it is.\n所以 alpha 表示的就是它有多透明\n\n518\n00:26:51,210 --> 00:26:53,544\nAn alpha of zero means fully transparent.\nalpha 值为0表示完全透明\n\n519\n00:26:53,546 --> 00:26:56,380\nSo if you had bright red but it was alpha zero\n所以如果你有个亮红色，但是 alpha 为0的话\n\n520\n00:26:56,382 --> 00:26:58,582\nyou wouldn't see anything because its fully transparent.\n你什么也看不到，以为它是完全透明的\n\n521\n00:26:58,584 --> 00:27:01,352\nYou're seeing completely through it with no blocking.\n你会看到它后面所有的东西，没有任何阻碍\n\n522\n00:27:01,354 --> 00:27:04,355\nAlpha of 1 means fully opaque, meaning you would not\nAlpha 值为1表示完全不透明，意味着\n\n523\n00:27:04,357 --> 00:27:07,191\nsee a single pixel of anything behind something that was\n当一个东西完全不透明的时候，你看不到它后面的\n\n524\n00:27:07,193 --> 00:27:10,728\nfully opaque. And between 0 and 1 is various degrees\n任何东西。值在0和1之间就是不同层次\n\n525\n00:27:10,730 --> 00:27:14,465\nof being able to see through. Okay, that's called alpha. And\n的透明程度。好的，这就叫做 alpha\n\n526\n00:27:14,467 --> 00:27:16,667\nyou can create colors, like here's a yellow.\n你能够创建颜色，像这里有个黄色\n\n527\n00:27:16,669 --> 00:27:20,337\nBy sending this message colorWithAlphaComponent, okay,\n通过使用这个方法 colorWithAlphaComponent，请问\n\n528\n00:27:20,339 --> 00:27:21,639\nis this a type method or\n这是个类方法还是\n\n529\n00:27:21,641 --> 00:27:26,243\nan instance method? Raise your hand if you think it's a type\n个实例方法？认为是类方法的请\n\n530\n00:27:26,245 --> 00:27:31,048\nmethod. Raise your hand if you think it's an instance method.\n举手。认为是实例方法的请举手\n\n531\n00:27:31,050 --> 00:27:32,583\nHardly anyone raised their hand for either of them.\n看来两边都没什么人举手啊\n\n532\n00:27:32,585 --> 00:27:34,518\nThat's great. But if you were to raise your hand for\n没问题。但是如果你举手并觉得是\n\n533\n00:27:34,520 --> 00:27:36,186\ninstance method you are correct. Okay.\n实例方法的话，你对了。好的\n\n534\n00:27:36,188 --> 00:27:38,989\nThis is an instance method. That's because we use this\n这时一个实例方法。那是因为我们用这个\n\n535\n00:27:38,991 --> 00:27:42,760\ntype method yellow color to get an instance of a color and\nyellowColor() 方法去获取一个颜色的实例\n\n536\n00:27:42,762 --> 00:27:45,396\nthen we sent it this instance method\n然后我们在后面写这个实例方法\n\n537\n00:27:45,398 --> 00:27:49,199\nto get a half transparent version of yellow. So\n去获取这个黄色的半透明的版本。所以说\n\n538\n00:27:49,201 --> 00:27:51,568\nthis is half transparent yellow right here, and\n这里是一个半透明的黄色，并且\n\n539\n00:27:51,570 --> 00:27:54,872\nif we drew with it it would draw yellow in our view, but\n如果我们用它来画的话，它会在 view 中画出黄色，但是\n\n540\n00:27:54,874 --> 00:27:57,274\nwe would be able to see through, to things behind,\n我们能够看到它后面，它后面的那些东西\n\n541\n00:27:57,276 --> 00:28:01,845\nperhaps even to other views, like our super view, behind.\n或者甚至看到其他的视图，比如后面的父视图\n\n542\n00:28:02,581 --> 00:28:05,282\nIf you want to draw with transparency in your view.\n如果你想在 view 里画有透明度的图\n\n543\n00:28:05,284 --> 00:28:07,651\nIf you want to draw with colors that are transparent.\n如果你想使用有透明度的颜色\n\n544\n00:28:07,653 --> 00:28:13,424\nYou have to set in your view this var opaque to be false.\n你需要在你的 view 里面设置这个 opaque 的变量为 false\n\n545\n00:28:13,426 --> 00:28:17,061\nAs a performance optimization the system has to assume\n为了最优化显示效果，系统必须假定\n\n546\n00:28:17,063 --> 00:28:18,429\nthe view is opaque okay?\nview 是不透明的，明白？\n\n547\n00:28:18,431 --> 00:28:21,065\nThat it doesn't draw with transparency. That's because\n所以它画的时候不会带透明度。那是因为\n\n548\n00:28:21,067 --> 00:28:23,667\nyou can imagine things that are transparent overlapping,\n你们想一下当各种有透明度的东西重叠在一起的时候\n\n549\n00:28:23,669 --> 00:28:26,904\nthink about the work that the system has to do to figure out\n想象一下系统需要去处理在后面显示的\n\n550\n00:28:26,906 --> 00:28:28,906\nwhat's showing through from behind.\n那些东西的时候需要的工作量\n\n551\n00:28:28,908 --> 00:28:31,008\nOkay? That kind of compositing,\n懂得？那是件有点庞杂的事\n\n552\n00:28:31,010 --> 00:28:33,877\nit's called, takes processor power and memory.\n这叫做提高处理效率，节约内存\n\n553\n00:28:33,879 --> 00:28:37,414\nOkay? So, it's gonna assume that everything is opaque. So\n懂了吗？所以说系统会假定所有东西都是不透明的\n\n554\n00:28:37,416 --> 00:28:40,050\nit doesn't have to do that, but if you are drawing with\n虽然没有必要，但是你在画有透明度的东西\n\n555\n00:28:40,052 --> 00:28:42,953\ntransparency, that's fine, just set this opaque to false,\n的时候，好吧，把 opaque 设成 false 就是了\n\n556\n00:28:42,955 --> 00:28:46,356\nto let the system know, no I'm not opaque. I'm gonna draw\n让系统知道，现在不是不透明的，我要画\n\n557\n00:28:46,358 --> 00:28:49,293\nwith transparency. Now another thing that's cool,\n有透明度的图了。然后另外一件挺酷的事是\n\n558\n00:28:49,295 --> 00:28:52,529\nis you can make your entire view transparent,\n你能让你的整个 view 带有透明度\n\n559\n00:28:52,531 --> 00:28:56,533\nby setting the alpha property on the view itself, okay? So\n通过在 view 自身上设定 alpha 属性，明白？所以说\n\n560\n00:28:56,535 --> 00:28:59,002\nyou could draw your whole view, your triangle,\n你能画出你的整个视图，三角形\n\n561\n00:28:59,004 --> 00:29:01,038\nlet's say, set the transparency to 0.5, and\n然后，来吧，把透明度设为0.5，然后\n\n562\n00:29:01,040 --> 00:29:02,906\nyou'd have a half transparent triangle,\n你就会有一个半透明的三角形\n\n563\n00:29:02,908 --> 00:29:04,842\neven though you drew all with opaque colors,\n即使你全部画的不透明的颜色\n\n564\n00:29:04,844 --> 00:29:07,711\nyou'd still have a half transparent triangle because\n你仍然会有一个半透明的三角形，因为\n\n565\n00:29:07,713 --> 00:29:11,381\nyou set your alpha to 0.5. Okay? Using alpha is\n你把 alpha 设成了0.5。懂了？当我们\n\n566\n00:29:11,383 --> 00:29:15,686\nreally cool for doing effects like fading views out. Okay,\n需要例如把视图渐隐的效果时，用 alpha 挺不错的。好的\n\n567\n00:29:15,688 --> 00:29:18,422\nsometimes you want a view just to fade out over time,\n有时候，你想让一个 view 在一段时间内渐隐\n\n568\n00:29:18,424 --> 00:29:19,790\nyou want to animate that,\n你想要做它的一个动画\n\n569\n00:29:19,792 --> 00:29:21,158\nalpha is one of the things you can animate,\nalpha 是你能用来做动画的东西之一\n\n570\n00:29:21,160 --> 00:29:23,560\nwe'll talk about animate in a couple of weeks, so\n我们将在几周之后谈到动画。所以\n\n571\n00:29:23,562 --> 00:29:27,131\nalpha is cool for doing that. All right,\nalpha 用来做这事儿挺不错的。好的\n\n572\n00:29:27,133 --> 00:29:29,633\nnow let's talk about this view transparency and\n现在我们来讨论一下这个视图透明度以及\n\n573\n00:29:29,635 --> 00:29:31,835\nhow that works when you're drawing with transparency.\n当你用透明度绘图的时候，它的工作原理\n\n574\n00:29:31,837 --> 00:29:34,938\nIf you have non-opaque views, okay, say they're drawn with\n如果你没有不透明的视图，也就是说是带有\n\n575\n00:29:34,940 --> 00:29:38,375\ntransparency, then what happens is that sub views list\n透明度的。然后就是，当子视图列表的第一个东西\n\n576\n00:29:38,377 --> 00:29:41,311\nthat shows all of the sub views is in order\n显示在后面的时候，显示所有子视图的那个子视图列表\n\n577\n00:29:41,313 --> 00:29:45,149\nwhere the first thing in the sub views list is in the back\n依然是井井有条的。\n\n578\n00:29:45,284 --> 00:29:46,550\nokay. The next thing is in front of that,\n下一个东西在它前面，\n\n579\n00:29:46,552 --> 00:29:48,285\nand the next one's in front of that, the next one's in front\n下一个又在这一个前面，下一个又在前面\n\n580\n00:29:48,287 --> 00:29:52,189\nof that and so it's gonna show through like that, get it? So\n所以，这就是它透视的原理。懂了吗？\n\n581\n00:29:52,191 --> 00:29:53,690\nthe sub views list matters okay.\n子视图列表是很重要的，明白？\n\n582\n00:29:53,692 --> 00:29:57,928\nThe sub views list is built by add subview, everything is\n子视图列表是通过添加子视图建立的。当你调用\n\n583\n00:29:57,930 --> 00:30:00,330\nalways put in the front when you call add subview. But,\naddSubview() 方法时，东西都是放在前面的。但是\n\n584\n00:30:00,332 --> 00:30:03,767\nthere's another method called insert subview at, that let you\n有另一个方法叫insertSubview at，让你\n\n585\n00:30:03,769 --> 00:30:06,370\nput it anywhere you want. You put a subview in the back.\n能再任何位置添加子视图。你在后面添加一个子视图\n\n586\n00:30:06,372 --> 00:30:08,038\nLike if you say, insert subview at zero,\n假设如果说，在索引值为0处插入子视图\n\n587\n00:30:08,040 --> 00:30:11,675\nit will put it up at the back. Okay. So, just note that,\n它就会在后面添加这个子视图。好的，这里记住\n\n588\n00:30:11,677 --> 00:30:16,180\nthat subviews orders obviously matters. You can\n子视图的秩序真的很重要。通过\n\n589\n00:30:16,182 --> 00:30:20,484\ncompletely hide a view by setting it's hidden to true.\n设置一个 view 的 hidden 为 true，你能完全隐藏它\n\n590\n00:30:20,486 --> 00:30:24,087\nIf you set it's hidden to true, it will not receive any\n如果你把它的 hidden 值设为 true 了，它不会接受任何的\n\n591\n00:30:24,089 --> 00:30:27,257\nevents, no touch events. Nor will it draw what it draws.\n事件，没有触摸事件。也不会画出它的图像\n\n592\n00:30:27,259 --> 00:30:29,560\nIt will still be in view hierarchy, okay, but\n它仍然会在这一层视图，但是\n\n593\n00:30:29,562 --> 00:30:32,129\nit's as if it's not there. Now why would you want this? Well\n看起来就像它没在那儿一样。好的，你什么时候会想要这样？\n\n594\n00:30:32,131 --> 00:30:34,431\nyou might have a view that only appears when a certain\n比如，或许你有一个视图，只在一个按钮\n\n595\n00:30:34,433 --> 00:30:37,568\nbutton is in a certain state. So you put it there.\n处在确定的状态时才显示。所以你把它放在在那儿\n\n596\n00:30:37,570 --> 00:30:39,903\nYou set it hidden. When the button goes to that state you\n设成隐藏。当那个按钮到那个状态的时候你\n\n597\n00:30:39,905 --> 00:30:44,341\nunhide it and it'll appear. Now to be frank you probably\n取消隐藏，然后它显示出来。实际上呢，你可能\n\n598\n00:30:44,343 --> 00:30:46,944\nanimate it's appearance with alpha okay so\n会使用动画，设置透明度，把它渐渐显示出来。所以\n\n599\n00:30:46,946 --> 00:30:48,111\nit would zooooo appear like that.\n看起来就像 zoooo 的一下出来了。\n\n600\n00:30:48,113 --> 00:30:51,648\nInstead of jumping on screen that's kind of disconsidering.\n而不是一下子跳到屏幕上，那看起来有点欠考虑。\n\n601\n00:30:51,650 --> 00:30:53,784\nBut you still would probably use hidden to have it hidden\n但是你最开始的时候可能要用 hidden 去\n\n602\n00:30:53,786 --> 00:30:55,319\nin the first place. Because you wouldn't want it for\n把它隐藏掉。因为，举个例子，在它完全显示之前\n\n603\n00:30:55,321 --> 00:30:57,688\nexample getting a touch of answer on like that until\n你不会想让它对任何点击\n\n604\n00:30:57,690 --> 00:31:02,359\nit was shown. What about drawing text.\n做出回应。那么画文字呢？\n\n605\n00:31:02,361 --> 00:31:07,164\nYou do not draw text using a UiBezier path. Text is\n我们不用 UIBezierPath 却画文字。文字算是\n\n606\n00:31:07,166 --> 00:31:12,069\nreally just a bunch of Bezier paths in a font. A font really\n在一种字体中的一大堆的贝塞尔线条。一种字体实际上\n\n607\n00:31:12,071 --> 00:31:14,905\ndefines a bunch of Bezier paths for each character,\n为每一个字符、每一条曲线都定义了一堆的\n\n608\n00:31:14,907 --> 00:31:19,943\neach gliff. It's called. So we have higher level ways of\n贝塞尔线条。这是它的原理。所以说我们有更高级的方法去\n\n609\n00:31:19,945 --> 00:31:22,880\ndrawing text by basically saying here's a string,\n画文字。基本来说就是，来，这里有个字符串\n\n610\n00:31:22,882 --> 00:31:25,883\ndraw it. Okay that's a high level way to get all those\n画出来。这是一种更高级的方法去把这些\n\n611\n00:31:25,885 --> 00:31:28,452\nbezier paths drawn, you don't want to be dealing with that\n线条画出来，你不会想要在 UIBezierPath 这一层\n\n612\n00:31:28,454 --> 00:31:31,588\nat the UI bezier path level for sure. But most the time,\n去画文字的，相信我。但是大多数时候\n\n613\n00:31:31,590 --> 00:31:35,325\nwe don't draw text even in our drawRect. We draw it by using\n我们甚至不用 drawRect 去画文字。我们通过使用\n\n614\n00:31:35,327 --> 00:31:37,728\nUILabel which you're used to all ready, okay?\n你已经完全熟悉的 UILabel 去画它。了解？\n\n615\n00:31:37,730 --> 00:31:39,997\nWe just have a rectangle? Boom, we put it on here.\n我们有一个矩形。当 ~ 我们把它放在这儿\n\n616\n00:31:39,999 --> 00:31:42,432\nIf we wanted to say hello on this guy's forehead,\n如果我们想在这个家伙额头上画个 \"hello\"\n\n617\n00:31:42,434 --> 00:31:45,969\nwe might put a UILabel right there say hello. Okay, but\n我们会在那儿放个 UILabel 然后写上 hello。好的，但是\n\n618\n00:31:45,971 --> 00:31:48,305\nwhat if we did want in our draw rect.\n假如我们想让它在 drawRect 里面\n\n619\n00:31:48,307 --> 00:31:51,241\nWhat if we wanted to put some text in here and\n假如我们想在这里放点文本\n\n620\n00:31:51,243 --> 00:31:53,343\nwe didn't want to put it as a subview,\n但是我们不想把它弄成 UILabel\n\n621\n00:31:53,345 --> 00:31:57,214\na UILabel subview on our face view. And the way you do that\n这样一个子视图，然后放在我们的 faceView 上。做这个的方法\n\n622\n00:31:57,216 --> 00:32:00,584\nis with a class called NS attributed string Okay,\n是用一个类，叫做 NSAtrributedString，明白？\n\n623\n00:32:00,586 --> 00:32:03,587\nNSAttributedString. And you create it by\nNSAttributedString。并且你要通过这里\n\n624\n00:32:03,589 --> 00:32:07,658\nthis constructor here. Usually you pass a string in here.\n这个构造器来创建它。通常来说，你在这里传一个字符串\n\n625\n00:32:07,660 --> 00:32:11,929\nWhat an attributed string is, it's a string that for every\n一个特征字符串是什么呢？它是一个字符串，它的每一个\n\n626\n00:32:11,931 --> 00:32:15,832\ncharacter has a dictionary of attributes that say how to\n字符，在字典中都有一个对应的属性，来说明怎么去\n\n627\n00:32:15,834 --> 00:32:19,903\ndraw it. And those attributes are things like, the color of\n画它。这些属性就像字符或者曲线的\n\n628\n00:32:19,905 --> 00:32:24,241\nthe character or of the glyph, the font to use obviously,\n颜色、使用的字体\n\n629\n00:32:24,243 --> 00:32:25,409\nmaybe a background color,\n或者背景颜色\n\n630\n00:32:25,411 --> 00:32:28,545\nthose kind of things, right? You have a dictionary that has\n像这些东西。明白？你有一个为每一个字符\n\n631\n00:32:28,547 --> 00:32:30,714\nall those kinds of settings for every single character.\n设置了这些东西的字典\n\n632\n00:32:30,716 --> 00:32:33,417\nNow often you have long runs of characters that have\n通常你有一长串有着同样的\n\n633\n00:32:33,419 --> 00:32:35,752\nexactly the same color and font or whatever, so\n颜色和字体的字符。不论如何\n\n634\n00:32:35,754 --> 00:32:38,789\nyou would have one dictionary for all of them. But\n你会有一个包含了这些所有东西的字典\n\n635\n00:32:38,791 --> 00:32:41,725\nthat is the basic way that AttributedString works. And\n这就是基本的 AttributedString 的工作原理。而且\n\n636\n00:32:41,727 --> 00:32:44,761\nonce you have an attributed string, okay, maybe you've set\n一旦你有一个 attributed string。或许你\n\n637\n00:32:44,763 --> 00:32:47,431\nthese dictionaries on the characters, then you draw it\n这些字符上设置了一些字典，然后你使用 text\n\n638\n00:32:47,433 --> 00:32:50,334\nin your drawRect by saying text, that's the attributed\n在你的 drawRect 里面画它，这就是 attributed string\n\n639\n00:32:50,336 --> 00:32:53,737\nstring. You send the method here, drawAtPoint,\n在这儿你调用 drawAtPoint\n\n640\n00:32:53,739 --> 00:32:57,674\nand then you give it a point. And it's going to draw that\n然后你给它一个点，它就会以那个点\n\n641\n00:32:57,676 --> 00:33:00,811\ntext with the upper left corner being at that point.\n为左上角的坐标把文字画出来\n\n642\n00:33:00,813 --> 00:33:03,480\nSo, if I wanted to do that hello and I would have drew\n所以，如果我想画那个 hello 而且我想\n\n643\n00:33:03,482 --> 00:33:07,351\nit right here. The hello would appear like this. Okay,\n就在这里画。那个 hello 就会像这样\n\n644\n00:33:07,353 --> 00:33:09,419\nthis is the upper left and it would appear,\n这里是左上角，它就会\n\n645\n00:33:09,421 --> 00:33:13,256\nthe text would appear here. Okay, got that? And I could\n这段文字就会在这显示。懂了？而且我能\n\n646\n00:33:13,258 --> 00:33:18,228\nfind out how big this is gonna be by using this size method,\n知道这个的大小是多少，用这个 size 方法\n\n647\n00:33:18,230 --> 00:33:22,833\nokay, the size property, actually of attributed string,\n这个 size 属性，纠正下，这个特征字符串的\n\n648\n00:33:22,835 --> 00:33:26,837\nokay? So that's how we draw a text. Now this is a little\n好了吗？所以这就是我们画文字的方法。这是个有点\n\n649\n00:33:26,839 --> 00:33:29,673\nbit of a nasty class to use, to be honest,\n用起来不太好的类，说实话，这个\n\n650\n00:33:29,675 --> 00:33:33,176\nNSAttributedString, for a couple of reasons. But\nNSAttributedString，因为各种原因\n\n651\n00:33:33,178 --> 00:33:36,480\nall the reasons come from the fact this is an Objective-C\n所有的这些原因都是因为这是一个Objective-C\n\n652\n00:33:36,482 --> 00:33:40,517\nclass that really didn't get a very good Swift treatment yet,\n的类，目前对 Swift 的适配度并不太好\n\n653\n00:33:40,519 --> 00:33:43,820\nokay? So there's two major differences\n明白吗？所以这里有两个原因，让这个\n\n654\n00:33:43,822 --> 00:33:47,157\nthat make using it a kind of complicated in Swift,\n东西在 Swift 里有点复杂\n\n655\n00:33:47,159 --> 00:33:52,129\nokay? One is that mutability is not done with var and\n一个是它的可变性不是用 var 和 let\n\n656\n00:33:52,131 --> 00:33:55,165\nlet. Okay, normally if you wanted an array that you can\n来控制的。通常如果你想要一个数组\n\n657\n00:33:55,167 --> 00:33:58,535\nadd things to do, you would just say var x array, and\n能给它加东西的话，你直接会说 var x array。然后\n\n658\n00:33:58,537 --> 00:34:00,337\nsince it's a var you can add to it. Okay,\n这是个 var，你能给它加东西。\n\n659\n00:34:00,339 --> 00:34:03,974\nif you said let x of an array, then you couldn't add to it.\n如果你说这个 x 是设为 let 的数组，你就不能加东西\n\n660\n00:34:03,976 --> 00:34:05,976\nWell that's not true for NSAttributedString.\n但是这在 NSAttributedString 里不适用\n\n661\n00:34:05,978 --> 00:34:08,078\nYou can't say var NSAttributedString,\n你不能把 NSAttributedString 设成 var\n\n662\n00:34:08,080 --> 00:34:11,448\nthat's still immutable. The way you do mutability is with\n它仍然是不可变的。你要使用可变性就要\n\n663\n00:34:11,450 --> 00:34:15,185\nNSMutableAttributedString, it's a different class, okay?\n用到 NSMutableAttributedString，这是另一个类，懂？\n\n664\n00:34:15,187 --> 00:34:17,687\nSo if you wanna built an attributed string and\n所以如果你想建一个特征数组而且\n\n665\n00:34:17,689 --> 00:34:20,824\nstart setting the attributes on it, you need to use\n要给它设置属性的话，你需要用到\n\n666\n00:34:20,826 --> 00:34:23,293\nMutableAttributedString instead, okay?\nMutableAttributedString，懂？\n\n667\n00:34:23,295 --> 00:34:25,362\nYou create it the same way with some string but\n你用了同样的创造字符串的方法，但是\n\n668\n00:34:25,364 --> 00:34:27,898\nnow you can set the attributes of it or whatever. So\n你能看到它的属性等等。所以\n\n669\n00:34:27,900 --> 00:34:30,634\nthat's one thing that's kinda weird, okay? Is this mutable,\n这是里面有点怪的一件事。要用到可变性\n\n670\n00:34:30,636 --> 00:34:33,737\nyou have to use this mutable version of it.\n你就需要设置它使用 mutable 的版本\n\n671\n00:34:33,739 --> 00:34:37,307\nBy the way, NSAttributedString is not a string, a Swift\n顺便，NSAttributedString 不是 Swift 的\n\n672\n00:34:37,309 --> 00:34:40,811\nstring, nor is it an NSString even an object string. It's\n字符串，也不是 NSString，甚至连个对象都不算\n\n673\n00:34:40,813 --> 00:34:44,581\nits own thing. It does have a property string and another\n它就是它自己。它有一个 string 的属性和一个\n\n674\n00:34:44,583 --> 00:34:47,317\nproperty called mutableString that will give you back\nmutableString 的属性，能在你想\n\n675\n00:34:47,319 --> 00:34:52,389\na string/NSString using that bridging thing but\n桥接这个东西的时候返回一个 string/NSString，但是\n\n676\n00:34:52,391 --> 00:34:55,625\nit itself is not a string. You can't pass it as an argument\n它本身不是一个字符串。你不能把它当参数传递\n\n677\n00:34:55,627 --> 00:34:57,461\nto something that's accepting a string, okay?\n给某个接收一个字符串的东西，明白？\n\n678\n00:34:57,463 --> 00:35:00,397\nNSAttributedString is a different thing. Now,\nNSAttributedString 是一个不一样的东西\n\n679\n00:35:00,399 --> 00:35:02,933\nthe second thing that's difficult with Swift and\n第二事，Swift 处理起来比较困难的\n\n680\n00:35:02,935 --> 00:35:07,337\nattributed string is the range here, okay?\nattributedString 是一个 range\n\n681\n00:35:07,339 --> 00:35:08,505\nYou're trying to set attributes.\n当你想设定一些属性的时候\n\n682\n00:35:08,507 --> 00:35:10,774\nThis is how you set attributes in the thing.\n这就是你能设定属性的方法\n\n683\n00:35:10,776 --> 00:35:11,007\nHere's the dictionary.\n这时这个字典的问题\n\n684\n00:35:11,009 --> 00:35:13,443\nI'm gonna show you what's in that dictionary in a second.\n我一会儿会说这个字典里的东西\n\n685\n00:35:13,445 --> 00:35:16,113\nAnd you're trying to set it for a range of characters in\n你要尝试把它理解为一个字符串里的\n\n686\n00:35:16,115 --> 00:35:19,316\nthe string. You want the font or a color to be something for\n一段区间的字符，你想让一个颜色或者字体\n\n687\n00:35:19,318 --> 00:35:22,686\na range of characters. Well, this range is not a Range,\n设成一段字符。实际上这个区段不是个 Range 类型\n\n688\n00:35:22,688 --> 00:35:27,157\nit's an NSRange. Okay, NSRange is different than Range.\n它是个 NSRange，NSRange 和 Range 不一样\n\n689\n00:35:27,159 --> 00:35:29,993\nAnd NSRange, the index is in here.\nNSRange 呢，这里的这个 index\n\n690\n00:35:29,995 --> 00:35:35,265\nOkay, it's a struct also that has a start in and a range,\n同样，它是个 struct \n\n691\n00:35:35,267 --> 00:35:38,902\nbasically. A distance, start in a distance. But\n\n692\n00:35:38,904 --> 00:35:43,240\nthese indexes are into the Objective-C NSString. Now,\n\n693\n00:35:43,242 --> 00:35:45,542\nwhat's the difference between a Objective-C NSString and\n\n694\n00:35:45,544 --> 00:35:47,544\na Swift string? Well, as I told you before,\n\n695\n00:35:47,546 --> 00:35:50,914\na Swift string is fully Unicode compliant, okay? So,\n\n696\n00:35:50,916 --> 00:35:53,550\nthings like emojis and stuff like that might be multiple\n\n697\n00:35:53,552 --> 00:35:57,654\ncharacters. So the length of an NSString might be different\n\n698\n00:35:57,656 --> 00:35:58,989\nthen the length of a Swift string,\n\n699\n00:35:58,991 --> 00:36:03,860\nokay? Swift string has a lot of possible Unicodes in there,\n\n700\n00:36:03,862 --> 00:36:07,264\nwhereas an NSString might not necessary do the full Unicode\n\n701\n00:36:07,266 --> 00:36:09,399\ntreatment. So, bottom line, they're different.\n\n702\n00:36:09,401 --> 00:36:12,302\nNow, if you have just normal text which I hesitate to even\n\n703\n00:36:12,304 --> 00:36:15,972\nsay that because of course you want to build apps that work\n\n704\n00:36:15,974 --> 00:36:16,106\nBut if you have text where there's no Unicodes in there\n\n705\n00:36:16,108 --> 00:36:19,609\nworldwide.\n\n706\n00:36:19,611 --> 00:36:21,711\nthat are multiple characters long.\n\n707\n00:36:21,713 --> 00:36:23,480\nYou don't have emojis in there and stuff.\n\n708\n00:36:23,482 --> 00:36:25,982\nThen they're gonna be quite similar, these ranges, but\n\n709\n00:36:25,984 --> 00:36:28,618\notherwise, you might have to be really careful to make sure\n\n710\n00:36:28,620 --> 00:36:31,855\nthat you get the range to be the NSString range.\n\n711\n00:36:31,857 --> 00:36:34,791\nThat might mean taking the Swift string that you have,\n\n712\n00:36:34,793 --> 00:36:35,725\nconverting it to an NSString,\n\n713\n00:36:35,727 --> 00:36:38,195\nwhich is really easy cuz it's bridged automatically.\n\n714\n00:36:38,197 --> 00:36:41,264\nAnd then, looking into the NSString to see how long it is\n\n715\n00:36:41,266 --> 00:36:44,267\nand where things are. Okay, I apologize for this.\n\n716\n00:36:44,269 --> 00:36:45,769\nOf course, I have never worked for Apple, so\n\n717\n00:36:45,771 --> 00:36:48,905\nI have nothing to do with it. But, this is the way it is.\n\n718\n00:36:48,907 --> 00:36:52,576\nHopefully, one day soon, Apple will come up with some\n\n719\n00:36:52,578 --> 00:36:55,712\nnice more Swifty way of doing this. What is in this,\n\n720\n00:36:55,714 --> 00:36:58,348\nby the way I'm not gonna ask you to do this very much in\n\n721\n00:36:58,350 --> 00:37:01,251\nyour homework. Okay, so don't worry too much about that.\n\n722\n00:37:01,253 --> 00:37:04,421\nWhat are the attributes you could put in this dictionary?\n\n723\n00:37:04,423 --> 00:37:05,789\nExactly what you would expect.\n\n724\n00:37:05,791 --> 00:37:09,192\nOkay, the foreground color is the color of the text.\n\n725\n00:37:09,194 --> 00:37:10,994\nThe stroke width is how thick you're gonna\n\n726\n00:37:10,996 --> 00:37:14,197\nstroke the text. The FontAttributeName is the font,\n\n727\n00:37:14,199 --> 00:37:17,634\nthe UIFont. There's a class called UIFont, okay?\n\n728\n00:37:17,636 --> 00:37:20,170\nYou put those in a dictionary and then you can set that for\n\n729\n00:37:20,172 --> 00:37:23,840\nwhichever characters you want in your attributed string.\n\n730\n00:37:23,842 --> 00:37:27,377\nNow let's talk about fonts, by the way. Fonts are super\n\n731\n00:37:27,379 --> 00:37:31,047\nimportant in iOS, okay? They are critical to the look and\n\n732\n00:37:31,049 --> 00:37:34,017\nfeel of it. You can see there's all kinds of different\n\n733\n00:37:34,019 --> 00:37:39,389\nfonts here, right? You see some bold, some not, some kind\n\n734\n00:37:39,391 --> 00:37:43,026\nof heading fonts, there's system fonts like up here.\n\n735\n00:37:43,028 --> 00:37:46,630\nLook at the use of fonts here, how important that is, okay?\n\n736\n00:37:46,632 --> 00:37:47,797\nSo fonts are very important and\n\n737\n00:37:47,799 --> 00:37:48,765\nif you're gonna build a good app,\n\n738\n00:37:48,767 --> 00:37:50,767\nyou really gotta pay attention to the fonts.\n\n739\n00:37:50,769 --> 00:37:54,237\nSo how do I get the fonts or pick the fonts that I want?\n\n740\n00:37:54,239 --> 00:37:56,339\nWell there's really three ways to do pick it,\n\n741\n00:37:56,341 --> 00:38:00,510\nokay? Number one way is using prefered fonts. So,\n\n742\n00:38:00,512 --> 00:38:03,013\npreferred fonts are the fonts you're gonna use for\n\n743\n00:38:03,015 --> 00:38:06,249\nthe user's content, okay? The user, the stuff the user is\n\n744\n00:38:06,251 --> 00:38:08,652\nactually, there, like if it's a calendar app,\n\n745\n00:38:08,654 --> 00:38:11,288\nthen it's all of the things about their appointments and\n\n746\n00:38:11,290 --> 00:38:13,423\nthings, okay? If it's the weather app,\n\n747\n00:38:13,425 --> 00:38:15,425\nit's the temperature and things like that.\n\n748\n00:38:15,427 --> 00:38:19,262\nThose are part of the user's content. You get these\n\n749\n00:38:19,264 --> 00:38:23,600\nmostly in storyboard by going to attributes inspector and\n\n750\n00:38:23,602 --> 00:38:26,703\nyou pick the font. And we've only picked the system font\n\n751\n00:38:26,705 --> 00:38:29,272\nbecause we've always just had buttons, which is a system\n\n752\n00:38:29,274 --> 00:38:32,575\nfont thing. But for content, you would pick in there\n\n753\n00:38:32,577 --> 00:38:35,312\nprefered font. Okay, and I'm gonna talk about what those\n\n754\n00:38:35,314 --> 00:38:38,048\nreferred font styles are in a second. In code,\n\n755\n00:38:38,050 --> 00:38:41,785\nyour gonna use this UIFont static type function called\n\n756\n00:38:41,787 --> 00:38:44,654\npreferredFontForTextStyle and say what kind of text\n\n757\n00:38:44,656 --> 00:38:47,891\nstyle you want and it's gonna give you UIFont, okay?\n\n758\n00:38:47,893 --> 00:38:50,994\nSo what are these text styles? Okay, there's about eight or\n\n759\n00:38:50,996 --> 00:38:54,297\nnine of them, but some examples are headlines, body\n\n760\n00:38:54,299 --> 00:38:57,600\nfont, footnote font, and you should use the one that's kind\n\n761\n00:38:57,602 --> 00:39:01,871\nof appropriate to what your UI's doing at that time, okay?\n\n762\n00:39:01,873 --> 00:39:04,307\nThere's like caption font, a couple of other things,\n\n763\n00:39:04,309 --> 00:39:08,011\nall right? And so, you know, sometimes you play with these.\n\n764\n00:39:08,013 --> 00:39:09,379\nThe difference between a caption and\n\n765\n00:39:09,381 --> 00:39:12,549\na footnote can sometimes be subtle so\n\n766\n00:39:12,551 --> 00:39:12,882\nyou might try both and\n\n767\n00:39:12,884 --> 00:39:15,518\nsee which one really feels the best. But, you're gonna use\n\n768\n00:39:15,520 --> 00:39:18,021\nthese various preferred fonts to build a cool looking\n\n769\n00:39:18,023 --> 00:39:21,124\nUI, okay, that's beautiful and all that.\n\n770\n00:39:21,126 --> 00:39:24,227\nThe second kind of font thing is systems font, okay?\n\n771\n00:39:24,229 --> 00:39:26,996\nsystemFontOfSize, boldSystemFontOfSize.\n\n772\n00:39:26,998 --> 00:39:30,200\nSystem font's what we'll been using in our calculator,\n\n773\n00:39:30,202 --> 00:39:33,937\nthose go on system elements like buttons, okay,\n\n774\n00:39:33,939 --> 00:39:35,972\nthat's where you would use a system font.\n\n775\n00:39:35,974 --> 00:39:37,407\nIn our display in the calculator,\n\n776\n00:39:37,409 --> 00:39:39,542\nwe probably shouldn't have used a system font there\n\n777\n00:39:39,544 --> 00:39:41,811\nbecause really what's in the display is kinda the user's\n\n778\n00:39:41,813 --> 00:39:44,848\ncontent. Probably we should've used a prefered font but\n\n779\n00:39:44,850 --> 00:39:48,051\nI hadn't shown you the slide yet so can't introduce it all\n\n780\n00:39:48,053 --> 00:39:51,988\nat once, okay? But that probably would be better.\n\n781\n00:39:51,990 --> 00:39:55,191\nAnd the kind of font we want to use there might be instead\n\n782\n00:39:55,193 --> 00:39:58,361\nof a, sometimes you want to use a specific font, okay,\n\n783\n00:39:58,363 --> 00:40:01,664\nso the third way here Is to use a specific kind of font.\n\n784\n00:40:01,666 --> 00:40:04,901\nLike maybe in the calculator display we wanna use something\n\n785\n00:40:04,903 --> 00:40:05,969\nthat looks like LED segments.\n\n786\n00:40:05,971 --> 00:40:08,171\nYou know what I'm talking about? The old style,\n\n787\n00:40:08,173 --> 00:40:11,941\nfunny calculator thing back when we had LED displays.\n\n788\n00:40:11,943 --> 00:40:15,578\n[LAUGH] So we might wanna font this LED font which they make\n\n789\n00:40:15,580 --> 00:40:18,982\nthose. In that case, you wanna check out UI font and\n\n790\n00:40:18,984 --> 00:40:20,884\nUI font descriptor, especially,\n\n791\n00:40:20,886 --> 00:40:23,620\nbecause those are how you pick a specific font from\n\n792\n00:40:23,622 --> 00:40:27,090\na specific family, okay. Like the LED font family, okay.\n\n793\n00:40:27,092 --> 00:40:31,728\nSo those are the three ways. Preferred system or highly\n\n794\n00:40:31,730 --> 00:40:36,399\ncustomized okay, how about drawing images? Just like\n\n795\n00:40:36,401 --> 00:40:39,102\nthere's UILabel for drawing text, there's something called\n\n796\n00:40:39,104 --> 00:40:41,571\nUIImageView for drawing images. So, you could just put\n\n797\n00:40:41,573 --> 00:40:44,707\nan image if I wanted to put image on this guy's forehead,\n\n798\n00:40:44,709 --> 00:40:48,711\nI could just put UIImage here and have my image here. Okay,\n\n799\n00:40:48,713 --> 00:40:50,213\nput it as a sub view of my face view.\n\n800\n00:40:50,215 --> 00:40:52,982\nSo, that's one way to do it. But, if I want to draw\n\n801\n00:40:52,984 --> 00:40:56,686\nUI image in my draw rack, it's very similar to the text,\n\n802\n00:40:56,688 --> 00:40:59,122\nI'm going to get a UI image, okay.\n\n803\n00:40:59,124 --> 00:41:01,958\nThere's a number of ways. I'll show you here to do that.\n\n804\n00:41:01,960 --> 00:41:04,360\nBut, the main way is you're gonna do it by name.\n\n805\n00:41:04,362 --> 00:41:07,063\nYou're gonna put the image in that images.xcassets.\n\n806\n00:41:07,065 --> 00:41:09,933\nDo you remember that thing I kept moving out of the way\n\n807\n00:41:09,935 --> 00:41:12,735\ninto supporting files? Okay Images.xcassets,\n\n808\n00:41:12,737 --> 00:41:15,738\nso you're gonna drag an image in there, give it a name, and\n\n809\n00:41:15,740 --> 00:41:18,975\nthen you're gonna say image named that name and you're\n\n810\n00:41:18,977 --> 00:41:22,912\ngonna get a UIImage. This is optional because it's my fail.\n\n811\n00:41:22,914 --> 00:41:25,448\nOkay, you might have forgotten to drag that image in there or\n\n812\n00:41:25,450 --> 00:41:28,751\nsomething. Who knows? But once you have this UIImage in your\n\n813\n00:41:28,753 --> 00:41:31,521\nhand. By the way there are other ways you can do it.\n\n814\n00:41:31,523 --> 00:41:32,956\nYou can create it from a file.\n\n815\n00:41:32,958 --> 00:41:35,158\nJust some image data you got from the Internet for example.\n\n816\n00:41:35,160 --> 00:41:38,261\nThat's another way to create a UI image. You can even do it\n\n817\n00:41:38,263 --> 00:41:42,532\nby drawing graphics onto an off screen buffer. You have\n\n818\n00:41:42,534 --> 00:41:47,237\nthat image in your hand, you draw it the same as the text.\n\n819\n00:41:47,239 --> 00:41:50,440\nYou say draw at point. That's the upper left.\n\n820\n00:41:50,442 --> 00:41:52,308\nBut you also can do what called draw erect.\n\n821\n00:41:52,310 --> 00:41:54,944\nWhich will draw the image but scale it to fit this\n\n822\n00:41:54,946 --> 00:41:58,548\nrect, okay? Or you can draw it as a pattern which will\n\n823\n00:41:58,550 --> 00:42:01,684\ntile it okay? It will take that rect and use it as a tile\n\n824\n00:42:01,686 --> 00:42:05,288\nto fill in the rectangle. Okay, so this code would be\n\n825\n00:42:05,290 --> 00:42:10,994\nthe kind of code that would be in your draw rect. Okay\n\n826\n00:42:10,996 --> 00:42:14,697\nthe last thing here above you is redrawing on bounds change,\n\n827\n00:42:14,699 --> 00:42:19,702\nokay. When your view's bounds changes, what happens\n\n828\n00:42:19,704 --> 00:42:25,241\nto the face inside here? Okay so, if I had this face and\n\n829\n00:42:25,243 --> 00:42:29,979\nit was in a portrait thing here. Let's say it looked like\n\n830\n00:42:29,981 --> 00:42:35,118\nthis, okay. Face. And I rotated my device in this\n\n831\n00:42:35,120 --> 00:42:40,757\nbounds of my view changed to be like this. Landscape.\n\n832\n00:42:40,759 --> 00:42:43,293\nYou think well I'm a face would you have to redraw and\n\n833\n00:42:43,295 --> 00:42:46,329\nit would probably look about the same. The answer is not.\n\n834\n00:42:46,331 --> 00:42:52,702\nIt would look like this, okay? It would get stretched out.\n\n835\n00:42:52,704 --> 00:42:56,472\nAnd that's cuz the default when your bounds change is to\n\n836\n00:42:56,474 --> 00:43:01,010\nscale all the bits, to not redraw, okay? And that's\n\n837\n00:43:01,012 --> 00:43:04,747\na performance thing as you can imagine. It's a lot more,\n\n838\n00:43:04,749 --> 00:43:07,417\na lot easier just to stretch those bits out than to ask\n\n839\n00:43:07,419 --> 00:43:11,220\ndraw rec to go again. So you can fix this though with this\n\n840\n00:43:11,222 --> 00:43:14,591\nproperty in your eye view called content mode. Okay,\n\n841\n00:43:14,593 --> 00:43:20,063\nUI content mode? And some of the value of it can be\n\n842\n00:43:20,065 --> 00:43:23,700\nto move the contents to the left to right top, bottom top,\n\n843\n00:43:23,702 --> 00:43:26,736\nright top left. Okay you could just move it, not stretch it\n\n844\n00:43:26,738 --> 00:43:29,706\nout but just move it to that place in the new bounce.\n\n845\n00:43:29,708 --> 00:43:33,176\nYou can scale it. This is the default, ScaleToFill, okay?\n\n846\n00:43:33,178 --> 00:43:35,578\nAnd that's a stretching out behavior.\n\n847\n00:43:35,580 --> 00:43:37,180\nOr the holy grail, Redraw.\n\n848\n00:43:37,182 --> 00:43:40,149\nIf you set your content mode to Redraw, it'll call your\n\n849\n00:43:40,151 --> 00:43:44,887\ndrawRect again, okay? You often want that. Maybe most of\n\n850\n00:43:44,889 --> 00:43:49,425\nthe time you want that, okay? All right, everybody got that?\n\n851\n00:43:49,427 --> 00:43:52,595\nWe'll be doing this in the demo, too, so you'll see it.\n\n852\n00:43:52,597 --> 00:43:54,530\nOkay, so I'm not going to come back to this slide.\n\n853\n00:43:54,532 --> 00:43:57,233\nSo, just tell you what's coming up after the demo.\n\n854\n00:43:57,235 --> 00:44:00,003\nNo section on Friday, as we said. Next week, gestures,\n\n855\n00:44:00,005 --> 00:44:03,439\nmultiple MVCs and View Controller Lifecycle, okay we\n\n856\n00:44:03,441 --> 00:44:05,908\nwill talk about next week. And right now I'm going to do\n\n857\n00:44:05,910 --> 00:44:08,745\nat demo where I'm gonna do custom UI view to draw this\n\n858\n00:44:08,747 --> 00:44:14,083\nface thing, okay. That's the timer saying we should\n\n859\n00:44:14,085 --> 00:44:20,556\nstart the demo. Let's do it. All right,\n\n860\n00:44:20,558 --> 00:44:23,393\nso I'm not going to be doing calculator here, this\n\n861\n00:44:23,395 --> 00:44:26,629\nis going to be a completely new application, alright,\n\n862\n00:44:26,631 --> 00:44:29,599\nso I'm going down here to create new XCode project.\n\n863\n00:44:29,601 --> 00:44:32,769\nOkay, here it is, it's still in iOS application though,\n\n864\n00:44:32,771 --> 00:44:34,237\nwe'll do single view application.\n\n865\n00:44:34,239 --> 00:44:38,007\nI'm gonna call it, Faceit, okay? It's a face drawing\n\n866\n00:44:38,009 --> 00:44:41,277\napp so I'm ca-calling it Faceit. Make sure it's Swift,\n\n867\n00:44:41,279 --> 00:44:43,312\nnot Objective-C and it'll be a universal\n\n868\n00:44:43,314 --> 00:44:45,515\napp cuz we're eventually gonna do multiple MVCs with\n\n869\n00:44:45,517 --> 00:44:50,386\nthis thing too. No core date or testing, okay? We're going\n\n870\n00:44:50,388 --> 00:44:52,855\nto put it in the same place we put the calculator here, not\n\n871\n00:44:52,857 --> 00:44:56,726\nsource code control yet. All right, so here's our new app,\n\n872\n00:44:56,728 --> 00:44:59,362\nI'm going to do the same thing I always do with this,\n\n873\n00:44:59,364 --> 00:45:00,963\nI called that images, that x, assets,\n\n874\n00:45:00,965 --> 00:45:02,732\nbut it's called assets.xz assets.\n\n875\n00:45:02,734 --> 00:45:04,934\nThis is where you would drag in your images if you wanted\n\n876\n00:45:04,936 --> 00:45:08,104\nto do that UI image named foo thing. You'll put them in\n\n877\n00:45:08,106 --> 00:45:11,340\nhere, but, obviously, I don't need these things,\n\n878\n00:45:11,342 --> 00:45:11,407\nas usual, so\n\n879\n00:45:11,409 --> 00:45:13,976\nI'm just gonna group them into that supporting\n\n880\n00:45:13,978 --> 00:45:16,412\nfiles so they're not distracting you every time you\n\n881\n00:45:16,414 --> 00:45:19,716\ntake a look over here on the left, cuz all we really care,\n\n882\n00:45:19,718 --> 00:45:22,251\ncare about, again, is our storyboard and\n\n883\n00:45:22,253 --> 00:45:25,054\nour view controller. Now, again, we're talking about\n\n884\n00:45:25,056 --> 00:45:26,556\nview controller lifecycle next week, so\n\n885\n00:45:26,558 --> 00:45:29,225\nwe're gonna delete these, all right? Now, the first\n\n886\n00:45:29,227 --> 00:45:31,761\nthing I'm gonna do is actually rename this ViewController,\n\n887\n00:45:31,763 --> 00:45:34,030\nbecause it gives me this [LAUGH] generic name,\n\n888\n00:45:34,032 --> 00:45:37,366\nViewController, which we talked about last week, not so\n\n889\n00:45:37,368 --> 00:45:40,603\ngood, okay? Well, I'm, I don't want that. I'm gonna,\n\n890\n00:45:40,605 --> 00:45:43,206\nI want mine to be called FaceViewController,\n\n891\n00:45:43,208 --> 00:45:44,807\nbecause it's gonna show a face.\n\n892\n00:45:44,809 --> 00:45:46,943\nSo I could just say FaceViewController, and\n\n893\n00:45:46,945 --> 00:45:50,113\nI might think, okay, I'm good to go, FaceViewController. But\n\n894\n00:45:50,115 --> 00:45:52,982\nof course, that's not good enough. First of all,\n\n895\n00:45:52,984 --> 00:45:55,885\nI probably wanna rename the file, because in Swift,\n\n896\n00:45:55,887 --> 00:45:59,455\ngenerally the name of the file should be the name of the most\n\n897\n00:45:59,457 --> 00:46:03,192\nimportant class in the file, okay? Cuz that's what people\n\n898\n00:46:03,194 --> 00:46:04,827\nare gonna expect when they see the name of the file.\n\n899\n00:46:04,829 --> 00:46:06,596\nSo that's one thing. But that's not enough,\n\n900\n00:46:06,598 --> 00:46:10,166\neither. Cuz if I go back here to my storyboard,\n\n901\n00:46:10,168 --> 00:46:12,635\nand I look at my view controller right here.\n\n902\n00:46:12,637 --> 00:46:15,805\nI can actually look at this inspector up here. If you pick\n\n903\n00:46:15,807 --> 00:46:18,841\nup your view controller and look at his one right here.\n\n904\n00:46:18,843 --> 00:46:20,409\nIt's called the identity inspector.\n\n905\n00:46:20,411 --> 00:46:23,813\nI can actually see what the story board thinks the class\n\n906\n00:46:23,815 --> 00:46:27,216\nof this view controller is. And you can see that it thinks\n\n907\n00:46:27,218 --> 00:46:31,554\nit's view controller, okay. Generic view controller. And\n\n908\n00:46:31,556 --> 00:46:34,357\nof course I renamed so that's not what I want. So I can\n\n909\n00:46:34,359 --> 00:46:36,959\nchange it though, just by clicking here and changing it\n\n910\n00:46:36,961 --> 00:46:41,397\nto face view controller, okay. So in your assignment to,\n\n911\n00:46:41,399 --> 00:46:42,231\nit's not a required task, but\n\n912\n00:46:42,233 --> 00:46:46,469\nI strongly recommend that you rename your view controller.\n\n913\n00:46:46,471 --> 00:46:48,971\nAssignment two is about the calculator. Rename it from\n\n914\n00:46:48,973 --> 00:46:52,441\ncalc, from View Controller to be Calculator View Controller.\n\n915\n00:46:52,443 --> 00:46:54,143\nYou will definitely want that for assignment three.\n\n916\n00:46:54,145 --> 00:46:57,113\nBut I recommend doing it in assignment two. Okay, just so\n\n917\n00:46:57,115 --> 00:46:58,748\nyou, this is all you have to do, what I just did.\n\n918\n00:46:58,750 --> 00:47:00,750\nIt's not that hard, but it's good practice.\n\n919\n00:47:00,752 --> 00:47:03,753\nOkay, it'll help you understand that the storyboard\n\n920\n00:47:03,755 --> 00:47:07,423\nhas classes of things in its identity inspect, inspector\n\n921\n00:47:07,425 --> 00:47:11,694\nthat have to match up with what's in your code, okay?\n\n922\n00:47:11,696 --> 00:47:12,829\nAll right so\n\n923\n00:47:12,831 --> 00:47:17,500\nwe got that renamed where we want to draw our face okay so\n\n924\n00:47:17,502 --> 00:47:20,536\nwe need a face view a UI view a subclass of UI view it\n\n925\n00:47:20,538 --> 00:47:23,506\ndoes that. So let's create a subclass of UI view. Anytime\n\n926\n00:47:23,508 --> 00:47:26,475\nwe're adding something to our project we go file new and\n\n927\n00:47:26,477 --> 00:47:30,046\nI'm gonna create a new file right here and this file's\n\n928\n00:47:30,048 --> 00:47:33,583\ngonna be iOS source. It's gonna be a Cocoa Touch Class,\n\n929\n00:47:33,585 --> 00:47:36,419\ncuz it's gonna be a subclass of UIView. Any time we create\n\n930\n00:47:36,421 --> 00:47:39,589\na subclass of something in Cocoa Touch like UIView or\n\n931\n00:47:39,591 --> 00:47:42,158\nUIViewController or whatever, this is what we want.\n\n932\n00:47:42,160 --> 00:47:45,061\nSo I'm gonna double-click that. Here it says subclass\n\n933\n00:47:45,063 --> 00:47:48,631\nof, it's already on UIView. But you can create subclasses\n\n934\n00:47:48,633 --> 00:47:51,934\nof NSObject, especially if you're doing Objective-C.\n\n935\n00:47:51,936 --> 00:47:54,337\nOr UIView controller or any of many, many,\n\n936\n00:47:54,339 --> 00:47:58,107\nmany, many other classes. But we're gonna do UIView here.\n\n937\n00:47:58,109 --> 00:48:00,376\nI'm gonna call my view Faceview.\n\n938\n00:48:00,378 --> 00:48:03,246\nOkay, cuz that's what it is, a view that draws a face.\n\n939\n00:48:03,248 --> 00:48:05,648\nOkay, I'm gonna put it in the same group right here,\n\n940\n00:48:05,650 --> 00:48:09,318\nthis group that has all this stuff in it. Okay, same thing.\n\n941\n00:48:09,320 --> 00:48:12,054\nWe'll put it in there. And here it is.\n\n942\n00:48:12,056 --> 00:48:13,990\nNotice that it gave me a drawRect.\n\n943\n00:48:13,992 --> 00:48:17,226\nLook at that, drawRect. But it's commented out.\n\n944\n00:48:17,228 --> 00:48:19,262\nNow why did it give me a drawRect commented out?\n\n945\n00:48:19,264 --> 00:48:22,632\nAnd this is because unless your drawRect actually does\n\n946\n00:48:22,634 --> 00:48:25,201\nsomething, do not have a drawRect, because if\n\n947\n00:48:25,203 --> 00:48:28,371\nthe systems sees that you have a UIB that has a drawRect,\n\n948\n00:48:28,373 --> 00:48:31,908\nit's gonna think that it needs to get you to draw itself all\n\n949\n00:48:31,910 --> 00:48:34,877\nthe time. But if you don't actually draw anything,\n\n950\n00:48:34,879 --> 00:48:35,645\nmaybe you just have subviews,\n\n951\n00:48:35,647 --> 00:48:38,214\nokay, you don't draw anything, then you don't want the system\n\n952\n00:48:38,216 --> 00:48:41,784\nwasting its time trying to get you to draw yourself, okay?\n\n953\n00:48:41,786 --> 00:48:46,255\nBut of course, we are going to draw, so I'm gonna uncomment\n\n954\n00:48:46,257 --> 00:48:50,326\nout my drawRect here and start drawing my face.\n\n955\n00:48:50,328 --> 00:48:56,866\nNow my face is gonna look like we drew before here, okay?\n\n956\n00:48:56,868 --> 00:49:00,803\nIt's gonna be a rectangle and here's my bounds, let's say,\n\n957\n00:49:00,805 --> 00:49:03,606\nthat I have to draw in. I'm gonna draw my face in\n\n958\n00:49:03,608 --> 00:49:07,176\nthe middle, okay? It's gonna be the smaller of the width or\n\n959\n00:49:07,178 --> 00:49:10,479\nthe height so the, its face fits completely, right? And\n\n960\n00:49:10,481 --> 00:49:13,082\nthen I'm just gonna have a couple of round eyes and\n\n961\n00:49:13,084 --> 00:49:15,117\na smiley face. And we're gonna make it so\n\n962\n00:49:15,119 --> 00:49:16,886\nthis smile can be a smile or a frown or\n\n963\n00:49:16,888 --> 00:49:18,521\nit's movable basically, changeable.\n\n964\n00:49:18,523 --> 00:49:21,123\nOkay, so that's, that's what we're gonna build right here,\n\n965\n00:49:21,125 --> 00:49:24,293\nokay? So since I want this thing to be in the center, and\n\n966\n00:49:24,295 --> 00:49:27,630\nI want it to be the smaller of the width or the height so\n\n967\n00:49:27,632 --> 00:49:30,967\nit fits, I'm gonna create two vars to start off for\n\n968\n00:49:30,969 --> 00:49:36,105\nthe center and this radius of this thing. So let's do that.\n\n969\n00:49:36,708 --> 00:49:39,875\nOkay, so let's, first let's do the radius here, so\n\n970\n00:49:39,877 --> 00:49:41,877\nI'm gonna say var. I'm inside my drawRect here,\n\n971\n00:49:41,879 --> 00:49:45,314\njust implement this. I'm gonna call this the skullRadius\n\n972\n00:49:45,316 --> 00:49:49,652\ncuz this is the radius of my face's skull, okay? And\n\n973\n00:49:49,654 --> 00:49:55,825\nI'm gonna make that equal to the minimum of the width or\n\n974\n00:49:55,827 --> 00:49:59,395\nthe height of my view. Now what is the width or\n\n975\n00:49:59,397 --> 00:50:02,565\nthe height of my view? Now there's different variables we\n\n976\n00:50:02,567 --> 00:50:05,735\ncould look at here. We could look at this rect, okay?\n\n977\n00:50:05,737 --> 00:50:10,339\nI could say let width equal rect.size.width.\n\n978\n00:50:10,341 --> 00:50:14,510\nWould that be right? No, that would not be right,\n\n979\n00:50:14,512 --> 00:50:16,879\nbecause this rect is just an optimization\n\n980\n00:50:16,881 --> 00:50:19,615\nthat says what part of the view to draw, okay?\n\n981\n00:50:19,617 --> 00:50:23,019\nWell, my face needs to kind of draw in the whole view or\n\n982\n00:50:23,021 --> 00:50:25,321\nwon't be the right size, okay, it would be all small.\n\n983\n00:50:25,323 --> 00:50:29,658\nSo this is not the right one. I could say frame.size.width.\n\n984\n00:50:29,660 --> 00:50:34,063\nWould that be right? No or yes?\n\n985\n00:50:34,065 --> 00:50:38,167\nNo, I see a couple of shaking heads no. The answer is no.\n\n986\n00:50:38,169 --> 00:50:41,137\nOkay, frame is the rectangle that contains me in my\n\n987\n00:50:41,139 --> 00:50:44,006\nsuperviews coordinates. I'm drawing myself,\n\n988\n00:50:44,008 --> 00:50:45,741\nI can't draw in my superviews coordinates.\n\n989\n00:50:45,743 --> 00:50:49,045\nI need to draw in my coordinate system, okay? So\n\n990\n00:50:49,047 --> 00:50:52,982\nwhat we want here is bounds, okay. Bounds is the rectangle\n\n991\n00:50:52,984 --> 00:50:56,185\nthat I'm drawing in in my coordinate system here,\n\n992\n00:50:56,187 --> 00:51:00,356\nokay? Same thing height, bounds.size.height, okay?\n\n993\n00:51:00,358 --> 00:51:01,824\nAnd also I want my skull's radius,\n\n994\n00:51:01,826 --> 00:51:06,429\nI'm not doing the diameter. I want it to be divided by 2.\n\n995\n00:51:06,431 --> 00:51:08,798\nNow it's kinda silly to do these local variables.\n\n996\n00:51:08,800 --> 00:51:11,400\nProbably a lot better just to take this and copy and\n\n997\n00:51:11,402 --> 00:51:16,005\npaste these right in here like this. Okay,\n\n998\n00:51:16,007 --> 00:51:19,141\nlet's make some more room here. All right, so\n\n999\n00:51:19,143 --> 00:51:22,211\nI've got the radius of my skull. That's good. What's\n\n1000\n00:51:22,213 --> 00:51:25,281\nthe other thing I needed, is the center of my skull, so\n\n1001\n00:51:25,283 --> 00:51:29,518\nI'm gonna call that skullCenter. Okay, and\n这里我就命名为 skullCenter. \n\n1002\n00:51:29,520 --> 00:51:34,690\nwhat is the center? Well, can I say center? Is that good?\n那么这里的中心指的是什么？ 我这里可以直接写 center 吗？ \n\n1003\n00:51:34,692 --> 00:51:38,427\nNo, center is my center in my superviews coordinates.\n当然不可以，这里的 center 指的是父视图坐标系的中心。\n\n1004\n00:51:38,429 --> 00:51:41,831\nThat's where I am, okay, not the center. Now here's two\n而这个真是我所在的地方， 所以不能用 center 。  \n\n1005\n00:51:41,833 --> 00:51:45,101\ninteresting ways to get the actual center of my bounds.\n这里有两种方式获得当前坐标系的 center 。\n\n1006\n00:51:45,103 --> 00:51:49,205\nOkay, one is, believe it or not, is I can say,\n信不信由你， 其中一种是通过 convertPoint 方法获得。\n\n1007\n00:51:49,207 --> 00:51:53,909\nconvertPoint. This is a UIView method, convertPoint,\n这是一个 UIView 的方法, convertPoint,\n\n1008\n00:51:53,911 --> 00:51:57,746\nconvert center, this point's center, from view,\n将 center 从父视图的坐标系转换获得。\n\n1009\n00:51:57,748 --> 00:52:01,183\nmy superview, okay? [LAUGH] So I would be converting that\n这样我就可以通过 center 来获得\n\n1010\n00:52:01,185 --> 00:52:03,953\npoint, the center, from my superviews coordinates to my\n从父视图的坐标系转换到当前视图的坐标系的坐标。\n\n1011\n00:52:03,955 --> 00:52:06,622\ncoordinate system. This would be right. This would work,\n这样做就能获得正确的结果， 这样做就能生效，\n\n1012\n00:52:06,624 --> 00:52:09,825\ncuz now I'm in my coordinates system. Same point, but\n因为现在是在当前视图的坐标系。 同一个点， 但是\n\n1013\n00:52:09,827 --> 00:52:10,826\nit's in my coordinate system.\n是在当前视图的坐标系中的表示。\n\n1014\n00:52:10,828 --> 00:52:12,294\nSo that's one way we could do it.\n这就是其中一种方法。\n\n1015\n00:52:12,296 --> 00:52:14,029\nWe probably wouldn't do it that way. Instead,\n我们通常不使用这种方法。 取而代之的是，\n\n1016\n00:52:14,031 --> 00:52:18,334\nwe'd probably use some of the vars that are on CGRect. For\n我们经常用 CGRect 中的属性来获得。 \n\n1017\n00:52:18,336 --> 00:52:21,570\nexample, I'd probably say something like\n例如， 我们经常说脸的骨架的中心\n\n1018\n00:52:21,572 --> 00:52:26,442\nthe skull center is a CGPoint whose x, okay, x and\n是一个 CGPoint， 一个通过 x 和 y组成的 CGPoint 。\n\n1019\n00:52:26,444 --> 00:52:30,913\ny of CGPoint, right, whose x is probably my bounds.midX and\n在这里我们的 x 应该是 bounds.midX ，\n\n1020\n00:52:30,915 --> 00:52:36,986\nmy y is my bounds.midY. Okay, so midX is just a property\ny 应该是 bounds.midY 。 这里的 midX 只是一个\n\n1021\n00:52:36,988 --> 00:52:40,890\non CGRect which tells you the x that's midway across this,\nCGRect 的属性， 这个属性可以告诉我们水平方向行的中点，\n\n1022\n00:52:40,892 --> 00:52:45,261\nthe rectangle. Same thing midY. Okay, so\n当然这里指的是这个矩形中， 同理可以说明 midY 。\n\n1023\n00:52:45,263 --> 00:52:48,264\nI've got my radius and my center. I put these as vars,\n这样我就获得骨架的半径。 我这里通过变量进行存储，\n\n1024\n00:52:48,266 --> 00:52:50,533\nbut really they probably wanna be lets,\n当时它们更应该用常亮进行存储。\n\n1025\n00:52:50,535 --> 00:52:51,567\nokay, cuz I'm, I've calculated,\n毕竟这个是通过我们计算获得的，\n\n1026\n00:52:51,569 --> 00:52:54,904\nI'm not gonna change them after this. All right, so\n并且在之后的代码中也不会修改。 这样我就有了\n\n1027\n00:52:54,906 --> 00:52:59,475\nnow that I have this, I need to create a Bezier path for\n一些信息， 我需要创建一个 Bezier Path 来绘制出骨架， \n\n1028\n00:52:59,477 --> 00:53:02,578\nmy skull, for the circle here. So I'm just going to\n这里通过一个圆来表示， 这里我通过\n\n1029\n00:53:02,580 --> 00:53:05,681\ncreate a local variable here called skull. It's going to be\n一个名为 skull 的局部变量进行存储。 它的类型\n\n1030\n00:53:05,683 --> 00:53:10,286\nof type UIBezierPath, and so UIBezierPath. And\n应该是 UIBezierPath 。\n\n1031\n00:53:10,288 --> 00:53:13,923\nyou can see UIBezierPath has a bunch of initializers here.\n你可以看到 UIbezierPath 有非常多的初始化的函数。\n\n1032\n00:53:13,925 --> 00:53:16,859\nI could use this one, ovalInRect, because a circle\n当然我这里可以使用 ovalInRect 这个函数， 因为\n\n1033\n00:53:16,861 --> 00:53:20,329\nis an oval. But I'm gonna use this one arcCenter because\n圆也是一个椭圆。 但是我这里更愿意用另一个名为 arcCenter 的初始化函数，\n\n1034\n00:53:20,331 --> 00:53:25,201\nI have the radius in center. I don't I don't wanna create\n因为我这里有半径和中心点。而我这里也不需要再\n\n1035\n00:53:25,203 --> 00:53:26,335\nan oval in my entire bound.\n我的整个矩形中画一个椭圆。\n\n1036\n00:53:26,337 --> 00:53:29,505\nI'd have to create just some kinda rectangle that gets my,\n我这里希望根据矩形绘制出我的脸型的轮廓。\n\n1037\n00:53:29,507 --> 00:53:32,441\nonly my skull. So I'm gonna use this one, arcCenter, which\n所以我这里用 arcCenter 这个初始化的函数， \n\n1038\n00:53:32,443 --> 00:53:35,477\ntakes a radius and a center, which I have right here.\n而这个函数需要半径和中心点作为参数， 而这些参数我已经在上面获得了。\n\n1039\n00:53:35,479 --> 00:53:38,547\nAnd then a start angle and an end angle as it goes around\n另外还需要一个起始角度和结束角度来绘制这个弧度，\n\n1040\n00:53:38,549 --> 00:53:42,151\nthe arc, and either clockwise or counterclockwise. Okay, so\n并且同时还需要配置是通过顺时针还是逆时针来绘制。\n\n1041\n00:53:42,153 --> 00:53:46,422\nlet's do that. So what is the center of my arc? skullCenter,\n那么我们开始绘制吧。 那么这个弧线的中心点是什么？ 当然是 skullCenter ,\n\n1042\n00:53:46,424 --> 00:53:49,625\nokay, that's the center of this arc I'm gonna draw that's\n这是我们即将绘制的轮廓弧线的中心点，\n\n1043\n00:53:49,627 --> 00:53:53,395\ngonna be my skull. The radius is the skullRadius, right,\n而这里的半径应该是 skullRadius, \n\n1044\n00:53:53,397 --> 00:53:55,664\nthat's the radius I'm going around.\n在上面获得的半径。\n\n1045\n00:53:55,666 --> 00:53:59,802\nNow startAngle to endAngle, that's in radians.\n接下来是弧线的其实角度和结束角度。\n\n1046\n00:53:59,804 --> 00:54:00,903\nDoes everyone know what radians?\n有人知道关于弧度的内容吗？\n\n1047\n00:54:00,905 --> 00:54:04,707\nRaise your hands if you know what radians are. Okay,\n如果知道弧度的请举手。\n\n1048\n00:54:04,709 --> 00:54:06,342\nalmost everybody, good. So radians,\n很好，大部分的人都知道。 那么弧度是从 0 到 2π\n\n1049\n00:54:06,344 --> 00:54:09,845\n0 to 2pi radians to go all the way around the circle.\n将会获得一个完整的圆形。\n\n1050\n00:54:09,847 --> 00:54:14,350\nSo I'm gonna go from 0 to 2*_PI, okay.\n那么这里我就知道为从 0 到 2π。\n\n1051\n00:54:14,352 --> 00:54:16,852\nAnd then I can either go clockwise around or I can go\n这里我可以选择顺时针也可以选择逆时针。\n\n1052\n00:54:16,854 --> 00:54:19,688\ncounterclockwise. In this case I'm going all the way around,\n因为在这里我需要绘制出完整的圆形，\n\n1053\n00:54:19,690 --> 00:54:23,058\nso it doesn't matter. So I'll just go counterclockwise,\n所以选择哪一个都没问题。 这里我就先选择逆时针。\n\n1054\n00:54:23,060 --> 00:54:27,930\nwhatever, okay? So you can see how this has drawn an arc, so\n这样你就可以看到如何绘制一个弧线了。\n\n1055\n00:54:27,932 --> 00:54:29,798\nI've create a Bezier path which the path\n\n1056\n00:54:29,800 --> 00:54:33,402\nis around a circle, okay? Now well, I have an error here?\n\n1057\n00:54:33,404 --> 00:54:35,137\nWhat's, what do you think this error right here is?\n\n1058\n00:54:35,139 --> 00:54:38,774\nLook at that. Cannot convert value of type 'Double'\n\n1059\n00:54:38,776 --> 00:54:40,776\nto expected argument type 'CGFloat'.\n\n1060\n00:54:40,778 --> 00:54:43,812\nIt's pointing to this little thing right here, this _PI,\n\n1061\n00:54:43,814 --> 00:54:45,648\nokay? Well, this is what I was telling you about before.\n\n1062\n00:54:45,650 --> 00:54:52,621\nAll these drawing things are in CGFloat. What type is this?\n\n1063\n00:54:52,623 --> 00:54:55,057\nWhat type is that expression? >> Double?\n\n1064\n00:54:55,059 --> 00:54:56,058\n>> It's a double, right. Okay,\n\n1065\n00:54:56,060 --> 00:54:58,861\nso we can't use a double there. It has to be a CGFloat.\n\n1066\n00:54:58,863 --> 00:55:02,564\nSo we have to convert it to a CGFloat by doing this,\n\n1067\n00:55:02,566 --> 00:55:06,969\nokay, CGFloat. Now how come this is not complaining?\n\n1068\n00:55:06,971 --> 00:55:10,706\nOkay, I told you last time that if you see a literal 0.0,\n\n1069\n00:55:10,708 --> 00:55:15,177\nit thinks that's a double. Didn't I tell you that? Well,\n\n1070\n00:55:15,179 --> 00:55:18,647\nI lied. Because when it sees 0.0, it can convert it to\n\n1071\n00:55:18,649 --> 00:55:22,017\na number of different types, since it's a literal.\n\n1072\n00:55:22,019 --> 00:55:25,220\nOkay, Swift can only do this automatic typing version for\n\n1073\n00:55:25,222 --> 00:55:27,990\nliterals, okay? So 0.0 is a literal, so\n\n1074\n00:55:27,992 --> 00:55:29,725\nit can convert to a number of different types.\n\n1075\n00:55:29,727 --> 00:55:34,596\nDouble, Float, CGFloat. It knows how to do that, okay?\n\n1076\n00:55:34,598 --> 00:55:36,732\nSo why does it pick CGFloat here?\n\n1077\n00:55:36,734 --> 00:55:41,036\nBecause it knows this method takes a CGFloat. And when\n\n1078\n00:55:41,038 --> 00:55:44,073\nit sees a literal and it sees CGFloat is the argument type,\n\n1079\n00:55:44,075 --> 00:55:46,408\nit tries to convert it to a CGFloat if it can.\n\n1080\n00:55:46,410 --> 00:55:52,081\nWhich it can, okay? Everybody got that? All right,\n\n1081\n00:55:52,083 --> 00:55:54,717\nso I have this skull. It's of type UIBezierPath.\n\n1082\n00:55:54,719 --> 00:55:56,919\nI can set attributes on this skull now,\n\n1083\n00:55:56,921 --> 00:56:00,723\nlike maybe it's Line with maybe we'll make it 5.0 point\n\n1084\n00:56:00,725 --> 00:56:05,027\nthat's 5.0 points wide. Right? If I wanna set a color,\n\n1085\n00:56:05,029 --> 00:56:07,930\nI don't say skull set color something like that.\n\n1086\n00:56:07,932 --> 00:56:12,334\nI create the color I want. So let's make our skull be blue\n\n1087\n00:56:12,336 --> 00:56:15,070\nokay? So blueColor, which is the type method on UIColor.\n\n1088\n00:56:15,072 --> 00:56:19,908\nAnd I'm gonna say set. There's setFill, there's setStroke,\n\n1089\n00:56:19,910 --> 00:56:23,579\nand there's also set, which sets both the fill and\n\n1090\n00:56:23,581 --> 00:56:26,448\nthe stroke. Okay? Now,\n\n1091\n00:56:26,450 --> 00:56:30,486\nto get it to draw, I just need to say skull.stroke, okay,\n\n1092\n00:56:30,488 --> 00:56:35,023\nand that's going to draw along this Arc, then I drew with\n\n1093\n00:56:35,025 --> 00:56:39,361\nthis line width and with the color that set. Okay, that's\n\n1094\n00:56:39,363 --> 00:56:44,032\nall that's necessary to draw the skull of our face here.\n\n1095\n00:56:44,034 --> 00:56:46,335\nSo, now we have this nice UIView, this custom UIView.\n\n1096\n00:56:46,337 --> 00:56:49,938\nIt draws the skull of a face anyway. How do we get it into\n\n1097\n00:56:49,940 --> 00:56:53,642\nour UI? So if we go back to out storyboard over here.\n\n1098\n00:56:53,644 --> 00:56:56,011\nRight now it's blank. There's nothing in here.\n\n1099\n00:56:56,013 --> 00:56:58,380\nThere's only this background view.\n\n1100\n00:56:58,382 --> 00:57:01,250\nAnd I promised you that there was a Var in\n\n1101\n00:57:01,252 --> 00:57:05,087\nthe Faceview controller that pointed to this view.\n\n1102\n00:57:05,089 --> 00:57:07,990\nAnd I'm going to show it to you by right clicking on this.\n\n1103\n00:57:07,992 --> 00:57:10,993\nYou see it right here? When I mouse over it you see how it's\n\n1104\n00:57:10,995 --> 00:57:15,998\nhighlighting it? This is a outlet called View, just like\n\n1105\n00:57:16,000 --> 00:57:17,833\nyou have an outlet on your display on your calculator,\n\n1106\n00:57:17,835 --> 00:57:22,671\nthis one is an outlet or var, which is a type UI view and\n\n1107\n00:57:22,673 --> 00:57:24,740\nit's connected to this thing right here so\n\n1108\n00:57:24,742 --> 00:57:25,674\nit's automatically connected up for\n\n1109\n00:57:25,676 --> 00:57:28,844\nyou., you don't even need to control, drag it or anything,\n\n1110\n00:57:28,846 --> 00:57:31,513\nokay? But we're not gonna be adding our viewing code, so\n\n1111\n00:57:31,515 --> 00:57:32,614\nwe don't really need that var,\n\n1112\n00:57:32,616 --> 00:57:33,816\nI just wanted to show you it was there.\n\n1113\n00:57:33,818 --> 00:57:36,552\nI'm going to add my view by dragging it out. And if I\n\n1114\n00:57:36,554 --> 00:57:39,388\ngo down here to my palette, obviously I'm not gonna find\n\n1115\n00:57:39,390 --> 00:57:42,291\nface view in here. Okay. IOS didn't know\n\n1116\n00:57:42,293 --> 00:57:45,828\nabout face view when it built Xcode. But I can go down to\n\n1117\n00:57:45,830 --> 00:57:49,031\nthe very bottom here and grab one of these. Okay?\n\n1118\n00:57:49,033 --> 00:57:53,101\nThis is a generic UI view Okay not a sub class of UI view\n\n1119\n00:57:53,103 --> 00:57:57,039\njust the UI view. So I'm gonna drag it out and put it here.\n\n1120\n00:57:57,041 --> 00:57:59,641\nNow I'm gonna do a cool thing okay I'm trying to show you\n\n1121\n00:57:59,643 --> 00:58:02,744\nbit by bit a little more of this constraints thing so\n\n1122\n00:58:02,746 --> 00:58:05,948\nI'm gonna take this thing I'm gonna us the blue lines okay.\n\n1123\n00:58:05,950 --> 00:58:09,184\nI'm gonna put it all the way up in the corner here and\n\n1124\n00:58:09,186 --> 00:58:12,020\nthen I'm gonna put the other edge all the way down in\n\n1125\n00:58:12,022 --> 00:58:14,723\nthe corner down here and I'm using blue lines you see blue\n\n1126\n00:58:14,725 --> 00:58:18,961\nlines? Appearing. Those blue lines are making this thing\n\n1127\n00:58:18,963 --> 00:58:21,930\nattach to well known point. In this case, the edges.\n\n1128\n00:58:21,932 --> 00:58:25,734\nSo I want my face view to fill the entire view, okay?\n\n1129\n00:58:25,736 --> 00:58:29,938\nThe entire view controller's view. All right, but just\n\n1130\n00:58:29,940 --> 00:58:32,841\ndoing the blue lines isn't enough as we learned, okay?\n\n1131\n00:58:32,843 --> 00:58:35,477\nThat's just kind of telling the system what you intend.\n\n1132\n00:58:35,479 --> 00:58:38,580\nTo make it do it you actually have to have constraints like\n\n1133\n00:58:38,582 --> 00:58:39,715\nthose things we control drag.\n\n1134\n00:58:39,717 --> 00:58:42,451\nSo I could try and control drag to an edge, control down\n\n1135\n00:58:42,453 --> 00:58:45,921\nto this edge, all that, but there's an easier way. If you\n\n1136\n00:58:45,923 --> 00:58:49,791\ndid all blue lines and that's all you needed, you could\n\n1137\n00:58:49,793 --> 00:58:53,161\ngo down here to the same place where you update frames and\n\n1138\n00:58:53,163 --> 00:58:57,933\ninstead do Reset to Suggested Constraints. And that will\n\n1139\n00:58:57,935 --> 00:59:02,504\nuse the blue lines to put some suggestive constraints. Now,\n\n1140\n00:59:02,506 --> 00:59:05,641\nlet's see what it did. You can see all the constraints on\n\n1141\n00:59:05,643 --> 00:59:08,210\na view by going over to the inspector and\n\n1142\n00:59:08,212 --> 00:59:12,347\ngoing to this tab right here, which is the size inspector.\n\n1143\n00:59:12,349 --> 00:59:14,850\nAnd if you look in the size inspector, down toward\n\n1144\n00:59:14,852 --> 00:59:18,954\nthe bottom, you can see constraints. You see them? And\n\n1145\n00:59:18,956 --> 00:59:20,589\nthis is showing me all the constraints and\n\n1146\n00:59:20,591 --> 00:59:23,825\nit put one trailing, that looks good. Leading yeah,\n\n1147\n00:59:23,827 --> 00:59:28,564\ntop nice, bottom perfect. So it put exactly the constraints\n\n1148\n00:59:28,566 --> 00:59:33,168\nI want because it followed the blue lines okay so now I have\n\n1149\n00:59:33,170 --> 00:59:36,071\nthis view constrained to stick to the edges.\n\n1150\n00:59:36,073 --> 00:59:38,273\nPerfect, because then when I go landscape or\n\n1151\n00:59:38,275 --> 00:59:42,344\nportrait my bounds are constantly being resized.\n\n1152\n00:59:42,346 --> 00:59:45,314\nTo fit the new shape. Okay? Now\n\n1153\n00:59:45,316 --> 00:59:48,951\nthe other thing I need to do is this is a generic UI view.\n\n1154\n00:59:48,953 --> 00:59:49,384\nIf I ran right now,\n\n1155\n00:59:49,386 --> 00:59:52,087\nit would come up blank because it has no draw rects.\n\n1156\n00:59:52,089 --> 00:59:55,691\nOkay? I did that nice face view draw rect but this is not\n\n1157\n00:59:55,693 --> 00:59:58,293\na face view. So how do I set this to be a face view?\n\n1158\n00:59:58,295 --> 01:00:02,331\nExactly the same way that I set this view controller to be\n\n1159\n01:00:02,333 --> 01:00:06,201\na face view controller. I go to the identity inspector and\n\n1160\n01:00:06,203 --> 01:00:09,504\ninstead of, so here is when I did the controller, I click on\n\n1161\n01:00:09,506 --> 01:00:13,041\nthis view and instead of it being a generic UI view,\n\n1162\n01:00:13,043 --> 01:00:17,279\nyou see, I change it to be face view.\n\n1163\n01:00:17,281 --> 01:00:21,183\nGot it? Okay. So let's run, okay it should work,\n\n1164\n01:00:21,185 --> 01:00:23,986\nlet's run on Iphone six, for example. And\n\n1165\n01:00:23,988 --> 01:00:29,491\nhopefully, we'll get the skull of our face to draw.\n\n1166\n01:00:35,532 --> 01:00:36,632\nPerfect it worked okay.\n\n1167\n01:00:36,634 --> 01:00:39,735\nSo here's our skull it picked the smaller of the width or\n\n1168\n01:00:39,737 --> 01:00:40,669\nthe height they went to smaller so\n\n1169\n01:00:40,671 --> 01:00:43,805\npicked is drawing the whole side, if I rotate? Uh-oh.\n\n1170\n01:00:43,807 --> 01:00:47,976\nStretch-a-roo. Okay? So that's this problem with the content\n\n1171\n01:00:47,978 --> 01:00:52,447\nmode of our face view is set to be scaled to fill. Okay, so\n\n1172\n01:00:52,449 --> 01:00:53,515\nit's scaling our thing.\n\n1173\n01:00:53,517 --> 01:00:56,318\nSo we don't want that. So let's go back here and\n\n1174\n01:00:56,320 --> 01:00:59,588\ngo to storyboard and select out face view right here,\n\n1175\n01:00:59,590 --> 01:01:00,789\ngo to the attributes inspector.\n\n1176\n01:01:00,791 --> 01:01:04,026\nThe very first thing is the content mode. And you can see\n\n1177\n01:01:04,028 --> 01:01:07,162\nit is scale to fill, and i want it to be redraw.\n\n1178\n01:01:07,164 --> 01:01:09,998\nIn other words when my bounds change, call my draw rect.\n\n1179\n01:01:10,000 --> 01:01:18,240\nYou see that? Okay here we go,\n\n1180\n01:01:18,242 --> 01:01:22,177\nworks in landscape works in portrait. Okay,\n\n1181\n01:01:22,179 --> 01:01:25,981\nit's even switching from using the width to the height.\n\n1182\n01:01:25,983 --> 01:01:27,883\n>> Because that gets smaller.\n\n1183\n01:01:30,654 --> 01:01:31,219\n>> Okay, sound good.\n\n1184\n01:01:31,221 --> 01:01:33,455\nNow one thing that's kind of a bummer.\n\n1185\n01:01:33,457 --> 01:01:37,726\nHere in my interface builder, I don't see my face.\n\n1186\n01:01:37,728 --> 01:01:40,796\nHow come I don't see my face here? And it is possible to\n\n1187\n01:01:40,798 --> 01:01:45,267\nmake the face appear here, and we'll do that next week, okay?\n\n1188\n01:01:45,269 --> 01:01:47,402\nCuz it's nice, when you're building your storyboard,\n\n1189\n01:01:47,404 --> 01:01:51,173\nto be able to see your custom views in there. All right, so\n\n1190\n01:01:51,175 --> 01:01:53,008\nlet's go back to our face view and add some more.\n\n1191\n01:01:53,010 --> 01:01:56,945\nLet's add some eyes. We'll add some eyes to, our face,\n\n1192\n01:01:56,947 --> 01:01:59,848\nhere, and to do that, I'm gonna start having some little\n\n1193\n01:01:59,850 --> 01:02:01,650\nhelper functions here along the way.\n\n1194\n01:02:01,652 --> 01:02:06,788\nI'm gonna make it so that my eyes and\n\n1195\n01:02:06,790 --> 01:02:10,258\nthe mouth are all relative to the size of my skull,\n\n1196\n01:02:10,260 --> 01:02:11,293\nwhat ever my skull size is,\n\n1197\n01:02:11,295 --> 01:02:14,629\nI'm gonna make everything else relative to it obviously. So\n\n1198\n01:02:14,631 --> 01:02:16,665\nI'm gonna take this skull center and radius, and\n\n1199\n01:02:16,667 --> 01:02:21,169\ntake them out of drawrect and make them vars, okay.\n\n1200\n01:02:21,171 --> 01:02:24,740\nThese are gonna be vars. Now when I tried to do this, and\n\n1201\n01:02:24,742 --> 01:02:27,309\nyou'll try this in your homework I'm sure.\n\n1202\n01:02:27,311 --> 01:02:28,210\nYou're gonna get this error.\n\n1203\n01:02:28,212 --> 01:02:32,013\nIt stays instance member bounds, okay? Is,\n\n1204\n01:02:32,015 --> 01:02:34,750\ncannot be used in type face view. And you are gonna get so\n\n1205\n01:02:34,752 --> 01:02:38,587\nfrustrated, cuz you're gonna say bounds is definitely\n\n1206\n01:02:38,589 --> 01:02:39,654\nan instance member of face view,\n\n1207\n01:02:39,656 --> 01:02:43,425\nhow come I can't use it here? Okay? And the answer\n\n1208\n01:02:43,427 --> 01:02:47,529\nof why you can't use it here is because you are in\n\n1209\n01:02:47,531 --> 01:02:52,134\nthe initialization phase. You are initializing this. And\n\n1210\n01:02:52,136 --> 01:02:56,471\nduring initialization, you cannot use your class.\n\n1211\n01:02:56,473 --> 01:02:59,307\nIt's not initialized yet. So you can't call vars and\n\n1212\n01:02:59,309 --> 01:03:04,513\nmethods like bounds. Okay? Everyone understand that?\n\n1213\n01:03:04,515 --> 01:03:08,049\nSo, you will see this message I'm sure. And you will post on\n\n1214\n01:03:08,051 --> 01:03:10,352\nPL as a Piazza probably and say, what's going on? But\n\n1215\n01:03:10,354 --> 01:03:12,087\nI'm telling you right now what's going on.\n\n1216\n01:03:12,089 --> 01:03:14,055\nDuring an initialization you cannot,\n\n1217\n01:03:14,057 --> 01:03:15,157\nuntil you're fully initialized,\n\n1218\n01:03:15,159 --> 01:03:17,659\nyou can't access your own properties. So,\n\n1219\n01:03:17,661 --> 01:03:18,760\nwhat are we going to do here about this?\n\n1220\n01:03:18,762 --> 01:03:22,330\nWell, I'm just going to change this to be calculated. Okay?\n\n1221\n01:03:22,332 --> 01:03:26,201\nTo be a computed property. Okay. I'm gonna just return\n\n1222\n01:03:26,203 --> 01:03:31,072\nthis value right here. Okay. Now, two things about computer\n\n1223\n01:03:31,074 --> 01:03:35,043\nproperties. Notice that I didn't say get},\n\n1224\n01:03:35,045 --> 01:03:39,681\nIf you have a computer property that only gets,\n\n1225\n01:03:39,683 --> 01:03:42,918\nyou do not need to put together in there. Okay.\n\n1226\n01:03:42,920 --> 01:03:46,388\nAnd we never would. Look much nicer not to put it.\n\n1227\n01:03:46,390 --> 01:03:48,790\nSame thing here, this is a CGPoint.\n\n1228\n01:03:48,792 --> 01:03:54,429\nWe're going to return this. Okay,\n\n1229\n01:03:54,431 --> 01:03:59,000\nnot gonna put the get in there. All right,\n\n1230\n01:03:59,002 --> 01:04:03,605\nthat make sense? Now one other thing I wanna do is,\n\n1231\n01:04:03,607 --> 01:04:08,777\nmy skull is all the way out to the edge. I'd like my skull to\n\n1232\n01:04:08,779 --> 01:04:12,747\nbe able to be kinda scalable, to be smaller than the edge.\n\n1233\n01:04:12,749 --> 01:04:16,184\nSo I'm gonna add a public var called scale, okay,\n\n1234\n01:04:16,186 --> 01:04:18,119\nwhich is going to be a CGFloat.\n\n1235\n01:04:18,121 --> 01:04:22,123\nAnd it's going to scale my skull. And I'm just gonna do\n\n1236\n01:04:22,125 --> 01:04:24,226\nthat by here when I'm calculating the radius,\n\n1237\n01:04:24,228 --> 01:04:27,529\nI'm just gonna multiply it by my scale. And\n\n1238\n01:04:27,531 --> 01:04:28,997\nI'm gonna set it to 90% so\n\n1239\n01:04:28,999 --> 01:04:32,100\nthat my skull's kinda 90% of all the way in.\n\n1240\n01:04:32,102 --> 01:04:34,002\nNow I'm gonna use these two vars, okay,\n\n1241\n01:04:34,004 --> 01:04:37,172\nthese computed vars, in all my other calculation. Eyes and\n\n1242\n01:04:37,174 --> 01:04:39,941\nmouth, all these things, I'm gonna use the same thing. So\n\n1243\n01:04:39,943 --> 01:04:43,411\nwe'll do eyes today, and then mouth, we'll either do mouth\n\n1244\n01:04:43,413 --> 01:04:46,081\nat the start of next lecture, or maybe I'll just post,\n\n1245\n01:04:46,083 --> 01:04:49,651\nI'm gonna post this code, by the way, on Piazza afterwards.\n\n1246\n01:04:49,653 --> 01:04:51,086\nMaybe I'll just post the mouth code so\n\n1247\n01:04:51,088 --> 01:04:55,156\nyou can take a look at it. But let's do these eyes first.\n\n1248\n01:04:55,158 --> 01:04:58,193\nHow do we do the eyes? To do the eyes,\n\n1249\n01:04:58,195 --> 01:05:02,497\nI need kind of the ratio between the skull radius and\n\n1250\n01:05:02,499 --> 01:05:05,400\nthe eye size. So to make things quick, I actually am\n\n1251\n01:05:05,402 --> 01:05:08,036\ngonna type those in real fast, here they are. Okay, so\n\n1252\n01:05:08,038 --> 01:05:11,072\nhere's all the ratios from the skull's radius to the eye's\n\n1253\n01:05:11,074 --> 01:05:14,743\noffset to the eye's radius to the mouth's width, height, and\n\n1254\n01:05:14,745 --> 01:05:18,914\noffset, etc. Notice how we do constants in Swift.\n\n1255\n01:05:18,916 --> 01:05:24,552\nWe create structs and then we have type variables, static.\n\n1256\n01:05:24,554 --> 01:05:27,956\nType variables, okay, which are lets. They're typed like\n\n1257\n01:05:27,958 --> 01:05:33,328\nthis too. That has the value, okay? So this is how we do it.\n\n1258\n01:05:33,330 --> 01:05:34,663\nNotice these are capitalized and\n\n1259\n01:05:34,665 --> 01:05:37,399\nof course as the name of a type we always capitalize\n\n1260\n01:05:37,401 --> 01:05:39,334\nthe names of types. Don't forget that.\n\n1261\n01:05:39,336 --> 01:05:42,103\nOkay, some of you don't like to do that. Please do it.\n\n1262\n01:05:42,105 --> 01:05:44,606\nIn Swift we capitalize all type names. And\n\n1263\n01:05:44,608 --> 01:05:48,443\nwe also capitalize these, okay, these static things that\n\n1264\n01:05:48,445 --> 01:05:50,612\nare basically constants in this struct.\n\n1265\n01:05:50,614 --> 01:05:53,348\nAnd I'll show you, we're gonna access these by saying Ratios\n\n1266\n01:05:53,350 --> 01:05:56,718\ndot this, okay, cuz this is the name of the type.\n\n1267\n01:05:56,720 --> 01:05:59,821\nThis is the, the value in it. So I'll show you that when we\n\n1268\n01:05:59,823 --> 01:06:03,591\nstart using these. So how am I gonna do this?\n\n1269\n01:06:03,593 --> 01:06:06,494\nHow am I gonna make my eye here? I'm gonna create a new\n\n1270\n01:06:06,496 --> 01:06:09,965\nmethod here. First of all, let me create a little type here,\n\n1271\n01:06:09,967 --> 01:06:13,068\nwhich is an enum. I'm gonna call it eye. It's gonna have\n\n1272\n01:06:13,070 --> 01:06:18,139\nleft eye and right eye. That's just so I can talk about my\n\n1273\n01:06:18,141 --> 01:06:23,278\neyes in my API. And then I'm gonna have a func,\n\n1274\n01:06:23,280 --> 01:06:28,883\nwhich I'm gonna call pathForCircleCenteredAtPoint,\n\n1275\n01:06:28,885 --> 01:06:33,621\nokay? It's going to take a midpoint, which is a CGPoint.\n\n1276\n01:06:33,623 --> 01:06:38,293\nAnd I'm gonna have withRadius, which is gonna be a CGFloat.\n\n1277\n01:06:38,295 --> 01:06:42,831\nAnd it's gonna return a UIBezierPath. So\n\n1278\n01:06:42,833 --> 01:06:44,199\nthis is gonna be a utility function,\n\n1279\n01:06:44,201 --> 01:06:47,936\nokay? It's private actually, make sure we get this private.\n\n1280\n01:06:47,938 --> 01:06:50,238\nAnd this is private also.\n\n1281\n01:06:50,240 --> 01:06:53,641\nOkay, these two are actually private. I'm gonna try and\n\n1282\n01:06:53,643 --> 01:06:57,946\nget in the habit of actually putting my privates in here so\n\n1283\n01:06:57,948 --> 01:07:00,382\nthat we get the, our things proper.\n\n1284\n01:07:00,384 --> 01:07:05,120\nThis is properly public, okay? So this function is just going\n\n1285\n01:07:05,122 --> 01:07:08,690\nto take a center point and a radius and give us a Bezier\n\n1286\n01:07:08,692 --> 01:07:10,859\npath, exactly the same thing we're doing here. So\n\n1287\n01:07:10,861 --> 01:07:14,362\nI'm actually even just gonna copy this, cut it actually,\n\n1288\n01:07:14,364 --> 01:07:19,467\nand put it here. Okay, so we got that.\n\n1289\n01:07:19,469 --> 01:07:20,935\nAnd the center is not the skullCenter,\n\n1290\n01:07:20,937 --> 01:07:24,506\nit's the midPoint. And the radius is not the skullRadius,\n\n1291\n01:07:24,508 --> 01:07:28,076\nit's this withRadius. Now let's just kind of point out\n\n1292\n01:07:28,078 --> 01:07:31,379\nthis weirdness of having something that reads nice when\n\n1293\n01:07:31,381 --> 01:07:35,116\nyou call it, because when I call this down here I'm gonna\n\n1294\n01:07:35,118 --> 01:07:37,619\nsay pathForCircle with CenteredAtPoint,\n\n1295\n01:07:37,621 --> 01:07:40,955\nthe skull's center, withRadius the skull's radius.\n\n1296\n01:07:40,957 --> 01:07:44,092\nThat reads really nicely, like English. Okay, got this nice\n\n1297\n01:07:44,094 --> 01:07:47,062\npreposition in here. But when I'm inside my code,\n\n1298\n01:07:47,064 --> 01:07:50,265\nit's kind of weird that this is called my withRadius.\n\n1299\n01:07:50,267 --> 01:07:52,200\nOkay, that doesn't really make sense.\n\n1300\n01:07:52,202 --> 01:07:54,869\nI really want this to be called radius inside.\n\n1301\n01:07:54,871 --> 01:07:57,038\nSo this is where I'm gonna have the internal name and\n\n1302\n01:07:57,040 --> 01:08:02,610\nthe external name that we talked about. See that? Okay,\n\n1303\n01:08:02,612 --> 01:08:06,247\nso that's all that this is gonna do. I'm not gonna return\n\n1304\n01:08:06,249 --> 01:08:09,084\nit directly though. I'm gonna let the path equal this and\n\n1305\n01:08:09,086 --> 01:08:11,886\nthen I'm going to use this to set my lineWidth as well.\n\n1306\n01:08:11,888 --> 01:08:15,023\nIn fact, let's just cut and paste this as well up here.\n\n1307\n01:08:15,025 --> 01:08:19,861\nSo I'm gonna have all my lineWidths be the same. Okay,\n\n1308\n01:08:19,863 --> 01:08:22,764\nthis is probably something I want to make a var out of,\n\n1309\n01:08:22,766 --> 01:08:23,431\njust like I have the scale,\n\n1310\n01:08:23,433 --> 01:08:25,967\nprobably want the lineWidth also to be settable, but for\n\n1311\n01:08:25,969 --> 01:08:28,636\nspeed we'll keep going here. And then we're gonna return\n\n1312\n01:08:28,638 --> 01:08:33,808\nthat path. Okay, got that? Make sense? By the way,\n\n1313\n01:08:33,810 --> 01:08:36,778\nwhen we have a really long line right here that wraps,\n\n1314\n01:08:36,780 --> 01:08:40,081\none way that we can kind of make it look nicer is just put\n\n1315\n01:08:40,083 --> 01:08:46,154\nevery argument on its own line. Like that,\n\n1316\n01:08:46,156 --> 01:08:49,090\nokay? Just a little more readable that way when it's\n\n1317\n01:08:49,092 --> 01:08:51,192\nreally long. So I've got this right here, and\n\n1318\n01:08:51,194 --> 01:08:54,329\nI've replaced this skull thing with this, okay? By the way,\n\n1319\n01:08:54,331 --> 01:08:57,765\nI don't really use skull, except for to do this stroke.\n\n1320\n01:08:57,767 --> 01:09:04,038\nSo let's take this, cut it out of here, and put it here,\n\n1321\n01:09:05,075 --> 01:09:08,710\nokay? Everyone see what I did there?\n\n1322\n01:09:08,712 --> 01:09:13,314\nI'm just chaining calling this and then calling stroke on it.\n\n1323\n01:09:13,316 --> 01:09:15,483\nAnd it's pretty obvious this is my skull,\n\n1324\n01:09:15,485 --> 01:09:17,252\nbecause I got skullCenter, skullRadius.\n\n1325\n01:09:17,254 --> 01:09:20,155\nOkay, so now I have this path for circle, I can use that to\n\n1326\n01:09:20,157 --> 01:09:23,591\ndraw my eyes as well. So I'm gonna add another private func\n\n1327\n01:09:23,593 --> 01:09:26,995\nhere called get eye, what did we call it, pathForEye,\n\n1328\n01:09:26,997 --> 01:09:28,730\npathForEye and it's gonna take an eye,\n\n1329\n01:09:28,732 --> 01:09:33,168\nwhich is of type Eye and it's gonna return a UIBezierPath.\n\n1330\n01:09:33,470 --> 01:09:35,737\nOkay, so this is gonna get an eye, either the left eye or\n\n1331\n01:09:35,739 --> 01:09:37,839\nthe right eye depending on what this argument here is\n\n1332\n01:09:37,841 --> 01:09:42,777\nright here. And to do that I need the eyeRadius.\n\n1333\n01:09:42,779 --> 01:09:44,179\nSo we'll have the eyeRadius,\n\n1334\n01:09:44,181 --> 01:09:47,248\nwhich is going to be equal to the skull's radius,\n\n1335\n01:09:47,250 --> 01:09:50,518\ndivided by one of these ratios up here, okay, in fact,\n\n1336\n01:09:50,520 --> 01:09:56,357\nthis ratio right here. So we'll say Ratio., Ratios.,\n\n1337\n01:09:56,359 --> 01:10:01,062\nthis one is SkullRadiusToEyeRadius, okay?\n\n1338\n01:10:01,064 --> 01:10:05,800\nAnd then I'm gonna let the eyeCenter equal the I'm gonna\n\n1339\n01:10:05,802 --> 01:10:09,571\nactually call a function here, getEyeCenter for\n\n1340\n01:10:09,573 --> 01:10:12,540\nthe given eye. Okay, and so let's do that.\n\n1341\n01:10:12,542 --> 01:10:17,679\nPrivate func, getEyeCenter for given eye. And\n\n1342\n01:10:17,681 --> 01:10:22,116\nthat's gonna return a CGPoint which is gonna be the center.\n\n1343\n01:10:23,019 --> 01:10:26,721\nAll right, so how do I get the eyes centered here?\n\n1344\n01:10:26,723 --> 01:10:31,726\nThat's pretty straightforward. Here I'm just going to say,\n\n1345\n01:10:31,728 --> 01:10:34,596\nwhat did I decide to do here on that one? Yeah, so\n\n1346\n01:10:34,598 --> 01:10:39,667\nI'm gonna let the eyeOffset = skullRadius\n\n1347\n01:10:39,669 --> 01:10:43,738\n/ Ratios.SkullRadiusToEyeOffset.\n\n1348\n01:10:43,740 --> 01:10:46,708\nOkay, so I'm just, see how I'm just doing all the positioning\n\n1349\n01:10:46,710 --> 01:10:48,943\nof everything based on the skullRadius and\n\n1350\n01:10:48,945 --> 01:10:50,778\nthe skullCenter? So\n\n1351\n01:10:50,780 --> 01:10:54,182\nthen I'm gonna let the eyeCenter = skullCenter.\n\n1352\n01:10:54,184 --> 01:10:56,651\nSo we'll start with the eye being right in the middle\n\n1353\n01:10:56,653 --> 01:10:59,053\nof our face, and then I'm gonna move it up and over,\n\n1354\n01:10:59,055 --> 01:11:03,558\nright? So first of all let's move it up by saying that\n\n1355\n01:11:03,560 --> 01:11:09,130\nthe eyeCenter.y -= because y minus is up, plus is down for\n\n1356\n01:11:09,132 --> 01:11:13,468\nthe y-axis, the y offset. So I'm gonna move it up by the y\n\n1357\n01:11:13,470 --> 01:11:18,673\noffset. And then depending on which eye it is, okay, if it's\n\n1358\n01:11:18,675 --> 01:11:23,544\nthe left eye I'm gonna move the eyeOffset.x to the left,\n\n1359\n01:11:23,546 --> 01:11:27,382\nokay, minus, oops, this is eyeCenter. And actually\n\n1360\n01:11:27,384 --> 01:11:30,451\nthis should be eyeCenter also. We're gonna move the eyeCenter\n\n1361\n01:11:30,453 --> 01:11:33,087\nto the left to by the eyeOffset.\n\n1362\n01:11:33,089 --> 01:11:34,555\nAnd if it's the right eye,\n\n1363\n01:11:34,557 --> 01:11:40,361\nthen I'm gonna move the eye to the right by the eyeOffset.\n\n1364\n01:11:41,598 --> 01:11:45,700\nOkay, so that tells where our eye is. So I'm gonna return\n\n1365\n01:11:45,702 --> 01:11:50,571\nthe eyeCenter here. Okay, everyone got that, where the,\n\n1366\n01:11:50,573 --> 01:11:54,876\nwhere the eye is? So we have a warning here, what is it?\n\n1367\n01:11:54,878 --> 01:11:59,614\nLet var, okay, so this needs to be var Or no, this needs to\n\n1368\n01:11:59,616 --> 01:12:03,217\nbe a var, I guess. This needs to be a let, okay, and\n\n1369\n01:12:03,219 --> 01:12:06,988\nthe lets and vars are right, yes. Okay, so here we're gonna\n\n1370\n01:12:06,990 --> 01:12:09,090\nget the center of the eye using that function, so\n\n1371\n01:12:09,092 --> 01:12:12,727\nwe have the radius and the center, for the eye. So,\n\n1372\n01:12:12,729 --> 01:12:18,399\nnow we can just return, return a path for\n\n1373\n01:12:18,401 --> 01:12:23,237\na circle centered at point, the eyeCenter withRadius\n\n1374\n01:12:23,239 --> 01:12:28,209\nthe eyeRadius. Okay, so we have this\n\n1375\n01:12:28,211 --> 01:12:31,212\npath for eye, now we just need to stroke this path. So we're\n\n1376\n01:12:31,214 --> 01:12:37,218\ngonna say pathForEye, for eye, let's do the left eye.\n\n1377\n01:12:37,220 --> 01:12:41,923\nAnd stroke that. And then path for I. Lets' do the right I,\n\n1378\n01:12:41,925 --> 01:12:45,026\nand stroke that, okay? Notice, by they way,\n\n1379\n01:12:45,028 --> 01:12:48,863\nI can say .left here. I don't have to say i.left.because\n\n1380\n01:12:48,865 --> 01:12:53,601\nit's going infer that path for I is going to be an I,\n\n1381\n01:12:53,603 --> 01:12:57,038\nokay? Everybody got that? Success?\n\n1382\n01:12:57,040 --> 01:13:01,943\nSo hopefully now when we draw we'll get some eyes on our\n\n1383\n01:13:01,945 --> 01:13:06,614\nface. Didn't quite work,\n\n1384\n01:13:06,616 --> 01:13:09,984\nokay? So, let's close what happened there.\n\n1385\n01:13:09,986 --> 01:13:11,853\nWe got one eye, the left eye looks good, but\n\n1386\n01:13:11,855 --> 01:13:16,023\nthe right eye is kind of stuck in the center. So why is that?\n\n1387\n01:13:16,025 --> 01:13:19,293\nLet's look here, well, looks to me like I moved the, for\n\n1388\n01:13:19,295 --> 01:13:23,631\nthe right eye, I moved the center y back to this,\n\n1389\n01:13:23,633 --> 01:13:25,233\nwhere it was before, see I moved there, so\n\n1390\n01:13:25,235 --> 01:13:32,573\nthis really needs to be the x, see that? It's over on that.\n\n1391\n01:13:32,575 --> 01:13:36,778\nOkay, bingo. Got a face,\n\n1392\n01:13:36,780 --> 01:13:39,747\ncan rotate him, it's looking good. So now we did the mouth,\n\n1393\n01:13:39,749 --> 01:13:42,984\nokay, let's see if we have time for the mouth, yeah,\n\n1394\n01:13:42,986 --> 01:13:45,486\nwe might, we'll get started on the mouth anyway. So\n\n1395\n01:13:45,488 --> 01:13:48,322\nhere I'm doing the same thing, private funk, path for\n\n1396\n01:13:48,324 --> 01:13:51,292\nmouth this time, okay, there's only one mouth, and\n\n1397\n01:13:51,294 --> 01:13:55,229\nit's going to return UI Bezier Path okay,\n\n1398\n01:13:55,231 --> 01:13:57,799\nand then we're gonna do the same thing down here.\n\n1399\n01:13:57,801 --> 01:14:00,802\nWe're gonna say pathForMouth().stroke.\n\n1400\n01:14:00,804 --> 01:14:01,969\nOkay, so how are we gonna do the mouth?\n\n1401\n01:14:01,971 --> 01:14:05,273\nI'm gonna have to use a bezier curve to do the mouth.\n\n1402\n01:14:05,275 --> 01:14:07,108\nHow many people know what a bezier curve is?\n\n1403\n01:14:07,110 --> 01:14:09,377\nRaise your hand if you know. Almost nobody. Okay, So\n\n1404\n01:14:09,379 --> 01:14:12,580\nBayesian curve is just a line you draw between two points,\n\n1405\n01:14:12,582 --> 01:14:15,383\nbut you have two control points somewhere, where,\n\n1406\n01:14:15,385 --> 01:14:20,254\nit tries to draw a tangent line to the control point and\n\n1407\n01:14:20,256 --> 01:14:20,988\nstart the curve on there.\n\n1408\n01:14:20,990 --> 01:14:23,558\nAnd then draw the tangent line to the other control point and\n\n1409\n01:14:23,560 --> 01:14:26,828\ntries to draw another one there, so you can make curves\n\n1410\n01:14:26,830 --> 01:14:28,329\nOkay, using these little control points.\n\n1411\n01:14:28,331 --> 01:14:30,598\nSo I have to determine the start and the end, and\n\n1412\n01:14:30,600 --> 01:14:31,532\nthe two control points.\n\n1413\n01:14:31,534 --> 01:14:35,470\nSo first I'm gonna create a rectangle to contain my mouth\n\n1414\n01:14:35,472 --> 01:14:40,208\nhere. I need these mouth ratios, so the mouth width,\n\n1415\n01:14:40,210 --> 01:14:43,044\nheight, and offset, I'm gonna make as ratios to the skull\n\n1416\n01:14:43,046 --> 01:14:46,280\nradius, okay? Save a little time by doing that. And\n\n1417\n01:14:46,282 --> 01:14:51,919\nthen I'm gonna make the The rectangle changes them out by\n\n1418\n01:14:51,921 --> 01:14:58,726\nequal a and this I'm going to use the X,\n\n1419\n01:14:58,728 --> 01:15:03,431\nY width height intizler here. So\n\n1420\n01:15:03,433 --> 01:15:08,503\nthe X is just the center. .x- mouthWidth/2,\n\n1421\n01:15:08,505 --> 01:15:12,840\nokay? So my mouth is going to be whatever the mouthWidth is\n\n1422\n01:15:12,842 --> 01:15:17,712\nfrom the skullCenter. Move it over. And the y is similarly\n\n1423\n01:15:17,714 --> 01:15:20,848\ngoing to be the skullCenter.y +,\n\n1424\n01:15:20,850 --> 01:15:25,119\nactually The mouth off set, because we're going to put\n\n1425\n01:15:25,121 --> 01:15:27,054\nthe mouth down below the center of the face, so\n\n1426\n01:15:27,056 --> 01:15:30,491\nwe're going to do it down. The width is just the mouth width,\n\n1427\n01:15:30,493 --> 01:15:33,861\nand the height is the mouth height, okay, and just to show\n\n1428\n01:15:33,863 --> 01:15:36,731\nyou what this is like, I'm going to create a rectangle,\n\n1429\n01:15:36,733 --> 01:15:40,768\nUI Bezier Path has a constructor which creates\n\n1430\n01:15:40,770 --> 01:15:45,339\na rectangle using mouth rect. Okay, so let's run that,\n\n1431\n01:15:45,341 --> 01:15:50,478\nlet's return that actually. Okay, that's the path\n\n1432\n01:15:50,480 --> 01:15:52,580\nwe're going to use, we're just going to do a rectangle first,\n\n1433\n01:15:52,582 --> 01:15:58,019\nI'm not going to do those control point things yet. So\n\n1434\n01:15:58,021 --> 01:15:59,353\nour rect is going to be a rectangle, so\n\n1435\n01:15:59,355 --> 01:16:01,222\nthis is where we're going to do the mouth, if it's smiling,\n\n1436\n01:16:01,224 --> 01:16:03,891\nit will be down here, if it's frowning, the mouth is going\n\n1437\n01:16:03,893 --> 01:16:06,494\nto be up here. Okay, so we are going to put this here.\n\n1438\n01:16:06,496 --> 01:16:09,864\nThis is going to be the start point of my busy path.\n\n1439\n01:16:09,866 --> 01:16:10,798\nThis is going to be the end point.\n\n1440\n01:16:10,800 --> 01:16:13,668\nI'm going to put one control point here and one control\n\n1441\n01:16:13,670 --> 01:16:16,337\npoint here for a full smile. And so it going to start\n\n1442\n01:16:16,339 --> 01:16:19,774\nheading down towards this control point bottom out. And\n\n1443\n01:16:19,776 --> 01:16:22,510\nthen start heading towards the tangent line between here and\n\n1444\n01:16:22,512 --> 01:16:25,546\nthis one. So, that's what is going to make a smile. Okay?\n\n1445\n01:16:25,548 --> 01:16:29,183\nDon't worry about it too much if you don't know Bézier path.\n\n1446\n01:16:29,185 --> 01:16:29,984\nSo here, I also,\n\n1447\n01:16:29,986 --> 01:16:33,254\nI'm gonna type this in really fast just to save\n\n1448\n01:16:33,256 --> 01:16:37,291\nsome time here. Most important thing is this mouth curvature.\n\n1449\n01:16:37,293 --> 01:16:40,661\nThis is just a double, which is somewhere between -1,\n\n1450\n01:16:40,663 --> 01:16:44,265\nwhich is a full front, and 1, which is a full smile.\n\n1451\n01:16:44,267 --> 01:16:48,235\nOkay and so the smile offset, first I'm gonna make sure\n\n1452\n01:16:48,237 --> 01:16:51,739\nit s between one and\n\n1453\n01:16:51,741 --> 01:16:55,309\ngoing to be that one to minus one times the mouth's height.\n\n1454\n01:16:55,311 --> 01:16:57,945\nThat's why I'm going to put my control point all that way day\n\n1455\n01:16:57,947 --> 01:17:03,184\nat the bottom if the smile is one All right, so here so\n\n1456\n01:17:03,186 --> 01:17:06,020\nhere I'm gonna start at the mouth's upper left. I'm gonna\n\n1457\n01:17:06,022 --> 01:17:09,256\nend at mouth upper right, okay? My first control point\n\n1458\n01:17:09,258 --> 01:17:12,593\nis a third of the way along the bottom. And the second\n\n1459\n01:17:12,595 --> 01:17:16,197\ncontrol is a third of the way on the other side, okay?\n\n1460\n01:17:16,199 --> 01:17:19,033\nAnd on the bottom, wherever the smileOffset\n\n1461\n01:17:19,035 --> 01:17:21,469\nputs it. Okay, so in full smile this is gonna be along\n\n1462\n01:17:21,471 --> 01:17:25,306\nthe bottom of the Rect. Could be up above the rack. Okay, so\n\n1463\n01:17:25,308 --> 01:17:28,776\nI've got that so now I'm just gonna return UIBEzier path\n\n1464\n01:17:28,778 --> 01:17:31,078\nhere that incorporates all that.\n\n1465\n01:17:31,080 --> 01:17:36,317\nLet's actually do this let's say let UIBEzier path. I'm\n\n1466\n01:17:36,319 --> 01:17:41,255\njust gonna create a blank one then I'm gonna tell the path\n\n1467\n01:17:41,257 --> 01:17:44,258\nthat to move to the start. Move to our starting point\n\n1468\n01:17:44,260 --> 01:17:48,262\nwhich is start, that's this thing right here. Okay then\n\n1469\n01:17:48,264 --> 01:17:51,632\nI'm gonna create a bezierPath or bezierCurve which is add\n\n1470\n01:17:51,634 --> 01:17:55,403\ncurve to point that's the way you add a bezierCurve\n\n1471\n01:17:55,405 --> 01:17:58,839\nto a path it goes to the end point which is this right\n\n1472\n01:17:58,841 --> 01:18:03,878\nhere, and here's my 2 control points cp1 and cp2.\n\n1473\n01:18:03,880 --> 01:18:08,082\nOkay, that's these two guys. All right, so I've done that.\n\n1474\n01:18:08,084 --> 01:18:11,252\nI'm gonna set the line width equal to 5.0 and\n\n1475\n01:18:11,254 --> 01:18:16,190\nreturn the path. Okay? So let's see if that works,\n\n1476\n01:18:16,192 --> 01:18:19,527\nwe have our mouth here set to be 0, which is not a smile or\n\n1477\n01:18:19,529 --> 01:18:22,763\na frown, it should be just kind of straight line Cuz our\n\n1478\n01:18:22,765 --> 01:18:25,833\ncontrol points are gonna be right along the line sure\n\n1479\n01:18:25,835 --> 01:18:29,804\nenough this is not a very happy camper let's make them\n\n1480\n01:18:29,806 --> 01:18:30,971\nvery sad.\n\n1481\n01:18:39,082 --> 01:18:42,149\nOkay aw that looks very sad but I don't you saying I don't\n\n1482\n01:18:42,151 --> 01:18:43,784\nwanna sending you guys out of here sad so\n\n1483\n01:18:43,786 --> 01:18:52,259\nwe're gonna go to full happy here. There it is. Very happy.\n\n1484\n01:18:52,261 --> 01:18:54,562\nOkay. Now, one thing I'm gonna do, last thing I'm gonna do\n\n1485\n01:18:54,564 --> 01:18:57,598\nbefore we leave is this mouth curvature is currently a local\n\n1486\n01:18:57,600 --> 01:19:00,267\nvariable inside this private method. I'm actually gonna\n\n1487\n01:19:00,269 --> 01:19:04,038\nmake this public. Okay, so I'm just gonna take it out of here\n\n1488\n01:19:04,040 --> 01:19:06,741\nI put my public bars up here at the front,\n\n1489\n01:19:06,743 --> 01:19:09,677\nloose scale. Put it there, I'm gonna make it a var so\n\n1490\n01:19:09,679 --> 01:19:13,347\nit's public. So now other people using my face view can\n\n1491\n01:19:13,349 --> 01:19:17,184\nset how happy it is, right? Cuz I've made this public so\n\n1492\n01:19:17,186 --> 01:19:18,252\nthey can set whether it's a smile or\n\n1493\n01:19:18,254 --> 01:19:21,322\na frown. And that's gonna be really valuable next week when\n\n1494\n01:19:21,324 --> 01:19:24,658\nwe stat having multiple NVCs cuz we're gonna wanna be able\n\n1495\n01:19:24,660 --> 01:19:27,161\nto use other NVCs to show things,\n\n1496\n01:19:27,163 --> 01:19:29,930\nokay? So just to show this still works,\n\n1497\n01:19:29,932 --> 01:19:35,970\nthe mouth curvature is still a full smile. There we go.\n\n1498\n01:19:36,405 --> 01:19:39,006\nOkay we'll pick this up next week.\n\n1499\n01:19:40,443 --> 01:19:40,808\n>> For more\n\n1500\n01:19:40,810 --> 01:19:40,841\nplease visit us at Stanford.edu.\n\n"
  },
  {
    "path": "subtitles/5. Interface Builder, FaceView Controller, Gestures, and Multiple MVCs.srt",
    "content": "1\n00:00:00,001 --> 00:00:03,836\n[MUSIC]\n[MUSIC]\n\n2\n00:00:03,838 --> 00:00:06,305\nStanford University. >> All right,\n斯坦福大学. >> 好的,\n\n3\n00:00:06,307 --> 00:00:12,177\nwell then welcome to lecture 5, of CS193P,\n欢迎来到 CS193P 的第五课，\n\n4\n00:00:12,179 --> 00:00:16,015\nthis is the spring of 2016. And\n现在是 2016 年春。\n\n5\n00:00:16,017 --> 00:00:21,420\ntoday we are going to, first, work a little more and\n今天我们首先要做的是在之前的工程中增加一点功能，然后\n\n6\n00:00:21,422 --> 00:00:24,957\nface it. I'm gonna show you a little kind of some cool\n看看效果。 我将会为你展示一些 Xcode 可视化界面中\n\n7\n00:00:24,959 --> 00:00:27,359\nfeatures in the interface builder part of Xcode,\n很酷的特性，\n\n8\n00:00:27,361 --> 00:00:30,662\nthat's the part where we're building our storyboard.\n这部分内容我们会在 Storyboard 上完成。\n\n9\n00:00:30,931 --> 00:00:34,033\nThen we're gonna start talking about what FACEIT's\n然后我们将开始讨论如何正确实现 FACEIT 中的\n\n10\n00:00:34,035 --> 00:00:36,802\nview controllers model really should be.\n视图、控制器和模型。\n\n11\n00:00:36,804 --> 00:00:39,638\nOkay, cuz right now if you look at the code in our\n好的, 现在如果你看了 FACEIT 中\n\n12\n00:00:39,640 --> 00:00:42,307\ncontroller of our MVC for FACEIT. It's blank,\n控制器的代码。 你会发现它是空白的，\n\n13\n00:00:42,309 --> 00:00:44,743\nthere's nothing in there. So we need to do some work there.\n什么都没有。我们需要在上面完成一些工作。\n\n14\n00:00:44,745 --> 00:00:48,113\nNow we're gonna come back to the slides and I'm gonna talk\n现在先回到幻灯片上来\n\n15\n00:00:48,115 --> 00:00:51,283\nabout gestures, okay which is the input side of UIView.\n我要讲解手势的相关知识点, 它是 UIView 的输入端。\n\n16\n00:00:51,285 --> 00:00:54,453\nAnd I'll do a demo where we put some gestures in FACEIT.\n我会演示一个在 FACEIT 上添加手势的 Demo。\n\n17\n00:00:54,455 --> 00:00:57,456\nAnd then time permitting I'm gonna end with some more\n然后如果时间允许的话，\n\n18\n00:00:57,458 --> 00:01:00,225\nslides starting to talk about multiple MVCs which is\n我会在幻灯片上讲解多重 MVC\n\n19\n00:01:00,227 --> 00:01:04,229\nthe gateway to building bigger applications. Okay, so that's\n它是构建更大型的应用的入口。 好吧\n\n20\n00:01:04,231 --> 00:01:07,499\nwhat's on tap for today. So let's dive right into the demo\n以上就是今天的主要内容。 让我们直接进入 demo 环节\n\n21\n00:01:07,501 --> 00:01:10,702\nhere. I'm gonna do these two things I talked about,\n我要开始做我刚刚谈到的那两件事,\n\n22\n00:01:10,704 --> 00:01:15,941\nwhich is the Interface Builder. And a model for\n一个是界面生成器。 另一个是\n\n23\n00:01:15,943 --> 00:01:16,508\nour FaceViewController,\n我们的 FaceViewController 的模型，\n\n24\n00:01:16,510 --> 00:01:18,243\nwhich is gonna be a facial expression,\n正常来说这个模型要描述一个面部表情。\n\n25\n00:01:18,245 --> 00:01:22,548\nnot surprisingly. All right, so here we are in FaceView,\n好的，现在我们来到 FaceView，\n\n26\n00:01:22,550 --> 00:01:26,285\nthis is where we left off last time. I'm gonna quickly\n这是我们上节课最后停留的部分。\n\n27\n00:01:26,287 --> 00:01:29,855\nenhance our FaceView to be a little cooler right now if you\n我会快速地强化 FaceView 的功能，让它变得更酷。\n\n28\n00:01:29,857 --> 00:01:33,559\nremember from last time our FaceView has a mouth which we\n如果你还记得上一次我们对 FaceView 上的嘴巴\n\n29\n00:01:33,561 --> 00:01:37,029\ncan configure a little bit. We can make it smile and\n进行了一些配置。 我们可以让它微笑、\n\n30\n00:01:37,031 --> 00:01:40,466\nfrown and then it has two eyes, okay. And I'm gonna add\n皱眉并且拥有两只眼睛，很不错。我现在要增加两样东西，\n\n31\n00:01:40,468 --> 00:01:43,368\ntwo things, one I'm gonna make it so he can close those eyes.\n首先我可以让它闭上眼睛。\n\n32\n00:01:43,370 --> 00:01:46,505\nAnd another thing I'm gonna do is, I'm gonna add eyebrows.\n我要做的另外一件事是:给它加上眉毛。\n\n33\n00:01:46,507 --> 00:01:49,208\nOkay, now I'm gonna do this really fast because the code\n我完成起来非常地快，\n\n34\n00:01:49,210 --> 00:01:51,577\nthat it takes me to do this really wouldn't learn that\n因为我所需要的代码不需要对现有的的代码做较大改动，\n\n35\n00:01:51,579 --> 00:01:53,879\nmuch from going through it, but it's pretty just more,\n只需要新增一些代码，\n\n36\n00:01:53,881 --> 00:01:56,081\npretty much more of the same of the stuff women doing.\n跟女人画眉毛相比要省事得多。\n\n37\n00:01:56,083 --> 00:02:01,120\nSo I'm gonna add a couple of more public vars because\n因此我需要定义一组新的公有变量，\n\n38\n00:02:01,122 --> 00:02:03,122\nthese are gonna be configurable thing. One is\n因为有一些东西需要可配置。\n\n39\n00:02:03,124 --> 00:02:06,758\nwhether the eyes are open, which is gonna be a bull. And\n一个属性表示眼睛是否是睁开的, 这是一个布尔变量。\n\n40\n00:02:06,760 --> 00:02:10,462\nI'm gonna say these are gonna start out open, okay?\n我将把眼睛的初始状态设置为睁开，怎么样？\n\n41\n00:02:10,464 --> 00:02:13,398\nSo it's just gonna be the default. And then I'm also\ntrue 是它的默认值。 然后我定义另一个新属性\n\n42\n00:02:13,400 --> 00:02:16,568\ngoing to have something called eyebrowTilt, okay?\n取名为 eyebrowTilt, 怎么样?\n\n43\n00:02:16,570 --> 00:02:20,272\nWhich is gonna be a double. And I'm gonna start it at 0.0.\n这是一个 double 类型的变量. 初始值设置为 0.0。\n\n44\n00:02:20,274 --> 00:02:23,575\nIt's similar to the kind of the mouth curvature. So\n它的定义类比于嘴巴弯曲的弧度。\n\n45\n00:02:23,577 --> 00:02:26,979\nwe're gonna have -1 be full furrow.\n我们让默认曲率为 0。\n\n46\n00:02:26,981 --> 00:02:31,016\nAnd one will be fully relaxed eyebrows, okay?\n-1代表很郁闷，1代表完全放松的眉毛, 怎么样?\n\n47\n00:02:31,018 --> 00:02:35,187\nSo similar kind of thing as we had for the mouth curvature.\n非常像我们对嘴巴的曲率做的设置。\n\n48\n00:02:35,189 --> 00:02:38,190\nSo let's do the eyes open first. Quite simple.\n先来让眼睛睁开。很简单。\n\n49\n00:02:38,192 --> 00:02:42,094\nIn path for eye right now. You can see that we use a path for\n在之前画眼睛的路径中， 你可以看到我们用一个圆的路径代表眼睛。\n\n50\n00:02:42,096 --> 00:02:44,429\ncircle, so that's why our eyes are circular. So\n这解释了为什么眼睛是圆的。\n\n51\n00:02:44,431 --> 00:02:48,800\nif my eyes are open, I'm just gonna continue to do that,\n所以如果眼睛睁开的话， 我打算还这么做，\n\n52\n00:02:48,802 --> 00:02:50,035\nokay? We'll do to pass the circle.\n如何? 我们继续用圆来表示。\n\n53\n00:02:50,037 --> 00:02:54,206\nBut if the eyes are closed, then instead what I'm gonna do\n但是如果眼睛是闭上的, 我会用另一个图形来表示\n\n54\n00:02:54,208 --> 00:02:58,877\nis do this, which is basically use a line.\n只使用一条线。\n\n55\n00:02:58,879 --> 00:03:00,546\nSo I'm just gonna draw a horizontal line,\n如果眼睛是闭合的话我会画一条水平的线。\n\n56\n00:03:00,548 --> 00:03:03,815\nif the eyes are closed. Okay? Very simple. Here, BezierPath,\n非常简单。看这里， BezierPath，\n\n57\n00:03:03,817 --> 00:03:07,786\nmove to a point, draw a line. Okay? And then for the brows,\n移动到一个点上,画一条线。然后画眉毛，\n\n58\n00:03:07,788 --> 00:03:10,422\nyou see, you know we have path for eye, we have path for\n如你所见，我们有眼睛的路径，\n\n59\n00:03:10,424 --> 00:03:15,093\nmouth, so I'm just gonna make a path for brows. Which I\n有嘴巴的路径，所以我仅仅需要为眉毛画一个路径\n\n60\n00:03:15,095 --> 00:03:19,198\nthink I have here, yes. So here's our path for brow and\n我想我可以用这里的代码！现在这就是我们的眉毛的路径\n\n61\n00:03:19,200 --> 00:03:22,167\nit's pretty straightforward. It's just drawing a line but\n它很简单. 画了一条直线\n\n62\n00:03:22,169 --> 00:03:28,207\nthis line is tilted. Depending on how much tilt we want.\n这条线是倾斜的。 倾斜程度取决于我们设置的斜率\n\n63\n00:03:28,209 --> 00:03:32,077\nAnd of course we need a little func a little static here to\n当然了我们还需要向比例中增加一些静态变量\n\n64\n00:03:32,079 --> 00:03:36,815\ngo up in our ratios. Which is the relative position of\n代表眉毛相对于旋转中心点的偏移距离\n\n65\n00:03:36,817 --> 00:03:40,285\nthe brow to the scroll radius, just like we have all these\n就像我们设置的\n\n66\n00:03:40,287 --> 00:03:44,089\nother things that are relative to the radius. Okay? And\n其他与半径相关的信息。\n\n67\n00:03:44,091 --> 00:03:46,892\nnow that we have pathForBrow, just like we did with\n现在我们有了方法 pathForBrow, 就像定义\n\n68\n00:03:46,894 --> 00:03:48,594\npathForEye and pathForMouth, we'll go ahead and\npathForEye 和 pathForMouth 那样， 让我们继续\n\n69\n00:03:48,596 --> 00:03:52,831\nstroke those. So I'll say pathFor, Brow, the left one,\n绘制它们。 我要绘制的路径是, 眉毛, 左边那条,\n\n70\n00:03:52,833 --> 00:03:58,270\nstroke, and then we'll do a pathForBrow, the right one,\n绘制, 然后绘制右边的眉毛。\n\n71\n00:03:58,272 --> 00:04:01,073\nand stroke. Okay?\n大功告成。\n\n72\n00:04:01,075 --> 00:04:03,408\nSo let's go ahead and run, see what we'll look,\n让我们继续并且运行程序, 看看我们能看到什么,\n\n73\n00:04:03,410 --> 00:04:08,280\nwe should have eyebrows now. Okay,\n现在我们应该有眉毛了。 好的,\n\n74\n00:04:08,282 --> 00:04:10,949\nyeah, look we got eyebrows, they're kinda cute. And\n耶, 看我们有眉毛了, 它们有一点可爱。\n\n75\n00:04:10,951 --> 00:04:12,384\nwe should also be able to close the eyes.\n我们应该也可以让眼睛闭上了。\n\n76\n00:04:12,386 --> 00:04:16,421\nSo I'm gonna change this eyesOpen to false.\n所以我要把 eyesOpen 设为 false。\n\n77\n00:04:18,559 --> 00:04:22,494\nSee if that works, it does, eyes closed.\n看下有没有起作用,起作用了, 眼睛闭上了。\n\n78\n00:04:22,496 --> 00:04:26,298\nWe could set our eyebrowTilt maybe to I don't know -0.5.\n我们可以把 eyebrowTilt 设置成..嗯..就-0.5吧。\n\n79\n00:04:26,300 --> 00:04:33,538\nSee what that does. Okay,\n看下效果。好的,\n\n80\n00:04:33,540 --> 00:04:36,775\nwe have some tilt there. Okay, so you can see with eyebrows,\n增加了倾斜的效果. 所以你看到了眉毛的效果,\n\n81\n00:04:36,777 --> 00:04:38,510\nwe can make more facial expressions.\n我们可以做出更多的面部表情。\n\n82\n00:04:38,512 --> 00:04:39,011\nThat's why I put him in there.\n这就是我把他放在这的原因。\n\n83\n00:04:39,013 --> 00:04:42,247\nSo we'd have a little more room to maneuver when it\n当涉及到面部表情时\n\n84\n00:04:42,249 --> 00:04:43,048\ncomes to facial expressions.\n我们有更多可操作的选项。\n\n85\n00:04:43,050 --> 00:04:46,318\nI'm gonna do a couple other things here. One is, there's\n我要在这设置更多的选项。 其中一个可以是\n\n86\n00:04:46,320 --> 00:04:51,290\nsome constants I have in here like my face is always blue.\n我在这里定义的一些常量，比如颜色总是蓝色的。\n\n87\n00:04:51,292 --> 00:04:53,959\nI don't really want that. So I'm gonna make that be a var,\n我不希望这样。 所以我把它改成一个变量,\n\n88\n00:04:53,961 --> 00:04:57,029\nso I'm gonna call it color. So I'm gonna go up here and\n我准备给变量取名为 color。 我在这里定义一个变量 Color\n\n89\n00:04:57,031 --> 00:05:01,967\nmake a var. Color, which is gonna be a UIColor.\n它的类型是 UIColor。\n\n90\n00:05:01,969 --> 00:05:06,371\nAnd I'm gonna let it be blue by default. Whoops UIColor,\n并且我设置它的默认值是蓝色。 唔 UIColor,\n\n91\n00:05:06,373 --> 00:05:10,909\nblueColor by default. And I'm also gonna do a var for\n默认是 blueColor。然后我也会把线的宽度定义为一个变量\n\n92\n00:05:10,911 --> 00:05:14,579\nthe linewidth, okay? Currently, our linewidth is\n怎么样? 现在, 我们的线宽一直是 0.5\n\n93\n00:05:14,581 --> 00:05:18,617\nalways 5.0, but I'm gonna, and we'll make the default 5.0.\n所以我把默认值设成 5.0.\n\n94\n00:05:18,619 --> 00:05:22,454\nBut I'm gonna change all those 5.0s with this var, so let's\n但是我会把所有用到 5.0 这个常量的地方替换成这个变量,\n\n95\n00:05:22,456 --> 00:05:28,994\ndo that. There's 1, 2, 3, 4. Okay, that's our four things.\n让我们完成这个工作。 一共有 1, 2, 3, 4. 好的, 我们替换了四处.\n\n96\n00:05:28,996 --> 00:05:33,298\nEyebrows, eyes, our mouth, and the skull. Okay? So now we've\n眉毛, 眼睛, 我们的嘴, 和骨头. okay?\n\n97\n00:05:33,300 --> 00:05:37,402\nkind of made our faceView quite externally usable, okay.\n我们增强了 faceView 的外部调用性, 好的。\n\n98\n00:05:37,404 --> 00:05:40,772\nAll these public functions are something that a controller\n所有这些公开的方法都是一个控制器\n\n99\n00:05:40,774 --> 00:05:44,443\nis likely to use. Because we're part of the view, okay.\n可能用到的。 因为我们都是视图的一部分, okay.\n\n100\n00:05:44,445 --> 00:05:48,280\nWe're a generic face-drawing view, and so we can be used by\n我们是一个通用的脸部绘制视图, 所以我们可以被\n\n101\n00:05:48,282 --> 00:05:52,084\nany controller that might want to draw a face. Okay? Which is\n任何想要绘制面部的控制器所使用。 Okay?\n\n102\n00:05:52,086 --> 00:05:53,985\nthe kind of controller we happen to have now.\n哪一个是我们已经拥有了的控制器呢？\n\n103\n00:05:53,987 --> 00:05:54,619\nIt's drawing a face. But\n这里绘制了一张脸。 不过\n\n104\n00:05:54,621 --> 00:05:57,222\nif we look at our controller right here, it's drawing\n如果我们查看这里我们自己的控制器的话,\n\n105\n00:05:57,224 --> 00:06:01,326\na face but doesn't really control that face much, okay?\n控制器绘制一张脸但是对这张脸做任何配置, okay?\n\n106\n00:06:01,328 --> 00:06:04,563\nIt has a view that it has in its storyboard, where we put\n它拥有了 storyboard 提供的视图,\n\n107\n00:06:04,565 --> 00:06:08,667\nour face right here, but it's not really doing much. And\n我们要把脸绘制在上面, 但是没有做其他的工作。\n\n108\n00:06:08,669 --> 00:06:12,037\nwe'll fix that in a minute. Now, one thing that's kind of\n我们一分钟就能完成。 现在， 有一件令人苦恼的事情，\n\n109\n00:06:12,039 --> 00:06:15,140\nannoying is if we look in our storyboard right here.\n当我们查看我们的 storyboard。\n\n110\n00:06:15,142 --> 00:06:16,341\nOkay, here's our storyboard right there.\nOkay, 这里是我们的 storyboard。\n\n111\n00:06:16,343 --> 00:06:20,312\nWe don't see that face and okay we only have one\n我们看不到我们绘制的脸，并且我们只有一个 MVC\n\n112\n00:06:20,314 --> 00:06:23,682\nMVC here we know it's a face and the fact that it\n我们知道它是一个脸，可是\n\n113\n00:06:23,684 --> 00:06:24,850\ndoesn't show up there,eh. But\n我们看不到。但是\n\n114\n00:06:24,852 --> 00:06:27,886\nwhat if we had like 20 view controllers and this is just,\n如果我们有 20 个控制器,\n\n115\n00:06:27,888 --> 00:06:29,755\nthis was the face but there's a whole bunch of other ones.\n这里会有一张脸，那里又会有一整套别的东西。\n\n116\n00:06:29,757 --> 00:06:32,958\nWould be really cool if that face would show up here. Okay.\n如果脸能在这里展示出来，岂不是很酷？ Okay。\n\n117\n00:06:32,960 --> 00:06:34,626\nSo we can see it in interface build. And in fact,\n等下我们会在可视化构造器上看到它。 实际上，\n\n118\n00:06:34,628 --> 00:06:38,330\nthat's really easy to do. All you do is you go to your view,\n很容易办到。你需要做的就是到你的视图上,\n\n119\n00:06:38,332 --> 00:06:41,366\nokay? Your custom UIView, faceView. And you just put\nokay? 你自定一个 UIView, 取名 faceView.并且它的定义上面加上\n\n120\n00:06:41,368 --> 00:06:46,638\n@IBdesignable at the front. And if you say @IBdesignable,\n@IBdesignable 关键字。 如果你声明了 @IBdesignable,\n\n121\n00:06:46,640 --> 00:06:51,676\nthen interface's builder is automatically going to assume,\n可视化构造器会认为你想要\n\n122\n00:06:51,678 --> 00:06:52,711\nyou want me to draw this thing.\n绘制这个东西。\n\n123\n00:06:52,713 --> 00:06:54,579\nSo you can see, it's even compiling it and drawing it.\n所以你可以看到, 代码会被编译并且绘制。\n\n124\n00:06:54,581 --> 00:06:59,684\nSo now it appears, here in my storyboard, okay. So that's\n在我的 storyboard 上，脸出现了。 okay。\n\n125\n00:06:59,686 --> 00:07:02,154\npretty cool. But one thing that's not so cool is, if I\n这真的很酷。但是还有一件不太酷的事情，\n\n126\n00:07:02,156 --> 00:07:05,724\nclick on my faceView and bring up the inspector. I can only\n如果我点击我的 faceView 并且打开检查器。\n\n127\n00:07:05,726 --> 00:07:08,593\ninspect the attributes about my faceView that inherits from\n我只能检查 faceView 从 View 继承来的属性\n\n128\n00:07:08,595 --> 00:07:11,663\nview like its background color and things like that, right?\n比如像它的背景色这样的属性, 没错吧?\n\n129\n00:07:11,665 --> 00:07:15,133\nIt'd be really cool if I could inspect things like eyebrow\n如果我能检查像眉毛、最的曲率\n\n130\n00:07:15,135 --> 00:07:15,500\nmouth curvature and the color and the scale. Wouldn't it be\n以及颜色和比例的话那就很酷了。\n\n131\n00:07:15,502 --> 00:07:18,770\ntilt and\n这里是不是该倾斜\n\n132\n00:07:18,772 --> 00:07:20,572\ncool if I could do all that in interface builder so\n如果我能在可视化构造器中完成所有这些属性的设置那就太酷了。\n\n133\n00:07:20,574 --> 00:07:23,842\nI could set up the face how I want it to initially look\n也许我可以按照我的想法来初始化一张脸，\n\n134\n00:07:23,844 --> 00:07:27,245\nmaybe, interface builder and you can do that too.\n可视化构造器可以实现。\n\n135\n00:07:27,247 --> 00:07:28,313\nIf you go back to faceView.\n如果你回顾 faceView.\n\n136\n00:07:28,315 --> 00:07:33,151\nAll of these things that are right here, that are settable,\n所有的这一切都在这里, 它们是可设置的,\n\n137\n00:07:33,153 --> 00:07:37,022\nyou can just put in front of them @IBInspectable.\n你只需在它们前面加上 @IBInspectable。\n\n138\n00:07:37,024 --> 00:07:38,957\nOkay, which means they will show up in the inspector.\nOkay, 这代表该属性会被显示在观察器中。\n\n139\n00:07:38,959 --> 00:07:42,561\nAnd so I am gonna make all of these things be inspectable,\n因此我把所有的这些属性都设置为可观察的，\n\n140\n00:07:42,563 --> 00:07:47,432\nput inspectable on all these guys. Okay. Could go into\n给这些家伙们都加上 inspectable。 Okay. 现在可以回到\n\n141\n00:07:47,434 --> 00:07:50,068\ninterface builder. But if I go here and bring out my\n可视化构造器中了。 你打开这里\n\n142\n00:07:50,070 --> 00:07:53,238\nutilities now you can see I've still got all the view stuff.\n你依旧能看到所有 View 相关的属性。\n\n143\n00:07:53,240 --> 00:07:55,774\nBut now I've got all these faceView things, so\n但是现在我们拥有 faceView 中的东西了， 所以\n\n144\n00:07:55,776 --> 00:07:59,010\nI can set my scale to 0.05. Okay, and that makes it small.\n我可以把比例设置为 0.5. Okay, 这使得人脸变小了。\n\n145\n00:07:59,012 --> 00:08:02,814\nOr I could set my color to orange. Okay,\n或者我可以把颜色设置成橘黄色。 Okay,\n\n146\n00:08:02,816 --> 00:08:05,383\nSan Francisco Giants color, all right! I can make my line\n洛杉矶巨人队的颜色。好吧! 我可以把线宽从5改为2\n\n147\n00:08:05,385 --> 00:08:09,254\nwidth B2 instead of 5, where it's a little thinner, okay?\n线就变细了， okay?\n\n148\n00:08:09,256 --> 00:08:13,925\nI could set my mouth curvature in here, let's say -0.5.\n在这里我可以设置嘴巴的曲率, 设置为 -0.5。\n\n149\n00:08:13,927 --> 00:08:18,196\nAll right, eyes open? On?\n对把, 眼睛是否睁开? 睁开状态?\n\n150\n00:08:18,198 --> 00:08:22,234\nThere we go, okay, see that? 3.9 again.\n让我们继续, okay,看到了吗? 比例变回0.9。\n\n151\n00:08:22,236 --> 00:08:25,103\nAll right, so that's kinda cool that we can do that.\n好的, 我们做到了，这很酷。\n\n152\n00:08:25,105 --> 00:08:27,372\nAnd, in fact, when we first run our application,\n实际上， 当我们第一次运行程序,\n\n153\n00:08:27,374 --> 00:08:30,842\nit will use these values. So let's go ahead and run and\n它就会应用这些值。 让我们继续并且运行程序\n\n154\n00:08:30,844 --> 00:08:32,711\nyou're gonna see it's gonna keep this exact face.\n你会看到屏幕上会显示相同的脸。\n\n155\n00:08:32,713 --> 00:08:35,981\nLine, the color, the line thickness, all these things.\n线条、颜色、线宽以及所有的这些属性。\n\n156\n00:08:35,983 --> 00:08:38,316\nJust like if we had set any other attribute over here,\n就像我们在检查器上设置的任何其他属性一样。\n\n157\n00:08:38,318 --> 00:08:40,819\nbackground color or something like that. When we run,\n比如背景颜色或者其他诸如此类的属性。 当然，当我们运行时\n\n158\n00:08:40,821 --> 00:08:43,889\nof course, those would be the things it starts out with,\n这些属性都会被初始化,\n\n159\n00:08:43,891 --> 00:08:46,758\nokay? Now, one little thing to watch out for\nokay? 现在， 有个小细节要注意\n\n160\n00:08:46,760 --> 00:08:50,428\nwhen you're doing this, is [COUGH] these IBInspectable\n当你要设置可变属性为 IBInspectable 时\n\n161\n00:08:50,430 --> 00:08:54,232\nvars, you have to explicitly type them. You see, there,\n你必须显式地声明它们的类型。 你看，像这里，\n\n162\n00:08:54,234 --> 00:08:56,434\nmost of these I wouldn't even need to type, right?\n大部分我原本都不需要声明类型的, 对吧?\n\n163\n00:08:56,436 --> 00:09:00,071\nSwift could infer that that's a double from there. But\nSwift 可以通过赋值推断出 Double 类型。 但是\n\n164\n00:09:00,073 --> 00:09:00,906\nif you're using the IBInspectable,\n如果你正在使用 IBInspectable,\n\n165\n00:09:00,908 --> 00:09:03,975\nyou have to explicitly type, basically interface builder\n你必须显式地写出类型， 因为可视化构造器不能推断它们的类型。\n\n166\n00:09:03,977 --> 00:09:07,379\ncan't infer it, Swift can, but interface builder can't.\nSwift 可以，但是可视化构造器不能。\n\n167\n00:09:07,381 --> 00:09:09,748\nSo you need to make those explicit, okay.\n所以你需要明确类型， okay。\n\n168\n00:09:09,750 --> 00:09:14,786\nJust a minor deal there. Okay, now, one other thing I wanna\n这只是一个小的需要注意的点。 Okay, 现在，另外一件我要说到的事情是\n\n169\n00:09:14,788 --> 00:09:19,224\ntalk about here with a view is if somebody sets the scale to\n这里的视图，如果某个人设置了它的比例，\n\n170\n00:09:19,226 --> 00:09:22,093\nsomething, okay, in the code. Like let's say our\nokay, 在代码里面设置的。\n\n171\n00:09:22,095 --> 00:09:24,696\ncontroller over here, let's say we have some code in here\n控制器在这里, 我们在视图的代码中设置比例。\n\n172\n00:09:24,698 --> 00:09:29,100\nto set the face view scale. It would actually do nothing.\n实际上没有起到任何效果。\n\n173\n00:09:29,102 --> 00:09:32,404\nOkay, nothing would change on screen, and why is that?\nOkay,屏幕上不会有变化， 这是为什么呢?\n\n174\n00:09:32,406 --> 00:09:35,373\nWell because when you set this scale to be 0.5,\n因为当我们把比例设置为 0.5 时,\n\n175\n00:09:35,375 --> 00:09:39,511\nall you did was set this var, you didn't do anything else,\n你所做的只是修改了这个变量, 你没有做其他的事情,\n\n176\n00:09:39,513 --> 00:09:41,379\nokay? So that var is set to 0.5 and\nokay? 因此当变量变为 0.5\n\n177\n00:09:41,381 --> 00:09:44,616\nif the face were to redraw, it would redraw smaller but\n人脸的视图进行重绘, 它会被绘制的更小\n\n178\n00:09:44,618 --> 00:09:49,020\nnothing is causing the face to redraw. So any time you have\n但是重绘的事件没有被触发。 所以任何时候\n\n179\n00:09:49,022 --> 00:09:53,625\nthese public vars that you allow to be set, you need to\n你允许这些公共的变量可以被修改的时候,\n\n180\n00:09:53,627 --> 00:09:57,562\nmake it so that when they change, the viewer redraws.\n你需要在属性改变时重绘视图。\n\n181\n00:09:57,564 --> 00:10:00,298\nOkay, now how are we gonna do that? Well we're gonna do that\nOkay, 现在我们该怎么做? 我们用之前讲到的属性观察器\n\n182\n00:10:00,300 --> 00:10:03,935\nusing these property observers we talked about before.\n来实现这个功能。\n\n183\n00:10:03,937 --> 00:10:07,172\nRemember, the dil, didSet and the willSet? These are little\n还记得 didSet 和 willSet 吗? 它们都是一小段代码\n\n184\n00:10:07,174 --> 00:10:10,475\npieces of code that get executed whenever this,\n这种情况下每当变量被赋值或者访问的时候就会触发,\n\n185\n00:10:10,477 --> 00:10:15,246\nin this case get set, okay? So if this got set to something\nokay? 因此如果该变量被赋值\n\n186\n00:10:15,248 --> 00:10:19,117\nthen in didSet, I wanna re-draw, and how do I re-draw?\n然后会进入 didSet 代码段, 我想要重绘, 那么我该如何重绘?\n\n187\n00:10:19,119 --> 00:10:24,756\nMaybe I say self.drawRect do I do that? No,\n也许我需要调用 self.drawRect 我要这么做吗? 不,\n\n188\n00:10:24,758 --> 00:10:27,926\nI would fail this class if I did that cuz we never call\n在类中这样做会失败， 因为我们永远都不能调用\n\n189\n00:10:27,928 --> 00:10:32,831\ndrawRect. We say instead setNeedsDisplay, okay,\ndrawRect。 我们说过使用 setNeedsDisplay 替代， okay，\n\n190\n00:10:32,833 --> 00:10:38,169\nsetNeedsDisplay is how we tell the system, please I need to\nsetNeedsDisplay 的作用是我们告诉系统， 我需要被重绘，谢谢。\n\n191\n00:10:38,171 --> 00:10:42,207\nbe redrawn, okay. And it will happen sometime in the future,\nokay。 重绘会在未来的某个时刻执行,\n\n192\n00:10:42,209 --> 00:10:45,043\nvery close near future but sometime in the future.\n非常接近的时刻，但是是在未来.\n\n193\n00:10:45,045 --> 00:10:48,380\nNow, this is so common to do this. Usually we will take out\n现在, 这种做法非常普遍。 通常我们会清除掉一些换行，\n\n194\n00:10:48,382 --> 00:10:51,349\na little bit of these character-turns here and\n\n\n195\n00:10:51,351 --> 00:10:55,987\nput this all on the same line. Okay, like that. And\nOkay, 就像这样。\n\n196\n00:10:55,989 --> 00:10:59,524\nwe're gonna put this after all of our little vars here.\n我们要在所有的变量后面增加观察器。\n\n197\n00:10:59,526 --> 00:11:02,861\nSo I'm gonna put it in the place of the comment there.\n它要占用注释的位置了。\n\n198\n00:11:02,863 --> 00:11:07,565\nPut one there. The same thing here just so you can easily\n在这里摆放一个。 这里也是相同的操作，你很容易发现\n\n199\n00:11:07,567 --> 00:11:11,302\nsee it cuz they're a little bit screen real estate\n它会造成屏幕的空间有些挤。\n\n200\n00:11:11,304 --> 00:11:14,205\nchallenged here. All right, so now all of these vars,\n好的, 所有的这些变量,\n\n201\n00:11:14,207 --> 00:11:17,475\nif someone sets it, it's gonna cause this thing to redraw.\n如果有人设置了它们, 就会引起重绘。\n\n202\n00:11:17,477 --> 00:11:18,777\nWhat's really cool is if they set three or\n如果变量中的三个或四个可以一次性地进行重绘那该多酷\n\n203\n00:11:18,779 --> 00:11:21,746\nfour of them right in a row, it's not gonna redraw three or\n而不会引起三四次的重复绘制。\n\n204\n00:11:21,748 --> 00:11:23,782\nfour times. It's gonna keep saying,\n它会不断地说,\n\n205\n00:11:23,784 --> 00:11:25,750\nI need to be displayed, I need to be displayed,\n我需要被显示，我需要被显示，\n\n206\n00:11:25,752 --> 00:11:25,817\nI need to be displayed.\n我需要被显示。\n\n207\n00:11:25,819 --> 00:11:28,553\nBut it's not gonna actually display until a little bit\n但它不会真正地被显示，直到一段时间后\n\n208\n00:11:28,555 --> 00:11:30,822\nlater, and they'll all get displayed at once.\n它们才会被一次性地重绘。\n\n209\n00:11:30,824 --> 00:11:33,458\nSo it's much more better performance to delay,\n所以延迟可以提升性能，\n\n210\n00:11:33,460 --> 00:11:37,128\nslightly, to do these things. That's not even the primary\n对这种问题不要太过于重视，这不是主要原因。\n\n211\n00:11:37,130 --> 00:11:39,164\nreason this is, does, it does it this way, but\n实际上 setNeedsDisplay 方法本来就是这样设计的, 不过\n\n212\n00:11:39,166 --> 00:11:44,135\nit's one of the reasons, okay? Everybody got that?\n这只是其中的一个原因, okay? 每个人都理解了吗?\n\n213\n00:11:44,137 --> 00:11:46,438\nOkay, so we're almost always gonna use this didSet.\nOkay, 我们几乎经常会用到 didSet。\n\n214\n00:11:46,440 --> 00:11:48,373\nNow you're gonna see we're using the didSet in\n现在你会看到我们在控制器中\n\n215\n00:11:48,375 --> 00:11:50,975\nthe controller as well for a slightly different reason,\n因为一些其他的原因使用 didSet\n\n216\n00:11:50,977 --> 00:11:53,111\nokay? But the did, didSet is super convenient.\nokay? 不过 didSet 真的是超级方便！\n\n217\n00:11:53,113 --> 00:11:57,415\nAll right, okay so let's talk about our controller here,\n好吧, okay 让我们来聊聊控制器，\n\n218\n00:11:57,417 --> 00:12:02,020\nit needs a model, okay. I have created a little class over\n它需要一个模型， okay。 我已经创建好了一个简单的类\n\n219\n00:12:02,022 --> 00:12:06,591\nhere called FacialExpression, which I'm gonna drag in.\n叫做 FacialExpression， 现在我把它拖进工程。\n\n220\n00:12:06,593 --> 00:12:09,461\nI'm gonna copy it in here, okay? When you draw things in,\n我把它复制进来, okay? 当你向工程总拖拽东西的时候,\n\n221\n00:12:09,463 --> 00:12:10,995\nyou almost always want this selected.\n你几乎总是会把这一项选中。\n\n222\n00:12:10,997 --> 00:12:12,997\nSo pay attention to that, you want it to copy in, you don't\n所以注意一下, 你希望它拷贝进来,\n\n223\n00:12:12,999 --> 00:12:16,134\nreally want it having a link to the other thing,\n你不希望它链接到别的东西上面\n\n224\n00:12:16,136 --> 00:12:16,267\nmost of the time.\n大部分情况下都是这样。\n\n225\n00:12:16,269 --> 00:12:19,537\nSo I'm gonna copy this little FacialExpression in.\n所以我要把这个小小的 FacialExpression 拷贝进来.\n\n226\n00:12:19,539 --> 00:12:22,474\nLet's take a look at FacialExpression. You'll see\n让我们来看看 FacialExpression。\n\n227\n00:12:22,476 --> 00:12:25,910\nwe'll see FacialExpression right here, is our model.\n你会在这里看到 FacialExpression，它是我们的模型。\n\n228\n00:12:25,912 --> 00:12:28,646\nSee, it's not a UI thing, it imports only foundation.\n看到了吗，它不是 UI 方面的东西，它仅仅引入了 foundation。\n\n229\n00:12:28,648 --> 00:12:31,549\nIt's completely UI independent. Its idea of\n它完全地与 UI 分离。 它对一张脸的描述\n\n230\n00:12:31,551 --> 00:12:34,586\na face is not really the same as a face view. Okay,\n和 face view 不同。 Okay,\n\n231\n00:12:34,588 --> 00:12:37,388\na face view thinks of mouth curvature and eyebrow tilt and\nface view 考虑的是嘴巴的曲率、眼睛的弧度以及\n\n232\n00:12:37,390 --> 00:12:40,125\nthings like that. This doesn't have any of that. It\n这方面的东西。完全不包含这个模型里的东西。\n\n233\n00:12:40,127 --> 00:12:44,262\ndoes have eyebrows but it just has Relaxed, Normal, Furrowed.\n它包含了眉毛的信息，但是只有 Relaxed, Normal, Furrowed这样的描述。\n\n234\n00:12:44,264 --> 00:12:46,965\nThat's the only thing it knows about, those three states.\n这三个状态是它唯一知道的。\n\n235\n00:12:46,967 --> 00:12:50,001\nSame thing with Mouth. It's Frown, Smirk, Neutral, Grin,\n嘴巴也是一样。 它的状态是 Frown, Smirk, Neutral, Grin 以及 Smile。\n\n236\n00:12:50,003 --> 00:12:52,704\nSmile. That's it, it doesn't have mouth curvature.\n它就是这样，不包含嘴的曲率。\n\n237\n00:12:52,706 --> 00:12:53,872\nIt doesn't even know what that is,\n它甚至不知道曲率什么，\n\n238\n00:12:53,874 --> 00:12:57,509\nokay? One thing kinda cool here, you see these are enums?\nokay? 有一件很有趣的事情，你看到了吗这些都是枚举?\n\n239\n00:12:57,511 --> 00:13:00,745\nNotice I have functions on my enums here, okay?\n请注意我在枚举中定义了方法， okay?\n\n240\n00:13:00,747 --> 00:13:03,114\nI'm not gonna talk about the implementation of those.\n我不打算讨论这些方法的实现.\n\n241\n00:13:03,116 --> 00:13:04,249\nIf you read the reading assignment,\n如果你读了作业题目,\n\n242\n00:13:04,251 --> 00:13:06,684\nyou should be able to figure these out. But\n你应该可以计算出这些。\n\n243\n00:13:06,686 --> 00:13:09,187\nI got some functions in here with my enums. But\n我在枚举中定义了方法。 但是\n\n244\n00:13:09,189 --> 00:13:12,490\nreally facial expression is just the eyes, eyebrows, and\n面部表情依然只有眼睛、眉毛和嘴巴。\n\n245\n00:13:12,492 --> 00:13:15,660\nmouth, okay, which is specified by these enums. And\nokay,使用了这些枚举来表达。\n\n246\n00:13:15,662 --> 00:13:18,463\nsome of the enums like eyes even has a state\n枚举中的一部分，比如眼睛，包含了 FaceView 中没有出现的状态。\n\n247\n00:13:18,465 --> 00:13:21,900\nFaceView can't even represent that face. It doesn't have\nFaceView并没有包含一个眯着的眼睛。\n\n248\n00:13:21,902 --> 00:13:23,868\na Squinting, it only knows how to have eyes open and\n它只知道如何控制眼睛的睁开与闭合。\n\n249\n00:13:23,870 --> 00:13:27,705\nclosed. So the point here is that this model has to be\n这里的要点是模型需要被控制器解释给视图\n\n250\n00:13:27,707 --> 00:13:31,643\ninterpreted by the controller for that view, okay?\nokay?\n\n251\n00:13:31,645 --> 00:13:35,213\nThe mo, the controller's gonna have to figure out, okay,\n此外，控制器必须弄清楚， okay,\n\n252\n00:13:35,215 --> 00:13:37,282\nwhat does relaxed eyebrow mean? Well, for\n一个 relaxed 的眉毛是什么意思? 好的，\n\n253\n00:13:37,284 --> 00:13:39,818\nthe face view it means some sort of of eyebrow tilt, and\n对脸的视图来说，它意味着眉毛的某种倾斜程度,\n\n254\n00:13:39,820 --> 00:13:42,253\nso the controller has to figure out what that is, and\n所以控制器需要把 relaxed 解释给视图，\n\n255\n00:13:42,255 --> 00:13:45,824\ntell the view, you see? So this shows the primary\n看到了吗? 所以这里就解释了控制器在 MVC 中的原始角色\n\n256\n00:13:45,826 --> 00:13:50,128\nrole of a controller in your MVC is to interpret\n就是把模型\n\n257\n00:13:50,130 --> 00:13:51,563\nthe model for the view.\n解释给视图。\n\n258\n00:13:51,565 --> 00:13:54,065\nIt also interprets input in the view for the model and\n它也会把视图中的输入值解释给模型\n\n259\n00:13:54,067 --> 00:13:56,401\nwe'll see that when we talk about gestures, okay.\n我们会在讲到手势的时候见到， okay.\n\n260\n00:13:56,403 --> 00:13:59,003\nThat's its kind of primary purpose in the controller.\n这就是控制器的原始目的。\n\n261\n00:13:59,005 --> 00:14:01,072\nSo let's make our controller do that,\n所以让我们的控制器来做这件事吧。\n\n262\n00:14:01,074 --> 00:14:04,943\nlet's make it turn a facial expression into something in\n我们把 facial expression 转换成\n\n263\n00:14:04,945 --> 00:14:09,180\nthe face view, okay. So in our controller, the first thing\n视图中的信息， okay。 所以在控制器中，我们要做的第一件事\n\n264\n00:14:09,182 --> 00:14:11,749\nwe're gonna do is we're gonna create a var here,\n就是在这里创建一个变量，\n\n265\n00:14:11,751 --> 00:14:14,953\nwhich is a pointer to our model, and it's just gonna be\n它是一个指向模型的指针, 它是 FacialExpression 类型的\n\n266\n00:14:14,955 --> 00:14:17,121\na FacialExpression, okay. And we are even\nokay。 我们甚至\n\n267\n00:14:17,123 --> 00:14:19,824\ngonna set it to some facial expression to start it off\n会把它初始化为某种面部表情。\n\n268\n00:14:19,826 --> 00:14:22,994\nhere. Remember we, with the FacialExpression, which is\n记住，我们使用的 FacialExpression，\n\n269\n00:14:22,996 --> 00:14:28,032\na struct by the way, we get the free constructor. I,\n是一个结构体,我们可以使用免费得到的构造器。 我,\n\n270\n00:14:28,034 --> 00:14:31,069\nby the way, I can infer this. I don't need to have that,\n顺便提一句，我可以推断它的类型。 我不需要写出来，\n\n271\n00:14:31,071 --> 00:14:34,272\nright? So I get the free constructure which is what,\n对吗? 我得到的这个免费的构造器中,\n\n272\n00:14:34,274 --> 00:14:40,678\neyes are we'll have them be open, and then eyeBrows.\n我们让眼睛睁开, 然后是眉毛。\n\n273\n00:14:41,114 --> 00:14:44,749\nWe'll have him be normal. I think is what it is,\n我们让眉毛是普通的。我认为它是这样的：普通\n\n274\n00:14:44,751 --> 00:14:48,820\nnormal. And then, we'll have mouth, which will have,\n然后我们设置嘴巴，\n\n275\n00:14:48,822 --> 00:14:55,293\nbe a smile I'd say, okay? So this is gonna be our default\n像我说过的一个微笑的嘴巴， okay? 这就是\n\n276\n00:14:55,395 --> 00:14:58,963\nvalue of our facial expression.\n我们的面部描述的默认值。\n\n277\n00:14:58,965 --> 00:15:00,732\nSo this is the model for our MVC.\n这就是我们的 MVC 中的模型。\n\n278\n00:15:00,734 --> 00:15:05,536\nNow what's interesting about this model is what if it\n现在这个模型中有趣的部分是\n\n279\n00:15:05,538 --> 00:15:09,741\nchanges? Okay, if it changes, I need to update my view.\n如何改变它? Okay, 如果它发生了改变, 我需要更新我的视图。\n\n280\n00:15:09,743 --> 00:15:15,046\nAll right, if, if it changes from smile to a frown\n好的, 如果, 如果它从微笑变成了皱眉\n\n281\n00:15:15,048 --> 00:15:18,917\nI need to change my curvature of my face view. So I'm gonna\n我需要改变视图中的曲率。 所以我要\n\n282\n00:15:18,919 --> 00:15:23,321\nuse that same magic the didSet thing that we did before to\n使用 didSet 的魔法就像我们之前做的那样\n\n283\n00:15:23,323 --> 00:15:27,692\nupdate my UI whenever this facial expression changes.\n当模型发生改变的时候更新 UI。\n\n284\n00:15:27,694 --> 00:15:31,229\nAnd since this is a value type FacialExpression,\n因为这个值的类型是 FacialExpression,\n\n285\n00:15:31,231 --> 00:15:34,465\nif any of the vars in that value type change,\n如果这个变量中的任何属性发生了变化，\n\n286\n00:15:34,467 --> 00:15:37,302\nthis didSet is gonna get called, okay?\ndidSet 就会被调用, okay?\n\n287\n00:15:37,304 --> 00:15:40,104\nIf this were a class, it wouldn't. So\n如果模型是一个类则不会调用 didSet。\n\n288\n00:15:40,106 --> 00:15:43,675\nluckily it's value type. So this is gonna get called. So\n所以庆幸它是个值类型。这部分将会被调用。\n\n289\n00:15:43,677 --> 00:15:46,945\nwe need this update UI. This can be any function we call.\n所以我们需要方法更新 UI。 我们可以在这里调用任何方法。\n\n290\n00:15:46,947 --> 00:15:48,680\nI like calling it function, updateUI, but\n我喜欢把这个方法取名为 updateUI。\n\n291\n00:15:48,682 --> 00:15:52,417\nyou can do whatever you want. And it's gonna be private,\n你可以取自己喜欢的名字。 这个方法应该是 private 的,\n\n292\n00:15:52,419 --> 00:15:53,184\nit's a func updateUI.\n现在我们有了 updateUI 方法。\n\n293\n00:15:53,186 --> 00:15:56,387\nAnd inside here we have to update our faceView.\n在它的内部我们需要更新 faceView。\n\n294\n00:15:56,389 --> 00:15:59,123\nOkay well, if we're gonna update our face view, we need\n好的, 如果我们想要更新我们的 faceview，我们需要\n\n295\n00:15:59,125 --> 00:16:02,860\na pointer to that as well. Okay, how do we make a pointer\n一个指向它的指针。 Okay, 我们该怎样创建一个视图的指针？\n\n296\n00:16:02,862 --> 00:16:06,331\nto something in our view? >> Click drag.\n>> 单击并且拖动。\n\n297\n00:16:06,333 --> 00:16:08,232\nYeah we click, we ctrl drag, right?\n我们点击，然后拖动，对吧?\n\n298\n00:16:08,234 --> 00:16:09,867\nWe made an outlet. So let's just do that.\n我们创建了一个 outlet。 动起手来吧.\n\n299\n00:16:09,869 --> 00:16:13,037\nLet's bring our storyboard up here. We've got our face view.\n打开 storyboard。我们已经得到了 face view。\n\n300\n00:16:13,039 --> 00:16:15,640\nHere's our controller right here. I'm just gonna control\n控制器在这里。 我将要\n\n301\n00:16:15,642 --> 00:16:18,509\ndrag from the face view into here and I'm gonna create\n把 faceView 拖动到这里然后创建一个\n\n302\n00:16:18,511 --> 00:16:21,679\nan outlet. I'm gonna to call it face view. It's my face\noutlet。 取名为face view。它就是我的小人脸\n\n303\n00:16:21,681 --> 00:16:24,782\nview, okay. We used display in our calculator. This is our\nokay。 我们在计算器项目中使用过它进行显示。 这既是我们的小人脸\n\n304\n00:16:24,784 --> 00:16:30,588\nface view. We click okay here and now we've got this outlet,\n我们点击这里的 okay 选项，然后我们得到了一个 outlet，\n\n305\n00:16:30,590 --> 00:16:32,156\nokay. So now we've got a pointer to this face.\nokay. 现在我们得到了一个指向人脸的指针.\n\n306\n00:16:32,158 --> 00:16:35,226\nSo now we can talk to this face set it's curvatures and\n接着我们会谈谈如何设置人脸的曲率以及\n\n307\n00:16:35,228 --> 00:16:37,628\nall that business, right?\n所有的这些逻辑，怎么样?\n\n308\n00:16:37,630 --> 00:16:42,333\nSo, now we've got a pointer to this in our update UI.\n现在我们得到了这个指针以及 updateUI 方法。\n\n309\n00:16:42,335 --> 00:16:44,969\nWe can just talk to it and set it based on what\n我们可以自由讨论视图并且基于面部表情来配置视图。\n\n310\n00:16:44,971 --> 00:16:46,838\nthe expression is. So how are we gonna do that?\n所以我们该怎么做呢?\n\n311\n00:16:46,840 --> 00:16:50,008\nAll right, well first of all let's start with the eyes. So\n好吧，首先从眼睛开始吧。\n\n312\n00:16:50,010 --> 00:16:55,313\nif the facial expression's eyes are in the state\n如果面部描述中的眼睛是睁开的，\n\n313\n00:16:55,315 --> 00:16:59,817\nopen, then we're gonna send a message to our faceView saying\n然后我们就需要向 faceView 发送一条消息告知它\n\n314\n00:16:59,819 --> 00:17:03,221\neyes open equals true. So that's an easy one okay our\n眼睛睁开的选项是 ture。这很容易办到，\n\n315\n00:17:03,223 --> 00:17:06,391\nface views very similar to our model in that way, and\n在眼睛的配置上模型和视图是相近的，\n\n316\n00:17:06,393 --> 00:17:10,461\nsame thing here closed. We'll do faceview.eyesopen\nclosed 选项的操作也很相近。 我们会把 faceview.eyesopen\n\n317\n00:17:10,463 --> 00:17:15,066\nequals false but what about case squinting?\n设置为 false 但是 squinting 的情况该怎么办?\n\n318\n00:17:15,502 --> 00:17:19,137\nOkay, we don't really have faceView.squint, okay we can't\nOkay, 实际上我们没有 faceView.squint 这样的属性, 好吧\n\n319\n00:17:19,139 --> 00:17:23,307\ndo that. So I'm just gonna say eyes open equals false.\n我们办不到。 所以我只能写 eyes open 为 false.\n\n320\n00:17:23,309 --> 00:17:26,878\nif you are squinting, eyes are closer to closed than they\n如果你是 squinting（斜视）的表情, 眼睛闭上的状态更加贴近一些。\n\n321\n00:17:26,880 --> 00:17:28,913\nare to open, okay. So it is the best I can do,\nokay。 这是我们实现的最好方案，\n\n322\n00:17:28,915 --> 00:17:31,482\nand this is the way some times a controller is. It's\n这就是有时候控制器所发挥的作用。\n\n323\n00:17:31,484 --> 00:17:34,886\nview might not be perfect at representing the model, it's\n这个视图可能并不能很好地展示视图，\n\n324\n00:17:34,888 --> 00:17:37,488\ndoing the best it can. Now it might be, we might be sending\n它只能尽力做到最好。现在控制器是这样做的，我们可能会向 face view 中的某一位\n\n325\n00:17:37,490 --> 00:17:40,091\nin a request to the face view guys on our team saying hey,\n发送一个请求，告诉它：嘿，伙计\n\n326\n00:17:40,093 --> 00:17:42,460\nwe wanna feature where our face view will do squinting\n我们想让视图能够展示 squinting\n\n327\n00:17:42,462 --> 00:17:44,929\nbecause we got squinting in our model. And they might be,\n因为我们从模型中得到了一个 squinting 。某些视图可能就会照做，\n\n328\n00:17:44,931 --> 00:17:47,465\nokay we'll take it under advisement and we'll see.\n好吧我们会采纳的，让我们看一下怎么做。\n\n329\n00:17:47,467 --> 00:17:48,833\nBut for now we're kind of stuck.\n但是现在我们陷入了困境。\n\n330\n00:17:48,835 --> 00:17:53,438\nSo we're gonna do squinting is the same as eyes closed.\n所以我们在处理 squinting 的时候只能让眼睛和 closed 中的情况一样。\n\n331\n00:17:53,440 --> 00:17:54,939\nHow about our other two things? Okay,\n那么其他两样东西会怎样呢? Okay，\n\n332\n00:17:54,941 --> 00:17:56,374\nwe've got these curvatures to deal with, right?\n我们有这些曲率需要处理，对吧?\n\n333\n00:17:56,376 --> 00:18:01,512\nSo, we want to say something like faceView.mouthCurvature =\n我们想要写 faceView.mouthCurvature =\n\n334\n00:18:01,514 --> 00:18:05,650\nsomething based on the expression's mouth. But\n模型中关于嘴部曲率描述的值。\n\n335\n00:18:05,652 --> 00:18:08,553\nthe expression's mouth is like grin and frown.\n嘴巴的描述就像 grin 和 frown。\n\n336\n00:18:08,555 --> 00:18:09,187\nWhat the heck are we gonna do?\n我们要做些什么?\n\n337\n00:18:09,189 --> 00:18:11,289\nHow are we gonna convert that to a curvature?\n我们该如何把它们转化成曲率?\n\n338\n00:18:11,291 --> 00:18:11,856\nAnd what I'm gonna do is,\n现在我就来解决这个问题，\n\n339\n00:18:11,858 --> 00:18:16,360\nI'm actually going to create a little private dictionary,\n我想要创建一个轻量的私有的字典，\n\n340\n00:18:16,362 --> 00:18:21,199\nI'm gonna call it mouthCurvatures. Okay, plural\n我会给它取名为 mouthCurvatures. Okay, 一对括号\n\n341\n00:18:21,201 --> 00:18:25,002\nand I'm gonna make it equal to a dictionary. Remember,\n并且我要让它等于一个字典。 记住，\n\n342\n00:18:25,004 --> 00:18:27,338\nwe can make a dictionary on the fly with square brackets.\n我们可以使用一对方括号创建一个字典。\n\n343\n00:18:27,340 --> 00:18:30,541\nAnd then I'm gonna have the keys of this dictionary be\n接下来我准备给这个字典设置一些键值来匹配\n\n344\n00:18:30,543 --> 00:18:31,909\nmouthCurvatures for my model and\n模型中的嘴巴曲率。\n\n345\n00:18:31,911 --> 00:18:35,146\nI'm gonna have the values be mouthCurvatures for my view.\n字典的值对应了视图中的嘴巴曲率。\n\n346\n00:18:35,148 --> 00:18:40,118\nOkay, doubles. All right, so for example let's do\n好的， double 类型。举个例子，让我们增加一个新的成员\n\n347\n00:18:40,120 --> 00:18:44,722\nFacialExpression.Mouth.Frown. Okay, that's\nFacialExpression.Mouth.Frown。 Okay, 这是键值。\n\n348\n00:18:44,724 --> 00:18:47,892\nthe key. And the values gonna be -1.0 that's the curvature\n对应的值为 -1.0，这是该种状态的嘴巴的曲率。\n\n349\n00:18:47,894 --> 00:18:50,194\nthat goes along with that. See what I'm saying? So\n看到了我所说的了吗?\n\n350\n00:18:50,196 --> 00:18:52,497\nI'm just creating this dictionary that's mapping\n我创建这个字典的目的是\n\n351\n00:18:52,499 --> 00:18:59,103\nbetween my model and my view. So how about Grin? Notice but\n映射模型与视图中的值。 那么 Grin（咧嘴）该是什么样?\n\n352\n00:18:59,105 --> 00:19:02,473\nby the way, when I do Grin, okay, it's already inferred to\n顺便说一句， 当我咧嘴的时候, okay, 系统的类型推断已经推测出了字典的键是\n\n353\n00:19:02,475 --> 00:19:04,342\nthe fact that we're doing a FacialExpression.Mouth.\n一个 FacialExpression.Mouth 类型的。\n\n354\n00:19:04,344 --> 00:19:07,578\nSo and I do, don't need to repeat this every single time.\n因此我会这样做, 不需要每次都重复写前缀。\n\n355\n00:19:07,580 --> 00:19:10,448\nI can just say the Grin. and the Grin, we'll say, is 0.5.\n我可以只写 Grin。我们把 Grin 设定为 0.5。\n\n356\n00:19:10,450 --> 00:19:12,617\nSo it's not a full smile, just kind of a little bit\n所以它不是开怀大笑，只是微微一笑的程度。\n\n357\n00:19:12,619 --> 00:19:16,854\nof a smile. But a full smile would be 1.0 and\n开怀大笑的曲率是 1.0\n\n358\n00:19:16,856 --> 00:19:22,660\na Smirk, now that sounds kinda like a little bit of a frown,\n一个 Smirk（傻笑）, 听起来有点像皱眉，\n\n359\n00:19:22,662 --> 00:19:23,227\nbut not too much of one.\n但是不是同一个表情。\n\n360\n00:19:23,229 --> 00:19:27,165\nSo, we'll -0.5 right there and then there's this neutral\n我们把这种表情的值设为 -0.5\n\n361\n00:19:27,167 --> 00:19:31,736\nmouth position which we'll have be zero point zero. Okay,\n最后还有一个 Neutral（中立）的表情，把它的值 设为 0.0。Okay，\n\n362\n00:19:31,738 --> 00:19:34,172\nso, I created these mouth curvatures in a table. So now,\n我把嘴巴的曲率装进了一个列表中。 现在，\n\n363\n00:19:34,174 --> 00:19:38,242\ndown here, I can just let my mouth curvature equal mouth\n完成了, 我可以把模型的 mouth 属性所提供的信息转换成\n\n364\n00:19:38,244 --> 00:19:42,780\ncurvatures sub expression.mouth.\n嘴巴视图的曲率。\n\n365\n00:19:42,782 --> 00:19:45,683\nOkay, now the problem with this, and you can see there's\nOkay, 现在遇到了问题，你可以看到这里有一个报错。\n\n366\n00:19:45,685 --> 00:19:49,420\nan error here. And can anyone see what the problem here is?\n所有人都能看到这里出问题了吧?\n\n367\n00:19:49,822 --> 00:19:53,824\nThis is a dictionary lookup. What is a dictionary lookup?\n这是一个字典的查找。 字典的查找是什么?\n\n368\n00:19:53,826 --> 00:19:56,861\nWhat type does it return? Optional,\n它返回什么类型? 可选型。\n\n369\n00:19:56,863 --> 00:20:00,965\nyeah, so this is a double. It's not an optional, okay?\n耶， 这是个小麻烦。 它不是个可选型， okay?\n\n370\n00:20:00,967 --> 00:20:02,200\nSo how are we gonna deal with this?\n所以我们该如何处理?\n\n371\n00:20:02,202 --> 00:20:07,972\nWhat if facial expression gets enhanced some future date and\n如果 Facial Expression 未来增加一些特性并且\n\n372\n00:20:07,974 --> 00:20:10,107\nthe expression's not in here?\n这些新的表情不在这个字典里该怎么办?\n\n373\n00:20:10,109 --> 00:20:14,345\nI'm going to have it default to zero. Okay?\n我把它的默认值设为 0.0。 Okay?\n\n374\n00:20:14,347 --> 00:20:18,749\nRemember this defaulting thing right here where you can take\n记得在这里设置一个默认值\n\n375\n00:20:18,751 --> 00:20:23,020\nsomething that's a double and if it turns into to nil if it\n当你想要获取某个 double 类型的值，当它遇到nil时\n\n376\n00:20:23,022 --> 00:20:27,024\nreturns nil then you can have a default value there,\n你会得到一个默认的 double 值,\n\n377\n00:20:27,026 --> 00:20:30,361\nmake sense? Var there. Okay, everyone's\n明白了吗? 这里加上 var。 Okay\n\n378\n00:20:30,363 --> 00:20:34,131\ncool with what I did there? All right, hopefully if you\n我这里的处理很酷吧? 好的， 希望你在计算器项目中用到过它\n\n379\n00:20:34,133 --> 00:20:36,300\nsolve it from calculator it's very similar to that,\n这里和那个项目中的情况很像。\n\n380\n00:20:36,302 --> 00:20:38,636\nlooking things up in the dictionary. So I'm gonna\n在字典中查找东西。 接下来\n\n381\n00:20:38,638 --> 00:20:41,038\ndo with the same thing with the eyebrow tilt okay\n我要给眉毛的曲率做相同处理。 okay\n\n382\n00:20:41,040 --> 00:20:44,208\nthe eyeBrowTilt equals eyeBrowTilts\neyeBrowTilt 等于 eyeBrowTilts（一个待生成的字典）\n\n383\n00:20:44,210 --> 00:20:48,446\nwhich is gonna be a dictionary and I'm gonna put the,\n并且我要用一个 expression.eyebrows 作为索引。\n\n384\n00:20:48,448 --> 00:20:53,651\na facial expression.eyebrows in there and\n然后当我们查找不到的时候\n\n385\n00:20:53,653 --> 00:20:57,822\nalso default that one to zero if we can't find it. And\n依旧设置为 0.0。\n\n386\n00:20:57,824 --> 00:20:59,991\nthen I'll just make a private var here,\n接下来我在这里定义一个私有变量，\n\n387\n00:20:59,993 --> 00:21:02,393\nwe'll call it eyeBrowTilts And\n取名为 eyeBrowTilts\n\n388\n00:21:02,395 --> 00:21:09,000\nthis one we'll do FacialExpression.Eyebrows.\n用来处理 FacialExpression.Eyebrows。\n\n389\n00:21:09,002 --> 00:21:11,669\nWhat do we got here, relaxed: so\n这里需要填写的东西有 relaxed\n\n390\n00:21:11,671 --> 00:21:16,707\nwe'll have relaxed be a CGFloat, which is 0.5, so\n我们要把 relaxed 解释成一个 CGFloat，值为 0.5，\n\n391\n00:21:16,709 --> 00:21:20,211\nit's kind of relaxed eyebrows notice I.\n这是一种放松的眉毛。注意\n\n392\n00:21:20,213 --> 00:21:23,681\nOops not CGFloat, that's 0.5 okay that's a double,\n它不是 CGFloat，字面量是 0.5 okay 所以它是一个 double，\n\n393\n00:21:23,683 --> 00:21:25,583\nokay the eyebrow tilts are doubles.\nokay 现在眉毛的倾斜度是 double 类型了。\n\n394\n00:21:25,585 --> 00:21:29,220\nSo we don't I did not want CG float there.\n这里我们不想要一个 CGFloat 类型。\n\n395\n00:21:29,222 --> 00:21:35,092\nOkay how about .furrowed is -0.5 tilt and\nOkay .furrowed 是 -0.5 的倾斜度\n\n396\n00:21:35,094 --> 00:21:41,132\n.normal we'll make be 0. Okay?\n.normal 我们设为 0。 Okay?\n\n397\n00:21:41,968 --> 00:21:46,337\nGot that? All make sense? So we are doing the same look up\n明白了吗? 所有人都明白了吗? 我们这里做了相同的查找。\n\n398\n00:21:46,339 --> 00:21:51,309\nthere. Okay so we've matched up our model with our view.\n我们把模型与视图进行了配对。\n\n399\n00:21:51,311 --> 00:21:54,945\nWe've kind of interpreted our model for view. Now,\n我们创建了一个为视图解释模型的控制器。 现在，\n\n400\n00:21:54,947 --> 00:21:59,150\nlets go ahead and run this and see what this looks like.\n让我们继续并且运行程序，看看是什么样子。\n\n401\n00:22:04,223 --> 00:22:08,025\nOkay, now, hmm this doesn't quite look right. Because,\nOkay, 现在，这个表情看起来不太对。 因为，\n\n402\n00:22:08,027 --> 00:22:11,095\nif we look at our model it's supposed to be eyes open.\n如果你查看我们的模型就会发现，从模型中看眼睛应该睁开。\n\n403\n00:22:11,097 --> 00:22:13,931\nOkay, that's good. Eyebrows normal. No.\nOkay, 这很棒。 眉毛是 normal。不。\n\n404\n00:22:13,933 --> 00:22:16,200\nThose are not normal eyebrows, those are kinda furrowed.\n屏幕上的眉毛不是 normal 的。没有有点皱。\n\n405\n00:22:16,202 --> 00:22:20,071\nAnd mouth is supposed to be smile. Hmm, no, it's a frown.\n并且嘴巴应该是 smile。 恩...， 不，这是一个 frown（愁眉苦脸） 的嘴型。\n\n406\n00:22:20,073 --> 00:22:24,175\nIn fact, all of this here instead of the UI looking like\n实际上，所有的这些面部表情不像是模型所表达的，\n\n407\n00:22:24,177 --> 00:22:28,212\nthe model it still looks like we set it in the storyboard.\n而是 storyboard 上的。\n\n408\n00:22:28,214 --> 00:22:32,717\nOkay, so, why is it that our update UI is not getting\nOkay，那么，为什么当我们初始化一个表情的时候\n\n409\n00:22:32,719 --> 00:22:37,188\ncalled here when we initialize our facial expression?\n我们更新 UI 的逻辑没有实现呢？\n\n410\n00:22:37,190 --> 00:22:39,957\nThat's because if you're setting a value during\n这是因为当你通过构造器初始化一个值的时候\n\n411\n00:22:39,959 --> 00:22:44,929\ninitialization, didSet is not called. Okay?\ndidSet 不会执行。 Okay?\n\n412\n00:22:44,931 --> 00:22:48,966\nIt's only called if you set it later. Now why is that?\n当你稍后对它赋值的时候 didSet 才会执行。这是为什么 ？\n\n413\n00:22:48,968 --> 00:22:52,169\nBecause you know that when things are being initialized\n因为你知道的在 Swift 中，当对象被初始化的时候，\n\n414\n00:22:52,171 --> 00:22:54,305\nin Swift, they have to be fully initialized before\n在你对它做任何操作之前，\n\n415\n00:22:54,307 --> 00:22:57,241\nyou can do anything with them. So of course, they have to be\n它必须被完全初始化。 所以理所当然的，当你想对 expression\n\n416\n00:22:57,243 --> 00:22:59,009\nfully initialized before you can do any of this\n做任何修改时，它必须被完全初始化。\n\n417\n00:22:59,011 --> 00:23:03,581\nstuff either. Okay? So, this initialization did happen, but\nOkay? 因此,这个对象已经初始化了, 但是\n\n418\n00:23:03,583 --> 00:23:05,983\nthis, you updateUI didn't get called because this was\n你的 updateUI 没有被调用，因为\n\n419\n00:23:05,985 --> 00:23:07,918\nhappening during the initialization phase of our\nexpression 的初始化过程发生在\n\n420\n00:23:07,920 --> 00:23:10,821\nfaceView controller. Now, if we were to set the expression\nfaceView controller 的初始化过程中。 现在， 如果我们稍后去设置 expression\n\n421\n00:23:10,823 --> 00:23:14,325\nlater, this would get called, our UI would change. So,\nupdateUI 方法会被调用。 我们的 UI 会发生改变。所以，\n\n422\n00:23:14,327 --> 00:23:16,927\nhow do we deal with that? Okay, what we are gonna do\n我们该如何处理？ Okay。 有些事情无论如何我们都需要做\n\n423\n00:23:16,929 --> 00:23:20,131\nthere is something we should of done anyway. Which is,\n那就是\n\n424\n00:23:20,133 --> 00:23:25,669\nwhen our face view outlet is set by the system.\n当我们的 faceView 的 outlet 被系统设置好的时候。\n\n425\n00:23:25,671 --> 00:23:30,040\nWe are gonna do didSet here and Update our UI. Okay?\n我们在它的 didSet 中更新我们的 UI。 Okay?\n\n426\n00:23:30,042 --> 00:23:35,279\nSo, this didSet is called when iOS comes along shortly after\n所以, 这里的 didSet 会在你的 MVC 创建不久之后\n\n427\n00:23:35,281 --> 00:23:39,250\nyour MVC is created, and it wires up this outlet. Okay?\n被 iOS 系统所调用, 它会关联这个 outlet。 Okay?\n\n428\n00:23:39,252 --> 00:23:42,019\nIt hooks up the outlet so it's actually pointing to that face\n系统会钩住（hook up）这个 outlet，让它指向内存中的 faceView。\n\n429\n00:23:42,021 --> 00:23:45,089\nview. So, as soon as that happens, now we have\n这样的话，只要这个过程发生，我们\n\n430\n00:23:45,091 --> 00:23:49,393\na hold of our face view. Now we can update it. Okay, so\n就会持有我们的 faceView 了。现在我们可以更新 UI 了。 Okay，所以\n\n431\n00:23:49,395 --> 00:23:51,929\nwe are updating it both when our model changes and\n当我们的模型发生变化以及我们的 faceView 第一次被系统钩住的时候，\n\n432\n00:23:51,931 --> 00:23:56,767\nthe first time our view is hooked up. Okay.\n我们都会更新 UI。 Okay。\n\n433\n00:23:56,769 --> 00:24:00,171\nAnd this is something also that we would usually\n我们经常把 didSet 与对象\n\n434\n00:24:00,173 --> 00:24:02,339\nput on the end like this.\n写在同一行。\n\n435\n00:24:07,747 --> 00:24:10,347\nOkay we might even do it here I might even leave this here\n我们可以像上面这样写，这里我的代码保持这个写法\n\n436\n00:24:10,349 --> 00:24:13,083\njust to emphasize that we're doing this but again this\n只是为了强调我们可以这么写\n\n437\n00:24:13,085 --> 00:24:16,587\nwould be a common thing to throw on the end there okay.\n不过写在末尾是更常见的写法。\n\n438\n00:24:16,589 --> 00:24:21,091\nAll right, so now let's run, now when Swift\n好的，现在运行一下，当 Swift（错说了）\n\n439\n00:24:21,093 --> 00:24:24,161\niOS basically comes along and hooks up that face view.\niOS 系统基本启动并且钩住了 faceView 之后，\n\n440\n00:24:24,163 --> 00:24:28,165\nBoom. It's going to be updated with our model, okay?\nBoom~。 faceView 就更新到模型中描述的样子了， okay?\n\n441\n00:24:28,167 --> 00:24:30,634\nAnd so now if we change our model here, let's make\n并且现在如果我们修改模型，让我们把\n\n442\n00:24:30,636 --> 00:24:35,773\nthe eyebrows be relaxed. We'll make the mouth be a smirk.\n眉毛设置为 relaxed（放松），把嘴巴设置为 smirk（傻笑）。\n\n443\n00:24:35,775 --> 00:24:39,610\nLet's get those eyes closed. Okay. And we change all of\n让眼睛闭上。 Okay。 我们改变了模型中的\n\n444\n00:24:39,612 --> 00:24:42,613\nthis in the model, then our view should be reflecting our\n所有属性， 我们的视图会按照模型进行更新。\n\n445\n00:24:42,615 --> 00:24:49,553\nmodel. Okay, and there it is. Kay? All good?\nOkay, 就是这样 Okay? 都很棒吧?\n\n446\n00:24:49,555 --> 00:24:53,057\nEveryone understand what we're doing there with our model?\n所有人都理解我们对模型做了什么事情吧?\n\n447\n00:24:53,793 --> 00:24:57,061\nOkay. So let's go back to the slides and\nOkay。 让我们回到幻灯片。\n\n448\n00:24:57,063 --> 00:25:00,030\ntalk a little bit about gestures and then we'll come\n让我们来讨论一下手势，并且我们将会回到项目中\n\n449\n00:25:00,032 --> 00:25:04,301\nback and add some gestures to our FACEIT right here.\n并且向其中增加一些手势。\n\n450\n00:25:11,711 --> 00:25:15,513\nOkay. So, we saw last time how to draw in a view.\nOkay。 所以，刚才我们看到了如何在视图中绘制。\n\n451\n00:25:15,515 --> 00:25:19,116\nWe drew the mouth, we drew the eyes, we did the eyebrows, but\n我们画了嘴、眼睛和眉毛，所有的这一切。\n\n452\n00:25:19,118 --> 00:25:22,086\nall of these things. We know how to do that pretty much,\n我们知道如何做到这一点，\n\n453\n00:25:22,088 --> 00:25:22,653\nright? We're using the use,\n对吧? 我们在绘制的区域使用了\n\n454\n00:25:22,655 --> 00:25:25,689\nUI bezier path in our draw rect, not so hard.\nUIBezierpath，并不复杂。\n\n455\n00:25:25,691 --> 00:25:29,727\nWhat about gestures? Okay? So this is input from the user on\n那么手势呢? Okay? 这是用户在屏幕上的输入方式之一。\n\n456\n00:25:29,729 --> 00:25:35,733\nthe screen. Now, we can get the location and movement\n现在， 我们可以得到每一次单个手指触碰到屏幕时的\n\n457\n00:25:35,735 --> 00:25:38,235\nof every single finger that touches down on the screen,\n位置和运动轨迹，\n\n458\n00:25:38,237 --> 00:25:42,573\nthat's possible. Okay? There's API for doing that, but we\n这是可以实现。 Okay? 捕获手势有专门的 API，不过我们\n\n459\n00:25:42,575 --> 00:25:46,010\nvirtually never do that ever. Okay? Why don't we do that?\n几乎从来没有用过这些 API。 Okay? 我们为什么不用?\n\n460\n00:25:46,012 --> 00:25:49,547\nThe reason for that is that the user thinks of interacting\n原因是用户认为当他们在屏幕上使用手势进行交互时\n\n461\n00:25:49,549 --> 00:25:53,417\nwith your UI as a gesture, like, they're swiping, or\n他们使用的手势是具体的，\n\n462\n00:25:53,419 --> 00:25:56,787\nthey're pinching. Okay, where they're panning around.\n比如滑动或者捏合。\n\n463\n00:25:56,789 --> 00:25:59,023\nThose are gestures that they're making.\n这些是他们正在做的手势。\n\n464\n00:25:59,025 --> 00:26:02,259\nSo iOS has an abstraction layer that lets your\n所以 iOS 系统中有一个抽象层\n\n465\n00:26:02,261 --> 00:26:06,630\napp think of the input as gestures as well, okay? So\n让你的应用可以把屏幕上的交互识别为对应的手势， okay?\n\n466\n00:26:06,632 --> 00:26:07,398\nyou're gonna get those gestures and\n所以你就可以得到这些手势并且\n\n467\n00:26:07,400 --> 00:26:10,067\ndo something when they happen. There's predefined gestures.\n当它们产生的时候做相应的处理。 这些都是预定义的手势。\n\n468\n00:26:10,069 --> 00:26:13,304\nThe great thing about that is, a swipe is exactly the same\n很棒的一点是，在每一个单独的应用中\n\n469\n00:26:13,306 --> 00:26:16,273\nthing in every single app. Okay? It's like, you know,\n滑动手势都是类似的。 Okay? 你知道的，就好比，\n\n470\n00:26:16,275 --> 00:26:19,209\nknow, the speed of swiping and how far you have to swipe,\n滑动的速度以及你需要滑动的距离，\n\n471\n00:26:19,211 --> 00:26:20,778\nall that's exactly the same in every single app,\n在每一个应用中这些都是相同的，\n\n472\n00:26:20,780 --> 00:26:23,247\ncuz every single app is using these gestures. Okay,\n这是因为每一个应用都用了相同的手势。 Okay,\n\n473\n00:26:23,249 --> 00:26:25,716\nif you had to do your own swipe, well, you know,\n如果你想要做自己的滑动手势，好吧，如你所知\n\n474\n00:26:25,718 --> 00:26:27,017\ndid, did the person swipe fast enough?\n多快速的动作算是滑动?\n\n475\n00:26:27,019 --> 00:26:29,853\nOr was that a pan? You'd have to do all that logic yourself.\n或者那是一个点击手势吗? 你必须去独自处理这些逻辑。\n\n476\n00:26:29,855 --> 00:26:30,487\nIt would be a pain in the neck, and\n这将是一个痛苦的过程，并且\n\n477\n00:26:30,489 --> 00:26:34,525\nit would be inconsistent between applications. Okay. So\n不同的程序间将会不一致。 Okay。所以\n\n478\n00:26:34,527 --> 00:26:38,696\ngestures are recognized by instances of a class called\n手势会被一个叫做 UIGestureRecognizer 的实例识别。\n\n479\n00:26:38,698 --> 00:26:42,066\nUIGestureRecognizer. Okay, good name. But\nOkay，好名字。不过\n\n480\n00:26:42,068 --> 00:26:44,468\nUIGestureRecognizer itself is abstract.\nUIGestureRecognizer 这个类本身是个抽象类。\n\n481\n00:26:44,470 --> 00:26:47,771\nYou never actually instatiate one. Instead there's a bunch\n你永远都不会实例化它。 取而代之的是一组\n\n482\n00:26:47,773 --> 00:26:50,140\nof sub-classes of UIGestureRecognizer. And\nUIGestureRecognizer 的子类。\n\n483\n00:26:50,142 --> 00:26:53,777\nthose are what you instantiate to get the kind of gesture you\n这些子类才是你需要根据具体的手势进行实例化的对象。\n\n484\n00:26:53,779 --> 00:26:55,746\nwant. So there's pan gesture recognizer and\n所以会有 pan gesture recognizer、\n\n485\n00:26:55,748 --> 00:26:58,916\npinch gesture resto recognizer and tap and swipe gesture\npinch gesture recognizer 以及 tap 和 swipe gesture\n\n486\n00:26:58,918 --> 00:27:03,554\nrecognizer etc. Okay. Now when you wanna use a recognizer,\nrecognizer 等等。 Okay。现在当你想要使用一个识别器的时候，\n\n487\n00:27:03,556 --> 00:27:06,256\nthere's really two parts to it, okay.\n它需要包含两部分, okay。\n\n488\n00:27:06,258 --> 00:27:11,028\nOne is you have to get some UIView to.\n一个是在其上识别手势的 UIView。\n\n489\n00:27:11,030 --> 00:27:14,465\nTake on this gesture recognizer and recognize that\n把这个手势识别器加到视图上然后识别对应的手势。\n\n490\n00:27:14,467 --> 00:27:17,034\ngesture. So there's the gesture recognition part\n所以这一步需要你\n\n491\n00:27:17,036 --> 00:27:19,203\nwhich is done by creating a gesture recognizer and\n创建一个手势识别器然后\n\n492\n00:27:19,205 --> 00:27:23,107\nthen a view to use it. Only views can recognize gesdri,\n指定一个视图去使用它。 只有视图才能识别手势，\n\n493\n00:27:23,109 --> 00:27:27,077\ngestures not controllers. They can't recognize it only views.\n控制器不能识别手势。\n\n494\n00:27:27,079 --> 00:27:29,947\nOkay? So part one is to create the gesture recognizer you\nOkay? 所以第一步就是创建你想要的手势识别器\n\n495\n00:27:29,949 --> 00:27:31,682\nwant, configure it how you want, and\n按照你的想法配置它，并且\n\n496\n00:27:31,684 --> 00:27:35,619\nthen ask some view please start recognizing this. Okay?\n指派一些视图开始识别。 Okay?\n\n497\n00:27:35,621 --> 00:27:39,957\nThen part two is, what if the recognizer does recognize it?\n然后第二步， 手势识别器识别了手势之后该做什么？\n\n498\n00:27:39,959 --> 00:27:43,193\nThen it needs to have that handled some how. And\n它需要一些处理。\n\n499\n00:27:43,195 --> 00:27:44,995\nthat's done with a gesture handler.\n这一步通过一个手势处理器（gesture handler）来完成。\n\n500\n00:27:44,997 --> 00:27:46,664\nSo you've got gesture recognizers and\n现在，你有一个手势识别器和\n\n501\n00:27:46,666 --> 00:27:50,067\ngesture handlers, okay? And the handler is called\n处理手势事件的方法，这个方法\n\n502\n00:27:50,069 --> 00:27:53,370\nas the recognizer goes through a basically a state machine\n在识别器不断从基础的状态机\n\n503\n00:27:53,372 --> 00:27:55,506\nof recognizing this gesture. Okay, and\n识别到这个手势时被调用\n504\n00:27:55,508 --> 00:27:58,142\nwe'll talk about what that state machine looks like. But\n我们稍后会讨论这个状态机\n\n505\n00:27:58,144 --> 00:27:58,475\nit's called repeatedly,\n这个状态会不断重复\n\n506\n00:27:58,477 --> 00:28:01,145\nthe handler's gonna be called repeatedly, as the gesture\n所以处理手势事件的方法也会不断被调用\n\n507\n00:28:01,147 --> 00:28:03,080\ngoes through the process of being recognized and\n手势不断继续，这个过程不断被识别到\n\n508\n00:28:03,082 --> 00:28:06,383\nmoving and all the things it does. Okay now usually\n调用也在继续\n\n509\n00:28:06,385 --> 00:28:10,454\nthe first of these things the creating of a recognizer and\n通常我们先创建一个手势识别器\n\n510\n00:28:10,456 --> 00:28:10,821\nadding it to some\n然后将它添加\n\n511\n00:28:10,823 --> 00:28:14,191\nview is usually done by your controller. Okay.\n到 view 上，这通常由控制器完成\n\n512\n00:28:14,193 --> 00:28:16,560\nIt doesn't have to be done by your controller but\n但并不是必须由控制器完成\n\n513\n00:28:16,562 --> 00:28:20,030\nit's a good way for\n但由控制器添加更好\n\n514\n00:28:20,032 --> 00:28:22,866\nits views. Okay the views are the minion of the controller\nviews 是 controller 的仆从\n\n515\n00:28:22,868 --> 00:28:26,603\nanyway. So, the controller wants to control its minions.\n所以，控制器想控制它的仆从\n\n516\n00:28:26,605 --> 00:28:30,541\nSo, it might usually be the one that wants to\n控制器通常\n\n517\n00:28:30,543 --> 00:28:32,976\nadd the gesture recognizer to a view but\n给 view 添加手势识别器\n\n518\n00:28:32,978 --> 00:28:36,013\nsome views, the gesture recognition is so\n但是，对于一些 view 来说，其手势识别器\n\n519\n00:28:36,015 --> 00:28:39,783\nfundamental to who they are that they add it themselves.\n太过于基础，所以他们自己添加\n\n520\n00:28:39,785 --> 00:28:40,084\nThey add it themselves.\n他们为自己添加手势识别器\n\n521\n00:28:40,086 --> 00:28:42,653\nFor example, ScrollView. Okay what would a ScrollView\n比如说，ScrollView 如果 ScrollView 没有\n\n522\n00:28:42,655 --> 00:28:45,456\nbe without a pan gesture. Just scrolling up and down it would\n拖动手势，只是滚来滚去\n\n523\n00:28:45,458 --> 00:28:48,726\nbe useless it wouldn't even be a ScrollView anymore.\n这样的 ScrollView 没有什么用，也不会再被叫做 ScrollView 了\n\n524\n00:28:48,728 --> 00:28:52,262\nSo ScrollView adds a pan gesture recognizer and\n所以，ScrollView自己添加了拖动手势和\n\n525\n00:28:52,264 --> 00:28:54,131\na pinch gesture recognizer to itself.\n捏合手势\n\n526\n00:28:54,133 --> 00:28:58,001\nProbably in it's initializer. Okay but lot of the times your\n可能是内部通过自己的初始化方法添加到\n\n527\n00:28:58,003 --> 00:28:59,903\ncontroller that's adding the gesture,\n但是，大多数时间都是 controller 添加手势的\n\n528\n00:28:59,905 --> 00:29:03,140\nagain the controller can't do the recognition to gesture\n再重复一遍，controller 不能识别到手势\n\n529\n00:29:03,142 --> 00:29:05,576\nonly of you with the gesture recognizer can. But\n只有你添加了手势识别器的控件可以\n\n530\n00:29:05,578 --> 00:29:08,879\nthe controller can add that gesture recognizer create and\n但是，controller可以添加手势识别器\n\n531\n00:29:08,881 --> 00:29:11,582\nadd the gesture I can add it to one of its views in its\n创建和添加手势给 controller 里的一个 view 中\n\n532\n00:29:11,584 --> 00:29:17,154\nview. Okay, the second thing that handler that handles it.\n第二件事是，处理方法来处理手势\n\n533\n00:29:17,156 --> 00:29:19,723\nWell that could be handled by the controller or\n可以使 controller 来处理\n\n534\n00:29:19,725 --> 00:29:20,691\nit might be handled by the view.\n也可以是添加了手势的 view 来处理\n\n535\n00:29:20,693 --> 00:29:23,393\nIt could even be handled by someone else. Would never be\n甚至可以是其他人\n536\n00:29:23,395 --> 00:29:26,663\nhandled by your model because UI independent. But it could\n但是，永远不要在你的 model 中处理，因为UI分离\n\n537\n00:29:26,665 --> 00:29:30,100\nbe anyone in the controller view camps can handle it.\n在 controller 或者 view 阵营中的任何一者可以处理\n\n538\n00:29:30,102 --> 00:29:34,872\nGenerally, kind of, if the things that's the gesture is\n通常，如果手势的处理事件是\n\n539\n00:29:34,874 --> 00:29:38,509\ndoing is only modifying how the view displays itself,\n怎么修改 view 的展示\n\n540\n00:29:38,511 --> 00:29:42,012\nlike in our Faceview, it was just the scale of the view or\n像我们的 FaceView 中 view 的大小\n\n541\n00:29:42,014 --> 00:29:44,414\nmaybe somehow it was change in the color of the view.\n或是 view 颜色的变化\n\n542\n00:29:44,416 --> 00:29:47,518\nThen the view is probably going to handle the gesture.\n这是，通常是这个view来处理这个手势\n\n543\n00:29:47,520 --> 00:29:49,052\nOkay, it's gonna both recognize it\n这个view不仅识别手势\n\n544\n00:29:49,054 --> 00:29:52,990\nwith the recognizers and handle it. But if the gesture\n而且处理对应的事件，但是如果这个手势\n\n545\n00:29:52,992 --> 00:29:56,260\nis changing the model, then definitely the controller\n改变了 model，这种情况绝对是\n\n546\n00:29:56,262 --> 00:29:58,662\nwould be the handler. Do you see why that is?\ncontroller要成为处理事件的对象，你明白吗？\n\n547\n00:29:58,664 --> 00:30:00,597\nBecause the view can't see the model, okay,\n因为，view 是看不到 model 的\n\n548\n00:30:00,599 --> 00:30:03,934\nbut the controller can. So the controller would set itself\n但是 controller 可以， controller会成为\n\n549\n00:30:03,936 --> 00:30:07,004\nas the recognizer of anything that's gonna affect the model.\n任何会影响 model 的识别器\n\n550\n00:30:07,006 --> 00:30:11,308\nWe'll see that in the demo as well. Okay, so how do we\n我们会在过会儿的 demo 中讲这一点 \n\n551\n00:30:11,310 --> 00:30:15,445\nadd a gesture to UIView? We've decided we want a view,\n我们应该如何给 UIView 添加手势呢，在这个例子中\n\n552\n00:30:15,447 --> 00:30:18,515\nin this case lets say to recognize pan.\n我们决定让 view 能识别到拖动手势\n\n553\n00:30:18,517 --> 00:30:21,752\nOkay a pan is putting your finger down on the screen and\n拖动手势就是在屏幕上拖动你的手指\n\n554\n00:30:21,754 --> 00:30:23,287\nmoving it around without lifting it up.\n拖动时并不抬起手指\n\n555\n00:30:23,289 --> 00:30:26,023\nAnd when you lift it up the pan is over. Kay,\n当手指抬起来的时候，拖动手势也就结束了\n\n556\n00:30:26,025 --> 00:30:27,157\nthat's what a pan is basically.\n这是拖动手势基本的含义\n\n557\n00:30:27,159 --> 00:30:30,160\nYou're panning your finger around. On the screen.\n你可以在屏幕上来回拖动你的手指\n\n558\n00:30:30,162 --> 00:30:33,831\nAll right? So if we wanted to do that. Well, one, so we have\n如果我们想添加这样一个手势\n\n559\n00:30:33,833 --> 00:30:37,067\nto somewhere in our controller code add a pan gesture\n我们需要在 controller 的代码中创建一个 pan 手势识别器\n\n560\n00:30:37,069 --> 00:30:40,437\nrecognizer to the view that we want the panning to happen in.\n并将它添加到我们想让拖动手势发生的 view 上\n\n561\n00:30:40,439 --> 00:30:45,142\nOkay? Well a great place to do that is in that didSet, okay?\n最好是在 didSet 方法中做这些事情\n\n562\n00:30:45,144 --> 00:30:48,111\nOf the outlet. Cuz as soon as that view that\n因为在获得这个 view 的同时\n\n563\n00:30:48,113 --> 00:30:48,145\nas soon as we get a pointer to it, let's immediately just add\n我们立即为他添加了手势\n\n564\n00:30:48,147 --> 00:30:51,381\nwe want to pan,\n我们想要拖动时 \n\n565\n00:30:51,383 --> 00:30:53,350\nthe gesture recognizer right there. Okay.\n对应的手势识别器已经准备好了\n\n566\n00:30:53,352 --> 00:30:55,886\nAnd we know that this didSet right here.\n我们知道这里的 didSet 方法\n\n567\n00:30:55,888 --> 00:30:58,622\nOkay we already saw this in the demo I just did. This\n在刚刚的 demo 中我写过这个方法\n\n568\n00:30:58,624 --> 00:31:01,758\ndidSet, when you're doing it to an outlet. This gets called\n当你处理一个 outlet 时\n\n569\n00:31:01,760 --> 00:31:05,963\nonly once. It gets called when iOS first hooks up that view.\n他在 iOS 绘制这个 view 时刚好调用，且只调用一次\n\n570\n00:31:05,965 --> 00:31:10,567\nKay, perfect time to go add a gesture recognizer. Okay, so\n这是一个添加手势识别器的完美时机\n\n571\n00:31:10,569 --> 00:31:14,938\nwe're gonna do that. First, we are going to create the pan\n我们开始这么做，首先，创建手势识别器\n\n572\n00:31:14,940 --> 00:31:18,275\ngesture recognizer. Okay, here is a concrete subclass of\nPanGestureRecognizer 是 UIGestureRecognizer 的\n\n573\n00:31:18,277 --> 00:31:21,478\nUIGestureRecognizer called pan gesture recognizer.\n一个继承实体类\n\n574\n00:31:21,480 --> 00:31:26,617\nIt takes two arguments here. The first is who is going\n他有两个参数\n\n575\n00:31:26,619 --> 00:31:31,822\nto handle this gesture when I recognize it. Okay.\n第一个是当识别到手势后，处理手势的对象\n\n576\n00:31:31,824 --> 00:31:33,957\nSo this gesture pan gesture recognizer saying hey,\n当PanGestureRecognizer\n\n577\n00:31:33,959 --> 00:31:36,760\nif I recognize a pan, who's gonna handle it for me?\n识别到拖动手势后，会问谁帮我来处理这个手势呢？\n\n578\n00:31:36,762 --> 00:31:40,764\nAnd the answer is, self, so that's the controller. Okay.\n答案是，controller 自己来处理手势\n\n579\n00:31:40,766 --> 00:31:42,499\nCuz there's an outlet in the controller so\n因为这是在一个 controller 中的 outlet\n\n580\n00:31:42,501 --> 00:31:44,968\nthe target itself means the controller is going to\ntarget 为 self，指这个 controller 自己将会\n\n581\n00:31:44,970 --> 00:31:50,007\nhandle this pan itself. Okay. The second argument here.\n处理拖动手势，第二个参数是\n\n582\n00:31:50,009 --> 00:31:55,379\nIs what method do you want me to invoke in self?\n在识别到这个手势后\n\n583\n00:31:55,381 --> 00:31:58,749\nWhen this gets recognized, okay?\n你想让我调用 self 中的什么方法？\n\n584\n00:31:58,751 --> 00:32:00,984\nNow there's some kind of funky syntax here.\n第二个参数的语法可能有些难以理解\n\n585\n00:32:00,986 --> 00:32:05,989\nThis has to be an Objective-C runtime compatible selector,\n这是一种兼容 OC 运行时的选择器\n\n586\n00:32:05,991 --> 00:32:10,093\nokay? That just means a selector, a method, okay,\n仅仅意味着是一个选择器、一个方法\n\n587\n00:32:10,095 --> 00:32:10,928\nthe name of a method,\n方法的名字\n\n588\n00:32:10,930 --> 00:32:14,631\nthat is visible to the Objective-C runtime. Now, for\n对于 OC 运行时是可见的\n\n589\n00:32:14,633 --> 00:32:17,701\nthis to be visible to run to the Objective-C runtime,\n因为他对于 OC 运行时是可见的\n\n590\n00:32:17,703 --> 00:32:21,538\nthis method must be in a class that inherits from NS object.\n所以，这个方法必须出现在某个继承自 NSObject 的类中\n\n591\n00:32:21,540 --> 00:32:24,641\nRemember I was talking about that NS object thing and\n记得我之前说过关于 NSObject\n\n592\n00:32:24,643 --> 00:32:25,776\nsometimes you're gonna need it, well,\n有些时候你需要它\n\n593\n00:32:25,778 --> 00:32:28,345\nhere you would need it. Now you don't usually care about\n此时我们就需要，但我们通常不用关心这个问题\n\n594\n00:32:28,347 --> 00:32:31,281\nthat here, because this is almost always being handled by\n因为这个处理方法通常在一个\n\n595\n00:32:31,283 --> 00:32:34,952\neither a UI view controller which definitely inherits from\nUIViewController 中， 而这个UIViewController 绝对继承了\n\n596\n00:32:34,954 --> 00:32:35,619\nNS objects or a UI view,\nNSObject 又或者在一个 UIView 中\n\n597\n00:32:35,621 --> 00:32:38,322\nwhich definitely inherits from NS object, right? So\nUIView 也绝对继承了 NSObject\n\n598\n00:32:38,324 --> 00:32:41,692\nyou usually don't care, okay? You're not usually going to be\n所以你通常不用关心这个问题，你不会\n\n599\n00:32:41,694 --> 00:32:44,761\ntrying to send this to some object that's a Swift object\n尝试将这个方法给一个没有\n\n600\n00:32:44,763 --> 00:32:48,699\nthat doesn't inherit from NS object. But this syntax here\n继承 NSObject 的 Swift 类\n\n601\n00:32:48,701 --> 00:32:53,070\nmeans create an Objective-C compatible selector, okay?\n这个语法表示创建一个 OC 运行时的兼容选择器\n\n602\n00:32:53,072 --> 00:32:56,573\nSelector just means a kind of an identifier for a method.\nselector 表示方法的一种标识符\n\n603\n00:32:56,575 --> 00:33:00,911\nAnd here is just the class, a dot, and then the name of\n这是处理方法的类、点，然后是 \n\n604\n00:33:00,913 --> 00:33:04,648\nthe method including the argument names. Don't forget\n包含参数名称的方法名称。\n\n605\n00:33:04,650 --> 00:33:07,951\nthe argument names here. Now, this pan method that I'm gonna\n别忘了参数名称，我会在下一页说明\n\n606\n00:33:07,953 --> 00:33:11,989\nshow you on the next screen, it has one argument.\n这个 pan 方法，只有一个参数\n\n607\n00:33:11,991 --> 00:33:14,958\nThat argument is the pan gesture recognizer.\n而这个参数就是这个拖动手势识别器\n\n608\n00:33:14,960 --> 00:33:16,994\nSo just like when we have target action, and\n就像我们有一个 target - action 方法\n\n609\n00:33:16,996 --> 00:33:19,863\nwe have a button that has the sender is sending itself.\n一个 button 将自己作为 sender 传递\n\n610\n00:33:19,865 --> 00:33:22,332\nSame thing here, when we have a pan gesture recognizer and\n同样的，当我们有一个拖动手势识别器\n\n611\n00:33:22,334 --> 00:33:25,502\nit starts to recognize, it sends this pan method\n当它识别到手势时，它会将自己作为参数\n\n612\n00:33:25,504 --> 00:33:29,706\nhere to the view controller with itself as the argument.\n调用 ViewController 的 pan 方法\n\n613\n00:33:29,708 --> 00:33:32,409\nNow you might say, why is this underbar right here?\n你可能会问，为什么有这个下划线呀？\n\n614\n00:33:32,411 --> 00:33:35,345\nWhy don't I have the name of whatever this first keyword\n为什么对于这个参数不能有一个名字\n\n615\n00:33:35,347 --> 00:33:39,349\nis? And that's because I don't really care what that name is.\n这是因为，我们不关心它的名字是什么\n\n616\n00:33:39,351 --> 00:33:39,883\nI just wanna make it clear,\n我只想让它保持优雅整洁\n\n617\n00:33:39,885 --> 00:33:44,221\nI want the version of pan that has one argument. Now if I had\n我希望这个 Pan 方法仅有一个参数\n\n618\n00:33:44,223 --> 00:33:49,426\nmultiple, pan methods that had different first, names there,\n如果我需要多个参数，那么这里就需要参数名称\n\n619\n00:33:49,428 --> 00:33:52,829\nthen I would have to put the name in there. But I can put\n我需要写名称，但是我可以\n\n620\n00:33:52,831 --> 00:33:56,133\nunderbar here because underbar in Swift means, I don't care,\n在这里写下划线，因为在 Swift 中，下划线表示我不关心\n\n621\n00:33:56,135 --> 00:33:59,269\nwhatever, okay? I don't really care what this is. It's\n我确实不关心这个参数名称的问题\n\n622\n00:33:59,271 --> 00:34:02,272\na substitute for I don't care. So I don't really care here.\n下划线是我不关心这个问题的代名词\n\n623\n00:34:02,274 --> 00:34:05,675\nSo I just wanna introduce that you can do this underbar here.\n我只是想说明你可以在这里用下划线替代参数名称\n\n624\n00:34:05,677 --> 00:34:09,179\nBut if I don't put this _:) here, then it's gonna try and\n但是，如果我在这里没有写 (_:)\n625\n00:34:09,181 --> 00:34:10,981\ncall a pan method that has no arguments.\n它会调用一个没有参数的 pan 方法\n\n626\n00:34:10,983 --> 00:34:14,017\nSo be careful, if you want the one that has the gesture\n在这里需要注意，如果你想将一个手势识别器\n\n627\n00:34:14,019 --> 00:34:17,854\nrecognizer as an argument, you gotta put that in there, okay?\n作为参数调用，你得在这里写 (_:)\n\n628\n00:34:17,856 --> 00:34:21,458\nSo that's specifying the selector. And then I just turn\n这是一个具体的选择器，然后\n\n629\n00:34:21,460 --> 00:34:25,562\non this recognizer by taking the view, this is the UIView,\n我通过添加手势识别器到这个 view 也就是这个 pannableView\n\n630\n00:34:25,564 --> 00:34:30,434\nthis pannableView, okay? And adding this thing I created as\n开启我的手势识别器 \n\n631\n00:34:30,436 --> 00:34:34,504\na gesture recognizer, okay? As soon as I add that,\n一旦我添加了手势识别器\n\n632\n00:34:34,506 --> 00:34:38,108\nthis view is gonna start recognizing pan gestures,\n这个 view 就开始识别拖动手势\n\n633\n00:34:38,110 --> 00:34:41,378\nokay? And when it does, it's gonna send this method to\n当确实有拖动手势发生时，它会调用 controller \n\n634\n00:34:41,380 --> 00:34:46,516\nself which is the controller, got it? Okay, makes sense,\n中的处理方法\n\n635\n00:34:46,518 --> 00:34:48,985\nthat's what we're doing there? All right, so now,\n我们在处理方法中干什么呢？\n\n636\n00:34:48,987 --> 00:34:50,420\nlet's talk about how we implement this handler?\n现在，我们讨论一下如何实现处理方法\n\n637\n00:34:50,422 --> 00:34:52,656\nThis method right here, this pan thing, okay?\n这个 pan 方法\n\n638\n00:34:52,658 --> 00:34:57,060\nWhat does that look like to implement? To,\n它应该如何处理呢？\n\n639\n00:34:57,062 --> 00:34:59,663\nto understand how we're gonna implement such a method, we\n为了明白我们在这个方法中如何处理手势事件\n\n640\n00:34:59,665 --> 00:35:02,766\nneeded to understand a little bit more about the concrete\n我们需要知道关于\n\n641\n00:35:02,768 --> 00:35:04,668\nsubclasses of UI gesture recognizer. So\nUIGestureRecognizer 继承实体类的一些知识\n\n642\n00:35:04,670 --> 00:35:09,272\nlet's look at pan, okay? So pan, UIPanGestureRecognizer,\n关于UIPanGestureRecognizer\n\n643\n00:35:09,274 --> 00:35:12,943\nit has a few methods on it that are specific to panning,\n有一些专门处理拖动手势的方法\n\n644\n00:35:12,945 --> 00:35:15,045\nokay? For example, it has translationInView.\n比如，translationInView 方法\n\n645\n00:35:15,047 --> 00:35:19,783\nIt takes a UIView and tells you how far the pan has moved\n它获取一个 UIView 参数，然后返回这个拖动手势\n\n646\n00:35:19,785 --> 00:35:23,053\nin that view's coordinate system, okay?\n在这个 view 的坐标中移动了多远\n\n647\n00:35:23,055 --> 00:35:25,789\nWhich is exactly what you want for a pan cuz you wanna know\n这个方法确切的告诉你关于拖动手势你想知道的\n\n648\n00:35:25,791 --> 00:35:29,459\nwhere you are, so calls wanted to know how far you moved?\n也就是这个拖动手势移动了多远\n\n649\n00:35:29,461 --> 00:35:32,129\nIt even has velocity in view, we'll tell you how fast\n甚至还有在这个 view 中，手指开始拖动的速度有多快\n\n650\n00:35:32,131 --> 00:35:34,998\nthe pan is happening, okay? If you're ripping it around\n如果你在周围非常非常非常缓慢地\n\n651\n00:35:35,000 --> 00:35:36,833\nversus going really really really really slow.\n拖动手指\n\n652\n00:35:36,835 --> 00:35:39,002\nLike if you had a drawing app, when you're going really slow,\n像你有个画画的应用，当你非常缓慢地拖动手指\n\n653\n00:35:39,004 --> 00:35:40,270\nyou might be drawing really carefully.\n这时就需要仔细绘图了\n\n654\n00:35:40,272 --> 00:35:41,271\nAnd if you're zipping it around,\n或者你在周围快速移动手指\n\n655\n00:35:41,273 --> 00:35:43,874\nnow you're making big arcs or something, who knows? And\n你就需要画一个大的弧度之类的(因为手指移动速度快)\n\n656\n00:35:43,876 --> 00:35:47,511\nit even has set translation, which is setting this.\n在配置手势识别器时，甚至需要设置 translation \n\n657\n00:35:47,513 --> 00:35:48,845\nWhy would you ever want to set this?\n为什么每次还得设置这个参数呢?\n\n658\n00:35:48,847 --> 00:35:53,583\nWell, if you don't set this, okay? Then this translationVew\n如果你不设置，之后\n\n659\n00:35:53,585 --> 00:35:56,620\nis going to be the cumulative translationInView,\ntranslationView 会变成一个递增的 translationView\n\n660\n00:35:56,622 --> 00:36:00,090\nokay? It's how far the pan has moved since it started,\n这个是你的拖动手势从开始到现在拖动的距离\n\n661\n00:36:00,092 --> 00:36:04,227\nthe cumulative thing. If you what you want instead is, how\n是一个递增的值，如果你不设置\n\n662\n00:36:04,229 --> 00:36:07,831\nmuch it's changed since last time you told me about it,\n手势内容会是上一次你拖动的距离\n\n663\n00:36:07,833 --> 00:36:11,468\nokay? You can constantly reset this to zero.\n应将这个值重置为 0 \n\n664\n00:36:11,470 --> 00:36:13,637\nIf you constantly reset this translation to zero,\n如果你再下一次将得到这个值时 \n\n665\n00:36:13,639 --> 00:36:14,504\nthen the next time you get it,\n不断将它设置为 0\n\n666\n00:36:14,506 --> 00:36:18,408\nit's gonna be the translation incremental, okay? Tiny bit,\n这就会是一个递增的 translation\n\n667\n00:36:18,410 --> 00:36:21,411\nlittle tiny bit it moves since the last time, okay?\n基于每一次最后拖动的一点点距离\n\n668\n00:36:21,413 --> 00:36:24,748\nSo you'll see in the demo that we we will reset this to zero\n一会儿在 demo 中你会看到我们每次将其重置为 0\n\n669\n00:36:24,750 --> 00:36:28,218\nevery time, cuz we just want the incremental panning, okay?\n因为我们想要一个慢慢递增的拖动手势\n\n670\n00:36:28,220 --> 00:36:32,956\nAll right, so the abstract superclass of UI pan gesture\nUIPanGesture 这个抽象的基类\n\n671\n00:36:32,958 --> 00:36:37,761\nalso provides a very important var, which is the state.\n也提供了一些重要的属性，比如说手势的状态\n\n672\n00:36:37,763 --> 00:36:40,730\nOkay, I told you that these gesture recognizers go through\n我之前说过手势识别器是在不断检测\n\n673\n00:36:40,732 --> 00:36:44,568\na state machine, okay? And this is how you can find out\n状态机的状态，你可以在处理方法中\n\n674\n00:36:44,570 --> 00:36:48,371\nin your handler what state the gesture is in.\n发现手势的状态\n\n675\n00:36:48,373 --> 00:36:52,409\nSo they all start around in this state possible, okay?\n所以他们在 possible 状态开始识别\n\n676\n00:36:52,411 --> 00:36:55,478\nUIGestureRecognizerState.Poss- ible. Then for\nUIGestureRecognizerState.Possible\n\n677\n00:36:55,480 --> 00:36:59,015\na discrete gesture, like a swipe, once the swipe happens,\n对于一个离散状态的手势，比方说扫动\n\n678\n00:36:59,017 --> 00:37:02,652\nit immediately goes to the state recognized, okay?\n这个手势很快就被识别到\n\n679\n00:37:02,654 --> 00:37:03,720\nIt recognized the swipe. So\n手势识别器识别到扫动手势\n\n680\n00:37:03,722 --> 00:37:07,591\nyour handler gets called, the state will be recognized. For\n处理方法被调用，这是状态就是 Recognize\n\n681\n00:37:07,593 --> 00:37:11,828\na continuous gesture like a pan or a pinch, okay? It goes\n对于一个连续状态的手势，比方说拖动或捏合\n\n682\n00:37:11,830 --> 00:37:15,599\nto the state Began as soon as the pan gets held down, and\n当手势开始时，状态就是 Began\n\n683\n00:37:15,601 --> 00:37:18,768\nas soon as the pan starts moving it keeps going to\n手势一开始移动，状态就立即变为 Changed\n\n684\n00:37:18,770 --> 00:37:21,471\nthe state Changed. Change, change, change, change,\n随着手势变化，状态一直是 Changed Changed Changed\n\n685\n00:37:21,473 --> 00:37:23,306\nchange, the handler keeps getting called over and\n这样处理方法一直被调用调用调用\n\n686\n00:37:23,308 --> 00:37:25,208\nover and over and over and over with Changed, okay?\n因为状态一直是 Changed\n\n687\n00:37:25,210 --> 00:37:28,812\nAnd every time this translation is changing, okay?\n每次手势状态变化就会是 Changed 状态\n\n688\n00:37:28,814 --> 00:37:33,883\nAnd then, when the finger goes up, then it goes to Ended.\n最后，当手指抬起，状态就变为 Ended\n\n689\n00:37:33,885 --> 00:37:38,188\nMake sense? Now there's couple other states here, Failed and\n明白了吗？还有一些状态，Failed\n\n690\n00:37:38,190 --> 00:37:41,925\nCancelled. Like if you're doing the middle of a pan and\n和 Cancelled，比如你正在做一个拖动手势\n\n691\n00:37:41,927 --> 00:37:43,760\na phone call comes in, okay?\n一个电话进来了\n\n692\n00:37:43,762 --> 00:37:45,996\nThen you're gesture is gonna get cancelled,\n这个拖动手势就 Cancelled 了\n\n693\n00:37:45,998 --> 00:37:49,032\nokay? So you might or might not have to deal with that.\n通常你不用特别的处理这个状态\n\n694\n00:37:49,034 --> 00:37:52,035\nIf you're dealing with your pan incrementally,\n如果前面一直在处理这个拖动手势\n \n695\n00:37:52,037 --> 00:37:54,638\nthen who cares if it gets interrupted?\n对于它突然被打断，我们并不需要关心这个\n\n696\n00:37:54,640 --> 00:37:55,605\nYou were moving the thing incrementally.\n因为你打断之前你已经做了相关处理了\n\n697\n00:37:55,607 --> 00:37:58,074\nIf you are dealing with your pan with some big\n如果你需要在拖动手势结束时\n\n698\n00:37:58,076 --> 00:38:01,678\nthing at the end, when the pan ends, then you better do in\n做一些操作，你最好在\n\n699\n00:38:01,680 --> 00:38:04,547\nhere what you were gonna do when it ended, okay?\n状态变为 Ended 时操作\n\n700\n00:38:04,549 --> 00:38:07,617\nBut a lot of times you don't care cuz you're doing all\n通常我们不用担心被打断\n\n701\n00:38:07,619 --> 00:38:09,919\nthe work in Changed so Cancelled and Failed is\n因为大多数时候，操作都在状态为 Changed 时完成了\n\n702\n00:38:09,921 --> 00:38:13,256\njust like Ended but you don't notice the finger going up.\nCancelled 和 Failed 就类似与一种手指没抬起时就 Ended 状态\n\n703\n00:38:13,258 --> 00:38:16,793\nWell, no big deal. Okay, so now that I have all this\n这不是什么大问题，现在\n\n704\n00:38:16,795 --> 00:38:17,927\ninformation about a pan gesture,\n我有了关于拖动手势的所有信息\n\n705\n00:38:17,929 --> 00:38:21,831\nhow do I make a handler that handles a pan gesture, okay?\n我的处理方法应该如何处理这个拖动手势呢？\n\n706\n00:38:21,833 --> 00:38:23,500\nThis is what the code would look like. This code is gonna\n处理方法在这里\n\n707\n00:38:23,502 --> 00:38:25,969\nbe in my controller because I said the controller is gonna\n这些应该写在 controller 中，因为我之前说过\n\n708\n00:38:25,971 --> 00:38:30,440\nhandle the pan. And first I'm gonna look at the state, okay?\ncontroller应该处理这个手势， 首先我要看手势的状态\n\n709\n00:38:30,442 --> 00:38:35,111\nOf the, okay, yeah, I'm sorry, here's that pan_:),\n不是，先看 pan_:)\n\n710\n00:38:35,113 --> 00:38:37,380\nyou see, this pan takes an argument,\n这个 pan 方法有一个参数\n\n711\n00:38:37,382 --> 00:38:39,983\nokay? Instead of underbar there I could have put gesture\n与写下划线相反的是，这里我写参数名为 gesture\n\n712\n00:38:39,985 --> 00:38:42,218\nbecause that's what I called it here, gesture, but\n因为后面是这么调用的，这是内部参数名\n\n713\n00:38:42,220 --> 00:38:45,188\nI don't care. But, this one take an argument,\n这里有一个参数\n\n714\n00:38:45,190 --> 00:38:47,190\nyou could have pan with no arguments here and\n你也可以在这里不写参数\n\n715\n00:38:47,192 --> 00:38:50,293\nnothing there and this would not pass the pan gesture along\n不写参数的话就不会将拖动手势作为参数传递\n\n716\n00:38:50,295 --> 00:38:52,896\nas an argument. But, here I need the pan gesture,\n但在这里我需要这个拖动手势\n\n717\n00:38:52,898 --> 00:38:56,499\ncuz I need to know how far the pan is gone, okay? So, next\n因为我需要知道这个手势我拖动了多远\n\n718\n00:38:56,501 --> 00:39:00,370\nI'm gonna switch on the state that the pan gesture is in and\n下面，switch 这个拖动手势的 state\n\n719\n00:39:00,372 --> 00:39:05,608\nif it's Changed Or Ended, then I am going to update something\n如果 state 是 Changed 或 Ended，我希望更新\n720\n00:39:05,610 --> 00:39:08,311\nin my controller, okay? Otherwise,\n在 controller 中的一些东西 \n\n721\n00:39:08,313 --> 00:39:10,947\nI'm gonna ignore it, okay? If it's Cancelled or Failed or\n剩下的 state 会直接被忽略 \n\n722\n00:39:10,949 --> 00:39:15,151\nif it Began, I don't care. I'm only interested when it moves,\n在 Cancelled、Failed、Began 状态中不用处理，我只关心它移动的时候\n \n723\n00:39:15,153 --> 00:39:17,053\nokay? So that's why I'm only looking at this.\n这就是为什么我只找关于移动的状态\n\n724\n00:39:17,055 --> 00:39:19,656\nNow, I wanna show you this kinda cool thing in Switch.\n现在，我想给你看一些在 Switch 中很 cool 的东西\n\n725\n00:39:19,658 --> 00:39:22,459\nHopefully you got this in your homework? But there's this\n希望你在作业中早已读过\n\n726\n00:39:22,461 --> 00:39:25,061\nthing, fallthrough. Remember that Swift cases\n就是 fallthrough，在 Swift 里\n\n727\n00:39:25,063 --> 00:39:28,631\ndon't fall through to the next case like they do in C, okay?\n不像 C 跳转到下一个 case 方法(将 case 后语句置为空)\n\n728\n00:39:28,633 --> 00:39:31,368\nBut you can force them to fall through with fallthrough.\n但是你可以通过添加 fallthrough 关键字跳转\n\n729\n00:39:31,370 --> 00:39:34,504\nNow, I probably wouldn't write code like this,\n代码也可以不这么写\n\n730\n00:39:34,506 --> 00:39:37,841\nI would just say case.Changed, .Ended, okay?\n直接写 case.Changed, .Ended  \n\n731\n00:39:37,843 --> 00:39:39,442\nThat's a easier way to do this, but\n这种方式更简单\n\n732\n00:39:39,444 --> 00:39:42,912\nI just wanted to show you fallthrough, okay? All right,\n我只是想秀一下 fallthrough 关键字\n\n733\n00:39:42,914 --> 00:39:46,616\nso here inside, when things have Changed or Ended,\n在这儿，当状态是 Changed 或 Ended\n\n734\n00:39:46,618 --> 00:39:50,653\nI'm gonna get the translation in the pannableView. Okay,\n可以得到 pannableView 的translation\n\n735\n00:39:50,655 --> 00:39:53,957\nremember this to that outlet? I'm gonna get that translation\n记得前面那个 outlet 吗？\n\n736\n00:39:53,959 --> 00:39:56,559\nfrom the gesture. And then I'm gonna go and\n获得手势的 translation \n\n737\n00:39:56,561 --> 00:39:59,629\nupdate something that depends on where the pan is.\n然后更新一些取决于手势发生位置的操作\n\n738\n00:39:59,631 --> 00:40:02,966\nI've got, I know where the pan, how far it has moved. So\n现在我知道手势在哪里发生了、手势挪动了多远\n\n739\n00:40:02,968 --> 00:40:06,836\nI'm just gonna update what, something that needs that.\n给需要这些信息的操作更新信息\n\n740\n00:40:06,838 --> 00:40:10,039\nAnd then I'm gonna set the translation back to 0.\n之后，将 translation 重置\n \n741\n00:40:10,041 --> 00:40:13,910\nOkay, this also could be CGPoint.Zero if you want. But\n需要的话，这将置为 CGPointZero\n\n742\n00:40:13,912 --> 00:40:15,078\nsee, I'm gonna set it back to 0 so\n我想让它变为0\n\n743\n00:40:15,080 --> 00:40:17,113\nthat the next time I get called to my handler,\n当下一次我调用处理方法时\n\n744\n00:40:17,115 --> 00:40:19,983\nnext time it comes back around, this translation will\n又走到这一步\n\n745\n00:40:19,985 --> 00:40:23,520\nbe the incremental translation from the last time it sent it\ntranslation 将从上一次我拖动到的地方继续拖动\n\n746\n00:40:23,522 --> 00:40:28,992\nto me. Everybody get that? Please? Okay? All right.\n大家明白吗？\n\n747\n00:40:28,994 --> 00:40:30,560\nSo that's it. That's what the handler looks like.\n在处理方法中大概就写这些\n\n748\n00:40:30,562 --> 00:40:32,896\nPretty straight forward. Okay. We'll see this in the demo,\n处理的方法很简单，我们待会儿在 demo 中会继续讲这些内容\n\n749\n00:40:32,898 --> 00:40:36,933\nit's not too bad, okay? Let's briefly talk about some of\n我们简单讲一下除了拖动手势\n\n750\n00:40:36,935 --> 00:40:39,102\nthe other concrete gestures besides pan,\n其他的手势实体类\n\n751\n00:40:39,104 --> 00:40:41,571\nthere's pinches. Pinches is two fingers down,\n比如捏合手势，捏合手势指\n752\n00:40:41,573 --> 00:40:44,741\npinching in and out like this, okay? And here what\n两个手指像这样\n\n753\n00:40:44,743 --> 00:40:48,378\nyou're getting instead of the translation, it is the scale.\n\n754\n00:40:48,380 --> 00:40:51,581\nSo if I start my fingers here and I bring them out twice as\n如果我把手指间距放宽到之前两倍\n\n755\n00:40:51,583 --> 00:40:55,185\nwide that will be a scale of two. If I start him here and\n这样 scale 会变为 2 \n\n756\n00:40:55,187 --> 00:40:57,654\nmove him in half way, that's a scale 0.5.\n如果我缩小到一半，scale 会变为 0.5\n\n757\n00:40:57,656 --> 00:41:01,791\nOkay, so I'm scaling whatever on my screen and again I can\n重复的在屏幕上进行捏合操作\n\n758\n00:41:01,793 --> 00:41:06,663\nget velocity, how fast I'm pinching. Rotation is two\n我可以得到 velocity 参数，代表我捏合的速度\n\n759\n00:41:06,665 --> 00:41:10,767\nfingers turning them, okay. Like you're turning a knob and\n旋转指两根手指转圈的手势，就像你旋转把手时\n\n760\n00:41:10,769 --> 00:41:14,337\nit will tell you how many radians you've turned, okay.\n会知道你旋转了多少度\n\n761\n00:41:14,339 --> 00:41:18,374\nAnd again velocity, how fast you're turning. Swipe gesture,\n这个手势也有 velocity 参数表示你旋转的速度\n \n762\n00:41:18,376 --> 00:41:21,544\nokay. The swipe gesture you usually have to configure\n轻扫手势，这个手势通常需要你配置参数\n763\n00:41:21,546 --> 00:41:24,147\nbefore you use it. You have to say, do you want a left\n在你用之前，你必须标明扫动方向\n\n764\n00:41:24,149 --> 00:41:27,484\ngoing swipe, or right going swipe or up or down. Okay, and\n是左是右，是上是下\n\n765\n00:41:27,486 --> 00:41:31,421\nalso two fingers swipe, or one finger or three fingers okay.\n也需要配置手势是一个、两个还是三个手指操作\n\n766\n00:41:31,423 --> 00:41:34,324\nYou have to configure that then you add the gesture\n你需要在添加手势之前配置好这些参数\n\n767\n00:41:34,326 --> 00:41:37,026\nrecognizer and it will only recognize it if all those\n在当前手势符合这些你配置的参数之后\n\n768\n00:41:37,028 --> 00:41:39,896\nthings are true. Two finger swipe up has all the,\n手势才会被识别到，你想识别到两根手指在这里扫动\n\n769\n00:41:39,898 --> 00:41:41,397\nit has to be a two finger swipe up.\n你的手势识别器就必须设置为两根手指的扫动\n\n770\n00:41:41,399 --> 00:41:44,334\nOtherwise it doesn't recognize it, okay. So\n不然的话，这个手势就不能被识别到\n\n771\n00:41:44,336 --> 00:41:48,037\nthat's swipe. Tap, which seems like it would be discreet,\n这就是轻扫手势，下面轻击手势\n\n772\n00:41:48,039 --> 00:41:49,939\nis not quite a discreet gesture, but\n轻击手势不是一个很单一的手势\n\n773\n00:41:49,941 --> 00:41:52,108\nyou also configure it with how many taps. You know,\n你仍需要配置点几下\n\n774\n00:41:52,110 --> 00:41:55,945\nis it a single tap, or a double tap? And two fingers,\n只是点一下还是双击？\n\n775\n00:41:55,947 --> 00:41:59,415\nor one? Okay, you configure that, add it, and here, you're\n是两根手指点还是一根？ 你需要配置这些，添加手势\n\n776\n00:41:59,417 --> 00:42:03,853\ngonna look for .ended to find out when the tap has happened,\n然后当手势开始后，识别手势状态是否结束\n\n777\n00:42:03,855 --> 00:42:07,290\nokay. That's because a tap actually has intermediate\n这是因为轻击的手势有中间状态\n\n778\n00:42:07,292 --> 00:42:10,593\nthings going on like a double tap has a, the first tap. And\n比方说，双击时第一下点完到第二下的状态\n\n779\n00:42:10,595 --> 00:42:12,929\nthen the second tap. And it might go through a state\n这会在你处理方法中经历一个\n\n780\n00:42:12,931 --> 00:42:16,533\nchange that will call your handler, but\n状态的变化\n\n781\n00:42:16,535 --> 00:42:20,236\nit's not done yet. Okay and you can't look at recognized,\n但是手势仍没结束，这时识别器就无法识别\n\n782\n00:42:20,238 --> 00:42:23,139\nat recognized with tap because it's not a discreet gesture.\n因为这不是一个简单手势\n\n783\n00:42:23,141 --> 00:42:25,675\nBecause it goes through those intermediate phases.\n它经历了一个中间的状态\n\n784\n00:42:25,677 --> 00:42:29,245\nSo you really look for .ended for tap, okay.\n所以你确实需要找到 ended 状态\n\n785\n00:42:29,247 --> 00:42:33,283\nAll right, so let's do a demo. Let's see all this in action\n好的，现在我们开始在 demo FaceIt 中添加这些操作 \n\n786\n00:42:33,285 --> 00:42:38,054\nwith our facet and what we're gonna do. First, I'm gonna add\n首先需要做什么，我先添加\n\n787\n00:42:38,056 --> 00:42:41,190\na pinch gesture that makes our face get bigger and\n一个可以让 face 变大变小的捏合手势\n\n788\n00:42:41,192 --> 00:42:43,493\nsmaller. Okay, we're just gonna pinch in and out and\n通过手势的捏合调整 face 的大小\n\n789\n00:42:43,495 --> 00:42:47,530\nadjust our scale. And then I'm gonna add a pan gesture.\n然后，我需要添加一个拖动手势\n\n790\n00:42:47,532 --> 00:42:48,398\nActually I'll probably do a swipe.\n哦不，我加的是轻扫手势\n\n791\n00:42:48,400 --> 00:42:53,002\nLet's do a swipe gesture, that modifies our model, okay.\n我们用轻扫手势修改我们的模型\n\n792\n00:42:53,004 --> 00:42:55,939\nWe're gonna use it to make our model happier or sadder.\n用这个手势使模型快乐一点或者悲伤一点\n\n793\n00:42:55,941 --> 00:42:59,375\nIf I make it happier or sadder, then we'll adjust our\n如果模型中的数据变化了，我们需要调整\n\n794\n00:42:59,377 --> 00:43:04,914\nface view, okay. Let's do that. Back to our facet here.\nfaceView 的状态，好了，回到FaceIt工程中\n795\n00:43:04,916 --> 00:43:09,419\nAll right, so how are we gonna do this?\n我们如何做呢？\n\n796\n00:43:09,421 --> 00:43:12,722\nFirst thing we need to do is add a gesture recognizer,\n首先，我们需要添加手势识别器\n\n797\n00:43:12,724 --> 00:43:16,759\nokay. And again I said inside faceView didset is a good\n再重复一遍我之前说的，faceView 的 didSet 方法是一个\n\n798\n00:43:16,761 --> 00:43:19,095\nplace to do that. So now I'm gonna expand this back out.\n合适的时机添加手势识别器，现在我需要把括号中内容扩大\n\n799\n00:43:19,097 --> 00:43:21,998\nBecause I'm gonna add more code than just that one,\n因为这里有一些代码超过一行了\n\n800\n00:43:22,000 --> 00:43:25,034\nthing here, okay. And I'm still gonna update you,\n添加完手势识别器，updateUI\n\n801\n00:43:25,036 --> 00:43:28,037\nUI here, but I'm also going to add a gesture recognizer.\n我添加完了手势识别器\n\n802\n00:43:28,039 --> 00:43:30,807\nI know that this didSet is only gonna be called once\n这个 didSet 方法只会在\n\n803\n00:43:30,809 --> 00:43:34,110\nwhen my outlet is first hooked up to my UI, so that's perfect\noutlet 绘制在UI上时被调用一次\n\n804\n00:43:34,112 --> 00:43:36,512\ncuz I only wanna add the gesture recognizer once. And\n所以这是一个添加手势识别器的完美时机\n\n805\n00:43:36,514 --> 00:43:39,582\nI know that the faceView is the guy who has to recognize\nfaceView 需要识别到这个手势\n\n806\n00:43:39,584 --> 00:43:43,953\nthe gesture. Only views can recognize gestures. So\n只有 view 可以识别手势\n\n807\n00:43:43,955 --> 00:43:48,024\nI'm going to add a gesture recognizer.\n我添加一个手势识别器\n\n808\n00:43:48,026 --> 00:43:50,994\nOkay and you can see that when you add a gesture\n你可以发现，当你添加一个手势识别器\n\n809\n00:43:50,996 --> 00:43:52,462\nrecognizer to a UI view it takes\n给一个 view \n\n810\n00:43:52,464 --> 00:43:56,132\na gesture recognizer an argument. So I'm gonna create\n它会把这个手势识别器当做参数\n\n811\n00:43:56,134 --> 00:44:00,703\none here, a UI pinch gesture recognizer, okay. And\n所以我在这儿写 UIPinchGestureRecognizer\n\n812\n00:44:00,705 --> 00:44:04,374\nthat recognizer takes that target and action as they are,\n创建这个识别器需要 target 和 action\n\n813\n00:44:04,376 --> 00:44:07,443\nas the two arguments, right? So the target here,\n作为两个参数\n\n814\n00:44:07,445 --> 00:44:11,381\nin this case, since that pinch is only changing the scale\n在这个例子中，因为捏合手势只是改变了\n\n815\n00:44:11,383 --> 00:44:13,216\nof the view, it's not changing my model,\n这个 view 的大小，并不会改变我的model\n\n816\n00:44:13,218 --> 00:44:18,488\nI'm gonna let the face view handle this thing itself. Now,\n所以我让 FaceView 自己处理这个手势\n\n817\n00:44:18,490 --> 00:44:21,157\nfor the FaceView to handle it, it's going to have to make\n如果 FaceView 自己处理这个方法，但我需要在controller中\n\n818\n00:44:21,159 --> 00:44:25,728\nsome sort of gesture handler available to my controller.\n调用这个方法，这个 FaceView 的方法必须可以让 controller 调用到\n\n819\n00:44:25,730 --> 00:44:28,765\nSo it's gonna have the public method right,\n所以我需要在这里写一个 public 方法\n\n820\n00:44:28,767 --> 00:44:30,133\nthat handles a pinch.\n来处理 pinch 手势\n\n821\n00:44:30,135 --> 00:44:32,969\nSo we're gonna have to add that to FaceView which will do\n下一步，我们应该给 FaceView 添加处理方法\n\n822\n00:44:32,971 --> 00:44:36,606\nnext. And the action here is gonna be a selector,\n这里的 action 必须是一个 selector\n\n823\n00:44:36,608 --> 00:44:41,477\nit's gonna be a FaceView selector. FaceView selector.\n是 FaceView 的 selector\n\n824\n00:44:41,479 --> 00:44:44,614\nAnd I'm gonna call it changeScale, okay.\n我叫它 changeScale\n\n825\n00:44:44,616 --> 00:44:49,318\nAnd I am definitely going to need the argument there.\n我这里确实需要参数\n\n826\n00:44:49,320 --> 00:44:52,422\nSo I'm gonna do that, as well, okay.\n我马上添加参数\n\n827\n00:44:52,424 --> 00:44:56,459\nMaybe this is a little easier to see if I do this.\n我处理的方法很简单\n\n828\n00:44:56,461 --> 00:45:02,865\nLike that. Okay. So it gives me an error here because\n这儿有一个 error \n\n829\n00:45:02,867 --> 00:45:05,635\nof course this method doesn't exist. So it's nice that it\n因为这个方法还没有写，这样很好\n\n830\n00:45:05,637 --> 00:45:08,404\nactually checks to make sure that this exist, okay.\n因为每次会检查这个方法是否存在\n\n831\n00:45:08,406 --> 00:45:11,140\nSo let's go ahead and add this method right here, okay. This\n现在让我们直接给 FaceView 添加这个方法\n\n832\n00:45:11,142 --> 00:45:14,644\nis the method that's going to handle when a pinch happens,\n这个方法将在每次捏护手势发生时被调用\n\n833\n00:45:14,646 --> 00:45:16,446\nokay. We're gonna put that in our FaceView, so\n我们在 FaceView 中写这个方法\n\n834\n00:45:16,448 --> 00:45:18,347\nI'm gonna go over here to FaceView.\n回到 FaceView\n\n835\n00:45:18,349 --> 00:45:20,883\nPut it up here towards the top since it's gonna be public,\n在上面一点写这个方法，因为他是公用的方法\n\n836\n00:45:20,885 --> 00:45:23,486\nokay. It has to be public, because the controller\n因为 controller 希望在处理手势的时候\n\n837\n00:45:23,488 --> 00:45:27,657\nwants the gesture handler to call it. So changeScale. It's\n调用这个方法，改变 FaceView 的大小\n\n838\n00:45:27,659 --> 00:45:31,427\ngoing to have a recognizer as its argument, okay?\n这里需要将一个手势识别器作为参数\n\n839\n00:45:31,429 --> 00:45:36,566\nThat UIPinchGestureRecognizer. Okay,\n这个参数是 UIPinchGestureRecognizer\n\n840\n00:45:36,568 --> 00:45:39,902\nso it's nice that when we're asked to handle the gesture,\n每次我们需要处理这个手势时，\n\n841\n00:45:39,904 --> 00:45:42,505\nthe recognizer is passed along to us.\ncontroller 将识别器作为参数传递给我们，这样很好\n\n842\n00:45:42,507 --> 00:45:44,540\nAnd, this is really easy to implement,\n实现起来也很简单\n\n843\n00:45:44,542 --> 00:45:49,879\nI'm just gonna switch on the recognizer state. And\n我需要 switch 手势识别器的状态\n\n844\n00:45:49,881 --> 00:45:52,115\nif the state is changed or\n如果这个状态 Changed\n\n845\n00:45:52,117 --> 00:45:57,186\nended, and yes you can do it that way in switches, in Swift\n或者 Ended ，在 Swift 你可以这么写\n\n846\n00:45:57,188 --> 00:46:00,656\nyou can have multiple things there. If it's changed or\n你可以写多个 case 在这里\n\n847\n00:46:00,658 --> 00:46:03,993\nended then I'm just gonna set my scale to be multiplied\n如果手势状态 Changed 或者 Ended，我需要通过\n\n848\n00:46:03,995 --> 00:46:08,965\nby the recognizer scale. Okay cuz here's my scale up here.\n手势的大小设置 view 的大小，这是原来的 scale\n\n849\n00:46:08,967 --> 00:46:13,436\nAnd so if this pinch goes 2.0 twice as wide,\n如果捏合手势变成两倍大小\n\n850\n00:46:13,438 --> 00:46:16,272\nthen I want my scale to be twice of what it was. And\n然后我就需要重置 scale 的大小为两倍\n\n851\n00:46:16,274 --> 00:46:17,673\nif it goes down to 0.5, I want my scale\n如果手势变为原来一半，我的 scale\n\n852\n00:46:17,675 --> 00:46:20,743\nto be 0.5 of what it was. Okay, but this is gonna\n就需要变为 0.5 这个过程\n\n853\n00:46:20,745 --> 00:46:24,380\nbe repeatedly called as that thing is moving in and out, so\n随着手势的变化会被重复调用\n\n854\n00:46:24,382 --> 00:46:30,219\nI need to make sure here that I reset the recognizer scale\n所以我总是需要重置识别器的大小为1\n\n855\n00:46:30,488 --> 00:46:33,589\nto 1.0 all the time. So that, as it moves out,\n随着手势变化\n\n856\n00:46:33,591 --> 00:46:37,126\nit's going to be give me the incremental scale in and out.\n这里需要一个递增的 scale 值\n\n857\n00:46:37,128 --> 00:46:40,630\nBecause I'm actually applying the scale change every single\n因为每次移动时都会应用这个 scale\n\n858\n00:46:40,632 --> 00:46:45,468\ntime it moves, every .Changed here I'm applying the scale,\n在手势 Changed 时，我需要应用 scale \n\n859\n00:46:45,470 --> 00:46:49,005\nokay. Now of course we need to have the default,\n当然也需要这个 default\n\n860\n00:46:49,007 --> 00:46:53,709\nstate which is cancel, it covers cancelled and began and\n当手势 Cancel 等状态，他包括了Cancel、Began\n\n861\n00:46:53,711 --> 00:46:53,876\nall those things.\n等等状态\n\n862\n00:46:53,878 --> 00:46:56,179\nAnd it those case statuses I'm just gonna do nothing because\n当识别到这些状态我什么也不做\n\n863\n00:46:56,181 --> 00:46:59,215\nI'm actually tracking the scale and implementing it\n因为实际上追踪 scale 变化和执行这些变化\n\n864\n00:46:59,217 --> 00:47:02,585\nas it goes along, so I don't even care when it ends, okay.\n是一直进行的，所以不用关心什么时候手势结束了\n\n865\n00:47:02,587 --> 00:47:06,389\nI mean, it's nice when the fingers go up to do that one\n在手指抬起时再做一次\n\n866\n00:47:06,391 --> 00:47:09,158\nlast adjustment of the scale but it's not crucial. Okay,\n尺寸大小的调整是很好，但是并不是必须的\n\n867\n00:47:09,160 --> 00:47:11,661\nand if we were cancelled, we wouldn't get that opportunity\n当他 Cancelled 我们不需要获取到这个时机\n\n868\n00:47:11,663 --> 00:47:15,131\nanyway. Okay, everyone understand that?\n大家明白了吗？\n\n869\n00:47:15,133 --> 00:47:21,737\nThis is a public method, yeah. >> [INAUDIBLE]\n这是一个 public 方法\n\n870\n00:47:21,739 --> 00:47:22,238\n>> Well, yeah, see I'm, this\n [提问]\n\n871\n00:47:22,240 --> 00:47:24,507\nis why I ask three or four times, everybody getting this.\n这就是为什么我问了三四次大家明白了吗\n\n872\n00:47:24,509 --> 00:47:25,808\nAnd everyone was kind of like yeah, I think so.\n大家都是一副我懂了的样子\n\n873\n00:47:25,810 --> 00:47:30,179\nOkay. The reason for this is, if I don't do this, okay,\n为什么这么做呢？因为如果我不重置 scale 大小\n\n874\n00:47:30,181 --> 00:47:34,517\nthen as I pinch, I'm gonna get the cumulative scale, okay. So\n在 pinch 手势中，我会得到一个累积的 scale\n\n875\n00:47:34,519 --> 00:47:37,520\nlet's say I start here, okay. And I start moving it out,\n我这么说，手势开始移动来\n\n876\n00:47:37,522 --> 00:47:39,021\nmoving it out. And it's getting called changed,\n移动去，它会调用 Changed\n\n877\n00:47:39,023 --> 00:47:43,726\nchange, change, change, okay. First time it's 1.1, 1.2, 1.3,\nChanged、Changed，scale 会变为 1.1, 1.2, 1.3,\n\n878\n00:47:43,728 --> 00:47:46,128\n1.4, 1.5, 1.6, 2.0, okay.\n1.4, 1.5, 1.6, 2.0\n\n879\n00:47:46,130 --> 00:47:49,198\nSo it's getting called seven times with all those numbers.\n这些数字代表 Changed case 会被执行七次\n880\n00:47:49,200 --> 00:47:52,501\nImagine if I took my scale and multiplied it times by 1.0.\n想象一下，我首先将这个 scale 乘以 1.0\n\n881\n00:47:52,503 --> 00:47:54,937\nAnd then I multiplied it times 1.2, 1.3, 1.4.\n之后乘以 1.2, 1.3, 1.4.\n\n882\n00:47:54,939 --> 00:47:57,306\nNow the scale's getting gigantic. Okay,\n现在这个 scale 会变得十分巨大\n\n883\n00:47:57,308 --> 00:48:00,943\nthat's not what I want. What I want is the incremental scale.\n这可不是我想要的，我想要的是一个递增的 scale\n\n884\n00:48:00,945 --> 00:48:03,679\nSo if I keep resetting it to 1, then when it gets a little\n所以我一直将 scale 重置为1\n\n885\n00:48:03,681 --> 00:48:07,116\nbigger, I'm gonna get 1.01 again, okay? Reset to 1,\n当 scale 变大时，会乘以 1\n\n886\n00:48:07,118 --> 00:48:11,621\n1.01 again, you see? Exactly, I'm not by the scale. Now,\n再乘以 1.01 你明白了吗？我不会直接乘以之前的 scale\n\n887\n00:48:11,623 --> 00:48:14,757\nthe alternative is, I could just have the pinch do nothing\n也可以在这里不重置\n\n888\n00:48:14,759 --> 00:48:17,793\nuntil you let go and then I could set the scale, okay?\n直接让 scale 变化，之后再重置\n\n889\n00:48:17,795 --> 00:48:18,928\nBut, since I'm doing it incrementally,\n但是，因为我想要让 scale 递增\n\n890\n00:48:18,930 --> 00:48:23,966\nI have to keep resetting it to 1, okay? Good question. All\n就需要每次将它重置为 1\n\n891\n00:48:23,968 --> 00:48:27,436\nright, so now if we go back to our FaceViewController,\n现在，我们回到 FaceViewController 中\n\n892\n00:48:27,438 --> 00:48:29,939\nyou'll see that we don't have an error here anymore on this\n你可以看到这时这里就不再有 error 了\n\n893\n00:48:29,941 --> 00:48:33,876\nline because we've actually defined this handler, okay? So\n因为我确实定义了处理手势的方法\n\n894\n00:48:33,878 --> 00:48:39,415\nnow when we run, and we pinch. We're gonna update the scale,\n现在我们运行、做捏合手势，这个 view 的 scale 就会被更新了\n\n895\n00:48:39,417 --> 00:48:40,683\nhopefully, of our face.\n希望如此\n\n896\n00:48:40,685 --> 00:48:42,952\nSo here's our face. He doesn't look very happy, but\n这是 face ，它看起来不怎么高兴\n\n897\n00:48:42,954 --> 00:48:45,755\nI'm going to make him smaller, so we won't notice, okay? Now,\n但是一会儿我们让它高兴些，现在先不用在意\n\n898\n00:48:45,757 --> 00:48:48,958\nyou might ask, how am I gonna pinch with my mouse, okay?\n你可能会问，我只有一个鼠标，怎么做捏合手势\n\n899\n00:48:48,960 --> 00:48:51,594\nI've got my mouse here, I can't, just a little,\n我把鼠标放这里，怎么捏合呢？\n\n900\n00:48:51,596 --> 00:48:55,564\nhow am I gonna do it? And the answer is, Option, okay?\n答案是，Option 键\n\n901\n00:48:55,566 --> 00:48:56,198\nIf you're running the simulator and\n如果你运行模拟器\n\n902\n00:48:56,200 --> 00:48:59,669\nyou hold down Option, look. Two fingers come up there,\n按下 Option键后，就出现两根手指了\n\n903\n00:48:59,671 --> 00:49:04,874\nokay? Now you can mouse down and drag and it's like you’re\n你可以用鼠标移动它\n\n904\n00:49:04,876 --> 00:49:09,512\npinching. You see, pinching in pinching out,\n看起来你想在做捏合手势，放大放小\n\n905\n00:49:09,514 --> 00:49:15,351\nokay? Got it, so you can see these gesture hands\n你看这些手势\n\n906\n00:49:15,353 --> 00:49:19,255\nare super easy to implement, okay? We probably had four\n做起来很简单的，我们可能\n\n907\n00:49:19,257 --> 00:49:22,725\nlines of code there, of actual lines of code. All right,\n就写了几行代码吧 \n\n908\n00:49:22,727 --> 00:49:25,761\nnow, let's do another gesture recognizer, okay? Let's have\n现在，我们添加另一个手势识别器\n\n909\n00:49:25,763 --> 00:49:28,464\nthis one modify our model. So what I'm gonna do here is,\n这个手势会改变我们的模型，所以我需要在这里\n\n910\n00:49:28,466 --> 00:49:32,368\nI'm gonna make it so that when I swipe down, he gets sadder.\n当我向下扫动时，它看起来更悲伤\n\n911\n00:49:32,370 --> 00:49:33,069\nAnd when I swipe up,\n向上扫动时\n\n912\n00:49:33,071 --> 00:49:37,039\nhe gets happier in a model sense, okay? Okay,\n它看起来高兴一点\n\n913\n00:49:37,041 --> 00:49:38,007\nI'm gonna make the model happier.\n需要改变 model 属性让它更高兴\n\n914\n00:49:38,009 --> 00:49:40,643\nI'm not gonna move my mouth curvature. I'm gonna change\n我需要设置嘴巴弯曲的程度，这将会改变 model 属性\n\n915\n00:49:40,645 --> 00:49:42,812\nthe model. Now of course, every time I change the model,\n每一次我改变了 model\n\n916\n00:49:42,814 --> 00:49:44,981\nthat's going to change my mouth curvature. So\n就会改变嘴巴的弯曲程度\n\n917\n00:49:44,983 --> 00:49:47,149\nit's gonna work. But we're gonna change the model.\n我们需要改变 model\n\n918\n00:49:47,151 --> 00:49:50,353\nSo to do that, I'm gonna do a swipe gesture.\n为了实现这个功能，我将加一个轻扫的手势\n\n919\n00:49:50,355 --> 00:49:51,887\nNow, a swipe gesture we have to configure.\n轻扫手势需要我们做一些配置\n\n920\n00:49:51,889 --> 00:49:55,725\nSo I'm to create a local variable to hold it, okay?\n创建一个局部变量保存这个手势识别器\n\n921\n00:49:55,727 --> 00:50:00,396\nI am gonna call this local variable,\n这个局部变量叫做\n\n922\n00:50:00,398 --> 00:50:05,201\nmy happierSwipeGestureRecognizer,\nhappierSwipeGestureRecognizer\n\n923\n00:50:05,203 --> 00:50:10,806\nand so I say UISwipeGestureRecognizer.\nUISwipeGestureRecognizer 方法创建\n\n924\n00:50:10,808 --> 00:50:11,007\nSwipeGestureRecognizer and same arguments though,\n与之前一样的参数\n\n925\n00:50:11,009 --> 00:50:15,411\nOops,\n\n926\n00:50:15,413 --> 00:50:19,982\ntarget and action, okay? So the target here, okay,\n需要设置 target 和 action，target 就是这个\n\n927\n00:50:19,984 --> 00:50:23,953\nis not going to be the faceView because it modifies\ntarget 不会是 faceView 了\n\n928\n00:50:23,955 --> 00:50:28,457\nthe model, it's gonna be self. Okay,\n因为这个手势会改变 model，应该是 self\n\n929\n00:50:28,459 --> 00:50:31,560\ncontroller has to be the one handling this one, okay?\ncontroller 应该来处理这个手势\n\n930\n00:50:31,562 --> 00:50:36,032\nAnd the action, which is the selector, is going to be\naction 应该是一个 controller 的方法\n\n931\n00:50:36,501 --> 00:50:41,804\na FaceViewController selector, not a FaceView one.\n并不是 FaceView 中的方法了\n\n932\n00:50:41,806 --> 00:50:45,107\nAnd we'll call this thing we'll do,\n我们会调用这个处理方法\n\n933\n00:50:45,109 --> 00:50:48,511\nwe'll make this be the happier one, so this is swipe up, so\n我们希望这个方法能让 FaceView 开心些\n\n934\n00:50:48,513 --> 00:50:52,748\nwe'll call this increaseHappiness, okay?\n这个方法被命名为 increaseHappiness\n\n935\n00:50:52,750 --> 00:50:55,017\nAnd I don't need the swipe gesture\n调用这个方法时，我就不需要这个轻扫手势了\n\n936\n00:50:55,019 --> 00:50:57,353\nbecause it's either gonna be recognized or not. So\n可以将它作为参数传递或者不传\n\n937\n00:50:57,355 --> 00:50:58,854\nI'm not gonna have any arguments\n我不需要任何参数\n\n938\n00:50:58,856 --> 00:51:03,092\nto that increaseHappiness method, okay?\n来调用 increaseHappiness\n\n939\n00:51:03,094 --> 00:51:05,061\nOkay, I'll do the same thing here so\n这里我会写这个\n\n940\n00:51:05,063 --> 00:51:08,297\nyou can see this a little better, okay? So this is not,\n这样写好一些\n\n941\n00:51:08,299 --> 00:51:11,233\nthis guy right here is not going to have any arguments.\n这个方法不需要写任何参数\n\n942\n00:51:11,235 --> 00:51:15,304\nSo that's gonna be a func, okay? increaseHappiness,\n所以只是一个 increaseHappiness\n\n943\n00:51:15,306 --> 00:51:18,641\nno arguments. And when the increaseHappiness happens,\n不包括参数，当 increaseHappiness 被调用时\n\n944\n00:51:18,643 --> 00:51:22,144\nwhat are we gonna do to our model, okay? Well,\n我们需要修改model\n\n945\n00:51:22,146 --> 00:51:25,581\nwe're just gonna say that our facial expression's mouth\n我们 expression.mouth\n\n946\n00:51:25,583 --> 00:51:30,753\nequals the expression's mouth.happierMouth.\n等于 expression.mouth.happierMouth\n\n947\n00:51:30,755 --> 00:51:34,323\nOkay, so if you look at our facial expression over here,\n如果你回过头看 FacialeExpression 类\n\n948\n00:51:34,325 --> 00:51:37,293\nokay, mouth okay?\n枚举类型 Mouth \n\n949\n00:51:37,295 --> 00:51:40,863\nThis enum has two methods, sadderMouth and happierMouth,\n这个枚举有两个方法，sadderMouth 和 happierMouth\n\n950\n00:51:40,865 --> 00:51:44,133\nwhich will take the current mouth and make it sadder or\n这个方法将改变当前的表情，更悲伤\n\n951\n00:51:44,135 --> 00:51:47,236\nhappier and return a new mouth, okay? So\n或者更高兴，并且返回一个新的 Mouth 枚举类型\n\n952\n00:51:47,238 --> 00:51:51,941\nit's just gonna go more happy or less happy along here.\n使表情高兴一点或者是更高兴\n\n953\n00:51:51,943 --> 00:51:57,880\nOkay, so we got that. Now so that's gonna be fine.\n好了，我们现在写完了\n\n954\n00:51:57,882 --> 00:52:02,017\nThis swipe gesture though, we have to add it to our view.\n这个轻扫手势我们需要添加到 view 上\n\n955\n00:52:02,019 --> 00:52:03,085\nWe have to do addGestureRecognizer.\n我们需要 addGestureRecognizer\n\n956\n00:52:03,087 --> 00:52:06,021\nWe haven't done that. And we also have to configure it.\n这一步还没写，我们还需要配置这个手势识别器\n\n957\n00:52:06,023 --> 00:52:08,791\nSo let's configure it. This is happier. So\n这个是更高兴的手势\n\n958\n00:52:08,793 --> 00:52:13,596\nI'm gonna have the hype, the SwipeGestureRecognizerDirect-\n所以我需要配置 SwipeGestureRecognizerDirection\n\n959\n00:52:13,598 --> 00:52:18,834\nion. Okay, which is the direction of the swipe,\n设置轻扫手势的 direction 为\n\n960\n00:52:18,836 --> 00:52:22,138\n= .Up. Okay, so you're swiping up, that's for\nUp, 好了，当你向上扫动时\n\n961\n00:52:22,140 --> 00:52:23,572\nhappier, and now we, and\n表情看起来会更高兴\n\n962\n00:52:23,574 --> 00:52:28,177\nit will have it be a single finger swipe, not two. And so\n是一个手指扫动不是两个\n\n963\n00:52:28,179 --> 00:52:33,382\nnow I can just say faceView.addGestureRecognizer-\n现在，我们可以给 faceView 添加手势识别器\n\n964\n00:52:33,384 --> 00:52:38,988\n(happierSwipeGestureRecogniz- er), okay?\nhappierSwipeGestureRecognizer\n\n965\n00:52:39,357 --> 00:52:43,259\nMake sense there? All right, let's go try this.\n明白了吗？\n\n966\n00:52:43,261 --> 00:52:45,761\nNow notice every time we change the expression here,\n现在每一次我们改变了 expression\n\n967\n00:52:45,763 --> 00:52:48,430\nit's gonna automatically update our UI because of this\n将会自动更新 UI\n\n968\n00:52:48,432 --> 00:52:52,201\ndidSet. You see that? We changed this expression, boom,\n因为expression 的 didSet 方法里\n\n969\n00:52:52,203 --> 00:52:55,571\nupdateUI. So, let's try it. All right, so,\n有 updateUI 再运行一次\n\n970\n00:52:55,573 --> 00:52:56,238\nhopefully this is still working.\n希望能奏效\n\n971\n00:52:56,240 --> 00:52:58,741\nPinching, yes, still working. Now I'm gonna swipe up and\n捏合手势还可以进行，现在我想\n\n972\n00:52:58,743 --> 00:53:03,245\nsure enough, he's getting happier and happier. Okay, but\n向上扫动，它变得高兴一点儿了\n\n973\n00:53:03,247 --> 00:53:05,481\nwe better do swipe down also, okay?\n但是向下扫动没有效果\n\n974\n00:53:05,483 --> 00:53:08,350\nWe don't have all only swipe up, let's get swipe down in\n我们不能只写向上扫动的方法，还得写向下扫动的\n\n975\n00:53:08,352 --> 00:53:10,719\nthere. In fact, I'm gonna do that by copying and\n事实上，因为向上和向下的代码差不多一样\n\n976\n00:53:10,721 --> 00:53:13,455\npasting because it's almost the same as this.\n我要复制粘贴这段代码\n\n977\n00:53:13,457 --> 00:53:18,360\nI'm just gonna replace this happier here with sadder.\n将 happier 替换为 sadder\n\n978\n00:53:21,465 --> 00:53:25,501\nAnd instead of it being an up swipe, it's gonna be a down\n将向上替换为向下\n\n979\n00:53:25,503 --> 00:53:28,871\nswipe. And instead of increasing the happiness,\n增加高兴值变成\n\n980\n00:53:28,873 --> 00:53:30,973\nit's going to decrease the happiness.\n降低高兴值\n\n981\n00:53:30,975 --> 00:53:37,479\nSo I need a new method here called decreaseHappiness.\n现在我需要一个新的方法叫 decreaseHappiness\n\n982\n00:53:38,216 --> 00:53:42,451\nAnd this one's going to get the sadderMouth, okay?\n设置为 sadderMouth\n\n983\n00:53:42,453 --> 00:53:45,454\nEveryone understand, it's real important to understand here\n大家都明白了吗？明白这个十分重要\n\n984\n00:53:45,456 --> 00:53:48,457\nthat we have recognizers that as they're being handled,\n我们写好了手势识别器\n\n985\n00:53:48,459 --> 00:53:49,658\nthey're being handled by the controller.\n手势被 controller 所识别\n\n986\n00:53:49,660 --> 00:53:53,829\nAnd the controller's modifying the model. And since, and\ncontroller 也将改变 model\n\n987\n00:53:53,831 --> 00:53:56,865\nevery time the model gets modified, it calls updateUI.\n每一次，model变化了，就会更新 UI\n\n988\n00:53:56,867 --> 00:54:00,469\nupdateUI is the thing that's going to update, in this case,\nupdateUI 就是在这个例子中就是更新 faceView\n\n989\n00:54:00,471 --> 00:54:04,940\nthe mouth curvature. Everybody understand that flow? Okay, so\n嘴巴的弯曲程度，大家都明白这个流程了吗？\n\n990\n00:54:04,942 --> 00:54:11,647\nlet's make sure that swipe down is working. All right,\n现在让我们看看轻扫手势生效了吗\n\n991\n00:54:11,649 --> 00:54:16,118\nso swipe down, sad. Swipe up, happy, okay? Sad,\n向下扫动，变悲伤，向上扫动，变高兴了\n\n992\n00:54:16,120 --> 00:54:21,023\nhappy, got it? All right, let's do one more gesture.\n让我们再做些手势\n\n993\n00:54:21,025 --> 00:54:24,593\nThis one, when you tap, he's gonna open and close his eyes.\n当你点击时，它会睁开或者闭上它的眼睛\n\n994\n00:54:24,595 --> 00:54:27,162\nEvery tap will toggle the opening and closing the eyes.\n每一次轻击就会在睁眼或闭眼中切换\n\n995\n00:54:27,164 --> 00:54:30,165\nNow I'm gonna do this one a little bit different, because\n现在，我想用不一样的方法写这个手势\n\n996\n00:54:30,167 --> 00:54:32,868\nwe added all these gesture recognizers in code here.\n因为我们在这里添加了所有的手势识别器代码\n\n997\n00:54:32,870 --> 00:54:35,271\nYou see how this adding GestureRecognizer in code?\n你想看看我怎么添加新手势吗？\n\n998\n00:54:35,273 --> 00:54:41,977\nYou can actually add these things in your storyboard,\n你完全可以在 storyboard 中添加手势\n\n999\n00:54:41,979 --> 00:54:46,115\nokay? So let's go over to our storyboard, right here,\n现在来到 storyboard \n\n1000\n00:54:46,117 --> 00:54:51,687\nokay? Let's get our controller onscreen at the same time,\n同时，让 controller 同时出现在屏幕上\n\n1001\n00:54:51,689 --> 00:54:53,989\nAutomatic. So here's our controller over here.\n\n1002\n00:54:53,991 --> 00:54:58,761\nHere's our faceView over here. If I wanna add a gesture to my\n\n1003\n00:54:58,763 --> 00:55:02,364\nfaceView right here from my storyboard, I go over here to\n\n1004\n00:55:02,366 --> 00:55:05,200\nthe bottom, same place I get buttons and things like that.\n\n1005\n00:55:05,202 --> 00:55:09,605\nIf you scroll way down, you'll see there are gesture\n\n1006\n00:55:09,607 --> 00:55:12,675\nrecognizers here, you see? Rotation, pinch, swipe, pan.\n\n1007\n00:55:12,677 --> 00:55:16,645\nHere's tap. I'm gonna take tap out and drag it onto the view\n\n1008\n00:55:16,647 --> 00:55:19,948\nI want to recognize the tap, which is my faceView. And\n\n1009\n00:55:19,950 --> 00:55:22,951\nwhen you do that, it actually appears along the top here.\n\n1010\n00:55:22,953 --> 00:55:25,054\nSee that Tap Gesture Recognizer right there? And\n\n1011\n00:55:25,056 --> 00:55:28,424\nyou can even inspect it. You could set how many taps,\n\n1012\n00:55:28,426 --> 00:55:31,727\nhow many touches, okay, how many fingers. Okay,\n\n1013\n00:55:31,729 --> 00:55:36,598\nyou can also Ctrl+drag from it over here, let's do it down\n\n1014\n00:55:36,600 --> 00:55:42,137\na little lower, here. Okay, you can Ctrl+drag and\n\n1015\n00:55:42,139 --> 00:55:47,776\ncreate the gesture recognizer action, okay, right here.\n\n1016\n00:55:47,778 --> 00:55:52,381\nSo I'm gonna call this toggleEyes,\n\n1017\n00:55:52,383 --> 00:55:53,449\nokay? And the argument,\n\n1018\n00:55:53,451 --> 00:55:55,951\nI'm gonna make it to a tap gesture instead of any object.\n\n1019\n00:55:55,953 --> 00:55:59,521\nWe all know to get rid of the any object in these little,\n\n1020\n00:55:59,523 --> 00:56:03,359\ndialogues. Okay, so here's my tap gesture right here.\n\n1021\n00:56:03,361 --> 00:56:07,363\nLet's go ahead and go back to full screen,\n\n1022\n00:56:07,365 --> 00:56:10,699\nokay? So, here's my tap gesture for toggleEyes. So,\n\n1023\n00:56:10,701 --> 00:56:14,603\nin here I need to toggle my eye, so I'm just going to say,\n\n1024\n00:56:14,605 --> 00:56:21,643\nif the recognizer's state is ended. Okay? So the tap ended,\n\n1025\n00:56:21,645 --> 00:56:24,446\nso I'm gonna take action here and do the toggle.\n\n1026\n00:56:24,448 --> 00:56:28,250\nThen, depending on what the expression's current eyes are,\n\n1027\n00:56:28,252 --> 00:56:30,519\nif it, they're open, then I'm gonna be the,\n\n1028\n00:56:30,521 --> 00:56:34,990\nmake the expression's eyes be closed. And\n\n1029\n00:56:34,992 --> 00:56:37,860\nif it's, if the eyes are closed, then I'm gonna make\n\n1030\n00:56:37,862 --> 00:56:42,598\nthe expression's eyes open. And if the express,\n\n1031\n00:56:42,600 --> 00:56:46,168\nif the expression is squinting then I'm going to do nothing\n\n1032\n00:56:46,170 --> 00:56:51,106\ncuz I don't know how to handle squinting. Okay make\n\n1033\n00:56:51,108 --> 00:56:57,079\nsense? Sorry notice I used recognizer.state here.\n\n1034\n00:56:57,081 --> 00:57:00,015\nBy default when you Ctrl+drag it calls a thing sender.\n\n1035\n00:57:00,017 --> 00:57:02,684\nI really like to call this recognizer. So\n\n1036\n00:57:02,686 --> 00:57:05,654\nthat you remember that it's a recognizer that we're dealing\n\n1037\n00:57:05,656 --> 00:57:09,425\nwith here, okay, gesture recognizer. Okay so\n\n1038\n00:57:09,427 --> 00:57:15,230\nlet's try that. All right,\n\n1039\n00:57:15,232 --> 00:57:19,001\nyour face. We can make him happier and we can open and\n\n1040\n00:57:19,003 --> 00:57:22,704\nclose his eyes. Okay? Maybe later in the quarter,\n\n1041\n00:57:22,706 --> 00:57:23,071\nwe'll talk about animation,\n\n1042\n00:57:23,073 --> 00:57:27,676\nwe'll talk about animating the eye it will turn so he blinks.\n\n1043\n00:57:27,678 --> 00:57:31,880\nOkay? And I'm gonna post code after lecture because\n\n1044\n00:57:31,882 --> 00:57:34,283\nthe time here I wanna make sure we get to the next thing.\n\n1045\n00:57:34,285 --> 00:57:37,753\nWhere I'm gonna show how to do rotation to move those\n\n1046\n00:57:37,755 --> 00:57:38,420\neyebrows. Okay?\n\n1047\n00:57:38,422 --> 00:57:42,558\nSo, rotate the eyebrows down or rotate them up. Okay?\n\n1048\n00:57:42,560 --> 00:57:44,026\nI'll show you how to do a rotation disk, so\n\n1049\n00:57:44,028 --> 00:57:46,762\nthat'll be in the code that I post. Okay,\n\n1050\n00:57:46,764 --> 00:57:50,866\nany questions about gestures? Pretty straightforward, okay?\n\n1051\n00:57:50,868 --> 00:57:54,136\nAll right, let's get back to our\n\n1052\n00:57:54,138 --> 00:57:58,674\nslides. >> Is\n\n1053\n00:57:58,676 --> 00:58:04,279\nthat odd gesture recognizer code automatically\n\n1054\n00:58:04,281 --> 00:58:06,782\nadded to the UIView? >> Okay so\n\n1055\n00:58:06,784 --> 00:58:11,453\nthe question was is that eye gesture recognize your code\n\n1056\n00:58:11,455 --> 00:58:12,721\nthat I put in there do the tap.\n\n1057\n00:58:12,723 --> 00:58:15,657\nIs it already automatically added to the UIView?\n\n1058\n00:58:15,659 --> 00:58:19,695\nAnd the answer, you mean the add gesture recognizer?\n\n1059\n00:58:19,697 --> 00:58:20,829\nCog it made? >> Yeah.\n\n1060\n00:58:20,831 --> 00:58:22,598\n>> Yeah, that, basically,\n\n1061\n00:58:22,600 --> 00:58:23,532\nwhen you can control,\n\n1062\n00:58:23,534 --> 00:58:27,002\nwhen I dragged the tap gesture onto the face view,\n\n1063\n00:58:27,004 --> 00:58:27,135\nthe add gesture recognizer was gonna happen. Make sense?\n\n1064\n00:58:27,137 --> 00:58:30,372\nthat made it so\n\n1065\n00:58:30,374 --> 00:58:35,410\nGood question, though. Okay, so, back to the slides here.\n\n1066\n00:58:35,412 --> 00:58:39,214\nNow we're gonna start talking about MVCs working together.\n\n1067\n00:58:39,216 --> 00:58:43,352\nOkay? This is a slide from when I was talking about MVCs\n\n1068\n00:58:43,354 --> 00:58:45,621\nand we talked about we wanted to build big apps, and\n\n1069\n00:58:45,623 --> 00:58:47,089\nwe're gonna do that with multiple MVCs.\n\n1070\n00:58:47,091 --> 00:58:50,959\nSo, we're gonna start talking about how we actually do that.\n\n1071\n00:58:50,961 --> 00:58:55,063\nAll right? The way we combine MVCs as\n\n1072\n00:58:55,065 --> 00:58:59,268\nI talked about before is that we're gonna have an MVC, okay?\n\n1073\n00:58:59,270 --> 00:59:04,506\nWhose view is made up of other MVCs. Okay?\n\n1074\n00:59:04,508 --> 00:59:09,378\nNow iOS provides for us some MVCs that are like this.\n\n1075\n00:59:09,380 --> 00:59:13,248\nOkay, MVCs whose view is other MVCs. Now, it is possible for\n\n1076\n00:59:13,250 --> 00:59:17,286\nyou to create your own MVCs that have other MVCs as view,\n\n1077\n00:59:17,288 --> 00:59:19,721\nbut it is really beyond the scope of this class.\n\n1078\n00:59:19,723 --> 00:59:22,424\nOkay? So in this class we are only gonna use the ones that\n\n1079\n00:59:22,426 --> 00:59:27,596\nare provided by iOS. These MVCs that use other MVCs as\n\n1080\n00:59:27,598 --> 00:59:30,799\ntheir view. Now specifically, we are gonna talk about\n\n1081\n00:59:30,801 --> 00:59:33,936\nTabBarController. Everyone know what that is all right?\n\n1082\n00:59:33,938 --> 00:59:34,369\nYou've seen that in an iOS\n\n1083\n00:59:34,371 --> 00:59:37,306\nAVS the little tabs on the bottom and each time you click\n\n1084\n00:59:37,308 --> 00:59:39,474\non a different tab, what appears on top?\n\n1085\n00:59:39,476 --> 00:59:45,280\nA different MVC, okay. Also SplitViewController mostly you\n\n1086\n00:59:45,282 --> 00:59:48,717\nsee this on an iPad you can all see on an iPhone 6 plus.\n\n1087\n00:59:48,719 --> 00:59:53,355\nThis is where you're splitting your screen into two halves.\n\n1088\n00:59:53,357 --> 00:59:53,522\nOkay, not really halves.\n\n1089\n00:59:53,524 --> 00:59:56,925\nTwo parts, one side's usually smaller that the other, okay?\n\n1090\n00:59:56,927 --> 01:00:00,295\nSo, each side a different MVC. So, you see how\n\n1091\n01:00:00,297 --> 01:00:03,231\nwe combine two MVCs right there. And then, of course,\n\n1092\n01:00:03,233 --> 01:00:08,003\nUINavigationController, the number one combiner of MVCs.\n\n1093\n01:00:08,005 --> 01:00:09,938\nOkay, this is something where you have\n\n1094\n01:00:09,940 --> 01:00:12,808\nan MVC, it's got a button in it, you click it, and a new\n\n1095\n01:00:12,810 --> 01:00:15,243\nMVC appears, where there's a back button at the top,\n\n1096\n01:00:15,245 --> 01:00:18,981\nand you've click it to go back to the one you were on. Okay?\n\n1097\n01:00:18,983 --> 01:00:21,950\nSee navigation controllers in almost every iOS app that's\n\n1098\n01:00:21,952 --> 01:00:24,553\never been designed ever except for\n\n1099\n01:00:24,555 --> 01:00:27,155\nmaybe games that are all one MVC.\n\n1100\n01:00:27,157 --> 01:00:29,558\nYou're gonna see navigation controllers. Okay so\n\n1101\n01:00:29,560 --> 01:00:32,160\nlet's talk a little bit about how all these things work.\n\n1102\n01:00:32,162 --> 01:00:33,895\nSo let's talk about the TabBarControllers and\n\n1103\n01:00:33,897 --> 01:00:35,831\nthe simplest of them all, right?\n\n1104\n01:00:35,833 --> 01:00:37,232\nYou've seen this right it's got the tabs along\n\n1105\n01:00:37,234 --> 01:00:39,468\nthe bottom here. I've got this one the dashboard this is\n\n1106\n01:00:39,470 --> 01:00:42,704\nthe health app I think. Got the dashboard selection here,\n\n1107\n01:00:42,706 --> 01:00:47,142\nand this entire space is being owned and managed\n\n1108\n01:00:47,144 --> 01:00:51,613\nby a Dashboard MVC. Not the TabBarController MVC, but\n\n1109\n01:00:51,615 --> 01:00:55,417\nthe dash part MVC. And in fact this dashboard is controlling\n\n1110\n01:00:55,419 --> 01:00:58,453\nnot only the contents of here. But it tells you,\n\n1111\n01:00:58,455 --> 01:01:00,889\nour TabBarcontroller what icon to put here and\n\n1112\n01:01:00,891 --> 01:01:04,926\nwhat word to put here. Okay? These tabs over here, these\n\n1113\n01:01:04,928 --> 01:01:09,564\nother tabs are, their contents are controlled by other MVCs.\n\n1114\n01:01:09,566 --> 01:01:14,269\nOkay? So, this var, tab bar item that you see right there.\n\n1115\n01:01:14,271 --> 01:01:18,306\nIt's kind of a little bag of goodies that each MVC,\n\n1116\n01:01:18,308 --> 01:01:20,509\nremember an MVC is controlled by its controller.\n\n1117\n01:01:20,511 --> 01:01:22,778\nSo this is a method in UIViewController.\n\n1118\n01:01:22,780 --> 01:01:25,781\nAnd it has things in there like the icon and the text for\n\n1119\n01:01:25,783 --> 01:01:28,617\nthe tab, okay? In TabBarItem. So you can take a look at\n\n1120\n01:01:28,619 --> 01:01:31,420\nthe TabBarItem and you'll immediately see. What's going\n\n1121\n01:01:31,422 --> 01:01:34,156\non there. All right. So, let's click on a different one,\n\n1122\n01:01:34,158 --> 01:01:38,160\nlike Health Data, and we get a completely different MVC here.\n\n1123\n01:01:38,162 --> 01:01:39,127\nThis is the Health Data MVC.\n\n1124\n01:01:39,129 --> 01:01:41,396\nCompletely unrelated to this one. Okay?\n\n1125\n01:01:41,398 --> 01:01:44,332\nUtterly and completely unrelated to this one.\n\n1126\n01:01:44,334 --> 01:01:48,403\nOkay? Here, one thing to notice about this is,\n\n1127\n01:01:48,405 --> 01:01:51,406\nif there are more than five tabs down here.\n\n1128\n01:01:51,408 --> 01:01:55,177\nThis actually still works. It'll automatically replace\n\n1129\n01:01:55,179 --> 01:01:57,512\nthe 5th one with a tab here that says More.\n\n1130\n01:01:57,514 --> 01:02:01,283\nAnd when you click on More it'll have a UITabBar\n\n1131\n01:02:01,285 --> 01:02:04,753\ncontrolled UI in here that has all the other tabs in here.\n\n1132\n01:02:04,755 --> 01:02:07,656\nAnd you can pick them. Or you can actually choose to put\n\n1133\n01:02:07,658 --> 01:02:11,393\nthem down here, okay, which four you want down here. Okay,\n\n1134\n01:02:11,395 --> 01:02:12,494\nand that happens automatically for you.\n\n1135\n01:02:12,496 --> 01:02:14,329\nYou don't have to do anything to make that work.\n\n1136\n01:02:14,331 --> 01:02:18,033\nI don't really recommend UIs that have more than five tabs\n\n1137\n01:02:18,035 --> 01:02:20,802\ndown here. It's a little bit of a pain for people to have\n\n1138\n01:02:20,804 --> 01:02:24,806\nto have that more thing, but it's not out of the question.\n\n1139\n01:02:24,808 --> 01:02:26,274\nObviously the functionality's in there.\n\n1140\n01:02:26,276 --> 01:02:29,277\nIf you can do it without it, that'd be nice. Okay here's\n\n1141\n01:02:29,279 --> 01:02:32,681\na couple more tabs here is the source's one another MVC\n\n1142\n01:02:32,683 --> 01:02:35,617\nanother so these are four completely separate MVCs.\n\n1143\n01:02:35,619 --> 01:02:37,119\nThey have nothing to do with each other okay.\n\n1144\n01:02:37,121 --> 01:02:40,722\nThe only thing that might link them maybe they share a model.\n\n1145\n01:02:40,724 --> 01:02:43,725\nThat's possible okay but maybe even not.\n\n1146\n01:02:44,194 --> 01:02:46,528\nOkay so a tab bar is what's you gonna use when you\n\n1147\n01:02:46,530 --> 01:02:51,967\nhave MVCs they're completely unrelated. Okay? All right.\n\n1148\n01:02:51,969 --> 01:02:52,634\nWhat about SplitViewController?\n\n1149\n01:02:52,636 --> 01:02:56,171\nSo, SplitViewController puts two MVCs side by side. So,\n\n1150\n01:02:56,173 --> 01:02:59,441\nlet's imagine your calculator was a graphing calculator.\n\n1151\n01:02:59,443 --> 01:03:00,242\nOkay, instead of just a calculator,\n\n1152\n01:03:00,244 --> 01:03:03,278\nit could graph, what's going on over here.\n\n1153\n01:03:03,280 --> 01:03:05,447\nThen on the left here, you'd have your calculator, and\n\n1154\n01:03:05,449 --> 01:03:08,550\non the right, you'd have a totally different MVC.\n\n1155\n01:03:08,552 --> 01:03:10,485\nWhich is a graph view calculator,\n\n1156\n01:03:10,487 --> 01:03:13,588\ncalculator graph view, or something like that. Okay,\n\n1157\n01:03:13,590 --> 01:03:18,693\nwe call this one on the left the Master View Controller and\n\n1158\n01:03:18,695 --> 01:03:22,764\nwe call the one on the right the Detail View Controller.\n\n1159\n01:03:22,766 --> 01:03:25,767\nOkay, when you take your iPad here and\n\n1160\n01:03:25,769 --> 01:03:29,905\nyou rotate it, you still get both. Its just that\n\n1161\n01:03:29,907 --> 01:03:32,974\nthe detail will usually take over the whole screen. And\n\n1162\n01:03:32,976 --> 01:03:37,145\nyou can slide from the right, you kind of swipe in from, or\n\n1163\n01:03:37,147 --> 01:03:41,082\nsorry from the left. And you'll see that the master\n\n1164\n01:03:41,084 --> 01:03:46,154\nslides in on top of the detail. Okay. So\n\n1165\n01:03:46,156 --> 01:03:47,989\nthat's what view, how it, how it arrange.\n\n1166\n01:03:47,991 --> 01:03:52,227\nNavigationController, so NavigationController it's like\n\n1167\n01:03:52,229 --> 01:03:57,132\na stack of cards. Okay? Where each card is a different MVC.\n\n1168\n01:03:57,134 --> 01:03:59,100\nSo here I have an all settings MVC,\n\n1169\n01:03:59,102 --> 01:04:02,003\nokay, inside of a navigation controller Now,\n\n1170\n01:04:02,005 --> 01:04:05,006\nthis navigation controller is responsible for\n\n1171\n01:04:05,008 --> 01:04:07,342\ndrawing this title bar at the top, okay?\n\n1172\n01:04:07,344 --> 01:04:09,978\nThis whole area in the top where it says Settings. But\n\n1173\n01:04:09,980 --> 01:04:12,480\nit's not responsible for the actual contents\n\n1174\n01:04:12,482 --> 01:04:15,550\nof what's in there. That word Settings is determined,\n\n1175\n01:04:15,552 --> 01:04:19,754\njust like in tab bar situation, with by this MVC,\n\n1176\n01:04:19,756 --> 01:04:25,660\nokay? This MVC down here has a, property on it. It's view,\n\n1177\n01:04:25,662 --> 01:04:27,929\nit's view controller called Navigation Item. And\n\n1178\n01:04:27,931 --> 01:04:31,833\nnavigation item has properties in it like the title, the,\n\n1179\n01:04:31,835 --> 01:04:36,171\nany buttons that go here, maybe a back button title,\n\n1180\n01:04:36,173 --> 01:04:37,472\nthose kind of things.\n\n1181\n01:04:37,474 --> 01:04:40,809\nAll would be in this navigation item of this all\n\n1182\n01:04:40,811 --> 01:04:44,512\nSettings MVC, not of the navigation controller,\n\n1183\n01:04:44,514 --> 01:04:49,084\nright? So, here if I touched on General and\n\n1184\n01:04:49,086 --> 01:04:52,554\nI wanted the general settings, then of course, the general\n\n1185\n01:04:52,556 --> 01:04:57,392\nsettings would slide in, okay? And replace the whole contents\n\n1186\n01:04:57,394 --> 01:05:01,596\nhere with a general settings MVP, yet another new MVC. And\n\n1187\n01:05:01,598 --> 01:05:04,633\nnotice the back button by default will be set to have\n\n1188\n01:05:04,635 --> 01:05:07,903\nthe name of the previous MVC. That other MVC is still in\n\n1189\n01:05:07,905 --> 01:05:11,473\nthe navigation controller, it's just underneath, okay?\n\n1190\n01:05:11,475 --> 01:05:14,542\nSo this is stack of cards, I just put another MVC on top,\n\n1191\n01:05:14,544 --> 01:05:17,612\nso the other one's still there, okay? And\n\n1192\n01:05:17,614 --> 01:05:21,349\nyou can also put toolbar items at the bottom here, okay?\n\n1193\n01:05:21,351 --> 01:05:24,185\nThat's also controlled by whatever MVC is showing.\n\n1194\n01:05:24,187 --> 01:05:27,022\nSo this tool by are, barItems is a property on\n\n1195\n01:05:27,024 --> 01:05:30,926\nUIViewController, it's an array of UI toolbarItem, and\n\n1196\n01:05:30,928 --> 01:05:34,796\nit'll let you put toolbarItems down here, okay? Little,\n\n1197\n01:05:34,798 --> 01:05:38,934\nsmall buttons, okay? So again, if I click, let's say sorry.\n\n1198\n01:05:38,936 --> 01:05:42,404\nYeah, the back button got the title there, but you can also\n\n1199\n01:05:42,406 --> 01:05:45,040\nset the title to something different if you want,\n\n1200\n01:05:45,042 --> 01:05:48,843\nokay? So let's say I clicked on Accessibility right here,\n\n1201\n01:05:48,845 --> 01:05:52,847\nI get another new MVC. Now I have three MVCs on my stack,\n\n1202\n01:05:52,849 --> 01:05:56,051\nokay? Let's go ahead and click on another one here,\n\n1203\n01:05:56,053 --> 01:05:59,387\na larger text right there. Now I got another one, so\n\n1204\n01:05:59,389 --> 01:06:03,725\nnow I have four MVCs on my stack, okay? Now,\n\n1205\n01:06:03,727 --> 01:06:07,028\nI'm going to go and click on Accessibility,\n\n1206\n01:06:07,030 --> 01:06:11,766\nup in the top there, the back button. Now what happens? Now,\n\n1207\n01:06:11,768 --> 01:06:17,072\nthis MVC gets thrown away, in the trash, out of the heap,\n\n1208\n01:06:17,074 --> 01:06:21,776\ngone forever, okay? Now there's only three MVCs left,\n\n1209\n01:06:21,778 --> 01:06:23,511\nokay? The other one's completely gone.\n\n1210\n01:06:23,513 --> 01:06:25,847\nIt's important to understand on a MVC,\n\n1211\n01:06:25,849 --> 01:06:29,851\nwhen you go back, the one that got thrown off literally gets\n\n1212\n01:06:29,853 --> 01:06:33,254\nthrown away, okay? And so, if we go back again, now that one\n\n1213\n01:06:33,256 --> 01:06:36,591\ngot thrown away. Now there's only two MVCs in the world,\n\n1214\n01:06:36,593 --> 01:06:39,327\nokay, on top of each other. And of course if we go back to\n\n1215\n01:06:39,329 --> 01:06:43,231\nthe beginning, now we get back to here, this MVC we'll call\n\n1216\n01:06:43,233 --> 01:06:45,567\nthe root view controller of the navigation controller.\n\n1217\n01:06:45,569 --> 01:06:48,770\nIt's just one that's at the bottom of the deck. Okay,\n\n1218\n01:06:48,772 --> 01:06:53,008\nit's always in there. Okay, so lets talk about how that\n\n1219\n01:06:53,010 --> 01:06:56,444\nnavigation controller works from our MVC standpoint, okay?\n\n1220\n01:06:56,446 --> 01:07:00,181\nLet's say I have an MVC here. And I just have too much\n\n1221\n01:07:00,183 --> 01:07:03,551\nfunctionality. I just can't fit all the functionality in\n\n1222\n01:07:03,553 --> 01:07:05,687\nmy view, I need to put this somewhere else.\n\n1223\n01:07:05,689 --> 01:07:09,257\nSo I create another MVC, okay? Cuz somebody has to control\n\n1224\n01:07:09,259 --> 01:07:12,394\nthis extra functionality. So there's another controller,\n\n1225\n01:07:12,396 --> 01:07:16,531\nokay? A whole other MVC here, okay? And I want these two,\n\n1226\n01:07:16,533 --> 01:07:19,901\nthey're related, okay? So somehow in this view, I,\n\n1227\n01:07:19,903 --> 01:07:24,005\nI get to this UI because this UI kinda all goes together in\n\n1228\n01:07:24,007 --> 01:07:26,808\nsome way. It's not related in some mechanism, maybe it's\n\n1229\n01:07:26,810 --> 01:07:30,578\nmaster detail kind of effect or something like that.\n\n1230\n01:07:30,580 --> 01:07:32,614\nSo how am I gonna make this work, okay? So\n\n1231\n01:07:32,616 --> 01:07:34,949\nI'm using UINavigationController. And\n\n1232\n01:07:34,951 --> 01:07:36,117\nhere's a UINavigationController.\n\n1233\n01:07:36,119 --> 01:07:40,588\nIt's view, looks like this, okay? It's blank, okay?\n\n1234\n01:07:40,590 --> 01:07:42,223\nIt's got room up here though for a title,\n\n1235\n01:07:42,225 --> 01:07:45,093\nback button, maybe some other buttons over here. But\n\n1236\n01:07:45,095 --> 01:07:48,096\nit never lives like this because there is an outlet\n\n1237\n01:07:48,098 --> 01:07:51,399\ncalled rootViewController, okay? Which is hooked up to\n\n1238\n01:07:51,401 --> 01:07:56,404\nsome MVC. And when it's hooked up, the contents of the view\n\n1239\n01:07:56,406 --> 01:07:59,841\nof the navigation controller are the contents of this MVCs\n\n1240\n01:07:59,843 --> 01:08:03,945\nview. Right, make sense, kinda obvious? Now\n\n1241\n01:08:03,947 --> 01:08:08,016\nthere's probably some button in here that if I touch it,\n\n1242\n01:08:08,018 --> 01:08:12,120\nmeans I wanna show this UI over here, I want this MVC. So\n\n1243\n01:08:12,122 --> 01:08:14,789\nif I touch it, what the navigation controller does,\n\n1244\n01:08:14,791 --> 01:08:16,825\nit moves over here, shows this view.\n\n1245\n01:08:16,827 --> 01:08:19,561\nThis one's still around, okay? It's just not showing but\n\n1246\n01:08:19,563 --> 01:08:23,098\nit's still in the UINavigationController stack,\n\n1247\n01:08:23,100 --> 01:08:25,333\nokay? It shows this guy right here.\n\n1248\n01:08:25,335 --> 01:08:28,069\nNotice we get this automatic back button right there.\n\n1249\n01:08:28,071 --> 01:08:31,806\nIf we press that back button, okay? Then it's going to\n\n1250\n01:08:31,808 --> 01:08:34,742\ngo back here, and look what happened to this MVC.\n\n1251\n01:08:34,744 --> 01:08:39,214\nGone, okay, completely got eliminated. If I press this\n\n1252\n01:08:39,216 --> 01:08:42,851\nbutton again to go back, it would create a new one,\n\n1253\n01:08:42,853 --> 01:08:49,090\nokay? A brand new instance of this MVC, okay? [INAUDIBLE] So\n\n1254\n01:08:49,092 --> 01:08:52,494\nthat's how the Navigation Controller is working from\n\n1255\n01:08:52,496 --> 01:08:56,030\nan MVC standpoint. All right, [COUGH] now in these MVCs,\n\n1256\n01:08:56,032 --> 01:08:59,000\nhow do I get at the other MVCs that are, I'm sharing\n\n1257\n01:08:59,002 --> 01:09:02,604\nthe navigation controller or the split view controller or\n\n1258\n01:09:02,606 --> 01:09:05,306\nthe tab bar controller, how do I get to them,\n\n1259\n01:09:05,308 --> 01:09:07,909\nsend them messages, talk to them in some way?\n\n1260\n01:09:07,911 --> 01:09:10,778\nAnd the answer is through this very important var in UI\n\n1261\n01:09:10,780 --> 01:09:13,915\nviewController, okay? Sorry, in UI tab bar controller,\n\n1262\n01:09:13,917 --> 01:09:17,185\nUI split view controller, and UI navigation controller,\n\n1263\n01:09:17,187 --> 01:09:17,952\nthey all have this var.\n\n1264\n01:09:17,954 --> 01:09:20,088\nAnd it's an array of view controllers,\n\n1265\n01:09:20,090 --> 01:09:22,790\nit's all the view controllers in this thing. All\n\n1266\n01:09:22,792 --> 01:09:25,927\nthe tabs in the tab bar, both this master and the detail and\n\n1267\n01:09:25,929 --> 01:09:30,498\nthe split view, all the things on the navigation stack. And\n\n1268\n01:09:30,500 --> 01:09:33,168\nnavigation controller. It can be an optional,\n\n1269\n01:09:33,170 --> 01:09:35,203\nlike the tab bar case, it can be an optional.\n\n1270\n01:09:35,205 --> 01:09:37,805\nI don't think it's an optional for the other two.\n\n1271\n01:09:37,807 --> 01:09:39,774\nYou're have to look at documentation there for\n\n1272\n01:09:39,776 --> 01:09:43,745\nthat. But in a tab bar this is just the array.\n\n1273\n01:09:43,747 --> 01:09:45,713\nI believe it's from left to right, okay?\n\n1274\n01:09:45,715 --> 01:09:48,316\nSo it's all the MVCs from the left tab to the right, and if\n\n1275\n01:09:48,318 --> 01:09:51,553\nyou have more then it spills into the order in the more\n\n1276\n01:09:51,555 --> 01:09:55,957\ntab. For split view, [0] in this array is the master and\n\n1277\n01:09:55,959 --> 01:09:59,360\n[1] is the detail. And for navigation controller,\n\n1278\n01:09:59,362 --> 01:10:02,230\n[0] is the bottom card and 1, 2, 3, 4, 5, 6,\n\n1279\n01:10:02,232 --> 01:10:05,633\n7 is going up the stack, okay? So the last one that's\n\n1280\n01:10:05,635 --> 01:10:10,605\nvisible would be the last one in this array, okay? Got it?\n\n1281\n01:10:10,607 --> 01:10:13,508\nNotice this is set table, it's get and set but we usually\n\n1282\n01:10:13,510 --> 01:10:16,177\ndon't set our viewControllers this way, okay?\n\n1283\n01:10:16,179 --> 01:10:19,914\nLike split view, we usually wire it up in our storyboard.\n\n1284\n01:10:19,916 --> 01:10:22,817\nIn navigation controller we're usually navigating to those\n\n1285\n01:10:22,819 --> 01:10:27,555\nother MVCs and tab bar we also set up in our storyboard,\n\n1286\n01:10:27,557 --> 01:10:31,893\nokay? So, it is set table but usually we're getting them.\n\n1287\n01:10:31,895 --> 01:10:34,529\nBut, so that's great but if I'm inside\n\n1288\n01:10:34,531 --> 01:10:37,599\na splitViewController, how do I get the splitViewController\n\n1289\n01:10:37,601 --> 01:10:40,034\nI'm in so that I can access this property? And\n\n1290\n01:10:40,036 --> 01:10:43,271\nthe answer is UIViewController has these three very important\n\n1291\n01:10:43,273 --> 01:10:45,540\nproperties, tabBarController, splitViewController and\n\n1292\n01:10:45,542 --> 01:10:48,843\nnavigationController, they're all optionals. They will tell\n\n1293\n01:10:48,845 --> 01:10:52,780\nyou the splitViewController you are in, if you're in one.\n\n1294\n01:10:52,782 --> 01:10:55,650\nIf you're not, it'll be nil, okay? It will also tell\n\n1295\n01:10:55,652 --> 01:10:58,886\nyou this one, what navigation controller you're in if you're\n\n1296\n01:10:58,888 --> 01:11:01,823\nin one? And you could be in both a splitViewController and\n\n1297\n01:11:01,825 --> 01:11:04,559\na navigationController. Imagine a splitVieController\n\n1298\n01:11:04,561 --> 01:11:07,161\nwhere the master is actually the navigationController\n\n1299\n01:11:07,163 --> 01:11:09,764\nthat you can navigate through, okay? So you can have\n\n1300\n01:11:09,766 --> 01:11:13,101\na navigationController inside a splitVewController and\n\n1301\n01:11:13,103 --> 01:11:15,536\nany MVC that's in that navigationController,\n\n1302\n01:11:15,538 --> 01:11:18,806\nthis would be nil, non nil and this would also be non nill,\n\n1303\n01:11:18,808 --> 01:11:22,644\nokay? Cuz it would be in, in both of those things. And\n\n1304\n01:11:22,646 --> 01:11:24,879\nonce you get the splitViewController or\n\n1305\n01:11:24,881 --> 01:11:25,913\nnavigationController in, you can\n\n1306\n01:11:25,915 --> 01:11:28,149\nfind the other MVCs using this thing up here.\n\n1307\n01:11:28,151 --> 01:11:31,019\nSo for example, if I have an MVC and it's the master in\n\n1308\n01:11:31,021 --> 01:11:33,988\na splitViewController, and I want to get the detail. I can\n\n1309\n01:11:33,990 --> 01:11:37,659\njust say, splitViewController? Because it might be nil and\n\n1310\n01:11:37,661 --> 01:11:40,828\nthis a chaining. Remember, everyone hopefully remembers\n\n1311\n01:11:40,830 --> 01:11:44,165\nchaining? I'm gonna get the view controllers, sub one.\n\n1312\n01:11:44,167 --> 01:11:47,368\nRemember, number one is the detail. And that's gonna give\n\n1313\n01:11:47,370 --> 01:11:50,238\nme the detail of the splitViewController I'm in,\n\n1314\n01:11:50,240 --> 01:11:53,808\nif I'm in one, otherwise it'd be nil, this would be nil.\n\n1315\n01:11:53,810 --> 01:11:56,444\nSo this actually says detailVC: UIViewController,\n\n1316\n01:11:56,446 --> 01:11:59,647\nbut this would be detailVC: UIViewController? Okay?\n\n1317\n01:11:59,649 --> 01:12:04,452\nThis would be optional. That's a bug in the slides there.\n\n1318\n01:12:04,454 --> 01:12:08,189\nOkay, so, how do we wire up these MVCs, how do we get this\n\n1319\n01:12:08,191 --> 01:12:14,095\nall set up? Let's take a look at Split View and briefly,\n\n1320\n01:12:14,097 --> 01:12:17,265\nNavigation Controller. And then on, in our next\n\n1321\n01:12:17,267 --> 01:12:20,702\nlecture we'll talk about how we transition between these\n\n1322\n01:12:20,704 --> 01:12:23,738\nvarious MVCs. Okay. especially in Navigation Controller,\n\n1323\n01:12:23,740 --> 01:12:26,274\nhow do we put things, more things on the stack? How do we\n\n1324\n01:12:26,276 --> 01:12:29,744\nmake it go to the next, thing? So, for split view controller,\n\n1325\n01:12:29,746 --> 01:12:32,647\nyou basically drag a split view controller out of your\n\n1326\n01:12:32,649 --> 01:12:36,184\nlittle utilities, object palette in interface mode.\n\n1327\n01:12:36,186 --> 01:12:38,786\nJust drag it out. Now, when you drag out a split view\n\n1328\n01:12:38,788 --> 01:12:41,422\ncontroller, you're gonna get a whole bunch of other MVCs.\n\n1329\n01:12:41,424 --> 01:12:43,658\nIt tries to help you out by giving you Navigation\n\n1330\n01:12:43,660 --> 01:12:45,860\ncontrollers with table views in it,\n\n1331\n01:12:45,862 --> 01:12:47,829\nall that stuff, just delete all that stuff, okay?\n\n1332\n01:12:47,831 --> 01:12:50,465\nYou just want the split view controller. You, it's being\n\n1333\n01:12:50,467 --> 01:12:52,900\na little too helpful for the, you most of the time there,\n\n1334\n01:12:52,902 --> 01:12:55,703\nkkay? So you're gonna drag that out, and then you're just\n\n1335\n01:12:55,705 --> 01:12:58,272\ngonna Ctrl + drag from the split control, view controller\n\n1336\n01:12:58,274 --> 01:13:01,576\nto the master, and the detail, okay? Looks like this.\n\n1337\n01:13:01,578 --> 01:13:02,477\nHere's my split view control and\n\n1338\n01:13:02,479 --> 01:13:04,412\nI dragged it out of the utilities pane.\n\n1339\n01:13:04,414 --> 01:13:07,715\nI'm just Ctrl + dragging to my calculator, for example,\n\n1340\n01:13:07,717 --> 01:13:11,119\nto be my master. When I do, this popover will appear and\n\n1341\n01:13:11,121 --> 01:13:14,222\nthe only two things that make sense to pick are master and\n\n1342\n01:13:14,224 --> 01:13:17,225\ndetail. Okay, these are the only two choices that make any\n\n1343\n01:13:17,227 --> 01:13:18,593\nsense. Those don't make sense here.\n\n1344\n01:13:18,595 --> 01:13:22,330\nSo let's pick the master. It's gonna create a connection,\n\n1345\n01:13:22,332 --> 01:13:25,767\nthe master connection. Ctrl+drag down here. I'm gonna\n\n1346\n01:13:25,769 --> 01:13:29,704\npick Detail. It's gonna make a connection down there. Voila,\n\n1347\n01:13:29,706 --> 01:13:33,174\nI've wired up my split view controller, okay?\n\n1348\n01:13:33,176 --> 01:13:38,246\nAll right, but split view can only do what it does on iPad,\n\n1349\n01:13:38,248 --> 01:13:42,383\nright? There's really, on most iPhones, everything except for\n\n1350\n01:13:42,385 --> 01:13:42,550\nthe iPhone 6 Plus,\n\n1351\n01:13:42,552 --> 01:13:45,853\nthere's really not enough room to have a split view. So\n\n1352\n01:13:45,855 --> 01:13:49,557\nwe want to simultaneously put the MVCs that are our master\n\n1353\n01:13:49,559 --> 01:13:52,326\nin details with split view into Navigation Controllers.\n\n1354\n01:13:52,328 --> 01:13:55,530\nAnd then iOS is smart enough, if it's on iPhone only, okay,\n\n1355\n01:13:55,532 --> 01:13:58,266\niPhone 6 or iPhone 5 or something like that, it knows\n\n1356\n01:13:58,268 --> 01:14:00,868\nnot to use the split view controller, it will only use\n\n1357\n01:14:00,870 --> 01:14:04,205\nthe Navigation Controllers. Okay, so let' take a look and\n\n1358\n01:14:04,207 --> 01:14:05,306\nsee what that looks like. So,\n\n1359\n01:14:05,308 --> 01:14:07,909\nhere I've got that thing I just showed you, right?\n\n1360\n01:14:07,911 --> 01:14:08,810\nThe calculator, the graph,\n\n1361\n01:14:08,812 --> 01:14:10,411\nhere's the split view controller.\n\n1362\n01:14:10,413 --> 01:14:12,180\nI'm just gonna take this guy and\n\n1363\n01:14:12,182 --> 01:14:14,115\nput it inside a Navigation Controller. And\n\n1364\n01:14:14,117 --> 01:14:17,051\nthe way we do that, easiest way is to select it and\n\n1365\n01:14:17,053 --> 01:14:20,054\nthen say embed in Navigation Controller. Same way we did\n\n1366\n01:14:20,056 --> 01:14:22,824\nembed in stack view, but here since we're choosing\n\n1367\n01:14:22,826 --> 01:14:25,860\na whole controller, we can't embed it in a stack view.\n\n1368\n01:14:25,862 --> 01:14:27,895\nSo we're gonna say embed in Navigation Controller. And\n\n1369\n01:14:27,897 --> 01:14:31,265\nit's gonna embed this thing into a Navigation Controller,\n\n1370\n01:14:31,267 --> 01:14:33,301\nwhich is gonna look like this. So split the controller,\n\n1371\n01:14:33,303 --> 01:14:36,571\nthis is still the master. Now this Navigation Controller,\n\n1372\n01:14:36,573 --> 01:14:40,274\nthis MVC, is the master and its root view controller\n\n1373\n01:14:40,276 --> 01:14:43,678\nis the calculator. Okay, and the cool thing about this,\n\n1374\n01:14:43,680 --> 01:14:46,214\nlike I say, if you run this in an iPhone it'll ignore this\n\n1375\n01:14:46,216 --> 01:14:49,217\nand just have your calculator in a Navigation Controller and\n\n1376\n01:14:49,219 --> 01:14:53,254\nwhen you try to show a graph it'll put this as a stack,\n\n1377\n01:14:53,256 --> 01:14:55,490\na card stack, on this Navigation Controller.\n\n1378\n01:14:55,492 --> 01:15:00,161\nIsn't that cool? Okay, so that way it'll work on both\n\n1379\n01:15:00,163 --> 01:15:02,930\nplatforms. Exactly the same storyboard.\n\n1380\n01:15:02,932 --> 01:15:08,469\nAll right, okay, yes, I'm just noticing, I'm mentioning here,\n\n1381\n01:15:08,471 --> 01:15:12,940\nyou can put this one inside a Navigation Controller too.\n\n1382\n01:15:12,942 --> 01:15:13,908\nYou don't really need to,\n\n1383\n01:15:13,910 --> 01:15:16,777\nokay? Only the thing that is the root view controller\n\n1384\n01:15:16,779 --> 01:15:18,045\nreally needs to be inside of it, but\n\n1385\n01:15:18,047 --> 01:15:20,615\nif you put it then you'll get a nice title on the top.\n\n1386\n01:15:20,617 --> 01:15:21,249\nYou see you've got a title there,\n\n1387\n01:15:21,251 --> 01:15:24,418\na calculator, you'll get that nice title here, even in\n\n1388\n01:15:24,420 --> 01:15:27,221\nthe split view case. The only thing to watch out for\n\n1389\n01:15:27,223 --> 01:15:30,958\nis this detail will now be a Navigation Controller,\n\n1390\n01:15:30,960 --> 01:15:32,260\nnot a calculator graph controller.\n\n1391\n01:15:32,262 --> 01:15:36,998\nYou always have to be careful of that case. All right, so\n\n1392\n01:15:37,000 --> 01:15:37,265\nthat's it for today.\n\n1393\n01:15:37,267 --> 01:15:39,800\nOn Wednesday, we'll talk about what are called segues.\n\n1394\n01:15:39,802 --> 01:15:42,703\nThat's how we transfer from one MVC to another,\n\n1395\n01:15:42,705 --> 01:15:44,472\neither in the split view or the Navigation Controller\n\n1396\n01:15:44,474 --> 01:15:48,543\ncase. We'll do a demo which is going to extend face it, okay,\n\n1397\n01:15:48,545 --> 01:15:51,212\nit's going to call, be called emotions as you can imagine,\n\n1398\n01:15:51,214 --> 01:15:53,848\nwe're gonna show some emotions on our faces. Then I'm going\n\n1399\n01:15:53,850 --> 01:15:55,917\nto start talking about the view controller lifecycle,\n\n1400\n01:15:55,919 --> 01:15:58,586\nthat's part of the two methods that I always delete\n\n1401\n01:15:58,588 --> 01:15:59,820\nwhen I start a new thing.\n\n1402\n01:15:59,822 --> 01:16:02,356\nWe'll learn what those are, so you don't have to delete them.\n\n1403\n01:16:02,358 --> 01:16:06,494\nFriday, really good optional section, which is source code\n\n1404\n01:16:06,496 --> 01:16:10,431\nmanagement. Remember I've been not clicking that button.\n\n1405\n01:16:10,433 --> 01:16:11,098\nNow you'll know what that is.\n\n1406\n01:16:11,100 --> 01:16:13,501\nAnd you can click that button from now on, if you want,\n\n1407\n01:16:13,503 --> 01:16:15,036\nafter Friday. And then next week,\n\n1408\n01:16:15,038 --> 01:16:17,338\nwe'll talk about protocols, delegations, scroll view,\n\n1409\n01:16:17,340 --> 01:16:21,509\nall kinds of wonderful stuff. Okay, that's it. I'll be here\n\n1410\n01:16:21,511 --> 01:16:23,744\nif you have any questions. >> For\n\n1411\n01:16:23,746 --> 01:16:23,777\nmore, please visit us at stanford.edu.\n\n\n"
  },
  {
    "path": "subtitles/6. Multiple MVCs, Segues, FaceIt, and View Controller Lifecycle.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,469\n[MUSIC]\n\n2\n00:00:03,471 --> 00:00:08,040\n>> Stanford University. >> Okay, well, this is\n\n3\n00:00:08,042 --> 00:00:13,212\nlecture six of Stanford SC193 P Spring of 2016. And today we\n\n4\n00:00:13,214 --> 00:00:18,283\nare gonna dive in more into this topic of multiple MVCs.\n\n5\n00:00:18,285 --> 00:00:20,652\nIf you remember, last lecture I talked a little about\n\n6\n00:00:20,654 --> 00:00:24,089\nmultiple MVCs and how we can combine them with tab bars,\n\n7\n00:00:24,091 --> 00:00:26,492\nsplit view controllers and navigation controllers. And\n\n8\n00:00:26,494 --> 00:00:28,961\nwe showed a little bit how to wire them up. Well, today, I'm\n\n9\n00:00:28,963 --> 00:00:32,464\ngonna talk a little about how we transition between them,\n\n10\n00:00:32,466 --> 00:00:35,334\nright? It's one thing to wire them up in our storyboard, but\n\n11\n00:00:35,336 --> 00:00:38,237\nas the user navigates our user interface, clicks on buttons\n\n12\n00:00:38,239 --> 00:00:42,408\nand stuff, we want to navigate between these MVCs, okay?\n\n13\n00:00:42,410 --> 00:00:44,676\nAnd then, time permitting at the end, I'm gonna talk\n\n14\n00:00:44,678 --> 00:00:46,979\na little bit more about this view controller lifecycle, the\n\n15\n00:00:46,981 --> 00:00:50,616\nthing that I always delete. Okay? Those two methods.\n\n16\n00:00:50,618 --> 00:00:53,085\nThere's a few more methods in the view controller lifecycle\n\n17\n00:00:53,087 --> 00:00:55,854\nthat I'm gonna talk about, and again, time permitting,\n\n18\n00:00:55,856 --> 00:01:00,192\nI'll do a quick little demo at the end. All right.\n\n19\n00:01:00,194 --> 00:01:03,529\nSo, segues. Okay, we've wired up these controllers of\n\n20\n00:01:03,531 --> 00:01:07,032\ncontrollers like tab bar split fuse navigation controllers,\n\n21\n00:01:07,034 --> 00:01:09,268\nand we've got all of our nice MVCs, and\n\n22\n00:01:09,270 --> 00:01:10,636\nnow we want to transition between them.\n\n23\n00:01:10,638 --> 00:01:12,571\nWe call those transitions segues, right?\n\n24\n00:01:12,573 --> 00:01:15,641\nThe word segue in English means a transition. And\n\n25\n00:01:15,643 --> 00:01:17,876\nthere's really four major kinds of segues.\n\n26\n00:01:17,878 --> 00:01:21,213\nI'm gonna talk about some more rare segues towards the end of\n\n27\n00:01:21,215 --> 00:01:23,982\nthe quarter, but the main segues that you're gonna wire\n\n28\n00:01:23,984 --> 00:01:27,519\nup in a story board, one is called a show segue.\n\n29\n00:01:27,521 --> 00:01:30,889\nSo, remember the navigation controller that's the stack of\n\n30\n00:01:30,891 --> 00:01:34,093\ncards, right? The settings app I showed you where you're\n\n31\n00:01:34,095 --> 00:01:36,862\nputting more stacks on the card. Well, transitioning to\n\n32\n00:01:36,864 --> 00:01:40,632\nput a new card on the stack, okay, is done using a show,\n\n33\n00:01:40,634 --> 00:01:44,336\nwhat we call a show sequeway cuz it shows another MVP or\n\n34\n00:01:44,338 --> 00:01:48,006\nMVC. I'm thinking about Steph Curry, I guess, okay?\n\n35\n00:01:48,008 --> 00:01:53,145\nMVC. And then, show detail is if you have a split view,\n\n36\n00:01:53,147 --> 00:01:55,380\nokay, and something happens in the master and\n\n37\n00:01:55,382 --> 00:01:59,351\nyou want to show an MVC, a different MVC in the detail,\n\n38\n00:01:59,353 --> 00:02:04,423\nokay? Show detail, that's the detail of a split view.\n\n39\n00:02:04,425 --> 00:02:07,259\nShow detail also works in a navigation controller,\n\n40\n00:02:07,261 --> 00:02:09,728\nokay? So, if you do show detail, it's this really\n\n41\n00:02:09,730 --> 00:02:12,564\nthe same as show in a navigation controller, unless\n\n42\n00:02:12,566 --> 00:02:17,503\nthat navigation controller is inside of a split view, okay?\n\n43\n00:02:17,505 --> 00:02:19,004\nShow and show detail would be the same. But\n\n44\n00:02:19,006 --> 00:02:21,440\nif a navigation controller's inside a split view,\n\n45\n00:02:21,442 --> 00:02:24,710\nthen show means show it in the Navigation Controller, and\n\n46\n00:02:24,712 --> 00:02:26,979\nShow Detail means show it in the Split View Controller,\n\n47\n00:02:26,981 --> 00:02:30,382\nright? Show the detail. Then there's Modal and Popover,\n\n48\n00:02:30,384 --> 00:02:33,352\nI'm not gonna talk about those today. Modal is basically\n\n49\n00:02:33,354 --> 00:02:37,289\nsegue into takeover the entire screen with another MVC, okay?\n\n50\n00:02:37,291 --> 00:02:40,392\nAnd a popover is almost exactly the same except for\n\n51\n00:02:40,394 --> 00:02:41,326\ninstead of taking over the entire screen,\n\n52\n00:02:41,328 --> 00:02:44,763\nit still takes over the entire screen in terms of input, but\n\n53\n00:02:44,765 --> 00:02:46,832\nit draws it in a little popover window and\n\n54\n00:02:46,834 --> 00:02:48,300\neverything else is kind of grayed out and\n\n55\n00:02:48,302 --> 00:02:51,703\nyou can click on the grayed out to dismiss the popover.\n\n56\n00:02:51,705 --> 00:02:54,940\nOkay? So those are the major kinds of segue that you wire\n\n57\n00:02:54,942 --> 00:02:55,607\nup in your story boards.\n\n58\n00:02:55,609 --> 00:02:57,943\nSo, we're gonna talk about navigation controllers,\n\n59\n00:02:57,945 --> 00:02:59,444\nsplit view controllers, tab bar today.\n\n60\n00:02:59,446 --> 00:03:01,446\nSo, for navigation and split view controllers,\n\n61\n00:03:01,448 --> 00:03:02,781\nwe're talking about show and show detail, okay?\n\n62\n00:03:02,783 --> 00:03:06,785\nSo, we're gonna talk about today. All right. It's very\n\n63\n00:03:06,787 --> 00:03:09,555\nimportant to understand that segue virtually\n\n64\n00:03:09,557 --> 00:03:13,892\nalways create a new MVC. Okay? If you segue to an MVC,\n\n65\n00:03:13,894 --> 00:03:17,596\nit's going to create it. You rarely, extremely rare,\n\n66\n00:03:17,598 --> 00:03:21,066\nthere's only one kind of segue where you're gonna segue to\n\n67\n00:03:21,068 --> 00:03:24,736\nan MVC that already exists. Okay? So, segues create new\n\n68\n00:03:24,738 --> 00:03:27,906\nMVCs, okay? Super important to understand. That's even true\n\n69\n00:03:27,908 --> 00:03:31,410\nin a split view. If you do a show detailed segue,\n\n70\n00:03:31,412 --> 00:03:34,980\nit replaces the MVC that's in the detail side.\n\n71\n00:03:34,982 --> 00:03:37,816\nThat's why we sometimes call a show detail a replace segue,\n\n72\n00:03:37,818 --> 00:03:42,254\nokay? That's kind of its old name. All right? So, how do we\n\n73\n00:03:42,256 --> 00:03:45,357\nmake these segues happen, okay? Just like we always do,\n\n74\n00:03:45,359 --> 00:03:46,959\nwe control drag, okay? Just like we\n\n75\n00:03:46,961 --> 00:03:50,395\ncontrol drag to wire up our MVCs to our split view\n\n76\n00:03:50,397 --> 00:03:52,931\ncontrol, navigation control, we're also gonna control drag\n\n77\n00:03:52,933 --> 00:03:55,701\nto determine how they segue up to each other, okay? How they\n\n78\n00:03:55,703 --> 00:03:59,204\ntransition. It's also possible to make segues happen in code.\n\n79\n00:03:59,206 --> 00:04:01,974\nThere's a method you call that says do this segue,\n\n80\n00:04:01,976 --> 00:04:05,177\nperform segue, it's called, okay? So\n\n81\n00:04:05,179 --> 00:04:08,480\nhere is something wired up as of our last lecture, here.\n\n82\n00:04:08,482 --> 00:04:09,748\nI've got a split view controller,\n\n83\n00:04:09,750 --> 00:04:14,653\nand the detail is this little graphing thing at the bottom.\n\n84\n00:04:14,655 --> 00:04:17,189\nAnd the master is a navigation controller with\n\n85\n00:04:17,191 --> 00:04:19,958\nyour little calculator view controller right there, okay?\n\n86\n00:04:19,960 --> 00:04:22,060\nThat calculator view controller up there,\n\n87\n00:04:22,062 --> 00:04:25,163\nlooking at this side today, that calculator up there might\n\n88\n00:04:25,165 --> 00:04:27,966\nbe exactly the same MVC as the one you're building in your\n\n89\n00:04:27,968 --> 00:04:32,437\nhomework, okay? All right? So, if we want to add a button to\n\n90\n00:04:32,439 --> 00:04:35,707\nthe calculator that caused this graph to show,\n\n91\n00:04:35,709 --> 00:04:38,377\nmaybe graph what's in your calculator. Wouldn't that be\n\n92\n00:04:38,379 --> 00:04:42,881\ncool? Then we would Ctrl-drag from that little button.\n\n93\n00:04:42,883 --> 00:04:45,484\nCan hardly see that button, but it's there. Ctrl-drag to\n\n94\n00:04:45,486 --> 00:04:48,987\nthe MVC we wanna segue to. Okay? So, that's how it works.\n\n95\n00:04:48,989 --> 00:04:52,524\nYou would just Ctrl-drag to. Now, when you Ctrl-drag to,\n\n96\n00:04:52,526 --> 00:04:55,394\nit's gonna put up a little black window here,\n\n97\n00:04:55,396 --> 00:04:58,897\nwhich I'll zoom in on, which is going to ask you what kind\n\n98\n00:04:58,899 --> 00:05:02,000\nof segue do you want. Do you want a show? A show detail?\n\n99\n00:05:02,002 --> 00:05:05,203\nA modal? Or a popover? Okay? So if you want this to appear\n\n100\n00:05:05,205 --> 00:05:08,707\nas the detail in a split view, you're gonna pick Show Detail.\n\n101\n00:05:08,709 --> 00:05:10,409\nOtherwise, it's just in a navigation controller,\n\n102\n00:05:10,411 --> 00:05:14,012\nyou're gonna pick Show, okay? Again, we'll talk about\n\n103\n00:05:14,014 --> 00:05:16,348\nthe other two later in the quarter. All right?\n\n104\n00:05:16,350 --> 00:05:19,151\nSo, you've got that wired up. As soon as you do that,\n\n105\n00:05:19,153 --> 00:05:20,852\nyou've get this little guy appearing here,\n\n106\n00:05:20,854 --> 00:05:23,522\nthis line with a little thing in the middle here.\n\n107\n00:05:23,524 --> 00:05:25,991\nThis is the segue. Okay? And this segue,\n\n108\n00:05:25,993 --> 00:05:29,261\njust like a button or anything else, is inspectable. So\n\n109\n00:05:29,263 --> 00:05:32,264\nif you go over here to the inspector and inspect it,\n\n110\n00:05:32,266 --> 00:05:34,666\nit's going to let you set some things about the segue.\n\n111\n00:05:34,668 --> 00:05:38,537\nThe most important thing is its identifier, okay?\n\n112\n00:05:38,539 --> 00:05:41,340\nEvery segue needs an identifier, because in your\n\n113\n00:05:41,342 --> 00:05:43,975\ncode, you're gonna have to refer to that segue,\n\n114\n00:05:43,977 --> 00:05:46,411\nand you do it by name. By this identifier.\n\n115\n00:05:46,413 --> 00:05:48,947\nThat's how you're gonna refer to this in your code.\n\n116\n00:05:48,949 --> 00:05:53,118\nSo it's critical that you give your segues names, okay?\n\n117\n00:05:53,120 --> 00:05:54,353\nThis identifier thing. And\n\n118\n00:05:54,355 --> 00:05:59,157\nwe'll see that in the demo. And the name of\n\n119\n00:05:59,159 --> 00:06:03,595\nthe identifier should probably describe what the segue does.\n\n120\n00:06:03,597 --> 00:06:07,366\nIt's usually a verb, like a verb phrase like show graph,\n\n121\n00:06:07,368 --> 00:06:09,835\ndo something. Cuz that's what segues do, they do something.\n\n122\n00:06:09,837 --> 00:06:15,240\nSo it's usually some kind of verb phrase. Okay. So, what,\n\n123\n00:06:15,242 --> 00:06:20,879\nso, where in our code are we gonna use that identifier for\n\n124\n00:06:20,881 --> 00:06:21,046\nthe segue?\n\n125\n00:06:21,048 --> 00:06:23,882\nIt's really two places. One place that we don't use too\n\n126\n00:06:23,884 --> 00:06:27,185\nmuch is when we want to make that segue happen from code.\n\n127\n00:06:27,187 --> 00:06:30,655\nAnd we can do that with this method in UI view controller,\n\n128\n00:06:30,657 --> 00:06:31,356\nokay? You have your controller.\n\n129\n00:06:31,358 --> 00:06:34,126\nYou all know what that is, okay? It's called perform\n\n130\n00:06:34,128 --> 00:06:37,095\nsegue with identifier. You give it the identifier, and\n\n131\n00:06:37,097 --> 00:06:40,565\nthen you can pass any object you want as the sender, okay?\n\n132\n00:06:40,567 --> 00:06:43,969\nThe sender is the object that is causing the segue to\n\n133\n00:06:43,971 --> 00:06:47,506\nhappen. Often that's a button, okay? But when you're doing it\n\n134\n00:06:47,508 --> 00:06:50,509\nfrom code, you can send any object really that you want.\n\n135\n00:06:50,511 --> 00:06:53,645\nOkay? And you'll see why we need that in a moment. Okay?\n\n136\n00:06:53,647 --> 00:06:55,514\nSo that's one reason you need the identifier.\n\n137\n00:06:55,516 --> 00:06:58,850\nBut a much more important reason is because when a segue\n\n138\n00:06:58,852 --> 00:07:01,620\nhappens, the MVC your segueing to,\n\n139\n00:07:01,622 --> 00:07:05,390\nusually needs to be prepared to come on screen. Okay?\n\n140\n00:07:05,392 --> 00:07:06,391\nIt needs some information.\n\n141\n00:07:06,393 --> 00:07:09,628\nMaybe it needs it's model to be set. That's a common thing.\n\n142\n00:07:09,630 --> 00:07:13,398\nMaybe it needs some of it's drawing attributes to be set,\n\n143\n00:07:13,400 --> 00:07:18,804\nokay? So that is happening in this preparation.\n\n144\n00:07:18,806 --> 00:07:19,771\nSo, this is so important.\n\n145\n00:07:19,773 --> 00:07:22,808\nI'm gonna talk about the preparation in detail. Now,\n\n146\n00:07:22,810 --> 00:07:26,278\nthe preparation happens with a method that is sent to\n\n147\n00:07:26,280 --> 00:07:30,916\nthe view controller that is causing this segue to happen.\n\n148\n00:07:30,918 --> 00:07:31,750\nNot the view controller on\n\n149\n00:07:31,752 --> 00:07:33,385\nthe other end that's being created, but\n\n150\n00:07:33,387 --> 00:07:35,120\nthe one that is causing it to happen, okay?\n\n151\n00:07:35,122 --> 00:07:38,190\nThat view controller is gonna be sent this message,\n\n152\n00:07:38,192 --> 00:07:41,993\nprepare for segue. Okay? And it's job in this method is\n\n153\n00:07:41,995 --> 00:07:45,564\nto prepare the MVC that's being created by the segue to\n\n154\n00:07:45,566 --> 00:07:49,000\ndo what it wants to do. Now, it's really important to\n\n155\n00:07:49,002 --> 00:07:52,637\nunderstand with this multi-MVC world, that it's object\n\n156\n00:07:52,639 --> 00:07:55,841\noriented in that each MVC kind of has it's own world.\n\n157\n00:07:55,843 --> 00:07:59,444\nOkay, they don't really wanna be talking back to each other.\n\n158\n00:07:59,446 --> 00:08:02,647\nAnd the MVC on the ender end of a segue is really part\n\n159\n00:08:02,649 --> 00:08:06,218\nof the view of the MVC that's causing the segue. Remember\n\n160\n00:08:06,220 --> 00:08:09,554\nthose graphics that I told you? So we really can't talk\n\n161\n00:08:09,556 --> 00:08:12,357\nback to the one causing the segue. We would have to use\n\n162\n00:08:12,359 --> 00:08:14,926\nsome kind of blind structured communication because the view\n\n163\n00:08:14,928 --> 00:08:17,829\nis not really allowed to talk to its controller, except for\n\n164\n00:08:17,831 --> 00:08:19,231\nin these structured ways, right?\n\n165\n00:08:19,233 --> 00:08:20,398\nThe controller can talk to the view,\n\n166\n00:08:20,400 --> 00:08:23,134\nno problem. And he's going to here. This is going to be\n\n167\n00:08:23,136 --> 00:08:26,204\nthe controller talking to its view by preparing\n\n168\n00:08:26,206 --> 00:08:26,471\nthat MVC. But\n\n169\n00:08:26,473 --> 00:08:29,641\nyou really wanna think of MVCs as living in their own world,\n\n170\n00:08:29,643 --> 00:08:32,210\nself-contained, they have some public API,\n\n171\n00:08:32,212 --> 00:08:35,714\nyou set things in their public API, and they do what they do,\n\n172\n00:08:35,716 --> 00:08:38,984\nokay? It's very tempting when you're writing code,\n\n173\n00:08:38,986 --> 00:08:41,052\nespecially maybe a lot of the code that you've written so\n\n174\n00:08:41,054 --> 00:08:43,555\nfar in classes, to think, well, I can just put a method\n\n175\n00:08:43,557 --> 00:08:45,924\nhere and a method there, and they can all call each other,\n\n176\n00:08:45,926 --> 00:08:48,426\nand it's all fine. But it's not, you need to start\n\n177\n00:08:48,428 --> 00:08:51,630\nthinking in terms of programming interfaces, okay,\n\n178\n00:08:51,632 --> 00:08:55,200\nencapsulation, true object oriented programming here.\n\n179\n00:08:55,202 --> 00:08:58,403\nOkay, I made you think about that a little bit in your\n\n180\n00:08:58,405 --> 00:08:58,436\ncalculator brain and the calculator view controller,\n\n181\n00:08:58,438 --> 00:09:01,640\nassignment with\n\n182\n00:09:01,642 --> 00:09:03,642\nright? The calculator brain has a public API,\n\n183\n00:09:03,644 --> 00:09:05,677\nit's very clear what the public methods are,\n\n184\n00:09:05,679 --> 00:09:08,847\nthose are the only methods a controller can use, okay?\n\n185\n00:09:08,849 --> 00:09:09,915\nHopefully you didn't write your assignment,\n\n186\n00:09:09,917 --> 00:09:12,584\nwhere they're each calling, private messaging each other,\n\n187\n00:09:12,586 --> 00:09:15,987\nor things like that, okay? There's gotta be well-defined,\n\n188\n00:09:15,989 --> 00:09:17,956\nwhat those objects encapsulate, okay.\n\n189\n00:09:17,958 --> 00:09:19,491\nThat's object oriented programming. So\n\n190\n00:09:19,493 --> 00:09:23,028\nsame thing here, but at the whole MVC level, right?\n\n191\n00:09:23,030 --> 00:09:26,331\nWe want the MVCs to be well-defined in what they do.\n\n192\n00:09:26,333 --> 00:09:30,101\nAll right, so let's talk about prepareForSegue here and,\n\n193\n00:09:30,103 --> 00:09:30,235\nhow you make it work, what all the parts of it are, okay? So\n\n194\n00:09:30,237 --> 00:09:33,572\nwhat it does,\n\n195\n00:09:33,574 --> 00:09:35,140\nfirst of all, you have the arguments here for\n\n196\n00:09:35,142 --> 00:09:38,443\nprepareForSegue. The first argument is the segue. So\n\n197\n00:09:38,445 --> 00:09:42,113\nthis is a instance of a class called UIStoryboardSegue.\n\n198\n00:09:42,115 --> 00:09:45,717\nAnd it contains interesting information about the segue,\n\n199\n00:09:45,719 --> 00:09:47,152\nmost notably the identifier.\n\n200\n00:09:47,154 --> 00:09:51,356\nOkay, that identifier we typed in the inspector, and also,\n\n201\n00:09:51,358 --> 00:09:54,993\nthe controller of the MVC that you're segueing to.\n\n202\n00:09:54,995 --> 00:09:59,164\nIt just created it, and you can, cuz remember,\n\n203\n00:09:59,166 --> 00:10:01,866\nsegue is always created an MVC, so it just created\n\n204\n00:10:01,868 --> 00:10:03,835\nthat thing, and you can get a pointer to it\n\n205\n00:10:03,837 --> 00:10:07,072\nfrom this segue argument right here, one of the properties on\n\n206\n00:10:07,074 --> 00:10:10,775\nUIStoryboardSegue is the destination view controller.\n\n207\n00:10:10,777 --> 00:10:12,911\nOkay, this other argument here, sender,\n\n208\n00:10:12,913 --> 00:10:16,915\nit's the same sender as was in perform segue with identifier.\n\n209\n00:10:16,917 --> 00:10:20,452\nThis is just who caused this segue to happen. Usually,\n\n210\n00:10:20,454 --> 00:10:23,622\nit's a button, okay. But it could be any object if you,\n\n211\n00:10:23,624 --> 00:10:26,658\nif it started in code with perform segue with identifier,\n\n212\n00:10:26,660 --> 00:10:30,295\nokay? So we'll, we'll see this in the demo sometimes why you\n\n213\n00:10:30,297 --> 00:10:35,300\nwould wanna know who this is, okay? All right, so\n\n214\n00:10:35,302 --> 00:10:36,234\nhere's the identifier,\n\n215\n00:10:36,236 --> 00:10:39,904\nI'm getting it with the, var here called identifier,\n\n216\n00:10:39,906 --> 00:10:42,807\nright, the property off of the segue thing.\n\n217\n00:10:42,809 --> 00:10:45,710\nI'm checking here to make sure it's not nil. Because someone\n\n218\n00:10:45,712 --> 00:10:47,679\nmight have created a segue in the storyboard, and\n\n219\n00:10:47,681 --> 00:10:49,314\nthey forgot to set the identifier or\n\n220\n00:10:49,316 --> 00:10:51,282\nthey didn't set the identifier. So\n\n221\n00:10:51,284 --> 00:10:51,416\nit could be nil, so\n\n222\n00:10:51,418 --> 00:10:54,119\nI'm checking to make sure it's not nil here. And then\n\n223\n00:10:54,121 --> 00:10:57,088\nI'm switching on it, okay? So I'm gonna switch on it.\n\n224\n00:10:57,090 --> 00:10:59,624\nAnd in this case, I'm gonna look for Show Graph,\n\n225\n00:10:59,626 --> 00:11:02,627\nwhich is in my previous slide, that's what I called,\n\n226\n00:11:02,629 --> 00:11:05,363\nthat's what the identifier for that thing was.\n\n227\n00:11:05,365 --> 00:11:09,200\nAnd when I see that this is a Show Graph segue, then\n\n228\n00:11:09,202 --> 00:11:13,705\nI'm going to try and prepare the destination of the segue,\n\n229\n00:11:13,707 --> 00:11:17,609\nassuming that it is some sort of graph controller, right,\n\n230\n00:11:17,611 --> 00:11:18,176\nsome code controller,\n\n231\n00:11:18,178 --> 00:11:20,245\ncontroller of an MVC that shows the graph. So\n\n232\n00:11:20,247 --> 00:11:22,080\nI'm gonna have to prepare it, I'm gonna have to prepare it,\n\n233\n00:11:22,082 --> 00:11:25,216\nokay. So the first thing that I'm gonna do is I'm gonna look\n\n234\n00:11:25,218 --> 00:11:28,420\nat the destination view controller of the segue, where\n\n235\n00:11:28,422 --> 00:11:32,457\nwe're segueing to, okay. And I'm gonna see if it's a graph\n\n236\n00:11:32,459 --> 00:11:34,693\ncontroller. And it better be, because that's the only\n\n237\n00:11:34,695 --> 00:11:38,730\nway I know how to prepare for a segue called Show Graph. So\n\n238\n00:11:38,732 --> 00:11:42,367\nthis thing better be, but I am doing if let with as to,\n\n239\n00:11:42,369 --> 00:11:46,604\nto see if it is, because destination view controller,\n\n240\n00:11:46,606 --> 00:11:50,041\nits type is just UIViewController, okay. So\n\n241\n00:11:50,043 --> 00:11:53,311\nI need to cast it with as just like I cast any\n\n242\n00:11:53,313 --> 00:11:54,546\nobject sometimes with as.\n\n243\n00:11:54,548 --> 00:11:56,915\nHere I'm gonna cast this view controller, if I can,\n\n244\n00:11:56,917 --> 00:11:59,751\nto be a specific kind of controller that I'm expecting\n\n245\n00:11:59,753 --> 00:12:02,754\nthis segue to be segueing to. Okay, so in this case,\n\n246\n00:12:02,756 --> 00:12:05,824\nsome sort of graph controller of some sort. All right,\n\n247\n00:12:05,826 --> 00:12:09,961\nnow once I've done that, now VC right here is gonna be\n\n248\n00:12:09,963 --> 00:12:13,498\nof type graph controller. Okay, that's what if let\n\n249\n00:12:13,500 --> 00:12:16,434\nthis as that does, right, inside this curly brace,\n\n250\n00:12:16,436 --> 00:12:20,038\nvc is gonna be of type graph controller. And so I can start\n\n251\n00:12:20,040 --> 00:12:24,743\nsending messages and setting properties, public ones only,\n\n252\n00:12:24,745 --> 00:12:29,814\nof this controller in order to prepare it to do its job. So\n\n253\n00:12:29,816 --> 00:12:32,117\nif it's a graph controller, I don't know,\n\n254\n00:12:32,119 --> 00:12:34,919\nit might wanna know the axes, the range of the axes.\n\n255\n00:12:34,921 --> 00:12:38,289\nSomehow it might wanna know what function it's graphing,\n\n256\n00:12:38,291 --> 00:12:40,992\nI don't know. Okay, but that is happening in here,\n\n257\n00:12:40,994 --> 00:12:43,728\nwhere I'm preparing this graph controller that just got\n\n258\n00:12:43,730 --> 00:12:48,433\ncreated cuz of a segue to do what it does. Okay, questions\n\n259\n00:12:48,435 --> 00:12:53,238\nabout that? All right, so it's really important\n\n260\n00:12:53,240 --> 00:12:55,840\nto understand, and that's why it's in red here, I don't put\n\n261\n00:12:55,842 --> 00:12:59,077\nthings in red very often. But it's in red that when you're\n\n262\n00:12:59,079 --> 00:13:02,046\ndoing this prepare of that destination view controller,\n\n263\n00:13:02,048 --> 00:13:07,218\nit was only just created just now, okay, femtoseconds ago,\n\n264\n00:13:07,220 --> 00:13:12,090\nokay. So its outlets have not been set, okay. This happens\n\n265\n00:13:12,092 --> 00:13:15,393\nbefore its outlets are set. This is quite annoying, okay,\n\n266\n00:13:15,395 --> 00:13:17,896\nbecause usually when you wanna prepare a view controller,\n\n267\n00:13:17,898 --> 00:13:20,899\nyou wanna set things up in its outlets, like a calculator\n\n268\n00:13:20,901 --> 00:13:22,767\none, you'd want to set something in the display or\n\n269\n00:13:22,769 --> 00:13:25,403\nsomething like that. But you can't do that, okay,\n\n270\n00:13:25,405 --> 00:13:26,171\nunfortunately, you can't do that.\n\n271\n00:13:26,173 --> 00:13:28,306\nThis is happening before your outlets are set, so\n\n272\n00:13:28,308 --> 00:13:31,009\nyou have to just give it the data it wants, and you're just\n\n273\n00:13:31,011 --> 00:13:33,545\ngonna have to hold on to that data. And then after its\n\n274\n00:13:33,547 --> 00:13:37,015\noutlets are set, it can start parceling that out to its UI,\n\n275\n00:13:37,017 --> 00:13:41,052\nokay? You will, at least once this quarter, get a crash,\n\n276\n00:13:41,054 --> 00:13:44,522\nbecause you'll start preparing some view controller.\n\n277\n00:13:44,524 --> 00:13:47,792\nYou'll start accessing its outlets, it goes out with your\n\n278\n00:13:47,794 --> 00:13:50,361\nstill nil, and you're gonna get optional nil was\n\n279\n00:13:50,363 --> 00:13:53,097\naccessed, okay. I'm gonna do it in my demo just to show\n\n280\n00:13:53,099 --> 00:13:55,300\nyou it happening because it can happen so much.\n\n281\n00:13:55,302 --> 00:13:58,770\nAll right, okay, so that's preparing,\n\n282\n00:13:58,772 --> 00:14:03,041\nsuper important part of segues, okay, so preparing.\n\n283\n00:14:03,043 --> 00:14:06,110\nNow there's a method you can also implement in your view\n\n284\n00:14:06,112 --> 00:14:09,113\ncontroller in addition to prepareForSegue called,\n\n285\n00:14:09,115 --> 00:14:11,416\nshouldPerformSegueWithIdentif- ier, okay.\n\n286\n00:14:11,418 --> 00:14:14,219\nAnd that is basically gonna return a bool, whether or\n\n287\n00:14:14,221 --> 00:14:18,423\nnot that segue should happen. So you can prevent it, for\n\n288\n00:14:18,425 --> 00:14:19,891\nexample, let's say in your calculator,\n\n289\n00:14:19,893 --> 00:14:22,527\nlet's say you had a button that did a graph, and\n\n290\n00:14:22,529 --> 00:14:24,229\nlet's say it was a partial result, so\n\n291\n00:14:24,231 --> 00:14:27,999\nyou couldn't really graph it. This might return false, okay?\n\n292\n00:14:28,001 --> 00:14:31,703\nAnd maybe you'll see that on your homework. All right, so\n\n293\n00:14:31,705 --> 00:14:33,905\nthe demo I'm gonna do is I'm gonna take FaceIt,\n\n294\n00:14:33,907 --> 00:14:36,407\nthat we have so far that draws that face, I'm gonna add\n\n295\n00:14:36,409 --> 00:14:39,510\na second MVC, okay. And this MVC's gonna have some emotions\n\n296\n00:14:39,512 --> 00:14:41,279\nlistened in it, and when you click on them,\n\n297\n00:14:41,281 --> 00:14:44,415\nit's gonna show a face that reflects that emotion, okay?\n\n298\n00:14:44,417 --> 00:14:45,350\nSo I'm gonna have two MVCs, and\n\n299\n00:14:45,352 --> 00:14:53,358\nwe're gonna hook them up. Okay,\n\n300\n00:14:53,360 --> 00:14:57,161\nso here we are back in FaceIt, exactly where we were.\n\n301\n00:14:57,163 --> 00:15:00,531\nI haven't, added anything or changed anything, right?\n\n302\n00:15:00,533 --> 00:15:02,700\nSo we've got our face view controller right here,\n\n303\n00:15:02,702 --> 00:15:05,703\nit's got its model, which is a facial expression. And\n\n304\n00:15:05,705 --> 00:15:08,506\nthen it's got its view, which is this face view thing right\n\n305\n00:15:08,508 --> 00:15:12,977\nhere. We add some gestures, we update our UI when this thing\n\n306\n00:15:12,979 --> 00:15:16,447\nis first set, our update UI just takes the model,\n\n307\n00:15:16,449 --> 00:15:19,651\nall these things out of the model, okay? And\n\n308\n00:15:19,653 --> 00:15:21,653\nit turns them into things in the view,\n\n309\n00:15:21,655 --> 00:15:23,922\nand and these are just the handlers for\n\n310\n00:15:23,924 --> 00:15:25,256\nthese gestures. And that's it, so\n\n311\n00:15:25,258 --> 00:15:28,760\nthat's all we have in our controller. And our story\n\n312\n00:15:28,762 --> 00:15:31,796\nboard is really, really simple, it only has this one\n\n313\n00:15:31,798 --> 00:15:35,433\nview controller, okay, this face view controller. And\n\n314\n00:15:35,435 --> 00:15:38,503\nwhat I'm gonna do right off the bat is add another MVC.\n\n315\n00:15:38,505 --> 00:15:41,572\nSo how do you add another MVC to your storyboard?\n\n316\n00:15:41,574 --> 00:15:45,043\nWell, you go over here to your object palette, and just like\n\n317\n00:15:45,045 --> 00:15:48,579\nfrom your object palette, you can do things like, adding\n\n318\n00:15:48,581 --> 00:15:51,816\nbuttons and labels, you can also add entirely new MVCs.\n\n319\n00:15:51,818 --> 00:15:54,485\nAnd the way you do that is by grabbing this thing called\n\n320\n00:15:54,487 --> 00:15:57,889\nview controller at the top. In dragging it out into your\n\n321\n00:15:57,891 --> 00:16:00,224\nstoryboard, okay. You can put it right there.\n\n322\n00:16:00,226 --> 00:16:03,628\nYou can move things around wherever you want. Okay, so\n\n323\n00:16:03,630 --> 00:16:07,098\nnow I have two MVCs in here. One really interesting thing\n\n324\n00:16:07,100 --> 00:16:12,704\nto note is that an NVC always need to have a custom class.\n\n325\n00:16:12,706 --> 00:16:14,472\nOkay, if it doesn't have a custom class,\n\n326\n00:16:14,474 --> 00:16:16,874\nwhere are you going to put your outlets and actions and\n\n327\n00:16:16,876 --> 00:16:20,311\nall that stuff. So just like this view controller,\n\n328\n00:16:20,313 --> 00:16:22,981\nif you look at it's identity inspector, remember we changed\n\n329\n00:16:22,983 --> 00:16:25,650\nit's identity and the identity inspector to be face\n\n330\n00:16:25,652 --> 00:16:27,719\nview controller, okay. So that makes it so\n\n331\n00:16:27,721 --> 00:16:30,655\nthat this class is the controller for that thing, so\n\n332\n00:16:30,657 --> 00:16:34,859\nit has a model and outlets and things like that. Okay we need\n\n333\n00:16:34,861 --> 00:16:37,128\nto do the exact same thing with this view controller.\n\n334\n00:16:37,130 --> 00:16:40,164\nIt needs to have a custom class. So the way you create\n\n335\n00:16:40,166 --> 00:16:43,034\nclasses, you'll remember just like we did when we created\n\n336\n00:16:43,036 --> 00:16:46,938\nFace view for example. Is we do new file here. Okay so\n\n337\n00:16:46,940 --> 00:16:50,174\nI'm do new file. It's going to be iOS source, It's going to\n\n338\n00:16:50,176 --> 00:16:52,543\nbe Coco Touch class because it's going to be a sub class\n\n339\n00:16:52,545 --> 00:16:56,047\nof UI view controller. Just like Face View controller was.\n\n340\n00:16:56,049 --> 00:16:58,983\nSo I'm gonna double click here. Here, subclass of,\n\n341\n00:16:58,985 --> 00:17:02,453\nthis is good, okay. Remember we did UI View before,\n\n342\n00:17:02,455 --> 00:17:05,523\nnow we want UI View controller as our class. We don't want\n\n343\n00:17:05,525 --> 00:17:07,859\nto call it view controller, that's a very generic name, so\n\n344\n00:17:07,861 --> 00:17:10,862\nI'm gonna call it Emotions View Controller because that's\n\n345\n00:17:10,864 --> 00:17:12,563\nwhat it shows. This view controller shows emotions,\n\n346\n00:17:12,565 --> 00:17:16,134\nokay. Put it in the same place we always put it,\n\n347\n00:17:16,136 --> 00:17:18,536\nright here, same same as all our other code.\n\n348\n00:17:18,538 --> 00:17:22,373\nAnd here we go. Here's our emotions view controller,\n\n349\n00:17:22,375 --> 00:17:24,509\nagain I'm going to remove these few controller\n\n350\n00:17:24,511 --> 00:17:28,513\nlife cycle methods for now. But\n\n351\n00:17:28,515 --> 00:17:30,114\nnotice also when I created this,\n\n352\n00:17:30,116 --> 00:17:34,819\nI got this little method. What is this method? Prepare for\n\n353\n00:17:34,821 --> 00:17:38,256\nsegue. Okay, segues are so important to have in multiple\n\n354\n00:17:38,258 --> 00:17:40,825\nview controllers. That when it gives you a blank one, it\n\n355\n00:17:40,827 --> 00:17:43,161\nalways gives you prepare for segue commented out, but it\n\n356\n00:17:43,163 --> 00:17:45,530\nknows you're almost certainly gonna want to prepare for\n\n357\n00:17:45,532 --> 00:17:47,865\nsegue. Okay, that's how important this is. And indeed\n\n358\n00:17:47,867 --> 00:17:51,436\nwe are gonna have to implement this if we want clicking on\n\n359\n00:17:51,438 --> 00:17:54,172\nemotions to go to our other MVC and do things, okay?\n\n360\n00:17:54,174 --> 00:17:57,008\nBut we're not going to do this right now. The next\n\n361\n00:17:57,010 --> 00:17:59,677\nthing we're going to do, and you'll forget this step, okay?\n\n362\n00:17:59,679 --> 00:18:02,213\nYou will for sure forget this step multiple times.\n\n363\n00:18:02,215 --> 00:18:05,983\nWhich is we have to remember to go here and set in\n\n364\n00:18:05,985 --> 00:18:11,155\nthe identity inspector, the class of this thing to be that\n\n365\n00:18:11,157 --> 00:18:13,958\nemotion's view controller. A lot of times you will create\n\n366\n00:18:13,960 --> 00:18:15,560\nthat emotion view control, you just dive right in,\n\n367\n00:18:15,562 --> 00:18:17,929\nyou start programming, and you forget to do this, and then\n\n368\n00:18:17,931 --> 00:18:19,931\nyou cannot connect any of your outlets, and you are like,\n\n369\n00:18:19,933 --> 00:18:22,300\nwhat is wrong with this thing? Okay, well this is why.\n\n370\n00:18:22,302 --> 00:18:23,835\nYou forgot to type your identity, here,\n\n371\n00:18:23,837 --> 00:18:26,537\nokay? So, now I have two, you see? This one says emotions\n\n372\n00:18:26,539 --> 00:18:29,040\nview controller and this says face view controller, so\n\n373\n00:18:29,042 --> 00:18:32,510\ntwo NVCs. Notice this little arrow right here.\n\n374\n00:18:32,512 --> 00:18:37,014\nYou see this arrow? This arrow tells the app when it runs,\n\n375\n00:18:37,016 --> 00:18:39,884\nstart with this view controller. So\n\n376\n00:18:39,886 --> 00:18:42,854\nif I were to run right now it would show the face, but\n\n377\n00:18:42,856 --> 00:18:45,556\nif I wanted to show my new view controller first I can\n\n378\n00:18:45,558 --> 00:18:49,560\njust pick this arrow up and drop it on this one.\n\n379\n00:18:49,562 --> 00:18:52,630\nOkay, so let's go ahead and run actually to verify that.\n\n380\n00:18:52,632 --> 00:18:58,536\nWe should get a nice blank screen. Okay?\n\n381\n00:18:58,538 --> 00:19:02,540\nHere it is. Nice blank screen, working perfectly. Now,\n\n382\n00:19:02,542 --> 00:19:05,977\none thing to notice, also is, it, I got a warning here.\n\n383\n00:19:05,979 --> 00:19:09,113\nLook, see this warning? Scene is unreachable due to lack of\n\n384\n00:19:09,115 --> 00:19:10,715\nentry points. It's talking about this scene,\n\n385\n00:19:10,717 --> 00:19:14,385\nokay? By the way, we call these MVCs in the storyboard.\n\n386\n00:19:14,387 --> 00:19:18,055\nThis is called a scene. Okay? A scene. So this scene\n\n387\n00:19:18,057 --> 00:19:21,025\nis unreachable, because this arrow doesn't point to it.\n\n388\n00:19:21,027 --> 00:19:25,396\nAnd nothing in here segues to it. So you can't get to it,\n\n389\n00:19:25,398 --> 00:19:27,431\nokay, which makes sense. So\n\n390\n00:19:27,433 --> 00:19:30,434\nit's good that it's warning us about that. All right let me\n\n391\n00:19:30,436 --> 00:19:33,871\nbuild the UI of this guy right here. Okay? As I said it's\n\n392\n00:19:33,873 --> 00:19:37,642\njust gonna have some emotions in here that you can click on.\n\n393\n00:19:37,644 --> 00:19:40,211\nNormally you probably wanna do this with the table view.\n\n394\n00:19:40,213 --> 00:19:42,446\nOkay a table and extensible list of them.\n\n395\n00:19:42,448 --> 00:19:45,016\nBut I can't I'm not teaching a table view until next week.\n\n396\n00:19:45,018 --> 00:19:46,484\nSo we're gonna use buttons. All right?\n\n397\n00:19:46,486 --> 00:19:52,156\nSo I'm just drag out four buttons here to be my\n\n398\n00:19:52,158 --> 00:19:57,828\nthe four emotions that I am going to have here.\n\n399\n00:19:57,830 --> 00:19:58,763\nSorry, put this in here.\n\n400\n00:19:58,765 --> 00:20:01,499\nAnd when I drag it out, it does not really matter where I\n\n401\n00:20:01,501 --> 00:20:04,101\nput it because I am going to stack view them. So\n\n402\n00:20:04,103 --> 00:20:07,939\nlet us go ahead and make the font a little bigger here, 40\n\n403\n00:20:07,941 --> 00:20:13,144\npoint. And so what buttons do we wanna have here? How about\n\n404\n00:20:13,146 --> 00:20:17,915\nan angry button and we'll have three other buttons.\n\n405\n00:20:17,917 --> 00:20:24,922\nHow about happy and how about worried? Is that a,\n\n406\n00:20:24,924 --> 00:20:26,991\nan emotion, worried? I don't, I don't know.\n\n407\n00:20:26,993 --> 00:20:30,995\nIt's good to make a face of it though. How about mischievous?\n\n408\n00:20:30,997 --> 00:20:34,865\nMischievous, is that how you spell that?\n\n409\n00:20:34,867 --> 00:20:36,667\nAgain I'm not sure that's an emotion, but\n\n410\n00:20:36,669 --> 00:20:39,870\nit makes a good face. Okay so here I have my things,\n\n411\n00:20:39,872 --> 00:20:40,605\nI'm going to stack view these.\n\n412\n00:20:40,607 --> 00:20:45,176\nJust going to select them all and go embed in stack view.\n\n413\n00:20:45,178 --> 00:20:46,844\nI don't want them left aligned like this, so\n\n414\n00:20:46,846 --> 00:20:49,947\nI'm going to change their alignment to fill the space.\n\n415\n00:20:49,949 --> 00:20:53,317\nI'll do fill equally although they're all the same font so\n\n416\n00:20:53,319 --> 00:20:55,019\nthey're all gonna be the same height anyway so\n\n417\n00:20:55,021 --> 00:20:58,823\nit doesn't really matter there. So,\n\n418\n00:20:58,825 --> 00:21:02,660\nI want these words to always be in the middle of my screen,\n\n419\n00:21:02,662 --> 00:21:04,895\neven if I'm rotated like if I'm in landscape or\n\n420\n00:21:04,897 --> 00:21:07,565\nportrait, I always want them in the middle. So I'm gonna\n\n421\n00:21:07,567 --> 00:21:10,735\nuse the dash blue lines to put it right in the middle.\n\n422\n00:21:10,737 --> 00:21:13,704\nAnd now you're going to do the same trick we did before,\n\n423\n00:21:13,706 --> 00:21:14,739\nwhich was rest to suggested constraints and\n\n424\n00:21:14,741 --> 00:21:17,475\nit's going to use those blue lines\n\n425\n00:21:17,477 --> 00:21:20,444\nto suggest some constraints to constrain this stack for\n\n426\n00:21:20,446 --> 00:21:23,180\nyou on here. And let's go look what it suggested,\n\n427\n00:21:23,182 --> 00:21:26,284\nremember to do that we go over here to the size inspector.\n\n428\n00:21:26,286 --> 00:21:29,320\nWe go down to where it says constraints, and sure enough,\n\n429\n00:21:29,322 --> 00:21:32,023\nalign the center in the x-axis to superview and\n\n430\n00:21:32,025 --> 00:21:34,158\nalign the center in the y-axis to superview. Perfect,\n\n431\n00:21:34,160 --> 00:21:39,363\nexactly what I want. So now if I run, it's gonna center this\n\n432\n00:21:39,365 --> 00:21:43,567\nhorizontally and vertically. Okay, even if I'm in\n\n433\n00:21:43,569 --> 00:21:48,406\nlandscape. Okay? So now, I've built this UI. Great,\n\n434\n00:21:48,408 --> 00:21:52,943\nit's exactly what I want. And I had now have two NVCs. Now,\n\n435\n00:21:52,945 --> 00:21:56,347\nI'm gonna show you all three ways of combining NVCs, tab\n\n436\n00:21:56,349 --> 00:21:59,583\nbars, split view controllers, and navigation controllers.\n\n437\n00:21:59,585 --> 00:22:02,019\nLet's start with tab bar controller, okay? How would I\n\n438\n00:22:02,021 --> 00:22:05,289\nput these two things one in its, each in its own tab?\n\n439\n00:22:05,291 --> 00:22:10,161\nWell, I'm gonna go down here, okay? To our object pallet.\n\n440\n00:22:10,163 --> 00:22:12,730\nAnd if you look, about six or seven down, there's this.\n\n441\n00:22:12,732 --> 00:22:15,733\nTab bar controller, you see that? And if I drag this\n\n442\n00:22:15,735 --> 00:22:19,937\nout here, okay, it'll put this tab bar out here.\n\n443\n00:22:19,939 --> 00:22:23,107\nIt unfortunately also brings some extra MVCs here,\n\n444\n00:22:23,109 --> 00:22:26,944\nthese little blank MVCs that I don't want. So I'm just gonna\n\n445\n00:22:26,946 --> 00:22:29,647\nclick on those and delete them. So get rid of that one.\n\n446\n00:22:29,649 --> 00:22:33,084\nAnd get rid of that one. So all I have now is my tab bar\n\n447\n00:22:33,086 --> 00:22:37,088\ncontroller. If you can read that, I'll zoom in a little.\n\n448\n00:22:37,090 --> 00:22:40,658\nOkay see tab bar controller and then I've got my two\n\n449\n00:22:40,660 --> 00:22:43,994\nMVC's here that I created. My emotions view controller and\n\n450\n00:22:43,996 --> 00:22:47,598\nmy face view controller. Now I for sure want\n\n451\n00:22:47,600 --> 00:22:50,868\nthe app to start with the tab bar controller, so I'm going\n\n452\n00:22:50,870 --> 00:22:53,003\nto move that arrow. This is another thing you'll forget.\n\n453\n00:22:53,005 --> 00:22:56,140\nYou'll forget to move this arrow. Okay. And\n\n454\n00:22:56,142 --> 00:22:59,243\nnow I just want this to be in one tab and this in the other.\n\n455\n00:22:59,245 --> 00:23:02,012\nI just do that with control drag. So control\n\n456\n00:23:02,014 --> 00:23:06,150\ndrag to this one, I'm going to hook up this view controllers.\n\n457\n00:23:06,152 --> 00:23:06,851\nRemember the view controllers\n\n458\n00:23:06,853 --> 00:23:10,354\nproperty in a tab bar is just an array of all the tabs.\n\n459\n00:23:10,356 --> 00:23:13,991\nOkay, the MVCs is there in the tabs and do this one also,\n\n460\n00:23:13,993 --> 00:23:17,528\nthat in the view controllers array, okay. You can even see\n\n461\n00:23:17,530 --> 00:23:19,897\nit's already starting to put the tabs on the bottom.\n\n462\n00:23:19,899 --> 00:23:22,933\nIf you wanted to edit what's in these tabs, like the names,\n\n463\n00:23:22,935 --> 00:23:26,137\nyou think, you double click down here something, but no,\n\n464\n00:23:26,139 --> 00:23:30,708\nbecause this is the Tab Bar Controller and these titles\n\n465\n00:23:30,710 --> 00:23:35,246\nand images are all set by the MVCs inside. Okay,\n\n466\n00:23:35,248 --> 00:23:38,482\nin an object oriented way, right. So, if you wanted to\n\n467\n00:23:38,484 --> 00:23:40,484\nset this you would actually go to each one of them.\n\n468\n00:23:40,486 --> 00:23:43,621\nAnd you can even double click right here and put in whatever\n\n469\n00:23:43,623 --> 00:23:47,191\nyou want. You can also click here and inspect them, okay,\n\n470\n00:23:47,193 --> 00:23:50,594\nif you go to the inspector, you can set images and also\n\n471\n00:23:50,596 --> 00:23:55,332\na bunch of system ones. Okay, so that's how you set that.\n\n472\n00:23:55,334 --> 00:23:59,403\nSo this is what our Storyboard looks like right now and\n\n473\n00:23:59,405 --> 00:24:06,844\nif we run this. We'll see that we get a tab bar.\n\n474\n00:24:06,846 --> 00:24:09,313\nSee, it's got two tabs at the bottom here. And\n\n475\n00:24:09,315 --> 00:24:12,616\nif I click between them, I get my two MVCs.\n\n476\n00:24:12,618 --> 00:24:16,187\nNow this is completely inappropriate to what I'm\n\n477\n00:24:16,189 --> 00:24:19,690\nbuilding here because I would never want, if I clicked on\n\n478\n00:24:19,692 --> 00:24:23,360\none of these, for it to switch over to this tab, okay?\n\n479\n00:24:23,362 --> 00:24:27,498\nThat's because when you do a tab bar UI, listen closely,\n\n480\n00:24:27,500 --> 00:24:30,935\nthe user owns which tab is showing, okay?\n\n481\n00:24:30,937 --> 00:24:33,871\nThey get to choose by clicking on those tabs. You don't get\n\n482\n00:24:33,873 --> 00:24:36,240\nto choose by throwing them over to one, okay?\n\n483\n00:24:36,242 --> 00:24:40,811\nThat is not appropriate for tab bar. Everyone got that? So\n\n484\n00:24:40,813 --> 00:24:43,681\nthings in a tab bar UI tend to be independent things,\n\n485\n00:24:43,683 --> 00:24:45,950\nthings that don't segue from one to another,\n\n486\n00:24:45,952 --> 00:24:48,786\nyou can't even make a segue from one tab to another, so no\n\n487\n00:24:48,788 --> 00:24:52,823\nsuch segue. So we don't want to do a tab bar controller\n\n488\n00:24:52,825 --> 00:24:55,259\nhere, so I'm just going to delete my tab bar controller,\n\n489\n00:24:55,261 --> 00:24:57,962\nokay? Now one thing you'll notice when I deleted my tab\n\n490\n00:24:57,964 --> 00:25:02,333\nbar controller is, where's my arrow? Okay, it's gone. So\n\n491\n00:25:02,335 --> 00:25:05,102\nnow it's not going to, if I run, I'm actually going to get\n\n492\n00:25:05,104 --> 00:25:08,506\nan error in the console saying I don't know where to start\n\n493\n00:25:08,508 --> 00:25:11,909\nin my storyboard, basically. So how do you get that arrow\n\n494\n00:25:11,911 --> 00:25:13,511\nback? Just click the one you want\n\n495\n00:25:13,513 --> 00:25:17,281\nthe arrow to be on, inspect it, and go right down here,\n\n496\n00:25:17,283 --> 00:25:19,550\nvery top, is initial view controller,\n\n497\n00:25:19,552 --> 00:25:22,786\nif you turn that on, the arrow will come back there, okay?\n\n498\n00:25:22,788 --> 00:25:25,990\nAnd you can move it, okay, down to here if you want.\n\n499\n00:25:25,992 --> 00:25:30,027\nOkay? All right, so let's talk about split view controller.\n\n500\n00:25:30,029 --> 00:25:33,230\nWe haven't even done anything with iPad at all in this class\n目前为止，这门课还没有任何涉及 iPad 应用的内容\n\n501\n00:25:33,232 --> 00:25:36,200\nyet. So this is our first time doing it and we're gonna put\n所以现在是我们第一次讨论关于\n\n502\n00:25:36,202 --> 00:25:40,004\nthis in split view controller where this is the master and\n有 master controller 和 detail controller 的\n\n503\n00:25:40,006 --> 00:25:41,839\nthis is the detail, makes sense, right?\nsplit view controller 明白了没？\n504\n00:25:41,841 --> 00:25:42,706\nBecause we're clicking in the master,\n我们点这个展示 master controller\n\n505\n00:25:42,708 --> 00:25:46,110\nthis will be the detail that's shown from clicking on this.\n点这个展示 detail controller\n\n506\n00:25:46,112 --> 00:25:47,545\nSo how do we do a split view controller?\n我们怎么处理一个 split view controller 呢？\n\n507\n00:25:47,547 --> 00:25:50,514\nSame way as tab bar. I'm gonna go down here, right below tab\n给 tab bar 的一样，我在这里\n\n508\n00:25:50,516 --> 00:25:53,884\nbar is split view controller. I'm gonna drag that out,\nTab Bar Controller 下面就是这个 Split View Controller\n\n509\n00:25:53,886 --> 00:25:56,987\nI get a whole bunch of junk with it. We'll zoom out so\n把这个拖出来，我就得到了一大堆垃圾(controller)\n\n510\n00:25:56,989 --> 00:26:00,858\nyou can see it. Okay. See, I got all these extra things, so\n缩小了你就看见了，我得到了好多额外的东西\n\n511\n00:26:00,860 --> 00:26:02,526\nI'm gonna, click on these extra things and\n所以我要把这些额外的统统删掉\n\n512\n00:26:02,528 --> 00:26:05,896\ndelete them, don't want any of them. Okay. So I just have\n一个都不想留，所以我现在只有\n\n513\n00:26:05,898 --> 00:26:08,832\nthe split view controller and my two guys here.\n这个 split view controller 和 刚刚那两个 controller\n\n514\n00:26:08,834 --> 00:26:11,402\nOf course I want the split view controller, again,\n我想让这个 split view controller 变为最早展示出来\n\n515\n00:26:11,404 --> 00:26:14,471\nto be the start so I'm going to put the arrow there. And\n所以我把箭头放在这里\n\n516\n00:26:14,473 --> 00:26:18,676\nthen, in order to hook up master and detail, Ctrl+Drag.\n然后，为了将 master、detail 与 split view controller 联系起来\n\n517\n00:26:18,678 --> 00:26:24,181\nMaster, Ctrl+Drag, detail. Okay,\nCtrl+Drag 选择 Master，Ctrl+Drag 选择 detail\n\n518\n00:26:24,183 --> 00:26:26,917\nso that's how we set it up, couldn't be simpler. So let's\n我们就是这么建立起他们的关系，再简单不过了\n\n519\n00:26:26,919 --> 00:26:30,854\nrun, but let's run on iPad, so I'm gonna, on iPad 2 here,\n现在在 iPad 上运行，我用 iPad 2 模拟器\n\n520\n00:26:30,856 --> 00:26:34,425\nwe'll run and hopefully this will show up as a master and\n运行起来，希望这个会作为 master \n\n521\n00:26:34,427 --> 00:26:42,566\nthis will be the detail. All right. So here's the iPad.\n这个会作为 detail 展示出来，这是 iPad\n\n522\n00:26:42,568 --> 00:26:45,469\nHere's the detail. You notice that when it's in portrait\n这是 detail controller，你可能注意到当在竖屏状态下\n\n523\n00:26:45,471 --> 00:26:46,604\nit fills the screen with the detail,\ndetail controller 充满了屏幕\n\n524\n00:26:46,606 --> 00:26:50,608\nand you get the master by dragging out from the side.\n通过拖动侧边，master controller 就展示出来了\n\n525\n00:26:50,610 --> 00:26:53,744\nSee that? Okay? That's how you get the master. And\n看到了吗？竖屏就通过这种方式看到 master controller\n\n526\n00:26:53,746 --> 00:26:54,778\nif you're in landscape,\n如果横过来，变成横屏状态\n\n527\n00:26:54,780 --> 00:26:58,782\nthen they're both onscreen at the same time. Now, if I click\nmaster 和 detail 就在屏幕上同时展示出来\n\n528\n00:26:58,784 --> 00:27:02,753\non these, I want this face to show me angry, show me happy,\n如果我点 Angry，我希望这个脸变成生气的样子\n\n529\n00:27:02,755 --> 00:27:04,455\nshow me worried, show me mischievous, okay?\n变成高兴、变成担忧、变成淘气的样子\n\n530\n00:27:04,457 --> 00:27:07,224\nSo how do I do that? This is where the segues come in.\n这怎么做呢？这时我们就需要用到 segue 了\n\n531\n00:27:07,226 --> 00:27:10,561\nOkay? This is where we have to have this view controller\n我们需要让这个 view controller 转场\n\n532\n00:27:10,563 --> 00:27:12,396\nsegue to create a new one of these and\n然后 create 一个detail controller\n\n533\n00:27:12,398 --> 00:27:15,132\nwhen it creates this, it's going to create it with\n当 create 时，会 create 一个有确切表情值的 controller\n\n534\n00:27:15,134 --> 00:27:18,769\nthe proper facial expression, okay? So it's going to prepare\n所以，它会准备好表情值\n\n535\n00:27:18,771 --> 00:27:22,172\nit with a facial expression and show it. Okay? So\n然后将这个确切的表情展示出来\n536\n00:27:22,174 --> 00:27:26,276\nlet's do those segues. The way we do segues, also Ctrl+Drag.\n我们来设置这些转场，同样是 Ctrl Drag 设置\n\n537\n00:27:26,278 --> 00:27:29,847\nSo, let me zoom in here so you can see this. All right?\n我放大点你就可以看到了\n\n538\n00:27:29,849 --> 00:27:32,783\nI'm gonna Ctrl+Drag from whichever of these buttons\n我按住 segue 开始的 button，然后 Ctrl + Drag \n\n539\n00:27:32,785 --> 00:27:35,352\nI want to segue from. I'm gonna segue from all four, so\n我想从这4个button开始连 segue\n\n540\n00:27:35,354 --> 00:27:38,222\nI'm gonna have four segues. So like angry here I'm\n所以我应该有4个segue，像从这里按住 angry button\n\n541\n00:27:38,224 --> 00:27:42,493\njust gonna Ctrl+Drag down to this MVC. And let go.\n然后 Ctrl + Drag 到这个 MVC，然后松手\n\n542\n00:27:42,495 --> 00:27:44,728\nAnd it says, well what kind of segue do you want?\n这里会让你选择你想要的 segue 类型\n\n543\n00:27:44,730 --> 00:27:45,896\nShow, show detail, modally or\nShow, show detail, modally 或者是\n\n544\n00:27:45,898 --> 00:27:49,133\npop over. Well, we're in the split view controller here so\npop over。因为我们用的是 split 控制器，所以\n\n545\n00:27:49,135 --> 00:27:52,002\nI want to show detail, right? Split view. Master detail.\n我选择 show detail \n\n546\n00:27:52,004 --> 00:27:55,406\nShow detail. Bam. There it is right there. Okay?\n这个是split view，然后 master detail 用 show detail 连接，对吧？\n\n547\n00:27:55,408 --> 00:27:58,409\nCreated this little thing here. That's my segue. And\n做了这些工作，这就是我的 segue\n\n548\n00:27:58,411 --> 00:28:01,578\nthis segue can be inspected. You can see it up here, okay?\n这些 segue 是可以被检查的，你可以在这里看到他们\n\n549\n00:28:01,580 --> 00:28:04,214\nThis is the attributes inspector. And it's got\n这是属性检查器，会显示 show detail 的类型\n\n550\n00:28:04,216 --> 00:28:07,184\nthe kind of show detail, also known as a replace segue.\n也常常被叫做 replace segue\n\n551\n00:28:07,186 --> 00:28:11,055\nIt animates, it shows that this segue is going to happen\n这是 Animates，这个说明这个 segue 可以用动画的形式展现\n\n552\n00:28:11,057 --> 00:28:13,991\nin an animated fashion, so it's going to slide in or\n是滑进或者别的方式\n\n553\n00:28:13,993 --> 00:28:16,427\nwhatever. It's not always makes sense to animate but\n并不总是可以选择 Animates 的，有时候可以\n\n554\n00:28:16,429 --> 00:28:19,963\nsometimes it does. Class and module, don't worry about\n有时候不行，不用担心这些，比如 Class 和 Module \n\n555\n00:28:19,965 --> 00:28:21,665\nthat. That's for creating your own custom segues,\n这些帮助你设置你自定义的 segue\n\n556\n00:28:21,667 --> 00:28:23,233\nwhich we're not going to talk about in this class.\n这些内容有一些超前，所以我们这节课不会讨论到\n\n557\n00:28:23,235 --> 00:28:26,303\nA little bit too advanced. And then, here is the all\n最重要的属性是 identifier\n\n558\n00:28:26,305 --> 00:28:29,440\nimportant identifier. So here, we have to give any string\n我们需要用字符串来唯一确定这个segue\n\n559\n00:28:29,442 --> 00:28:34,011\nwe want that identifies this segue. So I could call this,\n比如，我可以叫这个segue\n\n560\n00:28:34,013 --> 00:28:38,682\nfor example, the angry segue, maybe I'd want a verb\n为 angry segue \n\n561\n00:28:38,684 --> 00:28:41,885\nphrase like show anger or something like that but\n我应该用一个动词，比如 show anger 或者\n\n562\n00:28:41,887 --> 00:28:45,022\nit's fine also maybe to have a nice simple word like anger.\n就是一个单一的明确的名词，像 anger\n\n563\n00:28:45,024 --> 00:28:46,757\nSo that's my angry segue right there.\n所以，这是我的 angry segue\n\n564\n00:28:46,759 --> 00:28:50,461\nOkay. And so now let's wire up the other ones, Ctrl+Drag this\n好，现在我们连一下剩余的控件\n\n565\n00:28:50,463 --> 00:28:54,331\none down here. This one is also going to be show detail.\n在这里按 Ctrl + Drag，这个是 show detail\n \n566\n00:28:54,333 --> 00:28:58,569\nThey're all going to be show detail. I'll do worried also.\n我想这个也应该是 show detail\n\n567\n00:28:58,571 --> 00:29:03,340\nShow detail, oops, not present modally, get rid of that.\noops，不是 present modally，删掉这个\n568\n00:29:03,342 --> 00:29:08,278\nAlright. Then here. Show detail.\n这个也是 Show detail\n\n569\n00:29:08,280 --> 00:29:12,716\nMischievous. Show detail.\n给淘气的也连上Show detail segue\n\n570\n00:29:12,718 --> 00:29:15,886\nOkay, now I need to set the identifier for all of these.\n现在，我需要给这些 segue 都设置 identifier 作为唯一标示\n\n571\n00:29:15,888 --> 00:29:19,223\nWhat's really cool is if I click on one it'll tell me who\n特别酷的是，如果我点击一个 segue，他会显示\n\n572\n00:29:19,225 --> 00:29:23,227\nthe sender of this segue is. So there's worried, okay.\n这个 segue 的发送者是哪一个，这个是 worried\n\n573\n00:29:23,229 --> 00:29:27,030\nWorried. Here is happy, and\n这个是 happy\n\n574\n00:29:27,032 --> 00:29:30,200\nwe'll call this my happy segue.\n我想把这个叫 happy segue\n\n575\n00:29:30,202 --> 00:29:34,238\nThis one, angry already set up. This one, mischievous,\n这个，angry 已经设置好了\n\n576\n00:29:34,240 --> 00:29:38,876\nokay. Mischievous. Hopefully I spelled that right. Okay, so\n这个是 Mischievous，希望我正确地拼写了这几个词\n\n577\n00:29:38,878 --> 00:29:41,378\nnow we've got these segues set up so let's run and\n现在我设置了这几个 segue，然后运行一下\n\n578\n00:29:41,380 --> 00:29:48,218\nsee what happens here. All right, angry, happy,\n看看会发生什么\n\n579\n00:29:48,220 --> 00:29:51,855\nstill nothing's happening. What is the problem here?\n什么也没发生，问题出在什么地方呢？\n\n580\n00:29:51,857 --> 00:29:54,158\nOkay, well, it is actually segueing here.\nOkay，这确实是 segue 的问题\n\n581\n00:29:54,160 --> 00:29:56,527\nIt's replacing that face with a new MVC, but\n程序用了新的 MVC 来替换这张脸\n\n582\n00:29:56,529 --> 00:29:59,663\nthat new face has not been prepared to show the emotion\n但是，这个新 face 还没有准备好展示这个表情\n\n583\n00:29:59,665 --> 00:30:02,533\nwe want so it's just showing the default emotion,\n所以它仅仅展示在 storyboard 中展现的\n\n584\n00:30:02,535 --> 00:30:05,569\nwhatever happened to be in our storyboard, right?\n默认表情，对吗？\n\n585\n00:30:05,571 --> 00:30:07,471\nThis face right here just happens to be, or or\n这个 face 在这里是这么展示的\n\n586\n00:30:07,473 --> 00:30:10,374\nit's actually what happens to be the default our model is is\n或者会展示默认的 model 表现的表情\n\n587\n00:30:10,376 --> 00:30:14,611\nthat. Okay, so we need to, in all these segues, prepare\n所以，我们需要给所有 segue 准备\n\n588\n00:30:14,613 --> 00:30:18,849\nthe MVC that we are segueing to. We do that in the source\n其需要展示的 model，我们在 segue 的源头设置\n\n589\n00:30:18,851 --> 00:30:21,018\nview controller, that is the emotions view controller.\n在这里应该是 emotions 控制器\n\n590\n00:30:21,020 --> 00:30:23,287\nThis is the thing that implements Prepare for Segue.\n实现 prepareForSegue 这个方法\n\n591\n00:30:23,289 --> 00:30:26,924\nSo I am just going to un comment out the comments here,\n我要删掉这些注释\n\n592\n00:30:26,926 --> 00:30:31,595\nokay, for my Prepare for Segue. Make lots of space.\n为 prepareForSegue 挪一些空间\n\n593\n00:30:31,597 --> 00:30:33,363\nAlright, so here we have Prepare for Segue,\n在这里写上 prepareForSegue\n\n594\n00:30:33,365 --> 00:30:36,466\nwe get the two arguments, the segue which tells us a little\n我们需要两个参数，segue 参数告诉我们\n\n595\n00:30:36,468 --> 00:30:37,401\nbit about which segue it is and\n这是哪个segue \n\n596\n00:30:37,403 --> 00:30:40,137\nwhat the destination view controller is and then we have\n它的目的 controller 是哪一个\n\n597\n00:30:40,139 --> 00:30:42,339\nthe sender. That's going to be those buttons,\n还有一个 sender 参数，这应该是这些按钮\n\n598\n00:30:42,341 --> 00:30:44,675\nlike the angry button, the mischievous button.\n像是 angry button、mischievous button\n\n599\n00:30:44,677 --> 00:30:45,509\nThat's what this is going to be,\n这些应该就是这些控件\n600\n00:30:45,511 --> 00:30:46,977\nit's going to be the UI button. Okay?\n像是 UIButton\n\n601\n00:30:46,979 --> 00:30:49,913\nThis is any object because it is allowed to be any object.\n这里必须是一些对象\n\n602\n00:30:49,915 --> 00:30:50,747\nIn this case it's a button, but\n在这种情况下，就是 button\n\n603\n00:30:50,749 --> 00:30:53,083\nit's allowed to be any object. All right.\n但是，也可以允许是其他对象\n\n604\n00:30:53,085 --> 00:30:54,618\nSo what do we do here in preparing for\n我们在这里应该写些什么来为 segue 做准备呢？\n\n605\n00:30:54,620 --> 00:30:57,354\nsegue? The first thing I'm going to do is get a hold\n第一，我需要获取到\n\n606\n00:30:57,356 --> 00:30:59,089\nof the destination view controller, and\nsegue 目标 controller\n\n607\n00:30:59,091 --> 00:31:01,692\nmake sure that it's a face view controller.\n确保他是 face view controller\n\n608\n00:31:01,694 --> 00:31:04,695\nCuz if it's not, I don't really know how to,\n如果他不是的话，我确实不知道应该\n\n609\n00:31:04,697 --> 00:31:04,761\nthe segue so I'm just going to do nothing in that case. So\n怎么为这个 segue 做准备\n\n610\n00:31:04,763 --> 00:31:07,497\nto prepare for\n在这种条件下\n\n611\n00:31:07,499 --> 00:31:09,600\nI'm going to create a little local variable, okay?\n我需要创造一个局部变量\n\n612\n00:31:09,602 --> 00:31:13,537\nI'm going to call it destinationvc, destination\n叫做 destinationvc \n\n613\n00:31:13,539 --> 00:31:18,375\nview controller. And that's just equal to the segue,\n表示目的的 controller，这个等于\n\n614\n00:31:18,377 --> 00:31:21,979\ndestin, segue, destinationViewController,\nsegue 的 destinationViewController\n\n615\n00:31:21,981 --> 00:31:25,415\nokay? Now this is a UIViewController, okay,\n现在，这个就是一个 UIViewController\n\n616\n00:31:25,417 --> 00:31:30,087\nof some sort, it's some sub-class of UIViewController.\n但是，应该是 UIViewController 的子类\n\n617\n00:31:30,089 --> 00:31:32,556\nI suppose it could even be UIViewController itself.\n这应该就是 UIViewController 本身\n\n618\n00:31:32,558 --> 00:31:35,225\nThere's probably a subclass of it, and so I need to get\n这里应该用一个他的子类，所以我需要获得其子类\n\n619\n00:31:35,227 --> 00:31:38,595\nthat subclass, I need to get this variable, in some way,\n我需要让这个变量\n\n620\n00:31:38,597 --> 00:31:41,832\nso that it's a subclass of it. Or I can't work with it.\n变为其子类\n\n621\n00:31:41,834 --> 00:31:44,434\nRight? Because, UIViewController, I wouldn't\n要不然我不能将一些属于 faceViewController 的消息\n\n622\n00:31:44,436 --> 00:31:47,871\nbe able to send any of the face view controller messages\n传给他\n\n623\n00:31:47,873 --> 00:31:51,642\nto it, because it's just a generic UIViewController, so I\n因为他只是一个通用的 UIViewController\n\n624\n00:31:51,644 --> 00:31:55,612\nneed to get myself a faceview controller so I'm gonna say,\n所以我需要得到一个 faceViewController\n\n625\n00:31:55,614 --> 00:31:58,382\nif I can let facevc, which is a new variable,\nif let facevc \n\n626\n00:31:58,384 --> 00:32:01,785\nequal the destinationvc As a FaceViewController.\n等于之前的变量 destinationvc 作为 FaceViewController\n\n627\n00:32:01,787 --> 00:32:04,855\nThen I'm ready to rock here. Okay, now I have\n然后我准备在这里做操作\n\n628\n00:32:04,857 --> 00:32:07,324\na FaceViewController, okay? So I've just casted.\n现在，我通过转型获得了一个 FaceViewController\n\n629\n00:32:07,326 --> 00:32:10,460\nThey're similar to how I can't work with any object,\n这跟之前我不能做特殊操作的\n\n630\n00:32:10,462 --> 00:32:12,429\nI really can't work with a generic UIViewController.\n通用 UIViewController 类似\n\n631\n00:32:12,431 --> 00:32:15,265\nI need the subclass. Otherwise how am I going to set its\n我获得了他的子类，然后，\n632\n00:32:15,267 --> 00:32:19,269\nmodel, okay? I have to be able to talk to it. All right. So\n接下来，我需要设置这个 controller 的 model\n\n633\n00:32:19,271 --> 00:32:22,472\nnow I have this destination view controller.\n现在我有了代表目标的 controller\n\n634\n00:32:22,474 --> 00:32:25,676\nNow I need the identifier. So here I'm gonna say, if I can\n现在，我需要标识符\n\n635\n00:32:25,678 --> 00:32:30,180\nlet the identifier equal the segue's identifier. Okay,\n我需要让标识符等于 segue 的标识符\n\n636\n00:32:30,182 --> 00:32:33,183\nso here I'm just checking to make sure it's not nil.\n这样写是为了检查确保它不为空\n\n637\n00:32:33,185 --> 00:32:35,953\nNow it should be angry, or mischievous, or happy.\n他可以是 angry 、mischievous 或者是 happy\n\n638\n00:32:35,955 --> 00:32:38,355\nOne of those identifiers that I put in the stored word,\n可以是我之前设置的任何一个标识符，对吧？\n\n639\n00:32:38,357 --> 00:32:40,824\nright? And I could do something here like,\n我应该写\n\n640\n00:32:40,826 --> 00:32:42,793\nswitch on the identifier.\nswitch 标识符\n\n641\n00:32:42,795 --> 00:32:46,964\nAnd if it's angry then I'm going to have my face vc's\n如果是 angry，我应该写让我的表情 controller\n\n642\n00:32:46,966 --> 00:32:50,634\nexpression be a facial expression that's angry, blah,\n表现生气的表情\n\n643\n00:32:50,636 --> 00:32:51,668\nblah, blah. I could do that but\nblah，我可以这么写\n\n644\n00:32:51,670 --> 00:32:55,572\nthat's going to be allot of if then, blah, blah, okay, mess.\n但是，会是一些很乱的代码\n\n645\n00:32:55,574 --> 00:32:58,308\nSo instead I'm going to do one of my favorite ways to\n所以，相反的是，我会写一些我喜欢的\n\n646\n00:32:58,310 --> 00:33:01,878\nprogram, as you're probably getting the,\n编程风格的代码，你可能已经想到了\n\n647\n00:33:01,880 --> 00:33:05,048\nidea about which is use a dictionary. Okay, so\n对的，我们要用字典来表示\n\n648\n00:33:05,050 --> 00:33:08,752\nI have this dictionary I'm gonna type in real fast, okay,\n我快速的写一下这些代码\n\n649\n00:33:08,754 --> 00:33:12,556\nand this dictionary has keys which are the identifiers, and\n这些字典以这些标识符为键\n\n650\n00:33:12,558 --> 00:33:17,761\nit has values which are the appropriate facial expression.\n对应的值为合适的 facial expression 模型\n\n651\n00:33:21,100 --> 00:33:21,732\nOkay, got that, so\n明白了吗？\n\n652\n00:33:21,734 --> 00:33:25,402\ninstead of doing all of this switching on the identifier\n与在这里 switch 这些标识符相反的是\n\n653\n00:33:25,404 --> 00:33:29,206\nthing, I'm just going to say if I can let the expression\n让 expression 变量等于我想要的\n\n654\n00:33:29,208 --> 00:33:32,275\nthat I want equal these emotional faces up here.\nfacial expression 模型\n\n655\n00:33:32,277 --> 00:33:38,081\nTha's this dictionary up here. Index by the identifier.\n通过标识符来索引字典中的值\n\n656\n00:33:38,884 --> 00:33:41,184\nOkay? Then I know the expression that I want.\n然后，我获得了对应的表情模型\n\n657\n00:33:41,186 --> 00:33:45,489\nAnd now I can prepare my face VC okay, by setting its\n我可以为我要展示的 face VC 做准备\n\n658\n00:33:45,491 --> 00:33:48,992\nexpression equal to this expression. Okay, and remember\n让他的 expression 模型等于这个 expression\n\n659\n00:33:48,994 --> 00:33:54,197\nFaceVC.expression, that is just FaceViewControllers model\n你记得吗? 在 FaceViewControllers 里它的模型是一个\n\n660\n00:33:54,199 --> 00:33:57,534\nwhich is a public bar. This View Controller allows\n公共变量，它允许\n\n661\n00:33:57,536 --> 00:33:59,669\nits model to be set externally, publicly,\n在外部设置其模型\n\n662\n00:33:59,671 --> 00:34:04,041\nokay, which makes sense given this kind of model.\n这让我们可以在对应的地方设置其 model\n\n663\n00:34:04,043 --> 00:34:06,043\nNot all, and doesn't make sense always for\n这样仅是在这个 viewcontroller 中\n664\n00:34:06,045 --> 00:34:08,912\nevery MBC to allow it's model to be set but often it makes\n设置其 model ，并不是所有viewcontroller 都可以设置\n\n665\n00:34:08,914 --> 00:34:13,216\nsome sense. Alright, so now I've prepared this Faceview\n现在我已经为这个 faceViewController 设置好了\n\n666\n00:34:13,218 --> 00:34:17,754\ncontroller to do what it needs to do. Everybody got that? OK.\n它需要的东西，大家都明白吗？\n\n667\n00:34:17,756 --> 00:34:26,396\nSo now let's run it and see if it's working. Okay.\n现在我们运行一下，来看看是否正确显示\n\n668\n00:34:26,398 --> 00:34:30,267\nSo here we go, we have our iPad here, let's try angry.\n这是我们的模拟器 iPad，点击 angry\n\n669\n00:34:30,269 --> 00:34:35,338\nCrash a roo. Hmm. Wonder why that crashed? Well let's look,\n哦，崩溃了，想一想为什么会崩溃呢？我们来检查下\n\n670\n00:34:35,340 --> 00:34:37,941\nlet's use the debugger. Okay, we haven't used the debugger\n我们需要用一下 debugger 模式，我们还没有\n\n671\n00:34:37,943 --> 00:34:41,044\nmuch in these demos but let's do it here. Seems like,\n在这个 demo 中用过这个方法\n\n672\n00:34:41,046 --> 00:34:43,280\nokay, whenever I have a crash, I always look first in\n不管什么时候，程序崩溃了，我总是先查看\n\n673\n00:34:43,282 --> 00:34:45,615\nthe console, okay, because the console is always going to\n控制台输出的信息，因为控制台总会告诉我一些\n\n674\n00:34:45,617 --> 00:34:47,918\ntell me something about what happened. And here it says\n关于崩溃的信息，这里显示\n\n675\n00:34:47,920 --> 00:34:51,288\nunexpectedly found nil while unwrapping an optional value.\n在解包一个可选值时，意外地发现了空异常\n\n676\n00:34:51,290 --> 00:34:53,857\nOkay, well this is probably the number one crasher you're\n这种异常你可能经常获得\n\n677\n00:34:53,859 --> 00:34:56,927\never going to get, it's one of the few ways actually to crash\n在 Swift 代码中，你可能经常\n\n678\n00:34:56,929 --> 00:34:59,963\nSwift code is to have unwrapping and nil.\n在解包时，发现空异常\n\n679\n00:34:59,965 --> 00:35:03,366\nSo it is happening on this orange line of code.\n所以，在这一行，发生了这个异常\n\n680\n00:35:03,368 --> 00:35:10,607\nI am looking here. Does anyone see an optional here? No?\n我看这一行，有人发现这里有可选值了吗？\n\n681\n00:35:10,609 --> 00:35:13,110\nNobody sees an optional on this line of code?\n没有人在这一行发现可选值吗？\n\n682\n00:35:13,112 --> 00:35:15,846\nIt doesn't look like it, does it? Because you do not see any\n这一行看上去没有可选值吗？\n\n683\n00:35:15,848 --> 00:35:18,081\nexclamation points. I am not unwrapping anything.\n可能因为你没有看到感叹号，我没有解包任何值\n\n684\n00:35:18,083 --> 00:35:21,251\nWhat is going on? Well actually what is face view,\n发生了什么呢？其实是这个 faceVIew\n\n685\n00:35:21,253 --> 00:35:25,589\nwhat's its type? Anyone remember? Our outlet,\n它的类型有人记得吗？\n\n686\n00:35:25,591 --> 00:35:31,094\nthat's our outlet remember here? Right, it's a optional\n这是我们的 outlet，还记得吗？\n\n687\n00:35:31,096 --> 00:35:36,900\nface view, okay? It's implicitly unwrapped okay,\n这是一个可选值得 faceView，他隐式解包了\n\n688\n00:35:36,902 --> 00:35:40,904\nbut it's still an optional. And I told you in the slides,\n但是他确实是一个可选值，ppt 里我说过\n\n689\n00:35:40,906 --> 00:35:45,041\nthat your outlets are not set at the time you're preparing.\n在你准备 segue 时，这些outlet还没有被设置\n\n690\n00:35:45,043 --> 00:35:49,179\nSo this face view right here, okay, is nil, let's look.\n所以，这里的 faceView 为空\n\n691\n00:35:49,181 --> 00:35:52,215\nOkay, here's where our variables are down here,\n我们在这里可以看到这些变量\n\n692\n00:35:52,217 --> 00:35:55,952\nclicking on \"self\", face view, sure enough nil.\n点击 self，faceView 确实为nil\n\n693\n00:35:55,954 --> 00:35:58,822\nSo my pointer to my face view has not been set yet by iOS\n在 iOS 中，这里的 faceView 还没有被设置\n\n694\n00:35:58,824 --> 00:36:01,725\nand that's always gonna be the case when you're preparing so\n在你准备 segue 时，这种情形经常发生\n\n695\n00:36:01,727 --> 00:36:05,529\nbe prepared for that happening okay. So what can we do about\n所以，我们应该怎么做呢？\n696\n00:36:05,531 --> 00:36:10,066\nit here? Okay well one thing we could say if face view does\n我们可以设置如果 faceView 不为空\n\n697\n00:36:10,068 --> 00:36:14,738\nnot equal nil then we'll do all this updating UI stuff\n我们来更新这些 UI\n\n698\n00:36:14,740 --> 00:36:17,874\nright? K, by the way why is this happening,\n顺便说下，为什么会这样呢？\n\n699\n00:36:17,876 --> 00:36:20,644\nwhy are we on this line of code? If we look over here on\n这行代码怎么了？\n\n700\n00:36:20,646 --> 00:36:22,946\nthe left it'll show us how us we got here.\n如果我们看左边的展示给我们的信息\n\n701\n00:36:22,948 --> 00:36:24,915\nOkay, so we're in this place right here,\n然后再看对应的右边的代码\n\n702\n00:36:24,917 --> 00:36:28,919\nokay, and let's see how we got here by clicking here. See,\n我们点击一下看看这是什么\n\n703\n00:36:28,921 --> 00:36:33,156\nwe set our model which makes sense and it called up DUI, so\n看，这里我们设置了我们的 model，然后更新了UI\n\n704\n00:36:33,158 --> 00:36:36,626\nwhy are we setting our model, okay, let's go up more. Sure\n为什么会走这一行呢，我们朝上点\n\n705\n00:36:36,628 --> 00:36:39,563\nenough here we are preparing. Okay, setting our model.\n因为在这里我们 prepare segue\n\n706\n00:36:39,565 --> 00:36:42,566\nSo this is right, preparing for segway, goes in here set\n然后设置了model\n\n707\n00:36:42,568 --> 00:36:45,302\nto our model. Wants to update UI, it's great.\n设置了model 之后，更新UI\n\n708\n00:36:45,304 --> 00:36:48,271\nUnfortunately our view is not been connected via outlet.\n不幸的是，这里我们的view没有连接 outlet\n\n709\n00:36:48,273 --> 00:36:50,840\nAll right, so this is one way we could do it. By the way,\n我们可以这样设置，避免他为空\n\n710\n00:36:50,842 --> 00:36:53,443\nthere is another trickier way to do it which is to\n顺便说一下，还有另一个复杂的方法处理这个问题\n\n711\n00:36:53,445 --> 00:36:55,312\nuse question mark here.\n在这里用问号\n\n712\n00:36:55,314 --> 00:36:57,981\nYou know that question mark works for optional chaining,\n你们知道在等号的右手边处理\n\n713\n00:36:57,983 --> 00:36:59,683\nright, on the right hand side of an equals?\n用问号来处理可选链\n\n714\n00:36:59,685 --> 00:37:02,452\nIt also works on the left hand side. If you put a question\n在等号的左边也可以处理\n\n715\n00:37:02,454 --> 00:37:05,155\nmark there, that's and you can put as many of the question\n你可以在等号的左边放置\n\n716\n00:37:05,157 --> 00:37:07,457\nmarks as you want on the left side of an equals. And\n你希望放置的任意的问号\n\n717\n00:37:07,459 --> 00:37:10,760\nif any of the things that you put a question mark are nil,\n如果你在其后写问号的变量确实为空\n\n718\n00:37:10,762 --> 00:37:12,395\nit just ignores the whole statement.\n他会忽略掉整个状态\n\n719\n00:37:12,397 --> 00:37:15,799\nLike it didn't even happen. Okay. So, that would be\n就像没写这句话一样，这就是另一种方式了\n\n720\n00:37:15,801 --> 00:37:17,534\nanother way. But we would have to put a question mark on\n但是我们需要在这里的每一个 faceView\n\n721\n00:37:17,536 --> 00:37:20,437\nevery single access of faceview in here. So,\n后面都写上问号\n\n722\n00:37:20,439 --> 00:37:23,807\nwe might as well just check to see if it's not nil. Now, is\n所以，还不如我在上面检查一下 faceView 是否为空\n\n723\n00:37:23,809 --> 00:37:28,011\nthis going to fix our problem? And the answer is, yes it is.\n现在让我们看看这确实解决了我们的问题了没\n\n724\n00:37:28,013 --> 00:37:31,681\nBecause we do update UI when our model gets set, but\n确实解决了，因为在 model 被重新设置后需要更新UI\n\n725\n00:37:31,683 --> 00:37:37,621\nwe also do update UI when this outlet gets set, remember?\n我们需要在outlet被设置后，更新UI, 记得吗？\n\n726\n00:37:37,623 --> 00:37:40,523\nSo when the outlet later, after the prepare is done,\n所以，当outlet被设置后，准备好了\n\n727\n00:37:40,525 --> 00:37:42,926\nwhen the outlet comes along and gets set, boom,\noutlet被设置了\n728\n00:37:42,928 --> 00:37:46,162\nour UI will get updated with the model that we set during\n我们的 UI 界面被更新为我们设置的 model\n\n729\n00:37:46,164 --> 00:37:49,065\nprepare, okay? So it's going to work fine, okay?\n这里就会正确运行，对吧？\n\n730\n00:37:49,067 --> 00:37:52,569\nBut this is part of the reason why when our outlets get set,\n这就是为什么我们设置了 outlet \n\n731\n00:37:52,571 --> 00:37:54,838\nwe update UI and when our model gets set,\n更新了UI 然后这时 model 才设置\n\n732\n00:37:54,840 --> 00:37:58,208\nwe update our UI because the order of them happening can be\n我们更新 UI，因为这两项发生的顺序\n\n733\n00:37:58,210 --> 00:38:02,846\nyou know can vary. All right. Sound good alright.\n有时候是不同的，看起来就应该这样\n\n734\n00:38:02,848 --> 00:38:04,347\nSo we fixed that, we checked this so\n现在我们解决了这个问题，我们来检查下\n\n735\n00:38:04,349 --> 00:38:06,483\nit's not gonna crash anymore, so let's run and\n还会不会崩溃\n\n736\n00:38:06,485 --> 00:38:08,318\nhopefully this is all working like a charm now.\n我们运行一下，希望一切正常\n\n737\n00:38:08,320 --> 00:38:12,222\nAll right here we go ready? Angry,\n现在看看对不对，Angry，\n\n738\n00:38:12,224 --> 00:38:16,192\nhappy, worried, mischievous.\nhappy, worried, mischievous.\n\n739\n00:38:16,194 --> 00:38:19,929\nOkay. All right? So it's working great. Okay, and\n运行起来很好\n\n740\n00:38:19,931 --> 00:38:26,002\nlet's try it this way. Slide out. Angry, happy, right?\n现在我们这么做，侧滑，Angry, happy\n\n741\n00:38:26,338 --> 00:38:30,473\nWorking like a charm. Okay? Okay, all right.\n看起来很好看，好的\n\n742\n00:38:30,475 --> 00:38:35,111\nNow, what about iPhone? Okay, this is great on iPad.\n现在，在 iPhone 上是什么样子呢？在 iPad 上运行良好\n\n743\n00:38:35,113 --> 00:38:38,248\nLet's try running this on iPhone, and see what we get.\n我们试着在 iPhone 上运行，看看是什么样\n\n744\n00:38:45,991 --> 00:38:48,525\nAll right, here's our thing. We got it here. Let's try\n好的，我们的模拟器在这里\n\n745\n00:38:48,527 --> 00:38:53,496\nhappy. All right, we're happy! Actually, now we're not so\n让我们尝试点击 happy，对的 happy\n \n746\n00:38:53,498 --> 00:38:57,100\nhappy because we're stuck. Okay, there's no way for\n事实上，我们没有很开心，因为我们卡住了\n\n747\n00:38:57,102 --> 00:39:00,437\nme to get back to choosing something else. Okay, I could\n我没有办法返回去选择其他东西\n\n748\n00:39:00,439 --> 00:39:04,274\ntry rotating. No. I can try sliding out from the left.\n我尝试着旋转，不行，我从左边滑动\n\n749\n00:39:04,276 --> 00:39:09,579\nNope, no. OK, split view does not split on an iPhone.\n也不行，splitViewController 在 iPhone 上是不能分开的\n\n750\n00:39:09,581 --> 00:39:11,715\nOnly on the iPhone 6 Plus, which is\n只有在 iPhone 6 Plus 上可以运行\n\n751\n00:39:11,717 --> 00:39:13,550\nthe only one big enough to really do it,\niPhone 6 Plus 是唯一一个够大的机型来展示 splitViewController\n\n752\n00:39:13,552 --> 00:39:16,419\nokay? So we're stuck here. So this UI that we have in our\n所以，我们卡住了，在故事板中这套 UI 不能正常的运行在\n\n753\n00:39:16,421 --> 00:39:19,122\nstoryboard is no good for iPhone, okay? Now we can still\niPhone里，我们现在仅仅可以\n\n754\n00:39:19,124 --> 00:39:21,491\nmake our guy blink, okay? But that's all we can do.\n设置小人眨眼，但是我们只能做着一件事\n\n755\n00:39:21,493 --> 00:39:24,060\nSo unless we're happy just watching him blink all day\n除非我们看着他光眨眼就满意了\n\n756\n00:39:24,062 --> 00:39:27,130\nwe need to fix this. So how are we gonna make this work on\n我们需要解决这个问题，怎么让这个功能在\n\n757\n00:39:27,132 --> 00:39:30,800\niPhone? Okay. First we have to ask ourselves what would be\niPhone上也能正确运行呢？首先，我们需要思考\n\n758\n00:39:30,802 --> 00:39:32,902\nan appropriate UI on iPhone. Okay,\n在 iPhone 上的合适 UI\n\n759\n00:39:32,904 --> 00:39:35,538\nand this is where navigation controller comes in.\n这里就需要用到 navigationController 了\n760\n00:39:35,540 --> 00:39:37,507\nNavigation controller would be great here because\nNavigationController 用在这里会很合适\n\n761\n00:39:37,509 --> 00:39:40,777\nyou start the stack of cards with the angry mischievous\n现在有一叠代表生气、淘气、担心的视图\n\n762\n00:39:40,779 --> 00:39:44,814\nworried MVC. And then when you click the face it puts\n当你另外点击了一个 face ，它将\n\n763\n00:39:44,816 --> 00:39:47,217\na new card on top which is the face. And then if\n一个新的视图放在这个 face 之上\n\n764\n00:39:47,219 --> 00:39:49,786\nyou want a different one you just hit back, throw that card\n然后，如果你想换一个表情，你只需返回\n\n765\n00:39:49,788 --> 00:39:52,756\naway, and you are back to the angry mischievous worry choice\n将之前的 face 扔掉，你就回到之前选择表情的视图了\n\n766\n00:39:52,758 --> 00:39:54,557\nagain, right? Okay, so it's perfect, okay,\n对吗？这样很好\n\n767\n00:39:54,559 --> 00:39:57,193\nnavigation controller would be a perfect UI. So we need to\nnavigationController 是一个完美的 UI 控件\n\n768\n00:39:57,195 --> 00:40:00,830\nput navigation controller into our story board, okay. So\n所以我们需要将 navigationController 放进故事板中\n\n769\n00:40:00,832 --> 00:40:05,301\nlet's do that. Let's go back to our story board over here.\n我们回到故事板\n\n770\n00:40:05,704 --> 00:40:06,703\nThere's a lot of space here.\n把编辑空间弄大一点\n\n771\n00:40:06,705 --> 00:40:10,740\nSo where I'm gonna put this navigation controller? Well,\n我应该把 navigationController 放哪儿呢？\n\n772\n00:40:10,742 --> 00:40:15,278\nyou really need one navigation controller around the root.\n我们确实应该一个根控制器外放置一个 navigationController\n\n773\n00:40:15,280 --> 00:40:18,314\nView controller. The base card, cards at the bottom.\n这是最底下的 controller，在一叠 controller 下面\n\n774\n00:40:18,316 --> 00:40:21,251\nOkay? So I can put a navigation controller here in\n我可以像放置其他控件那样，从这里取出控件，然后放置\n\n775\n00:40:21,253 --> 00:40:24,154\nthe same way I put these other things by going down here. You\n我可以这么放置 navigationController\n\n776\n00:40:24,156 --> 00:40:26,723\ncan see there's a navigation controller right here.\n你可以看到，这个就是 navigationController\n\n777\n00:40:26,725 --> 00:40:28,758\nI could drag it out. I could control, drag,\n我可以把他拖出来，按住 control，然后 drag\n\n778\n00:40:28,760 --> 00:40:32,429\netc. There's actually a cooler way to do it, which is select\n确实还有更酷的方法来做这件事\n\n779\n00:40:32,431 --> 00:40:36,232\nyour route MVC which is this guy. That's the card that's\n先选中根控制器，就是这个\n\n780\n00:40:36,234 --> 00:40:39,068\nat the bottom of the stack and go up to editor and\n这个就是一叠视图中最下面的那个\n\n781\n00:40:39,070 --> 00:40:42,205\njust like you did in bed and stack view, do embed and\n然后选中 editor，就像把控件放进 stackView 中一样选中 embed in\n\n782\n00:40:42,207 --> 00:40:44,073\nnegotiation controller. You can also do it for\n然后选择 navigationController，你也可以通过这种方式\n\n783\n00:40:44,075 --> 00:40:47,210\ntab bar by the way, but do a navigation controller.\n来添加 Tab Bar Controller，我们先选择 navigationController\n\n784\n00:40:47,212 --> 00:40:51,381\nNow watch what happens here, boom! You put this\n看看发生了什么，boom！\n\n785\n00:40:51,616 --> 00:40:55,318\ninside a navigation control automatically wired it up.\n这个控制器自动封装进了 navigationController\n\n786\n00:40:55,320 --> 00:40:58,855\nNow whats kind of interesting about this is, it also made\n特别有趣的是，它会自动将\n\n787\n00:40:58,857 --> 00:41:01,491\nthat navigation controller be the master of the split view.\nnavigationController 变为 splitView 中的 master\n\n788\n00:41:01,493 --> 00:41:03,927\nIn other words, it kind of wrapped the navigation\n换句话说，它将根控制器包裹进 navigationController\n\n789\n00:41:03,929 --> 00:41:07,163\ncontroller around the root con, the root view controller\n而根控制器还保留了\n\n790\n00:41:07,165 --> 00:41:09,866\nand kept that pointer to the master. So\n之前作为 master 的指针\n\n791\n00:41:09,868 --> 00:41:14,204\nnow the master is actually a navigation controller,\n所以，master 实际上就是一个 navigationController\n792\n00:41:14,206 --> 00:41:17,974\nwith this as it's root view controller. Still all these\n这个控制器作为根控制器\n\n793\n00:41:17,976 --> 00:41:20,643\nsegways are still here. Okay, these segues are still,\n而且还保留着这些 segues\n\n794\n00:41:20,645 --> 00:41:23,079\nthey didn't it didn't undo any of these segues. And\n这些 segues 并没有被撤销\n\n795\n00:41:23,081 --> 00:41:28,485\nthis is still the detail of the split-view controller.\n这个控制器还是原来split-view controller 中的 detail\n\n796\n00:41:28,687 --> 00:41:29,018\n>> How did I put it in there?\n\n797\n00:41:29,020 --> 00:41:31,087\nI selected this, which is my root-view-controller,\n我选中根控制器\n\n798\n00:41:31,089 --> 00:41:36,159\nand I went to editor, embed in, navigation controller.\n然后选择 editor -> embed in -> navigationController\n\n799\n00:41:36,161 --> 00:41:40,663\nOkay? So, now this is an interesting set up right here.\n做这些挺有意思的\n\n800\n00:41:40,665 --> 00:41:43,099\nLet's see if just fixed it, maybe it will just work.\n现在，看看刚刚做的有没有起作用\n\n801\n00:41:43,101 --> 00:41:44,000\nBecause, you know, I hear,\n因为，你知道的\n\n802\n00:41:44,002 --> 00:41:46,769\nI got this, in a navigational controller, right now, so\n我刚刚得到了一个 navigationController\n803\n00:41:46,771 --> 00:41:47,904\nit should just work on a iPhone, right?\n他会不会只在 iPhone 中生效呢？\n\n804\n00:41:47,906 --> 00:41:53,743\nLet's try it. How many people think this going to work?\n有多少人认为会起作用？\n\n805\n00:41:53,745 --> 00:41:56,246\nRaise your hand if you think this is going to work.\n如果你觉得会起作用，请举起手\n\n806\n00:41:56,248 --> 00:42:01,150\nNobody thinks it's gonna work. It is going to work! Gotcha.\n没有人觉得这会起作用吗，事实上，会起作用的！\n\n807\n00:42:01,152 --> 00:42:03,186\nOkay. So here I am in my navigation controller.\n现在我看到的是 navigationController\n\n808\n00:42:03,188 --> 00:42:06,489\nI'm going to go back. Here is my stuff. Let us try worried.\n点击返回，这是选择表情的，点击担心的\n\n809\n00:42:06,491 --> 00:42:09,492\nHe looks worried. I am not worried though cuz I know it\n确实看起来很担心，我倒不会再担心了\n\n810\n00:42:09,494 --> 00:42:14,364\nis going to work. Okay so this worked fine, exactly what\n因为我知道这起作用了\n\n811\n00:42:14,366 --> 00:42:18,001\nwe want on iPhone. Now my question to you is,\niPhone 上运行良好，我的问题来了\n\n812\n00:42:18,003 --> 00:42:21,604\nis this still going to work on iPad? Okay.\n在 iPad 上会起作用吗？\n\n813\n00:42:21,606 --> 00:42:25,308\nLet's go look at that. Let's go back to iPad.\n我们来看看在 iPad 上\n\n814\n00:42:25,310 --> 00:42:28,344\nHow many people think it's going to work on iPad still.\n有多少人觉得在 iPad 上也会同样起作用呢？\n\n815\n00:42:28,346 --> 00:42:31,848\nOne. Two. Three. You guys are getting smart. Yes.\n一，二，三，你们变聪明啦\n\n816\n00:42:31,850 --> 00:42:33,082\nIt's still going to work on iPad.\n是的！在 iPad 上也会起作用\n\n817\n00:42:33,084 --> 00:42:36,419\nOkay. It's pretty cool the way they made this work so you can\n只在一个故事板中构建页面，但是能运行在\n\n818\n00:42:36,421 --> 00:42:39,789\nbuild one storyboard that'll work fine on both platforms.\n不同的平台上，确实是一件很酷的事情\n\n819\n00:42:39,791 --> 00:42:43,626\nSo here we go, this is iPad, we can turn it around,\n现在，这是 iPad，转过来\n\n820\n00:42:43,628 --> 00:42:46,329\nhere it is, it is in a navigation controller,\n页面在一个 navigationController 中\n\n821\n00:42:46,331 --> 00:42:48,264\nyou see? Which is actually kind of nice, cuz I can put\n你们看到了没？这样确实很好\n\n822\n00:42:48,266 --> 00:42:53,403\na nice title in here for this MBC, okay. But when I click in\n因为我可以在这上面写一个标题\n\n823\n00:42:53,405 --> 00:42:57,307\nhere, it's not going to slide a deck onto the deck of cards,\n当我点击时，这个视图并不会侧滑出视线\n\n824\n00:42:57,309 --> 00:43:00,743\nit's going to do the show detail, right, angry, happy,\n它会正确显示 detail ，生气的、高兴的\n\n825\n00:43:00,745 --> 00:43:05,381\nworried, mischievous. Okay? Everyone got that,\n担心的、淘气的，对吗？大家明白\n\n826\n00:43:05,383 --> 00:43:08,651\nhow we do that? Now this kind of structure,\n我们怎么做了吗?这是一种结构\n\n827\n00:43:08,653 --> 00:43:12,221\nwe have split view, navigation controller, and\n我们先有 splitViewController, navigationController\n\n828\n00:43:12,223 --> 00:43:14,357\nthen the content for your master, and\n然后是 master 的内容\n\n829\n00:43:14,359 --> 00:43:16,826\nthen the detail right here. Very common to build this,\n然后是 detail 的内容，这是通常的做法\n\n830\n00:43:16,828 --> 00:43:18,928\nbecause if you're building an app that works on both,\n因为，如果你在做一个app，这是常规的做法\n\n831\n00:43:18,930 --> 00:43:22,298\nthis is what it's gonna look like basically. All right,\n这是非常基本的操作\n\n832\n00:43:22,300 --> 00:43:22,498\nso I'm gonna show you one\n现在，我要向你展示\n\n833\n00:43:22,500 --> 00:43:26,402\nlast thing here of interest, which is these titles, okay.\n这里最后一个有趣的点，就是标题\n\n834\n00:43:26,404 --> 00:43:31,874\nSo we have this little space for a title up here, so\n我们这里给标题留了一个小空间\n\n835\n00:43:31,876 --> 00:43:35,445\nI'd like to put a title here, okay. And how do I put a title\n我要在这儿放置标题，我怎么在这儿放标题呢？\n\n836\n00:43:35,447 --> 00:43:37,647\nup here? Again, remember that's object oriented, okay.\n记住，这一切都是面向对象的\n\n837\n00:43:37,649 --> 00:43:41,250\nThat title comes from whatever MVC happens to be showing in\n这些标题会在 navigationController \n\n838\n00:43:41,252 --> 00:43:43,019\nthis navigation controller at the time. So\n展现MVC 的时候出现\n\n839\n00:43:43,021 --> 00:43:46,289\nI go to the storyboard, to that MVC, which is this one,\n我打开故事板，选择这个 MVC\n\n840\n00:43:46,291 --> 00:43:48,591\nand could just double click on it, okay? So\n双击一下，对吗？\n\n841\n00:43:48,593 --> 00:43:53,296\nwe'll call this one Emotions, okay. So now if I run,\n标题叫做 Emotions ，如果我运行下\n\n842\n00:43:57,535 --> 00:43:58,368\nI get a nice title up here,\n我得到一个很好地标题 Emotions\n\n843\n00:43:58,370 --> 00:44:03,840\nEmotions. What if I wanted a title over here? Okay,\n如果这里也想有个标题呢？\n\n844\n00:44:03,842 --> 00:44:07,844\nhow would I do it if I wanted a title over here?\n如果这个位置也想有标题，我应该怎么做呢？\n\n845\n00:44:08,079 --> 00:44:09,512\nWell if you look on the iPhone,\n你看在 iPhone 中\n\n846\n00:44:09,514 --> 00:44:13,650\nokay if we go back and oops, run this on iPhone.\n返回，要运行在 iPhone中\n\n847\n00:44:14,853 --> 00:44:19,122\nSince both MVCs are in that navigation controller,\n因为这些 MVC 都在navigation controller\n\n848\n00:44:19,124 --> 00:44:24,727\nthey both have titles Okay, so if I go here, here's emotions,\n所以他们都有标题，这里有标题emotions\n\n849\n00:44:24,729 --> 00:44:28,865\nangry. Look, there's room for a title up here. But\n这里也有标题\n\n850\n00:44:28,867 --> 00:44:34,170\nback on the iPad, that's not the case because the detail,\n但是，回到 iPad 上，这里就没有标题了\n\n851\n00:44:34,172 --> 00:44:37,573\nwhen you replace the detail it doesn't actually put it\n因为，在 iPad上，当你换到 detail 页面时\n\n852\n00:44:37,575 --> 00:44:40,543\ninside the same navigation controller that the master is\ndetail 并没有被包裹进 master 在的那个 navigationController\n\n853\n00:44:40,545 --> 00:44:44,247\nin. So the master is in a navigation controller, but\n所以，master 在 navigationController 中\n\n854\n00:44:44,249 --> 00:44:47,417\nthis is not. So if we wanted a title here,\n而 detail 并不在，所以如果我们想要设置标题\n\n855\n00:44:47,419 --> 00:44:49,752\nwe have to put this guy in a navigation controller.\n我们就需要把 detail 放进 navigationController里\n\n856\n00:44:49,754 --> 00:44:52,488\nEven though we're not going to use the navigation controller\n如果我们就是想用 navigationController 来展示个标题\n\n857\n00:44:52,490 --> 00:44:55,858\nfor anything except for the title on the split view case.\n并不做其他事情，在 splitViewController 里\n\n858\n00:44:55,860 --> 00:44:56,392\nWe would still have to do it.\n我们还得用 navigationController 来做\n\n859\n00:44:56,394 --> 00:45:01,264\nAnd in fact, iOS makes it so that just works, okay?\n事实上， iOS 就是这么设计的\n\n860\n00:45:01,266 --> 00:45:04,634\nSo I'm going to go here. Down to this guy. Okay and\n所以，点击这个 controller\n\n861\n00:45:04,636 --> 00:45:09,706\nI'm going to embed him in a navigation controller okay.\n把他包裹进一个 navigationController\n\n862\n00:45:09,708 --> 00:45:12,475\nSo just have this, I have the face selected,\n就这么做，点击一个表情\n\n863\n00:45:12,477 --> 00:45:17,280\nembed puts him in there, okay. Now this\n把他放进了一个 navigationController 里\n\n864\n00:45:17,282 --> 00:45:20,116\nalmost is going to work, okay, if we look at what this looks\n如果我们运行看看这样设置是什么样的\n\n865\n00:45:20,118 --> 00:45:23,119\nlike. Okay? There's a little bit of an issue here because\n可能是运行正常，可能有一些问题\n\n866\n00:45:23,121 --> 00:45:26,889\nthese segues are now going to this navigation controller.\n因为这些 segues 现在开始指向 navigationController\n\n867\n00:45:26,891 --> 00:45:32,028\nBut let's take a look at what it looks like anyway. Okay,\n我们还是看一下到底运行的怎么样吧\n\n868\n00:45:32,030 --> 00:45:34,363\non iPad look, they're both in navigation controller.\n在 iPad 上，确实都在 navigation controller 里\n\n869\n00:45:34,365 --> 00:45:37,633\nSo I've room for a title here now, okay? And if I click,\n我挪点空间来看看\n\n870\n00:45:37,635 --> 00:45:41,838\nit doesn't work anymore. Okay, so I broke it by putting this\n如果我点击了，这个表情并没有真正展现\n\n871\n00:45:41,840 --> 00:45:44,941\nin a navigation controller. Now why, and by the way,\n当我把它放置在 navigation controller 里了，反而破坏了这个表情\n\n872\n00:45:44,943 --> 00:45:47,944\ndoes it work on iPhone? Yes, still works on iPhone. So\n顺便看一下，在 iPhone 中正常吗？看起来很正常\n\n873\n00:45:47,946 --> 00:45:51,647\nit did not break it on iPhone because iOS is smart\n它没有破坏在 iPhone 上的显示，因为 iOS系统够聪明\n\n874\n00:45:51,649 --> 00:45:54,951\nenough to know this is already in a navigation controller, so\n它知道这个控制器已经在 navigation controller 里了\n\n875\n00:45:54,953 --> 00:45:57,453\nI'm just gonna ignore this navigation controller and\n所以在展示它时，会忽略它自己的那个 navigation controller了\n\n876\n00:45:57,455 --> 00:46:01,691\nput this in here. See? So this looks the same, no change,\n看到了吗？这看起来没啥不一样的\n\n877\n00:46:01,693 --> 00:46:02,825\nstill in a navigation controller.\n仍然在 navigation controller 中\n\n878\n00:46:02,827 --> 00:46:05,361\niOS didn't put a navigation controller inside a navigation\niOS 不会将一个 navigation controller 放在另一个 navigation controller 里\n\n879\n00:46:05,363 --> 00:46:08,498\ncontroller, in fact iOS never puts a navigation controller\n事实上，iOS 永远都不会将一个 navigation controller\n\n880\n00:46:08,500 --> 00:46:10,299\ninside another one. Okay, if it sees and\n放在另一个 navigation controller 里\n\n881\n00:46:10,301 --> 00:46:12,235\nencounters another one, it just ignores that one,\n如果它发现它包裹在另一个 navigation controller 里，它会自动忽略它\n\n882\n00:46:12,237 --> 00:46:14,170\nokay. It's like you're either in one or you're not,\n你可以把它放进一个 navigation controller 之中或者不放\n\n883\n00:46:14,172 --> 00:46:15,972\nyou can't be in two at the same time. So\n但是你不能同时包裹两个 navigation controller\n\n884\n00:46:15,974 --> 00:46:20,042\nit worked great on the iPhone. So why did it break though?\n所以，在 iPhone 中运行良好，但是，为什么崩溃了呢？\n\n885\n00:46:20,044 --> 00:46:22,145\nSorry, it worked great visually but it still,\n它看起来运行良好，但是\n\n886\n00:46:22,147 --> 00:46:24,413\nI didn't show it there but it didn't work to click.\n在点击时，运行的并不良好\n\n887\n00:46:24,415 --> 00:46:26,549\nOkay, just like in the iPad it didn't work to click. And\n跟在 iPad 里一样，点击后效果不对\n888\n00:46:26,551 --> 00:46:30,019\nwhy didn't it work to click? Well, we have to understand or\n为什么点击的效果不对呢，这里我们必须了解或者\n\n889\n00:46:30,021 --> 00:46:32,955\nprepare a little bit better there, okay?\n准备了这点知识\n\n890\n00:46:32,957 --> 00:46:35,525\nAnd in fact, let's take the time to do this.\n事实上，会耗费我们一点时间来说明这个问题\n\n891\n00:46:35,527 --> 00:46:37,160\nI'm gonna go in the debugger and show you this.\n我将在 debugger 模式下说明这个问题\n\n892\n00:46:37,162 --> 00:46:40,797\nSo I'm gonna set a break point right here, okay?\n我需要在这里打个断点\n\n893\n00:46:40,799 --> 00:46:43,199\nIn prepareForSegue because prepareForSegue is not\n在 prepareForSegue 这个方法里打断点\n\n894\n00:46:43,201 --> 00:46:48,204\nproperly preparing that thing. So let's see why it's failing.\n因为它没有很好地为这个 segue 做准备，我们来看看为什么失败了\n\n895\n00:46:53,044 --> 00:46:56,712\nAll right, so here we go. I'm going to hit happy. And\n我们准备好了，运行，点击 happy\n\n896\n00:46:56,714 --> 00:46:59,015\nit's going to break, okay, at this prepare.\n到断点这里了，在 prepareForSegue 里面\n\n897\n00:46:59,017 --> 00:47:02,285\nSo it's trying to prepare that thing to be happy. And\n所以，它准备为展示 happy 做一些事\n\n898\n00:47:02,287 --> 00:47:06,022\nwhat is, let's look at this destination VC right here.\n在这里看看 destinationVC\n\n899\n00:47:06,024 --> 00:47:11,794\nLook what its type is. It's a UN navigation controller.\n看看它的类型是什么，这是个 UINavigationController\n\n900\n00:47:11,796 --> 00:47:13,896\nAnd that kind of makes sense, right?\n这说明了一些问题，是吗？\n\n901\n00:47:13,898 --> 00:47:15,531\nBecause if you look at our storyboard,\n因为在 storyboard 中\n\n902\n00:47:15,533 --> 00:47:19,669\nthese segues are going down to this navigation controller.\n这些 segue 指向这些 navigation controller了\n\n903\n00:47:19,671 --> 00:47:21,938\nOkay? So that's just a little bit of a twist.\n所以这看起来有点纠结\n\n904\n00:47:21,940 --> 00:47:25,741\nA little bit tricky. And all we have to do is look at this\n有点复杂，我们需要判断这个 destinationvc\n\n905\n00:47:25,743 --> 00:47:28,811\ndestination VC and if it's a navigation controller,\n如果他是一个 navigation controller\n\n906\n00:47:28,813 --> 00:47:32,381\nthen let's get moving inside of it. Okay. And\n我们需要获得它里面包裹的东西\n\n907\n00:47:32,383 --> 00:47:36,519\nwork on that. Okay. So I'm just going to say here,\n让我们这样做吧，我得在这里说明\n\n908\n00:47:36,521 --> 00:47:39,755\nif I can let Navcon, which is a local variable,\n写一个局部变量，navcon \n\n909\n00:47:39,757 --> 00:47:44,393\nequal the destination VC as a UI navigation controller. So,\n如果将 destinationvc 作为一个 UINavigationController 赋值给 navcon\n\n910\n00:47:44,395 --> 00:47:49,165\nif the destination happens to be UINavigationController,\n如果 destinationvc 确实就是一个 UINavigationController\n\n911\n00:47:49,167 --> 00:47:54,270\nthen I'm gonna let I'm just gonna set the destination VC\n我将这个 destinationvc 等于这个\n\n912\n00:47:54,272 --> 00:47:58,307\nequal to the navcon.visibleViewController.\nnavcon 的 visibleViewController\n\n913\n00:47:58,309 --> 00:47:59,942\nWhich is optional, so I'm gonna,\n这是一个可选值，我打算\n\n914\n00:47:59,944 --> 00:48:01,277\nactually I won't even unwrap it.\n事实上，我不是要将它解包\n\n915\n00:48:01,279 --> 00:48:03,479\nI'm gonna say if it's visible view control and\n而是，如果它就是一个 visibleViewController\n\n916\n00:48:03,481 --> 00:48:06,048\nif the navigation control doesn't have a visible view\n或者这个 navigationController 没有 visibleViewController\n\n917\n00:48:06,050 --> 00:48:09,252\ncontrol then we'll just leave it to be the destination view\n它会直接赋值为自身\n\n918\n00:48:09,254 --> 00:48:13,823\ncontroller. This'll have to be bar. Okay? So\n这样做更保险，是吗？\n\n919\n00:48:13,825 --> 00:48:16,959\nhere all I'm doing is, I'm just saying if I'm preparing\n我要写的就是这些，如果在准备这个 segue 时\n\n920\n00:48:16,961 --> 00:48:19,695\nto segue to something and it's a navigation controller,\n它是一个 navigationController\n\n921\n00:48:19,697 --> 00:48:22,365\nthen instead look inside the navigation controller and\n我会获取到 navigationController 里面的东西\n\n922\n00:48:22,367 --> 00:48:26,135\nsegue to that instead. Okay? Prepare that instead. Okay?\nsegue 会指向里面的 controller ，为展示这个做准备，是吗？\n\n923\n00:48:26,137 --> 00:48:29,038\nEveryone understand what I'm doing there with these, this\n大家都明白我在这里写了什么吗？\n\n924\n00:48:29,040 --> 00:48:37,647\nlittle Three lines of code? >> [INAUDIBLE]\n明白我写的这三行代码吗？\n\n925\n00:48:37,649 --> 00:48:38,447\n>> Yes, so you're\n对，你说\n\n926\n00:48:38,449 --> 00:48:39,048\nsaying, could I go\n我能不能\n\n927\n00:48:39,050 --> 00:48:40,049\nback here in the storyboard and\n在 storyboard 做我刚刚写下的操作\n\n928\n00:48:40,051 --> 00:48:43,452\nhave all these segue things go down over this way instead?\n将这些 segue 直接指向展示的 controller？\n\n929\n00:48:43,454 --> 00:48:44,086\nYou wouldn't actually want that,\n事实上，你不会想这么做的\n\n930\n00:48:44,088 --> 00:48:47,523\nbecause when the segue creates the MVC that it's gonna show,\n因为当 segue 创造的这些 MVC 准备去展示时\n\n931\n00:48:47,525 --> 00:48:49,692\nyou want it to create a navigation controller. So\n你希望他在一个 navigationController 里\n\n932\n00:48:49,694 --> 00:48:51,827\nyou actually want it to go into this navigation.\n所以你希望在一个 navigationController 里看到那个 controller\n\n933\n00:48:51,829 --> 00:48:54,530\nIt's just that, when it comes to preparing it, you don't\n这样当你准备展示它时\n\n934\n00:48:54,532 --> 00:48:56,365\nreally want to prepare the navigation controller,\n你不是想为展示那个 navigationController 做准备\n\n935\n00:48:56,367 --> 00:48:58,567\nyou wanna prepare the thing inside. So\n而是为 navigationController 里面的东西做准备\n\n936\n00:48:58,569 --> 00:49:02,104\nthat's why we're in this code just looking inside\n这就是为什么我们在这些代码里\n\n937\n00:49:02,106 --> 00:49:04,206\nthe navigation controller to make the destination\n将 destinationvc 赋值为 navigationController 里包裹的东西\n\n938\n00:49:04,208 --> 00:49:07,576\nthat we're preparing be the thing inside. Okay?\n我们为里面的东西做准备，对吗？\n\n939\n00:49:07,578 --> 00:49:10,613\nSo little trickiness. You'll often have this little code.\n有一点点难，你会经常写这种代码\n\n940\n00:49:10,615 --> 00:49:12,381\nI'll actually show you later in the quarter kind of\n事实上，一会儿我会用\n\n941\n00:49:12,383 --> 00:49:16,585\na little more sophisticated way to put this in there.\n一个更常用的方法来设置这个\n\n942\n00:49:16,587 --> 00:49:21,824\nYou can put it there with one syntactical element,\n你可以用一个更语义性的元素\n\n943\n00:49:21,826 --> 00:49:25,628\nit's possible, but this I want to leave explicitly so\n但是，我想更明确的设置这个\n\n944\n00:49:25,630 --> 00:49:29,065\nyou understand what's going on here. So now when we run it's\n你也会明白这里做了什么，现在，我们运行一下\n\n945\n00:49:29,067 --> 00:49:32,101\ngoing to work because when we segue to something\n看看是否工作，因为我们在这里将 segue 指向了\n\n946\n00:49:32,103 --> 00:49:35,604\nthat's navigation controls, it can look inside. See, angry,\nnavigationController 里面的东西\n\n947\n00:49:35,606 --> 00:49:39,442\nhappy, worried, mischievous. And the last thing I wanna do\n看看， angry、happy、worried、mischievous 都正确的展示了\n\n948\n00:49:39,444 --> 00:49:43,346\nis set this title right here. Now this title was fixed.\n我需要做的最后一件事就是设置 controller 的标题\n\n949\n00:49:43,348 --> 00:49:45,247\nThis is always the emotions MVC.\n这需要在展示表情的 MVC 里设置标题\n\n950\n00:49:45,249 --> 00:49:49,285\nBut this MVC, its title kinda depends on what it's showing\n但是这个 MVC，它的标题像是需要在展示它的地方来设置\n\n951\n00:49:49,287 --> 00:49:52,054\nhere, doesn't it? Alright like if we are showing angry it\n是这样吗？就像是，如果我们要展示 angry\n952\n00:49:52,056 --> 00:49:53,556\nwould be nice if this title would be angry.\n它的标题就是 angry，这样应该很不错\n\n953\n00:49:53,558 --> 00:49:55,958\nIt would be nice if this title were worried.\n展示 worried 时，它的标题就是 worried\n\n954\n00:49:55,960 --> 00:49:59,662\nOkay? So where can we get the appropriate title here?\n所以，我们得在哪里获得这个对应的标题呢？\n\n955\n00:49:59,664 --> 00:50:02,098\nwe'll we can get it form the button that's asking us\n我们可以从引发 segue 的按钮那里获得标题\n\n956\n00:50:02,100 --> 00:50:05,935\nto segue. Right? If this angry button asks us to segue then\n对吗？如果是这个 angry 按钮让我们来展示表情\n\n957\n00:50:05,937 --> 00:50:10,773\nlet's set this title to be the title of the angry button.\n我们就将标题设置为这个 angry 按钮的标题\n\n958\n00:50:10,775 --> 00:50:15,911\nRight? So, looking back here, in our \"prepareForSegue\".\n对吗？回到 prepareForSegue 这里\n\n959\n00:50:15,913 --> 00:50:20,216\nIs that title of the angry button available to us here?\n我们可以用 angry 按钮的标题吗？\n\n960\n00:50:20,218 --> 00:50:25,087\nWhere? Where can I get it? From \"sender\", yeah, exactly.\n在哪里，在哪里我能获得这个标题呢？ sender！\n\n961\n00:50:25,089 --> 00:50:26,922\nOkay. You guys are getting it. That's really good.\n对的，你们已经明白这一点了，很好\n\n962\n00:50:26,924 --> 00:50:29,859\nSender is the button that's causing the segue to happen.\nSender 就是那个引发 segue 的按钮\n\n963\n00:50:29,861 --> 00:50:32,661\nThat's gonna be the angry button. So, it's any object.\n这应该就是那个 angry 按钮，这可以是任何对象\n\n964\n00:50:32,663 --> 00:50:35,197\nSo I'm gonna have to cast it to be a button. But that's no\n所以，我想让它转型为一个 button，这没什么问题\n\n965\n00:50:35,199 --> 00:50:38,734\nproblem. I'm just gonna say if I can let the sending button\n我要写如果我让 sending button 作为一个 UIButton\n\n966\n00:50:38,736 --> 00:50:41,937\nequal the sender as a UI button, okay? And\n等于 sender，对吗？\n\n967\n00:50:41,939 --> 00:50:45,307\nif not, if I'm segueing from code or something here,\n如果它不能转为一个UIButton，或者我是用代码\n\n968\n00:50:45,309 --> 00:50:45,741\nthen this is not gonna work.\n或者其他方法引发的 segue ，这样就不能正常工作了\n\n969\n00:50:45,743 --> 00:50:48,677\nBut so what. Okay? We just won't get the title we want.\n我们就不能给 Face View Controller\n\n970\n00:50:48,679 --> 00:50:52,748\nOn our Face View Controller. But if it is then I can just\n获取到我们想要的标题，如果能转为 UIButton\n\n971\n00:50:52,750 --> 00:50:58,087\nset the Face View Controllers navigation item. Does everyone\n我可以设置给 Face View Controller 设置它的 navigation item\n\n972\n00:50:58,089 --> 00:51:00,656\nremember what navigation item is? It's kind of just a bundle\n大家都记得 navigation item 吗？他就像一捆东西\n\n973\n00:51:00,658 --> 00:51:04,293\nof things like a little bag of goodies that the navigation\n像是 navigation controller 在展示它里面的 MVC时\n\n974\n00:51:04,295 --> 00:51:08,197\ncontroller looks inside of when that MVC is showing.\nnavigationController 有的一袋东西\n\n975\n00:51:08,199 --> 00:51:13,602\nTo get information like the buttons or the title, okay.\n为了得到这个 button 的属性，比如 title\n\n976\n00:51:13,604 --> 00:51:19,208\nEquals the sending button's current title,\n等于这个触发 button 的当前标题\n\n977\n00:51:19,210 --> 00:51:22,912\nokay. So this little bag of goodies, navigation item,\n我们在文档中看一下\n\n978\n00:51:22,914 --> 00:51:25,281\nhere let's look at it in the documentation, okay.\n这一袋 navigationItem 里的东西\n\n979\n00:51:25,283 --> 00:51:28,250\nI'm going to go here. The I View Controller,\n我要打开这个，这是 ViewController\n\n980\n00:51:28,252 --> 00:51:29,218\nit's like a navigation item.\n这是那些 navigationItem\n\n981\n00:51:29,220 --> 00:51:31,754\nYou can see it house things like the title to show\n你可以在目录里看到 title\n\n982\n00:51:31,756 --> 00:51:35,891\nwhen this MVC is showing in the navigation controller.\n当 MVC 在 navigationController 中展示时\n\n983\n00:51:35,893 --> 00:51:39,962\nBack bar button item to use instead of the default one.\nBack bar button item 就是默认的\n984\n00:51:39,964 --> 00:51:42,765\nLeft bar button items and right bar button items.\nLeft bar button item 和 right bar button item\n\n985\n00:51:42,767 --> 00:51:45,101\nYou can put you know things on the top, left and right.\n你可以将你获得的东西放在上面，左面或者右面\n\n986\n00:51:45,103 --> 00:51:46,902\nThat's what's in this little bag of goodies. And\n这就是这一袋东西里面的\n\n987\n00:51:46,904 --> 00:51:50,172\nthis bag of goodie is only looked in when you are on top\n这一袋东西只会在\n\n988\n00:51:50,174 --> 00:51:54,110\nthe of a navigation controller stack.\nnavigationController 堆中最上面展示\n\n989\n00:51:54,112 --> 00:51:57,279\nAll right, so let's see if that works.\n好的，让我们看看是否有用\n\n990\n00:52:00,585 --> 00:52:02,384\nAll right, here we go. Let's try angry,\n运行一下，我们来点击 angry\n\n991\n00:52:02,386 --> 00:52:07,022\nthere it is, angry, happy, worried, mischievous. Okay,\n这里的标题有 angry, happy, worried, mischievous\n\n992\n00:52:07,024 --> 00:52:10,626\nand let's make sure that it's working on iPhone.\n让我确认在 iPhone 中是否运行良好\n\n993\n00:52:19,237 --> 00:52:21,837\nAll right, let's go back here. Angry. Yes.\n好的，让我们回到这里，angry\n\n994\n00:52:21,839 --> 00:52:23,539\nLook he even got the title right. Happy.\n看起来我们正确的设置了标题\n\n995\n00:52:23,541 --> 00:52:27,743\nThat's definitely happy. Worried. Okay?\nhappy，这确确实实是 happy，worried\n\n996\n00:52:27,745 --> 00:52:32,381\nAll right, everyone got that? So this is how we can build\n好的，大家都明白了吗？这就是怎样\n\n997\n00:52:32,383 --> 00:52:36,085\nthese nice apps that work on both platforms, okay? They\n做一个 app 可以适配各个平台，对吗？\n \n998\n00:52:36,087 --> 00:52:38,254\nwork in split views. They work in navigation controllers.\n这是在 split view 里的，它们都在 navigationController 里面\n\n999\n00:52:38,256 --> 00:52:41,157\nNow if you were building an iPhone only app, you could do\n如果你只是做一个 iPhone 的 app\n\n1000\n00:52:41,159 --> 00:52:44,460\nthis exact same thing but you wouldn't need the split view.\n你可以不用 splitView 就完成同样的事情\n\n1001\n00:52:44,462 --> 00:52:45,327\nYou could just take this view and\n\n1002\n00:52:45,329 --> 00:52:48,264\nmove your start Your little starting arrow right here.\n\n1003\n00:52:48,266 --> 00:52:50,633\nYou just move right up here to this navigation controller,\n\n1004\n00:52:50,635 --> 00:52:53,402\nand you wouldn't need this navigation controller either,\n\n1005\n00:52:53,404 --> 00:52:57,139\nokay, because you don't have this issue where this whole\n\n1006\n00:52:57,141 --> 00:53:00,176\nthing is in a separate space like it is on iPad and iPhone.\n\n1007\n00:53:00,178 --> 00:53:02,845\nThey'd all be inside the navigation controller.\n\n1008\n00:53:03,347 --> 00:53:07,082\nOkay? Now not surprisingly for you're homework I'm going to\n\n1009\n00:53:07,084 --> 00:53:09,285\nask you to do pretty much exactly this. Okay?\n\n1010\n00:53:09,287 --> 00:53:10,186\nYou're going to have a calculator.\n\n1011\n00:53:10,188 --> 00:53:12,121\nYou're going to have a calculator graph,\n\n1012\n00:53:12,123 --> 00:53:12,221\nhave to write the code for. So you're going to have two MVC's\n\n1013\n00:53:12,223 --> 00:53:14,089\nwhich you're going to\n\n1014\n00:53:14,091 --> 00:53:16,358\nand you're going to have to put it in the situation like\n\n1015\n00:53:16,360 --> 00:53:18,594\nthis that works on both iPad and iPhone. Okay?\n\n1016\n00:53:18,596 --> 00:53:23,899\nAnd now you know how to do it. All right back to the slides.\n\n1017\n00:53:29,273 --> 00:53:31,173\nOkay the View Controller Lifecycle.\n\n1018\n00:53:31,175 --> 00:53:32,641\nSo I've been mentioning this and we delete\n\n1019\n00:53:32,643 --> 00:53:35,311\nthose methods in there for the View Controller Lifecycle. So\n\n1020\n00:53:35,313 --> 00:53:38,547\nnow let's talk about what this View Controller Lifecycle is.\n\n1021\n00:53:38,549 --> 00:53:41,450\nSo View Controller Lifecycle It's really just a set of\n\n1022\n00:53:41,452 --> 00:53:44,620\nmethods that gets sent to your view controller as your\n\n1023\n00:53:44,622 --> 00:53:47,489\nview controller goes through it's lifetime. Okay,\n\n1024\n00:53:47,491 --> 00:53:50,626\nmeaning it's lifetime is it gets created, it does things,\n\n1025\n00:53:50,628 --> 00:53:53,429\nit dies. Okay, and as it goes through that life,\n\n1026\n00:53:53,431 --> 00:53:57,299\nyou get sent these nice messages. Okay? So the start\n\n1027\n00:53:57,301 --> 00:54:03,272\nof the lifecycle is obviously the creation of your MVC. And\n\n1028\n00:54:04,508 --> 00:54:08,744\nMVCs are almost always created out of storyboards I'd say 99%\n\n1029\n00:54:08,746 --> 00:54:11,280\nof the time okay? That's how you've seen us do it and\n\n1030\n00:54:11,282 --> 00:54:13,616\nthat's how it's done, okay? It can be done in code but\n\n1031\n00:54:13,618 --> 00:54:18,120\nI'm not even gonna show you how to do that in this course,\n\n1032\n00:54:18,122 --> 00:54:18,921\nIt's rarely done, okay?\n\n1033\n00:54:18,923 --> 00:54:21,490\nThe great thing about putting in a storyboard is that people\n\n1034\n00:54:21,492 --> 00:54:24,994\nlooking at your code can see what you intend visually,\n\n1035\n00:54:24,996 --> 00:54:25,995\nokay? In terms of your MVC and\n\n1036\n00:54:25,997 --> 00:54:27,963\ntheir layout and their segways to each other. So\n\n1037\n00:54:27,965 --> 00:54:31,467\nthat's why we try to do stuff in the storyboard. So 99% of\n\n1038\n00:54:31,469 --> 00:54:35,337\nthe time these MVCs are being created out of the storyboard.\n\n1039\n00:54:35,339 --> 00:54:38,574\nAfter they're created they go through the following steps,\n\n1040\n00:54:38,576 --> 00:54:41,644\none they get prepared okay,\n\n1041\n00:54:41,646 --> 00:54:44,913\nthey get segwayed too they get prepared so that first.\n\n1042\n00:54:44,915 --> 00:54:48,317\nThen outlet setting happens that's why we had that crusher\n\n1043\n00:54:48,319 --> 00:54:51,086\nbecause outlet setting happens after prepare.\n\n1044\n00:54:51,088 --> 00:54:54,056\nThen they appear and disappear. Okay,\n\n1045\n00:54:54,058 --> 00:54:58,627\nnow this can happen over and over. This thing is gonna\n\n1046\n00:54:58,629 --> 00:55:01,030\nappear on screen, go away, appear on screen, go away. For\n\n1047\n00:55:01,032 --> 00:55:05,734\nexample, when we had the iPad version of our demo here, and\n\n1048\n00:55:05,736 --> 00:55:08,504\nI would pull out the master, and then I would hide it, and\n\n1049\n00:55:08,506 --> 00:55:10,105\nI'd pull out the master, and then I would hide it.\n\n1050\n00:55:10,107 --> 00:55:13,409\nOkay, it was appearing and disappearing. Alright?\n\n1051\n00:55:13,411 --> 00:55:17,179\nThen as this is all happening, geometry changes can happen to\n\n1052\n00:55:17,181 --> 00:55:20,015\nthis thing, mostly due to rotation from\n\n1053\n00:55:20,017 --> 00:55:23,886\nportrait to landscape, changes the geometry. And then,\n\n1054\n00:55:23,888 --> 00:55:26,522\nvery rarely you can get into a low memory situation\n\n1055\n00:55:26,524 --> 00:55:29,358\nwhere your view controller may be asked to participate in\n\n1056\n00:55:29,360 --> 00:55:31,660\nfreeing up some memory, super rare.\n\n1057\n00:55:31,662 --> 00:55:36,065\nAlright So let's talk about all these methods, okay?\n\n1058\n00:55:36,067 --> 00:55:38,567\nAfter instantiation and preparation and\n\n1059\n00:55:38,569 --> 00:55:42,071\noutlet-setting, you get a very important method sent to you\n\n1060\n00:55:42,073 --> 00:55:45,908\ncalled viewDidLoad. Okay Load refers to loading up your\n\n1061\n00:55:45,910 --> 00:55:49,478\noutlets, okay? So viewDidLoad is an awesome place to put\n\n1062\n00:55:49,480 --> 00:55:51,980\ninitialization code in your I view controller.\n\n1063\n00:55:51,982 --> 00:55:57,319\nIt's why you almost never have to override View controller's\n\n1064\n00:55:57,321 --> 00:56:00,856\ninit method. Okay it has a very strange init method.\n\n1065\n00:56:00,858 --> 00:56:02,624\nYou don't even wanna think about it's so weird.\n\n1066\n00:56:02,626 --> 00:56:04,960\nOkay? But luckily you never need to override because you\n\n1067\n00:56:04,962 --> 00:56:08,297\ngot viewDidLoad. Okay? You put all your initialization code\n\n1068\n00:56:08,299 --> 00:56:11,767\nalmost all into viewDidLoad, okay,\n\n1069\n00:56:11,769 --> 00:56:13,469\nit's kind of like your init for view controllers,\n\n1070\n00:56:13,471 --> 00:56:17,039\nit's awesome. And it's great there because you're prepared,\n\n1071\n00:56:17,041 --> 00:56:19,341\nand your outlets are set. So it's like, whoa,\n\n1072\n00:56:19,343 --> 00:56:21,643\nyou are ready to really get initialized, okay, and\n\n1073\n00:56:21,645 --> 00:56:24,146\nof course all your instance variables are initialize,\n\n1074\n00:56:24,148 --> 00:56:27,716\nor you wouldn't exist, okay? One really good thing to do\n\n1075\n00:56:27,718 --> 00:56:32,087\nhere is to update your UI, so you notice we had update UI in\n\n1076\n00:56:32,089 --> 00:56:34,790\nthe outlet setter property observer for\n\n1077\n00:56:34,792 --> 00:56:37,826\nface view, okay? More likely you'd put update UI\n\n1078\n00:56:37,828 --> 00:56:42,464\nin your viewDidLoad, okay. Cuz you know by viewDidLoad,\n\n1079\n00:56:42,466 --> 00:56:44,166\neverything is ready to be updated.\n\n1080\n00:56:44,168 --> 00:56:46,702\nOkay, now you're still gonna want it in your models,\n\n1081\n00:56:46,704 --> 00:56:49,838\ndidSet, because someone might change your model after\n\n1082\n00:56:49,840 --> 00:56:50,672\nyou've been loaded, okay?\n\n1083\n00:56:50,674 --> 00:56:53,642\nBut no one's going to change your outlets after you've been\n\n1084\n00:56:53,644 --> 00:56:56,645\nloaded, your outlets get set up and now you own them, okay?\n\n1085\n00:56:56,647 --> 00:56:59,615\nSo they're, no one's gonna set it to point to something else,\n\n1086\n00:56:59,617 --> 00:57:03,018\nokay? Now one thing to be careful about viewDidLoad,\n\n1087\n00:57:03,020 --> 00:57:06,989\nthough, is geometry, okay? The geometry of your view is\n\n1088\n00:57:06,991 --> 00:57:11,693\nstill probably the square, okay, of your storyboard. So\n\n1089\n00:57:11,695 --> 00:57:14,296\nit's useless to do any calculations in viewDidLoad,\n\n1090\n00:57:14,298 --> 00:57:16,098\nthat have anything to do with your geometry.\n\n1091\n00:57:16,100 --> 00:57:17,566\nIf you're looking at your bounds and trying to make\n\n1092\n00:57:17,568 --> 00:57:20,903\na calculation is a waste of time, because it's a square.\n\n1093\n00:57:20,905 --> 00:57:23,539\nIt's not, it hasn't been updated to the portrait or\n\n1094\n00:57:23,541 --> 00:57:26,008\nlandscape of the device you're running on. Okay,\n\n1095\n00:57:26,010 --> 00:57:28,610\nso this is the one think you don't do in viewDidLoad.\n\n1096\n00:57:28,612 --> 00:57:30,212\nThe other thing I wouldn't do in viewDidLoad is\n\n1097\n00:57:30,214 --> 00:57:33,882\nanything that's going to kick off something expensive, okay?\n\n1098\n00:57:33,884 --> 00:57:36,919\nComputing expensive or network intensive, whatever.\n\n1099\n00:57:36,921 --> 00:57:38,454\nThere's a better place to do that.\n\n1100\n00:57:38,456 --> 00:57:40,656\nThat's because viewDidLoad, kay,\n\n1101\n00:57:40,658 --> 00:57:42,724\nyour view controller got created. There's,\n\n1102\n00:57:42,726 --> 00:57:45,294\nit's not a 100% guarantee it's gonna appear onscreen.\n\n1103\n00:57:45,296 --> 00:57:47,796\nIt might or might not. Depends on what the user touches in\n\n1104\n00:57:47,798 --> 00:57:51,066\nyour UI. So you wouldn't wanna kick off something expensive\n\n1105\n00:57:51,068 --> 00:57:53,702\nuntil you know you're gonna be onscreen. And that brings us\n\n1106\n00:57:53,704 --> 00:57:57,105\nto viewWillAppear, kay? So, viewWillAppear is called right\n\n1107\n00:57:57,107 --> 00:58:00,108\nbefore you get put onscreen. So you are sure when this is\n\n1108\n00:58:00,110 --> 00:58:02,010\ncalled that you're going to be put onscreen.\n\n1109\n00:58:02,012 --> 00:58:04,780\nThis is a great place to start something expensive.\n\n1110\n00:58:04,782 --> 00:58:08,450\nNow you're gonna learn starting next week that iOS\n\n1111\n00:58:08,452 --> 00:58:12,287\napps, you wanna build them multi-threaded, okay?\n\n1112\n00:58:12,289 --> 00:58:14,990\nMulti-threaded means, you're gonna have multiple things\n\n1113\n00:58:14,992 --> 00:58:17,626\ngoing on at the same time in your app. They'll be sharing\n\n1114\n00:58:17,628 --> 00:58:20,596\nthe processor, time sharing the processor basically,\n\n1115\n00:58:20,598 --> 00:58:22,030\nunless you have multi-core I guess,\n\n1116\n00:58:22,032 --> 00:58:25,300\nwhich I guess that's formed is a basically running multiple\n\n1117\n00:58:25,302 --> 00:58:28,370\nthings at the same time. Your UIs gonna be running in one\n\n1118\n00:58:28,372 --> 00:58:30,772\nthread at a very high priority and then other things\n\n1119\n00:58:30,774 --> 00:58:33,542\nlike accessing the network or things that block, things that\n\n1120\n00:58:33,544 --> 00:58:35,677\ntake a long time, we are gonna be running another thread.\n\n1121\n00:58:35,679 --> 00:58:37,579\nAnd we are gonna be running simultaneously,\n\n1122\n00:58:37,581 --> 00:58:40,249\nbecause we never want our UI to be blocked. Okay,\n\n1123\n00:58:40,251 --> 00:58:42,951\nwhen user touches on something it should immediately respond.\n\n1124\n00:58:42,953 --> 00:58:45,354\nI don't care what you're doing. Okay, you don't wanna\n\n1125\n00:58:45,356 --> 00:58:47,589\ntouch on something and it does nothing, because you're out\n\n1126\n00:58:47,591 --> 00:58:49,124\ntrying to fetch something from the network and\n\n1127\n00:58:49,126 --> 00:58:50,726\nthe network is slow. That would be a nightmare,\n\n1128\n00:58:50,728 --> 00:58:52,961\nokay? So viewWillAppear is we would, you\n\n1129\n00:58:52,963 --> 00:58:56,064\nwould fire off another thread to go do something expensive.\n\n1130\n00:58:56,066 --> 00:59:00,702\nkay, now your view is going to instantly appear on\n\n1131\n00:59:00,704 --> 00:59:03,705\nscreen without that data that you tried to get,\n\n1132\n00:59:03,707 --> 00:59:05,173\nor whatever the expensive thing is.\n\n1133\n00:59:05,175 --> 00:59:08,410\nSo you have to learn to program in iOS, so\n\n1134\n00:59:08,412 --> 00:59:09,511\nthat multi-threading works.\n\n1135\n00:59:09,513 --> 00:59:12,648\nAnd mostly that's a matter of putting UIs on the screen\n\n1136\n00:59:12,650 --> 00:59:16,652\nthat might not have all the information yet. Okay,\n\n1137\n00:59:16,654 --> 00:59:19,254\nthey might be fetching some data from the network so they\n\n1138\n00:59:19,256 --> 00:59:23,258\nhave a little spinning wheel or something loading dot,\n\n1139\n00:59:23,260 --> 00:59:25,928\ndot, [LAUGH] dot. Something that tells the user, yeah,\n\n1140\n00:59:25,930 --> 00:59:28,864\nI know you wanna see this data. I'm working on it, but\n\n1141\n00:59:28,866 --> 00:59:30,866\nit has to come on screen instantly, okay?\n\n1142\n00:59:30,868 --> 00:59:33,602\nYou can't block, wait to get you one and then come on.\n\n1143\n00:59:33,604 --> 00:59:36,505\nIt's just, you can't do that, it doesn't work especially\n\n1144\n00:59:36,507 --> 00:59:37,839\niOS. Like the network can be really slow and\n\n1145\n00:59:37,841 --> 00:59:40,809\nit might be stall. All right, cell network can be super\n\n1146\n00:59:40,811 --> 00:59:43,545\nslow, so you can't do that. So the viewWillAppear\n\n1147\n00:59:43,547 --> 00:59:45,447\nis a good place to kick off that kind of stuff.\n\n1148\n00:59:45,449 --> 00:59:49,151\nNow, geometry is more likely to be correct here,\n\n1149\n00:59:49,153 --> 00:59:51,086\nbecause you are just about to come on screen. But,\n\n1150\n00:59:51,088 --> 00:59:53,555\nI still wouldn't put geometry calculations in here.\n\n1151\n00:59:53,557 --> 00:59:54,022\nThere is a better place for\n\n1152\n00:59:54,024 --> 00:59:57,693\nthat as well. There is also a viewDidAppear.\n\n1153\n00:59:57,695 --> 00:59:59,995\nThis gets sent right after you have come on screen.\n\n1154\n00:59:59,997 --> 01:00:01,430\nThis is a good place to do things like start\n\n1155\n01:00:01,432 --> 01:00:04,433\nan animation. Okay, cause now you know you're onscreen,\n\n1156\n01:00:04,435 --> 01:00:06,134\nboom, you can start an animation or something like\n\n1157\n01:00:06,136 --> 01:00:10,205\nthat. Okay, similarly there's viewWillDisappear, okay\n\n1158\n01:00:10,207 --> 01:00:12,975\nusually viewWillDisappear, you're going to undue\n\n1159\n01:00:12,977 --> 01:00:15,544\nthe things you did in view will appear, so here you might\n\n1160\n01:00:15,546 --> 01:00:19,615\nstop your animation. Or stop looking at the gyro, okay,\n\n1161\n01:00:19,617 --> 01:00:21,650\nbecause things, things are going to disappear, so\n\n1162\n01:00:21,652 --> 01:00:25,621\nthere's no point in looking at the gyro anymore And there is\n\n1163\n01:00:25,623 --> 01:00:29,591\nalso a viewDidDisappear. Okay. This is where you might free\n\n1164\n01:00:29,593 --> 01:00:33,495\nup something you fetched from the network in viewWillAppear.\n\n1165\n01:00:33,497 --> 01:00:36,331\nSee how they kind of a mirror each other, the will did\n\n1166\n01:00:36,333 --> 01:00:39,668\nappear and then they will and did disappear. Kinda do and\n\n1167\n01:00:39,670 --> 01:00:43,305\nundo things as it goes on and off, and these appear and\n\n1168\n01:00:43,307 --> 01:00:46,742\ndisappear could be viewDidLoad is only called once.\n\n1169\n01:00:46,744 --> 01:00:50,245\nOkay one time. This could be called repeatedly as your view\n\n1170\n01:00:50,247 --> 01:00:53,081\ncontroller comes on and off screen, appears it disappears,\n\n1171\n01:00:53,083 --> 01:00:56,084\nappears it disappears, so this could be called repeatedly,\n\n1172\n01:00:56,086 --> 01:00:58,086\nokay. So you wouldn't wanna do something in here\n\n1173\n01:00:58,088 --> 01:01:00,022\nlike if you're gonna fire off a fetch on the network\n\n1174\n01:01:00,024 --> 01:01:02,424\nthat's expensive, you wouldn't wanna be doing it over and\n\n1175\n01:01:02,426 --> 01:01:04,760\nover if you already have the information from the last time\n\n1176\n01:01:04,762 --> 01:01:08,497\nit appeared. Kay, so be a little careful about that. So\n\n1177\n01:01:08,499 --> 01:01:10,699\nif the geometry, if you wanna do something based in\n\n1178\n01:01:10,701 --> 01:01:12,668\ngeometry, where do you do that? Well,\n\n1179\n01:01:12,670 --> 01:01:14,269\nthere's lifecycle methods specifically for\n\n1180\n01:01:14,271 --> 01:01:18,006\nthat, viewWillLayoutSubviews and viewDidLayoutSubviews. So\n\n1181\n01:01:18,008 --> 01:01:21,643\nevery time your bounds changes and sometimes when it doesn't\n\n1182\n01:01:21,645 --> 01:01:24,880\nchange, be careful, you'll get these two messages.\n\n1183\n01:01:24,882 --> 01:01:29,051\nViewWillLayoutSubviews and viewDidLayoutSubviews. Yeah.\n\n1184\n01:01:29,053 --> 01:01:33,155\n>> [INAUDIBLE]\n\n1185\n01:01:33,157 --> 01:01:33,755\n>> Great question, so\n\n1186\n01:01:33,757 --> 01:01:37,492\nthe question is, would my bounds change if for example,\n\n1187\n01:01:37,494 --> 01:01:39,528\nI added a navigation bar at the top or\n\n1188\n01:01:39,530 --> 01:01:42,030\nmaybe the tab bar at appeared in the tab bar or\n\n1189\n01:01:42,032 --> 01:01:45,133\nI'm in the split view? And I appeared on the other side,\n\n1190\n01:01:45,135 --> 01:01:48,937\nin other words, can it change due to the environment I'm in?\n\n1191\n01:01:48,939 --> 01:01:49,838\nAnd the answer is, it can,\n\n1192\n01:01:49,840 --> 01:01:52,974\nnow it doesn't usually change with the navigation case,\n\n1193\n01:01:52,976 --> 01:01:55,811\nbecause action that navigation bar is layered on top of\n\n1194\n01:01:55,813 --> 01:01:59,381\nyour view, it's kinda semi see through, if you look. If you\n\n1195\n01:01:59,383 --> 01:02:02,884\ngo look at navigation items,in the navigation bars, they're\n\n1196\n01:02:02,886 --> 01:02:05,887\nactually kind of translucent and the thing is behind it, so\n\n1197\n01:02:05,889 --> 01:02:07,823\nyour bounds actually wouldn't probably change there.\n\n1198\n01:02:07,825 --> 01:02:09,758\nBut they might change if you're put into a tab bar,\n\n1199\n01:02:09,760 --> 01:02:12,627\nbecause that space at the bottom might not overlap.\n\n1200\n01:02:12,629 --> 01:02:15,330\nOkay, but the main time your balance changes when you\n\n1201\n01:02:15,332 --> 01:02:18,667\nrotate, but it can happen other times too.\n\n1202\n01:02:18,669 --> 01:02:21,269\nSo between viewWillLayoutSubviews and\n\n1203\n01:02:21,271 --> 01:02:24,573\nviewDidLayoutSubviews all that auto layout is gonna happen,\n\n1204\n01:02:24,575 --> 01:02:26,074\nthe stuff based on the constraints.\n\n1205\n01:02:26,076 --> 01:02:29,177\nRemember all that blue dash lines and all that stuff?\n\n1206\n01:02:29,179 --> 01:02:29,711\nThat's gonna happen between.\n\n1207\n01:02:29,713 --> 01:02:33,248\nSo you can do stuff before all the blue lines, the autolayout\n\n1208\n01:02:33,250 --> 01:02:35,751\nstuff is happening, or you can do it after, okay?\n\n1209\n01:02:35,753 --> 01:02:37,285\nYou rarely need to do anything here,\n\n1210\n01:02:37,287 --> 01:02:39,087\nbecause usually the constraints are making all\n\n1211\n01:02:39,089 --> 01:02:42,390\nthe decisions about what to do with everything, okay? But\n\n1212\n01:02:42,392 --> 01:02:46,228\nit is possible sometimes, you know, not in assignment three,\n\n1213\n01:02:46,230 --> 01:02:48,830\nmaybe in assignment six in this class. Maybe you might\n\n1214\n01:02:48,832 --> 01:02:52,434\nwanna do something in viewWill or DidLayoutSubviews. But this\n\n1215\n01:02:52,436 --> 01:02:55,737\nis the only place you wanna do anything that's geometry\n\n1216\n01:02:56,206 --> 01:03:00,942\ndependent, okay? Yeah, one thing about these methods,\n\n1217\n01:03:00,944 --> 01:03:02,144\ndon't think that these are only gonna\n\n1218\n01:03:02,146 --> 01:03:04,179\nbe called when you're bound to actually changes.\n\n1219\n01:03:04,181 --> 01:03:07,783\nThe system is allowed to call these any time it wants, and\n\n1220\n01:03:07,785 --> 01:03:10,552\nsometimes it might be drawing something to an offscreen\n\n1221\n01:03:10,554 --> 01:03:12,988\nbuffer to prepare to do an animation and so\n\n1222\n01:03:12,990 --> 01:03:14,756\nit calls this, okay? But, and\n\n1223\n01:03:14,758 --> 01:03:17,425\nthen it actually draws on the screen and calls it again.\n\n1224\n01:03:17,427 --> 01:03:20,061\nAnd the bounds have not actually changed, okay? So\n\n1225\n01:03:20,063 --> 01:03:23,265\ndon't expect that every single time this calls the bounds\n\n1226\n01:03:23,267 --> 01:03:25,834\nwill be different. If you do something really expensive as\n\n1227\n01:03:25,836 --> 01:03:28,436\na result of a bounds change, you might wanna keep track of\n\n1228\n01:03:28,438 --> 01:03:31,406\nwhat the bounds were the last time you did that expensive\n\n1229\n01:03:31,408 --> 01:03:33,141\nthing. And when this gets called,\n\n1230\n01:03:33,143 --> 01:03:36,344\nmake sure the bounds have actually changed, okay?\n\n1231\n01:03:36,346 --> 01:03:37,979\nAgain, you're not gonna need any of this for\n\n1232\n01:03:37,981 --> 01:03:39,247\nassignment three, but it's good to know.\n\n1233\n01:03:39,249 --> 01:03:41,583\nThis can be recalled all the time, repeatedly, over and\n\n1234\n01:03:41,585 --> 01:03:46,021\nover. Even if your bounds have not actually changed. Okay, so\n\n1235\n01:03:46,023 --> 01:03:48,523\nauto rotation. Usually what happens in auto rotation.\n\n1236\n01:03:48,525 --> 01:03:51,693\nWhen auto rotation is when you turn your phone from landscape\n\n1237\n01:03:51,695 --> 01:03:55,230\nto portrait, it automatically changes your bounds to be tall\n\n1238\n01:03:55,232 --> 01:03:58,200\nand skinny. And then wide and short, okay?\n\n1239\n01:03:58,202 --> 01:04:00,435\nSo autorotation is usually just a bounds change, so\n\n1240\n01:04:00,437 --> 01:04:03,538\nyou're just dealing with it in view did layout sub views, or\n\n1241\n01:04:03,540 --> 01:04:05,807\nmore likely, you just have constraints, and\n\n1242\n01:04:05,809 --> 01:04:08,043\nthe constraints just work, okay? So\n\n1243\n01:04:08,045 --> 01:04:10,512\nthere's really nothing to do, but it is possible to\n\n1244\n01:04:10,514 --> 01:04:14,449\nget involved in autorotation, specifically in the animation.\n\n1245\n01:04:14,451 --> 01:04:16,918\nIf you watch an autorotation really, really closely,\n\n1246\n01:04:16,920 --> 01:04:20,155\nyou'll see that the views actually move. They move from\n\n1247\n01:04:20,157 --> 01:04:23,158\ntheir position in portrait to where they are in landscape\n\n1248\n01:04:23,160 --> 01:04:25,427\nin an animated fashion. They don't just jump there,\n\n1249\n01:04:25,429 --> 01:04:29,197\nthey kind of fly across the screen. And you can fly things\n\n1250\n01:04:29,199 --> 01:04:32,200\nacross the screen, too, if you want using this,\n\n1251\n01:04:32,202 --> 01:04:35,837\nlife cycle method called will, viewWillTransitionToSize. And\n\n1252\n01:04:35,839 --> 01:04:38,406\nit's basically telling you, this is going to transition.\n\n1253\n01:04:38,408 --> 01:04:40,175\nIt has this thing called a transition coordinator.\n\n1254\n01:04:40,177 --> 01:04:41,676\nYou can look up the documentation on it. But\n\n1255\n01:04:41,678 --> 01:04:45,714\nthe main thing the transition coordinator has is a closure\n\n1256\n01:04:45,716 --> 01:04:50,185\nthat you can provide that will be executed alongside\n\n1257\n01:04:50,187 --> 01:04:52,520\nthe animation that it's doing to animate your,\n\n1258\n01:04:52,522 --> 01:04:56,391\nyour, rotation, okay? You won't need this in this class,\n\n1259\n01:04:56,393 --> 01:04:58,159\nbut I just wanna let you know this is here. Okay,\n\n1260\n01:04:58,161 --> 01:05:01,863\nin low-memory situations, didReceiveMemoryWarning, okay,\n\n1261\n01:05:01,865 --> 01:05:05,367\nthis is only gonna happen if your app uses a lot of memory,\n\n1262\n01:05:05,369 --> 01:05:08,603\nokay? iPhones today have so much memory,\n\n1263\n01:05:08,605 --> 01:05:08,803\nit's ridiculous, okay?\n\n1264\n01:05:08,805 --> 01:05:11,740\nSo this is not really gonna happen, likely. But if you had\n\n1265\n01:05:11,742 --> 01:05:15,744\na memory leak where you're leaking videos in memory,\n\n1266\n01:05:15,746 --> 01:05:17,479\nor images, huge images, or\n\n1267\n01:05:17,481 --> 01:05:19,915\nsomething like that, it's possible you might get this.\n\n1268\n01:05:19,917 --> 01:05:23,285\nWhen you get this, you should throw out any pointers to big\n\n1269\n01:05:23,287 --> 01:05:27,055\nthings you have in the heap that you can recreate, okay?\n\n1270\n01:05:27,057 --> 01:05:29,124\nSo you can re-download them from the web or\n\n1271\n01:05:29,126 --> 01:05:30,892\nfrom your file system or something.\n\n1272\n01:05:30,894 --> 01:05:34,162\nYou should throw them out when you get this one. Okay,\n\n1273\n01:05:34,164 --> 01:05:35,864\ngoing back to the very beginning of the lifecycle,\n\n1274\n01:05:35,866 --> 01:05:38,800\nthere's another interesting method called awakeFromNib.\n\n1275\n01:05:38,802 --> 01:05:42,103\nOkay, awakeFromNib is sent to you really early before\n\n1276\n01:05:42,105 --> 01:05:45,807\npreparation, before outlet setting, before all that, but\n\n1277\n01:05:45,809 --> 01:05:49,577\nonly if you're coming out of a storyboard. Okay, so it's this\n\n1278\n01:05:49,579 --> 01:05:53,181\nreally, really, really, really early method that gets called.\n\n1279\n01:05:53,183 --> 01:05:56,151\nAnd it actually gets sent to every object that comes out of\n\n1280\n01:05:56,153 --> 01:05:58,253\na storyboard, not just view controllers,\n\n1281\n01:05:58,255 --> 01:06:00,288\nokay? Now I mention it at the end here,\n\n1282\n01:06:00,290 --> 01:06:03,491\nbecause I really don't want you using it that much, okay?\n\n1283\n01:06:03,493 --> 01:06:06,127\nYou're much better off putting things in viewDidLoad,\n\n1284\n01:06:06,129 --> 01:06:08,897\nviewWillAppear, those kind of places than awakeFromNib,\n\n1285\n01:06:08,899 --> 01:06:11,366\nokay? Some people find out about this, and they just put\n\n1286\n01:06:11,368 --> 01:06:13,969\nall of their initialization junk into awakeFromNib, and\n\n1287\n01:06:13,971 --> 01:06:15,270\nit's not really for that. It's for\n\n1288\n01:06:15,272 --> 01:06:16,738\nreally kind of exceptional circumstances,\n\n1289\n01:06:16,740 --> 01:06:19,040\nwhere you really, really early you need to do something for\n\n1290\n01:06:19,042 --> 01:06:22,510\nsome reason, okay? Set, you're gonna need to set yourself\n\n1291\n01:06:22,512 --> 01:06:25,513\nas a controller of some other object that something's\n\n1292\n01:06:25,515 --> 01:06:29,451\nhappening early, whatever. But I just wanna let you know it's\n\n1293\n01:06:29,453 --> 01:06:33,054\nin there. Okay, so here's the summary of the lifecycle.\n\n1294\n01:06:33,056 --> 01:06:35,857\nYou're instantiated, usually from your storyboard.\n\n1295\n01:06:35,859 --> 01:06:37,258\nawakeFromNib is then called.\n\n1296\n01:06:37,260 --> 01:06:39,327\nSegue prep happens if you're being segued to,\n\n1297\n01:06:39,329 --> 01:06:42,130\nwhich you almost always are when MVCs are being created.\n\n1298\n01:06:42,132 --> 01:06:44,666\nIt's because you're being segued to usually. Then\n\n1299\n01:06:44,668 --> 01:06:48,303\nyour outlets get set, okay, the things like display and\n\n1300\n01:06:48,305 --> 01:06:51,873\nthe calculator get set. Then viewDidLoad gets called, and\n\n1301\n01:06:51,875 --> 01:06:54,609\nyou can do a lot of nice initialization here that's not\n\n1302\n01:06:54,611 --> 01:06:57,412\ngeometry related. Then viewWillAppear and, and\n\n1303\n01:06:57,414 --> 01:06:59,247\nDidAppear and then viewWillDisappear and\n\n1304\n01:06:59,249 --> 01:07:02,017\nviewDidDisappear will be sent to you as you appear and\n\n1305\n01:07:02,019 --> 01:07:04,819\ndisappear on screen. Meanwhile, at any time,\n\n1306\n01:07:04,821 --> 01:07:06,221\nwhether you are onscreen or not,\n\n1307\n01:07:06,223 --> 01:07:07,489\nwhether you've appeared or not,\n\n1308\n01:07:07,491 --> 01:07:08,957\nyou can be set viewWillLayoutSubviews and\n\n1309\n01:07:08,959 --> 01:07:11,860\nviewDidLayoutSubviews. Okay, and that's where you're going\n\n1310\n01:07:11,862 --> 01:07:14,429\nto react to geometry changes if nec, if you need to outside\n\n1311\n01:07:14,431 --> 01:07:17,866\nof constraints. Okay, usually constraints will just do it\n\n1312\n01:07:17,868 --> 01:07:19,000\nfor you. And if your memory gets\n\n1313\n01:07:19,002 --> 01:07:21,736\nlow at any time, you could get didReceiveMemoryWarning.\n\n1314\n01:07:21,738 --> 01:07:23,371\nIf you get didReceiveMemoryWarning and\n\n1315\n01:07:23,373 --> 01:07:24,205\nyou don't clean up your memory,\n\n1316\n01:07:24,207 --> 01:07:27,008\nthe system will probably kill you, okay? Just probably\n\n1317\n01:07:27,010 --> 01:07:32,013\nyour app will appear to crash to the user. Okay, so\n\n1318\n01:07:32,015 --> 01:07:34,983\nI have a short demo here for View Controller Lifecycle,\n\n1319\n01:07:34,985 --> 01:07:38,219\nand I'm just gonna throw some print statements into all of\n\n1320\n01:07:38,221 --> 01:07:41,389\nthose Lifecycle methods. Okay, that's all I'm gonna do. And\n\n1321\n01:07:41,391 --> 01:07:44,626\nthen we're gonna run our FaceIt, and we're gonna see,\n\n1322\n01:07:44,628 --> 01:07:47,028\nas view controllers appear and disappear and\n\n1323\n01:07:47,030 --> 01:07:50,165\nget created, what's happening in the Lifecycle,\n\n1324\n01:07:50,167 --> 01:07:52,333\nokay? So that's all this demo is,\n\n1325\n01:07:52,335 --> 01:07:57,305\nit's very brief. Okay, the way that I'm going to,\n\n1326\n01:07:57,307 --> 01:08:02,243\nkind of print in the console is I have this, a little\n\n1327\n01:08:02,245 --> 01:08:06,648\nextension here called, VCL, View Controller Lifecycle,\n\n1328\n01:08:06,650 --> 01:08:10,952\nthen I'm just gonna add to FaceIt, copy it in, and\n\n1329\n01:08:10,954 --> 01:08:14,255\nI will post this, so you can look at it if you want.\n\n1330\n01:08:14,257 --> 01:08:18,426\nBut it's basically, it's just extending these classes to\n\n1331\n01:08:18,428 --> 01:08:20,628\noverride all of these, things. And\n\n1332\n01:08:20,630 --> 01:08:23,898\none thing that's cool is it will show you, the log which\n\n1333\n01:08:23,900 --> 01:08:27,001\ninstance of the Face View Controller, which instance of\n\n1334\n01:08:27,003 --> 01:08:30,038\nthe emotion controller, okay? So, that's kind of fun.\n\n1335\n01:08:30,040 --> 01:08:33,074\nAll right, so let's go ahead and run this, let's do it on,\n\n1336\n01:08:33,076 --> 01:08:37,178\niPhone first. All right, so this thing appeared,\n\n1337\n01:08:37,180 --> 01:08:41,483\nall right, and it's showing the face, okay, this is kind\n\n1338\n01:08:41,485 --> 01:08:43,618\nof like on the iPad, it would be showing the detail here.\n\n1339\n01:08:43,620 --> 01:08:46,221\nIt's showing a face, but we haven't chosen an emotion. And\n\n1340\n01:08:46,223 --> 01:08:48,890\nlet's look over here what happened. Both an Emotions\n\n1341\n01:08:48,892 --> 01:08:52,894\nview controller and a Face view controller have been\n\n1342\n01:08:52,896 --> 01:08:56,431\ncreated and instantiated, okay? Now that's because\n\n1343\n01:08:56,433 --> 01:08:59,734\nthe Emotion view controller is at the bottom of the stack and\n\n1344\n01:08:59,736 --> 01:09:01,302\na Face view controller is on top of it.\n\n1345\n01:09:01,304 --> 01:09:04,272\nSo they're both on the stack, that means they both exist.\n\n1346\n01:09:04,274 --> 01:09:08,409\nHowever, notice that while the Emotions 1 has had viewDidLoad\n\n1347\n01:09:08,411 --> 01:09:10,612\ncalled, because its outlets have all been set and\n\n1348\n01:09:10,614 --> 01:09:12,447\nall that stuff, it has never appeared.\n\n1349\n01:09:12,449 --> 01:09:14,482\nYou see Emotions 1 never gets viewWillAppear,\n\n1350\n01:09:14,484 --> 01:09:17,652\nbecause it never has appeared. We've never seen the angry,\n\n1351\n01:09:17,654 --> 01:09:20,021\nmischievous, that has not appeared on screen. So\n\n1352\n01:09:20,023 --> 01:09:23,224\nit hasn't appeared, whereas the Face 1 has, so\n\n1353\n01:09:23,226 --> 01:09:27,428\nit's gotten viewWillAppear. It got, it laid out, okay,\n\n1354\n01:09:27,430 --> 01:09:29,898\nviewWillLayoutSubviews and DidLayoutSubviews.\n\n1355\n01:09:29,900 --> 01:09:31,666\nAnd then it got viewDidAppear, and sure enough,\n\n1356\n01:09:31,668 --> 01:09:35,904\nhere it is. Now I'm gonna press Back, the Back button,\n\n1357\n01:09:35,906 --> 01:09:39,474\nand let's watch what happens, okay?\n\n1358\n01:09:39,476 --> 01:09:42,010\nFace 1 got viewWillDisappear because of course,\n\n1359\n01:09:42,012 --> 01:09:45,813\nit was gonna disappear. Emotions 1, that's this one,\n\n1360\n01:09:45,815 --> 01:09:49,150\ngot viewWillAppear cuz it's about to appear.\n\n1361\n01:09:49,152 --> 01:09:53,288\nThen Emotions 1 got laid out a couple of times here.\n\n1362\n01:09:53,290 --> 01:09:57,892\nLet's see some more here, there we go. Okay,\n\n1363\n01:09:57,894 --> 01:10:01,329\nso Emotions 1 got laid out a couple of times here,\n\n1364\n01:10:01,331 --> 01:10:04,666\nsee if you will ask at the same exact size. So this\n\n1365\n01:10:04,668 --> 01:10:07,168\nis why I'm saying be careful, that can happen multiple\n\n1366\n01:10:07,170 --> 01:10:10,271\ntimes. Why might that happen? Again, maybe the system was\n\n1367\n01:10:10,273 --> 01:10:12,540\npreparing to animate that thing sliding in, and\n\n1368\n01:10:12,542 --> 01:10:15,577\nso it was drawing off screen, then it was drawing on screen,\n\n1369\n01:10:15,579 --> 01:10:17,445\nand it was laying out both times,\n\n1370\n01:10:17,447 --> 01:10:18,813\nit's called it both times. You don't know why,\n\n1371\n01:10:18,815 --> 01:10:20,615\nyou don't care why. You just have to be prepared for\n\n1372\n01:10:20,617 --> 01:10:23,518\nthe fact that it could call it multiple times. Then Face\n\n1373\n01:10:23,520 --> 01:10:27,388\n1 got viewDidDisappear because the face disappeared,\n\n1374\n01:10:27,390 --> 01:10:31,893\nit slid off. And Emotions 1 got viewDidAppear, because it\n\n1375\n01:10:31,895 --> 01:10:35,897\ngot replaced on top of it. Then notice Emotions 1 got lay\n\n1376\n01:10:35,899 --> 01:10:38,399\nout again. Okay, even though it was already on screen.\n\n1377\n01:10:38,401 --> 01:10:40,068\nWhy, I don't know. Maybe this is the layout for\n\n1378\n01:10:40,070 --> 01:10:43,238\nit actually appearing on screen. It's not clear. Okay,\n\n1379\n01:10:43,240 --> 01:10:45,373\neverybody got that? Now I'm gonna click on one of these,\n\n1380\n01:10:45,375 --> 01:10:48,576\nI'm gonna click on Happy, and let's watch what happens.\n\n1381\n01:10:48,578 --> 01:10:52,747\nOkay, now most important thing to watch here, okay, is that\n\n1382\n01:10:52,749 --> 01:10:57,819\nFace 1, that first face that we showed up is gone, see?\n\n1383\n01:10:57,821 --> 01:11:01,055\nNo more reference to Face 1. It has created a new face,\n\n1384\n01:11:01,057 --> 01:11:03,925\ncame out of the story board. Okay, this is what I'm talking\n\n1385\n01:11:03,927 --> 01:11:06,361\nabout. When you segue, it creates a new NVC.\n\n1386\n01:11:06,363 --> 01:11:10,331\nThat first Face 1 is out of the heap, it is gone, okay?\n\n1387\n01:11:10,333 --> 01:11:14,902\nEvery time you segue, you get a new one. But Emotions, okay?\n\n1388\n01:11:14,904 --> 01:11:18,606\nThe root, it's still Emotions 1, okay?\n\n1389\n01:11:18,608 --> 01:11:21,476\nSince it sits on the root, the base of the card stack,\n\n1390\n01:11:21,478 --> 01:11:25,013\nit never comes off. So, it just sits there forever, okay?\n\n1391\n01:11:25,015 --> 01:11:26,514\nNew cards come on and off, on and off.\n\n1392\n01:11:26,516 --> 01:11:27,815\nBut it's at the root, so it just sits there. So\n\n1393\n01:11:27,817 --> 01:11:32,020\nit's always gonna be Emotions 1, okay? And then, again you\n\n1394\n01:11:32,022 --> 01:11:35,623\ncan see it goes through willDidLoad, viewWillAppear,\n\n1395\n01:11:35,625 --> 01:11:39,494\ngot laid out, Face 2 finally did appear, okay? And notice\n\n1396\n01:11:39,496 --> 01:11:42,597\nthat Emotions 1 did disappear because it got covered up\n\n1397\n01:11:42,599 --> 01:11:44,932\nby this one. Okay, again if we go back and\n\n1398\n01:11:44,934 --> 01:11:47,268\nI click a different one like Mischievous,\n\n1399\n01:11:47,270 --> 01:11:50,938\nnow we have Face 3, okay? Face 2 is gone forever but\n\n1400\n01:11:50,940 --> 01:11:54,108\nstill Emotions 1. Everyone understand that?\n\n1401\n01:11:54,110 --> 01:11:57,812\nOkay, now let's run this on the iPad.\n\n1402\n01:12:06,056 --> 01:12:10,658\nOkay, so here, okay, we're seeing the detail, okay?\n\n1403\n01:12:10,660 --> 01:12:14,329\nNotice here that even though the master does not appear\n\n1404\n01:12:14,331 --> 01:12:17,699\non screen, it gets created. Not only does it get created,\n\n1405\n01:12:17,701 --> 01:12:20,702\nit gets laid out. But it never got viewWillAppear and\n\n1406\n01:12:20,704 --> 01:12:23,671\nviewDidAppear, because the master has never appeared,\n\n1407\n01:12:23,673 --> 01:12:28,843\nokay? Whereas Face 1, it did get appear, and it appeared,\n\n1408\n01:12:28,845 --> 01:12:29,143\nNow watch what happens if I rotate, okay, I'm gonna rotate\n\n1409\n01:12:29,145 --> 01:12:32,980\nright?\n\n1410\n01:12:32,982 --> 01:12:36,250\nto landscape. Okay, now when I rotate to landscape,\n\n1411\n01:12:36,252 --> 01:12:39,554\nall of a sudden the master, Emotions 1, it got that\n\n1412\n01:12:39,556 --> 01:12:41,155\nviewWillTransitionToSize thing.\n\n1413\n01:12:41,157 --> 01:12:45,293\nThat's the auto rotation thing I was telling you about, okay?\n\n1414\n01:12:45,295 --> 01:12:47,195\nAnd Emotions 1 also got laid out and\n\n1415\n01:12:47,197 --> 01:12:51,399\ntold it would appear, and then it did appear, okay? Now Face\n\n1416\n01:12:51,401 --> 01:12:55,603\n1 also got to participate in that rotation. See,\n\n1417\n01:12:55,605 --> 01:12:58,306\nanimatingAlongsideTransition. Okay, and\n\n1418\n01:12:58,308 --> 01:13:02,543\nthen here's Emotion 1 appear. Notice that inside here, okay,\n\n1419\n01:13:02,545 --> 01:13:06,581\nthere's no viewWillAppear or viewWillDisappear for Face 1.\n\n1420\n01:13:06,583 --> 01:13:08,383\nThat's cuz it was already on screen,\n\n1421\n01:13:08,385 --> 01:13:11,085\nokay, so even though its bounds changed, okay, and\n\n1422\n01:13:11,087 --> 01:13:14,856\nit got viewWillLayoutSubviews, it never got viewWillAppear,\n\n1423\n01:13:14,858 --> 01:13:16,924\nit already was on screen. That make sense?\n\n1424\n01:13:16,926 --> 01:13:20,461\nAnd now interesting. I'm gonna click on one of these, and\n\n1425\n01:13:20,463 --> 01:13:25,833\nwhat's gonna happen to Face 1? Out of the heap. Okay,\n\n1426\n01:13:25,835 --> 01:13:31,506\nwatch this. Angry, see Face 1 gone, now we're on Face 2.\n\n1427\n01:13:31,508 --> 01:13:34,108\nSo even in a split view where it seems like,\n\n1428\n01:13:34,110 --> 01:13:36,477\nyou know with the cards, it's really obvious that yeah,\n\n1429\n01:13:36,479 --> 01:13:39,247\nI'm throwing the card away, I'm making a new card. But\n\n1430\n01:13:39,249 --> 01:13:40,615\neven here in a split view,\n\n1431\n01:13:40,617 --> 01:13:41,649\nI'm throwing away the detail,\n\n1432\n01:13:41,651 --> 01:13:44,786\nI'm making a new one. Plopping it right in on top, okay?\n\n1433\n01:13:44,788 --> 01:13:48,756\nSo all of these segues create a new MVC, even if they're\n\n1434\n01:13:48,758 --> 01:13:50,825\na split view navigation controller, whatever.\n\n1435\n01:13:50,827 --> 01:13:54,562\nThe only ones that don't that you've seen is in tab bar. All\n\n1436\n01:13:54,564 --> 01:13:57,565\nthose things in the tab bar. It's too bad I don't really\n\n1437\n01:13:57,567 --> 01:13:59,767\nhave a tab bar, I wanted to show you this VCL thing.\n\n1438\n01:13:59,769 --> 01:14:02,770\nBut those ones get created when you click on the tab for\n\n1439\n01:14:02,772 --> 01:14:05,673\nthe first time and they live forever. Okay,\n\n1440\n01:14:05,675 --> 01:14:07,909\nthey never go away. And when you click on the tab,\n\n1441\n01:14:07,911 --> 01:14:10,411\nit comes back, it's still exactly the same way.\n\n1442\n01:14:10,413 --> 01:14:10,845\nIt's not a segue,\n\n1443\n01:14:10,847 --> 01:14:13,114\nin other words the tab bar is not segueing.\n\n1444\n01:14:13,116 --> 01:14:15,583\nNavigation control and split view are segueing, tab bar,\n\n1445\n01:14:15,585 --> 01:14:22,590\nnotice we never did anything there to do a segue, okay? So,\n\n1446\n01:14:22,592 --> 01:14:26,360\nyeah, notice here also that even though when I clicked on\n\n1447\n01:14:26,362 --> 01:14:29,397\nhere to show this, look what happened to Emotions 1,\n\n1448\n01:14:29,399 --> 01:14:32,266\nit got laid out a couple times even though its size did not\n\n1449\n01:14:32,268 --> 01:14:35,303\nchange. Here I'll do it again. We'll go to happy. Okay,\n\n1450\n01:14:35,305 --> 01:14:38,806\nI didn't change, this did not change size in the least.\n\n1451\n01:14:38,808 --> 01:14:40,942\nOkay, and yet it got viewDidLayoutSubviews,\n\n1452\n01:14:40,944 --> 01:14:44,178\nviewDidLayoutSubview. Okay, so you have to be prepared for\n\n1453\n01:14:44,180 --> 01:14:47,849\nthat being called all the time, okay? And so here is\n\n1454\n01:14:47,851 --> 01:14:51,619\nFace 3, it's getting pulled out of the storyboard. It's\n\n1455\n01:14:51,621 --> 01:14:54,889\nkind of interesting that it gets a viewWillDisappear here.\n\n1456\n01:14:54,891 --> 01:14:55,056\nI'm not sure why it gets that right there. Kind of strange\n\n1457\n01:14:55,058 --> 01:14:59,961\nI've noticed this,\n\n1458\n01:14:59,963 --> 01:15:04,098\nand then it loads, it gets a WillAppear it lays out,\n\n1459\n01:15:04,100 --> 01:15:08,536\nit gets DidDisappear, and then DidAppear. So I, this is\n\n1460\n01:15:08,538 --> 01:15:11,405\nstrange, I don't really understand why it goes through\n\n1461\n01:15:11,407 --> 01:15:15,209\nthat shenanigan right there, but the good news is that\n\n1462\n01:15:15,211 --> 01:15:18,246\nonce viewDidAppear happens, it has appeared so\n\n1463\n01:15:18,248 --> 01:15:21,516\nthat's good. It's just kind of strange, so be prepared for\n\n1464\n01:15:21,518 --> 01:15:23,751\nthat. Now you'll have this code of mine,\n\n1465\n01:15:23,753 --> 01:15:25,553\nthis little logging thing. So\n\n1466\n01:15:25,555 --> 01:15:28,356\nyou can always throw this in your own app, okay, change\n\n1467\n01:15:28,358 --> 01:15:31,192\nthe name to the classes. And then you can see if\n\n1468\n01:15:31,194 --> 01:15:33,995\nsomethings not going the way you expect and the lifecycle\n\n1469\n01:15:33,997 --> 01:15:36,130\nmethod is not getting called at the time you want,\n\n1470\n01:15:36,132 --> 01:15:41,569\nyou can see when it's happening exactly. Okay, all\n\n1471\n01:15:41,571 --> 01:15:45,606\nright, that is it for today. Your assignment is posted.\n\n1472\n01:15:45,608 --> 01:15:47,174\nI already explained what it's gonna be.\n\n1473\n01:15:47,176 --> 01:15:51,812\nIt's due next Wednesday before class. Hopefully you've\n\n1474\n01:15:51,814 --> 01:15:55,416\nfinished up all of the reading for the Swift thing.\n\n1475\n01:15:55,418 --> 01:15:58,052\nAll that Swift reading, you're really gonna want to have that\n\n1476\n01:15:58,054 --> 01:16:00,488\nin your memory bank as the rest of the course happens.\n\n1477\n01:16:00,490 --> 01:16:01,556\nSo if you're a little behind there,\n\n1478\n01:16:01,558 --> 01:16:05,026\nmake sure you catch up as soon as possible. All right, I'll\n\n1479\n01:16:05,028 --> 01:16:08,529\nbe here if you have questions. >> For\n\n1480\n01:16:08,531 --> 01:16:08,562\nmore, please visit us as stanford.edu.\n\n"
  },
  {
    "path": "subtitles/7. Closures, Extensions, Protocols, Delegation, and ScrollView.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,168\n[MUSIC]\n\n2\n00:00:03,170 --> 00:00:07,840\nStanford University. >> All right well welcome to\n\n3\n00:00:07,842 --> 00:00:11,810\nlecture number seven of CS193P,\n\n4\n00:00:11,812 --> 00:00:16,849\nSpring of 2016. So we've got a lot of different topics today,\n\n5\n00:00:16,851 --> 00:00:19,718\na couple of demos interspersed with it.\n\n6\n00:00:19,720 --> 00:00:22,354\nHere are all the topics. A lot of these are kind of,\n\n7\n00:00:22,356 --> 00:00:26,525\nI don't want to say advanced Swift features, but kind of\n\n8\n00:00:26,527 --> 00:00:30,596\nimportant Swift features that we haven't talked about so\n\n9\n00:00:30,598 --> 00:00:33,565\nfar. And then towards the end\n\n10\n00:00:33,567 --> 00:00:37,836\nwe'll talk a little about an iOS kind of concept,\n\n11\n00:00:37,838 --> 00:00:39,872\nthat comes over from the objective C world,\n\n12\n00:00:39,874 --> 00:00:42,775\nthat we have to deal with in Swift, called delegation, but\n\n13\n00:00:42,777 --> 00:00:45,778\nit's super important. It has to do with our whole NVC\n\n14\n00:00:45,780 --> 00:00:49,048\nmodel and how we do that blind structure communication and\n\n15\n00:00:49,050 --> 00:00:50,582\nnow I'm gonna finish off with scroll view.\n\n16\n00:00:50,584 --> 00:00:53,218\nOkay, very important class, because these devices\n\n17\n00:00:53,220 --> 00:00:55,554\nare really small and you want to look at something big.\n\n18\n00:00:55,556 --> 00:00:59,925\nSo you will need to be able to scroll and zoom in on it,\n\n19\n00:00:59,927 --> 00:01:03,629\nokay. All right, first topic, Memory management. So I told\n\n20\n00:01:03,631 --> 00:01:07,733\nyou already, that reference classes, or reference types,\n\n21\n00:01:07,735 --> 00:01:12,071\nwhich are classes, live in the heap, all right. And that,\n\n22\n00:01:12,073 --> 00:01:15,007\nthat memory is automatically taken care of for you, okay?\n\n23\n00:01:15,009 --> 00:01:17,009\nThat's called automatic reference counting,\n\n24\n00:01:17,011 --> 00:01:18,877\nbecause it's a reference counting base scheme. It keeps\n\n25\n00:01:18,879 --> 00:01:20,746\ntrack of how many pointers are pointing to something, and\n\n26\n00:01:20,748 --> 00:01:24,316\nwhen that count goes to zero, it immediately freezes, right?\n\n27\n00:01:24,318 --> 00:01:26,185\nWhich is different from, like, garbage collection,\n\n28\n00:01:26,187 --> 00:01:28,020\nwhere you're basically going through the heap and\n\n29\n00:01:28,022 --> 00:01:30,789\nmarking it, trying to find things that aren't pointed to,\n\n30\n00:01:30,791 --> 00:01:34,660\nand then sweeping through. Marking or sweeping and\n\n31\n00:01:34,662 --> 00:01:35,194\nthen clearing out. So\n\n32\n00:01:35,196 --> 00:01:38,797\nyou know, that kind of memory frame can be intermittent and\n\n33\n00:01:38,799 --> 00:01:41,600\nit's not really predictable, whereas, ARC is completely and\n\n34\n00:01:41,602 --> 00:01:45,137\nutterly predictable. Normally you don't think about ARC,\n\n35\n00:01:45,139 --> 00:01:47,739\nyou don't think about memory in the heap at all except for\n\n36\n00:01:47,741 --> 00:01:51,076\nthere are, there is a small way that you can influence ARC\n\n37\n00:01:51,078 --> 00:01:51,210\nthe way it works.\n\n38\n00:01:51,212 --> 00:01:54,012\nAnd that's with these three things right here. Strong,\n\n39\n00:01:54,014 --> 00:01:57,850\nweak, and unowned, okay? So we're going to talk about each\n\n40\n00:01:57,852 --> 00:02:00,619\nof these three keywords that you can put in Swift.\n\n41\n00:02:00,621 --> 00:02:04,256\nAnd all of them you use when you're declaring a variable,\n\n42\n00:02:04,258 --> 00:02:07,993\nokay? It's all for declaring variables. All right, so\n\n43\n00:02:07,995 --> 00:02:10,996\nstrong, you don't even see the word, strong in Swift,\n\n44\n00:02:10,998 --> 00:02:14,299\nbecause that's the default. Strong is normal\n\n45\n00:02:14,301 --> 00:02:18,837\nreference counting. Basically a pointer that is strong,\n\n46\n00:02:18,839 --> 00:02:21,807\nforces whatever's in the heap to stay in the heap,\n\n47\n00:02:21,809 --> 00:02:24,843\nuntil that pointer no longer points to it. Okay, so\n\n48\n00:02:24,845 --> 00:02:27,646\nit strongly holds things in the in the heap, so that's\n\n49\n00:02:27,648 --> 00:02:30,582\nthe default. Okay, if you go round creating pointers,\n\n50\n00:02:30,584 --> 00:02:33,051\nthey are strong pointers, gotta get rid of all\n\n51\n00:02:33,053 --> 00:02:36,255\nthe pointers to something for it to clean up. Okay, but\n\n52\n00:02:36,257 --> 00:02:41,460\nthen there's weak. So if you have a weak pointer, it means,\n\n53\n00:02:41,462 --> 00:02:43,595\nif no one else is interested in this thing in heap,\n\n54\n00:02:43,597 --> 00:02:47,766\nthen you can get rid of it in the heap and set me to nil.\n\n55\n00:02:48,002 --> 00:02:51,069\nOkay, so it's kind of like, yeah, I'm pointing to\n\n56\n00:02:51,071 --> 00:02:53,739\nthe thing in the heap, but I'm not that interested in it,\n\n57\n00:02:53,741 --> 00:02:56,808\nif it goes away then just set me to nil. Now for me to be\n\n58\n00:02:56,810 --> 00:02:59,745\nset to nill that means I have to be an optional pointer,\n\n59\n00:02:59,747 --> 00:03:04,216\nokay? So weak only works for optional reference pointers,\n\n60\n00:03:04,218 --> 00:03:06,652\nokay? So basically optional pointers to classes,\n\n61\n00:03:06,654 --> 00:03:11,023\nall right? A weak pointer never keeps things in\n\n62\n00:03:11,025 --> 00:03:13,892\nheap, okay? It's up to strong pointers, pointing to things\n\n63\n00:03:13,894 --> 00:03:16,962\nto keep them in the heap. So, a good example of this,\n\n64\n00:03:16,964 --> 00:03:19,131\nthat you've already seen, is outlets, right?\n\n65\n00:03:19,133 --> 00:03:22,167\nRemember your calculator, you have an outlet to the display,\n\n66\n00:03:22,169 --> 00:03:24,036\nthat UI label. That's weak, okay,\n\n67\n00:03:24,038 --> 00:03:28,473\nit automatically got set to be weak. Why is that weak? Well,\n\n68\n00:03:28,475 --> 00:03:30,008\nbecause the view hierarchy, okay?\n\n69\n00:03:30,010 --> 00:03:32,511\nThe super view, for example, of that UI label,\n\n70\n00:03:32,513 --> 00:03:35,380\nit has a strong pointer to that UI label. So your outlet\n\n71\n00:03:35,382 --> 00:03:38,350\ndoesn't have to keep it in the keep, in the heap, cuz it's\n\n72\n00:03:38,352 --> 00:03:41,420\ngoing to be kept in the heap by the view hierarchy. But\n\n73\n00:03:41,422 --> 00:03:44,156\nif the view hierarchy ever gets rid of that UI label,\n\n74\n00:03:44,158 --> 00:03:46,725\nin other words, it's no longer part of the view,\n\n75\n00:03:46,727 --> 00:03:49,461\nthen you're probably not interested in it as an outlet\n\n76\n00:03:49,463 --> 00:03:53,665\nanyway, so just set the outlet to nill. Now you notice when\n\n77\n00:03:53,667 --> 00:03:56,435\nyou make an outlet you can over at the bottom switch over\n\n78\n00:03:56,437 --> 00:03:59,738\nto strong, meaning that even if the UI label comes out of\n\n79\n00:03:59,740 --> 00:04:03,408\nthe view hierarchy it'll still stay in the heap. Okay, maybe\n\n80\n00:04:03,410 --> 00:04:05,978\nyou wanna do that because maybe you wanna put it back in\n\n81\n00:04:05,980 --> 00:04:08,013\nthe view hierarchy after it got removed from the view\n\n82\n00:04:08,015 --> 00:04:10,882\nhierarchy, okay. That'd be one of the only reasons I can\n\n83\n00:04:10,884 --> 00:04:13,385\nthink of that you would have a strong pointer through\n\n84\n00:04:13,387 --> 00:04:15,721\nan outlet to something in the view hierarchy.\n\n85\n00:04:15,723 --> 00:04:18,490\nRight, cuz maybe we are going to take in and out. Okay,\n\n86\n00:04:18,492 --> 00:04:21,493\neveryone understand weak? Optional reference pointers\n\n87\n00:04:21,495 --> 00:04:24,329\ncan be weak. Okay, and you just declare it when you say\n\n88\n00:04:24,331 --> 00:04:28,800\nvar, you say weak var whatever optional pointer, okay?\n\n89\n00:04:28,802 --> 00:04:33,605\nAnd then the last one here, unowned, unowned kind of means\n\n90\n00:04:33,607 --> 00:04:37,242\ndon't reference count this, which is very dangerous. If\n\n91\n00:04:37,244 --> 00:04:41,880\nyou have an unowned pointer, it means that reference\n\n92\n00:04:41,882 --> 00:04:45,517\ncounting is not going to track it. And so this pointer is\n\n93\n00:04:45,519 --> 00:04:47,953\nalways going to point to that little place in memory.\n\n94\n00:04:47,955 --> 00:04:50,589\nAnd you better be sure that the thing you point to\n\n95\n00:04:50,591 --> 00:04:54,993\nstays there. Okay, until you don't use that, this pointer\n\n96\n00:04:54,995 --> 00:04:58,230\nanymore, okay? And if you have an unknown pointer and\n\n97\n00:04:58,232 --> 00:05:00,132\nyou later reference it, and the thing that you're\n\n98\n00:05:00,134 --> 00:05:02,267\nreference got thrown out of the heap, because there were\n\n99\n00:05:02,269 --> 00:05:06,738\nno more strong pointers to it, then you will crash, okay?\n\n100\n00:05:06,740 --> 00:05:09,641\nWhich could be memory reference error.\n\n101\n00:05:09,643 --> 00:05:12,444\nNow you might say, why do I ever want this unowned thing?\n\n102\n00:05:12,446 --> 00:05:15,013\nAnd I will show you a little example, later in this\n\n103\n00:05:15,015 --> 00:05:18,817\nlecture, of a way to break a memory cycle between objects.\n\n104\n00:05:18,819 --> 00:05:19,584\nOne object points to another,\n\n105\n00:05:19,586 --> 00:05:22,187\nwhich points back to the first one, directly or indirectly,\n\n106\n00:05:22,189 --> 00:05:25,590\nkeeping them both in memory. You can break it with unknown,\n\n107\n00:05:25,592 --> 00:05:27,092\nbut often times you'll break it with weak.\n\n108\n00:05:27,094 --> 00:05:30,162\nBut you'll see that coming up. Okay, so this is the only way\n\n109\n00:05:30,164 --> 00:05:32,931\nyou can influence arc, is with these three things. And you\n\n110\n00:05:32,933 --> 00:05:35,634\nalmost never really use this, it's very rare to use these.\n\n111\n00:05:35,636 --> 00:05:39,438\nWeak, occasionally, strong, never, 'cuz of the default,\n\n112\n00:05:39,440 --> 00:05:44,042\nand unowned, next to never. Okay, all right, let's talk\n\n113\n00:05:44,044 --> 00:05:47,813\nmore about closures. We did closures in our first lecture,\n\n114\n00:05:47,815 --> 00:05:48,980\nour first week of lecture.\n\n115\n00:05:48,982 --> 00:05:51,950\nRemember we had those closures like $0 times $1.\n\n116\n00:05:51,952 --> 00:05:54,986\nThat's a closure, a closure is just an inline function.\n\n117\n00:05:54,988 --> 00:05:58,123\nAnd one thing that is interesting about closures,\n\n118\n00:05:58,125 --> 00:06:00,659\nthey are stored in the heap as well, okay?\n\n119\n00:06:00,661 --> 00:06:04,363\nSo closures are essentially a reference type, okay.\n\n120\n00:06:04,365 --> 00:06:05,997\nCuz you remember that closures are just functions,\n\n121\n00:06:05,999 --> 00:06:10,936\nfunctions are types, or just normal types in Swift. So,\n\n122\n00:06:10,938 --> 00:06:11,470\nthey're stored in the heap.\n\n123\n00:06:11,472 --> 00:06:14,706\nNow it has interesting ramifications for the way\n\n124\n00:06:14,708 --> 00:06:19,044\nthings work, because inside of a closure, you can reference\n\n125\n00:06:19,046 --> 00:06:23,115\nall kinds of variables that were in the scope around it.\n\n126\n00:06:23,117 --> 00:06:25,650\nOkay, cuz remember it's an inline function, so\n\n127\n00:06:25,652 --> 00:06:29,187\nyou might reference variables that are local variables in\n\n128\n00:06:29,189 --> 00:06:31,289\nthat inline, in the function you're in,\n\n129\n00:06:31,291 --> 00:06:34,393\nor maybe instance variable, properties of the class,\n\n130\n00:06:34,395 --> 00:06:37,396\nif you're inside a method you declare the closure.\n\n131\n00:06:37,398 --> 00:06:40,465\nIt's perfectly legal to access all of those things, and not\n\n132\n00:06:40,467 --> 00:06:43,435\nto only access them, but you can access them read-write.\n\n133\n00:06:43,437 --> 00:06:45,637\nOkay, well now we know, from the calculator,\n\n134\n00:06:45,639 --> 00:06:49,007\nthat sometimes a closure lives a long time, maybe it gets put\n\n135\n00:06:49,009 --> 00:06:52,544\nin a dictionary, like we did in the calculator, right. And\n\n136\n00:06:52,546 --> 00:06:54,746\nso that dictionary can live for a long, long time.\n\n137\n00:06:54,748 --> 00:06:57,516\nAnd that closure keeps getting pulled out and called,\n\n138\n00:06:57,518 --> 00:07:00,419\ncalled, so what happens if you put a local variable,\n\n139\n00:07:00,421 --> 00:07:04,122\nyou captured a local variable In one of these closures and\n\n140\n00:07:04,124 --> 00:07:04,156\nyou put it in there.\n\n141\n00:07:04,158 --> 00:07:06,057\nWell that local variable has to be kept around too,\n\n142\n00:07:06,059 --> 00:07:10,529\nand Swift automatically does this, okay? Anything that gets\n\n143\n00:07:10,531 --> 00:07:14,032\ncaptured inside a closure that you use inside a closure\n\n144\n00:07:14,034 --> 00:07:17,269\ngets moved, or if it already is in the heap, it gets\n\n145\n00:07:17,271 --> 00:07:19,838\na strong pointer to it from the closure, otherwise, it\n\n146\n00:07:19,840 --> 00:07:22,507\ngets moved to the heap. Okay, so everything get in the,\n\n147\n00:07:22,509 --> 00:07:24,876\nstays in the heap, okay? Everything that closure and\n\n148\n00:07:24,878 --> 00:07:26,611\neverything it references internally in its\n\n149\n00:07:26,613 --> 00:07:31,450\nimplementation, all of that gets in the heap, okay? So,\n\n150\n00:07:31,452 --> 00:07:34,453\nwhat is the problem with that? Well, there's no problem,\n\n151\n00:07:34,455 --> 00:07:36,988\nit generally just kind of works how you would think,\n\n152\n00:07:36,990 --> 00:07:39,424\nexcept for memory cycles. Okay, so\n\n153\n00:07:39,426 --> 00:07:42,127\nlet's go through why a memory cycle can be created and\n\n154\n00:07:42,129 --> 00:07:44,996\nwhat's bad about memory cycles. Okay, what's bad about\n\n155\n00:07:44,998 --> 00:07:47,466\nthem is, you have a closure pointing to an object, that\n\n156\n00:07:47,468 --> 00:07:50,335\nobject is pointing back to the closure, they're pointing to\n\n157\n00:07:50,337 --> 00:07:53,038\neach other, they have strong references to each other.\n\n158\n00:07:53,040 --> 00:07:56,208\nHow can they ever leave the heap? Never. Right.\n\n159\n00:07:56,210 --> 00:07:57,476\nBecause they each are pointing to each other.\n\n160\n00:07:57,478 --> 00:08:00,045\nThey always are gonna maintain a strong pointer to each\n\n161\n00:08:00,047 --> 00:08:03,181\nother. There's no way, unless you set one of those pointers\n\n162\n00:08:03,183 --> 00:08:04,916\nto nil, okay, or something else.\n\n163\n00:08:04,918 --> 00:08:07,853\nThere's no way they can stop pointing to each other. Okay?\n\n164\n00:08:07,855 --> 00:08:10,088\nSo let's see how this can happen with the calculator.\n\n165\n00:08:10,090 --> 00:08:12,457\nLet's say with my CalculatorBrain I added\n\n166\n00:08:12,459 --> 00:08:16,595\na new method called addUnary function that took a symbol\n\n167\n00:08:16,597 --> 00:08:18,029\nand a operation, right.\n\n168\n00:08:18,031 --> 00:08:20,232\nA function that takes a double or turns to a double.\n\n169\n00:08:20,234 --> 00:08:22,467\nAnd basically I'm making it so that the user of my\n\n170\n00:08:22,469 --> 00:08:24,970\nCalculatorBrain can add their own functions. Right now our\n\n171\n00:08:24,972 --> 00:08:27,405\nCalculatorBrain just has this built-in table of functions\n\n172\n00:08:27,407 --> 00:08:29,741\nand operations. Well what if I added this method and\n\n173\n00:08:29,743 --> 00:08:32,377\nI just let people add them? That would be really cool,\n\n174\n00:08:32,379 --> 00:08:36,448\nright? And so let's say we have our View Controller. And\n\n175\n00:08:36,450 --> 00:08:38,984\nwe wanted to add a Unary function which is the same\n\n176\n00:08:38,986 --> 00:08:42,587\nas square root except for that it would turn the display in\n\n177\n00:08:42,589 --> 00:08:48,093\nthe calculator red. Okay? So I call it red square root, okay.\n\n178\n00:08:48,095 --> 00:08:48,326\nIt's just square root but\n\n179\n00:08:48,328 --> 00:08:51,463\nit's gonna turn the thing red when the result comes back.\n\n180\n00:08:51,465 --> 00:08:54,099\nWell how would we do that? Okay, well we would just call\n\n181\n00:08:54,101 --> 00:08:57,202\nthis addUnaryOperation. Now one thing I just wanna\n\n182\n00:08:57,204 --> 00:08:58,737\nremind you a little bit of the syntax here.\n\n183\n00:08:58,739 --> 00:09:02,073\nYou see here's UnaryOperation, it has two arguments.\n\n184\n00:09:02,075 --> 00:09:03,542\nThere's the symbol, okay.\n\n185\n00:09:03,544 --> 00:09:07,612\nHere's the operation which is this closure. Of course,\n\n186\n00:09:07,614 --> 00:09:10,749\nbecause of type inference I don't, well, first of all,\n\n187\n00:09:10,751 --> 00:09:16,121\nI don't need to do this comma second. Second argument.\n\n188\n00:09:16,123 --> 00:09:19,524\nHere, I can actually put this closure after the end, right?\n\n189\n00:09:19,526 --> 00:09:22,027\nSo I can take this second argument and\n\n190\n00:09:22,029 --> 00:09:22,494\nput it after the end.\n\n191\n00:09:22,496 --> 00:09:24,996\nRemember that's the trailing closure syntax,\n\n192\n00:09:24,998 --> 00:09:25,764\neveryone remember this?\n\n193\n00:09:25,766 --> 00:09:28,833\nOkay since the closure is the last argument we can do this.\n\n194\n00:09:28,835 --> 00:09:32,070\nAlso I don't need any of this type stuff in here because it\n\n195\n00:09:32,072 --> 00:09:34,906\ncan infer that. Okay, so I can just take that away and\n\n196\n00:09:34,908 --> 00:09:37,242\nuse $0 down here. Okay, everyone remember that?\n\n197\n00:09:37,244 --> 00:09:40,812\nAll right, so here I am adding this UnaryOperation.\n\n198\n00:09:40,814 --> 00:09:43,415\nNotice that it sets the display color.\n\n199\n00:09:43,417 --> 00:09:46,051\nThis is in my View Controller, my calculator View Controller,\n\n200\n00:09:46,053 --> 00:09:48,753\nright? It sets the display color to red when it does\n\n201\n00:09:48,755 --> 00:09:51,022\nthe square root. Okay, this is gonna be UnaryOperation.\n\n202\n00:09:51,024 --> 00:09:53,091\nEverybody understand what this is doing?\n\n203\n00:09:53,093 --> 00:09:54,426\nIt's really super simple. Okay,\n\n204\n00:09:54,428 --> 00:09:56,428\nwell this code will not compile. Okay,\n\n205\n00:09:56,430 --> 00:09:59,364\nwhy will this code not compile? It's interesting.\n\n206\n00:09:59,366 --> 00:10:01,199\nIt's because, and when you look at the warning,\n\n207\n00:10:01,201 --> 00:10:02,968\nit's gonna say, you have to put self.\n\n208\n00:10:02,970 --> 00:10:06,471\nIn front of this. Which normally you don't have to do,\n\n209\n00:10:06,473 --> 00:10:08,974\nyou can just reference your own properties with display,\n\n210\n00:10:08,976 --> 00:10:11,676\nwhy do you have to put self.? Well you have to put self.\n\n211\n00:10:11,678 --> 00:10:15,280\nThere cuz the compiler wants you to realize that this\n\n212\n00:10:15,282 --> 00:10:20,852\nclosure is going to capture this self. And\n\n213\n00:10:20,854 --> 00:10:22,921\nkeep a strong pointer to it forever, for\n\n214\n00:10:22,923 --> 00:10:24,856\nas long as this closure lives. Okay? And\n\n215\n00:10:24,858 --> 00:10:27,759\nthis closure's gonna be put in a dictionary in another class\n\n216\n00:10:27,761 --> 00:10:30,795\nso it's gonna live a long time. It's gonna capture self.\n\n217\n00:10:30,797 --> 00:10:33,465\nSo self now has a strong point to it, it can never leave\n\n218\n00:10:33,467 --> 00:10:37,736\nthe heap until until this closure leaves the heap. Okay?\n\n219\n00:10:37,738 --> 00:10:40,472\nBut this closure is never gonna leave the heap because\n\n220\n00:10:40,474 --> 00:10:44,342\nit's in the CalculatorBrain which the View Controller has\n\n221\n00:10:44,344 --> 00:10:47,278\na strong point or two. So, who will leave the,\n\n222\n00:10:47,280 --> 00:10:50,715\nthe heap first? Neither of them, okay? So they're stuck.\n\n223\n00:10:50,717 --> 00:10:52,917\nSo, that's why swift forces you put that there so\n\n224\n00:10:52,919 --> 00:10:56,221\nyou realize that you are implicitly capturing and, and\n\n225\n00:10:56,223 --> 00:10:59,457\nmaking a strong point or two self. All right?\n\n226\n00:10:59,459 --> 00:11:02,794\nNow, how do we deal with this? How do we break this loop, so\n\n227\n00:11:02,796 --> 00:11:05,430\nthat we can have these things leave the heap normally?\n\n228\n00:11:05,432 --> 00:11:07,766\nOkay? There's a couple ways we can do it.\n\n229\n00:11:07,768 --> 00:11:10,702\nFirst, we have to realize that there's a cool syntax in\n\n230\n00:11:10,704 --> 00:11:14,839\nswift. That allows you to, declare variables to\n\n231\n00:11:14,841 --> 00:11:17,942\nuse inside your closure. Right at the beginning. All you do\n\n232\n00:11:17,944 --> 00:11:21,413\nis a square bracket tier and you just put the names\n\n233\n00:11:21,415 --> 00:11:22,514\nof the variables you want and\n\n234\n00:11:22,516 --> 00:11:25,483\ntheir initial values. Okay? Put it right here.\n\n235\n00:11:25,485 --> 00:11:30,455\nFor example, I can create a variable called, me. M-E.\n\n236\n00:11:30,457 --> 00:11:33,925\nAnd, I'm gonna set it to self. Okay. And so\n\n237\n00:11:33,927 --> 00:11:36,861\nme is now local variable only inside this closure and\n\n238\n00:11:36,863 --> 00:11:41,066\nits value is self. Okay? And sure enough look I can change\n\n239\n00:11:41,068 --> 00:11:43,835\nself right there to be me because me is just a local\n\n240\n00:11:43,837 --> 00:11:48,339\nvariable. But this will have no effect on the the closure\n\n241\n00:11:48,341 --> 00:11:51,309\nproblem because me is still self and it still gonna make\n\n242\n00:11:51,311 --> 00:11:54,746\na strong point in there. To self and hold it in memory.\n\n243\n00:11:54,748 --> 00:11:58,516\nBut I can use those unow, those unowned weak and strong\n\n244\n00:11:58,518 --> 00:12:02,454\nthings with this variable, so I'm gonna say unowned me =\n\n245\n00:12:02,456 --> 00:12:07,125\nself. Now, we've broken that cycle. Okay, because unowned\n\n246\n00:12:07,127 --> 00:12:10,261\nmeans don't reference count this, which means that swift\n\n247\n00:12:10,263 --> 00:12:14,566\nis not going to make a strong pointer to this me in this\n\n248\n00:12:14,568 --> 00:12:17,202\nclosure. So now this closure does not point strongly to\n\n249\n00:12:17,204 --> 00:12:19,904\nself. Self still points strongly to this closure\n\n250\n00:12:19,906 --> 00:12:22,640\nthrough the CalculatorBrain through the dictionary.\n\n251\n00:12:22,642 --> 00:12:26,144\nTo it, okay. But it does not now strongly point back to.\n\n252\n00:12:26,146 --> 00:12:28,213\nIt's not gonna keep the View Controller in memory.\n\n253\n00:12:28,215 --> 00:12:32,383\nNow the danger here, is if this closure lived longer than\n\n254\n00:12:32,385 --> 00:12:34,586\nthe View Controller lived, which is pretty much\n\n255\n00:12:34,588 --> 00:12:36,755\nimpossible because this is in the dictionary that's\n\n256\n00:12:36,757 --> 00:12:38,790\nin the brain that the controller owned. But\n\n257\n00:12:38,792 --> 00:12:42,026\nif some wackiness happened and this lived longer and we tried\n\n258\n00:12:42,028 --> 00:12:44,596\nto execute this longer after the View Controller is gone.\n\n259\n00:12:44,598 --> 00:12:47,899\nThis will crash. Okay? Because me would be pointing\n\n260\n00:12:47,901 --> 00:12:50,368\nto something that got free from the heat. But\n\n261\n00:12:50,370 --> 00:12:53,371\nanother way to do it besides unowned is weak. So\n\n262\n00:12:53,373 --> 00:12:57,175\nwe could make self weak, okay? This will work great.\n\n263\n00:12:57,177 --> 00:12:58,643\nThis will also break the cycle.\n\n264\n00:12:58,645 --> 00:13:01,679\nBecause weak things don't keep things in the heap. However,\n\n265\n00:13:01,681 --> 00:13:06,417\nself inside this closure now becomes what?\n\n266\n00:13:06,419 --> 00:13:11,389\nAn optional UIViewController. Okay, so this self right here,\n\n267\n00:13:11,391 --> 00:13:13,525\nthis local variable self has the same name but\n\n268\n00:13:13,527 --> 00:13:16,628\nit's a different variable than the outer self. Okay?\n\n269\n00:13:16,630 --> 00:13:19,531\nAnd this is weak so this will not work, anymore. This won't\n\n270\n00:13:19,533 --> 00:13:23,368\ncompile because display is not a message you can send to\n\n271\n00:13:23,370 --> 00:13:26,371\nan optional, you can only send it to our View Controller;\n\n272\n00:13:26,373 --> 00:13:28,940\ncalculator View Controller. So how do you fix this?\n\n273\n00:13:28,942 --> 00:13:32,644\nWell the simplest way is to use this optional changing and\n\n274\n00:13:32,646 --> 00:13:33,912\njust put a question mark in here.\n\n275\n00:13:33,914 --> 00:13:35,947\nRemember if you put a question mark on an optional,\n\n276\n00:13:35,949 --> 00:13:39,551\non the left hand side of an equal sign, it means if any of\n\n277\n00:13:39,553 --> 00:13:42,187\nthese things or the question mark are nil, just ignore this\n\n278\n00:13:42,189 --> 00:13:46,558\nwhole line. Okay? Bailout. So this is perfect. Weak self.\n\n279\n00:13:46,560 --> 00:13:49,360\nIf this self ever were nil, this would just bail out and\n\n280\n00:13:49,362 --> 00:13:53,398\nnot do it. Okay? So now this code would work even\n\n281\n00:13:53,400 --> 00:13:56,668\nif the View Controller got thrown out of the heap. And\n\n282\n00:13:56,670 --> 00:13:57,435\nsince this is weak,\n\n283\n00:13:57,437 --> 00:14:00,538\nwe're using a weak self in here, it won't keep the,\n\n284\n00:14:00,540 --> 00:14:02,807\nthe View Controller in the heap. Now,\n\n285\n00:14:02,809 --> 00:14:06,144\nwhen we do this weakSelf, here, we almost always declare\n\n286\n00:14:06,146 --> 00:14:10,248\na different name here. Almost always. WeakSelf. Okay? So\n\n287\n00:14:10,250 --> 00:14:12,851\nweak variable weakSelf = self, and then we'll\n\n288\n00:14:12,853 --> 00:14:15,220\nput that in there. And that tells people reading our code,\n\n289\n00:14:15,222 --> 00:14:16,855\nyeah, I understand I'm making this weak. So\n\n290\n00:14:16,857 --> 00:14:22,360\ndon't worry about that, that possible memory cycle. Okay so\n\n291\n00:14:22,362 --> 00:14:23,161\nthat's closure in memory cycle.\n\n292\n00:14:23,163 --> 00:14:26,197\nI'm gonna do a demo on this, okay. Which is I'm gonna do\n\n293\n00:14:26,199 --> 00:14:29,000\nthat red square root and let's see what this looks like\n\n294\n00:14:29,002 --> 00:14:34,072\nin the calculator. To do this. All right so\n\n295\n00:14:34,074 --> 00:14:37,242\nI'm going back to our calculator\n\n296\n00:14:39,880 --> 00:14:42,614\n[INAUDIBLE] There we go. Okay so here's our calculator as we\n\n297\n00:14:42,616 --> 00:14:45,350\nleft it off. This is not your homework calculator. This is\n\n298\n00:14:45,352 --> 00:14:48,386\nlecture four or whatever our last time. We just have\n\n299\n00:14:48,388 --> 00:14:52,624\nthis blank calculator right here. I'm going to now that\n\n300\n00:14:52,626 --> 00:14:55,760\nyou're comfortable with things like navigation controllers.\n\n301\n00:14:55,762 --> 00:14:58,863\nI'm going to actually add another View Controller here.\n\n302\n00:14:58,865 --> 00:15:05,236\nOkay, and I'm gonna put a button in it. Oops,\n\n303\n00:15:05,238 --> 00:15:08,373\nmake this bigger. Put a button in this. I'm gonna make it\n\n304\n00:15:08,375 --> 00:15:12,377\nbigger. We'll make it 40 point, I would say. Okay,\n\n305\n00:15:12,379 --> 00:15:16,881\nI'm gonna change the title to be Calculate.\n\n306\n00:15:17,050 --> 00:15:21,920\nOkay, and this button is going to cause this calculator here\n\n307\n00:15:21,922 --> 00:15:24,255\nto appear. So let's go ahead and Reset to\n\n308\n00:15:24,257 --> 00:15:26,925\nSuggested Constraints. Notice when I did that, look,\n\n309\n00:15:26,927 --> 00:15:28,927\nI got all kinds of constraints I didn't really want.\n\n310\n00:15:28,929 --> 00:15:31,596\nYou see, because, that's cuz I didn't have this thing be\n\n311\n00:15:31,598 --> 00:15:35,099\nin its natural size. So let's go over to the size inspector\n\n312\n00:15:35,101 --> 00:15:37,302\nover here and look at our constraints. And\n\n313\n00:15:37,304 --> 00:15:39,103\nwe see, it's constraining the width to be 204.\n\n314\n00:15:39,105 --> 00:15:42,674\nI don't want that. I wanna it to be its natural width. So\n\n315\n00:15:42,676 --> 00:15:45,376\nI'm just gonna select this constraint, constraint and\n\n316\n00:15:45,378 --> 00:15:47,245\nhit the Delete. Same thing here,\n\n317\n00:15:47,247 --> 00:15:50,448\nit's constraining it to the top by some magic number 203.\n\n318\n00:15:50,450 --> 00:15:54,085\nI don't want that because I want it to be aligned center x\n\n319\n00:15:54,087 --> 00:15:55,753\nand y. So it's okay in here just to go ahead and\n\n320\n00:15:55,755 --> 00:15:58,589\ndelete constraints you don't work want. Now of course now\n\n321\n00:15:58,591 --> 00:16:01,893\nthis is yellow, so we're gonna go down here and\n\n322\n00:16:01,895 --> 00:16:05,330\nsay click on this. All right. And go down here and\n\n323\n00:16:05,332 --> 00:16:09,334\nsay update frames, and that's gonna move the frames to where\n\n324\n00:16:09,336 --> 00:16:12,904\nthey should be, and now everything is cute. Okay,\n\n325\n00:16:12,906 --> 00:16:15,573\na little quick review there of constraints.\n\n326\n00:16:15,575 --> 00:16:18,409\nAlso, I don't want the entry point to be my calculator,\n\n327\n00:16:18,411 --> 00:16:19,811\nI want it to be this thing. Okay,\n\n328\n00:16:19,813 --> 00:16:22,447\nthis is going to be my first thing, and I'm going to put it\n\n329\n00:16:22,449 --> 00:16:25,850\ninside of a navigation controller. So, I'm going to\n\n330\n00:16:25,852 --> 00:16:28,987\nput this inside a navigation controller with embed in,\n\n331\n00:16:28,989 --> 00:16:34,892\noops, select this again, embed in navigation controller,\n\n332\n00:16:34,894 --> 00:16:39,464\nand now I have a nice little UI here. That has a navigation\n\n333\n00:16:39,466 --> 00:16:41,432\ncontroller in this and I'm going to make it so\n\n334\n00:16:41,434 --> 00:16:43,101\nthat this button, when it's clicked,\n\n335\n00:16:43,103 --> 00:16:47,138\nsegues to show a calculator. Okay, so let's do that.\n\n336\n00:16:47,140 --> 00:16:50,441\nControl, drag over here, we're going to do a show because\n\n337\n00:16:50,443 --> 00:16:52,810\nwe're inside a navigation controller. This is not for\n\n338\n00:16:52,812 --> 00:16:55,713\niPad, this is for iPhone only, so I'm just going to do Show,\n\n339\n00:16:55,715 --> 00:16:59,050\nand here's our show now. I'm not going to set an identifier\n\n340\n00:16:59,052 --> 00:17:01,786\nhere because I'm not gonna prepare that calculator. I'm\n\n341\n00:17:01,788 --> 00:17:04,856\njust gonna let it come up in whatever its state is. I'm not\n\n342\n00:17:04,858 --> 00:17:08,393\ngonna prepare it. So, no need to put an identifier here.\n\n343\n00:17:08,395 --> 00:17:13,131\nOkay, so this is what our UI looks like. All right, so\n\n344\n00:17:13,133 --> 00:17:16,834\nlet's go ahead and run this, see what this looks like.\n\n345\n00:17:28,681 --> 00:17:29,881\nOkay, so here's our calculator.\n\n346\n00:17:29,883 --> 00:17:32,717\nWe're inside a navigation controller. Hit Calculate,\n\n347\n00:17:32,719 --> 00:17:36,654\nit shows it, go back, hit calculate, it shows it.\n\n348\n00:17:36,656 --> 00:17:38,089\nNow remember in a navigation controller,\n\n349\n00:17:38,091 --> 00:17:41,692\nevery time we segue what happens? We get a new MVC. So,\n\n350\n00:17:41,694 --> 00:17:43,995\nwe're getting a new calculator MVC every single time.\n\n351\n00:17:43,997 --> 00:17:47,498\nIn fact, I'm going to prove that to you by going back here\n\n352\n00:17:47,500 --> 00:17:48,666\nto my calculator view controller.\n\n353\n00:17:48,668 --> 00:17:51,936\nAnd I'm going to have it print every time it creates a new\n\n354\n00:17:51,938 --> 00:17:54,839\none and every time it leaves the heap. Okay? So,\n\n355\n00:17:54,841 --> 00:17:56,908\nlet's start with every time that it creates a new one,\n\n356\n00:17:56,910 --> 00:18:00,144\nwe can use viewDidLoad() for that, okay?\n\n357\n00:18:00,146 --> 00:18:00,711\nSo, here's viewDidLoad().\n\n358\n00:18:00,713 --> 00:18:03,881\nRemember in our ViewController life-cycles we always need to\n\n359\n00:18:03,883 --> 00:18:07,185\ncall super, so I'm calling super.viewDidLoad().\n\n360\n00:18:07,187 --> 00:18:10,121\nI'm going to create a global variable here,\n\n361\n00:18:10,123 --> 00:18:13,191\nwhich is my calculatorCount Start out as zero.\n\n362\n00:18:13,193 --> 00:18:16,327\nThat's how many calculator instances are currently\n\n363\n00:18:16,329 --> 00:18:19,030\nexisting in the world. So when I do a viewDidLoa,\n\n364\n00:18:19,032 --> 00:18:22,900\nwhich I know happens only once per MVC, I'm going to take my\n\n365\n00:18:22,902 --> 00:18:25,536\ncalculator account and increment it by one.\n\n366\n00:18:25,538 --> 00:18:28,439\nAnd then I'm just going to print out, loaded up\n\n367\n00:18:28,441 --> 00:18:31,809\na new calculator and I'll tell you what the account is at\n\n368\n00:18:31,811 --> 00:18:37,415\nthat time, and that's going to be calculator count, okay?\n\n369\n00:18:37,417 --> 00:18:40,418\nSo, every time we create a new MBC where it's gonna get\n\n370\n00:18:40,420 --> 00:18:42,553\na message, now how do we find out\n\n371\n00:18:42,555 --> 00:18:45,690\nwhen something leaves the heap? Anyone do the homework,\n\n372\n00:18:45,692 --> 00:18:49,861\nthe reading homework and tell me? Special method?\n\n373\n00:18:49,863 --> 00:18:54,832\nWhat? Nobody? My gosh, okay.\n\n374\n00:18:54,834 --> 00:18:59,337\nDeinit. Okay, this special thing deinit gets called just\n\n375\n00:18:59,339 --> 00:19:02,540\nbefore you leave the heap, okay? So, in here I'm just\n\n376\n00:19:02,542 --> 00:19:05,543\ngoing to say the calculator Count minus equals one because\n\n377\n00:19:05,545 --> 00:19:09,213\nthis is leaving the heap, and I'm going to do a print here,\n\n378\n00:19:09,215 --> 00:19:14,519\nI'm gonna say calculator left the heap and\n\n379\n00:19:14,521 --> 00:19:16,187\nnow show our count. Okay? So now,\n\n380\n00:19:16,189 --> 00:19:19,524\nwhen I run, we're going to see our count of calculators.\n\n381\n00:19:19,526 --> 00:19:22,393\nAnd what happens to it as we keep clicking that calculator\n\n382\n00:19:22,395 --> 00:19:24,829\nbutton, and keep having new MVCs, all right? So,\n\n383\n00:19:24,831 --> 00:19:26,397\nhere we go, let's calculate. There it is,\n\n384\n00:19:26,399 --> 00:19:29,767\nloaded up a new calculator, count equals 1, looks good.\n\n385\n00:19:29,769 --> 00:19:33,371\nWe go back, calculator left the heap, count is 0,\n\n386\n00:19:33,373 --> 00:19:38,709\ngo back again, loaded up a new calculator, count is 1.\n\n387\n00:19:39,679 --> 00:19:43,181\nGo back, count to 0. So, this is proving what I was\n\n388\n00:19:43,183 --> 00:19:45,583\nsaying before. That every time we segue,\n\n389\n00:19:45,585 --> 00:19:47,451\nit's creating a new one. Every time we go back,\n\n390\n00:19:47,453 --> 00:19:51,656\nit throws it out. Everybody believe that now? Okay. So\n\n391\n00:19:51,658 --> 00:19:55,660\nnow, let's go ahead and do our red square root. Okay?\n\n392\n00:19:55,662 --> 00:19:57,895\nLet's do our red square root button. I told you,\n\n393\n00:19:57,897 --> 00:19:59,897\nI was gonna go to calculate the brain and\n\n394\n00:19:59,899 --> 00:20:04,268\nadd a new public function here called addUnaryOperation. It's\n\n395\n00:20:04,270 --> 00:20:08,172\ngonna take a symbol which is a string, and it's gonna take in\n\n396\n00:20:08,174 --> 00:20:10,942\noperation that goes along with it, which takes a double and\n\n397\n00:20:10,944 --> 00:20:16,013\nreturns a double. Okay? And adding a Unary operation\n\n398\n00:20:16,015 --> 00:20:18,382\nis really easy because all we all have\n\n399\n00:20:18,384 --> 00:20:21,686\nto do is add an Unary operation to this table right\n\n400\n00:20:21,688 --> 00:20:25,489\nhere, okay? So, I'm just gonna say operation some symbol,\n\n401\n00:20:25,491 --> 00:20:28,826\nokay? This is the symbol that the person wants this under.\n\n402\n00:20:28,828 --> 00:20:31,696\nWe're gonna set this equal to the operation.\n\n403\n00:20:31,698 --> 00:20:32,563\nWe can't really do that, though,\n\n404\n00:20:32,565 --> 00:20:36,300\nbecause we have e nums in here. So we need to wrap\n\n405\n00:20:36,302 --> 00:20:41,939\na operation dot unary operation around this thing,\n\n406\n00:20:41,941 --> 00:20:45,243\nokay, and the associated value is a double takes a double so\n\n407\n00:20:45,245 --> 00:20:51,015\nthat works. And that's it. So, I just added a unary operation\n\n408\n00:20:51,017 --> 00:20:55,620\nto my operation table. Okay. Now that we have that feature,\n\n409\n00:20:55,622 --> 00:20:57,888\nthen let's go back to our view controller and\n\n410\n00:20:57,890 --> 00:20:59,690\nuse it. We might viewDidLoad.\n\n411\n00:20:59,692 --> 00:21:04,895\nRight here. I'm going to add a unary operation, oops,\n\n412\n00:21:04,897 --> 00:21:10,701\nadd, and my brain, I'm gonna add a unary operation. And\n\n413\n00:21:10,703 --> 00:21:14,071\nI'm gonna say I'm gonna have it symbol be the letter Z, but\n\n414\n00:21:14,073 --> 00:21:18,542\nwe could make it a nice red dot and a square sign,\n\n415\n00:21:18,544 --> 00:21:20,144\nbut faster to type z, and\n\n416\n00:21:20,146 --> 00:21:23,814\nthe function is going to be a closure. Okay.\n\n417\n00:21:23,816 --> 00:21:26,851\nAnd again, I can use the trailing closure notation\n\n418\n00:21:26,853 --> 00:21:30,955\nto do that right here. Okay, and as we said in the slides,\n\n419\n00:21:30,957 --> 00:21:35,893\nI'm just going to set my displays text color\n\n420\n00:21:36,029 --> 00:21:39,597\nequal to UI color, red color. And\n\n421\n00:21:39,599 --> 00:21:43,000\nthen I'm gonna return the square root of $0.\n\n422\n00:21:43,002 --> 00:21:46,504\nOkay, and as promised I have an error right here.\n\n423\n00:21:46,506 --> 00:21:49,307\nIt says reference to property 'display' in closure requires\n\n424\n00:21:49,309 --> 00:21:53,177\nexplicit 'self' to make make capture semantics explicit.\n\n425\n00:21:53,179 --> 00:21:56,414\nOkay? Hopefully that with that warning it makes perfect sense\n\n426\n00:21:56,416 --> 00:21:59,483\nnow. Links wants you to be clear that you are going\n\n427\n00:21:59,485 --> 00:22:02,153\nto capture self, it's gonna get a strong pointer to it.\n\n428\n00:22:02,155 --> 00:22:03,821\nSo, I'm gonna do the fix right here,\n\n429\n00:22:03,823 --> 00:22:07,291\nwhich is insert self, fixes that problem.\n\n430\n00:22:07,293 --> 00:22:08,259\nAnd now we have [INAUDIBLE] operation. So,\n\n431\n00:22:08,261 --> 00:22:11,929\nlet's go to our story board and add that somewhere here.\n\n432\n00:22:11,931 --> 00:22:17,301\nWe'll replace, how about we replace our old square root\n\n433\n00:22:17,303 --> 00:22:19,670\nwith our new z square root and\n\n434\n00:22:19,672 --> 00:22:25,109\nrun? All right, so here we are,\n\n435\n00:22:25,111 --> 00:22:28,446\nokay, I'm gonna hit calculate, loaded up a new calculator.\n\n436\n00:22:28,448 --> 00:22:32,350\nLet's do 81 red square root, it's working perfectly, okay.\n\n437\n00:22:32,352 --> 00:22:35,720\nIt took the square root and it turned the display red. And so\n\n438\n00:22:35,722 --> 00:22:40,891\nlet's go back. We did't lo--, we didn't leave the heap,\n\n439\n00:22:40,893 --> 00:22:42,460\nthat's weird. Le's go back again. Wait,\n\n440\n00:22:42,462 --> 00:22:46,430\nnow we have two calculators, wha's going on, or three.\n\n441\n00:22:46,432 --> 00:22:48,299\nNo, we're collecting calculators.\n\n442\n00:22:48,301 --> 00:22:51,235\nNow, these calculators are not very big, they do't have\n\n443\n00:22:51,237 --> 00:22:53,270\na lot of storage so probably not gonna kill us. But\n\n444\n00:22:53,272 --> 00:22:56,741\nwhat if these had an image? Right or even like a video or\n\n445\n00:22:56,743 --> 00:22:58,743\nsomething in there, and w're collecting these things, and\n\n446\n00:22:58,745 --> 00:23:02,346\nthey were building up in the heap never to be freed. Okay,\n\n447\n00:23:02,348 --> 00:23:05,449\nthat would be a problem. Okay, so how can we make it so that\n\n448\n00:23:05,451 --> 00:23:08,419\nit goes back to where it was where when we left it would\n\n449\n00:23:08,421 --> 00:23:12,189\nfree up? Well all we have to do is go here to this and\n\n450\n00:23:12,191 --> 00:23:16,026\nfix a problem that this self is being held in memory so\n\n451\n00:23:16,028 --> 00:23:19,563\nthat a view controller can't be freed when it comes off.\n\n452\n00:23:19,565 --> 00:23:22,032\nOkay? So we can do exactly what we talked about before.\n\n453\n00:23:22,034 --> 00:23:26,704\nWe can create, for example, unowned. Me equals self, how\n\n454\n00:23:26,706 --> 00:23:29,573\nabout that one? Okay? Don't forget the in right here.\n\n455\n00:23:29,575 --> 00:23:32,543\nOkay? All this stuff has to go before the in, all right?\n\n456\n00:23:32,545 --> 00:23:34,745\nA closure in. So if we do that, and\n\n457\n00:23:34,747 --> 00:23:38,282\nnow we say, me, okay? So me, right here, is unowned.\n\n458\n00:23:38,284 --> 00:23:40,451\nSo, it's not going to keep anything in the heap.\n\n459\n00:23:40,453 --> 00:23:42,520\nAll right, and we know it's safe here because we're\n\n460\n00:23:42,522 --> 00:23:44,989\nthe view controller. We own the brain. So, there's no way\n\n461\n00:23:44,991 --> 00:23:50,094\nthat we're gonna get thrown out before the brain. So,\n\n462\n00:23:50,096 --> 00:23:53,597\nlet's run it again. So, here's calculate,\n\n463\n00:23:53,599 --> 00:23:57,902\n81 square root, okay, the red is still working,\n\n464\n00:23:57,904 --> 00:24:02,506\nback, left the heap Okay, working good. See that?\n\n465\n00:24:02,508 --> 00:24:06,677\nAll right, now another way we could've done it here instead\n\n466\n00:24:06,679 --> 00:24:10,781\nof unowned is we could've said weakSelf = self, okay.\n\n467\n00:24:10,783 --> 00:24:12,716\nSo, this is a weak variable right here.\n\n468\n00:24:12,718 --> 00:24:16,120\nIt's going to be an optional. In fact, if I look at it, see,\n\n469\n00:24:16,122 --> 00:24:17,588\nit's an optional view controller,\n\n470\n00:24:17,590 --> 00:24:19,390\nyou see that? Optional view controller, so\n\n471\n00:24:19,392 --> 00:24:22,626\nright here it's complaining, you can't send display to,\n\n472\n00:24:22,628 --> 00:24:25,529\noops, this was weakSelf, it would be complaining. You\n\n473\n00:24:25,531 --> 00:24:29,300\ncan't send display to weakSelf because it's an optional, see?\n\n474\n00:24:29,302 --> 00:24:32,336\nAnd it's asking do you want to put exclamation point? But\n\n475\n00:24:32,338 --> 00:24:36,373\nI'm gonna be more conservative and just put a question mark\n\n476\n00:24:36,375 --> 00:24:38,476\nright here, just in case this ever did get to be nil,\n\n477\n00:24:38,478 --> 00:24:41,645\nI just want this line of code not to happen. Okay, so,\n\n478\n00:24:41,647 --> 00:24:50,087\nlet's see if that fixes our problem. All right, Calculate,\n\n479\n00:24:50,089 --> 00:24:54,158\nBack, Calculate, Back, Calculate, and Square root.\n\n480\n00:24:54,160 --> 00:24:58,629\nStill turning it red. Okay, now, you are probably going to\n\n481\n00:24:58,631 --> 00:25:00,998\nbe using functions. I would imagine your assignment three\n\n482\n00:25:01,000 --> 00:25:05,970\nand closures too probably. I'm not going to require that you\n\n483\n00:25:05,972 --> 00:25:07,671\nnot have memory loops. In other words, you are allowed\n\n484\n00:25:07,673 --> 00:25:10,908\nto have these memory cycles in your assignment three, but\n\n485\n00:25:10,910 --> 00:25:12,710\nif you want to try and fix it in your assignment three,\n\n486\n00:25:12,712 --> 00:25:15,980\nyou are welcome to. Okay? I never ask you to do anything\n\n487\n00:25:15,982 --> 00:25:17,481\nin your assignment that I didn't teach you\n\n488\n00:25:17,483 --> 00:25:18,916\nin class before I gave you the assignment.\n\n489\n00:25:18,918 --> 00:25:21,185\nSo this is after I gave you the assignment so\n\n490\n00:25:21,187 --> 00:25:23,988\nit's totally optional if you want to fix it. But\n\n491\n00:25:23,990 --> 00:25:27,057\notherwise it's likely you probably will have a memory\n\n492\n00:25:27,059 --> 00:25:30,394\ncycle in your assignment three. It's possible you won't\n\n493\n00:25:30,396 --> 00:25:34,999\nbut likely you would if you don't do this. Okay?\n\n494\n00:25:35,001 --> 00:25:37,902\nAny questions about that? All right,\n\n495\n00:25:37,904 --> 00:25:44,708\nback to our slides. Okay, the next thing we're talk\n\n496\n00:25:44,710 --> 00:25:48,746\nabout is a cool little Swift feature called extensions.\n\n497\n00:25:48,748 --> 00:25:52,416\nOkay, extensions allow you to add methods and\n\n498\n00:25:52,418 --> 00:25:56,520\nproperties to other classes, even if you don't have\n\n499\n00:25:56,522 --> 00:25:59,023\nthe source code to the other classes. So, for\n\n500\n00:25:59,025 --> 00:26:01,892\nexample you can add it to classes in UIkit.\n\n501\n00:26:01,894 --> 00:26:05,863\nOkay. You could add a method to UIbutton or, in this case,\n\n502\n00:26:05,865 --> 00:26:09,700\nI've added a method to UIViewController. Okay. So\n\n503\n00:26:09,702 --> 00:26:12,636\nwhen I add this method, it's available all throughout my\n\n504\n00:26:12,638 --> 00:26:16,473\napp. All view controllers will now have this method. Okay,\n\n505\n00:26:16,475 --> 00:26:19,343\nnow what this is example this method I did right here? Well,\n\n506\n00:26:19,345 --> 00:26:21,845\nremember and when we're doing prepare for segway and\n\n507\n00:26:21,847 --> 00:26:25,416\nwe wanna handle the case where we put the detail of the split\n\n508\n00:26:25,418 --> 00:26:28,218\nview controller into a navigation controller. And so,\n\n509\n00:26:28,220 --> 00:26:31,221\nwhen the segue happens we have to look inside the navigation\n\n510\n00:26:31,223 --> 00:26:32,990\ncontroller. Remember that? And we had this\n\n511\n00:26:32,992 --> 00:26:36,026\nlittle code right here if let navcon equal\n\n512\n00:26:36,028 --> 00:26:38,696\nthe destination ViewController as NavigationController,\n\n513\n00:26:38,698 --> 00:26:40,431\nthen return the visibleViewController\n\n514\n00:26:40,433 --> 00:26:41,165\nremember all that business?\n\n515\n00:26:41,167 --> 00:26:43,968\nWell I'm just gonna add that inside of a method here in\n\n516\n00:26:43,970 --> 00:26:46,937\nViewController called contentViewController. So,\n\n517\n00:26:46,939 --> 00:26:48,572\nif I ask a ViewController what's your\n\n518\n00:26:48,574 --> 00:26:51,976\ncontentViewController? Well if it's a NavigationController\n\n519\n00:26:51,978 --> 00:26:54,712\nit's gonna give me the visibleViewController. Okay?\n\n520\n00:26:54,714 --> 00:26:56,347\nIf it's any other ViewController it's looking\n\n521\n00:26:56,349 --> 00:26:59,283\nto be itself cuz itself is the content.\n\n522\n00:26:59,285 --> 00:27:02,019\nThat way, whether it's in the ViewNavigationController or\n\n523\n00:27:02,021 --> 00:27:05,055\nnot, I'm gonna get the thing that I intend, the content\n\n524\n00:27:05,057 --> 00:27:08,125\nthat I'm trying to get at. Everyone understand that?\n\n525\n00:27:08,127 --> 00:27:10,494\nSo that makes you prepareForSegue instead of\n\n526\n00:27:10,496 --> 00:27:13,297\nlooking like this where you got this destination and\n\n527\n00:27:13,299 --> 00:27:15,799\nall this you can actually make this into a one-liner.\n\n528\n00:27:15,801 --> 00:27:17,768\nYou can get rid of all this and make a one-liner. So,\n\n529\n00:27:17,770 --> 00:27:20,137\nlet's see if we can understand this. Ready? Here we go. We're\n\n530\n00:27:20,139 --> 00:27:24,141\ngoing to save the Segue's destination ViewController,\n\n531\n00:27:24,143 --> 00:27:29,413\nit's contentViewController, as, my ViewController.\n\n532\n00:27:29,415 --> 00:27:31,649\nIf I can do that, then I'm good to go. See, so,\n\n533\n00:27:31,651 --> 00:27:36,987\nyou see how this simplified this code really nicely. Now,\n\n534\n00:27:36,989 --> 00:27:39,056\nextensions you got to be a little careful with.\n\n535\n00:27:39,058 --> 00:27:42,292\nThey could be abused. Okay. You start adding all\n\n536\n00:27:42,294 --> 00:27:44,595\nthese wacky methods to class, it makes no sense.\n\n537\n00:27:44,597 --> 00:27:47,598\nYou're still object on your programmers if you're gonna\n\n538\n00:27:47,600 --> 00:27:49,066\nadd a method to UIViewController,\n\n539\n00:27:49,068 --> 00:27:52,036\nit better makes sense as a UIViewController method.\n\n540\n00:27:52,038 --> 00:27:54,672\nOkay, it shouldn't be some calculator method,\n\n541\n00:27:54,674 --> 00:27:56,240\nokay this has nothing to do with calculators.\n\n542\n00:27:56,242 --> 00:27:59,643\nIt has everything to do with UIViewControllers, okay.\n\n543\n00:27:59,645 --> 00:28:02,279\nSo, if you use extensions, use them wisely,\n\n544\n00:28:02,281 --> 00:28:06,750\nuse them in an object oriented fashion. Okay? Now,\n\n545\n00:28:06,752 --> 00:28:11,088\ninside of an extension, notice that you can refer to self.\n\n546\n00:28:11,090 --> 00:28:13,691\nSelf of course means the UIViewController you sent\n\n547\n00:28:13,693 --> 00:28:17,761\nthis to. Just like self would mean if you had a method,\n\n548\n00:28:17,763 --> 00:28:20,197\nin UIViewController that was in that class.\n\n549\n00:28:20,199 --> 00:28:25,202\nOkay? Couple of interesting restrictions on\n\n550\n00:28:25,204 --> 00:28:28,305\nextensions. By the way, you can extend classes,\n\n551\n00:28:28,307 --> 00:28:31,408\nstructs and enums. Okay, all of them are extensible.\n\n552\n00:28:31,410 --> 00:28:35,713\nYou can't re-implement any methods or properties. It's\n\n553\n00:28:35,715 --> 00:28:38,649\nnot re-implement thing, okay? It's an additional thing.\n\n554\n00:28:38,651 --> 00:28:41,118\nYou can add methods, but you can't re-implement.\n\n555\n00:28:41,120 --> 00:28:45,022\nOkay? Also any properties that you add have to be computed\n\n556\n00:28:45,024 --> 00:28:47,157\nproperties like that content view controller was.\n\n557\n00:28:47,159 --> 00:28:50,861\nYou can't have any storage with your extension. Okay,\n\n558\n00:28:50,863 --> 00:28:54,098\nextension is purely for adding code, no storage.\n\n559\n00:28:54,100 --> 00:28:57,601\nAll right, this feature I say is easily abused because you\n\n560\n00:28:57,603 --> 00:29:00,504\ncan add all kinds of non objected oriented methods and\n\n561\n00:29:00,506 --> 00:29:03,707\nstuff like that, but actually this feature can be really\n\n562\n00:29:03,709 --> 00:29:06,877\npowerful for organizing and structuring your code.\n\n563\n00:29:06,879 --> 00:29:10,447\nOkay? And it's really beyond the scope for this class for\n\n564\n00:29:10,449 --> 00:29:13,417\nme to show you how you could use extensions in terms of\n\n565\n00:29:13,419 --> 00:29:17,121\nbuilding your kind of code infrastructure in your app,\n\n566\n00:29:17,123 --> 00:29:18,455\nbut know that it's possible.\n\n567\n00:29:18,457 --> 00:29:21,125\nBecause if you go out there in the real world and\n\n568\n00:29:21,127 --> 00:29:25,229\nyou start building big apps, extensions are a great way to\n\n569\n00:29:25,231 --> 00:29:28,031\nkind of divide up big complicated classes,\n\n570\n00:29:28,033 --> 00:29:32,269\ninto sensible sub-pieces that are each extensions.\n\n571\n00:29:32,271 --> 00:29:33,370\nAlso, if you have protocols,\n\n572\n00:29:33,372 --> 00:29:35,339\nwhich I'm going to talk about later in this lecture,\n\n573\n00:29:35,341 --> 00:29:38,208\nextensions are a great way to implement a protocol\n\n574\n00:29:38,210 --> 00:29:40,744\nin a class, so you'll see what that means in a minute.\n\n575\n00:29:40,746 --> 00:29:43,747\nOkay, for now you can use extensions in your homework or\n\n576\n00:29:43,749 --> 00:29:47,184\nwhatever, but use it more along the lines of the content\n\n577\n00:29:47,186 --> 00:29:48,318\nview controller example right?\n\n578\n00:29:48,320 --> 00:29:50,621\nSmall utility functions that make sense,\n\n579\n00:29:50,623 --> 00:29:54,057\nthat kind of thing okay? Maybe for your final project if you\n\n580\n00:29:54,059 --> 00:29:57,861\nwant to read up on how you can use extensions to build your\n\n581\n00:29:57,863 --> 00:29:59,129\ncode base you can try it then,\n\n582\n00:29:59,131 --> 00:30:00,631\nbut on your homework assignments let's stick to the\n\n583\n00:30:00,633 --> 00:30:04,468\nlittle stuff, okay? All right, so I mentioned protocols,\n\n584\n00:30:04,470 --> 00:30:08,405\nlet's talk about protocols. Protocols are a way to express\n\n585\n00:30:08,407 --> 00:30:12,743\nan API more concisely, okay? Protocols are another type,\n\n586\n00:30:12,745 --> 00:30:14,545\ntheir the last type I'm going to talk about, okay?\n\n587\n00:30:14,547 --> 00:30:16,413\nWe've talked about classes, enoms, strucks,\n\n588\n00:30:16,415 --> 00:30:19,049\nnow we're gonna talk about, and functions, those are also\n\n589\n00:30:19,051 --> 00:30:21,485\na type, now we're going to talk about protocols, okay,\n\n590\n00:30:21,487 --> 00:30:26,523\nthe last type. What a protocol does is it lets you have\n\n591\n00:30:26,525 --> 00:30:29,960\nan API where instead of having to specify the full class or\n\n592\n00:30:29,962 --> 00:30:32,729\nstruct that you're going to be using to do whatever\n\n593\n00:30:32,731 --> 00:30:35,566\nyou are going to do. You can just specify what it is about\n\n594\n00:30:35,568 --> 00:30:39,403\nthat class or struct that you actually need, okay, and\n\n595\n00:30:39,405 --> 00:30:42,139\nyou do this with a protocol. And a protocol is simply\n\n596\n00:30:42,141 --> 00:30:46,810\na collection of method and property declarations. Okay,\n\n597\n00:30:46,812 --> 00:30:48,946\nso it's just like a little bundle of methods,\n\n598\n00:30:48,948 --> 00:30:52,482\nand you can have part of your API that says I want something\n\n599\n00:30:52,484 --> 00:30:54,785\nthat implements this bundle of methods. And\n\n600\n00:30:54,787 --> 00:30:57,588\nit can be any kind of struct, enum, class, whatever as\n\n601\n00:30:57,590 --> 00:30:59,756\nlong as long as it implements those little methods.\n\n602\n00:30:59,758 --> 00:31:02,159\nOkay, and that's what the protocol is all about.\n\n603\n00:31:02,161 --> 00:31:04,595\nSo, it's a type, anywhere you can use\n\n604\n00:31:04,597 --> 00:31:07,064\na type, you can use a protocol. So, any like I might\n\n605\n00:31:07,066 --> 00:31:10,200\nhave an argument to a function that takes a UIViewController,\n\n606\n00:31:10,202 --> 00:31:13,170\nit could also take a protocol, okay, that has a few methods\n\n607\n00:31:13,172 --> 00:31:15,973\nin UIViewController that I needed. So then it wouldn't be\n\n608\n00:31:15,975 --> 00:31:17,708\nso restrictive and have to be a UIViewController,\n\n609\n00:31:17,710 --> 00:31:20,944\nit could just be something that implements those methods.\n\n610\n00:31:20,946 --> 00:31:23,447\nOkay, anywhere you can use a TYPE you can use a protocol.\n\n611\n00:31:23,449 --> 00:31:27,818\nOkay, the implementation of a protocol happens in the class\n\n612\n00:31:27,820 --> 00:31:32,556\nthat implements the protocol. The class or struct or\n\n613\n00:31:32,558 --> 00:31:34,391\nenum that implements the protocol. Okay,\n\n614\n00:31:34,393 --> 00:31:36,560\nthe protocol itself doesn't have any implementation.\n\n615\n00:31:36,562 --> 00:31:40,430\nThe protocol itself is just a declaration of the properties\n\n616\n00:31:40,432 --> 00:31:44,835\nand methods. Okay? Now, it is possible however,\n\n617\n00:31:44,837 --> 00:31:50,173\nto use extensions to implement some or all of a protocol.\n\n618\n00:31:50,175 --> 00:31:52,276\nSo, you just say extension, protocol,\n\n619\n00:31:52,278 --> 00:31:54,111\ninstead of saying extension class name.\n\n620\n00:31:54,113 --> 00:31:56,747\nWhatever, you say extension protocol open curly brace and\n\n621\n00:31:56,749 --> 00:32:00,851\nimplement some of the methods. Or properties in the protocol.\n\n622\n00:32:00,853 --> 00:32:05,022\nOkay, now protocols just like extensions can have\n\n623\n00:32:05,024 --> 00:32:08,125\nno storage, okay. Protocol can have no storage and\n\n624\n00:32:08,127 --> 00:32:10,994\nextensions can have no storage either. So there's no way to\n\n625\n00:32:10,996 --> 00:32:14,965\nimplement some of the protocol with any storage, no vars,\n\n626\n00:32:14,967 --> 00:32:18,802\nokay. You can have vars but they have to be computed.\n\n627\n00:32:18,804 --> 00:32:22,906\nOkay, so no storage in protocols or extensions.\n\n628\n00:32:22,908 --> 00:32:25,976\nAll right, so there's four aspects to using a protocol.\n\n629\n00:32:25,978 --> 00:32:27,811\nOne is the protocol declaration.\n\n630\n00:32:27,813 --> 00:32:29,746\nThat's where you declare what methods and\n\n631\n00:32:29,748 --> 00:32:30,981\nproperties are in this protocol.\n\n632\n00:32:30,983 --> 00:32:33,817\nThen there's the declaration where a class, a struct or\n\n633\n00:32:33,819 --> 00:32:38,221\nan enum says, I implement this protocol. So,\n\n634\n00:32:38,223 --> 00:32:39,656\nit's not good enough if you're a class or\n\n635\n00:32:39,658 --> 00:32:42,292\nstruct enum to just implement the methods or\n\n636\n00:32:42,294 --> 00:32:42,426\nthe property there.\n\n637\n00:32:42,428 --> 00:32:44,928\nYou have to actually declare I implement this,\n\n638\n00:32:44,930 --> 00:32:47,531\nthen you have to go implement all the methods and\n\n639\n00:32:47,533 --> 00:32:50,701\nproperties as well. Okay, and we'll show you how to do that.\n\n640\n00:32:50,703 --> 00:32:53,437\nThen there's the code that implements the protocol and\n\n641\n00:32:53,439 --> 00:32:58,442\nthat's usually going to be, in the class structure enum that\n\n642\n00:32:58,444 --> 00:32:59,576\nsaid it was going to implement it.\n\n643\n00:32:59,578 --> 00:33:02,713\nBut it could also be in an extension, okay?\n\n644\n00:33:02,715 --> 00:33:04,681\nIt can either be an extension to the protocol or\n\n645\n00:33:04,683 --> 00:33:06,416\nit could be an extension to the class, struct or\n\n646\n00:33:06,418 --> 00:33:09,586\nenum. Okay? You could have implementation in there.\n\n647\n00:33:09,588 --> 00:33:10,921\nAgain, no storage though.\n\n648\n00:33:10,923 --> 00:33:12,856\nSo if you need storage to implement it,\n\n649\n00:33:12,858 --> 00:33:16,460\nthat's gonna have to be inside the class, struct or enum.\n\n650\n00:33:16,462 --> 00:33:18,929\nAll right. Optional methods in a protocol.\n\n651\n00:33:18,931 --> 00:33:21,732\nThis one's a little bit tricky, okay, in Swift,\n\n652\n00:33:21,734 --> 00:33:27,104\nprotocols all the properties, all the methods are required.\n\n653\n00:33:27,106 --> 00:33:30,507\nIf you say you implement that protocol, you must implement\n\n654\n00:33:30,509 --> 00:33:33,677\nall of the protocol. You ca't just pick and choose.\n\n655\n00:33:33,679 --> 00:33:37,214\nHowever in Objective C, it had something called protocols.\n\n656\n00:33:37,216 --> 00:33:40,817\nOkay, and in Objective C things could be optional. So\n\n657\n00:33:40,819 --> 00:33:43,854\nin Objective C, you could put the word optional in front of.\n\n658\n00:33:43,856 --> 00:33:45,922\nSo you could say like optional func, whatever.\n\n659\n00:33:45,924 --> 00:33:47,391\nAnd it would mean that in this protocol,\n\n660\n00:33:47,393 --> 00:33:49,426\nyou could still say you implement this protocol and\n\n661\n00:33:49,428 --> 00:33:52,729\nyou don't have to implement this one. It's optional, okay?\n\n662\n00:33:52,731 --> 00:33:58,602\nThat was Objective C only. Now, I was used Objective C.\n\n663\n00:33:58,604 --> 00:33:59,836\nIt was written in Objective C and\n\n664\n00:33:59,838 --> 00:34:02,139\nuses this optional protocol stuff a lot. Okay, and\n\n665\n00:34:02,141 --> 00:34:05,609\nI'm gonna talk about how it uses it in a moment here. And\n\n666\n00:34:05,611 --> 00:34:08,979\nso Swift has to have this mechanism. And so the way\n\n667\n00:34:08,981 --> 00:34:13,517\nit does this is it lets you declare protocols to be @objc\n\n668\n00:34:13,519 --> 00:34:18,722\ncompliant. You just say @objc space protocol, whatever.\n\n669\n00:34:18,724 --> 00:34:22,492\nAnd that means this protocol is an objc compliant one. And\n\n670\n00:34:22,494 --> 00:34:27,297\ninside that kind of protocol, you can use the word optional\n\n671\n00:34:27,299 --> 00:34:31,468\nin front of any of the funcs or vars in there. To say this\n\n672\n00:34:31,470 --> 00:34:33,870\nis optional so that someone who implements that protocol\n\n673\n00:34:33,872 --> 00:34:37,407\ndoes not have to implement those optional things, okay?\n\n674\n00:34:37,409 --> 00:34:39,509\nThis is used in iOS for something called delegation\n\n675\n00:34:39,511 --> 00:34:43,346\nand we'll talk all about that. One thing that's interesting\n\n676\n00:34:43,348 --> 00:34:45,849\nis that any optional protocol implementing class.\n\n677\n00:34:45,851 --> 00:34:48,151\nSo if you're class and it implements a protocol,\n\n678\n00:34:48,153 --> 00:34:50,887\nan Objective C protocol. With these optional things must\n\n679\n00:34:50,889 --> 00:34:54,091\ninherit from NSObject, so this is the second time I'm telling\n\n680\n00:34:54,093 --> 00:34:56,793\nyou. Sometimes a class can't, a Swift class cant\n\n681\n00:34:56,795 --> 00:34:59,896\ninherit from nothing, you have to inherit from NSObject or\n\n682\n00:34:59,898 --> 00:35:03,733\nfrom a class that inherits from NSObject. Okay? So\n\n683\n00:35:03,735 --> 00:35:05,802\ncuz it's all part of this Objective C runtime and\n\n684\n00:35:05,804 --> 00:35:08,738\nthat class has to be available in the Objective C runtime.\n\n685\n00:35:08,740 --> 00:35:12,175\nJust like the protocol has to be available in\n\n686\n00:35:12,177 --> 00:35:13,643\nthe Objective C runtime,\n\n687\n00:35:13,645 --> 00:35:17,481\nokay? So that's the optional thing there.\n\n688\n00:35:17,483 --> 00:35:20,083\nAll right, so here is what the syntax looks like, here I'm\n\n689\n00:35:20,085 --> 00:35:24,154\ndeclaring a protocol, it's called some protocol. Okay?\n\n690\n00:35:24,156 --> 00:35:27,390\nSee it has, looks just like doing a class, right? Class,\n\n691\n00:35:27,392 --> 00:35:30,594\nsomeclass, enum, someenum, protocol, someproperty.\n\n692\n00:35:30,596 --> 00:35:33,196\nExactly the same. And then there's the curly braces and\n\n693\n00:35:33,198 --> 00:35:36,933\nthen there's these methods inside. Notice that you can\n\n694\n00:35:36,935 --> 00:35:41,471\nhave inheritance, in fact multiple inheritance for\n\n695\n00:35:41,473 --> 00:35:46,810\nprotocols. All right? Now, Swift is a single inheritance\n\n696\n00:35:46,812 --> 00:35:49,446\nmodel for classes, but for protocols, it's multiple\n\n697\n00:35:49,448 --> 00:35:53,083\ninheritance. What does it mean for a protocol to inherit from\n\n698\n00:35:53,085 --> 00:35:56,286\nanother protocol? Well, it just means that some property,\n\n699\n00:35:56,288 --> 00:35:59,055\nokay, some protocol, anyone who implements some protocol\n\n700\n00:35:59,057 --> 00:36:02,359\nalso has to implement all of these protocols as well.\n\n701\n00:36:02,361 --> 00:36:04,161\nInheritedProtocol1, InheritedProtocol2,\n\n702\n00:36:04,163 --> 00:36:06,596\nit's gotta implement those as well. So it's required,\n\n703\n00:36:06,598 --> 00:36:09,799\nthe requirement goes all the way through, okay, that's what\n\n704\n00:36:09,801 --> 00:36:13,470\nmultiple inheritance means there. Okay, inside here when\n\n705\n00:36:13,472 --> 00:36:17,707\nyou have a var, okay, remember this has to be, in here you\n\n706\n00:36:17,709 --> 00:36:21,645\nhave to specify whether it's a get only or get and set. You\n\n707\n00:36:21,647 --> 00:36:23,947\ncan do that with this little curly brace syntax here,\n\n708\n00:36:23,949 --> 00:36:26,683\nit could either have the word get in here or get space set.\n\n709\n00:36:26,685 --> 00:36:30,654\nThere's no such thing as a set only property, okay? Get or\n\n710\n00:36:30,656 --> 00:36:35,759\nget and set. Any functions that are mutated,\n\n711\n00:36:35,761 --> 00:36:36,660\nthey will mutate this thing.\n\n712\n00:36:36,662 --> 00:36:39,763\nThey're expected to mutate it. Have to be marked mutating and\n\n713\n00:36:39,765 --> 00:36:42,732\nthis is because struct can be allowed to implement these\n\n714\n00:36:42,734 --> 00:36:45,669\nprotocols. And we know that structs that have methods that\n\n715\n00:36:45,671 --> 00:36:48,038\nmutate themselves have to be declared mutating. So\n\n716\n00:36:48,040 --> 00:36:51,374\nwe have to do the same thing in the protocol here as well.\n\n717\n00:36:52,377 --> 00:36:55,979\nNow it is possible to restrict your protocol by the way to be\n\n718\n00:36:55,981 --> 00:36:58,215\nonly for classes. In other words, enums and\n\n719\n00:36:58,217 --> 00:37:00,784\nstructs are not allowed to implement it. You do that by\n\n720\n00:37:00,786 --> 00:37:03,920\nputting colon class comma right after the protocol\n\n721\n00:37:03,922 --> 00:37:07,824\nbefore all the inherited ones, you just put class comma.\n\n722\n00:37:07,826 --> 00:37:11,127\nOkay? That means this protocol is only for classes.\n\n723\n00:37:11,129 --> 00:37:12,896\nThen you would not need mutating, okay,\n\n724\n00:37:12,898 --> 00:37:17,434\ncuz we don't use mutating for classes. You can even\n\n725\n00:37:17,436 --> 00:37:19,703\nspecify initializers in your protocol. And\n\n726\n00:37:19,705 --> 00:37:23,974\nthat's basically saying anyone who implements this protocol\n\n727\n00:37:23,976 --> 00:37:27,844\nhas to have an initializer that looks like this, right?\n\n728\n00:37:27,846 --> 00:37:32,415\nOkay, now, you have this protocol declared with all\n\n729\n00:37:32,417 --> 00:37:37,520\nthe vars and funcs in there. How do you implement it, okay?\n\n730\n00:37:37,522 --> 00:37:38,989\nWell, a class or a structure or\n\n731\n00:37:38,991 --> 00:37:43,760\nenum comes along and it says at the end of its, after,\n\n732\n00:37:43,762 --> 00:37:45,495\nin the class' case after it says what its super\n\n733\n00:37:45,497 --> 00:37:49,266\nclass is. It puts a comma and says here's all the protocols\n\n734\n00:37:49,268 --> 00:37:52,369\nI implement. And when it says these other protocols\n\n735\n00:37:52,371 --> 00:37:54,604\nover here, it's promising to implement them. And\n\n736\n00:37:54,606 --> 00:37:57,774\nthe compiler will not let it get away with not implementing\n\n737\n00:37:57,776 --> 00:38:02,679\nthem, it will complain, okay? So simple as that.\n\n738\n00:38:02,681 --> 00:38:04,581\nIf you have an enum or structs,\n\n739\n00:38:04,583 --> 00:38:07,517\nlike here's an enum, there's no superclass obviously, but\n\n740\n00:38:07,519 --> 00:38:11,588\notherwise it looks the same. Right? So this enum is saying\n\n741\n00:38:11,590 --> 00:38:14,257\nI'm gonna implement these two protocols. Same thing with\n\n742\n00:38:14,259 --> 00:38:16,593\nthis struct, it's saying I'm gonna implement these. And\n\n743\n00:38:16,595 --> 00:38:18,295\nobviously if there are any mutating ones in here,\n\n744\n00:38:18,297 --> 00:38:21,865\nit's gonna have to be mutating in there. Okay?\n\n745\n00:38:21,867 --> 00:38:25,235\nThere's no limit to the number of protocols that a class or\n\n746\n00:38:25,237 --> 00:38:30,073\nstruct or enum can implement, can do as many as they want.\n\n747\n00:38:30,075 --> 00:38:33,376\nIf you have a init as part of the protocol and\n\n748\n00:38:33,378 --> 00:38:36,713\na class is implementing it, it has to make that init\n\n749\n00:38:36,715 --> 00:38:40,483\nrequired. Okay, that's because you wouldn't want\n\n750\n00:38:40,485 --> 00:38:44,354\nthis class to have a subclass that doesn't implement this.\n\n751\n00:38:44,356 --> 00:38:47,223\nNow it would not implement the protocol anymore. And yet\n\n752\n00:38:47,225 --> 00:38:51,428\nit inherits the fact that it has to implement the protocol.\n\n753\n00:38:51,430 --> 00:38:51,861\nSo, there's init,\n\n754\n00:38:51,863 --> 00:38:56,566\nthat's why you have to have this be required, okay? You\n\n755\n00:38:56,568 --> 00:38:59,669\nare allowed to add protocol conformance via an extension.\n\n756\n00:38:59,671 --> 00:39:02,639\nSo you could have extension to something, let's say this is\n\n757\n00:39:02,641 --> 00:39:06,776\na struct or a class or an enum colon some protocol and\n\n758\n00:39:06,778 --> 00:39:10,547\nthen put the methods in here. So now I'm extending that\n\n759\n00:39:10,549 --> 00:39:14,718\nclass or struct or enum to implement this protocol. And\n\n760\n00:39:14,720 --> 00:39:17,554\nthat just allows you to put this code off in another file,\n\n761\n00:39:17,556 --> 00:39:20,123\nfor example, you don't have to put it in the same file. Or\n\n762\n00:39:20,125 --> 00:39:21,925\nyou might be, this might be a class\n\n763\n00:39:21,927 --> 00:39:23,360\nyou don't have the source code for.\n\n764\n00:39:23,362 --> 00:39:24,094\nMaybe this is a UI kit thing,\n\n765\n00:39:24,096 --> 00:39:26,596\nmaybe you're extending UI button to implement some\n\n766\n00:39:26,598 --> 00:39:29,866\nprotocol. You could do that with an extension, you see?\n\n767\n00:39:29,868 --> 00:39:31,968\nAnd that saves you having to for example,\n\n768\n00:39:31,970 --> 00:39:35,138\nsubclass UI button to add protocol conformance. Just use\n\n769\n00:39:35,140 --> 00:39:39,309\nan extension. Okay, it's all really very well thought out.\n\n770\n00:39:39,311 --> 00:39:41,211\nThey did a really good job with Swift with protocols and\n\n771\n00:39:41,213 --> 00:39:44,381\nextensions. Protocols are a really important part of\n\n772\n00:39:44,383 --> 00:39:47,350\nsophisticated Swift programming. If you're really\n\n773\n00:39:47,352 --> 00:39:50,720\ngonna build powerful complex things, you really have to be\n\n774\n00:39:50,722 --> 00:39:53,890\nfacile with protocols. Because protocols really\n\n775\n00:39:53,892 --> 00:39:56,793\ngive it the heart of what the API contract is\n\n776\n00:39:56,795 --> 00:39:59,929\nbetween things. Okay, it's really talking about,\n\n777\n00:39:59,931 --> 00:40:02,699\nthese are the methods and functions I expect you to\n\n778\n00:40:02,701 --> 00:40:05,535\nimplement if you're gonna work with me, okay.\n\n779\n00:40:05,537 --> 00:40:06,403\nThat's what a protocol all about.\n\n780\n00:40:06,405 --> 00:40:09,639\nAnd that's fundamentally good object-oriented programming,\n\n781\n00:40:09,641 --> 00:40:11,441\nfundamentally good encapsulation, so\n\n782\n00:40:11,443 --> 00:40:13,176\nyou really wanna understand this.\n\n783\n00:40:13,178 --> 00:40:14,244\nNow, this is a beginning,\n\n784\n00:40:14,246 --> 00:40:16,746\nstarting class in iOS so I don't expect you to\n\n785\n00:40:16,748 --> 00:40:19,449\nhave mastered this by the end. But again, it's something you\n\n786\n00:40:19,451 --> 00:40:21,484\ngotta know that if you go out in the real world,\n\n787\n00:40:21,486 --> 00:40:22,819\nand start a program people are gonna\n\n788\n00:40:22,821 --> 00:40:25,021\nexpect if you're gonna be a sophisticated programmer.\n\n789\n00:40:25,023 --> 00:40:27,357\nIt's like you're gonna know how to use protocols, and\n\n790\n00:40:27,359 --> 00:40:28,792\nnot just make everything a class.\n\n791\n00:40:28,794 --> 00:40:31,961\nOkay all the courses you've had before now probably,\n\n792\n00:40:31,963 --> 00:40:34,063\neverything's a class. Okay it's a Java thing,\n\n793\n00:40:34,065 --> 00:40:36,666\neverything's a class. Now in the real world out there\n\n794\n00:40:36,668 --> 00:40:38,635\nyou're probably gonna have a lot of protocols.\n\n795\n00:40:38,637 --> 00:40:43,139\nOkay, question? >> In what case would you\n\n796\n00:40:43,141 --> 00:40:46,543\nuse a protocol other than extension?\n\n797\n00:40:46,545 --> 00:40:46,843\n>> Okay so this question is,\n\n798\n00:40:46,845 --> 00:40:49,245\nin what case would you use a protocol versus just\n\n799\n00:40:49,247 --> 00:40:51,981\nan extension for example, and that's a good question.\n\n800\n00:40:51,983 --> 00:40:55,852\nYou'd use a protocol anywhere you need to, specify that as\n\n801\n00:40:55,854 --> 00:41:00,957\na type in some API. Right, if you need to say the argument\n\n802\n00:41:00,959 --> 00:41:03,326\nto this method takes something that implements\n\n803\n00:41:03,328 --> 00:41:06,596\ncertain methods then you need that protocol type to say that\n\n804\n00:41:06,598 --> 00:41:10,867\nin your user data type. An extension is not its own type\n\n805\n00:41:10,869 --> 00:41:13,236\nit's just adding methods to an existing type.\n\n806\n00:41:13,238 --> 00:41:15,672\nSee the difference? So a protocol is a typing and\n\n807\n00:41:15,674 --> 00:41:20,410\nit's for strongly typing things. Okay, so,\n\n808\n00:41:20,412 --> 00:41:23,146\nlet's look at an example of protocols here.\n\n809\n00:41:23,148 --> 00:41:25,482\nI have a protocol called Moveable. Okay,\n\n810\n00:41:25,484 --> 00:41:29,452\nit has a mutating function called moveTo a certain point,\n\n811\n00:41:29,454 --> 00:41:33,156\nokay. That's its only method. And I have two classes, two,\n\n812\n00:41:33,158 --> 00:41:37,427\nnot classes, two data types here. A Car. It's a moveable.\n\n813\n00:41:37,429 --> 00:41:39,929\nSee? It implements moveTo. It doesn't have to say mutating\n\n814\n00:41:39,931 --> 00:41:43,333\ncuz it's a class. And I have a shape like a shape on screen.\n\n815\n00:41:43,335 --> 00:41:46,870\nIt's a triangle, a rectangle. Okay? It's moveable. Okay? And\n\n816\n00:41:46,872 --> 00:41:49,806\nit's mutating. Okay, and it's got, they've each got other\n\n817\n00:41:49,808 --> 00:41:52,942\nmethods like a car knows how to change the oil of a car.\n\n818\n00:41:52,944 --> 00:41:54,677\nAnd a shape knows how to draw the shape.\n\n819\n00:41:54,679 --> 00:41:58,515\nOkay. But, they share the fact that they're both moveable.\n\n820\n00:41:58,517 --> 00:42:01,518\nSo I can create a couple local variables here, a prius,\n\n821\n00:42:01,520 --> 00:42:04,087\nwhich is a car, initialized to a car here.\n\n822\n00:42:04,089 --> 00:42:06,556\nAnd let's say I have a square, which is a shape,\n\n823\n00:42:06,558 --> 00:42:08,691\nprobably this would be actually be square,\n\n824\n00:42:08,693 --> 00:42:09,526\nopen parentheses, closes parentheses,\n\n825\n00:42:09,528 --> 00:42:12,996\nprobably have a subclass or a different kind of, well,\n\n826\n00:42:12,998 --> 00:42:16,766\nlet's say it's a shape [LAUGH] okay. So we got a shape here.\n\n827\n00:42:16,768 --> 00:42:19,936\nBoth of these, okay the prius and the square, are each\n\n828\n00:42:19,938 --> 00:42:25,341\na local variable of their perspective type. Now I, and\n\n829\n00:42:25,343 --> 00:42:27,577\nso these, this is the method that's common to them all.\n\n830\n00:42:27,579 --> 00:42:32,282\nNow I can create a var called thingToMove which is of type\n\n831\n00:42:32,284 --> 00:42:35,985\nMoveable. That's its type. Okay, and I told you protocols\n\n832\n00:42:35,987 --> 00:42:39,589\ncould be type. And look, I can set this thing to moveTo\n\n833\n00:42:39,591 --> 00:42:43,293\na prius. Because a prius is a Moveable. Cuz it's a car.\n\n834\n00:42:43,295 --> 00:42:47,797\nYou see? So this is perfectly legal right here. And\n\n835\n00:42:47,799 --> 00:42:50,400\nI could even say thingToMove.moveTo, and\n\n836\n00:42:50,402 --> 00:42:54,137\nit'll call the car's version of moveTo, okay.\n\n837\n00:42:54,139 --> 00:43:01,377\nMake sense? However, I cannot say thingToMove.changeOil.\n\n838\n00:43:01,780 --> 00:43:05,148\nOkay? Why not? Prius is a car. Car can change oil.\n\n839\n00:43:05,150 --> 00:43:08,251\nHow come I can't say thingToMove change the oil?\n\n840\n00:43:08,820 --> 00:43:12,522\nBecause thingToMove is not a car,\n\n841\n00:43:12,524 --> 00:43:15,191\nit's a moveable. Okay? Moveables only know\n\n842\n00:43:15,193 --> 00:43:18,962\nhow to move. Now the fact that underlying there's an actual\n\n843\n00:43:18,964 --> 00:43:21,064\nthing a car in there that can do change oil, that's,\n\n844\n00:43:21,066 --> 00:43:23,433\nthat hasn't, it's irrelevant, okay. It has nothing to do it\n\n845\n00:43:23,435 --> 00:43:25,902\nwith because this thing is typed to only be a Moveable,\n\n846\n00:43:25,904 --> 00:43:32,008\nso you can only send moveable things to it. Okay? I could\n\n847\n00:43:32,010 --> 00:43:35,044\nalso say thingToMove, this same variable, equals square.\n\n848\n00:43:35,046 --> 00:43:38,014\nAlso perfectly legal, because a square is a shape,\n\n849\n00:43:38,016 --> 00:43:42,819\na shape is a Moveable. Okay? I could even create an array\n\n850\n00:43:42,821 --> 00:43:46,456\nof things to move that are moveables and\n\n851\n00:43:46,458 --> 00:43:48,324\nput the prius in the square in there.\n\n852\n00:43:48,326 --> 00:43:49,092\nOkay, so even though prius and\n\n853\n00:43:49,094 --> 00:43:50,159\nthe square are completely different things,\n\n854\n00:43:50,161 --> 00:43:53,796\na car and a shape, okay? They can live in this array because\n\n855\n00:43:53,798 --> 00:43:57,600\nthey're both moveables. This is an array of moveables,\n\n856\n00:43:57,602 --> 00:44:01,037\nokay? Now I could have a function here for\n\n857\n00:44:01,039 --> 00:44:04,040\nexample called slide which takes a slider or\n\n858\n00:44:04,042 --> 00:44:06,142\nthing to slide basically. And it's a moveable.\n\n859\n00:44:06,144 --> 00:44:09,379\nSo, with argument type here, this function is moveable.\n\n860\n00:44:09,381 --> 00:44:13,149\nAnd inside here, I could take slider move to some position.\n\n861\n00:44:13,151 --> 00:44:15,184\nAnd I don't care wether this is a car or shape.\n\n862\n00:44:15,186 --> 00:44:18,721\nThis function slide has no idea wether sliding a car or\n\n863\n00:44:18,723 --> 00:44:22,358\nsliding a shape. No idea. Cuz all it knows is it's working\n\n864\n00:44:22,360 --> 00:44:25,094\non a moveable. So that's how you could use a moveable as\n\n865\n00:44:25,096 --> 00:44:27,563\na type to an argument, of a function, okay.\n\n866\n00:44:27,565 --> 00:44:30,033\nAnd see, I can say slide(prius), slide(square),\n\n867\n00:44:30,035 --> 00:44:32,902\nworks perfectly, yeah. >> You said car [INAUDIBLE]\n\n868\n00:44:32,904 --> 00:44:36,272\ninto moveable it's another protocol.\n\n869\n00:44:36,274 --> 00:44:40,209\nCard could be seen as a little object as well\n\n870\n00:44:40,211 --> 00:44:42,578\nas the other. >> Yeah.\n\n871\n00:44:42,580 --> 00:44:45,848\nSo the question is, I think the question is if car\n\n872\n00:44:45,850 --> 00:44:48,117\nwas part of other protocols? >> Yeah.\n\n873\n00:44:48,119 --> 00:44:48,651\n>> Then could I set\n\n874\n00:44:48,653 --> 00:44:50,953\nsome variable that's of that other protocol equal to this?\n\n875\n00:44:50,955 --> 00:44:53,990\nAbsolutely I could. Because it is both removable and that\n\n876\n00:44:53,992 --> 00:44:56,793\nother thing. Independently it is both of those things.\n\n877\n00:44:56,795 --> 00:45:00,763\nAnd I can even have a protocol right here that's\n\n878\n00:45:00,765 --> 00:45:05,268\ntwo different things. Now this would mean that for something\n\n879\n00:45:05,270 --> 00:45:07,537\nto be passed to slip and slide through this variable.\n\n880\n00:45:07,539 --> 00:45:10,206\nIt would have to implement both of these protocols. So\n\n881\n00:45:10,208 --> 00:45:12,909\nit's almost like I'm inventing a protocol in this slot.\n\n882\n00:45:12,911 --> 00:45:15,044\nWith this syntax right here, it's almost like you're\n\n883\n00:45:15,046 --> 00:45:19,115\ninventing a protocol that inherits both of these.\n\n884\n00:45:19,117 --> 00:45:22,185\nOkay, so this means that it requires both that's what this\n\n885\n00:45:22,187 --> 00:45:24,353\nprotocol angle bracket means okay, and\n\n886\n00:45:24,355 --> 00:45:27,356\nthis could be any number of protocols in here. Now I can't\n\n887\n00:45:27,358 --> 00:45:31,494\nsay slipAndSlide(prius) here, because prius is not slippery.\n\n888\n00:45:31,496 --> 00:45:34,363\nIt's moveable but it's not slippery so it will not pass\n\n889\n00:45:34,365 --> 00:45:38,768\nthrough here, everybody got that? So that's protocol.\n\n890\n00:45:38,770 --> 00:45:41,437\nSuper powerful, you'll start to get a feel for\n\n891\n00:45:41,439 --> 00:45:44,240\nas we start using more and more. Now the first important\n\n892\n00:45:44,242 --> 00:45:46,909\nuse of protocol we're gonna talk about is Delegation.\n\n893\n00:45:46,911 --> 00:45:49,912\nAll right? So delegation is how we do this blind\n\n894\n00:45:49,914 --> 00:45:52,648\nstructured communication between our view and\n\n895\n00:45:52,650 --> 00:45:56,285\nour controller right there. And we talked about this very\n\n896\n00:45:56,287 --> 00:46:00,022\nsecond lecture, I think about how sometimes our view wants\n\n897\n00:46:00,024 --> 00:46:01,791\nto send message like, should I do this,\n\n898\n00:46:01,793 --> 00:46:05,828\nor I will do this like in the scroll view. I did scroll to\n\n899\n00:46:05,830 --> 00:46:09,766\nthis location, I will zoom to this zoom factor. Or\n\n900\n00:46:09,768 --> 00:46:12,869\nif I'm some data thing like a table, I'm gonna say, well\n\n901\n00:46:12,871 --> 00:46:16,005\nI've got a count of 400 rows, I want the data at row 7,\n\n902\n00:46:16,007 --> 00:46:20,276\nI want the data at row 12 through 20. Okay? These kind\n\n903\n00:46:20,278 --> 00:46:23,679\nof communications right here, you can see now with protocol,\n\n904\n00:46:23,681 --> 00:46:26,149\nit's really easy. You just create a protocol that has all\n\n905\n00:46:26,151 --> 00:46:29,285\nthese methods in it, and anybody can implement this.\n\n906\n00:46:29,287 --> 00:46:31,521\nEven though it's usually a controller, it doesn't have to\n\n907\n00:46:31,523 --> 00:46:33,923\nbe a controller. The controller for example could\n\n908\n00:46:33,925 --> 00:46:37,326\ninstantiate some other object that implements those methods.\n\n909\n00:46:37,328 --> 00:46:39,796\nOkay, it would still be a part of controller camp,\n\n910\n00:46:39,798 --> 00:46:41,631\nby the way, but it doesn't have to actually\n\n911\n00:46:41,633 --> 00:46:44,967\nbe a UIViewController sub-class anymore.\n\n912\n00:46:44,969 --> 00:46:49,539\nOkay, so let's see what that looks like. First some\n\n913\n00:46:49,541 --> 00:46:52,842\nview something in the view okay this generic remember\n\n914\n00:46:52,844 --> 00:46:55,678\nviews are generic minions okay of the controller.\n\n915\n00:46:55,680 --> 00:46:59,148\nThey declare some protocol which is the methods,\n\n916\n00:46:59,150 --> 00:47:00,049\nlike the will should did, or\n\n917\n00:47:00,051 --> 00:47:03,219\nthe data add count, those things that it wants somebody\n\n918\n00:47:03,221 --> 00:47:05,121\nelse like the controller to implement for it,\n\n919\n00:47:05,123 --> 00:47:07,356\nso it declares a protocol with all those methods and\n\n920\n00:47:07,358 --> 00:47:10,493\nproperties in it. Then the view's API, okay,\n\n921\n00:47:10,495 --> 00:47:13,896\nsomewhere in the view, it has a public property, okay, which\n\n922\n00:47:13,898 --> 00:47:20,303\nis weak delegate, and the type is this protocol it invented.\n\n923\n00:47:20,305 --> 00:47:22,972\nOkay so this is gonna be a var. Okay, that's going to\n\n924\n00:47:22,974 --> 00:47:25,808\nhave to be an object that implements that protocol and\n\n925\n00:47:25,810 --> 00:47:27,944\nit's weak because the view is kind of\n\n926\n00:47:27,946 --> 00:47:31,948\nsaying well if no one can do this will did should or can't\n\n927\n00:47:31,950 --> 00:47:34,750\ndo the count add data well I'll just sit here empty or I\n\n928\n00:47:34,752 --> 00:47:37,887\nwon't do what I do or I won't notify anyone of the wills and\n\n929\n00:47:37,889 --> 00:47:41,290\ndids. Okay, I won't ask anyone the shoulds. So it can be nil\n\n930\n00:47:41,292 --> 00:47:44,260\nso that's why the delegate is usually weak okay or\n\n931\n00:47:44,262 --> 00:47:47,396\nmight even be unowned but it's certainly not strong.\n\n932\n00:47:47,398 --> 00:47:50,900\nCuz you don't want the view to keep the controller in memory\n\n933\n00:47:50,902 --> 00:47:53,436\nright. The controller can keeps the view in memory but\n\n934\n00:47:53,438 --> 00:47:55,438\nyou don't want the view keeping the controller.\n\n935\n00:47:55,440 --> 00:47:58,441\nAll right, then the view uses this delegate property\n\n936\n00:47:58,443 --> 00:48:01,444\nany time it wants to send that will, should, did,\n\n937\n00:48:01,446 --> 00:48:03,946\ncount, data, add. It just sends it to this\n\n938\n00:48:03,948 --> 00:48:06,883\ndelegate, okay? Because it knows the delegate implements\n\n939\n00:48:06,885 --> 00:48:09,952\nthose protocol methods. Then the controller\n\n940\n00:48:09,954 --> 00:48:12,788\nhas to declare that it implements this protocol, so\n\n941\n00:48:12,790 --> 00:48:15,524\nit just puts it on its you know, class something,\n\n942\n00:48:15,526 --> 00:48:18,661\nUIV controller, comma, that protocol.\n\n943\n00:48:18,663 --> 00:48:22,899\nThen the controller sets itself as this delegate, so it\n\n944\n00:48:22,901 --> 00:48:26,802\nsets itself as this property. So now when the view talks\n\n945\n00:48:26,804 --> 00:48:29,739\nto that delegate it's talking back to the controller.\n\n946\n00:48:29,741 --> 00:48:34,243\nSo that's how it plays out to use delegation here.\n\n947\n00:48:34,245 --> 00:48:36,946\nNow of course the controller has to implement the protocol,\n\n948\n00:48:36,948 --> 00:48:38,247\nhas to implement the methods, but\n\n949\n00:48:38,249 --> 00:48:40,783\nremember this is all objective C worlds.\n\n950\n00:48:40,785 --> 00:48:43,619\nRight?The delegation is from the objective C world, so\n\n951\n00:48:43,621 --> 00:48:44,954\nall these things you're gonna see in iOS,\n\n952\n00:48:44,956 --> 00:48:47,924\nthese delegate protocols like scroll, views delegate,\n\n953\n00:48:47,926 --> 00:48:52,094\ntable views, delegate. Almost all the methods are optional,\n\n954\n00:48:52,096 --> 00:48:53,796\nokay. There's a few in there that aren't, and\n\n955\n00:48:53,798 --> 00:48:56,265\nthat's because you might not care that the scroll\n\n956\n00:48:56,267 --> 00:48:58,968\nview just finished scrolling to this location. So you don't\n\n957\n00:48:58,970 --> 00:49:01,871\nwanna that method scroll view did scroll to point.\n\n958\n00:49:01,873 --> 00:49:02,071\nYou don't want it, so\n\n959\n00:49:02,073 --> 00:49:04,740\nyou don't wanna even have to implement it. Okay? So\n\n960\n00:49:04,742 --> 00:49:06,976\nthese protocols are all gonna be Objective-C protocols,\n\n961\n00:49:06,978 --> 00:49:09,578\n@objc, and they're gonna have a lot of word optional in\n\n962\n00:49:09,580 --> 00:49:12,815\nfront of a lot of the funcs, okay. All right, so\n\n963\n00:49:12,817 --> 00:49:15,985\nnow the view's hooked up to the controller. The view still\n\n964\n00:49:15,987 --> 00:49:18,587\nhas no idea what kind of object is doing, is\n\n965\n00:49:18,589 --> 00:49:20,957\nimplementing the will, should, and did. It could be anything.\n\n966\n00:49:20,959 --> 00:49:22,391\nAny class, it could, doesn't even have to be a class!\n\n967\n00:49:22,393 --> 00:49:24,760\nIt could be a struct or something. Although actually,\n\n968\n00:49:24,762 --> 00:49:27,229\nprobably does have to be a class, cuz OBJC thing,\n\n969\n00:49:27,231 --> 00:49:29,465\nthose have to be classes, and it's an object thing. So\n\n970\n00:49:29,467 --> 00:49:32,301\nit is a class but it doesn't know that it's a UI view\n\n971\n00:49:32,303 --> 00:49:34,437\ncontroller. Ok, it doesn't have to be a view-a UI view\n\n972\n00:49:34,439 --> 00:49:37,106\ncontroller. So it's blind. But it's structured, because\n\n973\n00:49:37,108 --> 00:49:39,942\nthe protocol says exactly the method that had to be sent.\n\n974\n00:49:39,944 --> 00:49:45,948\nAll right? So, this, I keep talking about this happening,\n\n975\n00:49:45,950 --> 00:49:47,850\nbecause of objective C in the history of iOS.\n\n976\n00:49:47,852 --> 00:49:49,986\nWhat would you do in Swift? Because Swift doesn't have\n\n977\n00:49:49,988 --> 00:49:51,654\nthese optional protocols. Well, in Swift,\n\n978\n00:49:51,656 --> 00:49:54,523\neither you could do the same thing, ok? And just\n\n979\n00:49:54,525 --> 00:49:57,460\nbreak up your protocol into the pieces that make sense, so\n\n980\n00:49:57,462 --> 00:49:59,228\nyou might have three or four different protocols and\n\n981\n00:49:59,230 --> 00:50:01,163\nyou'll only implement the ones that you want.\n\n982\n00:50:01,165 --> 00:50:03,299\nLike you have the scroll view notification protocols,\n\n983\n00:50:03,301 --> 00:50:05,901\nand then you have the scroll view should protocols, and\n\n984\n00:50:05,903 --> 00:50:08,337\nthen you have the data app protocols, or whatever.\n\n985\n00:50:08,339 --> 00:50:12,842\nAnother way to do things like this is with closures, okay?\n\n986\n00:50:12,844 --> 00:50:15,644\nYou don't even need all this overhead of having\n\n987\n00:50:15,646 --> 00:50:18,948\nthese protocols do that you can just have a closure and\n\n988\n00:50:18,950 --> 00:50:20,683\nthe closure knows what\n\n989\n00:50:20,685 --> 00:50:22,284\nthe arguments to the closure are and\n\n990\n00:50:22,286 --> 00:50:22,885\nwhat it's supposed to return.\n\n991\n00:50:22,887 --> 00:50:25,821\nAnd that's essentially like having the protocol defined.\n\n992\n00:50:25,823 --> 00:50:28,724\nSo in this case what you could do you can imagine saying to\n\n993\n00:50:28,726 --> 00:50:33,062\nthe scroll view. When you're finished scrolling,\n\n994\n00:50:33,264 --> 00:50:37,333\nexecute this closure. Right, give it a closure. So\n\n995\n00:50:37,335 --> 00:50:39,235\nthat's another way to do it is with closures. And\n\n996\n00:50:39,237 --> 00:50:43,072\nyou're gonna see that iOS does some things with closures and\n\n997\n00:50:43,074 --> 00:50:45,508\nsome things with delegates. And they're not\n\n998\n00:50:45,510 --> 00:50:48,444\nexact substitutes for each other. Protocols are sometimes\n\n999\n00:50:48,446 --> 00:50:51,213\nnice because they make it really clear what this object\n\n1000\n00:50:51,215 --> 00:50:54,417\nis capable of delegating. So that's nice.\n\n1001\n00:50:54,419 --> 00:50:56,385\nClosures are really good for things like error\n\n1002\n00:50:56,387 --> 00:50:59,455\ncall backs and multi, when a multi-threaded world when\n\n1003\n00:50:59,457 --> 00:51:01,690\nthings are gonna take a long time and they're done later\n\n1004\n00:51:01,692 --> 00:51:04,226\nand it wants to tell you it's done, that kinda thing. So\n\n1005\n00:51:04,228 --> 00:51:07,930\nwe'll see both as the rest of the quarter goes on. All\n\n1006\n00:51:07,932 --> 00:51:10,633\nright, so here's an example of scroll view, right? So\n\n1007\n00:51:10,635 --> 00:51:14,837\nscroll view, the, is a UI view subclass. It has a var called\n\n1008\n00:51:14,839 --> 00:51:18,908\ndelegate, it's weak. Its type is UIScrollView delegate\n\n1009\n00:51:18,910 --> 00:51:21,811\noptional because you don't have to set a delegate here.\n\n1010\n00:51:21,813 --> 00:51:23,913\nOkay. The delegate protocol looks like this.\n\n1011\n00:51:23,915 --> 00:51:27,650\nIt's in OBJC protocol. Okay. And it has all these\n\n1012\n00:51:27,652 --> 00:51:29,919\noptional functions. It has over a dozen of them,\n\n1013\n00:51:29,921 --> 00:51:32,421\nthings like scrollViewDidScroll. View for\n\n1014\n00:51:32,423 --> 00:51:35,491\nassuming it's scroll view which gets a view to zoom on\n\n1015\n00:51:35,493 --> 00:51:38,360\non inside the scroll view etc. Okay? So\n\n1016\n00:51:38,362 --> 00:51:41,397\na Controller that wants to work with the ScrollView\n\n1017\n00:51:41,399 --> 00:51:45,367\nwill say MyViewController is a subclass of UIViewController\n\n1018\n00:51:45,369 --> 00:51:49,538\nand it implements this protocol. Okay?\n\n1019\n00:51:49,540 --> 00:51:50,272\nNow most of this is optional so\n\n1020\n00:51:50,274 --> 00:51:54,310\ndidn't have to do much to do that. Okay? And then\n\n1021\n00:51:54,312 --> 00:51:57,446\nthis UIViewController is gonna say, scrollView.delegate.\n\n1022\n00:51:57,448 --> 00:51:59,548\nThis is some outlet that points to the ScrollView.\n\n1023\n00:51:59,550 --> 00:52:02,184\nThat delegate equals self and that's gonna be okay because\n\n1024\n00:52:02,186 --> 00:52:05,321\nit says that it implements this protocol, okay.\n\n1025\n00:52:05,323 --> 00:52:08,390\nNow the scroll view is gonna use this to talk to this view\n\n1026\n00:52:08,392 --> 00:52:11,994\ncontroller. Okay, and then view controller implements\n\n1027\n00:52:11,996 --> 00:52:16,499\nwhichever of these it wants and, off to the races. Okay,\n\n1028\n00:52:16,501 --> 00:52:23,205\nmake sense? All right, let's go through and\n\n1029\n00:52:23,207 --> 00:52:25,107\ntalk about ScrollView in more detail, because this is\n\n1030\n00:52:25,109 --> 00:52:28,244\nan important class, all right. So here's an interesting,\n\n1031\n00:52:28,246 --> 00:52:30,346\nthis is like an iPhone one or something.\n\n1032\n00:52:30,348 --> 00:52:32,982\nNotice this very small little iPhone. But it has a cool\n\n1033\n00:52:32,984 --> 00:52:35,384\nlittle animation here to show you how ScrollViews work.\n\n1034\n00:52:35,386 --> 00:52:37,386\nLook at this ScrollView. See it can ScrollView\n\n1035\n00:52:37,388 --> 00:52:40,556\nhorizontally, and inside there can be vertical things.\n\n1036\n00:52:40,558 --> 00:52:44,527\nSo this is a ScrollView that's inside ScrollView. See that?\n\n1037\n00:52:44,529 --> 00:52:47,696\nSo ScrollView's really smart about that. Look at this one.\n\n1038\n00:52:47,698 --> 00:52:49,965\nOkay, you've got two things, top thing ScrollViews and\n\n1039\n00:52:49,967 --> 00:52:51,700\nthe bottom thing is a horizontal ScrollView\n\n1040\n00:52:51,702 --> 00:52:55,271\nwith vertical ones inside. So you can see an old iPhone\n\n1041\n00:52:55,273 --> 00:52:58,774\none here or whatever it is, not a lot of screen space, but\n\n1042\n00:52:58,776 --> 00:53:02,344\nit's very efficiently being used by the ScrollViews, okay.\n\n1043\n00:53:02,346 --> 00:53:04,446\nSo the ScrollView is super powerful. So\n\n1044\n00:53:04,448 --> 00:53:07,783\nlet's talk a little bit about how ScrollView works and\n\n1045\n00:53:07,785 --> 00:53:10,386\nwe do it mostly by adding subviews to it.\n\n1046\n00:53:10,388 --> 00:53:11,987\nLet's first remind ourselves what it's like to\n\n1047\n00:53:11,989 --> 00:53:15,958\nadd a subview to a normal UIView. It's really simple.\n\n1048\n00:53:15,960 --> 00:53:18,060\nI've got the UI view right here on my phone.\n\n1049\n00:53:18,062 --> 00:53:22,598\nI just set the frame, where I want this UI view to be added,\n\n1050\n00:53:22,600 --> 00:53:25,334\nand then I just add it. View, add sub-view.\n\n1051\n00:53:25,336 --> 00:53:27,203\nThis is probably in the view controllers so\n\n1052\n00:53:27,205 --> 00:53:28,971\nthis will be the top level view. And\n\n1053\n00:53:28,973 --> 00:53:31,674\nI'm just adding the sub-view, this specifies where it is.\n\n1054\n00:53:31,676 --> 00:53:34,276\nAll right, everyone is cool with that? Very simple.\n\n1055\n00:53:34,278 --> 00:53:38,881\nSo a scroll view is almost exactly the same. Okay. But\n\n1056\n00:53:38,883 --> 00:53:43,152\nthe big step that's different is first we declare a content\n\n1057\n00:53:43,154 --> 00:53:47,623\nsize. This is a big area, k, that the scroll view is going\n\n1058\n00:53:47,625 --> 00:53:52,795\nto be scrolling around and in. Okay. And we specify by size.\n\n1059\n00:53:52,797 --> 00:53:54,530\nOkay, here I've made one 3,000 wide by 2,000 high, so\n\n1060\n00:53:54,532 --> 00:53:58,067\nwe've got a lot of room to scroll around in there.\n\n1061\n00:53:58,069 --> 00:54:01,303\nBut once I've specified the content size which I've set\n\n1062\n00:54:01,305 --> 00:54:02,538\nthis bar right here.\n\n1063\n00:54:02,540 --> 00:54:05,574\nNow I just add sub views in the exact same way. Okay,\n\n1064\n00:54:05,576 --> 00:54:07,977\nlogo.frame here I've moved it over to 2700,\n\n1065\n00:54:07,979 --> 00:54:10,446\nso it's way over on the right. Scroll view,\n\n1066\n00:54:10,448 --> 00:54:12,915\nadd sub view logo, okay? Just like any other view.\n\n1067\n00:54:12,917 --> 00:54:15,217\nI've added it as a subview. Could add another one.\n\n1068\n00:54:15,219 --> 00:54:18,053\nLet's add an aerial photo of Stanford here, okay?\n\n1069\n00:54:18,055 --> 00:54:22,558\nAdded it as a subview. So they all get added in a coordinate\n\n1070\n00:54:22,560 --> 00:54:27,596\nsystem relative to this big content area right here, okay?\n\n1071\n00:54:27,598 --> 00:54:32,234\nNow the scroll view just moves around and lets you\n\n1072\n00:54:32,236 --> 00:54:36,872\nlook around inside that content area. See. That's all\n\n1073\n00:54:36,874 --> 00:54:40,609\nit's doing, is looking around. Now you can move the subviews\n\n1074\n00:54:40,611 --> 00:54:41,910\nto different places in the same way you can move\n\n1075\n00:54:41,912 --> 00:54:44,913\nthem in a regular view. Right? So I can change the frame of\n\n1076\n00:54:44,915 --> 00:54:45,981\nthe aerial view to be in the corner.\n\n1077\n00:54:45,983 --> 00:54:48,717\nI can change the frame of the logo, maybe, to overlap.\n\n1078\n00:54:48,719 --> 00:54:51,053\nI can also come along later and change the content size.\n\n1079\n00:54:51,055 --> 00:54:53,689\nMaybe I want this content size to be small enough to just fit\n\n1080\n00:54:53,691 --> 00:54:58,193\nmy views. Okay and again then when I'm kind of using\n\n1081\n00:54:58,195 --> 00:55:01,630\nmy finger, in the scroll view I'm just moving around in\n\n1082\n00:55:01,632 --> 00:55:05,000\nits content area. So the most important thing to understand\n\n1083\n00:55:05,002 --> 00:55:08,470\nabout this is if you don't set your content size\n\n1084\n00:55:08,472 --> 00:55:08,671\nyou get nothing.\n\n1085\n00:55:08,673 --> 00:55:10,306\nYou can't scroll because you're scrolling over that\n\n1086\n00:55:10,308 --> 00:55:14,643\ncontent size. This is the most commonly mistaken thing about\n\n1087\n00:55:14,645 --> 00:55:15,477\nscroll view people don't understand.\n\n1088\n00:55:15,479 --> 00:55:18,047\nThey don't set their content size and so things\n\n1089\n00:55:18,049 --> 00:55:22,518\ncan't scroll. Gotta have a content size, okay? Couple of\n\n1090\n00:55:22,520 --> 00:55:25,354\nother interesting things. If you want to find out where\n\n1091\n00:55:25,356 --> 00:55:30,225\nyou're currently showing in the content area, there's this\n\n1092\n00:55:30,227 --> 00:55:33,962\nvar inside of scrollView called contentOffset. And\n\n1093\n00:55:33,964 --> 00:55:36,732\nit's just a CG point. Gonna tell you the X and\n\n1094\n00:55:36,734 --> 00:55:40,102\nY of the upper left corner of where the scroll view is\n\n1095\n00:55:40,104 --> 00:55:43,272\nshowing right as it moves around that changes.\n\n1096\n00:55:43,274 --> 00:55:45,274\nAlso if you wanted to know the whole,\n\n1097\n00:55:45,276 --> 00:55:49,111\nwhat that whole rectangle is in the, coordinate system in\n\n1098\n00:55:49,113 --> 00:55:52,648\none of these views, like this thing or the, or the.\n\n1099\n00:55:52,650 --> 00:55:55,217\nThe logo or the, or the aerial view. You can get\n\n1100\n00:55:55,219 --> 00:55:59,154\nthe scrollView's bounds, okay. ScrollView.bound. And\n\n1101\n00:55:59,156 --> 00:56:04,426\nuse this UIView method convertRect fromView, okay?\n\n1102\n00:56:04,428 --> 00:56:07,463\nSo you're gonna convert this bounds from the scrollView's\n\n1103\n00:56:07,465 --> 00:56:10,532\ncoordinate system, to this aerial view. This is probably\n\n1104\n00:56:10,534 --> 00:56:13,836\nthe UIImageView, okay. To it, coordinate system. Now you\n\n1105\n00:56:13,838 --> 00:56:17,406\ncan find the whole rectangle in the a, in the aerial guy\n\n1106\n00:56:17,408 --> 00:56:22,244\ncoordinate system, to show what's, what's visible, okay?\n\n1107\n00:56:23,614 --> 00:56:26,348\nOkay, how do you create a scrollView,\n\n1108\n00:56:26,350 --> 00:56:27,583\nit's just like in the other UIView,\n\n1109\n00:56:27,585 --> 00:56:30,786\nusually you're gonna drag it out in, your story board,\n\n1110\n00:56:30,788 --> 00:56:36,091\nokay? You can also do Embed In Scroll View in the storyboard.\n\n1111\n00:56:36,093 --> 00:56:38,193\nWe don't usually do that very much, but you can.\n\n1112\n00:56:38,195 --> 00:56:40,496\nThat's if you just had one view inside there,\n\n1113\n00:56:40,498 --> 00:56:44,233\nit would embed it in there and also set its content size\n\n1114\n00:56:44,235 --> 00:56:46,735\nto the size of the thing you embedded, but usually we drag\n\n1115\n00:56:46,737 --> 00:56:51,540\nit out. You can also create it in code, right, it's just,\n\n1116\n00:56:51,542 --> 00:56:55,110\nit's just a view, so you can use UIView (frame:),\n\n1117\n00:56:55,112 --> 00:56:59,581\ninitializer there. Then you, add your too big UIView,\n\n1118\n00:56:59,583 --> 00:57:02,184\nof the view that's too big that you wanna scroll over,\n\n1119\n00:57:02,186 --> 00:57:05,854\njust by creating it and calling addSubView, okay?\n\n1120\n00:57:05,856 --> 00:57:10,192\nTalked about on the previous slides there,\n\n1121\n00:57:10,194 --> 00:57:12,661\nokay? Don't forget to set that contentSize,,\n\n1122\n00:57:12,663 --> 00:57:15,330\nI can't emphasize that enough. If you don't, if you don't set\n\n1123\n00:57:15,332 --> 00:57:17,366\nthe contentSize, it's just not gonna work, okay?\n\n1124\n00:57:17,368 --> 00:57:21,904\nAll right, so, you can scroll with your finger, but you can\n\n1125\n00:57:21,906 --> 00:57:25,307\nalso scroll programmatically. And the classic way to do is\n\n1126\n00:57:25,309 --> 00:57:28,210\nby saying scrollRectToVisible and you just specify\n\n1127\n00:57:28,212 --> 00:57:31,513\na rectangle in the contents size coordinate system, and\n\n1128\n00:57:31,515 --> 00:57:34,583\nit'll scroll to try and show as much of that rectangle\n\n1129\n00:57:34,585 --> 00:57:38,187\nas possible. It'll scoll, scroll as little as possible,\n\n1130\n00:57:38,189 --> 00:57:41,423\nto show as much as possible of the rectangle, okay?\n\n1131\n00:57:41,425 --> 00:57:44,026\nHere's also a ton of other methods in scrollView, I can't\n\n1132\n00:57:44,028 --> 00:57:47,296\ntalk about them all, you can go look them up. But you can\n\n1133\n00:57:47,298 --> 00:57:49,565\ncontrol which direction scrolling is allowed,\n\n1134\n00:57:49,567 --> 00:57:51,333\njust vertically or just horizontally, or\n\n1135\n00:57:51,335 --> 00:57:53,735\nif it starts being vertical, does it lock vertical?\n\n1136\n00:57:53,737 --> 00:57:56,772\nThat's how the scroll view inside scrollView works.\n\n1137\n00:57:56,774 --> 00:57:59,641\nThings like that, you can flash your scroll bars,\n\n1138\n00:57:59,643 --> 00:58:00,909\nall kinds of stuff there, okay.\n\n1139\n00:58:00,911 --> 00:58:03,745\nNow what about zooming? So we talked about kinda panning\n\n1140\n00:58:03,747 --> 00:58:08,016\naround, what if I wanna zoom in, like pinch to zoom in,\n\n1141\n00:58:08,018 --> 00:58:11,820\nhow do I do that? Okay, well, all UIViews, okay,\n\n1142\n00:58:11,822 --> 00:58:14,122\nhave a property called transform, it's\n\n1143\n00:58:14,124 --> 00:58:17,459\nan affine transform, which means translate, scale and\n\n1144\n00:58:17,461 --> 00:58:21,396\nrotate for, or is incorporated into to this transform. And so\n\n1145\n00:58:21,398 --> 00:58:25,267\nthe scrollView, as you zoom it's just modifying the scale\n\n1146\n00:58:25,269 --> 00:58:29,471\nof this transform property in the view. So basically, if you\n\n1147\n00:58:29,473 --> 00:58:32,140\nzoomed in really a lot your view would get very grainy,\n\n1148\n00:58:32,142 --> 00:58:35,978\nbecause all it's doing is basically scaling the bits up.\n\n1149\n00:58:35,980 --> 00:58:37,813\nNow, once it's finished zooming in,\n\n1150\n00:58:37,815 --> 00:58:39,448\nyou could redraw your view to not be so\n\n1151\n00:58:39,450 --> 00:58:43,485\ngrainy, okay? If you have, the ability to do that. But,\n\n1152\n00:58:43,487 --> 00:58:46,989\ngenerally when it's zooming, it is zooming the bits, okay?\n\n1153\n00:58:46,991 --> 00:58:52,261\nUsing this transform property. Zooming will not work unless\n\n1154\n00:58:52,263 --> 00:58:54,963\nyou set these properties. Because by default,\n\n1155\n00:58:54,965 --> 00:58:58,534\nthe minimumZoomScale and the maximumZoomScale is 1.\n\n1156\n00:58:58,536 --> 00:59:03,138\nMeaning no zoom, okay? So this is how much,\n\n1157\n00:59:03,140 --> 00:59:07,509\nyou can zoom size, zoom down, minimum. So 0.5\n\n1158\n00:59:07,511 --> 00:59:11,046\nwould mean it can zoom down to half its normal size. And\n\n1159\n00:59:11,048 --> 00:59:14,316\nthis is zooming out, eh, you can zoom to twice its normal\n\n1160\n00:59:14,318 --> 00:59:17,853\nsize if you set it to 2.0. Okay, so you have to set\n\n1161\n00:59:17,855 --> 00:59:20,455\nthese, don't forget that or your zooming won't work.\n\n1162\n00:59:20,457 --> 00:59:22,925\nYou also won't work if you don't implement this\n\n1163\n00:59:22,927 --> 00:59:24,359\ndelegate method, that's why I talked to you and\n\n1164\n00:59:24,361 --> 00:59:27,062\ntold you about delegates. You have to implement this method,\n\n1165\n00:59:27,064 --> 00:59:29,431\nviewForZoomingInScrollView, okay. By the way,\n\n1166\n00:59:29,433 --> 00:59:33,535\nnotice these delegate methods, the first argument is always\n\n1167\n00:59:33,537 --> 00:59:35,370\nthe thing that's sending you the delegate method,\n\n1168\n00:59:35,372 --> 00:59:37,940\nit's basically the sender. Okay, just so\n\n1169\n00:59:37,942 --> 00:59:39,575\nyou know which, if you had two scrollViews,\n\n1170\n00:59:39,577 --> 00:59:42,578\nyou'd know which one is asking you for the view for\n\n1171\n00:59:42,580 --> 00:59:43,145\nzooming in scrollView.\n\n1172\n00:59:43,147 --> 00:59:45,781\nNow this is going to return the UIView that's gonna\n\n1173\n00:59:45,783 --> 00:59:50,886\nhave its transform modified when you pinch, okay? So\n\n1174\n00:59:50,888 --> 00:59:51,386\nyou have to implement this.\n\n1175\n00:59:51,388 --> 00:59:54,856\nIf you don't implement this you get no zooming,\n\n1176\n00:59:54,858 --> 00:59:58,026\nall right? You can also zoom programmatically, not just\n\n1177\n00:59:58,028 --> 01:00:00,128\nwith a pinch obviously, you can set it to scale, or\n\n1178\n01:00:00,130 --> 01:00:02,931\nyou can zoom to a rectangle that looks like this. So here\n\n1179\n01:00:02,933 --> 01:00:07,135\nI have a zoom scale of 1.2 I'm kinda zoomed out a little bit,\n\n1180\n01:00:07,137 --> 01:00:08,637\nand I could zoom back to normal.\n\n1181\n01:00:08,639 --> 01:00:11,506\nOkay, this is 1.0 so this is the normal size of this image.\n\n1182\n01:00:11,508 --> 01:00:15,944\nOr I could zoom back out to 1.2, so that's 20% larger,\n\n1183\n01:00:15,946 --> 01:00:18,847\nright? I can also do the zoomToRect, let's say I have\n\n1184\n01:00:18,849 --> 01:00:21,516\nthis little rectangle here and I said zoom to this rect,\n\n1185\n01:00:21,518 --> 01:00:24,119\nit would show as much of the rectangle as possible. Or\n\n1186\n01:00:24,121 --> 01:00:27,489\nif I had the rect out there, and I said zoom to rect,\n\n1187\n01:00:27,491 --> 01:00:30,826\nit would zoom it down to fit that rectangle, okay.\n\n1188\n01:00:30,828 --> 01:00:34,730\nSo that's how you can zoom in from your code, okay?\n\n1189\n01:00:34,732 --> 01:00:36,732\nThere's lots and lots of other delegate methods,\n\n1190\n01:00:36,734 --> 01:00:38,800\nyou can look at the documentation to figure out,\n\n1191\n01:00:38,802 --> 01:00:40,135\na lot of them are the did and\n\n1192\n01:00:40,137 --> 01:00:42,004\nwill, like here's DidEndZooming.\n\n1193\n01:00:42,006 --> 01:00:46,208\nThis is where you might redraw your thing with more,\n\n1194\n01:00:46,210 --> 01:00:49,544\nwith a finer grain, if you got scaled up really big and\n\n1195\n01:00:49,546 --> 01:00:52,280\nyou got grainy, things like that. So you can take a look\n\n1196\n01:00:52,282 --> 01:00:55,717\nat all those. I have a demo here at the end, but\n\n1197\n01:00:55,719 --> 01:00:58,153\nfirst I want to talk about whats coming up here.\n\n1198\n01:00:58,155 --> 01:00:59,788\nOn Wednesday your Assignment 3 is due,\n\n1199\n01:00:59,790 --> 01:01:01,189\nof course before lecture you know that,\n\n1200\n01:01:01,191 --> 01:01:03,525\nand we're gonna start talking about Multithreading,\n\n1201\n01:01:03,527 --> 01:01:06,561\nall right? Friday this section is on UI Testing,\n\n1202\n01:01:06,563 --> 01:01:07,162\nwhich is really cool and\n\n1203\n01:01:07,164 --> 01:01:09,665\niOS, you can actually basically record mouse clicks\n\n1204\n01:01:09,667 --> 01:01:12,601\nand then play them back, and make sure that you're getting\n\n1205\n01:01:12,603 --> 01:01:16,104\nthe results you expect. Next week, we're gonna talk about\n\n1206\n01:01:16,106 --> 01:01:17,439\nTable View, and Object-Oriented Database.\n\n1207\n01:01:17,441 --> 01:01:21,076\nI'm give a little break this weekend, okay? I'm not gonna\n\n1208\n01:01:21,078 --> 01:01:23,912\nassign, Assignment 4 on Wednesday, I'll be assigning\n\n1209\n01:01:23,914 --> 01:01:26,882\nit next Monday. It'll be due the Monday after. So\n\n1210\n01:01:26,884 --> 01:01:29,217\nyou have no assignment over this coming weekend.\n\n1211\n01:01:29,219 --> 01:01:32,821\nThere's no more reading assignments at all. Okay,\n\n1212\n01:01:32,823 --> 01:01:36,558\nright now, I'm gonna do a little scrollView demo, okay,\n\n1213\n01:01:36,560 --> 01:01:41,663\ncalled Cassini. Any questions before I jump into that?\n\n1214\n01:01:41,665 --> 01:01:47,803\nOkay Cassini, okay, I'm gonna create a brand new thing here.\n\n1215\n01:01:47,805 --> 01:01:53,575\nSo let's quit that, let's go, oops, over here.\n\n1216\n01:01:54,578 --> 01:01:57,679\nCreate a new project. Okay, it's gonna be an iO, I'm gonna\n\n1217\n01:01:57,681 --> 01:02:00,082\nstart going fast through these new project creations here,\n\n1218\n01:02:00,084 --> 01:02:01,583\nSingle View Applications like we always do.\n\n1219\n01:02:01,585 --> 01:02:04,786\nI'm gonna call it Cassini. Okay all the things we\n\n1220\n01:02:04,788 --> 01:02:09,391\nnormally do there. Put it in the same place we always do.\n\n1221\n01:02:11,128 --> 01:02:14,963\nHere is our Cassini. I'm going to do the same thing where I'm\n\n1222\n01:02:14,965 --> 01:02:17,432\ngonna move these things out of the way, or\n\n1223\n01:02:17,434 --> 01:02:22,771\nat least most of them. Supporting,\n\n1224\n01:02:22,773 --> 01:02:24,906\noops, Supporting Files.\n\n1225\n01:02:24,908 --> 01:02:27,576\nOkay, they, that, there, I left info plist,\n\n1226\n01:02:27,578 --> 01:02:31,379\ncuz we're actually gonna look at that today. All right,\n\n1227\n01:02:31,381 --> 01:02:35,450\nhere's my storyboard, for Cossini right here,\n\n1228\n01:02:35,452 --> 01:02:39,020\nthis storyboard has a generic ViewController.\n\n1229\n01:02:39,022 --> 01:02:41,389\nYou know, we always get this generic ViewController.\n\n1230\n01:02:41,391 --> 01:02:43,692\nNow in the calculator, we renamed this,\n\n1231\n01:02:43,694 --> 01:02:45,794\nhopefully you did that for your assignment. But\n\n1232\n01:02:45,796 --> 01:02:48,130\nI'm not gonna rename it, I'm gonna do another thing here,\n\n1233\n01:02:48,132 --> 01:02:51,066\ncuz I don't want this to be a generic ViewController.\n\n1234\n01:02:51,068 --> 01:02:53,235\nI want it to be a subclass of ViewController, but\n\n1235\n01:02:53,237 --> 01:02:55,370\nI'm just going to delete this instead.\n\n1236\n01:02:55,372 --> 01:02:56,772\nSo I'm gonna take this ViewController and\n\n1237\n01:02:56,774 --> 01:02:57,405\nI'm gonna right-click and\n\n1238\n01:02:57,407 --> 01:03:00,041\nhit Delete, just get rid of that whole class and\n\n1239\n01:03:00,043 --> 01:03:02,277\nmove it to the trash. Now my storyboard,\n\n1240\n01:03:02,279 --> 01:03:04,813\nif I look at the Identity inspector over here,\n\n1241\n01:03:04,815 --> 01:03:08,016\nit still thinks this is a ViewController, okay.\n\n1242\n01:03:08,018 --> 01:03:10,652\nSo I need to create the actual class,\n\n1243\n01:03:10,654 --> 01:03:11,820\nnot this generic ViewController, so\n\n1244\n01:03:11,822 --> 01:03:15,190\nI'm gonna do that. Gonna create, a iOS Source,\n\n1245\n01:03:15,192 --> 01:03:18,460\nCocoa Touch Class, it's gonna be a ViewController, I'm gonna\n\n1246\n01:03:18,462 --> 01:03:21,730\ncall it ImageViewController. I'm gonna have my UI here,\n\n1247\n01:03:21,732 --> 01:03:25,100\nwhat it's gonna do is just display an image, okay.\n\n1248\n01:03:25,102 --> 01:03:27,769\nSo it's just, that's just very simple,\n\n1249\n01:03:27,771 --> 01:03:29,538\nUI is gonna display the image,\n\n1250\n01:03:29,540 --> 01:03:32,440\nin the whole screen of the phone or the iPad,\n\n1251\n01:03:32,442 --> 01:03:35,310\nwhatever. Okay, so it's gonna an ImageViewController,\n\n1252\n01:03:35,312 --> 01:03:38,547\nit's gonna display that. We'll put it in the same place we\n\n1253\n01:03:38,549 --> 01:03:39,614\nput all these other things over here.\n\n1254\n01:03:39,616 --> 01:03:43,318\nAll right, here it is. Okay, you can see we have\n\n1255\n01:03:43,320 --> 01:03:45,420\na couple of ViewController life cycles here, here.\n\n1256\n01:03:45,422 --> 01:03:46,888\nI'm not going to be a bad citizen, so\n\n1257\n01:03:46,890 --> 01:03:50,759\nhopefully I won't have any memory. Then I'm gonna leak,\n\n1258\n01:03:50,761 --> 01:03:53,995\nI'm also not going to navigate from this MVC,\n\n1259\n01:03:53,997 --> 01:03:57,165\nokay. On Wednesday, we'll be continuing this demo and\n\n1260\n01:03:57,167 --> 01:03:59,467\nwe will be navigating to this, but not from it,\n\n1261\n01:03:59,469 --> 01:04:01,236\nso I don't need, the prepareForSegue,\n\n1262\n01:04:01,238 --> 01:04:05,440\nthat's only for things that are navigating from, okay?\n\n1263\n01:04:05,442 --> 01:04:07,342\nI do need my viewDidLoad() right here, so\n\n1264\n01:04:07,344 --> 01:04:10,679\nI'm gonna leave that in here. When I create a new MVC\n\n1265\n01:04:10,681 --> 01:04:13,815\ncontroller here, you gotta remember to go back here to\n\n1266\n01:04:13,817 --> 01:04:17,419\nyour identity inspector and set the class. If you don't,\n\n1267\n01:04:17,421 --> 01:04:19,654\nobviously none of your outlets are gonna work right,\n\n1268\n01:04:19,656 --> 01:04:21,690\nyou'll probably crash at launch, all kinds of things,\n\n1269\n01:04:21,692 --> 01:04:24,693\nokay? So I'm just using the Identity Inspector right here\n\n1270\n01:04:24,695 --> 01:04:26,761\nto set that to ImageViewController.\n\n1271\n01:04:26,763 --> 01:04:29,064\nAnother thing I like to do when I create an MVC right\n\n1272\n01:04:29,066 --> 01:04:32,467\noff the bat is think about what is my model, okay?\n\n1273\n01:04:32,469 --> 01:04:35,503\nSo this is an image view controller, what does it do?\n\n1274\n01:04:35,505 --> 01:04:39,241\nIt shows an image, so I'm gonna have its model,\n\n1275\n01:04:39,243 --> 01:04:39,674\nwhich is gonna be public,\n\n1276\n01:04:39,676 --> 01:04:43,311\nI'm gonna allow the people to set it, be the URL\n\n1277\n01:04:43,313 --> 01:04:46,748\nof the image to display. Okay, so that's my model,\n\n1278\n01:04:46,750 --> 01:04:50,919\nit's a URL. It could be a file on the local filesystem, could\n\n1279\n01:04:50,921 --> 01:04:55,056\nbe something over the network, okay, that's what it is.\n\n1280\n01:04:55,058 --> 01:04:59,895\nNow to display this imageURL's image, I need an image view.\n\n1281\n01:04:59,897 --> 01:05:03,365\nNow we have created all of our classes,\n\n1282\n01:05:03,367 --> 01:05:06,401\nall our views by going over here and finding things,\n\n1283\n01:05:06,403 --> 01:05:07,702\nlike there's image view down here somewhere,\n\n1284\n01:05:07,704 --> 01:05:09,871\nhere it is right here, and we've been dragging them out.\n\n1285\n01:05:09,873 --> 01:05:12,574\nAnd I could drag this out and all this stuff, but I want to\n\n1286\n01:05:12,576 --> 01:05:15,110\nstart showing a little bit how to create views in code.\n\n1287\n01:05:15,112 --> 01:05:18,680\nSo we're going to create this image view in our controller's\n\n1288\n01:05:18,682 --> 01:05:21,116\ncode, and in fact I'm just going to create a private\n\n1289\n01:05:21,118 --> 01:05:23,985\nvar for it, which I'm going to call my image view, okay?\n\n1290\n01:05:23,987 --> 01:05:28,156\nAnd I'm just going to set it equal to UIImageView.\n\n1291\n01:05:28,158 --> 01:05:29,824\nSo I'm creating one right here.\n\n1292\n01:05:29,826 --> 01:05:32,861\nI'm using the init that takes no arguments, so that's going\n\n1293\n01:05:32,863 --> 01:05:36,932\nto create an image view that the frame is 0000, okay? Tiny,\n\n1294\n01:05:36,934 --> 01:05:39,968\ntiny little ImageView. So I'm going to have to be careful to\n\n1295\n01:05:39,970 --> 01:05:45,473\nreset it's frame whenever I put an image in there. Okay,\n\n1296\n01:05:45,475 --> 01:05:46,174\nso now I have this ImageView,\n\n1297\n01:05:46,176 --> 01:05:50,812\nthat's cool. I need my viewDidLoad right down here,\n\n1298\n01:05:50,814 --> 01:05:56,084\nokay. After I'm loaded I'm going to,\n\n1299\n01:05:56,086 --> 01:06:01,156\njust take this, ImageView that I created and\n\n1300\n01:06:01,158 --> 01:06:05,093\nadd it as a subview of my top level view.\n\n1301\n01:06:05,095 --> 01:06:09,331\nSo I'm gonna say view.addSubview my ImageView.\n\n1302\n01:06:09,333 --> 01:06:12,867\nOkay, so remember this view right here, this var, okay,\n\n1303\n01:06:12,869 --> 01:06:14,302\ncomes along with your UIViewController.\n\n1304\n01:06:14,304 --> 01:06:17,839\nIt's the view that's at the very top, okay?\n\n1305\n01:06:17,841 --> 01:06:21,676\nSo I'm just going to add this image view, in there.\n\n1306\n01:06:21,678 --> 01:06:25,647\nNow, its frame is 0000 so I'm putting it up in the corner\n\n1307\n01:06:25,649 --> 01:06:28,883\nthere, okay? So right now it's not gonna show anything, but I\n\n1308\n01:06:28,885 --> 01:06:31,953\nhaven't put any image in there either, so nothing's gonna\n\n1309\n01:06:31,955 --> 01:06:34,956\nhappen. So, I'm gonna kill two birds with one stone and\n\n1310\n01:06:34,958 --> 01:06:37,459\ndeal with that and create a new private var, which I'm\n\n1311\n01:06:37,461 --> 01:06:42,464\ngonna call image. It's gonna be a UI Image, optional, okay?\n\n1312\n01:06:42,466 --> 01:06:44,866\nAnd this is gonna be a computed var, okay? And\n\n1313\n01:06:44,868 --> 01:06:48,636\nin the set for this, this is when I'm gonna set my image,\n\n1314\n01:06:48,638 --> 01:06:52,073\nokay? So, this var, anytime I want to set the image that I'm\n\n1315\n01:06:52,075 --> 01:06:55,043\nshowing, I'm gonna set this var. And every, and I\n\n1316\n01:06:55,045 --> 01:06:57,579\ncould also use it for getting as you'll see in a second, but\n\n1317\n01:06:57,581 --> 01:06:58,313\nI'm just gonna set it. So\n\n1318\n01:06:58,315 --> 01:07:00,048\nwhat do I need to do when I set an image, okay.\n\n1319\n01:07:00,050 --> 01:07:03,218\nWell there's two things I need to do. One is I need to set\n\n1320\n01:07:03,220 --> 01:07:05,420\nthe imageView's image to that image,\n\n1321\n01:07:05,422 --> 01:07:09,057\nwhich is the newValue right? So now I've taking\n\n1322\n01:07:09,059 --> 01:07:12,927\nmy image view right here and I'm giving it the image. But\n\n1323\n01:07:12,929 --> 01:07:17,866\nI know I need to reset my frame, okay, to fit this new\n\n1324\n01:07:17,868 --> 01:07:22,604\nimage. So I'm also gonna say imageView.sizeToFit. Okay, so\n\n1325\n01:07:22,606 --> 01:07:27,075\nthis is a method on imageView that will size the imageView\n\n1326\n01:07:27,077 --> 01:07:31,513\nto fit whatever image is in it, okay? Now the get is\n\n1327\n01:07:31,515 --> 01:07:35,183\nreally easy. I'm just going to return the image view's image.\n\n1328\n01:07:35,385 --> 01:07:37,185\nSo this is an interesting var right here,\n\n1329\n01:07:37,187 --> 01:07:43,358\nit's a compute a var, that it's a computed var and\n\n1330\n01:07:43,360 --> 01:07:45,894\nit's actually storing its data somewhere else.\n\n1331\n01:07:45,896 --> 01:07:50,565\nIt's storing it in the image view, but it's intervening\n\n1332\n01:07:50,567 --> 01:07:54,969\nwhen that value gets set to do this little size to fit, okay,\n\n1333\n01:07:54,971 --> 01:07:57,872\neveryone understand why I have this image var? So\n\n1334\n01:07:57,874 --> 01:08:00,241\nnow the rest of my code looks really cool. Anytime I want to\n\n1335\n01:08:00,243 --> 01:08:02,177\nset an image I just say image equals whatever and\n\n1336\n01:08:02,179 --> 01:08:05,947\nit's going to set it in image view and size to fit it.\n\n1337\n01:08:06,116 --> 01:08:10,385\nOkay, now what else do we need to do here?\n\n1338\n01:08:10,387 --> 01:08:12,287\nSo we've got this nice image thing,\n\n1339\n01:08:12,289 --> 01:08:15,890\none thing we wanna do is whenever our model gets set,\n\n1340\n01:08:15,892 --> 01:08:18,593\nwe want to go load that image up. So,\n\n1341\n01:08:18,595 --> 01:08:22,397\nI'm gonna do a didSet here in my model. And\n\n1342\n01:08:22,399 --> 01:08:24,999\nI'm first going to set whatever image I have to nil,\n\n1343\n01:08:25,001 --> 01:08:26,267\nso if I have an image that I'm showing,\n\n1344\n01:08:26,269 --> 01:08:28,837\nI'm gonna clear that out. And now I'm going to go fetch\n\n1345\n01:08:28,839 --> 01:08:31,539\nthe image that the person is asking me for. And I'm going\n\n1346\n01:08:31,541 --> 01:08:34,209\nto do that in another little method here, fetchImage.\n\n1347\n01:08:34,211 --> 01:08:38,913\nOkay, its going to be all private func fetchImage.\n\n1348\n01:08:38,915 --> 01:08:42,417\nAnd all this thing is gonna do is gonna go out and look for\n\n1349\n01:08:42,419 --> 01:08:44,385\nthis URL either on the Internet or\n\n1350\n01:08:44,387 --> 01:08:48,323\nin a local file, okay. So how's it gonna do that?\n\n1351\n01:08:48,325 --> 01:08:53,027\nWell let's see if that URL is not nil first of all, okay so\n\n1352\n01:08:53,029 --> 01:08:57,265\nif I can let, oops, let the URL equal that image URL,\n\n1353\n01:08:57,267 --> 01:09:00,969\nokay. Now I know I have a real URL and I can go get it. So\n\n1354\n01:09:00,971 --> 01:09:05,273\nhow do I get the data from the URL to correspond to an image?\n\n1355\n01:09:05,275 --> 01:09:08,576\nWell I actually use the class NSData. Remember I mentioned\n\n1356\n01:09:08,578 --> 01:09:11,045\nthat class NSData that gets a bag of bits?\n\n1357\n01:09:11,047 --> 01:09:13,314\nIt knows how to go out to a URL on the internet and\n\n1358\n01:09:13,316 --> 01:09:17,552\nget the bag of bits. So I'm gonna say if let imageData\n\n1359\n01:09:17,554 --> 01:09:23,024\nequal the NSData's contents of URL it's called, this URL,\n\n1360\n01:09:23,026 --> 01:09:27,996\nnow I have the imageData. I just need to create a UIImage\n\n1361\n01:09:27,998 --> 01:09:30,198\nout of that and I'm good to go. So let's do that.\n\n1362\n01:09:30,200 --> 01:09:35,670\nI'm gonna set my image equal to the UIImage that is made\n\n1363\n01:09:35,672 --> 01:09:42,610\nwith that imageData. Okay, so this is an intializer for\n\n1364\n01:09:42,612 --> 01:09:46,581\nUIImage which takes the raw JPEG data basically. So\n\n1365\n01:09:46,583 --> 01:09:49,884\nhere I got the raw JPEG or png or whatever it is data.\n\n1366\n01:09:49,886 --> 01:09:52,320\nAnd here I'm just creating a UIImage out of it.\n\n1367\n01:09:52,322 --> 01:09:53,721\nAnd then I say image equals,\n\n1368\n01:09:53,723 --> 01:09:56,124\nwhich is gonna cause this setter to happen.\n\n1369\n01:09:56,126 --> 01:10:00,094\nWhich is gonna set the image in my imageView and resize my\n\n1370\n01:10:00,096 --> 01:10:04,699\nimageView to fit, all right? [COUGH] And then, we're good\n\n1371\n01:10:04,701 --> 01:10:09,337\nto go. Make sense? This code's pretty simple code,\n\n1372\n01:10:09,339 --> 01:10:12,373\nbut I've intentionally broken it down into pieces like this\n\n1373\n01:10:12,375 --> 01:10:15,276\nto show you how you can use some of these Swift mechanisms\n\n1374\n01:10:15,278 --> 01:10:19,447\nto compartmentalize your code and make things simpler. Like\n\n1375\n01:10:19,449 --> 01:10:22,283\nthis is very simple to set the image, because it's taken some\n\n1376\n01:10:22,285 --> 01:10:28,223\nof the image related handling stuff out of band there.\n\n1377\n01:10:28,225 --> 01:10:29,891\nNow we need an image to show, okay, so\n\n1378\n01:10:29,893 --> 01:10:32,627\nthe first thing I am gonna show is a little demo image,\n\n1379\n01:10:32,629 --> 01:10:35,296\nso I actually have a little class right here with some\n\n1380\n01:10:35,298 --> 01:10:38,866\ndemo URLs. Let's go take a look at this. It is actually\n\n1381\n01:10:38,868 --> 01:10:42,070\njust a struct with only static stuff in it, okay? So\n\n1382\n01:10:42,072 --> 01:10:44,606\nI've got a little Stanford URL here, to show some image of\n\n1383\n01:10:44,608 --> 01:10:47,141\nStanford, and I've also got some NASA images, which we're\n\n1384\n01:10:47,143 --> 01:10:51,212\ngoing to show when we get to this demo on Wednesday, okay?\n\n1385\n01:10:51,214 --> 01:10:56,251\nSo I'm just going to go here to my viewDidLoad, all right,\n\n1386\n01:10:56,253 --> 01:11:01,456\nand I'm going to say that my image URL, that's my model,\n\n1387\n01:11:01,458 --> 01:11:04,626\nall right. I set my model here equal to,\n\n1388\n01:11:04,628 --> 01:11:09,097\nI want to say it's equal to the demoURL.stanford, okay,\n\n1389\n01:11:09,099 --> 01:11:13,167\nthis is the demoURL.stanford that I have over here,\n\n1390\n01:11:13,169 --> 01:11:16,938\ndemoURL.stanford. Unfortunately this is\n\n1391\n01:11:16,940 --> 01:11:21,142\na string, okay, URLs are actually classes,\n\n1392\n01:11:21,144 --> 01:11:26,314\nokay, in iOS, so I have to use an NSURL constructor,\n\n1393\n01:11:26,316 --> 01:11:31,653\nwhich takes a string and turns it into a URL.\n\n1394\n01:11:33,223 --> 01:11:39,494\nGot it? Okay, so let's go ahead and run this.\n\n1395\n01:11:49,172 --> 01:11:51,873\nOkay, didn't work. It's blank and I have a little\n\n1396\n01:11:51,875 --> 01:11:54,275\nerror down here. And this is a very interesting error.\n\n1397\n01:11:54,277 --> 01:11:57,145\nOkay, you're gonna wanna pay attention here cuz it's gonna\n\n1398\n01:11:57,147 --> 01:11:59,280\nhappen when you do your. Homework next week.\n\n1399\n01:11:59,282 --> 01:12:03,451\nIt says App Transport Security has blocked a resource load\n\n1400\n01:12:03,453 --> 01:12:08,389\nsince it is insecure. By def, by default, only https,\n\n1401\n01:12:08,391 --> 01:12:12,927\nsecure http calls, are allowed to go through. If you\n\n1402\n01:12:12,929 --> 01:12:16,731\nwant insecure calls like this, okay, that's because my URL\n\n1403\n01:12:16,733 --> 01:12:21,436\nhappens to be this kind. If you want that to go through,\n\n1404\n01:12:21,438 --> 01:12:24,439\nyou have to put an entry in your info.p list.\n\n1405\n01:12:24,441 --> 01:12:27,408\nOkay, so this is what it like, looks like to put something\n\n1406\n01:12:27,410 --> 01:12:30,478\nin your info.p list, you just click on info.p list,\n\n1407\n01:12:30,480 --> 01:12:31,779\nso that's showing here, okay?\n\n1408\n01:12:31,781 --> 01:12:35,483\nAnd then you right click and say add row, okay?\n\n1409\n01:12:35,485 --> 01:12:38,119\nWhen you add a row, you can see there's [LAUGH] dozens and\n\n1410\n01:12:38,121 --> 01:12:40,855\ndozens of different things you can control in your p list\n\n1411\n01:12:40,857 --> 01:12:43,224\nhere. We actually want the third one down here,\n\n1412\n01:12:43,226 --> 01:12:46,594\nwhich is App, App Transport Security Settings.\n\n1413\n01:12:46,596 --> 01:12:49,330\nSee that right there? So App Transport Security Settings,\n\n1414\n01:12:49,332 --> 01:12:52,100\nSettings is a dictionary. So we click this to go down\n\n1415\n01:12:52,102 --> 01:12:54,902\narrow, which means we wanna edit what's in the dictionary.\n\n1416\n01:12:54,904 --> 01:12:59,707\nAnd we just hit plus, and it's gonna add a key value here.\n\n1417\n01:12:59,709 --> 01:13:01,843\nSo there's two different keys can be in that one.\n\n1418\n01:13:01,845 --> 01:13:05,012\nWe want Allow Arbitrary Loads. That allows us to load\n\n1419\n01:13:05,014 --> 01:13:11,052\narbitrary URLs, okay. And we wanna set it from NO to YES.\n\n1420\n01:13:11,054 --> 01:13:13,254\nOkay, so that means we're gonna allow arbitrary loads.\n\n1421\n01:13:13,256 --> 01:13:16,324\nSo you're definitely gonna need to do that, for\n\n1422\n01:13:16,326 --> 01:13:21,162\nyour homework. So now we run, we'll go out there.\n\n1423\n01:13:21,164 --> 01:13:22,930\nThere it is. Okay, just a picture of Stanford.\n\n1424\n01:13:22,932 --> 01:13:26,334\nNow the thing is, it's kinda good, but we can't see,\n\n1425\n01:13:26,336 --> 01:13:29,203\nwe can only see the left half of the quad here, and\n\n1426\n01:13:29,205 --> 01:13:30,605\nI can't scroll because of course,\n\n1427\n01:13:30,607 --> 01:13:33,608\nwe're not in a scroll view, all right? So how we,\n\n1428\n01:13:33,610 --> 01:13:36,310\nhow do we put this image view into a scroll view so\n\n1429\n01:13:36,312 --> 01:13:39,347\nthat we can drag it around and look at the whole thing?\n\n1430\n01:13:39,349 --> 01:13:42,617\nOkay, now for this one, for adding a scroll view, I could\n\n1431\n01:13:42,619 --> 01:13:46,487\ndo that in code as well, just like I did the image view. But\n\n1432\n01:13:46,489 --> 01:13:49,424\nto show you that it's not exclusive which you do,\n\n1433\n01:13:49,426 --> 01:13:52,126\nI'm gonna put the scroll view in the storyboard,\n\n1434\n01:13:52,128 --> 01:13:54,228\nand I'll put the image view in the code and\n\n1435\n01:13:54,230 --> 01:13:56,998\nwe can mix them, okay? So how do I do that?\n\n1436\n01:13:57,000 --> 01:13:59,100\nI'm gonna go to my storyboard right here, and\n\n1437\n01:13:59,102 --> 01:14:02,170\nI'm gonna go grab a scroll view outta here,\n\n1438\n01:14:02,172 --> 01:14:05,440\nI'm gonna search for it, actually. Scroll, here it is,\n\n1439\n01:14:05,442 --> 01:14:07,608\nScroll View. So, you're gonna drag it out and\n\n1440\n01:14:07,610 --> 01:14:15,616\nuse the blue lines to put it in the edges here. Like that.\n\n1441\n01:14:15,618 --> 01:14:18,686\nOkay, I'm gonna reset to suggested constraints.\n\n1442\n01:14:18,688 --> 01:14:20,688\nI'm gonna go over here to my Identity Inspector,\n\n1443\n01:14:20,690 --> 01:14:23,157\nwhich I always like to do when I do that reset, and\n\n1444\n01:14:23,159 --> 01:14:25,893\nmake sure you have trailing leading top, bottom.\n\n1445\n01:14:25,895 --> 01:14:27,728\nPerfect, that's exactly what I want.\n\n1446\n01:14:27,730 --> 01:14:29,564\nI obviously need an outlet to this scroll\n\n1447\n01:14:29,566 --> 01:14:30,631\nview if I'm gonna talk to it and\n\n1448\n01:14:30,633 --> 01:14:33,935\nbe its delegate, and things like that. So I'm going to get\n\n1449\n01:14:33,937 --> 01:14:36,604\nboth of these on screen at the same time, my controller and\n\n1450\n01:14:36,606 --> 01:14:41,042\nmy scroll view. Let's go ahead and control drag here,\n\n1451\n01:14:41,044 --> 01:14:45,112\nthis right here. I'm gonna call this outlet scroll view.\n\n1452\n01:14:45,114 --> 01:14:48,483\nNotice here's the weak, strong by the way, okay? If my scroll\n\n1453\n01:14:48,485 --> 01:14:51,285\nview leaves my view hierarchy, it can set me to nil, I am\n\n1454\n01:14:51,287 --> 01:14:55,756\nfine. Connect, okay, we've got our scroll view here. Now,\n\n1455\n01:14:55,758 --> 01:15:00,895\nall we need to do is set the image view as a subview\n\n1456\n01:15:00,897 --> 01:15:05,032\nof our scroll view instead of as a sub, subview of our top\n\n1457\n01:15:05,034 --> 01:15:08,102\nlevel view. So, really, all I need to do is change this\n\n1458\n01:15:08,104 --> 01:15:12,640\nto scrollView, okay, and it's gonna add as a subview. Now,\n\n1459\n01:15:12,642 --> 01:15:16,410\nlet's see, is this gonna work? Probably not cuz I wouldn't\n\n1460\n01:15:16,412 --> 01:15:19,981\nhave asked that question. Why is this not gonna work,\n\n1461\n01:15:19,983 --> 01:15:21,616\ndo you think? It looks like it worked,\n\n1462\n01:15:21,618 --> 01:15:25,920\nright? Let's scroll, it's not, why isn't this scrolling?\n\n1463\n01:15:25,922 --> 01:15:28,956\nWhat's going on? I put a scrollView in there. Is it,\n\n1464\n01:15:28,958 --> 01:15:30,424\nwhat's wrong with this thing? Okay,\n\n1465\n01:15:30,426 --> 01:15:33,361\nanyone have any idea why this is not scrolling?\n\n1466\n01:15:33,363 --> 01:15:34,262\n>> Content size.\n\n1467\n01:15:34,264 --> 01:15:35,096\n>> Bingo.\n\n1468\n01:15:35,098 --> 01:15:36,163\nIf I had a can, if I was Mehran,\n\n1469\n01:15:36,165 --> 01:15:39,433\nI'd be throwing candy out to you. Yeah, absolutely,\n\n1470\n01:15:39,435 --> 01:15:42,737\nno content size, so it's currently scrolling fine over\n\n1471\n01:15:42,739 --> 01:15:47,008\na zero by zero area, okay. And the image is just bleeding out\n\n1472\n01:15:47,010 --> 01:15:49,777\nfrom the edges of it, okay? So we need to set the content\n\n1473\n01:15:49,779 --> 01:15:52,346\nsize. Where do we set the content size? Well, one place\n\n1474\n01:15:52,348 --> 01:15:55,316\nwe definitely need to set it is anytime we have an image\n\n1475\n01:15:55,318 --> 01:15:58,152\nbecause we want the content size to fit the whole image.\n\n1476\n01:15:58,154 --> 01:16:02,590\nSo here, I would just say scrollView.contentSize,\n\n1477\n01:16:02,592 --> 01:16:09,163\ncontentSize = what, ever our image view's frame size is.\n\n1478\n01:16:09,165 --> 01:16:11,632\nOne thing I'm gonna do here is kinda tricky,\n\n1479\n01:16:11,634 --> 01:16:15,336\nis I'm gonna put a question mark right there. Why might I\n\n1480\n01:16:15,338 --> 01:16:20,875\nput a question mark there? Because this scrollView\n\n1481\n01:16:20,877 --> 01:16:25,146\nis an outlet. If this image setting happened, for example,\n\n1482\n01:16:25,148 --> 01:16:28,783\nwhen someone was preparing me, this would crash.\n\n1483\n01:16:28,785 --> 01:16:31,686\nCuz my scrollView wouldn't be set in prepare. Now no one,\n\n1484\n01:16:31,688 --> 01:16:33,921\nno one is yet segueing to me. But on Wednesday,\n\n1485\n01:16:33,923 --> 01:16:36,257\nthey're going to be. [LAUGH] So I have to be careful here.\n\n1486\n01:16:36,259 --> 01:16:39,193\nSo here, if I haven't set up my scrollView and\n\n1487\n01:16:39,195 --> 01:16:42,697\nI get an image, I'm just gonna do nothing. Well,\n\n1488\n01:16:42,699 --> 01:16:45,466\nthen I better do something when the scrollView gets set,\n\n1489\n01:16:45,468 --> 01:16:47,668\nokay? When the scrollView comes along later, later and\n\n1490\n01:16:47,670 --> 01:16:49,937\ngets set, I better do this content size, so\n\n1491\n01:16:49,939 --> 01:16:52,373\nI better do it in both places here. And here,\n\n1492\n01:16:52,375 --> 01:16:56,978\nwe don't need that, okay? See why I'm doing in both places,\n\n1493\n01:16:56,980 --> 01:16:58,613\ncuz I'm not sure which is gonna happen first.\n\n1494\n01:16:58,615 --> 01:17:01,215\nIs my scroll view gonna get set first, or my outlet,\n\n1495\n01:17:01,217 --> 01:17:03,985\nyou know, or my, model and thus my image gonna be set\n\n1496\n01:17:03,987 --> 01:17:09,924\nfirst? Okay? Okay, so now let's run, see if this works.\n\n1497\n01:17:14,230 --> 01:17:15,930\nAll right, here it is. And sure enough,\n\n1498\n01:17:15,932 --> 01:17:19,066\nscrolled beautifully, okay, and even if we rotate and\n\n1499\n01:17:19,068 --> 01:17:23,304\nscroll. All right, so that's great, it's working\n\n1500\n01:17:23,306 --> 01:17:27,174\nwonderfully. On Wednesday, we'll talk about zooming cuz\n\n1501\n01:17:27,176 --> 01:17:30,244\nwe wanna be able to zoom in on this. Then we're also going to\n\n1502\n01:17:30,246 --> 01:17:32,813\ntalk a little bit about what happens if these images\n\n1503\n01:17:32,815 --> 01:17:35,416\nare huge and take a long time to download. That's hard for\n\n1504\n01:17:35,418 --> 01:17:38,285\nme to demo on this network cuz this network is so fast.\n\n1505\n01:17:38,287 --> 01:17:41,188\nBut I have some huge NASA images that I think will go\n\n1506\n01:17:41,190 --> 01:17:42,423\nslow enough that you're gonna see my\n\n1507\n01:17:42,425 --> 01:17:45,159\nUI is really sluggish as I wait for these,\n\n1508\n01:17:45,161 --> 01:17:47,662\nthings to download. And that's why we use multithreading,\n\n1509\n01:17:47,664 --> 01:17:50,097\nWednesday's topic, to figure out how to make it all really,\n\n1510\n01:17:50,099 --> 01:17:53,300\nreally, really snappy. Okay, that's it,\n\n1511\n01:17:53,302 --> 01:17:55,102\nI'll see you then. >> For\n\n1512\n01:17:55,104 --> 01:17:55,135\nmore, please visit us at stanford.edu.\n\n"
  },
  {
    "path": "subtitles/8. Multithreading and Text Field.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:03,802\n[MUSIC]\n\n2\n00:00:03,804 --> 00:00:08,040\nStandford University. >> All right,\n斯坦福大学\n\n3\n00:00:08,042 --> 00:00:13,746\nwelcome then to lecture number eight. I think it's eight,\n欢迎参加第八讲。好像是第八讲。\n\n4\n00:00:13,748 --> 00:00:18,083\nyes, of CS193P Spring of 2016. So today, we start off\n是的，2016 春季 CS193P 课程。今天，我们将\n\n5\n00:00:18,085 --> 00:00:21,020\nby continuing that demo that we were doing last time.\n继续完成上一次的 demo\n\n6\n00:00:21,022 --> 00:00:24,423\nRemember we had the demo, Cassini demo with the, scroll\n今天用到之前 scroll view 写的 Cassini\n\n7\n00:00:24,425 --> 00:00:27,693\nview in there. And so I'm gonna make it more powerful,\n让它功能更加强大.\n\n8\n00:00:27,695 --> 00:00:30,262\nwe're gonna get multiple MVCs going in there.\n我们将会用到多个 MVC 的结构.\n\n9\n00:00:30,264 --> 00:00:34,533\nWe'll start doing some zooming in the scroll view.\n会用到 scroll view 的缩放属性.\n\n10\n00:00:34,535 --> 00:00:37,703\nDepending on how the time goes I might actually show you some\n如果有时间，我会通过实际案例来\n\n11\n00:00:37,705 --> 00:00:40,406\nthings that couple of you have asked about on Piazza.\n解答有些同学对 Piazza 项目的疑问.\n\n12\n00:00:40,408 --> 00:00:44,009\nLike, how to when I launch my calculator app can I have it\n例如，在启动我的计算器 app 的时候，\n\n13\n00:00:44,011 --> 00:00:46,311\nnot launch and show a blank graph, right,\n因为没有启动图而显示空白的情况.\n\n14\n00:00:46,313 --> 00:00:49,314\nhow can I have it launch and show the calculator for\n怎样才能在在第一次启动计算器时，\n\n15\n00:00:49,316 --> 00:00:52,651\nthe very first time, okay, those kinds of things.\n显示启动页等，诸如此类的问题.\n\n16\n00:00:52,653 --> 00:00:53,652\nSo we'll see how the time goes and\n最后，我们会根据时间安排\n\n17\n00:00:53,654 --> 00:00:56,121\ndecide on the fly whether to do that stuff.\n来决定是否要解答这些.\n\n18\n00:00:56,123 --> 00:00:57,623\nThen we're gonna dive back into the slides.\n让我们回到幻灯片上.\n\n19\n00:00:57,625 --> 00:00:59,358\nI'm gonna talk about multi-threading, okay?\n我之后还会讲到多线程.\n\n20\n00:00:59,360 --> 00:01:04,029\nVery, very important thing in iOS is how to multithread\n在 iOS 上，多线程的处理是非常非常重要的内容.\n\n21\n00:01:04,031 --> 00:01:06,799\nyour execution. And then I'll go back to the demo, and\n然后我们会回到 Cassini demo,\n\n22\n00:01:06,801 --> 00:01:10,436\nwe'll multithread this Cassini thing we're working on, okay?\n为它加上多线程支持.\n\n23\n00:01:10,438 --> 00:01:12,104\nAnd then time permitting at the end I'll go back to\n在时间允许的情况下, 最后还会回到幻灯片\n\n24\n00:01:12,106 --> 00:01:14,673\nthe slides and I'm gonna talk about text fields. And\n讲一下 text field. 然后\n\n25\n00:01:14,675 --> 00:01:19,511\nthen, next week we have table views, databases, etc. And\n下周会讲 table view，database 等内容.\n\n26\n00:01:19,513 --> 00:01:21,947\nagain, remember, no assignment going out today.\n今天不会布置作业.\n\n27\n00:01:21,949 --> 00:01:24,283\nThe assignment is gonna be a table view based thing, so\n作业是基于 table view 的,\n\n28\n00:01:24,285 --> 00:01:27,986\nit will go out after Monday's lecture, all right? So,\n所以我们会在下周一课程之后再布置, 没问题吧.\n\n29\n00:01:27,988 --> 00:01:30,589\nlet's dive back into this Cassini demo. Okay,\n那么, 让我们回到 Cassini demo.\n\n30\n00:01:30,591 --> 00:01:36,762\nwe'll start off just exactly where we left off before. So\n接着上一次的内容继续完善.\n\n31\n00:01:36,764 --> 00:01:41,100\nwe'll go to Xcode here. So I'm just gonna open Cassini,\n启动 Xcode, 打开 Cassini\n\n32\n00:01:41,102 --> 00:01:42,868\nhere it is. I'm just gonna run it real quick just\n我先来带大家快速过一遍\n\n33\n00:01:42,870 --> 00:01:47,139\nto remind you where we were for those with short memories.\n回忆下之前的内容.\n\n34\n00:01:47,141 --> 00:01:53,812\nEven though it's only two days ago. All right,\n虽然是两天前才讲的.\n\n35\n00:01:53,814 --> 00:01:56,915\nhere it is. So we've got, our image view, right?\n好的, 我们有一个 image view.\n\n36\n00:01:56,917 --> 00:02:00,285\nWe have an ImageView and it's inside a UIScrollView, and so\n这个 ImageView 嵌套在 UIScrollView 中,\n\n37\n00:02:00,287 --> 00:02:03,922\nwe're able to scroll around, okay, just by panning with our\n所以我们可以进行滚动, 用手指滑动就行\n\n38\n00:02:03,924 --> 00:02:06,291\nfinger. My mouse is like a finger there, so\n这光标就是手指\n\n39\n00:02:06,293 --> 00:02:10,262\nI'm just panning around, and that's all we can do, okay?\n目前就只能随意滑动\n\n40\n00:02:10,264 --> 00:02:11,997\nBut we've created this nice UI, or\n但是我们这个漂亮的界面\n\n41\n00:02:11,999 --> 00:02:15,734\nthis nice ImageViewController, which is an MVC that lets you\n或者说, 漂亮的 ImageViewController 所用的 MVC 模式,\n\n42\n00:02:15,736 --> 00:02:19,371\ntake any image and put it on screen inside the scroll view,\n能任意将图片加入到 scroll view 中, 并显示出来\n\n43\n00:02:19,373 --> 00:02:23,108\nthat's kind of a nice reusable, reusable MVC, right?\n有很好的重用性, 重用 MVC, 对吧\n\n44\n00:02:23,110 --> 00:02:26,378\nSo now we're going to make this a multi-MVC app, okay,\n接下来, 我们会做一个多 MVC 的 app\n\n45\n00:02:26,380 --> 00:02:28,213\nand I'm gonna reuse this ImageViewController\n重用的 ImageViewController\n\n46\n00:02:28,215 --> 00:02:31,450\nas one of the MVCs. So let's go right to our storyboard,\n也是其中之一. 让我们打开 storyboard.\n\n47\n00:02:31,452 --> 00:02:32,117\nsee what this is gonna look like.\n来看看里面都有什么内容\n\n48\n00:02:32,119 --> 00:02:34,419\nThis is where the Cassini part of this whole thing is gonna\nCassini 所展示的内容都从这里得到.\n\n49\n00:02:34,421 --> 00:02:37,589\ncome in. All right, I'm gonna create a new View Controller,\n现在, 我准备创建一个新的 View Controller\n\n50\n00:02:37,591 --> 00:02:39,224\njust gonna drag it out right here. Again,\n将它拖到这里就可以了\n\n51\n00:02:39,226 --> 00:02:41,693\nI'm gonna go fairly quickly, cuz I've done this all before,\n之前我们已经做过了, 所以这一步操作有点快\n\n52\n00:02:41,695 --> 00:02:44,630\nso this is almost like a review, for you here.\n更像是在帮大家复习\n\n53\n00:02:44,632 --> 00:02:45,397\nSo, I have this controller.\n好, controller 创建好了\n\n54\n00:02:45,399 --> 00:02:48,700\nIt needs to have a custom subclass of UIViewController\n因为需要自定义 UIViewController\n\n55\n00:02:48,702 --> 00:02:51,904\nso I'm going to create such a thing. Go here to New File,\n所以要做接下来的这些操作. 创建一个新文件\n\n56\n00:02:51,906 --> 00:02:55,274\nit's iOS source, it's a Cocoa Touch Class. Cuz it's\n选择 iOS source, Cocoa Touch Class, 因为\n\n57\n00:02:55,276 --> 00:02:58,210\na subclass of an iOS class, which is a UIViewController in\n要子类化的类属于 iOS, 这里是 UIViewController\n\n58\n00:02:58,212 --> 00:03:01,647\nthis case. I'm going to call this CassiniViewController,\n类名就叫 CassiniViewController 吧\n\n59\n00:03:01,649 --> 00:03:04,149\ncuz it's gonna let us look at some Cassini images.\n这个类会展示更多 Cassini 的图片\n\n60\n00:03:04,151 --> 00:03:08,587\nThat's what our app is gonna do. But just in the same place\n也是这个 app 的需求. 存放路径和之前一样\n\n61\n00:03:08,589 --> 00:03:11,523\nas always here is our CassiniViewController,\nCassiniViewController 创建好了\n\n62\n00:03:11,525 --> 00:03:15,327\nI'm gonna remove the view controller lifecycle methods\n暂时先删除模板给出的 view controller\n\n63\n00:03:15,329 --> 00:03:18,630\nthat it gives me right here just for now anyway.\n生命周期方法\n\n64\n00:03:18,632 --> 00:03:22,067\nAnd I'm actually gonna uncomment this prepareForSegue\n然后打开 prepareForSegue 的注释\n\n65\n00:03:22,069 --> 00:03:24,002\nbecause my CassiniViewController is\n因为 CassiniViewController 会\n\n66\n00:03:24,004 --> 00:03:27,005\ndefinitely going to be doing, some segueing.\n用到这个方法, 一些 segue\n\n67\n00:03:27,007 --> 00:03:29,341\nSo let's now go back to our storyboard,\n现在让我们回到 storyboard\n\n68\n00:03:29,343 --> 00:03:32,744\nnow that we have this ImageViewController class, and\n我们已经有了 ImageViewController\n\n69\n00:03:32,746 --> 00:03:36,315\nI'm gonna change the class of this controller right here\n再通过 identity inspector, 将这个\n\n70\n00:03:36,317 --> 00:03:40,452\nwith the identity inspector, to be a CassiniViewController,\ncontroller 改为 CassiniViewController\n\n71\n00:03:40,454 --> 00:03:45,724\nokay. Everybody got that? I'm going to put this whole\n好的, 都能跟上吧? 接下来, 我会将整个\n\n72\n00:03:45,726 --> 00:03:49,494\nMVC structure into that split view with navigation that's\nMVC 结构装到 split view 中\n\n73\n00:03:49,496 --> 00:03:52,331\nover in there, the thing that will work in both iPad and\n这样就能同时用 iPad 和\n\n74\n00:03:52,333 --> 00:03:55,300\niPhone, exact same thing we did for,\niPhone 上, 这种处理方式我们在\n\n75\n00:03:55,302 --> 00:03:57,869\nthe emotions view controller. So, let's do that.\nemotions view controller 上也做过. 下面来实现吧.\n\n76\n00:03:57,871 --> 00:04:00,939\nI'm going to start by dragging out the split view controller,\n接下来需要拖一个 split view controller\n\n77\n00:04:00,941 --> 00:04:02,007\nI'm gonna zoom way out here.\n先缩小画板\n\n78\n00:04:02,009 --> 00:04:04,810\nLet's go get a Split View Controller, here it is. I'll\n然后找到 Split View Controller\n\n79\n00:04:04,812 --> 00:04:09,781\ndrag it out. I'll get rid of these extra things that came\n拖拽出来. 删掉除了\n\n80\n00:04:09,783 --> 00:04:12,551\nalong here with the Split View Controller because I already\nSplit View Controller 的其他内容, 因为我们已经\n\n81\n00:04:12,553 --> 00:04:15,153\nhave my master and detail right here. The Cassini's\n有自己的 master 和 detail 了. Cassini 是\n\n82\n00:04:15,155 --> 00:04:17,956\ngonna be my master and this ImageViewController's gonna be\nmaster, ImageViewController 是 detail.\n\n83\n00:04:17,958 --> 00:04:21,260\nmy detail right there. So I'm just gonna Control drag, hook\n按住 Control 并拖拽到 master\n\n84\n00:04:21,262 --> 00:04:25,197\nup my master. And a Control drag, hook up my detail.\n然后按住 Control 并拖拽到 detail\n\n85\n00:04:25,199 --> 00:04:28,400\nI'm also gonna take my little entry arrow and make it so\n接下来, 将入口箭头移动到\n\n86\n00:04:28,402 --> 00:04:31,136\nthat it enters on the Split View Controller. Right,\nSplit View Controller\n\n87\n00:04:31,138 --> 00:04:32,738\ninstead of entering on my Image View Controller,\nImage View Controller 不再是入口\n\n88\n00:04:32,740 --> 00:04:37,376\nobviously. And, I want this to work on both iPhone and iPad,\n我想要在 iPhone 和 iPad 上使用\n\n89\n00:04:37,378 --> 00:04:41,013\nso I'm gonna take my master and put it embedded inside\n所以, 我准备将 master 嵌入到 \n\n90\n00:04:41,015 --> 00:04:45,917\nof a navigation controller, okay? And maybe I can even go\nnavigation controller 中, 然后我能在这\n\n91\n00:04:45,919 --> 00:04:50,589\nin here and put a nice title here, right here. Cassini,\n给它加上 title. Cassini.\n\n92\n00:04:50,591 --> 00:04:54,626\nokay? All right now, what is this UI going to do?\n跟上了吗? 最终, 这个界面到底有什么作用?\n\n93\n00:04:54,628 --> 00:04:57,029\nWhat's it going to look like? How's it gonna function?\n长什么样呢? 怎样触发一些功能?\n\n94\n00:04:57,031 --> 00:04:59,598\nWell, I'm just gonna have three buttons here.\n好的, 我会在这里放 3 个按钮\n\n95\n00:04:59,600 --> 00:05:01,500\nSimilar to how I had in emotions view controller.\n和之前的 emotions view controller 很像\n\n96\n00:05:01,502 --> 00:05:04,102\nIn a demo I can only do, I can't do a nice complicated\n在 demo 中也只能这样了, 不能像计算器\n\n97\n00:05:04,104 --> 00:05:07,172\nMVC like a calculator and then another complicated one like\n一样有复杂的 MVC 结构, 也不能像\n\n98\n00:05:07,174 --> 00:05:09,808\na graph view. I have to do a simple one. So I'm gonna do\ngraph view 那样复杂. 只能做个简单的界面了. 所以我也只好\n\n99\n00:05:09,810 --> 00:05:11,877\na simple one here. Where I'm gonna put three buttons and\n这样了. 之所以我要放三个按钮,\n\n100\n00:05:11,879 --> 00:05:15,180\nthose three buttons are just going to cause three different\n是因为要展示三张\n\n101\n00:05:15,182 --> 00:05:20,285\nimages from NASA, okay, about Cassini which is a little\nNASA 的图片. 至于 Cassini, 它是被\n\n102\n00:05:20,287 --> 00:05:22,988\nthing sent out into space to take pictures. I'm gonna put\n发送到太空来拍摄图片的. 我会把\n\n103\n00:05:22,990 --> 00:05:25,223\nthose three buttons here and then were just gonna segue,\n三个按钮放到这, 然后我们处理 segue,\n\n104\n00:05:25,225 --> 00:05:27,826\nas we know how to do, down to here,\n大家应该知道怎么做. 将 ImageViewController\n\n105\n00:05:27,828 --> 00:05:29,194\nwhich is gonna be our ImageViewController,\n放到下面来\n\n106\n00:05:29,196 --> 00:05:30,662\nall right. So the Image View Controller's just gonna show\nImage View Controller 会用来显示图片\n\n107\n00:05:30,664 --> 00:05:33,065\nthe image, and we already know that the Image View Controller\n我们已经知道展示图片的 Image View Controller 是一个\n\n108\n00:05:33,067 --> 00:05:35,901\nis a nice, little, reasonable MVC that shows an image.\n优雅的, 小巧的, 合理的 MVC 结构.\n\n109\n00:05:35,903 --> 00:05:37,836\nSo it's perfect, exactly what I want. So\n如此完美, 正是我们想要的\n\n110\n00:05:37,838 --> 00:05:39,871\nI'm gonna go down here and get the buttons. So it's this\n向下滚动, 找到按钮.\n\n111\n00:05:39,873 --> 00:05:44,343\nbutton right here. Let's go ahead and make it bigger,\n将按钮放在这. 继续, 把它放大点,\n\n112\n00:05:44,345 --> 00:05:48,580\nI'll say 40 point would be a pretty good size here.\n设置为 40 点看起来比较好\n\n113\n00:05:48,582 --> 00:05:52,417\nAnd, make three of them, copy, paste so\n然后创建三个这样按钮, 复制, 粘贴\n\n114\n00:05:52,419 --> 00:05:56,154\nI get that. Okay, one of them is gonna be called Earth,\n好了, 一个叫做 Earth\n\n115\n00:05:56,156 --> 00:05:59,291\nanother one is gonna be called Cassini.\n一个叫做 Cassini.\n\n116\n00:05:59,293 --> 00:06:02,194\nAnd another one is gonna be called Saturn, okay?\n剩下的一个叫 Saturn, 好了吗?\n\n117\n00:06:02,196 --> 00:06:04,262\nAnd then I'm just gonna take these three things.\n然后, 将这三个按钮\n\n118\n00:06:04,264 --> 00:06:06,031\nOf course it put them in a stack view.\n放到 stack view 中\n\n119\n00:06:06,033 --> 00:06:11,903\nOkay, we'll go ahead and have the stack view be fill.\nok, 将 stack view 对齐方式设置为 fill.\n\n120\n00:06:11,905 --> 00:06:13,338\nAnd we'll also do again fill equally.\n然后将分布设置为 fill equally.\n\n121\n00:06:13,340 --> 00:06:15,474\nIt doesn't really matter because they're all identical,\n这些都无关紧要, 它们都是相同的\n\n122\n00:06:15,476 --> 00:06:17,909\nthey're all buttons. We'll put a little spacing in there,\n都是按钮. 然后给它们加一些间隙\n\n123\n00:06:17,911 --> 00:06:21,179\nmaybe. 20 points something like that. Then I'm gonna drag\n20 点之类的. 接下来将它拖到\n\n124\n00:06:21,181 --> 00:06:24,082\nthis into the middle use my blue lines right there so that\n视图中间, 有蓝色对齐线这里\n\n125\n00:06:24,084 --> 00:06:27,152\nI can go here and say Reset to suggested constraints.\n点击这里, 选择 Reset to suggested constraints (重置为建议约束).\n\n126\n00:06:27,154 --> 00:06:29,588\nAnd then I'm gonna go over to my size inspector and\n接着看到 size inspector\n\n127\n00:06:29,590 --> 00:06:32,224\ndouble check that it did the kind of constraints I want.\n再次确认约束是否正确添加\n\n128\n00:06:32,226 --> 00:06:35,227\nWhich that looks good to me it's gonna align these things\n看来这些约束能正确将\n\n129\n00:06:35,229 --> 00:06:39,030\nin the center, okay? So, here's our UI right here.\n视图居中, 好了吗? 这就是我们的 UI 了.\n\n130\n00:06:39,032 --> 00:06:43,802\nNow, all we need to do is have these three things segue down\n现在, 就只需要将这三个按钮的事件和下面\n\n131\n00:06:43,804 --> 00:06:47,472\nto here to fill these images. Now, I'll show you where these\n这个关联, 来显示图片了. 之后, 我会展示这些\n\n132\n00:06:47,474 --> 00:06:49,841\nimages come from in a minute here, but let's just create\n图片从哪来, 现在先来创建 segue.\n\n133\n00:06:49,843 --> 00:06:52,110\nthe segue. Now, I'm gonna do something a little different\n这次我们处理 segue 的方式和之前不一样.\n\n134\n00:06:52,112 --> 00:06:55,847\nwith this segue. In our last one I, each segue had\n之前, 每个 segue 都有\n\n135\n00:06:55,849 --> 00:06:57,816\nits own identifier that was different, and\n自己的 identifier, 每一个都不同\n\n136\n00:06:57,818 --> 00:07:00,619\nit was the identifier that let us know which emotion to\n这些 identifier 使我们知道应该\n\n137\n00:07:00,621 --> 00:07:03,488\nshow in the emotions one. Here I'm gonna have them all have\n显示哪个表情. 这一次, 它们只有\n\n138\n00:07:03,490 --> 00:07:06,591\nthe same identifier, and I'm gonna use the title of\n一个相同的 identifier, 我将使用按钮的 title\n\n139\n00:07:06,593 --> 00:07:09,628\nthe button to decide which image, okay? So it's kind of\n来决定显示的图片. 所以, \n\n140\n00:07:09,630 --> 00:07:11,897\na cross between what we did in the calculator and\n这和我们之前做计算器,\n\n141\n00:07:11,899 --> 00:07:14,666\nwhat we did in emotions, all right? So, let's go ahead and\n做表情的处理不一样.\n\n142\n00:07:14,668 --> 00:07:17,969\ncreate these things. So, I'm gonna, Control drag, okay,\n下面我们来创建 segue 吧. 按钮 Contorl 并拖拽,\n\n143\n00:07:17,971 --> 00:07:21,540\nfrom Saturn down to here. This is in a split view, right,\n从 Saturn 到这里. 他们都在 split view 中.\n\n144\n00:07:21,542 --> 00:07:22,374\nso I'm gonna do Show Detail, right?\n选择 Show Detail.\n\n145\n00:07:22,376 --> 00:07:25,143\nThat's the kind of segue I want, not show. The same thing\n这才是我想要的 segue, 而不是 Show.\n\n146\n00:07:25,145 --> 00:07:29,514\nwith Cassini right here, Show Detail. And then up here to\nCassini 也是同样, ShowDetail. 接着是\n\n147\n00:07:29,516 --> 00:07:34,486\nEarth, Show Detail. Whoops, not Present Modally, undo,\nEarch, Show Detail. 噢, 不是 Present Modally, 撤销,\n\n148\n00:07:34,488 --> 00:07:38,990\nlet's try that again. Show Detail. Okay, so\n重新来一次, Show Detail.\n\n149\n00:07:38,992 --> 00:07:41,092\nwe've got these three things here. Let's go ahead and\n这三个就关联好了. 然后来检查下.\n\n150\n00:07:41,094 --> 00:07:43,662\ninspect them. I'm gonna put an identifier on them but\n我准备给它们设置 identifier, 但\n\n151\n00:07:43,664 --> 00:07:45,163\nthey're all gonna have the same identifier.\n它们的 identifier 都相同.\n\n152\n00:07:45,165 --> 00:07:48,266\nAnd what that means is when prepareForSegue gets called,\n那么, 这在调用 prepareForSegue 时意味着什么呢\n\n153\n00:07:48,268 --> 00:07:51,169\nit's gonna be called, and the same thing is gonna happen for\n调用时, 他们所触发的事件都是相同的.\n\n154\n00:07:51,171 --> 00:07:53,505\neach one. Again I'm gonna look at the sender in\n不过, 可以通过\n\n155\n00:07:53,507 --> 00:07:54,706\nprepareForSegue to know which button,\nprepareForSegue 的 sender 来区别按钮,\n\n156\n00:07:54,708 --> 00:07:57,175\nbut we're gonna use the same code. So I'm gonna call this\n但是它们的代码是共用的. 所以, 就命名为\n\n157\n00:07:57,177 --> 00:08:00,345\nShow Image, cuz that's what it does, okay, when you click On\nShow Image 吧, 见名知意.\n\n158\n00:08:00,347 --> 00:08:03,381\nhere to segue, it segues to this image view controller and\n点击 Segue, 跳转到 image view controller\n\n159\n00:08:03,383 --> 00:08:06,585\nshows an image. Okay, so let's make sure all three of\n显示图片. 确保三个按钮都\n\n160\n00:08:06,587 --> 00:08:10,755\nthem are doing that. Okay, so everybody cool with this?\n设置好. 好了, 大家对这一步有疑问吗?\n\n161\n00:08:10,757 --> 00:08:14,092\nThis is all just review, I haven't done anything new, yet\n以上是对之前的回顾，还没添加新的知识点\n\n162\n00:08:14,094 --> 00:08:17,829\nhere. K, now of course we know if we want these\n如果想要这些 segue 生效\n\n163\n00:08:17,831 --> 00:08:21,366\nlittle segues here to work, we need to prepare them, so\n还需要准备 segue\n\n164\n00:08:21,368 --> 00:08:25,003\nlet's go back to our Cassini View Controller right here and\n接下来回到 Cassini View Controller，\n\n165\n00:08:25,005 --> 00:08:27,973\ndo our prepare for segue. I'm gonna show you something\n准备 segue. 接下来我会演示如何\n\n166\n00:08:27,975 --> 00:08:31,109\nthat's kind of nice to do from a clean coding mechanism,\n在用纯代码来实现\n\n167\n00:08:31,111 --> 00:08:35,747\nwhich is I like to create a private struct here to\n我比较喜欢创建一个私有 struct\n\n168\n00:08:35,749 --> 00:08:38,750\nstore my constants that are strings in the storyboard.\n来存放 storyboard 中 string 类型的常量\n\n169\n00:08:38,752 --> 00:08:42,754\nSo I usually call this thing storyboard okay? And then I\n所以命名为 storyboard\n\n170\n00:08:42,756 --> 00:08:47,225\njust put these static lets inside. So the ShowImageSegue\n然后将这些静态常量放到 struct 中. ShowImageSegue\n\n171\n00:08:47,227 --> 00:08:51,296\n= \"Show Image\". So that this string, and basically any\n= \"Show Image\". 就是这样. 在\n\n172\n00:08:51,298 --> 00:08:55,400\nstring that I put anywhere in my story board, like in these,\nstoryboard 中的其他 string 也都和这个类似，\n\n173\n00:08:55,402 --> 00:08:58,236\nwhen I inspect these things down here like this string.\n比如看到的这个下面这个 string\n\n174\n00:08:58,238 --> 00:09:02,440\nOkay? That's all collected here into this nice struct.\n将这些都添加到 struct 中\n\n175\n00:09:02,442 --> 00:09:03,208\nOkay? So\n到此，\n\n176\n00:09:03,210 --> 00:09:05,644\nwe already know that this is what we do to do constants,\n我们已经知道怎样处理这些常量了\n\n177\n00:09:05,646 --> 00:09:08,113\nokay? I'm just calling this group of constants storyboard.\n我暂且把这个集合称为 storyboard 常量集吧\n\n178\n00:09:08,115 --> 00:09:10,882\nThey're my storyboard constants, all right?\n这就是我的 storyboard 常量集了\n\n179\n00:09:10,884 --> 00:09:14,252\nAll right, so let's do prepare for segue right here.\n然后在这里准备 segue\n\n180\n00:09:14,254 --> 00:09:15,820\nWhat do we need to do in prepare for segue?\n我们需要在 prepareForsSegue 中做哪些处理？\n\n181\n00:09:15,822 --> 00:09:19,324\nWell first of all, we probably want to make sure that this is\n首先，我们要确保 segue 是\n\n182\n00:09:19,326 --> 00:09:23,194\nthe show image segue, so I'm going to say if the segue's\nshow image segue，所以先进行判断\n\n183\n00:09:23,196 --> 00:09:28,366\nidentifier = the storyboard.ShowImageSegue.\nsegue 的 identifier 是否等于 Storyboard.ShowImageSegue\n\n184\n00:09:28,368 --> 00:09:31,469\nOkay? Then we know this is what we're preparing for.\n这一步是保证我们处理的是正确的 segue\n\n185\n00:09:31,471 --> 00:09:34,539\nAnd remember,\n记住，在一个复杂的 app 中，可能会有很多不同的\n\n186\n00:09:34,541 --> 00:09:37,309\nof segues, like we have in emotions actually, with\nsegue，就像我们有不同的情绪一样，它们有\n\n187\n00:09:37,311 --> 00:09:39,911\ndifferent identifiers going off. So that's why we almost\n不同的标识. 所以我们\n\n188\n00:09:39,913 --> 00:09:43,114\nalways check the identifier first just to make sure\n通常使用 identifier 来确保\n\n189\n00:09:43,116 --> 00:09:44,583\nthat we are doing the right thing, and\n处理方式是对的\n\n190\n00:09:44,585 --> 00:09:48,153\nusually we'll try and spell identifier properly. Okay.\n当然，还需要正确的拼写 identifier\n\n191\n00:09:48,155 --> 00:09:52,157\nSo now, we know this is the right segue. We need to get\n现在，我们知道这里就是想要的 segue 了. 还需要\n\n192\n00:09:52,159 --> 00:09:55,293\nthe MVC that we're segueing to so we can prepare it.\n有一个 MVC 结构来准备 segue\n\n193\n00:09:55,295 --> 00:09:57,662\nSo we know that's supposed to be an Image View Controller so\n假设需要的是 Image View Controller\n\n194\n00:09:57,664 --> 00:10:00,999\nI'm going to say if I can let IVC, short for\n所以定义一个叫做 ivc 的常量\n\n195\n00:10:01,001 --> 00:10:01,900\nImage View Controller,\nImageViewController 的简写\n\n196\n00:10:01,902 --> 00:10:07,772\nequal the segue's destination view controller as\n等于 segue 的 destinationViewController\n\n197\n00:10:07,774 --> 00:10:11,843\nan image view controller. Okay.\n转换为 ImageViewController\n\n198\n00:10:11,845 --> 00:10:15,513\nSo if I, I don't even need the parentheses there, sorry. So\n这里不需要大括号，不好意思\n\n199\n00:10:15,515 --> 00:10:19,217\nif I can get that destination view controller as an image\n如果能正确将 destinationViewController 转为\n\n200\n00:10:19,219 --> 00:10:24,122\nview controller then now I'm ready to prepare this thing.\nImageViewController，那么就可以开始做一些准备了\n\n201\n00:10:24,124 --> 00:10:26,024\nSo, how do I need to prepare it? Well,\n怎样去准备呢？\n\n202\n00:10:26,026 --> 00:10:29,828\nit depends on which button Is doing this show image, okay.\n这要取决于哪个按钮触发显示图片事件\n\n203\n00:10:29,830 --> 00:10:32,564\nSo, I'm actually gonna look back at the button. Now,\n所以，回头看看这些按钮\n\n204\n00:10:32,566 --> 00:10:34,966\nhere's the button. Remember it prepares for segue.\n这个参数就是按钮，并且是谁触发的 segue，\n\n205\n00:10:34,968 --> 00:10:38,970\nThe sender is the button or the line in a table or\n那这个 sender 就是谁，可能是按钮或者 table 的某一行\n\n206\n00:10:38,972 --> 00:10:40,772\nsomething like that that caused it to happen.\n或者其他触发事件的对象\n\n207\n00:10:40,774 --> 00:10:43,108\nSo, I need to convert this into a button. So\n所以，我需要将它强转为 button\n\n208\n00:10:43,110 --> 00:10:46,411\nI could actually do this like this. I could say, if I can\n我可以这样做，如果 sender\n\n209\n00:10:46,413 --> 00:10:52,017\nlet the sending button equal the sender as a UI button,\n是 UIButton，并解包给 sendingButton 不为空\n\n210\n00:10:52,019 --> 00:10:55,887\nthen I can go forward here and say let's let the image name,\n那么就可以定义一个 imageName\n\n211\n00:10:55,889 --> 00:10:57,822\nthat's the name of the image we wanna show,\n代表我们想要显示的图片名称\n\n212\n00:10:57,824 --> 00:11:02,827\nequal the sending button's current title. Oops,\n并将 sendingButton 的当前图片，哦，不\n\n213\n00:11:02,829 --> 00:11:05,363\nnot current image, current title. All right, so\n当前标题. \n\n214\n00:11:05,365 --> 00:11:06,531\nthis'll be one way to do this,\n这是一种处理方式\n\n215\n00:11:06,533 --> 00:11:11,603\nokay, but kind of a cool way here is, this is this, right?\n但是还有一种更好的方法，看这个和这个\n\n216\n00:11:11,605 --> 00:11:14,205\nSo what if I took this, cut and\n如果我将这个\n\n217\n00:11:14,207 --> 00:11:17,375\nput it in here like that. Okay, so\n剪切到这里\n\n218\n00:11:17,377 --> 00:11:21,479\nI don't need this except for this is If, let. So, if I put\n那就不再需要这个 if let 了，但如果\n\n219\n00:11:21,481 --> 00:11:24,616\nthis in here, this is going to be an optional. I can't send\n将它放到这里，那这就会是个可选值，不能从可选值\n\n220\n00:11:24,618 --> 00:11:28,053\ncurrent title to an optional. So, how can I deal with that?\n中直接访问 currentTitle 属性. 该怎么办呢？\n\n221\n00:11:28,055 --> 00:11:33,124\nLet's use optional chaining. Okay? So it's perfectly legal\n让我们试试可选链. 在表达式返回可选值的时候\n\n222\n00:11:33,126 --> 00:11:36,494\nto use the optional chaining stuff on the end of some,\n使用可选链来操作\n\n223\n00:11:36,496 --> 00:11:39,898\nsome other expression that returns a possible optional.\n是完全合法的\n\n224\n00:11:39,900 --> 00:11:42,400\nAnd remember, if this is nil right here,\n如果这里是 nil\n\n225\n00:11:42,402 --> 00:11:43,868\nthen this whole thing's just gonna be ignored.\n那么之后的都会被忽略\n\n226\n00:11:43,870 --> 00:11:46,571\nThat's what the question mark means, it means if it's nil,\n这个问号就是表示可能为 nil\n\n227\n00:11:46,573 --> 00:11:48,206\nnil then just return nil and ignore it.\n遇到 nil 会返回 nil，然后忽略掉\n\n228\n00:11:48,208 --> 00:11:52,677\nThat means imageName is gonna be returned to nil. Okay.\n也就是说 imageName 可能为 nil\n\n229\n00:11:52,679 --> 00:11:55,947\nSee how I did that? This cleans up our code a little\n接下来做什么呢？先把代码\n\n230\n00:11:55,949 --> 00:11:58,616\nbit, to do that. Less if then, if thens and\n整理一下. 减少分支语句\n\n231\n00:11:58,618 --> 00:12:02,554\nall that, business around there. Okay? Now I'm going\n接下来，要根据\n\n232\n00:12:02,556 --> 00:12:06,291\nto go get the image that goes with this button's title.\n按钮的 title 来获取图片\n\n233\n00:12:06,293 --> 00:12:07,659\nNow let me show you how we're gonna do that.\n让我来演示一下\n\n234\n00:12:07,661 --> 00:12:10,462\nThis DemoURL class, remember the one that had that little\n这个 DemoURL 类，有一个 Stanford 的 URL\n\n235\n00:12:10,464 --> 00:12:14,165\nStanford URL in there? Well it also had these NASA URLs,\n还有 NASA 的 URL\n\n236\n00:12:14,167 --> 00:12:16,568\none for Cassini, one for Earth, and one for Saturn.\n里面包含 Cassini，Earth 和 Saturn\n\n237\n00:12:16,570 --> 00:12:17,802\nThose are the three buttons we have. And\n对应着我们的三个按钮\n\n238\n00:12:17,804 --> 00:12:20,939\nI have a little function right here that just gets the name\n这还有个简单的方法，接收图片名称\n\n239\n00:12:20,941 --> 00:12:24,676\nof the image and looks it up in that dictionary right here,\n然后在字典中查找\n\n240\n00:12:24,678 --> 00:12:27,979\nokay, and returns it. So this a little function called\n并返回，所以这个方法叫\n\n241\n00:12:27,981 --> 00:12:30,815\nNASA Image Named. So let's use this NASA Image Named.\nNASAImageNamed. 来调用下这个方法\n\n242\n00:12:30,817 --> 00:12:35,520\nI'm just gonna say right here that the IVC's image URL\n在这里写 ivc 的 imageURL\n\n243\n00:12:35,522 --> 00:12:41,326\nequals the NASAImageNamed this imageName. Okay?\n等于 NASAImageNamed 的这个 imageNames\n\n244\n00:12:41,328 --> 00:12:46,731\nThis thing I got right here. >> [COUGH]\n就这样\n\n245\n00:12:46,733 --> 00:12:47,398\n>> All right.\n能跟上吗\n\n246\n00:12:47,400 --> 00:12:50,502\nAnd then, oops, sorry, this has gotta be DemoURL.,\n接下来，哦，不好意思，要加上 DemoURL. \n\n247\n00:12:50,504 --> 00:12:52,670\nbecause it's over here in this DemoURL.\n因为这个方法在 DemoURL 中\n\n248\n00:12:52,672 --> 00:12:55,306\nNotice this is a static function, right?\n注意这是个静态方法\n\n249\n00:12:55,308 --> 00:12:56,341\nNASAImageNamed is static function.\nNASAImageNamed 是个静态方法\n\n250\n00:12:56,343 --> 00:12:59,611\nSo, we send it to the class DemoURL, that's why I had to\n所以应该用 DemoURL 类来调用，所以\n\n251\n00:12:59,613 --> 00:13:05,116\nput DemoURL here. Okay, just kind of a utility function for\n应该加上 DemoURL. 这只是 DemoURL 中\n\n252\n00:13:05,118 --> 00:13:08,820\nthat little DemoURL class. And while we're at it,\n的一个工具方法而已. 接下来，\n\n253\n00:13:08,822 --> 00:13:12,323\nyou know what, let's set the title of that MVC to be that\n将 MVC 结构的 title 设置为\n\n254\n00:13:12,325 --> 00:13:15,527\nimage name as well. So that way we'll Earth or Cassini or\n图片名字吧. 这样 MVC 的 title 会是 Earth 或 Cassini\n\n255\n00:13:15,529 --> 00:13:21,766\nwhatever as the title of that MVC. Okay so this make sense?\n或者其他的名字. 这就是这段代码的作用\n\n256\n00:13:22,068 --> 00:13:25,203\nEverybody okay now? Let's go ahead and run this and\n都能跟上吗？运行程序\n\n257\n00:13:25,205 --> 00:13:30,141\nsee if this is working. Here we go.\n看看效果\n\n258\n00:13:33,380 --> 00:13:37,081\nOkay, there we go. So here's Cassini right here, and\n运行起来了，这是 Cassini，\n\n259\n00:13:37,083 --> 00:13:41,686\nif I click Earth, okay, whoa. So it worked. I clicked Earth\n如果我点击 Earth，有点击效果. 点击了 Earth\n\n260\n00:13:41,688 --> 00:13:44,923\nbut nothing's happening in my app. Wait, no there,\n但是 app 却没做出响应. 等下，不对啊\n\n261\n00:13:44,925 --> 00:13:47,358\nit's showing Stanford. Why is is showing Stanford here?\n这展示的是斯坦福，为什么会这样？\n\n262\n00:13:47,360 --> 00:13:50,361\nWell, that's because our nice reusable image view controller\n那是因为我们重用的 ImageViewController\n\n263\n00:13:50,363 --> 00:13:54,732\nwe have over here, it's view did load smashes Stanford on\n的 viewDidLoad 方法中，将斯坦福盖在了\n\n264\n00:13:54,734 --> 00:13:57,435\ntop of everything. So, that we only put that in there as\n所有视图的顶部. 这只是之前的 demo\n\n265\n00:13:57,437 --> 00:14:01,105\na demo. Right, so I'm taking that out, sorry about that.\n把它提出来，不好意思\n\n266\n00:14:01,107 --> 00:14:02,707\nMakes everyone see what happened there. So\n现在来看看都发生了什么\n\n267\n00:14:02,709 --> 00:14:05,143\nnow let's go back here. It won't be slamming a Stanford\n重新运行一次，这下我们的重用 ImageViewController\n\n268\n00:14:05,145 --> 00:14:08,880\nin there in our reusable image view controller. Okay? So\n应该不会被斯坦福盖住了\n\n269\n00:14:08,882 --> 00:14:11,182\nnow we'll go back to Cassini. We'll pick Earth this time.\n回到 Cassini 界面，选择 Earth\n\n270\n00:14:11,184 --> 00:14:15,119\nAgain it seems like it's kinda stuck. I can't click on any of\n又卡住了. 所有按钮都\n\n271\n00:14:15,121 --> 00:14:17,989\nthese buttons. I can't, actually I can't do anything.\n无法点击. 点不了，什么都做不了\n\n272\n00:14:17,991 --> 00:14:21,025\nThere it is. Okay. So that must have been a really big\n进来了，真是一张大图\n\n273\n00:14:21,027 --> 00:14:24,462\nimage. It took a very long time to load and here it is.\n需要这么长的时间加载，终于显示出来了\n\n274\n00:14:24,464 --> 00:14:27,131\nIt doesn't really look like Earth, but\n看起来不怎么像是地球，\n\n275\n00:14:27,133 --> 00:14:29,634\npictures of people on Earth, hm. That's interesting.,\n倒像是地球上的人，有意思.\n\n276\n00:14:29,636 --> 00:14:32,503\nLet's try one of these others. Let's try Cassini here. Okay,\n再试试别的，试试 Cassini\n\n277\n00:14:32,505 --> 00:14:35,106\nwhat happening? This is, basically, just blank.\n怎么回事，怎么只有一个白板\n\n278\n00:14:35,108 --> 00:14:39,310\nWhat's going on here? How about Saturn? Again,\n怎么回事？再试试 Saturn 呢？又来了\n\n279\n00:14:39,312 --> 00:14:41,312\ntaking a really long time, you can see why we're gonna talk\n又要等很久，这就是为什么之后我们要讲\n\n280\n00:14:41,314 --> 00:14:45,583\nabout multi-threading a little later. Okay, and here it is,\n多线程. 好，进来了\n\n281\n00:14:45,585 --> 00:14:47,385\nokay that's not good either. All right, so\n看起来也不怎么像. 好吧，\n\n282\n00:14:47,387 --> 00:14:50,722\nwe gotta start here. We know the Cassini's not working.\n刚才发现 Cassini 没能正常显示\n\n283\n00:14:50,724 --> 00:14:53,258\nIt comes up blank. So why might Cassini not be working.\n看到一片空白，为什么会这样\n\n284\n00:14:53,260 --> 00:14:56,027\nLet's go back here and check for example to make sure that\n回到这里，检查下 segue 有没有什么问题\n\n285\n00:14:56,029 --> 00:14:59,030\nour segue is good. Okay, the Earth's segue. Here's\n这是 Earth 的 segue，这是\n\n286\n00:14:59,032 --> 00:15:02,667\nthe Cassini segue. Let';s go look at its identifier.\nCassini 的 segue. 来检查下它的 identifier\n\n287\n00:15:02,669 --> 00:15:06,905\nLook at that. This Cassini identifier, no identifier.\n看到没，Cassini 的 identifier 是空的\n\n288\n00:15:06,907 --> 00:15:08,940\nSo let's put show image in here. Okay?\n设置为 Show Image\n\n289\n00:15:08,942 --> 00:15:11,743\nSo when you have a segue and it doesn't seem to be working,\n所以，如果你有一个segue，但是没能正常响应\n\n290\n00:15:11,745 --> 00:15:12,877\nlike it segues to the new MVC but\n比如想推出一个新的 MVC，但是\n\n291\n00:15:12,879 --> 00:15:15,346\nthe prepared doesn't happen, often you want to go back and\nprepare 中的代码没有运行，通常需要回头\n\n292\n00:15:15,348 --> 00:15:17,715\nlook at your identifier, make sure it's set properly or\n检查下 identifier，确保它正确的\n\n293\n00:15:17,717 --> 00:15:21,419\nset in there. Okay, so now, if we go back here.\n赋了值. 现在重新运行\n\n294\n00:15:25,458 --> 00:15:27,558\nAll right, we have Cassini here. Let's click on it.\n找到 Cassini 并点击\n\n295\n00:15:27,560 --> 00:15:30,728\nAgain, it's loading. That one must be a smaller image.\n再次等待加载，这图片应该不大\n\n296\n00:15:30,730 --> 00:15:32,797\nIt loaded pretty quick. And here it is.\n加载起来很快，显示出来了\n\n297\n00:15:32,799 --> 00:15:36,234\nIt looks like it's just a bunch of outer space. Okay, so\n看起来就只是外太空而已\n\n298\n00:15:36,236 --> 00:15:36,935\nwe've got a problem here,\n现在有一个问题\n\n299\n00:15:36,937 --> 00:15:39,637\nwhich is that these images that I loaded are huge. That's\n当我们加载一些大图的时候\n\n300\n00:15:39,639 --> 00:15:44,008\ncreated two problems for us. One, our app get's blocked.\n有两个问题摆在了面前. 一个是 app 被卡死了\n\n301\n00:15:44,010 --> 00:15:46,878\nSee I can't click on anything else. I can't even rotate or\n任何东西都没办法点击. 连旋转都不行\n\n302\n00:15:46,880 --> 00:15:49,547\nanything here. My app is just completely stuck.\napp 完完全全卡住\n\n303\n00:15:49,549 --> 00:15:51,916\nYou never want your app in that circumstance.\n你肯定不想你的 app 出现这样的情况\n\n304\n00:15:51,918 --> 00:15:54,652\nNever should your app be stuck like that. Users will just,\n你们的 app 绝不能出现这样的情况. 用户发现，\n\n305\n00:15:54,654 --> 00:15:56,988\nbasically, double click on the home button and\n就会双击 home 键\n\n306\n00:15:56,990 --> 00:15:58,456\nkill your app and never run it again.\n然后杀死进程，再也不会用了\n\n307\n00:15:58,458 --> 00:16:00,925\nThey'll think your app is totally hosed. And it is,\n他们会觉得你的 app 太烂了，这就是\n\n308\n00:16:00,927 --> 00:16:04,228\nif it behaves that way, okay, so we really need to fix that.\n界面卡死的后果，所以我们需要修复下\n\n309\n00:16:04,230 --> 00:16:06,197\nThe other thing is, this image is so\n另外一个问题就是，图片太大\n\n310\n00:16:06,199 --> 00:16:09,500\nhuge that we can't really see it. So we'd like to be able to\n无法直观的展示. 所以我们要添加\n\n311\n00:16:09,502 --> 00:16:11,936\nzoom in on it, right. So let's go ahead and\n缩放功能. 先来处理\n\n312\n00:16:11,938 --> 00:16:17,508\ndo the zooming, okay? How do we do the zooming in our,\n缩放吧. 怎么在 ImageViewController 中\n\n313\n00:16:18,178 --> 00:16:19,844\nback here in our image view controller, right?\n做缩放呢？\n\n314\n00:16:19,846 --> 00:16:22,146\nSo our image view controller has this scroll view,\nImageViewController 有一个 scrollView\n\n315\n00:16:22,148 --> 00:16:24,983\nright? That we dragged into the storyboard. It's got this\n我们拖到 storyboard 中的. 并将 imageView 添加\n\n316\n00:16:24,985 --> 00:16:28,453\nimage view as the subview of the scroll view. Okay, and\n到了 scrollView 上\n\n317\n00:16:28,455 --> 00:16:31,556\nwe set our content size, so it's working nicely. And\n我们还设置了 contentSize，看起来非常棒\n\n318\n00:16:31,558 --> 00:16:32,857\nwe know from the slides last time that\n从之前的幻灯片我们知道了\n\n319\n00:16:32,859 --> 00:16:37,495\nto make zooming work. Okay, we need to set some other things.\n缩放的原理. 那这里还需要处理一些东西\n\n320\n00:16:37,497 --> 00:16:39,364\nWhat are some of the things we need to do? Well,\n需要怎么做呢？\n\n321\n00:16:39,366 --> 00:16:42,600\nthe most important thing is we need to set ourselves\n最重要的一点，就是要将我们自己设置为\n\n322\n00:16:42,602 --> 00:16:44,135\nas the scrollView's delegate. Okay, so\nscrollView 的 delegate.\n\n323\n00:16:44,137 --> 00:16:48,373\nthis is the first time you're seeing delegation demoed here.\n这是我们在 demo 中第一次用到 delegate\n\n324\n00:16:48,375 --> 00:16:48,773\nAnd the way we do that,\n我的做法是\n\n325\n00:16:48,775 --> 00:16:52,844\nI'd probably do it here in my scrollView didSet here, right?\n在 scrollView 的 didSet 方法中来设置\n\n326\n00:16:52,846 --> 00:16:55,680\nThe didSet for my scrollView. Probably just say that Mr.\n这就是 scrollView 的 didSet 方法. 这样说，\n\n327\n00:16:55,682 --> 00:17:00,084\nscrollView, please set your delegate to be self. In other\n亲爱的 scrollView，让我成为你的代理吧！换句话说，\n\n328\n00:17:00,086 --> 00:17:04,856\nwords, send me any questions you have about how to operate.\n就是把你的问题抛给我来处理吧\n\n329\n00:17:04,858 --> 00:17:07,125\nNow when I put that in there I have a error,\n照我这样设置出现了一个错误\n\n330\n00:17:07,127 --> 00:17:11,796\nanyone guess what this error is? Okay,\n有谁知道这是什么错误吗？\n\n331\n00:17:11,798 --> 00:17:14,699\nit's going to say that these types, this and\n错误是说，他们的类型，这个和\n\n332\n00:17:14,701 --> 00:17:18,870\nthis do not match. Okay, and why is that? The type of this\n这个不匹配. 为什么呢？这个的类型是...\n\n333\n00:17:18,872 --> 00:17:22,006\nis, well the type of this, not showing, but the type of this\n好吧，看不到，但是这个的类型是\n\n334\n00:17:22,008 --> 00:17:27,211\nis UI scrollView delegate. Which is a protocol, okay.\nUIScrollViewDelegate. 是个协议\n\n335\n00:17:27,213 --> 00:17:31,883\nThe type of this is UI or image view controller.\n这个类型是 UI...哦，是ImageViewController\n\n336\n00:17:31,885 --> 00:17:34,652\nThat's its type. Those don't match. Okay, so\n这就是它们的类型，并不匹配. 难怪\n\n337\n00:17:34,654 --> 00:17:38,523\nthat's why this says cannot assign value of type image\n报错说不能将 ImageViewController\n\n338\n00:17:38,525 --> 00:17:42,260\nview controller to UI scroll view delegate, optional.\n赋值给可选的 UIScrollViewDelegate\n\n339\n00:17:42,262 --> 00:17:46,230\nOkay, so we need to say that this image view controller is\n所以，我们要先让 ImageViewController 遵循\n\n340\n00:17:46,232 --> 00:17:51,736\na UI scroll view delegate. And we do that by just putting\nUIScrollViewDelegate. 需要做的是，将 UIScrollViewDelegate 声明在\n\n341\n00:17:51,738 --> 00:17:54,672\nthat right after our super class there, a little comma,\n父类的右边，逗号分隔\n\n342\n00:17:54,674 --> 00:17:57,642\nUIScrollViewDelegate, and that says we are scroll view\n这表明我们就是 scrollView\n\n343\n00:17:57,644 --> 00:18:00,178\ndelegate, and all of a sudden this works.\n的代理，这样就没问题了\n\n344\n00:18:00,180 --> 00:18:03,047\nNow UIScrollViewDelegate has no methods or\nUIScrollViewDelegate 没有方法或\n\n345\n00:18:03,049 --> 00:18:05,950\nvars in there that are not optional. In other words\n变量是不可选的，换句话说，\n\n346\n00:18:05,952 --> 00:18:08,853\nthey're all optional, so we've successfully implemented so\n它们都是可选的，所以，遵循以后\n\n347\n00:18:08,855 --> 00:18:10,688\nthe compiler's not complaining. Okay,\n编译器并没有报错\n\n348\n00:18:10,690 --> 00:18:14,725\ncuz none of them are required. But, we still wanna implement\n因为没有必须实现的方法. 不过我们还是需要实现\n\n349\n00:18:14,727 --> 00:18:17,995\none, that zooming one, which is called\n其中一个方法，缩放的那个，叫做\n\n350\n00:18:17,997 --> 00:18:19,363\nviewForZoomingInScrollView. Now, one\nviewForZoomingInScrollView. 在你\n\n351\n00:18:19,365 --> 00:18:21,632\nthing that's cool is once you say that you're a ScrollView\n成为 ScrollView 的代理之后，\n\n352\n00:18:21,634 --> 00:18:24,735\ndelegate, look what happens when I start typing view\n在最新的 Xcode 键入字母时\n\n353\n00:18:24,737 --> 00:18:26,971\nin Xcode. It knows I'm a ScrollView delegate, so\n它就知道你已经是 ScrollView 的代理了，所以\n\n354\n00:18:26,973 --> 00:18:30,308\nthe very first thing it offers me is viewForScroll,\n提供的首个联想方法就是 viewForScroll\n\n355\n00:18:30,310 --> 00:18:33,177\nScrollingInScrollView. For\nZoomingInScrollView（白胡子口误了）\n\n356\n00:18:33,179 --> 00:18:36,981\nzooming in scrollView.、 Right? So that's kind of cool. And\n用做 scrollView 的缩放. 这真的非常棒\n\n357\n00:18:36,983 --> 00:18:40,017\nwhat view, which of the scrollView subviews do we want\n那个视图？我们想让 scrollView 的哪个子视图\n\n358\n00:18:40,019 --> 00:18:44,622\nto zoom in on? Well, of course, the image view. This\n做缩放？当然是 imageView. 这是\n\n359\n00:18:44,624 --> 00:18:48,159\nis our image view right here that we store our image in.\n我们的 imageView，里面存储了相应图片\n\n360\n00:18:48,161 --> 00:18:49,494\nThat's of course the thing we want\n很明显我们是想\n\n361\n00:18:49,496 --> 00:18:54,599\nto have its transform modified when we pinch in there. Okay?\n在手指捏合的时候，对图片做对应的缩放\n\n362\n00:18:54,601 --> 00:18:56,400\nNow you might think okay, that's good.\n你可能会想，那已经完成了，\n\n363\n00:18:56,402 --> 00:19:00,505\nGot it all ready to go. Let's go start zooming, and\n可以运行了. 让我来看看缩放效果吧\n\n364\n00:19:00,507 --> 00:19:03,341\nwe'll go over here. Let's get Cassini, kinda small.\n到这个界面，打开 Cassini，一张小图\n\n365\n00:19:03,343 --> 00:19:06,277\nLet's start zooming. Now how do I zoom? It's with Pinch, so\n试试缩放. 怎么进行缩放呢？需要捏合手势，所以\n\n366\n00:19:06,279 --> 00:19:08,913\nI'm gonna hold down the Option key right here and\n按住 Option 键，然后\n\n367\n00:19:08,915 --> 00:19:11,048\nstart pinching. And it's not working.\n进行捏合. 但并没有效果\n\n368\n00:19:11,050 --> 00:19:14,085\nIt's not doing anything. Okay, I can still scroll but\n完全没有效果. 依然可以滚动，但是\n\n369\n00:19:14,087 --> 00:19:18,990\nI can't zoom in. Anyone know why? Say\n不能缩放. 有人知道为什么吗？大点声.\n\n370\n00:19:18,992 --> 00:19:25,396\nit louder. I think I might have heard it back there.\n我刚才好像听到那有人回答.\n\n371\n00:19:25,398 --> 00:19:28,065\nYeah, this right now, our scrollView by default,\n是的，没错，现在 scrollView 的默认值是\n\n372\n00:19:28,067 --> 00:19:31,836\nit's maximum zoom and its minimum zoom is 1.0.\n放大倍数和缩小倍数都是 1.0\n\n373\n00:19:31,838 --> 00:19:33,738\nSo it is zooming to the maximum,\n所以我们放大\n\n374\n00:19:33,740 --> 00:19:36,974\nminimum extent we allow which is none, 1.0. So\n和缩小的效果根本看不出来，都是 1.0，所以\n\n375\n00:19:36,976 --> 00:19:41,779\nwe need to set the maximum and minimum scrolling factor or\n我们需要给 scrollView 的范围因子，或叫做给\n\n376\n00:19:41,781 --> 00:19:45,583\nzooming factor on this scrollView. So let's do that.\n缩放因子赋值. 回到代码.\n\n377\n00:19:45,585 --> 00:19:48,386\nLet's do that also right here when we're setting our\n在这里进行设置，在\n\n378\n00:19:48,388 --> 00:19:50,254\nscrollView from our storyboard. So\nscrollView 在 storyboard 中被赋值时调用的方法\n\n379\n00:19:50,256 --> 00:19:52,924\nwe just say that the scrollView's minimum zoom\n键入 scrollView 的 minimumZoomScale\n\n380\n00:19:52,926 --> 00:19:57,962\nscale. I'm gonna have this minimum zoom scale.\n来设置最小缩放因子\n\n381\n00:19:57,964 --> 00:20:02,433\nWhat did I think that worked well here? 0.03.\n设成多少效果比较好呢？0.03 吧\n\n382\n00:20:02,435 --> 00:20:04,735\nSo we're gonna zoom- allowed to zoom way out.\n我们可以进行缩放\n\n383\n00:20:04,737 --> 00:20:07,205\nSo it will make the image really small, okay?\n图片会缩小到很小\n\n384\n00:20:07,207 --> 00:20:10,975\nThree one-hundredths of it's size.\n是原图的百分之三\n\n385\n00:20:10,977 --> 00:20:13,844\n3% of its size. And then the maximum,\n也就是 3% 的大小，接下来设置最大因子\n\n386\n00:20:13,846 --> 00:20:16,480\nit is perfectly fine for us to say the maximum is 1.0.\n这个值设为 1.0 就好了\n\n387\n00:20:16,482 --> 00:20:20,318\nMaybe we never want the thing to be zoomed out any bigger\n可能我们永远不会将该图片放大\n\n388\n00:20:20,320 --> 00:20:23,020\nthan it already is, especially there are huge images already.\n毕竟它已经是一张很大的图片了\n\n389\n00:20:23,022 --> 00:20:26,190\nSo we can set the maximum to zoom scale. We don't even need\n其实我们完全可以不用设置放大因子，这条\n\n390\n00:20:26,192 --> 00:20:29,060\nto put this. Cuz by default, it's 1.0. But we'll put it\n语句可以不用谢，因为默认值就是 1.0. 这里就不删了，\n\n391\n00:20:29,062 --> 00:20:32,430\nin here just to kinda be very clear about what we're doing.\n看着更清晰一点\n\n392\n00:20:32,432 --> 00:20:39,737\nAll right, so now lets try it. All right,\n再来看看效果\n\n393\n00:20:39,739 --> 00:20:44,542\nso lets go get Cassini right here. All right, here it is.\n点击 Cassini，然后\n\n394\n00:20:44,544 --> 00:20:48,212\nLets zoom in on it, right. I'm pinching. Yeah, look at that,\n进行缩放，捏合一下，看到了吧\n\n395\n00:20:48,214 --> 00:20:50,314\nit's zooming. And sure enough, look,\n缩小了. 效果很好\n\n396\n00:20:50,316 --> 00:20:54,352\nthere's Cassini. Taking a little trip by Saturn, okay,\n这是 Cassini，在围着 Saturn 兜风\n\n397\n00:20:54,354 --> 00:20:57,021\nlet's zip it around here so we can see a little better. Okay,\n旋转一下屏幕，就能看到更多内容\n\n398\n00:20:57,023 --> 00:21:00,324\nhow about some of these other images, go look at the Earth,\n来看看其他图片呢，看看 Earch\n\n399\n00:21:00,493 --> 00:21:03,861\ndidn't look like much like Earth. Now if we zoom,\n之前看着并不像 Earth. 这次缩小试试\n\n400\n00:21:03,863 --> 00:21:07,131\nwe'll see something here. All right, so here it is,\n说不定能看到更多东西. 好了，加载出来了\n\n401\n00:21:07,133 --> 00:21:11,802\nscrolling around, I'm gonna pinch, pinch some more.\n滚动看看，然后捏合，再缩小点\n\n402\n00:21:11,804 --> 00:21:17,675\nLook at this Earth, okay? Same thing with Saturn.\n啊哈，这就是 Earch. 在看看 Saturn 呢\n\n403\n00:21:18,111 --> 00:21:20,244\nOkay, everyone see what we do with the zooming?\n每个人都知道怎么实现缩放了吗？\n\n404\n00:21:20,246 --> 00:21:21,279\nZooming quite simple\n实现起来真的很简单\n\n405\n00:21:21,281 --> 00:21:22,847\nin terms of the code you have to write, but\n就那么几句代码\n\n406\n00:21:22,849 --> 00:21:24,882\nyou have to understand that delegation piece for\n这全都要靠 delegate\n\n407\n00:21:24,884 --> 00:21:28,152\nit to really, to make it work. And you'll see Saturn,\n那才是真谛. 来看看 Saturn\n\n408\n00:21:28,154 --> 00:21:34,325\nthere's Saturn. Okay? Now let's try this on iPad,\n这是 Saturn. 没问题，运行在 iPad 上试试，\n\n409\n00:21:34,327 --> 00:21:37,528\nokay? Let's see what it looks like here.\n看看显示效果\n\n410\n00:21:47,373 --> 00:21:48,906\nAll right, so here is our master and\n这是 master\n\n411\n00:21:48,908 --> 00:21:51,542\nour detail right here. So if I click on Cassini,\n这是 detail，点击 Cassini，\n\n412\n00:21:51,544 --> 00:21:54,912\nhopefully Cassini will eventually really slow,\n加载起来确实很慢\n\n413\n00:21:54,914 --> 00:21:57,315\nappear right here. Okay? And we can zoom in here, okay?\n显示出来了，缩放试试呢\n\n414\n00:21:57,317 --> 00:22:02,119\nNow, what would be really cool here is if we could have\n如果在这里能有个标题\n\n415\n00:22:02,121 --> 00:22:05,856\na title up here that said this was Cassini,\n告诉我们这是 Cassini，\n\n416\n00:22:05,858 --> 00:22:09,560\nor Earth, or Saturn, right? So remember\n还是是 Earth，是 Saturn，就更好了\n\n417\n00:22:09,562 --> 00:22:12,863\nthe tricky way we did that, is we went to our storyboard, and\n其实有一个很取巧的方式，打开 storyboard\n\n418\n00:22:12,865 --> 00:22:17,201\nwe just put this one down here. Also in the scrollView.\n将下面的这个包含 scrollView 的控制器\n\n419\n00:22:17,203 --> 00:22:19,704\nSo we said embed in navigation control.\n加上 navigation\n\n420\n00:22:19,706 --> 00:22:21,872\nOr not in a scrollView, in a navigation controller. So\n或者嵌入到 navigation controller 中\n\n421\n00:22:21,874 --> 00:22:25,910\nI embed it in there, so that now I have a title. Right? And\n嵌入之后，就可以设置标题了\n\n422\n00:22:25,912 --> 00:22:26,644\nwe know that if we can go and\n如果现在运行\n\n423\n00:22:26,646 --> 00:22:29,547\nrun this, it's not going to work, right? Because these\n不会有任何效果，因为\n\n424\n00:22:29,549 --> 00:22:33,984\nsegues are segueing now to a navigation controller. And\n现在这个 segue 是 navigation controller 了.\n\n425\n00:22:33,986 --> 00:22:36,687\nso our prepare is not gonna work,\n所以 prepare 方法不会有效\n\n426\n00:22:36,689 --> 00:22:40,124\ncuz this line of code is going to fail. Right,\n这句代码代码判断失败了\n\n427\n00:22:40,126 --> 00:22:43,394\nbecause the destination view controller is now a navigation\n现在这个 destinationViewController 是 navigationController\n\n428\n00:22:43,396 --> 00:22:43,594\ncontroller. Of course,\n显然，\n\n429\n00:22:43,596 --> 00:22:46,063\na navigation controller is not an image view controller.\nnavigationController 不是 imageViewController\n\n430\n00:22:46,065 --> 00:22:48,165\nThis is the exact same problem we had before. So\n这种问题我们之前遇到过\n\n431\n00:22:48,167 --> 00:22:51,869\nI'm gonna show you now how to use that extensions mechanism\n下面我将演示如何使用 extension 来\n\n432\n00:22:51,871 --> 00:22:54,805\nto fix this. So I'm gonna create an extension. This is\n解决这个问题. 先创建一个 extension. \n\n433\n00:22:54,807 --> 00:22:59,143\nexactly what I did in the slides of UIViewController.\n这是给 UIViewController 的 extension.\n\n434\n00:23:00,012 --> 00:23:03,481\nOkay, and in this extension, like to scroll up a little so\n好的，在 extension 中，好像往下滚动一点\n\n435\n00:23:03,483 --> 00:23:07,351\nyou can see it better. Okay, inside this extension,\n更方便你们看. 好的，在这个 extension 中，\n\n436\n00:23:07,353 --> 00:23:11,689\nI'm gonna add the var contentViewController.\n我准备添加一个 contentViewController 变量.\n\n437\n00:23:11,691 --> 00:23:14,525\nWhich is a UIViewController, okay?\n类型是 UIViewController\n\n438\n00:23:14,527 --> 00:23:17,862\nI'm adding this var to the class UIViewController.\n这是给 UIViewController 添加的变量\n\n439\n00:23:17,864 --> 00:23:21,232\nSo, all UIViewControllers will now respond to this property\n所以所有的 UIViewController 都有一个叫做\n\n440\n00:23:21,234 --> 00:23:24,568\ncontentViewController. Okay? It's gonna be get only.\ncontentViewController 的属性了. 将它声明为只读属性.\n\n441\n00:23:24,570 --> 00:23:27,171\nIt's gonna get it. And what I'm gonna put in here is\n直接就能获取值. 这里的代码和\n\n442\n00:23:27,173 --> 00:23:29,907\nbasically that same code I had in prepareforSegue,\nmotion view controller 中的 prepareforSegue 方法\n\n443\n00:23:29,909 --> 00:23:32,309\nin a motionview controller. I'm gonna say,\n代码相同，这样写，\n\n444\n00:23:32,311 --> 00:23:37,915\nif I can let navcon = self as a UINavigationController,\nif let navcon = self as? UINavigationController，\n\n445\n00:23:37,917 --> 00:23:43,120\nso in otherwords, if I am a navigation controller,\n意思是，如果 self 是 UINaviagtionController，\n\n446\n00:23:43,122 --> 00:23:47,858\nthen return navcon.visibleViewController.\n就返回 navcon.visibleViewController.\n\n447\n00:23:47,860 --> 00:23:50,594\nOkay? The only problem with this is this is\n这里唯一的问题就是\n\n448\n00:23:50,596 --> 00:23:53,631\nan optional view controller, because the navigation\n这个 view controller 是可选值，因为 navigation\n\n449\n00:23:53,633 --> 00:23:56,700\ncontroller might not have anything showing. Okay, so\ncontroller 可能不会展示任何信息，所以\n\n450\n00:23:56,702 --> 00:24:00,237\nI need to return something because contentViewController\n这里必须要返回一个确切的值，因为 contentViewController\n\n451\n00:24:00,239 --> 00:24:02,940\ndoes not return an optional So I'm gonna use this\n不是一个可选类型. 所以我准备用 ?? 将默认值\n\n452\n00:24:02,942 --> 00:24:06,210\ndefaulting to say if I have a NavigationController and\n设置为 self，如果有 NavigationController\n\n453\n00:24:06,212 --> 00:24:08,779\nit has no visible ViewController, just return\n但是 visibleViewController 为空的话，就返回\n\n454\n00:24:08,781 --> 00:24:12,082\nself, which is to say the NavigationController itself,\nself，也就是 NavigationController\n\n455\n00:24:12,084 --> 00:24:14,819\nokay? Otherwise, we can just return self. So if it's not\n其他情况，就返回 self. 即如果不是\n\n456\n00:24:14,821 --> 00:24:17,655\na NavigationController, then the content is myself.\nNavigationController，就返回 self 作为 content\n\n457\n00:24:17,657 --> 00:24:22,293\nEveryone understand that code right there? Okay? Good.\n大家对这段代码有疑问吗？没有？好的. \n\n458\n00:24:22,295 --> 00:24:25,296\nSo, now that we have this, we can just use that method right\n有了这个以后，我们在这里直接调方法就可以了.\n\n459\n00:24:25,298 --> 00:24:29,400\nhere. Okay? Instead of asking if the destination can view\n这里还要把之前判断的 destination view \n\n460\n00:24:29,402 --> 00:24:31,535\ncontroller is an image view controller, I'm gonna ask if\ncontroller 是 imageViewController 改为判断\n\n461\n00:24:31,537 --> 00:24:36,240\nthe destination controller's content view controller, and\ndestination controller 的 content view controller 是否是 \n\n462\n00:24:36,242 --> 00:24:38,742\nI can escape complete, cuz now that's a method on U, I,\nimageViewController. 现在这个方法，哦，这个\n\n\n463\n00:24:38,744 --> 00:24:41,579\nthis is a UI view controller. This is a method on UI view\n就是 UIViewController 了，这个方法就是 UIViewController 的\n\n464\n00:24:41,581 --> 00:24:44,381\ncontroller. I'm just gonna ask if the content view controller\n只需要判断 content view controller 是否\n\n465\n00:24:44,383 --> 00:24:49,954\nis an image view controller. Okay? So now we should be able\n是 image view controller 就行了. 现在在 iPad 上跑起来\n\n466\n00:24:49,956 --> 00:24:54,825\nto run an iPad and get some nice titles. All right.\n应该就可以看到标题了.\n\n467\n00:24:54,827 --> 00:24:58,162\nCassini again. We've got the navigation controller up here.\n依然打开 Cassini，能看到这里有个 navigation controller\n\n468\n00:24:58,164 --> 00:25:00,297\nThere's Cassini. Sure enough, there's the title, right.\n这是 Cassini，没问题，这是标题\n\n469\n00:25:00,299 --> 00:25:04,568\nWe set the title right here. Ivc.title = imageName, okay?\n我们在这里加上了标题，ivc.title = imageName\n\n470\n00:25:04,570 --> 00:25:11,275\nAnd of course, we can zoom around, okay?\n当然，我们还可以进行缩放\n\n471\n00:25:11,277 --> 00:25:13,310\nAll right, any questions about that before I go back to\n讲到这里，大家有什么问题吗？\n\n472\n00:25:13,312 --> 00:25:18,449\nthe slides? All right. Let's hit the slides here.\n好的，再回到讲义.\n\n473\n00:25:23,689 --> 00:25:26,524\nOkay, so now we're gonna talk about multithreading, so\n接下来，我会讲讲多线程\n\n474\n00:25:26,526 --> 00:25:28,592\nwe can fix that problem where our Cassini app,\n这样就能修复 Cassini app 中，当我们加载大图时\n\n475\n00:25:28,594 --> 00:25:31,962\nwhen we click on the big image, it just froze. Okay.\n导致的界面卡死问题了.\n\n476\n00:25:31,964 --> 00:25:36,033\nWhen you build an app, never have it freeze like that ever.\n当你做一款 app 时，千万不要出现界面卡死的情况\n\n477\n00:25:36,035 --> 00:25:38,435\nIn fact, if it freezes like that, probably you won't get\n事实上，出现界面卡死的情况，\n\n478\n00:25:38,437 --> 00:25:41,605\nthrough the app store approval process. Okay. So the only\n还会影响你上架 app store. 解决界面卡死的\n\n479\n00:25:41,607 --> 00:25:44,808\nway to stop it from freezing is to use multithreading.\n唯一方式，就是使用多线程.\n\n480\n00:25:44,810 --> 00:25:48,646\nOkay. So, multithreading just means we're going to\n多线程意味着我们会在\n\n481\n00:25:48,648 --> 00:25:50,781\nhave different threads of execution,\n不同的线程中执行任务\n\n482\n00:25:50,783 --> 00:25:54,118\nokay? Different places in, in our iPhone or\n在，在 iPhone 或 iPad 的不同的地方\n\n483\n00:25:54,120 --> 00:25:56,887\nour iPad where code is running, okay?\n执行代码\n\n484\n00:25:56,889 --> 00:26:00,090\nAnd these, these appear to run simultaneously, but\n这些代码，几乎是同时运行的，\n\n485\n00:26:00,092 --> 00:26:03,227\nit'll even work on a single core processor, okay,\n即使在单核处理器上，也没问题\n\n486\n00:26:03,229 --> 00:26:07,231\nnot a multiprocessor. It works, then, by timesharing.\n虽然不是多核处理，但是运用了分时操作手段\n\n487\n00:26:07,233 --> 00:26:08,399\nOkay. And so you got one thing running,\n所以，一个事件在执行，\n\n488\n00:26:08,401 --> 00:26:09,867\nanother thing running and it's kinda going back and\n然后再切换到另一个事件，执行后又切回刚才的事件\n\n489\n00:26:09,869 --> 00:26:13,304\nforth. Letting them each run a little bit and maybe if one of\n继续执行. 每个事件都能执行一段时间，如果某个事件\n\n490\n00:26:13,306 --> 00:26:15,573\nthem's more important than the other, it gets run a lot and\n在其中比较重要，那么就会停留得就一些，\n\n491\n00:26:15,575 --> 00:26:18,576\nthe other one doesn't get to run so much. Okay? But\n次要的事件就不会占用那么长事件.\n\n492\n00:26:18,578 --> 00:26:21,545\nthat's basically what multithreading is all about.\n这就是多线程最基础的部分.\n\n493\n00:26:21,547 --> 00:26:22,079\nSo how many people have,\n在做的有同学已经，\n\n494\n00:26:22,081 --> 00:26:25,583\nhave done any multithreading programming of any kind? Okay,\n已经做过多线程的项目了？好吧，\n\n495\n00:26:25,585 --> 00:26:28,586\nso some of you have, okay. About a little less than half\n一部分同学，大概不到一半的人吧。\n\n496\n00:26:28,588 --> 00:26:31,722\nof you. Okay, good. So in iOS multithreading is about\n谈到 iOS 上的多线程，其实都是\n\n497\n00:26:31,724 --> 00:26:35,859\nqueues, okay? Queue meaning like, if you go to the movies\n队列. 队列就像是...如果你在 England 去\n\n498\n00:26:35,861 --> 00:26:37,895\nmaybe in England [LAUGH] they would say, well,\n看电影，那么他们会说，\n\n499\n00:26:37,897 --> 00:26:40,664\nget in the queue, meaning the line to get into the movie,\n排队去，意思是，排队依次进电影院.\n\n500\n00:26:40,666 --> 00:26:43,901\nokay? So same thing here, and it's the same thing as queue\n这里的队列和计算机科学中队列\n\n501\n00:26:43,903 --> 00:26:46,971\nin the computer science sense, right? A queue is a thing,\n的含义是一样的. 队列其实就是一个东西，\n\n502\n00:26:46,973 --> 00:26:48,973\na bunch of things lined up to do something.\n一个有先后顺序的东西.\n\n503\n00:26:48,975 --> 00:26:54,912\nAll right. And these queues contained an iOS functions.\n这些队列包含了 iOS 的方法.\n\n504\n00:26:54,914 --> 00:26:58,482\nOkay? Most of the time these functions are closures. Okay?\n绝大多数方法都是闭包. 好吧？\n\n505\n00:26:58,484 --> 00:27:02,052\nThat you've put in there. Okay? Blocks of code that you\n然后加入到队列中. 就是闭包中的代码，\n\n506\n00:27:02,054 --> 00:27:06,824\nput in this queue. Okay? And then, the system simply runs\n加入到队列中. 接着，系统会单独运行\n\n507\n00:27:06,826 --> 00:27:09,693\nalong this queue, pulls the next thing off the queue and\n这个队列，将队列中的任务取出，\n\n508\n00:27:09,695 --> 00:27:13,430\nstarts it running in a separate thread, okay?\n然后在独立的线程中运行.\n\n509\n00:27:13,432 --> 00:27:16,100\nAnd you can have multiple of these queues and the system is\n你也可以有很多个队列，然后系统便会\n\n510\n00:27:16,102 --> 00:27:18,602\npulling them off each one and running them un, in their\n分别取出，然后...在各自的线程中\n\n511\n00:27:18,604 --> 00:27:21,705\nown threads, simple as that, you just got multithreading.\n执行，就这么简单的用上了多线程.\n\n512\n00:27:21,707 --> 00:27:24,642\nOkay. Now there's a little bit of trickiness\n那么现在有个问题，\n\n513\n00:27:24,644 --> 00:27:25,909\nhere of what are these queues and\n队列是什么，\n\n514\n00:27:25,911 --> 00:27:27,444\nhow do you put things on the queues, but\n怎么将任务加入到队列中，\n\n515\n00:27:27,446 --> 00:27:30,180\nthat's the fundamental way these work. Now queues can\n这属于队列运行原理. 队列可以是\n\n516\n00:27:30,182 --> 00:27:34,118\neither be serial, which means the function that's on the top\n串行的，意思是只有当上一个任务执行完后，\n\n517\n00:27:34,120 --> 00:27:37,154\nof the queue gets pulled off, it runs to completion, and\n新的队首元素才会出队\n\n518\n00:27:37,156 --> 00:27:40,824\nthen the next one gets pulled off. That's serial queues. Or\n接着执行. 这就是串行队列.\n\n519\n00:27:40,826 --> 00:27:43,494\nthey can be concurrent, where the system pulls the top\n队列也可以是并行的，意思是系统出队\n\n520\n00:27:43,496 --> 00:27:46,130\none off the queue, starts it running in a thread. If it's\n一个队首元素，就立即在一个线程中执行. 如果是这样，\n\n521\n00:27:46,132 --> 00:27:48,599\ngot more thread resources, it takes the next one off,\n就会占用更多的资源，下一个任务出队以后\n\n522\n00:27:48,601 --> 00:27:51,402\nstarts it running in another thread while the first one's\n就会在另一个线程中进行执行，此时，第一个出队的任务\n\n523\n00:27:51,404 --> 00:27:51,502\nstill running, and\n仍在执行，\n\n524\n00:27:51,504 --> 00:27:55,873\nit might keep pulling a whole bunch of them off. Okay, so\n这种队列甚至可以直接将整个队列元素出队执行. \n\n525\n00:27:55,875 --> 00:27:57,775\nthat's a concurrent queue.\n这就是并行队列.\n\n526\n00:27:57,777 --> 00:28:00,544\nAll right, so let's talk about the queues, how we get them,\n接下来，再来看看队列的其他知识. 我们怎么获得队列，\n\n527\n00:28:00,546 --> 00:28:03,781\nwhat, what we call them, etc. The most important queue,\n怎样调用它们，等等. 对重要的队列，\n\n528\n00:28:03,783 --> 00:28:06,717\nit's a serial queue called the main queue, okay?\n就是一个称为主队列的串行队列.\n\n529\n00:28:06,719 --> 00:28:10,554\nThe main queue is where all UI activity has to happen. And\n主队列是刷新 UI 控件的队列. \n\n530\n00:28:10,556 --> 00:28:14,658\nthis is super important for you to understand. That if you\n大家一定要着重理解这个知识点. 如果你在\n\n531\n00:28:14,660 --> 00:28:19,063\nwant to do anything where you call something a UI kit, okay,\n做一些和 UIKit 相关的动作，比如\n\n532\n00:28:19,065 --> 00:28:21,331\nUI button, UI anything, all right,\nUIButton，或其他 UI 元素，\n\n533\n00:28:21,333 --> 00:28:24,334\nwith a couple of exceptions which I'll talk about later.\n包括之后我们还会学到的其他 UI 控件. \n\n534\n00:28:24,336 --> 00:28:27,104\nYou need to be making those calls on the main queue.\n它们都必须要在主队列中进行操作.\n\n535\n00:28:27,106 --> 00:28:31,241\nIn other words, you can't put those calls in a closure that\n换句话说，它们不能再其他队列的闭包\n\n536\n00:28:31,243 --> 00:28:34,378\nyou put on some other queue. Okay, it has to be on the main\n中执行. 必须在主队列中执行》 \n\n537\n00:28:34,380 --> 00:28:39,149\nqueue, all right? Now conversely, all non-UI\n记住了吗？相反，所有和 UI 控件\n\n538\n00:28:39,151 --> 00:28:42,519\nactivity that's gonna take any amount of time or resources,\n无关的操作，可能会耗时，或耗资源的操作，\n\n539\n00:28:42,521 --> 00:28:45,589\nprobably wants to be off the main queue. So it never blocks\n就不要放到主队列中. 千万不要阻塞\n\n540\n00:28:45,591 --> 00:28:48,092\nthe main queue. We want the main queue reserved for\n主队列. 我们应该尽可能的将主队列的资源\n\n541\n00:28:48,094 --> 00:28:51,562\ndoing our UI stuff as much as possible. Okay, now this is\n用来调度 UI 元素. 当然，希望 UI 控件能及时响应\n\n542\n00:28:51,564 --> 00:28:55,799\nnot only cuz we want our main queue UI to be responsive,\n只是其中一个原因，\n\n543\n00:28:55,801 --> 00:28:56,767\nokay, that's the main reason, but\n也是最主要的原因，另外\n\n544\n00:28:56,769 --> 00:29:00,671\nalso it serializes the activity on the main queue so\n一个原因，是因为主队列是串行队列，所以\n\n545\n00:29:00,673 --> 00:29:03,907\nthat our UI is presented in an orderly fashion. If,\nUI 元素能按照我们给的顺序来执行. 如果，\n\n546\n00:29:03,909 --> 00:29:06,343\nif we allowed our UI to be on all these different queues, it\n如果允许在不同的队列中操作 UI，实际上却是是\n\n547\n00:29:06,345 --> 00:29:08,912\ncould, things would be drawing at all different rates and\n可以的，但是绘制速度就会不同，从而出现\n\n548\n00:29:08,914 --> 00:29:09,480\noverlapping, it would be\n重叠，预测不了\n\n549\n00:29:09,482 --> 00:29:11,882\nunpredictable as to what happened on screen. Okay, so\n界面效果. 所以\n\n550\n00:29:11,884 --> 00:29:15,285\nwe use the main queue as kind of a synchronization point\n我们需要要利用主队列的同步性，\n\n551\n00:29:15,287 --> 00:29:18,522\nwhere everybody comes back to draw on the main queue,\n保证所有的绘制都在主队列中进行，\n\n552\n00:29:18,524 --> 00:29:22,259\nall right? Now the main queue can only pull a closure or\n明白了吗？主队列每次会出队一个闭包或\n\n553\n00:29:22,261 --> 00:29:24,294\na function off of the main queue and\n一个方法，\n\n554\n00:29:24,296 --> 00:29:26,630\nwork on it when it's quiet. In other words,\n在静默时，执行它. 换句话说，\n\n555\n00:29:26,632 --> 00:29:28,532\nit's not off doing something else, like drawing or\n它一直都是执行状态，比如在绘制，或\n\n556\n00:29:28,534 --> 00:29:31,835\nsomething like, like that. Now the system is using the main\n在执行和绘制差不多的任务. 主队列会一直在\n\n557\n00:29:31,837 --> 00:29:33,403\nqueue behind the scenes all the time.\n系统后台运行着.\n\n558\n00:29:33,405 --> 00:29:35,572\nFor example, you know about draw req. Right.\n比如，你知道绘制操作吧.\n\n559\n00:29:35,574 --> 00:29:38,342\nI told you draw req gets called by the system and\n我之前说过，绘制是系统在调用，\n\n560\n00:29:38,344 --> 00:29:40,277\nit doesn't get called, you don't call it,\n你并没有手动去调用，\n\n561\n00:29:40,279 --> 00:29:42,913\nyou don't tell it to, you just set needs display.\n并没有让系统去调，只是告诉系统它需要显示.\n\n562\n00:29:42,915 --> 00:29:44,348\nWell, you set needs display and\n设置在主线程空闲的时候\n\n563\n00:29:44,350 --> 00:29:48,585\nas soon as the main queue gets quiet, it goes and runs some\n进行显示，系统会运行或调用某些\n\n564\n00:29:48,587 --> 00:29:51,555\nfunction that causes that draw req to be called. So\n方法来进行绘制. 这便是\n\n565\n00:29:51,557 --> 00:29:54,525\nyou see how that works, okay? So that's what's going on in\n绘制的工作原理. 这便是主队列\n\n566\n00:29:54,527 --> 00:29:57,294\nthe main queue. What about other queues? Okay, so\n在处理的东西. 那么其他队列呢？看\n\n567\n00:29:57,296 --> 00:30:00,030\nthere's, I'm, in the next slide I'm gonna talk about\n这里，下个话题便会讲讲\n\n568\n00:30:00,032 --> 00:30:02,800\ntwo different kinds of other queues that you can use to run\n其他两种不同的队列，能用来处理\n\n569\n00:30:02,802 --> 00:30:06,236\nall your non-UI stuff. All right? So the first,\n所有和 UI 无关的队列. 目前，\n\n570\n00:30:06,238 --> 00:30:09,039\nnot gonna talk about this now, that'll be on the next slide.\n我们暂时不谈这个，这是下个话题.\n\n571\n00:30:09,041 --> 00:30:12,142\nSo on this slide I'm gonna talk a little bit about how we\n这张幻灯片还有一点东西没讲完，关于如何\n\n572\n00:30:12,144 --> 00:30:14,845\nput something on a queue and the main way we do it is\n将任务放到队列中，最常见的做法是\n\n573\n00:30:14,847 --> 00:30:17,981\nwith this function right here called dispatch_async.\n调用一个叫 dispatch_async 的方法.\n\n574\n00:30:17,983 --> 00:30:22,986\nDispatch_async takes two arguments. One is the queue to\nDispatch_async 有两个参数. 一个是要加入的\n\n575\n00:30:22,988 --> 00:30:25,455\nput it on, like the main queue or one of these other queues,\n队列，可以是主队列，或者其他队列，\n\n576\n00:30:25,457 --> 00:30:29,760\nand the second argument is the function to put on the queue,\n第二个参数是，要加入队列的方法，\n\n577\n00:30:29,762 --> 00:30:32,963\nagain, usually it's a closure. You see how I'm using trailing\n当然，通常是闭包. 我这里简单写了一个\n\n578\n00:30:32,965 --> 00:30:35,933\nclosure syntax right there? Okay. This is two arguments.\n闭包的语法. 这有两个参数，\n\n579\n00:30:35,935 --> 00:30:39,002\nOne argument. Two arguments. So this is the closure you're\n一个参数. 两个参数. 这就是加入到队列中的\n\n580\n00:30:39,004 --> 00:30:41,605\ngonna put on there. What's cool about these closures,\n闭包. 看起来很不错吧，\n\n581\n00:30:41,607 --> 00:30:43,607\nthey take no arguments and then return no arguments.\n闭包没有参数，也没有返回值.\n\n582\n00:30:43,609 --> 00:30:46,910\nSo they're really easy to, to [LAUGH] put into your code.\n所以，非常容易嵌到你的代码中（笑~\n\n583\n00:30:46,912 --> 00:30:50,180\nOkay? And you can put anything you want in here. Okay?\n你可以将任何想执行的代码扔到里面.\n\n584\n00:30:50,182 --> 00:30:53,884\nBut if this gonna do UI, you better not put it on anything\n当然，最好是将 UI 操作扔进去，而不是别的操作，\n\n585\n00:30:53,886 --> 00:30:58,388\nbut the main queue. All right, so how do you get the queue?\n毕竟这是主线程. 所以，怎样获得一个队列呢？\n\n586\n00:30:58,390 --> 00:30:59,823\nHow do you get this little queue argument?\n怎样传入这个队列参数？\n\n587\n00:30:59,825 --> 00:31:02,993\nWell, for the main queue, you call this function,\n对于主队列来说，可以通过调用\n\n588\n00:31:02,995 --> 00:31:05,963\ndispatch_get_main_queue. Now, you might ask,\ndispatch_get_main_queue 来获得. 你或许会问，\n\n589\n00:31:05,965 --> 00:31:10,100\nwhy is all these underbars and why does this look like this?\n为什么这么多下划线，为什么这个方法长这样？\n\n590\n00:31:10,102 --> 00:31:15,339\nThis is basically a CAPI, okay, from iOS before Swift,\n因为这是基于 CAPI 的，属于 iOS，而不是 Swift 的语法，\n\n591\n00:31:15,341 --> 00:31:18,008\nand so it comes into swift looking like a CAPI.\n所以这使得 Swift 看起来像 CAPI 一样.\n\n592\n00:31:18,010 --> 00:31:21,011\nThese are Swift, these are just Swift global functions.\n在 Swift 中，这是个全局方法.\n\n593\n00:31:21,013 --> 00:31:23,413\nBut the reason this is not object oriented, for\n它不是面向对象的，因为\n\n594\n00:31:23,415 --> 00:31:26,083\nexample is because this is a CAPI.\n它是 CAPI.\n\n595\n00:31:26,085 --> 00:31:28,852\nThis, this is called grand central dispatch actually,\n实际上，它被称为 GCD（大中枢派发）\n\n596\n00:31:28,854 --> 00:31:30,454\nthat's why they all start with dispatch,\n所以这个方法以 dispatch 开头，\n\n597\n00:31:30,456 --> 00:31:33,290\nall this multithreading stuff, and that's why it looks like\n这就是为什么，所有这类多线程接口，都和这个类似.\n\n598\n00:31:33,292 --> 00:31:37,094\nthis. I'm gonna show you the object-oriented way to do\n之后我会介绍怎么用面向对象的方式使用\n\n599\n00:31:37,096 --> 00:31:40,764\nthis in a minute, but actually we're gonna end up using these\n这些接口，在此之前，你还会继续\n\n600\n00:31:40,766 --> 00:31:44,768\nC-like ones more often, all right? So, again, all UI stuff\n使用 C 语言的风格的接口. 再次强调，所有 UI 的操作\n\n601\n00:31:44,770 --> 00:31:49,039\nhave to be on this main queue. It's a serial queue, okay, so\n都必须在主队列中进行. 这是个串行队列，\n\n602\n00:31:49,041 --> 00:31:51,608\nnothing happens concurrently on this queue,\n所以这个队列中不可能有并行的操作出现，\n\n603\n00:31:51,610 --> 00:31:55,112\nthings happen in order in the order they go in, okay?\n入队是什么顺序，出队就是什么顺序，有问题吗？\n\n604\n00:31:55,114 --> 00:31:57,381\nAnd, but all time-consuming stuff,\n所有耗时的操作，\n\n605\n00:31:57,383 --> 00:31:59,750\nokay, or even worse stuff that might block,\n或其他耗资源的操作，都可能造成阻塞，\n\n606\n00:31:59,752 --> 00:32:02,786\nlike you're going out to the network to get an image,\n就像网络请求图片这类的操作，\n\n607\n00:32:02,788 --> 00:32:05,555\nlike we are doing where that block's waiting for\n或者其他因等待网络响应，\n\n608\n00:32:05,557 --> 00:32:07,958\nthe Web server on the other side to respond,\n而导致阻塞的操作，\n\n609\n00:32:07,960 --> 00:32:10,794\nall that wants to happen off the main queue.\n这些操作，都不应该出现在主队列中.\n\n610\n00:32:10,796 --> 00:32:15,032\nNow you still dispatch to that queue using dispatch_async.\n目前我们在使用 dispatch_async 来派发队列.\n\n611\n00:32:15,034 --> 00:32:17,367\nYou go down here and you say look at the bottom,\n看到讲义的底部，\n\n612\n00:32:17,369 --> 00:32:20,170\nit says dispatc_async, not the main queue in here.\n参数这里写到，不一定非要传入主队列.\n\n613\n00:32:20,172 --> 00:32:22,973\nAnd I'll talk about where you get that queue in a second.\n之后会讲到如何获得其他队列.\n\n614\n00:32:22,975 --> 00:32:24,007\nAnd then open curly brace,\n接着，代码包含在大括号中，\n\n615\n00:32:24,009 --> 00:32:27,644\nso this is a closure, inside that closure you do the non-UI\n所以这是一个闭包，在闭包中，执行的是和 UI 无关的\n\n616\n00:32:27,646 --> 00:32:31,081\nthing that takes a long time or blocks. And then still\n操作，它可能会花很长时间，或者发生阻塞. 接着又是一个\n\n617\n00:32:31,083 --> 00:32:35,485\ninside this closure, you dispatch_async again. This\n闭包，再次 dispatch_async. 这次\n\n618\n00:32:35,487 --> 00:32:39,990\ntime back to the main queue to do the UI stuff that you need,\n回到了主队列中，处理和 UI 相关的操作，\n\n619\n00:32:39,992 --> 00:32:43,160\nmaybe that the image you got from doing this, you now put\n可能是你请求完了图片，需要\n\n620\n00:32:43,162 --> 00:32:47,064\nthis in the UI here. So look how I'm dispatching within\n扔到 UI 上进行显示. 所以来看看如何通过闭包\n\n621\n00:32:47,066 --> 00:32:50,567\na closure. So can you imagine this outer closure\n来派发它们. 你能想象外部闭包\n\n622\n00:32:50,569 --> 00:32:53,770\nis off running on some other thread in some other queue and\n在其他队列的其他线程上运行，\n\n623\n00:32:53,772 --> 00:32:57,908\nin the middle of it, it puts a block of code,\n然后在其中，又有一个代码块，\n\n624\n00:32:57,910 --> 00:32:58,508\nthis block right here,\n就是这个代码块，\n\n625\n00:32:58,510 --> 00:33:02,279\nthis closure. It puts it back on the main queue, this one\n这个闭包. 又回到了主队列，\n\n626\n00:33:02,281 --> 00:33:05,315\ncontinues to run after that in fact dispatc_async,\n继续通过 dispatch_async 方法执行操作，\n\n627\n00:33:05,317 --> 00:33:08,418\nthat function always returns immediately. Because all it\n这个方法会立即返回. 因为它是将任务\n\n628\n00:33:08,420 --> 00:33:11,655\ndoes is put things on queues, it doesn't actually execute\n扔到队列中，而没有真正执行\n\n629\n00:33:11,657 --> 00:33:13,490\nany of the code inside the block.\n代码块中的代码.\n\n630\n00:33:13,492 --> 00:33:16,827\nIt just puts that block of code onto the queue. Okay, and\n只是将代码块扔到了队列中. \n\n631\n00:33:16,829 --> 00:33:20,397\nthen this outer closure just happily runs to completion and\n接着，这个外部闭包就\n\n632\n00:33:20,399 --> 00:33:23,500\nit's done. Meanwhile, that inner block has been posted\n执行完了. 与此同时，内部闭包也扔到了\n\n633\n00:33:23,502 --> 00:33:24,868\non the main queue and it's just waiting for\n主队列中，等待\n\n634\n00:33:24,870 --> 00:33:27,637\nthe main queue, for it to be first in line and\n主队列执行. 排到主队列中，\n\n635\n00:33:27,639 --> 00:33:28,405\nfor the main queue to be quiet, and\n当主队列空闲下来，\n\n636\n00:33:28,407 --> 00:33:33,143\nthen it'll pick it up and run it. You got it? So this is why\n便会出队并执行. 这就是为什么\n\n637\n00:33:33,145 --> 00:33:36,680\nwe use the C function notation because it reads really cool,\n我们会用 C 函数，因为看起来真的挺酷的.\n\n638\n00:33:36,682 --> 00:33:39,816\nokay? Dispatch off the queue this, then dispatch the main\n先派发这个队列，然后派发\n\n639\n00:33:39,818 --> 00:33:44,087\nqueue this, okay? It reads very clearly to the person\n主队列. 很容易让阅读代码的人\n\n640\n00:33:44,089 --> 00:33:46,790\nwho's reading your code what you intend. Okay, but\n明白你的意图. 但是\n\n641\n00:33:46,792 --> 00:33:49,192\nyou do have to remember that this is async,\n注意这些都是异步的，\n\n642\n00:33:49,194 --> 00:33:53,163\nit's out of sync. Just because you say to execute this code,\n不是同步的. 因为我们并不需要显性调用这些代码，\n\n643\n00:33:53,165 --> 00:33:53,997\nit's not gonna happen right away.\n这些代码不会立刻执行.\n\n644\n00:33:53,999 --> 00:33:56,099\nIt's just being put on that queue, it'll happen sometime\n只是将它们加入到队列中，它们会在\n\n645\n00:33:56,101 --> 00:34:00,037\nin the future when that queue is ready, okay? When it rises\n队列空闲下来的时候自己执行. 当它们是队列\n\n646\n00:34:00,039 --> 00:34:04,975\nto the top of that queue and the main queue is quiet, okay?\n的队首元素，并且主队列闲下来的时候，就会执行.\n\n647\n00:34:04,977 --> 00:34:08,111\nSo how do we get these not the main queue queues?\n那么，怎么获得除了主队列以外的队列呢？\n\n648\n00:34:08,113 --> 00:34:10,313\nOkay, that we want to run something else on.\n比如我们想要执行其他的一些操作.\n\n649\n00:34:10,315 --> 00:34:11,415\nWell there's really two ways to do it.\n这有两种方式可用.\n\n650\n00:34:11,417 --> 00:34:15,552\nThe most common way is to use one of the concurrent queues\n最常见的直接使用系统提供的\n\n651\n00:34:15,554 --> 00:34:18,121\nprovided by the system, okay? Now these\n并行队列. 这四种队列\n\n652\n00:34:18,123 --> 00:34:21,758\nqueues provided by the system there's four of them, okay?\n就是系统提供的.\n\n653\n00:34:21,760 --> 00:34:25,295\nThey each have what's called a quality of service and\n它们有着不同的优先级的服务，\n\n654\n00:34:25,297 --> 00:34:28,165\nthe quality of service is really how\n服务的优先级其实就是\n\n655\n00:34:28,167 --> 00:34:31,668\nmuch attention the system gives to them.\n系统会给予多少的关注度.\n\n656\n00:34:31,670 --> 00:34:34,304\nYou can think of it as their priority. High-priority queues\n你可以顺着优先级来认识它们. 高优先级队列\n\n657\n00:34:34,306 --> 00:34:37,174\nget a high quality of service. They get serviced a lot, okay?\n拥有最高优先级的服务. 它们能获得较多的服务.\n\n658\n00:34:37,176 --> 00:34:41,111\nBut it's not purely that, but it's generally that. So\n但也不是绝对的，只是大致上来说而已.\n\n659\n00:34:41,113 --> 00:34:43,513\nwhat are the four qualities of service here?\n来看看这四种优先级的服务吧.\n\n660\n00:34:43,515 --> 00:34:46,817\nOne is USER_INTERACTIVE. So, you can get a queue, you\n一种是 USER_INTERACTIVE. 所以，你可以通过调用\n\n661\n00:34:46,819 --> 00:34:49,753\ncan call this dispatch, get global queue right here. And\nget_global_queue 方法来获得一个队列.\n\n662\n00:34:49,755 --> 00:34:52,589\nyou can say give me the user interactive queue. Again, it's\n然后给它 USER_INTERACTIVE 优先级. 这是个\n\n663\n00:34:52,591 --> 00:34:54,925\na concurrent queue, so it's doing things concurrently,\n并行队列，所以会并行处理操作，\n\n664\n00:34:54,927 --> 00:34:58,495\nit's not serial. And user interactive means\n这就不像串行了. USER_INTERACTIVE 意味着\n\n665\n00:34:58,497 --> 00:35:01,398\nthe user just asked to do something.\n这是用户要求处理的事情.\n\n666\n00:35:01,400 --> 00:35:03,066\nIt's gonna take a little bit of time,\n可能会花一些时间，\n\n667\n00:35:03,068 --> 00:35:04,801\nso I don't want to do it on the main queue,\n虽然我不想再主队列中进行处理，\n\n668\n00:35:04,803 --> 00:35:07,604\nbut I need this done as soon as possible because the user\n但是我仍然希望能进行执行，毕竟这是用户\n\n669\n00:35:07,606 --> 00:35:09,673\nis interacting with me right now, okay?\n希望立马响应的操作.\n\n670\n00:35:09,675 --> 00:35:11,641\nSo, this is very high priority, but\n所以它拥有最高优先级，\n\n671\n00:35:11,643 --> 00:35:15,345\nlower priority than the main queue, okay? So, this might be\n但这仍然要比主队列的优先级低. 这可能是\n\n672\n00:35:15,347 --> 00:35:18,081\nsomething where the user is dragging with their finger,\n用户在拖拽手指时，\n\n673\n00:35:18,083 --> 00:35:21,218\nand you're having to calculate something to make the image\n你需要同时计算一些数据并\n\n674\n00:35:21,220 --> 00:35:23,220\nthat's pretty intensive, time wise, and so\n立即给出反馈，这时就应该将任务扔到\n\n675\n00:35:23,222 --> 00:35:26,089\nyou put it off on the thread. The user continues to drag,\n这种队列中. 用户继续手指继续拖拽，\n\n676\n00:35:26,091 --> 00:35:27,390\nthey're not seeing the result and\n但是没有看到数据显示，\n\n677\n00:35:27,392 --> 00:35:28,558\nthen the result comes back in and\n等数据计算完成时，\n\n678\n00:35:28,560 --> 00:35:30,393\nthen the user gets to see the result. So\n用户才能看到数据. 所以，\n\n679\n00:35:30,395 --> 00:35:32,362\nthe results a little bit behind their finger,\n数据会比用户的手势慢一步，\n\n680\n00:35:32,364 --> 00:35:33,196\nbecause it takes so much time, but\n因为计算会花一些时间，\n\n681\n00:35:33,198 --> 00:35:35,799\nat least as their finger tracks the main queue is still\n但至少主线程一直在监听\n\n682\n00:35:35,801 --> 00:35:39,870\nlistening to their finger, okay, and responding, okay?\n手指的轨迹，并且响应还是有的，\n\n683\n00:35:39,872 --> 00:35:42,005\nSo that's what USE_INTERACTIVE is for.\n这就是 USER_INTERACTIVE 优先级.\n\n684\n00:35:42,007 --> 00:35:45,675\nUSE_INITIATED means the user just asked me to do this, but\nUSE_INITIATED 意思是，用户让我处理这个，但是不需要在\n\n685\n00:35:45,677 --> 00:35:48,812\nit's not in the middle of an interactive event so, you can\n用户交互的时候去处理，所以允许事件\n\n686\n00:35:48,814 --> 00:35:51,181\ntake a little bit of time but get back to me right away,\n等待一些事件，但一旦处理完一定要有反馈\n\n687\n00:35:51,183 --> 00:35:53,950\ncuz the user just asked for this, right now, okay?\n因为这是用户要求处理的\n\n688\n00:35:53,952 --> 00:35:58,255\nSo, that's lower priority, than an interactive thing.\n所以，它的优先级要比交互事件低一等\n\n689\n00:35:58,257 --> 00:36:02,626\nUTILITY is something that usually runs in the background\nUTILITY 一般用于在后台处理\n\n690\n00:36:02,628 --> 00:36:06,796\nfor a long time, okay? Maybe it's fetching data.\n一些耗时操作，比如获取数据什么的.\n\n691\n00:36:06,798 --> 00:36:09,633\nIt's cleaning up some database somewhere. It's doing\n也可以用于清理数据库，或者\n\n692\n00:36:09,635 --> 00:36:12,569\nsomething that the user didn't ask to do, but that needs to\n处理一些程序必须要处理，\n\n693\n00:36:12,571 --> 00:36:15,305\nbe done for this program. It's that kind of thing. And\n而用户又没有要求处理的事件. 大致就是这一类事件. \n\n694\n00:36:15,307 --> 00:36:17,941\nthen BACKGROUND is even lower priority. This is the kind of\nBACKGROUND 的优先级最低. 一般将一些可\n\n695\n00:36:17,943 --> 00:36:22,078\nthing well it could run today or tomorrow. But you know,\n今天，可明天处理的事件加到里面. 也就是，\n\n696\n00:36:22,080 --> 00:36:24,247\nit's really not something that I need done right away,\n没必要立马处理，\n\n697\n00:36:24,249 --> 00:36:26,516\nI don't really care. So, it's kind of just a,\n不需要过于关注的事件. 就好比是，\n\n698\n00:36:26,518 --> 00:36:28,318\nsomething that runs along in the background.\n在后台默默执行的事件. \n\n699\n00:36:28,320 --> 00:36:30,253\nIt's only gonna happen when things are really quiet,\n在没有其他事件需要占用资源的时候，\n\n700\n00:36:30,255 --> 00:36:34,991\nwhen nobody wants any other service, okay? So, you get one\n它才执行. 到此，你就已经学习了\n\n701\n00:36:34,993 --> 00:36:37,594\nof these four queues by saying dispatch_get_global_queue,\ndispatch_get_global_queue 包含的四种优先级. \n\n702\n00:36:37,596 --> 00:36:40,430\nyou specify which one you want. Then this has this\n可根据需要选择. 除此之外，\n\n703\n00:36:40,432 --> 00:36:44,768\nextra argument ,0 which is reserved for future use, so\n还有一个参数 0，这将在之后用到，\n\n704\n00:36:44,770 --> 00:36:45,602\nyou just always put ,0 there.\n现在就简单的传 0 就可以了.\n\n705\n00:36:45,604 --> 00:36:48,505\nAnd that's gonna give you back a queue, a dispatch_queue_t\n这样函数就会返回 dispatch_queue_t 类型的队列，\n\n706\n00:36:48,507 --> 00:36:51,942\nthat you can then use as your first argument to dispatch\n它可以作为 dispatch_async 的第一个参数.\n\n707\n00:36:51,944 --> 00:36:55,645\nasync, okay. So these are the, this is the cues,\n那么，这就是，\n\n708\n00:36:55,647 --> 00:36:57,514\nthese are the cues you're most often going to\n这就是在你要处理后台事件时，\n\n709\n00:36:57,516 --> 00:37:00,383\nput this work that needs to be done in the background onto.\n最为常用的队列了.\n\n710\n00:37:00,385 --> 00:37:03,720\nNow, its also possible for you to create your own\n当然，你也可以创建自己的\n\n711\n00:37:03,722 --> 00:37:07,023\nserial queue. You call dispatch_queue_create.\n串行队列. 通过调用 dispatch_queue_create 函数，\n\n712\n00:37:07,025 --> 00:37:09,626\nYou give it a name. This can be any name you want, okay?\n并给队列一个名字，任何名字都可以，\n\n713\n00:37:09,628 --> 00:37:12,028\nThis is usually just so you can see it in the debugger,\n这在调试的时候经常看到，\n\n714\n00:37:12,030 --> 00:37:14,297\nokay, this name is gonna appear in the debugger.\n队列名称会出现在调试界面中.\n\n715\n00:37:14,299 --> 00:37:16,366\nAnd then you say DISPATC_QUEUE_SERIAL,\n第二个参数是 DISPATC_QUEUE_SERIAL，\n\n716\n00:37:16,368 --> 00:37:17,500\nsaying you want a serial queue.\n表示你需要创建串行队列.\n\n717\n00:37:17,502 --> 00:37:20,737\nNow you will get a serial queue of your own.\n这样就能获得一个自己的串行队列了.\n\n718\n00:37:20,739 --> 00:37:22,672\nAnd it's gonna be a pretty high priority queue,\n这是一个优先级相当高的队列，\n\n719\n00:37:22,674 --> 00:37:25,742\nnothing like the main queue, but pretty high priority.\n虽然不像主队列那么高，但也算是万人之上了.\n\n720\n00:37:25,744 --> 00:37:27,644\nWhy would you ever want a serial queue?\n什么时候需要创建串行队列呢？\n\n721\n00:37:27,646 --> 00:37:31,581\nLet's say you had a big table that you wanna download\n假设你有一个长长的列表，想要下载\n\n722\n00:37:31,583 --> 00:37:34,351\na thousand images to put in that table.\n一千张图片扔到列表中\n\n723\n00:37:34,353 --> 00:37:37,754\nSmall little images, okay? Well you could do it on\n都是些小图标. 你可以\n\n724\n00:37:37,756 --> 00:37:40,290\none of these user initiated queues or something like that.\n在 USER_INITIATED 队列中或者其他队列中下载.\n\n725\n00:37:40,292 --> 00:37:42,225\nBut it's gonna fork off a whole bunch of threads and\n但是这样系统就会创建一大串线程，\n\n726\n00:37:42,227 --> 00:37:45,128\ntry to download as many as it can concurrently.\n而且尽可能多的进行并发下载.\n\n727\n00:37:45,130 --> 00:37:46,663\nOpen a whole bunch of network connections.\n同时发起一堆网络请求.\n\n728\n00:37:46,665 --> 00:37:50,800\nWhereas if you do is serially it will do it one by one,\n但如果你在串行队列中处理，就会一个一个按秩序下载，\n\n729\n00:37:50,802 --> 00:37:53,837\nokay? So it kind of throttles, it's a throttling,\n就像是限流的阀门，\n\n730\n00:37:53,839 --> 00:37:55,872\na way of throttling your access to the network,\n有限制的去访问网络.\n\n731\n00:37:55,874 --> 00:37:59,109\nall right? You usually don't need this.\n不过通常不需要这个.\n\n732\n00:37:59,111 --> 00:38:02,212\nThese are usually what you're gonna use for that not main\n这些通常会在其他队列中处理，而不是主队列.\n\n733\n00:38:02,214 --> 00:38:06,449\nqueue queue, okay? Now, we're only seeing the absolute\n到此，你已学习了多线程必备的一些知识，\n\n734\n00:38:06,451 --> 00:38:09,219\ntip of the iceberg on multithreading here,\n当然这只是冰山一角.\n\n735\n00:38:09,221 --> 00:38:13,323\nokay? There's a lot more to GCD, Grand Central Dispatch.\n更多关于 GCD，Grand Central Dispatch 的内容，\n\n736\n00:38:13,325 --> 00:38:14,557\nYou can look in the documentation for\n可以查看文档，\n\n737\n00:38:14,559 --> 00:38:16,660\nall the functions that start with dispatch underbar and\n所有方法都以 dispatch_ 开头，\n\n738\n00:38:16,662 --> 00:38:20,263\nyou'll get an idea, there's at least a couple dozen in there.\n至少有一打这样的方法.\n\n739\n00:38:20,265 --> 00:38:24,034\nI don't have time to cover it in this class.\n我没办法在课堂上依次为大家介绍.\n\n740\n00:38:24,036 --> 00:38:24,100\nYou won't need it,\n其他方法你也不需要，\n\n741\n00:38:24,102 --> 00:38:26,102\nyou won't need anything more than I just showed you for\n除了我介绍给大家的这些方法外，你暂时还用不到别的\n\n742\n00:38:26,104 --> 00:38:28,371\nthe work that you're gonna be doing in your assignments.\n包括课后作业也不会用到.\n\n743\n00:38:28,373 --> 00:38:31,007\nIn your final project, you probably also won't need\n甚至是最终考核项目，你都可能用不上\n\n744\n00:38:31,009 --> 00:38:33,910\nanymore than that, but at least you know where to look,\n别的方法，但至少要知道用的时候，\n\n745\n00:38:33,912 --> 00:38:38,214\nif you might need more. There is an object-oriented\n能在哪里查到. 这是面向对象的\n\n746\n00:38:38,216 --> 00:38:40,850\nway of doing all this called, there's two classes,\n调用方式，提供了两个类，\n\n747\n00:38:40,852 --> 00:38:43,853\nNSOperationQueue, which is kind of like dispatch queues.\nNSOperationQueue，和 dispatch queue 很像.\n\n748\n00:38:43,855 --> 00:38:47,824\nAnd NSOperation, which is kinda like those closures,\n还有 NSOperation，和闭包类似，\n\n749\n00:38:47,826 --> 00:38:52,929\nright, those little functions. Why would you ever want this?\n包含要处理的事件. 为什么我们需要这个两个类呢？\n\n750\n00:38:52,931 --> 00:38:56,132\nThese do have a little bit of extra functionality,\n因为它们在 GCD 基础上，\n\n751\n00:38:56,134 --> 00:38:59,069\nthat they wrap from GCD, things like, hey,\n还提供了一些额外的功能，比如，\n\n752\n00:38:59,071 --> 00:39:00,704\nI have these two operations and\n两个事件(operation)，\n\n753\n00:39:00,706 --> 00:39:04,441\nthis one depends on this one finishing, okay. And so\n一个要在另一个结束之后发起.\n\n754\n00:39:04,443 --> 00:39:06,076\nI'm gonna put them in a concurrent queue, but\n把它们扔在并发队列中，\n\n755\n00:39:06,078 --> 00:39:08,845\ndon't let this other one go until the first one finishes,\n也能保证一个在另一个结束之后发起.\n\n756\n00:39:08,847 --> 00:39:11,047\nright. So dependencies, you can have dependencies and\n这就是依赖，你能对事件添加依赖.\n\n757\n00:39:11,049 --> 00:39:14,417\nthings like that. We're not gonna talk about that.\n课堂上不讲，\n\n758\n00:39:14,419 --> 00:39:16,553\nYou can look at the documentation if you want.\n你可以在文档中看到.\n\n759\n00:39:16,555 --> 00:39:20,690\nYou can do, I think almost everything here with GCD.\n我们需要的处理，GCD 已经足够了.\n\n760\n00:39:20,692 --> 00:39:23,259\nThis would be more if you actually are building\n如果你是在创建一个\n\n761\n00:39:23,261 --> 00:39:26,029\nsomething where there's queue are doing queues and\n有很多队列，而且\n\n762\n00:39:26,031 --> 00:39:29,299\nthese operations are doing the actual calculation. Like as\noperation 都在处理相关运算. 就像\n\n763\n00:39:29,301 --> 00:39:31,568\nyour model is doing, you're doing some scientific app and\n建模一样，做一个科学相关的 app，\n\n764\n00:39:31,570 --> 00:39:33,803\nit's actually doing all this complex calculation where\n并且在处理一些非常复杂的计算，\n\n765\n00:39:33,805 --> 00:39:35,372\nthings depend on each other and all that stuff.\n每个计算都相互依赖.\n\n766\n00:39:35,374 --> 00:39:38,441\nAnd so it has a lot of queues and a lot of operations going.\n这样，就需要很多队列和操作了.\n\n767\n00:39:38,443 --> 00:39:40,910\nYou wouldn't use it as much for things like, I'm fetching\n也就这个时候，你需要使用到依赖，如果只是\n\n768\n00:39:40,912 --> 00:39:42,879\nsomething from the network and I need to put it in the UI,\n需要从网络上拉取数据，然后在 UI 上展示，\n\n769\n00:39:42,881 --> 00:39:45,181\nand I want that fetched to happen in another queue.\n即使想要在其他队列中发起请求，\n\n770\n00:39:45,183 --> 00:39:47,317\nThat kind of stuff you're just going to use the dispatch\ndispatch_ 相关方法已经够用了.\n\n771\n00:39:47,319 --> 00:39:53,156\nunderbar, okay. Now, in addition to dispatch underbar,\n作为 dispatch_ 的补充，\n\n772\n00:39:53,158 --> 00:39:55,625\nyou have to understand multithreading from\n你还需要从 iOS 的 API 中\n\n773\n00:39:55,627 --> 00:39:57,827\nthe perspective of how iOS's API uses it.\n理解多线程该如何使用.\n\n774\n00:39:57,829 --> 00:40:00,997\nBecause there are plenty of methods all throughout\n因为关于异步线程的方法，\n\n775\n00:40:00,999 --> 00:40:05,168\niOS that do what they do asynchronously, using threads.\n实在是太多了.\n\n776\n00:40:05,170 --> 00:40:08,438\nOkay? And the way you see this in the API, is that one of\n你在看 API 的时候，其中一个\n\n777\n00:40:08,440 --> 00:40:11,941\nthe arguments to these methods is a block, is a closure,\n参数是 block，一个闭包，\n\n778\n00:40:11,943 --> 00:40:14,477\nright? It's gonna be a closure you provide, and\n闭包内容由你提供，\n\n779\n00:40:14,479 --> 00:40:16,980\nthe documentation for that function will say your\n文档的解释是，你的闭包\n\n780\n00:40:16,982 --> 00:40:21,084\nclosure's executed off the main cue, asynchronously.\n会异步的在主队中执行.\n\n781\n00:40:21,086 --> 00:40:23,753\nSo what kind of methods are we talking about here that do\n这就是能解决我们之前问题的方法.\n\n782\n00:40:23,755 --> 00:40:27,690\nthat? Here's one that goes and fetches a URL. Okay,\n可以用它来拉取网络数据.\n\n783\n00:40:27,692 --> 00:40:30,794\nfrom the internet. Downloads it from the internet. And\n进行网络数据下载.\n\n784\n00:40:30,796 --> 00:40:32,595\nwhen it, and it does it asynchronously obviously.\n它会在异步中处理.\n\n785\n00:40:32,597 --> 00:40:34,798\nYou wouldn't wanna block the main queue waiting for\n你也不想要它因为加载 url，而阻塞主队列吧.\n\n786\n00:40:34,800 --> 00:40:37,233\nthis URL to load. And when it comes back,\n在响应回来后，\n\n787\n00:40:37,235 --> 00:40:39,936\nit calls this closure right here, okay? Now\n它救护调用这个闭包.\n\n788\n00:40:39,938 --> 00:40:44,040\ninside this closure, you might want to do some UI things.\n在这个闭包中，你就可以做一些 UI 操作了.\n\n789\n00:40:44,042 --> 00:40:46,543\nLike maybe you downloaded an image and you wanna put it.\n比如显示刚下载完成的图片.\n\n790\n00:40:46,545 --> 00:40:49,078\nBut you can't put that code right inside here.\n但是你不能直接将 UI 代码写在这，\n\n791\n00:40:49,080 --> 00:40:52,015\nBecause this closure is executed on a different\n因为这个闭包会在\n\n792\n00:40:52,017 --> 00:40:54,818\nthread and on a different queue than the main queue. So\n另一个队列的线程中执行，而不是在主队列中执行. 所以\n\n793\n00:40:54,820 --> 00:40:56,886\nwhat you would have to do in here is the same thing\n这里你还需要\n\n794\n00:40:56,888 --> 00:40:57,720\nyou have to do with the dispatch_async,\n像之前创建 dispatch_async 一样，\n\n795\n00:40:57,722 --> 00:41:03,560\nwhich is you have to wrap dispatc_async ge_mai_queue\n用一个主队列的异步线程去包裹它.\n\n796\n00:41:03,562 --> 00:41:07,464\naround it, okay? So here's the method. This is an iOS method\n就像这样写. 这是个 iOS 的\n\n797\n00:41:07,466 --> 00:41:10,333\ndownloadTaskWithRequest. It takes this last argument,\ndownloadTaskWithRequest 方法. 最后一个参数，\n\n798\n00:41:10,335 --> 00:41:12,836\nwhich is a closure. And inside there you're gonna have to\n是一个闭包. 在闭包中，\n\n799\n00:41:12,838 --> 00:41:15,572\ndo this dispatch to the main queue. Because if you wanna do\n你需要回到主队列. 因为你要处理\n\n800\n00:41:15,574 --> 00:41:18,107\nsomething to the UI, because this is not happening,\nUI 相关操作，就不能直接写，\n\n801\n00:41:18,109 --> 00:41:21,911\nthis closure will not be executed on the main queue.\n这个闭包不会在主队列中执行.\n\n802\n00:41:22,047 --> 00:41:25,982\nGot it? So we will talk a little bit about, you're just\n明白吗？所以建议大家\n\n803\n00:41:25,984 --> 00:41:29,919\ngonna run into occasional iOS APIs that take these closures,\n可以查查 iOS API 中，异步操作时，\n\n804\n00:41:29,921 --> 00:41:32,455\nand they're asynchronous. And you just have to know that if\n关于这个闭包的描述. 你需要知道，要处理任何\n\n805\n00:41:32,457 --> 00:41:33,957\nyou wanna do anything in the UI, you're gonna have\n与 UI 相关的操作，都必须要\n\n806\n00:41:33,959 --> 00:41:38,628\nto dispatch async back to the main queue. All right, so\n先回到主队列. 行，接下来\n\n807\n00:41:38,630 --> 00:41:41,364\nlet's do a demo of this where let's fix Cassini.\n我们来完善 Cassini demo 中的问题.\n\n808\n00:41:41,366 --> 00:41:44,934\nOkay, let's make Cassini so that it's UI's always\n优化一下 Cassini 的 UI，\n\n809\n00:41:44,936 --> 00:41:49,606\nresponsive even while it's off downloading these things.\n使之在有下载任务的时候，也能及时响应事件.\n\n810\n00:41:49,608 --> 00:41:53,376\nAll right lets go over here.\n那么从这里开始吧.\n\n811\n00:41:53,378 --> 00:41:55,445\nOkay, all this is gonna be, all this code that we're going\n先处理这些，这些在 ImageViewController\n\n812\n00:41:55,447 --> 00:41:57,514\nto have to do is going to be in our ImageViewController.\n中的代码.\n\n813\n00:41:57,516 --> 00:41:59,916\nWe're going to make our ImageViewController, so\n先要将 ImageViewController 改为\n\n814\n00:41:59,918 --> 00:42:02,952\nthat it is asynchronous, right? That it can load things\n异步处理，这样就能异步\n\n815\n00:42:02,954 --> 00:42:05,522\nasynchronously. Before I do that actually though,\n加载数据. 在实际操作之前，\n\n816\n00:42:05,524 --> 00:42:07,524\nI wanna talk one other thing we should be doing here,\n我还要讲到一件事，\n\n817\n00:42:07,526 --> 00:42:08,958\nprobably, in ImageViewController.\n需要在 ImageViewController 中注意的事.\n\n818\n00:42:08,960 --> 00:42:12,495\nNotice that if someone sets our model, we immediately go\n注意这里有一段设置模型的代码，我们在里面\n\n819\n00:42:12,497 --> 00:42:17,133\noff and fetch it, okay? Now what if we never appeared on\n获取数据. 但如果我们从未将它展示在\n\n820\n00:42:17,135 --> 00:42:21,437\nscreen? Okay, what if this or something that's in a,\n屏幕上呢？如果这是个，\n\n821\n00:42:21,439 --> 00:42:24,207\ngonna be in a navigation controller, it got created,\n这是个 navigation controller 之类的，虽然创建了，\n\n822\n00:42:24,209 --> 00:42:27,710\nbut no one ever clicked to cause it to happen on screen,\n并且进行了模型设置，\n\n823\n00:42:27,712 --> 00:42:28,311\nbut someone set our model.\n但是从来没有经过点击事件展示到屏幕上.\n\n824\n00:42:28,313 --> 00:42:30,980\nThen this wouldn't happen in Cassini, this app, but imagine\n虽然这问题不会出现在 Cassini 中，但是要小心在\n\n825\n00:42:30,982 --> 00:42:35,418\nan app where you've got this image MVC and some incentive.\n其他 app 中重用这个 image 的 MVC 结构或逻辑的情况.\n\n826\n00:42:35,420 --> 00:42:37,186\nReally we really wouldn't want to do this\n千万不要出现这种额外的资源消耗，\n\n827\n00:42:37,188 --> 00:42:39,789\nfetch cuz it could be very expensive as we've seen,\n这种资源占用非常昂贵.\n\n828\n00:42:39,791 --> 00:42:40,623\nright? It goes on the network,\n明白吗？这需要用到网络，\n\n829\n00:42:40,625 --> 00:42:42,292\nit's pulling down this thing if I'm paying for\n要从网络上拉去数据，而如果我允许\n\n830\n00:42:42,294 --> 00:42:44,928\ncellular data, it's costing me money! Okay,\n蜂窝数据，这会产生费用的！\n\n831\n00:42:44,930 --> 00:42:47,931\nto get that Cassini image, so I probably don't want to do\n所以，除非是在显示到屏幕上时，\n\n832\n00:42:47,933 --> 00:42:51,968\nthis fetch image unless I'm on screen. If I'm on screen,\n我才会去获取 Cassini 的图片数据. 只有在屏幕上时，\n\n833\n00:42:51,970 --> 00:42:55,004\nI definitely want to do this. So here I'm going to say how\n我才需要这样做. 那么，如何判断是否在\n\n834\n00:42:55,006 --> 00:42:58,341\ncan I tell if I'm on screen? If my view, okay,\n屏幕上呢？如果这个 view，\n\n835\n00:42:58,343 --> 00:43:03,913\nthis is my MVC's view the top level, if it's window\n即 MVC 结构中最顶层的 view，它的 window \n\n836\n00:43:03,915 --> 00:43:08,618\nis not nil. Okay, that's a pretty reliable way to tell,\n不是 nil. 则说明视图在屏幕上，\n\n837\n00:43:08,620 --> 00:43:12,989\nsorry, that you are on screen, right? Because your view,\n这种验证方式很靠谱. 因为你的 view，\n\n838\n00:43:12,991 --> 00:43:15,692\nyour mvc's view will not be in a window unless it's on\n你的 mvc view 不在屏幕上，才获取不到 window.\n\n839\n00:43:15,694 --> 00:43:19,529\nscreen. Make sense? We haven't talked about window much.\n明白吗？我们目前还没讲到太多 window 的知识.\n\n840\n00:43:19,531 --> 00:43:22,765\nIt's that UI Window class I told you that you really never\n它就是之前我告诉你们的，\n\n841\n00:43:22,767 --> 00:43:23,299\nuse it, and you don't.\n永远不要用，并且你们也没有用的那个 UIWindow 类.\n\n842\n00:43:23,301 --> 00:43:26,436\nYou're not going to send any messages to it here. But\n这里不需要调 window 的方法，\n\n843\n00:43:26,438 --> 00:43:26,569\nwhether it's nil or\n直接判断它是否是 nil，\n\n844\n00:43:26,571 --> 00:43:29,105\nnot will tell you whether your view is on screen.\n就能告诉你 view 是否在屏幕上.\n\n845\n00:43:29,107 --> 00:43:32,342\nNow what happens though if someone sets my image URL like\n那么，现在如果有人在 prepareForSegue 或者\n\n846\n00:43:32,344 --> 00:43:36,713\nin a prepare for segue and then I do go on screen later?\n视图展示在屏幕上时，设置了图片 URL，\n\n847\n00:43:36,982 --> 00:43:39,349\nNow I have to fetch that image, okay? Cuz now I\n我就回去获取图片数据. 因为下一步肯定能\n\n848\n00:43:39,351 --> 00:43:41,918\nam going to go on screen. So how can I find out in my view\n展示到屏幕上. 那么如何得知 view controller \n\n849\n00:43:41,920 --> 00:43:44,487\ncontroller lifecycle that now I'm gonna go on screen,\n生命周期中，何时展示到屏幕上呢？\n\n850\n00:43:44,489 --> 00:43:49,993\nwhich method? Which method in my view controller lifecycle?\n哪个方法？view controller 生命周期中的哪个方法？\n\n851\n00:43:49,995 --> 00:43:54,497\nDo you remember? It called. I'll put it down here\n还记得吗？它叫做...\n\n852\n00:43:54,499 --> 00:43:59,302\nnext to this viewDidLoad one. ViewWillAppear. Okay, so\n和 viewDidLoad 写在一起吧. 叫做，viewWillAppear.\n\n853\n00:43:59,304 --> 00:44:02,071\nviewWillAppear is sent to you when you're about to appear on\n在即将展示到屏幕上时，会调用 viewWillAppear 方法.\n\n854\n00:44:02,073 --> 00:44:06,509\nscreen. Okay and we always do super.viewWillAppear in\n对于 view controller 声明周期的方法，\n\n855\n00:44:06,511 --> 00:44:10,146\nall these view controller life cycles, all right. So,\n我们通常会先调用父类的方法，super.viewWillAppear.\n\n856\n00:44:10,148 --> 00:44:14,050\nhere I'm going to say if my image is nil,\n在这里判断，如果 image 是 nil，\n\n857\n00:44:14,052 --> 00:44:19,255\nthen I better go fetch it, okay? So, this is one\n那么就获取它，这样处理\n\n858\n00:44:19,257 --> 00:44:22,692\nthing I've done to increase my performance a little bit. But\n能提升一点点性能. 但是\n\n859\n00:44:22,694 --> 00:44:24,794\nit's still not going to stop things from blocking,\n依然没能解决阻塞问题，\n\n860\n00:44:24,796 --> 00:44:26,562\nbecause as soon as viewWillAppear happens,\n因为当 viewWillAppear 调用时，\n\n861\n00:44:26,564 --> 00:44:27,597\nand I'm just about to go on screen,\n并且视图在屏幕上，\n\n862\n00:44:27,599 --> 00:44:30,900\nmy whole app is going to freeze while I'm out fetching.\n整个 app 都被阻塞了，需要去获取数据.\n\n863\n00:44:30,902 --> 00:44:32,268\nThose big huge images, right?\n去获取一张很大的图片.\n\n864\n00:44:32,270 --> 00:44:34,437\nSo I haven't really fixed the problem. I need multithreading\n所以我们还没解决这个问题，我需要用到多线程.\n\n865\n00:44:34,439 --> 00:44:36,506\nfor that. But I just wanted to show you to be a little bit\n我将会演示如何小心翼翼的\n\n866\n00:44:36,508 --> 00:44:40,009\ncareful about when you fire off an expensive operation.\n开启这一昂贵操作的技能.\n\n867\n00:44:40,011 --> 00:44:42,178\nThat's what viewWillAppare, Appear is for.\n这也是 viewWillAppear 的作用.\n\n868\n00:44:42,180 --> 00:44:44,080\nThat's really where you wanna fire off things like going\n你需要在这里发起所有的操作，\n\n869\n00:44:44,082 --> 00:44:48,084\nout on the network and stuff, okay? All right, so now let's\n例如网络请求什么的. 那么现在就\n\n870\n00:44:48,086 --> 00:44:50,620\ndo our multi guiding and fix this. We're gonna do this here\n遵循着多线程规则，来解决阻塞问题吧. 我们需要对\n\n871\n00:44:50,622 --> 00:44:53,389\nin fetchImage. We're gonna make it so that fetchImage\nfetchImage 进行处理. 我们需要使 fetchImage\n\n872\n00:44:53,391 --> 00:44:57,126\ndoes the actual fetching in another thread. All right, so\n真正的获取事件发生在另一个线程中. \n\n873\n00:44:57,128 --> 00:45:00,997\nhow are we gonna do this? It's pretty simple actually.\n那么怎么实现呢？其实很简单.\n\n874\n00:45:00,999 --> 00:45:05,968\nWe're just going to take this code right here which blocks.\n只需要将这段代码，这个 block，\n\n875\n00:45:05,970 --> 00:45:07,937\nThis blocks the main queue while it goes out\n这个 block 是在主线程进行\n\n876\n00:45:07,939 --> 00:45:10,640\non the network, to forget the contents of this URL.\n网络请求来获取 url 内容的.\n\n877\n00:45:10,642 --> 00:45:13,843\nAnd we're going to use the GCD to\n我们使用 GCD 来\n\n878\n00:45:13,845 --> 00:45:16,846\nput it on a different thread, okay? So I'm just going to\n将操作扔到不同的线程中. 所以，代码应该是，\n\n879\n00:45:16,848 --> 00:45:21,718\nsay, dispatch, async, okay? Remember, dispatch async\ndispatch_async，记得吗，dispatch_async\n\n880\n00:45:21,720 --> 00:45:26,122\ntakes two arguments. A queue and a block here, a closure or\n有两个参数，一个队列和一个 block，即一个闭包或\n\n881\n00:45:26,124 --> 00:45:31,194\na function do that. So I'm going to put on one of those,\n一个方法. 我准备将处理扔到\n\n882\n00:45:31,196 --> 00:45:34,497\nconcurrent cues. And I'm gonna put it on the one where\n并行队列中. 优先级是\n\n883\n00:45:34,499 --> 00:45:36,733\nthe user initiated it but it's not interactive.\nuser initiated，而不是 interactive.\n\n884\n00:45:36,735 --> 00:45:38,634\nThe user's not in the middle of dragging or something.\n因为处理中，用户不会进行拖拽等交互.\n\n885\n00:45:38,636 --> 00:45:40,536\nThey initiated it so it's pretty high priority and\ninitiated 的优先级已经很高了，\n\n886\n00:45:40,538 --> 00:45:45,208\nso I get that by saying dispatch_get_global_queue and\n调用 dispatch_get_global_queue 来获得队列，\n\n887\n00:45:45,210 --> 00:45:47,477\nthe one I want is\n这个参数是\n\n888\n00:45:47,479 --> 00:45:54,083\nQOS_CLASS_USE_INITIATED. This one right here, okay?\nQOS_CLASS_USE_INITIATED. 第一个参数搞定，\n\n889\n00:45:54,085 --> 00:45:58,287\nThis flags is always zero, right? And now I have this\n这个标识直接填 0. 接下来配置 block，\n\n890\n00:45:58,289 --> 00:46:00,423\nblock here, so I'm gonna double-click on that.\n双击代码提示，\n\n891\n00:46:00,425 --> 00:46:00,957\nIt's really nice, by the way,\n就自动补全了，另外，\n\n892\n00:46:00,959 --> 00:46:04,193\nyou can double-click on these things to expand the block.\n除了能双击展开 block 以外，\n\n893\n00:46:04,195 --> 00:46:06,829\nI'm gonna use the clay trailing,\n我使用的的是尾闭包的形式，\n\n894\n00:46:06,831 --> 00:46:11,400\nclosure syntax here. Okay for my block, this block, you'll\n完善闭包语法. 这里就是我的 block 了，\n\n895\n00:46:11,402 --> 00:46:13,836\nnotice it takes no arguments, returns no arguments.\n你可以看到这个 block 没有参数，也没有返回值.\n\n896\n00:46:13,838 --> 00:46:18,941\nI'm just going to put all this blocking junk inside here,\n然后将这一大段 block 代码，扔到尾闭包中.\n\n897\n00:46:18,943 --> 00:46:23,012\nokay. So this is going to fix my problem, okay.\n这样就能解决我们的问题了.\n\n898\n00:46:23,014 --> 00:46:28,217\nExcept that it probably gonna make my app go all strange\n不过这样写可能会导致 app 出现以下莫名其妙的问题，\n\n899\n00:46:28,219 --> 00:46:32,155\nbecause I'm gonna be trying to do this inside\n因为我在\n\n900\n00:46:32,157 --> 00:46:36,459\na non-main queue. All right, cuz this queue, this block\n非主队列做了这个操作. 因为这个 block \n\n901\n00:46:36,461 --> 00:46:40,329\nright here is gonna be put on this queue, and so I can't do\n会在这个队列中执行，所以我们不能在 block 里面\n\n902\n00:46:40,331 --> 00:46:43,933\nthis inside of here. Question? >> Can you explain\n做这个操作. 什么问题？能讲一下\n\n903\n00:46:43,935 --> 00:46:44,867\nthe trailing, the plot,\n尾闭包吗？\n\n904\n00:46:44,869 --> 00:46:47,804\nthe trailing plot where you added the parenthesis and\n应该在哪添加括弧，它是怎样\n\n905\n00:46:47,806 --> 00:46:49,438\nwhat it does? >> Yeah, okay, so\n执行的？行，好的，\n\n906\n00:46:49,440 --> 00:46:55,511\nthis used to look like this. Okay, so this is normal.\n闭包以前是长这样的，这是一个普通的闭包.\n\n907\n00:46:55,513 --> 00:46:57,947\nI'm calling this function right here, okay? Sorry,\n我在调用这个方法时，哦，不好意思，\n\n908\n00:46:57,949 --> 00:47:00,750\nthis function right here. Here is its first arguments,\n这个方法. 这是第一个参数，\n\n909\n00:47:00,752 --> 00:47:05,388\nsee that? Here its second argument, okay.\n这是第二个参数.\n\n910\n00:47:05,390 --> 00:47:09,158\nIf the sec, if the last argument of any function is\n如果第二个参数，如果最后一个参数接收的是\n\n911\n00:47:09,160 --> 00:47:14,697\na closure, then you can put it outside of the parenthesis.\n闭包，那么就可以将其写在参数列表以外.\n\n912\n00:47:14,699 --> 00:47:17,466\nSee this dispatch_async parentheses starts here? So\n这个 dispatch_async 方法括号从这里开始，\n\n913\n00:47:17,468 --> 00:47:20,603\nI just took this parentheses off of here and\n我只是将这里的反括弧，\n\n914\n00:47:20,605 --> 00:47:26,475\nI put it over here. Okay, so now this is the first\n移到了这里. 所以，现在这里是函数的\n\n915\n00:47:26,477 --> 00:47:29,812\nargument to this function, inside these parenthesis. And\n第一个参数，在参数列表的括号内.\n\n916\n00:47:29,814 --> 00:47:33,149\nhere's the closure which is outside the parenthesis, okay.\n而这个闭包，在括号外面.\n\n917\n00:47:33,151 --> 00:47:36,185\nYou definitely wanna get used to that cuz we're almost\n这种写法你一定会熟悉的，因为之后我们\n\n918\n00:47:36,187 --> 00:47:39,155\nalways gonna do it that way. And when people design APIs\n都会这样写. 当开发者在设计 API 的时候，\n\n919\n00:47:39,157 --> 00:47:41,390\nthey almost always put the closure at the end so\n他们尽量将闭包扔到最后，这样\n\n920\n00:47:41,392 --> 00:47:44,560\npeople can do this. All right, so\n使用者就可以用尾闭包了.\n\n921\n00:47:44,562 --> 00:47:45,595\nwhat am I gonna do about this,\n所以我也这样去使用它.\n\n922\n00:47:45,597 --> 00:47:49,332\nokay? I need this to be back on the main queue. Well,\n现在我需要回到主队列.\n\n923\n00:47:49,334 --> 00:47:52,902\nvery simple here. I'm just going to dispatch it back to\n非常简单，只需要将它派发回\n\n924\n00:47:52,904 --> 00:47:57,707\nthe main queue. Now, another thing I'm gonna do here,\n主队列即可. 除此之外，还有一件事需要处理，\n\n925\n00:47:57,709 --> 00:48:02,278\nwhile I'm kinda at it is, let's get this NSData right\n先这样，先将这里获取的 NSData \n\n926\n00:48:02,280 --> 00:48:06,082\nhere. I'm gonna assign that to a local variable\n使用临时变量接受一下，\n\n927\n00:48:06,084 --> 00:48:10,519\nhere called content of URL, okay? And then I'm gonna put,\n叫 contentsOfURL，\n\n928\n00:48:10,521 --> 00:48:12,922\nso that's gonna be happening in my other queue.\n这一部分是发生在另一个队列中的.\n\n929\n00:48:12,924 --> 00:48:17,960\nAnd then I'm gonna dispatch async back to the main queue,\n然后，调用 dispatch_async 回到主队列，\n\n930\n00:48:17,962 --> 00:48:21,597\nwhich I get by dispatch_get_main_queue.\n传入 dispatch_get_main_queue.\n\n931\n00:48:21,599 --> 00:48:24,901\nOkay, same exact thing here, okay, here's the block,\n这个是一样的，这个 block，\n\n932\n00:48:24,903 --> 00:48:28,604\nI'm gonna do the same thing. Click trailing, close your\n和之前一样. 改为尾闭包，\n\n933\n00:48:28,606 --> 00:48:33,376\nnotation, and now I'm gonna put this inside here, okay.\n然后将代码扔进去，\n\n934\n00:48:33,378 --> 00:48:37,413\nBut now the image data is this thing that I got right there,\n现在 imageData 应该是这个，我将它放在这，\n\n935\n00:48:37,415 --> 00:48:41,317\nso that's content of URL.\n所以是 contentsOfURL.\n\n936\n00:48:41,319 --> 00:48:46,188\nOkay, now this happening on the main queue, all is well.\n现在，这就在主队列中执行了，全部搞定.\n\n937\n00:48:46,190 --> 00:48:50,459\nThis image=UIImage, the UI kit thing. This is a UI kit thing,\n这个 image 是 UIImage，UIKit 中的那个. 这个 UIKit 元素，\n\n938\n00:48:50,461 --> 00:48:52,795\nby the way, no, not actually because of the UIImage.\n准确的说不是严格是，因为它是 UIImage，\n\n939\n00:48:52,797 --> 00:48:55,898\nThat is the one UI thing you can do on a different thread.\n而 UIImage 可以在不同的线程中处理，\n\n940\n00:48:55,900 --> 00:48:58,367\nBut it's because when we say image= down here,\n这只是进行了图片下载，\n\n941\n00:48:58,369 --> 00:49:01,904\nit's gonna do something like imageview.image=new value.\n因为我们之后要将 image 赋值给 imageView.image.\n\n942\n00:49:01,906 --> 00:49:03,439\nOkay, well that's the UI kit right there, so\n而 UIImageView 是 UIKit 元素，所以\n\n943\n00:49:03,441 --> 00:49:06,575\nthat has to be on the main thread. So that's why I have\n必须要在主线程在中处理. 这才是我们要回到主线程的原因.\n\n944\n00:49:06,577 --> 00:49:08,878\nto do that. Now notice we still have an error here.\n注意我们这里还在报错.\n\n945\n00:49:08,880 --> 00:49:11,814\nAnyone know what this error is? It's pointing right here.\n有人知道这个错误原因吗？有人知道吗？\n\n946\n00:49:11,816 --> 00:49:17,987\nWhat do you think it wants there? No idea?\n知道编译器想要我们怎么做吗？没人知道？\n\n947\n00:49:21,059 --> 00:49:26,128\nIt wants self there, because this is a closure. Okay,\n它想要加上 self，因为这是一个闭包，\n\n948\n00:49:26,130 --> 00:49:27,697\nthis is inside a closure. And remember,\n这段代码在闭包中，记住，\n\n949\n00:49:27,699 --> 00:49:32,702\nwhenever we have a closure and we use a property on our\n无论何时，在闭包中访问属性或成员变量，\n\n950\n00:49:32,704 --> 00:49:36,472\nobject, we need to put self in there to make it\n都需要使用 self 调用，\n\n951\n00:49:36,474 --> 00:49:39,342\nclear that we understand this is being captured and\n以此指明变量值快照，\n\n952\n00:49:39,344 --> 00:49:44,480\nkept in the heap. So as long as this closure right here,\n并将它存到堆中. 所以，无论是这个闭包，\n\n953\n00:49:44,482 --> 00:49:46,749\nwhich it's got this closure inside of it.\n还是这个包含在闭包内的闭包，\n\n954\n00:49:46,751 --> 00:49:49,385\nAs long as this is out there fetching,\n只要是在函数作用域外了，\n\n955\n00:49:49,387 --> 00:49:54,190\nit's going to keep this view controller in the heap, okay?\n都需要将 view controller 保存在堆上.\n\n956\n00:49:54,192 --> 00:49:58,194\nNow if we wanted to here, we could do the week self thing\n如果我们要在这里使用，还需要用 weak 修饰 self，\n\n957\n00:49:58,196 --> 00:50:02,398\nand have week self question mark and that way if the image\n防止在图片数据回来的时候，self 已经被释放，\n\n958\n00:50:02,400 --> 00:50:06,469\ncame back and our MVC had been thrown out of the heap,\n导致 MVC 抛出的堆内存异常.\n\n959\n00:50:06,471 --> 00:50:09,405\nit would be fine, we would just ignore it.\n这样就能避免了，就能忽略掉异常了.\n\n960\n00:50:09,407 --> 00:50:11,841\nOkay, but I'm pressed for time so I'm not gonna do that but\n因为时间原因，我就不演示了，\n\n961\n00:50:11,843 --> 00:50:15,277\nyou could hopefully imagine doing that. Okay, so\n不过你们应该能想象出来. \n\n962\n00:50:15,279 --> 00:50:17,179\neveryone see what we've done here?\n每个人都能理解了吗？\n\n963\n00:50:17,181 --> 00:50:20,883\nSo that's really all we need to do. One thing that it's\n这就是我们需要的全部处理. 对了，\n\n964\n00:50:20,885 --> 00:50:24,053\na little, now, I told you that multithreading, it's pretty\n还有一小点，现在我讲解了多线程，\n\n965\n00:50:24,055 --> 00:50:26,522\neasy to read this code and understand what's going on.\n非常简单，一看代码就能明白.\n\n966\n00:50:26,524 --> 00:50:29,725\nBut you've got to think of the bigger picture of what's\n但是你想想，如果是在用多线程\n\n967\n00:50:29,727 --> 00:50:32,962\nhappening with multithreading here. For example,\n加载一张很大的图片呢，会怎样. 比如，\n\n968\n00:50:32,964 --> 00:50:37,500\nwhat happens in Cassini if I click on the Cassini,\n在点击 Cassini 按钮时，Cassini 会怎样，\n\n969\n00:50:37,502 --> 00:50:40,236\nwhich is a kind of a small image, and\n这还是张小图，\n\n970\n00:50:40,238 --> 00:50:43,305\nthen I change my mind and click on Earth.\n如果我临时改变主意，点击了 Earch.\n\n971\n00:50:43,307 --> 00:50:48,377\nOkay, so Cassini, which is small, comes back, okay?\n现在，Cassini 这张小图加载完成，\n\n972\n00:50:48,379 --> 00:50:51,280\nThis code is gonna put Cassini on screen. But then the Earth\n那么 Cassini 就会渲染在界面上，这时候，Earth \n\n973\n00:50:51,282 --> 00:50:53,883\nis gonna come back and this code's gonna put the Earth on\n加载完了，Earth 就会覆盖在 Cassini 上，\n\n974\n00:50:53,885 --> 00:50:55,951\ntop of it, okay? So I'm gonna get this flashing thing,\n所以就会导致 Cassini 图片闪一下，\n\n975\n00:50:55,953 --> 00:50:58,788\nCassini, Earth. Or worse, if I clicked Earth first and\n接着显示 Earth. 更糟的是，如果我先点击的 Earth，\n\n976\n00:50:58,790 --> 00:51:01,057\nthen clicked Cassini, it would show Cassini and\n之后再点击 Cassini，万一先展示 Cassini，\n\n977\n00:51:01,059 --> 00:51:03,359\nthen later Earth would come in and it would be showing Earth,\n之后再展示 Earth，然后 Earth 就是最终渲染的图片，\n\n978\n00:51:03,361 --> 00:51:04,693\neven though I clicked on Cassini.\n即使我最后点击的是 Cassini.\n\n979\n00:51:04,695 --> 00:51:07,830\nOkay, do you see the problem, is that I'm firing off these\n能明白这个问题吗？我在不同的线程中，\n\n980\n00:51:07,832 --> 00:51:09,265\nnetwork things in other threads.\n发起的网络请求，\n\n981\n00:51:09,267 --> 00:51:11,767\nThey're coming back at different times. So\n他们的响应时间可能会不同.\n\n982\n00:51:11,769 --> 00:51:12,435\nreally I want to,\n所以，\n\n983\n00:51:12,437 --> 00:51:14,870\nIf I'm gonna be a good programmer here,\n如果我是一个优秀的开发者，\n\n984\n00:51:14,872 --> 00:51:16,172\nmultithreaded, I need to check and\n在多线程中，我需要检查响应的\n\n985\n00:51:16,174 --> 00:51:19,208\nmake sure that the URL that I'm fetching,\nURL，是否是我之前获取的那个，\n\n986\n00:51:19,210 --> 00:51:24,480\nthat's this URL right here, is still equal to the image URL\n即这个 URL，是否匹配这个 imageURL.\n\n987\n00:51:24,482 --> 00:51:29,618\nthat I ask for. Okay, then I'll do this. If it's not,\n如果匹配，才赋值. 如果不匹配，\n\n988\n00:51:29,620 --> 00:51:34,156\nthen maybe I could print something like ignored data\n那么就输出 ignore data，\n\n989\n00:51:34,158 --> 00:51:39,061\nreturned from URL, and then we'll put the URL in here,\nreturned from URL，然后将 url 拼在后面.\n\n990\n00:51:39,063 --> 00:51:43,232\nokay? And that needs self here, of course, cuz that's\n这里也需要加上 self，毕竟\n\n991\n00:51:43,234 --> 00:51:47,002\ninside this closure as well, all right? Everybody got that?\n这也是在闭包中. 都懂了吗？\n\n992\n00:51:47,004 --> 00:51:50,439\nSo let's go ahead and run, see if this works. So\n那我们来运行下，看看效果.\n\n993\n00:51:50,441 --> 00:51:54,110\nwhat we should have now is a very responsive UI, okay,\n所以，现在拿到的是一个丝滑的 UI，\n\n994\n00:51:54,112 --> 00:51:56,412\nall the time, no matter what we click on, so let's try it.\n整个程序都是，无论是点击哪个按钮，试试，\n\n995\n00:51:56,414 --> 00:51:59,482\nEarth, Cassini, see I'm able to click on different things.\nEarth，Cassini，看见了吗，都没有被阻塞.\n\n996\n00:51:59,484 --> 00:52:04,587\nI can still rotate, okay. Whoops, wrong way around. And,\n还可以进行旋转. 噢喔...旋转方式错了.\n\n997\n00:52:04,589 --> 00:52:09,125\nthe it's gonna pick whichever the last one that I asked for.\n无论我最后请求的是哪个，\n\n998\n00:52:09,127 --> 00:52:11,060\nIt's still fetching right here. It's gonna eventually,\n都会获取到争取的图片. 最终，\n\n999\n00:52:11,062 --> 00:52:17,633\nhopefully, get one. And maybe it's even easier to see this,\n都会获取到一张. 可能要等会才能请求完，\n\n1000\n00:52:17,635 --> 00:52:20,402\nmaybe. Let's stop this action, go look on our iPhone, cuz you\n停止这个程序，重新跑在 iPhone 上看看，\n\n1001\n00:52:20,404 --> 00:52:23,172\ncan really see it happening on iPhone because when we click\n因为这个过程在 iPhone 上更清晰，\n\n1002\n00:52:23,174 --> 00:52:26,142\non them, it actually segues and comes back.\n它会有视图的转场效果.\n\n1003\n00:52:26,144 --> 00:52:31,881\nSo watch this. Are we running here?\n来看看. 跑起来了吗？\n\n1004\n00:52:31,883 --> 00:52:37,887\nOops, no, we want iPhone.\n哦，不对，我们需要的是 iPhone.\n\n1005\n00:52:40,491 --> 00:52:43,759\nOkay, so we go back here. Now I click Cassini,\n好了，回到这个界面，点击 Cassini，\n\n1006\n00:52:43,761 --> 00:52:46,228\nit's loading it, but I can go back, okay.\n程序正在加载，这时我点击返回，\n\n1007\n00:52:46,230 --> 00:52:48,197\nWhile this is still loading, I can go back and\n但其实加载还在继续，\n\n1008\n00:52:48,199 --> 00:52:51,634\nchange my mind because my UI is highly responsive,\n我能临时改变主意，能点击返回，因为 UI 并未被阻塞，\n\n1009\n00:52:51,636 --> 00:52:53,636\neven though it's loading those things in the background.\n即使图片在后台加载.\n\n1010\n00:52:53,638 --> 00:52:56,705\nWhen they eventually arrive, it's gonna put them in the UI,\n当图片下载完成后，便会在 UI 上显示，\n\n1011\n00:52:56,707 --> 00:53:00,109\nokay. But while they're out there fetching I can do things\n但在下载过程中，\n\n1012\n00:53:00,111 --> 00:53:06,882\nlike go back in my navigation controller. Make sense,\n我可以做其他的操作，比如点击返回按钮等。看吧，\n\n1013\n00:53:06,884 --> 00:53:13,522\nsee that? >> [INAUDIBLE]\n没问题。[清不清楚]\n\n1014\n00:53:13,524 --> 00:53:14,056\n>> What happens, what?\n什么事？怎么？\n\n1015\n00:53:14,058 --> 00:53:14,857\n>> [INAUDIBLE] Image each time\n[听不清] 假设每次\n\n1016\n00:53:14,859 --> 00:53:17,560\nyou click out. >> So the question is, if I\n都快速返回。那么，每次返回后，\n\n1017\n00:53:17,562 --> 00:53:20,596\nclick out, and then click back in, does it reload the image?\n再点进去，会重新下载图片吗？\n\n1018\n00:53:20,598 --> 00:53:22,831\nAnd the answer is absolutely, because when I click out,\n答案显而易见，因为再返回后，\n\n1019\n00:53:22,833 --> 00:53:26,068\nit throws that MVC out of the heap. Okay, it's gone.\nMVC 的堆内存就被销毁了，也就不存在了。\n\n1020\n00:53:26,070 --> 00:53:28,103\nNow actually, that MVC is not gonna immediately leave\n但这次，MVC 却没有立即销毁，\n\n1021\n00:53:28,105 --> 00:53:30,773\nthe heap, cuz that closure that's doing the fetching is\n因为闭包还在执行下载，\n\n1022\n00:53:30,775 --> 00:53:33,108\nstill holding it in the heap. But once that fetch comes\n持有了该内存。当数据下载完成后，\n\n1023\n00:53:33,110 --> 00:53:36,779\nback, then it'll leave the heap and the image with it. So\n堆内存便销毁了，下载的图片也是。\n\n1024\n00:53:36,781 --> 00:53:40,583\nyeah, every time we're re-fetching, okay?\n所以，每次都是重新下载的，明白？\n\n1025\n00:53:41,552 --> 00:53:41,684\nSo see how we built this nice responsive UI right now, okay?\n这就是我们讲到的快速响应 UI。\n\n1026\n00:53:41,686 --> 00:53:45,221\nEverybody got that?\n大家都明白吗？\n\n1027\n00:53:45,223 --> 00:53:48,090\nEven though it's still taking a long time to fetch things,\n即使数据下载依然需要很长时间，\n\n1028\n00:53:48,092 --> 00:53:51,493\nwe can still navigate. Now, what's a little weird about\n但并不影响跳转。但是，UI 还有些\n\n1029\n00:53:51,495 --> 00:53:54,330\nthis UI, though, is that while it's fetching,\n不足，在数据下载时，\n\n1030\n00:53:54,332 --> 00:53:57,633\nlike when I'm here, it's not clear what's going on.\n比如这个界面，并不知道它在处理什么。\n\n1031\n00:53:57,635 --> 00:53:59,168\nIt looks like there's just no Earth image,\n这里好像并没有 Earth 的图片，\n\n1032\n00:53:59,170 --> 00:54:02,171\nI guess. I don't know, I guess not, I don't see it. Wouldn't\n我也不知道，可能是吧，什么都看不见。如果\n\n1033\n00:54:02,173 --> 00:54:04,840\nit be cool if we could give some feedback to the user?\n能给用户一个标识不是更好吗？\n\n1034\n00:54:04,842 --> 00:54:08,544\nHey, I'm working on it, okay, this image is big.\nHey，我正在努力加载呢，图片太大了。\n\n1035\n00:54:08,546 --> 00:54:09,545\nAll right, and we can do that.\n是的，我们可以处理。\n\n1036\n00:54:09,547 --> 00:54:12,414\nAnd the cool way to do that is with a little spinner, okay,\n可以在这里加个指示器，\n\n1037\n00:54:12,416 --> 00:54:15,651\na little animating. You see them all in apps little thing\n一个小动画。在很多 app 中都能看到\n\n1038\n00:54:15,653 --> 00:54:17,886\nthat spins around basically telling him yeah, yeah,\n指示器，告知系统收到了交互，\n\n1039\n00:54:17,888 --> 00:54:20,789\nI know, I'm working on it. So let's put a spinner in there.\n正在进行处理。那么，让我们在这里加上指示器吧。\n\n1040\n00:54:20,791 --> 00:54:24,059\nTurns out to be really easy to put, do spinners in iOS.\n在 iOS 中加指示器，真的非常简单。\n\n1041\n00:54:24,061 --> 00:54:26,395\nWe're just gonna go to the storyboard, okay.\n打开 storyboard，\n\n1042\n00:54:26,397 --> 00:54:30,232\nI'm gonna put the spinner here in this view. Now when I put\n将指示器加到这个 view 中。但注意，\n\n1043\n00:54:30,234 --> 00:54:32,167\nit in there, I'm gonna have to be very careful.\n加进去要非常小心。\n\n1044\n00:54:32,169 --> 00:54:32,501\nAnd this is a good chance for\n正好给大家\n\n1045\n00:54:32,503 --> 00:54:35,004\nme to show you more about the document outline. But\n详细演示下 document outline。\n\n1046\n00:54:35,006 --> 00:54:38,140\nwatch this, so I'm gonna go down here. The spinner is just\n看这里，滚到这里，有个可以直接\n\n1047\n00:54:38,142 --> 00:54:40,509\na thing you can drag out. You see it right here.\n进行拖拽的指示器。就是这个。\n\n1048\n00:54:40,511 --> 00:54:42,544\nNow watch what happens when I drag this out, okay, and\n将它拖到界面中，\n\n1049\n00:54:42,546 --> 00:54:46,215\nI try to use the blue lines to put it in the middle, drop it.\n蓝色辅助线可帮助居中，就扔到这。\n\n1050\n00:54:46,217 --> 00:54:48,784\nIt looks like, okay, that worked, that's nice.\n看起来不错，正是我们需要的。\n\n1051\n00:54:48,786 --> 00:54:50,786\nI can even go here and inspect it up here.\n还可以打开上面的 inspect，\n\n1052\n00:54:50,788 --> 00:54:54,123\nYou see, I can make a nice larger one. Maybe I'll even\n这里，可以选择更大的样式。也可以\n\n1053\n00:54:54,125 --> 00:54:58,594\nmake it blue instead of white. Let's have it hide itself\n将其改为蓝色。还可以设置\n\n1054\n00:54:58,596 --> 00:54:59,595\nwhen it stops animating.\n动画停止时，自动隐藏。\n\n1055\n00:54:59,597 --> 00:55:01,597\nWe can do all kinds of cool stuff here. But\n这里可以设置很多属性。\n\n1056\n00:55:01,599 --> 00:55:04,400\nactually something terrible has happened,\n但同时引发了一个问题，\n\n1057\n00:55:04,535 --> 00:55:06,869\nwhich is that when I dragged that thing out and\n在我将控件拖出来，\n\n1058\n00:55:06,871 --> 00:55:08,037\ndropped it in the middle there,\n然后放置到中间时，\n\n1059\n00:55:08,039 --> 00:55:11,173\nit made it a subview of the Scroll View, okay?\n这个控件变成了 Scroll View 的子视图。\n\n1060\n00:55:11,175 --> 00:55:14,877\nIn the interface builder when you drag a view out on top of\n在 interface builder 中，如果将一个控件拖到\n\n1061\n00:55:14,879 --> 00:55:16,578\nanother view, it makes it a subview of that.\n另一个控件上，那该控件就成了另一个的子视图。\n\n1062\n00:55:16,580 --> 00:55:19,148\nNow you can't really tell that here, but that's what this\n直接从这里不大看的出来，\n\n1063\n00:55:19,150 --> 00:55:21,483\nlittle guy over in the corner, the document outline,\n要点击角落里的这个小按钮，打开 document outline，\n\n1064\n00:55:21,485 --> 00:55:24,353\nis really great at. If you look at the document outline,\n这非常棒，在 document outline 中，\n\n1065\n00:55:24,355 --> 00:55:27,189\ndo you see how the activity indicator is indented\n能看到 activity indicator 在\n\n1066\n00:55:27,191 --> 00:55:30,893\nfrom the Scroll View? Okay, that means it's a subview\nScroll View 中吗？这就意味着，它成为了\n\n1067\n00:55:30,895 --> 00:55:34,496\nof the Scroll View. Now, if you don't want that, okay,\nScroll View 的子视图。如果你不想这样，\n\n1068\n00:55:34,498 --> 00:55:36,665\nno problem. You can just drag it up above.\n没问题，将它拖到上面。\n\n1069\n00:55:36,667 --> 00:55:39,568\nNow, it's not a subview of the Scroll View. Now, of course,\n现在，它就不再是 Scroll View 的子视图了。当然，\n\n1070\n00:55:39,570 --> 00:55:41,804\nit's not in the right order right now, because I want this\n这还不是正确的视图层级，因为我想要指示器\n\n1071\n00:55:41,806 --> 00:55:44,340\nthing to be in front of the Scroll View. So, I'm gonna put\n放在 Scroll View 前面。所以，要把\n\n1072\n00:55:44,342 --> 00:55:47,643\nthe Scroll View on top of it. So, now they're siblings, and\nScroll View 移到指示器上面。现在，它们就在一个层级了，并且\n\n1073\n00:55:47,645 --> 00:55:51,447\nthis one is in front, because remember, the subview is list,\n这个再上面，记住，子视图是链表，\n\n1074\n00:55:51,449 --> 00:55:52,681\nthe top ones are in the back.\n越在后面，层级越高。\n\n1075\n00:55:52,683 --> 00:55:54,650\nThe other ones go towards the front. So,\n升序排列。所以，\n\n1076\n00:55:54,652 --> 00:55:58,020\nnow we have this thing in the front, okay? Now,\n现在这个就在前面了。\n\n1077\n00:55:58,022 --> 00:56:00,522\nanother thing is, what if I wanna have,\n还有个问题，如果我想，\n\n1078\n00:56:00,524 --> 00:56:03,359\nconstraints on this to keep this in the middle?\n想要给该空间加约束，是它一直居中，该怎么办？\n\n1079\n00:56:03,361 --> 00:56:05,060\nWell, I have to be very careful here too,\n这一步同样需要仔细。\n\n1080\n00:56:05,062 --> 00:56:08,230\ncuz those dashed lines. We're referring to the scroll view.\n因为这里的约束，都是与 scroll view 关联的。 \n\n1081\n00:56:08,232 --> 00:56:11,033\nSo if I tried to do reset to suggested constraints here,\n所以，先要重置默认的约束，\n\n1082\n00:56:11,035 --> 00:56:13,869\nI'm gonna get constraints that constrain the activity\n会发现现在 activity indicator\n\n1083\n00:56:13,871 --> 00:56:16,205\nindicator to the scroll view. I don't want that.\n的约束都是基于 scroll view 的，我可不想这样。\n\n1084\n00:56:16,207 --> 00:56:19,575\nI want the activity indicator to be in the middle of its\n我希望 activity indicator 相对其父视图\n\n1085\n00:56:19,577 --> 00:56:19,842\nsuperview.\n居中。\n\n1086\n00:56:19,844 --> 00:56:23,612\nAnd watch this, you can do control drag in the document\n看仔细了。你可以在 document outline 中，\n\n1087\n00:56:23,614 --> 00:56:26,782\noutline. So I'm gonna control drag from my activity\n按住 control。从 activity indicator 这里，\n\n1088\n00:56:26,784 --> 00:56:30,919\nindicator to its superview in the document outline,\n按住 control，拖到 document outline 中的父视图上，\n\n1089\n00:56:30,921 --> 00:56:33,255\nnot over here, but in the document outline.\n不是这，是在 document outline 中。\n\n1090\n00:56:33,257 --> 00:56:35,758\nAnd when I let go, I can do things like, yeah,\n松开鼠标，可以看到这个，是的，\n\n1091\n00:56:35,760 --> 00:56:41,764\nplease center it vertically and horizontally in yourself.\n请在水平与竖直方向都居中。\n\n1092\n00:56:41,766 --> 00:56:46,568\nOkay? So now this thing is centered and middle. Okay?\n那么，现在就居中了。\n\n1093\n00:56:46,570 --> 00:56:50,939\nSo, now we've got the spinner, how do we do anything with it?\n至此指示器就创建好了，那应该怎么处理逻辑呢？\n\n1094\n00:56:50,941 --> 00:56:51,440\nWell, we need an outlet to it.\n现在需要一个它的 outlet。\n\n1095\n00:56:51,442 --> 00:56:55,511\nSo, I'm going to bring out my code over here, okay?\n把代码显示出来，\n\n1096\n00:56:55,513 --> 00:56:56,712\nDo it automatic.\n自动关联文件。\n\n1097\n00:56:56,714 --> 00:56:59,681\nGot our image view controller here, let's give it to this,\n这是 image view controller。关掉这个，\n\n1098\n00:56:59,683 --> 00:57:02,851\ngive it to that, give it some room. Okay so\n关掉这个，腾点空间出来。好的，\n\n\n1099\n00:57:02,853 --> 00:57:05,721\nI'm just going to create an outlet from this little\n将指示器从这拖到这，\n\n1100\n00:57:05,723 --> 00:57:10,125\nspinner right here, over here. See it make sure that it's\n创建 outlet。注意这里的类型\n\n1101\n00:57:10,127 --> 00:57:13,796\ntype is activity indicator view not something else, and\n是 activity indicator，而不是别的。\n\n1102\n00:57:13,798 --> 00:57:14,730\nI'm just going to call it spinner,\n名字就叫 spinner 吧，\n\n1103\n00:57:14,732 --> 00:57:17,499\nI like spinner as my name. And it's just an outlet,\n我喜欢 spinner 这个名字，这是个 outlet，\n\n1104\n00:57:17,501 --> 00:57:20,769\nit's a normal outlet just like our scroll view or anything\n非常普通的 outlet，和 scroll view 或其他 outlet\n\n1105\n00:57:20,771 --> 00:57:23,272\nelse is an outlet. Okay just like your display was in your\n没区别。就像计算器能显示一样，\n\n1106\n00:57:23,274 --> 00:57:27,643\ncalculator there's nothing particularly special about it.\n没什么特别的。\n\n1107\n00:57:27,645 --> 00:57:31,413\nSo now that we have this nice spinner right here,\n现在，我们拿到了指示器变量，\n\n1108\n00:57:31,415 --> 00:57:34,450\nwe just need to turn it on and turn it off. So where are we\n只需要控制它的开始与结束。那什么时候开始呢？\n\n1109\n00:57:34,452 --> 00:57:37,352\ngonna turn it on? Well, I'm gonna turn it on right before\n我觉得它应该在其他线程开始\n\n1110\n00:57:37,354 --> 00:57:41,023\nI start doing something on that other thread, okay. So\n处理事情的时候开始。\n\n1111\n00:57:41,025 --> 00:57:44,493\nright here when I dispatch onto this other thread to go\n就是这里，在将处理 NSData 的 block 派发到\n\n1112\n00:57:44,495 --> 00:57:47,629\ndo this NSData, which is gonna block, I'm just gonna say\n其他线程的时候，让\n\n1113\n00:57:47,631 --> 00:57:53,435\nspinner startAnimating. And I'm gonna be even trickier and\nspinner startAnimating。我准备在这里增加点难度，\n\n1114\n00:57:53,437 --> 00:57:56,972\ngo spinner?.startAnimating just in case\n改为 spinner?startAnimating，防止\n\n1115\n00:57:56,974 --> 00:58:00,776\nI'm fetching my image like as a result of prepare for\n在 prepare for segue 的时候\n\n1116\n00:58:00,778 --> 00:58:03,846\nsegue, okay, because there my outlets aren't set.\n调用该方法获取图片，而这个时候，outlet 还未创建。\n\n1117\n00:58:03,848 --> 00:58:05,747\nSo even if my app spinner's not set,\n这样的话，在 spinner 还没创建时，\n\n1118\n00:58:05,749 --> 00:58:09,751\nI'll just do nothing. Now where do I wanna turn it off?\n没有任何响应就行。那应该在何时停止呢？\n\n1119\n00:58:09,753 --> 00:58:11,954\nIts actually two places that you can turn this off.\n应该有两处地方需要停止。\n\n1120\n00:58:11,956 --> 00:58:16,892\nOne good place might be down here when your image gets set.\n一处是在图片加载完成后。\n\n1121\n00:58:16,894 --> 00:58:18,994\nOkay? Cuz if someone sets your image,\n在图片加载完成后，\n\n1122\n00:58:18,996 --> 00:58:23,198\nthen you don't need to be spending anymore.\nspinner 就没必要显示了。\n\n1123\n00:58:23,367 --> 00:58:25,434\nBy definition, you're showing the image.\n理论上，这里图片都已经展示了。\n\n1124\n00:58:25,436 --> 00:58:29,004\nSo, it will make no sense to be spinning such a good place.\n所以，spinner 已经完成使命了。\n\n1125\n00:58:29,006 --> 00:58:31,106\nGot to be a little careful though here because,\n另外一个地方需要特别小心，\n\n1126\n00:58:31,108 --> 00:58:34,109\nwhat happens when we get in here, okay?\n这里会出现什么情况呢，\n\n1127\n00:58:34,111 --> 00:58:36,378\nAnd you get to the URL here, and\n这里是获得 URL，\n\n1128\n00:58:36,380 --> 00:58:38,647\nthe image data wasn't able to be found, so\n如果 URL 未找到图片数据，\n\n1129\n00:58:38,649 --> 00:58:41,583\nyou never call set image, so it's never going to stop.\n图片就无法创建，那指示器就一直没停止。\n\n1130\n00:58:41,585 --> 00:58:45,387\nSo you probably want to put in else spinner stop animating\n所以这里也需要加上 spinner 停止的代码。\n\n1131\n00:58:45,389 --> 00:58:48,490\nhere as well. Okay so this is gonna stop the spinner in\n所以， spinner 就会在\n\n1132\n00:58:48,492 --> 00:58:52,094\nthe case where it went off to the Internet to get something,\n无网络，或者未找到数据的情况下，\n\n1133\n00:58:52,096 --> 00:58:55,030\nand it couldn't find it. Okay, eh,\n停止。哦，\n\n1134\n00:58:55,032 --> 00:59:00,969\nlittle tricky. Okay, so let's see how that works.\n小失误。好，运行看看效果。\n\n1135\n00:59:06,644 --> 00:59:08,810\nAlright, here we go, let's try Earth, there it is,\n跑起来了，打开 Earth，对，没错，\n\n1136\n00:59:08,812 --> 00:59:11,513\nit's spinning, and we can go back, let's try Cassini, it's\n有指示器了，点击返回，打开 Cassini，也有\n\n1137\n00:59:11,515 --> 00:59:15,484\nspinning. Now when Cassini appears it stops spinning, and\n指示器。在 Cassini 加载完后，指示器停止，\n\n1138\n00:59:15,486 --> 00:59:19,354\nso it hides because we had, we set this switch over here\n并且自动消失，因为我们之前字 inspect 中，\n\n1139\n00:59:19,356 --> 00:59:23,158\non this one we inspected it called hides when stopped,\n将它设置为停止就自动隐藏，\n\n1140\n00:59:23,160 --> 00:59:28,196\nright. And so since it hides when stopped, it's not here\n没问题。所以，在停止后，指示器\n\n1141\n00:59:28,198 --> 00:59:32,734\nanymore okay. [INAUDIBLE] Saturn,\n就不见了。[听不清] Saturn，\n\n1142\n00:59:32,736 --> 00:59:38,974\nspins okay then we can rotate. Big image, taking a long time.\n旋转屏幕。是个大图，需要更长的时间。\n\n1143\n00:59:38,976 --> 00:59:43,312\nThere it is, okay? So see how we turn this into an app, it's\n完成，没问题。这就是在 app 中的运用，\n\n1144\n00:59:43,314 --> 00:59:45,948\nreally responsive and really nice and it's being as fast as\n非常友好，非常漂亮，说多快有多快。\n\n1145\n00:59:45,950 --> 00:59:47,983\nit can. It's getting those images as fast as it can,\n图片现在说多快有多快，\n\n1146\n00:59:47,985 --> 00:59:51,153\nbut from the user standpoint, it's very responsive.\n从用户的角度来说，也非常友好。\n\n1147\n00:59:51,155 --> 00:59:53,288\nYou really wanna go with that way.\n大家以后也应该这样做。\n\n1148\n00:59:53,290 --> 00:59:57,326\nOkay, so now I'm gonna show two unrelated to this, okay?\n接下来，我将提到两个不相关的东西。\n\n1149\n00:59:57,328 --> 01:00:01,697\nBut did you've asked about in Piazza. One is notice that\n大家对 Piazza 有以为吗。在运行的时候，\n\n1150\n01:00:01,699 --> 01:00:07,235\nwhen we run this, let's run again, watch what happens.\n重新运行下，看看出了什么问题。\n\n1151\n01:00:07,972 --> 01:00:14,009\nWhen we run, we get an empty image view controller\n在运行起来时，image view controller 是空的，\n\n1152\n01:00:14,011 --> 01:00:17,012\nwhich really doesn't make any sense. What we'd\n而这不应该出现才对。我们想要的是，\n\n1153\n01:00:17,014 --> 01:00:19,848\nreally want it to, when we first run and this is empty,\n在第一次运行的时候，这是空的，\n\n1154\n01:00:19,850 --> 01:00:23,251\nwe want it to come up showing this view controller. So\n而我们想要的是展示这个 controller。\n\n1155\n01:00:23,253 --> 01:00:24,152\nthis is like with your calculator,\n这和之前的计算器项目类似，\n\n1156\n01:00:24,154 --> 01:00:25,921\nyou don't want it to come up showing empty graph.\n我们不想展示空的界面。\n\n1157\n01:00:25,923 --> 01:00:28,857\nYou want it to come up showing the calculator because\n空界面什么用都没有，应该展示\n\n1158\n01:00:28,859 --> 01:00:29,391\nthe empty graph is useless,\n计算器界面才对。\n\n1159\n01:00:29,393 --> 01:00:32,394\nit just forces them to do that back thing right here for\n这个还必须要手动返回，而且\n\n1160\n01:00:32,396 --> 01:00:35,931\nno good reason. Okay, so how do we do that, okay this is\n还不知道为什么要这样。那么，该怎么处理呢，\n\n1161\n01:00:35,933 --> 01:00:38,367\nanother case where we need to use delegation.\n这是另个需要用到 delegation 的原因。\n\n1162\n01:00:38,369 --> 01:00:43,105\nIn this case it's the split view delegate. Okay, split\n这里要用到的是 split view delegate。split\n\n1163\n01:00:43,107 --> 01:00:45,407\nview controller's delegate. So what does this code look like?\nview controller 的 delegate。那代码该怎么写呢？\n\n1164\n01:00:45,409 --> 01:00:48,143\nI'm gonna put this in Cassini, view controller right here.\n我准备把代码放在 Cassiini view controller 的这个地方。\n\n1165\n01:00:48,145 --> 01:00:51,113\nThe first thing I need to do is I need to make the Cassini\n首先，我准备，我准备将 Cassini view controller 设为\n\n1166\n01:00:51,115 --> 01:00:55,150\nview controller be its own split view's delegate.\nsplit view 的 delegate。\n\n1167\n01:00:55,152 --> 01:00:57,052\nIn other words, it needs to be the delegate of\n也就是说，它需要成为\n\n1168\n01:00:57,054 --> 01:00:57,319\nthe split view it's in.\nsplit view 的代理。\n\n1169\n01:00:57,321 --> 01:01:01,156\nSo I'm gonna do this in viewDidLoad. Okay sometimes\n我准备在 viewDidLoad 里面处理。\n\n1170\n01:01:01,158 --> 01:01:03,525\nviewDidLoad is not quite early enough to do things for\n在 viewDidLoad 中，获取 split view 才\n\n1171\n01:01:03,527 --> 01:01:07,462\nsplit views. We might have to do it in a wait for even. But\n不算太早。别的方法可能还要判断时机，而\n\n1172\n01:01:07,464 --> 01:01:10,165\nthis will work in viewDidLoad. And I'm just going to set\nviewDidLoad 就不用。我准备在这里设置\n\n1173\n01:01:10,167 --> 01:01:14,136\nmy split view controllers remember MVC knows the split\nsplit view controller，每个 MVC 能拿到 split\n\n1174\n01:01:14,138 --> 01:01:16,872\nview controller its in. Or the navigation controller its in,\nview controller 变量。Navigation controller 也可以，\n\n1175\n01:01:16,874 --> 01:01:18,106\nor the tab bar controller its in. So\ntab bar controller 也行。\n\n1176\n01:01:18,108 --> 01:01:22,611\nSplitViewController says what it is, might be nil, okay? But\n而 splitViewController 也可能为空，\n\n1177\n01:01:22,613 --> 01:01:25,514\nif it's not I'm gonna set its delegate to be myself.\n如果不为空，则设置 self 为 delegate。\n\n1178\n01:01:25,516 --> 01:01:29,284\nOf course as soon as I do this I'm getting an error because\n当然，这样处理会出现错误，\n\n1179\n01:01:29,286 --> 01:01:32,954\nI didn't say that I was a UI SplitViewController delegate.\n因为 self 还未遵循 UISplitViewControllerDelegate。\n\n1180\n01:01:32,956 --> 01:01:33,822\nSo I need to go up here and\n滚动到顶部，\n\n1181\n01:01:33,824 --> 01:01:37,793\nsay that I'm a UI SplitViewController delegate.\n声明 self 遵循 UISplitViewControllerDelegate。\n\n1182\n01:01:39,096 --> 01:01:43,365\nAll right that satisfies that error. All is good. Now which\n好的，错误解决了。没问题，那么，\n\n1183\n01:01:43,367 --> 01:01:46,668\nsplit view controller method am I going to implement?\n应该实现 split view controller 的哪个方法呢？\n\n1184\n01:01:46,670 --> 01:01:49,538\nOkay hold on your chairs for this one, okay\n抓紧椅子，别被吓到了。\n\n1185\n01:01:49,540 --> 01:01:52,007\nby the way again on the split view controller delegate so\n因为已经遵循 split view controller delegate，所以\n\n1186\n01:01:52,009 --> 01:01:54,142\nI can just start typing split view and you can see it\n键入 split view 就可以索引出方法，看吧，\n\n1187\n01:01:54,144 --> 01:01:56,678\nshows me all the split view controller delegate methods.\n这些，全都是 split view controller delegate 的方法。\n\n1188\n01:01:56,680 --> 01:01:59,781\nThere's quite a few. Okay about a dozen of them.\n有很多方法，大概十多个。\n\n1189\n01:01:59,783 --> 01:02:02,918\nAnd the one I want is the one that controls\n而我需要的那个，\n\n1190\n01:02:02,920 --> 01:02:07,222\nthe collapsing of the detail on top of the master.\n是可以控制 detail 压缩的方法。\n\n1191\n01:02:07,224 --> 01:02:10,058\nBecause I don't want it to collapse that detail on top of\n因为在 detail 没有数据时，不需要将\n\n1192\n01:02:10,060 --> 01:02:13,595\nthe master if the detail is empty, okay?\ndetail 显示出来。\n\n1193\n01:02:13,597 --> 01:02:14,429\nIf it doesn't have an image in there,\n如果没有图片，\n\n1194\n01:02:14,431 --> 01:02:17,666\nI don't want it to do that. So this thing that controls that\n就不需要显示。这个方法叫做，\n\n1195\n01:02:17,668 --> 01:02:22,738\nit's called, called secondary view controller,\n叫做 secondary view controller，\n\n1196\n01:02:22,740 --> 01:02:26,708\non to primary view controller. Okay, called\non to primary view controller。\n\n1197\n01:02:26,710 --> 01:02:29,511\nsecondary view controller, on to primary view controller.\nsecondary view controller，on to primary view controller。\n\n1198\n01:02:29,513 --> 01:02:32,748\nNow, notice it returns a Bool, this Bool\n注意，返回值为 Bool，如果\n\n1199\n01:02:32,750 --> 01:02:35,650\nyou return true if you took care of this.\n返回 true，就是自行处理。\n\n1200\n01:02:35,652 --> 01:02:40,589\nReturn false if you want the system to do the collapse.\n如果返回 false，表示交由系统处理。\n\n1201\n01:02:40,591 --> 01:02:43,492\nOkay, so this is a way where the delegate can do this\n那么，这个代理方法就是用来处理\n\n1202\n01:02:43,494 --> 01:02:44,726\ncollapse if it wants, or not, and\n是否需要压缩的，\n\n1203\n01:02:44,728 --> 01:02:47,629\nit just lets the split view know whether it did it or not.\n而且，只是告知 split view 是否需要。\n\n1204\n01:02:47,631 --> 01:02:50,232\nSo that's what the bool is, let it know when it did it.\n这就是这个 bool 值的作用，用于告知 split 的。\n\n1205\n01:02:50,234 --> 01:02:53,568\nSo, this is actually quite simple right here.\n那这样就非常简单了。\n\n1206\n01:02:53,570 --> 01:02:56,738\nWe just want to get the image view controller,\n我么只想获得 image view controller，\n\n1207\n01:02:56,740 --> 01:03:00,675\nokay? Well first of all let's make sure that the primary\n首先判断 primary view controller\n\n1208\n01:03:00,677 --> 01:03:05,881\nview controller, content view controller, is ourself.\n的 content view controller 是 self。\n\n1209\n01:03:05,883 --> 01:03:08,083\nNow it should be, because we're setting ourselves\n这个应该是没问题的，因为我们之前将 self\n\n1210\n01:03:08,085 --> 01:03:09,718\nas our own split view delegate, so we should be\n设为了 split view controller 的 delegate，所以\n\n1211\n01:03:09,720 --> 01:03:13,188\nthe primary view controllers, the masters content Okay?\nself 应该是 primary view controller 的 master content。\n\n1212\n01:03:13,190 --> 01:03:16,658\nSo we showed you that, that should not be a problem. But\n所以写的这个判断，是能成功的。\n\n1213\n01:03:16,660 --> 01:03:20,896\nnow I'm gonna say, on top of that, if I can let ivc =\n接下来，在括号中写，if let ivc = \n\n1214\n01:03:20,898 --> 01:03:24,633\nthe secondaryViewController, that's the detail.\nsecondaryViewController，即 detail 页面，\n\n1215\n01:03:24,635 --> 01:03:30,238\nIt contentViewController as an ImageViewController. Okay? So,\n的 contentViewController，并强转为 ImageViewController。也就是说，\n\n1216\n01:03:30,240 --> 01:03:36,011\nif have a ImageViewController as my detail, and\n如果 detail 是 ImageViewController，然后\n\n1217\n01:03:36,013 --> 01:03:39,281\nwhere, everyone know about where, right? You did your\nwhere，where 大家应该都知道吧？如果做了\n\n1218\n01:03:39,283 --> 01:03:41,783\nreading assignments, you know about where. Where is\n预习，那应该是没问题的。 Where 是\n\n1219\n01:03:41,785 --> 01:03:44,686\nan additional clause that you can add onto an if, okay?\n可以加载 if 之后的从句。\n\n1220\n01:03:44,688 --> 01:03:47,856\nSo I'm gonna say where the image view controllers\n继续写，wherer image view controller\n\n1221\n01:03:47,858 --> 01:03:52,828\nimage URL is nil. So if I have an image view controller as\n的 image URL 是 nil。也就是说，如果 image view controller 是\n\n1222\n01:03:52,830 --> 01:03:58,166\nmy detail and it's, image url is nil, then it's empty.\ndetail，并且图片的 url 为 nil，那界面就是空的。\n\n1223\n01:03:58,168 --> 01:03:59,968\nThere's nothing in there. There's no Saturn or\n什么内容都没有，没有 Satrun 图片或\n\n1224\n01:03:59,970 --> 01:04:03,638\nanything else. So in this case I'm going to return true,\n别的内容。这种情况下，就返回 true，\n\n1225\n01:04:03,640 --> 01:04:05,874\nwhich is me telling the system, yeah,\n即告知系统，\n\n1226\n01:04:05,876 --> 01:04:08,710\nI took care of that. Okay, I put that detail, I collapsed\n我自己处理。我自己设置 detail，自己对\n\n1227\n01:04:08,712 --> 01:04:11,079\nthat detail on top of the master, don't worry about it.\nmaster 上的 detail 进行处理，你不用管。\n\n1228\n01:04:11,081 --> 01:04:13,982\nNow I didn't, didn't actually do anything, that's good,\n而在这里，我什么都没做，这很好，\n\n1229\n01:04:13,984 --> 01:04:16,017\ncuz that's what I want. I don't want that\n我就想这样。因为我并不想\n\n1230\n01:04:16,019 --> 01:04:18,753\ndetail to be collapsed on top of the master if the thing is\n在内容是空时，master 顶部的 detail 被压缩。\n\n1231\n01:04:18,755 --> 01:04:22,357\nnil. All right, so I just kind of lied to the system and told\n所以，这里是在骗系统，说\n\n1232\n01:04:22,359 --> 01:04:26,328\nthem I handled it when in fact I didn't. Okay, otherwise,\n我要自行处理，但实际上，我什么都没做。好的，除此之外，\n\n1233\n01:04:26,330 --> 01:04:29,431\nwe're just gonna let the system do whatever it does,\n别的情况就需要系统处理了。\n\n1234\n01:04:29,433 --> 01:04:33,902\nokay. Return false, we did not handle this so you handle it.\n返回 false，表示我自己不处理，你来处理吧。\n\n1235\n01:04:33,904 --> 01:04:41,543\nOkay, so let's see if that works. Okay, so here it is,\n接下来，看看效果吧。好的，\n\n1236\n01:04:41,545 --> 01:04:46,615\nlook at that. It came up, didn't show me a blank thing,\n你看，没有再展示空白的页面了，\n\n1237\n01:04:46,617 --> 01:04:51,319\nso it worked. Now let's click on one of these. Woop, okay,\n成功了。点击其中一个，\n\n1238\n01:04:51,321 --> 01:04:51,486\nit worked. So\n没问题。\n\n1239\n01:04:51,488 --> 01:04:54,789\nit collapsed the secondary on top of the primary when I\n能在我需要的时候，将 primary 顶部的 secondary \n\n1240\n01:04:54,791 --> 01:04:58,026\nwanted it too, okay? But if it came up nil,\n压缩。当回来为空的时候，\n\n1241\n01:04:58,028 --> 01:05:01,229\nthen it didn't show it. Everyone understand that? I\n就不会再显示。都能听懂吗？\n\n1242\n01:05:01,231 --> 01:05:03,899\nknow it seems a little, a lot of long words in here [LAUGH]\n我知道这个方法很长 「笑」\n\n1243\n01:05:03,901 --> 01:05:06,501\nlike primary view controller, secondary view controller, but\n又是 primary view controller，又是 secondary view controller 的，\n\n1244\n01:05:06,503 --> 01:05:09,871\nthis is just master in detail, that's all this is. And\n其实就是 master 和 detail，没什么奇怪的。\n\n1245\n01:05:09,873 --> 01:05:12,040\nwe're just checking where the image URL's nil and just\n而这里是检查 image 的 URL 是否为空，然后\n\n1246\n01:05:12,042 --> 01:05:14,809\nreturning that, we handled it when we really didn't handle\n返回这个，理论上需要我们处理，但实际没有，\n\n1247\n01:05:14,811 --> 01:05:18,013\nit because we don't want it handled. Okay. One other\n因为这本身就不需要处理什么。另外一个问题是，\n\n1248\n01:05:18,015 --> 01:05:24,252\nthing I want to show you is reusing the detail in iPad.\n在 iPad 上重用 detail 的情况。\n\n1249\n01:05:25,856 --> 01:05:31,326\nLook at iPad. And we have the master detail right here.\n看看 iPad。这是 master detail。\n\n1250\n01:05:31,328 --> 01:05:35,363\nEvery time we click on this thing, it's creating a new MVC\n每次点击的时候，会创建新的 MVC。\n\n1251\n01:05:35,365 --> 01:05:39,334\nhere. Okay? Creating a brand new MVC. And if there,\n创建一个全新的 MVC。但对此，\n\n1252\n01:05:39,336 --> 01:05:41,102\nthere's really no reason for that. Okay?\n其实完全没必要。\n\n1253\n01:05:41,104 --> 01:05:45,373\nWe could absolutely just reuse this MVC right here.\n完全可以对 MVC 进行重用。\n\n1254\n01:05:45,375 --> 01:05:47,842\nOkay, we don't have to create a new one every time.\n我们不需要每次都创建新的。\n\n1255\n01:05:47,844 --> 01:05:50,979\nSo, how would we do that? How would we reuse this?\n那么，该怎么办呢？如何重用呢？\n\n1256\n01:05:50,981 --> 01:05:54,182\nWell, if we're gonna reuse this, we can't use\n如果想要重用这个，就不能用\n\n1257\n01:05:54,184 --> 01:05:57,385\nsegues because segues always create a new MVC.\nsegue，因为 segue 每次都会创建新的 MVC。\n\n1258\n01:05:57,387 --> 01:05:59,254\nThat's what segues do, they create a new MVC.\n这就是 segue 在做的事情，创建新的 MVC。\n\n1259\n01:05:59,256 --> 01:06:02,390\nSo, we can't use segues, okay, to do that in that case. So,\n所以，这种情况下，我们不能用 segue。那么，\n\n1260\n01:06:02,392 --> 01:06:06,761\nlets go back to our Cassini right here. Our, storyboard.\n回到 Cassini 项目。看到 storyboard。\n\n1261\n01:06:06,763 --> 01:06:11,800\nAnd we're not going to use these segues over here. Okay,\n我们不再使用这里的 segue。\n\n1262\n01:06:11,802 --> 01:06:14,069\nsee these three segues? I'm gonna get rid of them.\n看到这三个 segue 了吗？我准备把它们去掉。\n\n1263\n01:06:14,071 --> 01:06:16,671\nGet rid of, oops, not that. Click here,\n都去掉，哦，点错了。点这个，\n\n1264\n01:06:16,673 --> 01:06:16,738\nget rid of that one,\n去掉它。\n\n1265\n01:06:16,740 --> 01:06:18,940\nI'm gonna get rid of that one, I'm gonna get rid of that one.\n去掉这个，去掉这个。\n\n1266\n01:06:18,942 --> 01:06:20,442\nCuz I cannot segue from these buttons or\n我不打算将 button 与 segue 关联了，\n\n1267\n01:06:20,444 --> 01:06:24,446\nit will constantly create a new one of these details.\n因为它每次都会创建新的 detail。\n\n1268\n01:06:24,448 --> 01:06:26,781\nInstead, what I'm gonna do is to use target action.\n而我准备用 target-action 来实现。\n\n1269\n01:06:26,783 --> 01:06:30,952\nSo I'm just gonna bring up my code here, some space,\n接着，打开 diamante，腾点空间，\n\n1270\n01:06:30,954 --> 01:06:34,289\nall right, and I'm gonna do a target action message from\n好的，我会给每个按钮都添加\n\n1271\n01:06:34,291 --> 01:06:38,626\neach of these that reuses the detail to show the image.\ntarget-action，用于重用显示 image 的 detial。\n\n1272\n01:06:38,628 --> 01:06:41,529\nSo let's do that. Let's just go Ctrl+drag here.\n那么，开始吧。按住 Ctrl 并拖到这里，\n\n1273\n01:06:41,531 --> 01:06:44,332\nI'm gonna call this show image, that's a good name for\n名字就叫 showimage，作为事件的名字\n\n1274\n01:06:44,334 --> 01:06:47,602\nthis action right here, and I'm gonna have UI button\n还挺合适， 事件的 sender 是\n\n1275\n01:06:47,604 --> 01:06:50,505\nbe the sender, cuz I'm gonna know which one to show because\nUIButton，因为我需要通过按钮\n\n1276\n01:06:50,507 --> 01:06:52,640\nI'm gonna look at the sender. Okay. So,\n判断应该显示哪一个。Okay，\n\n1277\n01:06:52,642 --> 01:06:54,909\nI got show image right here. So, let's go ahead and\nshowimage 方法创建好了。接下来，\n\n1278\n01:06:54,911 --> 01:06:56,978\nput the code here. So, show image is a lot like,\n就是填充代码了。showimage 的处理，\n\n1279\n01:06:56,980 --> 01:07:00,448\nlooks a lot like prepare for seg, segue. We can only do\n和 prepareforsegue 中的代码类似。只能在\n\n1280\n01:07:00,450 --> 01:07:04,119\nthis if we're in a split view. Right, we can only do the show\nsplit view 中这样做，这样来\n\n1281\n01:07:04,121 --> 01:07:07,555\nimage thing here, this trick, if we are in a split view,\n显示 image，如果在 split view 中，\n\n1282\n01:07:07,557 --> 01:07:11,192\nsorry, let me, just so we can see what's going on here.\n啊，不好意思，这里可以看到。\n\n1283\n01:07:11,194 --> 01:07:14,129\nAll right. Okay, we can only do a split view so\n因为只能在 split view 中使用，\n\n1284\n01:07:14,131 --> 01:07:17,098\nI'm gonna first check to see that. I'm gonna say,\n所以首先判断，\n\n1285\n01:07:17,100 --> 01:07:21,836\nif I can let the ivc = splitViewControllers,\nif let ivc = splitViewController，\n\n1286\n01:07:21,838 --> 01:07:24,773\nif I have one, view Controller,\n如果存在，viewcontrollers，\n\n1287\n01:07:24,775 --> 01:07:29,110\ncontroller[1]. We know that's the detail, right.\ncontroller[1]，我们知道这个是 detail，\n\n1288\n01:07:29,112 --> 01:07:30,478\nAnd actually I don't wanna use sub one\n但这里我不想用下标取值，\n\n1289\n01:07:30,480 --> 01:07:33,248\nbecause if for some reason my split view controller\n如果某些情况下，split view controller\n\n1290\n01:07:33,250 --> 01:07:36,217\ndoesn't have a detail, then view controllers only have one\n没有 detail，那么 viewcontrollers 就只有\n\n1291\n01:07:36,219 --> 01:07:39,721\nthing so I'm actually gonna use ViewController.last.\n一个值，所以我准备用 viewcontroller.last 取值。\n\n1292\n01:07:39,723 --> 01:07:43,258\nOkay, because last returns nil if there's no such thing.\n如果 last 返回空，则说明什么都没有。\n\n1293\n01:07:43,260 --> 01:07:46,227\nOkay, and then I'm gonna grab the content view controller as\n接下来，判断 content view controller\n\n1294\n01:07:46,229 --> 01:07:49,264\nalways and I'm gonna check to see if that's an image view\n是否是 image view controller，这和之前差不多，\n\n1295\n01:07:49,266 --> 01:07:50,765\ncontroller. So in other words,\n也就是说，\n\n1296\n01:07:50,767 --> 01:07:53,134\nif I can get my detail as an image view controller,\n如果 detail 是 image view controller，\n\n1297\n01:07:53,136 --> 01:07:56,271\nthen I'm basically gonna do this right here,\n就可以走这段逻辑，拷贝过来，\n\n1298\n01:07:56,273 --> 01:07:59,507\nin here, but here I don't have to say sender as UI button\n这里并不需要将 sender 转换为 UIButton，\n\n1299\n01:07:59,509 --> 01:08:00,008\nbecause the sender is\n因为 sender 本来就是\n\n1300\n01:08:00,010 --> 01:08:02,177\na UI button so I can just say sender and\nUIButton，而且 sender 在这里\n\n1301\n01:08:02,179 --> 01:08:06,614\nit's never gonna be nil there. Okay? And do that. So see,\n也不可能为空。Okay？就这样。\n\n1302\n01:08:06,616 --> 01:08:09,384\nsee what's going on here? So no segueing,\n这里在干嘛呢？没有了 segue，\n\n1303\n01:08:09,386 --> 01:08:16,825\nI'm not doing any segueing. So when I go over here, Okay,\n不再需要 segue 了。继续运行，\n\n1304\n01:08:16,827 --> 01:08:20,762\nand I pick something, like Cassini, or Earth, okay,\n点击按钮，比如 Cassini，或者 Earch，\n\n1305\n01:08:20,764 --> 01:08:25,767\nwe'll say. It loads it up. Actually,\n就可以看到，正在加载。实际上，\n\n1306\n01:08:25,769 --> 01:08:28,236\nwe got to do one other thing, sorry. Back here, in our\n我们忘了点东西，不好意思，回到程序，\n\n1307\n01:08:28,238 --> 01:08:31,673\nstoryboard, let's wire up all these buttons to do that.\n在 storyboard 中，应该给所有 button 添加事件。\n\n1308\n01:08:31,675 --> 01:08:35,977\n[LAUGH] Okay, we only wired up earth to do this show image so\n[笑] Okay，现在只是给 earth 关联了 showimage，所以，\n\n1309\n01:08:35,979 --> 01:08:39,080\nlet's do that. Let's go to automatic.\n来处理其余的，选择 automatic。\n\n1310\n01:08:39,583 --> 01:08:40,415\nAll right, so let's control,\n关联这个，\n\n1311\n01:08:40,417 --> 01:08:42,750\nso this one here and let's wire up this one here. Okay,\n关联这个。Okay，\n\n1312\n01:08:42,752 --> 01:08:46,354\nso now all three buttons are sending that same show image.\n现在三个按钮都和同一个 showimage 关联了。\n\n1313\n01:08:46,356 --> 01:08:49,057\nSo now we can actually demonstrate this. So let's\n这次演示应该没问题。点击\n\n1314\n01:08:49,059 --> 01:08:53,094\ndo Cassini. Here it is showing this and once this appears, or\nCassini，会在这里展示，在展示出来后，\n\n1315\n01:08:53,096 --> 01:08:55,930\neven before it appeared, I could hit Earth and\n或者还没展示的时候，就可以点击 Earth，\n\n1316\n01:08:55,932 --> 01:08:59,000\nit just reusing this. No seuges, so there's no way I'm\n而且这是重用的。没有 segue，所以不会\n\n1317\n01:08:59,002 --> 01:09:02,837\ncreating a new MVC here. It's just reloading it, okay,\n创建新的 MVC。只是在进行刷新，\n\n1318\n01:09:02,839 --> 01:09:07,842\njust by setting the image URL on the image there. Got it?\n只是重新设置了 image 的 URL。明白？\n\n1319\n01:09:08,178 --> 01:09:11,813\nOkay. Now, what about back on iPhone, though?\n那在 iPhone 上会怎样呢？\n\n1320\n01:09:11,815 --> 01:09:13,815\nLet's go back to iPhone.\n让我们回到 iphone。\n\n1321\n01:09:13,817 --> 01:09:18,286\nIs this going to work over here? No, it's not\n依然会有效吗？不，不行，\n\n1322\n01:09:18,288 --> 01:09:21,422\nbecause it only does that thing if it's in split view.\n因为这只能在 split view 的情况下可以。\n\n1323\n01:09:21,424 --> 01:09:24,759\nRemember I said if split view controller, so if I hit Earth,\n我记得我说过要 split view controller，所以这里点击 Earth，\n\n1324\n01:09:24,761 --> 01:09:28,163\nit's not working at all now, cuz it's not segueing here. So\n没有任何响应，因为根本没有 segue。\n\n1325\n01:09:28,165 --> 01:09:31,699\nreally what I need to do back here in Cassini is I need to\n所以，回到 Cassini 项目，需要加上\n\n1326\n01:09:31,701 --> 01:09:35,904\nsay [COUGH] if I'm in a split view controller, then do this.\n[咳嗽]，如果是 split view controller，处理这个。\n\n1327\n01:09:35,906 --> 01:09:39,107\nOtherwise, I basically want to segue. Okay, so\n否则，应该处理 segue 逻辑。\n\n1328\n01:09:39,109 --> 01:09:44,078\nnow I'm gonna show you how to segue from code. Okay,\n所以我会演示如何用代码实现 segue。\n\n1329\n01:09:44,080 --> 01:09:46,147\nyou've only learned how to segue from,\n因为之前只讲过从，\n\n1330\n01:09:46,149 --> 01:09:46,981\nby dragging in Storyboard.\n从 storyboard 中拖拽。\n\n1331\n01:09:46,983 --> 01:09:50,018\nAnd now I'm gonna show you how to do it in code,\n现在我会将如何使用代码，\n\n1332\n01:09:50,020 --> 01:09:53,788\nwhich is you just say performSegueWithIdentifier.\n只需要调用 performSegueWithIdentifier。\n\n1333\n01:09:53,790 --> 01:09:55,490\nAnd you give it the identifier. So\n给一个 identifier。\n\n1334\n01:09:55,492 --> 01:10:00,094\nwe'll use the Storyboard ShowImageSegue,\n可以使用 StoryBoard.ShowImageSegue，\n\n1335\n01:10:00,096 --> 01:10:01,930\nand the sender can be whatever you want,\nsender 这个可以随便填，\n\n1336\n01:10:01,932 --> 01:10:05,200\nI'm gonna have the sender be this sender button right here,\n这里我希望 sender 就是按钮事件的 sender，\n\n1337\n01:10:05,202 --> 01:10:06,868\nthis button that's asking us to show image, so\n就是这样按钮触发的 showimage，\n\n1338\n01:10:06,870 --> 01:10:09,137\nit's gonna be one of those Earth things or whatever.\n可能是 Earth，也可能是别的。\n\n1339\n01:10:09,139 --> 01:10:11,839\nNow this, perform segue with identifier,\nperformSegueWithIdentifier 方法，\n\n1340\n01:10:11,841 --> 01:10:16,477\nrequires that such a segue exist in the storyboard. Okay,\n要求传入的 segue 必须在 storyboard 中存在。\n\n1341\n01:10:16,479 --> 01:10:17,545\nand we got rid of all those segues.\n但我们之前删掉了所有 segue。\n\n1342\n01:10:17,547 --> 01:10:20,915\nSo that's not gonna work. We need to have a storyboard with\n所以代码不会生效。我们需要 storyboard 中，\n\n1343\n01:10:20,917 --> 01:10:24,252\nthis identifier, and the way you do this is, you actually\n有这些 identifier，实现方式是，\n\n1344\n01:10:24,254 --> 01:10:27,622\nsegue from the view controller itself. Instead of seguing\n从 view controller 自己发起 segue，而不是\n\n1345\n01:10:27,624 --> 01:10:30,792\nfrom one of the buttons, when you wanna segue in code,\n从 button 发起 segue。如果需要用代码实现 segue，\n\n1346\n01:10:30,794 --> 01:10:32,527\nyou segue from the view controller itself,\n那就需要 view controller 发起，\n\n1347\n01:10:32,529 --> 01:10:35,930\nfrom this little icon right here down to wherever you want\n从这个小图标拖到需要创建的\n\n1348\n01:10:35,932 --> 01:10:39,234\nto segue to. So we want to segue to this, right here,\nsegue 上。我们需要 segue 这个，\n\n1349\n01:10:39,236 --> 01:10:42,537\nput these close to each other. Okay, so I'm just gonna Ctrl +\n把它们放到一起。Okay，按住 Ctrl \n\n1350\n01:10:42,539 --> 01:10:47,242\ndrag from here to here. It's gonna be, it can be show,\n拖到，从这里到这里。选择 show，\n\n1351\n01:10:47,244 --> 01:10:50,178\nbecause we're never doing this in a split view controller cuz\n因为这个不会对 split view controller 中处理，\n\n1352\n01:10:50,180 --> 01:10:52,313\nsplit view controller we're doing the other thing. So\nsplit view controller 会有其他的处理逻辑。所以，\n\n1353\n01:10:52,315 --> 01:10:55,750\nwe do show. We've got this thing here now, this one\n这里选择 show。这就完成了，这就是一个\n\n1354\n01:10:55,752 --> 01:10:59,387\nsegue, this segue sets up the whole view controller to here.\nsegue，这个 segue 包含了整个 view controller。\n\n1355\n01:10:59,389 --> 01:11:03,992\nWe still need to set its identifier to ShowImage. Okay?\n我们还需要将 identifier 设为 ShowImage。Okay？\n\n1356\n01:11:03,994 --> 01:11:07,996\nAnd now, back here in this code, when we do perform segue\n现在，回到代码中，当 preform segue\n\n1357\n01:11:07,998 --> 01:11:11,399\nwith identifier, it's going to do that segue. And\nwith identifier 时，就会处理 segue。\n\n1358\n01:11:11,401 --> 01:11:13,368\nwe're seguing from the view controller to the other one,\nsegue 就会从一个 view controller 跳转另一个，\n\n1359\n01:11:13,370 --> 01:11:15,470\nnot with the buttons anymore, from the view controller, so\n而不是从按钮，是从 view controller，\n\n1360\n01:11:15,472 --> 01:11:22,977\nlet's see if that works now on iPhone All right, Cassini.\n来看看 Cassini 在 iPhone 上能成功吗。\n\n1361\n01:11:22,979 --> 01:11:24,279\nSure enough it's working. Okay, so\n当然没问题。Okay，\n\n1362\n01:11:24,281 --> 01:11:26,481\nit's doing that segue, it's back to doing the segues.\n能跳转过去，也能回来。\n\n1363\n01:11:26,483 --> 01:11:29,417\nSo this is a new MVC. Go back. This is a new MVC.\n这是一个新的 MVC，返回，这又是一个新的 MVC。\n\n1364\n01:11:29,419 --> 01:11:33,054\nBut it's only doing it on iPhone because if you look at\n但这只在 iPhone 上是这样，如果在代码的\n\n1365\n01:11:33,056 --> 01:11:35,089\nour code over here in the showImage,\nshowImage 方法中，\n\n1366\n01:11:35,091 --> 01:11:38,159\nif it's in a split view controller, it just reuses\n我们判断了如果是 split view controller，而且\n\n1367\n01:11:38,161 --> 01:11:41,863\nthe image view controller that's already in the split,\nimage view controller 是 split 的 detail 时，\n\n1368\n01:11:41,865 --> 01:11:46,234\nin the detail. Okay? Got all that? All right,\n才进行重用。明白吗？好的。\n\n1369\n01:11:46,236 --> 01:11:48,670\nI think I have time to do the last bit of slides here,\n应该还有时间讲最后一部分讲义，\n\n1370\n01:11:48,672 --> 01:11:54,242\noops, which is on text field, go through it pretty quickly.\noops，是关于 text field 的，很快过一遍。\n\n1371\n01:11:54,911 --> 01:11:56,878\nAll right, so UITextField. I haven't been able to show\n好的，UITextField。我现在还没办法展示，\n\n1372\n01:11:56,880 --> 01:11:59,714\nit to you right now because it requires delegation to work.\n因为它需要 delegation。\n\n1373\n01:11:59,716 --> 01:12:01,683\nWithout delegation, text fields don't work. So\n没有 delegation，text field 就没反应。\n\n1374\n01:12:01,685 --> 01:12:04,585\nUITextField is like UILabel but it's editable.\nUITextField 和 UILabel 差不多，但它可编辑。\n\n1375\n01:12:04,587 --> 01:12:08,089\nUsers can touch on it and then a keyboard comes up and\n用户点击它，键盘就会弹出，\n\n1376\n01:12:08,091 --> 01:12:09,424\nthey can start typing in it.\n然后可以进行输入。\n\n1377\n01:12:09,426 --> 01:12:11,926\nUITextField is not really a very main stream\nUITextField 的输入方式\n\n1378\n01:12:11,928 --> 01:12:15,530\ninput mechanism on the iPhone because the keyboard is very\n在 iPhone 上并不主流，因为键盘实在\n\n1379\n01:12:15,532 --> 01:12:18,700\nsmall, okay? So, you only want to use UITextField when you\n太小了，所以除非必要要用户\n\n1380\n01:12:18,702 --> 01:12:21,836\nabsolutely can't get the text from the user in any other\n用键盘，否则不要使用这种方式。\n\n1381\n01:12:21,838 --> 01:12:23,705\nway. You can't offer them a choice\n别让他们从清单\n\n1382\n01:12:23,707 --> 01:12:26,708\nfrom a list of the things, they have to actually type it\n中选择，这也是需要输入的。\n\n1383\n01:12:26,710 --> 01:12:29,477\nin, okay? So, be careful, this is not a desktop app that you\n所以，要时刻谨记，你开发的不是桌面应用，\n\n1384\n01:12:29,479 --> 01:12:33,214\nare building. It's a mobile app. All right so,\n而是手机应用。所以说，\n\n1385\n01:12:33,216 --> 01:12:35,416\nTextField is not a primary input source. Now,\ntextfield 不是主要的输入源。\n\n1386\n01:12:35,418 --> 01:12:39,354\nthe keyboard appears whenever a TextField becomes\n如果 textfild 是第一响应者，\n\n1387\n01:12:39,356 --> 01:12:41,989\nthe first responder, and you can make a TextField the first\n键盘就会弹出，要让 textfield 成为第一响应者，可调用\n\n1388\n01:12:41,991 --> 01:12:44,792\nresponder by sending it the message, becomeFirstResponder.\nbecomeFirstResponder 方法。\n\n1389\n01:12:44,794 --> 01:12:46,761\nAnd then it will become the first responder.\n然后它就成为第一响应者了。\n\n1390\n01:12:46,763 --> 01:12:48,529\nYou can make it stop being the first responder,\n可通过调用 resignFirstResponder，\n\n1391\n01:12:48,531 --> 01:12:51,299\nin which case the keyboard will go away, by saying,\n来取消是第一响应者，如此，\n\n1392\n01:12:51,301 --> 01:12:54,202\nresignFirstResponder, okay?\n键盘就会消失，okay？\n\n1393\n01:12:54,204 --> 01:12:54,669\nSo, the keyboard appears and\n所以，键盘的弹出与\n\n1394\n01:12:54,671 --> 01:12:57,905\ndisappears purely if there's something on the screen\n消失，是有屏幕上是否有第一响应者\n\n1395\n01:12:57,907 --> 01:13:00,641\nthat wants to be the first responder. Okay, simple as\n而决定的。就这样简单。\n\n1396\n01:13:00,643 --> 01:13:06,981\nthat. Now, delegation is used here primarily with the return\ndelegation 在这里可以用于处理返回按钮的事件。\n\n1397\n01:13:06,983 --> 01:13:09,951\nkey. So, if you bring up that little software keyboard\n如果你打开键盘，在它角落里的\n\n1398\n01:13:09,953 --> 01:13:11,919\nin the corner, there's a button called Return.\n那个按钮，就叫做返回按钮。\n\n1399\n01:13:11,921 --> 01:13:15,256\nAnd if you click return the TextField's delegate will\n如果点击返回按钮，textfield 的 delegate 方法 \n\n1400\n01:13:15,258 --> 01:13:17,892\nbe sent this message textFieldShouldReturn. It's\ntextFieldShouldReturn 就会被调用。之所以\n\n1401\n01:13:17,894 --> 01:13:20,762\ncalled ShouldReturn because it returns a Bool about whether\n叫做 ShouldReturn，是因为需要返回一个 bool 值，\n\n1402\n01:13:20,764 --> 01:13:23,631\nit should do target/action when that return happens.\n用于告知是否应该响应按钮的 target/action。\n\n1403\n01:13:23,633 --> 01:13:26,534\nBecause a TextField is like a button, if someone types in\n因为 textfield 就像是按钮，如果有键入值，\n\n1404\n01:13:26,536 --> 01:13:29,904\nthere and hits Return, it'll do target/action, okay?\n并且点击了返回，就会触发 target/action。\n\n1405\n01:13:29,906 --> 01:13:30,405\nYou can control drag and\n你可以通过按住 control 并拖拽\n\n1406\n01:13:30,407 --> 01:13:32,407\nit'll target/action just like a button. But\n来创建 target/action，这和 button 差不多。\n\n1407\n01:13:32,409 --> 01:13:35,476\nthis text field should return, either has to return true or\n对于 textfield 的 should return 来说，返回 true，\n\n1408\n01:13:35,478 --> 01:13:37,278\nit has to not be implemented by the delegate for\n或者不实现这个代理方法，\n\n1409\n01:13:37,280 --> 01:13:41,182\nthat to work. But one thing, so usually do implement this,\n都是一样的效果。不过通常这个方法都是实现了的，\n\n1410\n01:13:41,184 --> 01:13:43,818\nbecause one thing you wanna do in here is resign first\n因为需要在这个方法中，取消第一响应者。\n\n1411\n01:13:43,820 --> 01:13:47,155\nresponder. A lot of times when the user hits return,\n绝大多数时候，在用户点击返回时，\n\n1412\n01:13:47,157 --> 01:13:48,656\nyou do the target/action, but\n都会相应 target/action，\n\n1413\n01:13:48,658 --> 01:13:51,259\nyou want the keyboard to go away. So, a lot of times\n需要隐藏键盘。所以，一般情况下，\n\n1414\n01:13:51,261 --> 01:13:52,660\nyou'll do that here and TextField should return. So,\n都会在 should return 里面处理。\n\n1415\n01:13:52,662 --> 01:13:55,663\nyou just need to set yourself as the UITextField delegate,\n只需要将自己设置 UITextField 的代理，\n\n1416\n01:13:55,665 --> 01:13:58,466\nyou've got to save it to the UITextField delegate, and\n声明自己是 UITextField 的协议，并且\n\n1417\n01:13:58,468 --> 01:14:01,369\nthen you implement this method and inside just say sender,\n实现该方法，然后方法中的 sender\n\n1418\n01:14:01,371 --> 01:14:03,805\nwhich is the text field that's sending this to you,\n就是 text field，\n\n1419\n01:14:03,807 --> 01:14:08,342\nresign first responder. You can also find out when editing\nresign first responder。除此之外，也有其他地方需要\n\n1420\n01:14:08,344 --> 01:14:11,446\nhas ended in your TextField, meaning that the user\n结束编辑，比如用户在\n\n1421\n01:14:11,448 --> 01:14:14,682\nclicked on another TextField usually and you've resigned\n点击另外一个 textfield 时，通常也需要取消当前的\n\n1422\n01:14:14,684 --> 01:14:17,285\nfirst responder. Okay, any time you resign first\n第一响应者。在取消第一响应者时，\n\n1423\n01:14:17,287 --> 01:14:19,787\nresponder you'll get sent this and you can ask the TextField,\n就会调用这个方法，可以在方法中获取 textfield\n\n1424\n01:14:19,789 --> 01:14:23,758\nok, what text is in you. Okay, so that's another interesting\n的 text 是什么。这也是有趣的方法。\n\n1425\n01:14:23,760 --> 01:14:26,360\none. And as I said, TextField's UIControl,\n正如我所说，textfield 是 UIControl，\n\n1426\n01:14:26,362 --> 01:14:28,529\nyou can do target/action, just control, drag.\n你可以添加 target/action，只需要 control 并拖拽。\n\n1427\n01:14:28,531 --> 01:14:32,600\nThe keyboard, you configure the keyboard actually by\n对于键盘来说，其实配置键盘是和\n\n1428\n01:14:32,602 --> 01:14:33,401\ntalking to the TextField.\ntextfield 打交道的。\n\n1429\n01:14:33,403 --> 01:14:37,905\nThere's no UI keyboard object that you talk to in iOS, okay?\niOS 中并没有 UIKeyboard 这样的对象，okay？\n\n1430\n01:14:37,907 --> 01:14:39,407\nWhen you wanna configure your keyboard,\n要配置键盘时，\n\n1431\n01:14:39,409 --> 01:14:42,343\nyou talk to the thing that's bringing the keyboard up.\n就是在和唤起键盘的那个对象打交道。\n\n1432\n01:14:42,345 --> 01:14:43,411\nIn this case, the TextField. And\n比如，textfield。\n\n1433\n01:14:43,413 --> 01:14:45,913\nthere's all kinds of methods in here you could look at.\n大家可以看到，这里有一堆方法。\n\n1434\n01:14:45,915 --> 01:14:48,950\nThis is the UITextInputTraits protocol, so\n这些都定义在 UITextInputTraits 协议中，\n\n1435\n01:14:48,952 --> 01:14:51,085\nthat's where you wanna look in the documentation, for\n如果要在文档中查看，就要查\n\n1436\n01:14:51,087 --> 01:14:51,519\nthis protocol. Remember,\n这个协议。记住，\n\n1437\n01:14:51,521 --> 01:14:54,088\na protocol is just a bunch of methods and bars, that's all\n协议就是一堆方法的定义，\n\n1438\n01:14:54,090 --> 01:14:57,825\nthese are. And these will set what kind of keyboard it is,\n这就是协议。而这些就决定了键盘的属性，\n\n1439\n01:14:57,827 --> 01:15:00,895\nyou're entering a URL? Is it a password thing,\n如果在输入 URL？如果在输入密码，\n\n1440\n01:15:00,897 --> 01:15:04,999\nwhere you can't see the text? All that stuff Is part of that\n那就是不可见的文本。这些都是这个协议的\n\n1441\n01:15:05,001 --> 01:15:07,702\nprotocol, so you wanna look that up. One thing about\n一部分，所以你应该好好看看。关于键盘，\n\n1442\n01:15:07,704 --> 01:15:11,806\nthe keyboard, it comes up over your UI so it might block.\n还有一个问题，它弹起是，可能会挡住界面。\n\n1443\n01:15:11,808 --> 01:15:14,141\nIt might even block the TextField that you're\n如果没小心处理，也有可能正在输入时，\n\n1444\n01:15:14,143 --> 01:15:16,744\nediting in, if you're not careful about how you layer UI\n界面就被挡住了。\n\n1445\n01:15:16,746 --> 01:15:19,680\nout. And we are gonna talk later into the quarter about\n这个会在之后的\n\n1446\n01:15:19,682 --> 01:15:23,017\nthis NSNotification center. It's a way to get notified\nNSNotificationCenter 中谈到。这是得知这类事件的渠道。\n\n1447\n01:15:23,019 --> 01:15:25,920\nwhen things happened and when a keyboard comes up and\n当键盘弹起，可能挡住界面时，\n\n1448\n01:15:25,922 --> 01:15:28,789\nblocks your UI, you will get notified, okay?\n可以收到通知，\n\n1449\n01:15:28,791 --> 01:15:29,423\nAnd when we talk about this,\n在我们具体介绍的时候，\n\n1450\n01:15:29,425 --> 01:15:32,593\nyou'll understand what you can do. You could move your UI\n你就知道该怎么做了。你可以把界面\n\n1451\n01:15:32,595 --> 01:15:35,129\nup from out underneath it, or maybe it's in scroll view,\n移上去，如果是 scroll view，\n\n1452\n01:15:35,131 --> 01:15:37,265\nyou could scroll up or something like that, but\n可以滚上去之类的，\n\n1453\n01:15:37,267 --> 01:15:38,966\nyou have to be careful about this. They keyboard,\n但处理的时候要小心。键盘真的是\n\n1454\n01:15:38,968 --> 01:15:40,835\njust boom, comes up right on top of your UI and\n一下子就弹起来了，盖在界面上，\n\n1455\n01:15:40,837 --> 01:15:42,803\nit can really block things, okay? So,\n还挡住界面。\n\n1456\n01:15:42,805 --> 01:15:45,940\nyou'll need to eventually learn how to respond to this\n所以你必须要学会如何接收这个\n\n1457\n01:15:45,942 --> 01:15:49,443\nnotification. There's lots of other TextField properties\n通知。这些是 textfield 的另外一些属性，\n\n1458\n01:15:49,445 --> 01:15:53,447\nthat are interesting here. You can actually put a little\n也挺有趣的。这个可以给它\n\n1459\n01:15:53,449 --> 01:15:55,683\nbutton on the side. You can decide where,\n在边上加上小按钮，位置由你定，\n\n1460\n01:15:55,685 --> 01:15:58,920\nwhen the user touches it, does it clear out what's in there?\n当用户点击这个按钮时，可以清空输入。\n\n1461\n01:15:58,922 --> 01:16:00,855\nYou can have a place holder in there, so\n你也可以加 place holder，\n\n1462\n01:16:00,857 --> 01:16:02,189\nthat when there's nothing in the field,\n在 textfield 上什么都没有时，\n\n1463\n01:16:02,191 --> 01:16:03,457\nthere's a kind of a light gray text.\n可以展示一行浅灰色的文本。\n\n1464\n01:16:03,459 --> 01:16:05,626\nKind of telling the user what's supposed to be there,\n比如告诉用户这文本框支持什么，\n\n1465\n01:16:05,628 --> 01:16:06,994\nthat kind of thing.\n之类的。\n\n1466\n01:16:06,996 --> 01:16:09,430\nAnytime I show you anything in this class,\n每次我给大家展示类的信息是，\n\n1467\n01:16:09,432 --> 01:16:12,066\nlike UITextField or UIButton or anything, of course I'm\n比如 UITextField，UIButton 这类，都是\n\n1468\n01:16:12,068 --> 01:16:15,069\nexpecting you to go read the documentation, okay. Otherwise\n希望大家能去查阅文档。否则，\n\n1469\n01:16:15,071 --> 01:16:17,271\nyou're just not gonna know how to use these things.\n你无法知道这些该怎么使用。\n\n1470\n01:16:17,273 --> 01:16:18,306\nI only have a minute or\n课堂上，我只有\n\n1471\n01:16:18,308 --> 01:16:20,007\ntwo in these classes, in the lectures to\n几分钟时间，只够\n\n1472\n01:16:20,009 --> 01:16:22,610\nkind of tell you these exist. If you need to be able to go,\n告诉大家里面有什么。如果要弄清楚，\n\n1473\n01:16:22,612 --> 01:16:24,345\nuse the documentation to figure them out, okay?\n还是需要从文档中学习。\n\n1474\n01:16:24,347 --> 01:16:27,148\nAnd this is a classic example figuring out how to\n这是学习 textfield 最好的\n\n1475\n01:16:27,150 --> 01:16:30,184\nuse TextField here, Okay? Yeah, they have these left and\n方式了。这里的 left 和\n\n1476\n01:16:30,186 --> 01:16:33,120\nright overlays are kind of fun. You control the layout\nright 覆盖视图也挺有趣，你可以通过布局\n\n1477\n01:16:33,122 --> 01:16:35,890\nall this all kinds of stuff. The keyboard has\n来控制它们。键盘有\n\n1478\n01:16:35,892 --> 01:16:39,093\nan interesting bar in it which is sorry the input\n一个 bar，哦不，一个输入协议，\n\n1479\n01:16:39,095 --> 01:16:42,263\ntrait protocol. Called input accessory view you can\n名为 input accessory view，你可以将这个视图\n\n1480\n01:16:42,265 --> 01:16:44,131\nactually put a little view on top of your keyboard.\n放在键盘的顶部。\n\n1481\n01:16:44,133 --> 01:16:45,833\nYou've probably seen that in some apps. Right,\n你可能在其他的 app 中看见过。对吧，\n\n1482\n01:16:45,835 --> 01:16:48,436\nhas kind of like a little view has custom stuff,\n一个很小的，有些自定义控件的视图，\n\n1483\n01:16:48,438 --> 01:16:50,871\nyou can put your own view just by setting this bar.\n你可以通过配置这个 bar 来创建自己的视图。\n\n1484\n01:16:50,873 --> 01:16:54,308\nIt's kinda fun. All right, so that's it. On Friday,\n这倒是挺有趣的。好的，这就是全部内容。本周五，\n\n1485\n01:16:54,310 --> 01:16:56,377\nwe do have a section. It's on UI Testing,\n我们还有一个小节，关于 UITesting，\n\n1486\n01:16:56,379 --> 01:17:00,147\nwhich is literally being able to record the UI being\n它可以详尽的记录 UI 交互，\n\n1487\n01:17:00,149 --> 01:17:02,049\ninteracted with and then writing code that tests,\n还可以写代码进行测试，\n\n1488\n01:17:02,051 --> 01:17:03,484\nto make sure it's doing what it's supposed to be doing.\n以确保操作都是正确的。\n\n1489\n01:17:03,486 --> 01:17:06,921\nThat's really cool. A feature in xcode. And then next week,\n这是 xcode 中非常棒的特性。下一周，\n\n1490\n01:17:06,923 --> 01:17:08,823\nwe're going to talk about Table View and\n我们会讲解 tableview，\n\n1491\n01:17:08,825 --> 01:17:09,190\nCore Data, okay?\n还有 core data。\n\n1492\n01:17:09,192 --> 01:17:11,892\nTable View is a way of showing big huge amounts of data.\ntable view 用于展示一系列数据，\n\n1493\n01:17:11,894 --> 01:17:15,563\nAnd Core Data is a database to store big huge amounts of\n而 core data 则是用于存储\n\n1494\n01:17:15,565 --> 01:17:17,164\ndata in. Assignment four.\n一系列数据。关于作业，\n\n1495\n01:17:17,166 --> 01:17:18,399\nSince it's a table view based assignment,\n既然都是关于 table view 的作业，\n\n1496\n01:17:18,401 --> 01:17:21,869\nwe'll go out at the end of the next lecture, and it'll be due\n所以也会在下一讲结束，也就是\n\n1497\n01:17:21,871 --> 01:17:24,772\na week later. And there are no more reading assignments.\n一周以后。今天没有额外的阅读任务。\n\n1498\n01:17:24,774 --> 01:17:27,408\nI can tell some of you haven't done your reading assignment\n我知道一部分同学没有完成阅读任务，\n\n1499\n01:17:27,410 --> 01:17:29,777\nbecause you don't know some of the questions I'm asking.\n因为今天我提的好几个问题都没回答上来。\n\n1500\n01:17:29,779 --> 01:17:30,778\nGo back and read that stuff, really.\n记得之后要去看，真的，\n\n1501\n01:17:30,780 --> 01:17:34,348\nit's not that much stuff, you should really understand all\n这又没多少东西，而且这些知识你必须要知道，\n\n1502\n01:17:34,350 --> 01:17:36,350\nthese things, like the where clause,\n比如闭包，\n\n1503\n01:17:36,352 --> 01:17:37,718\nor you're going to be writing weird code.\n否则写出的代码就很奇怪。\n\n1504\n01:17:37,720 --> 01:17:40,154\nBecause people say, why didn't they just use where there,\n因为大家会说，你为什么不用这个，\n\n1505\n01:17:40,156 --> 01:17:40,588\nwhy did they put another if?.\n为什么这里要加上判断。\n\n1506\n01:17:40,590 --> 01:17:44,525\nOkay? So, you don't want to be that guy, okay? Allright,\nOkay？你不会想被这样对待的，好吗？\n\n1507\n01:17:44,527 --> 01:17:47,228\nI'll see you guys next week. >> For\n同学们，下周见。\n\n1508\n01:17:47,230 --> 01:17:47,261\nmore, please visit us at Stanford.edu\n更多信息，请访问 Stanford.edu\n\n"
  },
  {
    "path": "subtitles/9. Table View.srt",
    "content": "﻿1\n00:00:00,001 --> 00:00:04,436\n[MUSIC]\n\n2\n00:00:04,438 --> 00:00:08,507\nStanford University. >> Okay well\n\n3\n00:00:08,509 --> 00:00:13,846\nwelcome to lecture number nine of CS193P. This is spring of\n\n4\n00:00:13,848 --> 00:00:16,548\n2016. Today, we're gonna talk all about Table View that's\n\n5\n00:00:16,550 --> 00:00:20,185\nthe only topic for today. It's basically a way to create,\n\n6\n00:00:20,187 --> 00:00:22,721\napps that are looking at large data sets.\n\n7\n00:00:22,723 --> 00:00:24,523\nAnd our demo is gonna be a Twitter client, and\n\n8\n00:00:24,525 --> 00:00:26,859\nof course Twitter is this humongous data set,\n\n9\n00:00:26,861 --> 00:00:28,794\nbunch of tweets out there and more all the time.\n\n10\n00:00:28,796 --> 00:00:33,499\nAnd so a Table View is a great way to, show tweets. So what\n\n11\n00:00:33,501 --> 00:00:38,270\nis Table View? UITableView is a sub class of UIView, okay.\n\n12\n00:00:38,272 --> 00:00:42,374\nIt displays data in a big table, okay? And\n\n13\n00:00:42,376 --> 00:00:45,210\nthere's really two different looks to it, all right?\n\n14\n00:00:45,212 --> 00:00:48,547\nThere's the plain style which you see here on the left,\n\n15\n00:00:48,549 --> 00:00:51,717\nwhich is basically just all of the things it's showing in\n\n16\n00:00:51,719 --> 00:00:55,254\na big, long straight list. And then there's group style\n\n17\n00:00:55,256 --> 00:00:58,991\non the right, which is also a bunch of rows of data, but\n\n18\n00:00:58,993 --> 00:01:04,630\ngrouped. A little more obviously into little groups\n\n19\n00:01:04,632 --> 00:01:08,467\nand this ones in the right, okay, are usually more for\n\n20\n00:01:08,469 --> 00:01:12,571\nstatic tables, okay, where the stuff that in there is fixed.\n\n21\n00:01:12,573 --> 00:01:16,075\nIt's kinda fixed in your storyboard usually even,\n\n22\n00:01:16,077 --> 00:01:18,510\nwhereas on the left is more for data that\n\n23\n00:01:18,512 --> 00:01:20,712\nchanging every changing coming like even here.\n\n24\n00:01:20,714 --> 00:01:24,450\nIf you know anything about NFL you'll know that this this\n\n25\n00:01:24,452 --> 00:01:28,921\nlist has changed dramatically since I made this little list.\n\n26\n00:01:28,923 --> 00:01:31,056\nSo dynamic data on the left basically and\n\n27\n00:01:31,058 --> 00:01:34,159\nmore static data on the right. Is not exclusively that but\n\n28\n00:01:34,161 --> 00:01:36,462\nthat's generally how we use these two styles,\n\n29\n00:01:36,464 --> 00:01:41,066\nokay. Now let's talk about all the parts of a UITableView so\n\n30\n00:01:41,068 --> 00:01:42,201\nwe know the terminology, all right?\n\n31\n00:01:42,203 --> 00:01:44,837\nI'm gonna show this to you in plain style, but then I'll\n\n32\n00:01:44,839 --> 00:01:47,573\nshow you the grouped style version of it afterwards.\n\n33\n00:01:47,575 --> 00:01:49,808\nSo there's a Table Header at the top.\n\n34\n00:01:49,810 --> 00:01:52,678\nThis is just a UIView. It can be any UIView you want.\n\n35\n00:01:52,680 --> 00:01:54,113\nIn our demo we're gonna have one of these,\n\n36\n00:01:54,115 --> 00:01:56,348\nit's gonna be a UITextField, okay? But it can be,\n\n37\n00:01:56,350 --> 00:01:59,151\nit can be your own custom view with subviews in there.\n\n38\n00:01:59,153 --> 00:02:00,552\nIt can be absolutely anything, and\n\n39\n00:02:00,554 --> 00:02:02,888\nit always lives at the top of the header and as\n\n40\n00:02:02,890 --> 00:02:05,691\nthe table scrolls around it'll scroll off the top, right?\n\n41\n00:02:05,693 --> 00:02:08,727\nIt's at the very top of this thing you're scrolling on. And\n\n42\n00:02:08,729 --> 00:02:11,630\nsimilarly there's a footer, also some UIView.\n\n43\n00:02:11,632 --> 00:02:12,664\nNotice at the bottom I'm showing you\n\n44\n00:02:12,666 --> 00:02:16,001\na little bit of code like var tableViewFooter: UIView,\n\n45\n00:02:16,003 --> 00:02:18,337\nthat's basically telling you the function or\n\n46\n00:02:18,339 --> 00:02:20,572\nthe property where you set this thing. Okay,\n\n47\n00:02:20,574 --> 00:02:23,609\nthese would be functions or properties in UITableView.\n\n48\n00:02:23,611 --> 00:02:29,114\nOkay? Next is a bunch of stuff that's, we grouped together,\n\n49\n00:02:29,116 --> 00:02:33,051\nwe call it a section, okay? So the data that's in the table\n\n50\n00:02:33,053 --> 00:02:36,388\ncan be sectioned off into little, pieces.\n\n51\n00:02:36,390 --> 00:02:37,489\nAnd you'll see in the next slide\n\n52\n00:02:37,491 --> 00:02:41,260\na little more of an example of that. Each section, okay,\n\n53\n00:02:41,262 --> 00:02:45,197\nhas a header, this is usually a string but it could also\n\n54\n00:02:45,199 --> 00:02:48,600\nbe UIView if you wanted a complicated looking header,\n\n55\n00:02:48,602 --> 00:02:50,669\nmaybe with images or something like that. But,\n\n56\n00:02:50,671 --> 00:02:53,605\nusually this is just a string. And also a section footer.\n\n57\n00:02:53,607 --> 00:02:55,607\nOkay, so that's every section has a header and footer,\n\n58\n00:02:55,609 --> 00:02:59,077\nheader and footer, header and footer. Okay. And then inside\n\n59\n00:02:59,079 --> 00:03:02,281\nthe sections there's the rows. Now these roads like Row 0,\n\n60\n00:03:02,283 --> 00:03:05,417\nRow 1, these two sections each have two rows,\n\n61\n00:03:05,419 --> 00:03:07,719\nbut there can be any number of rows and it doesn't have to be\n\n62\n00:03:07,721 --> 00:03:09,421\nthe same number of rows in every section.\n\n63\n00:03:09,423 --> 00:03:12,791\nOne section might have zero rows or five rows and\n\n64\n00:03:12,793 --> 00:03:16,595\nanother one might have 100 rows okay. This\n\n65\n00:03:16,597 --> 00:03:20,432\nrow is basically represented in the table by a UIView. It's\n\n66\n00:03:20,434 --> 00:03:25,437\nactually a subclass of UIView called UITableViewCell. And\n\n67\n00:03:25,439 --> 00:03:29,875\nthis method right here it's gonna get called in your code,\n\n68\n00:03:29,877 --> 00:03:32,878\ncellForRowAtIndexPath and it returns\n\n69\n00:03:32,880 --> 00:03:36,148\none of these UITableViewCells. Okay, this is probably\n\n70\n00:03:36,150 --> 00:03:39,184\nthe most important method in implementing Table View,\n\n71\n00:03:39,186 --> 00:03:40,586\nis this cellForRowAtIndexPath.\n\n72\n00:03:40,588 --> 00:03:44,056\nWe'll be coming back to this again and again okay. So\n\n73\n00:03:44,058 --> 00:03:46,992\nthose are all the names of the parts of a Table View.\n\n74\n00:03:46,994 --> 00:03:49,394\nSo when I was talking about it you know what they are.\n\n75\n00:03:49,396 --> 00:03:50,829\nSo that's what it looks in plain style.\n\n76\n00:03:50,831 --> 00:03:55,234\nHere's the exact same thing in group style. Okay, so\n\n77\n00:03:55,236 --> 00:03:57,736\nit has the same thing, headers, cells, footers,\n\n78\n00:03:57,738 --> 00:04:01,106\nit's just that it displays them a little bit differently.\n\n79\n00:04:01,208 --> 00:04:04,443\nOkay. All right, sections or not? What does it look like to\n\n80\n00:04:04,445 --> 00:04:08,080\nhave sections or not? Now this is visible sections, so\n\n81\n00:04:08,082 --> 00:04:12,618\nlook here on the right you see I have some cities in Japan\n\n82\n00:04:12,620 --> 00:04:15,053\nfor example and this little gray bar right there.\n\n83\n00:04:15,055 --> 00:04:17,289\nI don't know how well you can see that, actually,\n\n84\n00:04:17,291 --> 00:04:18,323\nbut there's a gray bar there,\n\n85\n00:04:18,325 --> 00:04:21,860\nit says Japan, that's a section header, okay?\n\n86\n00:04:21,862 --> 00:04:23,662\nSo there's one section, the Japan section,\n\n87\n00:04:23,664 --> 00:04:25,998\nit's got three rows. Here's a Mexico section,\n\n88\n00:04:26,000 --> 00:04:28,867\nit's got three rows. Here's Italy section,\n\n89\n00:04:28,869 --> 00:04:30,869\nit's got at least two rows there at the top.\n\n90\n00:04:30,871 --> 00:04:34,139\nOkay, this one over here doesn't have any sections.\n\n91\n00:04:34,141 --> 00:04:36,208\nNow, it actually might have sections, but\n\n92\n00:04:36,210 --> 00:04:39,278\nno section headers. Okay, if you have sections but\n\n93\n00:04:39,280 --> 00:04:43,482\nno section headers, it looks like you have no sections. But\n\n94\n00:04:43,484 --> 00:04:47,185\nthis is what we mean by sections, so just groups of\n\n95\n00:04:47,187 --> 00:04:53,925\nthings in the table. The type of cell, those little rows,\n\n96\n00:04:53,927 --> 00:04:56,128\nthere are five types of cells. Here are four of\n\n97\n00:04:56,130 --> 00:04:59,798\nthem that are built into the system. The subtitle has\n\n98\n00:04:59,800 --> 00:05:02,701\na piece of text and then a small little piece under it,\n\n99\n00:05:02,703 --> 00:05:05,570\nokay? This is called the title and the subtitle, or\n\n100\n00:05:05,572 --> 00:05:08,740\nthe text and the detail text, sometimes we call it.\n\n101\n00:05:08,742 --> 00:05:12,444\nThe basic one, the second one has no detail text,\n\n102\n00:05:12,446 --> 00:05:15,480\nonly has the primary text. The right and\n\n103\n00:05:15,482 --> 00:05:18,383\nleft are similar to the subtitle but it puts the text\n\n104\n00:05:18,385 --> 00:05:21,219\nin a little different place with a little different color.\n\n105\n00:05:21,221 --> 00:05:23,755\nOkay? So you can see that the basic\n\n106\n00:05:23,757 --> 00:05:26,725\ncell types that come with the system, pretty limited.\n\n107\n00:05:26,727 --> 00:05:28,727\nOkay? It also can pl, display an image,\n\n108\n00:05:28,729 --> 00:05:32,831\nturns out, but they're pretty limited. There's a fifth type,\n\n109\n00:05:32,833 --> 00:05:35,734\nwhich is custom cell, which let's you build any UI\n\n110\n00:05:35,736 --> 00:05:38,470\nyou want inside the cell. You can drag buttons,\n\n111\n00:05:38,472 --> 00:05:40,572\ntext fields, images, anything you want in there. And\n\n112\n00:05:40,574 --> 00:05:44,743\nwe're going to talk about and demo that today. All right.\n\n113\n00:05:44,745 --> 00:05:50,082\nSo, how do I use a table view in my application?\n\n114\n00:05:50,084 --> 00:05:52,451\nAnd the answer is, 99% of the time you're gonna\n\n115\n00:05:52,453 --> 00:05:56,755\nuse a table view controller. Okay? TableViewController,\n\n116\n00:05:56,757 --> 00:05:59,991\nit's a UIViewController. A sub class of UIViewController.\n\n117\n00:05:59,993 --> 00:06:03,695\nThat sub class is called UITableViewController. And,\n\n118\n00:06:03,697 --> 00:06:05,364\njust like when you use a UIViewController,\n\n119\n00:06:05,366 --> 00:06:07,933\nyou sub class it to make a class you can hook\n\n120\n00:06:07,935 --> 00:06:10,001\nyour outlets and actions up to. Same thing here.\n\n121\n00:06:10,003 --> 00:06:12,971\nYou're gonna sub class UITableViewController so\n\n122\n00:06:12,973 --> 00:06:16,675\nyou can wire up things if you want inside your controller.\n\n123\n00:06:16,677 --> 00:06:19,711\nOkay? Now it is possible to use a UITableView without\n\n124\n00:06:19,713 --> 00:06:22,914\nthe UITableViewController but like I said we almost never\n\n125\n00:06:22,916 --> 00:06:26,952\ndo. 99% of the time we're going to use UIViewController.\n\n126\n00:06:26,954 --> 00:06:29,488\nOkay, and so if you drag the UIViewController\n\n127\n00:06:29,490 --> 00:06:32,257\nout into your storyboard, UITableViewController,\n\n128\n00:06:32,259 --> 00:06:34,693\nsorry. If you drag UITableViewController out,\n\n129\n00:06:34,695 --> 00:06:36,628\nyou're gonna get this thing right here,\n\n130\n00:06:36,630 --> 00:06:38,663\nthat's gonna be a UITableViewController.\n\n131\n00:06:38,665 --> 00:06:41,466\nAnd the view, remember the view property\n\n132\n00:06:41,468 --> 00:06:43,769\nin a UIViewController is that top level view?\n\n133\n00:06:43,771 --> 00:06:47,072\nIt's going to be of type UITableView. Okay. The very\n\n134\n00:06:47,074 --> 00:06:51,309\ntop top level is a table view. So this, UITableViewController\n\n135\n00:06:51,311 --> 00:06:54,446\nthe entire view is just one big table view.\n\n136\n00:06:54,448 --> 00:06:57,783\nNow it is possible to drag out your own UIViewController and\n\n137\n00:06:57,785 --> 00:07:00,085\nmake the table view only be a part of the view.\n\n138\n00:07:00,087 --> 00:07:03,321\nLike be a subview of the main view, but again very rare\n\n139\n00:07:03,323 --> 00:07:05,557\nto do that. Not even really gonna talk about doing that.\n\n140\n00:07:05,559 --> 00:07:08,527\nBut you could. Requires a little more work on your part.\n\n141\n00:07:08,529 --> 00:07:11,263\nThis is kind of a nice pre-packaged way to use\n\n142\n00:07:11,265 --> 00:07:15,801\nTableView here. Okay? Of course when you sub class\n\n143\n00:07:15,803 --> 00:07:19,771\nUITableViewController up here, you create your own class.\n\n144\n00:07:19,773 --> 00:07:21,840\nWe'll call it MyTableView Controller or\n\n145\n00:07:21,842 --> 00:07:22,307\nsomething like that.\n\n146\n00:07:22,309 --> 00:07:24,976\nYou're going to want to remember to go to the identity\n\n147\n00:07:24,978 --> 00:07:28,180\ninspector and set that as the type just like you would any\n\n148\n00:07:28,182 --> 00:07:31,149\nother UIViewController. If you right click on\n\n149\n00:07:31,151 --> 00:07:33,885\nit, okay, if you right click on the thing that represents\n\n150\n00:07:33,887 --> 00:07:36,254\nthe TableViewController, you'll see that, look,\n\n151\n00:07:36,256 --> 00:07:39,057\nhere's view, it's hooked up to a UITableview. And\n\n152\n00:07:39,059 --> 00:07:42,093\nthen down farther, you see dataSource and delegate.\n\n153\n00:07:42,095 --> 00:07:44,329\nThose are both delegates, okay, for\n\n154\n00:07:44,331 --> 00:07:49,334\ndelegation. They are protocol based communication outlets,\n\n155\n00:07:49,336 --> 00:07:52,771\ncommunication portals. From the Table View,\n\n156\n00:07:52,773 --> 00:07:55,607\nto the Table View Controller. And you can see look,\n\n157\n00:07:55,609 --> 00:07:57,342\nthey're automatically hooked up for you. And\n\n158\n00:07:57,344 --> 00:08:00,779\nwhat that means is that your UITableViewController subclass\n\n159\n00:08:00,781 --> 00:08:04,049\nJust has to implement any and all of the data source and\n\n160\n00:08:04,051 --> 00:08:06,117\ndelegate methods that it wants. Okay?\n\n161\n00:08:06,119 --> 00:08:08,720\nTo make things work. Just like we do with scroll view, right?\n\n162\n00:08:08,722 --> 00:08:10,288\nWe set ourselves as a scroll view delegate.\n\n163\n00:08:10,290 --> 00:08:12,724\nWe implement that view for zooming in scroll view.\n\n164\n00:08:12,726 --> 00:08:15,026\nNow we can zoom. Same thing with table view,\n\n165\n00:08:15,028 --> 00:08:17,996\nexcept for we're automatically hooked up as the delegate and\n\n166\n00:08:17,998 --> 00:08:18,263\nWe'll talk about these, the difference between these two.\n\n167\n00:08:18,265 --> 00:08:19,865\ndata source.\n\n168\n00:08:19,867 --> 00:08:22,601\nAnd there's just a bunch of methods in there like and\n\n169\n00:08:22,603 --> 00:08:25,637\nindex path for us to implement the table,\n\n170\n00:08:25,639 --> 00:08:29,674\nall right? You can, of course, click on this table and\n\n171\n00:08:29,676 --> 00:08:33,144\ninspect it in the inspector, just like anything else there.\n\n172\n00:08:33,146 --> 00:08:36,181\nYou can see things like, plain style and stuff. I'll show you\n\n173\n00:08:36,183 --> 00:08:39,651\nsome of that. Remember when you have a table view,\n\n174\n00:08:39,653 --> 00:08:43,188\nyou're gonna remember, wanna remember Ctrl+Shift click. If\n\n175\n00:08:43,190 --> 00:08:46,758\nyou remember ctrl-shift-click. It lets you, kind of, cli-,\n\n176\n00:08:46,760 --> 00:08:48,560\npick what's under the mouth,mouse,\n\n177\n00:08:48,562 --> 00:08:49,995\nif there are multiple things under there.\n\n178\n00:08:49,997 --> 00:08:52,597\nMm-kay? That's really valuable here because you've got\n\n179\n00:08:52,599 --> 00:08:55,600\nthe cell, under that you've got the table view, under that\n\n180\n00:08:55,602 --> 00:08:57,903\nyou've got the controller. And if you had a custom cell,\n\n181\n00:08:57,905 --> 00:08:59,871\nyou might have buttons and text fields in here.\n\n182\n00:08:59,873 --> 00:09:02,607\nSo, kind of drilling down to which of those things you want\n\n183\n00:09:02,609 --> 00:09:08,013\nto chose. Ctrl-shift-click. Okay, you want that. So\n\n184\n00:09:08,015 --> 00:09:10,849\nhere I'm gonna, switch the table view from being\n\n185\n00:09:10,851 --> 00:09:14,619\nplain style to being grouped, okay? You can see that,\n\n186\n00:09:14,621 --> 00:09:16,555\nwhen I switched a group, it changes a little bit and\n\n187\n00:09:16,557 --> 00:09:19,257\nlooks a little bit different, okay? Another thing I can\n\n188\n00:09:19,259 --> 00:09:23,628\nswitch is dynamic and static, okay? Now, grouped in plain,\n\n189\n00:09:23,630 --> 00:09:25,964\nI told you the plain was usually dynamic data, and\n\n190\n00:09:25,966 --> 00:09:28,767\ngrouped is static. They don't have to be that way, okay?\n\n191\n00:09:28,769 --> 00:09:34,139\nYou choose the dynamic versus static with this other pop up,\n\n192\n00:09:34,141 --> 00:09:37,208\nright here. But again, usually if it's grouped you're gonna\n\n193\n00:09:37,210 --> 00:09:38,143\npick static from this one, and\n\n194\n00:09:38,145 --> 00:09:40,745\nif it's plain your gonna be picking dynamic. So\n\n195\n00:09:40,747 --> 00:09:43,748\nI'm gonna switch to static right here. When I switch to\n\n196\n00:09:43,750 --> 00:09:48,420\nstatic, all of this, these little rows in here,\n\n197\n00:09:48,422 --> 00:09:49,888\nnow they become fully editable.\n\n198\n00:09:49,890 --> 00:09:52,424\nYou can drag buttons out. You can drag text fields.\n\n199\n00:09:52,426 --> 00:09:55,360\nWhatever. And whatever you put in your story board,\n\n200\n00:09:55,362 --> 00:09:58,196\nthat's what's gonna appear in your app, okay?\n\n201\n00:09:58,198 --> 00:09:59,731\nHowever many rows there are here,\n\n202\n00:09:59,733 --> 00:10:01,700\nthat's how many rows are gonna be in the app.\n\n203\n00:10:01,702 --> 00:10:03,668\nWhatever buttons and stuff you put in here,\n\n204\n00:10:03,670 --> 00:10:04,903\nthat's how many are gonna be in the app.\n\n205\n00:10:04,905 --> 00:10:08,173\nYou can wire up outlets in these static ones directly\n\n206\n00:10:08,175 --> 00:10:11,309\nto your controller, just like if this were a view and\n\n207\n00:10:11,311 --> 00:10:13,244\nyou dragged a button down to it, okay? So\n\n208\n00:10:13,246 --> 00:10:16,448\nthink of static as really just normal view,\n\n209\n00:10:16,450 --> 00:10:19,584\nbut grouped, okay? Grouped in these little sections.\n\n210\n00:10:19,586 --> 00:10:21,419\nReally great for things like settings like settings, like,\n\n211\n00:10:21,421 --> 00:10:25,690\nyou know, the settings app in iOS is just a big table view,\n\n212\n00:10:25,692 --> 00:10:28,393\na static grouped table view. So, it's really great for\n\n213\n00:10:28,395 --> 00:10:31,730\nthat. It's not good at all for dynamic data.\n\n214\n00:10:31,732 --> 00:10:34,199\nIt doesn't, grouped is not good for\n\n215\n00:10:34,201 --> 00:10:37,602\nthat. And if you have this set to static content,\n\n216\n00:10:37,604 --> 00:10:39,938\nthen you can't even do dynamic data, okay? So\n\n217\n00:10:39,940 --> 00:10:42,540\nstatic, you edit it all in the story board. Very different\n\n218\n00:10:42,542 --> 00:10:45,944\nfrom dynamic, okay? So let's go back to talk about dynamic,\n\n219\n00:10:45,946 --> 00:10:49,114\nthough, cuz that's really the more interesting one here,\n\n220\n00:10:49,116 --> 00:10:51,616\nokay? We're also gonna switch back to plain style for\n\n221\n00:10:51,618 --> 00:10:56,421\ndynamic. Now, these rows are prototypes, or\n\n222\n00:10:56,423 --> 00:11:00,225\ntemplates, okay? Because I've got three rows here, but I can\n\n223\n00:11:00,227 --> 00:11:04,696\nhave hundreds of rows in my app when I load my data up. So\n\n224\n00:11:04,698 --> 00:11:06,698\nthese are just the different templates you can have.\n\n225\n00:11:06,700 --> 00:11:08,166\nAnd you could have different kinds of templates.\n\n226\n00:11:08,168 --> 00:11:10,902\nLike, in your homework, you're gonna have two different\n\n227\n00:11:10,904 --> 00:11:14,305\nkinds of rows in one of your table views. One shows image,\n\n228\n00:11:14,307 --> 00:11:17,709\none's showing text. So you're gonna have one prototype for\n\n229\n00:11:17,711 --> 00:11:20,178\nimages, and you're gonna have another prototype for text,\n\n230\n00:11:20,180 --> 00:11:25,316\nokay? And these prototypes are copied hundreds of times,\n\n231\n00:11:25,318 --> 00:11:27,986\nor however many times is necessary for all the data.\n\n232\n00:11:27,988 --> 00:11:30,655\nNow, it doesn't actually copy it hundreds of times, cuz\n\n233\n00:11:30,657 --> 00:11:33,958\nit's really smart. It reuses them, so it only uses them for\n\n234\n00:11:33,960 --> 00:11:36,528\nvisible cells, okay? Table view's very efficient,\n\n235\n00:11:36,530 --> 00:11:39,798\nas you can imagine. If you had 100,000 items in there,\n\n236\n00:11:39,800 --> 00:11:42,400\nand you were making 100,000 UITableView cells,\n\n237\n00:11:42,402 --> 00:11:44,769\nit would be pretty inefficient so it doesn't do that.\n\n238\n00:11:44,771 --> 00:11:47,772\nIt reuses them. But these prototypes are a template\n\n239\n00:11:47,774 --> 00:11:50,408\nthat get, you know, essentially copied.\n\n240\n00:11:51,645 --> 00:11:55,180\nSo, the cells can be inspected just like the table view.\n\n241\n00:11:55,182 --> 00:11:55,780\nSo, here I'm gonna change,\n\n242\n00:11:55,782 --> 00:11:58,216\nI'm gonna pick this first cell, this first proto-type,\n\n243\n00:11:58,218 --> 00:11:59,451\nand I'm gonna change it to be subtitle.\n\n244\n00:11:59,453 --> 00:12:01,786\nAnd you can see it looks like this in the storyboard,\n\n245\n00:12:01,788 --> 00:12:04,122\njust to remind you that it's subtitle. Of course,\n\n246\n00:12:04,124 --> 00:12:06,491\nthis is not gonna say subtitle and title when I launch.\n\n247\n00:12:06,493 --> 00:12:09,461\nIt's gonna be replaced by the data that I load into that\n\n248\n00:12:09,463 --> 00:12:12,731\ncell, okay? Cuz I'm gonna have hundreds of these rows.\n\n249\n00:12:12,733 --> 00:12:16,601\nAll right. You can also set a little\n\n250\n00:12:16,603 --> 00:12:19,270\nthing to appear on the right hand side of a row.\n\n251\n00:12:19,272 --> 00:12:22,107\nFor example, I picked a detailed disclosure which is\n\n252\n00:12:22,109 --> 00:12:26,811\nthis little greater than sign, and then this little round\n\n253\n00:12:26,813 --> 00:12:31,483\ncircled i. This little gray, greater than sign means that\n\n254\n00:12:31,485 --> 00:12:35,353\nif I press on this row, it's gonna segue, okay? So, anytime\n\n255\n00:12:35,355 --> 00:12:37,989\nyou set up a segue from a row, which we're gonna talk about,\n\n256\n00:12:37,991 --> 00:12:40,925\nyou're always gonna wanna have your accessory be either\n\n257\n00:12:40,927 --> 00:12:42,994\ndetail disclosure or just disclosure.\n\n258\n00:12:42,996 --> 00:12:45,730\nDetail disclosure means you have this little blue i, and\n\n259\n00:12:45,732 --> 00:12:48,366\nI'll talk about what that means in a second, okay?\n\n260\n00:12:48,368 --> 00:12:51,669\nSo I'm gonna turn that off for now. All right.\n\n261\n00:12:51,671 --> 00:12:55,373\nSo, another style that you can choose is the custom style.\n\n262\n00:12:55,375 --> 00:12:59,711\nSo I'm gonna switch my style here to custom, okay? Now,\n\n263\n00:12:59,713 --> 00:13:02,347\nthis custom area, I can resize it, okay?\n\n264\n00:13:02,349 --> 00:13:07,085\nMake it bigger. I can go over to my object pallet down here.\n\n265\n00:13:07,087 --> 00:13:09,654\nI can pick up a label or a button or something.\n\n266\n00:13:09,656 --> 00:13:12,991\nI can drag it out. I can use the blue lines.\n\n267\n00:13:12,993 --> 00:13:17,195\nI can use stack views. I can control drag to the edges.\n\n268\n00:13:17,197 --> 00:13:20,732\nI can build whatever UI I want in here. And remember, it took\n\n269\n00:13:20,734 --> 00:13:24,035\nprototype. So every row that's gonna use this prototype\n\n270\n00:13:24,037 --> 00:13:27,739\nis gonna have all those labels and buttons in each row, okay?\n\n271\n00:13:27,741 --> 00:13:33,311\nSo there's a, when you have this kind of mechanism,\n\n272\n00:13:33,313 --> 00:13:36,381\nyou might well ask yourself, well, how am I gonna hook up\n\n273\n00:13:36,383 --> 00:13:38,616\nto that label? How am I gonna control drag?\n\n274\n00:13:38,618 --> 00:13:41,352\nI can't really control drag an outlet to my table view\n\n275\n00:13:41,354 --> 00:13:44,656\ncontroller because my table view controller's just one\n\n276\n00:13:44,658 --> 00:13:47,692\ncontroller, and I've got hundreds of rows. So,\n\n277\n00:13:47,694 --> 00:13:49,227\nwhich row is the outlet hooked to?\n\n278\n00:13:49,229 --> 00:13:53,331\nSo you can't hook your outlets up to dynamic prototype like,\n\n279\n00:13:53,333 --> 00:13:57,168\nrows like this. You have to hook it up to outlets in\n\n280\n00:13:57,170 --> 00:14:02,807\na sub-classed UI table view cell, okay?\n\n281\n00:14:02,809 --> 00:14:05,643\nSo we're gonna create a custom subclass of UITableViewCell.\n\n282\n00:14:05,645 --> 00:14:08,313\nAnd it's gonna have outlets in it. And we're gonna wire this\n\n283\n00:14:08,315 --> 00:14:11,749\nto it. And we know that, for all the visible cells anyway,\n\n284\n00:14:11,751 --> 00:14:14,552\nthere's another TableUIViewCell that's hooked\n\n285\n00:14:14,554 --> 00:14:16,254\nup. So, we're gonna have all these UITableViewCells,\n\n286\n00:14:16,256 --> 00:14:20,024\nthey're gonna all each have outlets to whatever is showing\n\n287\n00:14:20,026 --> 00:14:22,627\nin their custom cell, okay? So\n\n288\n00:14:22,629 --> 00:14:25,063\nyou do this with the identity inspector in the same way.\n\n289\n00:14:25,065 --> 00:14:26,464\nSo you're gonna do new file, right?\n\n290\n00:14:26,466 --> 00:14:29,734\nYou're gonna go over to new file, and when you do new file\n\n291\n00:14:29,736 --> 00:14:33,204\nyou're gonna say Tableview Cell as the superview class.\n\n292\n00:14:33,206 --> 00:14:35,240\nAnd then you're gonna go up here to the identity inspector\n\n293\n00:14:35,242 --> 00:14:38,009\nwith this selected, with this cell selected, and\n\n294\n00:14:38,011 --> 00:14:41,479\nsay that it's a my Tableview cell. And the reason you're\n\n295\n00:14:41,481 --> 00:14:43,648\ngonna do that sub-class is so that you can have outlets and\n\n296\n00:14:43,650 --> 00:14:45,650\nstuff. Just like the same reason you do it for\n\n297\n00:14:45,652 --> 00:14:47,418\na controller, but this is not a controller,\n\n298\n00:14:47,420 --> 00:14:49,087\nthis is a UI View subclass, actually.\n\n299\n00:14:49,089 --> 00:14:53,124\nUI TableView cell is a UI view subclass. All right. So now\n\n300\n00:14:53,126 --> 00:14:56,294\nonce you have that, you can wire up all the outlets and\n\n301\n00:14:56,296 --> 00:14:57,095\nactions you want, okay?\n\n302\n00:14:57,097 --> 00:14:58,263\nAnd we're gonna do this in the demo and\n\n303\n00:14:58,265 --> 00:15:00,431\nmake maybe a lot more sense. So, here's an example.\n\n304\n00:15:00,433 --> 00:15:04,369\nI'm creating an outlet to this label in my UI table view cell\n\n305\n00:15:04,371 --> 00:15:11,476\nsubclass, you see that? Okay? All right. And again,\n\n306\n00:15:11,478 --> 00:15:13,578\nremember it's a prototype, it's gonna be duplicated.\n\n307\n00:15:13,580 --> 00:15:17,081\nAll your label, this label and all the stuff and, it's\n\n308\n00:15:17,083 --> 00:15:20,418\ngonna be a different instance of this for every row, okay?\n\n309\n00:15:20,420 --> 00:15:24,122\nAll right. So, let's talk about those protocols that\n\n310\n00:15:24,124 --> 00:15:26,824\nwe're talking about dataSource and delegate, okay?\n\n311\n00:15:26,826 --> 00:15:30,295\nThere's two of them because the delegate controls how\n\n312\n00:15:30,297 --> 00:15:34,432\nthe table is displayed, okay? The dataSource controls what\n\n313\n00:15:34,434 --> 00:15:38,236\ndata is in the table, okay? What's in the rows, okay?\n\n314\n00:15:38,238 --> 00:15:40,705\nSo that's the difference between the two delegates.\n\n315\n00:15:40,707 --> 00:15:44,242\nNow, the UITableViewController automatically sets itself as\n\n316\n00:15:44,244 --> 00:15:47,478\nthe delegate, and as the data source. So, it's all preset\n\n317\n00:15:47,480 --> 00:15:50,148\nup. And as I told you, the view, the top level view,\n\n318\n00:15:50,150 --> 00:15:54,252\nis a UITableView. There's also a var called TableView which,\n\n319\n00:15:54,254 --> 00:15:56,921\nthe computed var, that just returns the view.\n\n320\n00:15:56,923 --> 00:15:59,757\nOkay, so that usually will access the table view,\n\n321\n00:15:59,759 --> 00:16:01,693\nbecause it's typed to be UITableView,\n\n322\n00:16:01,695 --> 00:16:03,861\nthat's how we access our table view inside of\n\n323\n00:16:03,863 --> 00:16:07,899\nour table view controller sub class code. All right.\n\n324\n00:16:07,901 --> 00:16:10,435\nAll right, so when do we need to implement the data source?\n\n325\n00:16:10,437 --> 00:16:14,072\nOnly if we're doing dynamic cells. If we're doing static,\n\n326\n00:16:14,074 --> 00:16:15,673\nlike, you know, the settings example, the group\n\n327\n00:16:15,675 --> 00:16:17,909\nsettings thing. Then you just do it in your storyboard,\n\n328\n00:16:17,911 --> 00:16:20,545\nyou don't need to do anything in the dataSource protocol to\n\n329\n00:16:20,547 --> 00:16:24,682\nmake that work. Okay? But if you're doing dynamic,\n\n330\n00:16:24,684 --> 00:16:26,751\nyou need to do it. And there are three very important\n\n331\n00:16:26,753 --> 00:16:28,920\nmethods in the dataSource protocol, there's a bunch of\n\n332\n00:16:28,922 --> 00:16:31,422\nmethods in there, but there's three really important ones.\n\n333\n00:16:31,424 --> 00:16:34,092\nOne is how many sections are in this table?\n\n334\n00:16:34,094 --> 00:16:36,461\nHow many rows are in each of the sections?\n\n335\n00:16:36,463 --> 00:16:37,462\nIt's gonna ask for every section,\n\n336\n00:16:37,464 --> 00:16:39,430\nhow many rows in this section? How many rows in this section?\n\n337\n00:16:39,432 --> 00:16:42,767\nHow many rows in this section? And then, give me a view,\n\n338\n00:16:42,769 --> 00:16:46,871\na UI table view cell subclass to draw this row, okay?\n\n339\n00:16:46,873 --> 00:16:49,207\nAnd that's when you're gonna implement cell for\n\n340\n00:16:49,209 --> 00:16:51,476\nrow at index path and give it your sub class,\n\n341\n00:16:51,478 --> 00:16:52,577\nan instance of your sub class. And\n\n342\n00:16:52,579 --> 00:16:56,014\nI'm going to show exactly how you do that in a second here.\n\n343\n00:16:56,549 --> 00:16:56,714\nto skip the two easy ones, the number of sections and rows,\n\n344\n00:16:56,716 --> 00:16:59,117\nSo we're going\n\n345\n00:16:59,119 --> 00:17:01,953\nand go straight to cell for row at index path. Okay?\n\n346\n00:17:01,955 --> 00:17:05,156\nSo this method looks like this. Okay?\n\n347\n00:17:05,158 --> 00:17:09,193\nI already talked about the fact that it's reusing here.\n\n348\n00:17:09,662 --> 00:17:11,796\nAnd the method's called cell for row at index path,\n\n349\n00:17:11,798 --> 00:17:16,167\nyou can see that it returns a UITablViewCell, right here.\n\n350\n00:17:16,169 --> 00:17:19,837\nThis index path is really just the section and\n\n351\n00:17:19,839 --> 00:17:23,207\nrow, section and the row in that section, okay? They could\n\n352\n00:17:23,209 --> 00:17:27,478\nhave called this cell for row at section in row, two\n\n353\n00:17:27,480 --> 00:17:29,414\nseparate arguments, but they decided to call it cell for\n\n354\n00:17:29,416 --> 00:17:31,449\nrow and index path and they just made a thing called\n\n355\n00:17:31,451 --> 00:17:33,851\nNSIndexPath that's got the section row in it, okay?\n\n356\n00:17:33,853 --> 00:17:37,789\nAnd in fact, if you wanted to, like, get your data, you would\n\n357\n00:17:37,791 --> 00:17:41,192\njust say let the data equal my internal data structure,\n\n358\n00:17:41,194 --> 00:17:44,262\nwhatever that is. IndexPath subsection, indexPath.row,\n\n359\n00:17:44,264 --> 00:17:46,831\nthat will tell your internal data structure where an array\n\n360\n00:17:46,833 --> 00:17:50,001\nof arrays, where the sections were in there in the rows,\n\n361\n00:17:50,003 --> 00:17:52,036\nyou can just do this. So this is how you get the section,\n\n362\n00:17:52,038 --> 00:17:55,773\nand this is how you get the row, okay? So\n\n363\n00:17:55,775 --> 00:17:57,075\nthen you have to take the data\n\n364\n00:17:57,077 --> 00:17:58,776\nthat corresponds to that section and row, and\n\n365\n00:17:58,778 --> 00:18:03,247\nyou have to load it up into a UITableViewCell. Okay, so\n\n366\n00:18:03,249 --> 00:18:05,183\nlet's talk about how that works. And\n\n367\n00:18:05,185 --> 00:18:08,352\nwhile I'm doing this, I'm gonna move this code on top of\n\n368\n00:18:08,354 --> 00:18:11,622\nthe storyboard so that we can see the storyboard at the same\n\n369\n00:18:11,624 --> 00:18:14,959\ntime we're looking at the code, okay? So here's how you\n\n370\n00:18:14,961 --> 00:18:19,097\nget the cell, okay? You call this table view method, okay?\n\n371\n00:18:19,099 --> 00:18:21,966\nThis is the table view here that's passed along, table\n\n372\n00:18:21,968 --> 00:18:26,170\nview first argument. Dequeued reusable cell with identifier.\n\n373\n00:18:26,172 --> 00:18:30,208\nThat's the thing that's reusing these cells. Okay?\n\n374\n00:18:30,210 --> 00:18:33,144\nAs things go off screen, they get put back into this reuse\n\n375\n00:18:33,146 --> 00:18:35,947\nqueue, and when people call this they get pulled out.\n\n376\n00:18:35,949 --> 00:18:39,450\nOkay? If there's not one available in the reuse queue,\n\n377\n00:18:39,452 --> 00:18:42,720\nit makes one. It copies your prototype to make one.\n\n378\n00:18:42,722 --> 00:18:47,225\nOkay? This says which prototype to use. Each of\n\n379\n00:18:47,227 --> 00:18:50,561\nthese prototypes can have a different identifier. You just\n\n380\n00:18:50,563 --> 00:18:54,599\nselect the row, and go into your storyboard, okay? And\n\n381\n00:18:54,601 --> 00:18:57,068\nyou set the identifier. Just like when you do with a segue,\n\n382\n00:18:57,070 --> 00:18:59,770\nright? In a segue you set the identifier? Same thing here.\n\n383\n00:18:59,772 --> 00:19:01,839\nYou're just saying what the name of this is so\n\n384\n00:19:01,841 --> 00:19:04,942\nthat in your code, you can dequeue the kind of\n\n385\n00:19:04,944 --> 00:19:07,044\none you want. So if you have multiple prototypes\n\n386\n00:19:07,046 --> 00:19:10,448\nyou'll dequeue the right one here. And maybe some sections\n\n387\n00:19:10,450 --> 00:19:13,151\nuse one kind of thing, and some sections use a different.\n\n388\n00:19:13,153 --> 00:19:14,585\nThat's probably going to be in your homework, right?\n\n389\n00:19:14,587 --> 00:19:16,888\nYou're gonna have a section using one of the prototypes\n\n390\n00:19:16,890 --> 00:19:19,824\nand a different section uses a different one, okay? Perfectly\n\n391\n00:19:19,826 --> 00:19:24,162\nfine. So after you get the cell, which I call dequeued\n\n392\n00:19:24,164 --> 00:19:29,133\nhere by referencing that, you are going to load this cell\n\n393\n00:19:29,135 --> 00:19:33,938\nup with the data from your internal data structure.\n\n394\n00:19:33,940 --> 00:19:37,141\nSee, data is this data right here, okay? And\n\n395\n00:19:37,143 --> 00:19:40,444\nI'm just gonna put this in this title, in subtitle.\n\n396\n00:19:40,446 --> 00:19:42,647\nNow you have to go look at the documentation for\n\n397\n00:19:42,649 --> 00:19:46,184\nUITableVIewCell, this is not a custom cell, right?\n\n398\n00:19:46,186 --> 00:19:48,886\nThis is of type subtitle. So it's just a built\n\n399\n00:19:48,888 --> 00:19:51,956\nin one, it only has these two things. If you'll look at\n\n400\n00:19:51,958 --> 00:19:53,424\nthe documentation for UITableViewCell,\n\n401\n00:19:53,426 --> 00:19:56,594\nyou'll see that it has a property called text label,\n\n402\n00:19:56,596 --> 00:19:59,664\nwhich corresponds to that title thing, and detail text\n\n403\n00:19:59,666 --> 00:20:03,568\nlabel, which corresponds to this little text label. Okay?\n\n404\n00:20:03,570 --> 00:20:07,438\nSo you can set the text of those things here.\n\n405\n00:20:07,440 --> 00:20:10,875\nTo whatever information, important information or\n\n406\n00:20:10,877 --> 00:20:13,477\nless important information, from your data,\n\n407\n00:20:13,479 --> 00:20:16,847\ninternal data structure. Then you just return the cell and\n\n408\n00:20:16,849 --> 00:20:20,518\nthat's it. Okay so you dequeue the cell, load it up with\n\n409\n00:20:20,520 --> 00:20:21,452\nthe information at that section and\n\n410\n00:20:21,454 --> 00:20:25,189\nrow in your data structure, and return it. Any question\n\n411\n00:20:25,191 --> 00:20:28,626\nabout that? Okay, now let's talk about the custom case.\n\n412\n00:20:28,628 --> 00:20:30,661\nLet's say you have a custom cell, okay? So\n\n413\n00:20:30,663 --> 00:20:33,698\nnow my type here is custom, I got this label, but I could\n\n414\n00:20:33,700 --> 00:20:36,601\nhave all kinds of buttons and stuff in here. In this\n\n415\n00:20:36,603 --> 00:20:39,971\ncase you do the same thing, dequeueReusableCell, okay?\n\n416\n00:20:39,973 --> 00:20:42,773\nProbably has a different identifier here.\n\n417\n00:20:42,775 --> 00:20:47,445\nOkay, then instead of doing that textLabel.text equals\n\n418\n00:20:47,447 --> 00:20:50,715\ndetailtextLabel.whatever equals, you just\n\n419\n00:20:50,717 --> 00:20:55,386\ncall some public API in your subclass of TableViewCell that\n\n420\n00:20:55,388 --> 00:20:58,656\npasses the information to it. Then it's gonna take that and\n\n421\n00:20:58,658 --> 00:21:03,728\nput it in all of its outlets. Okay? Make sense?\n\n422\n00:21:03,730 --> 00:21:06,564\nSo it's very very simple. Notice that I'm having to take\n\n423\n00:21:06,566 --> 00:21:11,435\nthe cell which gets dequeued as a UITableViewCell and\n\n424\n00:21:11,437 --> 00:21:15,506\nI'm having to cast it here to be MyTableViewCell so\n\n425\n00:21:15,508 --> 00:21:19,010\nI can call this public function in MyTableViewCell.\n\n426\n00:21:19,012 --> 00:21:21,779\nSee? Otherwise I wouldn't be able to call it because\n\n427\n00:21:21,781 --> 00:21:22,813\ndequeued would be a UITableViewCell,\n\n428\n00:21:22,815 --> 00:21:30,054\nnot a subclass of it. Everybody got that? Okay.\n\n429\n00:21:30,056 --> 00:21:31,856\nThe UITableViewlDataSource that cell for\n\n430\n00:21:31,858 --> 00:21:34,558\nrow at index path is the most important thing in it.\n\n431\n00:21:34,560 --> 00:21:37,762\nThe other two here, number of sections in TableView and\n\n432\n00:21:37,764 --> 00:21:41,966\nTableView's number of rows and section are the other two.\n\n433\n00:21:41,968 --> 00:21:44,835\nThe number of sections by default is one. So if\n\n434\n00:21:44,837 --> 00:21:47,972\nyou don't implement number of sections in table view at all,\n\n435\n00:21:47,974 --> 00:21:50,308\nyou just don't even implement it, it'll be one,\n\n436\n00:21:50,310 --> 00:21:54,478\nokay? But the other one has to be implemented because\n\n437\n00:21:54,480 --> 00:21:57,148\nthe TableView has to know how many rows there are.\n\n438\n00:21:57,150 --> 00:21:59,317\nTableView cannot survive unless it knows how many rows\n\n439\n00:21:59,319 --> 00:22:02,420\nthere are. So you have to implement this number of rows\n\n440\n00:22:02,422 --> 00:22:04,722\nin section right here. And it's simple, it's just gives\n\n441\n00:22:04,724 --> 00:22:06,691\nyou the section. You return how many rows are in that\n\n442\n00:22:06,693 --> 00:22:09,627\nsection, okay? And it's gonna call that repeatedly, once for\n\n443\n00:22:09,629 --> 00:22:12,897\nevery section. Okay, what about in a static table?\n\n444\n00:22:12,899 --> 00:22:15,199\nYou don't have to do any of this, okay? Static table,\n\n445\n00:22:15,201 --> 00:22:19,103\nit's fixed in your storyboard. All right? So that's how our\n\n446\n00:22:19,105 --> 00:22:22,940\ntable dataSource works. The section titles like you\n\n447\n00:22:22,942 --> 00:22:24,742\nremember I showed you the section had Japan and\n\n448\n00:22:24,744 --> 00:22:27,478\nthe Japan things, and then Mexico and the Mexico cities?\n\n449\n00:22:27,480 --> 00:22:30,247\nWell those titles like Japan, those are considered part of\n\n450\n00:22:30,249 --> 00:22:33,451\nthe data, as you might imagine. So there's another\n\n451\n00:22:33,453 --> 00:22:36,153\nTableView dataSource method called TableView,\n\n452\n00:22:36,155 --> 00:22:39,090\ntitleForHeader or FooterInSection. Okay?\n\n453\n00:22:39,092 --> 00:22:40,991\nYou give it this section and you return to string.\n\n454\n00:22:40,993 --> 00:22:44,528\nOr there's another one that you can return a view,\n\n455\n00:22:44,530 --> 00:22:45,796\na UI view, okay? So\n\n456\n00:22:45,798 --> 00:22:49,133\nthat's how you set the headers of your tables. There's\n\n457\n00:22:49,135 --> 00:22:51,602\na number of other methods in here that have to do with\n\n458\n00:22:51,604 --> 00:22:54,238\nediting and moving rows because when you're deleting\n\n459\n00:22:54,240 --> 00:22:56,140\nrows you're affecting your data source, right?\n\n460\n00:22:56,142 --> 00:22:57,508\nYour deleting the data out of your data source.\n\n461\n00:22:57,510 --> 00:23:00,144\nSo those can get involved, I'm not going to talk about those.\n\n462\n00:23:00,146 --> 00:23:03,013\nBut this is the kind of thing you probably want to do either\n\n463\n00:23:03,015 --> 00:23:06,584\nfor the extra credit or in your final project.\n\n464\n00:23:06,586 --> 00:23:08,319\nYou're almost certainly going to want to have a table.\n\n465\n00:23:08,321 --> 00:23:10,087\nAt least one where you can delete the rows or\n\n466\n00:23:10,089 --> 00:23:12,423\nmove them around. Or something, or insert rows.\n\n467\n00:23:12,425 --> 00:23:17,628\nEtc. Okay? Now, what about segueing from TableView cells?\n\n468\n00:23:17,630 --> 00:23:20,898\nHow do you do that? Exactly as you might imagine [LAUGH], you\n\n469\n00:23:20,900 --> 00:23:24,168\njust control drag from them to the MVC you want to segue to,\n\n470\n00:23:24,170 --> 00:23:27,138\nand when you do you're gonna get to choose what kind of\n\n471\n00:23:27,140 --> 00:23:28,906\nsegue you want, show or show detail,\n\n472\n00:23:28,908 --> 00:23:31,976\nor eventually we'll talk about these other kinds of segues.\n\n473\n00:23:31,978 --> 00:23:36,414\nOkay, if you have that little blue i, told you I'd get back\n\n474\n00:23:36,416 --> 00:23:40,584\nto that, here it is, you can control+drag from it, over,\n\n475\n00:23:40,586 --> 00:23:44,321\nand when you choose your segue, you choose it from this\n\n476\n00:23:44,323 --> 00:23:48,058\npart that says Accessory Action down here. And when you\n\n477\n00:23:48,060 --> 00:23:51,328\nhave a little i here, if you click on the row it will do\n\n478\n00:23:51,330 --> 00:23:55,733\nwhatever segue is specified by the top selection segue thing.\n\n479\n00:23:55,735 --> 00:23:57,902\nAnd if you Click just on the blue i,\n\n480\n00:23:57,904 --> 00:24:02,072\nyou'll get whatever segue is hooked up here, okay? So\n\n481\n00:24:02,074 --> 00:24:04,108\nyou can basically have a row that has two different segues,\n\n482\n00:24:04,110 --> 00:24:07,545\none if you click on the i and one if you click on the row.\n\n483\n00:24:08,414 --> 00:24:11,882\nAll right, you set your segue identifier as usual,\n\n484\n00:24:11,884 --> 00:24:12,850\nnothing special there. But\n\n485\n00:24:12,852 --> 00:24:15,953\nto prepareForSegue obviously is gonna be a little different\n\n486\n00:24:15,955 --> 00:24:17,087\nwhen you're segueing from a row. So\n\n487\n00:24:17,089 --> 00:24:19,657\nlet's look at prepareForSegue. And the difference is all\n\n488\n00:24:19,659 --> 00:24:22,793\nabout who the sender is. Normally, the sender in\n\n489\n00:24:22,795 --> 00:24:24,528\nprepareForSegue is like the UI button you clicked\n\n490\n00:24:24,530 --> 00:24:26,430\non that caused the segue to happen. Well, here,\n\n491\n00:24:26,432 --> 00:24:30,367\nof course, the sender is the UITableViewCell you clicked\n\n492\n00:24:30,369 --> 00:24:34,138\non, okay. So you're gonna have to get that UITableViewCell,\n\n493\n00:24:34,140 --> 00:24:36,941\nand since this is any object, you're gonna have to convert\n\n494\n00:24:36,943 --> 00:24:39,376\nit to either MyTableViewCell if it's custom,\n\n495\n00:24:39,378 --> 00:24:42,680\nor UITableViewCell if it's not custom. Then you're gonna call\n\n496\n00:24:42,682 --> 00:24:47,151\nthis very important method in tableView.indexPathforCell,\n\n497\n00:24:47,153 --> 00:24:49,620\nokay. It's gonna give you an NSIndexPath that's\n\n498\n00:24:49,622 --> 00:24:52,990\nbasically gonna tell you which row in which section\n\n499\n00:24:52,992 --> 00:24:55,593\nyou're segueing from. Cuz if you're preparing,\n\n500\n00:24:55,595 --> 00:24:57,828\nyou gotta know which row it came from so you know\n\n501\n00:24:57,830 --> 00:25:00,531\nhow to prepare with the guy you're segueing to. Okay, so\n\n502\n00:25:00,533 --> 00:25:04,368\nthen you just take, you get your destinationViewController\n\n503\n00:25:04,370 --> 00:25:04,435\nOkay, this is just like in any other, prepareForSegue.\n\n504\n00:25:04,437 --> 00:25:07,371\nas usual.\n\n505\n00:25:07,373 --> 00:25:11,008\nAnd then you get your data out of your model, okay,\n\n506\n00:25:11,010 --> 00:25:14,311\nin your TableViewController, in that section and row. Okay,\n\n507\n00:25:14,313 --> 00:25:16,580\nhowever, you might have to call a function to do that or\n\n508\n00:25:16,582 --> 00:25:19,416\nhowever you do it, and then you just assign that\n\n509\n00:25:19,418 --> 00:25:22,219\nto the public API of the thing you are segueing to just like\n\n510\n00:25:22,221 --> 00:25:25,422\nyou normally would in any prepareForSegue.\n\n511\n00:25:25,424 --> 00:25:27,658\nOkay, so the magic is just this little thing,\n\n512\n00:25:27,660 --> 00:25:30,094\nindexPathForCell, don't forget about that,\n\n513\n00:25:30,096 --> 00:25:32,830\nokay. That's how you figure out which row you're segueing\n\n514\n00:25:32,832 --> 00:25:36,767\nfrom. All right, how about the UITableViewDelegate,\n\n515\n00:25:36,769 --> 00:25:38,702\nnot the dataSource but the delegate?\n\n516\n00:25:38,704 --> 00:25:41,805\nIt has a lot of stuff for how the table view works.\n\n517\n00:25:41,807 --> 00:25:43,274\nI'm not gonna talk a lot about it but\n\n518\n00:25:43,276 --> 00:25:46,277\nI'll talk about a couple of interesting one.\n\n519\n00:25:46,279 --> 00:25:49,146\nUsually the dataSource and the delegate are the same object,\n\n520\n00:25:49,148 --> 00:25:50,147\nnamely your controller,\n\n521\n00:25:50,149 --> 00:25:52,983\nyour TableViewController. The delegate lets you\n\n522\n00:25:52,985 --> 00:25:56,353\nobserve what's going on inside the table, okay?\n\n523\n00:25:56,355 --> 00:25:58,255\nIt has a lot of will do something,\n\n524\n00:25:58,257 --> 00:26:00,257\ndid do something kind of methods in it.\n\n525\n00:26:00,259 --> 00:26:03,093\nIt has a very interesting one which is to let you know when\n\n526\n00:26:03,095 --> 00:26:06,096\nthe user selects a row, when a user touches on a row. Now\n\n527\n00:26:06,098 --> 00:26:08,532\nnormally when they touch on a row, you're just gonna segue,\n\n528\n00:26:08,534 --> 00:26:10,601\nbut sometimes you might wanna touch on a row in a table and\n\n529\n00:26:10,603 --> 00:26:12,603\nnot segue. You wanna do something else, okay?\n\n530\n00:26:12,605 --> 00:26:14,538\nAnd so this gives you, kind of, ta,\n\n531\n00:26:14,540 --> 00:26:18,008\nTableView Target/Action, okay. The way you do that,\n\n532\n00:26:18,010 --> 00:26:20,578\nis you implement this method in your controller,\n\n533\n00:26:20,580 --> 00:26:25,349\ndidSelectRowAtIndexPath, okay. And the table view will send\n\n534\n00:26:25,351 --> 00:26:28,485\nyou this whenever someone touches on a row, and\n\n535\n00:26:28,487 --> 00:26:33,724\nthis is just telling you which row they touched on, okay,\n\n536\n00:26:33,726 --> 00:26:37,227\nsimple. Another interesting one is if they\n\n537\n00:26:37,229 --> 00:26:40,564\npress on that little i, the little circled blue i,\n\n538\n00:26:40,566 --> 00:26:43,300\nyou'll get this method, accessory button tapped for\n\n539\n00:26:43,302 --> 00:26:47,104\nrow with index path. Okay, so you can find out that the i\n\n540\n00:26:47,106 --> 00:26:50,307\nbutton was pressed. Again, you might be segueing instead,\n\n541\n00:26:50,309 --> 00:26:53,877\nbut you can do, you can get notified if you want\n\n542\n00:26:53,879 --> 00:26:56,213\nalternatively. Lots of other methods,\n\n543\n00:26:56,215 --> 00:27:00,184\nI'm not really have time to talk about them all. So, you,\n\n544\n00:27:00,186 --> 00:27:03,020\nproviding the UIView for headers and\n\n545\n00:27:03,022 --> 00:27:08,926\nfooters is kind of a drawing thing so they do that.\n\n546\n00:27:08,928 --> 00:27:09,760\nEditing and moving the rows,\n\n547\n00:27:09,762 --> 00:27:11,395\nthere's not just a data source element to it,\n\n548\n00:27:11,397 --> 00:27:14,331\nthere's actually the visual moving the rows.\n\n549\n00:27:14,333 --> 00:27:17,434\nIt gets involved in that, that kind of thing, okay?\n\n550\n00:27:17,436 --> 00:27:21,372\nNow what if your model changes in your table view controller,\n\n551\n00:27:21,374 --> 00:27:22,640\nright, the underlying data? Well,\n\n552\n00:27:22,642 --> 00:27:25,442\nyou need all those sections and rows to change, right?\n\n553\n00:27:25,444 --> 00:27:27,044\nYou might have a different number of sections and\n\n554\n00:27:27,046 --> 00:27:28,612\na different number of rows in each section.\n\n555\n00:27:28,614 --> 00:27:30,280\nSo you're gonna call this method and\n\n556\n00:27:30,282 --> 00:27:31,615\ntable you'll call it reloadData.\n\n557\n00:27:31,617 --> 00:27:33,817\nAnd that causes the table view to go back and\n\n558\n00:27:33,819 --> 00:27:36,820\ncall all those methods, numberOfSectionsInTable,\n\n559\n00:27:36,822 --> 00:27:38,822\nnumber of rows in each section, cell or\n\n560\n00:27:38,824 --> 00:27:40,824\nrow at indexPath for all the visible cells,\n\n561\n00:27:40,826 --> 00:27:44,294\ncall them all again, okay, to get your table view reset up.\n\n562\n00:27:44,296 --> 00:27:45,629\nNow that might seem kinda heavy weight, and\n\n563\n00:27:45,631 --> 00:27:48,632\nfor a large table, maybe it would be. So if you know how\n\n564\n00:27:48,634 --> 00:27:52,302\nyour model changed such that you know which index paths,\n\n565\n00:27:52,304 --> 00:27:54,738\nwhich sections and which sections and rows,\n\n566\n00:27:54,740 --> 00:27:58,575\nlike maybe only one section would have been changed. Then\n\n567\n00:27:58,577 --> 00:28:03,781\nyou can try this more fine tuned reloadRowsAtIndexPaths,\n\n568\n00:28:03,783 --> 00:28:09,520\nwhich is just like reloadData but only certain index paths,\n\n569\n00:28:09,522 --> 00:28:11,789\nokay? How about the height of rows,\n\n570\n00:28:11,791 --> 00:28:13,991\nhow tall are rows? Rows are a fixed width.\n\n571\n00:28:13,993 --> 00:28:15,659\nThey're the entire width of of the table, but\n\n572\n00:28:15,661 --> 00:28:18,696\nwhat about the height? Normally the height is\n\n573\n00:28:18,698 --> 00:28:21,932\njust set in the inspector in your storyboard and\n\n574\n00:28:21,934 --> 00:28:24,601\nit's fixed. All of the rows are exactly the same height\n\n575\n00:28:24,603 --> 00:28:27,071\nrows of a certain prototype, all the rows that ma, or\n\n576\n00:28:27,073 --> 00:28:28,439\nof a certain prototype the same height.\n\n577\n00:28:28,441 --> 00:28:31,975\nBut it is possible to let the system calculate the proper\n\n578\n00:28:31,977 --> 00:28:36,113\nheight, and have the rows be different heights, okay.\n\n579\n00:28:36,115 --> 00:28:37,181\nSo it'll use autolayout,\n\n580\n00:28:37,183 --> 00:28:40,317\nright, inside the area of custom cell to figure out how\n\n581\n00:28:40,319 --> 00:28:42,920\nhigh it should be, and then make it that high, and\n\n582\n00:28:42,922 --> 00:28:45,322\nit'll do that for every row. But if you're doing that and\n\n583\n00:28:45,324 --> 00:28:48,559\nyou had a thousand rows, think about is really,\n\n584\n00:28:48,561 --> 00:28:50,661\nthe system's gonna load up a cell for\n\n585\n00:28:50,663 --> 00:28:53,697\nevery single one of those 10,000 rows? Do the autolayout\n\n586\n00:28:53,699 --> 00:28:56,400\non each one to figure how big the table is? No way,\n\n587\n00:28:56,402 --> 00:28:58,402\nthat would be horrendously inefficient. So\n\n588\n00:28:58,404 --> 00:29:01,972\ninstead, it asks you to tell it an estimated height and\n\n589\n00:29:01,974 --> 00:29:05,175\nuses the estimated height just to estimate the total size\n\n590\n00:29:05,177 --> 00:29:08,178\nof the table view. But then as one comes on screen,\n\n591\n00:29:08,180 --> 00:29:10,681\nit makes it to be the actual height based on using\n\n592\n00:29:10,683 --> 00:29:14,184\nthe autolayout. And the way you make it do the autolayout\n\n593\n00:29:14,186 --> 00:29:17,588\nis with this height UITableViewAutomaticDimension.\n\n594\n00:29:17,590 --> 00:29:19,857\nThat's a special height which means calculate it for\n\n595\n00:29:19,859 --> 00:29:24,762\nme using autolayout. Okay, you can also control the height.\n\n596\n00:29:24,764 --> 00:29:26,497\nAnd you're probably gonna do this, hint hint,\n\n597\n00:29:26,499 --> 00:29:28,632\nyou probably gonna do this in your homework assignment.\n\n598\n00:29:28,634 --> 00:29:32,302\nYou control that height right here with a method that'll get\n\n599\n00:29:32,304 --> 00:29:33,203\nsent to you, okay.\n\n600\n00:29:33,205 --> 00:29:34,671\nThe table view will send you this message,\n\n601\n00:29:34,673 --> 00:29:37,708\nheightForRowAtIndexPath. It'll give you the indexPath,\n\n602\n00:29:37,710 --> 00:29:40,410\nand it's asking you to tell it the height, okay.\n\n603\n00:29:40,412 --> 00:29:43,113\nAnd in here, you could calculate the height. So maybe\n\n604\n00:29:43,115 --> 00:29:45,215\nyou don't want autolayout to make the decision about the\n\n605\n00:29:45,217 --> 00:29:49,620\nheight, you wanna calculate it based on something else, okay,\n\n606\n00:29:49,622 --> 00:29:51,855\nsome information that you might have about what's in\n\n607\n00:29:51,857 --> 00:29:55,292\nthat cell, okay? So you don't wanna use autolayout to it,\n\n608\n00:29:55,294 --> 00:29:58,395\nthat's fine, you can calculate it here. So here's a big hint,\n\n609\n00:29:58,397 --> 00:30:00,330\nyou're gonna wanna do this in your homework,\n\n610\n00:30:00,332 --> 00:30:04,968\nokay? All right, so there's, in the TableView itself, we're\n\n611\n00:30:04,970 --> 00:30:07,404\ntalking about its delegate methods, in the TableView\n\n612\n00:30:07,406 --> 00:30:09,773\nitself, there are tons and tons of methods, okay?\n\n613\n00:30:09,775 --> 00:30:11,942\nCan't go over them all, you're gonna wanna look to them,\n\n614\n00:30:11,944 --> 00:30:15,712\nlook for them. But, you know, things like scrolling around\n\n615\n00:30:15,714 --> 00:30:17,681\nin there. The UITableView actually turns out to be\n\n616\n00:30:17,683 --> 00:30:21,318\na subclass of UIScrollView, so it inherits all the ability\n\n617\n00:30:21,320 --> 00:30:24,588\nUIScrollView can to scroll around and stuff like that. So\n\n618\n00:30:24,590 --> 00:30:27,191\nyou're gonna go take a look at UITableView and understand\n\n619\n00:30:27,193 --> 00:30:29,193\nwhat it can do. But you're controlling the TableView\n\n620\n00:30:29,195 --> 00:30:32,262\nmostly by these delegates, okay. But you can also send\n\n621\n00:30:32,264 --> 00:30:35,265\nmessages directly to TableView to make it do things.\n\n622\n00:30:35,267 --> 00:30:38,335\nAll right, so that's it on the slides for TableView.\n\n623\n00:30:38,337 --> 00:30:42,339\nAssignment 4 out, okay, it's basically going to be to do\n\n624\n00:30:42,341 --> 00:30:45,309\na better version of the demo I'm doing today.\n\n625\n00:30:45,311 --> 00:30:47,344\nSo you're gonna start with what I have today and\n\n626\n00:30:47,346 --> 00:30:50,280\nyou're gonna improve it, okay? It's gonna be due in a week,\n\n627\n00:30:50,282 --> 00:30:54,151\nnext Monday. On Wednesday, we're gonna start a two day\n\n628\n00:30:54,153 --> 00:30:58,255\nlecture on Core Data, which is object oriented database.\n\n629\n00:30:58,257 --> 00:31:01,258\nAnd next week's assignment is going to be enhance what\n\n630\n00:31:01,260 --> 00:31:04,962\nyou're building this week to include an object oriented\n\n631\n00:31:04,964 --> 00:31:06,096\ndatabase in there, okay.\n\n632\n00:31:06,098 --> 00:31:08,232\nObviously, we're dealing with big data sets,\n\n633\n00:31:08,234 --> 00:31:10,267\nit would make sense to put it in a database so\n\n634\n00:31:10,269 --> 00:31:11,668\nwe can query on it, things like that.\n\n635\n00:31:11,670 --> 00:31:14,705\nOn Friday, if there's enough interest, which is still to be\n\n636\n00:31:14,707 --> 00:31:18,008\ndetermined, watch the bulletin boards in the class to find\n\n637\n00:31:18,010 --> 00:31:19,710\nout, we might have UICollectionView.\n\n638\n00:31:19,712 --> 00:31:22,713\nNow UICollectionView is just like TableView, except for\n\n639\n00:31:22,715 --> 00:31:25,382\nit's much more flexible. It's not just rows,\n\n640\n00:31:25,384 --> 00:31:28,352\nit can lay things out in almost any arrangement.\n\n641\n00:31:28,354 --> 00:31:31,021\nBut it's still the same kind of thing, with the number of\n\n642\n00:31:31,023 --> 00:31:33,824\nsections, number of rows, all that. It's just that they're\n\n643\n00:31:33,826 --> 00:31:36,126\nnot called rows, they're just number of items, okay,\n\n644\n00:31:36,128 --> 00:31:38,929\nbecause they can be laid out in different ways.\n\n645\n00:31:38,931 --> 00:31:42,132\nSo now I'm going to do a demo, okay, it's a TableView demo.\n\n646\n00:31:42,134 --> 00:31:46,336\nWe're going to build a Twitter client, okay. I'm calling\n\n647\n00:31:46,338 --> 00:31:50,507\nit Smash Tag because hashtags are at the middle of it, and\n\n648\n00:31:50,509 --> 00:31:55,279\nso Smash Tag is kind of a fun name for it. So let's go here.\n\n649\n00:31:55,281 --> 00:31:55,946\nI'm just gonna go to Xcode,\n\n650\n00:31:55,948 --> 00:31:58,415\nwe're gonna start from scratch, as a brand new app,\n\n651\n00:31:58,417 --> 00:32:00,651\nokay. This is an iOS application as usual,\n\n652\n00:32:00,653 --> 00:32:04,388\nsingle view as always. We'll call it Smashtag here.\n\n653\n00:32:04,390 --> 00:32:07,858\nThis one's gonna be iPhone only, okay, this app's gonna\n\n654\n00:32:07,860 --> 00:32:09,826\nbe iPhone only. You will only be required\n\n655\n00:32:09,828 --> 00:32:11,428\nto do iPhone as well. You don't have to do,\n\n656\n00:32:11,430 --> 00:32:14,898\nyou've already kind of learned your split view doing it on\n\n657\n00:32:14,900 --> 00:32:16,867\nmultiple, so you don't have to do that again. So\n\n658\n00:32:16,869 --> 00:32:18,201\nwe'll put it in the same place we put everything,\n\n659\n00:32:18,203 --> 00:32:22,472\nhome directory developer, okay. Here it is. I'm gonna\n\n660\n00:32:22,474 --> 00:32:25,809\nclean up a little bit by going to my storyboard right here.\n\n661\n00:32:25,811 --> 00:32:28,745\nHere's my storyboard, and I'll zoom out so you can see it. It\n\n662\n00:32:28,747 --> 00:32:31,615\ncomes with this pre-packaged freebie view controller.\n\n663\n00:32:31,617 --> 00:32:34,751\nI don't even want that, so I'm just gonna delete that\n\n664\n00:32:34,753 --> 00:32:36,420\nokay and ditto the code that came with\n\n665\n00:32:36,422 --> 00:32:39,289\nit too right here. I'm just gonna delete this, get that\n\n666\n00:32:39,291 --> 00:32:42,426\nout of there and move it to the trash. We'll go ahead and\n\n667\n00:32:42,428 --> 00:32:45,595\nput all these other things into, not our storyboard, but\n\n668\n00:32:45,597 --> 00:32:48,799\nthese things into this little supporting files like we\n\n669\n00:32:48,801 --> 00:32:54,338\nusually do. Supporting 14 files. Okay,\n\n670\n00:32:54,340 --> 00:32:57,407\nso we're left with really a pretty much a blank app here.\n\n671\n00:32:57,409 --> 00:33:00,344\nOkay, storyboard's got nothing in it, and we're gonna have\n\n672\n00:33:00,346 --> 00:33:03,013\none view controller in this app to start. You're gonna add\n\n673\n00:33:03,015 --> 00:33:05,482\nmore view controllers in yours, but we're gonna start\n\n674\n00:33:05,484 --> 00:33:07,884\none and, of course, it's gonna be a table view controller.\n\n675\n00:33:07,886 --> 00:33:08,752\nSo let's drag it out, okay.\n\n676\n00:33:08,754 --> 00:33:11,755\nWell go down here. Go down to table view controller,\n\n677\n00:33:11,757 --> 00:33:15,625\nit's like 4th of 5th one down. I'm just gonna drag it out.\n\n678\n00:33:15,627 --> 00:33:18,195\nAs promised, if you do the identity inspector, you can\n\n679\n00:33:18,197 --> 00:33:21,031\nsee this view controller is a UITableViewController.\n\n680\n00:33:21,033 --> 00:33:25,502\nAnd if I click inside on the view that's inside this thing,\n\n681\n00:33:25,504 --> 00:33:30,073\nokay, you'll see that it's class is UITableView, okay.\n\n682\n00:33:30,075 --> 00:33:34,144\nIf I click here, on a row, you'll see it's class is\n\n683\n00:33:34,146 --> 00:33:37,848\na UITableViewCell. Does everyone got the parts here?\n\n684\n00:33:37,850 --> 00:33:40,751\nHave the parts all put together? Well,\n\n685\n00:33:40,753 --> 00:33:43,887\nwe obviously need to have our own custom subclass of UI,\n\n686\n00:33:43,889 --> 00:33:47,257\nTableViewController, okay, just like we do with anything.\n\n687\n00:33:47,259 --> 00:33:49,259\nSo let's go ahead an do that right off the bat.\n\n688\n00:33:49,261 --> 00:33:51,762\nFile, New File. Okay, it's gonna be a Cocoa Touch class,\n\n689\n00:33:51,764 --> 00:33:54,097\nit's gonna be a subclass of UITableViewController.\n\n690\n00:33:54,099 --> 00:33:56,500\nI'm gonna call it TweetTableViewController,\n\n691\n00:33:56,502 --> 00:34:00,170\nbecause it's gonna be a table view full of tweets. Okay, so,\n\n692\n00:34:00,172 --> 00:34:01,972\nit's a tweet table view controller, or\n\n693\n00:34:01,974 --> 00:34:04,674\na TweetTableViewController, whichever, you want to look at\n\n694\n00:34:04,676 --> 00:34:06,543\nit there, all right. So we got that, here it is,\n\n695\n00:34:06,545 --> 00:34:09,012\nwe'll put it in the same place as everything else.\n\n696\n00:34:09,014 --> 00:34:10,547\nOkay, here's my TweetTableViewController,\n\n697\n00:34:10,549 --> 00:34:12,582\nwe'll look at that in a second. Let's go back to our\n\n698\n00:34:12,584 --> 00:34:15,886\nstory board and make sure we set our custom class, okay.\n\n699\n00:34:15,888 --> 00:34:16,987\nThis is a easy thing to forget,\n\n700\n00:34:16,989 --> 00:34:19,289\nI'm sure a lot of you have. Let's go in here and\n\n701\n00:34:19,291 --> 00:34:20,857\nmake sure it's a TweetTableViewController.\n\n702\n00:34:20,859 --> 00:34:22,426\nSo, this is a TweetTableViewController right\n\n703\n00:34:22,428 --> 00:34:25,495\nhere. Let's go look at the code that it generated for us.\n\n704\n00:34:25,497 --> 00:34:28,065\nThis is a little more than we get when we normally\n\n705\n00:34:28,067 --> 00:34:30,734\nMake a UIViewController, okay? Because, of course,\n\n706\n00:34:30,736 --> 00:34:33,570\nwe're getting table view specific stuff here. So,\n\n707\n00:34:33,572 --> 00:34:34,905\nhere's our viewDidLoad, it has a couple\n\n708\n00:34:34,907 --> 00:34:38,875\ncomments in here that you can look at when you go build your\n\n709\n00:34:38,877 --> 00:34:41,411\napp. Has to do with selection being cleared and\n\n710\n00:34:41,413 --> 00:34:44,815\nwhether there's an Edit button for editing this thing. We're\n\n711\n00:34:44,817 --> 00:34:47,050\nnot gonna be doing that in this demo, so get rid of that.\n\n712\n00:34:47,052 --> 00:34:48,652\nAnd we're not gonna have to worry about memory, so\n\n713\n00:34:48,654 --> 00:34:54,191\nwe get rid of that. Here is our UITableViewDataSource\n\n714\n00:34:54,193 --> 00:34:58,528\nright here. Here's the number of sections in the table,\n\n715\n00:34:58,530 --> 00:35:00,464\nhere's the numberOfRowsInSection,\n\n716\n00:35:00,466 --> 00:35:01,865\nhere's cellForRowAtIndexPath.\n\n717\n00:35:01,867 --> 00:35:03,233\nOkay, and we know we're gonna want that, so\n\n718\n00:35:03,235 --> 00:35:05,368\nI'm even gonna uncomment that. Okay,\n\n719\n00:35:05,370 --> 00:35:08,038\nthis is the heart of a dynamic table.\n\n720\n00:35:08,040 --> 00:35:09,940\nOkay? So, we'll implement that in a little bit.\n\n721\n00:35:09,942 --> 00:35:12,709\nHere's a bunch of other stuff that has to do with editing\n\n722\n00:35:12,711 --> 00:35:15,479\nthe table, okay, deleting rows, things like that.\n\n723\n00:35:15,481 --> 00:35:17,114\nYou really want to look at this stuff if,\n\n724\n00:35:17,116 --> 00:35:19,850\nagain you're doing extra credit or the final project,\n\n725\n00:35:19,852 --> 00:35:21,485\nyou want to make the rows editable,\n\n726\n00:35:21,487 --> 00:35:24,321\nbut we'll clear it out of here to make it, clean. And\n\n727\n00:35:24,323 --> 00:35:27,824\nthen here's our navigation, okay? I'll leave it in here.\n\n728\n00:35:27,826 --> 00:35:30,560\nBecause you're gonna be doing a navigation,\n\n729\n00:35:30,562 --> 00:35:33,530\nbut I'm not doing navigation in my demo, okay.\n\n730\n00:35:33,532 --> 00:35:37,000\nTense, all right, that's our tweet controller.\n\n731\n00:35:37,002 --> 00:35:42,939\nSo we, any time we have a new view controller, we probably\n\n732\n00:35:42,941 --> 00:35:46,710\nwant to think about what our model is. Right? It's a really\n\n733\n00:35:46,712 --> 00:35:48,578\ngood start for any time you're building a view controller,\n\n734\n00:35:48,580 --> 00:35:53,350\nwhat's it's model? And so, this is a table that contains\n\n735\n00:35:53,352 --> 00:35:57,487\ntweets, right? So, could say our model probably looks\n\n736\n00:35:57,489 --> 00:36:02,859\nsomething like an array of Tweet or something like that.\n\n737\n00:36:02,861 --> 00:36:04,127\nOkay? Where this is a class yet\n\n738\n00:36:04,129 --> 00:36:06,329\nto be determined. I'm actually going to make,\n\n739\n00:36:06,331 --> 00:36:09,032\nand I could even say, you know, equals an array of Tweet\n\n740\n00:36:09,034 --> 00:36:11,301\nto make an empty array of them to start off.\n\n741\n00:36:11,303 --> 00:36:13,036\nBut I'm actually going to do a little bit trickier.\n\n742\n00:36:13,038 --> 00:36:16,873\nI'm actually going to have this be and array of and\n\n743\n00:36:16,875 --> 00:36:21,511\narray of Tweets. Okay, and the reason I'm gonna do this\n\n744\n00:36:21,513 --> 00:36:24,381\nis because I'm gonna go fetch a bunch of tweets and\n\n745\n00:36:24,383 --> 00:36:26,750\nput it in one section in my table and then later\n\n746\n00:36:26,752 --> 00:36:29,486\nI'm gonna let the use of fetch more tweets, and I'll put that\n\n747\n00:36:29,488 --> 00:36:32,088\nin another section, okay. And I'm gonna add the other\n\n748\n00:36:32,090 --> 00:36:35,392\nsection by just adding another array of tweets. So this array\n\n749\n00:36:35,394 --> 00:36:40,063\nof array of tweets each array inside is just a fetch. Okay?\n\n750\n00:36:40,065 --> 00:36:42,899\nSo that's why I'm doing an array of an array of tweets,\n\n751\n00:36:42,901 --> 00:36:46,136\nso I can just adding sections, okay? So this is really\n\n752\n00:36:46,138 --> 00:36:48,538\nnice, having an array of array of something is really\n\n753\n00:36:48,540 --> 00:36:51,708\nnice for table views, because this really makes it easy to\n\n754\n00:36:51,710 --> 00:36:54,477\nimplement all the table view methods. Because it's really\n\n755\n00:36:54,479 --> 00:36:56,546\nclear, the section is the outer part of the array, and\n\n756\n00:36:56,548 --> 00:37:00,584\nthen the row is in the inner part. Okay, everybody cool?\n\n757\n00:37:00,586 --> 00:37:02,419\nClear why I'm doing that? Now,\n\n758\n00:37:02,421 --> 00:37:06,823\nof course, if anyone sets my model, I'm going to need to\n\n759\n00:37:06,825 --> 00:37:11,428\nreload my table, which I do with TableView.reloadData().\n\n760\n00:37:11,430 --> 00:37:16,399\nOkay, that's gonna call all these methods down here to get\n\n761\n00:37:16,401 --> 00:37:19,002\ncalled again. Okay. Make sense? Now,\n\n762\n00:37:19,004 --> 00:37:21,972\nmy model is actually gonna be a little more than that.\n\n763\n00:37:21,974 --> 00:37:25,909\nI'm gonna have another part of my model which is searchText,\n\n764\n00:37:25,911 --> 00:37:28,612\nwhich is gonna be a string, okay? I'm gonna allow people\n\n765\n00:37:28,614 --> 00:37:32,115\nto set this part of my model. And I'm gonna go search for\n\n766\n00:37:32,117 --> 00:37:35,585\nthose tweets, tweets that match that search text and\n\n767\n00:37:35,587 --> 00:37:38,755\nload up the other part of my model with it. Okay, so\n\n768\n00:37:38,757 --> 00:37:40,257\nits kinda part of my model as well,\n\n769\n00:37:40,259 --> 00:37:42,492\neven though they're related in that way,\n\n770\n00:37:42,494 --> 00:37:44,661\nthey're both part of the model. Now in this one,\n\n771\n00:37:44,663 --> 00:37:48,765\nif someone set this one, okay, I'm gonna remove all\n\n772\n00:37:48,767 --> 00:37:52,836\nthe tweets I got, okay, using the removeAll method in array,\n\n773\n00:37:52,838 --> 00:37:55,905\njust wipe out all my tweets that I have. And then I'm\n\n774\n00:37:55,907 --> 00:37:58,475\ngonna call searchForTweets or something like that,\n\n775\n00:37:58,477 --> 00:38:00,877\nthat's gonna actually have to go do a search. By the way,\n\n776\n00:38:00,879 --> 00:38:05,181\nI'm also gonna set my title to whatever that searchText is.\n\n777\n00:38:05,183 --> 00:38:07,617\nSo if I'm in a navigation controller or something,\n\n778\n00:38:07,619 --> 00:38:11,288\nthe title up there will be whatever the search text was.\n\n779\n00:38:11,290 --> 00:38:12,822\nSo I need to search teets,\n\n780\n00:38:12,824 --> 00:38:17,694\nTweets here, so we'll private func searchForTweets, and\n\n781\n00:38:17,696 --> 00:38:22,165\nwe're gonna have to implement that. So that's my model,\n\n782\n00:38:22,167 --> 00:38:25,101\nall right, and I can also, here in my viewDidLoad,\n\n783\n00:38:25,103 --> 00:38:28,305\nmaybe I would maybe even say something like searchText\n\n784\n00:38:28,307 --> 00:38:32,208\nequals, I don't know, #stanford or something. Just,\n\n785\n00:38:32,210 --> 00:38:34,077\nI'll, in viewDidLoad for testing purposes,\n\n786\n00:38:34,079 --> 00:38:37,113\nI'll just have a initial thing that I'm gonna search for,\n\n787\n00:38:37,115 --> 00:38:39,549\nokay? And when I set this it's gonna call this.\n\n788\n00:38:39,551 --> 00:38:42,118\nIt's gonna remove all the tweet, it's gonna search for\n\n789\n00:38:42,120 --> 00:38:45,021\nnew tweets, okay? Eventually this thing's gonna find\n\n790\n00:38:45,023 --> 00:38:48,058\nthe tweets and call this. That's gonna reload the data,\n\n791\n00:38:48,060 --> 00:38:51,394\nthat's gonna call these. Okay, these are gonna load up\n\n792\n00:38:51,396 --> 00:38:56,833\nthe table and start making cells to, put the tweets.\n\n793\n00:38:57,169 --> 00:38:59,669\nEverybody understand that flow? All right,\n\n794\n00:38:59,671 --> 00:39:02,806\nlet's talk about tweet, this class tweet right here.\n\n795\n00:39:02,808 --> 00:39:05,008\nI just typed that. What is that, okay?\n\n796\n00:39:05,010 --> 00:39:09,679\nWell I could make you go and learn how to query Twitter and\n\n797\n00:39:09,681 --> 00:39:12,082\nget tweets down and all that stuff.\n\n798\n00:39:12,084 --> 00:39:14,718\nBut I really want you to learn about table views here, so\n\n799\n00:39:14,720 --> 00:39:17,554\nI'm gonna provide a framework for you that will do that.\n\n800\n00:39:17,556 --> 00:39:20,790\nWill go out and you give it a search text, it'll,\n\n801\n00:39:20,792 --> 00:39:22,125\nsearch text of some sort,\n\n802\n00:39:22,127 --> 00:39:23,426\nit'll just go do the tweets and\n\n803\n00:39:23,428 --> 00:39:26,763\ngive it back to you as an array of these tweet objects,\n\n804\n00:39:26,765 --> 00:39:29,032\nokay? Now I'm gonna give that to you\n\n805\n00:39:29,034 --> 00:39:32,202\nas a framework. Now we haven't really talked about frameworks\n\n806\n00:39:32,204 --> 00:39:34,838\ntoo much. The only time I ever mentioned frameworks actually\n\n807\n00:39:34,840 --> 00:39:37,774\nwas when I talked about public and private. Remember that? I\n\n808\n00:39:37,776 --> 00:39:42,879\nsaid there's private, there's public, and there's nothing.\n\n809\n00:39:42,881 --> 00:39:47,217\nAnd nothing means kind of public within your app,\n\n810\n00:39:47,219 --> 00:39:51,154\nright? And the word public, which we never use, that means\n\n811\n00:39:51,156 --> 00:39:54,424\npublic outside of my app or in the case I'm gonna do it,\n\n812\n00:39:54,426 --> 00:39:57,994\noutside of my framework. So I've made a framework for you,\n\n813\n00:39:57,996 --> 00:40:01,531\nand it has public methods, methods marked public, okay.\n\n814\n00:40:01,533 --> 00:40:03,166\nActually public put on the line there, and\n\n815\n00:40:03,168 --> 00:40:05,568\nthat means that you can call those methods,\n\n816\n00:40:05,570 --> 00:40:09,239\nuse those classes outside of the framework, okay?\n\n817\n00:40:09,241 --> 00:40:13,810\nSo to make a framework work, though, okay, you have to\n\n818\n00:40:13,812 --> 00:40:16,813\ncreate a higher level project than your project,\n\n819\n00:40:16,815 --> 00:40:19,849\ncalled a workspace, that has both the framework and your\n\n820\n00:40:19,851 --> 00:40:24,788\nproject in it, okay? So let's do that right away, let's go\n\n821\n00:40:24,790 --> 00:40:28,057\nover here to Xcode, and I'm gonna say New > Workspace.\n\n822\n00:40:28,059 --> 00:40:28,625\nWe've never done this, okay,\n\n823\n00:40:28,627 --> 00:40:31,428\nthis is a new kind of project-like thing, but\n\n824\n00:40:31,430 --> 00:40:33,897\nit's really just a collection of other projects. So\n\n825\n00:40:33,899 --> 00:40:37,167\nI hit New > Workspace. It says what do you wanna call it and\n\n826\n00:40:37,169 --> 00:40:37,734\nwhere do you wanna put it?\n\n827\n00:40:37,736 --> 00:40:40,270\nSo I'm gonna put it in my home directory Developer here.\n\n828\n00:40:40,272 --> 00:40:43,173\nI'm gonna call it Lecture9. I could call it anything.\n\n829\n00:40:43,175 --> 00:40:45,575\nI could even call it Smashtag if I want, but\n\n830\n00:40:45,577 --> 00:40:46,042\nit can be kind of confusing.\n\n831\n00:40:46,044 --> 00:40:49,279\nSo I'm gonna call it Lecture9, okay, and it creates this.\n\n832\n00:40:49,281 --> 00:40:51,915\nAnd look, it looks kinda like an empty project.\n\n833\n00:40:51,917 --> 00:40:55,151\nOkay, it has no files over here, and what you\n\n834\n00:40:55,153 --> 00:40:58,855\nput over here are other projects. So in a workspace,\n\n835\n00:40:58,857 --> 00:41:01,124\nthis is gonna have other projects. And in fact,\n\n836\n00:41:01,126 --> 00:41:05,495\nI'm just gonna go grab my Smashtag, here it is right\n\n837\n00:41:05,497 --> 00:41:10,433\nhere. You take the xcodeproj, okay, and you drag it in.\n\n838\n00:41:10,435 --> 00:41:14,904\nBoom, I've added this to my workspace. Now, I can work on\n\n839\n00:41:14,906 --> 00:41:18,775\nmy project here just as easily as working at it directly,\n\n840\n00:41:18,777 --> 00:41:22,779\nby double-clicking it to xcodeproj, okay? And, in fact,\n\n841\n00:41:22,781 --> 00:41:25,615\nbetter, because when I put this other framework in there,\n\n842\n00:41:25,617 --> 00:41:27,984\nthat framework will work here. If I don't,\n\n843\n00:41:27,986 --> 00:41:30,019\nwork here then that framework's not gonna be\n\n844\n00:41:30,021 --> 00:41:33,256\nvisible, okay. So what about this Twitter framework?\n\n845\n00:41:33,258 --> 00:41:36,326\nWhere's that? Well, that turns out to be right here, okay?\n\n846\n00:41:36,328 --> 00:41:37,360\nHere's my little Twitter project.\n\n847\n00:41:37,362 --> 00:41:39,195\nThis will be available to you obviously when you're doing\n\n848\n00:41:39,197 --> 00:41:42,165\nyour homework. And I'm just gonna drag it's Xcode project\n\n849\n00:41:42,167 --> 00:41:46,236\nin here too. Now, when I do, be very careful not to put it\n\n850\n00:41:46,238 --> 00:41:49,272\ninside the Smashtag project. You see how this is trying to\n\n851\n00:41:49,274 --> 00:41:52,575\nput it inside? You want it to be a sibling of sash,\n\n852\n00:41:52,577 --> 00:41:54,611\nSmashTags. So put it right up at the top so\n\n853\n00:41:54,613 --> 00:41:57,280\nthe two of them are siblings in this workspace.\n\n854\n00:41:57,282 --> 00:42:02,452\nOops, in this workspace right here, okay? See what I'm\n\n855\n00:42:02,454 --> 00:42:05,421\nsaying by that? Question. >> If you make\n\n856\n00:42:05,423 --> 00:42:08,391\nchanges to Smashtag in your workspace,\n\n857\n00:42:08,393 --> 00:42:10,627\ndo they stay? >> Yeah, so the questions is\n\n858\n00:42:10,629 --> 00:42:14,264\nif I change my framework or my project here in the workspace,\n\n859\n00:42:14,266 --> 00:42:16,933\ndo they effect the project? Absolutely, here you\n\n860\n00:42:16,935 --> 00:42:19,869\nare actually working on those projects in this workspace.\n\n861\n00:42:19,871 --> 00:42:22,105\nBut it's those projects you are working on, okay?\n\n862\n00:42:22,107 --> 00:42:24,541\nPutting in the workspace, just relates them,\n\n863\n00:42:24,543 --> 00:42:27,443\nit just gets them in the same grouping. So\n\n864\n00:42:27,445 --> 00:42:29,512\nhere's our Twitter project right here.\n\n865\n00:42:29,514 --> 00:42:31,748\nAnd we still have to say that this\n\n866\n00:42:31,750 --> 00:42:35,184\nSmashtag uses this framework, and we do that, right,\n\n867\n00:42:35,186 --> 00:42:39,122\nby clicking on our Smashtag project. We need to drag\n\n868\n00:42:39,124 --> 00:42:42,358\nour Twitter framework in here to let Smashtag know,\n\n869\n00:42:42,360 --> 00:42:45,061\nyeah, I want you to use Twitter. So what do we,\n\n870\n00:42:45,063 --> 00:42:47,864\nwhere do we do that? We do it right here where it says\n\n871\n00:42:47,866 --> 00:42:50,900\nproducts Twitter framework, okay, this right here.\n\n872\n00:42:50,902 --> 00:42:55,238\nWe're just gonna take this guy, and pick it up and\n\n873\n00:42:55,240 --> 00:42:58,274\ndrag it in here. Now before I do that, when you\n\n874\n00:42:58,276 --> 00:43:01,811\ndownload this you might find this to be red, okay.\n\n875\n00:43:01,813 --> 00:43:04,647\nThat means it's not built. So to build it, you're\n\n876\n00:43:04,649 --> 00:43:07,450\ngonna wanna go up to the top here, you can see now that in\n\n877\n00:43:07,452 --> 00:43:10,119\nthe workspace I have two choices of things I can build.\n\n878\n00:43:10,121 --> 00:43:13,823\nYou're gonna go to Twitter. Very importantly, you want to\n\n879\n00:43:13,825 --> 00:43:17,427\npick generic iOS device, because this is a framework.\n\n880\n00:43:17,429 --> 00:43:21,164\nAnd you wanna build it as a generic framework, okay, for\n\n881\n00:43:21,166 --> 00:43:24,300\nall iOS devices, okay. So do that and then it'll probably\n\n882\n00:43:24,302 --> 00:43:26,336\nautomatically build when you do that. But if not,\n\n883\n00:43:26,338 --> 00:43:29,238\nyou can hit Play to build and it'll build Twitter, and\n\n884\n00:43:29,240 --> 00:43:30,807\nthen this will stop being red, okay.\n\n885\n00:43:30,809 --> 00:43:33,076\nVery important, if this is red and you drag it in,\n\n886\n00:43:33,078 --> 00:43:35,845\nit's not gonna work. This has to be black, okay?\n\n887\n00:43:35,847 --> 00:43:40,249\nSo I'm gonna drag it in, okay, okay, to Smashtags1.\n\n888\n00:43:40,251 --> 00:43:43,920\nOkay, so here I picked Smashtag, drag this down here,\n\n889\n00:43:43,922 --> 00:43:48,224\nit adds it. Notice it shows in Smashtag inside Smashtag's\n\n890\n00:43:48,226 --> 00:43:51,160\nproject, it shows it right there as well. If you're doing\n\n891\n00:43:51,162 --> 00:43:53,796\nthat objective C, by the way, there's some headers right\n\n892\n00:43:53,798 --> 00:43:56,532\nhere because even though I wrote this in Swift, you could\n\n893\n00:43:56,534 --> 00:44:00,303\nuse an objective C using these headers right here, okay.\n\n894\n00:44:00,305 --> 00:44:03,006\nIf you're in Swift, you don't care about those headers,\n\n895\n00:44:03,008 --> 00:44:07,443\nall right? But now inside of our code of our Smashtag, we\n\n896\n00:44:07,445 --> 00:44:12,548\ncan reference that framework by saying import Twitter,\n\n897\n00:44:12,550 --> 00:44:16,252\nwhich is the name of this framework, okay.\n\n898\n00:44:16,254 --> 00:44:18,921\nAnd once we import Twitter, look, this, in fact,\n\n899\n00:44:18,923 --> 00:44:21,591\nif we go back here, which is where it is. And then we're\n\n900\n00:44:21,593 --> 00:44:24,694\ngonna build this one for, iPhone 6. If you go back here,\n\n901\n00:44:24,696 --> 00:44:27,597\nyou'll see that Tweet no longer generates an error, and\n\n902\n00:44:27,599 --> 00:44:29,966\nit turns purple, cuz it's recognized.\n\n903\n00:44:29,968 --> 00:44:33,202\nNow this is the only Tweet in our namespace, but the full\n\n904\n00:44:33,204 --> 00:44:36,873\nname of this thing is actually Twitter.Tweet. Okay, and\n\n905\n00:44:36,875 --> 00:44:39,676\nyou can either specify full name or if there's no other\n\n906\n00:44:39,678 --> 00:44:41,611\nTweets around, you could leave this off.\n\n907\n00:44:41,613 --> 00:44:43,746\nI'll put it in there just so you're reminded, okay,\n\n908\n00:44:43,748 --> 00:44:48,017\nthat that's coming from that framework. Got it? Now let's\n\n909\n00:44:48,019 --> 00:44:50,620\ngo look at this Twitter.Tweet and see what it is. Okay, so\n\n910\n00:44:50,622 --> 00:44:53,189\nI'm gonna look at my Twitter framework right here, here's\n\n911\n00:44:53,191 --> 00:44:55,925\nTweet. You can see Tweet is really just a collection of\n\n912\n00:44:55,927 --> 00:44:59,462\ninformation about a Tweet. The text in the Tweet, the user\n\n913\n00:44:59,464 --> 00:45:03,566\nwho Tweeted it, when it was created, a unique identifier,\n\n914\n00:45:03,568 --> 00:45:07,203\nimages that are attached to it, and hashtags, URLs and\n\n915\n00:45:07,205 --> 00:45:10,873\nusers that are mentioned in the Tweet. And you're homework\n\n916\n00:45:10,875 --> 00:45:13,910\nis gonna be about showing me these Mentions. Okay,\n\n917\n00:45:13,912 --> 00:45:16,579\nI'm not gonna do that in my demo, that's for you to do.\n\n918\n00:45:16,581 --> 00:45:18,915\nOkay, so that's what a Tweet is. Now we have user,\n\n919\n00:45:18,917 --> 00:45:21,951\nwhich is you know, the name, screenName of the user.\n\n920\n00:45:21,953 --> 00:45:24,287\nMediaItem, this is for attached images.\n\n921\n00:45:24,289 --> 00:45:28,124\nNotice it has the aspectRatio, that'll be very valuable to\n\n922\n00:45:28,126 --> 00:45:30,760\nyou as you try to build your table view, okay.\n\n923\n00:45:30,762 --> 00:45:32,729\nThis is just an image that's attached with the Tweet.\n\n924\n00:45:32,731 --> 00:45:34,664\nWhen people tweet, sometimes they attach an image or\n\n925\n00:45:34,666 --> 00:45:37,867\nwhatever. And then there's this very important class\n\n926\n00:45:37,869 --> 00:45:40,937\ncalled Request, okay, Twitter.Request. And\n\n927\n00:45:40,939 --> 00:45:45,975\nI'm gonna look at the public API of this actually. Let's go\n\n928\n00:45:45,977 --> 00:45:49,512\nover here, look at generated interface, here it is.\n\n929\n00:45:49,514 --> 00:45:51,781\nYou can see that I've marked a lot of these things public,\n\n930\n00:45:51,783 --> 00:45:55,551\nyou see public, public class. Here's all the public API.\n\n931\n00:45:55,553 --> 00:45:57,854\nThe things you're gonna, we're gonna use is this\n\n932\n00:45:57,856 --> 00:46:01,958\npublic initializer which gives the search String to search on\n\n933\n00:46:01,960 --> 00:46:05,962\nTwitter and then how many results you want, okay.\n\n934\n00:46:05,964 --> 00:46:08,798\nAnd then this guy fetchTweets, and what\n\n935\n00:46:08,800 --> 00:46:12,068\nfetchTweets does is it uses that search String to go fetch\n\n936\n00:46:12,070 --> 00:46:16,439\nTweets. And it calls a little function here, this function,\n\n937\n00:46:16,441 --> 00:46:19,342\nokay, a function of this type. It just hands you an array of\n\n938\n00:46:19,344 --> 00:46:21,778\nthe Tweets when they come back. Now this is\n\n939\n00:46:21,780 --> 00:46:24,947\nasynchronous, okay, obviously. We're gonna go to the network\n\n940\n00:46:24,949 --> 00:46:28,351\nhere. So this is coming back and the thread that this comes\n\n941\n00:46:28,353 --> 00:46:31,821\nback and calls you on is not necessarily the main thread.\n\n942\n00:46:31,823 --> 00:46:34,757\nSo we will wanna be sure to dispatch async outta here,\n\n943\n00:46:34,759 --> 00:46:37,727\nback to the main thread if we're gonna be doing any UI.\n\n944\n00:46:37,729 --> 00:46:39,829\nEveryone understand that?\n\n945\n00:46:39,831 --> 00:46:42,498\nOkay, so that's it. This is a really easy class to use,\n\n946\n00:46:42,500 --> 00:46:45,401\nright? We just initialize it with the search we want and\n\n947\n00:46:45,403 --> 00:46:48,171\nthen just fetch the Tweets, okay? It's also got this\n\n948\n00:46:48,173 --> 00:46:49,572\nlittle thing down here, which is kinda fun,\n\n949\n00:46:49,574 --> 00:46:52,675\nrequestFromNewer, ForNewer. If you have a request that was\n\n950\n00:46:52,677 --> 00:46:55,878\nsuccessfully got you some Tweets, you can call this\n\n951\n00:46:55,880 --> 00:46:59,682\nrequestForNewer and it'll give you a new request that will\n\n952\n00:46:59,684 --> 00:47:03,052\nrequest only more new Tweets. Tweets you didn't get in\n\n953\n00:47:03,054 --> 00:47:05,788\nthe last request. See what I'm saying? Cuz people are alway\n\n954\n00:47:05,790 --> 00:47:07,857\nTweeting all the time, so sometimes you just want\n\n955\n00:47:07,859 --> 00:47:09,458\nthe ones that were Tweeted since the last time\n\n956\n00:47:09,460 --> 00:47:14,063\nyou got it. So we'll use this as well, okay, in our demo.\n\n957\n00:47:14,065 --> 00:47:17,633\nAll right, everyone understand this Twitter thing? Pretty\n\n958\n00:47:17,635 --> 00:47:21,003\nsimple to use, all right? >> One more thing.\n\n959\n00:47:21,005 --> 00:47:21,204\n>> Yeah.\n\n960\n00:47:21,206 --> 00:47:22,138\n>> So it looked like it was\n\n961\n00:47:22,140 --> 00:47:24,407\nreturning a void. Do you have to type cast\n\n962\n00:47:24,409 --> 00:47:28,878\nthat to a Tweet array- >> On the previous one?\n\n963\n00:47:28,880 --> 00:47:29,145\n>> Down here?\n\n964\n00:47:29,147 --> 00:47:33,216\nIt returns void, but remember, this is a function that takes\n\n965\n00:47:33,218 --> 00:47:35,952\nan array of Tweets as the argument. So\n\n966\n00:47:35,954 --> 00:47:37,520\nyou're gonna pass a closure here,\n\n967\n00:47:37,522 --> 00:47:40,056\nand that closure is going to take that array and\n\n968\n00:47:40,058 --> 00:47:41,624\ndo something with it. Okay, it does,\n\n969\n00:47:41,626 --> 00:47:43,893\nit can't return the array because it's asynchronous.\n\n970\n00:47:43,895 --> 00:47:46,295\nIt has to go off and on that, it has to call you back.\n\n971\n00:47:46,297 --> 00:47:49,332\nOkay, with this function, when it's got the tweets, so\n\n972\n00:47:49,334 --> 00:47:52,869\nthat's a good question. All right, back here,\n\n973\n00:47:52,871 --> 00:47:55,738\nwe're in our tweets, let's get to the heart of this,\n\n974\n00:47:55,740 --> 00:47:57,406\nwhich is this guy, searchForTweets.\n\n975\n00:47:57,408 --> 00:47:59,675\nThat's the thing that's gonna use the Twitter,\n\n976\n00:47:59,677 --> 00:48:03,312\nframework to search for tweets. So how's this thing,\n\n977\n00:48:03,314 --> 00:48:06,649\ngonna do what it does basically, to do the tweets.\n\n978\n00:48:06,651 --> 00:48:08,918\nWell I'm actually going to create a little private var\n\n979\n00:48:08,920 --> 00:48:12,355\nwhich I'm going to call my twitterRequest. It's going to\n\n980\n00:48:12,357 --> 00:48:17,159\nbe of type Twitter.Request. Okay, and it's going to be\n\n981\n00:48:17,161 --> 00:48:20,763\ncomputed, and this is just going to be a little way I can\n\n982\n00:48:20,765 --> 00:48:24,166\nhave a little var which is the request I want to make.\n\n983\n00:48:24,168 --> 00:48:29,105\nAnd I'm going to say if, I can let query = searchText,\n\n984\n00:48:29,107 --> 00:48:34,110\nokay that's this thing right here, okay. And\n\n985\n00:48:34,112 --> 00:48:36,212\nI also don't want it to be empty so\n\n986\n00:48:36,214 --> 00:48:39,282\nI'm gonna say where the query is not empty.\n\n987\n00:48:39,284 --> 00:48:40,983\nOkay, there's that where clause again. So\n\n988\n00:48:40,985 --> 00:48:44,287\nhere I'm checking to see if it's not null with if let, and\n\n989\n00:48:44,289 --> 00:48:46,689\nthen I'm also making sure it's not empty, so,\n\n990\n00:48:46,691 --> 00:48:49,892\nbecause I don't wanna do a Twitter request for empty,\n\n991\n00:48:49,894 --> 00:48:52,261\nthat like asking for all Tweets. That makes no sense,\n\n992\n00:48:52,263 --> 00:48:55,197\nthere's gotta be at least something to search for. So\n\n993\n00:48:55,199 --> 00:48:57,600\nif that's okay, then I'm just gonna return your request by\n\n994\n00:48:57,602 --> 00:49:01,203\nsaying Twitter.Request. I'm gonna call that initializer\n\n995\n00:49:01,205 --> 00:49:04,040\nthat we were talking about. Search, we can search for\n\n996\n00:49:04,042 --> 00:49:07,376\nthe query as its own but maybe I wanna add some other stuff\n\n997\n00:49:07,378 --> 00:49:11,147\nlike I don't want retweets. So there if\n\n998\n00:49:11,149 --> 00:49:16,118\nyou can in the API for doing, for looking for\n\n999\n00:49:16,120 --> 00:49:18,754\ntweets you can specify things like filter out retweets I\n\n1000\n00:49:18,756 --> 00:49:21,958\ndon't want them, so I'm gonna do that. And then count,\n\n1001\n00:49:21,960 --> 00:49:24,627\nlet's get a hundred at a time. So we'll get a hundred tweets\n\n1002\n00:49:24,629 --> 00:49:30,132\nat a time, okay. Otherwise I'm just going to return nil here.\n\n1003\n00:49:30,134 --> 00:49:32,835\nOkay, so if, if some, if I want to do\n\n1004\n00:49:32,837 --> 00:49:35,771\na ter, twitter request, but I don't have any search text\n\n1005\n00:49:35,773 --> 00:49:36,505\nthen I'm just going to return nil,\n\n1006\n00:49:36,507 --> 00:49:38,574\nIll know not actually do any kind of search.\n\n1007\n00:49:38,576 --> 00:49:41,344\nOkay, do you understand what that var is?\n\n1008\n00:49:41,346 --> 00:49:43,980\nIt's just giving me the request that I'm gonna do. So\n\n1009\n00:49:43,982 --> 00:49:47,817\nlet's use that request. I'm just gonna say if I can let\n\n1010\n00:49:47,819 --> 00:49:52,722\nthe request = TwitterRequest, so it's gonna call that\n\n1011\n00:49:52,724 --> 00:49:57,560\nlittle computed var up there, okay. Then I'm going to use\n\n1012\n00:49:57,562 --> 00:50:02,198\nthat request to fetch tweets, okay. So here's fetchTweets,\n\n1013\n00:50:02,200 --> 00:50:03,866\nhere's that argument which is the handler.\n\n1014\n00:50:03,868 --> 00:50:06,769\nBy the way a really fun way when you're doing closures\n\n1015\n00:50:06,771 --> 00:50:10,806\nis to do the escape completion til it shows this in blue, and\n\n1016\n00:50:10,808 --> 00:50:11,674\nthen double click on it.\n\n1017\n00:50:11,676 --> 00:50:15,277\nYou see, cuz then it'll put the closure out there for\n\n1018\n00:50:15,279 --> 00:50:17,513\nyou with the right argument type here.\n\n1019\n00:50:17,515 --> 00:50:22,418\nNow I like closing, close, trailing, closure syntax.\n\n1020\n00:50:22,420 --> 00:50:25,221\nSo I'm just gonna get rid of my parentheses and put this\n\n1021\n00:50:25,223 --> 00:50:29,125\nclosure at the end. Okay, so that's kinda cool right?\n\n1022\n00:50:29,127 --> 00:50:32,128\nFetch tweets, it's gonna call this closure.\n\n1023\n00:50:32,130 --> 00:50:34,296\nHere's the tweets that it's gonna give back,\n\n1024\n00:50:34,298 --> 00:50:38,100\nan array of tweets, I'll call this newTweets, okay. And\n\n1025\n00:50:38,102 --> 00:50:40,169\nthen in this code I can use the new tweets,\n\n1026\n00:50:40,171 --> 00:50:43,372\nadd them to my table basically is really easy. But\n\n1027\n00:50:43,374 --> 00:50:46,275\nof course I have to dispatch async, okay,\n\n1028\n00:50:46,277 --> 00:50:50,913\nbecause this closure is being executed off the main queue\n\n1029\n00:50:50,915 --> 00:50:53,883\nwhen those tweets come back sometime in the future. So\n\n1030\n00:50:53,885 --> 00:50:57,486\nI've got to dispatch async. So, for my queue right here\n\n1031\n00:50:57,488 --> 00:51:00,022\nI'm going to dispatch back to the main queue, so\n\n1032\n00:51:00,024 --> 00:51:04,894\nthat's dispatc_ge_mai_queue and here's my block.\n\n1033\n00:51:04,896 --> 00:51:06,695\nAgain I'm going to double click it, okay.\n\n1034\n00:51:06,697 --> 00:51:11,700\nAgain I'm going closing, trailing closure syntax,\n\n1035\n00:51:11,702 --> 00:51:14,270\nokay, and so this is now dispatched to the main queue.\n\n1036\n00:51:14,272 --> 00:51:17,606\nSo all I need to do here is just say if the new tweets\n\n1037\n00:51:17,608 --> 00:51:21,010\nare not empty, in others words I got some back, then I'm just\n\n1038\n00:51:21,012 --> 00:51:25,147\ngoing to insert to my to my tweets at the beginning,\n\n1039\n00:51:25,783 --> 00:51:28,350\nthese new tweets at index 0.\n\n1040\n00:51:28,352 --> 00:51:31,454\nOkay, cuz I want the new tweet at the top of my table so\n\n1041\n00:51:31,456 --> 00:51:34,323\nI'm putting it at the beginning of my array, okay.\n\n1042\n00:51:34,325 --> 00:51:38,861\nMake sense? Now I've got a red error there,\n\n1043\n00:51:38,863 --> 00:51:43,766\nanyone know what that is? It's pointing to right here.\n\n1044\n00:51:43,768 --> 00:51:49,939\nAny ideas? Don't be shy. >> Self.\n\n1045\n00:51:49,941 --> 00:51:50,940\n>> Self, absolutely.\n\n1046\n00:51:50,942 --> 00:51:54,844\nWe need self here. That's Swift trying to remind us,\n\n1047\n00:51:54,846 --> 00:51:59,715\nhey, this closure, this closure right here is keeping,\n\n1048\n00:51:59,717 --> 00:52:02,952\nand actually this one out here too, okay, is keeping this\n\n1049\n00:52:02,954 --> 00:52:05,254\nself in the heap. Now I don't think we want\n\n1050\n00:52:05,256 --> 00:52:07,756\nthat here cuz what if we make some Twitter request and\n\n1051\n00:52:07,758 --> 00:52:11,026\nit takes forever and meanwhile the user just navigates away\n\n1052\n00:52:11,028 --> 00:52:11,060\nfrom this thing.\n\n1053\n00:52:11,062 --> 00:52:13,729\nWe want this thing to be able to leave the heap. So\n\n1054\n00:52:13,731 --> 00:52:17,733\nwe're going to fix this using weak.\n\n1055\n00:52:17,735 --> 00:52:21,303\nweak weakSelf = self.\n\n1056\n00:52:21,305 --> 00:52:24,039\nSo I'm just creating a new variable here called weakSelf.\n\n1057\n00:52:24,041 --> 00:52:27,543\nIt's weak so it don't won't hold anything in a heap and\n\n1058\n00:52:27,545 --> 00:52:28,878\nI'm gonna set it equal to self.\n\n1059\n00:52:28,880 --> 00:52:31,647\nSo it's a weak version of self. And then down here I'm\n\n1060\n00:52:31,649 --> 00:52:34,850\ngonna use weak self, okay, but this is an optional because it\n\n1061\n00:52:34,852 --> 00:52:36,886\ngets set to nil if this thing leaves the heap.\n\n1062\n00:52:36,888 --> 00:52:39,788\nSo I have to do question mark there so that this will just\n\n1063\n00:52:39,790 --> 00:52:42,591\nnot happen if it leaves the heap. And that's perfect,\n\n1064\n00:52:42,593 --> 00:52:45,528\nthat's exactly what I want. If those tweets come back and\n\n1065\n00:52:45,530 --> 00:52:49,798\nthis thing has left the heap, just ignore this. Okay,\n\n1066\n00:52:49,800 --> 00:52:52,568\nperfect. Now there's another problem here,\n\n1067\n00:52:52,570 --> 00:52:55,738\nmulti-threading problem we gotta think about, okay,\n\n1068\n00:52:55,740 --> 00:52:58,374\nwhich is what if this takes a long time and by the time it\n\n1069\n00:52:58,376 --> 00:53:02,378\ncomes back the user has issued a different Tweet request?\n\n1070\n00:53:02,380 --> 00:53:04,780\nThey type something else in to search for, okay.\n\n1071\n00:53:04,782 --> 00:53:06,282\nYou don't wanna show them these tweets,\n\n1072\n00:53:06,284 --> 00:53:07,516\nthey were from some old thing. So\n\n1073\n00:53:07,518 --> 00:53:10,119\njust like we did in the image view controller here,\n\n1074\n00:53:10,121 --> 00:53:11,287\nwe're gonna have to have a var,\n\n1075\n00:53:11,289 --> 00:53:13,889\nwe'll have some private var,\n\n1076\n00:53:14,225 --> 00:53:18,627\nwhich is our lastTwitterRequest, okay,\n\n1077\n00:53:18,629 --> 00:53:21,797\nwhich is gonna be a Twitter.Request,\n\n1078\n00:53:21,799 --> 00:53:24,300\nokay. And, we're gonna have to keep track of\n\n1079\n00:53:24,302 --> 00:53:26,869\nthis, okay. When we go off and do this fetch, right, before\n\n1080\n00:53:26,871 --> 00:53:30,105\nwe do it I'm gonna remember what that last Twitter request\n\n1081\n00:53:30,107 --> 00:53:33,108\nwas, okay, which is the request we're doing. And\n\n1082\n00:53:33,110 --> 00:53:38,614\nthen down here I'm gonna say, if the request that we did\n\n1083\n00:53:38,616 --> 00:53:41,450\nis the last one that we requested,\n\n1084\n00:53:41,452 --> 00:53:42,685\nthen we can do this.\n\n1085\n00:53:42,687 --> 00:53:46,622\nOtherwise just ignore these tweets coming back. Okay,\n\n1086\n00:53:46,624 --> 00:53:51,860\nthis needs weakSelf in front of it as well. Okay, everyone\n\n1087\n00:53:51,862 --> 00:53:54,463\nsee that? I really want you to start understanding,\n\n1088\n00:53:54,465 --> 00:53:56,465\nthis is really gonna be important in your homework.\n\n1089\n00:53:56,467 --> 00:53:58,934\nOkay cuz in your homework you're going to be\n\n1090\n00:53:58,936 --> 00:54:01,670\ndoing multi-thread stuff. And stuff's gonna come back and\n\n1091\n00:54:01,672 --> 00:54:04,340\nthis is a table view that's gonna be scrolling up and\n\n1092\n00:54:04,342 --> 00:54:05,741\ndown, reusing the cells.\n\n1093\n00:54:05,743 --> 00:54:08,644\nIt might come back to a cell that's no longer displaying\n\n1094\n00:54:08,646 --> 00:54:10,112\nthe same row as it was before cuz\n\n1095\n00:54:10,114 --> 00:54:13,415\nit got reused, okay. So you really got to understand this\n\n1096\n00:54:13,417 --> 00:54:16,385\nthing about understanding the world when you come back from\n\n1097\n00:54:16,387 --> 00:54:19,588\nall asynchronous requests, okay. The three things,\n\n1098\n00:54:19,590 --> 00:54:23,259\nthe two things really to understand about asynchrony.\n\n1099\n00:54:23,261 --> 00:54:24,360\nOne is memory cycles,\n\n1100\n00:54:24,362 --> 00:54:27,263\nmake sure you break them when appropriate. And number two is\n\n1101\n00:54:27,265 --> 00:54:29,164\nunderstanding that these things take time and\n\n1102\n00:54:29,166 --> 00:54:32,201\nwhen they come back things might not be the same. Okay,\n\n1103\n00:54:32,203 --> 00:54:33,902\nthose are the two things to make sure you understand when\n\n1104\n00:54:33,904 --> 00:54:38,607\nyou're doing asynchronous programming. All righty then,\n\n1105\n00:54:38,609 --> 00:54:42,778\nwe have our, this is all we need to do to build our model,\n\n1106\n00:54:42,780 --> 00:54:43,579\nbuild our data structure up.\n\n1107\n00:54:43,581 --> 00:54:46,682\nOkay, this thing is now built up. Okay, this tweets,\n\n1108\n00:54:46,684 --> 00:54:50,452\nwhen we add, when we insert more tweets to it, that's\n\n1109\n00:54:50,454 --> 00:54:54,089\ngonna cause didSet to happen because this is a value type.\n\n1110\n00:54:54,091 --> 00:54:55,457\nOkay, so didSet is gonna happen and boom,\n\n1111\n00:54:55,459 --> 00:54:58,794\nreload data's gonna happen. So now we gotta make sure that\n\n1112\n00:54:58,796 --> 00:55:02,197\nwhen reload data happens down here, that these things all do\n\n1113\n00:55:02,199 --> 00:55:05,234\nwhat they're supposed to, right. So let's talk about\n\n1114\n00:55:05,236 --> 00:55:10,239\nnumber of sections. That one's real easy. Tweets.count,\n\n1115\n00:55:10,241 --> 00:55:16,545\nokay, cuz our tweet is an array of arrays.\n\n1116\n00:55:16,547 --> 00:55:17,346\nThe number of arrays in the top\n\n1117\n00:55:17,348 --> 00:55:22,685\nlevel is how many sections we have, okay. So that's good.\n\n1118\n00:55:22,687 --> 00:55:25,988\nGot that warning out of there. How about this one? This one\n\n1119\n00:55:25,990 --> 00:55:32,061\nis tweets(section).count. So now we're looking at our array\n\n1120\n00:55:32,063 --> 00:55:35,564\nof arrays, finding the array that is, that is this section,\n\n1121\n00:55:35,566 --> 00:55:38,867\nand looking at how many rows are in it. Everybody got that?\n\n1122\n00:55:38,869 --> 00:55:42,504\nThis is really cool to have really simple implementations\n\n1123\n00:55:42,506 --> 00:55:46,608\nof these by designing our data structure to make this simple.\n\n1124\n00:55:46,610 --> 00:55:48,877\nHint, hint, hint, I strongly recommend that for\n\n1125\n00:55:48,879 --> 00:55:52,014\nyour homework as well. Try to design your data structure\n\n1126\n00:55:52,016 --> 00:55:53,882\nusing all you've learned about Swift,\n\n1127\n00:55:53,884 --> 00:55:56,418\nSwift is really awesome at being able to design\n\n1128\n00:55:56,420 --> 00:55:58,954\nsophisticated flexible data structures.\n\n1129\n00:55:58,956 --> 00:56:02,191\nDesign a data structure, you can have one liners like this,\n\n1130\n00:56:02,193 --> 00:56:06,061\nokay. Now you have a different thing going on. Your table's\n\n1131\n00:56:06,063 --> 00:56:08,330\ngonna have mixed things, different kinds of things,\n\n1132\n00:56:08,332 --> 00:56:09,331\nI have all the same kind of thing,\n\n1133\n00:56:09,333 --> 00:56:11,266\nall mine are all tweaked. You have mixed things so its\n\n1134\n00:56:11,268 --> 00:56:14,136\na little more complicated for you, but it still can be done.\n\n1135\n00:56:14,138 --> 00:56:18,941\nAll right so now we have to do this self wrote index pass we\n\n1136\n00:56:18,943 --> 00:56:23,112\nhave to make a cell. Well the first thing we want to\n\n1137\n00:56:23,114 --> 00:56:26,115\ndo is this reuse identifier right here. So I'm actually\n\n1138\n00:56:26,117 --> 00:56:29,184\ngoing to make a private struct called storyboard, just like I\n\n1139\n00:56:29,186 --> 00:56:34,957\ndid in the last demo. And it's gonna have a static let called\n\n1140\n00:56:35,693 --> 00:56:39,495\nTweetCellIdentifier and we'll call it- we'll just call it\n\n1141\n00:56:39,497 --> 00:56:42,364\nTweet. So this is gonna be the identifier,\n\n1142\n00:56:42,366 --> 00:56:44,133\nof the cells in the storyboard.\n\n1143\n00:56:44,135 --> 00:56:48,237\nSo I'm gonna replace this reuse identifier with\n\n1144\n00:56:48,239 --> 00:56:51,807\nStoryboard.TweetCellIdentif- ier. Okay?\n\n1145\n00:56:51,809 --> 00:56:54,743\nSo that's specifying it. Now I need to do that same thing in\n\n1146\n00:56:54,745 --> 00:56:58,414\nmy storyboard. Okay, here's my row right here,\n\n1147\n00:56:58,416 --> 00:57:02,451\nmy prototype row. I'm gonna start off by making it be\n\n1148\n00:57:02,453 --> 00:57:04,586\na subtitle row, we'll eventually make it custom, but\n\n1149\n00:57:04,588 --> 00:57:07,523\nlet's make it be a subtitle role. And I gotta make sure my\n\n1150\n00:57:07,525 --> 00:57:10,893\nreuse identifier is the same, so I'll make it be Tweet.\n\n1151\n00:57:10,895 --> 00:57:14,163\nSee the two things I did there? So that makes it so\n\n1152\n00:57:14,165 --> 00:57:18,634\nthis code matches up with my storyboard. All right?\n\n1153\n00:57:18,636 --> 00:57:22,371\nSo now, here I've dequeued this reusable cell, might have\n\n1154\n00:57:22,373 --> 00:57:25,140\nreused it, might have made one from my prototype in there\n\n1155\n00:57:25,142 --> 00:57:28,043\nwhich is a subtitle cell. So now I'm just gonna get\n\n1156\n00:57:28,045 --> 00:57:32,981\nthe tweet that corresponds to this index path right here.\n\n1157\n00:57:32,983 --> 00:57:35,818\nAgain, super simple because of our data structure,\n\n1158\n00:57:35,820 --> 00:57:44,393\ntweets[indexPath.section] [indexPath.row].\n\n1159\n00:57:44,395 --> 00:57:49,431\nGot it? Okay, cuz this is an array of arrays, right?\n\n1160\n00:57:49,433 --> 00:57:52,067\nSo now I just need to load this cell up so I'll,\n\n1161\n00:57:52,069 --> 00:57:55,604\nin its text label, which is that main label of the thing,\n\n1162\n00:57:55,606 --> 00:57:59,341\nI'll put the text which is the tweets text. Okay,\n\n1163\n00:57:59,343 --> 00:58:05,447\nthat's the text of the tweet, and then in the detail,\n\n1164\n00:58:05,449 --> 00:58:10,552\nTextLabel, we'll put the tweet user's name,\n\n1165\n00:58:10,554 --> 00:58:16,592\nokay? All right, so that's it. Loaded our table up,\n\n1166\n00:58:16,594 --> 00:58:21,396\nshould just work fine. Here we go. This is where we cross our\n\n1167\n00:58:21,398 --> 00:58:24,566\nfingers in the live demo we didn't forget anything.\n\n1168\n00:58:27,771 --> 00:58:31,707\nAll right, here we go. It's running, and black, and\n\n1169\n00:58:31,709 --> 00:58:33,876\nwhat do we got down here in the console?\n\n1170\n00:58:33,878 --> 00:58:36,378\nFailed to instantiate the default view controller Main,\n\n1171\n00:58:36,380 --> 00:58:40,182\nperhaps the designated entry point not set? Yeah,\n\n1172\n00:58:40,184 --> 00:58:43,552\nlet's go look at that. Main storyboard,\n\n1173\n00:58:43,554 --> 00:58:48,290\nZoom out, there's no little arrow going in here, okay.\n\n1174\n00:58:48,292 --> 00:58:51,093\nI'm sure your guys have experienced that as well. So\n\n1175\n00:58:51,095 --> 00:58:54,930\nlet's go here and just slack this, View Controller and\n\n1176\n00:58:54,932 --> 00:58:57,499\nsay that it is the initial View Controller and\n\n1177\n00:58:57,501 --> 00:59:02,838\nnow we have this arrow. Okay? Excellent.\n\n1178\n00:59:02,840 --> 00:59:07,843\nParty on. All right. So look at that, it worked perfectly.\n\n1179\n00:59:07,845 --> 00:59:11,013\nOkay, look at that, we can look at all these tweets,\n\n1180\n00:59:11,015 --> 00:59:13,916\nwho tweeted them, okay, we're looking at Stanford here,\n\n1181\n00:59:13,918 --> 00:59:16,385\nfantastic, scrolling up and down. Okay,\n\n1182\n00:59:16,387 --> 00:59:19,555\nthis is about the ugliest Twitter client I've ever seen.\n\n1183\n00:59:19,557 --> 00:59:20,088\n>> [LAUGH]\n\n1184\n00:59:20,090 --> 00:59:22,157\n>> Okay? This is,\n\n1185\n00:59:22,159 --> 00:59:24,526\nif you put this in the app store you've,\n\n1186\n00:59:24,528 --> 00:59:28,130\nthe ridicule would be, would be unending for this.\n\n1187\n00:59:28,132 --> 00:59:31,633\nNow how we gonna fix this, though? Really there's no way,\n\n1188\n00:59:31,635 --> 00:59:34,670\nnone of these standard cells are gonna make it look good.\n\n1189\n00:59:34,672 --> 00:59:37,306\nWe need to build a custom cell, obviously,\n\n1190\n00:59:37,308 --> 00:59:37,873\nto make this look good.\n\n1191\n00:59:37,875 --> 00:59:40,909\nSo it's doing the right thing, it just looks terrible. So\n\n1192\n00:59:40,911 --> 00:59:43,779\ninstead of using this subtitle cell right here,\n\n1193\n00:59:43,781 --> 00:59:46,582\nwe're gonna do a custom cell. All right, so\n\n1194\n00:59:46,584 --> 00:59:50,018\nhow do we do that? First thing we need to do is, let's change\n\n1195\n00:59:50,020 --> 00:59:54,489\nthis from subtitle to custom. Then we're gonna be a, need to\n\n1196\n00:59:54,491 --> 00:59:59,027\ngo here and change the, the, the identity inspector,\n\n1197\n00:59:59,029 --> 01:00:01,863\nneed to change this to be some subclass of UITableViewCell\n\n1198\n01:00:01,865 --> 01:00:03,865\nbecause obviously we're gonna have some labels and\n\n1199\n01:00:03,867 --> 01:00:07,202\nstuff in here that we need to have outlets to, okay? So\n\n1200\n01:00:07,204 --> 01:00:10,772\nlet's go up here, new, file, okay.\n\n1201\n01:00:10,774 --> 01:00:11,740\nCocoa Touch Class,\n\n1202\n01:00:11,742 --> 01:00:13,508\nthis time instead of UITableViewController,\n\n1203\n01:00:13,510 --> 01:00:17,245\nit's gonna be UITableViewCell subclass. And we'll call\n\n1204\n01:00:17,247 --> 01:00:20,182\nthis a TweetTableViewCell cuz that's what it is, shows\n\n1205\n01:00:20,184 --> 01:00:23,719\na Tweet. Okay, click that, put it in the same place we put\n\n1206\n01:00:23,721 --> 01:00:27,255\neverything. [SOUND] Here we go, there's our TableViewCell,\n\n1207\n01:00:27,257 --> 01:00:28,056\nwe'll look at that in a second.\n\n1208\n01:00:28,058 --> 01:00:31,727\nIn our storyboard, we're gonna change the custom class here\n\n1209\n01:00:31,729 --> 01:00:34,630\nto be TweetTableViewCell, okay. And\n\n1210\n01:00:34,632 --> 01:00:37,499\nhere's our TweetTableViewCell. We don't need to wait for\n\n1211\n01:00:37,501 --> 01:00:38,767\na nib, you all remember what that is and\n\n1212\n01:00:38,769 --> 01:00:41,703\nwe don't need it. Here's an interesting one right here.\n\n1213\n01:00:41,705 --> 01:00:42,671\nThis one will get called\n\n1214\n01:00:42,673 --> 01:00:45,207\nin the table view cell if the table view gets selected.\n\n1215\n01:00:45,209 --> 01:00:47,576\nI showed you how you can find out in the controller,\n\n1216\n01:00:47,578 --> 01:00:50,145\nhere you can actually find out in the table view cell. But\n\n1217\n01:00:50,147 --> 01:00:51,913\nwe don't need either of those things, okay?\n\n1218\n01:00:51,915 --> 01:00:54,216\nWe're not gonna do either of those things.\n\n1219\n01:00:54,218 --> 01:00:57,019\nWhat we really need is just to build our UI. So let's\n\n1220\n01:00:57,021 --> 01:01:00,288\ngo back to our storyboard, and build the UI that we want,\n\n1221\n01:01:00,290 --> 01:01:05,560\neh in here. So what kind of stuff do we need, for\n\n1222\n01:01:05,562 --> 01:01:09,498\na tweet? Well let's see, we probably need,\n\n1223\n01:01:09,500 --> 01:01:13,268\nwant something which is, the Tweets Text.\n\n1224\n01:01:13,270 --> 01:01:15,671\nOkay. The Tweets Text, by the way, is long and\n\n1225\n01:01:15,673 --> 01:01:18,407\nI want it to wrap into multiple lines. So\n\n1226\n01:01:18,409 --> 01:01:20,676\nI'm actually gonna go to the inspector up here and\n\n1227\n01:01:20,678 --> 01:01:24,980\nmake the number of lines in this text label be zero.\n\n1228\n01:01:24,982 --> 01:01:28,550\nZero means keep wrapping. Okay,\n\n1229\n01:01:28,552 --> 01:01:30,952\ndon't try to fit it all on one line with dot dot dot.\n\n1230\n01:01:30,954 --> 01:01:33,588\nRemember our display would always say dot dot dot. Zero\n\n1231\n01:01:33,590 --> 01:01:36,992\nmeans keep wrapping around so we definitely want that.\n\n1232\n01:01:37,461 --> 01:01:40,295\nWe also want the tweeter. So lets have one for\n\n1233\n01:01:40,297 --> 01:01:45,167\nthe tweeter. Okay, and that we do want to be on one line.\n\n1234\n01:01:45,169 --> 01:01:50,706\nLets show when the tweet was created. Maybe? And how about,\n\n1235\n01:01:50,708 --> 01:01:54,109\nlet's put an image in there. Let's put where's our UI\n\n1236\n01:01:54,111 --> 01:01:58,447\nimage view? Here it is. Put an u, image view, out here.\n\n1237\n01:01:58,449 --> 01:02:03,785\nWe'll have this be the profile image basically of the user.\n\n1238\n01:02:03,787 --> 01:02:07,656\nNow, some things here we gotta do to arrange this, and I'm\n\n1239\n01:02:07,658 --> 01:02:10,826\ngonna try and keep this mostly in what you already know.\n\n1240\n01:02:10,828 --> 01:02:13,528\nOne thing is the font, okay. These things\n\n1241\n01:02:13,530 --> 01:02:17,132\nare very different from like a button in terms of fonts.\n\n1242\n01:02:17,134 --> 01:02:20,802\nThese are user data. This is what the user is looking at.\n\n1243\n01:02:20,804 --> 01:02:24,639\nSo we need to not use system font here. We need to pick\n\n1244\n01:02:24,641 --> 01:02:28,810\na different font which is one of the textiles.\n\n1245\n01:02:28,812 --> 01:02:30,412\nRemember I mentioned the textiles? So\n\n1246\n01:02:30,414 --> 01:02:33,949\ntweeter is kind of like a headline. It goes at the top.\n\n1247\n01:02:33,951 --> 01:02:37,519\nTweet Text is probably like the body. That's the main,\n\n1248\n01:02:37,521 --> 01:02:42,657\noops, that's the main body of the, of what's showing here.\n\n1249\n01:02:42,659 --> 01:02:44,826\nCreated is kind of like a caption.\n\n1250\n01:02:44,828 --> 01:02:46,561\nIt's just a little thing on the side. So\n\n1251\n01:02:46,563 --> 01:02:49,931\nwe'll say, caption one. And we might play with these various\n\n1252\n01:02:49,933 --> 01:02:54,536\nthings to find out what, you know, is the best font that\n\n1253\n01:02:54,538 --> 01:02:57,205\nwe want in each circumstance. So, let's say one thing is\n\n1254\n01:02:57,207 --> 01:02:59,941\na font. Next thing is, we need to arrange them in stack\n\n1255\n01:02:59,943 --> 01:03:02,844\nviews. Obviously, we love stack view, so let's do that.\n\n1256\n01:03:02,846 --> 01:03:07,182\nLet's go here and embed these two in a stack view how about,\n\n1257\n01:03:07,184 --> 01:03:11,219\nwe'll have them both be filled there.\n\n1258\n01:03:11,221 --> 01:03:15,991\nLet's put these two in a stack view,\n\n1259\n01:03:15,993 --> 01:03:20,996\nthank you. Also we'll fill both directions there so\n\n1260\n01:03:20,998 --> 01:03:23,498\nwe got those. Let's put these in a stack view.\n\n1261\n01:03:23,500 --> 01:03:26,668\nYou can see a stack view, very powerful.\n\n1262\n01:03:26,670 --> 01:03:31,540\nNow let's put a little spacing between there. Like that.\n\n1263\n01:03:31,542 --> 01:03:34,209\nOne thing that's not really very nice about this.\n\n1264\n01:03:34,211 --> 01:03:36,845\nOkay, we probably want this to be fill also. One thing that's\n\n1265\n01:03:36,847 --> 01:03:39,881\nnot very nice about this is, look at this space right here.\n\n1266\n01:03:39,883 --> 01:03:43,218\nLook how it's giving so much space to the tweeter. And not\n\n1267\n01:03:43,220 --> 01:03:46,888\npretty much space to the Tweet text, okay. Well, it turns out\n\n1268\n01:03:46,890 --> 01:03:50,992\nthere's a way in auto layout to control that, which is you\n\n1269\n01:03:50,994 --> 01:03:55,063\ncan go to something that you want to hug to it's contents,\n\n1270\n01:03:55,065 --> 01:03:58,500\nright. You want to can it, be the smallest possible content.\n\n1271\n01:03:58,502 --> 01:04:01,636\nYou can select it, go over to the size inspector over here,\n\n1272\n01:04:01,638 --> 01:04:04,039\nwhich is where all the constraints are, right here.\n\n1273\n01:04:04,041 --> 01:04:07,209\nAnd change its content hugging priority. See content hugging\n\n1274\n01:04:07,211 --> 01:04:09,845\npriority? I'm gonna make its content hugging priority in\n\n1275\n01:04:09,847 --> 01:04:13,582\nthe vertical direction to be high, higher than the other\n\n1276\n01:04:13,584 --> 01:04:15,750\none, okay? And when I do that, look what happened,\n\n1277\n01:04:15,752 --> 01:04:19,788\nit hugged, okay? And now it made this one be the big one.\n\n1278\n01:04:19,790 --> 01:04:21,790\nBecause this one's content hugging priority is 251,\n\n1279\n01:04:21,792 --> 01:04:25,827\nthis one's 300. So, it's more of a priority to hug,\n\n1280\n01:04:25,829 --> 01:04:28,930\nyou got it? That's the only kinda special trick I'm gonna\n\n1281\n01:04:28,932 --> 01:04:31,132\nshow you today. I am going to do a whole\n\n1282\n01:04:31,134 --> 01:04:34,102\nlecture on autolayout next week. All right, so\n\n1283\n01:04:34,104 --> 01:04:37,339\nwe've got this. So now, let's do our thing when we hook it\n\n1284\n01:04:37,341 --> 01:04:41,376\nup to the edges. Leading edge up to top\n\n1285\n01:04:41,378 --> 01:04:46,414\ndown here to the bottom and over here to the trailing.\n\n1286\n01:04:46,416 --> 01:04:48,149\nLet's go ahead and click on these, and\n\n1287\n01:04:48,151 --> 01:04:51,219\nsee if we can make standard. No? So, let's make this zero,\n\n1288\n01:04:51,221 --> 01:04:56,157\nsee if we can make this one a standard. No, make this one\n\n1289\n01:04:56,159 --> 01:05:02,163\nalso zero. See if we can make this one a standard. No, make\n\n1290\n01:05:02,165 --> 01:05:06,034\nthis one zero. And the top one is probably already zero.\n\n1291\n01:05:06,036 --> 01:05:10,505\nLet's go ahead and look at it in our Spectre. Here, yeah,\n\n1292\n01:05:10,507 --> 01:05:12,941\nthe top is already zero. So, it's zero. Now, this is also\n\n1293\n01:05:12,943 --> 01:05:16,645\nnot looking like I want. Okay, the image view is dominating.\n\n1294\n01:05:16,647 --> 01:05:19,514\nThis is just the image view of the guy who tweeted it.\n\n1295\n01:05:19,516 --> 01:05:22,350\nSo, it just wants to be small and in the corner. So,\n\n1296\n01:05:22,352 --> 01:05:25,687\nI'm actually going to fix the size of this. So,\n\n1297\n01:05:25,689 --> 01:05:29,691\nif you control drag to itself, you can set a constraint,\n\n1298\n01:05:29,693 --> 01:05:33,295\na constraint itself. So it's going to react to controlled\n\n1299\n01:05:33,297 --> 01:05:36,331\nto itself, so I'm going to fix its height and width.\n\n1300\n01:05:36,333 --> 01:05:38,633\nSo, that has fixed it's height and width,\n\n1301\n01:05:38,635 --> 01:05:40,936\nof course I don't want it to be this big.\n\n1302\n01:05:40,938 --> 01:05:42,704\nI want it to be like, you know, 60 by 60, let's say.\n\n1303\n01:05:42,706 --> 01:05:47,242\nSo, I'm going over here to the inspector, size inspector.\n\n1304\n01:05:47,244 --> 01:05:50,779\nOn this thing. And I'm gonna change, this constraint, right\n\n1305\n01:05:50,781 --> 01:05:53,548\nhere, just by clicking edit. I'm gonna change it to 60. And\n\n1306\n01:05:53,550 --> 01:05:58,954\nI'm gonna change the height to also be 60. Okay. Now,\n\n1307\n01:05:58,956 --> 01:06:02,590\nwe have a much more reasonable layout here, right. The text\n\n1308\n01:06:02,592 --> 01:06:05,894\nis using most of the space. The tweeter's just at the top.\n\n1309\n01:06:05,896 --> 01:06:08,229\nWe got the little image for the tweeter up there, and\n\n1310\n01:06:08,231 --> 01:06:12,434\nwe've got this created in here. We're good? Okay.\n\n1311\n01:06:12,436 --> 01:06:14,903\nNow let's go and create outlets to all these things.\n\n1312\n01:06:14,905 --> 01:06:17,839\nSo, let's make more space here. Now one thing to\n\n1313\n01:06:17,841 --> 01:06:22,577\nbe careful of, if I go to, man to automatic here, and\n\n1314\n01:06:22,579 --> 01:06:24,913\nI try to make an outlet look at the class it puts here.\n\n1315\n01:06:24,915 --> 01:06:27,816\n[NOISE] The tableview controller. We know we cannot\n\n1316\n01:06:27,818 --> 01:06:30,518\nhook these outlets up to the tableview controller, because\n\n1317\n01:06:30,520 --> 01:06:33,355\nthey have to be different for every cell. So instead, we\n\n1318\n01:06:33,357 --> 01:06:38,293\nhave to go to Manual up here, okay, and go not in Twitter.\n\n1319\n01:06:38,295 --> 01:06:40,495\nWe need to go, actually we'll, let's go here.\n\n1320\n01:06:40,497 --> 01:06:43,531\n[LAUGH] How do we get to there? Let's see, Manual,\n\n1321\n01:06:43,533 --> 01:06:48,069\nTweetTableView, so here it is. Okay, so let's go here, so\n\n1322\n01:06:48,071 --> 01:06:50,405\nhere's our, our TweetTableViewCell right here,\n\n1323\n01:06:50,407 --> 01:06:55,810\nbut this is not quite right either. Hold on a second here.\n\n1324\n01:06:55,812 --> 01:07:00,215\nManual. Automatic.\n\n1325\n01:07:00,217 --> 01:07:03,485\nLevel object. Okay.\n\n1326\n01:07:03,487 --> 01:07:05,887\nIt's showing me the interface here for some reason.\n\n1327\n01:07:05,889 --> 01:07:09,090\nLets do something different here. Lets go over here.\n\n1328\n01:07:09,092 --> 01:07:15,463\n[SOUND] Okay, I'm not sure why it's doing that.\n\n1329\n01:07:25,275 --> 01:07:33,581\nOkay, strange let's do TweetTableViewCell.\n\n1330\n01:07:41,658 --> 01:07:42,257\nVery sorry about that.\n\n1331\n01:07:42,259 --> 01:07:43,792\nFor some reason you see it's fixed.\n\n1332\n01:07:43,794 --> 01:07:44,926\nIt's showing me the interface for\n\n1333\n01:07:44,928 --> 01:07:49,330\nthis. I'm not sure exactly why. Okay. Let's try this.\n\n1334\n01:07:49,332 --> 01:07:53,368\nLet's go here, and then over here.\n\n1335\n01:07:53,370 --> 01:08:01,576\n[INAUDIBLE] Okay,\n\n1336\n01:08:01,578 --> 01:08:04,679\nwell you know what I'm gonna do, I'm gonna quit this thing\n\n1337\n01:08:04,681 --> 01:08:09,584\nand re-launch. By the way when you go back in,\n\n1338\n01:08:09,586 --> 01:08:11,820\nbe careful not to go back in with your Xcode project,\n\n1339\n01:08:11,822 --> 01:08:16,391\nyou gotta go back in with your workspace, alright? Alright,\n\n1340\n01:08:16,393 --> 01:08:20,228\nnow let's see. All right, we got our storyboard,\n\n1341\n01:08:20,363 --> 01:08:23,298\nmanual swift module, that's no good either. Mm.\n\n1342\n01:08:23,300 --> 01:08:28,570\nThis, all right, no.\n\n1343\n01:08:33,176 --> 01:08:37,445\nOkay, this. This.\n\n1344\n01:08:39,516 --> 01:08:44,519\nOkay, hm. I better back out there.\n\n1345\n01:08:53,697 --> 01:08:58,633\nWell, weird. Hm,\n\n1346\n01:08:58,635 --> 01:09:03,538\nI guess maybe we can do this, there we go. Okay, so\n\n1347\n01:09:03,540 --> 01:09:07,041\nwe are going to, I'll make this wider too,\n\n1348\n01:09:07,043 --> 01:09:10,311\nso we are going to hook up our outlets, okay?\n\n1349\n01:09:10,313 --> 01:09:13,748\nFrom here to here. So we do that with control drag,\n\n1350\n01:09:13,750 --> 01:09:17,452\njust as we normally would, so here we'll control drag this.\n\n1351\n01:09:17,454 --> 01:09:23,324\nI'm gonna call this one the tweetScreenNameLabel,\n\n1352\n01:09:23,326 --> 01:09:27,328\nokay, because it's showing the screen name of the user.\n\n1353\n01:09:27,330 --> 01:09:34,068\nWell do this one here. We'll call the tweetTextLabel.\n\n1354\n01:09:34,070 --> 01:09:38,840\nWe'll do here, this is the TweetCreatedLabel,\n\n1355\n01:09:38,842 --> 01:09:43,211\nand we'll do this one. This is the,\n\n1356\n01:09:43,213 --> 01:09:48,183\nTweetProfileImageView, okay.\n\n1357\n01:09:48,185 --> 01:09:51,319\nAnd that's a UI image view. Okay, so\n\n1358\n01:09:51,321 --> 01:09:54,022\nI've got these nice outlets right here. And,\n\n1359\n01:09:54,024 --> 01:09:57,325\nlet's go back to here, get our Text here all right, so\n\n1360\n01:09:57,327 --> 01:10:00,028\nwe got these nice outlets. So, now we need to be able to\n\n1361\n01:10:00,030 --> 01:10:02,964\nload these outlets up. When this cell, okay,\n\n1362\n01:10:02,966 --> 01:10:05,967\ncomes on the screen, and we do self-reload index path we need\n\n1363\n01:10:05,969 --> 01:10:09,571\nto be able to tell this cell here is the tweet okay, so\n\n1364\n01:10:09,573 --> 01:10:12,340\nthat you can load up all this information about the tweet.\n\n1365\n01:10:12,342 --> 01:10:15,476\nSo, I'm gonna have a public var here called tweet,\n\n1366\n01:10:15,478 --> 01:10:19,214\nwhich is the tweet. And it's a twitter.tweet.\n\n1367\n01:10:19,216 --> 01:10:21,950\nOkay, and when you set that,\n\n1368\n01:10:21,952 --> 01:10:26,955\nI'm going to update my UI to set all of these things. So,\n\n1369\n01:10:26,957 --> 01:10:33,094\nI'm gonna have some private func updateUI here.\n\n1370\n01:10:34,297 --> 01:10:36,598\nOkay, makes sense? Now this is complaining\n\n1371\n01:10:36,600 --> 01:10:40,468\nabout twitter.tweet, because I have to import Twitter.\n\n1372\n01:10:40,470 --> 01:10:45,106\nDon't forget, import Twitter, otherwise you're not gonna see\n\n1373\n01:10:45,108 --> 01:10:50,078\nthe classes from that in this swift file. Okay, so\n\n1374\n01:10:50,080 --> 01:10:53,481\nwe have this update UI right here. In the interest of time,\n\n1375\n01:10:53,483 --> 01:10:57,785\nI'm gonna type this really fast okay, there it is.\n\n1376\n01:10:57,787 --> 01:11:01,889\nokay, you can go look at this at you later offline, but\n\n1377\n01:11:01,891 --> 01:11:02,423\nbasically what's it's doing it\n\n1378\n01:11:02,425 --> 01:11:04,726\nfirstly just clearing out all the outlets,\n\n1379\n01:11:04,728 --> 01:11:07,996\nokay, then it's one by one going through and\n\n1380\n01:11:07,998 --> 01:11:12,700\nsetting each of them based on the tweet, okay.\n\n1381\n01:11:12,702 --> 01:11:16,271\nTweet that we have. Notice by the way here,\n\n1382\n01:11:16,273 --> 01:11:20,208\nkind of fun thing, in the tweet's text, I add cameras,\n\n1383\n01:11:20,210 --> 01:11:23,878\na bunch of cameras at the end if the tweet has an image\n\n1384\n01:11:23,880 --> 01:11:26,748\nattached. Okay, that's what this little thing is here. I'm\n\n1385\n01:11:26,750 --> 01:11:29,517\njust going looking at all the images that this tweet has.\n\n1386\n01:11:29,519 --> 01:11:31,886\nThat's just media array and for each one, I'm adding\n\n1387\n01:11:31,888 --> 01:11:34,789\na little camera there just to let us know there's an image.\n\n1388\n01:11:34,791 --> 01:11:37,425\nOkay, tha's being added to the text of the end of\n\n1389\n01:11:37,427 --> 01:11:40,328\nthe text, all right? Then her's the created date in\n\n1390\n01:11:40,330 --> 01:11:43,931\nthe nice little format. Here's the image view, if it exists.\n\n1391\n01:11:43,933 --> 01:11:47,035\nAll right. UI image. Notice this blocks the main\n\n1392\n01:11:47,037 --> 01:11:50,138\nthread. Fix this in your homework because one of your\n\n1393\n01:11:50,140 --> 01:11:52,173\nrequired tasks is you cannot block the main thread. So\n\n1394\n01:11:52,175 --> 01:11:56,177\neven though I'm not doing the dispatch here, you need to.\n\n1395\n01:11:56,446 --> 01:12:00,381\nGot it? All right so, that's our TweetLabel.\n\n1396\n01:12:00,383 --> 01:12:04,385\nSo now to make this work, we just need to set this tweet\n\n1397\n01:12:04,387 --> 01:12:07,789\nvar in our cellForRowAtIndexPath.\n\n1398\n01:12:07,791 --> 01:12:10,024\nOkay, so here's our cellForRowAtIndexPath.\n\n1399\n01:12:10,026 --> 01:12:12,694\nRight now, it's doing all this business right here.\n\n1400\n01:12:12,696 --> 01:12:16,664\nWe don't want that. Okay, instead we're just gonna say\n\n1401\n01:12:16,666 --> 01:12:20,368\nif we can let a tweetCell equal the cell as one of our\n\n1402\n01:12:20,370 --> 01:12:25,006\nTweetTableViewCells, okay, which this should be, because\n\n1403\n01:12:25,008 --> 01:12:29,477\nall these the tweet prototype in our storyboard over here,\n\n1404\n01:12:29,479 --> 01:12:33,681\nokay, that this is this is the tweet prototype cell right\n\n1405\n01:12:33,683 --> 01:12:38,586\nhere if we look at it Type, it is, if I can select it here.\n\n1406\n01:12:38,588 --> 01:12:40,288\nHere's where I wanna use Ctrl+Shift, okay,\n\n1407\n01:12:40,290 --> 01:12:42,690\nCtrl+Shift lets me pick which, what I want,\n\n1408\n01:12:42,692 --> 01:12:43,858\nwhich is the TableView cell.\n\n1409\n01:12:43,860 --> 01:12:47,362\nYou can see that it's a custom type, right? So this should be\n\n1410\n01:12:47,364 --> 01:12:50,732\ngood right here. So if I can get this cell as that,\n\n1411\n01:12:50,734 --> 01:12:53,434\nthen I'm just gonna set the cell's tweet equal to\n\n1412\n01:12:53,436 --> 01:12:58,606\nthe tweet at that row and index path. Okay, all right,\n\n1413\n01:12:58,608 --> 01:13:03,111\ntweetCell. Okay? Got it? So\n\n1414\n01:13:03,113 --> 01:13:08,015\nthat's it. Not that hard to just custom UI.\n\n1415\n01:13:08,017 --> 01:13:13,688\nLet's go take a look, make sure it's working. All right,\n\n1416\n01:13:13,690 --> 01:13:17,959\nhere it is! So, well, this looks somewhat better,\n\n1417\n01:13:17,961 --> 01:13:22,630\nI guess. It's really not much better because, one thing is,\n\n1418\n01:13:22,632 --> 01:13:23,931\nlook at the heights of the rows.\n\n1419\n01:13:23,933 --> 01:13:26,734\nThey're all the same. Even if it's a short little one like\n\n1420\n01:13:26,736 --> 01:13:29,670\nthis, it gets all this yucky white space, this extra white\n\n1421\n01:13:29,672 --> 01:13:33,408\nspace. Compared to a long one, right? So that's bad. And, and\n\n1422\n01:13:33,410 --> 01:13:37,178\nbig ones are not even fitting, okay? Also, where's my profile\n\n1423\n01:13:37,180 --> 01:13:40,548\nimage view? Got a couple problems here. So let's talk\n\n1424\n01:13:40,550 --> 01:13:43,317\nabout the height first. What's going on with the height?\n\n1425\n01:13:43,319 --> 01:13:46,220\nAnd remember I said you can have the height be dynamic and\n\n1426\n01:13:46,222 --> 01:13:48,790\nautomatically calculated from the tweet by just\n\n1427\n01:13:48,792 --> 01:13:51,592\nsetting the height to automatic dimension. And\n\n1428\n01:13:51,594 --> 01:13:54,662\nthe place to do that is in your viewDidLoad.\n\n1429\n01:13:54,664 --> 01:13:56,431\nOkay, so here's my viewDidLoad and\n\n1430\n01:13:56,433 --> 01:14:02,236\nI'm just gonna set in here my tableView's row height\n\n1431\n01:14:02,238 --> 01:14:06,507\nequal to this UITableView automatic dimension thing.\n\n1432\n01:14:06,509 --> 01:14:09,043\nOkay, but now what about the estimated height?\n\n1433\n01:14:09,045 --> 01:14:10,678\nI need to give it an estimate height so I'm actually going\n\n1434\n01:14:10,680 --> 01:14:14,882\nto set the tableView's estimated row height equal to\n\n1435\n01:14:14,884 --> 01:14:19,554\nthe row height that came out of the storyboard. Okay?\n\n1436\n01:14:19,556 --> 01:14:22,857\nSo this is the row height I'm getting now. Same on every\n\n1437\n01:14:22,859 --> 01:14:25,159\none. I'm gonna make that one just be the estimated one,\n\n1438\n01:14:25,161 --> 01:14:28,463\nand then I'm gonna set the row height to be this automatic.\n\n1439\n01:14:28,465 --> 01:14:29,997\nAnd that's gonna recalculate it all the time.\n\n1440\n01:14:29,999 --> 01:14:32,300\nHow about the fact that I'm not getting those profile\n\n1441\n01:14:32,302 --> 01:14:34,402\nimage views? Well look, I have something in my console right\n\n1442\n01:14:34,404 --> 01:14:38,439\nhere. You recognize this? App Transport Security, okay?\n\n1443\n01:14:38,441 --> 01:14:40,842\nYou all remember that from last time? So let's fix that.\n\n1444\n01:14:40,844 --> 01:14:45,146\nWe go into our Info.plist. We're going to add a row here.\n\n1445\n01:14:45,148 --> 01:14:48,115\nIt's going to be the App Transport Security row right\n\n1446\n01:14:48,117 --> 01:14:53,754\nthere. We're going to go down here and add arbitrary loads,\n\n1447\n01:14:53,756 --> 01:14:56,591\nokay. And we're going to set it to yes. So\n\n1448\n01:14:56,593 --> 01:14:59,594\nwe're going to allow arbitrary URLs. Okay?\n\n1449\n01:14:59,596 --> 01:15:03,998\nMakes sense? Get this down out of there.\n\n1450\n01:15:04,267 --> 01:15:07,502\nOkay, let's run again. Hopefully, things will look\n\n1451\n01:15:07,504 --> 01:15:13,674\nreally nice. Okay, that does look quite a bit better,\n\n1452\n01:15:13,676 --> 01:15:16,878\nokay. It starts to look like some, I don't know if we could\n\n1453\n01:15:16,880 --> 01:15:20,481\npost it on the abstract quite yet, okay but getting there,\n\n1454\n01:15:20,483 --> 01:15:23,851\nokay. So I want to ask one more thing, which is I wanna\n\n1455\n01:15:23,853 --> 01:15:27,388\nput a search thing at the top here, so we can search. Okay,\n\n1456\n01:15:27,390 --> 01:15:30,424\nfor not just always being #Stanford, as much as\n\n1457\n01:15:30,426 --> 01:15:34,095\nwe love #Stanford. So the way we're gonna do that is we're\n\n1458\n01:15:34,097 --> 01:15:36,130\ngonna go to our storyboard. One thing is I'm gonna put\n\n1459\n01:15:36,132 --> 01:15:38,599\nit inside of a navigation controller here and\n\n1460\n01:15:38,601 --> 01:15:42,169\nembed this whole thing inside a navigation controller.\n\n1461\n01:15:42,171 --> 01:15:45,439\nThat means I can have a nice title on it, right?\n\n1462\n01:15:45,441 --> 01:15:47,241\nRemember I set the title to be what I search for.\n\n1463\n01:15:47,243 --> 01:15:51,746\nSo I'm gonna have that there. Then I'm also going to go and\n\n1464\n01:15:51,748 --> 01:15:53,915\ndrag out a text field to be my search. So\n\n1465\n01:15:53,917 --> 01:15:56,284\nthis is gonna be the editable kind of text field. Which\n\n1466\n01:15:56,286 --> 01:15:59,820\nis right here. And if you drag right up at the top. You have\n\n1467\n01:15:59,822 --> 01:16:01,989\nto be a little bit careful. It has to look like this,\n\n1468\n01:16:01,991 --> 01:16:03,491\nyou see where it stretches out.\n\n1469\n01:16:03,493 --> 01:16:05,426\nYou can set the tableView's header.\n\n1470\n01:16:05,428 --> 01:16:09,363\nSo I've set this text field as the tableView's header. Okay?\n\n1471\n01:16:09,365 --> 01:16:11,532\nAnd I probably wanna changed some things about it.\n\n1472\n01:16:11,534 --> 01:16:14,936\nMaybe a little bit bigger font. Maybe I wanna use\n\n1473\n01:16:14,938 --> 01:16:19,173\nthe place holder here like, Twitter, search,\n\n1474\n01:16:19,175 --> 01:16:21,809\ntext, or something like that. That's a little something\n\n1475\n01:16:21,811 --> 01:16:24,612\nthat tells what this field is. Okay. That's just always gonna\n\n1476\n01:16:24,614 --> 01:16:27,782\nbe in the background til they start typing or whatever.\n\n1477\n01:16:27,784 --> 01:16:30,351\nAnd I'm gonna need to have an outlet to it. So let's\n\n1478\n01:16:30,353 --> 01:16:33,354\ndo that. Okay, this time, I do want automatic, okay,\n\n1479\n01:16:33,356 --> 01:16:35,590\nbecause this is not in a cell, this is at the top. So\n\n1480\n01:16:35,592 --> 01:16:40,895\nlet's Ctrl+Drag down here, let's put this, I don't know,\n\n1481\n01:16:40,897 --> 01:16:44,498\ndown at the bottom here. Let's Ctrl-Drag out here, and\n\n1482\n01:16:44,500 --> 01:16:49,503\ncall this searchTextField. All right. When,\n\n1483\n01:16:49,505 --> 01:16:55,176\nsearchTextField is set, we're gonna set its delegate,\n\n1484\n01:16:55,178 --> 01:16:57,812\nto be ourself. We know that with text fields, we want our\n\n1485\n01:16:57,814 --> 01:17:02,350\ndelegate. We're also gonna set the searchTextField's text,\n\n1486\n01:17:02,352 --> 01:17:05,052\nequal to our own search text. Okay.\n\n1487\n01:17:05,054 --> 01:17:09,724\nEverybody understand that? Let's go back here and, so we\n\n1488\n01:17:09,726 --> 01:17:14,095\ncan see a little better. Okay it's complaining about self.\n\n1489\n01:17:14,097 --> 01:17:16,931\nIt doesn't like self because we are not\n\n1490\n01:17:16,933 --> 01:17:19,600\na UI text field delegate,\n\n1491\n01:17:19,602 --> 01:17:22,403\nso we better set ourselves to be that. All right,\n\n1492\n01:17:22,405 --> 01:17:26,974\nwhat else do we got down here? >> The didSet.\n\n1493\n01:17:27,777 --> 01:17:29,310\n>> The didSet, yeah thanks,\n\n1494\n01:17:29,312 --> 01:17:34,382\ndidSet. There we go, okay,\n\n1495\n01:17:34,384 --> 01:17:37,785\nso when the searchTextField is set we're gonna do this and\n\n1496\n01:17:37,787 --> 01:17:40,755\nthen of course we're gonna implement that method,\n\n1497\n01:17:40,757 --> 01:17:43,124\nthe textField method which is the textField,\n\n1498\n01:17:43,126 --> 01:17:46,661\nthe textFieldShouldReturn. Okay, and in here,\n\n1499\n01:17:46,663 --> 01:17:50,131\nwe're just going to have the textField.resignFirstRespon-\n\n1500\n01:17:50,133 --> 01:17:55,603\nder. Okay, and then we're gonna return true.\n\n1501\n01:17:55,605 --> 01:18:00,775\nAnd let's, also have the text, let's grab\n\n1502\n01:18:00,777 --> 01:18:06,180\nour search text out of there. searchText = textField.text.\n\n1503\n01:18:06,182 --> 01:18:08,916\nOkay, so when someone hits the return key, we're going to\n\n1504\n01:18:08,918 --> 01:18:12,653\ngrab the text out of there and hide the keyboard, okay makes\n\n1505\n01:18:12,655 --> 01:18:16,123\nsense? All right, I believe that's all we need to do,\n\n1506\n01:18:16,125 --> 01:18:18,626\nlet's get our Stanford out of there, where's Stanford?\n\n1507\n01:18:18,628 --> 01:18:24,298\nThere it is. No more Stanford. Run.\n\n1508\n01:18:28,504 --> 01:18:31,172\nOkay, so we've got our search text up there. So let's try,\n\n1509\n01:18:31,174 --> 01:18:33,974\nlet's put Stanford back in there, see if that works.\n\n1510\n01:18:33,976 --> 01:18:36,977\nThere it is, that's good. Let's try something else like\n\n1511\n01:18:36,979 --> 01:18:42,650\nNBA. Okay, there's the NBA. Okay, looking good.\n\n1512\n01:18:43,352 --> 01:18:49,857\nGo back to Stanford again, and see that again, okay?\n\n1513\n01:18:49,859 --> 01:18:51,759\nThere you go. All right, CS193P mentioned right there.\n\n1514\n01:18:51,761 --> 01:18:54,361\nHow about that? Okay, so that's it. Now,\n\n1515\n01:18:54,363 --> 01:18:57,131\nI have a couple more things I wanted to show, but we ran\n\n1516\n01:18:57,133 --> 01:19:00,401\noutta time, so I'm going to post them in this code.\n\n1517\n01:19:00,403 --> 01:19:02,703\nI'll be posting this code, I'll add a couple of things.\n\n1518\n01:19:02,705 --> 01:19:05,106\nThe two things I wanna do is. One is\n\n1519\n01:19:05,108 --> 01:19:07,842\nI want to be able to pull down on this tableView and\n\n1520\n01:19:07,844 --> 01:19:10,745\nshow more tweets. Okay, so the tableView,\n\n1521\n01:19:10,747 --> 01:19:13,681\nthe way to kind of update it, if you pull down on it and\n\n1522\n01:19:13,683 --> 01:19:14,715\na little spinner comes up on it,\n\n1523\n01:19:14,717 --> 01:19:17,952\nand it's gonna show more, okay. So I'll put that,\n\n1524\n01:19:17,954 --> 01:19:23,390\nI'll basically add that code into what I'm going to post.\n\n1525\n01:19:23,392 --> 01:19:27,995\nThat's all I'll show. Okay? That's it, sorry to run long.\n\n1526\n01:19:27,997 --> 01:19:29,764\nSee you next time. >> For\n\n1527\n01:19:29,766 --> 01:19:29,797\nmore, please visit us at Stanford.edu.\n\n"
  }
]