diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..e43b0f9 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store diff --git a/1. Logistics, iOS 8 Overview.srt b/1. Logistics, iOS 8 Overview.srt deleted file mode 100644 index 6a35faa..0000000 --- a/1. Logistics, iOS 8 Overview.srt +++ /dev/null @@ -1,7365 +0,0 @@ -1 -00:00:00,001 --> 00:00:04,803 -欢迎同学们观看 - -2 -00:00:04,805 --> 00:00:06,637 -Stanford University. -斯坦福大学公开课。 - -3 -00:00:06,639 --> 00:00:10,508 -本字幕由志愿者义务贡献 -https://github.com/x140yu/ -Developing_iOS_8_Apps_With_Swift - -4 -00:00:10,510 --> 00:00:17,147 ->> Welcome to Stanford CS193P,this is winter quarter 2015. -欢迎参加斯坦福大学2015年冬季学期的CS193P课程。 - -5 -00:00:17,149 --> 00:00:21,718 -And we're gonna dive right in today to some brief slide work. -我们首先简要的看一下今天课程的内容 - -6 -00:00:22,720 --> 00:00:26,221 -This people at Stanford, you've got a document that describe, -斯坦福的学生,你们都有一份文档, - -7 -00:00:26,223 --> 00:00:28,357 -describes all the grading and all that stuff -里面有每个学期所有东西的描述 - -8 -00:00:28,359 --> 00:00:32,126 -so I'm not gonna go over that in lecture like I often do to start the quarter. -所以我不想像以往开课那样说一些乱七八糟的东西。 - -9 -00:00:33,663 --> 00:00:36,296 -Instead I'm gonna talk a little bit about, what this class is about. -相反我首先要谈一谈关于本课程的内容。 - -10 -00:00:37,566 --> 00:00:42,068 -Brief mention of the prerequisites cuz they're pretty important in this class. -接下来要提一下学习本课程的先决条件, - -11 -00:00:42,070 --> 00:00:44,870 -Then just the [NOISE] quickest overview of iOS. -然后会对IOS进行快速的预览。 - -12 -00:00:44,872 --> 00:00:49,508 -I'm gonna assume that anyone who is here or is watching this, knows what that is. -我想在座各位或者观看视频的同学都知道那是什么吧。 - -13 -00:00:49,510 --> 00:00:51,609 -And then, we're gonna dive right into a big old demo. -再然后,我们会演示一个大的Demo。 - -14 -00:00:51,611 --> 00:00:54,779 -It's gonna be a two-day thing, where I'm really going to try and -这将是一个为期两天的事情,我将 - -15 -00:00:54,781 --> 00:00:57,381 -introduce you to Xcode and the development environment and -向你们介绍XCode,开发环境, - -16 -00:00:57,383 --> 00:01:01,818 -this language Swift, that you're gonna have to learn to develop for iOS. -和Swift语言,同学们将学会用这些工具来为IOS做开发。 - -17 -00:01:02,854 --> 00:01:04,120 -All right, so what is this class about? -好了,那么本课程是讲什么的呢? - -18 -00:01:04,122 --> 00:01:06,455 -It's about building cool apps, as we know. -它是讲关于创建我们知道的一些很酷的应用的课程。 - -19 -00:01:06,457 --> 00:01:09,091 -Why are these iOS apps so cool? -为什么这些IOS应用如此之酷? - -20 -00:01:09,093 --> 00:01:11,960 -Well, because the device you're gonna run them on is in your pocket or -因为运行这些应用的设备要么在你的口袋里, - -21 -00:01:11,962 --> 00:01:14,229 -in your backpack. -要么在你的背包里。 - -22 -00:01:14,230 --> 00:01:16,497 -Either, if you write an app, you can just pull it out and show your friends and -如果你写了一个应用,你可以将它展示给你的朋友 - -23 -00:01:16,500 --> 00:01:20,535 -it's highly networked and incredible graphics with animation. -它是高度网络化的,并有令人难以置信的图形和动画效果。 - -24 -00:01:20,537 --> 00:01:23,371 -It's just cool all the way around and I think you guys all know that or -它在各个方面都很酷。我想你们应该都知道这些, - -25 -00:01:23,373 --> 00:01:24,605 -you wouldn't be here. -否则你们就不会坐在这里了。 - -26 -00:01:24,607 --> 00:01:26,490 -But you're also gonna learn in -但是你们可能要学习一些 - -27 -00:01:26,491 --> 00:01:28,374 -this class a lot of real life Object-Oriented Programming. -关于面向对象编程的知识。 - -28 -00:01:28,377 --> 00:01:32,578 -You're taking a lot of other classes here at Stanford on things like graphics, and -你们也可能在斯坦福选一些有关于图形、 - -29 -00:01:32,580 --> 00:01:36,849 -networking, and databases, and maybe animation. -网络、数据库、动画 - -30 -00:01:36,851 --> 00:01:39,718 -Things like that. -或者其他类似的课程。 - -31 -00:01:39,719 --> 00:01:42,586 -And we're gonna is kinda tie that all together into a real world class. -然而我们将这些内容融合在一起, - -32 -00:01:42,589 --> 00:01:44,055 -'Kay? You're gonna get to see all this stuff. -你们会在本课程内看到所有这些东西。 - -33 -00:01:44,057 --> 00:01:46,891 -Now, you know, it's gonna be kind of a survey course in that, -现在,你应该知道这会是一个概述型课程, - -34 -00:01:46,893 --> 00:01:49,426 -I can't go too deep into networking. -我不会深入讲述网络的内容, - -35 -00:01:49,428 --> 00:01:52,462 -I can't go too deep into databases. -我不会深入讲述数据库的内容, - -36 -00:01:52,464 --> 00:01:56,366 -I can't go too deep into animation, but you'll get to see it all in a really real -我不会深入讲述动画的内容,但是你们会在 - -37 -00:01:56,368 --> 00:01:59,569 -world environment, where people out there building apps using that technology. -真实项目的环境中用到所有的这些技术。 - -38 -00:01:59,571 --> 00:02:03,906 -For some of you who haven't seen that before that'll be a big bonus of -我认为,对于一些之前没有接触过这些的同学, - -39 -00:02:03,908 --> 00:02:04,940 -this class, I think. -本课程对他们会有很大的提升。 - -40 -00:02:06,243 --> 00:02:07,975 -The prerequisites of this class. -学习本课程的先决条件。 - -41 -00:02:07,977 --> 00:02:11,712 -Number one thing is you have to be a pretty strong Object-Oriented programmer. -最重要的,你要是一个很给力的面向对象开发者。 - -42 -00:02:11,714 --> 00:02:14,014 -If you're not a strong Object-Oriented programmer, and -如果你不是, - -43 -00:02:14,016 --> 00:02:18,018 -you hit this class, you're probably gonna go under water, pretty quick. -还选了这个课,基本上你就要挂了,很快。 - -44 -00:02:18,020 --> 00:02:19,519 -Okay? I'm gonna assume you know, -我需要你知道 - -45 -00:02:19,521 --> 00:02:22,188 -everything about Object-Oriented Programming. -关于面向对象编程的一切。 - -46 -00:02:22,190 --> 00:02:24,456 -IOS is a completely Object-Oriented Programming envir, -IOS是一个完全的面向对象编程的环... - -47 -00:02:24,458 --> 00:02:26,658 -development environment, -额,开发环境, - -48 -00:02:26,659 --> 00:02:28,859 -I just don't mean I'm not just talking about the language is Object-Oriented. -我的意思不是说,我说的不只是编程语言是面向对象的。 - -49 -00:02:28,862 --> 00:02:31,863 -But the entire design of it the way you use it if you're not -整个的设计方式都是面向对象的。如果你不能 - -50 -00:02:31,865 --> 00:02:33,965 -comfortable with things like subclassing and -熟练的使用像是子类之类的东西, - -51 -00:02:33,967 --> 00:02:37,935 -stuff like that then you're just really gonna be behind the curve. -那么你真的离挂科不远了。 - -52 -00:02:37,937 --> 00:02:42,239 -In iOS so at Stanford here that means CS16A and B or -斯坦福的IOS相关课程有CS16A,CA16B或者 - -53 -00:02:42,241 --> 00:02:47,344 -CS16X, and then you know, CS107, while it's not really Object-Oriented course, -CS16X,以及众所周知的CS107,虽然它并不是专门的面向对象课程, - -54 -00:02:47,346 --> 00:02:49,746 -at least it's a heavy duty programming course. -但至少是一门重量级的编程课程。 - -55 -00:02:49,748 --> 00:02:52,615 -CS108 is a great Object-Oriented course so -CS108是非常好的面向对象课程,所以 - -56 -00:02:52,617 --> 00:02:55,918 -if you have, if you've taken CS108 you'll probably, be really well prepped. -如果你曾经,如果你上过CS108,你可能会觉得很轻松。 - -57 -00:02:55,920 --> 00:03:00,555 -110, again not really too much an Object-Oriented program but -110,同样也不是非常专门的面向对象课程, - -58 -00:03:00,557 --> 00:03:03,057 -good programming course cuz there's a lot of programming in this class, -但同样是一门非常好的编程课程,因为其中有大量的编程实践。 - -59 -00:03:03,059 --> 00:03:05,159 -in fact, all the work in this class is programming. -事实上,所有这些课程的内容都是关于编程的。 - -60 -00:03:05,161 --> 00:03:08,395 -You will not have, a little bit of reading the first couple of weeks just to -在头几个星期,你仅仅 - -61 -00:03:08,397 --> 00:03:12,299 -kinda learn this new language, but it's almost all programming after that all -只会学到一点这个新语言的内容,但是直到课程结束 - -62 -00:03:12,301 --> 00:03:14,467 -the way til the end, including your final project. -所有的编程任务都需要它,包括你们的最终项目。 - -63 -00:03:14,469 --> 00:03:17,804 -So if you're not really comfortable with all these terms, -所以,如果你真的不适应面向对象编程, - -64 -00:03:17,806 --> 00:03:21,674 -this Object-Oriented terms or if you're just not really comfortable with -或者你真的只是不喜欢写大程序, - -65 -00:03:21,676 --> 00:03:26,178 -writing big programs then this class will definitely be a challenge for you. -那么这个课程对你来说就是一个挑战。 - -66 -00:03:27,848 --> 00:03:30,682 -okay, so what's in iOS, what are the parts of it? -那么,IOS中有什么?都包括哪些部分呢? - -67 -00:03:30,684 --> 00:03:34,085 -You know, it's ha, it's such a big system, it's got so much in it. -它是...哈,它是一个庞大的系统,其中有很多东西。 - -68 -00:03:34,087 --> 00:03:36,170 -It's impossible for me to, -用一两句话将其表述清楚 - -69 -00:03:36,171 --> 00:03:38,254 -like, encapsulate it into a small little summary but. -那是不可能的。 - -70 -00:03:38,257 --> 00:03:42,659 -I do have this slide right here that divides it into these four layers. -我在这个课件中,将其分为四层。 - -71 -00:03:42,661 --> 00:03:46,763 -These four layers are approximately down near the hardware at the bottom. -这四层从靠近硬件的底层 - -72 -00:03:46,765 --> 00:03:48,264 -Up near the user at the top. -到靠近用户的顶层。 - -73 -00:03:48,266 --> 00:03:48,964 -Okay? -OK? - -74 -00:03:48,966 --> 00:03:52,284 -So at the bottom, so -在最下面一层, - -75 -00:03:52,285 --> 00:03:55,603 -a lot of people don't realize that iOS is basically a Unix-based operating system. -很多人没有意识到,IOS基本就是一个基于Unix的操作系统。 - -76 -00:03:55,605 --> 00:03:57,772 -'Kay? It's very similar shares a lot of -它大量借鉴了 - -77 -00:03:57,774 --> 00:03:59,206 -the core of Mac OS 10. -Mac OS 10的核心。 - -78 -00:03:59,208 --> 00:04:01,559 -Okay? -OK? - -79 -00:04:01,560 --> 00:04:03,911 -Now, it's certainly optimized for mobile devices, which have -当然,它是为有电池等等各方面限制的移动设备优化过的, - -80 -00:04:03,913 --> 00:04:08,748 -battery restrictions and things like that, but that is basically what it is. -但基本上它仍可看作是一个Mac OS。 - -81 -00:04:08,750 --> 00:04:11,517 -And so down at that layer you've got sockets, and -这样的话,在这层中包含了有关通信接口, - -82 -00:04:11,519 --> 00:04:15,121 -you've got you know, permissions, and things like that, -权限等等类似的功能, - -83 -00:04:15,123 --> 00:04:19,191 -that have to be near the oh you know, hardware to, to work properly. -它靠近底层硬件,并保证其正常工作。 - -84 -00:04:19,193 --> 00:04:23,495 -But above that there's kind of an Object-Oriented layer that lets you get at -在这之上,是一个面向对象的层, - -85 -00:04:23,497 --> 00:04:26,731 -a lot of that stuff using Object-Oriented Programming. -其能够让你使用大量的面向对象编程技术。 - -86 -00:04:26,733 --> 00:04:30,234 -'Kay? And this stuff is not UI oriented it's -但是这层不会处理用户界面, - -87 -00:04:30,236 --> 00:04:34,171 -more kind of accessing the hardware through Object-Oriented Programming or -其更多用于通过面向对象访问硬件, - -88 -00:04:34,173 --> 00:04:36,373 -accessing networking through Object-Oriented Programming but -或者访问网络,等等。 - -89 -00:04:36,375 --> 00:04:39,309 -it's a big layer there and so we will spend a fair amount of -它是一个很大的层,我们将花大量时间 - -90 -00:04:39,311 --> 00:04:44,980 -time in this layer because we need those primitives to build at the higher layers. -在该层上,因为我们需要这些原语来建立更高的层。 - -91 -00:04:44,982 --> 00:04:48,450 -Then, there's this whole layer, which I wish we had more time to spend on. -我希望我们有更多时间花在这一层, - -92 -00:04:48,452 --> 00:04:50,252 -We only get ten weeks in this whole class. -但是我们的课程只有十周。 - -93 -00:04:50,254 --> 00:04:53,321 -It goes by so fast, you'll be amazed, as you're probably, -你会感叹在斯坦福的课程中, - -94 -00:04:53,323 --> 00:04:54,655 -used to with your Stanford courses. -时间过得如此之快。 - -95 -00:04:55,758 --> 00:04:58,092 -But there's a whole media layer here, both for -再往上,是整个的媒体层, - -96 -00:04:58,094 --> 00:05:02,062 -static images, as you know, JPEG and things like that. -包括比如你们熟悉的JPEG等的静态图像, - -97 -00:05:02,064 --> 00:05:07,700 -And video both capturing video, editing video, all that. -包括视频捕获、视频编辑等的视频处理, - -98 -00:05:07,702 --> 00:05:11,404 -Incredible audio, the frameworks on this device for -不可思议的音频框架,用于处理3D音效, - -99 -00:05:11,406 --> 00:05:13,706 -doing 3D audio for games and all that. -以及游戏等等。 - -100 -00:05:13,708 --> 00:05:16,675 -I get to, unfortunately I get to very little of this layer. -很不幸,我对这层知道的不多。 - -101 -00:05:16,677 --> 00:05:20,879 -But I'll try to let you know, that it's in there and then you'll know to go out and -但是我可以告诉你它里面有什么,这样你用到的时候就可以 - -102 -00:05:20,881 --> 00:05:23,948 -seek out, if you're building a very audio intensive app or -查资料,或者当你正在写一个用到大量音频视频技术 - -103 -00:05:23,950 --> 00:05:26,484 -video intensive app, you'll seek out that layer. -的应用的时候,你要知道去哪找这些资料。 - -104 -00:05:26,486 --> 00:05:32,756 -But we'll spend the vast majority of our time at the Cocoa Touch layer. -我们会在Cocoa Touch层上花费大量的时间。 - -105 -00:05:32,758 --> 00:05:35,325 -So the Cocoa Touch layer, that's where the buttons and -Cocoa Touch层里包含了按钮, - -106 -00:05:35,327 --> 00:05:38,895 -sliders and things like that are it's the layer, -滑动条等类似的控件, - -107 -00:05:38,897 --> 00:05:43,032 -where you're gonna build the interactivity with your end user. -通过它们来和你的用户建立互动。 - -108 -00:05:43,034 --> 00:05:46,135 -And so, that's where we probably spend 70 plus percent of -我们会在Cocoa Touch层上 - -109 -00:05:46,137 --> 00:05:47,936 -our time in the Cocoa Touch layer. -花费70%甚至更多的时间。 - -110 -00:05:47,938 --> 00:05:50,271 -And this is a very powerful layer. -这也是一个非常强大的层。 - -111 -00:05:50,273 --> 00:05:54,809 -You know, you've seen things like the maps app on the phone. -你们可能在手机上见过地图类的应用。 - -112 -00:05:54,811 --> 00:05:58,346 -There's basically, an object that does almost the entire maps app, that you can -基本上,有一个几乎完整的地图应用对象, - -113 -00:05:58,348 --> 00:06:01,482 -just drop right into your program, and now you have maps in your program. -你只需要直接拖进你的程序里,现在你的程序中就有地图了。 - -114 -00:06:01,484 --> 00:06:04,051 -Same thing with web browser. -同样的还有浏览器。 - -115 -00:06:04,052 --> 00:06:06,619 -If you wanna put web browsing in your app, it's just boom, pop an object in there, -如果你想让你的应用有浏览网页的功能,那么仅仅需要拖拽一个对象, - -116 -00:06:06,622 --> 00:06:08,655 -call a couple methods and in your, on your way. -再调用几个方法即可。 - -117 -00:06:08,657 --> 00:06:13,592 -So very powerful, very high level in there's a lot going on in there and -在我这里你将学到非常NB的技术。 - -118 -00:06:13,594 --> 00:06:16,195 -that's where we will spend most of our time, 'kay? -我们将在此花费大量的时间。 - -119 -00:06:16,197 --> 00:06:19,831 -And by the way, if you have any questions I try to glance up, so -顺便说一嘴,如果你有任何问题,你就说嘛。 - -120 -00:06:19,833 --> 00:06:21,499 -the bright lights over there sometimes in my way, -你不说我怎么知道呢? - -121 -00:06:21,501 --> 00:06:25,302 -but, shout out or you know, otherwise get my attention. -虽然你很有诚意的看着我, - -122 -00:06:25,304 --> 00:06:28,105 -If you feel free to interrupt. -可是你还是要跟我说啊。 - -123 -00:06:28,107 --> 00:06:29,806 -Then there's the development platform itself. -接下来就是开发平台本身。 - -124 -00:06:29,808 --> 00:06:31,308 -'Kay? -OK? - -125 -00:06:31,309 --> 00:06:32,809 -With the tools we use to build these iOS apps. -我们会用这些工具来创建IOS应用。 - -126 -00:06:32,811 --> 00:06:34,978 -What's in that? -那么问题来了。都有什么? - -127 -00:06:34,979 --> 00:06:37,146 -Well, it's all pretty much now been funneled into this one -有很多很棒的工具 - -128 -00:06:37,148 --> 00:06:39,048 -application called Xcode 6. -都集成在一个名为Xcode6的应用内。 - -129 -00:06:39,050 --> 00:06:42,418 -There are some little adjuncts that it calls out to but -其中还有一些附件。 - -130 -00:06:42,420 --> 00:06:45,287 -Xcode 6 is everything, it's your code editor, -Xcode6,你值得拥有,它是一个代码编辑器, - -131 -00:06:45,289 --> 00:06:50,024 -it's your compiler, your debugger all of that in one, pretty awesome app. -它是一个编译器,是一个调试器,总之是一个很棒的应用。 - -132 -00:06:50,026 --> 00:06:54,395 -And so we'll be learning all about Xcode 6 in this class, and -所以我们学习的所有课程都会用到Xcode6。 - -133 -00:06:54,397 --> 00:06:59,366 -that's where you'll be spend all your time developing, you're not gonna be at -你所有编程的时间都在用Xcode,你不需要 - -134 -00:06:59,368 --> 00:07:04,337 -a terminal typing in Emacs or something, you're gonna be in Xcode 6. -在终端下用Emacs或其他的编辑器,一切尽在Xcode6。 - -135 -00:07:04,339 --> 00:07:08,874 -Languages I have there's actually, two languages in iOS now. -现在为IOS开发应用可以使用两种语言。 - -136 -00:07:08,876 --> 00:07:12,044 -There are peers that you can pretty much use either one. -你可以选择使用任何一个。 - -137 -00:07:12,046 --> 00:07:14,079 -One of them is called Objective-C, -其中一个名为Objective-C - -138 -00:07:14,081 --> 00:07:17,715 -that's the language that iOS was originally developed for. -它也是IOS一直以来使用的开发语言。 - -139 -00:07:17,717 --> 00:07:22,553 -It's a language been around a long time, probably 30 years it's been around or 25 -这个语言已经有大概30年的历史了, - -140 -00:07:22,555 --> 00:07:27,123 -to 30 years that's it's actually been used to build stuff that's on the Mac today. -25到30年以来,人们用它为Mac开发应用。 - -141 -00:07:27,125 --> 00:07:32,194 -So, it's very mature language but it's also 25, 30 years old. -因此,它是非常成熟的语言,但是已经25,30岁了。 - -142 -00:07:32,196 --> 00:07:36,965 -And so Apple last summer introduced a completely new language called Swift, and -所以苹果公司在去年夏天发布了一个全新的语言,Swift - -143 -00:07:36,967 --> 00:07:40,669 -Swift, you can do pretty much everything in iOS with Swift and/nSwift,你可以使用Swift在IOS上开发任何应用, - -144 -00:07:40,671 --> 00:07:45,172 -that's the language we're gonna learn because it's a modern language. -她也是本次课我们要学习的语言,她是一门现代的语言。 - -145 -00:07:45,174 --> 00:07:48,709 -Apple did a great job of kind of, building all the best stuff of -苹果公司做了很多伟大的工作创建Swift, - -146 -00:07:48,711 --> 00:07:52,346 -all the languages that have been invented over the last, you know, -她吸收了很多已存在的编程语言的优点。 - -147 -00:07:52,348 --> 00:07:57,684 -25 years of this especially the last five or ten years into this language. -25年来,特别是近五到十年的语言。 - -148 -00:07:57,686 --> 00:08:02,988 -It's very concise it's a very type safe language but has type inference and a lot -她语法简洁。她是类型安全的,并且还有类型推断以及 - -149 -00:08:02,990 --> 00:08:06,991 -of things that make it so that you get the best of both worlds by having type safety- -大量的特性使鱼与熊掌可以兼得。既有安全的类型 - -150 -00:08:06,993 --> 00:08:08,292 ->> [COUGH] >> And not have to -又不需要 - -151 -00:08:08,294 --> 00:08:11,295 -be constantly over specifying everything. -不断的指定各种类型。 - -152 -00:08:11,297 --> 00:08:14,665 -So we're gonna go Swift only, I'm not even gonna really talk about Objective-C, -所以我们只使用Swift,而完全不用Objective-C, - -153 -00:08:14,667 --> 00:08:16,400 -I just don't have time to do both languages. -我也没有时间讲两种语言 - -154 -00:08:16,402 --> 00:08:19,786 -Yeah. >> [INAUDIBLE] This is -(学生提问) - -155 -00:08:19,787 --> 00:08:23,171 -a [INAUDIBLE] course [INAUDIBLE] [COUGH] [INAUDIBLE] doing iOS development. -(学生提问) - -156 -00:08:23,174 --> 00:08:26,275 ->> Yeah, so the question is if I'm going out into the world to do -这个同学的问题是,如果我将步入社会, - -157 -00:08:26,277 --> 00:08:29,244 -iOS development in the real world for real companies. -并想找一份做IOS开发的工作, - -158 -00:08:29,246 --> 00:08:30,912 -Am I probably, gonna have to learn Objective-C? -我是否还需要学习Objective-C? - -159 -00:08:30,914 --> 00:08:34,049 -And the answer is [NOISE] it depends on the company you're at. -答案是...这取决于你的公司。 - -160 -00:08:34,051 --> 00:08:36,017 -Probably in the short term, yes. -可能在短期内,答案是肯定的。 - -161 -00:08:36,019 --> 00:08:39,920 -But as the time goes by probably, more and more people switch to siff, Swift. -但是随着时间的推移,可能有越来越多的人会转到丝芙,哦不,Swift。 - -162 -00:08:39,922 --> 00:08:43,490 ->> [COUGH] >> The good thing is the underlying iOS -好消息就是基础的IOS - -163 -00:08:43,492 --> 00:08:45,926 -APIs are exactly the same for both, its just the syntax- -API是完全相同的,仅仅只是语法上 - -164 -00:08:45,928 --> 00:08:49,162 ->> [COUGH] >> Of the language a little bit -对于一个语言如何调用API - -165 -00:08:49,163 --> 00:08:52,397 -about how the language approaches calling the API is slightly different, but any,会有略微的不同,但是 - -166 -00:08:52,400 --> 00:08:54,734 -everything that you learn in here about the underlying, -你们在这里学的基础, - -167 -00:08:54,736 --> 00:08:57,636 -lying parts of iOS will totally work in Objective-C. -使用Objective-C完全也可以实现。 - -168 -00:08:57,638 --> 00:08:59,571 -All the methods are the same you know, -所有的方法都是一样的, - -169 -00:08:59,573 --> 00:09:00,939 -it's just the syntax is a little different. -仅仅只有语法上的一点区别。 - -170 -00:09:00,941 --> 00:09:02,540 ->> [COUGH] >> So, don't feel too bad about not -所以对于没有学全两门语言, - -171 -00:09:02,542 --> 00:09:05,276 -learning both languages, and once you've learned this language, -不要感到沮丧。一旦你的Swift出师了, - -172 -00:09:05,278 --> 00:09:07,911 -learning Objective-C is gonna be pretty easy, too. -再学Objective-C也只是分分钟的事。 - -173 -00:09:07,913 --> 00:09:10,414 -So. Good question though. -这个问题问的很好。 - -174 -00:09:10,416 --> 00:09:11,815 -All right. -很好。 - -175 -00:09:11,817 --> 00:09:14,617 -Of course iOS is filled with tons of frameworks. -当然,IOS内部拥有成吨的框架, - -176 -00:09:14,619 --> 00:09:18,320 -Frameworks are libraries, basically, of objects that you use, -框架就是你会用到的类库以及基本对象。 - -177 -00:09:18,322 --> 00:09:20,989 -as building blocks to build your application. -作为搭建你的应用的模块, - -178 -00:09:20,991 --> 00:09:23,325 -And we are going to be covering them. -以供我们方便的使用。 - -179 -00:09:23,327 --> 00:09:25,193 -UIKit is the main one. -UIKit就是其中主要的一个。 - -180 -00:09:25,195 --> 00:09:27,829 -It's got most of the user interface stuff in it. -它包含了大量的关于用户界面的东西。 - -181 -00:09:27,831 --> 00:09:32,266 -Foundation is that most the course services layer that I was talking about, -Foundation将是在Core Service层中我提到最多的框架。 - -182 -00:09:32,268 --> 00:09:37,070 -and but there's tons of other ones, core motion for doing the, the device moving -其他还有很多,core motion框架用于设备移动, - -183 -00:09:37,072 --> 00:09:42,075 -around, you know, gyro and accelerometer, core data for Object-Oriented database. -旋转,陀螺及加速度等的响应,core data框架用于面向对象的数据库, - -184 -00:09:42,077 --> 00:09:44,961 -Things like that. -等等等等... - -185 -00:09:44,962 --> 00:09:47,846 -So I'll get to, as many as those as I can, especially the big ones. -我会尽我所能尽可能多的讲给你们,特别是那些大的框架。 - -186 -00:09:47,848 --> 00:09:50,849 -But there's just way too many to cover in ten weeks. -但是这对一个只有十周的课,显得太臃肿了。 - -187 -00:09:51,851 --> 00:09:53,884 -And finally we I, I put this, -然而最终的,以上的那些东西 - -188 -00:09:53,886 --> 00:09:58,188 -as a first class thing with all the rest, as a design strategy MVC. -均不是我们第一课要讲的内容。我首先要说的是一个叫做MVC的设计模式。 - -189 -00:09:58,190 --> 00:10:01,124 -I think, I usually ask, I'll all ask this year, too. -我想,我经常会问,同样今年我也要问一个问题, - -190 -00:10:01,126 --> 00:10:05,361 -How many people have used MVC in some other class? -你们有多少同学曾经在其他课上用过MVC? - -191 -00:10:05,363 --> 00:10:07,196 -See, so it's half of you. -哦,有一半的同学。 - -192 -00:10:07,198 --> 00:10:09,698 -So I'll be teaching MVC, as if you don't know it, so -有同学不知道,那么我先说说MVC。 - -193 -00:10:09,700 --> 00:10:11,599 -if you don't know it don't worry. -就算你不知道它,也不用担心。 - -194 -00:10:11,601 --> 00:10:15,636 -But MVC is a way of designing your application so that it's a little more -MVC是你设计应用的一种方式,用它设计的代码 - -195 -00:10:15,638 --> 00:10:21,141 -debuggable, reusable understandable to you and to anyone reading your code. -无论是你自己或者其他人去读都更易理解,也更易调试,易复用。 - -196 -00:10:21,143 --> 00:10:25,278 -And iOS was designed with MVC from the start. -而IOS从一开始就使用MVC设计。 - -197 -00:10:25,280 --> 00:10:28,214 -So it's just integral part to building an iOS. -而这仅仅是创建一个IOS应用整体中的一部分。 - -198 -00:10:28,216 --> 00:10:33,452 -Now, I'm gonna do the demo today, and on Wednesday I'm kinda not gonna follow MVC. -现在,我要做今天的演示。而在周三我有点不想遵循MVC。 - -199 -00:10:33,454 --> 00:10:37,922 -But then next Monday we're gonna apply MVC to the demo I'm doing today and -但是下周一我会应用MVC继续今天的演示, - -200 -00:10:37,924 --> 00:10:41,426 -Wednesday, so you're gonna get the full MVC treatment there. -周三的时候你们要对MVC有充分的理解。 - -201 -00:10:41,428 --> 00:10:45,262 -And I'll be having some slides on MVC on Wednesday to prepare you for next Monday.然后我将一些周三用的MVC课件准备到下周一。 - -202 -00:10:46,832 --> 00:10:49,699 -Okay? All right, so here's the demo. -OK?好,下面开始演示。 - -203 -00:10:49,701 --> 00:10:51,818 -The demo I'm gonna do, -接下来我要做的演示 - -204 -00:10:51,819 --> 00:10:53,936 -is something I actually did a few years ago that really works well- -是我前几年做的,运行起来还不错。 - -205 -00:10:53,938 --> 00:10:55,971 ->> [COUGH] >> With Swift, which is a calculator. -它是一个计算器,我们用Swift实现它。 - -206 -00:10:55,973 --> 00:10:57,373 -So, we're gonna build this calculator. -现在,我们来创建这个计算器。 - -207 -00:10:57,375 --> 00:11:00,509 -And we're gonna build it from scratch, all the way. -我们将从头开始,一步一步创建它。 - -208 -00:11:00,511 --> 00:11:04,545 -And I like to do my demos, where I only type in stuff, I don't copy and -我喜欢动手敲代码来做演示,而不会复制 - -209 -00:11:04,547 --> 00:11:06,914 -paste big chunks of code in or whatever. -粘贴大段代码或者什么的。 - -210 -00:11:06,916 --> 00:11:09,817 -I know, I'd see a lot of laptops open, a lot of people like to try and -我知道,我看到很多人都打开了笔记本,很多人都喜欢 - -211 -00:11:09,819 --> 00:11:12,736 -follow along with me. -跟着我亲自动手尝试。 - -212 -00:11:12,737 --> 00:11:15,654 -I'm a fast typer, but usually in most demos you can keep, keep up if you want. -我打字速度很快,但是通常在大多数演示中,你还是能够跟上我的速度,只要你想。 - -213 -00:11:15,657 --> 00:11:20,426 -I don't recommend it necessarily, or certainly I don't require it. -我并不推荐这么做,或者说不必要这样。 - -214 -00:11:20,428 --> 00:11:25,197 -I am going to, you, you'll be able to go back and -我想你,你可以回去 - -215 -00:11:25,199 --> 00:11:28,400 -watch this particular demo on video. -看一遍这个演示视频。 - -216 -00:11:28,402 --> 00:11:30,535 -Even Stanford people will be able to do that. -即使斯坦福的学生可以这么做, - -217 -00:11:30,537 --> 00:11:34,805 -Because your first assignment is gonna be to reproduce what I do. -因为你的首要任务是要重现我所做的。 - -218 -00:11:34,807 --> 00:11:37,041 -'Kay? That is 90% of your first assignment. -OK?这就是你第一份任务的90% - -219 -00:11:37,043 --> 00:11:40,277 -Reproduce what I'm gonna do, today and on Wednesday. -重现我要做的,今天和星期三。 - -220 -00:11:40,279 --> 00:11:42,946 -So I'm not gonna post the code because I want you to go through the experience of -我不会将代码给你,因为我要你通过这个体验 - -221 -00:11:42,948 --> 00:11:45,615 -typing the code in, and if you watch in on video, -自己动手敲代码,即时你是在看这个视频, - -222 -00:11:45,617 --> 00:11:50,119 -watching what I do again, and and typing it all in. -再看一遍我干了什么,然后自己敲代码。 - -223 -00:11:50,121 --> 00:11:51,219 ->> [COUGH] 'Kay? -OK? - -224 -00:11:51,221 --> 00:11:52,821 -And I'll explain that all on Wednesday. -我将在周三对所有问题做解释。 - -225 -00:11:54,457 --> 00:11:56,340 -Okay? -OK? - -226 -00:11:56,341 --> 00:11:58,224 -So, I put on the slide a bunch of things that I'm gonna cover, but I'm not gonna go -我要把课件盖住了。但是我不会 - -227 -00:11:58,227 --> 00:12:01,628 -over it in advance, I'm just gonna sit, sit and soon I'll start doing it. -向前翻,我要坐下,然后开始演示。 - -228 -00:12:01,630 --> 00:12:04,498 -So any questions before I dive in here? -在这之前还有什么问题吗? - -229 -00:12:04,500 --> 00:12:08,401 -I know we're gonna little fast, but I wanna maximize your learning time. -我知道我讲的有点快,因为我想最大化你们的学习时间。 - -230 -00:12:08,403 --> 00:12:11,870 -[INAUDIBLE] [NOISE]. -(同学提问) - -231 -00:12:11,872 --> 00:12:12,771 -Direct of what? -什么玩意? - -232 -00:12:12,773 --> 00:12:14,706 -Recommendation to which Xcode- -(同学提问) - -233 -00:12:14,708 --> 00:12:18,142 -So the questions, which Xcode should we use, should you use? -那么问题来了,我们应该用哪个版本的Xcode?你用的是哪个版本? - -234 -00:12:18,144 --> 00:12:20,811 -Well, you should just use the one on the Mac App store. -你们用Mac App Store上下载的就好了。 - -235 -00:12:20,813 --> 00:12:23,247 -So, just go to the Mac App store, it's free. -去Mac App Store上免费下载。 - -236 -00:12:23,249 --> 00:12:25,482 -Use the one there, whatever the latest one is. -那里的是最新的版本。 - -237 -00:12:25,484 --> 00:12:28,618 -If a new one comes out in the quarter, well, let's all switch over to it. -如果有更新的版本出来,那么我们就换成那个。 - -238 -00:12:28,620 --> 00:12:30,620 -Okay, let's just always be using the latest Xcode. -总之我们用的是最新版本的Xcode。 - -239 -00:12:30,622 --> 00:12:31,354 -'Kay any- -OK,还有问题吗? - -240 -00:12:31,356 --> 00:12:32,621 -[INAUDIBLE] Beta [INAUDIBLE] No. -(同学提问)[应该是问是否要用测试版] - -241 -00:12:32,623 --> 00:12:33,855 -Not. We're not gonna using a beta or -不,我们不用测试版 - -242 -00:12:33,857 --> 00:12:35,624 -anything like that. -或者类似的一些版本。 - -243 -00:12:35,625 --> 00:12:37,392 -We'll just use whatever the currently published Xcode is. -我们只用当前最新的Xcode的发布版本。 - -244 -00:12:38,995 --> 00:12:41,746 -Okay. -OK - -245 -00:12:41,747 --> 00:12:44,498 -So, I'm going to start this demo actually by launching Xcode. -那么我要开始运行Xcode来演示了。 - -246 -00:12:44,500 --> 00:12:46,265 -So, here it is, right here. -额,这,在这。 - -247 -00:12:48,069 --> 00:12:50,669 -Xcode. - -248 -00:12:50,670 --> 00:12:53,270 -And when you launch Xcode, let's hide others here. -运行Xcode以后,我们把其他东西隐藏起来。 - -249 -00:12:53,273 --> 00:12:55,140 -You're gonna get this splash screen and -你会看到这个欢迎界面 - -250 -00:12:55,142 --> 00:12:58,376 -on this splash screen on the right, this is gonna be all your projects. -在欢迎界面的右边,将展示你所有的项目。 - -251 -00:12:58,378 --> 00:13:00,711 -Now, since it's the beginning of the quarter, we don't have any projects yet, -现在,这学期刚刚开始,我们还没有任何的项目。 - -252 -00:13:00,713 --> 00:13:04,048 -but they'll all be listed here, so as the quarter goes by this will fill up. -但是慢慢的,我们会逐渐将这个列表填满。 - -253 -00:13:04,050 --> 00:13:07,284 -You can turn this splash screen off, if you don't like it by the way. -如果你不喜欢这个欢迎页面,可以将它关闭。 - -254 -00:13:07,286 --> 00:13:10,820 -This splash screen also lets us do things like playgrounds and -欢迎界面中也可以创建例如playground, - -255 -00:13:10,822 --> 00:13:13,256 -a source code management right down here. -或者源代码管理,像这里。 - -256 -00:13:13,258 --> 00:13:15,024 -We're not gonna be doing that for a while. -我们不会这么做很久, - -257 -00:13:15,026 --> 00:13:16,859 -We're gonna be focusing on this option, right here. -我们需要关注的是这个选项,这里。 - -258 -00:13:16,861 --> 00:13:18,760 -Create a new Xcode project. -创建新的Xcode项目。 - -259 -00:13:18,762 --> 00:13:22,463 -If you don't have the splash screen, you can go to File > New > Project. -如果你看不到欢迎界面,你也可以用菜单文件>新建>项目 - -260 -00:13:22,465 --> 00:13:23,748 -Kay. -OK - -261 -00:13:23,749 --> 00:13:25,032 -Same thing, those both the same thing. -一样的,它们都是一样的。 - -262 -00:13:25,034 --> 00:13:28,469 -So I'm gonna click right here on Create a new project. -下面我点击这里,创建一个新项目。 - -263 -00:13:28,471 --> 00:13:31,605 -When I create a new project, it wants to know what kind of project you want to -当我创建新项目的时候,她要知道你要创建的是什么类型的项目。 - -264 -00:13:31,607 --> 00:13:35,908 -create, because Xcode is actually used on Mac OS 10 and to build frameworks and -创建,Xcode用于在Mac OS 10上创建框架, - -265 -00:13:35,910 --> 00:13:38,494 -all that stuff. -以及所有东西。 - -266 -00:13:38,495 --> 00:13:41,079 -But we're always gonna be building iOS Applications. -但是我们经常创建的是IOS,应用。 - -267 -00:13:41,082 --> 00:13:43,382 -And in fact, we're always gonna use this template right here, -事实上,我们经常用到的模板是在这里, - -268 -00:13:43,384 --> 00:13:44,783 -Single View Application. -单页面(视图)应用。 - -269 -00:13:44,785 --> 00:13:47,236 -'Kay? -OK? - -270 -00:13:47,237 --> 00:13:49,688 -That's kind of your basic MVC starter application and -这就是你的基础MVC入门应用。 - -271 -00:13:49,690 --> 00:13:53,724 -we're gonna build very complicated apps out of that, but we're gonna start here, -我们会用其他这些创建非常复杂的应用,但是我们从这里开始。 - -272 -00:13:53,726 --> 00:13:55,592 -so you always click on that one. -所以你会经常点这个。 - -273 -00:13:55,594 --> 00:13:58,528 -Then it wants to know what you want to call your app, and -然后它想知道你会如何称呼你的应用。 - -274 -00:13:58,530 --> 00:14:02,598 -we're building a calculator, so we're gonna call our app, Calculator. -我们正在创建的是计算器,所以我们给我们的应用起名为,Calculator。 - -275 -00:14:02,600 --> 00:14:04,634 -'Kay? -OK? - -276 -00:14:04,635 --> 00:14:06,669 -This organization name doesn't really matter that's just gonna appear in -这个组织名称并不重要,它只会出现在 - -277 -00:14:06,671 --> 00:14:10,339 -copyright notice and the code that you write at the top in a comment so -类似版权信息,或者你的代码开头的注释中,所以 - -278 -00:14:10,341 --> 00:14:12,291 -don't worry about that. -不用管它。 - -279 -00:14:12,292 --> 00:14:14,242 -But this organization identifier that is very important. -但是这里的组织标识符是非常重要的。 - -280 -00:14:14,244 --> 00:14:17,611 -'Kay, this uniquely identifies you. -它是你的唯一标识符。 - -281 -00:14:17,613 --> 00:14:19,230 -Okay? -OK? - -282 -00:14:19,231 --> 00:14:20,848 -So that on the next line we can you just, -所以在下一行里我们,你会 - -283 -00:14:20,850 --> 00:14:23,950 -new uniquely idefy, identify your calculator. -有一个新的唯一的标识符,标识你的计算器。 - -284 -00:14:23,952 --> 00:14:26,219 -So here if your a Stanford student, -所以如果你是斯坦福的学生, - -285 -00:14:26,221 --> 00:14:31,490 -you'll wanna use this reverse DNS notation here edu.stanford.cs1983p. -你要使用这个反转的DNS域名,edu.stanford.cs1983p。 - -286 -00:14:31,492 --> 00:14:35,093 -And instead of instructor there, you wanna put your SU net ID. -并用你的SU网络ID将instructor替换 - -287 -00:14:35,095 --> 00:14:36,661 -'Kay? -OK? - -288 -00:14:36,663 --> 00:14:37,929 -Cuz nobody else has that but you. -[因为:Nobody Nobody But You] -Sorry,因为那东西只有你才有 - -289 -00:14:37,931 --> 00:14:39,864 -And that'll uniquely identify you. -这样这个标识符就是唯一的了。 - -290 -00:14:40,900 --> 00:14:44,201 -As I said, we're using Swift not Objective-C. -我说过,我们要用Swift而不是Objective-C。 - -291 -00:14:44,203 --> 00:14:49,272 -And we're gonna build an app that works be, equally well on iPad and -我们要创建的应用要能同时工作在iPad和 - -292 -00:14:49,274 --> 00:14:51,507 -iPhone, that's called a universal app. -iPhone上,所以选择Universal应用。 - -293 -00:14:51,509 --> 00:14:54,209 -You can pick to develop for only one or the other. -你也可以选择只为其中一种设备开发。 - -294 -00:14:54,211 --> 00:14:56,745 -But we are going to go universal here. -但是我们现在创建的是通用的。 - -295 -00:14:56,747 --> 00:15:00,248 -We're not gonna really be doing the iPad part of it for a couple weeks. -在这几周之内我们不会真的做它的iPad部分。 - -296 -00:15:00,250 --> 00:15:04,352 -But it is our intent to eventually build an app that works on both. -但是它最终会创建一个通用的应用[同时运行在iPad和iPhone上]。 - -297 -00:15:04,354 --> 00:15:06,186 -Okay we're not going to be using core data, -额,我们现在还用不到core data。 - -298 -00:15:06,188 --> 00:15:09,322 -that's object oriented database stuff so you just leave that unchecked. -那是关于面向对象数据库的东西,现在先不要选它。 - -299 -00:15:09,324 --> 00:15:13,993 -And now it's asking where we want to save it, I strongly recommend saving in your -现在,它问我们要把项目保存在哪里,我强烈建议保存在你的 - -300 -00:15:13,995 --> 00:15:18,998 -home directory, this is my home directory here in a folder called Developer, okay? -home目录下,这是我的home目录,里面有一个Developer的目录,看到没? - -301 -00:15:19,000 --> 00:15:22,001 -You could put other folders in here if you want to arrange it more, -当然你也可以在这里放其它文件夹,如果你想创建更多的话 - -302 -00:15:22,003 --> 00:15:25,103 -but home directory Developer, I highly recommend that. -不过我建议你放在主目录下的Developer文件夹 - -303 -00:15:25,105 --> 00:15:28,273 -Source control, we will be talking about that at some point in the quarter but -Source control,我们将会在这学期的某些时候讲到,不过 - -304 -00:15:28,275 --> 00:15:30,141 -we're not gonna do it right off the bat here so -我们先跳过这个 - -305 -00:15:30,143 --> 00:15:31,776 -you can leave that unchecked as well. -所以那个选项你可以不打勾 - -306 -00:15:33,045 --> 00:15:37,847 -All right, so here's our first project, its been created so -好啦,这就是我们创建的第一个项目 - -307 -00:15:37,849 --> 00:15:43,586 -this is Xcode that your seeing right here, this is Xcode's main screen and -这里你看到的就是XCode, 这是XCode的主窗口 - -308 -00:15:43,588 --> 00:15:46,955 -the center is really what your working on. -中间这部分是主要的工作区域 - -309 -00:15:46,957 --> 00:15:51,026 -The left is, area here, is called the navigator, and the navigator you, -左边的区域,被称作navigator(导航栏) - -310 -00:15:51,028 --> 00:15:54,829 -you use to kind of choose what you're working on but you can also do -通常用来选择特定的选项,不过也你可以用来 - -311 -00:15:54,831 --> 00:15:59,367 -things over here like search hough your whole project, that's this little guy. -搜索整个项目的东西,这就是这个小图标的作用 - -312 -00:15:59,369 --> 00:16:04,838 -Look at all your break points maybe, look at previous builds that you've done, -这里用来查看断点,这里用来查看之前编译的项目 - -313 -00:16:04,840 --> 00:16:09,076 -browse your project by class hierarchy, all that stuff. -这里可以以类的层次结构展开整个项目,等等 - -314 -00:16:09,078 --> 00:16:12,312 -But we're usually on the left most one here which is just all of the files in -不过我们通常会点击左边的区域,这里可以看到我们所有的文件 - -315 -00:16:12,314 --> 00:16:17,750 -your project which can also can be organized hierarchically like this. -像这样,你的项目可以有按层次展现出来 - -316 -00:16:17,752 --> 00:16:19,585 -And when you select something here on the left, -当你选择左边区域这里的某些部分, - -317 -00:16:19,587 --> 00:16:23,588 -the middle will fill up with what that you've selected so. -中间区域会出现你刚刚选择的那部分内容 - -318 -00:16:23,590 --> 00:16:26,591 -Here I have the actual project itself selected. -这里我选择了这个项目本身 - -319 -00:16:26,593 --> 00:16:28,993 -So these are the project settings of which there are tons. -所以这里可以看到这个项目的很多设置项 - -320 -00:16:28,995 --> 00:16:31,662 -All along the top here you can see tons of settings. -在这上面你还可以看到更多设置项 - -321 -00:16:31,664 --> 00:16:34,431 -We're, we'll go through them as the quarter goes on and -随着学期进展我们将会讲到这些 - -322 -00:16:34,433 --> 00:16:37,100 -you've already seen some of them like the bundle identifier there and -你已经看到其中的一部分,比如这里的Bundle identifier(包标识符) - -323 -00:16:37,102 --> 00:16:38,702 -the fact this is a universal app. -还可以看到这里是一个通用app - -324 -00:16:38,704 --> 00:16:41,037 -We're not going to talk about anymore of this today, -不过我们今天不会讲关于项目设置 - -325 -00:16:41,039 --> 00:16:42,805 -this project settings business. -的更多内容 - -326 -00:16:42,807 --> 00:16:45,107 -We're gonna focus here on some of these files. -我们会把注意力集中在这些文件 - -327 -00:16:45,109 --> 00:16:47,409 -And even some of these files, like this AppDelegate, -甚至是这些文件,比如AppDelegate - -328 -00:16:47,411 --> 00:16:50,845 -I'm just gonna move that down to Supporting Files to get it out of the way. -我会把它们移到Supporting Files - -329 -00:16:50,847 --> 00:16:53,081 -Same things with these image assets, -image assets文件夹也是 - -330 -00:16:53,083 --> 00:16:56,117 -LaunchScreen well get to this later in the quarter. -LaunchScreen我们之后会讲到 - -331 -00:16:56,119 --> 00:16:58,285 -But I wanna focus on these two files right here. -不过我们现在会把注意力集中在这两个文件上 - -332 -00:16:58,287 --> 00:17:03,957 -Okay Main.storyboard and ViewController.swift, okay -Main.storyboard 和ViewController.swift - -333 -00:17:03,959 --> 00:17:06,192 -In the MVC world by the way, this is the V, -顺便说,在MVC中这称为V - -334 -00:17:06,194 --> 00:17:10,896 -the view and this is the C, the controller but we will talk about MVC on Wednesday. -即视图,这是C,即控制器,我们将在周三讲到MVC - -335 -00:17:11,999 --> 00:17:13,665 -So what do these things contain? -所以这些东西包含什么 - -336 -00:17:13,667 --> 00:17:16,234 -So this Main.storyboard, if I click on it, -这是Main.storyboard,如果我点击它 - -337 -00:17:16,236 --> 00:17:18,936 -you see it appear in the middle, this is our UI. -可以看到我们的UI出现在中间 - -338 -00:17:19,972 --> 00:17:21,972 -Okay, this is our user interface. -恩,这就是我们的用户界面 - -339 -00:17:21,973 --> 00:17:23,973 -So for a calculator this is going to be a little display, -对于计算器而言,这里将会是一个稍微小一点的显示区域 - -340 -00:17:23,976 --> 00:17:27,811 -this shows the number that we're working on or whatever at the top. -这里会显示我们计算出来的数字或任何其它在上面的数字 - -341 -00:17:27,813 --> 00:17:32,448 -And lots of buttons down here, number buttons, times, multi, or sorry, times, -下面这里会有很多按钮,包括数字,乘除 - -342 -00:17:32,450 --> 00:17:34,917 -divide, plus, minus, square root. -加减,平方根 - -343 -00:17:34,919 --> 00:17:36,451 -That's all going to be here. -都会出现在这里 - -344 -00:17:36,453 --> 00:17:39,521 -So we're going to build this entire user interface. -所以我们即将完全图形化地搭建整个用户界面 - -345 -00:17:39,523 --> 00:17:41,055 -Purely graphically. - - -346 -00:17:41,057 --> 00:17:43,057 -Okay? We're not gonna be writing code. -明白不,我们不会写代码 - -347 -00:17:43,059 --> 00:17:45,259 -Put button at this location. -来指出哪个按钮该放哪个位置 - -348 -00:17:45,261 --> 00:17:47,411 -None of that, okay? -一点代码都没有,懂不? - -349 -00:17:47,412 --> 00:17:49,562 -We just literally with our mouse are gonna build this whole user interface. -我们只是用我们的鼠标来搭建我们的用户界面 - -350 -00:17:50,499 --> 00:17:53,700 -So what's the code, what do we need any code for? -所以我们的代码写在哪里,什么时候需要写代码? - -351 -00:17:53,702 --> 00:17:57,203 -Well, we, this ViewController.swift, this is a Swift file. -看ViewController.swif,这个Swift文件 - -352 -00:17:57,205 --> 00:18:00,539 -This is your first look at Swift for most of you. -这是你们第一次看Swift文件 - -353 -00:18:00,541 --> 00:18:03,108 -This controller is gonna control that user interface. -这是我们的控制器,用来控制我们的用户界面 - -354 -00:18:03,110 --> 00:18:05,877 -That's why we call it the view controller or the controller. -这就是为什么我们称之为视图控制器或控制器 - -355 -00:18:05,879 --> 00:18:09,180 -It controls user interface and that means it's gonna do things that -它控制用户界面,这意味着它会做某些事情来 - -356 -00:18:09,182 --> 00:18:13,651 -are specific to how this user interface, a calculator's user interface, works. -指定这个用户界面,计算器界面应该怎样工作 - -357 -00:18:13,653 --> 00:18:16,720 -So when we press the digit buttons, it's going to have update the display. -所以当你点击数字按钮,它会更新显示的内容 - -358 -00:18:16,722 --> 00:18:19,856 -When we press times, it's gonna have to do some multiplication and -当我们点击乘法,它将会进行乘法运算并且 - -359 -00:18:19,858 --> 00:18:21,524 -then put the result in the display. -把结果显示出来 - -360 -00:18:21,526 --> 00:18:24,227 -So it's controlling the display. -所以说它会控制界面的展示 - -361 -00:18:24,229 --> 00:18:28,597 -Okay so we'll get back to this code in a moment but we're gonna start by -我们稍后再回到这里,现在我们先从 - -362 -00:18:28,599 --> 00:18:33,802 -building our user interface and by the way, your user interface, you can see I -搭建界面开始,顺便说一句,你可以看到这个用户界面 - -363 -00:18:33,804 --> 00:18:39,140 -have a low resolution screen here so my UI doesn't even really fit in the space here. -因为屏幕的低分辨率,所以我的UI没有很好地适应空间 - -364 -00:18:39,142 --> 00:18:42,677 -You'll probably have maybe a little higher resolution screen then I do but -你可能有比我更高的屏幕分辨率,不过 - -365 -00:18:42,679 --> 00:18:45,979 -if you don't, you can zoom in and out, I'm just right-clicking, -如果你没有,你可以通过点击右键放大缩小 - -366 -00:18:45,981 --> 00:18:49,516 -if you right-click on the background area here, you can zoom in and out. -如果你在这个背景区域点击右键,你可以放大缩小 - -367 -00:18:49,518 --> 00:18:52,652 -You can also do it by double-clicking so if I double-click on this, -你也可以采用双击,看如果我双击这里 - -368 -00:18:52,654 --> 00:18:56,122 -it zooms it to normal, if I double-click on the background, it zooms out so -它放大到正常水平,如果我再双击背景,它会缩小所以 - -369 -00:18:56,124 --> 00:18:57,523 -that way I can see my whole UI. -我可以看到我的整个UI界面 - -370 -00:18:57,525 --> 00:18:59,992 -Now when we build a complicated app -当我们完成了一个复杂的app - -371 -00:18:59,994 --> 00:19:05,663 -we're gonna have a whole bunch of these little square areas, we call these scenes, -我们将会有一大堆这些方块区域,这些我们称之为scenes(场景) - -372 -00:19:05,665 --> 00:19:11,402 -and a scene represents kind of phone full, phone screen full of information. -一个场景代表一个完整显示所有信息的手机屏幕 - -373 -00:19:11,404 --> 00:19:15,072 -Okay and as you you've used many iOS applications, you know that you -就像你使用过的许多iOS程序,你知道 - -374 -00:19:15,074 --> 00:19:20,443 -transition from one screen to another as the user goes through the app and -用户使用这个app通过一个屏幕切换到另外一个屏幕 - -375 -00:19:20,445 --> 00:19:22,111 -that's how your gonna build your apps as well. -这就是你搭建app的方式 - -376 -00:19:22,113 --> 00:19:25,981 -And this storyboard is eventually gonna have a big map showing all -这个storyboard(故事版)最终将会有一个大的地图来显示所有的 - -377 -00:19:25,983 --> 00:19:28,951 -the transitions between all those scenes. -场景间的切换 - -378 -00:19:28,953 --> 00:19:31,019 -Okay, so this storyboard is gonna get big for -好了,所以这个storyboard将会用来搭建 - -379 -00:19:31,021 --> 00:19:35,323 -big apps, your really gonna see your whole application which is kinda cool. -完整的app,所以当你真的看到整个应用程序时,还挺酷的 - -380 -00:19:36,359 --> 00:19:39,893 -So we're gonna start small though, just this one little screen right here. -所以我们将从这一个小的场景开始 - -381 -00:19:39,895 --> 00:19:41,361 -Which is gonna be our calculator. -搭建我们的计算器 - -382 -00:19:41,363 --> 00:19:44,864 -So let's start building our calculator with it's display. -我们先从搭建计算器的界面显示开始 - -383 -00:19:44,866 --> 00:19:45,999 -So I wanna make a display. -所以,当我想显示一些东西时, - -384 -00:19:46,001 --> 00:19:47,917 -So how do I do that? -我应该这样做? - -385 -00:19:47,918 --> 00:19:49,834 -Well that brings us to the right side, the right-hand side here, -我们看一下这里的右边区域 - -386 -00:19:49,837 --> 00:19:53,939 -this whole right side, this is called the Utilities area -右边的整块区域,我们称为工具区域 - -387 -00:19:53,941 --> 00:19:56,675 -You can see that's it's got a bottom and a top, right? -你可以看到这里有底部和顶部,对不? - -388 -00:19:56,677 --> 00:20:01,979 -We want to go into the bottom and on the third tab right here, which is called -来到底部这里的第三个按钮,它被我们称为 - -389 -00:20:01,981 --> 00:20:07,818 -the Object Library, you'll see that there's tons and tons of objects in here. -对象库,你可你看到这里有非常多的对象 - -390 -00:20:07,820 --> 00:20:09,886 -Okay, dozens of these things and -非常多的这类东西 - -391 -00:20:09,888 --> 00:20:13,023 -we're gonna get to a lot of these by the end of the quarter. -我们在学期末将会接触到很多这样的东西 - -392 -00:20:13,025 --> 00:20:15,992 -But these are the things you build your user interface out of. -这些是用于搭建你的用户界面的 - -393 -00:20:15,994 --> 00:20:19,362 -So kind of towards the top, not all the way at the top, but towards the top, -靠近上面,但不完全靠近上面,就在这上面 - -394 -00:20:19,364 --> 00:20:22,731 -you'll start seeing things like buttons and text fields and things like that. -你会开始看到像按钮,文本区域这样的东西 - -395 -00:20:22,733 --> 00:20:26,401 -Well this is what we need obviously, to build our display here, -很明显这是我们构建显示区域所需要的东西 - -396 -00:20:26,403 --> 00:20:28,536 -is some sort of text field, and there's a couple of them here. -是某种显示文本的区域,这里有两种 - -397 -00:20:28,538 --> 00:20:32,140 -One, this one called Label is static text, you see? -这一种称为Label的是一种固定的文本,看到不? - -398 -00:20:32,142 --> 00:20:37,011 -And this one Text Field is editable text, in other words you can touch on this one. -这种称为Text Field是一张可编辑的文本,也就是说,你当你按下时 - -399 -00:20:37,013 --> 00:20:39,846 -And the little keyboard would slide up from the bottom and you could type in it. -键盘会从底部滑出来,所以你可以输入文本 - -400 -00:20:39,848 --> 00:20:42,882 -So, the calculator, you can't really touch on the screen and -因此对于计算器来说,你确实不能按下屏幕并且 - -401 -00:20:42,884 --> 00:20:45,018 -start typing so we want this static text. -输入,所以我们需要固定的文本 - -402 -00:20:45,020 --> 00:20:48,721 -So, I'm just going to pick this up with the mouse and drag it out. -所以我用我的鼠标把它拖出来 - -403 -00:20:48,723 --> 00:20:50,990 -Now, when I drag it out into my UI, -现在,当我把它拖入我的UI中时 - -404 -00:20:50,991 --> 00:20:53,258 -you're going to see a lot of little blue dash lines appearing. -你会看到很多蓝色虚线出现, - -405 -00:20:53,260 --> 00:20:55,227 -You see these? -看到没 - -406 -00:20:55,228 --> 00:20:57,195 -These are helping me put this in the right place. -这些可以帮助我们正确地摆放这些东西 - -407 -00:20:57,197 --> 00:21:00,798 -So, I can put it right in the center, for example, of my view. -所以,比如说我可以把它放在视图的中间 - -408 -00:21:01,734 --> 00:21:04,335 -I could put it up in a corner up here, which is what I'm gonna do. -我可以把它放在靠顶部这里,我待会就准备这样做 - -409 -00:21:04,337 --> 00:21:05,669 -Mm-kay. - - -410 -00:21:05,671 --> 00:21:10,073 -You always want your things that you put in your UI, -你总是会希望你放入UI中的东西 - -411 -00:21:10,075 --> 00:21:14,643 -as much as humanly possible, to be on one of these dashed blue lines. -尽可能地去利用这些蓝色虚线 - -412 -00:21:14,645 --> 00:21:16,445 -And you'll understand why in a couple weeks when we -你会明白为什么几周之后当我们 - -413 -00:21:16,447 --> 00:21:18,097 -starting talking about auto-layout. -开始关于auto-layou(自动布局)的课程 - -414 -00:21:18,098 --> 00:21:19,748 -I'm gonna do a little auto-layout right here just to kind of -我这里将会涉及一点关于auto-layou的东西,可以让你 - -415 -00:21:19,750 --> 00:21:22,351 -give you a feel for it. -它有点感觉 - -416 -00:21:22,352 --> 00:21:24,953 -But those blue, dashed blue lines are gonna be your best friend when it comes to -不过,在你搭建用户界面的时候,这些蓝色虚线将会是你最好的朋友 - -417 -00:21:24,955 --> 00:21:28,322 -building your user interface and you'll quickly see why that is. -你会很快知道为什么了 - -418 -00:21:28,324 --> 00:21:30,691 -Once you drag something out like this, you can, -每次你像这样拖动东西,你可以 - -419 -00:21:30,693 --> 00:21:34,061 -these little things are rounded that show it's selected, right? -看到环绕在外面的东西,它表明了这个被选中了 - -420 -00:21:34,063 --> 00:21:38,465 -They also are little resize handles so you can grab them and resize them when you -它们也可以用于调整大小,所以可以抓住它然后或者重新调整它们的大小 - -421 -00:21:38,467 --> 00:21:42,235 -resize it also re-puts those dashed blue lines out there, okay? -当你调整大小时,这些蓝色虚线会重新排成一列,看到没 - -422 -00:21:42,237 --> 00:21:43,969 -So you definitely wanna, even have, -所以当你调整大小时,你肯定想 - -423 -00:21:43,971 --> 00:21:47,106 -when you're resizing, get those things lining up. -把这些东西排成一列 - -424 -00:21:47,108 --> 00:21:50,976 -You can also manipulate it directly, just double-click on it, like a calculator -你还可以操作这些东西,只需要双击一下 - -425 -00:21:50,978 --> 00:21:54,145 -probably doesn't want to come up, this is gonna be initial state of this. -通常计算器的初始状态不是这样子 - -426 -00:21:54,147 --> 00:21:58,349 -Doesn't want to come up saying Label, it probably wants 0 or -初始状态上面不会显示Label,它可能会显示0 - -427 -00:21:58,351 --> 00:22:01,318 -something like that in it's display. -或类似的东西 - -428 -00:22:01,320 --> 00:22:04,354 -There's also things you wanna set about this though or -还有另外一张方式,当你无法正确地设置这种 - -429 -00:22:04,356 --> 00:22:08,258 -anything you drag in your UI that you just can't direct manipulate and -拖入你UI的任何东西时 - -430 -00:22:08,260 --> 00:22:12,261 -that's what the top half of this Utilities windows is, is for, okay? -你可以使用靠上的Utilities windows(工具窗口) - -431 -00:22:12,263 --> 00:22:13,829 -So if you look at the top half here, -所以当你看上面这里 - -432 -00:22:13,831 --> 00:22:17,065 -there's a bunch of tabs across the top including something like this, -在顶部这里有许多标签,包括像这种 - -433 -00:22:17,067 --> 00:22:20,035 -the Size Inspector for setting the size of this thing. -用于设置尺寸的Size Inspector(尺寸调节器) - -434 -00:22:20,037 --> 00:22:24,305 -And this tab right here, really important, this is the Attributes Inspector. -还有这里的这个标签,称作Attributes Inspector(属性检查器),非常重要 - -435 -00:22:24,307 --> 00:22:27,908 -And this is an object oriented inspector, depending on what you have selected. -这是一个面向对象的检查器,当你选择不同的东西时 - -436 -00:22:27,910 --> 00:22:30,611 -You'll have different user interface here in the top. -用户界面将会有所改变 - -437 -00:22:30,613 --> 00:22:33,880 -And this let's you edit attributes about what's selected. -这个可以让你编辑你选中的东西的属性 - -438 -00:22:33,882 --> 00:22:35,882 -So, for example, -比如 - -439 -00:22:35,883 --> 00:22:37,883 -a calculator, the zero doesn't really want to be on the left, right? -计算器中这个0其实不是在左边,对不 - -440 -00:22:37,886 --> 00:22:40,653 -Calculators, the zero, the numbers are on the right and -这个0应该是在右边 - -441 -00:22:40,655 --> 00:22:43,589 -they kind of grow out from the right. -这些数字就像是从右边出现的 - -442 -00:22:43,591 --> 00:22:47,426 -And so we can easily fix that with this alignment thing right here. -所以我们可以很轻松地使用这里的alignment(校准)修改它 - -443 -00:22:47,428 --> 00:22:50,595 -So I'm gonna click this and you see the zero move over to the right. -我点击这里所以你可以看到0移动到右边 - -444 -00:22:50,597 --> 00:22:52,130 -And, and maybe I want a bigger font. -还有,也许我想要大点的字体 - -445 -00:22:52,132 --> 00:22:53,231 -You see the font right here. -你可以看到这里的font(字体) - -446 -00:22:53,233 --> 00:22:55,666 -I can click on this, pick different fonts. -我可以点击这里,选择不同的字体 - -447 -00:22:55,668 --> 00:22:59,470 -I'm gonna just move it up to like 32 point, it's a nice big font. -把它增大到32点,稍微大点的字体 - -448 -00:22:59,472 --> 00:23:00,937 -You can notice it kinda cuts off. -你可以看到字体有点被截小了 - -449 -00:23:00,939 --> 00:23:02,572 -I made it so big that it's too small. -字体放大因此这里显得太小 - -450 -00:23:02,574 --> 00:23:06,976 -So I can always just resize this larger to make that fit. -所以我可以重新调整大小使之适应字体的大小 - -451 -00:23:08,479 --> 00:23:10,345 -So this is how we build our user interface. -这就是我们搭建用户界面的方式 - -452 -00:23:10,347 --> 00:23:14,949 -It's very direct manipulation and very object oriented as you'll start to -非常直观的操作,并且非常地面向对象 - -453 -00:23:14,951 --> 00:23:17,451 -see when we add different kinds of objects. -当你加入不同的对象时你就可以看到 - -454 -00:23:17,453 --> 00:23:20,187 -So, let's actually run this application, okay? -所以,让我们真正地运行我们的应用 - -455 -00:23:20,189 --> 00:23:22,956 -We haven't done, built any calculaterness about it, but -我们还没有完成,任何关于计算的东西 - -456 -00:23:22,958 --> 00:23:25,992 -we have this one field, let's run it and see what it looks like. -不过让我们运行一下看看是上面效果 - -457 -00:23:25,994 --> 00:23:27,226 -So, how do you run things? -所以,应该如何运行? - -458 -00:23:27,228 --> 00:23:29,562 -Well, you see right here where it says, iPhone 6? -嗯,这里你可以看到,iPhone 6? - -459 -00:23:29,564 --> 00:23:33,331 -This actually is a selector that lets you say where you want to -这实际上是可以让你选择在哪里 - -460 -00:23:33,333 --> 00:23:35,166 -run your application. -运行你的应用 - -461 -00:23:35,168 --> 00:23:38,636 -So you can see you can run it on an iOS device if you have one connected, -所以你有一个iOS设备连接上时,你可以运行在iOS设备上 - -462 -00:23:38,638 --> 00:23:40,271 -I don't have one connected -currently. -现在我还没有连接的设备 - -463 -00:23:41,273 --> 00:23:43,056 -But you can do that. -不过你可以选择那个选项 - -464 -00:23:43,057 --> 00:23:44,840 -And we'll talk in a Friday section probably in a week or -我们将会在一到两周后的周五 - -465 -00:23:44,843 --> 00:23:48,478 -two about how to get your devices hooked up. -谈论如何连接你的设备 - -466 -00:23:48,480 --> 00:23:52,948 -But also there's these plethora of simulators here, iPhone 6, -不过这里有很多模拟器iPhone 6 - -467 -00:23:52,950 --> 00:23:56,552 -6+, iPhone 5, iPhone 4s, iPad Airs. -6+, iPhone 5, iPhone 4s, iPad Airs - -468 -00:23:56,554 --> 00:23:58,920 -And you can pick one of these to run on and -你可以选择其中的一个运行 - -469 -00:23:58,922 --> 00:24:02,490 -it'll actually simulate that device right here on your computer. -它实际上是在你的电脑上模拟那些设备 - -470 -00:24:02,492 --> 00:24:05,827 -So I'm gonna run on the iPhone 6. -所以我将会运行在iPhone 6 - -471 -00:24:05,829 --> 00:24:08,729 -Okay,I'm just gonna hit Play, see this Play button right here? -好了,我将要点击Play按钮,看到Play按钮没 - -472 -00:24:08,731 --> 00:24:11,498 -That's how you simulate, so Play. -这就是使用模拟器的方式,所以点击Play - -473 -00:24:11,500 --> 00:24:12,933 -Now it's launching the simulator. -现在启动模拟器 - -474 -00:24:12,935 --> 00:24:14,601 -It's a separate process. -它是一个独立的处理进程 - -475 -00:24:14,603 --> 00:24:16,169 -And it's going to run our app in there. -将会在这里运行我们的app - -476 -00:24:16,171 --> 00:24:17,403 -And there it is. -情况就是这样 - -477 -00:24:17,405 --> 00:24:18,737 -Now you might say, whoop. -现在你可能会说,哇 - -478 -00:24:18,739 --> 00:24:19,905 -Big white square. -这么大的白色正方形 - -479 -00:24:19,907 --> 00:24:21,339 -Oh that's not so good. -看起来不怎么好 - -480 -00:24:21,341 --> 00:24:23,825 -And the reason this is so -这是因为 - -481 -00:24:23,826 --> 00:24:26,310 -big is because the iPhone 6 has a very high resolution display on it. -iPhone 6的高分辨率屏幕 - -482 -00:24:26,312 --> 00:24:30,881 -Okay, the retina display, and it's way higher resolution than my computer, okay? -视网膜屏幕,比我电脑上的分辨率大得多 - -483 -00:24:30,883 --> 00:24:35,151 -So I actually have to scroll around, you see there's the top of it. -所以我实际上不得不进行滑动,你可以看到它的顶部 - -484 -00:24:35,153 --> 00:24:37,754 -Scroll up and down to get to i all. -通过上下滑动可以看到整个区域 - -485 -00:24:37,756 --> 00:24:42,558 -Luckily if you go to Window, this is not in the simulator now, the iOS simulator. -幸运的是如果我们前往Window选项,这个选项现在不在iOS模拟器 - -486 -00:24:42,560 --> 00:24:46,628 -If you go to Window and Scale, you can scale it down to be smaller and -如果你点击Window并且点击Scale,你可以把它缩得更小 - -487 -00:24:46,630 --> 00:24:47,762 -then it'll fit. -使之适用屏幕 - -488 -00:24:47,764 --> 00:24:49,497 -Okay, so if you have a low resolution screen, -因此,如果你有低分辨率的屏幕 - -489 -00:24:49,499 --> 00:24:51,532 -you're definitely gonna wanna use Window > Scale. -你肯定会点击Window > Scale - -490 -00:24:51,534 --> 00:24:54,368 -Cmd+3 right there is another way to do it. -快捷键Cmd+3是另外一种方式 - -491 -00:24:54,370 --> 00:24:57,654 -Okay? -懂不 - -492 -00:24:57,655 --> 00:25:00,939 -So here's our UI, but it doesn't look to good, okay, because where's this? -所以,这就是我们的UI,不过看起来不怎么样,因为这个在哪? - -493 -00:25:00,942 --> 00:25:05,011 -We put this zero in there and it just never showed up, what did we do wrong? -我们把0放在这里然后它从来都没有出现,我们哪里做错了? - -494 -00:25:05,013 --> 00:25:08,781 -Well we didn't really do anything wrong and that zero is actually there. -实际上我们没有做错,那个0实际上就在那里 - -495 -00:25:08,783 --> 00:25:11,750 -It's just, here let me line up these UI's, this is not -它只是,先让我把UI排成一列,虽然没有 - -496 -00:25:11,752 --> 00:25:16,554 -necessarily exactly the same scale but its appropriate, approximately the same scale, -必要完全相同的缩放尺寸,不过刚好是同样的尺寸 - -497 -00:25:16,556 --> 00:25:19,857 -you can see that the zero is actually off screen, [NOISE] okay? -你可以看到那个0实际上在屏幕外面,看到不? - -498 -00:25:19,859 --> 00:25:24,028 -So its there but you just can't see it because its over here off the screen. -所以实际上它存在只不过你没有看到它,因为它在屏幕外面 - -499 -00:25:24,030 --> 00:25:28,465 -Okay, and that's a problem, but that's a problem we can fix. -这是一个问题,不过这个问题我们可以解决 - -500 -00:25:28,467 --> 00:25:29,732 -So let's go fix that problem. -所以我们开始解决这个问题 - -501 -00:25:31,302 --> 00:25:32,534 -Why is that thing off-screen? -为什么它在屏幕外面? - -502 -00:25:32,536 --> 00:25:35,837 -Well, look at this UI right here, okay? -好了,看到这个UI没 - -503 -00:25:35,839 --> 00:25:36,838 -What shape is it? -它是什么形状的? - -504 -00:25:36,840 --> 00:25:38,373 -It's square. -它是正方形的 - -505 -00:25:38,375 --> 00:25:40,908 -Okay, no IOS device is square. -不过没有任何iOS设备是正方形的 - -506 -00:25:40,910 --> 00:25:43,544 -There's not a single square iOS device in the world. -世界上没有任何一种正方形的iOS设备 - -507 -00:25:43,546 --> 00:25:45,078 -They're all, you know, tall and -你知道的,它们都是高的,并且 - -508 -00:25:45,080 --> 00:25:48,581 -thin, or, if you turn them sideways, then they're long and short. -瘦的,或者如果把它们侧身来看,它们都又长又短 - -509 -00:25:48,583 --> 00:25:50,650 -Or even like an iPad. -甚至像一个iPad - -510 -00:25:50,651 --> 00:25:52,718 -You know the aspect ratio on an iPad is slightly different than an iPhone so -你知道iPad的纵横比和iPhone稍微有点不同 - -511 -00:25:52,721 --> 00:25:55,588 -their all slightly different, but none of\ them are square. -它们略有不同,但他们都不是正方形的 - -512 -00:25:55,590 --> 00:25:58,657 -So why do we design our UI in a square? -所以为什么我们把我们的UI设计为方的? - -513 -00:25:58,659 --> 00:26:03,762 -Because the way you design iOS interfaces, you design them in this square and -因为你设计iOS界面的方式是你把它们设计在这个方形中并且 - -514 -00:26:03,764 --> 00:26:09,033 -you give everything inside the square rules, called constraints, -你给所有东西添加这些规则,这些规则我们称之为约束 - -515 -00:26:09,035 --> 00:26:12,236 -about what happens to them when they get squished down. -是关于当它们被压扁时应该发生什么事情 - -516 -00:26:12,238 --> 00:26:15,505 -Either squished down vertically, squished down horizontally, -不过是水平还是垂直的压扁 - -517 -00:26:15,507 --> 00:26:18,508 -depending on what kinda device their getting put on, okay? -取决于它们被放到哪种设备中,明白不 - -518 -00:26:18,510 --> 00:26:22,912 -So you put these rules in there, so, what does it look like to put these rules in? -所以你会在加入这些规则,所以当加入这样规则后看起来会怎样? - -519 -00:26:22,914 --> 00:26:26,115 -Well again, it's all direct manipulation, so -同样的,这些都是直观的操作 - -520 -00:26:26,117 --> 00:26:31,186 -I'm going to give some rules to this label right here to make it so that it knows -我将要对这里的这个标签增加一些规则,使得它知道 - -521 -00:26:31,188 --> 00:26:36,957 -what to do when this square gets squished down in any direction for any device. -对于任何方向的任何设备被压扁时应该如何显示 - -522 -00:26:36,959 --> 00:26:38,659 -So, what do I want the rules to be? -所以,我希望这些规则是什么样的? - -523 -00:26:38,661 --> 00:26:42,162 -Well, I always want this thing to use the whole width. -我总希望它可以使用全部的宽度 - -524 -00:26:42,164 --> 00:26:44,931 -However much width I have, I want it all. -不管我的宽度是多少,我都希望填满这个宽度 - -525 -00:26:44,933 --> 00:26:50,102 -So I'm gonna pin this right edge to this edge, okay? -所以我要固定这个右边缘到这个边缘的距离,ok? - -526 -00:26:50,104 --> 00:26:53,205 -I'm gonna make it so all widths are pinned to each other. -我这样做是因为所有宽度都会由另外一方决定 - -527 -00:26:53,207 --> 00:26:55,007 -And I do that with the Ctrl key. -我使用Ctrl键来完成 - -528 -00:26:55,009 --> 00:26:57,559 -I've turned on sticky keys so -我已经开启粘滞键所以 - -529 -00:26:57,560 --> 00:27:00,110 -you can see down in the lower left here, it's showing the modifier keys I'm using. -在左下角你可以看到,它显示了我正使用的修饰键 - -530 -00:27:00,113 --> 00:27:02,213 -So right now I'm holding down Ctrl. -所以现在我按住Ctrl - -531 -00:27:02,215 --> 00:27:08,485 -And I'm gonna Ctrl+drag from the right edge of this to the container it's in. -我会按Ctrl 从右边拖动到它的容器的右边 - -532 -00:27:08,487 --> 00:27:11,822 -See how it's showing me what I'm dragged to. -看它是如何展示我正在拖动的过程 - -533 -00:27:11,824 --> 00:27:15,125 -So when I drag to this container, it puts a menu up and says, -所以,当我拖到这个容器时,它会出现菜单并且提示我 - -534 -00:27:15,127 --> 00:27:20,830 -oh, okay, you want some rule between that label's right edge and -好吧,你想在标签和右边缘之间增加一些规则 - -535 -00:27:20,832 --> 00:27:23,999 -this thing's edge, what do you want it to be? -这个边缘,你希望是什么情况? - -536 -00:27:24,001 --> 00:27:26,568 -Well, I can do a lot of things here. -恩,我可以在这上面做很多事情 - -537 -00:27:26,569 --> 00:27:29,136 -I could center this label vertically in this container. -我可以使这个标签垂直居中于这个容器 - -538 -00:27:29,139 --> 00:27:31,590 -Up, you know, vertical up and down. -向上,你知道的,垂直向上和向下 - -539 -00:27:31,591 --> 00:27:34,042 -I definitely don't want that, I want my label at the top, so I don't want that. -我绝对不希望出现这种情况,我希望我的标签在顶部,所以我不希望出现这种情况 - -540 -00:27:34,044 --> 00:27:35,776 -I can make it the equal width, so -我可以使它的宽度相等,所以 - -541 -00:27:35,778 --> 00:27:38,479 -I can make this label the same width as the container. -我可以使这个标签和这个容器中宽度相同 - -542 -00:27:38,481 --> 00:27:42,049 -I don't want that either, cuz I want this little margin there, right? -我也不想那种情况,因为我想设置这个小边距,对不对? - -543 -00:27:42,051 --> 00:27:45,785 -But look at the top one, trailing space to container margin. -不过看上面的那个,trailing space to container margin(距离容器的间距) - -544 -00:27:45,787 --> 00:27:51,157 -This lets me pin the trailing space after my label to the margin of the container. -这让我规定了我的标签和它的容器的间距 - -545 -00:27:51,159 --> 00:27:55,194 -So that's the one I want, so I'm gonna click on this and it does it. -所以这就是我希望的那个,所以我点击这个 - -546 -00:27:55,196 --> 00:27:59,664 -Now, see all these yellow and orange lines that appeared when I did that? -现在,当我这样做时,看到这些黄色和橙色的线条出现没? - -547 -00:27:59,666 --> 00:28:03,401 -That's because the systems like, okay, you've started telling me the rules for -这就像是系统在说,OK,你已经开始告诉我应该遵循关于这些标签的某些规则 - -548 -00:28:03,403 --> 00:28:06,504 -this label, but your you haven't told me enough rules, -不过你没有告诉我足够多的规则 - -549 -00:28:06,506 --> 00:28:08,005 -I don't know what to do with this thing. -我不知道应该对它怎么做 - -550 -00:28:08,007 --> 00:28:11,141 -So now it's showing you all the places where it's like the system's not -所以它现在正在告诉你,当它被挤压的时候 - -551 -00:28:11,143 --> 00:28:13,310 -sure what to do now when this thing gets squished. -系统不确定应该怎么做 - -552 -00:28:13,312 --> 00:28:15,745 -Before it was like, okay, well you weren't telling me anything so -在这之前,你没有告诉我任何规则 - -553 -00:28:15,747 --> 00:28:18,081 -I'm not going to do anything, but now your starting to tell me. -所以我没有显示任何东西,不过现在你开始告诉我 - -554 -00:28:18,083 --> 00:28:19,648 -So what do I do? -所以我应该怎么做? - -555 -00:28:19,650 --> 00:28:24,353 -So we have to fully specify both the what happens horizontally and -所以我们不得不完整地告诉它水平方向 - -556 -00:28:24,355 --> 00:28:25,520 -vertically to this thing. -和垂直方向应该怎么显示 - -557 -00:28:25,522 --> 00:28:27,422 -So we've only just started here. -所以我们仅仅先从这里开始 - -558 -00:28:27,424 --> 00:28:31,225 -So let's pin this edge also cuz we want this edge to stay on this side. -所以让我们拖动固定这个边缘,我们希望这个边缘靠近这一边 - -559 -00:28:31,227 --> 00:28:34,528 -So I'm gonna hold down Ctrl and drag. -所以我按下Ctrl并且拖动 - -560 -00:28:34,530 --> 00:28:38,965 -And now I'm gonna pin the leading space to the container margin. -然后现在我想固定它到容器之间的间距 - -561 -00:28:38,967 --> 00:28:41,100 -Okay, boom that did that. -好了,我成功了 - -562 -00:28:41,102 --> 00:28:44,670 -Still have orange going on here, that's because I haven't specified anything about -这里仍然显示橙色,这是因为我还没指定任何关于 - -563 -00:28:44,672 --> 00:28:49,675 -the vertical position of this label so I'm gonna pin the top to the top, so -这个标签的垂直位置,所以我把顶部和顶部固定起来 - -564 -00:28:49,677 --> 00:28:54,212 -hold Ctrl again, drag up here, this is now top space. -所以我有一次按住Ctrl,拖到这里,这是顶部间距 - -565 -00:28:54,214 --> 00:28:58,882 -Notice that it realizes where I am dragging to and from, right? -注意到它识别出我正把它拖向哪里没? - -566 -00:28:58,884 --> 00:29:00,984 -So they can give me options that make sense, -所以它能给我有意义的选项 - -567 -00:29:00,986 --> 00:29:03,186 -like Top Space to Layout Guide here. -比如这里的Top Space to Layout Guide(顶部间距) - -568 -00:29:03,188 --> 00:29:04,921 -So I'm going to do that. -所以我会选这个 - -569 -00:29:04,923 --> 00:29:06,489 -So now I'm starting to get blue lines. -所以我开始看到蓝色的线了 - -570 -00:29:06,491 --> 00:29:07,489 -You see these lines? -看到没 - -571 -00:29:07,491 --> 00:29:08,657 -I hope you can see that there. -希望你能看到 - -572 -00:29:08,659 --> 00:29:11,493 -They're solid blue, not orange or red. -它们是实心蓝线,不是橙色或红色 - -573 -00:29:11,495 --> 00:29:16,230 -Okay, that's because they're okay, we are okay horizontally here. -这是因为它们ok了,水平方向上ok了 - -574 -00:29:16,232 --> 00:29:18,332 -But we still have a problem vertically. -不过这里仍然有一个垂直方向上的问题 - -575 -00:29:18,334 --> 00:29:21,335 -Now I'm not sure exactly what the problem is vertically cuz I really don't -现在我不是非常确定这个垂直方向上的问题因为我确实不 - -576 -00:29:21,337 --> 00:29:23,536 -want the bottom of this. -希望这样的底部 - -577 -00:29:23,538 --> 00:29:27,773 -I just want it to hang out wherever it wants to hang out based on the size of my -希望我这个刚刚摆放的标签的底部是基于我的 - -578 -00:29:27,775 --> 00:29:29,041 -font or whatever. -字体大小 - -579 -00:29:29,043 --> 00:29:31,610 -So I don't, I don't really wanna specify anything here so -因此,我不,我确实不想在这里指明特定的高度 - -580 -00:29:31,612 --> 00:29:34,212 -why is this orange and how do I get rid of this? -所以为什么橙色警告会出现,我应该怎样避免它? - -581 -00:29:34,214 --> 00:29:37,648 -Well any time you have orange and when you're doing this layout stuff and -任何时候当你在布局时看到橙色警告 - -582 -00:29:37,650 --> 00:29:38,949 -you don't know what to do. -你不知道应该怎样做 - -583 -00:29:38,951 --> 00:29:41,885 -You wanna go down to this button right here, okay? -你会来到下面这里点击这个按钮,看到不? - -584 -00:29:41,887 --> 00:29:44,905 -This is the document outline. -这是document outline(文档大纲) - -585 -00:29:44,906 --> 00:29:47,924 -And when you click this, a little thing will slide out, a little shelf here. -当你点击这里时,这一小部分会滑出来,一个小架子 - -586 -00:29:47,926 --> 00:29:53,095 -And this is an outline view of everything that's in your UI. -这是你的UI中所有东西的大纲 - -587 -00:29:53,097 --> 00:29:54,897 -Okay? And they're linked, so -并且它们之间已经连接起来 - -588 -00:29:54,899 --> 00:29:58,000 -if I click the background, nothing is selected. -如果我点击背景,什么都没有被选中 - -589 -00:29:58,002 --> 00:30:00,769 -Then the background, the view is what's selected here. -然后这个背景,这个视图就是我这里选择的 - -590 -00:30:00,771 --> 00:30:04,605 -But if I click this L0, which means a label with zero in it, -但当我点击这里L0标签时,L0指的是Label中显示内容是0 - -591 -00:30:04,607 --> 00:30:06,240 -look it's selected my. -看我的标签被 - -592 -00:30:06,242 --> 00:30:10,143 -Zero label, and vice versa if I click on this here, it selects it over here. -选中,反之亦然如果我点击这里,这里显示被选中 - -593 -00:30:10,145 --> 00:30:14,380 -So this is this same thing in an outline mode. -所以这和大纲模式一样 - -594 -00:30:14,382 --> 00:30:16,349 -This is really nice to have. -这是一种非常好的方式 - -595 -00:30:16,350 --> 00:30:18,317 -Sometimes you have views that are overlapping and they're kind of in -有时候你的视图重叠在一起,所以它们显得有点 - -596 -00:30:18,319 --> 00:30:22,421 -each other's way, you can always go here to select the one you want, okay? -难以选择,你可以来到这里选择你想选择的视图,ok? - -597 -00:30:22,423 --> 00:30:27,525 -And you can Ctrl+drag to these over here too it's just as much Ctrl+draggable as -并且你也可以在这里Ctrl加拖动,这里和其它东西 - -598 -00:30:27,527 --> 00:30:30,294 -some of these other things. -一样可Ctrl+拖动 - -599 -00:30:30,296 --> 00:30:32,513 -But what we're, and we'll look, -但这些我们将会 - -600 -00:30:32,514 --> 00:30:34,731 - we'll talk about top layout - guide, bottom - layout guide a little later. -稍后我们将讨论一下顶部和底部的布局指南。 - -601 -00:30:34,734 --> 00:30:38,369 - But what I really want you to - focus on is - this little yellow circle up - here. -但是我想让你注意这个黄色的小圆圈 - -602 -00:30:38,371 --> 00:30:39,870 - 'Kay? - Any time you got yellow and -好的,任何时候,你都会在使用auto-Layout中看到黄色和橙色的警告 - -603 -00:30:39,872 --> 00:30:42,172 - orange problems with this - auto-layout - business, - -604 -00:30:42,174 --> 00:30:45,108 - you're gonna get this little - yellow circle - appearing in your document - outline. -你可以在你的左侧文档中看到这个小黄圈出现。 - -605 -00:30:45,110 --> 00:30:50,479 -And if you click it, it'll slide - in a list - of all the problems. -如果你点击它,它会展开一个列表,呈现所有的问题 - -606 -00:30:50,481 --> 00:30:54,349 - And so here I highlight over - this and this - is where all the orange and - yellow is. -如果选中它,出现高亮的部分就是警告所出现的地方 - -607 -00:30:54,351 --> 00:30:59,487 -It's saying the label with the 0 - in it -expected the height to be 39 but -它提示这个label的高度应该是39,但 - -608 -00:30:59,489 --> 00:31:00,955 - the actual height is 57. -真实的情况却是57。 - -609 -00:31:00,957 --> 00:31:03,824 -Well that's because after I set - this font, -这是因为我在设置了这个字体后, - -610 -00:31:03,826 --> 00:31:06,460 - I just dragged this down a - little bit to - make space. -我向下的拖动了一部分,让它多出来一些区域。 - -611 -00:31:06,462 --> 00:31:09,262 -All right, I, I wasn't very, I, - I didn't - know it was supposed to be 39. -好吧,我不是很,我不是很清楚它支持的高度是39。 - -612 -00:31:09,264 --> 00:31:11,330 - I just dragged down. -我只是稍稍向下拖动了而已。 - -613 -00:31:11,332 --> 00:31:14,283 -And so it's saying that's wrong. -这样,Xcode给了我一个警告。 - -614 -00:31:14,284 --> 00:31:17,235 - Now, I could just try drag it - back up and - meet this dashed line. -现在,我可以试着将其拖动,和这个虚线重叠。 - -615 -00:31:17,238 --> 00:31:19,738 - This dashed line, by the way, -强调下这条虚线, - -616 -00:31:19,739 --> 00:31:22,239 - is where it's kind of saying, - this is -really where this thing wants to - be. -它表明了这个标签真实的大小。 - -617 -00:31:22,242 --> 00:31:24,642 -But the solid lines are where it - actually - is. -但是实线是我们希望的样子。 - -618 -00:31:24,644 --> 00:31:29,313 - So I could kinda drag it up to - there, but -I, I could be off by a pixel or -所以我可能拖动到那里,但是我也许会相差1个像素或 - -619 -00:31:29,315 --> 00:31:31,749 - something else. -出现一些其他的区别。 - -620 -00:31:31,750 --> 00:31:34,184 - A much more reliable way is to - click this - little yellow triangle, 'kay? -现在有一个可靠的方法,点击这个黄色小三角,好了吗? - -621 -00:31:34,186 --> 00:31:36,186 - So I'm gonna click this yellow - triangle. -我将要点击这个。 - -622 -00:31:36,188 --> 00:31:37,854 -It's gonna bring up this pop-up - window. -它会弹出一个窗口。 - -623 -00:31:37,856 --> 00:31:42,091 - And there's three ways to fix - the - problems, okay? -这里给出了三个修改问题的方法,好了吗同学? - -624 -00:31:42,093 --> 00:31:45,327 - One way, Update Constraints, - this middle - way right here. -其中一个,更新约束,在第二个。 - -625 -00:31:45,329 --> 00:31:49,098 - That's a way that says, hey, I - want this - thing to be, -这个方法是,我想要这样做, - -626 -00:31:49,100 --> 00:31:51,199 -this label to be right where it - is. -这个label这样才是正确的。 - -627 -00:31:51,201 --> 00:31:52,967 - So just make some constraints. -所以只要做一些约束。 - - -628 -00:31:52,969 --> 00:31:53,634 - Make it up. -弥补上这个缺点。 - -629 -00:31:53,636 --> 00:31:56,237 - Make it happen! -让它自己完成。 - -630 -00:31:56,238 --> 00:31:58,839 - And it'll put some wacky - constraints in - there like 52 high, which is a - bad -它会把一些古怪的约束添加到这个52高度,这是一个坏的 - -631 -00:31:58,841 --> 00:32:02,309 - constraint for it to be, 52 - high, cuz this - label wants to be its natural - height. -约束,因为52的高度不是这个标签真正的高度。 - -632 -00:32:02,311 --> 00:32:04,378 - It doesn't want to be 52 high. - 它的高度不是52。 - -633 -00:32:04,380 --> 00:32:06,346 - So this'll kinda force - constraint. -所以这里就可以用强制性的约束。 - -634 -00:32:06,348 --> 00:32:08,614 - You'll almost never want this - one, 'kay. -当然你也许不希望这样。 - -635 -00:32:08,616 --> 00:32:11,250 - Rarely do you wanna force the - constraints. -你很少想强制性的去约束。 - -636 -00:32:11,252 --> 00:32:14,520 - Reset to Suggested Constraints - would - probably just work here. -这个就是设置label为建议性的约束。 - -637 -00:32:14,522 --> 00:32:16,788 - I'm not gonna choose this one, - but it - would probably work. -我不会选择这个,即使它可能是正确的。 - -638 -00:32:16,790 --> 00:32:21,125 - This one is going to make the - constraints - match the blue lines. -这个是将约束调整为蓝色的线条。 - -639 -00:32:21,127 --> 00:32:24,762 - Those dashed blue lines that I - told you - always wanna meet. -那些蓝线,我告诉你是必须达到的。 - -640 -00:32:24,764 --> 00:32:28,899 -Those are what's gonna help the - system - pick suggested constraints. -那些是系统帮助选择出来的约束。 - -641 -00:32:28,901 --> 00:32:32,769 - So since we dragged that label - out to the - blue lines perfectly, -因为我们拖动的label是蓝色的, - -642 -00:32:32,771 --> 00:32:36,639 - I'll bet if I said Reset to - Suggested -Constraints, it might just work. -我敢打赌,我点击了重置约束,它也是能够工作的。 - -643 -00:32:36,641 --> 00:32:38,941 - Okay. -But I'm actually gonna show you - this -好的。我想告诉你这个 - -644 -00:32:38,943 --> 00:32:43,646 -last option up on top, which is - Update - Frame and what this says is, - take into -选项,它是能够更新框架和 - -645 -00:32:43,648 --> 00:32:49,918 -consideration all the rules and - move this -label to where the rules say it - should be. -所有的约束规则,让label的按照规则进行移动。 - -646 -00:32:49,920 --> 00:32:52,187 - 'Kay. - And I like this option a lot - because it -好的,我喜欢这个选项 - -647 -00:32:52,189 --> 00:32:55,523 - lets you kind of preview, do I - have my - little rules right, okay? -它让你能够预览,我有一个正确的结果,对吗? - -648 -00:32:55,525 --> 00:32:59,860 -So let's try that, let's see if - the, we'll - tell the, move this label, go - ahead and -我们尝试一下,看下移动后的标签是 - -649 -00:32:59,862 --> 00:33:03,564 -move yourself and size yourself - to obey -these three rules we you put in, - and -遵守你自己的设定的那三个约束, - -650 -00:33:03,566 --> 00:33:06,066 - we'll fix the misplacement, so - let's try - it. -我们点击这个按钮,让我们尝试下。 - -651 -00:33:07,069 --> 00:33:10,269 - And sure enough it did it, it - says there - are no auto layout issues. -果然做到了,没有任何问题。 - -652 -00:33:10,271 --> 00:33:14,940 - If I go back to my document - outline, this - little yellow circle is gone. -如果你回到自己的目录列表,这个黄色的小圆圈已经消失了。 - -653 -00:33:14,942 --> 00:33:18,810 -If I look in my view, everything - is - blue-lined, no yellow or red. -看看自己的视图,全部都是蓝线,没有红色或黄色的。 - -654 -00:33:20,146 --> 00:33:22,630 - Okay? - So that's your -好了吗?这就说明你的 - -655 -00:33:22,631 --> 00:33:25,115 -crash course on auto layout, and - we're -gonna talk a lot more about auto - layout, -自动布局已经完成,我们接下来讨论下更多的自动布局 - -656 -00:33:25,118 --> 00:33:28,719 - in fact, even on Wednesday I'm - gonna do -another auto layout with all the - buttons. -在周三的时候我们将要尝试给所有的按钮进行自动布局。 - -657 -00:33:28,721 --> 00:33:30,671 - Right? - The keypad buttons, and -真的?所有的键盘按钮 - -658 -00:33:30,672 --> 00:33:32,622 - all that, which is a lot more - things being - laid out. -这听起来真的蛮多的。 - -659 -00:33:32,624 --> 00:33:34,224 -But let's see if this fixes our - problem. -接着让我们看下如何修改这些。 - -660 -00:33:34,226 --> 00:33:37,527 - Let's go ahead and run our - application - again. -我们再次运行一下应用。 - -661 -00:33:37,529 --> 00:33:39,795 - So I'm just hitting that play - button. -点击这个运行按钮。 - -662 -00:33:39,797 --> 00:33:41,563 - Here it, oh, we got our zero - this time. -此刻,我们现在可以看到这个0了。 - -663 -00:33:41,565 --> 00:33:45,334 -You see how it pinned this zero - to that - edge? -你注意到这个零的边缘了吗? - -664 -00:33:45,336 --> 00:33:48,036 -And not only that, if we rotate - this - phoned, -不仅可以这样,如果我们旋转模拟器, - -665 -00:33:48,038 --> 00:33:52,273 - which you can do in the - Simulators menu, - Hardware > Rotate. -你可以在模拟器的菜单中点击Hardware>Rotate。 - -666 -00:33:53,976 --> 00:33:58,378 - Look the 0, this got wider and - the 0 kept - pin, pinning itself over to - that. -看看这个0,它本身还保持着这个距离。 - -667 -00:33:58,380 --> 00:34:01,981 - And it also stayed on the top - even though - this got, whole thing got - shorter. -它也保持着距离顶部的距离,底部距离变短了。 - -668 -00:34:01,983 --> 00:34:04,884 - Okay. - And if I rotate back, the 0 - stays there. -接下来,如果我旋转回来,0还是保持原样。 - -669 -00:34:04,886 --> 00:34:07,420 - Question. -So what did it do at the bottom - there? -学生提问:是什么让它底部产生了变化。 - -670 -00:34:07,422 --> 00:34:10,422 -Like what did the actual update - frame end - up doing? -就像你已经更新过那里的约束了一样。 - -671 -00:34:10,424 --> 00:34:12,758 -What did the update frame in the - document - outline do? -在目录中的更新框架做了什么呢? - -672 -00:34:12,760 --> 00:34:14,693 - Yes. - It moved this bottom edge up. -是的,它改变了底部的边缘距离。 - -673 -00:34:14,695 --> 00:34:17,462 - You see this is only 39 pixels - high now. -你看现在是39的像素高度。 - -674 -00:34:17,464 --> 00:34:18,396 - It was 52. -之前它是52. - -675 -00:34:18,397 --> 00:34:19,329 - So, yeah, it just moved it up. -这样,它发生了改变,向上移动了。 - -676 -00:34:19,332 --> 00:34:21,665 -It, it, and if other things had - been - yellow, -如果其他事情提示黄色, - -677 -00:34:21,667 --> 00:34:23,133 - it could have moved the whole - thing. -它可能移动整体了。 - -678 -00:34:23,135 --> 00:34:24,718 - Right? - It would move that -好的,它将移动这 - -679 -00:34:24,719 --> 00:34:26,302 - whole rectangle wherever the - rule said but -整个矩形达到约束的那样,但是 - -680 -00:34:26,304 --> 00:34:29,539 - in this case, you can fi that - one problem - by moving it up. -这种情况,你能够向上拖动来修改这个问题。 - -681 -00:34:29,541 --> 00:34:30,139 - Good question. -好问题。 - -682 -00:34:31,342 --> 00:34:32,040 - Okay? -可以了嘛? - -683 -00:34:32,042 --> 00:34:33,541 - So that's good. -不错。 - -684 -00:34:33,543 --> 00:34:34,976 - All right. -好的。 - -685 -00:34:34,977 --> 00:34:36,410 - So that's it for auto layout. -让我们回到自动布局上。 - -686 -00:34:36,413 --> 00:34:38,346 - Auto layout part one. -自动布局的第一部分。 - -687 -00:34:38,348 --> 00:34:43,016 - So now let's talk a little bit - about - connecting our user interface - that we're -所以现在让我们来谈谈我们的界面,我们 - -688 -00:34:43,018 --> 00:34:45,385 - building right here, up to the - code, -建立在这里,通过代码 - -689 -00:34:45,387 --> 00:34:48,254 -cuz we want that code to be able - to talk - to the user interface. -因为我们想让代码能够告诉用户界面。 - -690 -00:34:48,256 --> 00:34:51,157 -Otherwise how are we gonna have - the number - buttons, -否则我们如何拥有数字按钮, - -691 -00:34:51,159 --> 00:34:53,425 - make numbers appear up here in - the - display? -使数字展现在这里 - -692 -00:34:53,427 --> 00:34:56,795 - Or the times button, give the - results of - the calculation up here. -或一些按钮,告诉计算结果在这里。 - -693 -00:34:56,797 --> 00:34:58,363 - We gotta be able to talk to - this. -我们必须能够与之交互。 - -694 -00:34:58,365 --> 00:35:01,633 - So how do we do that? -但是如何做到呢? - -695 -00:35:01,634 --> 00:35:04,902 - And the answer, first step is, - we need to - get both this co, this Swift - Code, -正确答案,第一步需要我们在controller中编写Swift代码, - -696 -00:35:04,904 --> 00:35:10,440 -the controller, and this view on - screen at - the same time, 'kay? -和这个视图相互对应。 - -697 -00:35:10,442 --> 00:35:12,742 -Cuz we're gonna connect them so - we need -them on screen at the same time, -因为我们会连接他们,所以我们需要在屏幕上在同一时间 - -698 -00:35:12,744 --> 00:35:17,180 -and there's a lot of ways to do - that, but - I'll do the simplest way right - here, -还有很多方面,在这里我要用最简单的方法, - -699 -00:35:17,182 --> 00:35:20,616 - which is this little button - called the - assistant editor, all right? -这个小按钮叫助理编辑,好了吗? - -700 -00:35:20,618 --> 00:35:22,184 - So I'm gonna click that and - look! -我要点击这个。 - -701 -00:35:22,186 --> 00:35:25,120 - It put them both on screen at - the same - time, exactly what I wanted. -这时你能看到屏幕分成了两部分,这正是我想要的。 - -702 -00:35:25,122 --> 00:35:27,355 - Now it's all a little crowded - here. -现在它这里是比较拥挤的。 - -703 -00:35:27,357 --> 00:35:31,892 - Even if I expand my view a - little bit, - it's like it's all smashed in - here. -即使我放大整个界面,它看起来还是这么小。 - -704 -00:35:31,894 --> 00:35:35,696 - Luckily the navigator and the - utilities - can also be hidden, -幸运的是导航栏这些都是可以隐藏起来的, - -705 -00:35:35,698 --> 00:35:37,931 -see these buttons up here, these - three - buttons? -看到这些按钮了嘛,这有三个按钮。 - -706 -00:35:37,933 --> 00:35:40,734 - This left one, if you click it - hides the - navigator and -左侧这个,如果你点击它则会隐藏左侧导航, - -707 -00:35:40,736 --> 00:35:45,504 - this right one if you click it - hides - utilities, 'kay? -点击右侧这个,则会右侧右边的工具栏。 - -708 -00:35:45,506 --> 00:35:50,308 - So now we have both my UI and - over here we - can still double click to zoom - out, but -现在我们可以看到他们都在视线中,我们可以双击缩放它,但 - -709 -00:35:50,310 --> 00:35:54,646 - the thing is, anytime we're - actually -connecting our UI to our code or -事情是这样的,在我们实际连接UI代码或 - -710 -00:35:54,648 --> 00:35:59,183 -trying to edit anything in here, - you need - to be zoomed to normal, 'kay? -尝试去编辑的时候,你需要把缩放比例调到正常。 - -711 -00:35:59,185 --> 00:36:02,353 -For example if I tried to select - if I'm - zoomed out and -例如这个,如果我选择这个比例 - -712 -00:36:02,355 --> 00:36:04,955 - I try to select this 0 I just - can't. -我就不能选中这个0了。 - -713 -00:36:04,957 --> 00:36:08,891 -This is really kind of a bird's - eye view - just for seeing what your UI - looks like. -这个其实只是一个预览图,让你看看大体样子,而不能编辑。 - -714 -00:36:08,893 --> 00:36:10,726 - If you wanna actually work on - it, -你只有这样才能够继续工作, - -715 -00:36:10,727 --> 00:36:12,560 - you double-click to zoom in on - this scene - that you're interested in. -你双击选择这个窗口即可。 - -716 -00:36:14,064 --> 00:36:15,630 -Okay, so here's our Swift code. -好了,现在我们开始编写Swift代码。 - -717 -00:36:15,632 --> 00:36:17,598 -I'm actually gonna delete these. -我将要删除这些。 - -718 -00:36:17,600 --> 00:36:20,635 - We don't need them for the - calculator. -在我们的应用中是不需要这些的。 - -719 -00:36:20,636 --> 00:36:23,671 - We will need these things for - future -application but we don't need it - for -我们需要一些计算功能,但这些不需要。 -720 -00:36:23,673 --> 00:36:24,338 - the calculator. - -721 -00:36:24,340 --> 00:36:27,974 - And this is your first look at - Swift, - 'kay. -接着,你将要开始第一个Swift的编写。 - -722 -00:36:27,976 --> 00:36:31,711 - So Swift, as I said, very - concise -language, but it's basically an - object -我说过,Swift是非常简洁的语言,但它还是一个 - -723 -00:36:31,713 --> 00:36:36,048 - oriented language, it's gonna - look a lot - like C, some things look a lot - like Java. -面向对象语言,它看起来像C,有人说它有点像java。 - -724 -00:36:36,050 --> 00:36:40,385 -It's kind of the, you know, best - of, of a -lot of different worlds at once. -你知道,最好的,很多不同的地方。 - -725 -00:36:40,387 --> 00:36:44,823 - Now this import is just - importing the UI - portion of iOS. -这只是iOS导入UI的一部分。 - -726 -00:36:44,825 --> 00:36:47,658 - You usually won't have to - specify import - yourself unless you start -你通常不需要指定导入,除非你开始 - -727 -00:36:47,660 --> 00:36:52,496 - using frameworks that are not, - you know, - the base frameworks and we'll - get to that -不使用框架,你知道基础框架和我们将要 - -728 -00:36:52,498 --> 00:36:56,233 -probably weeks into the quarter - where you -fi, finally have to do an import - yourself. -使用的一些会需要自己进行导入。 - -729 -00:36:56,235 --> 00:36:58,601 -So this how it automatically got - put here - for us. -这里我们看到它自动的为我们添加了。 - -730 -00:36:58,603 --> 00:37:02,838 -And so this is really your first - line of - Swift code, 'kay? -在这里要开始你的第一行Swift的代码。 - -731 -00:37:02,840 --> 00:37:06,975 -Appropriately, it's a definition - of a - class. -这里是定义了一个类。 - -732 -00:37:06,977 --> 00:37:10,479 - Cuz Swift is fundamentally - object-oriented -and here we're defining a class. -因为Swift从根本上来讲是面向对象的,这里是定义的一个类。 - -733 -00:37:10,481 --> 00:37:13,448 - So what does the syntax look - like to - define a class? -这里的语法看起来像定义一个类吗? - -734 -00:37:13,450 --> 00:37:15,416 - You got the keyword class. -你看到类这个关键字。 - -735 -00:37:15,418 --> 00:37:16,817 - You got the name of the class. -这里是这个类的名称。 - -736 -00:37:16,819 --> 00:37:20,654 - Now this name ViewController, - pretty bad - name, [LAUGH]. -现在这个名字看起来很糟糕。 - -737 -00:37:20,656 --> 00:37:23,523 -Okay, very generic, really they - should - probably be something like -好吧,真的很一般,他们应该是类似 - -738 -00:37:23,525 --> 00:37:26,593 - CalculatorViewController, - something - specific to -CalculatorViewController这样的命名 - -739 -00:37:26,595 --> 00:37:33,599 -this particular scene that we're - working - on right here, that it's - controlling. -这样看起来就让人清楚他是控制哪里的了。 - -740 -00:37:33,601 --> 00:37:35,668 - This is the default name it - gives you. -这是个默认的名字。 - -741 -00:37:35,670 --> 00:37:38,337 - I don't want to spend the - valuable demo - time showing how to -我不想花费宝贵的时间去演示如何 - -742 -00:37:38,339 --> 00:37:40,656 - rename this cuz unfortunately, -重命名这个,因为 - -743 -00:37:40,657 --> 00:37:42,974 - I can't just type a new name - here because -I gotta keep the UI in sync with - it. -我不能在这里输入一个新名字,因为我要保持UI同步。 - -744 -00:37:42,976 --> 00:37:45,276 -So I would have to do something - in the UI - as well. -所以我必须做一些事情在UI中。 - -745 -00:37:45,278 --> 00:37:48,079 - But, for now, for your first - assignment or - two we're, we'll just -但是现在,你的第一个任务或两个,我们只会 - -746 -00:37:48,081 --> 00:37:51,548 - call this ViewController, but - down the - road you're gonna wanna pick - better names. -叫他ViewController,但你最好给他更换一个好的名字。 - -747 -00:37:51,550 --> 00:37:54,251 - And of course you're gonna be - building - multiple of -当然你可以创建一个 - -748 -00:37:54,253 --> 00:37:57,554 - these scenes in this class in - the same app - in the future, so -新的类在其中, - -749 -00:37:57,556 --> 00:38:01,024 - of course, they'll all have - different - controller names. -他们都有一个不同的名称。 - -750 -00:38:01,026 --> 00:38:07,796 - Okay, this :UIViewController, - that's - inheritance, that's its - superclass, okay? -这个UIViewController是告诉我们它的父类是谁。 - -751 -00:38:08,799 --> 00:38:12,334 -Swift is single inheritance, so - you can - only inherit from one class. -Swift是一个单继承,你只能让他继承一个类。 - -752 -00:38:12,336 --> 00:38:16,137 -It's perfectly fine in Swift not - to - inherit from a class if you - don't want to, -如果你不想这样,它是能够完整的继承一个类, - -753 -00:38:16,139 --> 00:38:18,139 - all right? - -754 -00:38:18,140 --> 00:38:20,140 -But here we have to inherit from - UIViewController cuz we -在这里我们有UIViewController,因为我们 - -755 -00:38:20,142 --> 00:38:23,176 -want all this magic that allows - us to - control the UI, -想通过它来控制UI, - -756 -00:38:23,178 --> 00:38:27,880 - like that whole auto layout - business, and - there's a ton of mechanism in - here for -像自动布局功能,这其中有许多的原理 - -757 -00:38:27,882 --> 00:38:31,083 -the, the allowing the controller - to - control this UI. -允许控制器来控制这个UI - -758 -00:38:31,085 --> 00:38:35,487 - So obviously we do that so all -ViewControllers, all controllers - of these -很明显,所有viewcontroller,所有控制器 - -759 -00:38:35,489 --> 00:38:40,425 - little scenes always inherit - from either - from UIViewController directly - or they -这些小场景总是继承UIViewController或者它们 - -760 -00:38:40,427 --> 00:38:45,296 - inherit from a class that - inherits from - UIViewController or up their - chain so. -继承的类的UIViewController或它们的链。 - -761 -00:38:46,399 --> 00:38:51,134 -And then inside this curly brace - is simply - all the instance variables and -然后在这个花括号中所有实例变量和 - -762 -00:38:51,136 --> 00:38:54,070 - methods in this class, 'kay? -方法在这个类中。 - -763 -00:38:54,072 --> 00:38:58,207 -So very simple syntax to define - a class. -定义类的语法是非常简练的。 - -764 -00:38:58,209 --> 00:39:02,144 -So let's dive right into making - some - instance variables and methods - so -所以让我们忙于做一些实例变量和方法 - -765 -00:39:02,146 --> 00:39:03,912 - you can see what those look - like. -你可以调整下位置。 - -766 -00:39:03,914 --> 00:39:09,216 - And I thought we, this was - segued to - because we're going to -我想我们,应该连接这个,因为我们想要这个 - -767 -00:39:09,218 --> 00:39:12,953 -say we wanted to connect this UI - to this - code. -UI连接到代码中。 - -768 -00:39:12,955 --> 00:39:15,072 - So let's do that. -我们现在就这样做。 - -769 -00:39:15,073 --> 00:39:17,190 - Let's connect this label right - here into - this code, and -我们连接这个label到代码中去, - -770 -00:39:17,192 --> 00:39:20,560 - then we're gonna do that by - making an - instance variable. -然后我们会通过一个实例变量。 - -771 -00:39:20,562 --> 00:39:23,062 - In Swift we call them - properties. -在Swift中我们叫它属性。 - -772 -00:39:23,064 --> 00:39:25,330 - 'Kay so if you hear me say - property, -如果你听到我说属性, - -773 -00:39:25,332 --> 00:39:27,165 - I'm basically talking about an - instance - variable. -那我其实就是在说实例变量。 - -774 -00:39:27,167 --> 00:39:29,467 - Right? - A variable that is part of the - class. -清楚吗?一个变量是类的一部分。 - -775 -00:39:29,469 --> 00:39:31,869 -Every instance of the class gets - its own - copy of it. -类的每个实例都有自己的拷贝。 - -776 -00:39:31,871 --> 00:39:34,171 - Hopefully you all know what an - instance - variable is. -希望你都知道什么是一个实例变量。 - -777 -00:39:34,173 --> 00:39:35,739 -If you don't, again, this class, -如果你不清楚,再说一次,这是类, - -778 -00:39:35,741 --> 00:39:38,408 - heavy object-oriented, you - should - definitely know that. -面向对象的,你应该清楚。 - -779 -00:39:38,410 --> 00:39:41,678 - So I'm gonna make a property - here, an - instance variable, -我将要声明一个属性在这里,也可以说是一个实例变量。 - -780 -00:39:41,680 --> 00:39:45,848 - that points to this label, so - that I can -update the label's text, right? -使用指针指向这个lable,这样就我就能够更新这个label的内容了。 - -781 -00:39:45,850 --> 00:39:50,486 - I need to be able to talk to - this label, - and the way you do that in iO - eh, -我需要告诉这个label, - -782 -00:39:50,488 --> 00:39:55,824 -in Xcode is you hold down Ctrl, - just like - we did when we were making -在Xcode中,你按住Ctrl,像刚才那样 - -783 -00:39:55,826 --> 00:39:59,627 -a connection to the edge, so I'm - holding - down Ctrl and clicking on the - label, but -连接边缘,我保持住点击Ctrl和左键在这个label上,但是 - -784 -00:39:59,629 --> 00:40:02,596 - instead of going to the edge, - I'm gonna go - into the code, 'kay? -不是要添加约束,我是想让它到代码中去, - -785 -00:40:02,598 --> 00:40:06,166 - Now this is kinda wacky. -这是有点古怪。 - - -786 -00:40:06,168 --> 00:40:07,901 - I know a lot of you are like - what? -我知道很多你喜欢什么? - -787 -00:40:07,903 --> 00:40:08,501 - Into the code? -在代码中? - -788 -00:40:08,503 --> 00:40:11,004 - Yeah? - -789 -00:40:11,005 --> 00:40:13,506 - So we're going right into the - code here - and let go and it's gonna say - oh, -现在我们到右边代码中,松开鼠标。 - -790 -00:40:13,508 --> 00:40:16,308 - you wanna make a connection - between your - UI and your controller. -你能连接UI和控制器了。 - -791 -00:40:16,310 --> 00:40:18,844 - No problem, what kinda - connection you - wanna make? -没问题了,接下来需要做什么? - -792 -00:40:18,846 --> 00:40:20,846 -And we wanna make what's called - an outlet - connection. -我们需要设置outlet连接。 - -793 -00:40:20,848 --> 00:40:22,681 - An outlet means an instance - variable or -一个outlet在实例变量或 - -794 -00:40:22,683 --> 00:40:25,717 - property that points to this - thing in the - UI. -属性,这个指针指向UI。 - -795 -00:40:25,719 --> 00:40:30,021 - And all it needs to know to do - that is, - what do you wanna call this - property? -接着你需要给这个属性一个名称。 - -796 -00:40:30,023 --> 00:40:34,925 - And this is the display of my - calculator - so I'm gonna call this display - and it -它将出现在我的计算器,所以我将命名为了display, - -797 -00:40:34,927 --> 00:40:38,962 - already knows the type of the - thing is UI - label of course cuz we dragged - from here. -这是说它是什么类型的,因为我们是从这里拖出来的。 - -798 -00:40:38,964 --> 00:40:41,431 - Don't worry about this weak, - I'll talk - about that in a moment. -不要担心这个弱连接,在后面我们会讲到。 - -799 -00:40:41,433 --> 00:40:45,067 - And then we just hit Connect, - and it -creates an instance variable or -然后我们点击这个按钮,它会创建一个实例变量或 - -800 -00:40:45,069 --> 00:40:47,202 - property, right here in our - controller. -称之为属性,完成后就出现在这里了。 - -801 -00:40:47,204 --> 00:40:51,339 - So this is a great opportunity - to look at - the syntax in Swift for -在Swift中这个语法就是 - -802 -00:40:51,341 --> 00:40:54,109 - creating a property. -创建一个属性。 - -803 -00:40:54,110 --> 00:40:56,878 - And there's a couple of things - on here - that are not normally part of - it. -这里有几件事情通常都不是它的一部分。 - -804 -00:40:56,880 --> 00:41:02,516 -This is you, the main syntax for - creating - a property. -这是你的主要语法创建一个属性。 - -805 -00:41:02,518 --> 00:41:04,418 -Let's quickly look at this thing - to get it - out of the way. -我们快速的了解下这个get方法。 - -806 -00:41:04,420 --> 00:41:07,454 - This is not really part of the - Swift - language proper. -这不是Swift真正语言的一部分。 - -807 -00:41:07,456 --> 00:41:09,555 -This is something Xcode puts in - here so -这是Xcode将在这里 - -808 -00:41:09,557 --> 00:41:14,526 -that this little circle, do you - see the - little circle in this gutter, - appears? -这个小圆圈,你可以看到这个小圆圈出现在这里。 - -809 -00:41:14,528 --> 00:41:18,463 -This little circle when I mouse - over it, - look what Xcode does. -当我把鼠标移动到上面时候,看看Xcode的变化。 - -810 -00:41:18,465 --> 00:41:21,933 - It shows me what this line of - code is - connected to. -它展示了我选中的代码所连接的UI。 - -811 -00:41:21,935 --> 00:41:23,852 - 'Kay? - So that's really cool, and -这看起来非常酷, - -812 -00:41:23,853 --> 00:41:25,770 - you're gonna see that's really - valuable - later in this demo, -在这个demo中这是非常有用的, - -813 -00:41:25,772 --> 00:41:27,838 - is being able to find out what - things are - connected to. -它能找到我们连接的是什么控件。 - -814 -00:41:27,840 --> 00:41:29,773 - So that's all this thing means - here. -这个就是它所展示的意义。 - -815 -00:41:29,775 --> 00:41:33,777 -You, you, you don't type this in - yourself, -that when you Ctrl+drag, it puts - it there. -当你Ctrl+点击拖动时候你不清楚是什么类型,它所说的。 - -816 -00:41:33,779 --> 00:41:38,748 -This weak, all you, you, if you - come from - other languages, -这个weak,如果你从其他语言过来到。 - -817 -00:41:38,750 --> 00:41:44,653 - you're used to things like - garbage -collection to clean up the heap. -你会使用过类似的垃圾回收机制。 - -818 -00:41:44,655 --> 00:41:46,288 -Or maybe you even have to alloc - and -或者你也许习惯自己分配和 - -819 -00:41:46,290 --> 00:41:50,258 -free things yourself manually in - some - languages. -释放管理在一些语言中。 - -820 -00:41:50,260 --> 00:41:51,792 - None of that in Swift. -在Swift中是没有的。 - -821 -00:41:51,794 --> 00:41:54,828 -In Swift, the, all objects live - in the - heap, 'kay. -在Swift中,所有的对象都在堆中。 - -822 -00:41:54,830 --> 00:41:58,398 - All class, the instances of - classes live - in the heap. -所有类,类的实例都存在类的堆中。 - -823 -00:41:58,400 --> 00:42:02,335 - And the memory for them is - managed for - you, 'kay? -替你进行了内存管理。 - -824 -00:42:02,337 --> 00:42:05,371 -You allocate them as much as you - want, as - soon as there's no pointers to - them, -你分配他们尽可能多的你想要的,只要没有了指针指向它们, - -825 -00:42:05,373 --> 00:42:08,274 - they get cleaned up, and it's - not garbage - collection, 'kay? -它们会自动清理,不需要垃圾回收。 - -826 -00:42:08,276 --> 00:42:10,493 - It's reference counting. -这就是引用计数。 - -827 -00:42:10,494 --> 00:42:12,711 - It's actually counting - references to them - but it's all automatic. -它实际上是计算引用他们的次数,但这都是自动的。 - -828 -00:42:12,713 --> 00:42:16,548 -The only thing you ever have to - be maybe - interested in is this weak - business which -你曾经也许唯一感兴趣的是这个weak的功能, - -829 -00:42:16,550 --> 00:42:19,851 - is less than a hundredth of a - percent of - the time. -在小于百分之一的时间。 - -830 -00:42:19,853 --> 00:42:23,788 -And for the first four weeks of - this - class, forget about weak. -前四周的课程中,忘掉有关weak的吧。 - -831 -00:42:23,790 --> 00:42:27,591 -It'll automatically happen when - you do -this Ctrl+drag, but just ignore - it. -当你使用Ctrl+点击拖动时候,它会自动完成,所以先忽略这个吧。 - -832 -00:42:27,593 --> 00:42:29,560 - But the main thing to know is - that all - that memory -但是最主要的事情是知道有关内存管理 - -833 -00:42:29,562 --> 00:42:31,128 -management is happening for you. -会发生在你身上的。 - -834 -00:42:31,130 --> 00:42:34,330 - Also this, instance variable - right here, -同时,实例变量在这里, - -835 -00:42:34,332 --> 00:42:38,267 - which is a pointer to this - object, notice - there's no ampersands or -通过一个指针指向对象,注意到没有与符号或 - -836 -00:42:38,269 --> 00:42:42,271 - stars or any other kind of - syntax that - says this is a pointer. -星或者其他任何语法说这是一个指针。 - -837 -00:42:42,273 --> 00:42:44,406 - 'Kay? - -838 -00:42:44,407 --> 00:42:46,540 -If you have a instance, variable - or - property or -如果你有一个实例变量或属性或 - -839 -00:42:46,543 --> 00:42:48,910 - local variable that is an - object, okay, -局部变量都是一个对象。 - -840 -00:42:48,912 --> 00:42:52,980 -it's always a pointer to it cuz - objects - only live in the heap, 'kay? -它总是一个指针,因为对象只在堆中存在着。 - -841 -00:42:52,982 --> 00:42:54,648 -So you don't need all that extra - stars and -所以不需要多余的*和&, - -842 -00:42:54,650 --> 00:42:57,184 -ampersand, any of that business - from other - languages, okay? -不要从其他语言中借鉴。 - -843 -00:42:58,286 --> 00:43:01,587 - This exclamation point, by the - way, I'm - gonna talk about in a few - minutes, -这个感叹号,顺便说一下,我要谈几分钟 - -844 -00:43:01,589 --> 00:43:04,023 - has nothing to do with this - being an - object, okay? -这是和对象不相关的。 - -845 -00:43:04,025 --> 00:43:05,858 - This is, this totally separate - thing. -这完全不相干的事情。 - -846 -00:43:05,860 --> 00:43:07,092 - We'll get to it. -我们会得到它。 - -847 -00:43:07,094 --> 00:43:08,043 - All right. - -848 -00:43:08,044 --> 00:43:08,993 - So let's look at this. -让我们看看这个。 - -849 -00:43:08,995 --> 00:43:15,166 -This is the syntax for defining - a - property, 'kay? -这个语法是定义了一个属性,对吗? - -850 -00:43:15,168 --> 00:43:16,066 - An instance variable. -一个实例变量。 - -851 -00:43:16,068 --> 00:43:18,519 - And it's very simple. -并且它是如此的简单。 - -852 -00:43:18,520 --> 00:43:20,971 -You got var, short for variable - cuz that's - what this is, a variable. -你看到var,它是变量的缩写。 - -853 -00:43:20,973 --> 00:43:23,473 - The name, this is the name of - it, display. -这是变量的名称,display - -854 -00:43:23,475 --> 00:43:25,475 - Okay? - That's just the name of this - property. -这个属性的名字是这个。 - -855 -00:43:25,477 --> 00:43:26,909 - And then :UILabel! -紧接着就是UILabel。 - -856 -00:43:26,911 --> 00:43:28,510 - Is the type, 'kay? -这个是它的类型。 - -857 -00:43:28,512 --> 00:43:33,815 -That's the type of this instance - variable. -这个类似是这个实例变量的。 - -858 -00:43:33,817 --> 00:43:38,452 - So again, I'll talk about the - exclamation - point later, but -我稍后会讲到那个感叹号,但 - -859 -00:43:38,454 --> 00:43:42,389 -obviously this thing is pointing - to this -label so that we can talk to it. -很明显,这是指向label的,我们能这样说。 - -860 -00:43:42,391 --> 00:43:43,590 - And we'll be doing that in a - moment. -我们能够这样去做。 - -861 -00:43:43,592 --> 00:43:44,424 - 'Kay? - -862 -00:43:44,426 --> 00:43:46,325 - Questions? -有什么疑问吗? - -863 -00:43:46,327 --> 00:43:49,962 - All right, let's talk about - another kind - of connection we may, -好的,让我们来谈谈另一种连接, - -864 -00:43:49,964 --> 00:43:52,364 -we can make, let's start putting - some - buttons in our calculator. -我们可以,让我们开始放一些计算器的按钮吧。 - -865 -00:43:52,366 --> 00:43:55,100 - So I'm gonna go back to the - Utilities - window, 'kay? -我将要打开这个工具窗口。 - -866 -00:43:55,102 --> 00:43:56,734 - By pressing this button over - here, -按下这个按钮, - -867 -00:43:56,736 --> 00:44:00,705 -go down to the bottom, go to the - third tab - over here, the object library. -找到下方的第三个选项的对象目录。 - -868 -00:44:00,707 --> 00:44:04,775 - And instead of a label, this - time I'm - gonna drag out a button. -这次拖的不是label,我将要拖动出来一个按钮。 - -869 -00:44:04,777 --> 00:44:07,143 - Okay? - I'm gonna put this button here - now. -现在我要把这个按钮放到这里。 - -870 -00:44:07,145 --> 00:44:11,414 - Just to be different, I'm not - gonna -initially line it up with a blue - line. -有些不同,我没有初始化蓝色的线。 - -871 -00:44:11,416 --> 00:44:14,283 - I'm just gonna put it kinda in - space out - here and -我只是想把它放在这个空间中, - -872 -00:44:14,285 --> 00:44:17,119 - I'll line it up with the blue - line later, - 'kay? -将它放在蓝线的下面。 - -873 -00:44:17,121 --> 00:44:19,487 - But I don't wanna forget to do - that -though, I always wanna do that. -但我不会忘记做,我总是期望这样。 - -874 -00:44:19,489 --> 00:44:22,724 - What I'm gonna do later is to - show you it - can be done. -以后我要做的就是告诉你这是可以做到的。 - -875 -00:44:22,726 --> 00:44:26,127 -So, this is gonna be, let's say - this is - gonna be one of our number - buttons. -接着,我们可以说这就是一个数字按钮。 - -876 -00:44:26,129 --> 00:44:30,197 - Like the upper left corner of - our keypad - is a 7. -就像键盘左上角的数字7。 - -877 -00:44:30,199 --> 00:44:31,598 - Okay? - -878 -00:44:31,599 --> 00:44:32,998 - Again, I have the same thing - over here. -我还需要其他的一些。 - -879 -00:44:33,001 --> 00:44:35,368 - Okay? -With the attributes inspector I - can -通过属性设置,我能够 - -880 -00:44:35,370 --> 00:44:37,203 - change things like the font. -修改一些字体大小什么的。 - -881 -00:44:37,205 --> 00:44:40,872 - Let's make this be 24 point, - let's say. -让我们尝试下尺寸为24的。 - -882 -00:44:40,874 --> 00:44:42,791 - I can resize. -我能够修改尺寸。 - -883 -00:44:42,792 --> 00:44:44,709 - Notice that when I resize it - will actually - tell me the size, -注意,当我调整它时候,会显示尺寸。 - -884 -00:44:44,711 --> 00:44:46,978 -see it saying there what size it - is? -看到它说这是多大的尺寸 - -885 -00:44:46,980 --> 00:44:50,381 - I can also set the size maybe - with this - size inspector right here, -我还可以在设置尺寸这里修改, - -886 -00:44:50,383 --> 00:44:51,348 - type it in exactly. -类型的准备。 - -887 -00:44:51,350 --> 00:44:53,517 - Maybe 64 by 64, something like - that. -也许64 x 64 看起来更合适。 - -888 -00:44:53,519 --> 00:44:54,918 - We don't usually do that. -我们通常不这样做。 - -889 -00:44:54,920 --> 00:44:57,587 -We want things to be kinda their - natural - sizes but -我们希望它能够是原始的大小,但 - -890 -00:44:57,589 --> 00:45:01,156 -just want to show you that there - are other - inspectors over here. -这里只想向你展示有其他的方法。 - -891 -00:45:01,158 --> 00:45:02,491 - So we have this 7. -所以我们有这个7。 - -892 -00:45:02,493 --> 00:45:05,460 -Now when this 7 is pressed, what - do we - want to happen? -当7被按下的时候,会发生什么呢? - -893 -00:45:05,462 --> 00:45:07,963 - What we want. -我们想要的。 - -894 -00:45:07,964 --> 00:45:10,465 -Numbers just start appearing up - here in - the display, right? -数字出现在需要展示的地方。 - -895 -00:45:10,467 --> 00:45:13,000 - So that's something our - controller is - going to have to do. -这就是我们的控制器不得不做的事。 - -896 -00:45:13,002 --> 00:45:17,071 - So, when we touch this button, - we kinda - want this button to send a - message to -当我们点击这个按钮,我们想让这个按钮发送信息到 - -897 -00:45:17,073 --> 00:45:21,307 - our controller, and we do that - the exact - same way as we did this one, -我们的控制器,跟之前的方式一样, - -898 -00:45:21,309 --> 00:45:25,911 -we hold down control, drag into - our code. -我们按住Ctrl,点击,拖动到代码中。 - -899 -00:45:25,913 --> 00:45:29,248 -When we let go though, we're not - going to -an outlet connection this time, -当我们松开时候,我们不想要outlet这个, - -900 -00:45:29,250 --> 00:45:34,085 -because I dont want an instance - variable - here, what i want is a method, - right? -因为此时我不想要一个实例变量,我需要一个方法。 - - -901 -00:45:34,087 --> 00:45:39,790 - A function on my class, a - method, everyone - understand the word method I - hope, - -902 -00:45:39,792 --> 00:45:44,161 - okay, so we want it to send an - [INAUDIBLE] -message to our control board, so - -903 -00:45:44,163 --> 00:45:48,831 - I'm going to pick" action", - [COUGH] losing - my voice here. - -904 -00:45:48,833 --> 00:45:50,433 -Bad time to have a little cold, - but. - -905 -00:45:50,435 --> 00:45:52,968 - [SOUND] So I'm doing an action - so - -906 -00:45:52,970 --> 00:45:56,838 -an action is a little different - than a - outlet, okay? - -907 -00:45:56,840 --> 00:45:58,973 - An outlet means an instance - variable or - -908 -00:45:58,975 --> 00:46:01,909 -property, action means create a - method for - me. - -909 -00:46:01,911 --> 00:46:03,944 - So again it wants to know the - name of the - method. - -910 -00:46:03,946 --> 00:46:05,512 - So what does this thing do? - -911 -00:46:05,514 --> 00:46:08,815 - Well when I press seven, it - appends a - digit onto the end of - -912 -00:46:08,817 --> 00:46:12,852 - whatever's already in the - display, so I'm - going to call it append, - -913 -00:46:12,854 --> 00:46:17,390 - I could call it append seven, - but I'm -actually going to call it append - digit, - -914 -00:46:17,392 --> 00:46:20,859 - because I want to have one - method that all - of my buttons use. - -915 -00:46:20,861 --> 00:46:23,328 - All right? - -916 -00:46:23,329 --> 00:46:25,796 - I don't want to, copy and - pasting a bunch -of methods, that would be really - bad code. - -917 -00:46:27,400 --> 00:46:29,566 - But if I'm gonna have one - method, - -918 -00:46:29,568 --> 00:46:33,437 -then I need to know which button - is - sending me this message, okay? - -919 -00:46:33,439 --> 00:46:37,073 - Luckily, when you haven't - actioned a - message being sent here, - -920 -00:46:37,075 --> 00:46:40,977 - you can specify that it has - arguments, you - see right here where it says - arguments? - -921 -00:46:40,979 --> 00:46:45,414 -And it can have no arguments or - it can - have the sender. - -922 -00:46:45,416 --> 00:46:48,483 -Which is the button here as the - argument. - -923 -00:46:48,485 --> 00:46:52,787 - The only tricky thing here is, - and I'm not -sure why they did this in Xcode. - -924 -00:46:52,789 --> 00:46:54,455 -Hopefully, they'll change it in - the - future. - -925 -00:46:54,457 --> 00:46:59,092 - By default, the type of that - argument, - which is right here, is any - object. - -926 -00:46:59,094 --> 00:47:01,961 -Now, we're gonna talk about any - object - next week. - -927 -00:47:01,963 --> 00:47:04,330 - But, we don't want any object - here. - -928 -00:47:04,332 --> 00:47:06,599 -We know that the sender is a UI - button, so - -929 -00:47:06,601 --> 00:47:09,935 -I picked, click this little blue - thing and - switch this to UI button. - -930 -00:47:09,937 --> 00:47:13,672 -When you're doing your homework, - if you - forget to switch that to UI - button, - -931 -00:47:13,674 --> 00:47:15,907 - you'll be sad, okay. - -932 -00:47:15,909 --> 00:47:17,541 - So don't forget. - -933 -00:47:17,543 --> 00:47:21,978 -And obviously the event that the - message - is gonna be sent on, touch up - inside, - -934 -00:47:21,980 --> 00:47:25,448 - just means the user touched on - this button - and the touch went up. - -935 -00:47:25,450 --> 00:47:27,116 - While it was still inside the - button. - -936 -00:47:27,118 --> 00:47:29,952 - That's all a touch up inside - means there. - -937 -00:47:29,954 --> 00:47:32,021 - All right so when I connect - this, - -938 -00:47:32,023 --> 00:47:35,824 -I'm gonna get a method with one - argument -which is a sender which is a UI - button. - -939 -00:47:35,826 --> 00:47:38,760 - So let's take a look. - -940 -00:47:38,761 --> 00:47:41,695 - So here's your first method - declaration in - SWIFT, okay? - -941 -00:47:41,698 --> 00:47:46,133 - Again it's got this little IB - action thing - which is kinda like IB outlet. - -942 -00:47:46,135 --> 00:47:47,967 - It puts a little dot in the - gutter. - -943 -00:47:49,104 --> 00:47:50,436 - Okay? - So that you can - -944 -00:47:50,438 --> 00:47:52,938 -see what this thing is connected - to. - -945 -00:47:52,940 --> 00:47:59,010 - So this is the normal, Swift - method - syntax. - -946 -00:47:59,012 --> 00:48:02,213 - Starts with func because - function, - -947 -00:48:02,215 --> 00:48:04,215 - basically that method is a - function in - class. - -948 -00:48:04,217 --> 00:48:06,483 - [COUGH] Here's the name. - -949 -00:48:06,485 --> 00:48:07,918 - Append digit. - -950 -00:48:07,920 --> 00:48:10,987 -And then in parentheses, all the - arguments - separated by commas. - -951 -00:48:10,989 --> 00:48:12,989 - We only have one argument, - though. - -952 -00:48:12,991 --> 00:48:15,057 - Here's the name of the first - argument. - -953 -00:48:15,059 --> 00:48:18,860 - That's the name we're going to - use to -access it inside of our method, - and - -954 -00:48:18,862 --> 00:48:20,295 - here is the type. - -955 -00:48:21,264 --> 00:48:22,496 - Okay? - It's a UI button. - -956 -00:48:22,498 --> 00:48:24,598 - I, notice no exclamation point - there, by - the way. - -957 -00:48:26,535 --> 00:48:31,237 -Okay if this had a return value, - if this - method returned something this - one doesn't - -958 -00:48:31,239 --> 00:48:36,208 - [COUGH] but if it returned - something, it - would look like this arrow the - return type - -959 -00:48:37,745 --> 00:48:40,311 -okay so that's how you specify a - return - type. - -960 -00:48:42,215 --> 00:48:48,185 - Okay, pretty simple the syntax - and then - inside here we just type, - -961 -00:48:48,187 --> 00:48:51,822 -well whatever we want this thing - to do - when one of these buttons is - touched. - -962 -00:48:51,824 --> 00:48:53,774 - So what do we want it to do? - -963 -00:48:53,775 --> 00:48:55,725 -Well, okay, first of all before - we do - that, let's go ahead and make - more of - -964 -00:48:55,727 --> 00:48:58,928 - these buttons because I need - seven, eight, -nine, four, five, six, all this. - -965 -00:48:58,930 --> 00:49:01,664 - So let's copy and paste the - button. - -966 -00:49:01,666 --> 00:49:04,400 - When I copy and - -967 -00:49:04,401 --> 00:49:07,135 - paste the button, notice I'm - using the - blue lines to put it perfectly - lined up. - -968 -00:49:07,138 --> 00:49:11,373 -Okay, also notice that it there - also - sending this message. - -969 -00:49:11,375 --> 00:49:14,776 - All right, see how their both - sending the -message, because when I copy and - -970 -00:49:14,778 --> 00:49:18,012 -paste, it copied that aspect of - it as - well. - -971 -00:49:18,014 --> 00:49:21,182 -So there's another one, I could - select all - three of these and - -972 -00:49:21,184 --> 00:49:27,154 - copy and paste, okay, I could - select all -six of these and copy and paste. - -973 -00:49:27,156 --> 00:49:30,990 -So I can quickly make, my entire - keypad. - -974 -00:49:30,992 --> 00:49:33,343 - Just need to edit the title. - -975 -00:49:33,344 --> 00:49:35,695 -Now, if while I'm editing these - titles, -sometimes you're clicking around - in - -976 -00:49:35,697 --> 00:49:39,431 -here and, you know, you're not a - very - accurate clicker. - -977 -00:49:39,433 --> 00:49:43,368 - [LAUGH] Or, you know, you just - get out, - out of control clicking here, - and oh, - -978 -00:49:43,370 --> 00:49:45,236 - you moved it out of the way. - -979 -00:49:45,238 --> 00:49:46,821 - Okay? - -980 -00:49:46,822 --> 00:49:48,405 -No problem, you can just put it - right back - in. - -981 -00:49:48,408 --> 00:49:51,675 -Okay, use the blue lines to your - advantage. - -982 -00:49:52,844 --> 00:49:55,278 - And we'll put our zero down - here. - -983 -00:49:55,279 --> 00:49:57,713 - And I don't need these buttons - so I'm just - hit, selecting it, hitting - delete. - -984 -00:49:57,716 --> 00:49:59,715 - That's how you can get rid of - something. - -985 -00:49:59,717 --> 00:50:02,985 - And I promised I was gonna put - these all - on blue lines, so I'm gonna do - that. - -986 -00:50:02,987 --> 00:50:05,921 - I'm gonna put it right - underneath the - zero. - -987 -00:50:05,923 --> 00:50:08,890 -So here's a blue line that means - underneath the zero, and - -988 -00:50:08,892 --> 00:50:10,692 - then I'm going to put at this - edge. - -989 -00:50:10,694 --> 00:50:14,962 -So now you can see that the blue - lines are - not just the edges, but - -990 -00:50:14,964 --> 00:50:17,965 -they are other objects, like the - other - objects in the keypad and - -991 -00:50:17,967 --> 00:50:20,667 -also now the title, the display - rather at - the top. - -992 -00:50:21,870 --> 00:50:26,205 - So I've got all these buttons, - they're all - sending this message append - digit. - -993 -00:50:26,207 --> 00:50:28,874 - So I need to figure out which - one is - sending it, - -994 -00:50:28,876 --> 00:50:30,942 - so that I can do the right - thing. - -995 -00:50:30,944 --> 00:50:33,611 -So let's start writing some code - inside - the method. - -996 -00:50:33,613 --> 00:50:37,281 -So the first thing I'm going to - do is - declare a local variable, - -997 -00:50:37,283 --> 00:50:39,917 - it's just a local variable - inside this - method. - -998 -00:50:39,919 --> 00:50:43,520 - I'm going to do that by saying - let digit - equal. - -999 -00:50:43,522 --> 00:50:47,824 -So I want this local variable to - be the - digit that was pressed. - -1000 -00:50:47,826 --> 00:50:50,743 - Okay. - -1001 -00:50:50,744 --> 00:50:53,661 - So, first thing that's quite - different - here is, what's let? - -1002 -00:50:53,664 --> 00:50:54,363 - Okay? - -1003 -00:50:54,365 --> 00:50:56,999 - Why isn't this var, right? - -1004 -00:50:57,001 --> 00:51:00,735 -Cuz var means variable, what the - heck does - let mean? - -1005 -00:51:00,737 --> 00:51:05,973 -Well let is exactly the same as - var except - it's a constant. - -1006 -00:51:07,143 --> 00:51:10,744 -Which means you're going to sign - this - right off the bat, and - -1007 -00:51:10,746 --> 00:51:13,046 - it's never going to change in - this method. - -1008 -00:51:13,048 --> 00:51:15,415 -Now Swift makes a big deal about - this, and - -1009 -00:51:15,417 --> 00:51:19,552 -I love this feature, because if - I'm - reading this code, - -1010 -00:51:19,554 --> 00:51:23,355 -I know the digit is never going - to change - all, this might be, you know. - -1011 -00:51:23,357 --> 00:51:24,856 - It might have a dozen lines of - code. - -1012 -00:51:24,858 --> 00:51:26,792 - Which by the way, - -1013 -00:51:26,793 --> 00:51:28,727 - you shouldn't have very many - methods, with - many more lines of code then - that. - -1014 -00:51:28,729 --> 00:51:30,294 - Okay? - You want people to be able to - -1015 -00:51:30,296 --> 00:51:31,796 - kind of see what a method's - doing. - -1016 -00:51:33,232 --> 00:51:34,765 - You can use other methods, - -1017 -00:51:34,767 --> 00:51:37,801 - call other methods if you need - to get more - code in there. - -1018 -00:51:37,803 --> 00:51:38,935 - so. - -1019 -00:51:38,937 --> 00:51:39,835 - Here I can de-, - -1020 -00:51:39,837 --> 00:51:41,270 - rely on that not changing. - -1021 -00:51:41,272 --> 00:51:44,406 - That's big for readability. - -1022 -00:51:44,407 --> 00:51:47,541 - You'll be surprised how much - more readable -it makes the code, to know that - this is a, - -1023 -00:51:47,544 --> 00:51:49,177 - local variable, but it's - constant. - -1024 -00:51:49,179 --> 00:51:50,111 - Only set at the beginning. - -1025 -00:51:50,113 --> 00:51:52,913 - Yeah. -Is there a reason, constants and - -1026 -00:51:52,915 --> 00:51:54,715 - like, variables have the same - naming - convention. - -1027 -00:51:54,717 --> 00:51:56,450 -Since [UNKNOWN] like Java there. - -1028 -00:51:56,451 --> 00:51:58,184 -Like the naming conventions like - all caps - or lowercase. - -1029 -00:51:58,186 --> 00:52:00,770 - Yeah. - So, yeah. - -1030 -00:52:00,771 --> 00:52:03,355 - The question is, why don't I - call digit - like all caps digit, or - -1031 -00:52:03,358 --> 00:52:05,424 - something like that, so I know - it's a - constant. - -1032 -00:52:05,426 --> 00:52:07,626 - That would be a programming - style thing. - -1033 -00:52:07,628 --> 00:52:10,929 -Generally in Swift they don't do - that. - -1034 -00:52:10,931 --> 00:52:13,765 - And, I'll show you why that is - in a - moment. - -1035 -00:52:13,767 --> 00:52:15,233 -Why you don't really need to do - that. - -1036 -00:52:15,235 --> 00:52:18,069 - Because you can very quickly - find out the - declaration of - -1037 -00:52:18,071 --> 00:52:22,406 - any symbol anywhere with one - click, and - you'll see that. - -1038 -00:52:22,408 --> 00:52:25,209 - Good question though. - -1039 -00:52:25,210 --> 00:52:28,011 - All right, so I wanna let the - digit, equal - the number that's on the, - -1040 -00:52:28,013 --> 00:52:30,196 - the sending button. - -1041 -00:52:30,197 --> 00:52:32,380 - So I'm gonna have to send a - message to - this button. - -1042 -00:52:32,383 --> 00:52:34,316 - Okay? - Gonna have to somehow access - this button. - -1043 -00:52:34,318 --> 00:52:37,886 -So I'm gonna have to do sender, - something. - -1044 -00:52:37,888 --> 00:52:40,655 - Give me what your title is, - okay? - -1045 -00:52:40,657 --> 00:52:44,091 - So this is a good time to talk - about the - documentation. - -1046 -00:52:44,093 --> 00:52:45,543 - [COUGH]. - -1047 -00:52:45,544 --> 00:52:46,994 - Because being a good iOS - developer, - -1048 -00:52:46,996 --> 00:52:50,397 -really demands that you are good - at - navigating the documentation. - -1049 -00:52:50,399 --> 00:52:54,334 - Luckily, the documentation is - really well - plugged in to Xcode. - -1050 -00:52:54,336 --> 00:52:57,036 -For example, if I wanna find out - about - button, - -1051 -00:52:57,038 --> 00:53:00,339 - all I need to do is hold down - the option - key. - -1052 -00:53:00,341 --> 00:53:01,373 - Okay? - -1053 -00:53:01,375 --> 00:53:02,974 - And watch what happens now. - -1054 -00:53:02,976 --> 00:53:04,542 - As I mouse over things, - -1055 -00:53:04,544 --> 00:53:09,680 -everything, it turns blue with a - dashed - blue line under it, okay? - -1056 -00:53:09,682 --> 00:53:10,748 - If I click on it, - -1057 -00:53:12,117 --> 00:53:14,884 -it gives me a little blurb from - the -documentation about this thing. - -1058 -00:53:14,886 --> 00:53:17,954 - So it's saying, you know, - here's, button - is a class. - -1059 -00:53:17,956 --> 00:53:19,288 - Here's its inheritance. - -1060 -00:53:19,290 --> 00:53:20,689 - Here's a little bit of what it - does. - -1061 -00:53:20,691 --> 00:53:22,691 -And really awesome at the bottom - here, - -1062 -00:53:22,693 --> 00:53:25,427 -here's a link that takes you to - the - detailed documentation. - -1063 -00:53:25,429 --> 00:53:27,962 - So I'm gonna click this little - link right - here. - -1064 -00:53:27,964 --> 00:53:34,501 - It's going to be up a - documentation - window, with UI button in it, - hello? - -1065 -00:53:34,503 --> 00:53:38,038 -Did I not click that right thing - here, - -1066 -00:53:38,040 --> 00:53:43,076 -oh I hope I don't have a network - issue - here. - -1067 -00:53:43,078 --> 00:53:47,046 - hm, okay well, I guess I'm not - connected - to the network, - -1068 -00:53:47,048 --> 00:53:50,149 - that's the problem, so it's - getting this - off the network. - -1069 -00:53:50,151 --> 00:53:53,819 - Okay so. - -1070 -00:53:53,820 --> 00:53:57,488 - Imagine that there were - documentation here - and, it would have along this - side here - -1071 -00:53:57,491 --> 00:54:03,294 - on the left all the instance - variables or - properties and methods of u i - button. - -1072 -00:54:03,296 --> 00:54:05,929 -And you could click on any one, - and - -1073 -00:54:05,931 --> 00:54:08,165 - in there we'd have a full - description of - it here. - -1074 -00:54:08,167 --> 00:54:11,735 - And all the types that it - referenced you - could click on it here, and - -1075 -00:54:11,737 --> 00:54:14,504 - basically it's a hyper linked - documentation [UNKNOWN]. - -1076 -00:54:14,506 --> 00:54:16,773 - As you can imagine. - -1077 -00:54:16,774 --> 00:54:19,041 - I'll try to get the networking - working on -Wednesday and we'll take a look - at this. - -1078 -00:54:19,043 --> 00:54:21,494 - But if I was looking in here, - -1079 -00:54:21,495 --> 00:54:23,946 - I'd look down in the section - that says - getting the button's current - state, and - -1080 -00:54:23,948 --> 00:54:30,185 - I'd find that there is an - instance - property there called current - title. - -1081 -00:54:30,187 --> 00:54:31,552 - Okay? - It's unfortunate I'm not going - to - -1082 -00:54:31,554 --> 00:54:32,186 - link these things. - -1083 -00:54:32,188 --> 00:54:33,687 - But. - -1084 -00:54:33,689 --> 00:54:39,993 -So how do we access, property or - call a - method in another object, - -1085 -00:54:39,995 --> 00:54:43,429 - will look exactly the same - whether you - call it a method or - -1086 -00:54:43,431 --> 00:54:46,332 - accessing a property, which is - you use - dot. - -1087 -00:54:46,334 --> 00:54:49,435 - Okay. -It's the same syntax that's used - in - -1088 -00:54:49,437 --> 00:54:52,771 -a lot of languages is to, to do - dot. - -1089 -00:54:52,773 --> 00:54:55,173 - And so when you do that, Xcode - is going to - say, oh, - -1090 -00:54:55,175 --> 00:54:58,209 - well, here's all the things - button knows - how to do. - -1091 -00:54:58,211 --> 00:54:59,894 - Okay? - -1092 -00:54:59,895 --> 00:55:01,578 -And as you can see, button knows - how to do - a lot of things. - -1093 -00:55:01,581 --> 00:55:03,747 - Because it inherits from a - class, it - inherits from a class, - -1094 -00:55:03,749 --> 00:55:07,451 - it inherits from a class, that - all have - lots of methods in them. - -1095 -00:55:07,453 --> 00:55:10,320 - So when I looked at that - documentation. - -1096 -00:55:10,322 --> 00:55:13,823 - I've found that current title - was the - thing I wanted. - -1097 -00:55:13,825 --> 00:55:18,194 -Now notice as I start to type a - c, it's - already cutting down - -1098 -00:55:18,196 --> 00:55:23,331 - the things that could be - starting with a - c, and then c u, they cut down - even more. - -1099 -00:55:23,333 --> 00:55:28,770 - I can type tab, to get to the - first -ambiguity point, then I can type - t. - -1100 -00:55:29,739 --> 00:55:31,889 - Okay? - -1101 -00:55:31,890 --> 00:55:34,040 -And then tab again, and I'm here - at - current title and then I can - press return. - -1102 -00:55:35,243 --> 00:55:35,875 - Okay? - -1103 -00:55:35,877 --> 00:55:37,327 - So there it is. - -1104 -00:55:37,328 --> 00:55:38,778 - Digit equals sender current - title. - -1105 -00:55:38,780 --> 00:55:45,484 - so, what's going on here in - terms of did, - descender title. - -1106 -00:55:45,486 --> 00:55:49,520 - Let's go ahead and print this - out to the -console just to see what's going - on. - -1107 -00:55:49,522 --> 00:55:50,688 - So I'm gonna print lin. - -1108 -00:55:50,690 --> 00:55:55,992 -At which is a function, a global - function - that takes a string. - -1109 -00:55:55,994 --> 00:55:57,694 - So I give it a string. - -1110 -00:55:57,696 --> 00:55:59,762 - And inside that string, I'll - type mm, - -1111 -00:55:59,764 --> 00:56:05,000 - digit equals and now I wanna - embed the - value of digit in this string. - -1112 -00:56:05,002 --> 00:56:08,337 - And Swift has a really cool - feature which - is backslash open parentheses - -1113 -00:56:08,339 --> 00:56:11,924 - close parentheses. - -1114 -00:56:11,925 --> 00:56:15,510 -If you put that in a string, and - then - inside there you put some - expression, then - -1115 -00:56:15,512 --> 00:56:21,048 -it will evaluate that expression - turn it - into a string, and embed it in - the string. - -1116 -00:56:21,050 --> 00:56:24,718 - Okay, so its really easy to - print lin - values by - -1117 -00:56:24,720 --> 00:56:27,487 - using this backslash - parenthesis. - -1118 -00:56:27,489 --> 00:56:28,254 - Okay? - -1119 -00:56:28,256 --> 00:56:30,189 - So let's go ahead and run and - -1120 -00:56:30,190 --> 00:56:32,123 - see what happens when we press - these - buttons to see what kind of - result we get. - -1121 -00:56:32,126 --> 00:56:35,027 -It's not going to be quite what - we expect, - but let's see. - -1122 -00:56:37,864 --> 00:56:42,066 - Alright so, here's our BUY we - got our - buttons that's a good start. - -1123 -00:56:42,068 --> 00:56:44,435 - And now, and console, where's - the console? - -1124 -00:56:44,437 --> 00:56:46,269 - Watch this. - I'm going to press a button - five. - -1125 -00:56:47,372 --> 00:56:49,238 - The console appears at the - bottom here. - -1126 -00:56:49,240 --> 00:56:50,172 - See this down here. - -1127 -00:56:50,174 --> 00:56:51,874 - This is the console. - -1128 -00:56:51,876 --> 00:56:56,277 - And it's saying digit equals, - hm, optional - five. - -1129 -00:56:56,279 --> 00:56:57,211 - Okay. - -1130 -00:56:57,213 --> 00:56:58,746 - How about a nine? - -1131 -00:56:58,748 --> 00:56:59,713 - They're all optional. - -1132 -00:56:59,715 --> 00:57:01,081 -What the heck is going on here? - -1133 -00:57:01,083 --> 00:57:03,250 - Okay. - -1134 -00:57:03,251 --> 00:57:05,418 -This is crucial to understanding - Swift. - -1135 -00:57:05,420 --> 00:57:08,421 - This is probably the most - important thing - to understand that - -1136 -00:57:08,423 --> 00:57:11,424 - people don't quite get right - from the - start. - -1137 -00:57:11,426 --> 00:57:15,827 - So we're really going to focus - here on - understanding what - -1138 -00:57:15,829 --> 00:57:17,862 - optional means right there. - -1139 -00:57:17,864 --> 00:57:18,730 - Okay? - -1140 -00:57:18,731 --> 00:57:19,597 - So let's go back to our code. - -1141 -00:57:22,168 --> 00:57:25,969 -And look at this, oh and by the - way it, - when the console appears down - here, - -1142 -00:57:25,971 --> 00:57:28,538 - you can make it go away with - this little - button, or - -1143 -00:57:28,540 --> 00:57:31,274 -you can just drag it out of the - way okay? - -1144 -00:57:31,276 --> 00:57:34,711 -But sometimes it's nice to have - that - console still there, so - -1145 -00:57:34,713 --> 00:57:39,548 - you can look at your output - while you're - you know reacting to whatever - you found, - -1146 -00:57:39,550 --> 00:57:41,750 - in fact we will leave that up - there, so - you can see the optionals. - -1147 -00:57:42,753 --> 00:57:45,186 - Alright, so, what's going on - here? - -1148 -00:57:45,188 --> 00:57:48,956 -Well, what's happening here is, - well, - first of all, - -1149 -00:57:48,958 --> 00:57:52,759 -don't you find this a little bit - odd, let - digit, I didn't put a type. - -1150 -00:57:52,761 --> 00:57:55,595 - You see that? - -1151 -00:57:55,597 --> 00:57:57,663 - How, what type is digit? - -1152 -00:57:57,665 --> 00:58:02,334 - Okay, well there's no type in - there, no -type information whatsoever, so. - -1153 -00:58:02,336 --> 00:58:04,636 - Does Swift have untyped - variables? - -1154 -00:58:04,638 --> 00:58:06,171 - No, it's exact opposite. - -1155 -00:58:06,173 --> 00:58:08,940 - Swift is very strongly typed. - -1156 -00:58:08,942 --> 00:58:10,141 - Okay. - -1157 -00:58:10,142 --> 00:58:11,341 - All variables have a type. - -1158 -00:58:11,344 --> 00:58:12,943 - You have to specify type. - -1159 -00:58:12,945 --> 00:58:17,847 - But, Swift is also incredibly - good at - what's called type inference. - -1160 -00:58:17,849 --> 00:58:20,817 - So it can infer the type from - the context. - -1161 -00:58:20,819 --> 00:58:25,554 - So here I let digit equal - whatever this - is, this current title, and - -1162 -00:58:25,556 --> 00:58:29,391 - so it just made digit be the - same type as - this. - -1163 -00:58:29,393 --> 00:58:31,543 - Okay. - -1164 -00:58:31,544 --> 00:58:33,694 - Now back to the question - earlier, so what - type is that? - -1165 -00:58:33,697 --> 00:58:37,365 - Well, if I hold down option, - okay, just - like we used option to - -1166 -00:58:37,367 --> 00:58:42,636 -go look into the documentation, - we can - also option click on our own - variables. - -1167 -00:58:42,638 --> 00:58:44,337 - To see are they constant? - -1168 -00:58:44,339 --> 00:58:45,204 - Are they variables? - -1169 -00:58:45,206 --> 00:58:46,138 - And what type are they? - -1170 -00:58:46,140 --> 00:58:47,306 - So watch this. - -1171 -00:58:47,308 --> 00:58:50,225 - Option click. - -1172 -00:58:50,226 --> 00:58:53,143 -It says digit is of type string - question - mark. - -1173 -00:58:53,146 --> 00:58:54,579 - Okay? - String question mark. - -1174 -00:58:55,515 --> 00:58:58,248 - That question mark means - optional. - -1175 -00:58:58,250 --> 00:59:02,585 - So there is a type in Swift, - it's a type, - called optional. - -1176 -00:59:02,587 --> 00:59:04,087 - Okay. - -1177 -00:59:04,089 --> 00:59:08,257 - Optional, that type can have - only two - values. - -1178 -00:59:08,259 --> 00:59:10,592 - One value is not set. - -1179 -00:59:12,095 --> 00:59:16,997 -Okay, this optional is not set, - there has - never been set or someone has - -1180 -00:59:16,999 --> 00:59:20,934 - set it to the not set state, - they unset it - if you want to think about it - that way. - -1181 -00:59:20,936 --> 00:59:25,405 - So optional one value is not - set, we call - that there's a, symbol for - -1182 -00:59:25,407 --> 00:59:28,241 -it in here called nil, N, I, L, - okay? - -1183 -00:59:28,243 --> 00:59:31,210 - That means not set, that's the - value of an - optional not set. - -1184 -00:59:31,212 --> 00:59:34,747 -That's the only thing nil means - in Swift - is option this is an optional, - -1185 -00:59:34,749 --> 00:59:36,948 -the value of an optional that is - not set. - -1186 -00:59:36,950 --> 00:59:41,586 - What's the other value that an - optional -could have well the other value - is. - -1187 -00:59:41,588 --> 00:59:44,655 - Something, it's set to - something, okay. - -1188 -00:59:44,657 --> 00:59:47,624 - And the type of that something - is what, - -1189 -00:59:47,626 --> 00:59:51,261 - is specified next to the - question mark - string. - -1190 -00:59:51,263 --> 00:59:55,932 - So really you can almost think - of the -question mark there, that's the - type - -1191 -00:59:55,934 --> 01:00:00,769 -optional, and that string to the - left is -just saying if this optional is - set, - -1192 -01:00:00,771 --> 01:00:04,139 -what type of thing is it set to, - in this - case a string. - -1193 -01:00:04,141 --> 01:00:06,941 - So we would call this an - optional string. - -1194 -01:00:06,943 --> 01:00:11,846 - But it's really an optional, - it's not a - string that can be nil, - -1195 -01:00:11,848 --> 01:00:14,815 - it's an optional that can be a - string. - -1196 -01:00:14,817 --> 01:00:16,516 - Everybody cool with that - sentence? - -1197 -01:00:16,518 --> 01:00:19,019 -That's an important sentence to - understand, okay. - -1198 -01:00:20,055 --> 01:00:23,956 - So, this got to be an optional - because -this current title method right - here, - -1199 -01:00:23,958 --> 01:00:26,525 - returns an optional string, - let's look at - that. - -1200 -01:00:26,527 --> 01:00:29,094 -So I'm going to Alt+Option down - here, - click. - -1201 -01:00:31,531 --> 01:00:36,334 -It's an instance variable a, a, -property -on UI button. -这是一个实例变量,UIButton的属性 - -1202 -01:00:36,336 --> 01:00:37,267 -Name is current title. -名字是current title - -1203 -01:00:37,269 --> 01:00:39,302 -The type is string, question mark. -类型是string,问号标记。 - -1204 -01:00:39,304 --> 01:00:41,271 -And this little get means it's read-only. -而这里的“get”表示这个是只读的。 - -1205 -01:00:41,273 --> 01:00:42,672 -I can only get the current title. -我只能获得current title。 - -1206 -01:00:42,674 --> 01:00:44,807 -I can't set it, there are other ways to set a button's title. -但是我不能设置,有其他方式进行设置。 - -1207 -01:00:44,809 --> 01:00:47,810 -You can't set it with this method or this property. -你不能通过这个方法或者属性进行设置。 - -1208 -01:00:47,812 --> 01:00:51,480 -So it's an optional, so that's why this ended up being an optional all right. -所以这是一个选项,这就是为什么最后是一个选项。 - -1209 -01:00:51,482 --> 01:00:53,081 -Well, that's all wonderful. -嗯,这非常不错。 - -1210 -01:00:53,083 --> 01:00:54,549 -How do I get the string? -我怎么获取这个string呢? - -1211 -01:00:54,551 --> 01:00:57,318 -I don't want it optional, I want that button's string. -我不需要它的选项,我要的是这个按钮的标题。 - -1212 -01:00:57,320 --> 01:01:02,923 -And the way you do that is you unwrap the optional, meaning you look in there and -方法就是你可以打开这个方法,意思是你正在 - -1213 -01:01:02,925 --> 01:01:08,061 -get the val, the associated value, with exclamation point, okay. -用“!”从里边获取关联的值。 - -1214 -01:01:08,063 --> 01:01:11,330 -What happens if I put that exclamation point there? -如果我把感叹号放在这里会怎么样? - -1215 -01:01:11,332 --> 01:01:13,732 -Well first of all, let me show you that when I put that exclamation point, -首先我先会展示给你们看,我把感叹号放在这里 - -1216 -01:01:13,734 --> 01:01:17,002 -look what happened to digit, I'm Option-clicking on digit. -看看会有什么变化,我现在点击数字。 - -1217 -01:01:17,004 --> 01:01:19,270 -It's not an optional anymore. -它不再是选项了。 - -1218 -01:01:19,272 --> 01:01:22,507 -Digit turned to a string because I unwrapped the optional that -数字变成了string,因为我打开了选项 - -1219 -01:01:22,509 --> 01:01:25,576 -came back from current title, got the string out of there. -从当前的标题里的到了string。 - -1220 -01:01:25,578 --> 01:01:28,612 -But what happens if this is nil? -但是如果这是个nil值会怎么样? - -1221 -01:01:28,614 --> 01:01:30,180 -What happened if this optional is nil? -如果选项是nil会发生什么事情? - -1222 -01:01:30,182 --> 01:01:34,718 -In other words the button option has never been set, crash, 'kay, -换句话说,就是这些按钮选项没有设置会怎么样?对的,会崩溃。 - -1223 -01:01:34,720 --> 01:01:39,855 -crashes your program, so if you use exclamation point to unwrap an optional, -所以如果你使用"!"号来打开一个选项的时候。 - -1224 -01:01:39,857 --> 01:01:45,660 -and that optional's current value is not set, nil, then it will crash your program. -并且这个选项没有设值为空的时候,你的程序会崩溃。 - -1225 -01:01:46,930 --> 01:01:50,498 -Now a lot of you might be like whoa, I'm, my products are gonna be crashing all over -现在你们中的不少人肯定在想,怎么我的东西老是崩溃? - -1226 -01:01:50,500 --> 01:01:55,903 -the place and, because there's a lot of optionals in iOS, I mean a lot, okay? -这是因为iOS有着非常多的选项,记住是非常多。 - -1227 -01:01:55,905 --> 01:01:58,939 -Most things are probably optionals, because most things, it make sense, -多数东西都是选项,因为这些东西都是有意义的。 - -1228 -01:01:58,941 --> 01:02:00,840 -they can be in an not set state at some point. -他们能在一些情况下出于不需设值的状态。 - -1229 -01:02:02,177 --> 01:02:07,746 -And yeah, in this case though, maybe you want your program to crash, okay? -在这个情况下,说不定你就希望你的程序崩溃?对不对? - -1230 -01:02:07,748 --> 01:02:11,850 -You might want your program to crash, because if you had a button, that never -你也许就是希望自己的程序崩溃,因为你有一个按键, - -1231 -01:02:11,852 --> 01:02:15,920 -had its title set, and it's sending a pen digit to your controller, you probably -但是它的标题从未设值,并且它传了一个数字给你的控制器 - -1232 -01:02:15,922 --> 01:02:20,358 -wanna have that crash, so you can find that bug, before you ship your program. -在你分发你的程序之前,你就能找到bug,所以你希望它崩溃。 - -1233 -01:02:20,360 --> 01:02:23,360 -You see why sometimes fra, crashing is good? -现在你知道为什么有时候程序崩溃是个好事吧。 - -1234 -01:02:23,362 --> 01:02:26,763 -Now if you don't wanna crash, there's a way to get around that as well. -现在如果你不想你的程序崩溃,这里有一个方法来解决。 - -1235 -01:02:26,765 --> 01:02:28,164 -And I'll show you that a little bit later. -我等一下就和你们说。 - -1236 -01:02:28,166 --> 01:02:32,802 -But for now understanding that that's what this exclamation point does. -但是现在,先弄明白这个感叹号是干什么的。 - -1237 -01:02:32,804 --> 01:02:35,638 -It unwraps that optional and crashes if it's nil. -它打开了选项,如果它是nil就崩溃。 - -1238 -01:02:35,640 --> 01:02:38,040 -But if it's not nil, it gets to the string or -但如果不是空,它是得到string还是 - -1239 -01:02:38,042 --> 01:02:40,809 -whatever the optional type is out of there for you. -给你其他的选项类型? - -1240 -01:02:40,811 --> 01:02:44,579 -So now let's go ahead and run again and -所以让我们继续,重新运行一次 - -1241 -01:02:44,581 --> 01:02:51,318 -we're gonna see that digit equals is gonna say the number, 'kay? -我们将看看是不是能得到相等的数字? - -1242 -01:02:51,320 --> 01:02:56,556 -It's got the string off the current title, no more optional in there, okay? -我们得到了当前的标题,没有更多的选项了。 - -1243 -01:02:56,558 --> 01:02:59,492 -Good? -看上去不错。 - -1244 -01:02:59,494 --> 01:03:03,362 -All right, so, now, what are we gonna do with that digit? -好的,现在,我们要用这些按钮做什么呢? - -1245 -01:03:03,364 --> 01:03:06,715 -We got the digit, -我们已经能得到数字。 - -1246 -01:03:06,716 --> 01:03:10,067 -we want to append it onto the end of this display right here, okay. -我们希望按的数字能显示在这里的末尾。 - -1247 -01:03:10,070 --> 01:03:13,972 -And so let's just do that by saying display, dot. -所以让我们输入display. - -1248 -01:03:13,974 --> 01:03:17,241 -Now, again, if we have the documentation,I'd go look in the documentation and -现在继续,如果我们查文档。 - -1249 -01:03:17,243 --> 01:03:21,712 -it would say oh, there's a property on UILabel, which is what display is, -它会告诉我们,UILabel有一个属性 - -1250 -01:03:21,714 --> 01:03:23,046 -display is a UILabel. -负责显示UILabel应该显示的什么。 - -1251 -01:03:23,048 --> 01:03:25,982 -There's a property and it' called text. -这个属性叫做text - -1252 -01:03:25,984 --> 01:03:28,518 -See it right there? -就在这里。 - -1253 -01:03:28,519 --> 01:03:31,053 -And actually, you can even see right here, the type of that, it's an optional as -而且实际上,输入这个,你能在这里看到,这是一个选项。 - -1254 -01:03:31,056 --> 01:03:36,225 -well, because this label's text might not have been set either, okay? -所以这个label的text还没有设值。 - -1255 -01:03:36,227 --> 01:03:39,061 -So it has to be an optional string, okay? -所以这里是选项string。 - -1256 -01:03:39,063 --> 01:03:43,297 -So I'm just gonna set that equal now, display that text as an optional, so -所以我现在要用等号设值,显示的text作为一个选项 - -1257 -01:03:43,299 --> 01:03:46,567 -what values can I send it to,set it to? -什么值可以设给它? - -1258 -01:03:46,569 --> 01:03:51,705 -I could set it to nil, that would be legal because it's an optional, -我可以设成nil,因为它是一个选项,是完全合法的。 - -1259 -01:03:51,707 --> 01:03:53,940 -see, no warnings, no errors. -看,没有警告也没有错误。 - -1260 -01:03:53,942 --> 01:03:55,475 -That would clear out that display. -这将什么也不显示。 - -1261 -01:03:55,477 --> 01:03:57,943 -It would not be set to anything, or -它不能设值成其他东西 - -1262 -01:03:57,945 --> 01:04:00,979 -I can set it to a string because it's an optional string. -我能给它设一个string值,因为它是一个选项string。 - -1263 -01:04:00,981 --> 01:04:03,682 -So I'm going to set it to a string and the string I'm going to set it -所以我将把它设值一个string - -1264 -01:04:03,684 --> 01:04:08,586 -to is display.text, what's currently in there, plus digit, okay? -这个string我设置成display.text,这里加个数字。 - -1265 -01:04:08,588 --> 01:04:10,087 -So I'm going to append that digit on. -这样子就能增加数字了。 - -1266 -01:04:10,089 --> 01:04:11,655 -Let's get rid of that. -让我们摆脱删掉这句。 - -1267 -01:04:11,657 --> 01:04:14,124 -Okay, now, this has an error here. -好吧,现在又有一个错误。 - -1268 -01:04:14,126 --> 01:04:15,025 -Why does this have an error? -这个错误是为什么呢?为什么这里有个错误呢? - -1269 -01:04:15,027 --> 01:04:17,093 -Anyone volunteer why this is an error? -有谁自愿回答这里为什么有个错误? - -1270 -01:04:17,095 --> 01:04:18,661 -See it's pointing right here. -发现错误指向这里。 - -1271 -01:04:18,663 --> 01:04:21,897 -There's an error, back there. -这里有个错误,后面那位同学回答。 - -1272 -01:04:21,899 --> 01:04:24,733 -The display.text is an optional string. -display.text是一个选项string。 - -1273 -01:04:24,735 --> 01:04:27,702 -Bingo. Because display.text right here is not -答对了,因为这里的display.tex它不是个string。 - -1274 -01:04:27,704 --> 01:04:33,341 -a string, it's an optional, and you can't add a string to an optional. -你不能将一个string加在一个选项上。 - -1275 -01:04:33,343 --> 01:04:35,476 -You can only add strings to other strings. -你只能将一个string加在另外的string上。 - -1276 -01:04:35,478 --> 01:04:39,813 -So we need to turn this into a string by unwrapping it. -所以我们通过打开选项,将选项转变为string。 - -1277 -01:04:39,815 --> 01:04:44,250 -And again, yes, this would crash if the display currently has nothing in it, -对的,这个东西会crash,如果display没有值。 - -1278 -01:04:44,252 --> 01:04:46,185 -it's not set, okay? -现在还没有设值。 - -1279 -01:04:46,187 --> 01:04:48,887 -Are we cool with that? -大家都了解这个了吧? - -1280 -01:04:48,889 --> 01:04:49,821 -So let's run again. -再让我们运行一次。 - -1281 -01:04:49,823 --> 01:04:52,857 -[BLANK_AUDIO] -[背景音] - -1282 -01:04:52,859 --> 01:04:54,058 -All right. -好的。 - -1283 -01:04:54,060 --> 01:04:57,461 -So now 5, oh, it put the 5 on there. -所以现在点击5,噢,5显示在这里了。 - -1284 -01:04:57,463 --> 01:04:58,762 -6, excellent. -点击6,好极了。 - -1285 -01:04:58,764 --> 01:05:00,497 -It's kinda working. -它能够工作了。 - -1286 -01:05:00,499 --> 01:05:02,565 -I don't really like that 0 though. -这个0在这里我很不喜欢。 - -1287 -01:05:02,567 --> 01:05:03,966 -That's kinda weak, 0, 5, 6. -这里就有点不对劲了,5和6前面有个0。 - -1288 -01:05:03,968 --> 01:05:06,669 -That should not, -这样子是不对的。 - -1289 -01:05:06,670 --> 01:05:09,371 -that 0 should've gotten cleared out, right, when I first typed that 5. -这个0应该在我按下5的时候就清除掉。 - -1290 -01:05:09,374 --> 01:05:12,808 -And that's because we really need some way in our controller to know whether we're in -这是因为我们确实需要一些方法让我们的controller知道我们是否在 - -1291 -01:05:12,810 --> 01:05:14,777 -the middle of typing a number right now. -一个数字膻中输入数字。 - -1292 -01:05:14,778 --> 01:05:16,745 -Because if we're in the middle of typing a number, we want to append, but -因为如果我们在一个已有数字中部输入数字,我们是希望数字加在输入的地方的。 - -1293 -01:05:16,747 --> 01:05:18,079 -if we're not in the middle of typing a number, -但是如果我们不用从一个数字的中部进行输入。 - -1294 -01:05:18,081 --> 01:05:21,182 -we want to start a new number, right? -也就是我们想要从头开始输入一个新的数字。 - -1295 -01:05:21,184 --> 01:05:27,021 -So, let's do that, and I'm going to do that by adding a property, okay? -所以,让我们通过添加一个属性实现这个效果。 - -1296 -01:05:27,023 --> 01:05:35,628 -Var userIsInTheMiddleOfTypingANumber , which you might say, -设个叫做“userIsInTheMiddleOfTypingANumber”的变量,你也许会说 - -1297 -01:05:35,630 --> 01:05:38,464 -oh my God, that terrible variable, now I have to type that over and over. -天哪,这么糟糕的变量名字,每次都得这么输入还不得累死? - -1298 -01:05:38,466 --> 01:05:40,900 -This is the last time I'll ever have to type that, okay? -其实下次用到这个变量我可不需要输入这么多的。 - -1299 -01:05:40,902 --> 01:05:44,169 -Because Xcode is always going to escape complete it for me, okay? -因为下次用到Xcode会帮我自动补齐的。 - -1300 -01:05:44,171 --> 01:05:48,840 -So long names are perfectly fine, in terms of typing load anyway. -所以这么长的名字没有问题。 - -1301 -01:05:48,842 --> 01:05:50,608 -So I like this name so I'm gonna keep it. -我就挺喜欢这个名字的,就这么用了。 - -1302 -01:05:50,610 --> 01:05:53,077 -And it's a bool, okay. -这是一个布尔型数值。 - -1303 -01:05:53,079 --> 01:05:54,845 -So I'm typing its, giving its type. -所以输入它的类型。 - -1304 -01:05:54,847 --> 01:06:01,618 -So here's var name type, and notice, look at this little error right here, 'kay. -命名完变量的名字和类型,注意看这里,有一个小错误标记。 - -1305 -01:06:01,620 --> 01:06:06,222 -Okay, sometimes you're gonna get errors in Swift that are completely incomprehensible -好吧,有时候你用Swift会遇到难以理解的错误。 - -1306 -01:06:06,224 --> 01:06:08,724 -to you because you haven't learned enough of Swift. -但是这是因为你对Swift的了解不够深入。 - -1307 -01:06:08,726 --> 01:06:11,143 -This one's kind of like that. -这个错误就是因为这个。 - -1308 -01:06:11,144 --> 01:06:13,561 -You see, it says, class view controller has no initializers. -你看,这里说类视图控制器没有初始化。 - -1309 -01:06:13,564 --> 01:06:19,667 -And that's because, and pay attention, in Swift all properties -请注意,这是因为,在Swift里 - -1310 -01:06:19,669 --> 01:06:24,271 -have to be initialized when the object is initialized. -一个对象没有初始化,那么对象的属性都不会初始化。 - -1311 -01:06:24,273 --> 01:06:29,142 -Okay, you can't have a property just sitting around not initialized, -所以你不能用没有初始化的属性。 - -1312 -01:06:29,144 --> 01:06:30,977 -they have to have a value. -它们需要一个值。 - -1313 -01:06:30,979 --> 01:06:32,862 -Now if they're an optional, -现在,它们是一个选项。 - -1314 -01:06:32,863 --> 01:06:34,746 -their value can be nil, but they have to have some value. -它们的值可以为空,但是它们必须有值。 - -1315 -01:06:34,749 --> 01:06:37,750 -So we can't have this have no value. -所以我们不能在它们没有值前使用。 - -1316 -01:06:37,752 --> 01:06:40,052 -Now there's two ways to give it a value. -有两种方法给它设值。 - -1317 -01:06:40,054 --> 01:06:42,087 -One is, with an initializer. -一种就是用初始化。 - -1318 -01:06:42,089 --> 01:06:45,156 -Unfortunately, I'm not gonna teach that to you until next week, so -但是不幸的是,这个方法要下周才讲。 - -1319 -01:06:45,158 --> 01:06:46,557 -you can't do it that way. -你还不能用这个方法。 - -1320 -01:06:46,559 --> 01:06:51,228 -Another way is just to say what it equals right here, okay? -所以另外一种方法就是对其直接赋值。 - -1321 -01:06:51,230 --> 01:06:55,298 -And boom, gets rid of all our errors, obviously we don't start out in -一下子, 所有问题都解决了。 - -1322 -01:06:55,300 --> 01:06:59,402 -the middle of typing a number,so we're good to go here, all right. -很明显用户不会从中间输入数字,所以从这一点出发 - -1323 -01:07:01,105 --> 01:07:04,373 -So now we have, we know whether the use is in the middle of typing a number. -现在我们知道了用户是否会从中间输入数字。 - -1324 -01:07:04,375 --> 01:07:06,241 -We can go down here and say if the user, -我们能从这里继续深入,如果说用户 - -1325 -01:07:06,243 --> 01:07:12,246 -now again, I'm just gonna hit Tab to jump past this, maybe a couple times. -按一下Tab,可能要花点时间,找到这个 - -1326 -01:07:12,248 --> 01:07:14,648 -But if the user's in the middle of typing a number, -但是如果用户从中间输入数字。 - -1327 -01:07:14,650 --> 01:07:17,184 -then we'll do what we were doing before. -那就和刚才我们已经做得一样处理。 - -1328 -01:07:17,186 --> 01:07:21,187 -Otherwise, we're just gonna set the display.text equal to the new digit we -另外,如果我们计划设置display.text为一个新的数字 - -1329 -01:07:21,189 --> 01:07:24,557 -just typed, 'kay? -只需要输入这个: - -1330 -01:07:24,558 --> 01:07:27,926 -And we're gonna say that the user is now in the middle of typing a number. -这句表示用户现在在数字的中间输入数字。 - -1331 -01:07:27,928 --> 01:07:30,062 -Question? -什么问题? - -1332 -01:07:30,063 --> 01:07:32,197 -Why would we have to do -[INAUDIBLE] to -display it? - -1333 -01:07:32,199 --> 01:07:34,833 -Initialize? - -1334 -01:07:34,835 --> 01:07:37,669 -Why did we not have to initialize this? -为什么我们部初始化这个? - -1335 -01:07:37,671 --> 01:07:39,988 -That's a fantastic question and -这是个不错的问题 - -1336 -01:07:39,989 --> 01:07:42,306 -I'm gonna talk about that on Wednesday cuz there's only one minute left. -我将在下周三说这个问题,现在只剩下一分钟了。 - -1337 -01:07:42,308 --> 01:07:44,908 -But that is a great question and it'll also, when I talk about it, -在我下次说到的时候,这依然是个很好的问题。 - -1338 -01:07:44,910 --> 01:07:48,679 -I'm gonna tell you why this is an exclamation point and not a question mark. -我说一下为什么这里是个感叹号而不是个问好。 - -1339 -01:07:48,681 --> 01:07:52,548 -Because I told you that optionals are made with question marks. -因为我之前说过选项都是用问号标记的。 - -1340 -01:07:52,550 --> 01:07:55,318 -So why the heck is this optional? -但是为什么这个东西是选项 - -1341 -01:07:55,319 --> 01:07:58,087 -Cuz that's what it is, an exclamation point, so we'll talk about that next time. -因为可是个感叹号,我们下次课再说这个问题。 - -1342 -01:07:58,089 --> 01:08:01,056 -All right, so let's go ahead and run one last time here. -所以让我们下次课继续。 - -1343 -01:08:01,058 --> 01:08:04,793 -And hopefully this is gonna, this 0 will be cleared out, it is and -我们之前希望这个0可以正确的清除掉,看来没问题,看看这个 - -1344 -01:08:04,795 --> 01:08:07,696 -hopefully this will continue to append, it is. -希望这个可以正常的增加,看来也没问题。 - -1345 -01:08:07,698 --> 01:08:11,532 -So we're in a great spot right here, we've got a calculator, -我们今天已经有了一个不错的开始,我们将会做一个计算器。 - -1346 -01:08:11,534 --> 01:08:16,904 -we can enter numbers in it, next step is, we gotta make it do some calculating, and -我们已经能够输入数字了,下一步我们将让其能够计算。 - -1347 -01:08:16,906 --> 01:08:19,406 -we're gonna do that next time so I will see you then. -我们下节课再做,大家下节课见。 - -1348 -01:08:21,042 --> 01:08:24,910 -For more, please visit us at stanford.edu. -想浏览更多?请访问stanford.edu。 diff --git a/2. More Xcode and Swift, MVC.srt b/2. More Xcode and Swift, MVC.srt deleted file mode 100644 index 4c454b7..0000000 --- a/2. More Xcode and Swift, MVC.srt +++ /dev/null @@ -1,8503 +0,0 @@ -1 -00:00:00,001 --> 00:00:04,636 -[MUSIC] - -2 -00:00:04,638 --> 00:00:08,373 -Stanford University.斯坦福大学 - -3 -00:00:08,375 --> 00:00:11,942 ->> All right, well,welcome -to Stanford CS193P,好 欢迎来到斯坦福CS193P - -4 -00:00:11,944 --> 00:00:13,377 -winter of 2015.2015冬季课程 - -5 -00:00:13,379 --> 00:00:14,744 -This is lecture number two.这是我们的第二讲 - -6 -00:00:14,746 --> 00:00:18,581 -I apologize upfront for my -terrible voice, we are going由于我糟糕的嗓音,预先向大家致歉。今天我们将要 - -7 -00:00:18,583 --> 00:00:20,549 -to try to get through this -as best we can today.尽可能去克服这个困难。 - -8 -00:00:22,153 --> 00:00:23,819 -Our topics are two fold.我们的话题有两个方面。 - -9 -00:00:23,821 --> 00:00:25,854 -[COUGH] We're going to -continue the calculator 我们将继续在上一讲中已经开始的计算器Demo, - -10 -00:00:25,856 --> 00:00:29,924 -demo that we started, in last -lecture and then we're gonna然后我们将会有 - -11 -00:00:29,926 --> 00:00:32,526 -have some slides about this -model view controller,一些关于模型视图控制器, - -12 -00:00:32,528 --> 00:00:35,462 -object-oriented design pattern -that we're gonna use in和面向对象设计模式的幻灯片 - -13 -00:00:35,464 --> 00:00:36,797 -everything we do.这种设计模式我们已经广泛的使用。 - -14 -00:00:36,799 --> 00:00:40,066 -When we build applications -in this class.当我们在这节课中开发应用时 - -15 -00:00:40,068 --> 00:00:41,151 -All right?有问题么? - -16 -00:00:41,152 --> 00:00:42,235 -So let's get started -with that demo.没问题就让我开始演示Demo - -17 -00:00:42,237 --> 00:00:44,136 -Again, here's a slide with -the summary of kind of这里是一张总结 - -18 -00:00:44,138 --> 00:00:46,538 -the important things -we're gonna talk about.接下去我们即将要讲的重点的幻灯片 - -19 -00:00:46,540 --> 00:00:48,540 -You don't need to read -those in advance here,你们并不需要提前去阅读这些 - -20 -00:00:48,542 --> 00:00:49,708 -it's more for reference.它便于提供参考。 - -21 -00:00:49,710 --> 00:00:52,410 -My slides in general, -I post them,我做的幻灯片一般来讲, - -22 -00:00:52,412 --> 00:00:55,246 -it's mostly intended to almost -be note taking for you.主要是为了方便你们记笔记用 - -23 -00:00:55,248 --> 00:00:56,580 -To be able go back and try and为了你们在复习的时候能够 - -24 -00:00:56,582 --> 00:00:58,515 -figure out, whoa, when did -he talked about that day?回忆出,哇哦,他什么时候讲过这些? - -25 -00:00:58,517 --> 00:00:59,382 -Oh yeah.哦耶 - -26 -00:00:59,384 --> 00:01:00,983 -What's important, et cetera.什么是重要的,等等。 - -27 -00:01:00,985 --> 00:01:03,419 -So my slides do tend to -be a little bit dense.所以,我的幻灯片也往往是有点多。 - -28 -00:01:03,421 --> 00:01:05,187 -I tend to put a little -more on them, than,我更倾向于多放一些关于这个的内容, - -29 -00:01:05,189 --> 00:01:06,989 -than just bullet items.与项目相比 - -30 -00:01:06,990 --> 00:01:08,790 -But that's because I want you -to be able to look back and但是,那是因为我希望你们能够回过头来看的时候 - -31 -00:01:08,792 --> 00:01:11,726 -kind of get just a little -bit more depth to对于我所说的 - -32 -00:01:11,728 --> 00:01:14,162 -remind yourself what -I talked about.你们更深入的理解 - -33 -00:01:14,164 --> 00:01:15,363 -Okay?ok? - -34 -00:01:15,365 --> 00:01:17,882 -All right, so好了, - -35 -00:01:17,883 --> 00:01:20,400 -this demo, if you'll remember -last time, where we left off,关于这个Demo,如果你们还记得上次我们快结束时, - -36 -00:01:20,403 --> 00:01:23,603 -we had gotten the keypad -fully working.我们已经完全实现了计算器的键盘的功能 - -37 -00:01:23,605 --> 00:01:26,606 -All right, and we were talking -a little bit about properties我们将要讲一些关于属性和 - -38 -00:01:26,608 --> 00:01:28,808 -and instant variables and -how we had to initialize them.实例变量相关的内容,以及如何去初始化它们 - -39 -00:01:28,810 --> 00:01:30,710 -And so I'm gonna ask -a question right at我将会在这讲结束的时候问一个问题 - -40 -00:01:30,712 --> 00:01:33,012 -the end of lecture, -perfect timing.多完美的时机 - -41 -00:01:33,014 --> 00:01:37,248 -What about the little -outlet that we dragged out为什么我们拖出的 - -42 -00:01:37,250 --> 00:01:40,284 -that display UI label -exclamation point, how come we显示UI Lable的outlet后面有个感叹号 - -43 -00:01:40,286 --> 00:01:43,888 -didn't have to make that -equal to something, to start.以及为什么我们从一开始不需要将它赋值 - -44 -00:01:43,890 --> 00:01:46,123 -And that's where this -demo is gonna pick up.我们将从这个地方继续上次的Demo - -45 -00:01:46,125 --> 00:01:46,890 -Okay?OK? - -46 -00:01:46,892 --> 00:01:49,759 ->> Okay.ok - -47 -00:01:49,760 --> 00:01:52,627 -[COUGH] Well, let's dive back -into this demonstration,好吧,让我们深入到演示中来 - -48 -00:01:52,630 --> 00:01:54,647 -where we left off.接着我们上次讲的地方 - -49 -00:01:54,648 --> 00:01:56,665 -Which it was this -line of code, here.上次我们在这行代码结束的 - -50 -00:01:56,668 --> 00:01:59,868 -And, we had just talked about -the fact that we have to我们之前讲过我们必须 - -51 -00:01:59,870 --> 00:02:04,572 -initialize all of our -variables [COUGH] in a class,在类中初始化我们的变量 - -52 -00:02:04,574 --> 00:02:05,807 -in any class.在任何类中都必须这样做 - -53 -00:02:05,809 --> 00:02:09,510 -And, so that's why we need -this equals falls here.所以我们需要在这个加个等号 - -54 -00:02:09,512 --> 00:02:13,747 -They wanted the equal falls -too but we needed it and yet这里也需要等号赋值,但是 - -55 -00:02:13,749 --> 00:02:15,482 -it didn't seem like -we needed one here.这里看起来并不需要等号赋值 - -56 -00:02:15,484 --> 00:02:17,050 -And why was that?为什么会是这样? - -57 -00:02:17,052 --> 00:02:19,085 -Well, it turns out -that this right here,好吧,事实证明,在这里 - -58 -00:02:19,087 --> 00:02:22,254 -even though it doesn't quite -look like one, is an optional.即使它看起来不完全像之前那个,这是一个optional - -59 -00:02:23,490 --> 00:02:28,559 -And, optionals automatically -get equaled nil, given to you.而且optionals在你使用之前就赋了nil - -60 -00:02:29,595 --> 00:02:31,862 -So, you don't actually have -to put the equals nil here.所以,其实你们并不需要在这里给它赋nil - -61 -00:02:31,864 --> 00:02:35,365 -So that's why, so this one -here is getting initialized.这就是为什么这里已经初始化了 - -62 -00:02:35,367 --> 00:02:37,600 -It's just being done -automatically for you.它都自动帮你做好了 - -63 -00:02:37,602 --> 00:02:39,635 -But, let's talk about -the look of this thing.但是,我们来谈论一下这个东西的样子 - -64 -00:02:40,905 --> 00:02:43,772 -It's got this -exclamation point here.在这里有个感叹号 - -65 -00:02:43,774 --> 00:02:45,040 -And, if it were an optional,如果它是一个optional - -66 -00:02:45,042 --> 00:02:47,208 -you'd be used to it -having a question mark.你们通常会在这里看到一个问号 - -67 -00:02:47,210 --> 00:02:49,310 -For example, we look at -this optional right here,例如,我们来看这里这个optional - -68 -00:02:49,312 --> 00:02:51,028 -current title,current title, - -69 -00:02:51,029 --> 00:02:52,745 -you see it's string question -mark not exclamation point,你们将会看到这里string是问号而不是感叹号 - -70 -00:02:52,748 --> 00:02:54,665 -question mark.这里是问号 - -71 -00:02:54,666 --> 00:02:56,583 -So what's the difference -between a question mark and那么,在问号和感叹号之间 - -72 -00:02:56,585 --> 00:02:58,551 -an exclamation point here?有什么区别? - -73 -00:02:58,553 --> 00:03:00,570 -And the answer is,答案是 - -74 -00:03:00,571 --> 00:03:02,588 -it makes no difference to -the actual type, it's still对于实际类型而言它们没有区别, - -75 -00:03:02,590 --> 00:03:05,958 -an optional whose value -here could be a UI label.它仍然是一个optional,其值在这里可能是一个UI label类型。 - -76 -00:03:07,161 --> 00:03:09,761 -But it matters on -the usage of it.但是它的区别在于它的用法上 - -77 -00:03:09,763 --> 00:03:12,597 -[COUGH] And -this is purely just kind of这完全是编译器 - -78 -00:03:12,599 --> 00:03:15,466 -a compiler helping -you out thing, here.帮你把这事做掉了 - -79 -00:03:16,502 --> 00:03:18,602 -But if we look at -when I change this to但是如果我们将这个感叹号 - -80 -00:03:18,604 --> 00:03:21,538 -a question mark you see that -some errors appear down here.改成问号。Xcode将会在这里报出一些错误提示 - -81 -00:03:21,540 --> 00:03:23,940 -So then let's click on one of -these errors, like this one,那么,让我们点击这其中的一个错误提示,比如说这个 - -82 -00:03:23,942 --> 00:03:26,208 -and you can see -the errors that UI label,你们将会看到UI label控件 - -83 -00:03:26,210 --> 00:03:29,244 -question mark does not -have a member named text.问号没有叫text的成员变量 - -84 -00:03:29,246 --> 00:03:31,279 -In other words you -can't send text.换句话说,你不能将text赋给 - -85 -00:03:31,281 --> 00:03:32,580 -UI label question mark,UI label问号 - -86 -00:03:32,582 --> 00:03:35,350 -which is what this is and that -makes sense because UI label因为UI label后面这个问号 - -87 -00:03:35,352 --> 00:03:36,784 -question mark is -an optional and是一个optional,而且 - -88 -00:03:36,786 --> 00:03:39,453 -obviously an optional -doesn't respond to text.很显然这个optional不是回应text的 - -89 -00:03:39,455 --> 00:03:42,889 -UI labels do, but -optionals don't.UI label是这样的,但optional不一定这样 - -90 -00:03:42,891 --> 00:03:44,858 -So, why are we getting -this error now when we那么,为什么我们会这出错 - -91 -00:03:44,860 --> 00:03:46,726 -weren't getting it before.在这之前却没有 - -92 -00:03:46,728 --> 00:03:47,993 -And how would we get -rid of this error?我们又如何去避免这个错误? - -93 -00:03:47,995 --> 00:03:49,461 -Well, you could -certainly get rid of好了,我们当然可以通过 - -94 -00:03:49,463 --> 00:03:51,630 -this error by just putting -an exclamation point here,添加一个感叹号来避免这个错误 - -95 -00:03:51,632 --> 00:03:54,399 -that would unwrap -this optional.它将会去除这个optional - -96 -00:03:54,401 --> 00:03:56,734 -And now this would be -an UI label right here and那么现在这里会变成UI label,而且 - -97 -00:03:56,736 --> 00:03:57,819 -we can send a text.我们可以将text赋值给它 - -98 -00:03:57,820 --> 00:03:58,903 -And we do the same -thing up here.我们在这里也做同样的操作 - -99 -00:03:58,905 --> 00:04:03,073 -We can unwrap it there and -we can unwrap it there.我们可以在这里去除它,也可以在那里去除它 - -100 -00:04:03,075 --> 00:04:05,742 -And that gets rid of -all of our errors.这样一来避免了所有同样的错误 - -101 -00:04:05,744 --> 00:04:09,012 -But [COUGH] this kind of an -interesting property in that但是这里有个很有意思的属性 - -102 -00:04:09,014 --> 00:04:11,213 -even though it's -not initialized in即使它并没有初始化 - -103 -00:04:11,215 --> 00:04:14,450 -the very beginning of -a colossus creation starts out在庞大得创建方法中 - -104 -00:04:14,452 --> 00:04:16,451 -as nil not set.都没有对其赋nil - -105 -00:04:16,453 --> 00:04:21,723 -As soon as as this user -interface gets loaded up只要这个接口被加载了 - -106 -00:04:21,725 --> 00:04:23,891 -by this new controller.通过新的控制器 - -107 -00:04:23,893 --> 00:04:26,794 -Then this gets wired up, -alright, so, that gets那么这个将连接起来,好了,那么那里 - -108 -00:04:26,796 --> 00:04:30,497 -wired up, and this is set, and -then this it's set forever.也将连接起来,只要这里被赋值了,那么所有的这个都被赋值了 - -109 -00:04:30,499 --> 00:04:33,199 -So it's really, kinda would -be sad if we actually,假如这是真的,那么当我们每次在用的时候 - -110 -00:04:33,201 --> 00:04:36,536 -every time we used it had -to unwrap it all the time.我们都将加上感叹号,这真是挺悲伤的 - -111 -00:04:36,538 --> 00:04:38,437 -So these kind of -properties that.所以这些属性 - -112 -00:04:38,439 --> 00:04:42,674 -Get set very early, maybe -not right at creation like很早就被赋值的,不一定像这个一样是正确地创建 - -113 -00:04:42,676 --> 00:04:44,976 -this one, but very, -they get set very early, and但是,绝大部分还是会在创建的时候就赋值 - -114 -00:04:44,978 --> 00:04:46,511 -then they stay -set all the time.然后之后就一直被赋值 - -115 -00:04:47,447 --> 00:04:49,030 -You can, instead of你也可以 - -116 -00:04:49,031 --> 00:04:50,614 -putting a question mark -in their decoration.在声明的地方加一个问号来代替 - -117 -00:04:50,616 --> 00:04:52,683 -We're talking about -their decoration here.我们将在这里谈论他们的声明 - -118 -00:04:52,685 --> 00:04:54,317 -You can put -an exclamation point.你们可以在这里加一个感叹号 - -119 -00:04:54,319 --> 00:04:56,586 -And what that says is.那么它会提示你 - -120 -00:04:56,588 --> 00:04:58,521 -This is just an optional, but这只是一个optional,但是 - -121 -00:04:58,523 --> 00:05:03,625 -always automatically unwrap -it so that you don't have to它会自动解开为了让你不用 - -122 -00:05:03,627 --> 00:05:06,261 -put this exclamation -point in here.在这里加感叹号 - -123 -00:05:06,263 --> 00:05:07,695 -So I take this -exclamation point out.所以,我把这里的感叹号删掉了 - -124 -00:05:07,697 --> 00:05:09,764 -You can see, it's not -generating any errors.你们可以看到,它将不再报错 - -125 -00:05:10,933 --> 00:05:15,735 -And it's still going to -unwrap this display and它将把display转化成 - -126 -00:05:15,737 --> 00:05:17,670 -turn into a UI label.UI label - -127 -00:05:17,672 --> 00:05:18,838 -And.而且 - -128 -00:05:18,840 --> 00:05:21,006 -It's still gonna crash -your program if for它还是会奔溃由于 - -129 -00:05:21,008 --> 00:05:22,307 -some reason -the display were nil.某些原因比如display是nil - -130 -00:05:22,309 --> 00:05:25,110 -If you tried to execute -this code, that may如果你执意要执行这段代码,那是 - -131 -00:05:25,112 --> 00:05:28,146 -be impossible because this -is the button sending those.不可能的,因为这里是由按钮来发送这些的 - -132 -00:05:28,148 --> 00:05:31,716 -So the button wouldn't be here -if this hadn't gotten already这个按钮不会在这里除非它加载的时候 - -133 -00:05:31,718 --> 00:05:33,818 -loaded up in the set.被赋值 - -134 -00:05:33,819 --> 00:05:35,919 -But if somehow you had some -place in your controller or但是如果在某种情况下你必须 - -135 -00:05:35,921 --> 00:05:39,589 -you were accessing display -before this UI got loaded.在UI加载之前你要获取display - -136 -00:05:39,591 --> 00:05:42,158 -It would crash, -because it is unwrapping this,它将奔溃,因为它还没有解开联系 - -137 -00:05:42,160 --> 00:05:44,327 -it's just that you don't have -to put the explanation point,你不需要在这里写感叹号 - -138 -00:05:44,329 --> 00:05:46,629 -it's kinda like auto -explanation point.它会自动解析 - -139 -00:05:46,631 --> 00:05:51,066 -And, this is called a -implicitly unwrapped optional.这个就叫做unwrapped optional - -140 -00:05:51,068 --> 00:05:53,968 -Okay? -Implicitly unwrapped optional.有问题嘛?隐式unwrapped optional - -141 -00:05:53,970 --> 00:05:56,704 -And it's really only useful -for this kind, of property,在这种情况下它真的很有用对于属性来说 - -142 -00:05:56,706 --> 00:06:00,274 -that's, set very early, and -then stay set, forever.在创建的时候就赋值,那么将一直被赋值 - -143 -00:06:00,276 --> 00:06:02,642 -It's kind of sugar, really.这真是一个好的语法糖 - -144 -00:06:04,379 --> 00:06:07,246 -Okay, so let's move on好了,我们将继续 - -145 -00:06:07,248 --> 00:06:11,117 -to the next button in -our [INAUDIBLE] here.接着下一个按钮 - -146 -00:06:11,119 --> 00:06:13,285 -Which is going to -be an enter button.它就是Enter键 - -147 -00:06:13,287 --> 00:06:16,655 -Now our calculator does -not have an equals sign.现在我们的计算器还没有等号 - -148 -00:06:16,657 --> 00:06:18,223 -So you're probably used -to calculators where you你们也许通常会这样使用计算器 - -149 -00:06:18,225 --> 00:06:21,726 -say six plus three then when -you hit equals it shows you6乘以3,然后你们按等号计算器展示 - -150 -00:06:21,728 --> 00:06:23,027 -the result.结果 - -151 -00:06:23,029 --> 00:06:24,912 -This calculator is我们的计算器会 - -152 -00:06:24,913 --> 00:06:26,796 -a little more like -a scientific calculator.更像科学计算器 - -153 -00:06:26,799 --> 00:06:27,564 -Has an enter key.将没有等号按钮 - -154 -00:06:27,566 --> 00:06:31,668 -And so, instead you put -the numbers you want to add or那么,你们按你们想相加的数字按钮或者 - -155 -00:06:31,670 --> 00:06:35,671 -divide or multiply or whatever -onto a stack and then when you除以或者乘以无论什么都将会入栈,然后当你 - -156 -00:06:35,673 --> 00:06:38,440 -press the operation keys it -pulls them off the stack.按下操作按钮的时候,数字将会出栈 - -157 -00:06:38,442 --> 00:06:43,011 -So that looks like this, -6 enter 3 times.比如这样 6 乘以 3 - -158 -00:06:43,013 --> 00:06:45,279 -Four, six, enter, -three, enter, times.46 乘以 3 - -159 -00:06:45,281 --> 00:06:48,449 -So the times is going -to pull the six and这个乘法操作符将会把6 和 - -160 -00:06:48,451 --> 00:06:50,735 -the three off the stack.3 出栈 - -161 -00:06:50,736 --> 00:06:53,020 -You could even go six, enter, -five, enter, four, enter, and你也可以按6,?,5, ?4?然后 - -162 -00:06:53,022 --> 00:06:54,521 -then go times plus.按乘以 - -163 -00:06:55,590 --> 00:06:58,624 -That would multiply the top -two on the stack and它将会把栈顶的两个元素出栈 - -164 -00:06:58,626 --> 00:07:00,893 -then add the last one on.操作完再将加上栈顶的元素 - -165 -00:07:01,829 --> 00:07:04,629 -So we need an enter key -here for our calculator.所以我们的计算器还是需要一个Enter键 - -166 -00:07:04,631 --> 00:07:06,798 -Now, I'm gonna create that -enter key in a way that's 现在,我将要通过这种方式创建一个enter键 - -167 -00:07:06,800 --> 00:07:09,367 -actually gonna cause a problem -for me in a moment, but它虽然会引起一些问题,但是 - -168 -00:07:09,369 --> 00:07:12,370 -I wanna show you how to -resolve that very problem.我将会展示给你们看如何解决这些问题 - -169 -00:07:12,372 --> 00:07:16,039 -So I'm gonna create this enter -key by copying and pasting.那么,我将通过复制粘贴 - -170 -00:07:16,041 --> 00:07:18,608 -This digit key right here.这里的数字键来创建Enter键 - -171 -00:07:18,610 --> 00:07:19,475 -And I'm just gonna -put it in here.那么我将会把这段代码放在这里 - -172 -00:07:19,477 --> 00:07:20,743 -Notice that I'm lining these,注意我要粘贴在这里 - -173 -00:07:22,113 --> 00:07:23,745 -blue lines up -absolutely perfectly.蓝色的辅助线出现最好 - -174 -00:07:23,747 --> 00:07:27,315 -I don't want them to be, like -it's lined up with that one,我不想这些按钮像这个一样 - -175 -00:07:27,317 --> 00:07:28,750 -but not that one or -vice versa.或者那个一样 - -176 -00:07:28,752 --> 00:07:30,685 -I want them -perfectly lined up.我希望它完全对齐 - -177 -00:07:30,687 --> 00:07:33,520 -Cuz later I'm gonna spread -these out over the whole UI因为我待会要在整个UI中放大这些按钮 - -178 -00:07:33,522 --> 00:07:37,057 -and if I haven't lined these -up just absolutely perfectly如果我没有将这些按钮对齐的话 - -179 -00:07:37,059 --> 00:07:39,693 -then Expo's not gonna quite -know what I want here inXcode将不会知道我想把它放在这里 - -180 -00:07:39,695 --> 00:07:41,828 -terms of the relationship -between these.在这个和这个之间 - -181 -00:07:43,264 --> 00:07:46,999 -All right so we don't want a -three on here, we want to have好了,我们不希望这个按钮上还是3,所以我们需要修改一下 - -182 -00:07:47,001 --> 00:07:52,237 -a,enter symbol so I'm gonna go -up here to special characters.一个enter的符号,我将输入一个特殊的符号 - -183 -00:07:52,239 --> 00:07:54,505 -This is on in most -Mac applications.这个符号在很多的Mac应用中都有 - -184 -00:07:54,507 --> 00:07:57,174 -You can go to the edit menu -to get special characters.你们可以从编辑菜单中获取这些特殊符号 - -185 -00:07:57,176 --> 00:07:58,342 -And I'm going to search for我想要搜索 - -186 -00:07:58,344 --> 00:08:00,510 -this one actually, I think -that's called a return.这个特殊符号,我觉得它应该叫返回 - -187 -00:08:00,512 --> 00:08:01,945 -Yeah. -And these are just是的,这些都是 - -188 -00:08:01,947 --> 00:08:04,614 -Unicode characters right here.Unicode字符 - -189 -00:08:04,616 --> 00:08:06,615 -And so -I want this one that looks,我想要这个 - -190 -00:08:06,617 --> 00:08:09,551 -kind of like a return or -enter key.看起来像返回或者enter按钮的 - -191 -00:08:10,487 --> 00:08:11,686 -So I have this.好了,我找到了 - -192 -00:08:11,688 --> 00:08:13,721 -And I'm gonna use the same -mechanism we used before,我将使用之前使用过的机制 - -193 -00:08:13,723 --> 00:08:14,822 -which is CTRL+drag.那就是CTRL+drag - -194 -00:08:14,824 --> 00:08:18,958 -So I'm just gonna -CTRL+drag out here.那么我想CTRL+drag拖到这里 - -195 -00:08:18,960 --> 00:08:21,027 -And, we're creating an action,然后,我们创建一个action - -196 -00:08:21,029 --> 00:08:24,196 -of course, cuz we want this -button to send us a message.当然,我们希望这个按钮传递给我们一个信息 - -197 -00:08:24,198 --> 00:08:25,431 -I'm gonna call it Enter.我讲叫它Enter - -198 -00:08:26,700 --> 00:08:28,333 -That's what it is -the answer key那就是我们的返回键. - -199 -00:08:28,335 --> 00:08:30,134 -Now one thing is -different about this one,现在有一件事会有一点不同 - -200 -00:08:30,136 --> 00:08:32,470 -if you'll remember when -we wired this action up,如果你记得当我们连接这个action的时候 - -201 -00:08:32,472 --> 00:08:35,906 -we had the button that was -sending it as an argument and我们让这个按钮传递给我们一个参数 - -202 -00:08:35,908 --> 00:08:37,441 -we don't want that this time.但是我们这次不需要这么做 - -203 -00:08:37,443 --> 00:08:38,808 -Because there's only -one answer key we因为这里只有一个返回键 - -204 -00:08:38,810 --> 00:08:40,977 -really don't need to talk -back to the answer key, so我们并不需要让返回键传参,所以 - -205 -00:08:40,979 --> 00:08:42,712 -we're going to say -none right here.我们在这里不需要参数 - -206 -00:08:42,714 --> 00:08:45,714 -It also doesn't really matter -about this type because we're这里我们更不用关心它的类型,因为 - -207 -00:08:45,716 --> 00:08:46,948 -not going to have -an argument so我们这里并不需要参数 - -208 -00:08:46,950 --> 00:08:48,750 -it doesn't matter -what this type is.不用管它这里是什么类型 - -209 -00:08:48,752 --> 00:08:49,717 -So disconnect that.那么先断开他们的连接 - -210 -00:08:49,719 --> 00:08:51,686 -As you can see right here.你们可以看这里 - -211 -00:08:51,688 --> 00:08:54,154 -We have Enter, and -it has no arguments.我们已经有一个enter键,没有参数的 - -212 -00:08:55,691 --> 00:08:57,690 -Now, what are we gonna -do inside Enter?那么现在,我们将在这个Enter里做什么操作? - -213 -00:08:57,692 --> 00:08:59,558 -Well, the main thing -we need to do is,好吧,我们主要要做的是 - -214 -00:08:59,560 --> 00:09:03,228 -put whatever number is -in this display up here,把所有的数字在这里加起来 - -215 -00:09:03,230 --> 00:09:05,697 -okay, onto our internal stack.ok.在我们的栈中 - -216 -00:09:05,699 --> 00:09:06,931 -So, we're gonna need那么,我们需要 - -217 -00:09:06,933 --> 00:09:09,367 -an internal stack, -in a moment, here.一个暂时的栈 - -218 -00:09:09,369 --> 00:09:10,868 -Another thing we -might wanna do, is.另一件我们想做的事 - -219 -00:09:11,904 --> 00:09:14,604 -Set users in the middle of -typing the number to false.设置用户中间操作数字这个参数为false - -220 -00:09:14,606 --> 00:09:17,507 -Because we might have -been typing a number, but因为我们可能已近输入了一个数字 - -221 -00:09:17,509 --> 00:09:20,343 -as soon as we hit enter, -we're putting it on the stack.但是,只要我们单击enter键,我们将把数字放入栈中 - -222 -00:09:20,345 --> 00:09:21,977 -Next time we type a digit,接下来我们再输入一个数字 - -223 -00:09:21,979 --> 00:09:23,846 -we're going to be -starting a new number.我们将输入一个新的数字 - -224 -00:09:23,848 --> 00:09:27,182 -[COUGH] All right, so we'll -call that user [NOISE] in好了,那么我们就叫它 输入好了 - -225 -00:09:27,184 --> 00:09:29,451 -the middle of -typing falls there.中间输入那里 - -226 -00:09:29,453 --> 00:09:32,387 -Now, let's go ahead and, -and actually run this and现在,让我们继续,运行这个 - -227 -00:09:32,389 --> 00:09:33,788 -see how this is working.看看它是怎么工作的 - -228 -00:09:33,790 --> 00:09:37,991 -Because there's going to -be a little problem here.因为这里有个小问题 - -229 -00:09:37,993 --> 00:09:44,197 -So, run this.那么,先运行一下 - -230 -00:09:44,199 --> 00:09:47,499 -Alright, so -let's try eight, enter.好了,让我们试一下输入8,然后enter - -231 -00:09:47,501 --> 00:09:48,367 -Oh.Oh - -232 -00:09:48,369 --> 00:09:50,001 -What's that? -Oh, my god.那是什么?上帝啊 - -233 -00:09:50,003 --> 00:09:52,337 -Six, enter.6,然后 enter键 - -234 -00:09:52,338 --> 00:09:54,672 -Well it's, it's kind of -working because after we好吧,它能运行因为我们 - -235 -00:09:54,674 --> 00:09:57,241 -press enter the user is in -the middle of typing numbers.按了enter键,the user is in the middle of typing numbers参数 - -236 -00:09:57,243 --> 00:09:59,160 -Starts over.重新开始 - -237 -00:09:59,161 --> 00:10:01,078 -So that's good, but -I had no intention for所以这是好的,但是我并不想 - -238 -00:10:01,080 --> 00:10:03,380 -this to be showing up on -the end of my display.让这个在最后显示出来 - -239 -00:10:03,382 --> 00:10:05,115 -This little enter.这个enter - -240 -00:10:05,117 --> 00:10:06,749 -What the heck is -that doing on there?这个heck是做什么的? - -241 -00:10:06,751 --> 00:10:07,783 -Why is that happening?为什么会发生这样的事 - -242 -00:10:09,086 --> 00:10:09,951 -Let's take a look here.让我们看看这里 - -243 -00:10:11,988 --> 00:10:15,023 -The problem here, has to do -with the messages being sent.问题出在这里,在信息传递之前 - -244 -00:10:15,025 --> 00:10:17,358 -So, when we wire this up, -that's good.那么,当我们连接好了,它就好了 - -245 -00:10:17,360 --> 00:10:20,161 -We got enter.我们已经有enter键了 - -246 -00:10:20,162 --> 00:10:22,963 -The problem is that button -also sends a pen digit.问题是那个按钮还传递数字 - -247 -00:10:22,965 --> 00:10:25,598 -That's because we copied and -pasted this three, remember?那是因为我们复制粘贴的3的按钮,记得么? - -248 -00:10:25,600 --> 00:10:28,735 -And the three sends a pen -digit, until we copy and而3按钮还传递了一个数字,直到我们复制 - -249 -00:10:28,737 --> 00:10:29,903 -paste it.粘贴了它 - -250 -00:10:29,904 --> 00:10:31,070 -Now, this one sends, -sends a pen digit.现在 ,这个按钮传递了一个数字 - -251 -00:10:31,072 --> 00:10:32,805 -So this is both.而且这个也是 - -252 -00:10:32,807 --> 00:10:34,874 -Okay, sending two.ok,传递了两次 - -253 -00:10:34,875 --> 00:10:36,942 -Now, that's a common -mistake to make.现在,这是一个很常见的错误 - -254 -00:10:36,944 --> 00:10:39,744 -You know, you only think -about that when you copy and你们知道么,你们不会去想这些当你们复制 - -255 -00:10:39,746 --> 00:10:41,145 -paste it.粘贴它 - -256 -00:10:41,147 --> 00:10:42,947 -And how do we fix this?那么我们如何来修复这个问题? - -257 -00:10:42,949 --> 00:10:44,348 -Well if you right click, so好了,如果你们右击一下 - -258 -00:10:44,350 --> 00:10:46,717 -I'm going to right -click on this button.我将右键一下这个按钮 - -259 -00:10:46,719 --> 00:10:48,885 -You'll get this -window that comes up.你们将会看到这个窗口 - -260 -00:10:48,887 --> 00:10:51,687 -And it shows you all -the connections from this然后你们可以看到所有的连接 - -261 -00:10:52,723 --> 00:10:54,189 -UY element to your code.UY元素到你们的代码 - -262 -00:10:54,191 --> 00:10:57,025 -And you can see here -both appendage and你们可以看到这里都连接 - -263 -00:10:57,027 --> 00:10:58,826 -enter are connected.enter键 - -264 -00:10:58,828 --> 00:11:01,562 -The great thing is I can just -click this little X right here最棒的事我可以点击这里的X按钮 - -265 -00:11:01,564 --> 00:11:03,530 -and it'll take this -connection away.然后这个连接就被取消了 - -266 -00:11:04,666 --> 00:11:06,232 -So now I only have enter.那么,现在我们只有enter键的连接了 - -267 -00:11:06,234 --> 00:11:08,101 -So now if I go back here.那么现在我们再回到之前的地方 - -268 -00:11:08,103 --> 00:11:09,853 -See it's,看这里 - -269 -00:11:09,854 --> 00:11:11,604 -it's not sending appendage, -it is sending enter.它将不再传递附加物,它只传递enter - -270 -00:11:11,606 --> 00:11:14,440 -And you can do this right -clicking for anything.你们可以右键操作任何你们想做的 - -271 -00:11:14,442 --> 00:11:16,608 -Like we need to do it for -our label up here.就像我们必须连接label一样 - -272 -00:11:16,610 --> 00:11:21,112 -See there's the display -connection we have right here.看到没,这里显示了我们的连接 - -273 -00:11:21,114 --> 00:11:24,448 -So don't forget right click -to disconnect things.不要忘记右键去除连接 - -274 -00:11:24,450 --> 00:11:27,918 -Now if you forget about -this and you don't do it.现在,如果你们忘记这个,你们不要去操作它 - -275 -00:11:27,920 --> 00:11:32,455 -Or maybe you have it wired to -some thing that you change.否则你们会连接一些你们修改的东西 - -276 -00:11:32,457 --> 00:11:35,391 -For example, if we have -accidentally put an argument比如,我们需要传递一个参数 - -277 -00:11:35,393 --> 00:11:40,062 -here to enter, if we had made -it do descending button trick,对于enter键来说,如果我们已经做过了 - -278 -00:11:40,064 --> 00:11:42,064 -kind of like this.像这样的 - -279 -00:11:42,066 --> 00:11:44,432 -You can't just say, oh okay.你们不能说好的 - -280 -00:11:44,434 --> 00:11:45,066 -I'll fix that.我将会修复它的 - -281 -00:11:45,068 --> 00:11:46,667 -I'll just delete that我将会删除它的. - -282 -00:11:46,669 --> 00:11:49,136 -Because that would -not work because,因为它将会不工作 - -283 -00:11:49,138 --> 00:11:52,072 -enter with an argument -is actually a different因为带有参数的enter键它是不同的 - -284 -00:11:52,074 --> 00:11:54,774 -message than enter -with no argument.对于没参数的enter键来说 - -285 -00:11:54,776 --> 00:11:57,510 -And so, if you just deleted -that when you were running如果你们在运行的时候删除了这些 - -286 -00:11:57,512 --> 00:11:58,978 -your program it -would crash and你的应用将会奔溃 - -287 -00:11:58,980 --> 00:12:02,581 -it would say, couldn't -send message enter colon.它会说,enter不能传递参数 - -288 -00:12:02,583 --> 00:12:05,150 -When you touch this button -cause enter colon means enter当你点击enter键的时候 - -289 -00:12:05,152 --> 00:12:08,853 -with an argument, only for the -purpose of this tour It doe-, - -290 -00:12:08,855 --> 00:12:10,655 -we don't see enter -colon in our code.我们看不到enter的代码 - -291 -00:12:10,657 --> 00:12:12,656 -That's just something that's, -this story board here.还好这里有story board - -292 -00:12:13,793 --> 00:12:17,661 -So if that happens, you need -to right click on here and那么如果这个发生了,你必须点击这里 - -293 -00:12:17,663 --> 00:12:21,431 -disconnect the enter colon, -that happened in there and去除连接,然后再重新 - -294 -00:12:21,433 --> 00:12:23,566 -then you just recontrol drag.拖拉连接 - -295 -00:12:23,568 --> 00:12:25,834 -When you recontrol -drag it's nice it will.当你重新连接好,它会变正常了 - -296 -00:12:25,836 --> 00:12:28,103 -Kind of let you try to -grab onto something, so让你们尝试一下 - -297 -00:12:28,105 --> 00:12:32,373 -its easy to reconnect.它很容易重新连接。 - -298 -00:12:32,375 --> 00:12:35,293 -Kay?OK? - -299 -00:12:35,294 --> 00:12:38,212 -All right, so now we want to -actually implement enter here.好了,那么现在我们在这里实现这个方法 - -300 -00:12:38,214 --> 00:12:41,248 - We want to enter - the guts of it. - 我们开始着手实现它的内部。 - -301 -00:12:41,250 --> 00:12:44,150 - And so we are going to need - another property here which is - 我们需要在这定义另一个属性, - -302 -00:12:44,152 --> 00:12:45,702 - going to be that - 它将会是 - -303 -00:12:45,703 --> 00:12:47,253 - internal stack that these - numbers are going to go on. - 这些数字的内部栈。 - - -304 -00:12:47,255 --> 00:12:52,057 - And so that's gonna - be a var just like - 所以它会是一个变量,就像 - -305 -00:12:52,059 --> 00:12:54,393 - this var up here that - we've created and - 我们刚创建的这个变量。 - -306 -00:12:54,395 --> 00:12:57,562 - I'm call it operand stack - that's a good name for it. - 我叫它操作符栈,不错的名字。 - - -307 -00:12:57,564 --> 00:12:58,730 - And it's gonna have a type, - 它会有一个类型, - - -308 -00:12:58,732 --> 00:13:02,233 - it's type is going - to be an array and - 它的类型是数组, - -309 -00:13:02,235 --> 00:13:05,869 - just like in other languages - like Java when you specify, - 就像在其他语言中,比如说Java—— - -310 -00:13:05,871 --> 00:13:08,805 - when you create an array - type you have to specify. - 当你创建一个数组,你必须指明它的类型, - -311 -00:13:08,807 --> 00:13:10,840 - What kind of thing - is in the array. - 表明数组里面存储的是什么。 - -312 -00:13:10,842 --> 00:13:15,211 - And so, I'm gonna put - doubles in my array. - 因此,我打算在里面存放double元素 - -313 -00:13:17,214 --> 00:13:20,782 - And that's, even though you - might say, well we can't - 嗯。也许你会说,好吧我们并不能 - -314 -00:13:20,784 --> 00:13:25,286 - enter doubles, because these - are all integers, basically. - 输入double,因为这里大都是些integer。 - -315 -00:13:25,288 --> 00:13:29,723 - But if I were to say, - 3 enter 6 divide, I get .5. - 但是假如我说,输入3除以6,我会得到0.5, - -316 -00:13:29,725 --> 00:13:31,925 - So than a double would appear. - 这样就出现了一个double。 - -317 -00:13:31,927 --> 00:13:34,661 - So that's why I'm - going to use double. - 这就是我为什么要使用double。 - -318 -00:13:34,663 --> 00:13:38,964 - Now, you can see that we've - got this error up here again. - 现在,你们可以看到这里又弹出了这个错误, - -319 -00:13:38,966 --> 00:13:41,133 - It says stored property - operandStack does not - 上面说存储的属性operandStack并没有 - -320 -00:13:41,135 --> 00:13:43,368 - have initial value. - 初始值。 - -321 -00:13:43,370 --> 00:13:45,036 - So we have to give - this an initial value. - 所以我们得赋给它初始值。 - -322 -00:13:45,038 --> 00:13:47,071 - So I'm going to give - this an initial value of - 我准备把初始值赋为 - -323 -00:13:47,073 --> 00:13:48,472 - an empty array. - 一个空的数组。 - -324 -00:13:48,474 --> 00:13:51,608 - So now you're seeing for the - first time how you actually. - 现在你们第一次看到实际上如何 - -325 -00:13:51,610 --> 00:13:57,480 - Create an instance of - a class or of a data type. - 创建一个类或者数据类型的实例。 - -326 -00:13:57,482 --> 00:14:00,249 - And you do that just by - specifying the type and - 你只需要在这指明类型 - -327 -00:14:00,251 --> 00:14:01,984 - then use parenthesis. - 然后写上分号。 - -328 -00:14:01,986 --> 00:14:03,752 - Now, we're not, - 现在,我们没有, - -329 -00:14:03,754 --> 00:14:05,554 - again we haven't talked - about initializers. - 我们还没有讨论过构造器。 - -330 -00:14:05,556 --> 00:14:06,888 - A class or - 一个类或者 - -331 -00:14:06,890 --> 00:14:09,390 - a data structure can have - multiple initializers. - 一种数据类型可以有许多构造器。 - -332 -00:14:09,392 --> 00:14:11,158 - Some of them might - have arguments in here. - 其中的一些可能会在这里有参数。 - -333 -00:14:12,128 --> 00:14:16,863 - But most, if it's possible - they'll allow you to - 但大多数情况,如果允许,你都可以 - -334 -00:14:16,865 --> 00:14:21,133 - create them with no - arguments and in a case on - 创建没有参数的构造器,对于 - -335 -00:14:21,135 --> 00:14:22,835 - our right(!!array,我听的是这个,请校验) it's very - obvious what to do. - 数组,该做什么一目了然。 - -336 -00:14:22,837 --> 00:14:25,103 - No arguments just creates - an empty array right, - 不需要参数,只要创建一个空的数组,在右边 - -337 -00:14:25,105 --> 00:14:27,739 - with no elements in it. - 这里不需要任何参数。 - -338 -00:14:27,741 --> 00:14:31,142 - Now, one thing I want to talk - about is this right here. - 现在,我想说一下这里这个东西, - -339 -00:14:31,144 --> 00:14:32,376 - This type, you know? - 这种类型,你们知道吗, - -340 -00:14:32,378 --> 00:14:34,078 - It's kind of annoying that - we have to type this and - 你会觉得很烦,如果在这定义了类型, - -341 -00:14:34,080 --> 00:14:36,147 - then we have to type - it right again. - 然后在这又得定义一遍。 - -342 -00:14:36,148 --> 00:14:38,215 - And the answer is, - we don't have to do that, - 而事实上,我们并不需要这么做, - - -343 -00:14:38,217 --> 00:14:41,051 - because in swift, - swift is very strongly typed. - 因为swift是严格强类型的。 - -344 -00:14:41,053 --> 00:14:43,252 - You know there's all - the variables, but - 你要知道所有的变量, - -345 -00:14:43,254 --> 00:14:45,221 - the properties - are strongly typed. - 属性都是强类型的。 - -346 -00:14:45,223 --> 00:14:48,724 - But they, there's also - a lot of type inference. - 而且它们都有许多类型推断。 - -347 -00:14:48,726 --> 00:14:50,625 - So swift can infer.(此处应该没有句号,this type应该在这里) - 因此swift可以推断类型。 - -348 -00:14:50,627 --> 00:14:53,995 - This type in the exact same - way that digit had no type and - 比如说这里的digit并没有类型, - -349 -00:14:53,997 --> 00:14:55,596 - it inferred it from here. - 但它可以从这里推断出来。 - -350 -00:14:55,598 --> 00:14:58,366 - OperandStack, we don't have - to specify they type, and - OperandStack,我们并不需要指明它的类型,因为 - -351 -00:14:58,368 --> 00:14:59,633 - it can infer it from here. - 可以从这里推断出来。 - -352 -00:14:59,635 --> 00:15:02,302 - And if we option click on - operandStack you'll see that - 如果我们按住option点击operandStack,你会看到 - -353 -00:15:02,304 --> 00:15:05,271 - indeed, it's figured out that - that's an array of double. - 它确实可以辨识出这是一个double类型的数组。 - -354 -00:15:05,273 --> 00:15:07,824 - And in fact, - 事实上, - -355 -00:15:07,825 --> 00:15:10,376 - putting the type in here - is considered bad form. - 在这里指明类型被认为是不好的书写形式。 - -356 -00:15:10,378 --> 00:15:14,080 - If it can be inferred, - you should let it infer, so, - 如果可以推断出类型,你就应该让它自己去推断,所以 - -357 -00:15:14,082 --> 00:15:16,915 - if we didn't have this blue(for example,而且明明是bool!英文是机器录入的么) up - here we shouldn't that either, - 拿这里的Bool来说,我们其实也需要声明类型。 - -358 -00:15:16,917 --> 00:15:21,419 - because, false, and true are, - can only be blue values so,(bool!!!) - 因为false和true只可能是Bool的值。 - -359 -00:15:21,421 --> 00:15:22,887 - we're gonna take - that off as well. - 所以我们也可以把它去掉。 - -360 -00:15:22,889 --> 00:15:28,025 - Okay, so, now, our brand(operand好伐,我真是醉了,好累) - 好了,那么现在,我们这里有操作符栈, - -361 -00:15:28,027 --> 00:15:30,994 - stack right here what - do we wanna do with it? - 我们打算把怎么处理它呢? - -362 -00:15:30,996 --> 00:15:34,597 - Well, when we press enter, - we just want to append. - 嗯,我们按下回车,然后我们想要append, - -363 -00:15:34,599 --> 00:15:35,798 - So, append. - 所以,append。 - -364 -00:15:35,800 --> 00:15:39,034 - This is actually the first - time we're sending an actual - 事实上这是我们第一次发送一条 - -365 -00:15:39,036 --> 00:15:41,703 - message to an object - looks just like when we - 消息给一个对象。就像去 - -366 -00:15:41,705 --> 00:15:43,738 - accessed a property. - 获取了一个属性一样。 - -367 -00:15:43,740 --> 00:15:47,375 - The dot and it's just the name - of the method that we're - 输入点号,然后就出现了我们想要在数组上调用的方法名字。 - -368 -00:15:47,377 --> 00:15:49,110 - trying to invoke - in our arrays. - -369 -00:15:49,112 --> 00:15:51,478 - Just an array, an array method - right here called a pen(append!!). - 这是一个数组;这是一个叫做append的数组方法。 - -370 -00:15:51,480 --> 00:15:54,414 - I think you see the arguments - as newElement: T. - 我想你们看到了这个参数——newElement: T - -371 -00:15:54,416 --> 00:15:57,517 - This : T means it has - to be of this type. - 这个 : T 意味着它必须是这个类型。 - -372 -00:15:57,519 --> 00:16:00,853 - Type of things in the array so - this has to be a double. - 这个数组里面东西的类型,所以它必须是一个double。 - -373 -00:16:00,855 --> 00:16:04,223 - So that's kind of a problem, - cuz really what I want to - 这也是一个问题,因为事实上我想要在 - -374 -00:16:04,225 --> 00:16:08,060 - append onto my stack is what's - up here in this display text. - 我的栈上附加的是,这里display text的内容。 - -375 -00:16:08,062 --> 00:16:11,830 - And, you know, I'd like to - say something along the lines - 然后在这行输入display.text - -376 -00:16:11,832 --> 00:16:13,164 - of display.text. - - -377 -00:16:13,166 --> 00:16:15,099 - Okay? - But what type is this? - 好吧,它的类型是什么呢? - -378 -00:16:15,101 --> 00:16:16,767 - I can type display.text.(type of display.text??) - display.text的类型。 - -379 -00:16:18,437 --> 00:16:19,936 - Now that's not string. - 它不是string。 - -380 -00:16:19,938 --> 00:16:22,205 - That is an optional. - 它是一个optional。 - -381 -00:16:22,207 --> 00:16:24,874 - Remember that display.text - is an optional. - 记住这里的display.text是一个optional, - -382 -00:16:24,876 --> 00:16:28,043 - So we can unwrap - it even though - 所以我们可以把它拆包,但 - -383 -00:16:28,045 --> 00:16:29,911 - that's not gonna - solve the problem. - 这并不能解决问题。 - -384 -00:16:29,913 --> 00:16:31,212 - This is still a string and - 这仍是一个string, - -385 -00:16:31,214 --> 00:16:33,381 - you're still seeing - an error here. - 你们还是可以看到这里有一个错误。 - -386 -00:16:33,383 --> 00:16:36,217 - The same string is not - convertible to double [COUGH]. - 这个string不可以转化为double[咳]。 - -387 -00:16:36,219 --> 00:16:37,651 - Because we're supposed - to be putting doubles in - 因为我们本应把double放入 - -388 -00:16:37,653 --> 00:16:39,086 - this array putting strings. - 这个数组而不是string。 - -389 -00:16:39,088 --> 00:16:40,987 - So, we have a problem here. - 所以,我们在这有个问题。 - -390 -00:16:40,989 --> 00:16:44,323 - We have somehow to convert - this string into a double so - 我们得用某种方式把string转化成double以便 - -391 -00:16:44,325 --> 00:16:45,358 - we can put it on this stack. - 我们把它放入栈中。 - -392 -00:16:46,394 --> 00:16:48,994 - I'm gonna use - this opportunity. - 我要借用这个机会, - -393 -00:16:48,996 --> 00:16:51,129 - Just show you another - feature which we - 向你们展示另一个特性,我们 - -394 -00:16:51,131 --> 00:16:52,930 - call Computed Properties. - 称之为计算型属性。 - - -395 -00:16:52,932 --> 00:16:56,000 - So I'm gonna create another - property display value and - 所以我要在这里创建另一个属性displayValue, - -396 -00:16:56,002 --> 00:16:57,401 - it's gonna be a double. - 它是一个double。 - -397 -00:16:57,403 --> 00:17:00,671 - And what I want this to be - equal to is, I always want it - 然后我想让它等于,我想让它 - -398 -00:17:00,673 --> 00:17:03,773 - to be whatever's in this - display converted to a double. - 等于这里的显示转化成double的值。 - -399 -00:17:04,742 --> 00:17:05,786 - Okay? - And I want to - 好了,然后我想 - -400 -00:17:05,787 --> 00:17:06,831 - be able to set it or get it so - 有办法对它进行设值以及取值,以便 - -401 -00:17:06,832 --> 00:17:07,876 - I'm gonna be able to get - the value of this double. - 我能够取到这个double的值。 - -402 -00:17:07,878 --> 00:17:10,112 - I just want to be able to - set it as a double and - 我想把它设值成一个double然后 - -403 -00:17:10,114 --> 00:17:11,413 - have it turn into text. - 把它转化成文本。 - -404 -00:17:13,016 --> 00:17:15,616 - Well, that kind of - 好吧,这种类型的 - -405 -00:17:15,618 --> 00:17:19,886 - property really is tied to - some data somewhere else. - 属性实际上是与其他地方的某些数据绑定的。 - -406 -00:17:19,888 --> 00:17:22,756 - So, I don't ever want to set - it equal to some initial value - 所以,我不想把它设成某个初始值 - -407 -00:17:22,758 --> 00:17:25,125 - or something. - 还是什么。 - -408 -00:17:25,126 --> 00:17:27,493 - Really, I want it to always be - calculated and we can do that. - 实际上,我想让它总是可计算的,而我们可以做到。 - -409 -00:17:27,495 --> 00:17:29,295 - Instead of saying - equals something, - 与其说等于什么, - -410 -00:17:29,297 --> 00:17:32,364 - you just put curly - braces after. - 你只需要在后面写上大括号。 - -411 -00:17:32,366 --> 00:17:37,168 - And you say, get, - and we say, set. - 然后写下get,再写set。 - -412 -00:17:37,170 --> 00:17:39,871 - Okay? - 好了。 - -413 -00:17:39,872 --> 00:17:42,573 - And inside here we are gonna - compute the value of this. - 然后在这里面,我们要对它的值进行计算了。 - -414 -00:17:42,575 --> 00:17:46,010 - Which is we are gonna - convert this display text - 这将会把这里的显示文本转化成 - -415 -00:17:46,012 --> 00:17:49,479 - to a double and then inside - here, we are, someone said, - double,然后在这里,我们要,要让 - -416 -00:17:49,481 --> 00:17:52,449 - display value equal something - and we are going to - 显示值等于什么,我们要做的是 - -417 -00:17:52,451 --> 00:17:55,251 - somehow compute, - not really compute it, but. - 想办法能够计算它,并不是真的去计算“它”,而是 - -418 -00:17:55,253 --> 00:17:58,854 - We're gonna de, decide, - what code we need to put that - 我们要决定我们需要什么样的代码能够把 - -419 -00:17:58,856 --> 00:18:02,024 - number that they tried to set - the display value to in here. - 那个显示值在这里设值。 - -420 -00:18:03,126 --> 00:18:05,393 - 'Kay, so - let's do the set side first. - 好吧,那么让我们先来写set方法。 - -421 -00:18:05,395 --> 00:18:07,695 - It's actually - a little simpler. - 这其实会简单一些。 - -422 -00:18:07,697 --> 00:18:08,929 - Inside this set, - 在set方法里, - -423 -00:18:08,931 --> 00:18:11,231 - there's a magic variable - called new value. - 会有一个叫作newValue的魔法变量, - -424 -00:18:12,300 --> 00:18:14,901 - It doesn't, it's not purple - for some reason, but. - 它不是,因为某些原因它并不是紫色的 - -425 -00:18:14,903 --> 00:18:16,235 - New value in this, - this is the new value. - 这里的newValue。 - -426 -00:18:16,237 --> 00:18:17,903 - So if someone says - somewhere in our code, - 如果说在我们的代码里, - -427 -00:18:17,905 --> 00:18:19,338 - display value equals five, - 显示值等于5, - -428 -00:18:19,340 --> 00:18:21,306 - this new value will - have the five. - 那这个newValue就会是5。 - -429 -00:18:22,442 --> 00:18:23,541 - And so all I really wanna do。 - 我所想做的 - -430 -00:18:23,543 --> 00:18:26,276 - here is say display text - equals the new value. - 就是在这让display.text等于newValue。 - -431 -00:18:26,278 --> 00:18:30,480 - But again, of course this - is an optional string. - 但同样的问题,这是个optional string, - -432 -00:18:30,482 --> 00:18:33,216 - You can't set it to a double - because displayValue equals - 你不能把它设成一个double因为displayValue等于 - -433 -00:18:33,218 --> 00:18:36,419 - five, this new values - going to be a double. - 5,这个newValue将会是一个double。 - -434 -00:18:36,421 --> 00:18:41,557 - But we know how to convert - something to a string by - 但是我们知道如何把它转化成string,只需要写上 - -435 -00:18:41,559 --> 00:18:45,260 - using backlash parenthesis. - 反斜线,圆括号。 - -436 -00:18:45,262 --> 00:18:48,129 - And this is the same - thing we did when we - 这其实和我们 - -437 -00:18:48,131 --> 00:18:51,399 - printed out [COUGH] - our digit up here. - 输出[咳]这里digit是一样的。 - -438 -00:18:51,401 --> 00:18:53,501 - We just use the back - slash parenthesis. - 我们只需要写上反斜线和圆括号。 - -439 -00:18:53,503 --> 00:18:55,336 - It tries to convert - this thing inside here, - 它会试着在这里转化这个东西, - -440 -00:18:55,338 --> 00:18:57,938 - which is a double into - a string of doubles. - 把一个double转化成string。 - -441 -00:18:57,940 --> 00:19:00,540 - You know how to do - that themselves. - 你知道该怎么做了。 - -442 -00:19:00,542 --> 00:19:02,575 - And so bingo, - we've got our display text and - 没错。我们得到了display.text, - -443 -00:19:02,577 --> 00:19:04,477 - that's all that necessary. - 这就够了。 - -444 -00:19:04,479 --> 00:19:07,479 - also, every time someone sets - this value and then we're - 而且,每次有人设值时,很明显我们 - -445 -00:19:07,481 --> 00:19:10,282 - clearly not in the middle - of typing a number anymore. - 不再是在输入一个数字了。 - -446 -00:19:10,284 --> 00:19:14,085 - [INAUDIBLE] Say that. - 说。 - -447 -00:19:14,087 --> 00:19:17,221 - [INAUDIBLE] All right, - what about the getting? - 好吧,那关于取值呢? - -448 -00:19:17,223 --> 00:19:19,290 - Now in the getting - all we have to do is - 在取值方法中,我们所要做的就是 - -449 -00:19:19,292 --> 00:19:21,258 - return this display value. - 返回displayValue。 - -450 -00:19:21,260 --> 00:19:24,161 - So it's do something - to calculate what this - 就是要去计算 - -451 -00:19:24,163 --> 00:19:26,363 - display value is here. - 这里的displayValue。 - -452 -00:19:27,399 --> 00:19:29,215 - And then return it. - 然后返回它。 - -453 -00:19:29,216 --> 00:19:31,032 - Now this one I'm not - gonna take time to go - 这次我不会花时间去 - -454 -00:19:31,035 --> 00:19:32,801 - through the details here. - 详细说明细节。 - -455 -00:19:32,803 --> 00:19:37,205 - And actually I've made it an - extra credit item that you can - 实际上我把它算作一个给你们去做的额外加分项, - -456 -00:19:37,207 --> 00:19:40,008 - do, which requires - you to figure out - 需要你们利用文档,去搞清楚我要在这写什么, - -457 -00:19:40,010 --> 00:19:44,345 - what I'm gonna type here - using the documentation. - - -458 -00:19:44,347 --> 00:19:45,879 - But I'm not going - to explain it here. - 而我不会在这解释它。 - -459 -00:19:45,881 --> 00:19:49,382 - I'm gonna use a class that's - in this number formatter. - 我要在这个使用一个叫作NumberFormatter的类 - -460 -00:19:49,384 --> 00:19:52,051 - I'm actually gonna - create one and - 我先创建一个,然后 - -461 -00:19:52,053 --> 00:19:56,822 - I'm gonna use a method on it - called number from string. - 我要使用它的一个方法叫numberFromString。 - -462 -00:19:57,858 --> 00:19:59,624 - And I'm gonna give it - this string which is - 然后我会把这个string传给他, - - -463 -00:19:59,626 --> 00:20:02,593 - the display values text, - unwrapped of course. - display.text,当然得拆包。 - - -464 -00:20:03,596 --> 00:20:06,497 - The result is acting optional - so I'm gonna unwrap that. - 结果是一个optional,所以我要把它拆包。 - -465 -00:20:06,499 --> 00:20:09,499 - And then I'm gonna get the - double value of the thing I - 然后我要得到它返回的的double值。 - - -466 -00:20:09,501 --> 00:20:11,067 - get back [COUGH]. - [咳] - -467 -00:20:11,068 --> 00:20:12,634 - Number gives me this - kind of generic number so - Number给了我这种泛型的数字,所以 - -468 -00:20:12,637 --> 00:20:14,637 - I am gonna take it and - turn it into a double. - 我把它转化成一个double。 - -469 -00:20:14,639 --> 00:20:15,738 - So there we go. - 好了。 - -470 -00:20:15,739 --> 00:20:16,838 - So you can go - the next spread and - 你们可以继续下一步了, - -471 -00:20:16,841 --> 00:20:18,374 - look at that later - if you want. - 以后再考虑它,如果你想的话。 - -472 -00:20:19,410 --> 00:20:20,959 - But surprising to say we - 高兴的是我们 - - -473 -00:20:20,960 --> 00:20:22,509 - now have a property display - value that when we set it and - 现在有了一个displayValue的属性,我们可以调用set和 - -474 -00:20:22,512 --> 00:20:24,579 - get it, it's gonna be - setting and getting. - get方法来设值和取值。 - -475 -00:20:24,581 --> 00:20:27,415 - It has a string here, so - that is really convenient. - 这里有一个string,所以它也挺方便的。 - -476 -00:20:27,417 --> 00:20:29,400 - Especially for - 尤其是这里, - -477 -00:20:29,401 --> 00:20:31,384 - right here, where we - wanna say display value. - 其实我们想写的是displayValue - -478 -00:20:31,387 --> 00:20:32,285 - 'Kay? - 好。 - -479 -00:20:32,287 --> 00:20:33,953 - So let's see the double. - 让我们来看看这个double - -480 -00:20:33,955 --> 00:20:34,987 - No problem. - 没错。 - -481 -00:20:34,989 --> 00:20:37,256 - We're pinning that - onto operandStack. - 我们把它附到operandStack上了。 - -482 -00:20:37,258 --> 00:20:40,058 - So let's print in our - operandStack here. - 所以让我们把operandStack在这打印出来。 - -483 -00:20:42,362 --> 00:20:45,162 - Just so, I mean we can do the - same thing here, operandStack. - 就像这样,一样的方式,operandStack。 - -484 -00:20:46,632 --> 00:20:48,649 - Okay? - - -485 -00:20:48,650 --> 00:20:50,667 - And this worked because - operandStack is an array, and - 这种方式可行是因为operandStack是一个数组, - -486 -00:20:50,669 --> 00:20:53,636 - arrays know how to turn - themselves into strings. - 数组是知道如何把他们自身转化成string的。 - -487 -00:20:53,638 --> 00:20:55,938 - You'll see how they do that in - the console in a moment here. - 你一会儿就会在console里看到它们是怎么做到的了。 - -488 -00:20:56,874 --> 00:20:58,040 - So let's go ahead and - 所以我们继续 - -489 -00:20:58,042 --> 00:21:00,842 - see if our application is - actually putting things on - 来看看我们的程序是否真的正确地能够把东西放到 - -490 -00:21:00,844 --> 00:21:02,343 - our stack properly here. - 我们的栈里。 - -491 -00:21:04,547 --> 00:21:14,054 - [NOISE] - All right. - 好的。 - -492 -00:21:14,056 --> 00:21:14,854 - Let's try here. - 我们试着在这里, - -493 -00:21:14,856 --> 00:21:18,591 - Let's try 56 enter. - 在这里输入56, - -494 -00:21:18,593 --> 00:21:21,761 - And look, operandStack - equals 56 doing good. - 看,operandStack是等于56,运行正常。 - -495 -00:21:21,763 --> 00:21:23,128 - Seven enter. - 输入7, - -496 -00:21:23,130 --> 00:21:24,429 - All right, 56.0 and 7.0. - 好的,56.0和7.0。 - -497 -00:21:24,431 --> 00:21:27,699 - So, you can see that arrays - turn themselves into strings - 所以你们看到了数组是如何把自身转化成string的, - -498 -00:21:27,701 --> 00:21:30,735 - by doing open square bracket - and then they turn each of - 在这个方括号里,它们把自身的每个 - -499 -00:21:30,737 --> 00:21:33,937 - their elements into strings - and separated by commas. - 元素转化成string并以逗号分隔。 - -500 -00:21:35,507 --> 00:21:37,207 - Now this is good. - 这个就搞定了。 - -501 -00:21:37,209 --> 00:21:39,642 - So we got our operand, - operandStack building here. - 我们这的operandStack就创建好了。 - - -502 -00:21:41,179 --> 00:21:44,713 - So all we need to do is have - some times, and plus, and - 所以我们现在需要做的就是要有乘法,加法和 - -503 -00:21:44,715 --> 00:21:45,947 - minus buttons, et cetera. - 减法之类的按钮。 - -504 -00:21:45,949 --> 00:21:47,549 - I'm gonna put them right here. - 我要把他们放在这里。 - -505 -00:21:47,551 --> 00:21:50,385 - That will operate on these - items uh,on the stack. - 它在在这些项上进行运算,在栈上。 - -506 -00:21:50,387 --> 00:21:52,119 - So, if I pressed - plus right now, - 所以,如果我现在按下加, - -507 -00:21:52,121 --> 00:21:55,122 - it would pull the seven and - the eight off the stack. - 它就会把7和8从栈中拉出来, - -508 -00:21:55,124 --> 00:21:57,057 - Add them together, - it would be 15. - 把他们相加,得到15。 - -509 -00:21:57,059 --> 00:21:58,758 - Show that 15 here, and - 在这里显示15, - -510 -00:21:58,760 --> 00:22:00,560 - it actually will put - the 15 back on the stack. - 实际上15会被放回到栈里。 - -511 -00:22:00,562 --> 00:22:03,696 - So then, we'd have 56 and - 15 on our stack. - 然后,我们的栈里就有了56和15。 - -512 -00:22:03,698 --> 00:22:04,863 - Then we could, maybe. - 接着我们就可以, - -513 -00:22:04,865 --> 00:22:08,400 - Plus those together and - we wanted by it plus again. - 把它们加到一起,再运行一次加法。 - -514 -00:22:08,402 --> 00:22:08,933 - All right? - 没错吧? - -515 -00:22:08,935 --> 00:22:12,036 - [COUGH] Okay. - 好的。 - -516 -00:22:12,038 --> 00:22:15,539 - So how are we gonna do that? - 所以我们应该怎么做呢? - -517 -00:22:15,541 --> 00:22:17,040 - Well, we would make - our buttons here. - 嗯,我们把按钮放到这。 - -518 -00:22:17,042 --> 00:22:22,245 - And I'm gonna make the buttons - again by copying and - 我通过复制粘贴数字按钮来创建这些按钮。 - -519 -00:22:22,247 --> 00:22:24,580 - pasting a digit button. - -520 -00:22:24,582 --> 00:22:26,648 - But this time I know - about that problem, - 但是这次我已经知道那个问题了, - -521 -00:22:26,650 --> 00:22:29,584 - so right off the bat I'm - gonna right click on it. - 所以马上就点击它。 - -522 -00:22:29,586 --> 00:22:31,353 - And disconnect appendage it.(appendDigit。。。) - 然后取消和appendDigit的关联。 - -523 -00:22:31,355 --> 00:22:34,472 - Okay? - So - 好的,那么 - -524 -00:22:34,473 --> 00:22:37,590 - now this button sends no - messages, yet anyway. - 这个按钮现在就不会发送任何消息了。 - -525 -00:22:37,593 --> 00:22:40,461 - And then we could - put a type on here. - 然后我们要在这上面设置一个符号。 - -526 -00:22:40,463 --> 00:22:44,331 - So here I'm gonna have my all - my operations buttons use - 这里我要让所有的运算按钮使用 - -527 -00:22:44,333 --> 00:22:47,000 - mathematical symbols so if we - go down here to math symbols. - 数学符号,所以我们看这里的math symbols。 - -528 -00:22:47,002 --> 00:22:49,936 - See there's a bunch - of math symbols here. - 看这里有好多数学符号。 - -529 -00:22:49,938 --> 00:22:51,737 - So let's do times, right here, - 我们来给乘法设置符号,就在这里。 - -530 -00:22:51,739 --> 00:22:56,775 - first, we'll put times right - there, and we can wire it up. - 首先,把乘法放到这,然后我们可以把他嵌入代码。 - -531 -00:22:56,777 --> 00:22:59,511 - I'm just gonna hold that - Ctrl and drag out here. - 按住Ctrl然后拉到这里来。 - -532 -00:23:00,580 --> 00:23:03,881 - We're gonna call - this action method. - 我们把这个action称作方法 - -533 -00:23:03,883 --> 00:23:05,549 - Operate. - operate。 - -534 -00:23:05,551 --> 00:23:09,052 - And because I'm gonna have - multiple operation buttons and - 因为会有许多运算按钮,而且 - -535 -00:23:09,054 --> 00:23:11,588 - they're all going - to send operate. - 他们都会发送operate。 - -536 -00:23:11,590 --> 00:23:13,289 - Just like I did - with append digit, - 就像附加digit一样, - -537 -00:23:13,291 --> 00:23:14,457 - I am going to use the sender. - 我要使用这个sender, - -538 -00:23:14,459 --> 00:23:18,193 - So I'm gonna be very - careful to change this any - 所以我得仔细地 - -539 -00:23:18,195 --> 00:23:19,661 - object to be button. - 把这个按钮上的anyObject改称UIButton。 - -540 -00:23:20,697 --> 00:23:22,129 - Do not forget that. - 不要忘记这点。 - -541 -00:23:22,131 --> 00:23:24,965 - 'Kay, so action, - we are gonna have it centered.(set sender!!) - 好了,action,设置好的sender。 - -542 -00:23:24,967 --> 00:23:25,932 - UIButton. - UIButton。 - -543 -00:23:25,934 --> 00:23:26,666 - Call it operate. - operate。 - -544 -00:23:27,669 --> 00:23:28,868 - There it is. - 就是这样。 - -545 -00:23:28,870 --> 00:23:30,269 - That's method doing operate. - 这就是operate方法。 - -546 -00:23:31,338 --> 00:23:33,438 - We can copy and - paste this button now, right? - 我们现在可以复制粘贴按钮了。 - -547 -00:23:33,440 --> 00:23:34,639 - We got this one, so - 我们用这个, - -548 -00:23:34,641 --> 00:23:37,775 - let's copy and paste and - make some more of these. - 让我们复制粘贴然后重复。 - -549 -00:23:37,777 --> 00:23:41,778 - We'll start out with - four of them, let's say. - 我们先搞出4个。 - -550 -00:23:41,780 --> 00:23:43,680 - 'Kay? - 好。 - -551 -00:23:43,681 --> 00:23:45,581 - Let's get back our - special characters here. - 我们回到特殊符号这里。 - -552 -00:23:45,584 --> 00:23:51,087 - [COUGH] All right, so - let's make this one be divide. - [咳]好的,我们来把它做成除法。 - -553 -00:23:51,089 --> 00:23:53,522 - Let's make this one plus. - 我们把这个做成加法。 - -554 -00:23:53,524 --> 00:23:55,924 - And this one be minus. - 这个是减法。 - -555 -00:23:55,926 --> 00:23:58,660 - All right. - 好了。 - -556 -00:23:58,662 --> 00:24:00,461 - So we've got these - buttons [COUGH]. - 按钮就完成了。 - -557 -00:24:00,463 --> 00:24:02,930 - And they're all sending, - if we look at this here, - 它们都会发送,如果我们看这里, - -558 -00:24:02,932 --> 00:24:04,598 - they're all sending operate. - 它们都会发送operate。 - -559 -00:24:05,701 --> 00:24:08,535 - Luckily, they're not sending - anything except operate, so - 幸运的是它们并不会发送运算之外的东西, - -560 -00:24:08,537 --> 00:24:09,869 - that's good. - 这样刚好。 - -561 -00:24:09,871 --> 00:24:12,905 - And when they send operate, - we're gonna figure out - 当他们发送operate的时候,我们要搞清楚 - -562 -00:24:12,907 --> 00:24:15,808 - which one is sending it by the - same exact way we did above. - 哪个是按照我们之前的方式去发送的。 - -563 -00:24:15,810 --> 00:24:18,543 - We're gonna say what is - the sender's current title? - sender的currentTitle是什么? - -564 -00:24:18,545 --> 00:24:20,111 - We're gonna unwrap it. - 我们要把它拆包。 - -565 -00:24:20,113 --> 00:24:24,582 - So operation here is - gonna be a string. - 这里的operation是一个string。 - -566 -00:24:24,584 --> 00:24:28,418 - And it's going to tell us - the title of the buttons so - 它会告诉我们按钮的title,所以 - -567 -00:24:28,420 --> 00:24:31,721 - we know which one - to use there. - 我们就知道了该用哪个。 - -568 -00:24:31,723 --> 00:24:35,758 - Now I'm gonna show you a - control flow operator here in - 现在我要给你们展示swfit中的控制流符号, - -569 -00:24:35,760 --> 00:24:39,128 - Swift that's very powerful, - much more powerful than - 它非常强大,比其他语言中的强大多了。 - -570 -00:24:39,130 --> 00:24:41,463 - this operator is in - other languages. - - -571 -00:24:41,465 --> 00:24:43,432 - And also very, - very important to switch.(swift) - 而且对Swfit来说很重要。 - -572 -00:24:43,434 --> 00:24:46,401 - I'm only gonna show you the - simplest usage of it here, but - 这里我只会向你们展示它的最简单用法,但是 - -573 -00:24:46,403 --> 00:24:49,170 - you're gonna see on - Monday's demonstration and - 你们会在周一的展示和 - - -574 -00:24:49,172 --> 00:24:51,906 - later in the quarter how - important this operator is. - 接下来的一个季度感受到它的强大。 - -575 -00:24:51,908 --> 00:24:54,541 - But, it's switch, okay, and - 它是就switch,而且 - -576 -00:24:54,543 --> 00:24:59,846 - switch looks like switch - in other languages, like C. - 它和其他语言中的switch看起来很像,比如C。 - -577 -00:24:59,848 --> 00:25:01,080 - You switch on something. - 你在某种东西上switch。 - -578 -00:25:01,082 --> 00:25:03,015 - In this case I'm gonna - switch on this string. - 这里我会在string上switch。 - -579 -00:25:03,017 --> 00:25:04,483 - This is the string. - 这就是那个string, - -580 -00:25:04,485 --> 00:25:06,852 - Then you just specify - the case of each thing. - 然后你要指明所有case。 - -581 -00:25:06,854 --> 00:25:10,822 - So for - example here I have a case. - 所以举例来说,有一个case, - -582 -00:25:10,824 --> 00:25:17,561 - Let's do the multiply. - 进行乘法, - -583 -00:25:17,563 --> 00:25:21,031 - Okay, so we've got - multiply case right here. - 这就是一个乘法case, - -584 -00:25:21,033 --> 00:25:24,234 - And then we just put - the code that we want here - 接着我们把需要的代码放到这里, - -585 -00:25:24,236 --> 00:25:26,203 - for multiply. - 做乘法。 - -586 -00:25:26,204 --> 00:25:28,171 - And we'd do that for - all the other cases here. - 接着对其他的case也这么做。 - -587 -00:25:28,173 --> 00:25:30,439 - So let's copy and paste. - 复制然后粘贴。 - -588 -00:25:30,441 --> 00:25:36,478 - And we'll do this - be our divide case. - 这个是除法case, - -589 -00:25:36,480 --> 00:25:39,347 - And we'll have this - be our plus case and - 这个是加法case, - -590 -00:25:39,349 --> 00:25:41,215 - we'll have this be our, - 这个是, - -591 -00:25:41,217 --> 00:25:45,753 - make sure we're doing the same - [INAUDIBLE] here, plus case. - 要确保方式一致,加法 - -592 -00:25:47,923 --> 00:25:49,689 - Again, you've got to be - a little careful here. - 这里你们又得仔细一点了, - -593 -00:25:49,691 --> 00:25:51,858 - You know, this minus is - slightly different from this - 这里的减法符号是和 - -594 -00:25:51,860 --> 00:25:54,593 - minus which might be slightly - different than the minus - 这个减法符号和 - -595 -00:25:54,595 --> 00:25:55,828 - you type with the keyboard. - 你们键盘上输入的减法符号是有一些不同的。 - -596 -00:25:55,830 --> 00:25:59,164 - So, when you're putting - the symbols here, - 所以,当你们在这放置这个符号的时候, - -597 -00:25:59,166 --> 00:26:03,434 - you wanna use exactly the same - symbols here in your case. - 你们要确定使用的是同一个符号。 - -598 -00:26:03,436 --> 00:26:06,871 - Now, one thing about Switch - on Swift though is it - 关于Swift的Switch的要注意的一件事就是 - -599 -00:26:06,873 --> 00:26:11,274 - absolutely requires that you - have every case covered. - 你必须确保覆盖所有情况。 - -600 -00:26:11,276 --> 00:26:13,877 - Now since this is a string, - obviously can't have case of - 由于这是一个字符串,显然不可能 - -601 -00:26:13,879 --> 00:26:15,345 - every single string - in the universe. - 穷举每一种情况 -602 -00:26:15,347 --> 00:26:18,280 - That is almost infinite, - but luckily there, - 通常是无限多的,但是很幸运的是, -603 -00:26:18,282 --> 00:26:22,584 - you can take defaults and - just break out of the switch. - 可以再default后,使用break跳出switch -604 -00:26:22,586 --> 00:26:26,187 - That means if it's not one of - these cases by default just - 也就是如果不是上面列举的情况, -605 -00:26:26,189 --> 00:26:27,088 - break out of the switch. - 就会默认跳出switch语句 -606 -00:26:27,090 --> 00:26:28,355 - You could put code - here as well, - 代码也可以放在这里 -607 -00:26:28,357 --> 00:26:31,091 - but breaking out of it is - what we wanna do in our case. - 在需要的地方break -608 -00:26:33,028 --> 00:26:35,861 - now, in here, we're just going - to put the code for multiply. - 现在,在这里,放乘法相关的语句 -609 -00:26:35,863 --> 00:26:37,896 - So, what do we need to do for - multiply? - 那么,乘法需要做些什么? -610 -00:26:37,898 --> 00:26:40,432 - For the moment, - I'm gonna comment this out. - 我会暂时将这部分注视掉 -611 -00:26:40,434 --> 00:26:42,667 - I'm gonna use command, slash, - 使用command + / 来注释 -612 -00:26:42,669 --> 00:26:44,502 - which is a really - nice feature. - 这种注释方法的确称得上是一个很不错的功能. -613 -00:26:44,504 --> 00:26:46,103 - You do command slash. - command + /之后, -614 -00:26:46,105 --> 00:26:48,238 - And then command slash again, - to uncomment. - 再次command + /来取消给代码注释. -615 -00:26:48,240 --> 00:26:55,311 - [INAUDIBLE] real quick cuz I - just wanna focus on times. - 这样就可以专注于当前的事情上, -616 -00:26:55,313 --> 00:26:58,247 - Now any time I - press any operator, - 任何时候,点击任何操作符, -617 -00:26:58,249 --> 00:27:02,317 - I probably wanna give - the user an automatic enter. - 可能会给用户自动按下enter键 -618 -00:27:02,319 --> 00:27:05,087 - That's so that six enter, - three enter, - 也就是6,enter,3,enter -619 -00:27:05,089 --> 00:27:07,989 - times is the same as - six enter three times. - 乘,和6乘以3一样 -620 -00:27:09,392 --> 00:27:12,393 - Okay, so six enter three times - is gonna do an automatic enter - 好了,6 enter 3 乘 会自动来一个enter -621 -00:27:12,395 --> 00:27:13,927 - on that three. - 在那个3之上 - -622 -00:27:14,996 --> 00:27:16,596 - Cuz obviously, - I intend to have six and - 显然,在这种情况下,我想让6和 -623 -00:27:16,598 --> 00:27:18,998 - three be multiplied - in that case. - 3相乘 -624 -00:27:19,000 --> 00:27:26,705 - So for all of these - operations, I going to say, - 对于所有的操作符,我要说的是 -625 -00:27:26,707 --> 00:27:29,708 - if the users in the middle - of typing a number. - 如果用户在中间输入一个数字, - -626 -00:27:29,710 --> 00:27:32,443 - Then hit enter for - me, right here. - 然后点击enter键. - -627 -00:27:32,445 --> 00:27:36,347 - Okay, so [COUGH] what - do we need to do in - 好了,我们需要 -628 -00:27:36,349 --> 00:27:39,516 - this specific case of times? - 在乘这里做什么? - - -629 -00:27:39,518 --> 00:27:42,886 - Well, really we just want - to set our display value. - 我们需要在这里显示计算的结果. -630 -00:27:42,888 --> 00:27:46,856 - Remember we have our nice - display value down here. - 记住,我们有自己的显示值的方法. -631 -00:27:46,858 --> 00:27:49,492 - And we can do setting - as well as getting. - 我们可以进行赋值,也可以进行取值 -632 -00:27:49,494 --> 00:27:52,094 - So I set that display value. - 因此,在这里赋值. -633 -00:27:52,096 --> 00:27:55,264 - Up here. - 这里. -634 -00:27:55,265 --> 00:27:58,433 - Equal to multiplying the top - two things on this stack. - 等于将栈顶的两个数相乘 -635 -00:27:58,435 --> 00:28:02,270 - So I can actually remove - something off our stack. - 因此,我可以从栈里移除一些元素. -636 -00:28:02,272 --> 00:28:04,705 - We're representing our - stack as an array. - 我们使用一个数组带代表栈结构. -637 -00:28:05,941 --> 00:28:07,908 - Of course, - they are stacked as an array. - 当然了,确实是使用一个数组来表示的栈. -638 -00:28:07,910 --> 00:28:11,311 - And so a stack is something - you push things on, - 栈是一个可以压入元素到栈离, -639 -00:28:11,313 --> 00:28:12,979 - you pop things off. - 可以从栈里弹出元素 -640 -00:28:12,981 --> 00:28:15,614 - And with an array, we're just - gonna add something there at - 使用数组的话,只要 -641 -00:28:15,616 --> 00:28:17,082 - the end to push something on, - and - 在数组的末尾添加一个元素来模拟元素入栈 -642 -00:28:17,084 --> 00:28:19,317 - that will just remove it - from the end to pop it off. - 在数组的末尾移除一个元素来模拟元素出栈 -643 -00:28:19,319 --> 00:28:21,653 - So there's a nice. - 这种模拟看起来很酷吧. -644 -00:28:21,655 --> 00:28:23,654 - All right. - This is an array, right? - 好了,这是一个数组,是么? -645 -00:28:23,656 --> 00:28:26,007 - Operand stacks. - 操作符栈. -646 -00:28:26,008 --> 00:28:28,359 - There's a nice method - called remove last. - 有个很好使的方法叫做:移除最后一个元素 -647 -00:28:28,361 --> 00:28:30,894 - And if we option click on - remove last, you'll see here - 如果在removelast方法上按住option键, -648 -00:28:30,896 --> 00:28:33,430 - that it removes an element - from the end of the array. - 可以看到说明:从数组的末尾移除一个元素 -649 -00:28:34,666 --> 00:28:37,567 - Now, it does require - a count greater than zero. - 需要数组的元素个数大于零. -650 -00:28:37,569 --> 00:28:42,705 - So if our array were empty - this would crash our program. - 如果数组是空的话,移除元素会导致程序崩溃 -651 -00:28:42,707 --> 00:28:44,840 - So let's put a little - protective thing here. - 所以,在这里做一些保护性的措施. -652 -00:28:44,842 --> 00:28:47,742 - If the operand stacks. - 如果操作符栈 -653 -00:28:47,744 --> 00:28:50,411 - There's a nice property - here called Count on that. - 操作符栈变量有一个属性叫做Count -654 -00:28:50,413 --> 00:28:52,947 - It is greater or - 如果大于或者 -655 -00:28:52,948 --> 00:28:55,482 - equal to two actually because - multiply takes two operand so - 等于2,因为乘法需要2个操作数 -656 -00:28:55,485 --> 00:28:57,484 - there better two - things on this stack. - 所以至少需要栈中有2个元素 -657 -00:28:58,921 --> 00:29:01,121 - Then we can do this and so - 然后,我们可以这样做, -658 -00:29:01,123 --> 00:29:05,324 - we're gonna multiply that - by and remove the next one. - 相乘,然后移除最后一个元素 -659 -00:29:05,326 --> 00:29:06,125 - Okay? - 对么? -660 -00:29:06,127 --> 00:29:07,259 - So here we got- - 这样的话, -661 -00:29:09,062 --> 00:29:12,463 - We're just taking the last two - things off of this stack by - 我们从栈中移除最后两个元素, -662 -00:29:12,465 --> 00:29:14,832 - removing them from - the end of the array and - 通过从数组中移除元素 -663 -00:29:14,834 --> 00:29:17,334 - just assigning it - to display value. - 赋值给displayValue变量 -664 -00:29:17,336 --> 00:29:19,469 - And we probably also - want to do an enter here, - 这里可能需要做一个enter, -665 -00:29:19,471 --> 00:29:22,539 - because [COUGH] if I go - six enter three times, - 如果单击6 enter 3 乘, -666 -00:29:22,541 --> 00:29:25,108 - well then I want to be able - to say then nine plus and - 这样就得到9加 -667 -00:29:25,110 --> 00:29:28,744 - have it add onto - the six times three. - 然后加上6乘以3 -668 -00:29:29,713 --> 00:29:32,213 - So we want an automatic - enter here, as well. - 这里需要一个自动点击enter, -669 -00:29:32,215 --> 00:29:34,149 - Okay? - 是么? -670 -00:29:34,150 --> 00:29:36,084 - So, that's pretty much - all we need to do here. - 这大概就是我们需要在这里做的了. -671 -00:29:36,086 --> 00:29:41,021 - Let's go ahead and run this, - see how this works. - 继续,运行这个程序,看它是怎么工作的, -672 -00:29:43,826 --> 00:29:47,527 - And so, six enter, or - three enter, six enter. - 6 确认 或者 3 确认 6 确认 -673 -00:29:47,529 --> 00:29:49,996 - Now we've got them - both on the stack. - 可以在栈上看到它们 -674 -00:29:49,998 --> 00:29:52,898 - Times and you can see - we put our 18 here. - 相乘,然后可以看到结果是18 -675 -00:29:52,900 --> 00:29:55,668 - It also put it back - on the stack and - 结果也被放入的栈中, -676 -00:29:55,670 --> 00:29:57,536 - we can say five times. - 比如,5 乘 -677 -00:29:57,538 --> 00:29:59,237 - That put a five - on the stack and - 将5放入栈中, -678 -00:29:59,239 --> 00:30:01,372 - then multiplied them, - took it off. - 将它们相乘,从栈中移除, -679 -00:30:01,374 --> 00:30:03,107 - So that's working nicely. - 程序运行的不错啊 -680 -00:30:03,109 --> 00:30:05,576 - [COUGH] Now what about our- - 现在, -681 -00:30:05,578 --> 00:30:06,743 - Other buttons, here. - 这里,我们的其他的按钮, -682 -00:30:06,745 --> 00:30:08,745 - We gonna make those work. - 我们要让它们工作. -683 -00:30:08,747 --> 00:30:12,548 - Let's do that. - 让我们完成这个工作. -684 -00:30:12,550 --> 00:30:16,152 - Now, they do a very - similar thing, here. - 它们需要完成十分相似的事情, -685 -00:30:16,154 --> 00:30:20,088 - So, one temptation would - be to just copy here. - 所以,来复制下这部分, -686 -00:30:20,090 --> 00:30:22,657 - Let's uncomment these out. - 打开这部分的注释, -687 -00:30:23,693 --> 00:30:25,459 - And then just paste it, - repeatedly. - 然后粘贴到这里,重复粘贴, -688 -00:30:25,461 --> 00:30:26,827 - So, put it there. - 放到这里. -689 -00:30:27,996 --> 00:30:31,831 - There, there and then just - changes times in here. - 只需要更改这里的乘号. -690 -00:30:31,833 --> 00:30:35,868 - D note to plus for - example on this one. - 这个换成一个加号, -691 -00:30:35,870 --> 00:30:39,038 - But his is pretty messy code, - look at all this - 但是,这样的代码看起来很乱, -692 -00:30:39,040 --> 00:30:42,841 - incredible amount of - duplicating code, in here. - 这里有大量的重复的代码, -693 -00:30:42,843 --> 00:30:47,145 - We really probably wouldn't - to write our code like this. - 我们确实不希望我们的代码写成这样. -694 -00:30:47,147 --> 00:30:49,780 - People would think we were - terrible programmers I - 别人会认为我们是很糟糕的程序员 -695 -00:30:49,782 --> 00:30:51,482 - think if we did that. - 如果我们像这样写代码的话. -696 -00:30:51,484 --> 00:30:54,251 - Really what would be - nice is if we had some, - 什么样的代码看起来会不错呢? -697 -00:30:54,253 --> 00:30:56,453 - could write some - kind of function. - 那就是如果我们可以把这些重复的代码写成函数 -698 -00:30:56,455 --> 00:31:00,990 - Maybe we could call it - perform operation or - 我们可能会给这个函数起名perfomOperation -699 -00:31:00,992 --> 00:31:02,458 - something like that. - 或者类似意思的名字. -700 -00:31:02,460 --> 00:31:05,927 - And if the argument - to that function. - 至于函数的参数, -701 -00:31:05,929 --> 00:31:08,196 - Remember that - arguments have names. - 注意,函数参数也是又名字的, -702 -00:31:08,198 --> 00:31:09,163 - Here's the name. - 这就是名字. -703 -00:31:09,165 --> 00:31:10,364 - And then we have the type. - 然后是参数类型. -704 -00:31:11,434 --> 00:31:16,269 - The argument were something - which basically was this - 这里的参数就是 -705 -00:31:16,271 --> 00:31:19,305 - little operation in here, or - 这里的操作符, -706 -00:31:19,307 --> 00:31:21,707 - some sort of function that - would do this operation. - 这就是完成操作符操作的函数. -707 -00:31:21,709 --> 00:31:24,576 - So if this could be some - sort of function that - 如果可以写成函数的话, -708 -00:31:24,578 --> 00:31:25,277 - would be cool. - 看起来就不错了. -709 -00:31:25,279 --> 00:31:27,078 - Then, maybe we could. - 然后,我们可能会, -710 -00:31:27,080 --> 00:31:28,880 - I take this code out of here, - put it in here. - 将这段代码移动到这里, -711 -00:31:30,149 --> 00:31:34,384 - Let's call it perform not - pre-form, perform operation. - 起码为perform,而不是pre-form -712 -00:31:34,386 --> 00:31:36,353 - [LAUGH] Put it in here and - 放在这里. -713 -00:31:36,355 --> 00:31:38,921 - instead of doing, - you know, multiply here. - 你懂的,这里不是使用乘. -714 -00:31:38,923 --> 00:31:41,190 - Let's go ahead and we can - do this operation some how. - 继续,完成这个操作. -715 -00:31:41,192 --> 00:31:42,891 - I guess, well maybe operation, - 可能是operation函数, -716 -00:31:42,893 --> 00:31:48,196 - call it like a function - with two arguments here. - 像一个带两个参数的函数一样调用. -717 -00:31:51,067 --> 00:31:52,500 - Okay. - That would be - 好了,看起来很不错了. -718 -00:31:52,502 --> 00:31:55,202 - cool because we'd be sharing, - you know, this check. - 因为我们共用了这段代码. -719 -00:31:55,204 --> 00:31:57,204 - We'd be sharing this enter. - 公用了这enter方法 -720 -00:31:57,206 --> 00:31:59,472 - [COUGH] We'd be sharing - the removal of the operator. - 共用了removal操作方法. -721 -00:31:59,474 --> 00:32:01,441 - We'd be sharing - the same display value. - 共用了displayValue变量. -722 -00:32:01,443 --> 00:32:04,209 - We'd be kind of sharing - a lot of code here and - 这样,公用了大段的代码, -723 -00:32:05,746 --> 00:32:08,179 - then up here if we could - just do something like, - 在上面,只需要像这样做, -724 -00:32:08,181 --> 00:32:12,850 - perform operation, - and, somehow, specify, - 调用函数, -725 -00:32:12,852 --> 00:32:16,186 - multiply, as the operation - we wanted to do here. - 指定函数参数, -726 -00:32:16,188 --> 00:32:23,593 - And then we wouldn't need - all this stuff here, right? - 这段代码就不需要了,对么? -727 -00:32:23,595 --> 00:32:24,527 - So this is gonna be cool. - 看起来很不错吧? -728 -00:32:24,529 --> 00:32:25,995 - Now, can we do this? - 可以这样做么? -729 -00:32:25,997 --> 00:32:28,564 - Well, yes, - the answer is we can. - 当然了,可以的. -730 -00:32:28,566 --> 00:32:33,134 - And so, types, functions. - 参数类型,函数 -731 -00:32:33,136 --> 00:32:37,005 - Can be types in Swift, - just like any other type. - 在Swift里可以当做类型,就像其他的类型一样 -732 -00:32:37,007 --> 00:32:40,040 - So, you know, we have - a double here, oops, double. - 这里需要一个double, -733 -00:32:41,844 --> 00:32:42,809 - That's a type. - 就是这个类型, -734 -00:32:42,811 --> 00:32:43,943 - You can also have - a function type. - 也可以有一个函数类型. -735 -00:32:43,945 --> 00:32:45,611 - So how do you specify - a function type? - 那么,怎么指定一个函数类型呢? -736 -00:32:45,613 --> 00:32:47,846 - Well multiple I or - 比如multiple, -737 -00:32:47,848 --> 00:32:49,981 - whatever function I'm - about to perform here. - 或者是任何其他想要执行的函数, -738 -00:32:49,983 --> 00:32:54,686 - This is a function that takes - two doubles as arguments. - 这个函数需要两个double类型的参数 -739 -00:32:54,688 --> 00:32:56,354 - And it returns a double. - 函数的返回值类型也是一个double类型 -740 -00:32:56,356 --> 00:33:00,190 - So, I can just say, - I want operation to be - 我想要一个函数, -741 -00:33:00,192 --> 00:33:04,661 - a function that takes two - doubles and returns a double. - 带两个double类型参数,返回double类型 -742 -00:33:04,663 --> 00:33:07,363 - I can express that right here. - 这就是我要表达的, -743 -00:33:07,365 --> 00:33:11,300 - This is a type, - the type of this. - 这就是参数类型,这种类型. -744 -00:33:12,369 --> 00:33:15,870 - Argument right here that you - can click on and say yeah - 在这里的参数上右键, -745 -00:33:15,872 --> 00:33:18,639 - that type is double takes two - doubles and returns a double. - 可以看到信息:2个double类型的参数,一个double类型返回值. -746 -00:33:20,276 --> 00:33:22,176 - So, just simple as that. - 就是这么简单. -747 -00:33:22,177 --> 00:33:24,077 - So all we need now - is a function here - 我们所知道的,这里是一个函数, -748 -00:33:24,079 --> 00:33:26,379 - called multiply that - takes two doubles and - 函数名multiply,带2个参数, -749 -00:33:26,381 --> 00:33:28,514 - returns a double and - does multiplication. - 返回double类型,完成乘法操作. -750 -00:33:28,516 --> 00:33:33,118 - So we could go down here and - say okay multiply and - 好了,看下面的乘, -751 -00:33:33,120 --> 00:33:35,587 - you'll have op1 which - is double and op2. - 有一个参数,double类型,第二个参数, -752 -00:33:35,589 --> 00:33:39,157 - [COUGH] A double and - it returned the double. - double类型,返回一个double类型. -753 -00:33:39,159 --> 00:33:41,926 - And it's just return - one times out two. - 这个函数返回参数1乘以参数2 -754 -00:33:42,962 --> 00:33:44,261 - Okay? - 对么? -755 -00:33:44,263 --> 00:33:45,729 - And that worked great. - 看来起不错哟! -756 -00:33:45,731 --> 00:33:51,600 - Back out again so we can - see if this actually works. - 回到上面,看它是否真的可以正常运行. -757 -00:33:51,602 --> 00:33:53,168 - But there's no arrows here. - 没有任何错误. -758 -00:33:53,170 --> 00:33:55,387 - Right? - It seems to work. - 对么?看起来可行. -759 -00:33:55,388 --> 00:33:57,605 - Multiply seems to be - a function to take the $2 and - -760 -00:33:57,608 --> 00:33:59,274 - turns it double. - -761 -00:33:59,275 --> 00:34:00,941 - And that's what this - argument here is and - 这里的这个参数, -762 -00:34:00,944 --> 00:34:02,661 - I'm passing it along. - 将它传入 -763 -00:34:02,662 --> 00:34:04,379 - It should all work so - let's give it a try. - 应该是可行的,那么试一下吧. -764 -00:34:08,818 --> 00:34:10,684 - So here we go as - it takes enter. - 点下enter -765 -00:34:10,686 --> 00:34:15,188 - 54 times and - sure enough it's working it. - 54乘以,好了,没问题. -766 -00:34:15,190 --> 00:34:17,757 - It's doing that - multiplication. - 完成了乘法操作. -767 -00:34:18,826 --> 00:34:23,428 - Works great and so what about - all of our other cases here? - 做的不错,其他的case语句呢? -768 -00:34:23,430 --> 00:34:26,731 - Well we would just - need to take this same. - 只需要也像这样做. -769 -00:34:26,733 --> 00:34:29,400 - Piece of code right here and - put it for all of them. - 所有的case语句,这里一段代码, -770 -00:34:29,402 --> 00:34:32,169 - And of course we need a divide - method, so we have to - 当然了,我们需要除法函数, -771 -00:34:32,171 --> 00:34:35,805 - come down here, and copy and - paste that, and make divide. - 来到下面,复制,粘贴,起名divide -772 -00:34:35,807 --> 00:34:37,907 - Oh wait a second, - 稍等, -773 -00:34:37,909 --> 00:34:41,210 - this is starting to be just - as bad as I had before. - 看起来又像之前的一样,很糟糕了. -774 -00:34:41,212 --> 00:34:44,646 - Having to make all these - extra functions, multiply and - 需要这些额外的函数,乘法, -775 -00:34:44,648 --> 00:34:46,081 - divide and all that. - 触发,等等. -776 -00:34:46,082 --> 00:34:47,515 - Well [COUGH] it - turns out it's so - 事情上, -777 -00:34:47,518 --> 00:34:52,553 - common to pass functions as - arguments in Swift, that it - 字啊Swift中,把函数作为参数传递是很常见的. -778 -00:34:52,555 --> 00:34:56,390 - allows you to put a function - like multiply right in - 允许你传递一个,比如multiply,的函数, -779 -00:34:56,392 --> 00:35:00,327 - here without having to create - a separate function like this. - 不需要再创建一个函数 -780 -00:35:00,329 --> 00:35:02,195 - And all you do is - you just pick it up. - 需要做的是,选中, -781 -00:35:02,197 --> 00:35:05,131 - So I'm just going to cut - that from down here and - 从这里剪切 -782 -00:35:05,133 --> 00:35:06,599 - I'm going to paste - it right in here. - 粘贴到这里来 -783 -00:35:07,702 --> 00:35:10,168 - The only thing you have to - change syntactically when you - 唯一需要做语法上的改变的是, -784 -00:35:10,170 --> 00:35:13,738 - do that is this curly brace, - okay. - 这里是一个大括号. -785 -00:35:13,740 --> 00:35:16,541 - Instead of being after - the declaration of - 而不是之前在声明 -786 -00:35:16,543 --> 00:35:21,779 - the arguments in the return - value, it needs to be before. - 函数,返回值之后. -787 -00:35:21,781 --> 00:35:24,314 - So, you move the curly - brace before. - 把大括号放到前面. -788 -00:35:24,316 --> 00:35:25,648 - And then where - the curly brace was, - 之前这里是小括号. -789 -00:35:25,650 --> 00:35:27,417 - you gonna put in, the word in. - 这里添加一个单词in -790 -00:35:28,586 --> 00:35:30,486 - And so that allows us to just. - 允许我们稍微调整下. -791 -00:35:30,488 --> 00:35:34,723 - Come and do that again to - eliminate some of our errors. - 现在把这些错误解决了, -792 -00:35:34,725 --> 00:35:37,291 - And we can get rid of - function multiply down here. - 移除这里的mutiply -793 -00:35:39,328 --> 00:35:42,862 - So that allows me to just put - that multiplier right in here. - 把乘法放在这里. -794 -00:35:42,864 --> 00:35:44,030 - Right in line. - 就是这里. -795 -00:35:44,032 --> 00:35:46,032 - Write as the argument - to this function. - 给这个函数写一个参数. -796 -00:35:46,034 --> 00:35:48,167 - And this things kind of wacky. - 看起来略古怪. -797 -00:35:48,169 --> 00:35:49,701 - For those of you - who don't know it, - 对于一些不了解的人来讲, -798 -00:35:49,703 --> 00:35:51,469 - user programming languages - that allow this kind - 编程语言中, -799 -00:35:51,471 --> 00:35:53,604 - of thing to happen - are called closures. - 这种情况称之为闭包. -800 -00:35:54,607 --> 00:35:56,540 - It basically allows you to put - a function right in there. - 允许在这里放一个函数. -801 -00:35:56,542 --> 00:36:02,812 - And this, okay here, looks - okay, I mean we can certainly - 好了,这看起来还不错. -802 -00:36:02,814 --> 00:36:05,481 - you know, now we can copy and - paste this and put it here. - 下面又是复制,粘贴,放着 -803 -00:36:05,483 --> 00:36:06,615 - You know, here and - 放这里 -804 -00:36:06,617 --> 00:36:09,118 - change this and - put it here and change this. - 改了这个,放在这里,改了这个, -805 -00:36:09,120 --> 00:36:12,287 - But it can even be - better than this. - 但是,我们可以进一步改进. -806 -00:36:12,289 --> 00:36:15,223 - So we know that Swift - is really good at - 我们知道Swift很擅长的 -807 -00:36:15,225 --> 00:36:17,658 - something called - type inference. - 一个特性称为类型引用. -808 -00:36:17,660 --> 00:36:19,493 - Where I can kinda - figure out the type, - 从类型引用可以看出是什么类型, -809 -00:36:19,495 --> 00:36:22,863 - of something, - from the context. - 结合上下文来看. -810 -00:36:22,865 --> 00:36:25,165 - And you can do - the same thing here. - 这里也可以这么做. -811 -00:36:25,167 --> 00:36:27,267 - Because its looking - at perform operation. - 看下这里的performOperation -812 -00:36:27,269 --> 00:36:29,435 - It knows you're calling - perform operation. - 它知道你在调用performOperation -813 -00:36:29,437 --> 00:36:33,039 - It knows this argument is - a function that takes two - 它知道这个函数的参数, -814 -00:36:33,041 --> 00:36:34,940 - doubles and returns a double. - 2个double类型,一个double类型的返回值. -815 -00:36:34,942 --> 00:36:38,377 - So you really don't have to - specify all the types in here. - 所以,这里不需要明确的指定类型, -816 -00:36:38,379 --> 00:36:39,978 - Cuz it knows all of this. - 因为它知道这些事情. -817 -00:36:39,980 --> 00:36:43,381 - So you can actually get rid of - all these type decorations, - 所以,可以删除这些类型声明. -818 -00:36:43,383 --> 00:36:45,416 - right here, even the return. - 甚至是返回值类型也可以省去. -819 -00:36:45,418 --> 00:36:47,851 - And, again, - seeing no warnings, no errors. - 可以看到,没有任何警告,错误. -820 -00:36:47,853 --> 00:36:49,553 - It knows that this has - to be a double, and - 它知道这个参数是double, -821 -00:36:49,555 --> 00:36:51,454 - this has to be a double. - 这个参数也是dobule类型. -822 -00:36:51,456 --> 00:36:53,556 - Because it knows you're - calling perform operation. - 因为它知道你需要调用的函数. -823 -00:36:53,558 --> 00:36:56,959 - So it knows the argument - to that is like that. - 就像这样,它知道函数的参数. -824 -00:36:58,529 --> 00:37:00,962 - Okay, and you can even make - this look a little nicer. - 好了,可以进行进一步的改进. -825 -00:37:00,964 --> 00:37:03,631 - We can move this all - up onto one line. - 把这些上移一行. -826 -00:37:04,800 --> 00:37:08,168 - Really nice for - readability here. - 看来起更具有可读性. -827 -00:37:08,170 --> 00:37:11,037 - But, we can actually do - even better than this, - 事实上,我们可以做的更好. -828 -00:37:11,039 --> 00:37:15,074 - because Swift knows that - perform operations argument - 因为Swift知道这个函数 -829 -00:37:15,076 --> 00:37:18,844 - returns something, you don't - need this return key if your - 返回一个值,所以你不需要return -830 -00:37:18,846 --> 00:37:22,715 - whole is just an expression - like this return key word. - 如果所有的代码只有一个返回语句. -831 -00:37:22,717 --> 00:37:25,717 - You don;t need that key word - because it knows this is - 不需要return这个关键字了, -832 -00:37:25,719 --> 00:37:27,485 - going to return something so - 因为程序知道你要返回什么. -833 -00:37:27,487 --> 00:37:32,056 - this is just an expression - it's going to return it. - 这样只返回一个表达式就可以了. -834 -00:37:33,325 --> 00:37:37,260 - But it's even better than - that because a swift does - 更好的做法是, -835 -00:37:37,262 --> 00:37:40,597 - not force you to name - these two arguments. - swift不强制你给这两个参数命名. -836 -00:37:40,599 --> 00:37:44,967 - If you don;t name them it - will use the names Dar0. - 如果不手动命名的话,程序自动给参数起码$0 -837 -00:37:44,969 --> 00:37:46,952 - Dollar 1, and - $1, -838 -00:37:46,953 --> 00:37:48,936 - if you have more arguments, - dollar 2, dollar 3, dollar 4. - 如果有更多的参数,会命名为$2,$3,$4. -839 -00:37:48,939 --> 00:37:50,706 - So you don't even need this. - 所以,这也不要了. -840 -00:37:52,142 --> 00:37:53,441 - Okay? - 对么? -841 -00:37:53,443 --> 00:37:55,710 - So this is a function - right here. - 这里是一个函数. -842 -00:37:55,712 --> 00:37:58,112 - It takes two doubles, - dollar 0 and dollar 1, and - 这个函数有两个double类型参数,$0,$1 -843 -00:37:58,114 --> 00:37:59,546 - returns a double. - 返回一个double类型的值. -844 -00:37:59,548 --> 00:38:02,916 - Now Swift knows that they're - doubles because it knows that - Swift知道它们是double类型. -845 -00:38:02,918 --> 00:38:04,517 - you're passing them to - perform an operation. - 因为你将它们传递给了这个函数. -846 -00:38:04,519 --> 00:38:07,920 - If you were passing this to - some other, a function that - 如果把它们传递给其他的函数, -847 -00:38:07,922 --> 00:38:10,789 - took different kind of - function as an argument, then, - 比如有不同类型的参数, -848 -00:38:10,791 --> 00:38:14,126 - you know, these types might be - different but in this case it - 这些类型可能和上面不同. -849 -00:38:14,128 --> 00:38:16,961 - knows that's what it is and - it knows that it returns once - 但是Swift知道该使用什么类型 -850 -00:38:16,963 --> 00:38:20,731 - it knows it's going to return - what this calculation is. - 这里就是这样的. -851 -00:38:21,801 --> 00:38:22,366 - All right. - 好了. -852 -00:38:23,568 --> 00:38:26,536 - Now one more cool syntactic - thing you can do is if you - 更酷的事情是, -853 -00:38:26,538 --> 00:38:29,305 - have a function like - performOperation, and - 如果有一个performOperation这样的函数, -854 -00:38:29,307 --> 00:38:32,741 - it has an argument which is a - function like operation here, - 有个像operation这样的参数, -855 -00:38:32,743 --> 00:38:36,445 - if this argument is - the last argument, okay, so - 如果是最后一个参数, -856 -00:38:36,447 --> 00:38:38,446 - if I had other arguments - before it, and - 在之前又别的参数, -857 -00:38:38,448 --> 00:38:42,917 - this was the argument, then - you can move the function. - 这是参数,可以移动这个函数的位置 -858 -00:38:43,886 --> 00:38:47,888 - Outside the parentheses, - so other arguments, - 移动到括号外,参数也是. -859 -00:38:47,890 --> 00:38:50,123 - if there were other arguments - before, they would go in here. - 如果又其他类型的参数,可以放在这里. -860 -00:38:51,726 --> 00:38:54,327 - But this last argument, - 但是这个最后的一个参数. -861 -00:38:54,328 --> 00:38:56,929 - which is this operation, gets - to go outside the parentheses. - 这个函数,需要放在括号外. -862 -00:38:56,931 --> 00:38:59,564 - And if there are no other - arguments, if this is - 如果没有其他的参数, -863 -00:38:59,566 --> 00:39:02,033 - the only argument, you can - actually get rid of that. - 如果只有一个参数,可以删除它. -864 -00:39:03,870 --> 00:39:05,269 - Okay. - 好了. -865 -00:39:05,271 --> 00:39:08,705 - So, we're cutting down - to incredibly concise - 因此,我们把程序变得很简洁了 -866 -00:39:08,707 --> 00:39:13,509 - language here and we can - do this exact same deal, - 可以再这样做. -867 -00:39:13,511 --> 00:39:18,047 - of course with these - other form operations. - 其他的操作也可以这样做. -868 -00:39:18,049 --> 00:39:19,848 - We just need to change the. - 只需要改这里. -869 -00:39:20,817 --> 00:39:21,382 - Nothing here. - 这里不需要改. -870 -00:39:22,585 --> 00:39:24,184 - This one, we be a little - careful with the order of - 这里,需要注意参数的顺序, -871 -00:39:24,186 --> 00:39:27,421 - operations here, - we wanna do this because we - 我们会这么做, -872 -00:39:27,423 --> 00:39:30,824 - click the thing that we're - dividing by on the stack last. - 除以栈中的最后一个元素. -873 -00:39:30,826 --> 00:39:34,660 - And that's the first thing - that comes off the stack. - 栈中最先离开的元素 -874 -00:39:34,662 --> 00:39:35,494 - And same thing here actually, - 这里也要注意, -875 -00:39:35,496 --> 00:39:38,163 - the subtraction - minus dollar here. - 减法,减号,$, -876 -00:39:38,165 --> 00:39:41,900 - Okay, so, this is our - entire operate, and - 好了,这就是我们的全部操作. -877 -00:39:41,902 --> 00:39:44,469 - you can see that it's - incredibly concise. - 你可以看到,这相当的简洁. -878 -00:39:44,471 --> 00:39:45,803 - Very readable. - 很高的可读性. -879 -00:39:45,805 --> 00:39:47,504 - TImes is clearly - doing this function. - 这里改成乘法. -880 -00:39:47,506 --> 00:39:48,905 - And very extensible. - 也有很高的可扩展性 -881 -00:39:48,907 --> 00:39:50,206 - If you wanna add - more functions, - 如果需要添加更多的操作, -882 -00:39:50,208 --> 00:39:51,974 - we just one liners here, - 只需要这里添加一行代码. -883 -00:39:51,976 --> 00:39:55,745 - but more these [COUGH] binary - functions that have two So, - 这里我们就只有这么多. -884 -00:39:55,747 --> 00:39:58,814 - let's go ahead and make - sure these are all working. - 继续,确保我们程序运行问题. -885 -00:40:02,753 --> 00:40:04,686 - All right. - 好的. -886 -00:40:04,687 --> 00:40:06,620 - So, 6 enter 5 times, - that's 30, that's good. - 6乘以5,结果是30,看起来不错. -887 -00:40:06,623 --> 00:40:11,291 - How about 47 plus 77, - excellent. - 47加上77,不错. -888 -00:40:11,293 --> 00:40:13,593 - How about 2 divide. - 2除以 -889 -00:40:13,595 --> 00:40:14,928 - 38.5. - 38.5 -890 -00:40:14,930 --> 00:40:17,397 - [INAUDIBLE] number there. - 这个数,三十八点五. -891 -00:40:17,399 --> 00:40:20,299 - Working, you can see the stack - doing all the right things. - 正常,可以看到做的还错. -892 -00:40:21,368 --> 00:40:24,102 - Okay? - Make sense? - 对么?正确的吧? -893 -00:40:24,104 --> 00:40:26,771 - Now, I'm going to do - one more thing, here. - 现在,还需要做一个事情. -894 -00:40:27,840 --> 00:40:29,473 - Which is to add - another operation, - 就是添加另外的一个操作符. -895 -00:40:29,475 --> 00:40:31,174 - this is going to be a slightly - different operation. - 稍有不同的一个操作. -896 -00:40:31,176 --> 00:40:32,375 - So, I'm going to copy and - 复制一下, -897 -00:40:32,377 --> 00:40:35,144 - paste these operation - buttons here. - 粘贴到这里. -898 -00:40:35,146 --> 00:40:37,880 - Again, I'm going to make sure - they are lined up really - 确保真正的对齐了. -899 -00:40:37,882 --> 00:40:41,350 - nice with as many of these - blue lines as I can get. - 使用蓝色的线来对齐. -900 -00:40:42,786 --> 00:40:44,919 - I'm actually going to - leave these buttons here. - 把按钮放在这. -901 -00:40:46,255 --> 00:40:48,389 - Because you're going to need - them for your homework. - -902 -00:40:48,391 --> 00:40:50,323 - But we gonna change this - button right down here to be - -903 -00:40:50,325 --> 00:40:51,825 - a different operator. - -904 -00:40:52,894 --> 00:40:54,760 - Which is going to be, - square root. - -905 -00:40:54,762 --> 00:40:57,629 - Which is right here, - square root operator. - -906 -00:40:58,732 --> 00:40:59,297 - All right? - -907 -00:40:59,299 --> 00:41:05,803 - And, so, I'm going to go back - her to do square root, and - -908 -00:41:05,805 --> 00:41:07,704 - it's just another case, right. - -909 -00:41:07,706 --> 00:41:08,805 - Case square root. - -910 -00:41:09,841 --> 00:41:12,808 - And, maybe I should just - be able to use the same - -911 -00:41:12,810 --> 00:41:13,709 - mechanism, right? - -912 -00:41:13,711 --> 00:41:14,843 - Let's see if that works. - -913 -00:41:15,946 --> 00:41:18,897 - Place that in there. - -914 -00:41:18,898 --> 00:41:21,849 - And instead of this bracket - here, let's use the built in - -915 -00:41:21,851 --> 00:41:25,285 - function in Swift to do - square root called sqrt. - -916 -00:41:25,287 --> 00:41:26,219 - And a dollar there. - -917 -00:41:26,221 --> 00:41:27,187 - Looks good. - -918 -00:41:27,189 --> 00:41:29,322 - And then we're ready to go. - -919 -00:41:29,324 --> 00:41:32,591 - Let's just work, call it, - what's going on here. - -920 -00:41:32,593 --> 00:41:35,794 - They have some sort of error, - what's the problem. - -921 -00:41:35,796 --> 00:41:36,995 - I don't understand. - -922 -00:41:36,997 --> 00:41:38,163 - Let's take a look at this. - -923 -00:41:38,165 --> 00:41:42,867 - Now this error is a little - hard to understand but - -924 -00:41:42,869 --> 00:41:46,970 - basically what it's saying - is that you're calling - -925 -00:41:46,972 --> 00:41:51,207 - performOperation here with an - argument which is a function, - -926 -00:41:51,209 --> 00:41:54,177 - it only takes on argument. - -927 -00:41:54,179 --> 00:41:55,378 - Goes Swift looks here and - -928 -00:41:55,380 --> 00:41:57,579 - it's used that it's only - using a dollar zero so - -929 -00:41:57,581 --> 00:42:00,849 - this is a one argument - function this whole - -930 -00:42:00,851 --> 00:42:03,785 - curly brace thing is a - function that is one argument. - -931 -00:42:03,787 --> 00:42:07,121 - Well four operation - takes a function that - -932 -00:42:07,123 --> 00:42:08,189 - has two arguments. - -933 -00:42:09,692 --> 00:42:11,591 - So that's a mismatch - that doesn't work. - -934 -00:42:12,594 --> 00:42:14,694 - So how can we fix this. - -935 -00:42:14,695 --> 00:42:16,795 - Well actually believe it or - not we can just make a copy of - -936 -00:42:16,798 --> 00:42:19,398 - form operation of another - method, same name. - -937 -00:42:19,400 --> 00:42:22,067 - This one we are gonna - have different arguments. - -938 -00:42:22,069 --> 00:42:24,736 - It's gonna have a, - an argument which is - -939 -00:42:24,738 --> 00:42:27,605 - a function that only takes one - double and returns a double. - -940 -00:42:28,574 --> 00:42:30,224 - And then inside here, - -941 -00:42:30,225 --> 00:42:31,875 - obviously we don't need to - pull two things off the stack, - -942 -00:42:31,877 --> 00:42:32,609 - just one. - -943 -00:42:32,611 --> 00:42:35,645 - And obviously we only need to - -944 -00:42:35,647 --> 00:42:37,413 - check to make sure there - is one thing on the stack. - -945 -00:42:37,415 --> 00:42:41,950 - And look, - all error warnings gone, okay? - -946 -00:42:41,952 --> 00:42:44,319 - So it automatically - figured out that this - -947 -00:42:44,321 --> 00:42:46,321 - performer operation - must be this one, - -948 -00:42:46,323 --> 00:42:49,857 - because this is a function - that only has one argument. - -949 -00:42:49,859 --> 00:42:52,460 - And so it matched it up - with this version of it. - -950 -00:42:52,462 --> 00:42:55,996 - So in Swift, you can have - functions with the same name. - -951 -00:42:55,998 --> 00:42:58,265 - As long as they have - different arguments. - -952 -00:42:58,267 --> 00:42:59,399 - And that Swift will - -953 -00:42:59,401 --> 00:43:02,168 - automatically pick - the right one, if it can. - -954 -00:43:02,170 --> 00:43:03,936 - There are sometimes - when it's just like, - -955 -00:43:03,938 --> 00:43:05,971 - I can't really tell - which one you mean. - -956 -00:43:05,973 --> 00:43:08,673 - And it will certainly - complain, in that case. - -957 -00:43:11,378 --> 00:43:14,311 - But most of the type it's - gonna be on [INAUDIBLE] from - -958 -00:43:14,313 --> 00:43:16,647 - the types involved, - what's going on. - -959 -00:43:16,649 --> 00:43:18,582 - So, just gonna run this - one again real quick. - -960 -00:43:18,584 --> 00:43:22,852 - [INAUDIBLE] 36 square root. - -961 -00:43:22,854 --> 00:43:27,423 - Looks like it's working, - 9 times square root. - -962 -00:43:27,425 --> 00:43:27,989 - Excellent. - -963 -00:43:29,726 --> 00:43:30,291 - Okay. - -964 -00:43:31,627 --> 00:43:33,894 - All right. - So, - -965 -00:43:33,895 --> 00:43:36,162 - the last thing I'm going - to do here is work on - -966 -00:43:36,165 --> 00:43:37,431 - the layout of these buttons. - -967 -00:43:37,433 --> 00:43:38,531 - So that's all I'm gonna do for - the code. - -968 -00:43:38,533 --> 00:43:40,333 - You can see that we - really didn't have to - -969 -00:43:40,335 --> 00:43:41,367 - write that much code. - -970 -00:43:42,436 --> 00:43:45,003 - To make this work and - -971 -00:43:45,005 --> 00:43:47,939 - we got to do a lot of - stuff in our UI here. - -972 -00:43:47,941 --> 00:43:50,708 - So, let's go ahead and make it - so these buttons spread out. - -973 -00:43:50,710 --> 00:43:54,778 - Cuz right now you see all this - space is wasted right here. - -974 -00:43:54,780 --> 00:43:57,481 - And on an iPhone - in portrait mode. - -975 -00:43:57,483 --> 00:43:59,549 - Whole bottom space is wasted. - -976 -00:43:59,551 --> 00:44:01,484 - And an iPhone on - landscape mode, - -977 -00:44:01,486 --> 00:44:02,685 - this whole size can be wasted. - -978 -00:44:02,687 --> 00:44:04,920 - So I really want these - buttons much bigger, and - -979 -00:44:04,922 --> 00:44:05,687 - stretching out. - -980 -00:44:07,124 --> 00:44:09,791 - Now, when you do something - like that, you have to think - -981 -00:44:09,793 --> 00:44:12,226 - a little bit of kind of what - your strategy is gonna be. - -982 -00:44:12,228 --> 00:44:15,696 - You can't just kinda root - four start, you know, - -983 -00:44:15,698 --> 00:44:17,597 - control drag it - between things. - -984 -00:44:17,599 --> 00:44:20,667 - And trying to set up - the horizontal spacing, - -985 -00:44:20,669 --> 00:44:24,437 - and maybe line up the, make - the equal width and height. - -986 -00:44:24,439 --> 00:44:27,106 - Oh my gosh, you'd be control - dragging all day long, - -987 -00:44:27,108 --> 00:44:28,374 - by doing that. - -988 -00:44:28,376 --> 00:44:30,475 - So I'm not going to use - control drag to do this. - -989 -00:44:30,477 --> 00:44:33,945 - I'm going to use these buttons - down here which will kind of - -990 -00:44:33,947 --> 00:44:36,414 - bulk out a layout buttons. - -991 -00:44:36,416 --> 00:44:40,451 - Let's go ahead and - use the whole screen here. - -992 -00:44:40,453 --> 00:44:43,620 - Document outline. - -993 -00:44:43,622 --> 00:44:45,939 - So what is going - to be my strategy? - -994 -00:44:45,940 --> 00:44:48,257 - Well, my strategy is I'm going - to make a perfect grid here. - -995 -00:44:48,260 --> 00:44:52,195 - So, I almost have one, except - for there's one missing here. - -996 -00:44:52,197 --> 00:44:54,897 - So I'm actually going to take - a button, copy and paste it. - -997 -00:44:54,899 --> 00:44:59,167 - Okay, just kind of be - a dummy button here actually. - -998 -00:44:59,169 --> 00:45:00,969 - With no title. - -999 -00:45:00,970 --> 00:45:02,770 - I'm going to right click on it - also because I don't want it - -1000 -00:45:02,773 --> 00:45:04,939 - sending appendage or - anything else, So - -1001 -00:45:04,941 --> 00:45:06,841 - its not going to - send any messages. - -1002 -00:45:06,843 --> 00:45:09,309 - But it's just a dummy, - so I'm kind of using. - -1003 -00:45:09,311 --> 00:45:12,245 - A little bit of brains - over brawn here to do - -1004 -00:45:12,247 --> 00:45:13,680 - this perfect grid. - -1005 -00:45:13,682 --> 00:45:16,916 - Now if I have this perfect - grid, then if I had a rule - -1006 -00:45:16,918 --> 00:45:20,720 - where all these buttons had to - be the same size, and they all - -1007 -00:45:20,722 --> 00:45:24,857 - had the same spacing between - their neighbors, not just. - -1008 -00:45:24,859 --> 00:45:28,160 - Between each other but the - same spacing to this edge and - -1009 -00:45:28,162 --> 00:45:30,929 - the same spacing - to this top edge. - -1010 -00:45:30,931 --> 00:45:33,631 - Okay, if I had a rule like - that then they would get - -1011 -00:45:33,633 --> 00:45:36,434 - big and of course the spacing - is facing from this edge - -1012 -00:45:36,436 --> 00:45:38,035 - to edge and - this edge to this edge. - -1013 -00:45:38,037 --> 00:45:41,304 - If it was all the exactly the - same, which I'll make it be - -1014 -00:45:41,306 --> 00:45:44,708 - whatever this is, whatever the - dash for the lines gave me. - -1015 -00:45:44,710 --> 00:45:47,443 - If that was the same then they - would all have to spread out. - -1016 -00:45:48,479 --> 00:45:50,179 - Okay, they'd get bigger but - -1017 -00:45:50,180 --> 00:45:51,880 - they'd all stay the same - size because I'm going to - -1018 -00:45:51,882 --> 00:45:54,516 - make a rule that they - have to be the same size. - -1019 -00:45:54,518 --> 00:45:56,317 - But they would move - out to this edge so - -1020 -00:45:56,319 --> 00:46:00,121 - that this nearest neighbor - would be the same, you know, - -1021 -00:46:00,123 --> 00:46:02,322 - this distance would be - the same as this distance. - -1022 -00:46:02,324 --> 00:46:05,092 - So that's my strategy, - I'm going to try to do that. - -1023 -00:46:05,094 --> 00:46:06,760 - Now to make that work, - -1024 -00:46:06,762 --> 00:46:09,128 - all these buttons need to know - who their nearest neighbor is. - -1025 -00:46:09,130 --> 00:46:11,564 - Well, these all know their - nearest neighbor here, - -1026 -00:46:11,566 --> 00:46:13,999 - the other buttons, because - I made sure I used dashed, - -1027 -00:46:14,001 --> 00:46:17,035 - blue lines when I - dragged them in there. - -1028 -00:46:17,037 --> 00:46:18,303 - So, that's what kind of - -1029 -00:46:18,305 --> 00:46:19,904 - teaches them their - nearest neighbor. - -1030 -00:46:19,906 --> 00:46:22,573 - And I'm also going to make - sure that the entire grid - -1031 -00:46:22,575 --> 00:46:25,442 - knows that the left edge and - -1032 -00:46:25,444 --> 00:46:29,046 - just under the label there, - our nearest neighbor. - -1033 -00:46:29,048 --> 00:46:30,447 - So now it knows on the top, - -1034 -00:46:30,449 --> 00:46:32,348 - the nearest neighbor - is the label, and - -1035 -00:46:32,350 --> 00:46:34,383 - on the left is this edge. - -1036 -00:46:34,385 --> 00:46:37,386 - And it's going to - pick this edge as - -1037 -00:46:37,388 --> 00:46:39,888 - the nearest neighbor for these - buttons and the bottom edge, - -1038 -00:46:39,890 --> 00:46:41,356 - cuz that's all there is and - -1039 -00:46:41,357 --> 00:46:42,823 - nothing else out here - that's gonna become, - -1040 -00:46:42,826 --> 00:46:45,326 - that's the only neighbor there - is, it's gonna pick those. - -1041 -00:46:47,263 --> 00:46:48,962 - So now that I've - used my dash for - -1042 -00:46:48,964 --> 00:46:51,898 - the lines it makes - this all quite easy. - -1043 -00:46:51,900 --> 00:46:53,866 - Now, if you don't use - the dash for the lines, or - -1044 -00:46:53,868 --> 00:46:56,602 - if you make some mistakes - then it's not going to work. - -1045 -00:46:56,604 --> 00:47:00,305 - This strategy won't work and - I've made doing this part of - -1046 -00:47:00,307 --> 00:47:03,809 - this demonstration - be extra credit. - -1047 -00:47:03,811 --> 00:47:06,044 - And so if you can't get it, - don't worry about it too much, - -1048 -00:47:06,046 --> 00:47:09,247 - just keep all your buttons in - the upper left corner here - -1049 -00:47:09,249 --> 00:47:11,199 - and that's fine. - -1050 -00:47:11,200 --> 00:47:13,150 - But if you want to give - this a try, the key is to - -1051 -00:47:13,152 --> 00:47:15,753 - use the dash lines to - make the perfect grid. - -1052 -00:47:15,755 --> 00:47:18,822 - Make sure that you set - the nearest neighbors here by - -1053 -00:47:18,824 --> 00:47:22,225 - dragging the whole grid to - make blue lines appear on - -1054 -00:47:22,227 --> 00:47:23,793 - the sides. - -1055 -00:47:23,795 --> 00:47:26,962 - And then, we are going to - set these rules in bulk and - -1056 -00:47:26,964 --> 00:47:29,965 - we do that with these - buttons down here. - -1057 -00:47:29,966 --> 00:47:32,967 - So there's this button right - here the left most button and - -1058 -00:47:32,969 --> 00:47:36,337 - it let's you set things like - lining up leading edges or - -1059 -00:47:36,339 --> 00:47:37,872 - the tops or the centers. - -1060 -00:47:37,874 --> 00:47:40,174 - And you could imagine there - might be a way to do this by - -1061 -00:47:40,176 --> 00:47:42,542 - doing that but I am not - going to use that strategy. - -1062 -00:47:42,544 --> 00:47:45,045 - My strategy is just make - them the same size and - -1063 -00:47:45,047 --> 00:47:48,447 - make the space in between - them, be the same. - -1064 -00:47:49,617 --> 00:47:51,450 - But, I bet there's - probably a way to do it by - -1065 -00:47:51,452 --> 00:47:54,919 - lining up their centers, or - something like that, too. - -1066 -00:47:54,921 --> 00:47:56,921 - So I'm not going - to use this one. - -1067 -00:47:56,923 --> 00:47:59,357 - The next one over, - -1068 -00:47:59,358 --> 00:48:01,792 - right here, is the one that - has the things I want. - -1069 -00:48:01,794 --> 00:48:04,094 - And so you can see - that it'll ask you to - -1070 -00:48:04,096 --> 00:48:06,196 - make all the buttons - equal widths and heights. - -1071 -00:48:06,198 --> 00:48:07,464 - Okay, not width and - -1072 -00:48:07,466 --> 00:48:09,832 - height, that fixes them - at a certain width and - -1073 -00:48:09,834 --> 00:48:12,401 - height, this means that there, - they can be any width and - -1074 -00:48:12,403 --> 00:48:14,803 - height they want, but they all - have to be the same width and - -1075 -00:48:14,805 --> 00:48:16,938 - height all these buttons. - -1076 -00:48:16,940 --> 00:48:18,840 - Of course I had these all - selected by the way, if you - -1077 -00:48:18,842 --> 00:48:20,842 - don't have them selected - it doesn't make any sense. - -1078 -00:48:22,011 --> 00:48:23,711 - And then up here, you can - see there is spacing to - -1079 -00:48:23,713 --> 00:48:25,679 - nearest neighbor, so this - is where I am going to set - -1080 -00:48:25,681 --> 00:48:29,716 - that spacing between all - these, to be the same. - -1081 -00:48:29,718 --> 00:48:31,417 - And you can see that - it's put eight here. - -1082 -00:48:31,419 --> 00:48:33,585 - That's because when I - did the the dash lines - -1083 -00:48:35,022 --> 00:48:39,323 - to the top eight seems to be - kind of a standard number of - -1084 -00:48:39,325 --> 00:48:42,727 - points between elements. - -1085 -00:48:42,729 --> 00:48:45,429 - These are all multiple because - some of these buttons, - -1086 -00:48:45,431 --> 00:48:48,432 - their nearest neighbor is - way over here and it's huge. - -1087 -00:48:48,434 --> 00:48:50,250 - All right. - -1088 -00:48:50,251 --> 00:48:52,067 - The bottom or their right. - -1089 -00:48:52,070 --> 00:48:55,838 - But all these buttons, - the thing on top, - -1090 -00:48:55,840 --> 00:48:58,274 - whether it's another button or - whether it's this label, - -1091 -00:48:58,276 --> 00:49:01,343 - all of them happen to be this - eight points right here. - -1092 -00:49:01,345 --> 00:49:03,178 - So I want all of - these to be eight. - -1093 -00:49:03,180 --> 00:49:07,482 - So I'm just going to turn this - bar on right here, which says, - -1094 -00:49:07,484 --> 00:49:11,018 - yes please enforce, and - make the rule that all of - -1095 -00:49:11,020 --> 00:49:15,255 - these are 8 points from their - nearest neighbor to the top. - -1096 -00:49:15,257 --> 00:49:18,124 - And also, 8 to the left, - 8 to the right, and - -1097 -00:49:18,126 --> 00:49:19,459 - 8 to the bottom. - -1098 -00:49:19,461 --> 00:49:21,060 - Really wanna make sure - these beams are on, - -1099 -00:49:21,062 --> 00:49:23,362 - if these beams are off, - even if there's a number here, - -1100 -00:49:23,364 --> 00:49:24,963 - then it's not gonna - add this rule. - -1101 -00:49:24,965 --> 00:49:26,998 - So we wanted to add this rule. - -1102 -00:49:27,000 --> 00:49:30,101 - So this adds up to - 87 different rules. - -1103 -00:49:30,103 --> 00:49:32,554 - All these equal widths and - -1104 -00:49:32,555 --> 00:49:35,006 - heights and all these So - if you don't have 87 in here, - -1105 -00:49:35,008 --> 00:49:36,974 - if it says a hundred and - something, - -1106 -00:49:36,976 --> 00:49:39,209 - probably you don't have - everything lined up right. - -1107 -00:49:39,211 --> 00:49:43,279 - It only takes 87 constraints - to express all these rules. - -1108 -00:49:44,482 --> 00:49:45,547 - All right. - -1109 -00:49:45,549 --> 00:49:48,316 - Now, when I click this - Add 87 Constraints it's - -1110 -00:49:48,318 --> 00:49:51,886 - going to add these rules - to all these buttons, and - -1111 -00:49:51,888 --> 00:49:52,787 - watch what happens. - -1112 -00:49:54,790 --> 00:49:56,723 - So, I get all kinds of, - -1113 -00:49:56,725 --> 00:49:59,392 - first these blue lines - are showing me the rules. - -1114 -00:49:59,394 --> 00:50:01,094 - 'Kay? - A lot them are saying here - -1115 -00:50:01,096 --> 00:50:03,062 - that things are equal - widths and heights. - -1116 -00:50:03,064 --> 00:50:05,531 - So these are what - equals rules means. - -1117 -00:50:05,533 --> 00:50:08,700 - But there's also tiny little - I beams right up here. - -1118 -00:50:08,702 --> 00:50:13,671 - That are showing this basing - to nearest neighbor, and - -1119 -00:50:13,673 --> 00:50:16,073 - also like there's a yellow, - yellow here. - -1120 -00:50:16,075 --> 00:50:18,409 - This yellow, - remember, means yeah, - -1121 -00:50:18,411 --> 00:50:21,044 - there's constraints on these, - but they're not actually where - -1122 -00:50:21,046 --> 00:50:23,113 - they're supposed to be - based on those rules. - -1123 -00:50:24,049 --> 00:50:27,016 - So we really want to move - them all to be in their - -1124 -00:50:27,018 --> 00:50:29,852 - proper spaces based - on these rules. - -1125 -00:50:29,854 --> 00:50:31,753 - That's what these dashed - yellow lines mean. - -1126 -00:50:31,755 --> 00:50:33,221 - So we can do the same - thing to do that, - -1127 -00:50:33,223 --> 00:50:36,224 - that we did at the beginning - with the label on the top - -1128 -00:50:36,226 --> 00:50:38,225 - which is go to our - document outline here, - -1129 -00:50:38,227 --> 00:50:39,393 - in the lower left corner. - -1130 -00:50:39,395 --> 00:50:42,929 - Okay these are document - outline when we last saw it, - -1131 -00:50:42,931 --> 00:50:45,331 - it only had this - one label in there. - -1132 -00:50:46,401 --> 00:50:47,700 - Now we got all these - buttons added. - -1133 -00:50:47,702 --> 00:50:50,002 - And you can see - they're all selected. - -1134 -00:50:50,004 --> 00:50:52,304 - All selected here as well. - -1135 -00:50:52,306 --> 00:50:54,673 - And, we've got this little - yellow thing up here. - -1136 -00:50:54,675 --> 00:50:58,643 - Now, if this is red, okay, - if you do all this and - -1137 -00:50:58,645 --> 00:51:02,747 - this is red, well that means - that you've got not just - -1138 -00:51:02,749 --> 00:51:05,516 - warnings that your constraints - aren't in the right place, but - -1139 -00:51:05,518 --> 00:51:08,452 - you've got errors, usually - conflicting constraints, - -1140 -00:51:08,454 --> 00:51:11,721 - where you've asked - auto layout to - -1141 -00:51:11,723 --> 00:51:13,890 - enforce two rules that - conflict with each other. - -1142 -00:51:13,892 --> 00:51:17,626 - So if you get to that red, - this is not going to work. - -1143 -00:51:17,628 --> 00:51:20,295 - So, you'll want to start over, - and - -1144 -00:51:20,297 --> 00:51:23,432 - I'll show you in a minute how - you can start over if things, - -1145 -00:51:23,434 --> 00:51:26,234 - or not going your way, but - if it's yellow that just means - -1146 -00:51:26,236 --> 00:51:27,201 - things were in - the wrong place. - -1147 -00:51:27,203 --> 00:51:29,136 - So no problem, - we click the yellow. - -1148 -00:51:29,138 --> 00:51:30,637 - Here's all the things that - were in the wrong place. - -1149 -00:51:30,639 --> 00:51:31,972 - This is all the buttons, - -1150 -00:51:31,974 --> 00:51:34,274 - you can see they highlight - as I mouse over them. - -1151 -00:51:34,276 --> 00:51:38,077 - And you can really pick on - any one of them to fix this - -1152 -00:51:38,079 --> 00:51:40,880 - because there's a nice little - switch here called apply to - -1153 -00:51:40,882 --> 00:51:42,047 - all views and containers. - -1154 -00:51:42,049 --> 00:51:44,116 - You don't have to - click on each one and - -1155 -00:51:44,118 --> 00:51:46,985 - have it to frame update - to the proper thing. - -1156 -00:51:46,987 --> 00:51:50,588 - You can just click quite - obvious in container and it's - -1157 -00:51:50,590 --> 00:51:55,125 - going to move the frame of all - the buttons top fix the fact - -1158 -00:51:55,127 --> 00:51:57,494 - that they're in the wrong - place based on their rules. - -1159 -00:51:57,496 --> 00:51:59,096 - So let's try that. - -1160 -00:51:59,097 --> 00:52:00,697 - I'm gonna hit this button - here, Fix Misplacement. - -1161 -00:52:01,933 --> 00:52:03,032 - And it moved them all. - -1162 -00:52:03,034 --> 00:52:03,966 - There's no more yellow. - -1163 -00:52:03,968 --> 00:52:06,101 - There's no auto layout issues. - -1164 -00:52:06,103 --> 00:52:07,435 - Okay. - All looks good here. - -1165 -00:52:07,437 --> 00:52:09,070 - We can close our - document outline. - -1166 -00:52:10,306 --> 00:52:13,440 - We zoom out, we can see, - wow, it spread them all out. - -1167 -00:52:13,442 --> 00:52:14,675 - Okay? - Because, - -1168 -00:52:14,677 --> 00:52:18,444 - maybe it's obeying - those rules I gave it. - -1169 -00:52:18,446 --> 00:52:20,079 - Okay? - -1170 -00:52:20,080 --> 00:52:21,713 - So let's now run this on - some devices here and - -1171 -00:52:21,716 --> 00:52:23,182 - see what this looks like. - -1172 -00:52:26,220 --> 00:52:30,221 - So turn off on an iPhone 6, - which is a pretty tall device. - -1173 -00:52:30,223 --> 00:52:32,790 - It's made, you know, - kind of tall and thin. - -1174 -00:52:32,792 --> 00:52:35,459 - So if this still - works fine enter. - -1175 -00:52:35,461 --> 00:52:39,763 - 69874 times 5 divide maybe - square root something like - -1176 -00:52:39,765 --> 00:52:44,266 - that, it all seems - to be working. - -1177 -00:52:44,268 --> 00:52:48,804 - Now, not only is it working - here in this portrait mode, - -1178 -00:52:48,806 --> 00:52:51,023 - tall and thin. - -1179 -00:52:51,024 --> 00:52:53,241 - But if we go over here to this - we can rotate the device. - -1180 -00:52:54,277 --> 00:52:55,843 - Okay, so - I'm going to rotate left and - -1181 -00:52:55,845 --> 00:52:58,979 - right and use the command - keys to do this. - -1182 -00:52:58,981 --> 00:53:02,449 - And we rotate it right and - you see it - -1183 -00:53:02,451 --> 00:53:08,220 - may the buttons spread out - to this new location and - -1184 -00:53:09,190 --> 00:53:13,491 - we can rotate back using - the command keys here. - -1185 -00:53:14,627 --> 00:53:17,461 - And it looks good in - either orientation. - -1186 -00:53:17,463 --> 00:53:21,465 - And in fact, it can look good - on other devices as well. - -1187 -00:53:21,467 --> 00:53:23,066 - So let's go over here and - -1188 -00:53:23,068 --> 00:53:26,235 - instead of doing iPhone 6, - let's try it on an iPhone 4S. - -1189 -00:53:26,237 --> 00:53:27,937 - Okay so, - -1190 -00:53:27,939 --> 00:53:32,407 - gonna switch the simulation - here, let's run that. - -1191 -00:53:34,077 --> 00:53:37,345 - Now the iPhone 4s, you can - see is a little shorter, - -1192 -00:53:37,347 --> 00:53:39,280 - it's not quite as tall. - -1193 -00:53:39,282 --> 00:53:42,416 - A little lower resolution, - obviously. - -1194 -00:53:42,418 --> 00:53:46,986 - But it relayed out the buttons - to look good in that case too. - -1195 -00:53:46,988 --> 00:53:52,558 - 9 times 9, divided by 8, - square root, et cetera. - -1196 -00:53:52,560 --> 00:53:56,995 - And same thing here - we can rotate and - -1197 -00:53:56,997 --> 00:54:00,131 - look at this one as well. - -1198 -00:54:00,133 --> 00:54:03,067 - Okay. - -1199 -00:54:03,069 --> 00:54:05,019 - All righty. - -1200 -00:54:05,020 --> 00:54:06,970 - So the last thing I just want - to talk about briefly is if - -1201 -00:54:06,973 --> 00:54:10,207 - you try this extra credit and - it doesn't work for you. - -1202 -00:54:10,209 --> 00:54:16,413 - Get all messed up, you can - kind of start over by clicking - -1203 -00:54:16,415 --> 00:54:21,450 - on this and using the third - button over here on the right. - -1204 -00:54:21,452 --> 00:54:23,852 - And this allows you to - reset your constraints and - -1205 -00:54:23,854 --> 00:54:26,688 - you can see the top section - here is the selected views. - -1206 -00:54:26,690 --> 00:54:27,922 - I don't have any - selected here so - -1207 -00:54:27,924 --> 00:54:29,257 - this wouldn't do - anything right now. - -1208 -00:54:29,259 --> 00:54:31,659 - But the bottom is all - views in container and - -1209 -00:54:31,661 --> 00:54:34,161 - I kinda recommend going - down here to all views - -1210 -00:54:34,163 --> 00:54:37,164 - container and clearing - the constraints entirely. - -1211 -00:54:37,166 --> 00:54:40,000 - Reset to suggested - constraints and try and - -1212 -00:54:40,002 --> 00:54:44,437 - make some sense of your dashed - lines but if it's not working, - -1213 -00:54:44,439 --> 00:54:47,673 - you're probably, you're - dashed lines are off anyway. - -1214 -00:54:47,675 --> 00:54:49,875 - So you can just go here and - -1215 -00:54:49,877 --> 00:54:51,343 - Clear Constraints, - that'll clear them all. - -1216 -00:54:51,345 --> 00:54:53,211 - Now that's gonna clear - not just your buttons but - -1217 -00:54:53,213 --> 00:54:55,880 - also it's gonna - clear your labels. - -1218 -00:54:55,882 --> 00:54:59,450 - So you'll have to reposition - your label with blue lines and - -1219 -00:54:59,452 --> 00:55:02,953 - use control drag to say - your top space, and, and - -1220 -00:55:02,955 --> 00:55:05,388 - all that stuff, you know? - -1221 -00:55:05,390 --> 00:55:08,458 - If your buttons are really - huge, they got really huge, - -1222 -00:55:08,460 --> 00:55:10,726 - but they're not in the right - place, you can actually change - -1223 -00:55:10,728 --> 00:55:13,595 - the size of all your buttons - in the utilities window. - -1224 -00:55:14,565 --> 00:55:16,164 - You can go to the size - inspector right here, - -1225 -00:55:16,166 --> 00:55:19,467 - that's this one, you can - actually type in the width and - -1226 -00:55:19,469 --> 00:55:22,370 - the height you want - the buttons to be, make them - -1227 -00:55:22,372 --> 00:55:25,272 - smaller again, which, - you know, maybe 64 by 64. - -1228 -00:55:25,274 --> 00:55:29,376 - That might make them easier to - re-drag them into position so - -1229 -00:55:29,378 --> 00:55:31,210 - the blue lines are working. - -1230 -00:55:32,313 --> 00:55:36,015 - And don't forget the very - important blue line dragging, - -1231 -00:55:36,017 --> 00:55:38,283 - which is you want to take - the whole grid and drag it, - -1232 -00:55:38,285 --> 00:55:40,285 - so that it's sitting - underneath your label. - -1233 -00:55:41,654 --> 00:55:44,021 - If you have problems dragging - the whole grid underneath your - -1234 -00:55:44,023 --> 00:55:46,490 - label, sometimes it's - a good idea, clear all - -1235 -00:55:46,492 --> 00:55:48,892 - your constraints, kind of move - your buttons out of the way, - -1236 -00:55:48,894 --> 00:55:51,761 - just kind of move them down - to the bottom here and then - -1237 -00:55:51,763 --> 00:55:56,132 - just for your label, do reset - to suggest your constraint. - -1238 -00:55:56,134 --> 00:55:57,499 - This top one selected view - -1239 -00:55:57,501 --> 00:56:01,036 - Rest Suggestion Constraints - cuz that will work for - -1240 -00:56:01,038 --> 00:56:03,204 - the label if you move it - into position as long as - -1241 -00:56:03,206 --> 00:56:06,407 - the buttons aren't too close - and it thinks that, you know. - -1242 -00:56:06,409 --> 00:56:08,042 - Those buttons are near - neighbors or something. - -1243 -00:56:09,145 --> 00:56:11,945 - And sometimes resetting it to - suggest the constraints will - -1244 -00:56:11,947 --> 00:56:17,483 - make it so that, that bottom - edge of your UI label will - -1245 -00:56:17,485 --> 00:56:21,253 - be attainable when you drag - your buttons into position. - -1246 -00:56:22,289 --> 00:56:23,538 - But again, not to - -1247 -00:56:23,539 --> 00:56:24,788 - worry too much about - this auto layout stuff. - -1248 -00:56:25,825 --> 00:56:27,158 - It's extra credit - in assignment one. - -1249 -00:56:27,160 --> 00:56:29,493 - It's not going to be extra - credit in assignment two, - -1250 -00:56:29,495 --> 00:56:31,728 - so you're eventually - going to have to do it. - -1251 -00:56:31,730 --> 00:56:34,197 - I'm going to be giving a big - lecture on this in a couple of - -1252 -00:56:34,199 --> 00:56:35,465 - weeks, on auto layout. - -1253 -00:56:35,467 --> 00:56:38,968 - I've really just shown you - just kind of what it can do, - -1254 -00:56:38,970 --> 00:56:41,770 - I haven't really - taught you how to do - -1255 -00:56:41,772 --> 00:56:43,338 - auto layout in particular. - -1256 -00:56:44,374 --> 00:56:48,409 - Auto layout is very important - because we work in this - -1257 -00:56:48,411 --> 00:56:50,745 - square area and - -1258 -00:56:50,746 --> 00:56:53,080 - we want our UIs to work on all - kinds of different devices. - -1259 -00:56:53,082 --> 00:56:54,614 - That's why we're - starting off in the very - -1260 -00:56:55,584 --> 00:56:57,717 - start with some - experience with it. - -1261 -00:56:59,820 --> 00:57:00,686 - All right. - -1262 -00:57:00,688 --> 00:57:02,520 - So that is it. - -1263 -00:57:02,522 --> 00:57:06,190 - Now, later today, - I'm gonna, in this lecture, - -1264 -00:57:06,192 --> 00:57:10,828 - I'm gonna give you a talk - about this design paradigm - -1265 -00:57:10,830 --> 00:57:14,197 - called model-view-controller, - and we actually designed our - -1266 -00:57:14,199 --> 00:57:17,300 - calculator kind of poorly, - because all of - -1267 -00:57:17,302 --> 00:57:20,436 - this code here is really - nothing to do with UI. - -1268 -00:57:20,438 --> 00:57:26,141 - This is all calculator brain, - calculator engine code. - -1269 -00:57:26,143 --> 00:57:28,143 - And this really wants to - meet a different object and - -1270 -00:57:28,145 --> 00:57:30,211 - that's what NBC is all about. - -1271 -00:57:30,213 --> 00:57:33,648 - And so I'll give a little - talk about NBC later today. - -1272 -00:57:33,650 --> 00:57:36,650 - And then on Monday, we're - going to fix our calculator - -1273 -00:57:36,652 --> 00:57:41,855 - to obey MVC and be a proper - citizen in the iOS world, - -1274 -00:57:41,857 --> 00:57:45,258 - where all apps need to obey - model V controller paradigm. - -1275 -00:57:46,294 --> 00:57:49,261 - >> So let's try and - understand for, I mean half of - -1276 -00:57:49,263 --> 00:57:52,764 - you said that you already - know MVC or you've seen it - -1277 -00:57:52,766 --> 00:57:54,499 - somewhere else so, this is - going to be mostly review. - -1278 -00:57:54,501 --> 00:57:57,769 - But the other half of you, - this will hopefully give you - -1279 -00:57:57,771 --> 00:58:00,705 - an idea of what - MVC is all about. - -1280 -00:58:00,707 --> 00:58:04,975 - So MVC is basically - a mechanism where we divide up - -1281 -00:58:04,977 --> 00:58:09,379 - all the objects in our - application into one of - -1282 -00:58:09,381 --> 00:58:11,180 - these three camps. - -1283 -00:58:11,182 --> 00:58:12,281 - Okay? - -1284 -00:58:12,283 --> 00:58:14,182 - So, the three camps. - -1285 -00:58:14,184 --> 00:58:15,884 - On the left there - you see the model. - -1286 -00:58:15,886 --> 00:58:19,220 - So, the model camp is gonna be - all the objects that are what - -1287 -00:58:19,222 --> 00:58:21,355 - your application does. - -1288 -00:58:21,357 --> 00:58:24,858 - So, for our calculator its, - it calculates. - -1289 -00:58:24,860 --> 00:58:26,794 - Okay, that's what it does. - -1290 -00:58:26,795 --> 00:58:28,729 - So, all the parts what we're - doing perform operation, and - -1291 -00:58:28,731 --> 00:58:32,098 - all that stuff, that's all - kind of calculator stuff. - -1292 -00:58:32,100 --> 00:58:35,935 - That should be in a calculator - object somewhere else, - -1293 -00:58:35,937 --> 00:58:37,569 - it shouldn't be in - our controller. - -1294 -00:58:38,639 --> 00:58:43,841 - And then the second camp is - the controller, the controller - -1295 -00:58:43,843 --> 00:58:48,178 - controls how the model - is presented on screen. - -1296 -00:58:48,180 --> 00:58:51,348 - And the view is the minions, - the classes that - -1297 -00:58:51,350 --> 00:58:52,916 - the controller is going - to use are kind of - -1298 -00:58:52,918 --> 00:58:55,485 - like the the building blocks, - the Lincoln Logs, - -1299 -00:58:55,487 --> 00:58:57,520 - I know maybe that's - before all of your time. - -1300 -00:58:57,522 --> 00:59:00,289 - But, you know, these things - we're gong to do to build our - -1301 -00:59:00,291 --> 00:59:02,524 - UI, we're going to - use in the view. - -1302 -00:59:02,526 --> 00:59:06,127 - So the stuff that's in the - view is pretty generic, okay, - -1303 -00:59:06,129 --> 00:59:07,795 - generic UI elements. - -1304 -00:59:07,797 --> 00:59:10,030 - The stuff in the controller - is very specific to - -1305 -00:59:10,032 --> 00:59:11,498 - how your UI works. - -1306 -00:59:11,500 --> 00:59:13,600 - And the stuff in the model - is completely independent of - -1307 -00:59:13,602 --> 00:59:15,234 - how your UI works. - -1308 -00:59:15,236 --> 00:59:15,801 - Okay? - -1309 -00:59:15,803 --> 00:59:22,007 - So doing MVC right is about - knowing where things go but - -1310 -00:59:22,009 --> 00:59:25,543 - also about how to communicate - between these three camps. - -1311 -00:59:25,545 --> 00:59:27,412 - And so we can try and - summarize how - -1312 -00:59:27,414 --> 00:59:29,113 - the communication works - between these camps, and - -1313 -00:59:29,115 --> 00:59:32,182 - I've used road markings, you - see the double yellow line and - -1314 -00:59:32,184 --> 00:59:33,350 - then the dashed white line. - -1315 -00:59:33,352 --> 00:59:34,884 - So that's like you're - driving in your car. - -1316 -00:59:35,887 --> 00:59:40,356 - Try to use them as an image - for how this communication - -1317 -00:59:40,358 --> 00:59:42,090 - happens, where it's allowed, - where it's not allowed. - -1318 -00:59:43,093 --> 00:59:45,693 - So let's talk about - the Controller talking to - -1319 -00:59:45,695 --> 00:59:47,294 - the Model. - -1320 -00:59:47,296 --> 00:59:50,097 - Going from that side of the - road over to the Model side is - -1321 -00:59:50,099 --> 00:59:51,565 - a dashed white line, - in other words, - -1322 -00:59:51,567 --> 00:59:52,799 - you can head right - across there. - -1323 -00:59:52,801 --> 00:59:54,267 - You probably want to - look before you go, but - -1324 -00:59:54,269 --> 00:59:56,603 - you can go right across, okay? - -1325 -00:59:56,604 --> 00:59:58,938 - The controller has to know - everything about the model, - -1326 -00:59:58,940 --> 01:00:01,740 - and it has to have complete - ability to talk to - -1327 -01:00:01,742 --> 01:00:04,776 - the model, use its public - API as much as it wants - -1328 -01:00:04,778 --> 01:00:08,313 - because the controller's job - is to present the model to - -1329 -01:00:08,315 --> 01:00:10,848 - the user using its - view as its minions. - -1330 -01:00:10,850 --> 01:00:12,650 - So it has to have this access. - -1331 -01:00:12,652 --> 01:00:16,319 - That full, unrestricted access - the controller has talking to - -1332 -01:00:16,321 --> 01:00:17,320 - the model. - -1333 -01:00:17,322 --> 01:00:18,354 - This is a one way arrow. - -1334 -01:00:18,356 --> 01:00:20,289 - Control, or - -1335 -01:00:20,290 --> 01:00:22,223 - one way arrow, from - the controller to the model. - -1336 -01:00:22,226 --> 01:00:25,160 - And similarly, from - the controller to the view, - -1337 -01:00:25,162 --> 01:00:27,095 - is also unlimited - communication, - -1338 -01:00:27,097 --> 01:00:28,830 - because the controller - is responsible for - -1339 -01:00:28,832 --> 01:00:30,798 - talking using - it's own minions. - -1340 -01:00:30,800 --> 01:00:32,667 - The view is, the controller's - new meaning is - -1341 -01:00:32,669 --> 01:00:35,569 - to lay out the user interface - and all that stuff. - -1342 -01:00:35,571 --> 01:00:37,671 - So, the controller can - do anything it wants. - -1343 -01:00:37,673 --> 01:00:39,305 - I put that little green word, - outlet, - -1344 -01:00:39,307 --> 01:00:42,809 - up there because when we have - a property of a controller - -1345 -01:00:42,811 --> 01:00:46,278 - that points into the view, - we call it an outlet, okay? - -1346 -01:00:46,280 --> 01:00:48,213 - And you're gonna see that - in the demo on Wednesday. - -1347 -01:00:48,215 --> 01:00:51,249 - I'm gonna say, oh let's create - an outlet from our controller - -1348 -01:00:51,251 --> 01:00:52,634 - to our view so - -1349 -01:00:52,635 --> 01:00:54,018 - our controller can talk - to it's view, all right? - -1350 -01:00:55,055 --> 01:00:56,354 - What about this communication? - -1351 -01:00:56,356 --> 01:00:57,554 - Model to view? - -1352 -01:00:57,556 --> 01:00:58,422 - Never. - -1353 -01:00:58,424 --> 01:00:59,989 - And why is that? - -1354 -01:00:59,991 --> 01:01:03,292 - 100% obvious, the model is - completely UI independent. - -1355 -01:01:03,294 --> 01:01:05,494 - So, there's absolutely - no way it could talk to - -1356 -01:01:05,496 --> 01:01:07,863 - a viewer object or - anyone in that camp. - -1357 -01:01:07,865 --> 01:01:10,399 - Because the view objects - are fundamentally UI objects. - -1358 -01:01:10,401 --> 01:01:11,466 - They're kind of generic, but - -1359 -01:01:11,468 --> 01:01:13,401 - they're still - fundamentally UI objects. - -1360 -01:01:13,403 --> 01:01:16,237 - Similarly, since the view - objects are kind of generic, - -1361 -01:01:16,239 --> 01:01:18,272 - they can't be talking - to any specific model. - -1362 -01:01:18,274 --> 01:01:20,674 - They need a controller - to interpret a model - -1363 -01:01:20,676 --> 01:01:22,375 - for them, okay? - -1364 -01:01:22,377 --> 01:01:24,377 - So there's never any - communication this way. - -1365 -01:01:24,379 --> 01:01:25,911 - That's why it's - a double yellow line. - -1366 -01:01:25,913 --> 01:01:27,780 - That's why these - lines are red. - -1367 -01:01:27,782 --> 01:01:29,748 - That's why there's fire, okay? - -1368 -01:01:29,750 --> 01:01:31,783 - Never go across that line, - ever. - -1369 -01:01:34,120 --> 01:01:36,520 - What about the view talking - back to the controller? - -1370 -01:01:36,522 --> 01:01:38,588 - You got these generic view - objects, like buttons. - -1371 -01:01:38,590 --> 01:01:40,724 - Can they talk to - the controller? - -1372 -01:01:40,726 --> 01:01:43,593 - Well, yes, they can. - -1373 -01:01:43,595 --> 01:01:46,495 - But, they have to be careful - because the view objects - -1374 -01:01:46,497 --> 01:01:48,397 - are generic. - -1375 -01:01:48,398 --> 01:01:50,298 - So they can't really know - much about the controller. - -1376 -01:01:50,301 --> 01:01:53,201 - So, they can only communicate - back to the controller - -1377 -01:01:53,203 --> 01:01:55,437 - in a blind way where they - don't know the class of - -1378 -01:01:55,439 --> 01:01:58,673 - the thing they're talking to, - and in a structured way. - -1379 -01:01:58,675 --> 01:02:02,776 - A way where we all agree we're - gonna communicate this way - -1380 -01:02:02,778 --> 01:02:03,844 - between the view and - the controller. - -1381 -01:02:03,846 --> 01:02:05,512 - So, whats an example - of a structured way? - -1382 -01:02:05,514 --> 01:02:07,480 - Well one is called - target action. - -1383 -01:02:07,482 --> 01:02:10,816 - So, the controller basically - drops a target on itself, and - -1384 -01:02:10,818 --> 01:02:15,087 - then it hands out an action, - which is like an arrow, - -1385 -01:02:15,089 --> 01:02:17,389 - to the view and - says to the view, - -1386 -01:02:17,391 --> 01:02:20,058 - okay, when you do what you do, - like you're a button and - -1387 -01:02:20,060 --> 01:02:21,659 - someone touches you or - your a slider and - -1388 -01:02:21,661 --> 01:02:24,828 - someone moves you, - send me that action. - -1389 -01:02:24,830 --> 01:02:26,430 - Okay? - -1390 -01:02:26,431 --> 01:02:28,031 - So, in this way, - the generic button or - -1391 -01:02:28,033 --> 01:02:30,600 - slider is communicating - back to the controller. - -1392 -01:02:30,602 --> 01:02:32,835 - It has no idea that it's - a card game controller or - -1393 -01:02:32,837 --> 01:02:34,103 - a space game controller. - -1394 -01:02:34,105 --> 01:02:36,071 - It doesn't know what - kind of controller it is. - -1395 -01:02:36,073 --> 01:02:38,607 - All it knows is that when - something happens in itself, - -1396 -01:02:38,609 --> 01:02:40,108 - boom, it sends a message - to the target. - -1397 -01:02:40,110 --> 01:02:43,678 - So that's a blind, simple, - structured way for - -1398 -01:02:43,680 --> 01:02:45,780 - the view to communicate - with the controller. - -1399 -01:02:45,782 --> 01:02:47,465 - Okay? - -1400 -01:02:47,466 --> 01:02:49,149 - But what about more - complicated ways? - -1401 -01:02:49,151 --> 01:02:52,119 - Sometimes the view, things - are happening in the view - -1402 -01:02:52,121 --> 01:02:53,987 - that are somewhat complicated, - and - -1403 -01:02:53,989 --> 01:02:56,456 - the controller needs to be - informed of what's going on, - -1404 -01:02:56,458 --> 01:02:58,791 - synchronizing what's - happening. - -1405 -01:02:58,793 --> 01:03:01,694 - And one way to think about - this is these words I - -1406 -01:03:01,696 --> 01:03:04,096 - put up here, will, - should and did. - -1407 -01:03:04,098 --> 01:03:06,598 - When the view is kind of like, - -1408 -01:03:06,600 --> 01:03:08,132 - let's say I am in - the scroll view and - -1409 -01:03:08,134 --> 01:03:11,669 - I am scrolling around, and - I want to let the controller - -1410 -01:03:11,671 --> 01:03:15,806 - somebody know that - the user just did scroll. - -1411 -01:03:15,808 --> 01:03:17,691 - Okay? - Or - -1412 -01:03:17,692 --> 01:03:19,575 - the user puts down the touch - and is about to scroll, I want - -1413 -01:03:19,578 --> 01:03:23,413 - to let the controller know the - user will be scrolling, okay? - -1414 -01:03:23,415 --> 01:03:25,114 - Or, the user puts - the touch down and - -1415 -01:03:25,116 --> 01:03:26,448 - the scroll viewer - wants to know, - -1416 -01:03:26,450 --> 01:03:30,452 - should I allow the user to - scroll here, is that allowed? - -1417 -01:03:30,454 --> 01:03:33,221 - All those things, the scroll - view itself might not - -1418 -01:03:33,223 --> 01:03:36,190 - have enough logic to know - the answer to those questions. - -1419 -01:03:36,192 --> 01:03:39,727 - So what it does is, - it delegates the authority to - -1420 -01:03:39,729 --> 01:03:42,730 - answer those questions - to some other object. - -1421 -01:03:42,732 --> 01:03:44,664 - Now, it doesn't know - the class of that object. - -1422 -01:03:44,666 --> 01:03:46,199 - All it knows is that - other object can - -1423 -01:03:46,201 --> 01:03:49,135 - answer these questions, will, - should, did, this, that, or - -1424 -01:03:49,137 --> 01:03:51,570 - the other thing like, - should allow scrolling. - -1425 -01:03:51,572 --> 01:03:53,939 - Did scroll to point. - -1426 -01:03:53,941 --> 01:03:54,539 - Things like that. - -1427 -01:03:54,541 --> 01:03:56,591 - So those are the kind of - -1428 -01:03:56,592 --> 01:03:58,642 - methods you are going to see - in these delicate protocols. - -1429 -01:03:58,645 --> 01:04:00,878 - Now, I know this here is 1, - 6 a and b, - -1430 -01:04:00,880 --> 01:04:02,847 - do not teach protocols. - -1431 -01:04:02,849 --> 01:04:04,582 - How many people know what - -1432 -01:04:04,583 --> 01:04:06,316 - the word protocol means an - object during a programming? - -1433 -01:04:06,318 --> 01:04:07,117 - I can see very few of you. - -1434 -01:04:07,119 --> 01:04:08,818 - So, I will be teaching that. - -1435 -01:04:08,820 --> 01:04:12,421 - A protocol is just a blind way - to talk to another object. - -1436 -01:04:12,423 --> 01:04:13,556 - When I teach it, - -1437 -01:04:13,557 --> 01:04:14,690 - you're gonna be like oh, - yeah, I know what that is. - -1438 -01:04:14,692 --> 01:04:16,958 - So we can really call it - protocol or whatever. - -1439 -01:04:16,960 --> 01:04:19,160 - But that's how we do - delegation, okay, - -1440 -01:04:19,162 --> 01:04:20,862 - this blind communication. - -1441 -01:04:21,931 --> 01:04:24,932 - Also another - important thing is - -1442 -01:04:24,934 --> 01:04:28,502 - that views should not own the - data that they're displaying. - -1443 -01:04:28,504 --> 01:04:30,170 - They should not own it. - -1444 -01:04:30,171 --> 01:04:31,837 - In other words, it shouldn't - be a property inside of them, - -1445 -01:04:31,840 --> 01:04:34,707 - where that's the truth - of that data. - -1446 -01:04:34,709 --> 01:04:37,810 - And the easiest example for - this is, all the songs in - -1447 -01:04:37,812 --> 01:04:40,679 - your iPod, on your iPhone or - your iPad, right? - -1448 -01:04:40,681 --> 01:04:43,281 - You might have 10,000 - songs in there. - -1449 -01:04:43,283 --> 01:04:46,017 - So, if you have some kind - of generic list view in - -1450 -01:04:46,019 --> 01:04:50,354 - your view, you can't transfer - all 10,000 songs to its - -1451 -01:04:50,356 --> 01:04:52,773 - instance variables, and - -1452 -01:04:52,774 --> 01:04:55,191 - expect it to hold 10,000 songs - so it can list through it. - -1453 -01:04:55,194 --> 01:04:56,860 - A, that would be inefficient, - and - -1454 -01:04:56,862 --> 01:05:01,064 - B that information, those - 10,000 songs belongs where? - -1455 -01:05:01,066 --> 01:05:02,131 - In the model. - -1456 -01:05:02,133 --> 01:05:04,900 - Okay, because your song - database is a model. - -1457 -01:05:04,902 --> 01:05:06,468 - It has nothing to do with UI. - -1458 -01:05:06,469 --> 01:05:08,035 - It's just a list of songs and - artists and albums and - -1459 -01:05:08,038 --> 01:05:09,604 - all that, it's in the model. - -1460 -01:05:09,606 --> 01:05:12,073 - Some controller has to - look at that database and - -1461 -01:05:12,075 --> 01:05:16,243 - tell a view how to - display all those songs. - -1462 -01:05:16,245 --> 01:05:18,429 - Okay? - -1463 -01:05:18,430 --> 01:05:20,614 - So, we need that communication - to happen here and the view is - -1464 -01:05:20,616 --> 01:05:23,249 - displaying some sort of list, - and you're touching down and - -1465 -01:05:23,251 --> 01:05:26,619 - you're flicking on the list - and trying to see more songs, - -1466 -01:05:26,621 --> 01:05:28,087 - how does that - communication happen? - -1467 -01:05:28,089 --> 01:05:30,923 - And the answer is, we have - another special kind of - -1468 -01:05:30,925 --> 01:05:33,992 - delegate, which we - call a data source. - -1469 -01:05:33,994 --> 01:05:36,928 - Now the data source doesn't - do the will did should. - -1470 -01:05:36,930 --> 01:05:39,230 - It's gonna be asking - questions like count, - -1471 -01:05:39,232 --> 01:05:41,098 - like how many songs are there? - -1472 -01:05:41,100 --> 01:05:42,900 - And the controller - looks in the model, - -1473 -01:05:42,902 --> 01:05:45,435 - 10,000 response to the view. - -1474 -01:05:45,437 --> 01:05:47,020 - There's 10,000. - The view - -1475 -01:05:47,021 --> 01:05:48,604 - makes space internally for - 10,000 things. - -1476 -01:05:48,607 --> 01:05:50,340 - It doesn't know what they are. - -1477 -01:05:50,342 --> 01:05:53,009 - Moves the scroll bar - indicator a little bit so - -1478 -01:05:53,011 --> 01:05:54,276 - that you know where it is. - -1479 -01:05:54,278 --> 01:05:57,779 - And then you start scrolling, - flipping through it, and - -1480 -01:05:57,781 --> 01:06:00,849 - it starts sending the message - to the controller, - -1481 -01:06:00,851 --> 01:06:03,785 - give me the data at - line 150 next 10 items. - -1482 -01:06:03,787 --> 01:06:04,975 - You see what I mean? - -1483 -01:06:04,976 --> 01:06:06,164 - And then you flick - down some more. - -1484 -01:06:06,165 --> 01:06:07,353 - Now it's saying 250, - 10 more items. - -1485 -01:06:07,357 --> 01:06:10,257 - And so the control is going - back to the model and - -1486 -01:06:10,259 --> 01:06:11,725 - saying give me more, - give me more data. - -1487 -01:06:11,727 --> 01:06:14,361 - And it's providing it to - the view in this blind way. - -1488 -01:06:14,363 --> 01:06:17,230 - So to see how the view is - getting data from the model - -1489 -01:06:17,232 --> 01:06:20,232 - through the controller in this - kind of blind structured way. - -1490 -01:06:20,234 --> 01:06:21,767 - Okay? - -1491 -01:06:21,768 --> 01:06:23,301 - That makes sense to everybody? - -1492 -01:06:23,304 --> 01:06:24,970 - So data source is just - a kind of delegate, - -1493 -01:06:24,972 --> 01:06:27,105 - it's a specific kind of - delegate for getting data. - -1494 -01:06:27,107 --> 01:06:30,408 - So you're gonna see that there - are classes in iOS that have - -1495 -01:06:30,410 --> 01:06:33,477 - a data source, and they - usually also have a delegate. - -1496 -01:06:33,479 --> 01:06:36,547 - Most sophisticated classes in - iOS have a delegate, the will, - -1497 -01:06:36,549 --> 01:06:38,415 - did, should, kind of things. - -1498 -01:06:38,417 --> 01:06:40,316 - Some of them have - a data source, - -1499 -01:06:40,318 --> 01:06:43,219 - it depends on whether they are - showing a lot of data or not. - -1500 -01:06:43,221 --> 01:06:46,455 - Now simple data, like if I had - a view, if I invented a view - 一些简单的数据,比如我给纸牌游戏 - -1501 -01:06:46,457 --> 01:06:49,224 - for my card game called - playing card view and - 创建了一个叫playing card view的视图 - -1502 -01:06:49,226 --> 01:06:51,109 - it just has a suit and a rank. - 它仅有花色和点数两点属性。 - -1503 -01:06:51,110 --> 01:06:52,993 - Okay, we're not going to - do count data app for - 我们不会为了花色和点数 - -1504 -01:06:52,996 --> 01:06:54,262 - just suit and rank. -进行计算。 - -1505 -01:06:54,264 --> 01:06:56,030 - We are going to set - those properties. - 我们会把它们设置成属性。 - -1506 -01:06:56,032 --> 01:06:58,766 - And so the view then would - have that data set in it but - 所以view里会有设置好的数据,但是 - -1507 -01:06:58,768 --> 01:07:00,267 - it wouldn't be owning it. - 它不会拥有这些数据。 - -1508 -01:07:00,269 --> 01:07:02,536 - Right? - The model would still be - model仍然会是花色和点数的 - -1509 -01:07:02,538 --> 01:07:04,571 - owning the suit and - 拥有者, - -1510 -01:07:04,572 --> 01:07:06,605 - rank, the view is just getting - that data to present it. - view仅仅是为了显示而获取那些数据。 - -1511 -01:07:06,608 --> 01:07:07,840 - 'Kay. - So simple data, - 所以对于简单的数据, - -1512 -01:07:07,842 --> 01:07:10,743 - we might transfer to - the view but it's merely for - 我们会把它传送到view里,但是 - -1513 -01:07:10,745 --> 01:07:12,878 - it to display it. - 只是给view来显示。 - -1514 -01:07:12,880 --> 01:07:14,312 - Okay. - -1515 -01:07:14,314 --> 01:07:17,615 - This all adds up to - the controller's job being to - 所以controller的工作就是 - -1516 -01:07:17,617 --> 01:07:22,520 - interpret and format - the model's data for the view. - 给view解释并格式化这些model提供的数据。 - -1517 -01:07:22,522 --> 01:07:23,654 - That's the controller's job. - 这就是controller的工作。 - -1518 -01:07:23,656 --> 01:07:25,188 - And when we do our demo, - 在我们做deomo的时候, - -1519 -01:07:25,190 --> 01:07:28,758 - I'm going to be marking like, - oh see I'm writing this code. - 我会在写代码的时候提示大家, - -1520 -01:07:28,760 --> 01:07:31,494 - This is to make the controller - perform its job, - 这段代码是为了让controller执行它的工作, - -1521 -01:07:31,496 --> 01:07:34,430 - which is to take - the model data and - 也就是从model中取出数据然后 - -1522 -01:07:34,432 --> 01:07:36,265 - using its view minion - to put it on screen. - 运用到view中去,然后显示到屏幕上。 - -1523 -01:07:36,267 --> 01:07:37,132 - Okay? - That's what - 这就是 - -1524 -01:07:37,134 --> 01:07:38,667 - the controller does. - controller做的事情。 - -1525 -01:07:38,669 --> 01:07:40,468 - What about this communication? - 那关于通信呢? - -1526 -01:07:40,470 --> 01:07:42,970 - Can the model talk - to the controller? - model可以和controller通信吗? - -1527 -01:07:42,972 --> 01:07:46,040 - Again, obviously that's - verboten because model knows -同样的,显然是不可以。因为model对于UI - -1528 -01:07:46,042 --> 01:07:47,708 - nothing about UI, so - 一无所知,所以 - -1529 -01:07:47,710 --> 01:07:50,710 - it couldn't possibly talk to a - UI object like the controller. - 它不可能同像controller一样的UI对象进行通信。 - -1530 -01:07:50,712 --> 01:07:53,046 - But sometimes things - change in the model, and - 但是有些时候,model中的数据变了, - -1531 -01:07:53,048 --> 01:07:54,580 - the controller needs to - know about it, okay? - controller需要只要这个变化,OK? - -1532 -01:07:54,582 --> 01:07:56,782 - Data changes, - a database changes or - 数据改变了,数据库改变了,或者 - -1533 -01:07:56,784 --> 01:07:59,017 - the model is some - network database, and - model是网络数据库, - -1534 -01:07:59,019 --> 01:08:01,186 - somebody changes something on - the network and it changes. - 某人在网络上修改了数据,数据改变了。 - -1535 -01:08:01,188 --> 01:08:02,587 - And the controller - needs to find out. - controller需要了解这些。 - -1536 -01:08:02,589 --> 01:08:04,555 - So, how do we do - that communication? - 所以,我们怎样做这种通信呢? - -1537 -01:08:05,958 --> 01:08:09,592 - We do that using kind of - a radio station model. - 这可以通过一种电台的模型来理解 - -1538 -01:08:09,594 --> 01:08:11,928 - Okay? - -1539 -01:08:11,929 --> 01:08:14,263 - So, the model, a radio station - concept, the model will use - 所以,model是一种电台的概念, - -1540 -01:08:14,265 --> 01:08:17,866 - this concept to essentially - broadcast information to - model将会利用这一 概念,把信息广播给 - -1541 -01:08:17,868 --> 01:08:19,768 - anyone who's interested. - 感兴趣的任何人。 - -1542 -01:08:19,770 --> 01:08:21,937 - Okay? - -1543 -01:08:21,938 --> 01:08:24,105 - And the mechanisms for - doing this in iOS are called - 在iOS中为了解决这种问题而使用的技术我们叫做 - -1544 -01:08:24,107 --> 01:08:28,476 - Notification and Key Value - Observing, KVO we call it. - Notification和KVO。 - -1545 -01:08:28,478 --> 01:08:31,211 - And so, the model can - just say, oh, anytime - 所以,model可以说, - -1546 -01:08:31,213 --> 01:08:33,547 - something changes in my model - I'm just gonna broadcast on -我当中的任何东西发生了变化,我会通过我的电台 - -1547 -01:08:33,549 --> 01:08:37,484 - my radio station, and then the - controller simply tunes into - 广播一下,随后,controller - -1548 -01:08:37,486 --> 01:08:40,453 - that radio station, and he can - find out things are changing. - 会接收到来自电台的信息,它会发现数据在变化 - -1549 -01:08:40,455 --> 01:08:42,254 - And when he finds out - something changes, - 发现数据变化以后, - -1550 -01:08:42,256 --> 01:08:46,058 - it's gonna communicate via its - green arrow to the model and - 它就会通过它的绿剪头同model进行通信, - -1551 -01:08:46,060 --> 01:08:47,659 - say, okay, give me - that data that changed. - 给我那个改变过的数据。 - -1552 -01:08:48,962 --> 01:08:49,560 - Right? - -1553 -01:08:49,562 --> 01:08:50,978 - That make sense? - 能听懂吗? - -1554 -01:08:50,979 --> 01:08:52,395 - So, towards the end of - the quarter we'll start seeing - 所以在课程快要结束的时候,我们将会学习 - -1555 -01:08:52,398 --> 01:08:54,531 - a little how to do - notification to find out, for - 如何利用通知得知 - -1556 -01:08:54,533 --> 01:08:57,334 - example, if the data - in a database changes. - 数据库中的数据发生了改变。 - -1557 -01:08:57,336 --> 01:09:00,070 - We'll get a notification, - the UI can then, you know, - 我们将会获取这个通知,UI中的controller - -1558 -01:09:00,072 --> 01:09:03,272 - controller can then go talk - to the model to get the info. - 随后可以同model通信来获取信息。 - -1559 -01:09:05,309 --> 01:09:06,286 - Okay? - -1560 -01:09:06,287 --> 01:09:07,264 - Some people have asked, - 有些人会问, - -1561 -01:09:07,265 --> 01:09:08,242 - can a view tune into - the radio station? - view可以接收广播吗? - -1562 -01:09:08,245 --> 01:09:09,878 - They probably could, but - 它们也许可以,但是 - -1563 -01:09:09,880 --> 01:09:11,179 - you probably wouldn't - want to do that. - 你最好不要这样做。 - -1564 -01:09:11,181 --> 01:09:12,980 - That would probably be - a violation of MVC. - 这可能违背了MVC的原则。 - -1565 -01:09:12,982 --> 01:09:14,749 - All right. - 好的。 - -1566 -01:09:14,751 --> 01:09:16,750 - So we do this. - 我们这样做, - -1567 -01:09:16,752 --> 01:09:18,785 - We have all this nice - communication and - 我们有这些很好的通信和 - -1568 -01:09:18,787 --> 01:09:21,288 - all these rules, - 所有的这些规则。 - -1569 -01:09:21,289 --> 01:09:23,790 - and we can imagine building - something simple using this. - 我们可以利用这些来制作一些小的应用。 - -1570 -01:09:23,792 --> 01:09:26,259 - But what if we wanna build - a big complicated app? - 但是如果我们想要制作一个巨大复杂的应用呢? - -1571 -01:09:26,261 --> 01:09:28,861 - An app that has multiple - screens on our iPhone, or - 一个在iPhone或iPad上运行,有多个屏幕, - -1572 -01:09:28,863 --> 01:09:30,863 - an iPad, it's got three or - 在屏幕上有三个或四个不同的区域, - -1573 -01:09:30,865 --> 01:09:34,166 - four different areas on screen - where things are happening. - 都发生着事情。 - -1574 -01:09:34,168 --> 01:09:35,433 - How do we do that? - 我们该怎么做? - -1575 -01:09:35,435 --> 01:09:36,834 - Well, we're - essentially going to - 我们 - -1576 -01:09:36,836 --> 01:09:40,071 - combine multiple MVCs, okay? - 会结合多个MVC - -1577 -01:09:40,073 --> 01:09:47,244 - Because an MVC can use as part - of its view, another MVC. -因为一个MVC可以将另一个MVC当做视图的一部分。 - -1578 -01:09:47,246 --> 01:09:48,311 - Okay? - -1579 -01:09:48,313 --> 01:09:52,114 - So an MVC, - an entire MVC can be one of - 所以一个完整的MVC可以被一个稍大些的 - -1580 -01:09:52,116 --> 01:09:56,051 - the minions of - some bigger MVC. - MVC当做仆人使用。 - -1581 -01:09:56,053 --> 01:09:57,803 - 'Kay? - -1582 -01:09:57,804 --> 01:09:59,554 - And by doing that and - cascading it down, - 我们可以一层一层地这样堆叠, - -1583 -01:09:59,556 --> 01:10:01,756 - we can build more and - more complicated applications. - 就可以制作出越来越复杂的应用。 - -1584 -01:10:01,758 --> 01:10:07,561 - So, an example of this is, you - might have your calendar app, - 例如,你可能有一个日历应用, - -1585 -01:10:07,563 --> 01:10:09,930 - and it's showing you - the entire year. - 它展示给你一整年的信息。 - -1586 -01:10:09,932 --> 01:10:12,599 - And you click on a month, and - now it shows you a month view. - 随后你点击了一个月份,于是它展示给你月视图。 - -1587 -01:10:12,601 --> 01:10:14,567 - Well, a month view looks a lot - different than a year view. - 月视图看起来和年视图就不太一样了。 - -1588 -01:10:14,569 --> 01:10:17,503 - A month view just has all - the days and maybe some circle - 一个月视图只含有所有的日期,也许在日期上 - -1589 -01:10:17,505 --> 01:10:19,204 - that tells you where you have - an appointment on a day. - 会有一些通知你在某天会有任务的圈圈。 - -1590 -01:10:19,206 --> 01:10:20,939 - And then when you - click on a day, and - 随后,你点击了一天,然后你 - -1591 -01:10:20,941 --> 01:10:23,074 - now you get a day view, okay? - 获得了一个日视图 - -1592 -01:10:23,076 --> 01:10:25,043 - And the day is showing you - the hours and what all - 日视图会显示小时信息和这天你的所有 - -1593 -01:10:25,045 --> 01:10:27,611 - your appointments are, and you - click on the Appointment now - 任务,随后你点击了任务, - -1594 -01:10:27,613 --> 01:10:29,947 - you get an appointment view - and it showing the detail of -你会获得任务视图,它会显示任务的细节, - -1595 -01:10:29,949 --> 01:10:32,182 - where you're going and - when it is et cetera, okay? - 将要去哪,何时动身还有其它一些东西 - -1596 -01:10:32,184 --> 01:10:36,452 - Well, each of those views, - year view, month view, the day - 这些view中的每一个,年视图,月视图,日视图, - -1597 -01:10:36,454 --> 01:10:40,155 - view, and the appointment - view are their own MVCs. - 任务视图,都有他们自己的MVC。 - -1598 -01:10:40,157 --> 01:10:41,857 - Okay? - -1599 -01:10:41,858 --> 01:10:43,558 - But you can see how - the last three, okay, - 但是你可以发现,最后三个view, - -1600 -01:10:43,560 --> 01:10:47,628 - are used as essentially a - minion of the top level view, - 都被最顶层的年视图为了展示更多的细节 - -1601 -01:10:47,630 --> 01:10:51,032 - year view, - to show more detail, okay? - 而被当做仆人使用。 - -1602 -01:10:51,034 --> 01:10:52,766 - So the year view, - you click on a month, - 所以在年视图里,你点击了一个月份, - -1603 -01:10:52,768 --> 01:10:57,404 - it's going to use the month - view MVC to show more detail. - 它会利用月份视图的MVC来展现更多细节。 - -1604 -01:10:57,406 --> 01:11:00,406 - So it's part of its view, - okay? - 所以它是它视图的一部分, - -1605 -01:11:00,408 --> 01:11:03,476 - So, you see this also - in iOS with tab bar -所以你也在带有便签控制栏的iOS应用 - -1606 -01:11:03,478 --> 01:11:05,228 - controllers, right? - 中见过这些吧 - -1607 -01:11:05,229 --> 01:11:06,979 - You have the tab bar at - the bottom, I have four or - 在底部有一个标签栏,有四个或五个 - -1608 -01:11:06,981 --> 01:11:09,615 - five things you can choose. - 项可以供你选择。 - -1609 -01:11:09,616 --> 01:11:12,250 - Well there's some MVC at the - top whose has four pointers to - 在上面有一个MVC,它指向四个仆人, - -1610 -01:11:12,252 --> 01:11:15,120 - four minions, which are the - four MVCs that are each going -也就是将要出现在标签栏中的MVC, - -1611 -01:11:15,122 --> 01:11:17,488 - to appear in a tab bar, okay? - -1612 -01:11:17,490 --> 01:11:18,673 - We'll be doing that for - 我们将会做一个这方面的例子, - -1613 -01:11:18,674 --> 01:11:19,857 - example, in assignment - number two or - 在第二次或第三次作业,我们会 - -1614 -01:11:19,859 --> 01:11:21,792 - three where we'll be - making a tab bar and - 制作一个标签栏, - -1615 -01:11:21,794 --> 01:11:25,328 - you're gonna have to do - multiple MVCs, okay? - 你们将会学习如何使用多个MVC - -1616 -01:11:25,330 --> 01:11:28,531 - So, that basically results - in a picture looks kinda - 所以使用多个MVC的效果看起来就像 - -1617 -01:11:28,533 --> 01:11:29,899 - like this. - 这张图片一样。 - -1618 -01:11:29,901 --> 01:11:31,434 - All right? - -1619 -01:11:31,435 --> 01:11:32,968 - Where you got this MVC, and - 在你看到的这个MVC里, - -1620 -01:11:32,969 --> 01:11:34,502 - you see the purple one that's - like underneath the word - 找到'together'下面的那个 - -1621 -01:11:34,505 --> 01:11:37,239 - together there, and - 紫色的, - -1622 -01:11:37,240 --> 01:11:39,974 - it points to three other MVCs - outside of its view thing. - 它从view指向了另外三个MVC, - -1623 -01:11:39,977 --> 01:11:40,542 - Okay? - -1624 -01:11:41,478 --> 01:11:42,710 - That's how we're - going to build it, so - 这就是我们创建标签栏控制器的方式, - -1625 -01:11:42,712 --> 01:11:43,944 - that might be a tab - bar control and - 这些可能就是它的 - -1626 -01:11:43,946 --> 01:11:45,812 - those might be the three tabs. -三个标签。 - -1627 -01:11:45,814 --> 01:11:47,614 - Okay, and - each one is its own little MVC - 并且它们每一个都是 - -1628 -01:11:47,616 --> 01:11:50,249 - completely independent, - operates on its own. - 完全独立的,可以独自行动的小MVC。 - -1629 -01:11:50,251 --> 01:11:52,418 - Doesn't even know, - 这时它就是一个 - -1630 -01:11:52,419 --> 01:11:54,586 - it's a generic reusable view - like thing at this point. -普通的可重用的view之类的东西, - -1631 -01:11:54,589 --> 01:11:56,689 - Doesn't even know that - it's in a tab bar. - 它甚至不知道它在标签栏中。 - -1632 -01:11:56,691 --> 01:11:58,090 - Okay, it just knows that - it's supposed to do - 它只知道它应该做 - -1633 -01:11:58,092 --> 01:11:59,591 - whatever it does. - 这些事情。 - -1634 -01:11:59,593 --> 01:12:01,192 - And so - it's modular in that way. - 所以在这方面,它是模块化的。 - -1635 -01:12:01,194 --> 01:12:04,328 - You can also see that there's - no communication between any - 可以看到这里不再有其他箭头, - -1636 -01:12:04,330 --> 01:12:06,397 - other, there's no other - arrows, except for - 除了一些模型。 - -1637 -01:12:06,399 --> 01:12:08,249 - some of the models. - -1638 -01:12:08,250 --> 01:12:10,100 - You see some of the models are - communicating with each other. - 某些模型之间在互相通信。 - -1639 -01:12:10,102 --> 01:12:11,852 - You know a big - 要知道, - -1640 -01:12:11,853 --> 01:12:13,603 - application might have - a single shared model. - 一个大型的应用也许会有一个单独的共享模型。 - -1641 -01:12:13,605 --> 01:12:17,606 - Or the models might be split - off into pieces to be used by - 或者,模型会被分开来供子MVC使用。 - -1642 -01:12:18,876 --> 01:12:20,208 - sub MVCs. - -1643 -01:12:20,210 --> 01:12:21,326 - Okay? - But - 但是, - -1644 -01:12:21,327 --> 01:12:22,443 - that's the only kind of - communication you have there. - 这里只能使用这种通信方式。 - -1645 -01:12:22,446 --> 01:12:23,678 - All other communication is - 其它所有的通信 - -1646 -01:12:23,680 --> 01:12:26,681 - either the structure view - communication we saw on MVC, - 要么是MVC中的结构化通信, - -1647 -01:12:26,683 --> 01:12:29,716 - or it's using MVCs as part - of the view of another MVC. - 要么是将MVC用作另一个MVC视图的一部分。 - -1648 -01:12:31,386 --> 01:12:32,385 - Any question about that? - 有问题吗? - -1649 -01:12:33,688 --> 01:12:36,689 - So we definitely don't want - to be having designs that - 所以我们当然不希望设计成这样, - -1650 -01:12:36,691 --> 01:12:38,190 - look like this, okay? - -1651 -01:12:38,192 --> 01:12:39,824 - Where everybody's - talking to everybody. - 所有都在互相通信, - -1652 -01:12:39,826 --> 01:12:41,459 - We can't tell who's - talking to what. - 我们不能分清谁在和什么通信。 - -1653 -01:12:41,461 --> 01:12:43,994 - It's just impossible to debug - a program like this, and - 这会让调试程序变得异常艰难, - -1654 -01:12:43,996 --> 01:12:45,446 - it doesn't scale. - 而且它无法规模化。 - -1655 -01:12:45,447 --> 01:12:46,897 - You can't build really - big programs this way. - 你不能通过这种方式创建出大程序。 - -1656 -01:12:46,899 --> 01:12:48,165 - It just becomes impossible to - 这样的话, - -1657 -01:12:48,167 --> 01:12:51,634 - know how touching anything - would break everything, right? - 你无法弄清楚,什么地方会引发整个程序的崩溃。 - -1658 -01:12:51,636 --> 01:12:53,469 - So we're definitely not - going to be doing that. - 所以我们绝对不会这样做的。 - -1659 -01:12:54,639 --> 01:12:57,573 - All right so that's MVC and, - 所以,这就是MVC, - -1660 -01:12:57,575 --> 01:13:00,875 - like I say, on Monday we'll - apply MVC to our calculator. - 我们将会在周一的课里把MVC应用到我们的计算器程序中。 - -1661 -01:13:01,845 --> 01:13:02,977 - So what's coming up? - 所以,接下来是什么? - -1662 -01:13:02,979 --> 01:13:06,146 - I always try to get to - this slide every lecture. - 我每节课都尽量讲到这里, - -1663 -01:13:06,148 --> 01:13:09,716 - Sometimes I forget but - it's posted in the slides. - 有时我会忘记,但是它被放到了课件中。 - -1664 -01:13:09,718 --> 01:13:12,018 - It says tomorrow is Friday. - 周五也就是明天, - -1665 -01:13:12,020 --> 01:13:14,320 - No, day after - tomorrow is Friday. - 不对,后天的周五, - -1666 -01:13:14,322 --> 01:13:17,256 - And people who - are watching on iTunes U, - 在iTunes U上观看的同学们, - -1667 -01:13:17,258 --> 01:13:19,858 - these Friday sections will - not be on iTunes U so - 周五的部分不会被放到iTunes U上, - -1668 -01:13:19,860 --> 01:13:22,461 - don't go looking for - them only the normal Monday, - 只有周一和周三的课件才会被放上去, - -1669 -01:13:22,463 --> 01:13:24,596 - Wednesday lectures - went on iTunes U. - 所以不要到处找。 - -1670 -01:13:25,999 --> 01:13:27,164 - But, for Stanford students, - 但是对于在坐的同学, - -1671 -01:13:27,166 --> 01:13:30,300 - Friday we have this debugger - section we talked about. - 周五我们将讨论之前谈到的调试部分。 - -1672 -01:13:30,302 --> 01:13:32,769 - And then next Monday, - 下周一,你们的阅读作业 - -1673 -01:13:32,771 --> 01:13:35,638 - your reading assignment - is gonna be due. - 将会截至。 - -1674 -01:13:35,640 --> 01:13:37,040 - In other words, - you should be done with that - 换句话说,你应当在周一上课之前 - -1675 -01:13:37,042 --> 01:13:40,176 - reading assignment before - the start of Monday's lecture. - 完成阅读作业。 - -1676 -01:13:40,178 --> 01:13:43,045 - And I'm gonna assign you - another reading assignment. - 我会再布置给你们一个阅读作业。 - -1677 -01:13:43,047 --> 01:13:45,180 - It might be your only - other reading assignment. - 它将会是你们最后一个阅读作业。 - -1678 -01:13:45,182 --> 01:13:46,815 - Perhaps there'll be - a reassignment three, - 也许以后还会有阅读作业, - -1679 -01:13:46,817 --> 01:13:48,383 - but it won't be any - more than that. - 但是不会像那个一样多。 - -1680 -01:13:49,318 --> 01:13:50,351 - And then on Wednesday I'm - 下周三,我会深入介绍 - -1681 -01:13:50,353 --> 01:13:53,420 - really gonna dive into - swift and foundation. - Swift语言和Foundation框架。 - -1682 -01:13:53,422 --> 01:13:56,556 - I'm gonna talk a little bit - about the Objective C legacy, - 我将会介绍一点遗留下来的Objective-C。 - -1683 -01:13:57,625 --> 01:13:59,425 - and then your assignment - one is gonna be - 你们的作业一将会在 - -1684 -01:13:59,427 --> 01:14:00,792 - due a week from today. - 一周后截至。 - -1685 -01:14:00,794 --> 01:14:05,129 - It's been posted for you, and - your assignment two is gonna - 你们已经看到了,作业二将会在 - -1686 -01:14:05,131 --> 01:14:08,032 - go out next Wednesday and be - due the Wednesday after that. - 下周三布置下去,下下周三截至。 - -1687 -01:14:08,034 --> 01:14:09,900 - Just for a little bit of - advanced planning for - 提前为你们所有人 - -1688 -01:14:09,902 --> 01:14:11,335 - all of you. - 做一些计划。 - -1689 -01:14:11,337 --> 01:14:12,235 - Okay? - -1690 -01:14:12,237 --> 01:14:13,202 - Any other questions? - 还有问题吗? - -1691 -01:14:14,439 --> 01:14:15,904 - Okay, thank you. - 好的,谢谢。 - -1692 -01:14:15,906 --> 01:14:19,808 - >> For more, please visit - us at stanford.edu. - >> 想了解更多,请登录 stanford.edu diff --git a/3. Applying MVC.srt b/3. Applying MVC.srt deleted file mode 100644 index 25d6aac..0000000 --- a/3. Applying MVC.srt +++ /dev/null @@ -1,8375 +0,0 @@ -1 -00:00:00,001 --> 00:00:04,636 - [MUSIC] - -2 -00:00:04,638 --> 00:00:07,171 - Stanford University. - -3 -00:00:07,173 --> 00:00:09,807 - [BLANK_AUDIO] - -4 -00:00:09,809 --> 00:00:13,343 - >> Okay, well welcome to - CS193p, Winter 2015. - -5 -00:00:13,345 --> 00:00:15,445 - This is Lecture 3. - -6 -00:00:15,447 --> 00:00:17,714 - This is gonna be all demo. - -7 -00:00:17,716 --> 00:00:21,283 - today, my voice is mostly - recovered from last week, - -8 -00:00:21,285 --> 00:00:22,918 - not 100% as you can tell. - -9 -00:00:22,920 --> 00:00:23,985 - But it's getting there. - -10 -00:00:25,455 --> 00:00:29,924 - So what we're gonna be doing - today is a demo. - -11 -00:00:29,926 --> 00:00:31,825 - We're gonna extend our - calculator a little bit, - -12 -00:00:31,827 --> 00:00:33,460 - we're gonna make it more - powerful. - -13 -00:00:33,462 --> 00:00:36,629 - But more importantly, we're - gonna have it obey this MVC - -14 -00:00:36,631 --> 00:00:37,930 - design paradigm. - -15 -00:00:37,932 --> 00:00:39,682 - 'Kay? - -16 -00:00:39,683 --> 00:00:41,433 - So it's good, a pretty good - example of showing how - -17 -00:00:41,436 --> 00:00:44,670 - we're gonna separate the stuff - into the camps here. - -18 -00:00:44,672 --> 00:00:46,138 - Now, we're gonna cover a bunch - of other things, - -19 -00:00:46,140 --> 00:00:48,473 - language features and stuff as - I always do. - -20 -00:00:48,475 --> 00:00:52,143 - That's really the primary goal - of these first three lectures - -21 -00:00:52,145 --> 00:00:54,078 - with the demo. - -22 -00:00:54,079 --> 00:00:56,012 - So I just mean for you to see - it in action because you can - -23 -00:00:56,015 --> 00:00:59,750 - read all you want about swift - or, about iOS, but until you - -24 -00:00:59,752 --> 00:01:02,619 - actually see it act, turning - into an app, it's not real. - -25 -00:01:02,621 --> 00:01:04,420 - So I'm just trying to make it - real for you. - -26 -00:01:06,057 --> 00:01:08,590 - I'm going to go to my last - slide, because, - -27 -00:01:08,592 --> 00:01:11,093 - once I go to the demo, I'll - forget to come back. - -28 -00:01:11,095 --> 00:01:13,895 - Which is just the what's - coming up in this class. - -29 -00:01:13,897 --> 00:01:17,031 - On Wednesday, it's gonna be no - demo, it's gonna be all - -30 -00:01:17,033 --> 00:01:19,967 - slides, it's going to be one - of the few lectures where it's - -31 -00:01:19,969 --> 00:01:21,185 - all slides. - -32 -00:01:21,186 --> 00:01:22,402 - But what I'm gonna try to do, - -33 -00:01:22,405 --> 00:01:25,205 - on Wednesday, is give you the - highlights of this all - -34 -00:01:25,207 --> 00:01:27,307 - this reading that you're - doing. - -35 -00:01:27,309 --> 00:01:28,658 - Okay? - Because you're - -36 -00:01:28,659 --> 00:01:30,008 - reading a lot of stuff and - it's sometimes hard to - -37 -00:01:30,011 --> 00:01:32,611 - tell what's really important - in there and what's not. - -38 -00:01:32,613 --> 00:01:34,279 - So I'm gonna kinda give you - the highlights so - -39 -00:01:34,281 --> 00:01:36,448 - you can get an idea of what's - important. - -40 -00:01:36,450 --> 00:01:40,618 - And then I'm also gonna start - talking about some of - -41 -00:01:40,620 --> 00:01:45,255 - the foundation layer API in - IOS that's the non you, - -42 -00:01:45,257 --> 00:01:47,891 - user interface layer basically - and - -43 -00:01:47,893 --> 00:01:51,227 - kinda what some of the classes - are in there. - -44 -00:01:51,229 --> 00:01:54,130 - And then also just a little - bit of how we use the language - -45 -00:01:54,132 --> 00:01:57,099 - features of swift, and - foundation, in iOS so - -46 -00:01:57,101 --> 00:02:00,169 - that you can kinda get this - kind of your, this want, - -47 -00:02:00,171 --> 00:02:01,870 - next Wednesday's lecture is, - -48 -00:02:01,872 --> 00:02:03,772 - is gonna be your baseline - lecture, - -49 -00:02:03,774 --> 00:02:07,241 - can kinda get you grounded in - how to do all this stuff. - -50 -00:02:07,243 --> 00:02:10,044 - And then next week we'll start - diving in, - -51 -00:02:10,046 --> 00:02:13,814 - to build a more sophisticated - iOS application. - -52 -00:02:13,816 --> 00:02:15,682 - Okay, I know this is kind of a - new whirlwind in first two - -53 -00:02:15,684 --> 00:02:18,752 - weeks, you're learning a new - language, all new system. - -54 -00:02:18,754 --> 00:02:20,920 - But hopefully by the end of - this week and the end of your - -55 -00:02:20,922 --> 00:02:24,757 - second assignment which will - go out on Wednesday you'll be - -56 -00:02:24,759 --> 00:02:26,225 - pretty confident that you'll - at least, - -57 -00:02:26,227 --> 00:02:30,595 - you know, have a, solid ground - foundation to build from, - -58 -00:02:30,597 --> 00:02:31,662 - no pun intended there. - -59 -00:02:33,032 --> 00:02:36,767 - There's a holiday weekend this - weekend no Friday section and - -60 -00:02:36,769 --> 00:02:39,603 - no class on Monday until we - resume next Wednesday, and - -61 -00:02:39,605 --> 00:02:42,305 - the primary thing I'm gonna do - next Wednesday, - -62 -00:02:42,307 --> 00:02:44,341 - not day after tomorrow but - -63 -00:02:44,342 --> 00:02:46,376 - the next Wednesday, is talk a - little more about auto layout. - -64 -00:02:46,378 --> 00:02:49,445 - Cause you've only just seen - kind of a glimpse of auto - -65 -00:02:49,447 --> 00:02:51,013 - layouts so far and - -66 -00:02:51,015 --> 00:02:53,849 - I haven't even really told you - how to do auto layout and so - -67 -00:02:53,851 --> 00:02:55,383 - you're kinda just fumbling - around and trying, - -68 -00:02:55,385 --> 00:02:58,619 - trying to reproduce what I do - so next Wednesday we'll - -69 -00:02:58,621 --> 00:03:01,588 - talk about how to really do - auto layout hm, and all that. - -70 -00:03:02,825 --> 00:03:05,225 - 'Kay, any questions before I - dive into this demo? - -71 -00:03:06,194 --> 00:03:10,396 - Hopefully my voice will hold - out I can already hear it - -72 -00:03:10,398 --> 00:03:14,065 - starting to not hold out but - we will see. - -73 -00:03:14,067 --> 00:03:15,266 - All right. - -74 -00:03:15,268 --> 00:03:21,839 - So, I'm going to just go to - Xcode here, launch Xcode. - -75 -00:03:22,941 --> 00:03:25,942 - And we're gonna leave off - right where we, were, - -76 -00:03:25,944 --> 00:03:27,410 - last time, in the calculator. - -77 -00:03:28,846 --> 00:03:32,681 - There it is right here, and so - these are UI. - -78 -00:03:32,683 --> 00:03:34,783 - Hopefully you recognize that - and you did, - -79 -00:03:34,785 --> 00:03:36,051 - did your homework. - -80 -00:03:36,053 --> 00:03:38,070 - I hope. - -81 -00:03:38,071 --> 00:03:40,088 - And here is this area that I - selected at the end, - -82 -00:03:40,090 --> 00:03:43,290 - which is this area that's - really has not, - -83 -00:03:43,292 --> 00:03:47,928 - this is not about how, how the - calculator gets presented on - -84 -00:03:47,930 --> 00:03:51,064 - screen, this blue area is - about how the calculator is - -85 -00:03:51,066 --> 00:03:52,165 - a calculator, okay? - -86 -00:03:52,167 --> 00:03:54,367 - This is where all our - calculations are and - -87 -00:03:54,369 --> 00:03:57,302 - this blue area really - shouldn't be in this class, - -88 -00:03:57,304 --> 00:04:00,839 - this view controller class - because this is the C - -89 -00:04:00,841 --> 00:04:01,973 - of our MVC, okay. - -90 -00:04:01,975 --> 00:04:06,910 - And our MVC, this is the C, - this is the V, the view, - -91 -00:04:06,912 --> 00:04:09,546 - these are the minions that - this controller's using. - -92 -00:04:09,548 --> 00:04:11,948 - And today we're gonna create - the M. - -93 -00:04:11,950 --> 00:04:13,349 - Okay? - The model. - -94 -00:04:13,351 --> 00:04:15,351 - The model is gonna be what our - calcu, - -95 -00:04:15,353 --> 00:04:18,854 - what our application is, which - is, it's a calculator. - -96 -00:04:18,856 --> 00:04:20,155 - 'Kay? - -97 -00:04:20,157 --> 00:04:23,758 - We're also going to enhance - our calculator the primary new - -98 -00:04:23,760 --> 00:04:26,360 - feature we're gonna give our - calculator is that - -99 -00:04:26,362 --> 00:04:30,030 - our calculators model is gonna - remember every operand and - -100 -00:04:30,032 --> 00:04:32,833 - operation you ever asked it to - do. - -101 -00:04:32,835 --> 00:04:38,271 - Okay, so right now as we do - operations we consume all - -102 -00:04:38,273 --> 00:04:39,505 - the operands. - -103 -00:04:39,507 --> 00:04:41,040 - 'Kay, they consume, kinda, - they're gone. - -104 -00:04:42,276 --> 00:04:43,792 - So in this case, - -105 -00:04:43,793 --> 00:04:45,309 - we're going to actually - collect all the operations and - -106 -00:04:45,312 --> 00:04:48,346 - operands in our, in a stack - and then we can - -107 -00:04:48,348 --> 00:04:53,350 - ask the model to, evaluate - that stack of operations and - -108 -00:04:53,352 --> 00:04:55,385 - operands at any time we want. - -109 -00:04:55,387 --> 00:04:57,654 - And the reason we're adding - that ability is because your - -110 -00:04:57,656 --> 00:05:00,256 - homework, assignment number - two, you're gonna add two - -111 -00:05:00,258 --> 00:05:03,726 - major features where having - all the operands and the - -112 -00:05:03,728 --> 00:05:06,628 - operations in a stack is gonna - be really valuable to you. - -113 -00:05:06,630 --> 00:05:09,264 - So you'll be starting your - second homework with what I - -114 -00:05:09,266 --> 00:05:12,334 - do today cause you'll need - this capability to do what I - -115 -00:05:12,336 --> 00:05:13,735 - ask you there. - -116 -00:05:13,737 --> 00:05:14,902 - Okay, and I'll talk about that - at the end. - -117 -00:05:14,904 --> 00:05:17,237 - If I forget to talk about - that, remind me. - -118 -00:05:17,239 --> 00:05:18,805 - Say, tell us about assignment - two. - -119 -00:05:20,175 --> 00:05:21,240 - Okay. - -120 -00:05:21,242 --> 00:05:22,908 - So, how do we create a new - class. - -121 -00:05:22,910 --> 00:05:25,911 - Because we're gonna put our - model, 'kay, the calculator, - -122 -00:05:25,913 --> 00:05:28,680 - kind of, it, it's the guts, in - a different class. - -123 -00:05:28,682 --> 00:05:31,983 - So how do we create a new - class, in Xcode. - -124 -00:05:31,985 --> 00:05:33,651 - We do that up here from the - File menu. - -125 -00:05:33,653 --> 00:05:35,619 - We go, New > File. - -126 -00:05:35,621 --> 00:05:38,489 - So, you're gonna do File menu - > New > File for a lot of - -127 -00:05:38,491 --> 00:05:41,291 - different things you're gonna - add to your project. - -128 -00:05:41,293 --> 00:05:43,693 - Not even just, new classes or - -129 -00:05:43,695 --> 00:05:46,863 - whatever, but, when you click - that you're gonna see - -130 -00:05:46,865 --> 00:05:48,497 - there's a lot of different - things you could add. - -131 -00:05:48,499 --> 00:05:49,865 - And, we're in iOS, so - -132 -00:05:49,867 --> 00:05:52,267 - you're gonna click on this iOS - thing at the top. - -133 -00:05:52,269 --> 00:05:53,635 - And we wanna add a source - file. - -134 -00:05:53,637 --> 00:05:56,671 - And over here we're gonna be - doing this later in - -135 -00:05:56,673 --> 00:06:00,941 - the quarter, this is how we - basically add subclasses of - -136 -00:06:00,943 --> 00:06:04,378 - iOS classes, Co, Cocoa Touch - classes. - -137 -00:06:04,380 --> 00:06:06,446 - But we're gonna do today this - one Swift File, - -138 -00:06:06,448 --> 00:06:08,948 - you can see it's an empty - Swift File. - -139 -00:06:08,950 --> 00:06:11,517 - And since our model is - completely UI independent it - -140 -00:06:11,519 --> 00:06:15,287 - doesn't inherit, it doesn't - subclass any IOS class or - -141 -00:06:15,289 --> 00:06:17,923 - anything, it's just a basic, - Swift File. - -142 -00:06:17,925 --> 00:06:19,824 - So I'm gonna pick on this - Swift File, - -143 -00:06:19,826 --> 00:06:23,394 - click Next, and now it wants - to know the name of - -144 -00:06:23,396 --> 00:06:26,564 - it and where we wanna put it, - and we're gonna put it in - -145 -00:06:26,566 --> 00:06:29,466 - the same place that all our - other swift files are. - -146 -00:06:29,468 --> 00:06:30,901 - Here's our Controller and - -147 -00:06:30,902 --> 00:06:32,335 - this AppDelegate, we moved it - out of the way at the very - -148 -00:06:32,338 --> 00:06:34,571 - beginning of the very first - lecture but it's in there too. - -149 -00:06:34,573 --> 00:06:36,439 - So we want to put it in this - same directory. - -150 -00:06:36,441 --> 00:06:41,910 - And we're gonna call this new - class CalculatorBrain. - -151 -00:06:41,912 --> 00:06:43,645 - Now, you don't have to have - the name of - -152 -00:06:43,647 --> 00:06:47,048 - this Swift File here be the - name of the primary class but - -153 -00:06:47,050 --> 00:06:48,049 - we always do that. - -154 -00:06:48,051 --> 00:06:49,617 - It would be kinda confusing to - -155 -00:06:49,619 --> 00:06:52,019 - people a little bit if the - name of the Swift File - -156 -00:06:52,021 --> 00:06:54,554 - was different than whatever - the primary class is in there. - -157 -00:06:54,556 --> 00:06:55,755 - But it's certainly legal. - -158 -00:06:55,757 --> 00:06:56,422 - All right. - -159 -00:06:56,424 --> 00:06:57,556 - And Swift, the name of - -160 -00:06:57,558 --> 00:06:58,857 - the file really doesn't mean - anything. - -161 -00:06:58,859 --> 00:07:00,359 - It's what's inside that - matters. - -162 -00:07:00,361 --> 00:07:03,461 - But, CalculatorBrain is gonna - be the name of our class, - -163 -00:07:03,463 --> 00:07:04,929 - our model. - -164 -00:07:04,930 --> 00:07:06,396 - I'm calling it that cause it's - the brain of our calculator, - -165 -00:07:06,399 --> 00:07:07,898 - I'm trying to pick a - descriptive name. - -166 -00:07:09,201 --> 00:07:12,302 - Notice the capitalization - here, - -167 -00:07:12,304 --> 00:07:16,306 - types in swift, we always - capitalize them. - -168 -00:07:16,308 --> 00:07:19,409 - And we do not put underbars - and other stuff in there. - -169 -00:07:19,411 --> 00:07:20,609 - Okay? - We use what's called this - -170 -00:07:20,611 --> 00:07:25,380 - camel notation here, where - every word gets capitalized, - -171 -00:07:25,382 --> 00:07:27,882 - including the first name, word - for types. - -172 -00:07:27,884 --> 00:07:31,219 - Everything else, we don't - capitalize. - -173 -00:07:31,221 --> 00:07:34,755 - So property names and things - like that, function names, - -174 -00:07:34,757 --> 00:07:36,457 - those all start with lower - case, - -175 -00:07:36,459 --> 00:07:38,992 - they still do the uppercase - and the other words. - -176 -00:07:38,994 --> 00:07:40,427 - That way we, in our reading - our code we - -177 -00:07:40,429 --> 00:07:43,196 - can really quickly pick out - what to type and what to not. - -178 -00:07:43,198 --> 00:07:45,164 - 'Kay? - So please adhere to that. - -179 -00:07:45,166 --> 00:07:48,334 - If you don't, you're gonna - look like a newb out there. - -180 -00:07:48,336 --> 00:07:49,501 - 'Kay. - Calculator brains what we're - -181 -00:07:49,503 --> 00:07:50,835 - gonna call it, I'm gonna - create it. - -182 -00:07:51,938 --> 00:07:53,121 - Here it is right here. - -183 -00:07:53,122 --> 00:07:54,305 - I'm gonna make it my whole - screen. - -184 -00:07:55,541 --> 00:07:58,975 - You can see that the import - here is not import UI kit, - -185 -00:07:58,977 --> 00:08:00,477 - it's import Foundation. - -186 -00:08:00,479 --> 00:08:03,379 - Foundation is that layer, that - kinda core services layer I - -187 -00:08:03,381 --> 00:08:05,581 - talked about in the first - lecture. - -188 -00:08:05,583 --> 00:08:07,883 - It don't have many UI stuff in - it which is good because our - -189 -00:08:07,885 --> 00:08:11,687 - model is UI independent so - there should be no UI in here. - -190 -00:08:11,689 --> 00:08:15,957 - So we would never be importing - UI kit into a model class, - -191 -00:08:15,959 --> 00:08:17,392 - 'kay? - -192 -00:08:17,393 --> 00:08:18,826 - You can feel free to stop me, - by the way, - -193 -00:08:18,828 --> 00:08:19,793 - if you have any questions. - -194 -00:08:19,795 --> 00:08:22,095 - All right, so we're gonna - create a new class, - -195 -00:08:22,097 --> 00:08:23,029 - you already know how to do - that. - -196 -00:08:23,031 --> 00:08:24,364 - We just type class and - -197 -00:08:24,366 --> 00:08:27,500 - then the name of the class, - it's gonna be CalculatorBrain. - -198 -00:08:27,502 --> 00:08:31,336 - Now, this class is not going - to inherit from any other - -199 -00:08:31,338 --> 00:08:32,537 - class, 'kay? - -200 -00:08:32,539 --> 00:08:35,640 - Just gonna be a basic swift, - class. - -201 -00:08:35,642 --> 00:08:38,509 - Now sometimes your model might - inherit from a class called - -202 -00:08:38,511 --> 00:08:40,861 - NSObject, and - -203 -00:08:40,862 --> 00:08:43,212 - I'll talk about that a little - later maybe on Wednesday even. - -204 -00:08:43,215 --> 00:08:46,683 - You'll get a little bit if you - inherit from NSObject, but - -205 -00:08:46,685 --> 00:08:50,587 - we're just gonna have it be - basic swift base class, 'kay. - -206 -00:08:50,589 --> 00:08:52,388 - It doesn't, doesn't need to - inherit any functionality. - -207 -00:08:53,691 --> 00:08:55,224 - Okay. - -208 -00:08:55,225 --> 00:08:56,758 - So what's gonna be our data - structure of - -209 -00:08:56,761 --> 00:08:57,859 - our calculator brain. - -210 -00:08:57,861 --> 00:08:59,961 - It, it has to be a little - different than the data - -211 -00:08:59,963 --> 00:09:01,662 - structure we used in our - controller to - -212 -00:09:01,664 --> 00:09:04,565 - capture the operand because we - gotta capture operand, - -213 -00:09:04,567 --> 00:09:07,368 - operations and operands both - into this. - -214 -00:09:07,370 --> 00:09:12,305 - So we want it to be a stack, - I'm gonna call it opStack and - -215 -00:09:12,307 --> 00:09:14,741 - but the type can't be array of - double. - -216 -00:09:15,743 --> 00:09:20,245 - Okay, because operands are - doubles but operations - -217 -00:09:20,247 --> 00:09:23,648 - are like a combination of a - syn, a mathematical symbol - -218 -00:09:23,650 --> 00:09:26,651 - like plus, times and then also - a function. - -219 -00:09:26,653 --> 00:09:29,186 - Function that actually does - the thing, 'kay? - -220 -00:09:29,188 --> 00:09:30,888 - So obviously we can't do that - so - -221 -00:09:30,890 --> 00:09:32,022 - we're gonna have to need some, - -222 -00:09:32,024 --> 00:09:34,691 - some new data structure I'm - gonna call that data - -223 -00:09:34,693 --> 00:09:37,760 - structure op and we're gonna - define that in a second. - -224 -00:09:37,762 --> 00:09:41,663 - So op is gonna be something - that could be an operand or - -225 -00:09:41,665 --> 00:09:43,532 - maybe it could be an - operation. - -226 -00:09:43,534 --> 00:09:45,233 - 'Kay? - It could be either or. - -227 -00:09:45,235 --> 00:09:47,519 - 'Kay? - -228 -00:09:47,520 --> 00:09:49,804 - Now a couple of things about - this here is of course I - -229 -00:09:49,806 --> 00:09:51,572 - have to initialize this so I'm - gonna do - -230 -00:09:51,574 --> 00:09:54,575 - the exact same thing that I - did in the controller which is - -231 -00:09:54,577 --> 00:09:56,810 - I'm just gonna create an empty - array of op. - -232 -00:09:56,812 --> 00:09:59,496 - 'Kay? - And - -233 -00:09:59,497 --> 00:10:02,181 - I'm even gonna use a little - different syntax, 'kay? - -234 -00:10:02,183 --> 00:10:03,382 - We've been using this. - -235 -00:10:03,384 --> 00:10:05,851 - I like this syntax because - especially for - -236 -00:10:05,853 --> 00:10:08,553 - people who are first time to - swift it's very clear, - -237 -00:10:08,555 --> 00:10:12,624 - this is an array and inside - the array are these ops but - -238 -00:10:12,626 --> 00:10:17,661 - this is evidently not the - syntax that is preferred. - -239 -00:10:17,663 --> 00:10:23,433 - The preferred syntax is - actually to do [Op] 'kay? - -240 -00:10:23,435 --> 00:10:27,070 - So this is just an alternate - syntax, putting square - -241 -00:10:27,072 --> 00:10:29,739 - brackets with the type in the - middle for declaring an array. - -242 -00:10:29,741 --> 00:10:32,008 - It's exactly the same thing - just different way of - -243 -00:10:32,010 --> 00:10:34,276 - typing in, identical in every - possible way, - -244 -00:10:34,278 --> 00:10:35,777 - it's exactly the same. - -245 -00:10:35,779 --> 00:10:37,062 - Okay. - -246 -00:10:37,063 --> 00:10:38,346 - I think this is a little bit - preferred because if - -247 -00:10:38,348 --> 00:10:41,449 - you ever initialize an array - which will see later. - -248 -00:10:41,451 --> 00:10:43,884 - You use this syntax to create - the array and - -249 -00:10:43,886 --> 00:10:45,686 - put things in it. - -250 -00:10:45,687 --> 00:10:47,487 - So I, I can understand why - they do that. - -251 -00:10:47,490 --> 00:10:50,257 - Okay? - So this is an array of op. - -252 -00:10:50,259 --> 00:10:50,924 - That make sense? - -253 -00:10:51,860 --> 00:10:53,859 - Now, let's talk about op. - -254 -00:10:53,861 --> 00:10:55,094 - What kinda thing should op be? - -255 -00:10:55,096 --> 00:10:57,596 - Well, we could make op a - class. - -256 -00:10:57,598 --> 00:10:59,731 - An op could have a property - for op, - -257 -00:10:59,733 --> 00:11:02,033 - for an operand, which would be - the value of the operand. - -258 -00:11:02,035 --> 00:11:05,169 - It could have another - property, which is the, - -259 -00:11:05,171 --> 00:11:07,371 - symbol, mathematical symbol - for the operation and - -260 -00:11:07,373 --> 00:11:10,173 - another property, which was a - function, which does it, - -261 -00:11:10,175 --> 00:11:12,509 - and obviously, if the operand - is set, - -262 -00:11:12,511 --> 00:11:15,144 - then the other two would be - not set and vice versa. - -263 -00:11:15,146 --> 00:11:18,481 - But that, that's a little bit - weird to have a class that - -264 -00:11:18,483 --> 00:11:21,250 - has properties that sometimes - they're set and, - -265 -00:11:21,252 --> 00:11:23,218 - and if other things are set, - they're not set. - -266 -00:11:23,220 --> 00:11:24,285 - It's really not what we want. - -267 -00:11:24,287 --> 00:11:27,621 - What we really want is an - enum. - -268 -00:11:28,591 --> 00:11:31,658 - Okay, so you're probably used - to enums in other languages so - -269 -00:11:31,660 --> 00:11:32,959 - I'm gonna create an ema, - -270 -00:11:32,961 --> 00:11:35,728 - [UNKNOWN] enum, it looks very - similar creating a class. - -271 -00:11:35,730 --> 00:11:38,397 - I just use the word enum - instead of class, - -272 -00:11:38,399 --> 00:11:41,633 - obviously no inheritance for - enum, sorry. - -273 -00:11:41,635 --> 00:11:45,537 - But enums can have functions, - just like the class, - -274 -00:11:45,539 --> 00:11:49,474 - they can also have properties - but only computed properties. - -275 -00:11:49,476 --> 00:11:51,242 - 'Kay, the Camry's stored - properties. - -276 -00:11:52,278 --> 00:11:55,779 - So you know enums are kinda - for basic types and - -277 -00:11:55,781 --> 00:11:58,782 - enums are really great when - you have something that can be - -278 -00:11:58,784 --> 00:12:01,317 - one thing one time and a - different thing another time. - -279 -00:12:01,319 --> 00:12:02,585 - And never both at the same - time, - -280 -00:12:02,587 --> 00:12:03,952 - that's kinda what enums are - right, - -281 -00:12:03,954 --> 00:12:06,421 - they're enumerating different - possibilities so - -282 -00:12:06,423 --> 00:12:09,257 - we could say you know case - operand and we could have - -283 -00:12:09,259 --> 00:12:15,563 - a case operation, to have the - different things that we have. - -284 -00:12:15,565 --> 00:12:19,133 - Now, in other languages, this - would be as far as we can go. - -285 -00:12:19,135 --> 00:12:21,101 - And this would be pretty - useless. - -286 -00:12:21,103 --> 00:12:24,270 - Because if we had an array - that just said whether it - -287 -00:12:24,272 --> 00:12:26,105 - was an operand or an - operation, that doesn't help. - -288 -00:12:26,107 --> 00:12:27,973 - I need the actual operand. - -289 -00:12:27,975 --> 00:12:30,242 - I need the operations - mathematical symbol and - -290 -00:12:30,244 --> 00:12:31,977 - its function. - -291 -00:12:31,978 --> 00:12:33,711 - I need them, they have to be - in this e-mail. - -292 -00:12:33,714 --> 00:12:36,448 - And Swift has a really cool - feature where you can - -293 -00:12:36,450 --> 00:12:41,085 - associate data with any of the - cases in the e-mail. - -294 -00:12:41,087 --> 00:12:44,021 - So for an operand I'm gonna - associate the data double. - -295 -00:12:45,123 --> 00:12:48,157 - So if my enum is an operand - it'll have this - -296 -00:12:48,159 --> 00:12:49,558 - double associated with it, - -297 -00:12:49,560 --> 00:12:52,194 - that's gonna be the value of - the operand. - -298 -00:12:52,196 --> 00:12:54,013 - And similarly for - -299 -00:12:54,014 --> 00:12:55,831 - operation I'm actually gonna - do unary operation first, - -300 -00:12:55,833 --> 00:12:57,866 - that's a single argument - operation. - -301 -00:12:57,868 --> 00:13:00,768 - I'm gonna have a string which - is gonna be the symbol, - -302 -00:13:00,770 --> 00:13:01,936 - the mathematical symbol for - -303 -00:13:01,938 --> 00:13:04,238 - it and of course I'm gonna - have a function. - -304 -00:13:05,341 --> 00:13:08,408 - Okay again functions are just - types in swift, - -305 -00:13:08,410 --> 00:13:11,344 - it's no different than string - 'kay we're just saying this is - -306 -00:13:11,346 --> 00:13:13,612 - a function, put a function in - there. - -307 -00:13:13,614 --> 00:13:15,147 - A lot of times we'll do the - curly braces and - -308 -00:13:15,149 --> 00:13:17,883 - put a closure use closures to - create our function but - -309 -00:13:17,885 --> 00:13:19,584 - we could create actual - functions and - -310 -00:13:19,586 --> 00:13:21,185 - pass them in there, that's - fine. - -311 -00:13:21,187 --> 00:13:24,121 - So, and we'd also want a - binary function here that - -312 -00:13:24,123 --> 00:13:25,289 - takes two arguments. - -313 -00:13:26,959 --> 00:13:28,625 - Binary operation and - -314 -00:13:28,627 --> 00:13:30,726 - just those two arguments here - in it's function. - -315 -00:13:32,963 --> 00:13:34,296 - Okay? - -316 -00:13:34,297 --> 00:13:35,630 - So now we have the stack. - -317 -00:13:35,632 --> 00:13:37,499 - Okay. - Which is an array of ops. - -318 -00:13:37,501 --> 00:13:41,369 - And these ops are either each - op in this, is array is either - -319 -00:13:41,371 --> 00:13:44,638 - an operand or it's one of - these two kinds of operations. - -320 -00:13:46,308 --> 00:13:49,142 - Okay so so this is great. - -321 -00:13:49,144 --> 00:13:53,979 - We got this op it's either an - operation or an operand. - -322 -00:13:53,981 --> 00:13:56,882 - How are we going to, you know, - put things into - -323 -00:13:56,884 --> 00:13:59,251 - this op stack for example and - something like that. - -324 -00:13:59,253 --> 00:14:01,653 - So let, let's go talk about, - the API. - -325 -00:14:01,655 --> 00:14:05,356 - A, API stands for application - programing interface. - -326 -00:14:05,358 --> 00:14:09,060 - API is kind of the meth, all - the methods and properties - -327 -00:14:09,062 --> 00:14:13,230 - that make up your class, the - description of them. - -328 -00:14:13,232 --> 00:14:16,066 - So I'll use that word a lot, - API. - -329 -00:14:16,068 --> 00:14:18,835 - And we really need to be able - to put an operand on there and - -330 -00:14:18,837 --> 00:14:20,736 - stack, and we need to be able - to put an operation on. - -331 -00:14:20,738 --> 00:14:24,573 - So I'm gonna have a function - called pushOperand, and - -332 -00:14:24,575 --> 00:14:27,809 - it's gonna take an operand, - which is a double. - -333 -00:14:27,811 --> 00:14:30,578 - Okay it's not gonna return - anything yet anyway. - -334 -00:14:30,580 --> 00:14:33,715 - And to push an operand on my - stack, could not be easier, - -335 -00:14:33,717 --> 00:14:36,217 - I'm just gonna say - opStack.append, - -336 -00:14:36,219 --> 00:14:41,088 - you'll remember that append is - a function in array and - -337 -00:14:41,090 --> 00:14:42,355 - the thing that you put on, - -338 -00:14:42,357 --> 00:14:45,858 - obviously has to be this - little type T. - -339 -00:14:45,860 --> 00:14:48,627 - T is whatever you put in here, - so op in this case. - -340 -00:14:48,629 --> 00:14:50,729 - So we have to have an op here. - -341 -00:14:50,731 --> 00:14:52,964 - How do you create an enum - item? - -342 -00:14:52,966 --> 00:14:58,436 - You just Op.Operand and you - give it the associated value. - -343 -00:14:58,438 --> 00:15:01,539 - 'Kay? - -344 -00:15:01,541 --> 00:15:06,777 - So, very simple kind of way to - create these enums and - -345 -00:15:06,779 --> 00:15:10,013 - associate the value with them. - -346 -00:15:10,015 --> 00:15:11,114 - Any questions about that? - -347 -00:15:12,450 --> 00:15:13,749 - Okay, and then how about - operations? - -348 -00:15:13,751 --> 00:15:15,384 - We'll have instead of push, - -349 -00:15:15,386 --> 00:15:18,720 - we're gonna call this - performOperation. - -350 -00:15:18,722 --> 00:15:20,922 - And I think when I do - performOperation, what I'm - -351 -00:15:20,924 --> 00:15:23,024 - gonna have is, my calculator - brain is going to have - -352 -00:15:23,026 --> 00:15:26,493 - a bunch of known operations, - things it knows how to do. - -353 -00:15:26,495 --> 00:15:27,861 - And when you perform an - operation, - -354 -00:15:27,863 --> 00:15:30,697 - you just specify the - mathematical symbol of it. - -355 -00:15:30,699 --> 00:15:33,533 - So the argument here is going - to be symbol, - -356 -00:15:33,535 --> 00:15:34,800 - which is a string. - -357 -00:15:34,802 --> 00:15:36,301 - Okay? - -358 -00:15:36,303 --> 00:15:41,306 - So, to append an op on here - that is, an operation, - -359 -00:15:41,308 --> 00:15:43,274 - I'm gonna need to have these - known operations. - -360 -00:15:43,276 --> 00:15:44,775 - So, how am I gonna do that? - -361 -00:15:44,777 --> 00:15:47,878 - Well, to have known - operations, I'm gonna create - -362 -00:15:47,880 --> 00:15:51,048 - another instance variable here - called knownOps, so - -363 -00:15:51,050 --> 00:15:52,816 - my known operations. - -364 -00:15:52,818 --> 00:15:55,251 - And it's gonna be a - dictionary. - -365 -00:15:55,253 --> 00:15:57,019 - Okay, now, you read about - dictionaries in - -366 -00:15:57,021 --> 00:15:58,987 - last week's reading - assignment. - -367 -00:15:58,989 --> 00:16:00,489 - That's why I have the reading - assignment due today. - -368 -00:16:00,491 --> 00:16:02,257 - Cuz then I can know you've - read about them. - -369 -00:16:02,259 --> 00:16:02,824 - I hope you have. - -370 -00:16:05,495 --> 00:16:07,428 - And so, how do I create a - dictionary? - -371 -00:16:07,430 --> 00:16:08,995 - It looks like this, - Dictionary. - -372 -00:16:08,997 --> 00:16:11,531 - And it's the same kind of - thing with these angled - -373 -00:16:11,533 --> 00:16:14,434 - brackets, because you have to - say for the dictionary, - -374 -00:16:14,436 --> 00:16:17,036 - what type are the keys, what - type are the values. - -375 -00:16:17,038 --> 00:16:20,506 - And our dictionary is gonna - have keys that are strings and - -376 -00:16:20,508 --> 00:16:22,874 - it's gonna have values that - are ops. - -377 -00:16:22,876 --> 00:16:26,478 - Oops, sorry, ops. - -378 -00:16:26,480 --> 00:16:28,913 - Okay, and I'm gonna create - one. - -379 -00:16:28,915 --> 00:16:29,947 - 'Kay? - -380 -00:16:29,949 --> 00:16:32,316 - Everyone understand this? - -381 -00:16:32,317 --> 00:16:34,684 - Now, this knownOps, I'm just - gonna put all of the ops that - -382 -00:16:34,687 --> 00:16:38,955 - I know in there, where the key - is the symbol and the value is - -383 -00:16:38,957 --> 00:16:42,392 - the actual op, and then when - someone says performOperation, - -384 -00:16:42,394 --> 00:16:44,527 - I'm gonna look it up in the - knownOps. - -385 -00:16:44,529 --> 00:16:47,329 - And when I find it, then - that's the operation I'm - -386 -00:16:47,331 --> 00:16:49,531 - gonna push onto the stack, all - right? - -387 -00:16:49,533 --> 00:16:51,183 - Make sense? - -388 -00:16:51,184 --> 00:16:52,834 - But I have to load this - knownOps up. - -389 -00:16:52,836 --> 00:16:55,903 - Oh, but first of all, so let - me talk about this syntax. - -390 -00:16:55,905 --> 00:16:58,973 - Just like array has a special - syntax with the square - -391 -00:16:58,975 --> 00:17:00,941 - brackets, so does dictionary. - -392 -00:17:00,943 --> 00:17:03,510 - So to have a dictionary like - this with this kind of - -393 -00:17:03,512 --> 00:17:07,080 - special syntax, we're gonna do - open square bracket. - -394 -00:17:07,082 --> 00:17:12,752 - And then a colon in between - the key and - -395 -00:17:12,754 --> 00:17:15,254 - the value type, so it looks - like that. - -396 -00:17:15,256 --> 00:17:17,789 - So it looks very similar to - array, but - -397 -00:17:17,791 --> 00:17:19,524 - you've got this thing where - you've got the key and - -398 -00:17:19,526 --> 00:17:22,093 - the value separated by a - colon. - -399 -00:17:22,095 --> 00:17:22,660 - 'Kay? - -400 -00:17:23,796 --> 00:17:25,429 - Same thing, though, exact same - thing. - -401 -00:17:25,431 --> 00:17:27,430 - Just a dictionary, strings, - -402 -00:17:27,432 --> 00:17:28,698 - looking up in strings to find - ops. - -403 -00:17:28,700 --> 00:17:32,701 - All right, so how am I gonna - initialize this knownOps? - -404 -00:17:32,703 --> 00:17:33,869 - Well, this is a great time for - -405 -00:17:33,871 --> 00:17:37,906 - the first time for you see an - initializer, okay? - -406 -00:17:37,908 --> 00:17:41,876 - So far we've been creating - classes like right here, okay, - -407 -00:17:41,878 --> 00:17:44,311 - just by putting these - parentheses. - -408 -00:17:44,313 --> 00:17:46,680 - And I told you that was - calling an initializer in - -409 -00:17:46,682 --> 00:17:47,947 - Dictionary, okay, and - -410 -00:17:47,949 --> 00:17:50,817 - this one was calling an - initializer in Array. - -411 -00:17:50,819 --> 00:17:52,585 - And so we're gonna have our - own initializer in - -412 -00:17:52,587 --> 00:17:55,421 - CalculatorBrain, and - -413 -00:17:55,422 --> 00:17:58,256 - we just do that by saying - init, like this, okay. - -414 -00:17:58,258 --> 00:18:01,726 - Now any time someone says - something like let brain equal - -415 -00:18:01,728 --> 00:18:05,296 - CalculatorBrain, with the - parentheses, okay? - -416 -00:18:05,298 --> 00:18:07,531 - It's going to call an init - that - -417 -00:18:07,533 --> 00:18:09,667 - matches the same arguments. - -418 -00:18:09,669 --> 00:18:11,668 - In this case, no arguments, so - it's gonna call this init. - -419 -00:18:13,505 --> 00:18:14,070 - Okay. - -420 -00:18:15,439 --> 00:18:16,838 - Couldn't be simpler there. - -421 -00:18:16,840 --> 00:18:18,173 - So what are we gonna do in - this init? - -422 -00:18:18,175 --> 00:18:20,375 - We're just gonna initialize - this known op, so - -423 -00:18:20,377 --> 00:18:24,545 - I'm just gonna start putting - some known ops into this - -424 -00:18:24,547 --> 00:18:26,780 - knownOps dictionary. - -425 -00:18:26,782 --> 00:18:31,617 - We need our friend special - characters here for that. - -426 -00:18:31,619 --> 00:18:34,253 - So let's go ahead and - -427 -00:18:34,254 --> 00:18:36,888 - put, well, let's put times - here first, I guess. - -428 -00:18:36,891 --> 00:18:39,257 - Okay, and we need to create an - operation. - -429 -00:18:39,259 --> 00:18:40,392 - How do we create an operation? - -430 -00:18:40,394 --> 00:18:43,461 - Very similar to how we created - this enum. - -431 -00:18:43,463 --> 00:18:47,431 - Op, dot, and times is a binary - operation. - -432 -00:18:47,433 --> 00:18:49,566 - And you can see that it's - typing this for me. - -433 -00:18:49,568 --> 00:18:51,735 - I'm just pressing Tab to get - along. - -434 -00:18:51,737 --> 00:18:56,105 - This is the symbol, which is - this thing here. - -435 -00:18:56,107 --> 00:18:58,908 - Now, this is kinda bad code - that I ended up - -436 -00:18:58,910 --> 00:19:00,809 - typing this twice in the same - line. - -437 -00:19:00,811 --> 00:19:03,378 - If I accidentally use the - wrong x, - -438 -00:19:03,380 --> 00:19:06,881 - like some x from somewhere - else or the x just from my - -439 -00:19:06,883 --> 00:19:10,451 - keyboard might be different - from this x, than this x, ugh, - -440 -00:19:10,453 --> 00:19:12,920 - we could get in trouble where - these things don't match up. - -441 -00:19:12,922 --> 00:19:15,489 - So later, in the, right at the - very end of the demo, - -442 -00:19:15,491 --> 00:19:16,857 - I'm gonna show you how we - could do this in - -443 -00:19:16,859 --> 00:19:20,960 - a way where we don't have to - type this x twice like that. - -444 -00:19:20,962 --> 00:19:22,161 - Okay. - -445 -00:19:22,162 --> 00:19:23,361 - But now we just need the - function. - -446 -00:19:23,364 --> 00:19:25,230 - We know how to do that with - closures. - -447 -00:19:25,232 --> 00:19:27,866 - We say $0 times $1. - -448 -00:19:27,868 --> 00:19:29,000 - End the closure. - -449 -00:19:29,002 --> 00:19:31,736 - And yes, I could put this - closure outside, - -450 -00:19:31,738 --> 00:19:33,838 - since it's the last thing - here. - -451 -00:19:33,840 --> 00:19:37,107 - That is also legal to do when - you're creating - -452 -00:19:37,109 --> 00:19:39,109 - the operations like this. - -453 -00:19:39,111 --> 00:19:40,310 - 'Kay? - -454 -00:19:40,312 --> 00:19:41,377 - So that's kinda nice. - -455 -00:19:41,379 --> 00:19:44,880 - Let's do our other three - binary operations here. - -456 -00:19:44,882 --> 00:19:46,982 - We'll go divide. - -457 -00:19:46,984 --> 00:19:49,784 - And this is where it really - gets annoying to have to - -458 -00:19:49,786 --> 00:19:51,736 - type it twice. - -459 -00:19:51,737 --> 00:19:53,687 - But I have to show you - something else before I can - -460 -00:19:53,690 --> 00:19:56,357 - show you how to do that right. - -461 -00:19:57,726 --> 00:19:58,591 - Let's go here. - -462 -00:19:58,593 --> 00:20:02,362 - And there we have minus. - -463 -00:20:02,364 --> 00:20:04,997 - You can see there's two - different minuses there, so - -464 -00:20:04,999 --> 00:20:07,866 - hopefully I clicked the same - minus in both those spots. - -465 -00:20:07,868 --> 00:20:09,434 - And then we change these - things. - -466 -00:20:09,436 --> 00:20:13,671 - We know that divide is 1 - divided by $0, and - -467 -00:20:13,673 --> 00:20:15,106 - this is plus. - -468 -00:20:16,742 --> 00:20:21,678 - And this is 1 minus 0, $1 - minus $0, okay, so - -469 -00:20:21,680 --> 00:20:23,813 - everyone cool here? - -470 -00:20:25,350 --> 00:20:27,483 - These enums are really easy to - create. - -471 -00:20:27,485 --> 00:20:31,920 - The API of them is really, - really nice, simple. - -472 -00:20:31,922 --> 00:20:34,055 - And then we have our other - operation, - -473 -00:20:34,057 --> 00:20:37,058 - which is our unary operation, - which is square root. - -474 -00:20:37,060 --> 00:20:40,861 - So let's put that in here, - square root is right here. - -475 -00:20:40,863 --> 00:20:43,830 - And we'll put it right here. - -476 -00:20:45,266 --> 00:20:48,267 - And square root is not a - binary operation it's - -477 -00:20:48,269 --> 00:20:49,601 - a unary operation. - -478 -00:20:49,603 --> 00:20:53,738 - Oops, look at all this. - -479 -00:20:53,740 --> 00:20:56,591 - 'Kay? - -480 -00:20:56,592 --> 00:20:59,443 - And of course, inside here, - it's square root of $0. - -481 -00:20:59,445 --> 00:21:01,745 - Okay, you remember that from - last time. - -482 -00:21:01,747 --> 00:21:02,879 - So this is good. - -483 -00:21:02,881 --> 00:21:04,864 - Now, while I'm here, - -484 -00:21:04,865 --> 00:21:06,848 - I wanna show you a couple - things more about closures. - -485 -00:21:06,851 --> 00:21:07,950 - Okay. - -486 -00:21:07,952 --> 00:21:10,052 - This, what is this curly - brace? - -487 -00:21:10,054 --> 00:21:12,721 - It's a function that takes one - argument and - -488 -00:21:12,723 --> 00:21:14,356 - returns one argument. - -489 -00:21:14,358 --> 00:21:16,308 - And we know that - -490 -00:21:16,309 --> 00:21:18,259 - it's doubles because we're - creating a unary operation. - -491 -00:21:18,261 --> 00:21:21,962 - And so, it's inferring the - type here, right? - -492 -00:21:21,964 --> 00:21:23,530 - Everyone understand that? - -493 -00:21:23,532 --> 00:21:27,133 - Well, there's another function - that returns a function, or - -494 -00:21:27,135 --> 00:21:28,901 - there's another function that - takes a double and - -495 -00:21:28,903 --> 00:21:31,570 - returns a double, that does - square root, - -496 -00:21:31,572 --> 00:21:33,772 - it's called square root. - -497 -00:21:33,774 --> 00:21:36,941 - So inside here, we could just - say square root. - -498 -00:21:38,178 --> 00:21:40,811 - Okay, we don't even need this - business. - -499 -00:21:42,881 --> 00:21:44,080 - Just wanna emphasize that - -500 -00:21:44,082 --> 00:21:45,515 - we're just passing a function - here. - -501 -00:21:45,517 --> 00:21:47,450 - And it can be a named - function, or -它可以是一个被命名的函数 - -502 -00:21:47,452 --> 00:21:49,518 - we could use these curly - braces. -或者可以用花括号 - -503 -00:21:49,520 --> 00:21:52,754 - Now, this is really gonna - freak you out, cuz watch this. -现在,让你惊讶的事来了,看好了 - -504 -00:21:52,756 --> 00:21:57,091 - For times, there's a function - that does times called times. -对于乘法,有一个做乘法运算的函数就叫做“*” -505 -00:21:58,728 --> 00:22:00,728 - Okay. - -506 -00:22:00,729 --> 00:22:02,729 - So in Swift, all these - operators, times and -在Swift里,所有的运算符,乘号等等 -507 -00:22:02,732 --> 00:22:04,664 - all these things, are just - functions. - 都是函数 - -508 -00:22:04,666 --> 00:22:06,966 - They just happen to be - specified in a way that says - -509 -00:22:06,968 --> 00:22:09,068 - that they can be infix, right, - between the two - -510 -00:22:09,070 --> 00:22:11,370 - arguments instead of taking - the arguments in parentheses. - -511 -00:22:11,372 --> 00:22:13,138 - And we do the same thing here - with plus. -然后我们对加法做同样的事 - -512 -00:22:14,641 --> 00:22:16,074 - All right, plus. -好的,加号 -513 -00:22:16,076 --> 00:22:17,508 - Now, we can't do it with - divide and -现在要注意,这种方法不适用于除法和减法 - -514 -00:22:17,510 --> 00:22:20,378 - minus because the order is - backwards. -因为运算方向是反的 - -515 -00:22:20,380 --> 00:22:22,146 - Right, we put the things on - the stack, -好,我们把这些东西放到栈上 - -516 -00:22:22,148 --> 00:22:23,513 - we pull them out backwards, so - -517 -00:22:23,515 --> 00:22:25,081 - we can't do it with those, - but. - -518 -00:22:27,919 --> 00:22:31,086 - I just wanna emphasize, that's - what's going on there. - -519 -00:22:31,088 --> 00:22:33,455 - Okay, so now we have this nice - knownOps. -好,现在我们做好了这些KnwonOps - -520 -00:22:33,457 --> 00:22:34,222 - So we have this thing. - -521 -00:22:34,224 --> 00:22:36,724 - It's loaded up. -它已经装载好了 -522 -00:22:36,725 --> 00:22:39,225 - It gets loaded up whenever the - CalculatorBrain gets created. -每当CalculatorBrain被创建它就会被装载 - -523 -00:22:39,228 --> 00:22:41,612 - So that's all good. -万事俱备 - -524 -00:22:41,613 --> 00:22:43,997 - Now we can use that down here - in performOperation. -现在我们可以将它用在performOperation上 - -525 -00:22:43,999 --> 00:22:47,134 - All right, so how are we gonna - use this in performOperation? -好,那我们要怎么使用呢 - -526 -00:22:47,136 --> 00:22:50,870 - Well, we basically wanna let - the operation equal -我们让operation等于 - -527 -00:22:50,872 --> 00:22:53,172 - knownOps sub symbol. -knownOps参数symbol - -528 -00:22:53,174 --> 00:22:55,240 - Okay? - Someone passed us a symbol. -明白了吗?使用者传递给我们一个参数symbol - -529 -00:22:55,242 --> 00:22:56,641 - They're trying to perform this - operation. -当他们想用这个方法的时候 - -530 -00:22:56,643 --> 00:22:58,810 - So this is either a plus or a - times. -参数可以是加法或者乘法 -531 -00:22:58,812 --> 00:23:00,111 - Hopefully an operation we - know. - 是我们已知的运算符 - -532 -00:23:00,113 --> 00:23:02,747 - And we're gonna look it up in - knownOps. -然后我们会来到KnownOps - -533 -00:23:02,749 --> 00:23:05,683 - And the way we do that is with - the subscript notation with -然后要做的就是在 - -534 -00:23:05,685 --> 00:23:06,650 - the square brackets. - -535 -00:23:06,652 --> 00:23:07,951 - Okay? - That's how you - -536 -00:23:07,952 --> 00:23:09,251 - look something up in a - dictionary. - -537 -00:23:09,254 --> 00:23:11,454 - But what might be kind of - surprising to you, -不过有一点可能会让你惊讶 - -538 -00:23:11,456 --> 00:23:13,622 - what type do you think this - would be, operation? -得到的operation,你觉得是什么类型的呢? - -539 -00:23:15,292 --> 00:23:17,959 - Any guesses, yeah, some people - are saying the right thing. -猜猜?哈,有人说出了正确答案 - -540 -00:23:17,961 --> 00:23:20,128 - You'd think this might be an - Op, -你可能会觉得这个是一个Op - -541 -00:23:20,130 --> 00:23:24,498 - because I'm looking up in - knownOps right here, a string. -因为我在KnownOps这里看,String:Op - -542 -00:23:24,500 --> 00:23:27,134 - And so hopefully I'm getting - an Op, but this is not an Op, -因此可以预见得到的会是一个Op,事实上它并不是Op - -543 -00:23:27,136 --> 00:23:30,971 - this actually is an Optional - Op. -实际上它是一个Optional Op - -544 -00:23:30,973 --> 00:23:33,173 - Okay, now why is that an - Optional Op, because you -好了,为什么它会是一个Optional Op,因为 - -545 -00:23:33,175 --> 00:23:35,541 - might be looking up something - that's not in there. -因为它可能不存在于此 -546 -00:23:35,543 --> 00:23:38,344 - And it has to return, oh, nil, - sorry, couldn't find it, -而且它没有返回值。“噢,nil,不好意思找不到该值” - -547 -00:23:38,346 --> 00:23:41,413 - so that's why it has to be an - optional, is returned. -所以这就是为什么它必须是optional - -548 -00:23:41,415 --> 00:23:43,015 - So a dictionary, -比方说字典 - -549 -00:23:43,016 --> 00:23:44,616 - whenever you look up something - in a dictionary, -每当你要在字典里面寻找东西的时候 - -550 -00:23:44,618 --> 00:23:47,118 - it always returns an Optional, - okay, either nil or -它总是会返回一个Optional类型。nil或者是 - -551 -00:23:47,120 --> 00:23:50,655 - the type of thing you said was - supposed to be in there. -其他它原本的类型 - -552 -00:23:50,657 --> 00:23:53,457 - So I'm gonna if let here, I'm - gonna say, -所以我在这里加上if - -553 -00:23:53,459 --> 00:23:56,827 - if I'm able to look up my - operation in my knownOps, -如果 我能在knownOps里取得我的operation - -554 -00:23:56,829 --> 00:23:59,696 - then I'm going to push it on - to my op stack. -那我就将它放进我的op stack. - -555 -00:24:02,534 --> 00:24:03,232 - Okay. - -556 -00:24:03,234 --> 00:24:06,068 - Are you cool with that? -明白了吗? - -557 -00:24:06,070 --> 00:24:08,303 - Make sense? - -558 -00:24:08,305 --> 00:24:10,171 - Okay. - -559 -00:24:10,173 --> 00:24:12,407 - Now, what's next? -好,下一步是什么呢 - -560 -00:24:12,409 --> 00:24:13,908 - Well. - -561 -00:24:13,910 --> 00:24:14,541 - Now we have. - -562 -00:24:14,543 --> 00:24:15,509 - Oh, well. - -563 -00:24:15,510 --> 00:24:16,476 - I'm gonna take a pause here to - -564 -00:24:16,478 --> 00:24:18,845 - talk a little bit about access - control. - -565 -00:24:18,847 --> 00:24:20,697 - Okay? - -566 -00:24:20,698 --> 00:24:22,548 - Access control is about public - and private. - -567 -00:24:22,550 --> 00:24:25,017 - Okay? - What methods in this class - -568 -00:24:25,019 --> 00:24:27,353 - are public, in other words, - other people can use them, - -569 -00:24:27,355 --> 00:24:30,022 - other classes in my code - allowed to call them? - -570 -00:24:30,024 --> 00:24:31,189 - And what things are private? - -571 -00:24:31,191 --> 00:24:32,757 - My internal data structures - that I - -572 -00:24:32,759 --> 00:24:34,458 - don't want people messing - with? - -573 -00:24:34,460 --> 00:24:38,428 - Okay, so the way public - private works in - -574 -00:24:38,430 --> 00:24:41,064 - Swift is kind of interesting. - -575 -00:24:41,066 --> 00:24:42,999 - You basically specify the - things you want to - -576 -00:24:43,001 --> 00:24:45,935 - be private by putting the word - private on them. - -577 -00:24:45,937 --> 00:24:47,569 - If you don't put any word on - them, - -578 -00:24:47,571 --> 00:24:50,639 - then they're public inside - your program. - -579 -00:24:50,641 --> 00:24:52,040 - 'Kay? - -580 -00:24:52,042 --> 00:24:55,109 - And you only use the word - public if you're shipping out, - -581 -00:24:55,111 --> 00:24:58,979 - like, a framework of objects - to other people, and - -582 -00:24:58,981 --> 00:25:02,215 - you want stuff in there to be - public outside the framework. - -583 -00:25:03,251 --> 00:25:04,684 - So I'm making some framework, - -584 -00:25:04,686 --> 00:25:07,153 - a bunch of objects that I'm - trying to sell to people or - -585 -00:25:07,155 --> 00:25:09,555 - I get people to use to do - something, and - -586 -00:25:09,557 --> 00:25:12,624 - of course I'm gonna have - things where my objects inside - -587 -00:25:12,626 --> 00:25:14,192 - my framework can talk to each - other. - -588 -00:25:14,194 --> 00:25:16,361 - There's no keyword needed for - that. - -589 -00:25:16,363 --> 00:25:18,229 - Then I'll have things inside - certain objects - -590 -00:25:18,231 --> 00:25:20,464 - that are private only to that - object, I'll say private. - -591 -00:25:20,466 --> 00:25:24,267 - And them some of them might be - public that the customer who's - -592 -00:25:24,269 --> 00:25:27,404 - buying my objects, my - framework, can use. - -593 -00:25:27,406 --> 00:25:29,238 - Now, in this class we're not - gonna be doing frameworks, - -594 -00:25:29,240 --> 00:25:30,840 - we don't really have time to - get to that, so - -595 -00:25:30,842 --> 00:25:32,508 - we're not gonna be using the - keyword public, - -596 -00:25:32,510 --> 00:25:34,076 - we won't ever use that, - -597 -00:25:34,078 --> 00:25:35,510 - because we don't have any - frameworks. - -598 -00:25:35,512 --> 00:25:37,578 - But we are gonna use private. - -599 -00:25:37,580 --> 00:25:39,180 - And, starting with assignment - two, - -600 -00:25:40,216 --> 00:25:42,516 - it's one of your evaluation - criteria is gonna be, - -601 -00:25:42,518 --> 00:25:44,918 - make private things private. - -602 -00:25:44,920 --> 00:25:45,985 - 'Kay? - -603 -00:25:45,987 --> 00:25:47,453 - So that is important to do. - -604 -00:25:47,455 --> 00:25:48,354 - And you could just say, - -605 -00:25:48,356 --> 00:25:49,988 - well, I like everything to be - public. - -606 -00:25:49,990 --> 00:25:51,156 - Well, that's bad. - -607 -00:25:51,158 --> 00:25:53,391 - Okay? - If you make your - -608 -00:25:53,392 --> 00:25:55,625 - internal structure public, and - some other object in your - -609 -00:25:55,628 --> 00:25:58,796 - program starts mucking with it - and breaks your object, and - -610 -00:25:58,798 --> 00:26:00,931 - then you come to a new version - of your program, and - -611 -00:26:00,933 --> 00:26:03,467 - you change something, and now - everybody's breaking. - -612 -00:26:03,469 --> 00:26:05,335 - That's bad, okay, that's - chaos. - -613 -00:26:05,337 --> 00:26:08,671 - So the only things that want - to be not private are things - -614 -00:26:08,673 --> 00:26:11,507 - that you're committing to sign - up to support. - -615 -00:26:11,509 --> 00:26:14,677 - So in this class, the only - public things so - -616 -00:26:14,679 --> 00:26:17,279 - far are the initializer. - -617 -00:26:17,281 --> 00:26:18,513 - Obviously, we want to allow - people to - -618 -00:26:18,515 --> 00:26:19,847 - create a CalculatorBrain. - -619 -00:26:19,849 --> 00:26:21,349 - That's clearly public. - -620 -00:26:21,351 --> 00:26:25,385 - Also pushing and performing - operands and operations. - -621 -00:26:25,387 --> 00:26:26,586 - That's public. - -622 -00:26:26,588 --> 00:26:28,238 - Okay? - -623 -00:26:28,239 --> 00:26:29,889 - Everything else, for now, I'm - gonna make private. - -624 -00:26:29,891 --> 00:26:31,657 - So I'm gonna make this - private. - -625 -00:26:31,659 --> 00:26:33,592 - Notice that if I make this - private, - -626 -00:26:33,594 --> 00:26:35,427 - it's gonna start saying, whoa, - -627 -00:26:35,429 --> 00:26:38,730 - wait a second, this can't be - public, you know, it can't be - -628 -00:26:38,732 --> 00:26:42,100 - non-private because this is - private and it uses it. - -629 -00:26:42,102 --> 00:26:44,368 - That's what this warning's - gonna say right here, see. - -630 -00:26:44,370 --> 00:26:45,720 - Property must be - -631 -00:26:45,721 --> 00:26:47,071 - declared private because its - type is private. - -632 -00:26:47,073 --> 00:26:48,205 - Okay, that's the type of this. - -633 -00:26:48,207 --> 00:26:49,906 - But I want this to be private - anyway, - -634 -00:26:49,908 --> 00:26:52,742 - this is my internal data - structure, opStack. - -635 -00:26:52,744 --> 00:26:56,278 - Now, knownOps is kind of an - interesting one. - -636 -00:26:56,280 --> 00:26:58,614 - Maybe I would want that to be - public one day, - -637 -00:26:58,616 --> 00:27:01,650 - because maybe I want people to - use my calculator brain and - -638 -00:27:01,652 --> 00:27:03,685 - teach it new ops. - -639 -00:27:03,687 --> 00:27:05,386 - That wouldn't be that - unreasonable. - -640 -00:27:05,388 --> 00:27:08,356 - However, I'm not ready to - support that functionality in - -641 -00:27:08,358 --> 00:27:09,456 - my CalculatorBrain. - -642 -00:27:09,458 --> 00:27:12,059 - I'm just not sure I wanna do - it this way. - -643 -00:27:12,061 --> 00:27:13,827 - Maybe I don't want this - property to be public, - -644 -00:27:13,829 --> 00:27:17,263 - I might want to just have some - functions to learn an op or - -645 -00:27:17,265 --> 00:27:18,982 - something like that, so - -646 -00:27:18,983 --> 00:27:20,700 - I'm just not sure, so I'm - gonna start out private. - -647 -00:27:20,702 --> 00:27:23,268 - And that's really, when you're - designing APIs, - -648 -00:27:23,270 --> 00:27:24,536 - you wanna kinda start out, - -649 -00:27:24,538 --> 00:27:27,405 - make it private first, and - then open it up as you're - -650 -00:27:27,407 --> 00:27:30,308 - willing to support that - functionality. - -651 -00:27:30,310 --> 00:27:31,709 - Question? - >> Is the common view in - -652 -00:27:31,711 --> 00:27:34,278 - Swift to make most instance - variables private and - -653 -00:27:34,280 --> 00:27:36,980 - use getters and setters, or is - it to make them, if, - -654 -00:27:36,982 --> 00:27:38,882 - if they are supposed to be - public, or - -655 -00:27:38,884 --> 00:27:40,683 - make them public and then let - the? - -656 -00:27:40,685 --> 00:27:43,052 - >> All right. - So the question is, is it, - -657 -00:27:43,054 --> 00:27:45,854 - is it kind of part of the - Swift way to make - -658 -00:27:45,856 --> 00:27:47,889 - most instant variables private - and - -659 -00:27:47,891 --> 00:27:50,759 - then have getters and setters - that are public to get them. - -660 -00:27:50,761 --> 00:27:52,226 - That doesn't really even make - sense in Swift. - -661 -00:27:52,228 --> 00:27:53,961 - That's more of an Objective-C - thing. - -662 -00:27:53,963 --> 00:27:56,263 - In Objective-C, you had - instance variables, and - -663 -00:27:56,265 --> 00:27:59,032 - then you had properties that - would get and set them. - -664 -00:27:59,034 --> 00:28:00,967 - And Swift has kind of merged - those a little bit - -665 -00:28:00,969 --> 00:28:05,638 - closer together so that - properties are really kind of - -666 -00:28:05,640 --> 00:28:08,907 - the public or private getters - and setters. - -667 -00:28:08,909 --> 00:28:11,043 - So, if you have a property, - you just have to - -668 -00:28:11,045 --> 00:28:13,178 - decide whether you want people - to access it or - -669 -00:28:13,180 --> 00:28:15,246 - not, and if not, make it - private. - -670 -00:28:15,248 --> 00:28:16,681 - And if so, make it public. - -671 -00:28:16,683 --> 00:28:19,350 - And that, you know, don't make - it non-private, basically. - -672 -00:28:19,352 --> 00:28:21,685 - And that's, just that's all - you need to think about. - -673 -00:28:21,687 --> 00:28:24,854 - I wouldn't even think in Swift - in terms of instance variable - -674 -00:28:24,856 --> 00:28:26,289 - versus the property. - -675 -00:28:26,291 --> 00:28:28,557 - Now, it is still possible in - Swift to do that, - -676 -00:28:28,559 --> 00:28:30,526 - because you have computed - properties. - -677 -00:28:30,528 --> 00:28:32,328 - And those could be setters and - -678 -00:28:32,329 --> 00:28:34,129 - getters that are setting - private properties. - -679 -00:28:34,131 --> 00:28:36,464 - But we're gonna see on - Wednesday, even, - -680 -00:28:36,466 --> 00:28:39,634 - I'm gonna talk to you a little - bit about a way that when your - -681 -00:28:39,636 --> 00:28:41,902 - properties get set, you can - intervene, - -682 -00:28:41,904 --> 00:28:44,571 - you can check them to make - sure the value is okay. - -683 -00:28:44,573 --> 00:28:46,373 - So if you have a public - property, - -684 -00:28:46,375 --> 00:28:49,142 - you can still protect it by - intervening a little bit - -685 -00:28:49,144 --> 00:28:51,110 - when people set it or try and - get it. - -686 -00:28:51,112 --> 00:28:52,912 - So it is possible to still - have some protection there, - -687 -00:28:52,914 --> 00:28:53,545 - we'll see that. - -688 -00:28:56,016 --> 00:28:57,749 - All right, so these are our - only public things. - -689 -00:28:57,751 --> 00:29:00,651 - Now, there's only one other - public thing we need to do in - -690 -00:29:00,653 --> 00:29:02,420 - our CalculatorBrain, which is, - -691 -00:29:02,422 --> 00:29:04,688 - we need to let people evaluate - this stack. - -692 -00:29:06,058 --> 00:29:09,492 - So people are pushing operands - and performing operations, - -693 -00:29:09,494 --> 00:29:11,828 - now they wanna know what's the - result. - -694 -00:29:11,830 --> 00:29:12,979 - Okay? - They - -695 -00:29:12,980 --> 00:29:14,129 - pushed an operand of a five. - -696 -00:29:14,132 --> 00:29:15,898 - They pushed an operand of a - four. - -697 -00:29:15,900 --> 00:29:18,166 - They performed operation plus, - -698 -00:29:18,168 --> 00:29:19,668 - they want to see four plus - five. - -699 -00:29:19,670 --> 00:29:21,202 - Where's that nine, okay? - -700 -00:29:21,204 --> 00:29:22,403 - They need the result. - -701 -00:29:22,405 --> 00:29:25,606 - So we need another public - method here, - -702 -00:29:25,608 --> 00:29:29,876 - which I'm gonna call evaluate. - -703 -00:29:29,878 --> 00:29:31,344 - 'Kay? - And evaluate, - -704 -00:29:31,346 --> 00:29:34,880 - we could have it return a - double, for example. - -705 -00:29:34,882 --> 00:29:38,917 - And it would just evaluate - this opStack and - -706 -00:29:38,919 --> 00:29:40,535 - return the value. - -707 -00:29:40,536 --> 00:29:42,152 - But I really can't make this a - double. - -708 -00:29:43,390 --> 00:29:46,524 - Really, this has to be an - optional. - -709 -00:29:46,526 --> 00:29:48,892 - 'Kay, why does this have to be - an optional? - -710 -00:29:48,894 --> 00:29:52,295 - Well, that's because someone - might get my CalculatorBrain, - -711 -00:29:52,297 --> 00:29:53,963 - and the first thing they do - is, - -712 -00:29:53,965 --> 00:29:55,932 - they say, perform operation - plus. - -713 -00:29:55,934 --> 00:29:57,600 - Okay, well I have no operands. - -714 -00:29:57,602 --> 00:29:59,051 - Okay? - And - -715 -00:29:59,052 --> 00:30:00,501 - you're asking to evaluate - plus. - -716 -00:30:00,504 --> 00:30:02,287 - I can't do that. - -717 -00:30:02,288 --> 00:30:04,071 - So, I have to return something - to you, that lets you know, - -718 -00:30:04,074 --> 00:30:07,776 - I could not evaluate what you - ask me to evaluate. - -719 -00:30:07,778 --> 00:30:09,477 - So, I'm gonna return nil in - that case, - -720 -00:30:09,479 --> 00:30:12,213 - so valuate here really needs - to be an optional. - -721 -00:30:13,249 --> 00:30:14,848 - 'Kay, so you can see some of - the thinking, - -722 -00:30:14,850 --> 00:30:17,283 - when do you make something an - optional when not. - -723 -00:30:17,285 --> 00:30:19,285 - 'Kay, so this is a classic - case of that, - -724 -00:30:19,287 --> 00:30:21,787 - where you got sometimes you - wanna return it and - -725 -00:30:21,789 --> 00:30:23,889 - you can't do it, so you have - to return no. - -726 -00:30:23,891 --> 00:30:28,793 - All right, so how we going to - implement evaluate? - -727 -00:30:28,795 --> 00:30:30,595 - Okay, how many people in the - class, - -728 -00:30:30,597 --> 00:30:34,365 - raise your hands don't be shy, - are you comfortable with - -729 -00:30:34,367 --> 00:30:37,067 - the computer science concept - of recursion? - -730 -00:30:39,271 --> 00:30:40,903 - Okay. - Excellent, that's about 80 or - -731 -00:30:40,905 --> 00:30:43,939 - 90%, so I'm gonna explain this - really fast then. - -732 -00:30:43,941 --> 00:30:45,974 - And if you don't understand - recursion, - -733 -00:30:45,976 --> 00:30:47,309 - if you didn't raise your hand, - -734 -00:30:47,311 --> 00:30:48,843 - that's something you should go - review. - -735 -00:30:48,845 --> 00:30:50,378 - Okay? - [LAUGH] Recursion is - -736 -00:30:50,379 --> 00:30:51,912 - something, you should know by - the time you take this class, - -737 -00:30:51,915 --> 00:30:53,714 - so that's something you - definitely wanna know. - -738 -00:30:53,716 --> 00:30:57,317 - So, how are we going to use - recursion to - -739 -00:30:57,319 --> 00:30:59,252 - evaluate this stack? - -740 -00:30:59,254 --> 00:31:00,653 - All right, looks like this. - -741 -00:31:00,655 --> 00:31:02,988 - I'm gonna do a sample stack, - right here. - -742 -00:31:02,990 --> 00:31:08,393 - So, let's say I put a 6 on the - stack, and then I put a 5, and - -743 -00:31:08,395 --> 00:31:14,065 - then I put a plus, and then I - put a 4, and then I put times. - -744 -00:31:14,067 --> 00:31:15,166 - Okay? - -745 -00:31:15,168 --> 00:31:17,968 - So here's our stack, and I'm - gonna evaluate this, - -746 -00:31:17,970 --> 00:31:18,702 - I'm gonna recursion. - -747 -00:31:18,704 --> 00:31:19,769 - How am I gonna do that? - -748 -00:31:19,771 --> 00:31:21,437 - Well, really, what I'm gonna - do is I'm gonna - -749 -00:31:21,439 --> 00:31:24,740 - have a helper method here, a - recursive helper method. - -750 -00:31:24,742 --> 00:31:27,543 - I'm gonna call it evaluate - also, actually. - -751 -00:31:27,545 --> 00:31:29,644 - And it's gonna take a stack, - as an argument, - -752 -00:31:29,646 --> 00:31:31,012 - a stack of things to evaluate. - -753 -00:31:31,014 --> 00:31:34,449 - And it's only gonna evaluate - the top thing on the stack. - -754 -00:31:34,451 --> 00:31:36,717 - That's it just gonna value the - top of the stack and - -755 -00:31:36,719 --> 00:31:38,819 - return it, but the top thing - of the stack might - -756 -00:31:38,821 --> 00:31:41,421 - involve looking at every - single of one of these, right? - -757 -00:31:41,423 --> 00:31:44,157 - Cuz, this times needed to two - operations. - -758 -00:31:44,159 --> 00:31:47,026 - So, lets look at this, this - recursive evaluates gonna come - -759 -00:31:47,028 --> 00:31:48,961 - in here, it's gonna try and - -760 -00:31:48,962 --> 00:31:50,895 - evaluate the top of the stack, - which is a times. - -761 -00:31:50,898 --> 00:31:51,597 - Okay? - So it's like, - -762 -00:31:51,599 --> 00:31:53,265 - okay, I'm doing times. - -763 -00:31:53,267 --> 00:31:56,101 - Now for times it needs two - operate, - -764 -00:31:56,103 --> 00:31:58,302 - two operands here for times. - -765 -00:31:58,304 --> 00:31:59,737 - So, it recursively calls, - -766 -00:31:59,739 --> 00:32:03,807 - itself to say give me to first - operand for time. - -767 -00:32:03,809 --> 00:32:07,010 - And so recursively, comes in - here, it finds a 4 on - -768 -00:32:07,012 --> 00:32:10,913 - the top it's like, I know how - to evaluate 4, it's 4. - -769 -00:32:10,915 --> 00:32:12,148 - So, it just returns. - -770 -00:32:12,150 --> 00:32:15,751 - Okay, so now I have my first - operands. - -771 -00:32:15,753 --> 00:32:16,618 - 'Kay? - Now, - -772 -00:32:16,620 --> 00:32:18,386 - I take the rest of the stack - and - -773 -00:32:18,388 --> 00:32:21,255 - evaluate it, to get the second - one. - -774 -00:32:21,257 --> 00:32:24,291 - And when I do that, I get - plus, 'kay? - -775 -00:32:24,293 --> 00:32:26,393 - So, plus says, oh, I have to - evaluate plus. - -776 -00:32:26,395 --> 00:32:27,727 - It needs operands. - -777 -00:32:27,729 --> 00:32:30,763 - So, I come over here, I'm - getting a plus. - -778 -00:32:30,765 --> 00:32:34,700 - And I gotta go recursive - again, to go get its operands. - -779 -00:32:34,702 --> 00:32:36,401 - I get the 5, that's good. - -780 -00:32:36,403 --> 00:32:41,072 - I'm gonna go recursive again, - get the 6, over here. - -781 -00:32:41,074 --> 00:32:42,907 - And I've evaluated the whole - stack. - -782 -00:32:42,909 --> 00:32:45,876 - So, you see how I have to keep - going backward recursively to - -783 -00:32:45,878 --> 00:32:46,576 - my evaluate- - -784 -00:32:46,578 --> 00:32:47,911 - >> [COUGH] - -785 -00:32:47,912 --> 00:32:49,245 - >> To get the operands for my - operations. - -786 -00:32:49,247 --> 00:32:51,848 - Once, I get to an operand I - can stop, - -787 -00:32:51,850 --> 00:32:54,483 - okay number, I got it and I'm - out of of there. - -788 -00:32:54,485 --> 00:32:56,418 - But every time I encounter - another operation, - -789 -00:32:56,420 --> 00:32:58,153 - I have to keep going - recursively to - -790 -00:32:58,155 --> 00:33:00,822 - get all my arguments, any - questions about that? - -791 -00:33:00,824 --> 00:33:06,327 - 'Kay, so it's actually gonna - be pretty simple recursion. - -792 -00:33:06,329 --> 00:33:08,862 - When you see the code, you're - gonna be, that makes sense. - -793 -00:33:08,864 --> 00:33:12,832 - So, I'm gonna have this - separate I'm gonna put this up - -794 -00:33:12,834 --> 00:33:15,201 - on top for scrolling reasons. - -795 -00:33:15,203 --> 00:33:18,237 - Oops. - Didn't mean that. - -796 -00:33:18,239 --> 00:33:19,672 - The separate evaluate. - -797 -00:33:20,808 --> 00:33:25,677 - And this evaluate is going to - take a stack of ops, - -798 -00:33:25,679 --> 00:33:27,078 - as its argument. - -799 -00:33:27,080 --> 00:33:28,645 - And why does it take a stack - of ops? - -800 -00:33:28,647 --> 00:33:31,048 - Because as it's recursing, - -801 -00:33:31,050 --> 00:33:32,882 - it's using the rest of the - ops. - -802 -00:33:32,884 --> 00:33:34,050 - So, you see what I mean? - -803 -00:33:34,052 --> 00:33:35,618 - It's not, - -804 -00:33:35,619 --> 00:33:37,185 - it can't be looking at the big - opStack in our brain. - -805 -00:33:37,188 --> 00:33:38,320 - It can't look at this. - -806 -00:33:38,322 --> 00:33:40,756 - 'Kay, cuz it's kind of - consuming it. - -807 -00:33:40,758 --> 00:33:42,991 - Right? - And every time I call it - -808 -00:33:42,992 --> 00:33:45,225 - recursively, I'm gonna get - fewer operands to work with. - -809 -00:33:45,228 --> 00:33:46,194 - So this is what I'm doing. - -810 -00:33:46,196 --> 00:33:47,962 - Now, the first time I call it, - -811 -00:33:47,964 --> 00:33:50,864 - right here, I'm gonna give it - the full opStack. - -812 -00:33:50,866 --> 00:33:53,767 - So, I'll call my recursive one - from here. - -813 -00:33:53,769 --> 00:33:56,036 - Now, what's this thing gonna - return? - -814 -00:33:56,038 --> 00:33:56,836 - 'Kay. - -815 -00:33:56,838 --> 00:33:57,770 - That's interesting and - -816 -00:33:57,772 --> 00:34:00,873 - here's a big new thing for you - to see. - -817 -00:34:00,875 --> 00:34:03,709 - You've read about it I, I - can't remember I - -818 -00:34:03,711 --> 00:34:05,910 - even asked you to read about - this but I think I. - -819 -00:34:05,912 --> 00:34:06,811 - No, I guess I didn't. - -820 -00:34:06,813 --> 00:34:08,846 - Which is tuples, 'kay? - -821 -00:34:08,848 --> 00:34:14,484 - So in Swift, you can combine - multiple things together - -822 -00:34:14,486 --> 00:34:16,853 - into one kind of really te, - -823 -00:34:16,855 --> 00:34:19,922 - mini data structure called a - tuple, 'kay? - -824 -00:34:19,924 --> 00:34:22,124 - Don't let the tu [LAUGH] sound - in there fool you. - -825 -00:34:22,126 --> 00:34:24,560 - It's not just two, it's any - number, okay? - -826 -00:34:24,562 --> 00:34:26,762 - And you just put them in a - parentheses, okay? - -827 -00:34:26,764 --> 00:34:28,664 - And, and that's it. - -828 -00:34:28,665 --> 00:34:30,565 - So you can use this for return - values. - -829 -00:34:30,567 --> 00:34:32,033 - So I've gotta function right - here, - -830 -00:34:32,035 --> 00:34:34,735 - and I actually need to return - two things from this evaluate. - -831 -00:34:35,771 --> 00:34:37,754 - 'Kay? - One thing I - -832 -00:34:37,755 --> 00:34:39,738 - need to return is the result - of a evaluating it. - -833 -00:34:40,975 --> 00:34:43,042 - But the other thing I - -834 -00:34:43,043 --> 00:34:45,110 - need to return is the rest of - the stack that I didn't use. - -835 -00:34:45,112 --> 00:34:48,647 - Cuz as I'm working my way down - here and I take off that - -836 -00:34:48,649 --> 00:34:52,884 - times, and the 4 and the 5, - okay, I'm consuming things but - -837 -00:34:52,886 --> 00:34:54,652 - then I'm leaving the rest of - the stacks, so - -838 -00:34:54,654 --> 00:34:56,920 - I have to keep returning - what's left of the stacks, - -839 -00:34:56,922 --> 00:34:58,722 - while we keep consuming it. - -840 -00:34:58,724 --> 00:34:59,689 - Okay? - -841 -00:34:59,691 --> 00:35:01,958 - So, I'm gonna return this in a - tuple. - -842 -00:35:01,960 --> 00:35:04,126 - Tuples could not be simpler - syntax, - -843 -00:35:04,128 --> 00:35:08,097 - just open parentheses, not - nine, open parentheses. - -844 -00:35:08,099 --> 00:35:11,066 - Open parentheses, and just all - the types that you, - -845 -00:35:11,068 --> 00:35:12,634 - of things that you want in - here. - -846 -00:35:12,636 --> 00:35:14,569 - So, I'm gonna return a double - question mark, - -847 -00:35:14,571 --> 00:35:16,070 - that's my results. - -848 -00:35:16,072 --> 00:35:17,683 - 'Kay? - -849 -00:35:17,684 --> 00:35:19,295 - That's what's eventually, - gonna be - -850 -00:35:19,296 --> 00:35:20,907 - returned out here after all - the recursion unwinds. - -851 -00:35:20,910 --> 00:35:23,643 - And then also I'm going to - -852 -00:35:23,645 --> 00:35:28,348 - have the ops that are left - over. - -853 -00:35:28,350 --> 00:35:32,851 - Now, a tuple could look just - like this, unnamed. - -854 -00:35:32,853 --> 00:35:34,519 - Did you see how these things - are not named, - -855 -00:35:34,521 --> 00:35:35,920 - each of these things in here. - -856 -00:35:35,922 --> 00:35:38,956 - But you can also put names in - here as, if you want, as well. - -857 -00:35:38,958 --> 00:35:41,092 - So maybe I would call this one - the result. - -858 -00:35:42,061 --> 00:35:44,728 - Okay? - And - -859 -00:35:44,729 --> 00:35:47,396 - I would call this one - remainingOps, 'kay? - -860 -00:35:47,399 --> 00:35:49,666 - And I kinda recommend putting - those in there, and - -861 -00:35:49,668 --> 00:35:52,601 - you'll see why in a second - because there's two ways to - -862 -00:35:52,603 --> 00:35:56,138 - call a function that returns a - tuple and get the results. - -863 -00:35:56,140 --> 00:36:00,208 - And one of the ways requires - that you name these, 'kay? - -864 -00:36:00,210 --> 00:36:01,843 - So, it doesn't hurt to name - the, you might, as well. - -865 -00:36:01,845 --> 00:36:03,111 - It's good documentation. - -866 -00:36:03,113 --> 00:36:05,379 - Someone looking at this now - knows, oh, yeah, - -867 -00:36:05,381 --> 00:36:07,147 - this is the result of the - evaluation, and - -868 -00:36:07,149 --> 00:36:09,783 - these the ops that were left - over. - -869 -00:36:09,785 --> 00:36:10,784 - 'Kay? - -870 -00:36:10,786 --> 00:36:13,419 - All right. - -871 -00:36:13,421 --> 00:36:15,121 - So let's dive in here. - -872 -00:36:15,123 --> 00:36:16,956 - The first thing, - -873 -00:36:16,957 --> 00:36:18,790 - line of code I'm gonna put in - this recursive function - -874 -00:36:18,793 --> 00:36:21,193 - is the failure line of code, - -875 -00:36:21,195 --> 00:36:25,930 - which is return nil, ops, - okay? - -876 -00:36:25,932 --> 00:36:28,566 - So if I fail, okay, I'm gonna - try and - -877 -00:36:28,568 --> 00:36:33,303 - do my best in here to evaluate - these ops you passed me, but - -878 -00:36:33,305 --> 00:36:36,272 - if I fail I'm just gonna - return my result of nil. - -879 -00:36:36,274 --> 00:36:37,974 - 'Kay? - -880 -00:36:37,975 --> 00:36:39,675 - And that's gonna be my default - is to return nil so - -881 -00:36:39,678 --> 00:36:40,643 - I know I failed. - -882 -00:36:40,645 --> 00:36:42,344 - So, if I run out of operands - or - -883 -00:36:42,346 --> 00:36:44,613 - I run out of stack can't find - it for - -884 -00:36:44,615 --> 00:36:47,915 - example, it's just gonna fall - out here and return nil. - -885 -00:36:49,152 --> 00:36:49,683 - Okay? - -886 -00:36:49,685 --> 00:36:50,784 - So that's good. - -887 -00:36:50,786 --> 00:36:52,619 - So, what do I need to do here? - -888 -00:36:52,621 --> 00:36:56,089 - Well, first thing is I need to - make sure I have some ops. - -889 -00:36:56,091 --> 00:36:59,859 - So I'm gonna check to see if - the ops is not empty. - -890 -00:36:59,861 --> 00:37:04,529 - Okay, if you've handed me a - stack of no ops to evaluates, - -891 -00:37:04,531 --> 00:37:05,463 - I can't do that. - -892 -00:37:05,465 --> 00:37:06,698 - So I'm just gonna return nil. - -893 -00:37:06,700 --> 00:37:07,615 - 'Kay? - So - -894 -00:37:07,616 --> 00:37:08,531 - that's the very first thing, - -895 -00:37:08,534 --> 00:37:11,035 - I gotta make sure I have some - ops to work with. - -896 -00:37:11,037 --> 00:37:14,237 - Now, I'm gonna grab the first - op of the stack, so - -897 -00:37:14,239 --> 00:37:16,639 - in this example, I'm gonna - grab that x off of here. - -898 -00:37:16,641 --> 00:37:17,206 - 'Kay? - -899 -00:37:17,208 --> 00:37:18,574 - I'm gonna do that, - -900 -00:37:18,576 --> 00:37:24,012 - I'm gonna try to do that by - saying, let op equal ops. - -901 -00:37:24,014 --> 00:37:26,114 - 'Kay, ops is this argument, - right here. - -902 -00:37:26,116 --> 00:37:28,483 - 'Kay, that's the ops, you told - me to work on. - -903 -00:37:28,485 --> 00:37:31,519 - And we know how to removeLast. - -904 -00:37:31,521 --> 00:37:33,687 - Remember, removeLast from last - time? - -905 -00:37:33,689 --> 00:37:36,156 - Removes the last thing off an - array. - -906 -00:37:36,158 --> 00:37:38,992 - And when we are trying to make - an array look like a stack, - -907 -00:37:38,994 --> 00:37:40,594 - that's how we do it, okay? - -908 -00:37:40,595 --> 00:37:42,195 - We push things by putting - these on the end of the array. - -909 -00:37:42,197 --> 00:37:44,196 - We pop things by, by pulling - it out. - -910 -00:37:44,198 --> 00:37:45,431 - But you can see I got an error - there. - -911 -00:37:45,433 --> 00:37:48,166 - [BLANK_AUDIO] - -912 -00:37:48,168 --> 00:37:49,768 - And it's very important to - understand why I - -913 -00:37:49,770 --> 00:37:50,835 - have an error here, okay? - -914 -00:37:51,838 --> 00:37:53,704 - So I'm gonna click on it. - -915 -00:37:53,706 --> 00:37:54,805 - We're gonna read what it says, - -916 -00:37:54,807 --> 00:38:00,009 - it says, immutable value of - type array of op, - -917 -00:38:00,011 --> 00:38:04,113 - only has a mutating member - named removeLast. - -918 -00:38:04,115 --> 00:38:06,548 - Okay, well this is kind of a - formal way of saying, - -919 -00:38:06,550 --> 00:38:13,221 - you can't do removeLast on ops - because ops is immutable. - -920 -00:38:13,223 --> 00:38:14,455 - It's read-only. - -921 -00:38:14,457 --> 00:38:15,556 - You cannot mutate it. - -922 -00:38:15,558 --> 00:38:16,990 - You cannot change it. - -923 -00:38:16,992 --> 00:38:20,160 - Okay, why is ops read-only? - -924 -00:38:20,162 --> 00:38:23,063 - Well, there's two things to - think about here. - -925 -00:38:23,065 --> 00:38:26,899 - One is, when you pass - arguments into functions, - -926 -00:38:26,901 --> 00:38:29,702 - unless it's a class that - you're passing, - -927 -00:38:29,704 --> 00:38:32,137 - unless you're passing an - instance of a class. - -928 -00:38:32,139 --> 00:38:34,172 - The thing you pass is copied. - -929 -00:38:34,174 --> 00:38:35,791 - 'Kay? - -930 -00:38:35,792 --> 00:38:37,409 - It's very important to - understand that, - -931 -00:38:37,411 --> 00:38:38,876 - that's passed by value. - -932 -00:38:38,878 --> 00:38:40,845 - You're used to it in other - languages, - -933 -00:38:40,847 --> 00:38:43,313 - most languages do this, pass - by value. - -934 -00:38:43,315 --> 00:38:46,516 - Arrays and dictionaries are - not classes. - -935 -00:38:47,652 --> 00:38:49,952 - They're not classes in Swift. - -936 -00:38:49,954 --> 00:38:50,886 - They're structs. - -937 -00:38:50,888 --> 00:38:52,754 - You know, like a C struct? - -938 -00:38:52,756 --> 00:38:53,955 - 'Kay? - -939 -00:38:53,957 --> 00:38:55,723 - Arrays and dictionaries are - structs. - -940 -00:38:55,725 --> 00:38:58,759 - Structs in Swift look a lot - like classes. - -941 -00:38:58,761 --> 00:39:00,594 - They have functions, - -942 -00:39:00,595 --> 00:39:02,428 - they can even have properties - that have storage. - -943 -00:39:02,431 --> 00:39:04,865 - They're almost identical to a - class, really. - -944 -00:39:04,867 --> 00:39:09,102 - The only two huge differences - between structs and classes. - -945 -00:39:09,104 --> 00:39:12,638 - One is that classes can have - inheritance. - -946 -00:39:12,640 --> 00:39:15,274 - And structs cannot, okay? - -947 -00:39:15,276 --> 00:39:20,745 - But number two is that structs - are passed by value and - -948 -00:39:20,747 --> 00:39:25,049 - classes are passed by - reference, okay? - -949 -00:39:25,051 --> 00:39:27,751 - Very important that you - understand that distinction. - -950 -00:39:27,753 --> 00:39:30,687 - So structs are usually only - used for basic. - -951 -00:39:30,689 --> 00:39:33,289 - You know, components like - arrays and dictionaries. - -952 -00:39:33,291 --> 00:39:37,159 - Even doubles and ints are - structs in Swift, okay? - -953 -00:39:37,161 --> 00:39:38,627 - >> [COUGH] - -954 -00:39:38,628 --> 00:39:40,094 - >> And that's great because - that means doubles and - -955 -00:39:40,097 --> 00:39:42,564 - ints can have functions on - them and things like that, - -956 -00:39:42,566 --> 00:39:44,599 - which we will see as the - quarter goes by. - -957 -00:39:44,601 --> 00:39:46,501 - But those things are all - passed by values. - -958 -00:39:46,503 --> 00:39:48,669 - So that's the first thing to - understand is that this ops, - -959 -00:39:48,671 --> 00:39:52,139 - when I call evaluate, whatever - array of ops I pass to it, - -960 -00:39:52,141 --> 00:39:53,840 - it's gonna be copied. - -961 -00:39:53,842 --> 00:39:55,108 - Okay? - -962 -00:39:55,110 --> 00:39:57,643 - The second thing to understand - here is that they're kind of - -963 -00:39:57,645 --> 00:40:03,682 - an implicit let in front of - all things you pass. - -964 -00:40:03,684 --> 00:40:05,484 - In other words, they're - read-only. - -965 -00:40:05,486 --> 00:40:06,651 - Make sense? - -966 -00:40:06,653 --> 00:40:12,390 - And a read-only array can't be - mutated. - -967 -00:40:12,392 --> 00:40:14,475 - I can't append things to it. - -968 -00:40:14,476 --> 00:40:16,559 - You can't remove things from - it cuz it's read-only. - -969 -00:40:16,562 --> 00:40:21,364 - Now, I can actually put the - word var here, okay? - -970 -00:40:21,366 --> 00:40:22,999 - If I, sorry. - -971 -00:40:23,001 --> 00:40:25,267 - If I put the word var here, - -972 -00:40:25,269 --> 00:40:29,204 - then ops inside here look no - error. - -973 -00:40:29,206 --> 00:40:32,674 - Ops is a mutable array. - -974 -00:40:32,676 --> 00:40:34,575 - It's still a copy though. - -975 -00:40:34,577 --> 00:40:36,711 - So they copied it, made it - mutable. - -976 -00:40:36,713 --> 00:40:41,381 - And now inside here, I have a - mutable copy to work with. - -977 -00:40:41,383 --> 00:40:45,084 - Now, I'm not a big fan of - doing that, 'kay? - -978 -00:40:45,086 --> 00:40:46,118 - Putting var up here. - -979 -00:40:46,120 --> 00:40:47,586 - I think it's a little - confusing for - -980 -00:40:47,588 --> 00:40:49,221 - readers of the code, - -981 -00:40:49,222 --> 00:40:50,855 - to understand exactly what's - going on there. - -982 -00:40:50,858 --> 00:40:53,208 - So, I'm not gonna do that, - -983 -00:40:53,209 --> 00:40:55,559 - instead, I'm gonna make a - local variable here, which I'm - -984 -00:40:55,562 --> 00:41:00,865 - gonna call remainingOps and - I'm gonna set it equal to ops. - -985 -00:41:00,867 --> 00:41:03,000 - Now, when you set equals like - this, - -986 -00:41:04,103 --> 00:41:07,103 - that copies it if it's not a - class. - -987 -00:41:07,105 --> 00:41:08,571 - Classes are all by reference. - -988 -00:41:08,573 --> 00:41:09,438 - It's exactly, what you would - think. - -989 -00:41:09,440 --> 00:41:10,539 - >> [COUGH]. - >> But anything else, - -990 -00:41:10,541 --> 00:41:12,808 - strucks or enums or anything - else. - -991 -00:41:12,810 --> 00:41:14,543 - When you do equals here, - -992 -00:41:14,544 --> 00:41:16,277 - this is actually going to make - a copy of this, and - -993 -00:41:16,279 --> 00:41:17,895 - put it in here. - -994 -00:41:17,896 --> 00:41:19,512 - And since it's a var, it's - going to be mutable. - -995 -00:41:21,584 --> 00:41:23,083 - Okay? - -996 -00:41:23,084 --> 00:41:24,583 - So now I have a mutable array - of opts and - -997 -00:41:24,586 --> 00:41:26,519 - now I can say remainingOpts. - -998 -00:41:26,521 --> 00:41:27,854 - Remove the last one. - -999 -00:41:27,856 --> 00:41:30,122 - And now I truly do have the - remainingOpts. - -1000 -00:41:30,124 --> 00:41:32,358 - I've removed the first thing - in there. - -1001 -00:41:32,360 --> 00:41:35,594 - [BLANK_AUDIO] - -1002 -00:41:35,596 --> 00:41:38,463 - Did everyone understand that - little tidbit there? - -1003 -00:41:38,465 --> 00:41:39,464 - Yeah? - >> So there's a, - -1004 -00:41:39,466 --> 00:41:42,800 - like a, a unseen let in sort - of the opts? - -1005 -00:41:42,802 --> 00:41:43,600 - >> Yeah. - >> Why isn't that like in - -1006 -00:41:43,602 --> 00:41:47,371 - front of doubles and - -1007 -00:41:47,373 --> 00:41:48,672 - like ends or straightened - >> It is. - -1008 -00:41:48,674 --> 00:41:50,873 - So, the question is why is - there not a kind of unseen, - -1009 -00:41:50,875 --> 00:41:52,508 - let in front of all arguments? - -1010 -00:41:52,510 --> 00:41:54,376 - Pretty much all arguments to - functions kind of - -1011 -00:41:54,378 --> 00:41:55,577 - have that unseen let in there. - -1012 -00:41:55,579 --> 00:41:57,545 - They're all read on, 'kay? - -1013 -00:41:57,547 --> 00:41:59,681 - So and you could put var in - front of any one and - -1014 -00:41:59,683 --> 00:42:02,516 - turn it into a mutable copy of - it, - -1015 -00:42:02,518 --> 00:42:03,484 - that you could use locally. - -1016 -00:42:03,486 --> 00:42:04,885 - But if you only use it - locally, - -1017 -00:42:04,887 --> 00:42:06,219 - it's not that great a thing. - -1018 -00:42:06,221 --> 00:42:08,371 - Okay? - -1019 -00:42:08,372 --> 00:42:10,522 - Now, there is a way to have, - to pass by value things back - -1020 -00:42:10,525 --> 00:42:13,959 - out, but I'm not even gonna - talk about that. - -1021 -00:42:13,961 --> 00:42:14,726 - Okay. - -1022 -00:42:14,728 --> 00:42:16,027 - You can read about it. - -1023 -00:42:16,029 --> 00:42:17,328 - It's this in out thing. - -1024 -00:42:18,698 --> 00:42:20,665 - I'm not even gonna talk about - it. - -1025 -00:42:20,666 --> 00:42:22,633 - I really think it's better to - stay within the value, - -1026 -00:42:22,635 --> 00:42:25,035 - pass by value, pass by - reference parameters. - -1027 -00:42:25,037 --> 00:42:27,604 - I think you can get more - readable code that way. - -1028 -00:42:27,606 --> 00:42:30,139 - But there is a way, there is a - way I'm not going to talk - -1029 -00:42:30,141 --> 00:42:33,075 - about to do in out basically, - prime numbers that go in out. - -1030 -00:42:33,077 --> 00:42:33,842 - Yeah. - -1031 -00:42:33,844 --> 00:42:36,712 - >> Is there any way to - -1032 -00:42:36,714 --> 00:42:39,180 - [INAUDIBLE] - -1033 -00:42:39,182 --> 00:42:40,949 - >> Yeah that's what I just - said. - -1034 -00:42:40,950 --> 00:42:42,717 - There is a way to pass it kind - of by reference in out. - -1035 -00:42:42,719 --> 00:42:44,618 - You know, you pass it in, you - modify it, - -1036 -00:42:44,620 --> 00:42:47,054 - and then it'll come back out - when it's done at the end. - -1037 -00:42:47,056 --> 00:42:48,255 - So, it's kind of like by - reference. - -1038 -00:42:49,224 --> 00:42:50,323 - But the other thing you said - is, - -1039 -00:42:50,325 --> 00:42:52,558 - oh this is terrible I'm making - three copies of - -1040 -00:42:52,560 --> 00:42:55,394 - that dang thing, this must be - super slow. - -1041 -00:42:55,396 --> 00:42:57,029 - And the answer is no. - -1042 -00:42:57,031 --> 00:43:01,599 - Swift is super smart about not - actually copying it, - -1043 -00:43:01,601 --> 00:43:04,135 - until you actually make a - change to it. - -1044 -00:43:04,137 --> 00:43:07,271 - So here when it passes a copy - in it didn't really - -1045 -00:43:07,273 --> 00:43:10,073 - copy it, it just kinda passed - a pointer in but it knows that - -1046 -00:43:10,075 --> 00:43:13,576 - pointer is by, you know, not - by reference it's by value. - -1047 -00:43:13,578 --> 00:43:15,611 - And then when I copied it - again here. - -1048 -00:43:15,613 --> 00:43:17,146 - It still didn't really copy - it. - -1049 -00:43:17,148 --> 00:43:19,081 - Even if this array had 10,000 - things in it, - -1050 -00:43:19,083 --> 00:43:21,116 - it didn't make 10,000 copy of - it. - -1051 -00:43:21,118 --> 00:43:25,019 - It was only here where I - actually mutated, - -1052 -00:43:25,021 --> 00:43:26,120 - now it had to make a copy. - -1053 -00:43:26,122 --> 00:43:28,989 - And it may not even have made - an entire copy. - -1054 -00:43:28,991 --> 00:43:32,025 - It might have just kept track - of the changes, for example. - -1055 -00:43:32,027 --> 00:43:33,860 - So, it's super smart behind - the scenes. - -1056 -00:43:33,862 --> 00:43:34,861 - Sweet to very smart. - -1057 -00:43:34,863 --> 00:43:36,862 - So, don't worry too, about - much about oh, - -1058 -00:43:36,864 --> 00:43:38,630 - I'm copying these things over - and over. - -1059 -00:43:38,632 --> 00:43:40,332 - Swift is making the minimum - out of - -1060 -00:43:40,334 --> 00:43:41,433 - actual copying going on. - -1061 -00:43:41,435 --> 00:43:42,600 - Okay? - -1062 -00:43:42,602 --> 00:43:47,171 - All right, so now I have - remainingOpts here, - -1063 -00:43:47,173 --> 00:43:49,840 - which truly are my remaining - opts. - -1064 -00:43:49,842 --> 00:43:51,842 - 'Kay. - Because I've - -1065 -00:43:51,843 --> 00:43:53,843 - removed the top one, the x, - off the top. - -1066 -00:43:53,845 --> 00:43:56,279 - So now I've got all the - remainingOps, - -1067 -00:43:56,281 --> 00:43:59,181 - in this local variable here - called remainingOps. - -1068 -00:43:59,183 --> 00:44:00,566 - Okay. - -1069 -00:44:00,567 --> 00:44:01,950 - Now, what am I gonna do with - this op that I pulled off, - -1070 -00:44:01,952 --> 00:44:03,218 - this one on the top, x? - -1071 -00:44:03,220 --> 00:44:06,621 - Well I'm gonna get the - associated value from - -1072 -00:44:06,623 --> 00:44:07,888 - the enum. - -1073 -00:44:07,890 --> 00:44:11,792 - 'Kay. - Either this or these or this. - -1074 -00:44:11,794 --> 00:44:13,226 - And how do I do that? - -1075 -00:44:13,228 --> 00:44:15,094 - I use Switch. - -1076 -00:44:15,096 --> 00:44:17,496 - 'Kay, I told you that Switch - is really important. - -1077 -00:44:17,498 --> 00:44:20,032 - And now you're seeing that - Switch is really important. - -1078 -00:44:20,034 --> 00:44:21,867 - Switch is how you pull things - out, - -1079 -00:44:21,869 --> 00:44:23,668 - associated values out of - enums. - -1080 -00:44:23,670 --> 00:44:25,036 - So I'm just gonna switch on - the op. - -1081 -00:44:25,038 --> 00:44:27,772 - 'Kay, this is the op that I - pulled off the top, - -1082 -00:44:27,774 --> 00:44:30,708 - that x from the thing we did - on the board. - -1083 -00:44:30,710 --> 00:44:32,109 - And I'm just gonna look at the - cases, so - -1084 -00:44:32,111 --> 00:44:35,412 - I have the case operand, okay. - -1085 -00:44:35,414 --> 00:44:38,581 - Notice that it puts a little - dot here because it's - -1086 -00:44:38,583 --> 00:44:41,450 - really Op.Operand and it's - using type inference to - -1087 -00:44:41,452 --> 00:44:43,652 - know that it's Op.Operand, - right. - -1088 -00:44:43,654 --> 00:44:47,289 - Op.op, Op.Operand but it - doesn't need the op there. - -1089 -00:44:47,291 --> 00:44:50,892 - And here it's asking in this - space, what do you wanna do - -1090 -00:44:50,894 --> 00:44:54,628 - with the associated value if - you're handling this case. - -1091 -00:44:54,630 --> 00:44:56,864 - Where the enum is operand. - -1092 -00:44:56,866 --> 00:44:58,432 - 'Kay? - -1093 -00:44:58,434 --> 00:45:04,037 - Well I want to let that - associated value - -1094 -00:45:04,039 --> 00:45:10,175 - be assigned to a constant - called operand. - -1095 -00:45:10,177 --> 00:45:11,510 - 'Kay? - -1096 -00:45:11,512 --> 00:45:14,746 - And yes I could put var here, - which would do the same thing, - -1097 -00:45:14,748 --> 00:45:17,715 - except for I could then change - the thing in here. - -1098 -00:45:17,717 --> 00:45:20,685 - But I almost never wanna do - this, almost always let. - -1099 -00:45:20,687 --> 00:45:23,887 - So let operand means that - inside the handling of - -1100 -00:45:23,889 --> 00:45:27,157 - this case, 'kay, this case of - the switch. - -1101 -00:45:27,159 --> 00:45:30,693 - Inside here, operand is gonna - have the associated value of - -1102 -00:45:30,695 --> 00:45:31,427 - the operand. - -1103 -00:45:32,430 --> 00:45:34,196 - 'Kay? - -1104 -00:45:34,198 --> 00:45:35,897 - Oh, that's exactly what I - want. - -1105 -00:45:35,899 --> 00:45:38,599 - I'm just gonna return right - now I have to return this - -1106 -00:45:38,601 --> 00:45:40,301 - tuple right here. - -1107 -00:45:40,303 --> 00:45:42,569 - So I'm gonna returned the - operand. - -1108 -00:45:42,571 --> 00:45:45,005 - That's the result, 'kay. - -1109 -00:45:45,007 --> 00:45:47,191 - When I go here and - -1110 -00:45:47,192 --> 00:45:49,376 - I encounter that next one down - which was a four, I got a four - -1111 -00:45:49,378 --> 00:45:52,845 - I can just return that result - to evaluate this one. - -1112 -00:45:52,847 --> 00:45:55,881 - And I also though have to - return the remainingOps. - -1113 -00:45:57,018 --> 00:46:00,085 - 'Kay, so I'm just returning - the two values of this tuple, - -1114 -00:46:00,087 --> 00:46:02,754 - notice I don't have to put - result colon and - -1115 -00:46:02,756 --> 00:46:06,390 - remaining opt colon in here it - knows that those match and - -1116 -00:46:06,392 --> 00:46:07,224 - so it's still doing it. - -1117 -00:46:07,226 --> 00:46:09,159 - All right, makes sense. - -1118 -00:46:09,161 --> 00:46:13,763 - That's it for operand that's - all I have to do. - -1119 -00:46:13,765 --> 00:46:15,064 - It's kind of a, in the - recursion, - -1120 -00:46:15,066 --> 00:46:20,102 - it's kind of an end case. - -1121 -00:46:20,104 --> 00:46:21,069 - Yeah? - >> Is remainingOps part of - -1122 -00:46:21,071 --> 00:46:22,520 - the stack or heap? - -1123 -00:46:22,521 --> 00:46:23,970 - >> This one here, or this one - here? - -1124 -00:46:23,973 --> 00:46:24,989 - >> What in general - [INAUDIBLE]. - -1125 -00:46:24,990 --> 00:46:26,006 - >> Okay so, so the question - is, - -1126 -00:46:26,009 --> 00:46:29,276 - when I do something like this, - where is remainingOps? - -1127 -00:46:29,278 --> 00:46:30,377 - Is it in the heap? - -1128 -00:46:30,379 --> 00:46:31,812 - Is it on the stack? - -1129 -00:46:31,813 --> 00:46:33,246 - And the thing is, that's - implementation detail. - -1130 -00:46:34,282 --> 00:46:36,148 - So, you, you don't know, but - you don't care. - -1131 -00:46:38,018 --> 00:46:40,185 - All right, so that's operand. - -1132 -00:46:40,187 --> 00:46:42,020 - Operand was really, really - easy. - -1133 -00:46:42,022 --> 00:46:44,321 - How about our operation, - that's you, you, - -1134 -00:46:44,323 --> 00:46:46,090 - UnaryOperation right here. - -1135 -00:46:46,092 --> 00:46:49,659 - Now when we handle the case of - the unary operation, - -1136 -00:46:49,661 --> 00:46:52,195 - we don't need that first - associated value, - -1137 -00:46:52,197 --> 00:46:54,330 - that's the symbol, like plus. - -1138 -00:46:54,332 --> 00:46:56,332 - Okay well I'm evaluating here - I don't care what this - -1139 -00:46:56,334 --> 00:46:58,500 - symbol is, I only care what - the function is cause I'm - -1140 -00:46:58,502 --> 00:47:00,002 - gonna evaluate the function. - -1141 -00:47:00,004 --> 00:47:05,807 - So we can actually ignore this - by putting in underbar, 'kay? - -1142 -00:47:05,809 --> 00:47:08,642 - Underbar in swift is kind of - -1143 -00:47:08,644 --> 00:47:12,212 - the universal I don't care - about this thing. - -1144 -00:47:12,214 --> 00:47:14,681 - Okay and we're gonna see it - other places we use it - -1145 -00:47:14,683 --> 00:47:16,549 - where it's kinda like, I don't - really care about that. - -1146 -00:47:16,551 --> 00:47:18,251 - So you just put an underbar - there. - -1147 -00:47:18,253 --> 00:47:19,819 - That way you don't have to - declare a variable with - -1148 -00:47:19,821 --> 00:47:22,221 - some dumb name or something - like that. - -1149 -00:47:22,223 --> 00:47:24,389 - Just put an underbar it - ignores it. - -1150 -00:47:24,391 --> 00:47:25,323 - 'Kay? - -1151 -00:47:25,324 --> 00:47:26,256 - But I do care about this. - -1152 -00:47:26,259 --> 00:47:29,794 - I'm gonna let that equal the - operation that I'm doing. - -1153 -00:47:29,796 --> 00:47:30,361 - 'Kay? - -1154 -00:47:31,397 --> 00:47:32,929 - Everyone, make sense there? - -1155 -00:47:32,931 --> 00:47:34,897 - So I'm ignoring the string, - but - -1156 -00:47:34,899 --> 00:47:36,699 - I'm grabbing the operation. - -1157 -00:47:36,701 --> 00:47:40,402 - So here, what I wanna do is - return and I'll try to do it, - -1158 -00:47:40,404 --> 00:47:41,370 - but I'm not gonna be able to. - -1159 -00:47:41,372 --> 00:47:45,540 - I'm gonna say, return this - operation with - -1160 -00:47:45,542 --> 00:47:48,342 - its operand which I don't - have. - -1161 -00:47:48,344 --> 00:47:51,512 - And there's some remaining ops - that are leftover after I - -1162 -00:47:51,514 --> 00:47:52,579 - get the operand. - -1163 -00:47:52,581 --> 00:47:55,515 - So I'm kinda, I need to do - some stuff here to - -1164 -00:47:55,517 --> 00:47:58,251 - be able to return what I want. - -1165 -00:47:58,253 --> 00:48:01,053 - The first thing I need to do - is get the operand. - -1166 -00:48:01,055 --> 00:48:03,689 - 'Kay? - -1167 -00:48:03,690 --> 00:48:06,324 - So, I did a unary operation - let's say it was square root. - -1168 -00:48:06,326 --> 00:48:07,625 - I need to go back to the staff - and - -1169 -00:48:07,627 --> 00:48:10,862 - pick off the next thing but I - can't just - -1170 -00:48:10,864 --> 00:48:13,931 - assume that it's a number it - might be more operations so - -1171 -00:48:13,933 --> 00:48:17,001 - I have to recurse, so here's - where the recursion comes in. - -1172 -00:48:17,003 --> 00:48:20,103 - And I'm gonna show you how to - call a function that - -1173 -00:48:20,105 --> 00:48:22,172 - returns a tuple. - -1174 -00:48:22,174 --> 00:48:25,274 - And get it's value up so this - is important little example - -1175 -00:48:25,276 --> 00:48:27,677 - here, so there's two ways to - do it. - -1176 -00:48:27,679 --> 00:48:30,279 - I'm gonna do it one way here, - which is, - -1177 -00:48:30,281 --> 00:48:32,881 - I'm gonna let - operandEvaluation, - -1178 -00:48:32,883 --> 00:48:37,919 - which is just a local variable - that I'm inventing, equal call - -1179 -00:48:37,921 --> 00:48:43,057 - evaluate with the remainingOps - that I have. - -1180 -00:48:43,059 --> 00:48:45,025 - 'Kay, so here I've recursed. - -1181 -00:48:45,027 --> 00:48:46,459 - Okay, I'm recursing. - -1182 -00:48:46,461 --> 00:48:48,661 - And I just set it to - operandEvaluation. - -1183 -00:48:48,663 --> 00:48:51,564 - Now, let's look at the type of - this thing. - -1184 -00:48:51,566 --> 00:48:55,300 - If I look at its type, you can - see that it's a tuple. - -1185 -00:48:55,302 --> 00:48:56,468 - That's its type. - -1186 -00:48:56,470 --> 00:48:58,770 - It's a tuple result - remainingOps. - -1187 -00:48:58,772 --> 00:49:00,671 - It's this tuple right here. - -1188 -00:49:00,673 --> 00:49:03,140 - That is the type of this - operandEvaluation. - -1189 -00:49:04,309 --> 00:49:06,242 - So now that I have that tuple, - -1190 -00:49:06,244 --> 00:49:09,245 - it's the result of evaluation - how do I get the result and - -1191 -00:49:09,247 --> 00:49:13,716 - the remaining op out of it - well I can get the operand by - -1192 -00:49:13,718 --> 00:49:19,621 - saying operand eval, [UNKNOWN] - operandEvaluation.result. - -1193 -00:49:19,623 --> 00:49:21,423 - 'Kay? - -1194 -00:49:21,424 --> 00:49:23,224 - So that just pull this is the - tuple here I'm - -1195 -00:49:23,226 --> 00:49:26,227 - getting this value of the - tuple out of there. - -1196 -00:49:26,229 --> 00:49:27,461 - Now what type is this? - -1197 -00:49:29,298 --> 00:49:29,863 - Anybody? - -1198 -00:49:30,865 --> 00:49:31,931 - It's an optional. - -1199 -00:49:31,932 --> 00:49:32,998 - You're pretty safe saying - optional when I - -1200 -00:49:33,001 --> 00:49:34,099 - ask what type it is, aren't - you? - -1201 -00:49:34,101 --> 00:49:35,801 - It's almost always an - optional. - -1202 -00:49:35,803 --> 00:49:37,168 - Cuz I usually don't ask if - it's not. - -1203 -00:49:37,170 --> 00:49:40,672 - But it is indeed an optional, - an optional double. - -1204 -00:49:40,674 --> 00:49:42,707 - It's this type right here, - okay? - -1205 -00:49:42,709 --> 00:49:46,043 - So we need to turn it into a - double if we're gonna pass it - -1206 -00:49:46,045 --> 00:49:48,078 - to this operation right here. - -1207 -00:49:48,080 --> 00:49:52,648 - So I'm gonna use if let to - turn that into a double. - -1208 -00:49:52,650 --> 00:49:55,084 - 'Kay? - -1209 -00:49:55,085 --> 00:49:57,519 - Now, I can actually do this - because I have the operand. - -1210 -00:49:57,521 --> 00:49:58,587 - Just got it right here. - -1211 -00:49:58,589 --> 00:50:00,755 - 'Kay? - This is now a double, see? - -1212 -00:50:00,757 --> 00:50:04,125 - And I can call this operation - right here. - -1213 -00:50:04,127 --> 00:50:06,327 - And this is the remaining ops, - but this has got to - -1214 -00:50:06,329 --> 00:50:09,229 - be the remaining ops after we - recursed. - -1215 -00:50:09,231 --> 00:50:13,233 - So it's gotta be the remaining - ops in this operandEvaluation. - -1216 -00:50:13,235 --> 00:50:15,368 - So that - operandEvaluation.remaining- - -1217 -00:50:15,370 --> 00:50:19,471 - Ops. - Everybody cool with that? - -1218 -00:50:19,473 --> 00:50:21,206 - So that's it. - -1219 -00:50:21,208 --> 00:50:25,343 - It's just recurse, we just - recursed to evaluate that. - -1220 -00:50:25,345 --> 00:50:29,180 - If this fails if, if this - recursion returned nil, - -1221 -00:50:29,182 --> 00:50:31,849 - then this is, this, if let's - not gonna happen this - -1222 -00:50:31,851 --> 00:50:34,584 - return's not gonna happen, - gonna fall all the way out and - -1223 -00:50:34,586 --> 00:50:37,454 - return nill which is what we - want, 'kay. - -1224 -00:50:37,456 --> 00:50:39,522 - We failed in any of our - recursive attempts to - -1225 -00:50:39,524 --> 00:50:40,756 - get the operands we need, - -1226 -00:50:40,758 --> 00:50:42,825 - we gotta fail all the way up - to the top level. - -1227 -00:50:42,827 --> 00:50:46,028 - [BLANK_AUDIO] - -1228 -00:50:46,030 --> 00:50:48,063 - Okay now binary operation. - -1229 -00:50:49,299 --> 00:50:52,466 - Also okay, let's do yeah, - binary here case. - -1230 -00:50:53,535 --> 00:50:54,267 - Binary. - -1231 -00:50:55,470 --> 00:50:57,570 - Obviously same exact thing - here. - -1232 -00:50:57,572 --> 00:50:59,438 - We don't care about that. - -1233 -00:50:59,440 --> 00:51:00,906 - And here we're gonna let - operation. - -1234 -00:51:00,908 --> 00:51:03,708 - And we're gonna do the exactly - the same thing we did - -1235 -00:51:03,710 --> 00:51:06,577 - here but we just have to do it - twice because we have two - -1236 -00:51:06,579 --> 00:51:08,646 - operands to do here, through - here. - -1237 -00:51:08,648 --> 00:51:15,052 - So let's let opp1Evaluation = - evaluate(remainingOps). - -1238 -00:51:16,088 --> 00:51:17,487 - 'Kay. - -1239 -00:51:17,488 --> 00:51:18,887 - And then if we can let - operand1 = - -1240 -00:51:18,890 --> 00:51:20,756 - op1Evaluation.result. - -1241 -00:51:20,758 --> 00:51:23,625 - 'Kay, then we got op1, that's - good. - -1242 -00:51:23,627 --> 00:51:27,262 - So now let's let op2Evaluation - = - -1243 -00:51:27,264 --> 00:51:32,600 - evaluation(op1Evaluation.rema- - iningOps). - -1244 -00:51:32,602 --> 00:51:36,370 - 'Kay? - -1245 -00:51:36,371 --> 00:51:40,139 - And if we can let operand, - oops, if we can let operand2 - -1246 -00:51:40,142 --> 00:51:44,844 - = op2Evaluation.result, then - we can - -1247 -00:51:44,846 --> 00:51:50,716 - return (operation(operand1, - operand2). - -1248 -00:51:50,718 --> 00:51:53,185 - 'Kay? - And - -1249 -00:51:53,186 --> 00:51:55,653 - we'll have - op2Evaluation.remainingOps) as - -1250 -00:51:55,656 --> 00:51:57,355 - our remaining ops. - -1251 -00:51:57,357 --> 00:52:00,825 - Okay? - [BLANK_AUDIO] - -1252 -00:52:00,827 --> 00:52:01,692 - Make sense? - -1253 -00:52:01,694 --> 00:52:02,426 - All right. - What's our. - -1254 -00:52:02,428 --> 00:52:03,159 - We have an error here. - -1255 -00:52:03,161 --> 00:52:04,560 - What is it? - -1256 -00:52:04,562 --> 00:52:05,695 - okay. - Yeah, - -1257 -00:52:05,696 --> 00:52:06,829 - this is a good error to cover - here. - -1258 -00:52:06,831 --> 00:52:09,665 - See this it says method must - be declared private because - -1259 -00:52:09,667 --> 00:52:12,501 - this parameter uses a private - value. - -1260 -00:52:12,503 --> 00:52:16,137 - And sure enough op is private - so this has to be private. - -1261 -00:52:17,740 --> 00:52:19,273 - 'Kay? - -1262 -00:52:20,476 --> 00:52:21,875 - Now notice by the way, - -1263 -00:52:21,877 --> 00:52:28,080 - I don't have default: break - here in this switch. - -1264 -00:52:28,082 --> 00:52:30,215 - And why do I not have that? - -1265 -00:52:30,217 --> 00:52:33,418 - Because I've handled every - possible value of op. - -1266 -00:52:35,088 --> 00:52:35,986 - 'Kay? - There are only - -1267 -00:52:35,988 --> 00:52:37,254 - three kinds of op. - -1268 -00:52:37,256 --> 00:52:38,522 - I've handled them all. - -1269 -00:52:38,524 --> 00:52:40,374 - So I don't need any default. - -1270 -00:52:40,375 --> 00:52:42,225 - It wasn't like in the other - one where we had a string and - -1271 -00:52:42,227 --> 00:52:44,761 - we only handle a few strings, - we had a default break. - -1272 -00:52:44,763 --> 00:52:47,863 - You don't put default break in - when you handle every thing. - -1273 -00:52:47,865 --> 00:52:49,598 - And it's really bad programing - style to - -1274 -00:52:49,600 --> 00:52:51,633 - put a default break in every - single switch. - -1275 -00:52:51,635 --> 00:52:54,903 - 'Kay, you should only put them - in on the ones where you - -1276 -00:52:54,905 --> 00:52:58,373 - truly are breaking because you - can't handle every case. - -1277 -00:52:58,375 --> 00:53:00,574 - 'Kay? - All right. - -1278 -00:53:00,576 --> 00:53:03,844 - Now, the last thing we have to - do is just call this recursive - -1279 -00:53:03,846 --> 00:53:06,113 - version from here. - -1280 -00:53:06,115 --> 00:53:08,782 - And I'm gonna call this one - and - -1281 -00:53:08,784 --> 00:53:11,117 - get these tuple values a - little differently. - -1282 -00:53:11,119 --> 00:53:12,718 - I'm not gonna call it in the - same way here. - -1283 -00:53:12,720 --> 00:53:14,920 - I'm not gonna say, let - something equal. - -1284 -00:53:14,922 --> 00:53:20,091 - Instead I'm gonna say let a - tuple which has let's call it - -1285 -00:53:20,093 --> 00:53:24,062 - say (result, remainder) = - evaluate and - -1286 -00:53:24,064 --> 00:53:28,666 - I'm gonna pass my whole - (opStack) here, okay. - -1287 -00:53:28,668 --> 00:53:31,668 - So this is a different way to - call a function that returns - -1288 -00:53:31,670 --> 00:53:35,305 - a tuple here you actually let - a tuple equal the result. - -1289 -00:53:35,307 --> 00:53:37,974 - Instead of letting a single - thing equal result and - -1290 -00:53:37,976 --> 00:53:42,111 - then using the dots to get it, - you let the tuple equal it and - -1291 -00:53:42,113 --> 00:53:45,547 - notice that these names don't - have to be the same as these - -1292 -00:53:45,549 --> 00:53:48,283 - names so result is the same, - but here I - -1293 -00:53:48,285 --> 00:53:52,286 - use the word remainder instead - of the word remainingOps. - -1294 -00:53:52,288 --> 00:53:53,754 - Okay they do not have to be - the same. - -1295 -00:53:55,024 --> 00:54:00,694 - And then here we just return - our result. - -1296 -00:54:00,696 --> 00:54:02,261 - Okay? - -1297 -00:54:02,263 --> 00:54:04,163 - So we learned a lot right - there, okay. - -1298 -00:54:04,165 --> 00:54:05,297 - We learned about tuple, - -1299 -00:54:05,299 --> 00:54:08,033 - passing you know things back - tuples in - -1300 -00:54:08,035 --> 00:54:13,237 - different ways you know how to - ignore things in enums and - -1301 -00:54:13,239 --> 00:54:15,106 - when we're getting associate - values all that stuff. - -1302 -00:54:15,108 --> 00:54:16,974 - So hopefully, you got all - that. - -1303 -00:54:16,976 --> 00:54:19,676 - I see a few people still kinda - catching up on their typing. - -1304 -00:54:19,678 --> 00:54:21,444 - So I'll break for second here. - -1305 -00:54:21,446 --> 00:54:24,480 - [BLANK_AUDIO] - -1306 -00:54:24,482 --> 00:54:27,283 - [SOUND] So that's it that's - the entire implementation of - -1307 -00:54:27,285 --> 00:54:28,384 - our calculator brain. - -1308 -00:54:28,386 --> 00:54:30,919 - It wasn't really that bad - actually, right? - -1309 -00:54:30,921 --> 00:54:33,722 - Pretty simple little data - structure here. - -1310 -00:54:33,724 --> 00:54:36,858 - Just have to say what our - known ops are. - -1311 -00:54:36,860 --> 00:54:38,726 - And have this recursion which - you know, - -1312 -00:54:38,728 --> 00:54:42,196 - actually is quite simple, - powerful code. - -1313 -00:54:42,198 --> 00:54:44,031 - If you're not comfortable with - your recursion I - -1314 -00:54:44,033 --> 00:54:46,533 - can see how it might be a - little bit disturbing. - -1315 -00:54:46,535 --> 00:54:48,301 - But go stare at it for - -1316 -00:54:48,302 --> 00:54:50,068 - awhile and you'll, you'll get - it, how it works. - -1317 -00:54:50,071 --> 00:54:51,921 - Okay. - -1318 -00:54:51,922 --> 00:54:53,772 - So, now that we've got this - new calculator brain, - -1319 -00:54:53,775 --> 00:54:57,509 - we have to use it in our old - controller. - -1320 -00:54:57,511 --> 00:54:59,678 - Okay, yeah question? - -1321 -00:54:59,679 --> 00:55:01,846 - >> Do we have to let like the - op stack equal the remainder? - -1322 -00:55:01,848 --> 00:55:04,549 - >> Do we have to let the op - stack equal the remainder? - -1323 -00:55:04,551 --> 00:55:05,349 - Here, you mean? - -1324 -00:55:05,351 --> 00:55:05,916 - >> Yeah. - -1325 -00:55:07,119 --> 00:55:08,418 - >> well, we're not gonna use - remainder, so - -1326 -00:55:08,420 --> 00:55:10,620 - actually, even I could put I - don't care here. - -1327 -00:55:10,622 --> 00:55:13,255 - I only put that remainder - there to show you could have - -1328 -00:55:13,257 --> 00:55:15,257 - a different name, but I'm not - using the remainder. - -1329 -00:55:15,259 --> 00:55:16,892 - I only want the result. - -1330 -00:55:16,894 --> 00:55:19,861 - You see. - >> Won't the op stack contain - -1331 -00:55:19,862 --> 00:55:22,829 - what was previously in it - before you evaluate it? - -1332 -00:55:22,832 --> 00:55:25,016 - >> Yes, the op stack will be - -1333 -00:55:25,017 --> 00:55:27,201 - unaffected by this because op - stack is an array. - -1334 -00:55:27,203 --> 00:55:28,702 - Arrays are passed by value so - -1335 -00:55:28,704 --> 00:55:30,837 - a copy of it gets passed into - here. - -1336 -00:55:30,839 --> 00:55:33,506 - So this would be untouched and - which is what I want. - -1337 -00:55:33,508 --> 00:55:36,242 - I don't want evaluate to - consume my op stack. - -1338 -00:55:36,244 --> 00:55:38,010 - I wanna be able to call - evaluate over and - -1339 -00:55:38,012 --> 00:55:38,744 - over and over. - -1340 -00:55:38,746 --> 00:55:39,945 - 'Kay? - Especially if, - -1341 -00:55:39,947 --> 00:55:43,581 - I let's say introduced - variable operands and - -1342 -00:55:43,583 --> 00:55:45,550 - that's what you're homeworks - gonna be, then I wouldn't - -1343 -00:55:45,552 --> 00:55:47,685 - want to change the variables - to different things and - -1344 -00:55:47,687 --> 00:55:49,520 - be calling it over and - -1345 -00:55:49,521 --> 00:55:51,354 - over with different values for - the variable for example and - -1346 -00:55:51,357 --> 00:55:53,690 - then maybe next week I can - have an assignment where I'm - -1347 -00:55:53,692 --> 00:55:57,894 - gonna make your graph such a - thing, which I'm going to do. - -1348 -00:55:57,896 --> 00:55:59,012 - Okay? - -1349 -00:55:59,013 --> 00:56:00,129 - So that's why I wanna do that. - -1350 -00:56:00,131 --> 00:56:02,131 - So anyway, yeah, remainder - here can just be anything. - -1351 -00:56:02,133 --> 00:56:03,532 - I'm actually gonna put this - here because we're - -1352 -00:56:03,534 --> 00:56:05,300 - gonna print one this in a - second just so - -1353 -00:56:05,302 --> 00:56:06,567 - we can get a better look at - what's going on. - -1354 -00:56:06,569 --> 00:56:10,904 - But first, let's go back to - our controller and use this - -1355 -00:56:10,906 --> 00:56:14,007 - calculator brain, this nice - model we just invented. - -1356 -00:56:14,009 --> 00:56:15,842 - Let's use it. - Now, - -1357 -00:56:15,843 --> 00:56:17,676 - I'm gonna show you how to get - two things on screen at - -1358 -00:56:17,679 --> 00:56:18,644 - the same time. - -1359 -00:56:18,646 --> 00:56:20,880 - That aren't necessarily - directly related. - -1360 -00:56:20,882 --> 00:56:23,549 - Before we have the story board - and then I went up and - -1361 -00:56:23,551 --> 00:56:25,784 - clicked this system editor - right here and - -1362 -00:56:25,786 --> 00:56:27,319 - it showed me the controller. - -1363 -00:56:27,320 --> 00:56:28,853 - Because the system editor - figured out that, oh, - -1364 -00:56:28,855 --> 00:56:30,388 - if you have the story board up - you probably want - -1365 -00:56:30,390 --> 00:56:33,257 - the controller for the scene - you have selected. - -1366 -00:56:33,259 --> 00:56:34,992 - But here it's like, I don't - know what to show you. - -1367 -00:56:34,994 --> 00:56:36,827 - So I'm gonna show you a - different way to - -1368 -00:56:36,829 --> 00:56:39,229 - get something in here, two - ways actually. - -1369 -00:56:39,231 --> 00:56:41,931 - One is if you go to this top - bar where - -1370 -00:56:41,933 --> 00:56:44,667 - it says counterparts, you can - mouse down and - -1371 -00:56:44,669 --> 00:56:47,603 - you can find all kinds of - things about this - -1372 -00:56:47,605 --> 00:56:50,272 - like subclasses of this class - on the left. - -1373 -00:56:51,341 --> 00:56:54,642 - Superclasses of this [UNKNOWN] - class on the left. - -1374 -00:56:54,644 --> 00:56:57,111 - Of course it has no - superclasses or subclasses. - -1375 -00:56:57,113 --> 00:57:00,547 - But other things, things it - includes are included by it. - -1376 -00:57:00,549 --> 00:57:02,115 - You can also just manually go - in. - -1377 -00:57:02,117 --> 00:57:03,283 - We can go over here for - example and - -1378 -00:57:03,285 --> 00:57:06,152 - find our view controller and - load it up that way, but - -1379 -00:57:06,154 --> 00:57:09,088 - I'm gonna show you a different - way than doing that - -1380 -00:57:09,090 --> 00:57:11,423 - which is to go over here to - your navigator. - -1381 -00:57:11,425 --> 00:57:14,893 - If you hold down Option and - press on - -1382 -00:57:14,895 --> 00:57:18,663 - a file like ViewController it - will appear on the right. - -1383 -00:57:18,665 --> 00:57:20,464 - 'Kay? - -1384 -00:57:20,466 --> 00:57:22,866 - So Option clicking in here is - another good way to - -1385 -00:57:22,868 --> 00:57:23,767 - put things on the right. - -1386 -00:57:25,437 --> 00:57:27,320 - Okay? - -1387 -00:57:27,321 --> 00:57:29,204 - So now here we have our - calculator brain on the left - -1388 -00:57:29,207 --> 00:57:31,040 - and we have our controller on - the right, - -1389 -00:57:31,042 --> 00:57:34,943 - we are going to rip out all of - the stuff in our - -1390 -00:57:34,945 --> 00:57:39,180 - controller that had to do with - being calculator. - -1391 -00:57:39,182 --> 00:57:41,716 - Okay, so that's all this stuff - right in here. - -1392 -00:57:41,718 --> 00:57:43,484 - 'Kay. - -1393 -00:57:43,485 --> 00:57:45,251 - All this calculating stuff, we - don't need any of this - -1394 -00:57:45,254 --> 00:57:47,254 - because those were only called - from there. - -1395 -00:57:47,256 --> 00:57:49,022 - 'Kay, so our controller's - getting quite simple, - -1396 -00:57:49,024 --> 00:57:50,757 - our controller hardly has - anything left in it. - -1397 -00:57:50,759 --> 00:57:54,727 - And that's because the UI only - needs this to be controlled. - -1398 -00:57:54,729 --> 00:57:56,579 - 'Kay? - -1399 -00:57:56,580 --> 00:57:58,430 - We also don't need our operand - stack because the brain is - -1400 -00:57:58,432 --> 00:58:00,766 - gonna do that. - -1401 -00:58:00,767 --> 00:58:03,101 - However, we do need a new - instance variable here - -1402 -00:58:03,103 --> 00:58:04,903 - which is the calculator brain. - -1403 -00:58:05,905 --> 00:58:07,838 - Okay I'm just gonna create one - like that, - -1404 -00:58:07,840 --> 00:58:12,676 - this is extremely common okay - this is - -1405 -00:58:12,678 --> 00:58:16,680 - the green arrow that goes from - the controller to the model. - -1406 -00:58:16,682 --> 00:58:18,948 - Remember that in our MVC talk - that I did last time I - -1407 -00:58:18,950 --> 00:58:21,584 - said that the controller has a - green arrow to the model, - -1408 -00:58:21,586 --> 00:58:24,386 - it can talk to it all at once, - say anything it wants. - -1409 -00:58:24,388 --> 00:58:26,922 - This is essentially that green - arrow. - -1410 -00:58:26,924 --> 00:58:29,591 - This is our model right here. - -1411 -00:58:29,593 --> 00:58:31,592 - And this is the controller - this is how the controller - -1412 -00:58:31,594 --> 00:58:33,661 - talks to it through this thing - we call the brain. - -1413 -00:58:33,663 --> 00:58:35,562 - Thing you can call it anything - you want and - -1414 -00:58:35,564 --> 00:58:38,298 - of course this might be much - more complicated green arrow, - -1415 -00:58:38,300 --> 00:58:40,767 - it might be a network database - that is connecting to you to - -1416 -00:58:40,769 --> 00:58:41,934 - get the data. - -1417 -00:58:41,936 --> 00:58:43,102 - Okay? - -1418 -00:58:43,104 --> 00:58:45,671 - But in our case it's this very - simple little brain. - -1419 -00:58:45,673 --> 00:58:47,206 - Okay. - -1420 -00:58:47,207 --> 00:58:48,740 - So now we don't need this - either down here. - -1421 -00:58:48,742 --> 00:58:51,343 - This is where we're appending - onto the op stack and - -1422 -00:58:51,345 --> 00:58:52,044 - printing it out. - -1423 -00:58:52,045 --> 00:58:52,744 - So we don't need that. - -1424 -00:58:52,746 --> 00:58:57,548 - But we do need an enter to - push the operand onto - -1425 -00:58:57,550 --> 00:58:58,615 - the stack. - -1426 -00:58:59,718 --> 00:59:00,516 - Okay. - -1427 -00:59:00,518 --> 00:59:03,519 - So here I'm just gonna say, - -1428 -00:59:03,521 --> 00:59:08,657 - that I'm gonna say I'm just - gonna - -1429 -00:59:08,659 --> 00:59:13,561 - say brain.pushOperand(display) - value. - -1430 -00:59:13,563 --> 00:59:15,413 - 'Kay? - -1431 -00:59:15,414 --> 00:59:17,264 - That's the main thing I need - to do, is just do that. - -1432 -00:59:17,266 --> 00:59:21,902 - One thing though is, I also - need to update my display. - -1433 -00:59:21,904 --> 00:59:23,870 - Because when I push this - operand, - -1434 -00:59:23,872 --> 00:59:25,672 - that's gonna change the brain. - -1435 -00:59:25,674 --> 00:59:28,341 - I need to call that evaluate, - right? - -1436 -00:59:28,343 --> 00:59:29,442 - And get the value. - -1437 -00:59:29,443 --> 00:59:30,542 - So I could call evaluate here, - but - -1438 -00:59:30,544 --> 00:59:34,613 - actually, I'm gonna go back to - my brain, and I'm gonna change - -1439 -00:59:34,615 --> 00:59:39,484 - pushOperand to return the va, - the result of evaluating. - -1440 -00:59:39,486 --> 00:59:42,486 - Typing today. - -1441 -00:59:43,789 --> 00:59:46,623 - From it, from its, from - internally, so - -1442 -00:59:46,625 --> 00:59:48,991 - I'm gonna return evaluate - here. - -1443 -00:59:48,993 --> 00:59:50,593 - So that every time you push an - operand, - -1444 -00:59:50,595 --> 00:59:52,127 - it'll just return the - evaluation. - -1445 -00:59:52,129 --> 00:59:55,163 - Now one could argue whether - this is the best thing to do. - -1446 -00:59:55,165 --> 00:59:57,932 - Because, you know, you might - not be interested in - -1447 -00:59:57,934 --> 01:00:00,568 - the result of evaluating that - right now. - -1448 -01:00:00,570 --> 01:00:03,671 - But it kind of feels to me - kind of good. - -1449 -01:00:03,673 --> 01:00:05,339 - And it's not gonna be, - -1450 -01:00:05,341 --> 01:00:07,341 - there's not gonna be that many - things on the stack. - -1451 -01:00:07,343 --> 01:00:10,143 - You're not gonna usually have - calculator brain - -1452 -01:00:10,145 --> 01:00:12,712 - have 1,000 operations and - operands, although you could. - -1453 -01:00:12,714 --> 01:00:14,013 - But you're not usually going - to so - -1454 -01:00:14,015 --> 01:00:16,548 - it's probably not a - performance issue. - -1455 -01:00:16,550 --> 01:00:19,751 - To have it just return this - and it'll make caller's code, - -1456 -01:00:19,753 --> 01:00:22,320 - you know, look a little - simpler. - -1457 -01:00:22,322 --> 01:00:24,522 - And if they don't want this - return value, - -1458 -01:00:25,858 --> 01:00:27,808 - then they can just ignore it. - -1459 -01:00:27,809 --> 01:00:29,759 - They don't have to use it but - I am gonna use it. - -1460 -01:00:29,762 --> 01:00:31,495 - So, when I push this operand - right here, - -1461 -01:00:31,497 --> 01:00:35,798 - I'm gonna say, I'm gonna if - let the results equal that. - -1462 -01:00:36,734 --> 01:00:38,000 - Okay, because it's an - optional. - -1463 -01:00:39,036 --> 01:00:41,836 - And if it's not nil then I'm - gonna - -1464 -01:00:41,838 --> 01:00:43,671 - set the display value to the - result. - -1465 -01:00:43,673 --> 01:00:46,140 - So in other words, every time - I push an operand, - -1466 -01:00:46,142 --> 01:00:49,343 - I'm gonna up my display value - with the evaluation. - -1467 -01:00:49,345 --> 01:00:50,811 - Make sense? - -1468 -01:00:50,813 --> 01:00:53,446 - Okay, what if this comes back - nil? - -1469 -01:00:54,982 --> 01:00:56,615 - So, I push something on, - -1470 -01:00:56,617 --> 01:00:59,151 - this is not gonna happen - probably with Push Operand, - -1471 -01:00:59,153 --> 01:01:02,587 - but it might, and after your - homework it might. - -1472 -01:01:02,589 --> 01:01:04,022 - So, what if I push and it - comes back nil? - -1473 -01:01:04,024 --> 01:01:07,258 - Well, now I'm kinda stuck, - okay? - -1474 -01:01:07,260 --> 01:01:10,728 - This is why, in your homework - assignment, I suggested, wow - -1475 -01:01:10,730 --> 01:01:13,730 - wouldn't it be cool if display - value took an optional. - -1476 -01:01:15,100 --> 01:01:17,600 - Right, if display value took - and returned an optional. - -1477 -01:01:17,602 --> 01:01:20,769 - You could put something - sensible in the display when - -1478 -01:01:20,771 --> 01:01:23,605 - you had something that - couldn't be evaluated. - -1479 -01:01:23,607 --> 01:01:25,874 - So in assignment two making - display value into - -1480 -01:01:25,876 --> 01:01:27,809 - an optional is gonna be - required task. - -1481 -01:01:27,811 --> 01:01:29,977 - So you might as well do it for - homework one, - -1482 -01:01:29,979 --> 01:01:33,447 - cuz you're gonna have to do it - for homework two anyway. - -1483 -01:01:33,449 --> 01:01:35,182 - Okay. - -1484 -01:01:35,183 --> 01:01:36,916 - Just wanted to give you more - time because I didn't - -1485 -01:01:36,917 --> 01:01:38,650 - really teach you the things - about NumberFormatter and - -1486 -01:01:38,653 --> 01:01:41,320 - stuff in time for assignment - one. - -1487 -01:01:41,322 --> 01:01:44,623 - But it's going to be required - and that's because the best I - -1488 -01:01:44,625 --> 01:01:48,093 - can do here is maybe say - display value equals zero. - -1489 -01:01:48,095 --> 01:01:50,962 - That's really lame but that's - the best I can do. - -1490 -01:01:50,964 --> 01:01:54,432 - I really wanna say, display - value was nil, okay. - -1491 -01:01:54,434 --> 01:01:56,634 - I really just wanna set - display value equal to - -1492 -01:01:56,636 --> 01:01:58,953 - the result of this. - -1493 -01:01:58,954 --> 01:02:01,271 - And I wanna have nil, you - know, clear out my display or - -1494 -01:02:01,274 --> 01:02:02,606 - in assignment two, - -1495 -01:02:02,608 --> 01:02:06,743 - extra credit, maybe it puts an - error message in my display. - -1496 -01:02:07,912 --> 01:02:09,545 - Now that's extra credit, but - -1497 -01:02:09,547 --> 01:02:11,246 - that would be an even better - thing to put there. - -1498 -01:02:12,216 --> 01:02:14,216 - Okay? - -1499 -01:02:14,217 --> 01:02:16,217 - But same thing for, for - forming the operation. - -1500 -01:02:16,219 --> 01:02:17,652 - Here's our operation right - here. - -1501 -01:02:17,654 --> 01:02:21,005 - And I'm just gonna say, - -1502 -01:02:21,006 --> 01:02:24,357 - if I can let the result equal - brains perform operation of - -1503 -01:02:24,360 --> 01:02:27,361 - the operation that I got off - the button, then I'm going to - -1504 -01:02:27,363 --> 01:02:29,963 - let my display value equal - that result. - -1505 -01:02:31,366 --> 01:02:34,667 - Otherwise I'm going to do the - very lame thing of - -1506 -01:02:34,669 --> 01:02:38,904 - saying display value equals, - whoops, value equals zero. - -1507 -01:02:38,906 --> 01:02:40,389 - Okay? - Unders, - -1508 -01:02:40,390 --> 01:02:41,873 - people understand why that's - kind of lame? - -1509 -01:02:41,875 --> 01:02:43,240 - All right. - -1510 -01:02:45,644 --> 01:02:47,077 - Okay. - -1511 -01:02:47,079 --> 01:02:48,144 - So that's it. - -1512 -01:02:48,146 --> 01:02:49,812 - Look at how simple our - controller is here. - -1513 -01:02:49,814 --> 01:02:52,481 - It has almost no code in it, - okay. - -1514 -01:02:52,483 --> 01:02:54,550 - And that's really iOS is great - about that. - -1515 -01:02:54,552 --> 01:02:56,885 - It really is pretty good about - making it so - -1516 -01:02:56,887 --> 01:02:58,920 - that you can build your UI - mostly graphically so - -1517 -01:02:58,922 --> 01:03:01,923 - that there's very little code - to control what's going on. - -1518 -01:03:01,925 --> 01:03:03,491 - And then even our model, - -1519 -01:03:03,493 --> 01:03:05,759 - which is a pretty powerful - calculator right now, - -1520 -01:03:05,761 --> 01:03:07,961 - we could add as many functions - as we wanted to. - -1521 -01:03:07,963 --> 01:03:09,963 - It's just one liners here. - -1522 -01:03:09,965 --> 01:03:13,766 - And it would be capable of, - you know, evaluating any se, - -1523 -01:03:13,768 --> 01:03:15,334 - series of them that's - evaluatable. - -1524 -01:03:15,336 --> 01:03:18,003 - And it's also set up to do - your homework, okay, - -1525 -01:03:18,005 --> 01:03:19,738 - which is to add those - variables, - -1526 -01:03:19,740 --> 01:03:22,140 - to be able to push operands - that are variables. - -1527 -01:03:22,142 --> 01:03:25,309 - The other thing your homework - is gonna ask you to do is to - -1528 -01:03:25,311 --> 01:03:28,112 - eval, to draw this, okay, - -1529 -01:03:28,114 --> 01:03:30,848 - the contents of it in a human - readable form. - -1530 -01:03:30,850 --> 01:03:33,850 - Using infix notation like this - with parentheses when - -1531 -01:03:33,852 --> 01:03:36,019 - necessary, things like that - and - -1532 -01:03:36,021 --> 01:03:37,820 - that's gonna be a lot easier - here too. - -1533 -01:03:37,822 --> 01:03:39,055 - Cuz you can recur, - -1534 -01:03:39,056 --> 01:03:40,289 - use recursion, use recursion - to build this as well. - -1535 -01:03:41,559 --> 01:03:43,725 - Okay, so that's the main two - things of - -1536 -01:03:43,727 --> 01:03:44,693 - your homework that's what they - are. - -1537 -01:03:44,695 --> 01:03:48,496 - All right, so let's see if we - broke anything here all right, - -1538 -01:03:48,498 --> 01:03:50,064 - so we're gonna go up here and - run. - -1539 -01:03:52,168 --> 01:03:53,834 - See if this all still works. - -1540 -01:03:53,836 --> 01:03:55,101 - Our UI has not changed. - -1541 -01:03:55,103 --> 01:03:57,804 - You notice I never even opened - the storyboard here. - -1542 -01:03:57,806 --> 01:03:59,005 - Didn't even open the - storyboard. - -1543 -01:03:59,007 --> 01:04:01,607 - Okay all these changes were - pushing things out of - -1544 -01:04:01,609 --> 01:04:03,175 - the controller into the model. - -1545 -01:04:03,177 --> 01:04:04,510 - Okay? - The co, - -1546 -01:04:04,511 --> 01:04:05,844 - communication between the - controller and - -1547 -01:04:05,846 --> 01:04:08,012 - the view has not changed here. - -1548 -01:04:08,014 --> 01:04:10,915 - So hopefully this is gonna - work let's try 85, and - -1549 -01:04:10,917 --> 01:04:13,083 - our number entering is still - working in - -1550 -01:04:13,085 --> 01:04:15,252 - our controller that's good, - Enter. - -1551 -01:04:15,254 --> 01:04:17,921 - Okay it still says 85 that's - good, - -1552 -01:04:17,923 --> 01:04:22,224 - how about 41 plus seems to - actually be working. - -1553 -01:04:22,226 --> 01:04:23,325 - Square root, - -1554 -01:04:23,327 --> 01:04:26,861 - that's also working, nine - times, excellent. - -1555 -01:04:26,863 --> 01:04:28,813 - That's working. - -1556 -01:04:28,814 --> 01:04:30,764 - Now what if we do something - that's not evaluatable? - -1557 -01:04:30,767 --> 01:04:33,034 - I'm going to press times a - whole bunch of times. - -1558 -01:04:33,036 --> 01:04:33,901 - Right? - Times, times. - -1559 -01:04:33,903 --> 01:04:35,736 - Oh, times no, zero. - -1560 -01:04:35,738 --> 01:04:37,404 - See that's not really great - feedback. - -1561 -01:04:37,406 --> 01:04:41,207 - Okay? - But, it's not really zero but - -1562 -01:04:41,209 --> 01:04:43,642 - it's, it's not good either. - -1563 -01:04:43,644 --> 01:04:46,912 - So your homework is going to - be printing out what's on - -1564 -01:04:46,914 --> 01:04:48,747 - the stack in a nice form so - -1565 -01:04:48,749 --> 01:04:50,548 - you'll be able to see that you - have times, times, - -1566 -01:04:50,550 --> 01:04:53,918 - times, and it's gonna equal a - blank display. - -1567 -01:04:53,920 --> 01:04:56,353 - And that's gonna make sense - that it's blank. - -1568 -01:04:56,355 --> 01:04:57,020 - 'Kay? - -1569 -01:04:57,022 --> 01:04:59,422 - All right. - -1570 -01:04:59,424 --> 01:05:01,724 - Now, I wanna do one other - thing here, though, just so - -1571 -01:05:01,726 --> 01:05:03,659 - you can really visualize - what's going on, - -1572 -01:05:03,661 --> 01:05:05,561 - which is, I wanna print out, - -1573 -01:05:05,563 --> 01:05:08,630 - when we evaluate, I wanna - print out this stack. - -1574 -01:05:08,632 --> 01:05:10,265 - I wanna print out the thing - we're evaluating, - -1575 -01:05:10,267 --> 01:05:12,934 - I wanna print out the result, - and I even wanna print out - -1576 -01:05:12,936 --> 01:05:14,702 - the remainder here so we can - see what's going on. - -1577 -01:05:14,704 --> 01:05:17,471 - So, I wanna say print ln. - -1578 -01:05:17,473 --> 01:05:21,841 - And I'm gonna say I'm gonna - use my backslash thing here. - -1579 -01:05:21,843 --> 01:05:30,916 - Op stack equals result with - how did I say this? - -1580 -01:05:30,918 --> 01:05:32,685 - With [NOISE], oh, yeah. - -1581 -01:05:32,687 --> 01:05:36,688 - With our remainder left over. - -1582 -01:05:37,857 --> 01:05:39,507 - Okay. - -1583 -01:05:39,508 --> 01:05:41,158 - So wouldn't it be cool if I - could just do this. - -1584 -01:05:41,160 --> 01:05:44,361 - Just say, okay, the op stack - evaluated equals this - -1585 -01:05:44,363 --> 01:05:47,064 - result with the remainder left - over. - -1586 -01:05:47,066 --> 01:05:47,897 - Okay? - -1587 -01:05:47,899 --> 01:05:48,765 - Let's run that. - -1588 -01:05:48,766 --> 01:05:49,632 - Do you think that's going to - work? - -1589 -01:05:51,302 --> 01:05:52,468 - Maybe. - Let's see. - -1590 -01:05:52,470 --> 01:05:54,336 - [BLANK_AUDIO] - -1591 -01:05:54,338 --> 01:05:56,204 - Okay. - -1592 -01:05:56,205 --> 01:05:58,071 - So let's try putting eight on - the stack. - -1593 -01:05:59,709 --> 01:06:01,375 - Okay? - -1594 -01:06:01,376 --> 01:06:03,042 - Let's make so we can see this - over here, where is it, - -1595 -01:06:03,045 --> 01:06:06,213 - it's this probably right - there, there it is. - -1596 -01:06:06,215 --> 01:06:08,114 - We don't need that one okay, - so - -1597 -01:06:08,116 --> 01:06:11,117 - here is our okay it's gonna be - that, it's this. - -1598 -01:06:11,119 --> 01:06:16,288 - Okay, so it said here hm, enum - value in, in an array, equals - -1599 -01:06:16,290 --> 01:06:21,860 - result of optional 8, that's - good, optional 8 is good. - -1600 -01:06:21,862 --> 01:06:23,161 - With nothing left over. - -1601 -01:06:23,163 --> 01:06:24,962 - Okay, that's good. - -1602 -01:06:24,964 --> 01:06:26,397 - Let's go 6, Enter. - -1603 -01:06:26,399 --> 01:06:30,734 - Oh, now we have enum enum on - the stack equals optional 6, - -1604 -01:06:30,736 --> 01:06:32,602 - with enum left over. - -1605 -01:06:32,604 --> 01:06:33,936 - Well that's not so good. - -1606 -01:06:33,938 --> 01:06:38,807 - Times enum, enum, enum equals - it with, this is terrible. - -1607 -01:06:38,809 --> 01:06:40,342 - This is, I can't understand - what the heck is - -1608 -01:06:40,344 --> 01:06:41,342 - going on here. - -1609 -01:06:41,344 --> 01:06:42,943 - Why is this happening? - -1610 -01:06:42,945 --> 01:06:47,014 - Okay, when you put something - in parentheses like this, - -1611 -01:06:47,016 --> 01:06:49,315 - it tries to convert it to a - string. - -1612 -01:06:49,317 --> 01:06:51,718 - Okay, well the thing that's in - here is an array. - -1613 -01:06:51,720 --> 01:06:54,520 - Arrays know how to convert - themselves to strings. - -1614 -01:06:54,522 --> 01:06:57,623 - What they do is, they put open - square bracket. - -1615 -01:06:57,625 --> 01:07:00,759 - Then they ask every single - thing in the array, - -1616 -01:07:00,761 --> 01:07:04,462 - convert yourself to a string - 'kay, and it puts them here. - -1617 -01:07:04,464 --> 01:07:07,298 - Well our op is converting - itself to this string. - -1618 -01:07:07,300 --> 01:07:10,334 - Enum value 'kay? - -1619 -01:07:10,336 --> 01:07:12,670 - That's because the system - doesn't really know how to - -1620 -01:07:12,672 --> 01:07:14,171 - convert it any other way so - -1621 -01:07:14,173 --> 01:07:15,872 - it's just saying that's an - enum value. - -1622 -01:07:15,874 --> 01:07:18,241 - It doesn't know how to convert - itself to a string. - -1623 -01:07:18,243 --> 01:07:20,376 - So, you see, see what's going - on here? - -1624 -01:07:20,378 --> 01:07:24,146 - So, I'm going to show you how - to teach a type to - -1625 -01:07:24,148 --> 01:07:26,381 - turn itself into a string. - -1626 -01:07:26,383 --> 01:07:28,716 - Okay, cuz that's really - valuable for debugging and - -1627 -01:07:28,718 --> 01:07:30,651 - also might be valuable for - your homework. - -1628 -01:07:33,756 --> 01:07:35,356 - So, how we gonna do that? - -1629 -01:07:35,357 --> 01:07:36,957 - All right, the way you do that - is, - -1630 -01:07:36,959 --> 01:07:42,595 - you have to add a computed - property to your type. - -1631 -01:07:42,597 --> 01:07:44,730 - And enums, just like structs - and - -1632 -01:07:44,732 --> 01:07:47,599 - classes, can have properties, - okay? - -1633 -01:07:47,601 --> 01:07:50,435 - Only computer properties in - enums, structs and - -1634 -01:07:50,437 --> 01:07:53,104 - classes can have properties - that are values. - -1635 -01:07:53,106 --> 01:07:56,240 - Like these, like this over - here, all right. - -1636 -01:07:56,242 --> 01:07:57,408 - But they can only be computed. - -1637 -01:07:57,410 --> 01:08:00,344 - You remember a computer - property looks like this, var. - -1638 -01:08:00,346 --> 01:08:01,929 - The name of it. - -1639 -01:08:01,930 --> 01:08:03,513 - It has to be called - description because - -1640 -01:08:03,515 --> 01:08:05,081 - it's gonna be a string - description of it. - -1641 -01:08:05,083 --> 01:08:07,517 - The type has to be string. - -1642 -01:08:07,519 --> 01:08:09,418 - It's a string description of - it. - -1643 -01:08:09,420 --> 01:08:12,588 - And then of course you want - your get here. - -1644 -01:08:12,590 --> 01:08:18,360 - And, whoops, your get and your - set set. - -1645 -01:08:18,362 --> 01:08:21,896 - But it has to not only be a - computer property. - -1646 -01:08:21,898 --> 01:08:24,165 - This description thing to make - this work. - -1647 -01:08:24,167 --> 01:08:26,900 - It wants to be a read only - one. - -1648 -01:08:26,902 --> 01:08:28,068 - So we're not going to put the - set, - -1649 -01:08:28,070 --> 01:08:29,769 - so there will be no set, just - a get. - -1650 -01:08:30,805 --> 01:08:36,108 - So this get just has to return - this op as a string, so - -1651 -01:08:36,110 --> 01:08:38,176 - I say someone turned it into a - string. - -1652 -01:08:38,178 --> 01:08:40,045 - Well how would we turn our op - into a string. - -1653 -01:08:40,047 --> 01:08:44,749 - Well for the operations we're - just gonna return the symbol. - -1654 -01:08:44,751 --> 01:08:47,484 - Okay if this is a plus - operation turning into - -1655 -01:08:47,486 --> 01:08:49,052 - string is I'm just gonna - return a plus, - -1656 -01:08:49,054 --> 01:08:53,389 - cuz that pretty well describes - a plus operation, a plus. - -1657 -01:08:53,391 --> 01:08:55,224 - For the operand, - -1658 -01:08:55,225 --> 01:08:57,058 - I'm gonna have to turn this - double into a string. - -1659 -01:08:57,061 --> 01:08:58,627 - And return that. - -1660 -01:08:58,629 --> 01:08:59,528 - Okay so how am I gonna do - that? - -1661 -01:08:59,530 --> 01:09:03,131 - I'm gonna do that using - switch, - -1662 -01:09:03,133 --> 01:09:05,867 - I need to switch on myself. - -1663 -01:09:07,070 --> 01:09:09,837 - Okay cuz I'm gonna do this - switch so that I can get these - -1664 -01:09:09,839 --> 01:09:12,939 - same things out here, and you - do the same thing I did here, - -1665 -01:09:12,941 --> 01:09:14,307 - see how I did this switch. - -1666 -01:09:14,309 --> 01:09:16,309 - So I could get these - associated values out. - -1667 -01:09:16,311 --> 01:09:18,177 - I'm gonna do the same thing - here. - -1668 -01:09:18,179 --> 01:09:20,512 - So how do I switch on my self? - -1669 -01:09:20,514 --> 01:09:23,415 - I say switch self. - -1670 -01:09:23,417 --> 01:09:24,716 - 'Kay? - -1671 -01:09:24,718 --> 01:09:28,019 - And then I just have to say - the case for operand. - -1672 -01:09:28,021 --> 01:09:29,987 - And I'll let that be the - operand. - -1673 -01:09:29,989 --> 01:09:33,657 - And I have to do the case for - unary operation. - -1674 -01:09:33,659 --> 01:09:34,624 - Now when I do the case for - -1675 -01:09:34,626 --> 01:09:37,493 - unary operation, I want the - symbol. - -1676 -01:09:37,495 --> 01:09:40,529 - But I don't care about the - function. - -1677 -01:09:40,531 --> 01:09:42,831 - Cuz I'm not actually gonna - compute anything. - -1678 -01:09:42,833 --> 01:09:45,500 - I'm just going to return the - symbol. - -1679 -01:09:45,502 --> 01:09:47,469 - And then for binary options - same, - -1680 -01:09:47,471 --> 01:09:51,972 - same thing I want the symbol - but I don't want this. - -1681 -01:09:51,974 --> 01:09:53,307 - So that's the, the don't care. - -1682 -01:09:53,309 --> 01:09:55,609 - And what am I gonna do in each - of these cases? - -1683 -01:09:55,611 --> 01:10:01,080 - Well in the operands case I'm - gonna return a string that - -1684 -01:10:01,082 --> 01:10:02,848 - is that operand. - -1685 -01:10:02,850 --> 01:10:06,251 - Oops, don't like the way it - puts that extra thing - -1686 -01:10:06,253 --> 01:10:06,985 - on there. - -1687 -01:10:06,987 --> 01:10:08,286 - Okay. - -1688 -01:10:08,287 --> 01:10:09,586 - And then in the unary - operation case I'm - -1689 -01:10:09,589 --> 01:10:11,522 - just gonna return the symbol. - -1690 -01:10:11,524 --> 01:10:13,390 - And in the binary operation - case I'm also just - -1691 -01:10:13,392 --> 01:10:14,224 - gonna return the symbol. - -1692 -01:10:14,226 --> 01:10:19,329 - And we have, oops, don't want - the parentheses there. - -1693 -01:10:19,331 --> 01:10:22,965 - Kay and we've covered every - case of this switch. - -1694 -01:10:22,967 --> 01:10:25,735 - So not only does it know that - this switch is covered but - -1695 -01:10:25,737 --> 01:10:28,604 - it knows that we for sure have - returned something out of - -1696 -01:10:28,606 --> 01:10:31,506 - here, because we only have one - expression here which is - -1697 -01:10:31,508 --> 01:10:34,909 - this Swift and switch and we - know that covers every case. - -1698 -01:10:34,911 --> 01:10:36,377 - So there goes so we have this - nice description. - -1699 -01:10:36,379 --> 01:10:40,814 - Now this is not quite enough - 'kay? - -1700 -01:10:40,816 --> 01:10:42,916 - You have to implement this - property, - -1701 -01:10:42,918 --> 01:10:44,784 - this computer property - read-only. - -1702 -01:10:44,786 --> 01:10:46,652 - But if you do one other thing, - -1703 -01:10:46,654 --> 01:10:50,456 - which is up here, you have to - put, colon printable. - -1704 -01:10:51,859 --> 01:10:56,961 - Now, I told you enums and - structs have no inheritance. - -1705 -01:10:56,963 --> 01:10:58,696 - So you're like what, wait a - second, there. - -1706 -01:10:58,698 --> 01:11:01,098 - You're telling me op inherits - from printable? - -1707 -01:11:01,100 --> 01:11:04,234 - And the answer is no, does not - inherit, okay, it's an enum. - -1708 -01:11:04,236 --> 01:11:07,070 - Enums don't have any - inheritance, only classes do. - -1709 -01:11:07,072 --> 01:11:10,540 - What this colon printable - means is, and - -1710 -01:11:10,542 --> 01:11:12,842 - this can be true for classes - or structs or whatever. - -1711 -01:11:12,844 --> 01:11:14,643 - You can put after the colon - here. - -1712 -01:11:15,713 --> 01:11:17,979 - This is called a protocol. - -1713 -01:11:17,981 --> 01:11:21,215 - And all this means is you're - telling Swift that this - -1714 -01:11:21,217 --> 01:11:24,852 - enum implements whatever is in - this protocol. - -1715 -01:11:24,854 --> 01:11:28,389 - And this protocol happens to - just be one computer - -1716 -01:11:28,391 --> 01:11:30,590 - property called Description - that returns the string. - -1717 -01:11:31,826 --> 01:11:33,326 - Okay? - -1718 -01:11:33,327 --> 01:11:34,827 - Now we're going to talk about - protocols in depth. - -1719 -01:11:34,829 --> 01:11:37,062 - Because protocols are very - important for - -1720 -01:11:37,064 --> 01:11:40,065 - explaining how things work - 'kay? - -1721 -01:11:40,067 --> 01:11:43,501 - But we're not gonna cover it - today, though. - -1722 -01:11:43,503 --> 01:11:46,204 - Okay, so if you do those two - things, put description in - -1723 -01:11:46,206 --> 01:11:52,209 - printable, now when we run, - you'll see, I'll go 5 enter. - -1724 -01:11:52,211 --> 01:11:54,511 - Six, and you see it's put a - five in there. - -1725 -01:11:54,513 --> 01:11:55,512 - There's a 6. - -1726 -01:11:55,514 --> 01:11:57,447 - Times, it's even putting the - times. - -1727 -01:11:57,449 --> 01:11:59,915 - If I hit times again, now I - get nil and - -1728 -01:11:59,917 --> 01:12:03,652 - i tshows me the whole thing is - leftover, okay. - -1729 -01:12:03,654 --> 01:12:06,454 - Let's go another thing here, - -1730 -01:12:06,456 --> 01:12:10,358 - what if I go 6 Enter 5 Enter 4 - Enter. - -1731 -01:12:10,360 --> 01:12:13,661 - Now if I do times it says - times of 4 and - -1732 -01:12:13,663 --> 01:12:18,098 - 5 is 20 with the 6 left over, - exactly right. - -1733 -01:12:19,134 --> 01:12:22,368 - Kay now notice I had to rerun - there to do that, - -1734 -01:12:22,370 --> 01:12:24,303 - you're gonna have a clear - button right, - -1735 -01:12:24,305 --> 01:12:25,571 - that you do in assignment one, - you're gonna have to - -1736 -01:12:25,573 --> 01:12:27,239 - make that work in assignment - two as well. - -1737 -01:12:28,308 --> 01:12:31,309 - Okay the last thing really out - of time but I'm gonna show you - -1738 -01:12:31,311 --> 01:12:34,311 - the last thing really quickly - that I was gonna do is use - -1739 -01:12:34,313 --> 01:12:38,182 - this description to fix this - problem I said right here. - -1740 -01:12:38,184 --> 01:12:41,385 - Which is what if I had a - function called learn - -1741 -01:12:41,387 --> 01:12:45,388 - op 'kay and it took an op as - an argument here. - -1742 -01:12:45,390 --> 01:12:53,029 - And it just said known ops ops - description equals that op. - -1743 -01:12:53,031 --> 01:12:59,368 - You see, now these could all - just be learn op this. - -1744 -01:13:00,404 --> 01:13:03,438 - Okay which is a lot nicer, I - only have to type this thing - -1745 -01:13:03,440 --> 01:13:05,306 - once, and I just use the - description here. - -1746 -01:13:05,308 --> 01:13:08,875 - The other thing about this, - notice where this function is. - -1747 -01:13:08,877 --> 01:13:10,143 - Inside the init. - -1748 -01:13:11,246 --> 01:13:12,545 - Okay you are allowed to - -1749 -01:13:12,547 --> 01:13:14,513 - put functions inside other - functions. - -1750 -01:13:14,515 --> 01:13:17,549 - If this is only called inside - here, you can put it in here. - -1751 -01:13:17,551 --> 01:13:20,518 - If if I put it outside in fact - I'd have a little a problem, - -1752 -01:13:20,520 --> 01:13:22,387 - because it would have to be - private. - -1753 -01:13:22,389 --> 01:13:26,390 - Because it uses op, and that's - what this error right here is. - -1754 -01:13:26,392 --> 01:13:29,460 - All right I'd have say private - func, but I don't want to do - -1755 -01:13:29,462 --> 01:13:32,462 - private func, instead I'm just - gonna put this right down - -1756 -01:13:32,464 --> 01:13:35,131 - here, okay and obviously I - would do that one last. - -1757 -01:13:35,133 --> 01:13:37,333 - Okay that's it, hope you - learned a lot and - -1758 -01:13:37,335 --> 01:13:40,236 - stuff elsewhere for that and I - will see you on Wednesday, - -1759 -01:13:40,238 --> 01:13:42,037 - I'm here if you have - questions. - -1760 -01:13:44,074 --> 01:13:47,976 - For more, please visit us at - stanford.edu. - diff --git a/README.md b/README.md index f8ea4c8..175eb62 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,39 @@ -Developing iOS 8 Apps with Swift +Developing iOS 8 Apps with Swift 字幕简体中文翻译项目 --- -iTunes U 课程地址:[iTunes](https://itunes.apple.com/us/course/developing-ios-8-apps-swift/id961180099) +iTunes U 课程地址:[iTunes U/Developing iOS 8 Apps Swift](https://itunes.apple.com/us/course/developing-ios-8-apps-swift/id961180099) CS193P 课程地址:[CS193P iPhone Application Development](http://web.stanford.edu/class/cs193p/cgi-bin/drupal/) -### 视频及课件下载地址 +### 相关链接 -[Developing iOS 8 Apps with Swift - 百度网盘](http://pan.baidu.com/s/1i3glp2l) +[iTunes U/Developing iOS 9 Apps Swift](https://itunes.apple.com/cn/course/developing-ios-9-apps-swift/id1104579961) + +### 翻译进度 + +翻译已全部完成,如果你发现字幕有哪些不妥,欢迎提 Pull Request。 ### 校对规则 -请参见项目内文档:[校对规则](./proofread-rules.md) +请参见项目内文档:[校对规则](./proofread-rules.md)。 + +### 字幕下载 + +直接点击[项目 Zip 包](https://github.com/x140yu/Developing_iOS_8_Apps_With_Swift/archive/master.zip)进行全部已有字幕的下载。 + +### 字幕的使用 + +字幕的格式是.srt,所以您可能需要用带外挂字幕功能的视频播放器才可使用,比如 [VLC](http://www.videolan.org/vlc/index.html),如果字幕有乱码,请点击这里进行报错和寻求解决方案:[中文乱码报错用的 Issue](https://github.com/x140yu/Developing_iOS_8_Apps_With_Swift/issues/131)。 + +### 视频及课件第三方网盘下载 + +[百度网盘](https://pan.baidu.com/s/18cBhz393KZZiEojYM6n-KQ),密码:`h9y8` + +### 联系我们 + +如果您想参与项目,请加入 CS193P 工作用 QQ 群:277542197 ,如果你只是想和我们取得联络,请直接在 [Issues](https://github.com/x140yu/Developing_iOS_8_Apps_With_Swift/issues) 区发言。 + +如果仅仅是想了解翻译的进度,无需加入 QQ 群,关注项目的更新或者到 [Issues](https://github.com/x140yu/Developing_iOS_8_Apps_With_Swift/issues) 区发言即可。 ### 版权说明 diff --git a/assignments/Reading_Assignment_1.md b/assignments/Reading_Assignment_1.md deleted file mode 100644 index 9113d18..0000000 --- a/assignments/Reading_Assignment_1.md +++ /dev/null @@ -1,130 +0,0 @@ -# 阅读任务 I:初识 Swift - -## 目标 -我们第一周阅读任务的目标是为了让你们对必须学习的 Swift 语言有一个初步的认识。我们将会介绍一些基本的东西,例如变量和流程控制,但也会介绍一些比较高阶的话题,例如闭包(把函数作为类型)。 - -你们大部分可能没有 Objective-C 的编程经验,但是不用担心。Swift 中的文档从来没要求你需要这些技能。然而,如果你从来没有用 C(或者 C++ 和其它语言)编过程,那么你会觉得 Swift 非常陌生(但是还是希望你能够克服这些困难来学习它)。 - -## 材料 -- 所有的阅读材料都来自 [Swift Programming Language](https://developer.apple.com/library/mac/documentation/Swift/Conceptual/Swift_Programming_Language/index.html) 文档。(如果需要中文版,可以参阅 [中文版 Apple 官方 Swift 教程《The Swift Programming Language》](https://github.com/numbbbbb/the-swift-programming-language-in-chinese)) - -## 需要阅读的章节 -为了充分利用你们的宝贵时间并且强调一些重点概念,阅读的章节被分成以下四个种类: -- [Red] ___非常重要___而且可能比较难理解。阅读的时候尽量用心。 -- [Yellow] 重要,但是不难理解。 -- [Green] 重要,但是只包含一些基本的简单的东西(大部分像 C 一样)。 -- [Grayed-out] 不需要阅读(本周)。也许会在将来的几周用到。 - -千万别忽略 NOTE 中的文字(在灰色块中的)- 它们也很重要。 - -如果在你阅读的章节里发现了指向其它不是本次阅读规定的章节,可以不必点击。 - -在 ___Language Guide___ 部分,阅读下面的章节: - -### The Basics -[Green] Constants and Variables -[Yellow] Comments -[Yellow] Semicolons -[Yellow] Integers -[Red] Floating-Point Numbers -[Grayed-out] Type Safety and Type Inference Numeric Literals -[Grayed-out] Numeric Type Conversion Type Aliases -[Red] Booleans -[Grayed-out] Tuples -[Red] Optionals -[Green] Assertions - -以 Unicode 字符命名常量和变量可能会很有趣,但是你需要为代码中的变量命名以及可读性负责(比如做注释)。 - -每行代码不要使用分号结尾(除非在极少数的情况用于分隔在一行中的两条语句)。 - -### Basic Operators - -这章的大部分与 C 类似(这也是为什么大部分章节都是 [Green])。 - -[Green] Terminology -[Green] Assignment Operator (不要担心引用 tuples 的部分) -[Green] Arithmetic Operators -[Green] Compound Assignment Operators -[Green] Comparison Operators -[Green] Ternary Conditional Operator -[Grayed-out] Nil Coalescing Operator -[Green] Range Operators -[Green] Logical Operators - -### Strings and Characters - -不要担心章节介绍中灰色 NOTE 的部分。我们将在下周讨论 Objective-C 当中的类,例如:NSString。 - -[Green] String Literals -[Yellow] Initializing an Empty String (暂时不用担心 “initializer syntax”) -[Green] String Mutability -[Red] Strings Are Value Types (不用担心 NOTE 部分) -[Yellow] Working with Characters -[Green] Concatenating Strings and Characters -[Red] String Interpolation -[Grayed-out] Unicode -[Red] Counting Characters -[Yellow] Comparing Strings -[Grayed-out] Unicode Representations of Strings - -`let myArrayOfCharacters = Array(myString)` 可以将 `String` 类型的转换成 `Array` 类型的。因为这章在 `Array` 前面,所以这个方法还没提到。 - -### Collection Types - -[Red] Mutability of Collections -[Red] Arrays (不必担心在章节尾部提到的 initializers 部分) -[Grayed-out] Dictionaries - -如果你试图越界访问 `Array` 之外的元素,你的程序会崩溃。 - -`Array` 中有一个 `last` 方法,可以返回一个 `Optional`(当且仅当 `Array` 是空,会返回 `nil`)。 - -你需要了解,`+=` 数组运算符把另一个数组当做右值(而不是向这个数组添加一个元素)。 - -### Control Flow - -[Green] For Loops (for-in 和 ranges 也许对于你们其中的一些人是新事物,例如:1..5) -[Green] While Loops -[Red] Conditional Statements (尤其是 Switch, 可以忽略 Tuples, Value Bindings & Where) -[Red] Control Transfer Statements (忽略 Labeled Statements) - -Swift 中的 `switch` 语句比你之前在 C 或者其它语言中的使用要重要得多。 - -### Functions - -[Red] Defining and Calling Functions -[Red] Function Parameters and Return Values (忽略多个和 `Optional Tuple` 类型的返回值函数) -[Grayed-out] Function Parameter Names -[Red] Function Types (这也许是对你们中多数人的巨大挑战) -[Yellow] Nested Functions - -### Closures - -理解在 Swift 中,一个函数的描述(例如:它的参数和返回值)可以作为一种初始“类型”(就像 `Array` 或者 `Int`)是很重要的。许多 iOS 中的 API 把 closures 作为参数。 - -[Red] Closure Expressions (确保你理解了上面的 Function Types) -[Yellow] Trailing Closures -[Grayed-out] Capturing Values -[Grayed-out] Closures are Reference Types - -### Classes and Structures - -[Red] Comparing Classes and Structures -[Grayed-out] Structures and Enumerations are Value Types -[Grayed-out] Classes are Reference Types -[Grayed-out] Choosing Between Classes and Structures -[Grayed-out] Assignment and Copy Behavior for Strings, Arrays, and Dictionaries - -这周我们只知道两种创建 `class` 或 `struct` 的方式:在 `class` 或 `struct` 名称之后加上一对圆括号,例如:`let x = VideoMode()`,或者对于 `struct` ,在名字之后,把它中的变量都赋初始值,例如:`let hd = Resolution(width: 1920, height: 1080)`。我们将在下周学习更多更有力的方式来初始化 `class` 和 `struct`。 - -### Properties - -忽略掉引用的枚举(`enum`)部分。枚举很重要,但是我们将在下周详细讨论。 - -[Red] Stored Properties (忽略 `Lazy Stored Properties` 和 `Stored Properties and Instance Variables`) -[Red] Computed Properties -[Grayed-out] Property Observers -[Grayed-out] Global and Local Variables Type Properties - - diff --git a/lectures/Lecture 1 Slides.pdf b/lectures/Lecture 1 Slides.pdf deleted file mode 100644 index 6b59c9c..0000000 Binary files a/lectures/Lecture 1 Slides.pdf and /dev/null differ diff --git a/proofread-rules.md b/proofread-rules.md index 3e737d1..90c9e71 100644 --- a/proofread-rules.md +++ b/proofread-rules.md @@ -2,50 +2,36 @@ 校对是一个很重要的部分,甚至比翻译还要重要。 +**不遵守此规定的校对 Pull Request 可能会被直接关闭!** + ### 文字要求 + - 修改错别字,明显的笔误。 - 原字幕中的英文也会有错误,例如:false -> fall,Mac OS X -> Mac OS 10如有遇到,请改正。 +- 上下文需要保持良好的通顺性,以便于使用者的理解,两个句子之间不必一定按照英文顺序。 - 英文的规范: - - 英文同中文之间应当有一个空格,例如:我的手机是 iOS 系统。 - - 专业的技术词汇可以不需要翻译(参见本节末尾)。 - - 'OK',‘All Right’ 等语气词也可以不翻译。 + - 英文同中文之间应当有一个空格,例如:我的手机是 iOS 系统。**如遇到英文词汇和标点符号相邻的情况,则不需要再留空格**。 + - 专业的技术词汇可以不需要翻译,如翻译,请参考[《The Swift Programming Language》中文版](http://numbbbbb.gitbooks.io/-the-swift-programming-language-/content/)。 + - 'Okay?',‘All Right’ 等语气词也可以不翻译,也可以根据内容翻译成“明白了吗?”,“好的”。 - 注意大小写规范,如'iPhone','Xcode'。 - 标点的要求: - - 全部使用中文标点。 + - 全部使用**全角中文标点**,由于上下文之间的关联性,所以**请勿在句末加入逗号(,)和句号(。)**。 - 使用 ‘-’ 来区分不同人的对话。 - 原文中例如 [COUGH] 等类似的部分不需要翻译。 -- 其它: - - 学生提问的部分,听不清楚,字幕也不全,但是老师回答的时候会把问题复述一遍, - 所以字幕只需要'[学生提问]'就好。 - 不需要翻译的词汇 - - Xcode 中的词语,例如:Story board。 - - model, view, controller, view controller 等。 + - Xcode 中的词语,例如:Storyboard。 + - Model, View, Controller, View Controller 等。 - true, false 等 Swift 中的关键字。 + +- 其它: + - 学生提问的部分,听不清楚,字幕也不全,但是老师回答的时候会把问题复述一遍, + 所以字幕只需要'- [学生提问]'就好。 ### 格式要求 -- 把一条字幕中的多行合并成一行。 -- 所以请根据情况,把多条字幕合并成一条: - - 单条只带有类似 'OK' 的语气词,合并到上一条。 - - 一个完整的句子被分成多条,但是合并后,屏幕能装得下合并后的一条。 - 例如(注意时间轴的调整): - - 1616 - 01:11:25,330 --> 01:11:28,531 - So, that basically results - in a picture looks kinda - - 1617 - 01:11:28,533 --> 01:11:29,899 - - - 1618 - 01:11:29,901 --> 01:11:31,434 - All right? - 可以修改成: - - 1616 - 01:11:25,330 --> 01:11:31,434 - So, that basically results in a picture looks kinda like this. All right? + +- 把一条字幕中的多行英文合并成一行。 +- 中英文字幕开头均不留空格。 +- 不要合并多条字幕! diff --git a/subtitles/1. Logistics, iOS 8 Overview.srt b/subtitles/1. Logistics, iOS 8 Overview.srt new file mode 100644 index 0000000..5530add --- /dev/null +++ b/subtitles/1. Logistics, iOS 8 Overview.srt @@ -0,0 +1,6515 @@ +1 +00:00:00,001 --> 00:00:06,637 +欢迎收看斯坦福大学公开课 + +3 +00:00:06,639 --> 00:00:10,508 +本字幕由志愿者义务贡献 + +4 +00:00:10,510 --> 00:00:17,147 +Welcome to Stanford CS193P,this is winter quarter 2015. +欢迎参加斯坦福大学 2015 年冬季学期的 CS193P 课程 + +5 +00:00:17,149 --> 00:00:21,718 +And we're gonna dive right in today to some brief slide work. +我们首先简要地概览一下今天课程的内容 + +6 +00:00:22,720 --> 00:00:28,357 +This people at Stanford, you've got a document that describe, describes all the grading and all that stuff +在座的同学,你们手里都有一份叙述评分标准的文档, + +8 +00:00:28,359 --> 00:00:32,126 +so I'm not gonna go over that in lecture like I often do to start the quarter. +所以我不想像以往开课时那样再复述一遍 + +9 +00:00:33,663 --> 00:00:36,296 +Instead I'm gonna talk a little bit about, what this class is about. +相反,我首先要谈一谈,这门课到底是讲什么的 + +10 +00:00:37,566 --> 00:00:42,068 +Brief mention of the prerequisites cuz they're pretty important in this class. +接下来简单提一下学习本课程的先决条件,这个事对于课程挺重要的 + +11 +00:00:42,070 --> 00:00:44,870 +Then just the quickest overview of iOS. +然后会对 iOS 进行一个快速的预览 + +12 +00:00:44,872 --> 00:00:49,508 +I'm gonna assume that anyone who is here or is watching this, knows what that is. +我想在座的和观看视频的各位同学都知道那是什么吧 + +13 +00:00:49,510 --> 00:00:51,609 +And then, we're gonna dive right into a big old demo. +再然后,会带领大家做一个大的 demo + +14 +00:00:51,611 --> 00:00:54,779 +It's gonna be a two-day thing, where I'm really going to try and +这个 demo 会讲两节课,在这期间我会 + +15 +00:00:54,781 --> 00:00:57,381 +introduce you to Xcode and the development environment and +向你们介绍开发 iOS 需要用到的 + +16 +00:00:57,383 --> 00:01:01,818 +this language Swift, that you're gonna have to learn to develop for iOS. +集成开发工具 Xcode 和编程语言 Swift + +17 +00:01:02,854 --> 00:01:04,120 +All right, so what is this class about? +那么本课程是讲什么的呢? + +18 +00:01:04,122 --> 00:01:06,455 +It's about building cool apps, as we know. +这门课讲述的是开发超 cool 的 iOS 应用 + +19 +00:01:06,457 --> 00:01:09,091 +Why are these iOS apps so cool? +为什么这些 iOS 应用这么 cool 呢? + +20 +00:01:09,093 --> 00:01:11,960 +Well, because the device you're gonna run them on is in your pocket or +因为运行这些应用的设备要么在你的口袋里, + +21 +00:01:11,962 --> 00:01:14,229 +in your backpack. +要么在你的背包里 + +22 +00:01:14,230 --> 00:01:16,497 +Either, if you write an app, you can just pull it out and show your friends and +如果你写了一个应用,你可以把它展示给你的朋友, + +23 +00:01:16,500 --> 00:01:20,535 +it's highly networked and incredible graphics with animation. +它高度集成网络,并有惊艳的动画图形效果 + +24 +00:01:20,537 --> 00:01:24,605 +It's just cool all the way around and I think you guys all know that or you wouldn't be here. +它在各个方面都很 cool 我想你们应该都知道这些,否则你们就不会坐在这里了 + +26 +00:01:24,607 --> 00:01:28,374 +But you're also gonna learn in this class a lot of real life Object-Oriented Programming. +在这们课程中,你们也需要学习一些关于面向对象编程的知识 + +28 +00:01:28,377 --> 00:01:32,578 +You're taking a lot of other classes here at Stanford on things like graphics, and +你们也可能在斯坦福参加过一些关于图形、 + +29 +00:01:32,580 --> 00:01:39,718 +networking, and databases, and maybe animation. Things like that. +网络、数据库也许还有动画方面的课程 + +31 +00:01:39,719 --> 00:01:42,586 +And we're gonna is kinda tie that all together into a real world class. +然而我们将这些内容融合在一起, + +32 +00:01:42,589 --> 00:01:44,055 +'Kay? You're gonna get to see all this stuff. +你们会在本课程内看到所有这些东西 + +33 +00:01:44,057 --> 00:01:46,891 +Now, you know, it's gonna be kind of a survey course in that, +现在,你应该知道这会是一个概述型课程, + +34 +00:01:46,893 --> 00:01:52,462 +I can't go too deep into networking. I can't go too deep into databases. +我不会深入讲述网络的内容,我不会深入讲述数据库的内容, + +36 +00:01:52,464 --> 00:01:56,366 +I can't go too deep into animation, but you'll get to see it all in a really real +我不会深入讲述动画的内容,但是你们会在 + +37 +00:01:56,368 --> 00:01:59,569 +world environment, where people out there building apps using that technology. +真实项目的环境中用到所有的这些技术 + +38 +00:01:59,571 --> 00:02:04,940 +For some of you who haven't seen that before that'll be a big bonus of this class, I think. +我认为,对于一些之前没有接触过这些的同学,本课程对他们会有很大的提升 + +40 +00:02:06,243 --> 00:02:07,975 +The prerequisites of this class. +学习本课程的先决条件 + +41 +00:02:07,977 --> 00:02:11,712 +Number one thing is you have to be a pretty strong Object-Oriented programmer. +最重要的,你需要有很好的面向对象编程功底 + +42 +00:02:11,714 --> 00:02:14,014 +If you're not a strong Object-Oriented programmer, and +如果你不是, + +43 +00:02:14,016 --> 00:02:18,018 +you hit this class, you're probably gonna go under water, pretty quick. +还选了这个课,你可能很快就会掉队了 + +44 +00:02:18,020 --> 00:02:22,188 +Okay? I'm gonna assume you know, everything about Object-Oriented Programming. +我假设你已经了解关于面向对象编程的一切 + +46 +00:02:22,190 --> 00:02:26,658 +iOS is a completely Object-Oriented Programming envir, development environment. +iOS 是一个完全的面向对象编程的开发环境 + +48 +00:02:26,659 --> 00:02:28,859 +I just don't mean I'm not just talking about the language is Object-Oriented. +我的意思不只是说编程语言是面向对象的 + +49 +00:02:28,862 --> 00:02:31,863 +But the entire design of it the way you use it if you're not +在你使用过程中,它的整个设计方式都是面向对象的 如果你 + +50 +00:02:31,865 --> 00:02:33,965 +comfortable with things like subclassing and +不熟悉类似于子类之类的东西, + +51 +00:02:33,967 --> 00:02:37,935 +stuff like that then you're just really gonna be behind the curve. +那么你真的有可能真的跟不上了 + +52 +00:02:37,937 --> 00:02:42,239 +In iOS so at Stanford here that means CS16A and B or +斯坦福编程相关课程有 CS16A、CA16B、 + +53 +00:02:42,241 --> 00:02:47,344 +CS16X, and then you know, CS107, while it's not really Object-Oriented course, +CS16X、以及 CS107,虽然它并不是专门的面向对象课程, + +54 +00:02:47,346 --> 00:02:49,746 +at least it's a heavy duty programming course. +但至少是一门重量级的编程课程 + +55 +00:02:49,748 --> 00:02:52,615 +CS108 is a great Object-Oriented course so +CS108 是非常好的面向对象课程 + +56 +00:02:52,617 --> 00:02:55,918 +if you have, if you've taken CS108 you'll probably, be really well prepped. +如果你曾经参加过 CS108,你可能已经有了充分的准备 + +57 +00:02:55,920 --> 00:03:00,555 +110, again not really too much an Object-Oriented program but +CS110,同样也没有太多关于面向对象的知识, + +58 +00:03:00,557 --> 00:03:03,057 +good programming course cuz there's a lot of programming in this class, +但同样是一门非常好的编程课程,因为其中有大量的编程实践 + +59 +00:03:03,059 --> 00:03:05,159 +in fact, all the work in this class is programming. +事实上,所有这些课程的内容都是关于编程的 + +60 +00:03:05,161 --> 00:03:08,395 +You will not have, a little bit of reading the first couple of weeks just to +在头几个星期,你们需要为了学习新语言,多做一些阅读 + +61 +00:03:08,397 --> 00:03:12,299 +kinda learn this new language, but it's almost all programming after that all +在这之后,一直到最终的项目, + +62 +00:03:12,301 --> 00:03:14,467 +the way til the end, including your final project. +都需要运用到你新学到的语言进行编程任务 + +63 +00:03:14,469 --> 00:03:17,804 +So if you're not really comfortable with all these terms, +所以,如果你真的不适应面向对象编程, + +64 +00:03:17,806 --> 00:03:21,674 +this Object-Oriented terms or if you're just not really comfortable with +或者你真的不太适应写较大的程序, + +65 +00:03:21,676 --> 00:03:26,178 +writing big programs then this class will definitely be a challenge for you. +那么这门课程对你来说将是一个巨大的挑战 + +66 +00:03:27,848 --> 00:03:30,682 +okay, so what's in iOS, what are the parts of it? +那么,iOS 都包括哪些部分呢? + +67 +00:03:30,684 --> 00:03:34,085 +You know, it's ha, it's such a big system, it's got so much in it. +它是一个庞大的系统,其中包含很多部分 + +68 +00:03:34,087 --> 00:03:38,254 +It's impossible for me to, like, encapsulate it into a small little summary but. +不太可能能用一两句话将其表述完整 + +70 +00:03:38,257 --> 00:03:42,659 +I do have this slide right here that divides it into these four layers. +我在这个 slides 中,将其分为四层 + +71 +00:03:42,661 --> 00:03:46,763 +These four layers are approximately down near the hardware at the bottom. +这四层从靠近硬件的底层, + +72 +00:03:46,765 --> 00:03:48,964 +Up near the user at the top. Okay? +到靠近用户的顶层 + +74 +00:03:48,966 --> 00:03:52,284 +So at the bottom, so +在最下面一层, + +75 +00:03:52,285 --> 00:03:55,603 +a lot of people don't realize that iOS is basically a Unix-based operating system. +很多人没有注意到,iOS 基本就是一个基于 Unix 的操作系统 + +76 +00:03:55,605 --> 00:04:01,559 +'Kay? It's very similar shares a lot of the core of Mac OS X. Okay? +它大量借鉴了 Mac OS X 的内核部分 + +79 +00:04:01,560 --> 00:04:03,911 +Now, it's certainly optimized for mobile devices, which have +当然,它专门为在电池等等方面受到限制的移动设备优化过的, + +80 +00:04:03,913 --> 00:04:08,748 +battery restrictions and things like that, but that is basically what it is. +但基本上它仍可看作是一个 Unix 系统 + +81 +00:04:08,750 --> 00:04:11,517 +And so down at that layer you've got sockets, and +这样的话,在这层中包含了 socket(套接字)、 + +82 +00:04:11,519 --> 00:04:15,121 +you've got you know, permissions, and things like that, +permission(权限) 等等类似的部分 + +83 +00:04:15,123 --> 00:04:19,191 +that have to be near the oh you know, hardware to, to work properly. +它靠近底层硬件,并保证其正常工作 + +84 +00:04:19,193 --> 00:04:23,495 +But above that there's kind of an Object-Oriented layer that lets you get at +在这之上,是一个能够让你使用大量的面向对象编程技术的 + +85 +00:04:23,497 --> 00:04:26,731 +a lot of that stuff using Object-Oriented Programming. +面向对象的层 + +86 +00:04:26,733 --> 00:04:30,234 +'Kay? And this stuff is not UI oriented it's +但是这层不包含 UI + +87 +00:04:30,236 --> 00:04:34,171 +more kind of accessing the hardware through Object-Oriented Programming or +其更多用于通过面向对象的编程方式访问硬件, + +88 +00:04:34,173 --> 00:04:36,373 +accessing networking through Object-Oriented Programming but +或者访问网络,等等 + +89 +00:04:36,375 --> 00:04:39,309 +it's a big layer there and so we will spend a fair amount of +它是一个很大的层,我们将花大量时间在该层上, + +90 +00:04:39,311 --> 00:04:44,980 +time in this layer because we need those primitives to build at the higher layers. +因为我们需要这些原始组件来建立更高的层 + +91 +00:04:44,982 --> 00:04:48,450 +Then, there's this whole layer, which I wish we had more time to spend on. +我希望我们有更多时间花在这一层, + +92 +00:04:48,452 --> 00:04:50,252 +We only get ten weeks in this whole class. +但是我们的课程只有十周 + +93 +00:04:50,254 --> 00:04:54,655 +It goes by so fast, you'll be amazed, as you're probably, used to with your Stanford courses. +在斯坦福的课程中,你会感叹时间过得如此之快 + +95 +00:04:55,758 --> 00:04:58,092 +But there's a whole media layer here, both for +再往上,是一整个媒体层, + +96 +00:04:58,094 --> 00:05:02,062 +static images, as you know, JPEG and things like that. +包括比如你们熟悉的 JPEG 等的静态图像, + +97 +00:05:02,064 --> 00:05:07,700 +And video both capturing video, editing video, all that. +包括拍摄视频、编辑视频等的视频处理, + +98 +00:05:07,702 --> 00:05:13,706 +Incredible audio, the frameworks on this device for doing 3D audio for games and all that. +不可思议的音频框架,用于处理 3D 音效,以及游戏等等 + +100 +00:05:13,708 --> 00:05:16,675 +I get to, unfortunately I get to very little of this layer. +很不幸,我对这层知道的并不多 + +101 +00:05:16,677 --> 00:05:20,879 +But I'll try to let you know, that it's in there and then you'll know to go out and +但是我可以告诉你它里面有什么,这样你用到的时候就可以查阅相关资料, + +102 +00:05:20,881 --> 00:05:23,948 +seek out, if you're building a very audio intensive app or +或者当你正在写一个用到大量音频视频技术的应用的时候, + +103 +00:05:23,950 --> 00:05:26,484 +video intensive app, you'll seek out that layer. +你会知道去哪找这些资料 + +104 +00:05:26,486 --> 00:05:32,756 +But we'll spend the vast majority of our time at the Cocoa Touch layer. +我们会在 Cocoa Touch 层上花费大量的时间 + +105 +00:05:32,758 --> 00:05:35,325 +So the Cocoa Touch layer, that's where the buttons and +Cocoa Touch 层里包含了 button, + +106 +00:05:35,327 --> 00:05:38,895 +sliders and things like that are it's the layer, +slider 等类似的控件, + +107 +00:05:38,897 --> 00:05:43,032 +where you're gonna build the interactivity with your end user. +你可以通过它们来和你的用户建立互动 + +108 +00:05:43,034 --> 00:05:47,936 +And so, that's where we probably spend 70 plus percent of our time in the Cocoa Touch layer. +我们会在 Cocoa Touch 上花费 70% 甚至更多的时间 + +110 +00:05:47,938 --> 00:05:50,271 +And this is a very powerful layer. +这也是一个非常强大的层 + +111 +00:05:50,273 --> 00:05:54,809 +You know, you've seen things like the maps app on the phone. +你们可能在手机上见过地图类的应用 + +112 +00:05:54,811 --> 00:05:58,346 +There's basically, an object that does almost the entire maps app, that you can +事实上,有一个几乎完整的地图应用对象, + +113 +00:05:58,348 --> 00:06:01,482 +just drop right into your program, and now you have maps in your program. +你只需要直接拖进你的程序里,你的程序中就有地图了 + +114 +00:06:01,484 --> 00:06:04,051 +Same thing with web browser. +同样的还有浏览器 + +115 +00:06:04,052 --> 00:06:06,619 +If you wanna put web browsing in your app, it's just boom, pop an object in there, +如果你想让你的应用有浏览网页的功能,那么仅仅需要拖拽一个对象, + +116 +00:06:06,622 --> 00:06:08,655 +call a couple methods and in your, on your way. +再调用几个方法即可 + +117 +00:06:08,657 --> 00:06:13,592 +So very powerful, very high level in there's a lot going on in there and +所以在强大和高级的 Cocoa Touch ,我们会了解很多, + +118 +00:06:13,594 --> 00:06:16,195 +that's where we will spend most of our time, 'kay? +并且在此花费大量的时间 + +119 +00:06:16,197 --> 00:06:19,831 +And by the way, if you have any questions I try to glance up, so +顺便说一下,我抬眼一瞥的时候, + +120 +00:06:19,833 --> 00:06:21,499 +the bright lights over there sometimes in my way, +有可能会看到你们的提问,但是有时我也会注意不到, + +121 +00:06:21,501 --> 00:06:25,302 +but, shout out or you know, otherwise get my attention. +所以尽量让我注意到你 + +122 +00:06:25,304 --> 00:06:28,105 +If you feel free to interrupt. +如果你感觉打断我没什么问题的话 + +123 +00:06:28,107 --> 00:06:31,308 +Then there's the development platform itself.'Kay? +接下来就是开发平台本身 + +125 +00:06:31,309 --> 00:06:32,809 +With the tools we use to build these iOS apps. +我们会用这些工具来搭建 iOS 应用 + +126 +00:06:32,811 --> 00:06:34,978 +What's in that? +其中都有什么? + +127 +00:06:34,979 --> 00:06:39,048 +Well, it's all pretty much now been funneled into this one application called Xcode 6. +有很多很棒的工具都集成在 Xcode 6 内 + +129 +00:06:39,050 --> 00:06:42,418 +There are some little adjuncts that it calls out to but +可能还有其它一些辅助编程工具, + +130 +00:06:42,420 --> 00:06:45,287 +Xcode 6 is everything, it's your code editor, +但是 Xcode 6,你值得拥有,它是一个代码编辑器, + +131 +00:06:45,289 --> 00:06:50,024 +it's your compiler, your debugger all of that in one, pretty awesome app. +它是一个编译器,是一个调试器,总之是一个很棒的应用 + +132 +00:06:50,026 --> 00:06:54,395 +And so we'll be learning all about Xcode 6 in this class, and +所以我们这个课程里会讲到很多有关 Xcode 6 的知识 + +133 +00:06:54,397 --> 00:06:59,366 +that's where you'll be spend all your time developing, you're not gonna be at +而你编程的时候会一直使用 Xcode,你不需要 + +134 +00:06:59,368 --> 00:07:04,337 +a terminal typing in Emacs or something, you're gonna be in Xcode 6. +在终端下用 Emacs 或其他的编辑器,你只需要使用 Xcode 6 + +135 +00:07:04,339 --> 00:07:08,874 +Languages I have there's actually, two languages in iOS now. +现在可以使用两种语言开发 iOS 应用 + +136 +00:07:08,876 --> 00:07:12,044 +There are peers that you can pretty much use either one. +你可以选择使用任何一个 + +137 +00:07:12,046 --> 00:07:14,079 +One of them is called Objective-C, +其中一个名为 Objective-C, + +138 +00:07:14,081 --> 00:07:17,715 +that's the language that iOS was originally developed for. +它也是 iOS 一直以来使用的开发语言 + +139 +00:07:17,717 --> 00:07:22,553 +It's a language been around a long time, probably 30 years it's been around or 25 +这个语言已经有大概 25 到 30 年的历史了, + +140 +00:07:22,555 --> 00:07:27,123 +to 30 years that's it's actually been used to build stuff that's on the Mac today. +人们用它为 Mac 开发应用 + +141 +00:07:27,125 --> 00:07:32,194 +So, it's very mature language but it's also 25, 30 years old. +因此,它是非常成熟的语言,但是已经 25,30 岁了 + +142 +00:07:32,196 --> 00:07:36,965 +And so Apple last summer introduced a completely new language called Swift, and +所以苹果公司在去年夏天发布了一个叫 Swift 的全新的语言, + +143 +00:07:36,967 --> 00:07:40,669 +Swift, you can do pretty much everything in iOS with Swift, +你可以使用 Swift 在 iOS 上开发任何应用, + +144 +00:07:40,671 --> 00:07:45,172 +that's the language we're gonna learn because it's a modern language. +它也是本次课我们要学习的语言,它是一门现代的语言 + +145 +00:07:45,174 --> 00:07:48,709 +Apple did a great job of kind of, building all the best stuff of +为了创建 Swift,苹果公司做了很多工作, + +146 +00:07:48,711 --> 00:07:52,346 +all the languages that have been invented over the last, you know, +它吸收了很多已存在的编程语言的优点 + +147 +00:07:52,348 --> 00:07:57,684 +25 years of this especially the last five or ten years into this language. +二十五年以来,特别是近五到十年的语言的优点 + +148 +00:07:57,686 --> 00:08:02,988 +It's very concise it's a very type safe language but has type inference and a lot +它语法简洁,类型安全,并且还有类型推断以及 + +149 +00:08:02,990 --> 00:08:06,991 +of things that make it so that you get the best of both worlds by having type safety- +大量的特性,可以同时拥有类型安全, + +150 +00:08:06,993 --> 00:08:11,295 +And not have to be constantly over specifying everything. +又不需要不断地指定各种类型 + +152 +00:08:11,297 --> 00:08:14,665 +So we're gonna go Swift only, I'm not even gonna really talk about Objective-C, +所以我们只使用 Swift,不会讲太多 Objective-C, + +153 +00:08:14,667 --> 00:08:16,400 +I just don't have time to do both languages. +我也没有时间讲两种语言 + +154 +00:08:16,402 --> 00:08:19,786 +Yeah. >> +(学生提问) + +155 +00:08:19,787 --> 00:08:23,171 +(学生提问) + +156 +00:08:23,174 --> 00:08:26,275 +>> Yeah, so the question is if I'm going out into the world to do +这个同学的问题是,如果我将步入社会, + +157 +00:08:26,277 --> 00:08:29,244 +iOS development in the real world for real companies. +并想找一份做 iOS 开发的工作, + +158 +00:08:29,246 --> 00:08:30,912 +Am I probably, gonna have to learn Objective-C? +我是否还需要学习 Objective-C? + +159 +00:08:30,914 --> 00:08:34,049 +And the answer is it depends on the company you're at. +答案是,这取决于你的公司 + +160 +00:08:34,051 --> 00:08:36,017 +Probably in the short term, yes. +可能在短期内,答案是肯定的 + +161 +00:08:36,019 --> 00:08:39,920 +But as the time goes by probably, more and more people switch to siff, Swift. +但是随着时间的推移,可能有越来越多的人会转到 Swift + +162 +00:08:39,922 --> 00:08:43,490 +The good thing is the underlying iOS +好消息这两门语言在 iOS 之下的 API + +163 +00:08:43,492 --> 00:08:45,926 +APIs are exactly the same for both, its just the syntax- +是完全相同的, + +164 +00:08:45,928 --> 00:08:49,162 +Of the language a little bit +仅仅只是语法上 + +165 +00:08:49,163 --> 00:08:52,397 +about how the language approaches calling the API is slightly different, but any, +会有略微的不同,但是 + +166 +00:08:52,400 --> 00:08:54,734 +everything that you learn in here about the underlying, +你们在这里学习的 iOS 的部分, + +167 +00:08:54,736 --> 00:08:57,636 +lying parts of iOS will totally work in Objective-C. +使用 Objective-C 完全也可以实现 + +168 +00:08:57,638 --> 00:08:59,571 +All the methods are the same you know, +所有的方法都是一样的, + +169 +00:08:59,573 --> 00:09:00,939 +it's just the syntax is a little different. +仅仅只有语法上的一点区别 + +170 +00:09:00,941 --> 00:09:02,540 +So, don't feel too bad about not +所以对于没有学全两门语言, + +171 +00:09:02,542 --> 00:09:05,276 +learning both languages, and once you've learned this language, +不要感到沮丧,一旦你掌握了 Swift, + +172 +00:09:05,278 --> 00:09:07,911 +learning Objective-C is gonna be pretty easy, too. +再学 Objective-C 也很快 + +173 +00:09:07,913 --> 00:09:11,815 +So. Good question though. All right. +这个问题问得很好 + +175 +00:09:11,817 --> 00:09:14,617 +Of course iOS is filled with tons of frameworks. +当然,iOS 内部拥有众多的框架, + +176 +00:09:14,619 --> 00:09:18,320 +Frameworks are libraries, basically, of objects that you use, +框架就是你会用到的类库以及基本对象 + +177 +00:09:18,322 --> 00:09:20,989 +as building blocks to build your application. +作为搭建你的应用的模块, + +178 +00:09:20,991 --> 00:09:23,325 +And we are going to be covering them. +我们也会学习它们 + +179 +00:09:23,327 --> 00:09:25,193 +UIKit is the main one. +UIKit 就是其中主要的一个 + +180 +00:09:25,195 --> 00:09:27,829 +It's got most of the user interface stuff in it. +它包含了大量的关于用户界面的内容 + +181 +00:09:27,831 --> 00:09:32,266 +Foundation is that most the Core Service layer that I was talking about, +在 Core Service 中,我提及最多的就是 Foundation 框架 + +182 +00:09:32,268 --> 00:09:37,070 +and but there's tons of other ones, Core Motion for doing the, the device moving +其他还有很多,Core Motion 框架用于处理设备移动、 + +183 +00:09:37,072 --> 00:09:42,075 +around, you know, gyro and accelerometer, Core Data for Object-Oriented database. +旋转、陀螺及加速度等响应,Core Data 框架用于操作面向对象的数据库, + +184 +00:09:42,077 --> 00:09:44,961 +Things like that. +等等 + +185 +00:09:44,962 --> 00:09:47,846 +So I'll get to, as many as those as I can, especially the big ones. +我会尽我所能尽可能多的传授给你们,特别是那些大的框架 + +186 +00:09:47,848 --> 00:09:50,849 +But there's just way too many to cover in ten weeks. +但是这对一个只有十周的课程来说,内容太多了 + +187 +00:09:51,851 --> 00:09:58,188 +And finally we I, I put this, as a first class thing with all the rest, as a design strategy MVC. +然而以上的那些东西均不是我们第一课要讲的内容 我首先要说的是一个叫做 MVC 的设计模式 + +189 +00:09:58,190 --> 00:10:01,124 +I think, I usually ask, I'll all ask this year, too. +每年我都会问,同样今年我也要问这个问题, + +190 +00:10:01,126 --> 00:10:05,361 +How many people have used MVC in some other class? +你们有多少同学曾经在其他课上用过 MVC? + +191 +00:10:05,363 --> 00:10:07,196 +See, so it's half of you. +哦,有一半的同学 + +192 +00:10:07,198 --> 00:10:09,698 +So I'll be teaching MVC, as if you don't know it, so +有同学不知道,那么我先说说 MVC + +193 +00:10:09,700 --> 00:10:11,599 +if you don't know it don't worry. +就算你不了解它,也不用担心 + +194 +00:10:11,601 --> 00:10:15,636 +But MVC is a way of designing your application so that it's a little more +MVC 是你设计应用的一种方式,用它设计的代码 + +195 +00:10:15,638 --> 00:10:21,141 +debuggable, reusable understandable to you and to anyone reading your code. +无论对于你自己或者其他人都具有可读性,也更易调试,易复用 + +196 +00:10:21,143 --> 00:10:25,278 +And iOS was designed with MVC from the start. +而 iOS 从一开始就使用 MVC 设计 + +197 +00:10:25,280 --> 00:10:28,214 +So it's just integral part to building an iOS. +而这仅仅是创建一个 iOS 应用整体中的一部分 + +198 +00:10:28,216 --> 00:10:33,452 +Now, I'm gonna do the demo today, and on Wednesday I'm kinda not gonna follow MVC. +我要开始做今天的 demo,但是在周三的课上不会使用 MVC + +199 +00:10:33,454 --> 00:10:37,922 +But then next Monday we're gonna apply MVC to the demo I'm doing today and +但是下周一我会应用 MVC 继续今天的 demo, + +200 +00:10:37,924 --> 00:10:41,426 +Wednesday, so you're gonna get the full MVC treatment there. +周三的时候你们就会对 MVC 有了充分的理解 + +201 +00:10:41,428 --> 00:10:45,262 +And I'll be having some slides on MVC on Wednesday to prepare you for next Monday. +然后在周三我会放一些 MVC 的 slides 来为下周一做准备 + +202 +00:10:46,832 --> 00:10:49,699 +Okay? All right, so here's the demo. +好,下面开始做 demo + +203 +00:10:49,701 --> 00:10:53,936 +The demo I'm gonna do, is something I actually did a few years ago that really works well- +接下来我要做的 demo,是我前几年做的一个计算器,运行起来还不错 + +205 +00:10:53,938 --> 00:10:55,971 +With Swift, which is a calculator. +我们用 Swift 来实现它 + +206 +00:10:55,973 --> 00:10:57,373 +So, we're gonna build this calculator. +现在,我们来创建这个计算器 + +207 +00:10:57,375 --> 00:11:00,509 +And we're gonna build it from scratch, all the way. +我们将从头开始,一步一步创建它 + +208 +00:11:00,511 --> 00:11:04,545 +And I like to do my demos, where I only type in stuff, I don't copy and +我喜欢动手敲代码来做演示,而不会复制或者 + +209 +00:11:04,547 --> 00:11:06,914 +paste big chunks of code in or whatever. +粘贴大段代码什么的 + +210 +00:11:06,916 --> 00:11:09,817 +I know, I'd see a lot of laptops open, a lot of people like to try and +我知道,我看到很多人已经打开笔记本电脑,很多人都喜欢 + +211 +00:11:09,819 --> 00:11:12,736 +follow along with me. +跟着我亲自动手尝试 + +212 +00:11:12,737 --> 00:11:15,654 +I'm a fast typer, but usually in most demos you can keep, keep up if you want. +我打字速度很快,但是通常在大多数演示中,只要你想,还是能够跟上我的速度 + +213 +00:11:15,657 --> 00:11:20,426 +I don't recommend it necessarily, or certainly I don't require it. +我并不推荐这么做,或者说不必要这样 + +214 +00:11:20,428 --> 00:11:28,400 +I am going to, you, you'll be able to go back and watch this particular demo on video. +你们可以回去看视频 + +216 +00:11:28,402 --> 00:11:30,535 +Even Stanford people will be able to do that. +斯坦福的学生也可以这么做 + +217 +00:11:30,537 --> 00:11:34,805 +Because your first assignment is gonna be to reproduce what I do. +因为你们的第一次作业是要重现我所做的 + +218 +00:11:34,807 --> 00:11:37,041 +'Kay? That is 90% of your first assignment. +这就是你第一次作业的 90% + +219 +00:11:37,043 --> 00:11:40,277 +Reproduce what I'm gonna do, today and on Wednesday. +重现我今天和星期三做的 + +220 +00:11:40,279 --> 00:11:42,946 +So I'm not gonna post the code because I want you to go through the experience of +我不会把代码给你,因为我想让你自己动手敲代码 + +221 +00:11:42,948 --> 00:11:45,615 +typing the code in, and if you watch in on video, +如果你是在看这个视频, + +222 +00:11:45,617 --> 00:11:51,219 +watching what I do again, and and typing it all in. 'Kay? +看一遍我干了什么,然后自己敲代码 + +224 +00:11:51,221 --> 00:11:56,340 +And I'll explain that all on Wednesday. Okay? +我将在周三对所有问题做解释 + +226 +00:11:56,341 --> 00:11:58,224 +So, I put on the slide a bunch of things that I'm gonna cover, but I'm not gonna go +我把一些将要提及的部分放到了 slides 里,但我不会提前 + +227 +00:11:58,227 --> 00:12:01,628 +over it in advance, I'm just gonna sit, sit and soon I'll start doing it. +给你们讲这些内容 我要坐下,然后开始演示 + +228 +00:12:01,630 --> 00:12:04,498 +So any questions before I dive in here? +在这之前还有什么问题吗? + +229 +00:12:04,500 --> 00:12:08,401 +I know we're gonna little fast, but I wanna maximize your learning time. +我知道我讲得有点快,因为我想最大化你们的学习时间 + +230 +00:12:08,403 --> 00:12:11,870 +-(同学提问) + +231 +00:12:11,872 --> 00:12:12,771 +Direct of what? +什么? + +232 +00:12:12,773 --> 00:12:14,706 +-(同学提问) + +233 +00:12:14,708 --> 00:12:18,142 +So the question is, which Xcode should we use, should you use? +问题是,我们应该用哪个版本的 Xcode? + +234 +00:12:18,144 --> 00:12:20,811 +Well, you should just use the one on the Mac App Store. +你们直接使用在 Mac App Store 上的那个版本就好了 + +235 +00:12:20,813 --> 00:12:23,247 +So, just go to the Mac App Store, it's free. +去 Mac App Store 上免费下载 + +236 +00:12:23,249 --> 00:12:25,482 +Use the one there, whatever the latest one is. +使用那里的最新的版本 + +237 +00:12:25,484 --> 00:12:28,618 +If a new one comes out in the quarter, well, let's all switch over to it. +如果有更新的版本出来,那么我们就更新 + +238 +00:12:28,620 --> 00:12:30,620 +Okay, let's just always be using the latest Xcode. +总之我们用的是最新版本的 Xcode + +239 +00:12:30,622 --> 00:12:31,354 +'Kay any- +还有问题吗? + +240 +00:12:31,356 --> 00:12:32,621 +(同学提问) + +241 +00:12:32,623 --> 00:12:35,624 +Not. We're not gonna using a beta or anything like that. +不,我们不用测试版或者类似的一些版本 + +243 +00:12:35,625 --> 00:12:37,392 +We'll just use whatever the currently published Xcode is. +我们只用当前最新的 Xcode + +244 +00:12:38,995 --> 00:12:41,746 +Okay. + +245 +00:12:41,747 --> 00:12:44,498 +So, I'm going to start this demo actually by launching Xcode. +那么我要开始运行 Xcode 来演示了 + +246 +00:12:44,500 --> 00:12:50,669 +So, here it is, right here. Xcode. +在这 Xcode + +248 +00:12:50,670 --> 00:12:53,270 +And when you launch Xcode, let's hide others here. +运行 Xcode 以后,我们把其他东西隐藏起来 + +249 +00:12:53,273 --> 00:12:55,140 +You're gonna get this splash screen and +你会看到这个欢迎界面, + +250 +00:12:55,142 --> 00:12:58,376 +on this splash screen on the right, this is gonna be all your projects. +在欢迎界面的右边,将显示你所有的项目 + +251 +00:12:58,378 --> 00:13:00,711 +Now, since it's the beginning of the quarter, we don't have any projects yet, +由于这是本学期开始,我们还没有任何项目 + +252 +00:13:00,713 --> 00:13:04,048 +but they'll all be listed here, so as the quarter goes by this will fill up. +但是慢慢的,我们会逐渐将这个列表填满 + +253 +00:13:04,050 --> 00:13:07,284 +You can turn this splash screen off, if you don't like it by the way. +如果你不喜欢这个欢迎页面,可以将它关闭 + +254 +00:13:07,286 --> 00:13:10,820 +This splash screen also lets us do things like playgrounds and +欢迎界面中也可以创建例如 playground, + +255 +00:13:10,822 --> 00:13:13,256 +a source code management right down here. +或者源代码管理,在这里 + +256 +00:13:13,258 --> 00:13:15,024 +We're not gonna be doing that for a while. +我们在很长一段时间内不会碰那些 + +257 +00:13:15,026 --> 00:13:16,859 +We're gonna be focusing on this option, right here. +我们需要关注的是这个选项,这里 + +258 +00:13:16,861 --> 00:13:18,760 +Create a new Xcode project. +创建一个新的 Xcode 项目 + +259 +00:13:18,762 --> 00:13:23,748 +If you don't have the splash screen, you can go to File > New > Project. Kay. +如果你看不到欢迎界面,你也可以 File > New > Project + +261 +00:13:23,749 --> 00:13:25,032 +Same thing, those both the same thing. +它们都是一样的 + +262 +00:13:25,034 --> 00:13:28,469 +So I'm gonna click right here on Create a new project. +下面我点击这里,创建一个新项目 + +263 +00:13:28,471 --> 00:13:31,605 +When I create a new project, it wants to know what kind of project you want to create, +当我创建新项目的时候,它需要知道你想创建什么类型的项目 + +264 +00:13:31,607 --> 00:13:38,494 +because Xcode is actually used on Mac OS X and to build frameworks and all that stuff. +Xcode 可以被用于在 Mac OS X 上创建框架,以及所有类似的东西 + +266 +00:13:38,495 --> 00:13:41,079 +But we're always gonna be building iOS Applications. +但是我们将要创建的是 iOS 应用 + +267 +00:13:41,082 --> 00:13:43,382 +And in fact, we're always gonna use this template right here, +事实上,我们经常用到这里的模板, + +268 +00:13:43,384 --> 00:13:47,236 +Single View Application.'Kay? +Single View Application + +270 +00:13:47,237 --> 00:13:49,688 +That's kind of your basic MVC starter application and +这就是你的基础 MVC 入门应用 + +271 +00:13:49,690 --> 00:13:53,724 +we're gonna build very complicated apps out of that, but we're gonna start here, +我们会用其他这些创建非常复杂的应用,但是我们从这里开始 + +272 +00:13:53,726 --> 00:13:55,592 +so you always click on that one. +所以你会经常点这个 + +273 +00:13:55,594 --> 00:13:58,528 +Then it wants to know what you want to call your app, and +你需要填写应用的名称, + +274 +00:13:58,530 --> 00:14:04,634 +we're building a calculator, so we're gonna call our app, Calculator.'Kay? +我们在创建的是计算器应用,所以我们给它起名为,Calculator + +276 +00:14:04,635 --> 00:14:06,669 +This organization name doesn't really matter that's just gonna appear in +orgnization 并不重要,它只会出现在 + +277 +00:14:06,671 --> 00:14:10,339 +copyright notice and the code that you write at the top in a comment so +类似版权信息,或者你的代码开头的注释中,所以 + +278 +00:14:10,341 --> 00:14:12,291 +don't worry about that. +不用管它 + +279 +00:14:12,292 --> 00:14:14,242 +But this organization identifier that is very important. +但是这里的 organization Identifier 是非常重要的 + +280 +00:14:14,244 --> 00:14:19,230 +'Kay, this uniquely identifies you. Okay? +它是你的唯一标识符 + +282 +00:14:19,231 --> 00:14:20,848 +So that on the next line we can you just, +所以在下一行里,我们需要一个新的 + +283 +00:14:20,850 --> 00:14:23,950 +new uniquely idefy, identify your calculator. +唯一的标识符,标识你的计算器 + +284 +00:14:23,952 --> 00:14:26,219 +So here if your a Stanford student, +所以如果你是斯坦福的学生, + +285 +00:14:26,221 --> 00:14:31,490 +you'll wanna use this reverse DNS notation here edu.stanford.cs193p. +你可以用这个倒序的域名:edu.stanford.cs193p + +286 +00:14:31,492 --> 00:14:36,661 +And instead of instructor there, you wanna put your SU net ID.'Kay? +并用你的 SU net ID 将 instructor 替换 + +288 +00:14:36,663 --> 00:14:37,929 +Cuz nobody else has that but you. +因为你的 ID 不会和别人的重复 + +289 +00:14:37,931 --> 00:14:39,864 +And that'll uniquely identify you. +这样这个标识符就能作为唯一标识你 + +290 +00:14:40,900 --> 00:14:44,201 +As I said, we're using Swift not Objective-C. +我说过,我们要用 Swift 而不是 Objective-C + +291 +00:14:44,203 --> 00:14:49,272 +And we're gonna build an app that works be, equally well on iPad and iPhone, +我们要创建的应用要能同时工作在 iPad 和 iPhone 上, + +292 +00:14:49,274 --> 00:14:51,507 +that's called a universal app. +所以选择 Universal + +293 +00:14:51,509 --> 00:14:54,209 +You can pick to develop for only one or the other. +你也可以选择只为其中一种设备开发 + +294 +00:14:54,211 --> 00:14:56,745 +But we are going to go Universal here. +但是我们在这里选择 Universal + +295 +00:14:56,747 --> 00:15:00,248 +We're not gonna really be doing the iPad part of it for a couple weeks. +在这几周之内我们不会做这个应用的 iPad 部分 + +296 +00:15:00,250 --> 00:15:04,352 +But it is our intent to eventually build an app that works on both. +但是我们最终会把它设计成一个同时能够运行在 iPad 和 iPhone 上的应用 + +297 +00:15:04,354 --> 00:15:06,186 +Okay we're not going to be using Core Data, +我们现在还用不到 Core Data + +298 +00:15:06,188 --> 00:15:09,322 +that's object oriented database stuff so you just leave that unchecked. +那是面向对象的数据库,现在先不选它 + +299 +00:15:09,324 --> 00:15:13,993 +And now it's asking where we want to save it, I strongly recommend saving in your +现在,它问我们要把项目保存在哪里,我强烈建议保存在你的 + +300 +00:15:13,995 --> 00:15:18,998 +home directory, this is my home directory here in a folder called Developer, okay? +home 目录下,这是我的 home 目录,里面有一个 Developer 的目录,看到没? + +301 +00:15:19,000 --> 00:15:22,001 +You could put other folders in here if you want to arrange it more, +当然你也可以在这里放其它文件夹,如果你想创建更多的话 + +302 +00:15:22,003 --> 00:15:25,103 +but home directory Developer, I highly recommend that. +不过我建议你放在主目录下的 Developer 文件夹 + +303 +00:15:25,105 --> 00:15:28,273 +Source Control, we will be talking about that at some point in the quarter but +Source Control,我们将会在这学期的某些时候讲到,不过 + +304 +00:15:28,275 --> 00:15:30,141 +we're not gonna do it right off the bat here so +我们先跳过这个 + +305 +00:15:30,143 --> 00:15:31,776 +you can leave that unchecked as well. +所以那个选项你可以不打勾 + +306 +00:15:33,045 --> 00:15:37,847 +All right, so here's our first project, its been created so +好,这就是我们创建的第一个项目 + +307 +00:15:37,849 --> 00:15:43,586 +this is Xcode that your seeing right here, this is Xcode's main screen and +这里你看到的就是 Xcode, 这是 Xcode 的主窗口 + +308 +00:15:43,588 --> 00:15:46,955 +the center is really what your working on. +中间这部分是主要的工作区域 + +309 +00:15:46,957 --> 00:15:51,026 +The left is, area here, is called the navigator, and the navigator you, +左边的区域,被称作 Navigator(导航栏) + +310 +00:15:51,028 --> 00:15:54,829 +you use to kind of choose what you're working on but you can also do +通常用来选择特定的选项,不过也你可以 + +311 +00:15:54,831 --> 00:15:59,367 +things over here like search hough your whole project, that's this little guy. +点击这个小图标,对整个项目进行搜索 + +312 +00:15:59,369 --> 00:16:04,838 +Look at all your break points maybe, look at previous builds that you've done, +这里用来查看断点,这里用来查看之前编译的项目 + +313 +00:16:04,840 --> 00:16:09,076 +browse your project by class hierarchy, all that stuff. +这里可以以类的层次结构展开整个项目,等等 + +314 +00:16:09,078 --> 00:16:12,312 +But we're usually on the left most one here which is just all of the files in +不过我们通常会点击最左边的这里,这里可以看到我们所有的文件 + +315 +00:16:12,314 --> 00:16:17,750 +your project which can also can be organized hierarchically like this. +你的项目可以像这样按层次的展现出来 + +316 +00:16:17,752 --> 00:16:19,585 +And when you select something here on the left, +当你选择左边区域这里的某些部分, + +317 +00:16:19,587 --> 00:16:23,588 +the middle will fill up with what that you've selected so. +中间区域会出现你刚刚选择的那部分内容 + +318 +00:16:23,590 --> 00:16:26,591 +Here I have the actual project itself selected. +这里我选择了这个项目本身 + +319 +00:16:26,593 --> 00:16:28,993 +So these are the project settings of which there are tons. +所以这里可以看到这个项目的很多设置项 + +320 +00:16:28,995 --> 00:16:31,662 +All along the top here you can see tons of settings. +在这上面你还可以看到更多设置项 + +321 +00:16:31,664 --> 00:16:34,431 +We're, we'll go through them as the quarter goes on and +随着学期进展我们将会讲到这些 + +322 +00:16:34,433 --> 00:16:37,100 +you've already seen some of them like the bundle identifier there and +你已经看到其中的一部分,比如这里的 Bundle identifier(包标识符) + +323 +00:16:37,102 --> 00:16:38,702 +the fact this is a universal app. +还可以看到这里是一个通用 app + +324 +00:16:38,704 --> 00:16:41,037 +We're not going to talk about anymore of this today, +不过我们今天不会讲关于项目设置 + +325 +00:16:41,039 --> 00:16:42,805 +this project settings business. +的更多内容 + +326 +00:16:42,807 --> 00:16:45,107 +We're gonna focus here on some of these files. +我们会把注意力集中在这些文件 + +327 +00:16:45,109 --> 00:16:47,409 +And even some of these files, like this AppDelegate, +甚至是这些文件,比如 AppDelegate + +328 +00:16:47,411 --> 00:16:50,845 +I'm just gonna move that down to Supporting Files to get it out of the way. +我会把它们移到 Supporting Files + +329 +00:16:50,847 --> 00:16:53,081 +Same things with these image assets, +image assets 文件夹也是 + +330 +00:16:53,083 --> 00:16:56,117 +LaunchScreen well get to this later in the quarter. +LaunchScreen 我们之后会讲到 + +331 +00:16:56,119 --> 00:16:58,285 +But I wanna focus on these two files right here. +不过我们现在会把注意力集中在这两个文件上 + +332 +00:16:58,287 --> 00:17:03,957 +Okay Main.storyboard and ViewController.swift, okay +Main.storyboard 和 ViewController.swift + +333 +00:17:03,959 --> 00:17:06,192 +In the MVC world by the way, this is the V, +顺便说,在 MVC 中这称为 V + +334 +00:17:06,194 --> 00:17:10,896 +the view and this is the C, the controller but we will talk about MVC on Wednesday. +即视图,这是 C,即控制器,我们将在周三讲到 MVC + +335 +00:17:11,999 --> 00:17:13,665 +So what do these things contain? +所以,这些东西包含什么 + +336 +00:17:13,667 --> 00:17:16,234 +So this Main.storyboard, if I click on it, +这是 Main.storyboard,如果我点击它 + +337 +00:17:16,236 --> 00:17:18,936 +you see it appear in the middle, this is our UI. +可以看到我们的 UI 出现在中间 + +338 +00:17:19,972 --> 00:17:21,972 +Okay, this is our user interface. +这就是我们的 UI + +339 +00:17:21,973 --> 00:17:23,973 +So for a calculator this is going to be a little display, +对于计算器而言,这里将会是一个稍微小一点的显示区域 + +340 +00:17:23,976 --> 00:17:27,811 +this shows the number that we're working on or whatever at the top. +这里会显示我们计算出来的数字或任何其它在上面的数字 + +341 +00:17:27,813 --> 00:17:32,448 +And lots of buttons down here, number buttons, times, multi, or sorry, times, +下面这里会有很多按钮,包括数字,乘除 + +342 +00:17:32,450 --> 00:17:34,917 +divide, plus, minus, square root. +加减,平方根 + +343 +00:17:34,919 --> 00:17:36,451 +That's all going to be here. +都会出现在这里 + +344 +00:17:36,453 --> 00:17:39,521 +So we're going to build this entire user interface. +所以我们完全使用图形化来搭建 + +345 +00:17:39,523 --> 00:17:41,055 +Purely graphically. +整个用户界面 + +346 +00:17:41,057 --> 00:17:43,057 +Okay? We're not gonna be writing code. +我们不会写代码 + +347 +00:17:43,059 --> 00:17:45,259 +Put button at this location. +来指出哪个按钮该放哪个位置 + +348 +00:17:45,261 --> 00:17:47,411 +None of that, okay? +一点代码都没有 + +349 +00:17:47,412 --> 00:17:49,562 +We just literally with our mouse are gonna build this whole user interface. +我们只是用我们的鼠标来搭建我们的用户界面 + +350 +00:17:50,499 --> 00:17:53,700 +So what's the code, what do we need any code for? +那我们的代码写在哪里,什么时候需要写代码? + +351 +00:17:53,702 --> 00:17:57,203 +Well, we, this ViewController.swift, this is a Swift file. +看 ViewController.swift,这个 Swift 文件 + +352 +00:17:57,205 --> 00:18:00,539 +This is your first look at Swift for most of you. +这是你们中多数人第一次看 Swift 文件 + +353 +00:18:00,541 --> 00:18:03,108 +This controller is gonna control that user interface. +这是我们的 controller,用来控制我们的用户界面 + +354 +00:18:03,110 --> 00:18:05,877 +That's why we call it the view controller or the controller. +这就是为什么我们称之为 view controller 或 controller + +355 +00:18:05,879 --> 00:18:09,180 +It controls user interface and that means it's gonna do things that +它控制 UI,这意味着它会做某些事情来 + +356 +00:18:09,182 --> 00:18:13,651 +are specific to how this user interface, a calculator's user interface, works. +比如指定这个 UI,计算器界面应该怎样工作 + +357 +00:18:13,653 --> 00:18:16,720 +So when we press the digit buttons, it's going to have update the display. +这样当你点击数字按钮,它会更新显示的内容 + +358 +00:18:16,722 --> 00:18:19,856 +When we press times, it's gonna have to do some multiplication and +当我们点击乘法,它将会进行乘法运算并且 + +359 +00:18:19,858 --> 00:18:21,524 +then put the result in the display. +把结果显示出来 + +360 +00:18:21,526 --> 00:18:24,227 +So it's controlling the display. +所以说它会控制界面的展示 + +361 +00:18:24,229 --> 00:18:28,597 +Okay so we'll get back to this code in a moment but we're gonna start by +我们稍后再回到这里,现在我们先从搭建界面开始 + +362 +00:18:28,599 --> 00:18:33,802 +building our user interface and by the way, your user interface, you can see I +顺便说一句,你可以看到这个用户界面 + +363 +00:18:33,804 --> 00:18:39,140 +have a low resolution screen here so my UI doesn't even really fit in the space here. +因为屏幕的低分辨率,所以我的 UI 没有很好地适应空间 + +364 +00:18:39,142 --> 00:18:42,677 +You'll probably have maybe a little higher resolution screen then I do but +你们可能有比我更高的屏幕分辨率的屏幕 + +365 +00:18:42,679 --> 00:18:45,979 +if you don't, you can zoom in and out, I'm just right-clicking, +不过如果你们没有,你们可以通过右键点击来进行放大和缩小 + +366 +00:18:45,981 --> 00:18:49,516 +if you right-click on the background area here, you can zoom in and out. +如果你在这个背景区域点击右键,你可以放大缩小 + +367 +00:18:49,518 --> 00:18:52,652 +You can also do it by double-clicking so if I double-click on this, +你也可以采用双击,看如果我双击这里 + +368 +00:18:52,654 --> 00:18:56,122 +it zooms it to normal, if I double-click on the background, it zooms out so +它放大到正常水平,如果我再双击背景,它会缩小 + +369 +00:18:56,124 --> 00:18:57,523 +that way I can see my whole UI. +这样我可以看到我的整个 UI 界面 + +370 +00:18:57,525 --> 00:18:59,992 +Now when we build a complicated app +当我们完成了一个复杂的 app + +371 +00:18:59,994 --> 00:19:05,663 +we're gonna have a whole bunch of these little square areas, we call these scenes, +我们将会有一大堆这些方块区域,这些我们称之为 scenes(场景) + +372 +00:19:05,665 --> 00:19:11,402 +and a scene represents kind of phone full, phone screen full of information. +一个场景代表一个完整显示所有信息的手机屏幕 + +373 +00:19:11,404 --> 00:19:15,072 +Okay and as you you've used many iOS applications, you know that you +就像你使用过的许多 iOS 程序 + +374 +00:19:15,074 --> 00:19:20,443 +transition from one screen to another as the user goes through the app and +你知道用户使用这个 app 从一个屏幕切换到另外一个屏幕 + +375 +00:19:20,445 --> 00:19:22,111 +that's how your gonna build your apps as well. +这也是你搭建 app 的方式 + +376 +00:19:22,113 --> 00:19:25,981 +And this StoryBoard is eventually gonna have a big map showing all +这个 StoryBoard 最终将会有一个大的图来显示所有的 + +377 +00:19:25,983 --> 00:19:28,951 +the transitions between all those scenes. +场景间的切换 + +378 +00:19:28,953 --> 00:19:31,019 +Okay, so this StoryBoard is gonna get big for +好了,所以这个 StoryBoard 将会用来搭建 + +379 +00:19:31,021 --> 00:19:35,323 +big apps, your really gonna see your whole application which is kinda cool. +完整的 app,所以当你真的看到整个应用程序时,还挺 cool 的 + +380 +00:19:36,359 --> 00:19:39,893 +So we're gonna start small though, just this one little screen right here. +所以我们将从这一个小的场景开始 + +381 +00:19:39,895 --> 00:19:41,361 +Which is gonna be our calculator. +搭建我们的计算器 + +382 +00:19:41,363 --> 00:19:44,864 +So let's start building our calculator with it's display. +我们先从搭建计算器的界面显示开始 + +383 +00:19:44,866 --> 00:19:45,999 +So I wanna make a display. +当我想显示一些东西时, + +384 +00:19:46,001 --> 00:19:47,917 +So how do I do that? +我应该怎么做呢? + +385 +00:19:47,918 --> 00:19:49,834 +Well that brings us to the right side, the right-hand side here, +我们看一下这里的右边区域 + +386 +00:19:49,837 --> 00:19:53,939 +this whole right side, this is called the Utilities area +右边的整块区域,我们称为 Utilities (工具)区域 + +387 +00:19:53,941 --> 00:19:56,675 +You can see that's it's got a bottom and a top, right? +你可以看到这里有底部和顶部,对不? + +388 +00:19:56,677 --> 00:20:01,979 +We want to go into the bottom and on the third tab right here, which is called +来到底部这里的第三个按钮,它被我们称为 + +389 +00:20:01,981 --> 00:20:07,818 +the Object Library, you'll see that there's tons and tons of objects in here. +Object Library (对象库),你可你看到这里有非常多的对象 + +390 +00:20:07,820 --> 00:20:09,886 +Okay, dozens of these things and +非常多的这类东西 + +391 +00:20:09,888 --> 00:20:13,023 +we're gonna get to a lot of these by the end of the quarter. +我们整个学期会接触到很多这样的东西 + +392 +00:20:13,025 --> 00:20:15,992 +But these are the things you build your user interface out of. +这些是用于搭建你的 UI 的 + +393 +00:20:15,994 --> 00:20:19,362 +So kind of towards the top, not all the way at the top, but towards the top, +靠近上面,但不完全靠近上面,就在这上面 + +394 +00:20:19,364 --> 00:20:22,731 +you'll start seeing things like buttons and text fields and things like that. +你会开始看到像按钮,文本区域这样的东西 + +395 +00:20:22,733 --> 00:20:26,401 +Well this is what we need obviously, to build our display here, +很明显这是我们构建显示区域所需要的东西 + +396 +00:20:26,403 --> 00:20:28,536 +is some sort of text field, and there's a couple of them here. +是某种显示文本的区域,这里有两种 + +397 +00:20:28,538 --> 00:20:32,140 +One, this one called Label is static text, you see? +这一种称为 Label 的是一种静态的文本 + +398 +00:20:32,142 --> 00:20:37,011 +And this one Text Field is editable text, in other words you can touch on this one. +这种称为 Text Field 是可编辑的文本,也就是说,你当你按下时 + +399 +00:20:37,013 --> 00:20:39,846 +And the little keyboard would slide up from the bottom and you could type in it. +键盘会从底部滑出来,所以你可以输入文本 + +400 +00:20:39,848 --> 00:20:43,600 +So, the calculator, you can't really touch on the screen and start typing +因此对于计算器来说,你确实不能按下屏幕并且输入, + +401 +00:20:43,604 --> 00:20:45,018 +so we want this static text. +所以我们需要静态的文本 + +402 +00:20:45,020 --> 00:20:48,721 +So, I'm just going to pick this up with the mouse and drag it out. +所以我用鼠标把它拖出来 + +403 +00:20:48,723 --> 00:20:50,990 +Now, when I drag it out into my UI, +现在,当我把它拖入我的 UI 中时 + +404 +00:20:50,991 --> 00:20:53,258 +you're going to see a lot of little blue dash lines appearing. +你会看到很多蓝色虚线出现 + +405 +00:20:53,260 --> 00:20:55,227 +You see these? +看到没? + +406 +00:20:55,228 --> 00:20:57,195 +These are helping me put this in the right place. +这些可以帮助我们正确地摆放这些东西 + +407 +00:20:57,197 --> 00:21:00,798 +So, I can put it right in the center, for example, of my view. +比如说我可以把它放在视图的中间 + +408 +00:21:01,734 --> 00:21:04,335 +I could put it up in a corner up here, which is what I'm gonna do. +我可以把它放在靠顶部这里,我待会就准备这样做 + +409 +00:21:04,337 --> 00:21:05,669 +Mm-kay. + + +410 +00:21:05,671 --> 00:21:10,073 +You always want your things that you put in your UI, +你总是会希望你放入 UI 中的东西 + +411 +00:21:10,075 --> 00:21:14,643 +as much as humanly possible, to be on one of these dashed blue lines. +尽可能地去利用这些蓝色虚线 + +412 +00:21:14,645 --> 00:21:18,097 +And you'll understand why in a couple weeks when we starting talking about Auto Layout. +当你后面学习到 Auto Layout (自动布局) 时就会明白为什么这么做了 + +414 +00:21:18,098 --> 00:21:19,748 +I'm gonna do a little Auto Layout right here just to kind of +我这里将会涉及一点关于 Auto Layout 的东西,可以让你 + +415 +00:21:19,750 --> 00:21:21,251 +give you a feel for it. +对它有点感觉 + +416 +00:21:21,252 --> 00:21:24,953 +But those blue, dashed blue lines are gonna be your best friend when it comes to +不过,在你搭建用户界面的时候,这些蓝色虚线将会给你最大的帮助 + +417 +00:21:24,955 --> 00:21:28,322 +building your user interface and you'll quickly see why that is. +你会很快知道为什么了 + +418 +00:21:28,324 --> 00:21:30,691 +Once you drag something out like this, you can, +每次你像这样拖动东西,你可以 + +419 +00:21:30,693 --> 00:21:34,061 +these little things are rounded that show it's selected, right? +看到环绕在外面的东西,它表明了这个被选中了 + +420 +00:21:34,063 --> 00:21:37,465 +They also are little resize handles so you can grab them and resize them. +它们也可以用于调整大小,所以可以抓住它然后或者重新调整它们的大小 + +421 +00:21:37,467 --> 00:21:42,235 +When you resize it also re-puts those dashed blue lines out there, okay? +当你调整大小时,这些蓝色虚线会重新排成一列,看到没? + +422 +00:21:42,237 --> 00:21:43,969 +So you definitely wanna, even have, +所以当你调整大小时,你肯定想 + +423 +00:21:43,971 --> 00:21:47,106 +when you're resizing, get those things lining up. +把这些东西排成一列 + +424 +00:21:47,108 --> 00:21:49,976 +You can also manipulate it directly, just double-click on it. +你还可以直接编辑它,只需要双击一下 + +425 +00:21:49,978 --> 00:21:54,145 +like a calculator probably doesn't want to come up, this is gonna be initial state of this. +通常计算器的初始状态不是这样子 + +426 +00:21:54,147 --> 00:21:58,349 +Doesn't want to come up saying Label, it probably wants 0 or +初始状态上面不会显示 Label,它可能会显示 0 + +427 +00:21:58,351 --> 00:22:01,318 +something like that in it's display. +或类似的东西 + +428 +00:22:01,320 --> 00:22:04,354 +There's also things you wanna set about this though or +另外还有一种,当你无法直接编辑这些 + +429 +00:22:04,356 --> 00:22:08,258 +anything you drag in your UI that you just can't direct manipulate and +你拖到 UI 里的内容时, + +430 +00:22:08,260 --> 00:22:12,261 +that's what the top half of this Utilities windows is, is for, okay? +你可以使用右上方的 Utilities windows(工具窗口) + +431 +00:22:12,263 --> 00:22:13,829 +So if you look at the top half here, +所以当你看上面这里, + +432 +00:22:13,831 --> 00:22:17,065 +there's a bunch of tabs across the top including something like this, +在顶部这里有许多标签,包括像这种 + +433 +00:22:17,067 --> 00:22:20,035 +the Size Inspector for setting the size of this thing. +用于设置尺寸的 Size Inspector(尺寸检查器) + +434 +00:22:20,037 --> 00:22:24,305 +And this tab right here, really important, this is the Attributes Inspector. +这个标签,称作 Attributes Inspector(属性检查器),非常重要 + +435 +00:22:24,307 --> 00:22:27,908 +And this is an object oriented inspector, depending on what you have selected. +这是一个面向对象的检查器,当你选择不同的东西时 + +436 +00:22:27,910 --> 00:22:30,611 +You'll have different user interface here in the top. +用户界面将会有所改变 + +437 +00:22:30,613 --> 00:22:33,880 +And this let's you edit attributes about what's selected. +通过它可以让你修改选中的内容的属性 + +438 +00:22:33,882 --> 00:22:34,882 +So, for example, +比如 + +439 +00:22:34,883 --> 00:22:37,883 +a calculator, the zero doesn't really want to be on the left, right? +计算器中这个 0 其实不是在左边,对不? + +440 +00:22:37,886 --> 00:22:40,653 +Calculators, the zero, the numbers are on the right and +这个 0 应该是在右边 + +441 +00:22:40,655 --> 00:22:43,589 +they kind of grow out from the right. +这些数字就像是从右边出现的 + +442 +00:22:43,591 --> 00:22:47,426 +And so we can easily fix that with this Alignment thing right here. +我们可以很轻松地使用这里的 Alignment(校准)修改它 + +443 +00:22:47,428 --> 00:22:50,595 +So I'm gonna click this and you see the zero move over to the right. +我点击这里,你就可以看到 0 到了右边 + +444 +00:22:50,597 --> 00:22:52,130 +And, and maybe I want a bigger font. +还有,也许我想要大点的字体 + +445 +00:22:52,132 --> 00:22:53,231 +You see the Font right here. +你可以看到这里的 Font(字体) + +446 +00:22:53,233 --> 00:22:55,666 +I can click on this, pick different fonts. +我可以点击这里,选择不同的字体 + +447 +00:22:55,668 --> 00:22:59,470 +I'm gonna just move it up to like 32 point, it's a nice big font. +把它增大到 32 点,稍微大点的字体 + +448 +00:22:59,472 --> 00:23:00,937 +You can notice it kinda cuts off. +你可以看到内容有点被裁剪了 + +449 +00:23:00,939 --> 00:23:02,572 +I made it so big that it's too small. +字体放大后,因此这里显得太小 + +450 +00:23:02,574 --> 00:23:06,976 +So I can always just resize this larger to make that fit. +所以我可以重新调整大小,使它能够适应字体的大小 + +451 +00:23:08,479 --> 00:23:10,345 +So this is how we build our user interface. +这就是我们搭建用户界面的方式 + +452 +00:23:10,347 --> 00:23:14,949 +It's very direct manipulation and very object oriented as you'll start to +非常直观的操作,并且非常地面向对象 + +453 +00:23:14,951 --> 00:23:17,451 +see when we add different kinds of objects. +当你加入不同的对象时你就可以看到 + +454 +00:23:17,453 --> 00:23:20,187 +So, let's actually run this application, okay? +所以,让我们真正地运行我们的应用吧 + +455 +00:23:20,189 --> 00:23:22,956 +We haven't done, built any calculaterness about it, +尽管我们还没有完成任何关于计算的东西, + +456 +00:23:22,958 --> 00:23:25,992 +but we have this one field, let's run it and see what it looks like. +不过可以让我们运行一下看看是什么效果 + +457 +00:23:25,994 --> 00:23:27,226 +So, how do you run things? +应该怎么运行? + +458 +00:23:27,228 --> 00:23:29,562 +Well, you see right here where it says, iPhone 6? +嗯,这里你可以看到,iPhone 6? + +459 +00:23:29,564 --> 00:23:33,331 +This actually is a selector that lets you say where you want to +这实际上是可以让你选择用什么设备 + +460 +00:23:33,333 --> 00:23:35,166 +run your application. +运行你的应用 + +461 +00:23:35,168 --> 00:23:38,636 +So you can see you can run it on an iOS device if you have one connected, +如果当你连上了一个 iOS 设备时,你可以在 iOS 设备上运行, + +462 +00:23:38,638 --> 00:23:40,271 +I don't have one connected currently. +现在我还没有连接 + +463 +00:23:41,273 --> 00:23:43,056 +But you can do that. +不过你可以这样做试试 + +464 +00:23:43,057 --> 00:23:44,840 +And we'll talk in a Friday section probably in a week or +我们将会在一到两周后的周五的课上 + +465 +00:23:44,843 --> 00:23:48,478 +two about how to get your devices hooked up. +谈论如何连接你的设备 + +466 +00:23:48,480 --> 00:23:52,948 +But also there's these plethora of simulators here, iPhone 6, +不过这里有很多模拟器, iPhone 6 、 + +467 +00:23:52,950 --> 00:23:56,552 +6+, iPhone 5, iPhone 4s, iPad Airs. +6+、 iPhone 5、 iPhone 4s、 iPad Airs + +468 +00:23:56,554 --> 00:23:58,920 +And you can pick one of these to run on and +你可以选择其中的一个运行, + +469 +00:23:58,922 --> 00:24:02,490 +it'll actually simulate that device right here on your computer. +它们实际上是在你的电脑上模拟那些设备 + +470 +00:24:02,492 --> 00:24:05,827 +So I'm gonna run on the iPhone 6. +这里我将会运行在 iPhone 6 上 + +471 +00:24:05,829 --> 00:24:08,729 +Okay,I'm just gonna hit Play, see this Play button right here? +好了,我将要点击 Play 按钮,看到 Play 按钮没? + +472 +00:24:08,731 --> 00:24:11,498 +That's how you simulate, so Play. +这就是使用模拟器的方式,点击 Play + +473 +00:24:11,500 --> 00:24:12,933 +Now it's launching the simulator. +现在启动模拟器 + +474 +00:24:12,935 --> 00:24:14,601 +It's a separate process. +它是一个单独的程序 + +475 +00:24:14,603 --> 00:24:16,169 +And it's going to run our App in there. +我们的 App 将会运行在它里面 + +476 +00:24:16,171 --> 00:24:17,403 +And there it is. +就是这样 + +477 +00:24:17,405 --> 00:24:18,737 +Now you might say, whoop. +现在你可能会说,哇! + +478 +00:24:18,739 --> 00:24:19,905 +Big white square. +这么大的白色正方形 + +479 +00:24:19,907 --> 00:24:21,339 +Oh that's not so good. +看起来不怎么好 + +480 +00:24:21,341 --> 00:24:23,825 +And the reason this is so +这是因为 + +481 +00:24:23,826 --> 00:24:26,310 +big is because the iPhone 6 has a very high resolution display on it. +iPhone 6 的高分辨率屏幕 + +482 +00:24:26,312 --> 00:24:30,881 +Okay, the retina display, and it's way higher resolution than my computer, okay? +这种视网膜屏幕,比我电脑上的分辨率大得多,对吧? + +483 +00:24:30,883 --> 00:24:35,151 +So I actually have to scroll around, you see there's the top of it. +所以我不得不上下滚动,你可以看到它的顶部 + +484 +00:24:35,153 --> 00:24:37,754 +Scroll up and down to get to it all. +通过上下滚动可以看到整个区域 + +485 +00:24:37,756 --> 00:24:42,558 +Luckily if you go to Window, this is not in the simulator now, the iOS simulator. +如果我们前往 Window 选项,这个选项现在不在 iOS 模拟器 + +486 +00:24:42,560 --> 00:24:46,628 +If you go to Window and Scale, you can scale it down to be smaller and +如果你点击 Window 并且点击 Scale, 你可以把它缩小, + +487 +00:24:46,630 --> 00:24:47,762 +then it'll fit. +然后它的大小就与屏幕的大小匹配了 + +488 +00:24:47,764 --> 00:24:49,497 +Okay, so if you have a low resolution screen, +因此,如果你有低分辨率的屏幕 + +489 +00:24:49,499 --> 00:24:51,532 +you're definitely gonna wanna use Window > Scale. +你可以点击 Window > Scale + +490 +00:24:51,534 --> 00:24:54,368 +Cmd+3 right there is another way to do it. +也可以实用快捷键 Cmd+3 + +491 +00:24:54,370 --> 00:24:55,154 +Okay? +懂不? + +492 +00:24:55,155 --> 00:25:00,939 +So here's our UI, but it doesn't look to good, okay, because where's this? +这就是我们的 UI,不过看起来不怎么样,因为这些在哪里? + +493 +00:25:00,942 --> 00:25:05,011 +We put this zero in there and it just never showed up, what did we do wrong? +我们把 0 放在那里,却从来都没有出现,我们哪里做错了? + +494 +00:25:05,013 --> 00:25:08,781 +Well we didn't really do anything wrong and that zero is actually there. +实际上我们没有做错,那个 0 实际上就在那里 + +495 +00:25:08,783 --> 00:25:11,750 +It's just here. Let me line up these UI's, this is not +就在那,先让我把它们排成一列,虽然没有 + +496 +00:25:11,752 --> 00:25:16,554 +necessarily exactly the same scale but its appropriate, approximately the same scale, +完全相同的比例但也是近似的,近似相同的比例, + +497 +00:25:16,556 --> 00:25:19,857 +you can see that the zero is actually off screen, [NOISE] okay? +你可以看到那个 0 实际上在屏幕外面,看到不? + +498 +00:25:19,859 --> 00:25:24,028 +So its there but you just can't see it because its over here off the screen. +所以实际上它存在不过你看不到它,因为它在屏幕外面 + +499 +00:25:24,030 --> 00:25:28,465 +Okay, and that's a problem, but that's a problem we can fix. +这是一个问题,不过这个问题我们可以解决 + +500 +00:25:28,467 --> 00:25:29,732 +So let's go fix that problem. +来,我们开始解决这个问题吧 + +501 +00:25:31,302 --> 00:25:32,534 +Why is that thing off-screen? +为什么它在屏幕外面? + +502 +00:25:32,536 --> 00:25:35,837 +Well, look at this UI right here, okay? +好了,看到这个 UI 没? + +503 +00:25:35,839 --> 00:25:36,838 +What shape is it? +它是什么形状的? + +504 +00:25:36,840 --> 00:25:38,373 +It's square. +它是正方形的 + +505 +00:25:38,375 --> 00:25:40,908 +Okay, no iOS device is square. +不过没有任何 iOS 设备是正方形的 + +506 +00:25:40,910 --> 00:25:43,544 +There's not a single square iOS device in the world. +世界上没有任何一种正方形的 iOS 设备 + +507 +00:25:43,546 --> 00:25:46,078 +They're all, you know, tall and thin, +你知道的,它们都是高的,并且瘦的, + +508 +00:25:46,080 --> 00:25:48,581 +or, if you turn them sideways, then they're long and short. +或者如果把它们侧身来看,它们都又长又短 + +509 +00:25:48,583 --> 00:25:50,650 +Or even like an iPad. +甚至包括 iPad + +510 +00:25:50,651 --> 00:25:52,718 +You know the aspect ratio on an iPad is slightly different than an iPhone so +你知道 iPad 的纵横比例和 iPhone 稍微有点不同 + +511 +00:25:52,721 --> 00:25:55,588 +their all slightly different, but none of them are square. +它们略有不同,但它们都不是正方形的 + +512 +00:25:55,590 --> 00:25:58,657 +So why do we design our UI in a square? +那为什么我们把 UI 设计为方的? + +513 +00:25:58,659 --> 00:26:03,762 +Because the way you design iOS interfaces, you design them in this square and +因为你这种 iOS 界面的设计,是将内容放这个方形中 + +514 +00:26:03,764 --> 00:26:09,033 +you give everything inside the square rules, called constraints, +然后给所有的内容都添加规则,这些规则我们称之为约束, + +515 +00:26:09,035 --> 00:26:12,236 +about what happens to them when they get squished down. +是关于当它们被压扁时应该发生什么变化 + +516 +00:26:12,238 --> 00:26:15,505 +Either squished down vertically, squished down horizontally, +不过是水平还是垂直的压扁 + +517 +00:26:15,507 --> 00:26:18,508 +depending on what kinda device their getting put on, okay? +取决于它们被放到哪种设备中,明白不? + +518 +00:26:18,510 --> 00:26:22,912 +So you put these rules in there, so, what does it look like to put these rules in? +所以你会在这里加入这些规则,那当加入这样规则后会怎样? + +519 +00:26:22,914 --> 00:26:25,115 +Well again, it's all direct manipulation +同样的,这些都是直观的操作 + +520 +00:26:25,117 --> 00:26:31,186 +So I'm going to give some rules to this label right here to make it so that it knows +我将要对这里的这个 Label 增加一些规则,使得它知道 + +521 +00:26:31,188 --> 00:26:36,957 +what to do when this square gets squished down in any direction for any device. +对于任何方向的任何设备被压扁时应该如何显示 + +522 +00:26:36,959 --> 00:26:38,659 +So, what do I want the rules to be? +那我希望这些规则是什么样的? + +523 +00:26:38,661 --> 00:26:42,162 +Well, I always want this thing to use the whole width. +我总希望它可以使用全部的宽度 + +524 +00:26:42,164 --> 00:26:44,931 +However much width I have, I want it all. +不管我的宽度是多少,我都希望填满这个宽度 + +525 +00:26:44,933 --> 00:26:50,102 +So I'm gonna pin this right edge to this edge, okay? +所以我要固定这个右边缘到这个边缘的距离,对吧? + +526 +00:26:50,104 --> 00:26:53,205 +I'm gonna make it so all widths are pinned to each other. +我这样做是因为所有宽度都会由另外一方决定 + +527 +00:26:53,207 --> 00:26:55,007 +And I do that with the Ctrl key. +我使用 Ctrl 键来完成 + +528 +00:26:55,009 --> 00:26:57,559 +I've turned on sticky keys so +我已经开启粘滞键所以 + +529 +00:26:57,560 --> 00:27:00,110 +you can see down in the lower left here, it's showing the modifier keys I'm using. +在左下角你可以看到,它显示了我正使用的按键 + +530 +00:27:00,113 --> 00:27:02,213 +So right now I'm holding down Ctrl. +现在我按住 Ctrl + +531 +00:27:02,215 --> 00:27:08,485 +And I'm gonna Ctrl+drag from the right edge of this to the container it's in. +我按住 Ctrl,同时从右边拖动到它的容器的右边 + +532 +00:27:08,487 --> 00:27:11,822 +See how it's showing me what I'm dragged to. +看它是如何展示我正在拖动的过程 + +533 +00:27:11,824 --> 00:27:15,125 +So when I drag to this container, it puts a menu up and says, +当我拖到这个容器时,弹出了一个菜单,上面说, + +534 +00:27:15,127 --> 00:27:20,830 +oh, okay, you want some rule between that label's right edge and +好吧,你想在标签的右边缘和当前边缘之间增加一些规则 + +535 +00:27:20,832 --> 00:27:23,999 +this thing's edge, what do you want it to be? +你希望是怎么样的规则? + +536 +00:27:24,001 --> 00:27:26,568 +Well, I can do a lot of things here. +恩,我可以做很多事情 + +537 +00:27:26,569 --> 00:27:29,136 +I could center this label vertically in this container. +我可以使这个标签垂直居中于这个容器 + +538 +00:27:29,139 --> 00:27:31,590 +Up, you know, vertical up and down. +向上,你知道的,垂直向上和向下 + +539 +00:27:31,591 --> 00:27:34,042 +I definitely don't want that, I want my label at the top, so I don't want that. +我绝对不希望出现这种情况,我是希望我的 Label 在顶部 + +540 +00:27:34,044 --> 00:27:34,776 +I can make it the equal width, +我可以使它的宽度相等, + +541 +00:27:34,778 --> 00:27:38,479 +So I can make this label the same width as the container. +所以我可以使这个 Label 和容器的宽度相同 + +542 +00:27:38,481 --> 00:27:42,049 +I don't want that either, cuz I want this little margin there, right? +我也不想那种情况,因为我想设置这个小的边距,对不对? + +543 +00:27:42,051 --> 00:27:45,785 +But look at the top one, trailing space to container margin. +不过看上面的那个,trailing space to container margin(距离容器的右间距) + +544 +00:27:45,787 --> 00:27:51,157 +This lets me pin the trailing space after my label to the margin of the container. +这让我规定了我的 Label 尾部与它的容器的间距 + +545 +00:27:51,159 --> 00:27:55,194 +So that's the one I want, so I'm gonna click on this and it does it. +这就时我需要的,我点击这个来完成 + +546 +00:27:55,196 --> 00:27:59,664 +Now, see all these yellow and orange lines that appeared when I did that? +现在,当我这样做后,看到这些黄色和橙色的线条出现没? + +547 +00:27:59,666 --> 00:28:04,401 +That's because the systems like, okay, you've started telling me the rules for this label, +这就像是系统在说,嗯, +你已经开始告诉我应该遵循对这个标签的某些规则, + +548 +00:28:04,403 --> 00:28:06,504 +but your you haven't told me enough rules, +不过你没有告诉我足够多的规则 + +549 +00:28:06,506 --> 00:28:08,005 +I don't know what to do with this thing. +我不知道应该对它怎么做, + +550 +00:28:08,007 --> 00:28:11,141 +So now it's showing you all the places where it's like the system's not +所以现在提示你,当它被挤压的时候 + +551 +00:28:11,143 --> 00:28:13,310 +sure what to do now when this thing gets squished. +系统不确定应该怎么做 + +552 +00:28:13,312 --> 00:28:15,745 +Before it was like, okay, well you weren't telling me anything so +在这之前,你没有告诉我任何规则 + +553 +00:28:15,747 --> 00:28:18,081 +I'm not going to do anything, but now your starting to tell me. +所以我没有显示任何东西,不过现在你开始告诉我 + +554 +00:28:18,083 --> 00:28:19,648 +So what do I do? +所以我应该怎么做? + +555 +00:28:19,650 --> 00:28:24,353 +So we have to fully specify both the what happens horizontally and +所以我们不得不完整地告诉它水平方向 + +556 +00:28:24,355 --> 00:28:25,520 +vertically to this thing. +和垂直方向应该怎么显示 + +557 +00:28:25,522 --> 00:28:27,422 +So we've only just started here. +所以我们只是先从这里开始 + +558 +00:28:27,424 --> 00:28:31,225 +So let's pin this edge also cuz we want this edge to stay on this side. +让我们拖动固定这个边缘,我们希望这个边缘靠近这一边 + +559 +00:28:31,227 --> 00:28:34,528 +So I'm gonna hold down Ctrl and drag. +所以我按下 Ctrl 并且拖动 + +560 +00:28:34,530 --> 00:28:38,965 +And now I'm gonna pin the leading space to the container margin. +然后现在我想固定 Label 前部到容器之间的间距 + +561 +00:28:38,967 --> 00:28:41,100 +Okay, boom that did that. +好了,我成功了 + +562 +00:28:41,102 --> 00:28:44,670 +Still have orange going on here, that's because I haven't specified anything about +这里仍然显示橙色,这是因为我还没指定任何关于 + +563 +00:28:44,672 --> 00:28:49,675 +the vertical position of this label so I'm gonna pin the top to the top, so +这个 Label 的垂直方向的规则,所以我把 Label 的顶部和容器顶部间距固定起来, + +564 +00:28:49,677 --> 00:28:54,212 +hold Ctrl again, drag up here, this is now top space. +所以我又一次按住 Ctrl,拖到这里,这是顶部间距 + +565 +00:28:54,214 --> 00:28:58,882 +Notice that it realizes where I am dragging to and from, right? +注意到它识别出我正把它拖向哪里没? + +566 +00:28:58,884 --> 00:29:00,984 +So they can give me options that make sense, +所以它能给我有意义的选项, + +567 +00:29:00,986 --> 00:29:03,186 +like Top Space to Layout Guide here. +比如这里的 Top Space to Layout Guide(顶部间距) + +568 +00:29:03,188 --> 00:29:04,921 +So I'm going to do that. +所以我会选这个 + +569 +00:29:04,923 --> 00:29:06,489 +So now I'm starting to get blue lines. +所以我开始看到蓝色的线了 + +570 +00:29:06,491 --> 00:29:07,489 +You see these lines? +看到没? + +571 +00:29:07,491 --> 00:29:08,657 +I hope you can see that there. +希望你能看到 + +572 +00:29:08,659 --> 00:29:11,493 +They're solid blue, not orange or red. +它们是实心蓝线,不是橙色或红色 + +573 +00:29:11,495 --> 00:29:16,230 +Okay, that's because they're okay, we are okay horizontally here. +这是因为它们可以了,水平方向上没问题了 + +574 +00:29:16,232 --> 00:29:18,332 +But we still have a problem vertically. +不过这里仍然有一个垂直方向上的问题 + +575 +00:29:18,334 --> 00:29:21,335 +Now I'm not sure exactly what the problem is vertically cuz I really don't +现在我不是非常确定这个垂直方向上的问题因为我确实不 + +576 +00:29:21,337 --> 00:29:23,536 +want the bottom of this. +希望这样的底部 + +577 +00:29:23,538 --> 00:29:27,773 +I just want it to hang out wherever it wants to hang out based on the size of my +我只是希望这个刚刚摆放的 Label 的底部是基于我的 + +578 +00:29:27,775 --> 00:29:29,041 +font or whatever. +字体大小之类的 + +579 +00:29:29,043 --> 00:29:31,610 +So I don't, I don't really wanna specify anything here so +因此,我确实不想在这里指明特定的高度 + +580 +00:29:31,612 --> 00:29:34,212 +why is this orange and how do I get rid of this? +所以为什么橙色警告会出现,我应该怎样避免它? + +581 +00:29:34,214 --> 00:29:37,648 +Well any time you have orange and when you're doing this layout stuff and +任何时候当你在布局时看到橙色警告 + +582 +00:29:37,650 --> 00:29:38,949 +you don't know what to do. +你不知道应该怎样做的时候 + +583 +00:29:38,951 --> 00:29:41,885 +You wanna go down to this button right here, okay? +你可以点击下面的这个按钮,看到不? + +584 +00:29:41,887 --> 00:29:44,905 +This is the document outline. +这是 document outline(文档大纲) + +585 +00:29:44,906 --> 00:29:47,924 +And when you click this, a little thing will slide out, a little shelf here. +当你点击这里时,这部分会滑出来,一个小架子 + +586 +00:29:47,926 --> 00:29:53,095 +And this is an outline view of everything that's in your UI. +这是你的 UI 中所有内容的大纲 + +587 +00:29:53,097 --> 00:29:53,897 +Okay? And they're linked, +并且它们之间是相互关联的, + +588 +00:29:53,899 --> 00:29:58,000 +So if I click the background, nothing is selected. +如果我点击背景,没有选中任何内容 + +589 +00:29:58,002 --> 00:30:00,769 +Then the background, the view is what's selected here. +然后这个背景,这个视图就是我这里选择的 + +590 +00:30:00,771 --> 00:30:04,605 +But if I click this L0, which means a label with zero in it, +但当我点击这里 L0 标签时,L0 指的是 Label 中显示内容是 0, + +591 +00:30:04,607 --> 00:30:06,240 +look it's selected my Zero label, +看我被选中的 Label, + +592 +00:31:06,242 --> 00:30:10,143 +And vice versa if I click on this here, it selects it over here. +选中,反之亦然如果我点击这里,这里显示被选中 + +593 +00:30:10,145 --> 00:30:14,380 +So this is this same thing in an outline mode. +所以这和大纲模式一样 + +594 +00:30:14,382 --> 00:30:16,349 +This is really nice to have. +这是一种非常好的方式 + +595 +00:30:16,350 --> 00:30:18,317 +Sometimes you have views that are overlapping and they're kind of in +有时候你的视图重叠在一起,所以它们显得有点 + +596 +00:30:18,319 --> 00:30:22,421 +each other's way, you can always go here to select the one you want, okay? +难以选择,你可以来到这里选择你想选择的视图 + +597 +00:30:22,423 --> 00:30:27,525 +And you can Ctrl+drag to these over here too it's just as much Ctrl+draggable as +并且你也可以在这里 Ctrl + 拖动,这里和其它东西 + +598 +00:30:27,527 --> 00:30:30,294 +some of these other things. +一样可 Ctrl + 拖动 + +599 +00:30:30,296 --> 00:30:32,513 +But what we're, and we'll look, +但这些我们将会 + +600 +00:30:32,514 --> 00:30:34,731 +We'll talk about top layout guide, bottom layout guide a little later. +我们将讨论一下顶部和底部的布局指南 + +601 +00:30:34,734 --> 00:30:38,369 +But what I really want you to focus on is this little yellow circle up here. +但是我想让你注意这个黄色的小圆圈 + +602 +00:30:38,371 --> 00:30:39,870 +'Kay? Any time you got yellow and +好的,任何时候,你在使用 Auto-layout 中 + +603 +00:30:39,872 --> 00:30:42,172 +orange problems with this auto-layout business, +看到黄色和橙色的线 + +604 +00:30:42,174 --> 00:30:45,108 +you're gonna get this little yellow circle appearing in your document outline. +你可以在你的 document outline 中看到这个小黄圈 + +605 +00:30:45,110 --> 00:30:50,479 +And if you click it, it'll slide in a list of all the problems. +如果你点击它,它会滑入一个列表,列出所有的问题 + +606 +00:30:50,481 --> 00:30:54,349 +And so here I highlight over this and this is where all the orange and yellow is. +如果选中它,出现高亮的部分就是警告所出现的地方 + +607 +00:30:54,351 --> 00:30:59,487 +It's saying the label with the 0 in it expected the height to be 39 but +它提示这个显示 0 的 label 的高度应该是 39,但 + +608 +00:30:59,489 --> 00:31:00,955 +the actual height is 57. +真实的情况却是 57 + +609 +00:31:00,957 --> 00:31:03,824 +Well that's because after I set this font, +这是因为我在设置了这个字体后, + +610 +00:31:03,826 --> 00:31:06,460 +I just dragged this down a little bit to make space. +我向下的拖动了一部分,让它多出来一些空间 + +611 +00:31:06,462 --> 00:31:09,262 +All right, I, I wasn't very, I, I didn't know it was supposed to be 39. +我不是很清楚它的高度是否应该 39 + +612 +00:31:09,264 --> 00:31:11,330 +I just dragged down. +我只是稍稍向下拖动了而已 + +613 +00:31:11,332 --> 00:31:14,283 +And so it's saying that's wrong. +这样,Xcode 给了我一个警告 + +614 +00:31:14,284 --> 00:31:17,235 +Now, I could just try drag it back up and meet this dashed line. +现在,我可以试着将其拖动,和这个虚线重叠 + +615 +00:31:17,238 --> 00:31:19,738 +This dashed line, by the way, +强调下这条虚线, + +616 +00:31:19,739 --> 00:31:22,239 +is where it's kind of saying, this is really where this thing wants to be. +它好像就在表明,这个东西想要出现在这里 + +617 +00:31:22,242 --> 00:31:24,642 +But the solid lines are where it actually is. +但是实线是它真实存在的地方 + +618 +00:31:24,644 --> 00:31:31,749 +So I could kinda drag it up to there, but I, I could be off by a pixel or something else. +所以我可以把它拖动到那里,但是我也许会相差 1 个像素或有些其它差别 + +620 +00:31:31,750 --> 00:31:34,184 +A much more reliable way is to click this little yellow triangle, 'kay? +现在有一个可靠的方法,点击这个黄色小三角 + +621 +00:31:34,186 --> 00:31:36,186 +So I'm gonna click this yellow triangle. +我将要点击这个 + +622 +00:31:36,188 --> 00:31:37,854 +It's gonna bring up this pop-up window. +它会弹出一个窗口 + +623 +00:31:37,856 --> 00:31:42,091 +And there's three ways to fix the problems, okay? +这里给出了三个修改问题的方法 + +624 +00:31:42,093 --> 00:31:45,327 +One way, Update Constraints, this middle way right here. +其中一个,Update Constraints,在中间 + +625 +00:31:45,329 --> 00:31:49,098 +That's a way that says, hey, I want this thing to be, +这个方法是,我想要这样做 + +626 +00:31:49,100 --> 00:31:51,199 +this label to be right where it is. +我想让这个 label 出现在它该出现的位置 + +627 +00:31:51,201 --> 00:31:52,967 +So just make some constraints. +所以只要做一些约束 + +628 +00:31:52,969 --> 00:31:53,634 +Make it up. +弥补上这个缺点 + +629 +00:31:53,636 --> 00:31:56,237 +Make it happen! +发生吧! + +630 +00:31:56,238 --> 00:31:58,839 +And it'll put some wacky constraints in there like 52 high, which is a bad +它会添加一些古怪的约束,例如把高度设置为 52 + +631 +00:31:58,841 --> 00:32:02,309 +constraint for it to be, 52 high, cuz this label wants to be its natural height. +这不是我想要的约束,因为 52 的高度不是这个 label 本来的高度 + +632 +00:32:02,311 --> 00:32:04,378 +It doesn't want to be 52 high. +它的不想变成 52 这么高 + +633 +00:32:04,380 --> 00:32:06,346 +So this'll kinda force constraint. +所以这里就像是强制性的约束 + +634 +00:32:06,348 --> 00:32:08,614 +You'll almost never want this one, 'kay. +你几乎永远不会用到这一项 + +635 +00:32:08,616 --> 00:32:11,250 +Rarely do you wanna force the constraints. +你很少需要强制性地去约束 + +636 +00:32:11,252 --> 00:32:14,520 +Reset to Suggested Constraints would probably just work here. +Reset to Suggested Constraints 也许会在这里起作用 + +637 +00:32:14,522 --> 00:32:16,788 +I'm not gonna choose this one, but it would probably work. +我不会选择这个,但是它可能会起作用 + +638 +00:32:16,790 --> 00:32:21,125 +This one is going to make the constraints match the blue lines. +这个可以把 label 的约束与蓝线重合 + +639 +00:32:21,127 --> 00:32:24,762 +Those dashed blue lines that I told you always wanna meet. +我告诉过你那些蓝线,是需要必须重叠的 + +640 +00:32:24,764 --> 00:32:28,899 +Those are what's gonna help the system pick suggested constraints. +那些是能够帮助系统选择建议的约束 + +641 +00:32:28,901 --> 00:32:32,769 +So since we dragged that label out to the blue lines perfectly, +如果我们把 label 拖动到蓝线的位置 + +642 +00:32:32,771 --> 00:32:36,639 +I'll bet if I said Reset to Suggested Constraints, it might just work. +Reset to Suggested Constraints 也是会起作用的 + +643 +00:32:36,641 --> 00:32:38,941 +Okay. But I'm actually gonna show you this +但是我想给你们展示顶部的这一项 + +644 +00:32:38,943 --> 00:32:43,646 +last option up on top, which is Update Frame and what this says is, take into +Update Frame,这个能够根据已经设定的约束, + +645 +00:32:43,648 --> 00:32:49,918 +consideration all the rules and move this label to where the rules say it should be. +把 label 移动到该放置的位置 + +646 +00:32:49,920 --> 00:32:52,187 +'Kay.And I like this option a lot because it +我比较喜欢这个选项 + +647 +00:32:52,189 --> 00:32:55,523 +lets you kind of preview, do I have my little rules right, okay? +它让你能够预览,我的约束是否设置正确了 + +648 +00:32:55,525 --> 00:32:59,860 +So let's try that, let's see if the, we'll tell the, move this label, go ahead and +我们尝试一下,label 是否能够按照已有的约束,移动到 + +649 +00:32:59,862 --> 00:33:03,564 +move yourself and size yourself to obey these three rules we you put in, and +它该去的地方并且设置好自己应有的大小 + +650 +00:33:03,566 --> 00:33:06,066 +we'll fix the misplacement, so let's try it. +我们点击这个按钮,让我们尝试下 + +651 +00:33:07,069 --> 00:33:10,269 +And sure enough it did it, it says there are no Auto Layout issues. +果然做到了,没有任何问题 + +652 +00:33:10,271 --> 00:33:14,940 +If I go back to my document outline, this little yellow circle is gone. +如果回到 document outline,这个黄色的小圆圈已经消失了 + +653 +00:33:14,942 --> 00:33:18,810 +If I look in my view, everything is blue-lined, no yellow or red. +看看自己的视图,全部都是蓝线,没有红色或黄色的 + +654 +00:33:20,146 --> 00:33:22,630 +Okay? So that's your +好了吗?这就说明你的 + +655 +00:33:22,631 --> 00:33:25,115 +crash course on Auto Layout, and we're gonna talk a lot more about Auto Layout, +Auto Layout 已经完成,我们接下来讨论更多 Auto Layout + +656 +00:33:25,118 --> 00:33:28,719 +in fact, even on Wednesday I'm gonna do another Auto Layout with all the buttons. +在周三的课上,我会对所有的按钮做一下 Auto Layout + +657 +00:33:28,721 --> 00:33:30,671 +Right? The keypad buttons, and +计算器的所有按钮 + +658 +00:33:30,672 --> 00:33:32,622 +all that, which is a lot more things being laid out. +这听起来真的蛮多的 + +659 +00:33:32,624 --> 00:33:34,224 +But let's see if this fixes our problem. +看看是否修复了问题 + +660 +00:33:34,226 --> 00:33:37,527 +Let's go ahead and run our application again. +我们再次运行一下应用 + +661 +00:33:37,529 --> 00:33:39,795 +So I'm just hitting that play button. +点击这个运行按钮 + +662 +00:33:39,797 --> 00:33:41,563 + Here it, oh, we got our zero this time. +此刻,我们可以看到这个 0 了 + +663 +00:33:41,565 --> 00:33:45,334 +You see how it pinned this zero to that edge? +你注意到这个 0 固定在边缘了吗? + +664 +00:33:45,336 --> 00:33:48,036 +And not only that, if we rotate this phoned, +不仅可以这样,如果我们旋转模拟器, + +665 +00:33:48,038 --> 00:33:52,273 +which you can do in the Simulators menu, Hardware > Rotate. +你可以在模拟器的菜单中点击 Hardware > Rotate + +666 +00:33:53,976 --> 00:33:58,378 +Look the 0, this got wider and the 0 kept pin, pinning itself over to that. +看看这个 0,它变得更宽,0 还是把自己固定在边缘 + +667 +00:33:58,380 --> 00:34:01,981 +And it also stayed on the top even though this got, whole thing got shorter. +它也保持着距离顶部的距离,即使它变窄了一些 + +668 +00:34:01,983 --> 00:34:04,884 +Okay. And if I rotate back, the 0 stays there. +接下来,如果我旋转回来,0 还是保持原样 + +669 +00:34:04,886 --> 00:34:07,420 +Question. So what did it do at the bottom there? +学生提问:底部发生了什么? + +670 +00:34:07,422 --> 00:34:10,422 +Like what did the actual update frame end up doing? +Update Frame 到底做了什么事情? + +671 +00:34:10,424 --> 00:34:12,758 +What did the update frame in the document outline do? +Document Outline 中的 Update Frame 到底做了什么事情? + +672 +00:34:12,760 --> 00:34:14,693 +Yes. It moved this bottom edge up. +它移动了底部的边缘 + +673 +00:34:14,695 --> 00:34:17,462 +You see this is only 39 pixels high now. +你看现在是 39 的像素高度 + +674 +00:34:17,464 --> 00:34:18,396 +It was 52. +之前它是 52 + +675 +00:34:18,397 --> 00:34:19,329 +So, yeah, it just moved it up. +这样,它发生了改变,向上移动了 + +676 +00:34:19,332 --> 00:34:21,665 +It, it, and if other things had been yellow, +如果还有其他部分有黄色线, + +677 +00:34:21,667 --> 00:34:23,133 +it could have moved the whole thing. +它可能就会移动整个 label + +678 +00:34:23,135 --> 00:34:24,718 +Right? It would move that +好的,它将移动这个 label + +679 +00:34:24,719 --> 00:34:26,302 +whole rectangle wherever the rule said but +来实现约束但是 + +680 +00:34:26,304 --> 00:34:29,539 +in this case, you can fix that one problem by moving it up. +这种情况,你可以通过向上拖动来修复这个问题 + +681 +00:34:29,541 --> 00:34:30,139 +Good question. +问得不错 + +682 +00:34:31,342 --> 00:34:33,541 +Okay? So that's good. +还不错 + +684 +00:34:33,543 --> 00:34:34,976 +All right. + +685 +00:34:34,977 --> 00:34:36,410 +So that's it for Auto Layout. +这就是 Auto Layout + +686 +00:34:36,413 --> 00:34:38,346 +Auto Layout part one. +Auto Layout 第一部分 + +687 +00:34:38,348 --> 00:34:43,016 +So now let's talk a little bit about connecting our user interface that we're +现在我们来说一下如何将 UI + +688 +00:34:43,018 --> 00:34:45,385 +building right here, up to the code, +和代码建立起联系 + +689 +00:34:45,387 --> 00:34:48,254 +cuz we want that code to be able to talk to the user interface. +因为我们想让代码和 UI 进行交流 + +690 +00:34:48,256 --> 00:34:51,157 +Otherwise how are we gonna have the number buttons, +否则我们如何能够使数字按钮产生的数字 + +691 +00:34:51,159 --> 00:34:53,425 +make numbers appear up here in the display? +显示在顶部的 label 里 + +692 +00:34:53,427 --> 00:34:56,795 +Or the times button, give the results of the calculation up here. +或者按下乘法按钮,就会把结果显示在这里 + +693 +00:34:56,797 --> 00:34:58,363 +We gotta be able to talk to this. +我们需要这样的交流 + +694 +00:34:58,365 --> 00:35:01,633 +So how do we do that? +但是如何做到呢? + +695 +00:35:01,634 --> 00:35:04,902 +And the answer, first step is, we need to get both this co, this Swift Code, +第一步,我们要把 view 和 controller 中的 Swift 代码 + +696 +00:35:04,904 --> 00:35:10,440 +the controller, and this view on screen at the same time, 'kay? +同时显示在屏幕上 + +697 +00:35:10,442 --> 00:35:12,742 +Cuz we're gonna connect them so we need them on screen at the same time, +因为我们会连接它们,所以我们需要它们同时显示在屏幕上 + +698 +00:35:12,744 --> 00:35:17,180 +and there's a lot of ways to do that, but I'll do the simplest way right here, +我将用最简单的方式实现这个 + +699 +00:35:17,182 --> 00:35:20,616 +which is this little button called the assistant editor, all right? +使用 Assistant Editor 这个按钮 + +700 +00:35:20,618 --> 00:35:22,184 +So I'm gonna click that and look! +我要点了,看看会发生什么 + +701 +00:35:22,186 --> 00:35:25,120 +It put them both on screen at the same time, exactly what I wanted. +它把它们同时放上屏幕,这正是我想要的 + +702 +00:35:25,122 --> 00:35:27,355 +Now it's all a little crowded here. +现在这里有一点拥挤 + +703 +00:35:27,357 --> 00:35:31,892 +Even if I expand my view a little bit, it's like it's all smashed in here. +即使我放大整个界面,它看起来还是这么小 + +704 +00:35:31,894 --> 00:35:35,696 +Luckily the navigator and the utilities can also be hidden, +幸运的是 Navigator 和 Utilities 这些都是可以隐藏起来的, + +705 +00:35:35,698 --> 00:35:37,931 +see these buttons up here, these three buttons? +这里有三个按钮 + +706 +00:35:37,933 --> 00:35:40,734 +This left one, if you click it hides the navigator and +左侧这个,如果你点击它会隐藏 Navigator + +707 +00:35:40,736 --> 00:35:45,504 +this right one if you click it hides utilities, 'kay? +点击右侧这个,会隐藏右侧的 Utilities + +708 +00:35:45,506 --> 00:35:50,308 +So now we have both my UI and over here we can still double click to zoom out, but +现在它们都在我们的视线中,我可以双击缩放它 + +709 +00:35:50,310 --> 00:35:54,646 +the thing is, anytime we're actually connecting our UI to our code or +但是我们在想要连接代码和 UI 或者 + +710 +00:35:54,648 --> 00:35:59,183 +trying to edit anything in here,you need to be zoomed to normal, 'kay? +尝试去编辑的时候,你需要把缩放比例调到正常 + +711 +00:35:59,185 --> 00:36:02,353 +For example if I tried to select if I'm zoomed out and +例如这个,如果我缩小 + +712 +00:36:02,355 --> 00:36:04,955 +I try to select this 0 I just can't. +我就不能选中这个 0 了 + +713 +00:36:04,957 --> 00:36:08,891 +This is really kind of a bird's eye view just for seeing what your UI looks like. +这个其实只是一个预览图模式,让你看看大体样子,而不能编辑 + +714 +00:36:08,893 --> 00:36:10,726 +If you wanna actually work on it, +如果你想要编辑 + +715 +00:36:10,727 --> 00:36:12,560 +you double-click to zoom in on this scene that you're interested in. +双击你需要编辑的窗口就可以了 + +716 +00:36:14,064 --> 00:36:15,630 +Okay, so here's our Swift code. +这是我们的 Swift 代码 + +717 +00:36:15,632 --> 00:36:17,598 +I'm actually gonna delete these. +我将要删除这些 + +718 +00:36:17,600 --> 00:36:20,635 +We don't need them for the calculator. +在我们的应用中是不需要这些的 + +719 +00:36:20,636 --> 00:36:24,338 +We will need these things for future application but we don't need it for the calculator. +我们会在将来的应用需要这些,但在这里不需要 + +721 +00:36:24,340 --> 00:36:27,974 +And this is your first look at Swift, 'kay. +这是你第一次看到 Swift 代码 + +722 +00:36:27,976 --> 00:36:31,711 +So Swift, as I said, very concise language, but it's basically an object +Swift 是非常简洁的、 + +723 +00:36:31,713 --> 00:36:36,048 +oriented language, it's gonna look a lot like C, some things look a lot like Java. +面向对象的语言,它看起来像 C,有些东西像 Java + +724 +00:36:36,050 --> 00:36:40,385 +It's kind of the, you know, best of, of a lot of different worlds at once. +它集众多语言之长 + +725 +00:36:40,387 --> 00:36:44,823 +Now this import is just importing the UI portion of iOS. +这句 import 导入了 iOS 的 UI 部分 + +726 +00:36:44,825 --> 00:36:47,658 +You usually won't have to specify import yourself unless you start +除非你需要使用一些框架, + +727 +00:36:47,660 --> 00:36:52,496 +using frameworks that are not, you know, the base frameworks and we'll get to that +通常来说不需要自己导入,我们几周后会讲到那里 + +728 +00:36:52,498 --> 00:36:56,233 +probably weeks into the quarter where you fi, finally have to do an import yourself. +最后你还是得自己导入 + +729 +00:36:56,235 --> 00:36:58,601 +So this how it automatically got put here for us. +这里我们看到它自动的为我们添加了 + +730 +00:36:58,603 --> 00:37:02,838 +And so this is really your first line of Swift code, 'kay? +在这是你的第一行 Swift 代码 + +731 +00:37:02,840 --> 00:37:06,975 +Appropriately, it's a definition of a class. +这里是定义了一个类 + +732 +00:37:06,977 --> 00:37:10,479 +Cuz Swift is fundamentally object-oriented and here we're defining a class. +因为 Swift 是以面向对象为基础的,这里是定义的一个类 + +733 +00:37:10,481 --> 00:37:13,448 +So what does the syntax look like to define a class? +定义一个类的语法是什么样的? + +734 +00:37:13,450 --> 00:37:15,416 +You got the keyword class. +你得使用关键字 class + +735 +00:37:15,418 --> 00:37:16,817 +You got the name of the class. +这里是这个类的名称 + +736 +00:37:16,819 --> 00:37:20,654 +Now this name ViewController, pretty bad name, +现在这个名字 ViewController 看起来很糟糕 + +737 +00:37:20,656 --> 00:37:23,523 +Okay, very generic, really they should probably be something like +非常普通的名字,它应该起名为例如 + +738 +00:37:23,525 --> 00:37:26,593 +CalculatorViewController,something specific to +CalculatorViewController 这样有针对的名字, + +739 +00:37:26,595 --> 00:37:33,599 +this particular scene that we're orking on right here, that it's controlling. +这样看起来就让人清楚它是控制哪里的了 + +740 +00:37:33,601 --> 00:37:35,668 +This is the default name it gives you. +这是个默认的名字 + +741 +00:37:35,670 --> 00:37:38,337 +I don't want to spend the valuable demo time showing how to +我不想花费宝贵的时间去演示如何 + +742 +00:37:38,339 --> 00:37:40,656 +rename this cuz unfortunately, +重命名,因为 + +743 +00:37:40,657 --> 00:37:42,974 +I can't just type a new name here because I gotta keep the UI in sync with it. +我不能在这里输入一个新名字, 因为我要保持 UI 与之同步 + +744 +00:37:42,976 --> 00:37:45,276 +So I would have to do something in the UI as well. +所以我必须在 UI 中做一些事情 + +745 +00:37:45,278 --> 00:37:48,079 +But, for now, for your first assignment or two we're, we'll just +你的第一次或第二次作业,我们只会 + +746 +00:37:48,081 --> 00:37:51,548 +call this ViewController, but down the road you're gonna wanna pick better names. +叫它 ViewController,但在这之后,你最好给他更换一个好的名字 + +747 +00:37:51,550 --> 00:37:54,251 +And of course you're gonna be building multiple of +当然你将会在这个应用的这个类中 + +748 +00:37:54,253 --> 00:37:57,554 +these scenes in this class in the same app in the future, so +创建多个场景 + +749 +00:37:57,556 --> 00:38:01,024 +of course, they'll all have different controller names. +当然它们每一个都有不同的 controller 名称 + +750 +00:38:01,026 --> 00:38:07,796 +Okay, this :UIViewController, that's inheritance, that's its superclass, okay? +这个 ':UIViewController' 是告诉我们它的父类是谁 + +751 +00:38:08,799 --> 00:38:12,334 +Swift is single inheritance, so you can only inherit from one class. +Swift 是单继承,你只能让它继承一个类 + +752 +00:38:12,336 --> 00:38:18,139 +It's perfectly fine in Swift not to inherit from a class if you don't want to, all right? +在 Swift 中,你不想继承也可以 + +754 +00:38:18,140 --> 00:38:20,140 +But here we have to inherit from UIViewController cuz we +但在这里我们必须继承于 UIViewController + +755 +00:38:20,142 --> 00:38:23,176 +want all this magic that allows us to control the UI, +想通过它来控制 UI, + +756 +00:38:23,178 --> 00:38:27,880 +like that whole Auto Layout business, and there's a ton of mechanism in here for +像 Auto Layout,这有很多种方式来让 + +757 +00:38:27,882 --> 00:38:31,083 +the, the allowing the controller to control this UI. +controller 控制 UI + +758 +00:38:31,085 --> 00:38:35,487 +So obviously we do that so all ViewControllers, all controllers of these +很明显,所有 ViewController, 所有这些场景中的 controller + +759 +00:38:35,489 --> 00:38:40,425 +little scenes always inherit from either from UIViewController directly or they +必须直接继承于 UIViewController,或者继承于继承 UIViewController 的子类 + +760 +00:38:40,427 --> 00:38:45,296 +inherit from a class that inherits from UIViewController or up their chain so. +或者在继承链条上 + +761 +00:38:46,399 --> 00:38:51,134 +And then inside this curly brace is simply all the instance variables and +在这个花括号里是所有的实例变量和 + +762 +00:38:51,136 --> 00:38:54,070 +methods in this class, 'kay? +方法 + +763 +00:38:54,072 --> 00:38:58,207 +So very simple syntax to define a class. +定义类的语法是非常简练的 + +764 +00:38:58,209 --> 00:39:02,144 +So let's dive right into making some instance variables and methods so +所以让我们定义一些实例变量和方法 + +765 +00:39:02,146 --> 00:39:03,912 +you can see what those look like. +来看看语法是什么样的 + +766 +00:39:03,914 --> 00:39:09,216 +And I thought we, this was segued to because we're going to +我们要把这个 + +767 +00:39:09,218 --> 00:39:12,953 +say we wanted to connect this UI to this code. +这个 UI 对象连接到代码中 + +768 +00:39:12,955 --> 00:39:15,072 +So let's do that. +我们现在就这样做 + +769 +00:39:15,073 --> 00:39:17,190 +Let's connect this label right here into this code, and +我们连接这个 label 到代码中去, + +770 +00:39:17,192 --> 00:39:20,560 +then we're gonna do that by making an instance variable. +然后我们会创建一个实例变量 + +771 +00:39:20,562 --> 00:39:23,062 +In Swift we call them properties. +在 Swift 中我们叫它们 properties + +772 +00:39:23,064 --> 00:39:25,330 +'Kay so if you hear me say property, +如果你听到我说 property, + +773 +00:39:25,332 --> 00:39:27,165 +I'm basically talking about an instance variable. +那我其实就是在说实例变量 + +774 +00:39:27,167 --> 00:39:29,467 +Right? A variable that is part of the class. +清楚吗?实例变量是类中的一个变量 + +775 +00:39:29,469 --> 00:39:31,869 +Every instance of the class gets its own copy of it. +类的每个实例都有它自己的拷贝 + +776 +00:39:31,871 --> 00:39:34,171 +Hopefully you all know what an instance variable is. +希望你们都知道什么是实例变量 + +777 +00:39:34,173 --> 00:39:35,739 +If you don't, again, this class, +如果你不清楚,再说一次,这门课程 + +778 +00:39:35,741 --> 00:39:38,408 +heavy object-oriented, you should definitely know that. +需要很强的面向对象功底,你们应当很清楚 + +779 +00:39:38,410 --> 00:39:41,678 +So I'm gonna make a property here, an instance variable, +我将要声明一个 property ,也可以说是一个实例变量 + +780 +00:39:41,680 --> 00:39:45,848 +that points to this label, so that I can update the label's text, right? +使用指针指向这个 label,这样就我就能够更新这个 label 的内容了 + +781 +00:39:45,850 --> 00:39:50,486 +I need to be able to talk to this label, and the way you do that in eh, +我得跟这个 label 通信,方法是 + +782 +00:39:50,488 --> 00:39:55,824 +in Xcode is you hold down Ctrl, just like we did when we were making +在 Xcode 中,按住 Ctrl,像刚才和边缘连接那样 + +783 +00:39:55,826 --> 00:39:59,627 +a connection to the edge, so I'm holding down Ctrl and clicking on the label, but +所以我按住 Ctrl,连接 label + +784 +00:39:59,629 --> 00:40:02,596 +instead of going to the edge, I'm gonna go into the code, 'kay? +但这次是连接到代码中去 + +785 +00:40:02,598 --> 00:40:06,166 +Now this is kinda wacky. +这是有点古怪 + +786 +00:40:06,168 --> 00:40:07,901 +I know a lot of you are like what? +我知道你们都会感觉很奇怪 + +787 +00:40:07,903 --> 00:40:08,501 +Into the code? +放到代码里? + +788 +00:40:08,503 --> 00:40:11,004 +Yeah? + +789 +00:40:11,005 --> 00:40:13,506 +So we're going right into the code here and let go and it's gonna say oh, +现在我们到右边代码中,松开鼠标 + +790 +00:40:13,508 --> 00:40:16,308 +you wanna make a connection between your UI and your controller. +你想连接 UI 和 controller + +791 +00:40:16,310 --> 00:40:18,844 +No problem, what kinda connection you wanna make? +你需要哪种连接? + +792 +00:40:18,846 --> 00:40:20,846 +And we wanna make what's called an outlet connection. +我们需要设置 outlet 连接 + +793 +00:40:20,848 --> 00:40:22,681 +An outlet means an instance variable or +outlet 代表指向 UI 的 + +794 +00:40:22,683 --> 00:40:25,717 +property that points to this thing in the UI. +实例变量或 property + +795 +00:40:25,719 --> 00:40:30,021 +And all it needs to know to do that is, what do you wanna call this property? +接下来它需要知道 property 应该叫什么名字 + +796 +00:40:30,023 --> 00:40:34,925 +And this is the display of my calculator so I'm gonna call this display and it +它将是我计算器的显示部分,所以我将它命名为 display, + +797 +00:40:34,927 --> 00:40:38,962 +already knows the type of the thing is UILabel of course cuz we dragged from here. +因为我们是从 label 拽过来的,所以知道它的类型 + +798 +00:40:38,964 --> 00:40:41,431 +Don't worry about this weak, I'll talk about that in a moment. +不要担心这个 weak,在后面我们会讲到 + +799 +00:40:41,433 --> 00:40:45,067 +And then we just hit Connect, and it creates an instance variable or +然后我们点击 connect, 它会在 controller 中 + +800 +00:40:45,069 --> 00:40:47,202 +property, right here in our controller. +创建一个实例变量或 property + +801 +00:40:47,204 --> 00:40:51,339 +So this is a great opportunity to look at the syntax in Swift for +这是一个很好的机会了解,在 Swift 中如何 + +802 +00:40:51,341 --> 00:40:54,109 +creating a property. +创建一个 property 的语法 + +803 +00:40:54,110 --> 00:40:56,878 +And there's a couple of things on here that are not normally part of it. +这里有几件事情通常都不是它的一部分 + +804 +00:40:56,880 --> 00:41:02,516 +This is you, the main syntax for creating a property. +这是你创建一个 property 的主要语法 + +805 +00:41:02,518 --> 00:41:04,418 +Let's quickly look at this thing to get it out of the way. +我们快速的了解下这个用法 + +806 +00:41:04,420 --> 00:41:07,454 +This is not really part of the Swift language proper. +这不是 Swift 真正语言的一部分 + +807 +00:41:07,456 --> 00:41:09,555 +This is something Xcode puts in here so +这个小圆圈是 Xcode 生成的 + +808 +00:41:09,557 --> 00:41:14,526 +that this little circle, do you see the little circle in this gutter, appears? +这个小圆圈出现在这里,你看到了吗? + +809 +00:41:14,528 --> 00:41:18,463 +This little circle when I mouse over it, look what Xcode does. +当我把鼠标移动到上面时候,看看 Xcode 的变化 + +810 +00:41:18,465 --> 00:41:21,933 +It shows me what this line of code is connected to. +它展示了这行代码所连接到了什么地方 + +811 +00:41:21,935 --> 00:41:23,852 +'Kay? So that's really cool, and +这看起来非常酷, + +812 +00:41:23,853 --> 00:41:25,770 +you're gonna see that's really valuable later in this demo, +在这个 demo 中,这是非常有用的, + +813 +00:41:25,772 --> 00:41:27,838 +is being able to find out what things are connected to. +它能找到我们连接的是什么控件 + +814 +00:41:27,840 --> 00:41:29,773 +So that's all this thing means here. +这个就是它在这里所展示的意义 + +815 +00:41:29,775 --> 00:41:33,777 +You, you, you don't type this in yourself, that when you Ctrl+drag, it puts it there. +当你按下 Ctrl 同时点击拖动时候,你(可能)不懂这里出现的 Weak 的意思 + +816 +00:41:33,779 --> 00:41:38,748 +This weak, all you, you, if you come from other languages, +如果你从其他语言过来的 + +817 +00:41:38,750 --> 00:41:44,653 +you're used to things like garbage collection to clean up the heap. +你会使用过类似的垃圾回收机制 + +818 +00:41:44,655 --> 00:41:46,288 +Or maybe you even have to alloc and +或者你也许在一些语言里习惯 + +819 +00:41:46,290 --> 00:41:50,258 +free things yourself manually in some languages. +自己手动管理内存 + +820 +00:41:50,260 --> 00:41:51,792 +None of that in Swift. +在 Swift 中是没有的 + +821 +00:41:51,794 --> 00:41:54,828 +In Swift, the, all objects live in the heap, 'kay. +在 Swift 中,所有的对象都在堆中 + +822 +00:41:54,830 --> 00:41:58,398 +All class, the instances of classes live in the heap. +所有类,类的实例都存在堆中 + +823 +00:41:58,400 --> 00:42:02,335 +And the memory for them is managed for you, 'kay? +而 Swift 已经替你进行了内存管理 + +824 +00:42:02,337 --> 00:42:05,371 +You allocate them as much as you want, as soon as there's no pointers to them, +只要没有了指针指向它们,你可以随意分配它们内存 + +825 +00:42:05,373 --> 00:42:08,274 +they get cleaned up, and it's not garbage collection, 'kay? +它们会自动清理,但不是垃圾回收机制 + +826 +00:42:08,276 --> 00:42:10,493 +It's reference counting. +这就是引用计数 + +827 +00:42:10,494 --> 00:42:12,711 +It's actually counting references to them but it's all automatic. +它实际上是计算引用它们的次数,但这都是自动的 + +828 +00:42:12,713 --> 00:42:16,548 +The only thing you ever have to be maybe interested in is this weak business which +你刚才也许唯一感兴趣的是这个 weak 的作用 + +829 +00:42:16,550 --> 00:42:19,851 +is less than a hundredth of a percent of the time. +这东西出现的次数不会太频繁 + +830 +00:42:19,853 --> 00:42:23,788 +And for the first four weeks of this class, forget about weak. +前四周的课程中,忘掉这个 weak + +831 +00:42:23,790 --> 00:42:27,591 +It'll automatically happen when you do this Ctrl+drag, but just ignore it. +它会自动在你当你按下 Ctrl 同时拖动时候出现,但是先忽略它 + +832 +00:42:27,593 --> 00:42:29,560 +But the main thing to know is that all that memory +而最主要的事情是你要知道内存管理 + +833 +00:42:29,562 --> 00:42:31,128 +management is happening for you. +是如何发生的 + +834 +00:42:31,130 --> 00:42:34,330 +Also this, instance variable right here, +同时,实例变量在这里, + +835 +00:42:34,332 --> 00:42:38,267 +which is a pointer to this object, notice there's no ampersands or +它是指向对象的指针,注意这里没有与符号 “&” 或者 “*” + +836 +00:42:38,269 --> 00:42:42,271 +stars or any other kind of syntax that says this is a pointer. +或者其他任何语法说这是一个指针 + +837 +00:42:42,273 --> 00:42:44,406 +'Kay? + +838 +00:42:44,407 --> 00:42:46,540 +If you have a instance, variable or property or +一个实例,变量或属性或 + +839 +00:42:46,543 --> 00:42:48,910 +local variable that is an object, okay, +局部变量都是一个对象 + +840 +00:42:48,912 --> 00:42:52,980 +it's always a pointer to it cuz objects only live in the heap, 'kay? +它总是一个指针,因为对象只在堆中存在着 + +841 +00:42:52,982 --> 00:42:54,648 +So you don't need all that extra stars and +所以不需要多余的 “*” 和 “&”, + +842 +00:42:54,650 --> 00:42:57,184 +ampersand, any of that business from other languages, okay? +或者其他语言中类似作用的东西 + +843 +00:42:58,286 --> 00:43:01,587 +This exclamation point, by the way, I'm gonna talk about in a few minutes, +顺便说一下这个感叹号,我要谈几分钟 + +844 +00:43:01,589 --> 00:43:04,023 +has nothing to do with this being an object, okay? +这是和对象不相关的 + +845 +00:43:04,025 --> 00:43:05,858 +This is, this totally separate thing. +这完全不相干的事情 + +846 +00:43:05,860 --> 00:43:07,092 +We'll get to it. +我们待会就会理解它 + +847 +00:43:07,094 --> 00:43:08,043 +All right. + +848 +00:43:08,044 --> 00:43:08,993 +So let's look at this. +所以让我们看看这个 + +849 +00:43:08,995 --> 00:43:15,166 +This is the syntax for defining a property, 'kay? +这个语法定义了一个属性,对吗? + +850 +00:43:15,168 --> 00:43:16,066 +An instance variable. +一个实例变量 + +851 +00:43:16,068 --> 00:43:18,519 +And it's very simple. +并且它是如此的简单 + +852 +00:43:18,520 --> 00:43:20,971 +You got var, short for variable cuz that's what this is, a variable. +你看到的这个 var,它是变量(variable)的缩写 + +853 +00:43:20,973 --> 00:43:23,473 +The name, this is the name of it, display. +这是变量的名称:display + +854 +00:43:23,475 --> 00:43:25,475 +Okay? That's just the name of this property. +这个属性的名字就是这个 + +855 +00:43:25,477 --> 00:43:26,909 +And then :UILabel! +紧接着就是 UILabel + +856 +00:43:26,911 --> 00:43:28,510 +Is the type, 'kay? +这个是它的类型 + +857 +00:43:28,512 --> 00:43:33,815 +That's the type of this instance variable. +这个是这个实例变量的类型 + +858 +00:43:33,817 --> 00:43:38,452 +So again, I'll talk about the exclamation point later, but +我稍后会讲到那个感叹号 + +859 +00:43:38,454 --> 00:43:42,389 +obviously this thing is pointing to this label so that we can talk to it. +但很明显,我们可以确定这个东西是指向 label 的 + +860 +00:43:42,391 --> 00:43:43,590 +And we'll be doing that in a moment. +我们待会就能确定 + +861 +00:43:43,592 --> 00:43:44,424 +'Kay? + +862 +00:43:44,426 --> 00:43:46,325 +Questions? +有什么疑问吗? + +863 +00:43:46,327 --> 00:43:49,962 +All right, let's talk about another kind of connection we may, +好的,让我们来谈谈另一种连接, + +864 +00:43:49,964 --> 00:43:52,364 +we can make, let's start putting some buttons in our calculator. +让我们开始放一些计算器的按钮吧 + +865 +00:43:52,366 --> 00:43:55,100 +So I'm gonna go back to the Utilities window, 'kay? +我将要回到这个 Utilities 窗口 + +866 +00:43:55,102 --> 00:43:56,734 +By pressing this button over here, +按下这个按钮 + +867 +00:43:56,736 --> 00:44:00,705 +go down to the bottom, go to the third tab over here, the object library. +找到下方的第三个选项卡的对象目录 + +868 +00:44:00,707 --> 00:44:04,775 +And instead of a label, this time I'm gonna drag out a button. +这次拖的不是 label,我将要拖出来一个按钮 + +869 +00:44:04,777 --> 00:44:07,143 +Okay? I'm gonna put this button here now. +现在我要把这个按钮放到这里 + +870 +00:44:07,145 --> 00:44:11,414 +Just to be different, I'm not gonna initially line it up with a blue line. +和刚才有点不一样,没有初始化蓝色的线 + +871 +00:44:11,416 --> 00:44:14,283 +I'm just gonna put it kinda in space out here and +我只是想把它放在这个空间中, + +872 +00:44:14,285 --> 00:44:17,119 +I'll line it up with the blue line later, 'kay? +我等下将把它放在蓝线的下面 + +873 +00:44:17,121 --> 00:44:19,487 +But I don't wanna forget to do that though, I always wanna do that. +希望我待会不会忘记这么做 + +874 +00:44:19,489 --> 00:44:22,724 +What I'm gonna do later is to show you it can be done. +我等下要做的事就是告诉你这是可以做到的 + +875 +00:44:22,726 --> 00:44:26,127 +So, this is gonna be, let's say this is gonna be one of our number buttons. +所以,这会是我们其中的一个数字按钮 + +876 +00:44:26,129 --> 00:44:30,197 +Like the upper left corner of our keypad is a 7. +就像键盘左上角的数字 7 + +877 +00:44:30,199 --> 00:44:31,598 +Okay? + +878 +00:44:31,599 --> 00:44:32,998 +Again, I have the same thing over here. +我还需要其他的一些按钮 + +879 +00:44:33,001 --> 00:44:35,368 +Okay? With the attributes inspector I can +通过 attributes inspector ,我能够 + +880 +00:44:35,370 --> 00:44:37,203 +change things like the font. +对字体什么的作出修改 + +881 +00:44:37,205 --> 00:44:40,872 +Let's make this be 24 point, let's say. +让我们试着把字号改成 24 + +882 +00:44:40,874 --> 00:44:42,791 +I can resize. +我能这么调整大小 + +883 +00:44:42,792 --> 00:44:44,709 +Notice that when I resize it will actually tell me the size, +注意,当我调整它时候,会实时显示字号 + +884 +00:44:44,711 --> 00:44:46,978 +see it saying there what size it is? +看到这里显示的当前的字号 + +885 +00:44:46,980 --> 00:44:50,381 +I can also set the size maybe with this size inspector right here, +还可以通过在这里,进行字号的修改 + +886 +00:44:50,383 --> 00:44:51,348 +type it in exactly. +输入精确的字号 + +887 +00:44:51,350 --> 00:44:53,517 +Maybe 64 by 64, something like that. +先设个 64 x 64 + +888 +00:44:53,519 --> 00:44:54,918 +We don't usually do that. +我们通常不这样做 + +889 +00:44:54,920 --> 00:44:57,587 +We want things to be kinda their natural sizes but +我们希望它能够是原始的大小 + +890 +00:44:57,589 --> 00:45:01,156 +just want to show you that there are other inspectors over here. +但这里只想向你展示有其他的方法 + +891 +00:45:01,158 --> 00:45:02,491 +So we have this 7. +所以我们有这个 7 + +892 +00:45:02,493 --> 00:45:05,460 +Now when this 7 is pressed, what do we want to happen? +当 7 被按下的时候,会发生什么呢? + +893 +00:45:05,462 --> 00:45:07,963 +What we want. +我们想要的是 + +894 +00:45:07,964 --> 00:45:10,465 +Numbers just start appearing up here in the display, right? +数字出现在需要展示的地方 + +895 +00:45:10,467 --> 00:45:13,000 +So that's something our controller is going to have to do. +这就是我们的控制器必须处理的 + +896 +00:45:13,002 --> 00:45:17,071 +So, when we touch this button, we kinda want this button to send a message to +当我们点击这个按钮,我们想让这个按钮发送信息到 + +897 +00:45:17,073 --> 00:45:21,307 +our controller, and we do that the exact same way as we did this one, +我们的控制器,跟之前的方式一样, + +898 +00:45:21,309 --> 00:45:25,911 +we hold down control, drag into our code. +我们按住 Ctrl,然后点击拖动它到代码中 + +899 +00:45:25,913 --> 00:45:29,248 +When we let go though, we're not going to an outlet connection this time, +当我们松开时候,这回我们要的不是 outlet 这个连接, + +900 +00:45:29,250 --> 00:45:34,085 +because I dont want an instance variable here, what i want is a method, right? +因为我不想要个实例变量,我要的是一个方法对吧? + +901 +00:45:34,087 --> 00:45:39,790 +A function on my class, a method, everyone understand the word method I hope, +我类里的一个函数,方法,我想大家都知道 “方法” 这个词的含义, + +902 +00:45:39,792 --> 00:45:44,161 +okay, so we want it to send an [INAUDIBLE] message to our control board, so +我们想让它发送一个消息给控制板 + +903 +00:45:44,163 --> 00:45:48,831 +I'm going to pick" action", [COUGH] losing my voice here. +所以我选 "action" ,[咳嗽],今天有点失声 + +904 +00:45:48,833 --> 00:45:50,433 +Bad time to have a little cold, but. +关键时刻有点感冒……不过还好 + +905 +00:45:50,435 --> 00:45:52,968 +[SOUND] So I'm doing an action so +所以在这里我选了 action + +906 +00:45:52,970 --> 00:45:56,838 +an action is a little different than a outlet, okay? +action 跟 outlet 略有不同 + +907 +00:45:56,840 --> 00:45:58,973 +An outlet means an instance variable or +outlet 代表一个实例变量 + +908 +00:45:58,975 --> 00:46:01,909 +property, action means create a method for me. +或者是一个 property ,action 则是为我创建了一个方法 + +909 +00:46:01,911 --> 00:46:03,944 +So again it wants to know the name of the method. +所以紧接着它要我输入方法的名字 + +910 +00:46:03,946 --> 00:46:05,512 +So what does this thing do? +这个方法要做什么呢? + +911 +00:46:05,514 --> 00:46:08,815 +Well when I press seven, it appends a digit onto the end of +当我按 7 的时候, + +912 +00:46:08,817 --> 00:46:12,852 +whatever's already in the display, so I'm going to call it append, +不管原先显示着什么,都在后面加个 7,所以我应该叫它 append... + +913 +00:46:12,854 --> 00:46:17,390 +I could call it append seven, but I'm actually going to call it append digit, +本来应该叫做 append 7,但我还是选择 appenDigit, + +914 +00:46:17,392 --> 00:46:20,859 +because I want to have one method that all of my buttons use. +因为我想所有的按钮都使用一个方法 + +915 +00:46:20,861 --> 00:46:23,328 +All right? +懂了吗? + +916 +00:46:23,329 --> 00:46:25,796 +I don't want to, copy and pasting a bunch of methods, that would be really bad code. +我不想复制粘贴一堆雷同的方法,那样只会把代码变得一团糟 + +917 +00:46:27,400 --> 00:46:29,566 +But if I'm gonna have one method, +相反我仅仅使用一个方法, + +918 +00:46:29,568 --> 00:46:33,437 +then I need to know which button is sending me this message, okay? +所以我就需要知道是哪个按钮发送的这个消息,对吧? + +919 +00:46:33,439 --> 00:46:37,073 +Luckily, when you haven't actioned a message being sent here, +幸运的是,当你从这里发出消息前 + +920 +00:46:37,075 --> 00:46:40,977 +you can specify that it has arguments, you see right here where it says arguments? +你可以规定它有没有参数,你看这里它写着 arguments 了么? + +921 +00:46:40,979 --> 00:46:45,414 +And it can have no arguments or it can have the sender. +你可以选择没有参数,或者是 sender + +922 +00:46:45,416 --> 00:46:48,483 +Which is the button here as the argument. +sender 的意思就是把这个按钮当作参数 + +923 +00:46:48,485 --> 00:46:52,787 +The only tricky thing here is, and I'm not sure why they did this in Xcode. +这里有点诡异,我不懂 Xcode 为什么要这样处理 + +924 +00:46:52,789 --> 00:46:54,455 +Hopefully, they'll change it in the future. +希望他们以后能改进下 + +925 +00:46:54,457 --> 00:46:59,092 +By default, the type of that argument, which is right here, is anyObject. +就是参数的默认类型是 anyObject + +926 +00:46:59,094 --> 00:47:01,961 +Now, we're gonna talk about anyObject next week. +下周我们会讲什么是 anyObject + +927 +00:47:01,963 --> 00:47:04,330 +But, we don't want anyObject here. +不过在这里我们肯定不要 anyObject + +928 +00:47:04,332 --> 00:47:06,599 +We know that the sender is a UIButton, +我们知道 sender 其实是 UIButton, + +929 +00:47:06,601 --> 00:47:09,935 +So I picked, click this little blue thing and switch this to UIButton. +所以点这里选择 UIButton + +930 +00:47:09,937 --> 00:47:13,672 +When you're doing your homework, if you forget to switch that to UIButton, +如果你做作业的时候,忘了选择 UIButton, + +931 +00:47:13,674 --> 00:47:15,907 +you'll be sad, okay. +你就悲剧了. + +932 +00:47:15,909 --> 00:47:17,541 +So don't forget. +所以,别忘了哦 + +933 +00:47:17,543 --> 00:47:21,978 +And obviously the event that the message is gonna be sent on, touch up inside, +然后很明显,触发事件应该选为 touch up inside, + +934 +00:47:21,980 --> 00:47:25,448 +just means the user touched on this button and the touch went up. +意思是你手指点击的时候落在按钮的范围内 + +935 +00:47:25,450 --> 00:47:27,116 +While it was still inside the button. +而手指抬起来时也还在按钮的范围内 + +936 +00:47:27,118 --> 00:47:29,952 +That's all a touch up inside means there. +这就是 touch up inside 的意思 + +937 +00:47:29,954 --> 00:47:32,021 +All right so when I connect this, +当我点了 connect 以后, + +938 +00:47:32,023 --> 00:47:35,824 +I'm gonna get a method with one argument which is a sender which is a UIButton. +我就得到了一个方法,有一个参数,类型是 UIButton + +939 +00:47:35,826 --> 00:47:38,760 +So let's take a look. +让我们看一下 + +940 +00:47:38,761 --> 00:47:41,695 +So here's your first method declaration in SWIFT, okay? +它就是你的第一个 Swift 声明的方法 + +941 +00:47:41,698 --> 00:47:46,133 +Again it's got this little IBAction thing which is kinda like IBOutlet. +同样这里有一个叫 IBAction 的东西,跟 IBOutlet 类似 + +942 +00:47:46,135 --> 00:47:47,967 +It puts a little dot in the gutter. +左边有一个小圆点 + +943 +00:47:49,104 --> 00:47:50,436 +Okay? So that you can +这样你就可以看见它连的是哪里 + +944 +00:47:50,438 --> 00:47:52,938 +see what this thing is connected to. +这样你就可以看见它连的是哪里 + +945 +00:47:52,940 --> 00:47:59,010 +So this is the normal, Swift method syntax. +这个就是 Swift 定义方法的标准语法 + +946 +00:47:59,012 --> 00:48:02,213 +Starts with func because function, +以 func 开头,这是 function 的缩写 + +947 +00:48:02,215 --> 00:48:04,215 +basically that method is a function in class. +它就是我们类里的一个方法了 + +948 +00:48:04,217 --> 00:48:06,483 +[COUGH] Here's the name. +这是它的名字, AppendDigit + +949 +00:48:06,485 --> 00:48:07,918 +AppendDigit. +这是它的名字,AppendDigit + +950 +00:48:07,920 --> 00:48:10,987 +And then in parentheses, all the arguments separated by commas. +在括号里,所有参数都用逗号分隔 + +951 +00:48:10,989 --> 00:48:12,989 +We only have one argument, though. +我们这只有一个参数 + +952 +00:48:12,991 --> 00:48:15,057 +Here's the name of the first argument. +这个是第一个参数的名字 + +953 +00:48:15,059 --> 00:48:18,860 +That's the name we're going to use to access it inside of our method, and +我们在方法里就要用到这个名字, + +954 +00:48:18,862 --> 00:48:20,295 +here is the type. +这是它的类型 + +955 +00:48:21,264 --> 00:48:22,496 +Okay? It's a UIButton. +懂了么?类型是 UIButton + +956 +00:48:22,498 --> 00:48:24,598 +I, notice no exclamation point there, by the way. +顺便提下,要注意到这里是没有叹号的 + +957 +00:48:26,535 --> 00:48:31,237 +Okay if this had a return value, if this method returned something this one doesn't +虽然这个方法没有返回值,但如果 + +958 +00:48:31,239 --> 00:48:36,208 +[COUGH] but if it returned something, it would look like this arrow the return type +如果它有的话,这里就写这样的箭头 + +959 +00:48:37,745 --> 00:48:40,311 +okay so that's how you specify a return type. +这样就定义了它的返回类型 + +960 +00:48:42,215 --> 00:48:48,185 +Okay, pretty simple the syntax and then inside here we just type, +看见了么?非常简单的语法 + +961 +00:48:48,187 --> 00:48:51,822 +well whatever we want this thing to do when one of these buttons is touched. +继续看我们的函数,当点击了其中一个按钮, + +962 +00:48:51,824 --> 00:48:53,774 +So what do we want it to do? +我们要让它干什么 + +963 +00:48:53,775 --> 00:48:55,725 +Well, okay, first of all before we do that, let's go ahead and make more of +在此之前,我们先多弄几个按钮 + +964 +00:48:55,727 --> 00:48:58,928 +these buttons because I need seven, eight, nine, four, five, six, all this. +我们还需要其他的按钮,4,5,6 等等等等 + +965 +00:48:58,930 --> 00:49:01,664 +So let's copy and paste the button. +我们可以复制粘贴这些按钮 + +966 +00:49:01,666 --> 00:49:04,400 +When I copy and +当我复制粘贴这些按钮 + +967 +00:49:04,401 --> 00:49:07,135 +paste the button, notice I'm using the blue lines to put it perfectly lined up. +注意我用这些蓝线来对齐 + +968 +00:49:07,138 --> 00:49:11,373 +Okay, also notice that it there also sending this message. +而且它们都同样发送这个消息 + +969 +00:49:11,375 --> 00:49:14,776 +All right, see how their both sending the message, because when I copy and +它们发送同样这个消息是为什么呢 + +970 +00:49:14,778 --> 00:49:18,012 +paste, it copied that aspect of it as well. +因为拷贝按钮的时候连同这些信息也一起拷贝了 + +971 +00:49:18,014 --> 00:49:21,182 +So there's another one, I could select all three of these and +可以一次选三个,一起拷贝 + +972 +00:49:21,184 --> 00:49:27,154 +copy and paste, okay, I could select all six of these and copy and paste. +6 个一起选 + +973 +00:49:27,156 --> 00:49:30,990 +So I can quickly make, my entire keypad. +这样快速得把键盘造出来了 + +974 +00:49:30,992 --> 00:49:33,343 +Just need to edit the title. +只需要改改 title + +975 +00:49:33,344 --> 00:49:35,695 +Now, if while I'm editing these titles, sometimes you're clicking around in +如果你像现在这样,做些改动,点来点去 + +976 +00:49:35,697 --> 00:49:39,431 +here and, you know, you're not a very accurate clicker. +不小心没点准 + +977 +00:49:39,433 --> 00:49:43,368 +[LAUGH] Or, you know, you just get out, out of control clicking here, and oh, +手一滑把控件拖飞了 + +978 +00:49:43,370 --> 00:49:45,236 +you moved it out of the way. +手一滑把控件拖飞了 + +979 +00:49:45,238 --> 00:49:46,821 +Okay? +怎么办? + +980 +00:49:46,822 --> 00:49:48,405 +No problem, you can just put it right back in. +没关系,只要把它再拖回原地 + +981 +00:49:48,408 --> 00:49:51,675 +Okay, use the blue lines to your advantage. +那些蓝色的辅助线会帮你个大忙 + +982 +00:49:52,844 --> 00:49:55,278 +And we'll put our zero down here. +把 0 放在这 + +983 +00:49:55,279 --> 00:49:57,713 +And I don't need these buttons so I'm just hit, selecting it, hitting delete. +选中这些,按下 Delete,我们就可以把不需要的按钮删除 + +984 +00:49:57,716 --> 00:49:59,715 +That's how you can get rid of something. +就这么删东西 + +985 +00:49:59,717 --> 00:50:02,985 +And I promised I was gonna put these all on blue lines, so I'm gonna do that. +我刚才说过要把它们对齐蓝线 + +986 +00:50:02,987 --> 00:50:05,921 +I'm gonna put it right underneath the zero. +把它们放在 0 标签控件的底下 + +987 +00:50:05,923 --> 00:50:08,890 +So here's a blue line that means underneath the zero, and +这条蓝线就表明我可以放在标签底下 + +988 +00:50:08,892 --> 00:50:10,692 +then I'm going to put at this edge. +让它对起左边这条蓝线 + +989 +00:50:10,694 --> 00:50:14,962 +So now you can see that the blue lines are not just the edges, but +你可以发现,这些蓝线不仅在调整边缘的时候出现 + +990 +00:50:14,964 --> 00:50:17,965 +they are other objects, like the other objects in the keypad and +在调整其他对象,比如这些按钮的时候,它们也会出现 + +991 +00:50:17,967 --> 00:50:20,667 +also now the title, the display rather at the top. +同样,标题,标签这些也同样受用 + +992 +00:50:21,870 --> 00:50:26,205 +So I've got all these buttons, they're all sending this message append digit. +现在按钮齐了,它们都发送 appendDigit 这个消息 + +993 +00:50:26,207 --> 00:50:28,874 +So I need to figure out which one is sending it, +所以我就需要分辨出是哪个按钮发送的消息 + +994 +00:50:28,876 --> 00:50:30,942 +so that I can do the right thing. +然后针对性的做相应的功能 + +995 +00:50:30,944 --> 00:50:33,611 +So let's start writing some code inside the method. +现在让我们来往这个方法里添加代码 + +996 +00:50:33,613 --> 00:50:37,281 +So the first thing I'm going to do is declare a local variable, +首先,我要声明一个局部变量 + +997 +00:50:37,283 --> 00:50:39,917 +it's just a local variable inside this method. +就是方法内部的局部变量 + +998 +00:50:39,919 --> 00:50:43,520 +I'm going to do that by saying let digit equal. +输入 let digit = + +999 +00:50:43,522 --> 00:50:47,824 +So I want this local variable to be the digit that was pressed. +我想让这个局部变量表示我们输入的数字 + +1000 +00:50:47,826 --> 00:50:50,743 +Okay. +我想让这个变量表示我们输入的数字 + +1001 +00:50:50,744 --> 00:50:53,661 +So, first thing that's quite different here is, what's let? +这里值得注意的是,这个 let 是什么? + +1002 +00:50:53,664 --> 00:50:54,363 +Okay? + +1003 +00:50:54,365 --> 00:50:56,999 +Why isn't this var, right? +为什么不是跟上面那个一样的 var ? + +1004 +00:50:57,001 --> 00:51:00,735 +Cuz var means variable, what the heck does let mean? +因为 var 是变量的意思,那 let 是什么鬼? + +1005 +00:51:00,737 --> 00:51:05,973 +Well let is exactly the same as var except it's a constant. +其实 let 跟 var 差不多,只不过 let 代表常量 + +1006 +00:51:07,143 --> 00:51:10,744 +Which means you're going to sign this right off the bat, and +意味着一旦你为它设置了初值 + +1007 +00:51:10,746 --> 00:51:13,046 +it's never going to change in this method. +它在这个方法内就再也不能被改变了 + +1008 +00:51:13,048 --> 00:51:15,415 +Now Swift makes a big deal about this, and +这在 Swift 里很重要 + +1009 +00:51:15,417 --> 00:51:19,552 +I love this feature, because if I'm reading this code, +我大爱这个特性,因为当我读代码的时候, + +1010 +00:51:19,554 --> 00:51:23,355 +I know the digit is never going to change all, this might be, you know. +我知道它不会变,而上面那个(var)会变 + +1011 +00:51:23,357 --> 00:51:24,856 +It might have a dozen lines of code. +假设你的方法里有几十行代码, + +1012 +00:51:24,858 --> 00:51:26,792 +Which by the way, +顺便提一下, + +1013 +00:51:26,793 --> 00:51:28,727 +you shouldn't have very many methods, with many more lines of code then that. +你最好别在一个方法里面塞太多的代码, + +1014 +00:51:28,729 --> 00:51:30,294 +Okay? You want people to be able to +你应该让人清楚明了的知道你这个方法要做的是什么事情 + +1015 +00:51:30,296 --> 00:51:31,796 +kind of see what a method's doing. +你应该让人清楚明了的知道你这个方法要做的是什么事情 + +1016 +00:51:33,232 --> 00:51:34,765 +You can use other methods, +你可以添加其他的方法, + +1017 +00:51:34,767 --> 00:51:37,801 +call other methods if you need to get more code in there. +然后通过调用那些方法来实现更多的逻辑 + +1018 +00:51:37,803 --> 00:51:38,935 +so. +回过头来 + +1019 +00:51:38,937 --> 00:51:39,835 +Here I can de-, +回过头来 + +1020 +00:51:39,837 --> 00:51:41,270 +rely on that not changing. +因为有了这个 “不变” 的性质, + +1021 +00:51:41,272 --> 00:51:44,406 +That's big for readability. +代码的可读性得到了很大的提升 + +1022 +00:51:44,407 --> 00:51:47,541 +You'll be surprised how much more readable it makes the code, to know that this is a, +你会惊叹仅仅知道哪些是变量,哪些是常量,就会对代码的可阅读性带来这么大的提升 + +1023 +00:51:47,544 --> 00:51:49,177 +local variable, but it's constant. +你会惊叹仅仅知道哪些是变量,哪些是常量,就会对代码的可阅读性带来这么大的提升 + +1024 +00:51:49,179 --> 00:51:50,111 +Only set at the beginning. +只需要声明的时候加个关键字就行 + +1025 +00:51:50,113 --> 00:51:52,913 +Yeah. Is there a reason, constants and +[学生提问] 对于像变量、常量这些东西,这里为什么都用相同的命名规范? + +1026 +00:51:52,915 --> 00:51:54,715 +like, variables have the same naming convention. +[学生提问] 对于像变量、常量这些东西,这里为什么都使用相同的命名规范? + +1027 +00:51:54,717 --> 00:51:56,450 +Since [UNKNOWN] like Java there. +因为比如说 Java 会用 “全部大写” 或者 “全部小写” 来区别这些概念 + +1028 +00:51:56,451 --> 00:51:58,184 +Like the naming conventions like all caps or lowercase. +因为比如说 Java 会用 “全部大写” 或者 “全部小写” 来区别这些概念 + +1029 +00:51:58,186 --> 00:52:00,770 +Yeah. So, yeah. +[提问完毕] + +1030 +00:52:00,771 --> 00:52:03,355 +The question is, why don't I call digit like all caps digit, or +这位同学的问题是,为什么不把 digit 写成 DIGIT, + +1031 +00:52:03,358 --> 00:52:05,424 +something like that, so I know it's a constant. +以此来区分它是不是常量 + +1032 +00:52:05,426 --> 00:52:07,626 +That would be a programming style thing. +这算是编程风格的问题, + +1033 +00:52:07,628 --> 00:52:10,929 +Generally in Swift they don't do that. +但在 Swift 里,我们通常不这样做 + +1034 +00:52:10,931 --> 00:52:13,765 +And, I'll show you why that is in a moment. +我之后会给你们演示, + +1035 +00:52:13,767 --> 00:52:15,233 +Why you don't really need to do that. +为什么我们不需要通过玩弄命名规范来区别这些概念, + +1036 +00:52:15,235 --> 00:52:18,069 +Because you can very quickly find out the declaration of +因为你可以非常快速的找到每个变量的定义, + +1037 +00:52:18,071 --> 00:52:22,406 +any symbol anywhere with one click, and you'll see that. +只需要点一下鼠标就一目了然 + +1038 +00:52:22,408 --> 00:52:25,209 +Good question though. +是个好问题 + +1039 +00:52:25,210 --> 00:52:28,011 +All right, so I wanna let the digit, equal the number that's on the, +所以,接下来我要 let digit = 被触发的按钮上的那个数字 + +1040 +00:52:28,013 --> 00:52:30,196 +the sending button. +所以,接下来我要 let digit = 被触发的按钮上的那个数字 + +1041 +00:52:30,197 --> 00:52:32,380 +So I'm gonna have to send a message to this button. +所以我要向那个按钮发送一个消息 + +1042 +00:52:32,383 --> 00:52:34,316 +Okay? Gonna have to somehow access this button. +对吧?我们得访问这个按钮对象 + +1043 +00:52:34,318 --> 00:52:37,886 +So I'm gonna have to do sender, something. +我就打 sender 然后.. + +1044 +00:52:37,888 --> 00:52:40,655 +Give me what your title is, okay? +拿到它的 title 对吧? + +1045 +00:52:40,657 --> 00:52:44,091 +So this is a good time to talk about the documentation. +现在就是讲讲文档的好时机了 + +1046 +00:52:44,093 --> 00:52:45,543 +[COUGH]. +[咳嗽] + +1047 +00:52:45,544 --> 00:52:46,994 +Because being a good iOS developer, +想要成为一名好的 iOS 开发者, + +1048 +00:52:46,996 --> 00:52:50,397 +really demands that you are good at navigating the documentation. +熟练地使用文档是必须的 + +1049 +00:52:50,399 --> 00:52:54,334 +Luckily, the documentation is really well plugged in to Xcode. +幸运的是,Xcode 已经完美地嵌入了文档支持 + +1050 +00:52:54,336 --> 00:52:57,036 +For example, if I wanna find out about button, +比如,我想看看按钮的文档 + +1051 +00:52:57,038 --> 00:53:00,339 +all I need to do is hold down the option key. +我只要按住 option 键 + +1052 +00:53:00,341 --> 00:53:01,373 +Okay? +我只要按住 option 键 + +1053 +00:53:01,375 --> 00:53:02,974 +And watch what happens now. +看见有什么变化么? + +1054 +00:53:02,976 --> 00:53:04,542 +As I mouse over things, +当我的鼠标移动到文本上方时,它们底下就会出现一条蓝色的虚线 + +1055 +00:53:04,544 --> 00:53:09,680 +everything, it turns blue with a dashed blue line under it, okay? +当我的鼠标移动到文本上方时,它们底下就会出现一条蓝色的虚线 + +1056 +00:53:09,682 --> 00:53:10,748 +If I click on it, +如果我点击 + +1057 +00:53:12,117 --> 00:53:14,884 +it gives me a little blurb from the documentation about this thing. +它就弹出一个文档的摘要 + +1058 +00:53:14,886 --> 00:53:17,954 +So it's saying, you know, here's, button is a class. +它说这是 button, 这是一个类, + +1059 +00:53:17,956 --> 00:53:19,288 +Here's its inheritance. +这里有它的继承关系 + +1060 +00:53:19,290 --> 00:53:20,689 +Here's a little bit of what it does. +这里是关于它的功能 + +1061 +00:53:20,691 --> 00:53:22,691 +And really awesome at the bottom here, +最棒的是在最后这里, + +1062 +00:53:22,693 --> 00:53:25,427 +here's a link that takes you to the detailed documentation. +这是一个指向详细文档的链接 + +1063 +00:53:25,429 --> 00:53:27,962 +So I'm gonna click this little link right here. +我点击这个链接 + +1064 +00:53:27,964 --> 00:53:34,501 +It's going to be up a documentation window, with UIButton in it, hello? +它就打开了 UIButton 的文档窗口……咦? + +1065 +00:53:34,503 --> 00:53:38,038 +Did I not click that right thing here, +我没点错吧? + +1066 +00:53:38,040 --> 00:53:43,076 +oh I hope I don't have a network issue here. +不会是网络出问题了吧.. + +1067 +00:53:43,078 --> 00:53:47,046 +hm, okay well, I guess I'm not connected to the network, +好吧,我猜我的网络出问题了 + +1068 +00:53:47,048 --> 00:53:50,149 +that's the problem, so it's getting this off the network. +果然,没有联上网。 + +1069 +00:53:50,151 --> 00:53:53,819 +Okay so. +好吧 + +1070 +00:53:53,820 --> 00:53:57,488 +Imagine that there were documentation here and, it would have along this side here +那就想象一下,文档出现在了这里 + +1071 +00:53:57,491 --> 00:54:03,294 +on the left all the instance variables or properties and methods of u i button. +在窗口的左边,就会出现很长的一列关于 UIButton 的属性,变量,方法什么的 + +1072 +00:54:03,296 --> 00:54:05,929 +And you could click on any one, and +你可以点击它们 + +1073 +00:54:05,931 --> 00:54:08,165 +in there we'd have a full description of it here. +然后就可以在这里看见完整的描述 + +1074 +00:54:08,167 --> 00:54:11,735 +And all the types that it referenced you could click on it here, and +所有文档间的引用你都可以点击, + +1075 +00:54:11,737 --> 00:54:14,504 +basically it's a hyper linked documentation [UNKNOWN]. +它本质上就是一些文档间的超链接, + +1076 +00:54:14,506 --> 00:54:16,773 +As you can imagine. +你可以想象得到的 + +1077 +00:54:16,774 --> 00:54:19,041 +I'll try to get the networking working on Wednesday and we'll take a look at this. +我争取在下周三把网络问题搞定,到时候我们就能一睹芳容了 + +1078 +00:54:19,043 --> 00:54:21,494 +But if I was looking in here, +假设我能看到文档的话, + +1079 +00:54:21,495 --> 00:54:23,946 +I'd look down in the section that says getting the button's current state, and +我会在这里找到一些如何获取 UIButton 状态的信息 + +1080 +00:54:23,948 --> 00:54:30,185 +I'd find that there is an instance property there called current title. +我会找到一个叫做 currentTitle 的属性 + +1081 +00:54:30,187 --> 00:54:31,552 +Okay? It's unfortunate I'm not going to +很遗憾没能演示这个流程 + +1082 +00:54:31,554 --> 00:54:32,186 +link these things. +很遗憾没能演示这个流程 + +1083 +00:54:32,188 --> 00:54:33,687 +But. +不过问题不大 + +1084 +00:54:33,689 --> 00:54:39,993 +So how do we access, property or call a method in another object, +那么怎么访问到一个对象的属性、方法呢? + +1085 +00:54:39,995 --> 00:54:43,429 +will look exactly the same whether you call it a method or +答案是,访问属性和调用方法的方式是一模一样的 + +1086 +00:54:43,431 --> 00:54:46,332 +accessing a property, which is you use dot. +访问属性,你用点(.) + +1087 +00:54:46,334 --> 00:54:49,435 +Okay. It's the same syntax that's used in +这跟大多数语言是一样的,都用点号来访问成员 + +1088 +00:54:49,437 --> 00:54:52,771 +a lot of languages is to, to do dot. +这跟大多数语言是一样的,都用点号来访问成员 + +1089 +00:54:52,773 --> 00:54:55,173 +And so when you do that, Xcode is going to say, oh, +当你在 Xcode 里打一个点的时候,它就说,呐, + +1090 +00:54:55,175 --> 00:54:58,209 +well, here's all the things button knows how to do. +这里是所有 UIButton 可访问的成员 + +1091 +00:54:58,211 --> 00:54:59,894 +Okay? +看见了么? + +1092 +00:54:59,895 --> 00:55:01,578 +And as you can see, button knows how to do a lot of things. +你可以发现,UIButton 能做很多事情, + +1093 +00:55:01,581 --> 00:55:03,747 +Because it inherits from a class, it inherits from a class, +这是因为它继承于一个类,它的父类又继承于另一个类,不停继承 + +1094 +00:55:03,749 --> 00:55:07,451 +it inherits from a class, that all have lots of methods in them. +所以累积起来就有很多方法可供调用 + +1095 +00:55:07,453 --> 00:55:10,320 +So when I looked at that documentation. +所以当我查看了文档以后, + +1096 +00:55:10,322 --> 00:55:13,823 +I've found that current title was the thing I wanted. +我知道 currentTitle 这个属性正是我想要的 + +1097 +00:55:13,825 --> 00:55:18,194 +Now notice as I start to type a c, it's already cutting down +注意这里我打个字母 c,它会帮我过滤出那些开头是 c 的选择 + +1098 +00:55:18,196 --> 00:55:23,331 +the things that could be starting with a c, and then c u, they cut down even more. +然后接着打 cu,它有棒我过滤掉了一些 + +1099 +00:55:23,333 --> 00:55:28,770 +I can type tab, to get to the first ambiguity point, then I can type t. +我可以按 Tab 键,前进到第一个歧义点,然后接着打 t + +1100 +00:55:29,739 --> 00:55:31,889 +Okay? +我可以按 Tab 键,前进到第一个歧义点,然后接着打 t + +1101 +00:55:31,890 --> 00:55:35,875 +And then tab again, and I'm here at currentTitle and then I can press return. Okay? +然后再敲 Tab 键,得到 currentTitle,然后按 Enter 键 + +1103 +00:55:35,877 --> 00:55:37,327 +So there it is. +好了 + +1104 +00:55:37,328 --> 00:55:38,778 +digit = sender.currentTitle + +1105 +00:55:38,780 --> 00:55:45,484 +so, what's going on here in terms of the sender title. +我们现在拿到了 sender 的 currentTitle 了,然后呢? + +1106 +00:55:45,486 --> 00:55:49,520 +Let's go ahead and print this out to the console just to see what's going on. +我们把它在 console(控制台)中打印出来,看看它里面是什么东西 + +1107 +00:55:49,522 --> 00:55:50,688 +So I'm gonna println. +这里使用 println 函数 + +1108 +00:55:50,690 --> 00:55:55,992 +At which is a function, a global function that takes a String. +它是一个全局函数,以一个 String 为参数 + +1109 +00:55:55,994 --> 00:55:57,694 +So I give it a String. +所以我就给它一个 String + +1110 +00:55:57,696 --> 00:55:59,762 +And inside that String, I'll type mm, +在 String 里,我打 + +1111 +00:55:59,764 --> 00:56:05,000 +digit equals and now I wanna embed the value of digit in this String. +"digit = ",我想把 digit 的值嵌入到这个 string 里面 + +1112 +00:56:05,002 --> 00:56:08,337 +And Swift has a really cool feature which is backslash open parentheses +这里介绍一个 Swift 很酷的特性,就是, + +1113 +00:56:08,339 --> 00:56:11,924 +close parentheses. +如果你在字符串里里放进这个 "\()",然后你就可以在括号里面放入一个表达式 + +1114 +00:56:11,925 --> 00:56:15,510 +If you put that in a String, and then inside there you put some expression, then +如果你在字符串里里放进这个 "\()",然后你就可以在括号里面放入一个表达式 + +1115 +00:56:15,512 --> 00:56:21,048 +it will evaluate that expression turn it into a String, and embed it in the String. +Swift 就会对这个表达式求值,然后把值转换成 String,最后嵌入到那个字符串里 + +1116 +00:56:21,050 --> 00:56:24,718 +Okay, so its really easy to println values by +所以用这个 "\()" 语法可以很方便的 println 一个对象的值 + +1117 +00:56:24,720 --> 00:56:28,254 +using this backslash parenthesis. Okay? +所以用这个 "\()" 语法可以很方便的 println 一个对象的值 + +1119 +00:56:28,256 --> 00:56:30,189 +So let's go ahead and run and +现在让我们编译运行然后 + +1120 +00:56:30,190 --> 00:56:32,123 +see what happens when we press these buttons to see what kind of result we get. +看看我们按这些按钮的时候会打印出什么结果 + +1121 +00:56:32,126 --> 00:56:35,027 +It's not going to be quite what we expect, but let's see. +结果可能会跟预期的有所不同, + +1122 +00:56:37,864 --> 00:56:42,066 +Alright so, here's our UI we got our buttons that's a good start. +好咧,这里是我们的 UI,有了一些按钮,看起来不错 + +1123 +00:56:42,068 --> 00:56:44,435 +And now, and console, where's the console? +但是控制台呢?输出结果的控制台去哪了? + +1124 +00:56:44,437 --> 00:56:46,269 +Watch this. I'm going to press a button five. +看好了,当我点击 5 按钮的时候 + +1125 +00:56:47,372 --> 00:56:49,238 +The console appears at the bottom here. +控制台就在下面出现了 + +1126 +00:56:49,240 --> 00:56:50,172 +See this down here. +看见了吗?在底栏这里 + +1127 +00:56:50,174 --> 00:56:51,874 +This is the console. +这就是控制台 + +1128 +00:56:51,876 --> 00:56:56,277 +And it's saying digit equals, hm, optional five. +这里显示了, digit 等于……呃……Optional("5") + +1129 +00:56:56,279 --> 00:56:57,211 +Okay. +好吧 + +1130 +00:56:57,213 --> 00:56:58,746 +How about a nine? +那 9 呢? + +1131 +00:56:58,748 --> 00:56:59,713 +They're all optional. +也是 Optional 的 + +1132 +00:56:59,715 --> 00:57:03,250 +What the heck is going on here? Okay. +这是什么鬼? + +1134 +00:57:03,251 --> 00:57:05,418 +This is crucial to understanding Swift. +接下来我们将要理解一个 Swift 里的重要概念 + +1135 +00:57:05,420 --> 00:57:08,421 +This is probably the most important thing to understand that +这个概念初学者常常会搞错,但在 Swift 里它非常特别十分重要 + +1136 +00:57:08,423 --> 00:57:11,424 +people don't quite get right from the start. +这个概念初学者常常会搞错,但在 Swift 里它非常特别十分重要的 + +1137 +00:57:11,426 --> 00:57:15,827 +So we're really going to focus here on understanding what +所以接下来我们集中精力,好好的理解这个 Optional 到底是什么意思 + +1138 +00:57:15,829 --> 00:57:17,862 +optional means right there. +所以接下来我们集中精力,好好的理解这个 Optional 到底是什么意思 + +1139 +00:57:17,864 --> 00:57:18,730 +Okay? +注意听咯 + +1140 +00:57:18,731 --> 00:57:19,597 +So let's go back to our code. +先回到代码 + +1141 +00:57:22,168 --> 00:57:25,969 +And look at this, oh and by the way it, when the console appears down here, +看这个,对了,顺便提一下,当控制台出现了以后, + +1142 +00:57:25,971 --> 00:57:28,538 +you can make it go away with this little button, or +你可以用这个按钮把它隐藏掉,或者 + +1143 +00:57:28,540 --> 00:57:31,274 +you can just drag it out of the way okay? +也可以用鼠标把它拖走 + +1144 +00:57:31,276 --> 00:57:34,711 +But sometimes it's nice to have that console still there, so +不过让它一直显示在那里也挺好的, + +1145 +00:57:34,713 --> 00:57:39,548 +you can look at your output while you're you know reacting to whatever you found, +你可以随时看见你的输出,及时察觉问题 + +1146 +00:57:39,550 --> 00:57:41,750 +in fact we will leave that up there, so you can see the optionals. +我就不隐藏它了,让你可以看见我们现在要讲的 Optional + +1147 +00:57:42,753 --> 00:57:45,186 +Alright, so, what's going on here? +言归正传 + +1148 +00:57:45,188 --> 00:57:48,956 +Well, what's happening here is, well, first of all, +首先, + +1149 +00:57:48,958 --> 00:57:52,759 +don't you find this a little bit odd, let digit, I didn't put a type. +你有没有发现一个奇怪的地方? 这里 let digit = …… 我并没有给 digit 一个类型 + +1150 +00:57:52,761 --> 00:57:55,595 +You see that? +看到么? + +1151 +00:57:55,597 --> 00:57:57,663 +How, what type is digit? +那这个 digit 到底是什么类型呢? + +1152 +00:57:57,665 --> 00:58:02,334 +Okay, well there's no type in there, no type information whatsoever, so. +你可能会想,这里没有指定任何类型,难道 Swift 支持无类型变量? + +1153 +00:58:02,336 --> 00:58:04,636 +Does Swift have untyped variables? +你可能会想,这里没有指定任何类型,难道 Swift 支持无类型变量? + +1154 +00:58:04,638 --> 00:58:06,171 +No, it's exact opposite. +错!恰恰相反 + +1155 +00:58:06,173 --> 00:58:10,141 +Swift is very strongly typed. Okay. +Swift 是非常非常强类型的语言 + +1157 +00:58:10,142 --> 00:58:11,341 +All variables have a type. +所有变量都有它的类型 + +1158 +00:58:11,344 --> 00:58:12,943 +You have to specify type. +你必须规定一个类型 + +1159 +00:58:12,945 --> 00:58:17,847 +But, Swift is also incredibly good at what's called type inference. +然后,Swift 有一个非常强大的特性,叫做类型推导 + +1160 +00:58:17,849 --> 00:58:20,817 +So it can infer the type from the context. +这样它就能通过当前上下文来推断出变量的类型 + +1161 +00:58:20,819 --> 00:58:25,554 +So here I let digit equalwhatever this is, this currentTitle, and +所以,当我写 digit = ... 无论我等号后面写什么,这个 currentTitle, + +1162 +00:58:25,556 --> 00:58:29,391 +so it just made digit be the same type as this. +它都能将 digit 设置成等号后面那个东西的类型 + +1163 +00:58:29,393 --> 00:58:31,543 +Okay. +懂了么? + +1164 +00:58:31,544 --> 00:58:33,694 +Now back to the question earlier, so what type is that? +回到之前的问题,那么这个到底是什么类型? + +1165 +00:58:33,697 --> 00:58:37,365 +Well, if I hold down option, okay, just like we used option to +我可以按住 Option 键,就像查看文档那样, + +1166 +00:58:37,367 --> 00:58:42,636 +go look into the documentation, we can also option click on our own variables. +我们也可以按住 Option 来点击我们的变量, + +1167 +00:58:42,638 --> 00:58:44,337 +To see are they constant? +看看它是常量还是变量 + +1168 +00:58:44,339 --> 00:58:45,204 +Are they variables? +它们是变量么? + +1169 +00:58:45,206 --> 00:58:46,138 +And what type are they? +还可以看看它们是什么类型? + +1170 +00:58:46,140 --> 00:58:47,306 +So watch this. +看这个 + +1171 +00:58:47,308 --> 00:58:50,225 +Option click. +按住 Option 然后点击 + +1172 +00:58:50,226 --> 00:58:53,143 +It says digit is of type String question mark. +它说,digit 是 “String?” 类型的 + +1173 +00:58:53,146 --> 00:58:54,579 +Okay? String question mark. +嗯,String 后面有个问号 + +1174 +00:58:55,515 --> 00:58:58,248 +That question mark means optional. +这个问号的意思是 —— “Optional(可选)” + +1175 +00:58:58,250 --> 00:59:02,585 +So there is a type in Swift, it's a type, called optional. +在 Swift 里面,有一种类型,叫做 optional + +1177 +00:59:02,587 --> 00:59:08,257 +Okay. Optional, that type can have only two values. +Optional 这种类型,只有两个值 + +1178 +00:59:08,259 --> 00:59:10,592 +One value is not set. +一个值叫:未设 + +1179 +00:59:12,095 --> 00:59:16,997 +Okay, this optional is not set, there has never been set or someone has +代表着这个值还没有被任何人设置过,或者,有人故意把它设置成了 “未设” 状态 + +1180 +00:59:16,999 --> 00:59:20,934 +set it to the not set state, they unset it if you want to think about it that way. +代表着这个值还没有被任何人设置过,或者,有人故意把它设置成了 “未设” 状态 + +1181 +00:59:20,936 --> 00:59:25,405 +So optional one value is not set, we call that there's a, symbol for +当一个 Optional 的变量是 “未设” 状态时, + +1182 +00:59:25,407 --> 00:59:28,241 +it in here called nil, N, I, L, okay? +有一个符号用来表示这个状态,这个符号叫做 nil, N, I, L. + +1183 +00:59:28,243 --> 00:59:31,210 +That means not set, that's the value of an optional not set. +nil 就是 “未设” 的意思,就是 optional 变量在 “未设” 状态下的值 + +1184 +00:59:31,212 --> 00:59:34,747 +That's the only thing nil means in Swift is option this is an optional, +在 Swift 里,nil 只有这一个意义,就是说这个变量是 Optional 的, + +1185 +00:59:34,749 --> 00:59:36,948 +the value of an optional that is not set. +而且它的值是 “未设” + +1186 +00:59:36,950 --> 00:59:41,586 +What's the other value that an optional could have well the other value is. +那 Optional 的另一种值是是什么呢? + +1187 +00:59:41,588 --> 00:59:44,655 +Something, it's set to something, okay. +“有值”,就是说它被设置赋了一个值 + +1188 +00:59:44,657 --> 00:59:47,624 +And the type of that something is what, +那 “有值” 的这个值,是什么类型呢? + +1189 +00:59:47,626 --> 00:59:51,261 +is specified next to the question mark String. +就是 “?” 前面那个东西代表的类型 + +1190 +00:59:51,263 --> 00:59:55,932 +So really you can almost think of the question mark there, that's the type +所以,你可以这样想: + +1191 +00:59:55,934 --> 01:00:00,769 +optional, and that String to the left is just saying if this optional is set, +问号左边的那个 String,就表示,如果这个 Optional 变量被赋了值的话,那么它的类型就是 String + +1192 +01:00:00,771 --> 01:00:04,139 +what type of thing is it set to, in this case a String. +问号左边的那个 String,就表示,如果这个 Optional 变量被赋了值的话,那么它的类型就是 String + +1193 +01:00:04,141 --> 01:00:06,941 +So we would call this an optional String. +所以,我们可以称其为 “Optional String” + +1194 +01:00:06,943 --> 01:00:11,846 +But it's really an optional, it's not a String that can be nil, +但是它实际上确确实实是 Optional 类型的,它不是一个可以为 nil 的 String + +1195 +01:00:11,848 --> 01:00:14,815 +it's an optional that can be a String. +它是 Optional 类型,只不过可以被赋值为 Stirng + +1196 +01:00:14,817 --> 01:00:16,516 +Everybody cool with that sentence? +好好理解这句话 + +1197 +01:00:16,518 --> 01:00:19,019 +That's an important sentence to understand, okay. +理解这个句子和含义非常非常关键 + +1198 +01:00:20,055 --> 01:00:23,956 +So, this got to be an optional because this currentTitle method right here, +所以在这里,currentTitle 返回的值肯定是 Optional 类型的 + +1199 +01:00:23,958 --> 01:00:26,525 +returns an optional String, let's look at that. +我们来看看 + +1200 +01:00:26,527 --> 01:00:29,094 +So I'm going to press Option down here, click. +按住 Option 点 currentTitle + +1201 +01:00:29,096 --> 01:00:31,529 +Look at this, this is the documentation for it. +看,这是它的文档 + +1201 +01:00:31,531 --> 01:00:36,334 +It's an instance variable a, a, property on UIButton. +这是一个实例变量,UIButton 的属性 + +1202 +01:00:36,336 --> 01:00:37,267 +Name is currentTitle. +名字是 currentTitle + +1203 +01:00:37,269 --> 01:00:39,302 +The type is String, question mark. +类型是 “String?” + +1204 +01:00:39,304 --> 01:00:41,271 +And this little get means it's read-only. +而这里的 “get” 表示这个是只读的 + +1205 +01:00:41,273 --> 01:00:42,672 +I can only get the currentTitle. +我只能 get(读取值) currentTitle + +1206 +01:00:42,674 --> 01:00:44,807 +I can't set it, there are other ways to set a button's title. +但是我不能 set (写入值),有其他方式 set 这个按钮的 title + +1207 +01:00:44,809 --> 01:00:47,810 +You can't set it with this method or this property. +你不能通过这个方法或者属性 set 这个 title + +1208 +01:00:47,812 --> 01:00:51,480 +So it's an optional, so that's why this ended up being an optional all right. +所以这是一个 optional,这就是为什么它最后也是 optional + +1209 +01:00:51,482 --> 01:00:53,081 +Well, that's all wonderful. +嗯,这非常不错 + +1210 +01:00:53,083 --> 01:00:54,549 +How do I get the String? +那我该如何获取这个 String 呢? + +1211 +01:00:54,551 --> 01:00:57,318 +I don't want it optional, I want that button's String. +我不希望它是 optional 的,我要的是这个按钮的 String + +1212 +01:00:57,320 --> 01:01:02,923 +And the way you do that is you unwrap the optional, meaning you look in there and +方法就是解包这个 optional,意思是你打开这个它找到里面的东西, + +1213 +01:01:02,925 --> 01:01:08,061 +get the val, the associated value, with exclamation point, okay. +用 “!” 就可以获取到它的值 + +1214 +01:01:08,063 --> 01:01:11,330 +What happens if I put that exclamation point there? +如果我把感叹号放在这里会怎么样? + +1215 +01:01:11,332 --> 01:01:13,732 +Well first of all, let me show you that when I put that exclamation point, +首先我先会展示给你们看,当我把感叹号放在这里 + +1216 +01:01:13,734 --> 01:01:17,002 +look what happened to digit, I'm Option-clicking on digit. +看看会有什么变化,我现在点击数字 我按 Option 然后点击这个 digit + +1217 +01:01:17,004 --> 01:01:19,270 +It's not an optional anymore. +它不再是 optional 类型了 + +1218 +01:01:19,272 --> 01:01:22,507 +Digit turned to a String because I unwrapped the optional that +digit 变成了 String,因为我把 optional 解包了, + +1219 +01:01:22,509 --> 01:01:25,576 +came back from currentTitle, got the String out of there. +从 currentTitle 里得到了 String + +1220 +01:01:25,578 --> 01:01:28,612 +But what happens if this is nil? +但是如果这是个 nil 值会怎么样? + +1221 +01:01:28,614 --> 01:01:30,180 +What happened if this optional is nil? +如果 optional 是 nil 会怎样呢? + +1222 +01:01:30,182 --> 01:01:34,718 +In other words the button optional has never been set, crash, 'kay, +换句话说,就是这些 optional 类型的按钮没有 set 值会怎样?对的,程序会崩溃 + +1223 +01:01:34,720 --> 01:01:39,855 +crashes your program, so if you use exclamation point to unwrap an optional, +所以如果你使用 "!" 号来解包一个 optional 的时候 + +1224 +01:01:39,857 --> 01:01:45,660 +and that optional's current value is not set, nil, then it will crash your program. +并且这个 optional 的 currentTitle 没有设值,为 nil 的时候,你的程序会崩溃 + +1225 +01:01:46,930 --> 01:01:50,498 +Now a lot of you might be like whoa, I'm, my products are gonna be crashing all over +现在你们中的不少人肯定在想,我的程序将会整天 crash 掉, + +1226 +01:01:50,500 --> 01:01:55,903 +the place and, because there's a lot of optionals in iOS, I mean a lot, okay? +因为 iOS 有着非常多的 optional,非,常,多 + +1227 +01:01:55,905 --> 01:01:58,939 +Most things are probably optionals, because most things, it make sense, +大部分东西都是 optional 的,因为大部分东西都是有意义的 + +1228 +01:01:58,941 --> 01:02:00,840 +they can be in an not set state at some point. +某些时候它们会处于 “未设” 状态 + +1229 +01:02:02,177 --> 01:02:07,746 +And yeah, in this case though, maybe you want your program to crash, okay? +在这个情况下,说不定你就希望你的程序 crash?对不对? + +1230 +01:02:07,748 --> 01:02:11,850 +You might want your program to crash, because if you had a button, that never +你也许就是希望自己的程序 crash,因为如果你有一个按键, + +1231 +01:02:11,852 --> 01:02:15,920 +had its title set, and it's sending a pen digit to your controller, you probably +但是它的标题从未被 set,并且它传了一个数字给你的 controller,你也许 + +1232 +01:02:15,922 --> 01:02:20,358 +wanna have that crash, so you can find that bug, before you ship your program. +想在你的程序见客户之前,你就能找到 bug,所以你希望它 crash + +1233 +01:02:20,360 --> 01:02:23,360 +You see why sometimes fra, crashing is good? +现在你知道为什么有时候程序 crash 是个好事吧 + +1234 +01:02:23,362 --> 01:02:26,763 +Now if you don't wanna crash, there's a way to get around that as well. +现在如果你不想你的程序 crash ,这里有一个方法来解决 + +1235 +01:02:26,765 --> 01:02:28,164 +And I'll show you that a little bit later. +我等一下下展示给你们看, + +1236 +01:02:28,166 --> 01:02:32,802 +But for now understanding that that's what this exclamation point does. +但是现在,先弄明白这个感叹号是干什么的 + +1237 +01:02:32,804 --> 01:02:35,638 +It unwraps that optional and crashes if it's nil. +它解包了 optional,如果它是 nil 就 crash + +1238 +01:02:35,640 --> 01:02:38,040 +But if it's not nil, it gets to the String or +但如果不是 nil,它是得到 String 或者 + +1239 +01:02:38,042 --> 01:02:40,809 +whatever the optional type is out of there for you. +其他的 optional 解包后的类型? + +1240 +01:02:40,811 --> 01:02:44,579 +So now let's go ahead and run again and +所以让我们继续,重新运行一次, + +1241 +01:02:44,581 --> 01:02:51,318 +we're gonna see that digit equals is gonna say the number, 'kay? +我们将看看是不是能得到 “digit = ” 对应的数字? + +1242 +01:02:51,320 --> 01:02:56,556 +It's got the String off the currentTitle, no more optional in there, okay? +我们得到了 currentTitle 的 String,不再是 optional 的类型了 + +1243 +01:02:56,558 --> 01:02:59,492 +Good? +看上去不错 + +1244 +01:02:59,494 --> 01:03:03,362 +All right, so, now, what are we gonna do with that digit? +好的,现在,我们要用这些 digit 做什么呢? + +1245 +01:03:03,364 --> 01:03:06,715 +We got the digit, +我们已经能得到了数字 + +1246 +01:03:06,716 --> 01:03:10,067 +we want to append it onto the end of this display right here, okay. +我们希望按的数字能显示并附加在这里的末尾 + +1247 +01:03:10,070 --> 01:03:13,972 +And so let's just do that by saying display, dot. +所以让我们输入 display. + +1248 +01:03:13,974 --> 01:03:17,241 +Now, again, if we have the documentation,I'd go look in the documentation and +现在继续,如果我们查文档 + +1249 +01:03:17,243 --> 01:03:21,712 +it would say oh, there's a property on UILabel, which is what display is, +它会告诉我们,UILabel 有一个属性,这个属性告诉我们 display 是什么, + +1250 +01:03:21,714 --> 01:03:23,046 +display is a UILabel. +负责显示 UILabel 应该显示的什么 + +1251 +01:03:23,048 --> 01:03:25,982 +There's a property and it' called text. +这个属性叫做 text + +1252 +01:03:25,984 --> 01:03:28,518 +See it right there? +就在这里 + +1253 +01:03:28,519 --> 01:03:31,053 +And actually, you can even see right here, the type of that, it's an optional as +而且实际上,输入这个,你能在这里看到,这是一个 optional + +1254 +01:03:31,056 --> 01:03:36,225 +well, because this label's text might not have been set either, okay? +所以这个 label 的 text 应该还没有设值 + +1255 +01:03:36,227 --> 01:03:39,061 +So it has to be an optional String, okay? +所以这里是 optional String + +1256 +01:03:39,063 --> 01:03:43,297 +So I'm just gonna set that equal now, display that text as an optional, so +所以我现在要用等号设值,显示的 text 作为一个 optional + +1257 +01:03:43,299 --> 01:03:46,567 +what values can I send it to,set it to? +什么值可以设给它? + +1258 +01:03:46,569 --> 01:03:51,705 +I could set it to nil, that would be legal because it's an optional, +我可以设成 nil,因为它是一个 optional,所以它是完全合法的 + +1259 +01:03:51,707 --> 01:03:53,940 +see, no warnings, no errors. +看,没有警告也没有错误 + +1260 +01:03:53,942 --> 01:03:55,475 +That would clear out that display. +这将什么也不显示 + +1261 +01:03:55,477 --> 01:03:57,943 +It would not be set to anything, or +它不能设值成其他东西, + +1262 +01:03:57,945 --> 01:04:00,979 +I can set it to a String because it's an optional String. +我能给它设一个 String 值,因为它是一个 optional String + +1263 +01:04:00,981 --> 01:04:03,682 +So I'm going to set it to a String and the String I'm going to set it +所以我将把它设值一个 String + +1264 +01:04:03,684 --> 01:04:08,586 +to is display.text, what's currently in there, plus digit, okay? +这个 String 我设置成 display.text ,这里加个数字 + +1265 +01:04:08,588 --> 01:04:10,087 +So I'm going to append that digit on. +这样子就能附加数字上去了 + +1266 +01:04:10,089 --> 01:04:11,655 +Let's get rid of that. +让我们摆脱删掉这句 + +1267 +01:04:11,657 --> 01:04:14,124 +Okay, now, this has an error here. +好吧,现在又有一个错误 + +1268 +01:04:14,126 --> 01:04:15,025 +Why does this have an error? +这个错误是为什么呢?为什么这里有个错误呢? + +1269 +01:04:15,027 --> 01:04:17,093 +Anyone volunteer why this is an error? +有谁自愿回答这里为什么有个错误? + +1270 +01:04:17,095 --> 01:04:18,661 +See it's pointing right here. +发现错误指向这里 + +1271 +01:04:18,663 --> 01:04:21,897 +There's an error, back there. +这里有个错误,后面那位同学回答 + +1272 +01:04:21,899 --> 01:04:24,733 +The display.text is an optional String. +display.text 是一个 optional String + +1273 +01:04:24,735 --> 01:04:27,702 +Bingo. Because display.text right here is not +答对了,因为这里的 display.text 它不是个 String, + +1274 +01:04:27,704 --> 01:04:33,341 +a String, it's an optional, and you can't add a String to an optional. +你不能将一个 String 后附加一个 optional + +1275 +01:04:33,343 --> 01:04:35,476 +You can only add Strings to other Strings. +你只能将一个 String 附加在另外的 String 上 + +1276 +01:04:35,478 --> 01:04:39,813 +So we need to turn this into a String by unwrapping it. +所以我们通过解包 optioanl,将 optioanl 转变为 String + +1277 +01:04:39,815 --> 01:04:44,250 +And again, yes, this would crash if the display currently has nothing in it, +对的,这个东西会 crash,如果 display 没有值 + +1278 +01:04:44,252 --> 01:04:46,185 +it's not set, okay? +现在还没有设值 + +1279 +01:04:46,187 --> 01:04:48,887 +Are we cool with that? +大家都了解这个了吧? + +1280 +01:04:48,889 --> 01:04:49,821 +So let's run again. +再让我们运行一次 + +1281 +01:04:49,823 --> 01:04:52,857 +[BLANK_AUDIO] +[背景音] + +1282 +01:04:52,859 --> 01:04:54,058 +All right. +好的 + +1283 +01:04:54,060 --> 01:04:57,461 +So now 5, oh, it put the 5 on there. +所以现在点击 5,噢,5 显示在这里了 + +1284 +01:04:57,463 --> 01:04:58,762 +6, excellent. +点击 6,好极了 + +1285 +01:04:58,764 --> 01:05:00,497 +It's kinda working. +它能够工作了 + +1286 +01:05:00,499 --> 01:05:02,565 +I don't really like that 0 though. +这个 0 在这里我很不喜欢 + +1287 +01:05:02,567 --> 01:05:03,966 +That's kinda weak, 0, 5, 6. +这里就有点问题,5 和 6 前面有个 0 + +1288 +01:05:03,968 --> 01:05:06,669 +That should not, +这样子是不对的 + +1289 +01:05:06,670 --> 01:05:09,371 +that 0 should've gotten cleared out, right, when I first typed that 5. +这个 0 应该在我按下 5 的时候就清除掉 + +1290 +01:05:09,374 --> 01:05:12,808 +And that's because we really need some way in our controller to know whether we're in +这是因为我们确实需要一些方法让我们的 controller 知道我们是否在 + +1291 +01:05:12,810 --> 01:05:14,777 +the middle of typing a number right now. +已经输入了数字 + +1292 +01:05:14,778 --> 01:05:16,745 +Because if we're in the middle of typing a number, we want to append, but +因为如果我们在一个已经输入了数字,我们是希望数字加在后面, + +1293 +01:05:16,747 --> 01:05:18,079 +if we're not in the middle of typing a number, +但是如果我们还没开始输入数字, + +1294 +01:05:18,081 --> 01:05:21,182 +we want to start a new number, right? +我们想要开始输入的是一个新的数字(而不是在 0 后面附加新数字),对吧? + +1295 +01:05:21,184 --> 01:05:27,021 +So, let's do that, and I'm going to do that by adding a property, okay? +所以,让我们通过添加一个 property 来实现这个效果 + +1296 +01:05:27,023 --> 01:05:35,628 +var userIsInTheMiddleOfTypingANumber , which you might say, +“var userIsInTheMiddleOfTypingANumber”,你也许会说, + +1297 +01:05:35,630 --> 01:05:38,464 +oh my God, that terrible variable, now I have to type that over and over. +天哪,这么糟糕的变量名字,每次都得这么输入还不得累死? + +1298 +01:05:38,466 --> 01:05:40,900 +This is the last time I'll ever have to type that, okay? +其实下一次用到这个变量时我并不需要输入这么多的 + +1299 +01:05:40,902 --> 01:05:44,169 +Because Xcode is always going to escape complete it for me, okay? +因为下一次 Xcode 会帮我自动补齐的 + +1300 +01:05:44,171 --> 01:05:48,840 +So long names are perfectly fine, in terms of typing load anyway. +所以这么长的名字没有问题 + +1301 +01:05:48,842 --> 01:05:50,608 +So I like this name so I'm gonna keep it. +我就挺喜欢这个名字的,就这么用了. + +1302 +01:05:50,610 --> 01:05:53,077 +And it's a bool, okay. +这是一个布尔型数值 + +1303 +01:05:53,079 --> 01:05:54,845 +So I'm typing its, giving its type. +所以我输入它,给了它的这个类型 + +1304 +01:05:54,847 --> 01:06:01,618 +So here's var name type, and notice, look at this little error right here, 'kay. +这个是变量名的类型,注意看这里,有一个小的错误标记 + +1305 +01:06:01,620 --> 01:06:06,222 +Okay, sometimes you're gonna get errors in Swift that are completely incomprehensible +有时候你在 Swift 会遇到对你来说难以理解的错误 + +1306 +01:06:06,224 --> 01:06:08,724 +to you because you haven't learned enough of Swift. +这是因为你对 Swift 的了解还不够深入 + +1307 +01:06:08,726 --> 01:06:11,143 +This one's kind of like that. +这个错误就是因为这个 + +1308 +01:06:11,144 --> 01:06:13,561 +You see, it says, class viewController has no initializers. +你看,这里说,viewController 没有初始化方法 + +1309 +01:06:13,564 --> 01:06:19,667 +And that's because, and pay attention, in Swift all properties +请注意,这是因为,在 Swift 里, + +1310 +01:06:19,669 --> 01:06:24,271 +have to be initialized when the object is initialized. +当一个对象初始化了,那么这个对象的所有属性都必须要初始化 + +1311 +01:06:24,273 --> 01:06:29,142 +Okay, you can't have a property just sitting around not initialized, +所以你不能用没有初始化的属性, + +1312 +01:06:29,144 --> 01:06:30,977 +they have to have a value. +它们需要一个值, + +1313 +01:06:30,979 --> 01:06:32,862 +Now if they're an optional, +现在,它们是一个 optional, + +1314 +01:06:32,863 --> 01:06:34,746 +their value can be nil, but they have to have some value. +它们的值可以为 nil,但是它们必须有值 + +1315 +01:06:34,749 --> 01:06:37,750 +So we can't have this have no value. +所以我们不能在它们没有值前使用 + +1316 +01:06:37,752 --> 01:06:40,052 +Now there's two ways to give it a value. +有两种方法给它设值, + +1317 +01:06:40,054 --> 01:06:42,087 +One is, with an initializer. +一种就是用初始化方法, + +1318 +01:06:42,089 --> 01:06:45,156 +Unfortunately, I'm not gonna teach that to you until next week, so +但是不幸的是,这种方法要下周才会教你们, + +1319 +01:06:45,158 --> 01:06:46,557 +you can't do it that way. +你还不能用这种方法 + +1320 +01:06:46,559 --> 01:06:51,228 +Another way is just to say what it equals right here, okay? +所以另外一种方法就是对其直接赋值 + +1321 +01:06:51,230 --> 01:06:55,298 +And boom, gets rid of all our errors, obviously we don't start out in +一下子,所有错误都解决了 很明显我们 + +1322 +01:06:55,300 --> 01:06:59,402 +the middle of typing a number,so we're good to go here, all right. +不会一开始就有数字,所以这样就很好了 + +1323 +01:07:01,105 --> 01:07:04,373 +So now we have, we know whether the use is in the middle of typing a number. +现在我们就知道了什么时候输入了数字 + +1324 +01:07:04,375 --> 01:07:06,241 +We can go down here and say if the user, +我们能从这里继续深入,如果说用户 —— + +1325 +01:07:06,243 --> 01:07:12,246 +now again, I'm just gonna hit Tab to jump past this, maybe a couple times. +再一次,按一下 Tab 跳过这些,可能还要多按几次,找到这个 —— + +1326 +01:07:12,248 --> 01:07:14,648 +But if the user's in the middle of typing a number, +但是如果用户正在输入数字, + +1327 +01:07:14,650 --> 01:07:17,184 +then we'll do what we were doing before. +那就和刚才我们刚刚做的操作一样, + +1328 +01:07:17,186 --> 01:07:21,187 +Otherwise, we're just gonna set the display.text equal to the new digit we +不然的话,如果我们设置 “display.text = ” + +1329 +01:07:21,189 --> 01:07:24,557 +just typed, 'kay? +我们刚刚输入的新数字 + +1330 +01:07:24,558 --> 01:07:27,926 +And we're gonna say that the user is now in the middle of typing a number. +这就表示了用户现在正在输入数字 + +1331 +01:07:27,928 --> 01:07:30,062 +Question? +什么问题? + +1332 +01:07:30,063 --> 01:07:32,197 +Why would we have to do [INAUDIBLE] to display it? +[学生提问] + +1333 +01:07:32,199 --> 01:07:34,833 +Initialize? +[学生提问] + +1334 +01:07:34,835 --> 01:07:37,669 +Why did we not have to initialize this? +为什么我们没有初始化这个? + +1335 +01:07:37,671 --> 01:07:39,988 +That's a fantastic question and +这是个非常棒的的问题, + +1336 +01:07:39,989 --> 01:07:42,306 +I'm gonna talk about that on Wednesday cuz there's only one minute left. +我将在周三说这个问题,因为现在只剩下一分钟了 + +1337 +01:07:42,308 --> 01:07:44,908 +But that is a great question and it'll also, when I talk about it, +在我下次说到的时候,这依然是个很好的问题 + +1338 +01:07:44,910 --> 01:07:48,679 +I'm gonna tell you why this is an exclamation point and not a question mark. +我将会说一下为什么这里是个感叹号而不是个问号, + +1339 +01:07:48,681 --> 01:07:52,548 +Because I told you that optionals are made with question marks. +因为我之前说过 optional 都是由问号组成的, + +1340 +01:07:52,550 --> 01:07:55,318 +So why the heck is this optional? +但是为什么这个 optional 是这样的? + +1341 +01:07:55,319 --> 01:07:58,087 +Cuz that's what it is, an exclamation point, so we'll talk about that next time. +因为这是个感叹号,我们下节课再说这个问题, + +1342 +01:07:58,089 --> 01:08:01,056 +All right, so let's go ahead and run one last time here. +所以让我们下次课继续, + +1343 +01:08:01,058 --> 01:08:04,793 +And hopefully this is gonna, this 0 will be cleared out, it is and +我们之前希望这个 0 可以被清掉,看来没问题,看看这个, + +1344 +01:08:04,795 --> 01:08:07,696 +hopefully this will continue to append, it is. +希望这个也可以正常的附加数字,看来也没问题 + +1345 +01:08:07,698 --> 01:08:11,532 +So we're in a great spot right here, we've got a calculator, +我们今天已经有了一个不错的开始,我们已经有一个计算器了, + +1346 +01:08:11,534 --> 01:08:16,904 +we can enter numbers in it, next step is, we gotta make it do some calculating, and +我们已经能够输入数字了,下一步我们将让其能够计算, + +1347 +01:08:16,906 --> 01:08:19,406 +we're gonna do that next time so I will see you then. +我们下节课再来实现,大家下节课见 + +1348 +01:08:21,042 --> 01:08:24,910 +For more, please visit us at stanford.edu. +想浏览更多?请访问 stanford.edu diff --git a/subtitles/10. Table View.srt b/subtitles/10. Table View.srt new file mode 100644 index 0000000..7cd91c3 --- /dev/null +++ b/subtitles/10. Table View.srt @@ -0,0 +1,9448 @@ +1 +00:00:00,001 --> 00:00:07,706 +[SOUND] Stanford University. +斯坦福大学 + +2 +00:00:07,708 --> 00:00:08,706 +>> Okay. +OK + +3 +00:00:08,708 --> 00:00:11,108 +Welcome to Lecture 10 of Stanford CS193P. +欢迎来到 CS193P 2015 的冬季课程 + +4 +00:00:11,110 --> 00:00:12,609 +This is Winter 2015. +这是第十次课 + +5 +00:00:12,611 --> 00:00:17,447 +Today, we really only have one big topic. +今天我们会讨论一个很大的话题 + +6 +00:00:17,449 --> 00:00:18,848 +And I've got one little small topic +还会讨论几个 + +7 +00:00:18,850 --> 00:00:20,683 +that I'm gonna talk about. +比较小的话题 + +8 +00:00:20,685 --> 00:00:22,518 +At the beginning which is text field. +最开始讲的是 Text Field + +9 +00:00:22,520 --> 00:00:26,088 +But the main topic today is going to be table view, okay? +但是今天最主要的话题是 Table View + +10 +00:00:26,090 --> 00:00:29,624 +And so, table view is a really powerful object is iOS, and +在 iOS 中,Table View 是一个很强大的对象 + +11 +00:00:29,626 --> 00:00:31,526 +it uses a lot of the things you've learned already like +它使用了你们已经学到的,例如代理之类 + +12 +00:00:31,528 --> 00:00:33,361 +delegation. +的东西 + +13 +00:00:33,362 --> 00:00:35,195 +And you'll get a chance to see how, +你们有机会将会看到 + +14 +00:00:35,198 --> 00:00:37,231 +once you kind of have the basic concept, +一旦你掌握了基本的概念 + +15 +00:00:37,233 --> 00:00:39,933 +you can build this powerful user interface features. +就可以建造很强大 UI 特性 + +16 +00:00:39,935 --> 00:00:42,902 +But let's take a minute or two to talk about text field, +但是我们先花几分钟讨论一下 Text Field + +17 +00:00:42,904 --> 00:00:46,605 +because I actually used a text field in the last demo. +因为我在上一个 demo 里使用了它 + +18 +00:00:46,607 --> 00:00:49,808 +Okay. A text field, +OK,Text Field + +19 +00:00:49,809 --> 00:00:53,010 +it's kind of like UI label, but it's editable. +它有点像 Label, 但是它可以被编辑 + +20 +00:00:53,013 --> 00:00:57,148 +Text fields are not a big deal on the iPhone because +在 iPhone 上 Text Field 不是很重要 + +21 +00:00:57,150 --> 00:00:59,851 +you want to try and build your UIs to not use them, +因为在搭建 UI 的时候会尽力避免使用它们 + +22 +00:00:59,853 --> 00:01:02,953 +because that keyboard is so small on a phone. +在手机上,键盘太小了 + +23 +00:01:02,955 --> 00:01:07,891 +On an iPad, a little more useful to have TextField, +在 iPad 上,Text Field 会有一点用处 + +24 +00:01:07,893 --> 00:01:10,293 +but even there users would rather just be click, +但即使这样,用户还是喜欢通过点击 + +25 +00:01:10,295 --> 00:01:11,527 +touching on things and +触摸东西 + +26 +00:01:11,529 --> 00:01:14,397 +things without having to, you know, hit that keyboard. +而不是点击键盘 + +27 +00:01:14,399 --> 00:01:18,500 +And when you're building a UI and you pull, put a TextField, +当你在搭建 UI 的时候放入了一个 Text Field + +28 +00:01:18,502 --> 00:01:20,301 +it'll seem like oh, this is great. +看起来好像还不错 + +29 +00:01:20,303 --> 00:01:21,869 +That's because in the simulator you can use your +因为那是在模拟器中,你可以使用 + +30 +00:01:21,871 --> 00:01:23,037 +keyboard on your computer. +电脑上的键盘 + +31 +00:01:23,039 --> 00:01:25,673 +And it seems like, wow I really like this UI. +这会给你造成一种你很喜欢这种 UI 的假象 + +32 +00:01:25,675 --> 00:01:26,907 +But then when your users get it, +但是当用户使用的时候 + +33 +00:01:26,909 --> 00:01:29,175 +they're like, I hate this UI. +他们会不讨厌这个 UI 的 + +34 +00:01:29,177 --> 00:01:30,343 +Okay? +OK? + +35 +00:01:30,345 --> 00:01:31,877 +So, be careful with UITextField. +所以使用 Text Field 的时候慎重一点 + +36 +00:01:31,879 --> 00:01:33,579 +But there's sometimes when you just absolutely +但是也有时候你必须从用户那里 + +37 +00:01:33,581 --> 00:01:37,215 +need an arbitrary string from the user and so you need it. +接收一些字符,这时候,你就需要它了 + +38 +00:01:38,251 --> 00:01:40,301 +Now, the keyboard, +键盘 + +39 +00:01:40,302 --> 00:01:42,352 +that little software keyboard appears whenever your +当 Text Field 变成了 first responder(第一回应者) + +40 +00:01:42,355 --> 00:01:46,223 +text field becomes what's called the first responder. +键盘就会弹出 + +41 +00:01:46,225 --> 00:01:47,924 +When a text field becomes a first responder, +当 Text Field 变成 First Responder + +42 +00:01:47,926 --> 00:01:50,894 +the keyboard will slide up from the bottom. +键盘会从底部滑出 + +43 +00:01:50,896 --> 00:01:51,761 +Okay. +OK + +44 +00:01:51,763 --> 00:01:54,597 +You can make the keyboard appear, and +你可以通过 + +45 +00:01:54,599 --> 00:01:57,700 +cause the little blinking carrot to start by sending +发送 becomeFirstResponder 消息 + +46 +00:01:57,702 --> 00:01:59,267 +become first responder. +给 Text Field + +47 +00:01:59,269 --> 00:02:03,138 +That message, to a text field. +来让键盘显示出来 + +48 +00:02:03,140 --> 00:02:07,808 +Or if you wanted to make the keyboard go away, +如果你想让键盘消失 + +49 +00:02:09,412 --> 00:02:11,878 +you can do that by saying resign first responder. +你可以发送 resignFirstResponder 消息 + +50 +00:02:11,880 --> 00:02:13,046 +So it's that first responder thing. +这就是关于 first responder 的事情 + +51 +00:02:13,048 --> 00:02:15,415 +That's what decides whether they keyboard's up, and +它决定了键盘是否出现 + +52 +00:02:15,417 --> 00:02:17,049 +whether the blinking caret is there. +闪动的光标是否在那里 + +53 +00:02:17,051 --> 00:02:17,883 +Okay, very easy. +非常简单 + +54 +00:02:19,286 --> 00:02:21,653 +The text field, unlike UI label, +Text Field 不像 Label + +55 +00:02:21,655 --> 00:02:24,655 +does most of its communication with the UI via delegation. +Text Field 是通过 delegate 与 UI 交流的 + +56 +00:02:24,657 --> 00:02:26,657 +That's why I don't really +这就是为什么 + +57 +00:02:26,658 --> 00:02:28,658 +teach it to you until you've already learned delegation. +我在你们学习 delegate 之后才讲它 + +58 +00:02:30,229 --> 00:02:33,096 +One of the most important text field delegate methods is text +Text Field 最重要的一个 delegate 方法是 + +59 +00:02:33,098 --> 00:02:35,498 +field should return. +textFieldShouldReturn + +60 +00:02:35,499 --> 00:02:37,899 +And that happens when someone on the little keyboard presses +在用户点击键盘上的 return 键之后 + +61 +00:02:37,902 --> 00:02:39,869 +the Return key, +发生 + +62 +00:02:39,870 --> 00:02:41,837 +which sometimes says search, sometimes it says go. +那个键也有可能是 search 或 go + +63 +00:02:41,839 --> 00:02:43,105 +Sometimes it says return. +某时是 return + +64 +00:02:43,107 --> 00:02:46,274 +Just depends on what kind of keyboard you have configured. +只取决于你设置的是哪种类型的键盘 + +65 +00:02:46,276 --> 00:02:49,544 +And a lot of times in that should return, you are going +大部分情况下都是 return + +66 +00:02:49,546 --> 00:02:52,513 +to resign first responder, because the users hit Return, +你需要调用 resignFirstResponder 因为用户点击了 return + +67 +00:02:52,515 --> 00:02:54,281 +they want you to take the text they type in and +用户想让你获取他们输入的内容 + +68 +00:02:54,283 --> 00:02:55,182 +do something with it. +然后处理它们 + +69 +00:02:55,184 --> 00:02:56,816 +You can make the keyboard go away. +你可以让键盘隐藏 + +70 +00:02:59,253 --> 00:03:00,619 +This does return a Boole. +这个方法返回一个 Bool + +71 +00:03:00,621 --> 00:03:02,387 +Actually, I didn't really show that on the slide there, but +我没有在课件上展示 + +72 +00:03:02,389 --> 00:03:03,755 +it does return a boule. +但它确实返回一个 Bool + +73 +00:03:03,757 --> 00:03:05,957 +And that boule is whether it should do what it normally +当用户点击 return 的时候 + +74 +00:03:05,959 --> 00:03:07,858 +does when the user hits return, +这个 bool 就会做相应的事情 + +75 +00:03:07,860 --> 00:03:10,027 +which is usually going to be to do target action. +通常应该是 target action + +76 +00:03:10,029 --> 00:03:13,497 +Because UI text field is a UI control, so +因为 Text Field 是个 UI Control + +77 +00:03:13,499 --> 00:03:15,432 +it can also be set up to do target action. +所以它可以完成 target action + +78 +00:03:15,434 --> 00:03:17,333 +But usually, we get involved with the delegate because we +但通常,我们使用 delegate + +79 +00:03:17,335 --> 00:03:21,837 +want this resign first responder activity going on. +因为我们想让这个 resignFirstResponder 行为发生 + +80 +00:03:21,839 --> 00:03:24,806 +So you can find out that the editing has ended. +所以你可以发现编辑已经结束了 + +81 +00:03:24,808 --> 00:03:26,207 +Either by the person who didn't return, +即使用户没有 return + +82 +00:03:27,377 --> 00:03:31,712 +by the text field did end editing delegate method, or +通过 textfield 的 didEndEditing delegate 方法 + +83 +00:03:31,714 --> 00:03:35,382 +you can also just set up target action Ctrl+drag to +你也可以通过 Ctrl+Drag 设置 target action + +84 +00:03:35,384 --> 00:03:40,186 +have it in action when it ends. +当编辑结束时让它有所动作 + +85 +00:03:40,188 --> 00:03:42,788 +The keyboard, so the keyboard, +对于键盘来说 + +86 +00:03:42,790 --> 00:03:45,424 +you'd think that there would be a class like UIKeyboard or +你们可能认为会有 UIKeyboard 类 + +87 +00:03:45,426 --> 00:03:48,794 +something and to do things with, but really not. +或者之类的东西,但是其实是没有的 + +88 +00:03:48,796 --> 00:03:52,063 +The keyboard appears because as a side of effect of +键盘出现时因为一个叫做 UITextInputTraits + +89 +00:03:52,065 --> 00:03:57,201 +a protocol called the UI text input traits protocol so +协议的影响 + +90 +00:03:57,203 --> 00:03:59,903 +objects like UA text field that implement this, +UITextField 之类的对象需要实现它 + +91 +00:03:59,905 --> 00:04:01,538 +they get to configure the keyboard. +来设置键盘 + +92 +00:04:01,540 --> 00:04:02,572 +What type it is, +它的类型是什么 + +93 +00:04:02,574 --> 00:04:05,475 +what auto-capitalization it's doing. +是否自动大写 + +94 +00:04:05,477 --> 00:04:08,244 +You know, whether it's secure text we saw. +是否是安全输入 + +95 +00:04:08,246 --> 00:04:12,781 +We use secure text entry when we did the demo before. +在之前的 demo 我们使用了安全输入 + +96 +00:04:12,783 --> 00:04:16,684 +So all these actually are not methods that are on text field +所以这些基本不是我们 + +97 +00:04:16,686 --> 00:04:18,102 +natively. +在 text field 上使用的方法 + +98 +00:04:18,103 --> 00:04:19,519 +They're actually because text field is implementing this UI +这是因为 text field 实现了 + +99 +00:04:19,522 --> 00:04:20,688 +text input traits. +UITextInputTraits 协议 + +100 +00:04:20,690 --> 00:04:23,557 +And that's how you configure the keyboard. +它才让你设置键盘 + +101 +00:04:23,559 --> 00:04:24,875 +All right? +懂了吗? + +102 +00:04:24,876 --> 00:04:26,192 +And of course, text field implements that, and +当然 TextField 实现这些 + +103 +00:04:26,194 --> 00:04:29,796 +the other object it implements is UITextView, which is a very +其他实现的是 UITextView + +104 +00:04:29,798 --> 00:04:35,901 +powerful text editing object, multi-line, multi-font, etc. +它是一个非常强大的编辑对象,多行,多种字体等等 + +105 +00:04:35,903 --> 00:04:38,270 +The keyboard, when it comes up from the bottom, +从底部弹出的键盘 + +106 +00:04:38,272 --> 00:04:41,439 +it comes up on top of other views, okay? +出现在其他 view 之上 + +107 +00:04:41,441 --> 00:04:43,841 +So you are responsible, when that keyboard comes up, +当键盘弹出时,你需要负责任 + +108 +00:04:43,843 --> 00:04:46,644 +for moving anything out of the way that needs to still be +把仍然需要显示给用户的东西 + +109 +00:04:46,646 --> 00:04:47,411 +visible. +提上去 + +110 +00:04:47,413 --> 00:04:49,179 +Especially if, for +尤其是对于 + +111 +00:04:49,180 --> 00:04:50,946 +example, the text field the user clicked on that caused +用户在屏幕底部点击了一个 TextField + +112 +00:04:50,949 --> 00:04:53,283 +the keyboard to happen is at the bottom of the screen. +键盘从底部弹起 + +113 +00:04:53,285 --> 00:04:55,685 +It will just get covered right up, so now the user's like, +刚好把它盖住了,用户就会觉得 + +114 +00:04:55,687 --> 00:04:58,020 +whoa, where's that thing that I was typing in? +我刚才输入的地方跑哪去了? + +115 +00:04:58,022 --> 00:05:00,456 +So you're responsible for moving that. +所以你应该负责移动它 + +116 +00:05:00,458 --> 00:05:02,958 +A lot of times, you're gonna put your text fields at +大部分情况下,你需要把 TextField 放在顶部 + +117 +00:05:02,960 --> 00:05:05,293 +the top so that you don't have that problem. +所以你不需要应对这个问题 + +118 +00:05:05,295 --> 00:05:08,062 +Or your text field might be in a static table view. +或者把 TextField 放在静态的 TableView 中 + +119 +00:05:08,064 --> 00:05:10,898 +I'm gonna talk about table views today. +我们今天会讨论 TableView + +120 +00:05:10,900 --> 00:05:12,183 +In which case, +在这种情况下 + +121 +00:05:12,184 --> 00:05:13,467 +TableView will automatically scroll it up out of the way. +TableView 会自动滑上去 + +122 +00:05:13,469 --> 00:05:15,135 +You don't have to worry about it. +你不需要担心这个问题 + +123 +00:05:15,137 --> 00:05:16,336 +But, if you have a UI, +但是,如果你有这样一个 UI + +124 +00:05:16,338 --> 00:05:18,705 +where you have a text field down at the bottom, and +TextField 在底部 + +125 +00:05:18,707 --> 00:05:20,773 +the keyboard comes up, and you have to move it, +键盘弹出来,你需要移动 TextField + +126 +00:05:20,775 --> 00:05:23,842 +you're gonna have to learn how to do this NSNotification +你就需要学习一下 NSNotification + +127 +00:05:23,844 --> 00:05:24,609 +business. +的知识 + +128 +00:05:24,611 --> 00:05:26,378 +Because the way to find out that +你通过获取 UIKeyboardDidShowNotification + +129 +00:05:26,380 --> 00:05:28,980 +the keyboard appeared is you get this notification +通知,来得知 + +130 +00:05:28,982 --> 00:05:31,115 +called the UIKeyboardDidShowNotification. +键盘已经弹出 + +131 +00:05:31,117 --> 00:05:34,184 +So, not really gonna go into notifications today. +我们今天不会谈论 notification + +132 +00:05:34,186 --> 00:05:36,286 +You're not gonna have to do any of this for +你不需要在你的作业中使用这些 + +133 +00:05:36,288 --> 00:05:38,105 +any of your homework assignments but +所以你不需要担心 + +134 +00:05:38,106 --> 00:05:39,923 +when you get to your final project just know that this is +但是如果在最后的作业里,你需要处理键盘的问题 + +135 +00:05:39,925 --> 00:05:41,290 +how you're gonna have to deal with the keyboard. +你需要这里的知识 + +136 +00:05:41,292 --> 00:05:43,959 +If you have a text field or some text +如果有一个 TextField + +137 +00:05:43,961 --> 00:05:46,128 +typeable thing down towards the bottom of the screen. +在屏幕底部之类的 + +138 +00:05:47,264 --> 00:05:47,829 +Okay? +OK? + +139 +00:05:48,998 --> 00:05:52,133 +Other properties on text field I'm not gonna go into but +我不会介绍 TextField 中的其他属性 + +140 +00:05:52,135 --> 00:05:54,168 +we'll see a couple of them in the demo today cuz I'm gonna +但是我们会在 demo 中见到 + +141 +00:05:54,170 --> 00:05:55,669 +do text field again. +我们会再做一次 TextField + +142 +00:05:55,671 --> 00:05:58,438 +But you can look them up in the documentation. +但是你可以在文档中查看它们 + +143 +00:05:58,440 --> 00:05:59,939 +Obviously just things to configure the way +都是些很明显的属性 + +144 +00:05:59,941 --> 00:06:02,341 +the text field inputs or displays. +配置 TextField 输入或显示 + +145 +00:06:03,778 --> 00:06:06,578 +Text fields also have left and right overlays for +TextField 也有左右的小图标 + +146 +00:06:06,580 --> 00:06:08,146 +little things like search. +为了例如做搜索一样的工作 + +147 +00:06:08,148 --> 00:06:10,648 +You've probably seen text fields that have a little icon +你可能也已经看过有小图标的 TextField + +148 +00:06:10,650 --> 00:06:13,117 +for search that you can click on there. +你可以点击它进行搜索 + +149 +00:06:13,119 --> 00:06:15,185 +Or like a little icon that says whether you're doing find +或者做一些查找替换 + +150 +00:06:15,187 --> 00:06:17,688 +or find and replace or something like that. +之类的工作 + +151 +00:06:17,690 --> 00:06:19,155 +That's all in there too. +它们都在这里 + +152 +00:06:19,157 --> 00:06:20,223 +So it's pretty powerful. +所以 TextField 很强大 + +153 +00:06:20,225 --> 00:06:23,959 +The little control. +这个小控件 + +154 +00:06:23,961 --> 00:06:28,897 +The keyboard, it gets enhanced by this InputAccessoryView. +键盘,可以通过 InputAccessoryView 得到加强 + +155 +00:06:28,899 --> 00:06:32,200 +So that's, again, a method in the UITextfield. +它是 UITextField 中的一个方法 + +156 +00:06:32,202 --> 00:06:34,168 +And you set a view, the UIView. +你设置这个 view,UIView 类型 + +157 +00:06:34,170 --> 00:06:36,003 +And when the keyboard comes up, +当键盘弹出的时候 + +158 +00:06:36,005 --> 00:06:38,739 +that UIview will appear along the top of the keyboard. +这个 view 会出现在键盘的顶部 + +159 +00:06:38,741 --> 00:06:41,041 +So you can add extra buttons there or +所以你可以在上面添加按钮 + +160 +00:06:41,043 --> 00:06:42,542 +any kind of mechanism. +或者其他东西 + +161 +00:06:42,544 --> 00:06:43,843 +So that's how you enhance the keyboard. +这就是你增强键盘的方式 + +162 +00:06:45,446 --> 00:06:47,246 +All right, so that's enough text field. +这对于 TextField 来说足够了 + +163 +00:06:47,248 --> 00:06:48,814 +Again, I'm going to be using the demo today, so +我一会儿会做一个 demo + +164 +00:06:48,816 --> 00:06:50,215 +you'll see a little bit more. +所以你可以看到更多 + +165 +00:06:50,217 --> 00:06:53,084 +But today mostly we're going to talk about UITableView. +但是今天的重点是 UITableView + +166 +00:06:53,086 --> 00:06:56,020 +So, UITableView is very important class for +UITableView 是为了展示数据的 + +167 +00:06:56,022 --> 00:06:57,338 +displaying data. +一个非常重要的类 + +168 +00:06:57,339 --> 00:06:58,655 +Especially when you have a large amount of data +尤其是有大量的数据 + +169 +00:06:58,657 --> 00:06:59,756 +to display. +需要显示 + +170 +00:06:59,758 --> 00:07:02,425 +It's essentially a one dimensional table. +它本质上是一个一维的表格 + +171 +00:07:02,427 --> 00:07:05,395 +A list if you want to think of it that way, some people think +你也可以把它想象成一个列表 + +172 +00:07:05,397 --> 00:07:06,796 +it maybe should have been called List View, +一些人认为它应该被叫做 ListView + +173 +00:07:06,798 --> 00:07:09,531 +but you'll see that Table View ends up being +但是你会发现,TableView + +174 +00:07:09,533 --> 00:07:10,499 +a pretty good name for it. +是一个很适合它的名字 + +175 +00:07:10,501 --> 00:07:11,666 +But it's a one dimensional list, +但是它是一个一维的列表 + +176 +00:07:11,668 --> 00:07:13,401 +it's a subclass of UIScrollView, so +它是 UIScrollView 的子类 + +177 +00:07:13,403 --> 00:07:16,837 +it has all the things that scrolling can do of course. +所以它拥有所有 ScrollView 的功能 + +178 +00:07:16,839 --> 00:07:19,406 +And it's very efficient with large sets of data. +它在拥有大量数据的时候非常有效率 + +179 +00:07:19,408 --> 00:07:22,409 +So you can imagine having a list of all the songs in +所以你可以想象,在你手机的 iPod 中 + +180 +00:07:22,411 --> 00:07:26,312 +the iPod part of your phone showing in an app, +有许多歌曲 + +181 +00:07:26,314 --> 00:07:28,981 +even if you have tens of thousands of them, okay? +即使有上千首歌曲 + +182 +00:07:28,983 --> 00:07:31,584 +TableView knows how to be efficient with that. +TableView 只要如何有效率地处理它们 + +183 +00:07:32,653 --> 00:07:34,419 +Now, what about multi-dimensional tables, +那么多维的 Table 呢? + +184 +00:07:34,421 --> 00:07:36,021 +tables that have rows and columns? +有行和列的表格 + +185 +00:07:36,023 --> 00:07:39,023 +Well we usually do that with multiple table views inside +我们通常把多个 TableView 嵌入 + +186 +00:07:39,025 --> 00:07:41,325 +a navigation controller. +NavigationController 中 + +187 +00:07:41,327 --> 00:07:43,894 +So you'll pick something from column one and it's going +你从第一列中选择了一个东西 + +188 +00:07:43,896 --> 00:07:46,063 +to show you column two that matches column one and +它展示给你了第二列,关联第一列的东西 + +189 +00:07:46,065 --> 00:07:48,498 +you pick something there, and it's going push over, +你在其中选择的一个 + +190 +00:07:48,500 --> 00:07:49,532 +show you the next one. +它展现给你下一列 + +191 +00:07:49,534 --> 00:07:51,934 +So that's basically how you get through, +这就是你实现的方式 + +192 +00:07:51,936 --> 00:07:54,603 +how you build multi-dimension tables which. +如何在电话,这个如此小的设备上 + +193 +00:07:54,605 --> 00:07:57,139 +Kind of have to do it that way on a small device like +搭建多维表格 + +194 +00:07:57,141 --> 00:07:59,674 +a phone, unless the fonts going to be really tiny +除非字体变得非常小 + +195 +00:07:59,676 --> 00:08:03,578 +because you can't build a big actual two-dimensional table. +因为你无法建立真正的二维表格 + +196 +00:08:03,580 --> 00:08:05,346 +So, the combination of table view and +所以把 TableView 和 UINavigationController + +197 +00:08:05,348 --> 00:08:07,247 +UINavigation Controller is pretty cool for +结合在一起搭建多维表格 + +198 +00:08:07,249 --> 00:08:10,050 +building multi-dimensional tables. +是非常酷的方式 + +199 +00:08:10,052 --> 00:08:12,452 +Now, there's different kinds of table views and +这里有不同种类的 TableView + +200 +00:08:12,454 --> 00:08:14,220 +I'm going to show you pictures of them. +我给你们展示一下它们的图片 + +201 +00:08:14,222 --> 00:08:18,724 +You want to configure the table view to display in a way +你希望让 TableView 通过一种匹配你数据的方式 + +202 +00:08:18,726 --> 00:08:20,359 +that matches your data. +来展示数据 + +203 +00:08:20,361 --> 00:08:23,961 +So let's take a look at some of these different +所以我们一起来看看 + +204 +00:08:23,963 --> 00:08:25,196 +kind of looks. +这几种不同的显示方式 + +205 +00:08:25,198 --> 00:08:27,865 +One is a plain style. +第一种是 Plain Style + +206 +00:08:27,867 --> 00:08:29,633 +You can see that one on the left. +左边的就是 + +207 +00:08:29,635 --> 00:08:31,001 +And the other one is a group style. +另一种是 Group Style + +208 +00:08:31,003 --> 00:08:33,703 +Now a group style you can actually see that the little +Group Style 可以把一列的信息管理起来 + +209 +00:08:33,705 --> 00:08:36,739 +rows are kind of grouped so like in miles, +比如 kilometers 和 miles + +210 +00:08:36,741 --> 00:08:39,375 +in kilometers is grouped into the distance as a group. +被放进了 DISTANCE 组里面 + +211 +00:08:39,377 --> 00:08:42,277 +And then driving and walking is grouped into the preferred +Driving 和 Walking 被放进了 + +212 +00:08:42,279 --> 00:08:44,379 +directions group there. +PREFERRED DIRECTIONS 组里面 + +213 +00:08:44,381 --> 00:08:47,949 +Whereas the plain style is just a big long list. +但是 Plain Style 只是一个长长的列表 + +214 +00:08:47,951 --> 00:08:50,518 +That can be divided into sections as well, but +它们可以被分进不同的 section 中 + +215 +00:08:50,520 --> 00:08:52,286 +it's mostly just a big long list. +但是它仅仅是一个长长的列表 + +216 +00:08:52,288 --> 00:08:54,721 +Usually the plain style is for +通常 Plain Style 用于动态的数据 + +217 +00:08:54,723 --> 00:08:58,425 +dynamic data, like all the songs coming out of your iPod. +例如显示你 iPod 中的所有歌曲 + +218 +00:08:58,427 --> 00:09:00,927 +The group style is more for fixed data like +Group Style 用于固定的数据 + +219 +00:09:00,929 --> 00:09:03,896 +the settings app, you know, in your iPhone the setting app. +就像 iPhone 中的设置应用 + +220 +00:09:03,898 --> 00:09:05,598 +If you look in there, +如果你打开它看一看 + +221 +00:09:05,599 --> 00:09:07,299 +a lot of table views in there, all with the group style, +其中有许多 TableView 都是 Group Style + +222 +00:09:07,301 --> 00:09:09,434 +and what's in there is kind of fixed, more static. +其中的都是固定的静态数据 + +223 +00:09:11,871 --> 00:09:14,905 +So let me talk about some of the words we used to describe +现在我们来看看 TableView 中的 + +224 +00:09:17,410 --> 00:09:18,459 +the parts of a table view. +一些相关词汇 + +225 +00:09:18,460 --> 00:09:19,509 +This part at the top of the table view is called the table +Table View 上面这个部分叫做 + +226 +00:09:19,511 --> 00:09:21,745 +header, it's a UIView. +Table Header,它是个 UIView + +227 +00:09:21,747 --> 00:09:23,780 +I'm going to put along the bottom here, +我放在底部的这些是 + +228 +00:09:23,782 --> 00:09:25,681 +is just going to be the code. +一些代码 + +229 +00:09:25,683 --> 00:09:27,282 +Like the name of the property or +类似于与之相关的属性 + +230 +00:09:27,284 --> 00:09:29,151 +the function that accesses this thing. +或者方法名 + +231 +00:09:29,153 --> 00:09:31,319 +But you obviously don't know any of that yet. +但是显然你们还不知道这些 + +232 +00:09:31,321 --> 00:09:32,771 +So this is morely for +这些是为了你们以后翻课件的时候 + +233 +00:09:32,772 --> 00:09:34,222 +reference when you're looking back at the slides later. +方便查找而放置的 + +234 +00:09:35,425 --> 00:09:36,757 +So there's the table header, +这是 Table Header + +235 +00:09:36,759 --> 00:09:39,926 +it's at the top of the entire table, it's a UIView. +它在整个 Table 的上部,是一个 UIView + +236 +00:09:39,928 --> 00:09:41,861 +You can put things in there like a text field if +如果你想给 Table 添加搜索功能 + +237 +00:09:41,863 --> 00:09:44,230 +you wanted to add searching to your table, things like that, +你可以把 TextField 放到这里 + +238 +00:09:44,232 --> 00:09:45,865 +we'll do that in the demo. +我们将在 demo 里这么做 + +239 +00:09:45,867 --> 00:09:48,934 +There's also a corresponding table footer, at the bottom, +也有与之相关的 Table Footer,在底部 + +240 +00:09:48,936 --> 00:09:50,936 +that's also UIView. +也是 UIView + +241 +00:09:50,938 --> 00:09:52,237 +It's at the very bottom of the table. +在 Table 的最底部 + +242 +00:09:52,239 --> 00:09:54,939 +If you had 10,000 iPod items it'd be way down at +如果 iPod 里有 一万首歌 + +243 +00:09:54,941 --> 00:09:56,174 +the very bottom, +它会在非常非常底部 + +244 +00:09:56,175 --> 00:09:57,408 +you'd have to scroll all the way to 10,000 to get to that. +你必须划过这个一万首歌才能看到它 + +245 +00:09:58,444 --> 00:10:01,078 +Then, all the information is divided into up into +所有的信息可以被分入 + +246 +00:10:01,080 --> 00:10:02,879 +sections, okay. +不同的 section + +247 +00:10:02,881 --> 00:10:05,415 +So you can have any number of sections in the table view. +你可以在 Table View 中拥有任意数量的 section + +248 +00:10:05,417 --> 00:10:07,350 +And each section has a header, +每个 section 都有一个 header + +249 +00:10:07,352 --> 00:10:10,119 +a section header like that, okay. +它是这个样子的 + +250 +00:10:10,121 --> 00:10:12,721 +And of course, each section also has a section footer. +当然,每个 section 都有一个 footer + +251 +00:10:14,224 --> 00:10:16,141 +The section footer and +Footer 和 header + +252 +00:10:16,142 --> 00:10:18,059 +the section header are usually just strings but there's also +通常都是字符串,但是也有一种方式 + +253 +00:10:18,061 --> 00:10:20,661 +a way to make them be UIViews as well, if you really wanted +能把它们变成 UIView + +254 +00:10:20,663 --> 00:10:22,896 +complicated headers and footers. +如果你想要复杂的 header 和 footer + +255 +00:10:23,865 --> 00:10:25,898 +And then you have what are called the table cells, +Table View 中有 Table View Cell + +256 +00:10:25,900 --> 00:10:28,217 +so that's the actual data. +那是真是数据的地方 + +257 +00:10:28,218 --> 00:10:30,535 +This would be the actual songs in your iPod would be shown +在每一行里展示的,都是你 iPod 中 + +258 +00:10:30,538 --> 00:10:32,338 +here in each row. +真实的歌曲 + +259 +00:10:32,340 --> 00:10:34,439 +And these table cells are highly configurable to show +这个 cell 为了在 table 中 + +260 +00:10:34,441 --> 00:10:36,508 +all kinds of information for +展示各种数据 + +261 +00:10:36,510 --> 00:10:39,744 +each piece of data in your table. +都是高度可定制的 + +262 +00:10:39,746 --> 00:10:43,214 +Okay, so that's basically the terminology we use. +这些就是我们使用的基本术语 + +263 +00:10:43,216 --> 00:10:45,649 +So that's what it all looks like in plain style. +Plain Style 是这个样子的 + +264 +00:10:45,651 --> 00:10:48,585 +We use the exact same terminology in group style, so +我们在 Group Style 也使用相同的术语 + +265 +00:10:48,587 --> 00:10:50,620 +it looks like this, okay. +它看起来是这样的 + +266 +00:10:50,622 --> 00:10:52,655 +See the section headers are kind of the names of +每个部分的标题,是每个 group 的 + +267 +00:10:52,657 --> 00:10:55,408 +the groups. +名字 + +268 +00:10:55,409 --> 00:10:58,160 +All right, here's what a table looks like, +Table View 长这个样子 + +269 +00:10:58,162 --> 00:10:59,461 +I hope that shows up. +我希望你们都看到了 + +270 +00:10:59,463 --> 00:11:00,995 +It look a little washed out, +右边的版本是 + +271 +00:11:00,997 --> 00:11:04,932 +but the version on the right there has sections. +section + +272 +00:11:04,934 --> 00:11:06,767 +You can see, like above the word Tokyo, +在 Tokyo 上面 + +273 +00:11:06,769 --> 00:11:08,568 +there's a little word there, says Japan. +有一个叫 Japan 的小单词 + +274 +00:11:08,570 --> 00:11:15,608 +And above Amsterdam, there's a little Netherlands there. +在 Amsterdam 上面有 Netherlands + +275 +00:11:15,610 --> 00:11:17,309 +Those are the section headers. +这些是 section 的标题 + +276 +00:11:17,311 --> 00:11:19,128 +Those are the names of the sections. +是 section 的名字 + +277 +00:11:19,129 --> 00:11:20,946 +And the one on the left has no section title, so +左边的没有标题 + +278 +00:11:20,948 --> 00:11:25,350 +all the things are all just listed not grouped, okay. +所有的东西仅仅被罗列出来而没有进行分组 + +279 +00:11:25,352 --> 00:11:30,354 +Now each cell can have one of five different types, okay. +每一个 cell 可以有五种不同的类型 + +280 +00:11:30,356 --> 00:11:31,922 +Here's four of them right here. +这里是其中四种 + +281 +00:11:31,924 --> 00:11:33,523 +So you got the Subtitle type, +有 Subtitle 类型 + +282 +00:11:33,525 --> 00:11:36,459 +which just has some big texts and little text underneath it. +上面有一大一小两行文字 + +283 +00:11:36,461 --> 00:11:39,996 +You got Basic, which has no little text underneath it. +Basic 类型,只有一行大文字 + +284 +00:11:39,998 --> 00:11:41,931 +You've got the Right Detail and the Left Detail, +还有 Right Detail 和 Left Detail + +285 +00:11:41,933 --> 00:11:43,999 +which is the big text and the little text, +也是有一大一小两部分文字 + +286 +00:11:44,001 --> 00:11:46,702 +just kind of arranged a little differently, okay. +只是被安排了在不同的位置 + +287 +00:11:46,704 --> 00:11:50,171 +So the type of cell that you choose determines how +你选择的 cell 类型决定了 + +288 +00:11:50,173 --> 00:11:53,274 +the big text and the little text are going to appear. +大小文字是怎样显示的 + +289 +00:11:53,276 --> 00:11:56,344 +There's a fifth kind of cell type, though, which is custom. +第五种类型是 custom + +290 +00:11:56,346 --> 00:11:59,613 +Which allows you to build whatever you want by dragging +你可以通过拖拽 + +291 +00:11:59,615 --> 00:12:02,783 +in UI labels and UI text fields and image views, +各种 UI 组件 + +292 +00:12:02,785 --> 00:12:04,951 +whatever you want to do to build your own custom cell. +决定 cell 的样子 + +293 +00:12:04,953 --> 00:12:07,020 +And that's what we're going to do in the demo today. +我们的 demo 就会这么做 + +294 +00:12:07,989 --> 00:12:09,388 +Okay, so that's the cell type. +这就是 cell 的类型 + +295 +00:12:11,025 --> 00:12:12,791 +All right, so how does this whole table view +怎样才能让 TableView + +296 +00:12:12,793 --> 00:12:13,624 +business work? +工作呢? + +297 +00:12:15,294 --> 00:12:19,363 +There is a class in iOS called UITableViewController, +在 iOS 中有一个类叫做 UITableViewController + +298 +00:12:19,365 --> 00:12:21,698 +it's a subclass of UIViewController. +它是 UIViewController 的子类 + +299 +00:12:21,700 --> 00:12:24,667 +And it is kind of a prepackaged way to +如果在你的 UI 中可以 + +300 +00:12:24,669 --> 00:12:27,169 +use table view that I highly recommend you use if it's at +使用它的情况下 + +301 +00:12:27,171 --> 00:12:28,437 +all possible in your UI. +我强烈建议你使用 + +302 +00:12:28,439 --> 00:12:31,306 +The only real limitation of UITableViewController is that +它唯一的短板就是 + +303 +00:12:31,308 --> 00:12:36,711 +the entire view of the MVC, has to be a tableView. +MVC 的全部 view 都必须得是 tableview + +304 +00:12:36,713 --> 00:12:38,813 +So if you had some view where you had a tableView and +如果你的 view 中除了 tableview + +305 +00:12:38,815 --> 00:12:41,448 +then some other stuff around it, you would not +还有其他 UI 组件 + +306 +00:12:41,450 --> 00:12:44,051 +be using UITableViewController for that. +你就不能使用 UITableViewController + +307 +00:12:44,053 --> 00:12:47,354 +You'd build your own viewController, and you'd just +你得搭建自己的 ViewController + +308 +00:12:47,356 --> 00:12:50,523 +drag in a UITableView, which is just a UIView, okay. +拽进一个 UITableView,它的类型是 UIView + +309 +00:12:51,892 --> 00:12:55,093 +You can add a UITableViewController to your +你可以直接拽进来一个 + +310 +00:12:55,095 --> 00:12:58,363 +app just by dragging it out of the object palette there. +UITableViewController 加入到你的 app 中 + +311 +00:12:58,365 --> 00:13:00,598 +You can see a TableViewController and +这个 TableViewController + +312 +00:13:00,600 --> 00:13:03,901 +it'll pull the whole MVC out, okay, a UITable, MVC. +它会是一整个 MVC + +313 +00:13:03,903 --> 00:13:07,671 +So, here's UITable MVC that I've dragged out. +这就是一整个 MVC + +314 +00:13:07,673 --> 00:13:10,907 +It's controller is usually a subclass of +它的 controller 通常是 UITableViewController 的子类 + +315 +00:13:10,909 --> 00:13:16,512 +UITableViewController, and its view is the tableView, okay. +它的 view 是 tableview + +316 +00:13:16,514 --> 00:13:18,447 +Ultra simple little MVC here. +非常简单的 MVC + +317 +00:13:20,718 --> 00:13:23,418 +But like any UIView controller you're probably going to want +与其他 UIViewController 类似 + +318 +00:13:23,420 --> 00:13:27,922 +to set the class of the controller to be some subclass +你需要把 controller 设置为 + +319 +00:13:27,924 --> 00:13:30,291 +of UITableViewController. +UITableViewController 的子类 + +320 +00:13:30,293 --> 00:13:33,360 +So when you do new file to create your subclass make sure +当你创建子类的时候 + +321 +00:13:33,362 --> 00:13:37,564 +that you pick subclass of UITableViewController, +确定你选择了 UITableViewController 的子类 + +322 +00:13:37,566 --> 00:13:39,532 +if that's the kind of view controller you're making +如果你使用的是 UITableViewController + +323 +00:13:39,534 --> 00:13:41,334 +there, okay. +OK + +324 +00:13:41,336 --> 00:13:43,002 +And then once you do it, +一旦你这样做了 + +325 +00:13:43,004 --> 00:13:45,003 +same thing as any other view controller, +跟其他的 viewcontroller 一样 + +326 +00:13:45,005 --> 00:13:49,540 +you set the class in the identity inspector, okay. +需要在 Identity Inspector 设置类 + +327 +00:13:49,542 --> 00:13:50,274 +Everyone cool with that? +都懂吧? + +328 +00:13:51,410 --> 00:13:55,445 +Now, the way that we're going to kind of connect +我们使用代码关联 + +329 +00:13:55,447 --> 00:13:58,014 +our code to the UITableView +UITableView 的方式 + +330 +00:13:58,016 --> 00:14:00,850 +is via two delegates that the UITableView has. +是通过两个代理 + +331 +00:14:00,852 --> 00:14:03,719 +One's called delegate and one's called data source. +其中一个是 data source + +332 +00:14:03,721 --> 00:14:06,488 +Okay, and I'm going to talk all about those later in this +之后 + +333 +00:14:06,490 --> 00:14:07,555 +presentation. +我会详细介绍 + +334 +00:14:07,557 --> 00:14:09,157 +But just know that when you drag out one of +你需要知道,当你拽出一个 + +335 +00:14:09,159 --> 00:14:10,858 +these UITableViewController's, +UITableViewController 的时候 + +336 +00:14:10,860 --> 00:14:14,528 +it's going to automatically wire up the controller itself, +它会自动帮你把 tableview 的 delegate 和 + +337 +00:14:14,530 --> 00:14:17,264 +as both the delegate and the dataSource. +dataSource 连接起来 + +338 +00:14:17,266 --> 00:14:19,133 +And in fact, +实际上 + +339 +00:14:19,134 --> 00:14:21,001 +if you right clicked on the TableViewController there and +当你右键单击 TableViewController 的时候 + +340 +00:14:21,003 --> 00:14:22,101 +you looked at it's connections, +看其中的连接 + +341 +00:14:22,103 --> 00:14:24,637 +you'll see dataSource and +你会看到 + +342 +00:14:24,638 --> 00:14:27,172 +delegate will be connected there to the TableView, okay. +data source 和 delegate 已经连接到 TableView 上了 + +343 +00:14:27,175 --> 00:14:29,508 +Now, if you don't use a UITableViewController, +如果你不使用 UITableViewController + +344 +00:14:29,510 --> 00:14:30,676 +you just use your own ViewController and +你使用自己的 ViewController + +345 +00:14:30,678 --> 00:14:32,110 +you drag out a UITableView, +你拽进来一个 UITableView + +346 +00:14:32,112 --> 00:14:33,711 +you will have to wire up the dataSource and +你需要手动连接 dataSource + +347 +00:14:33,713 --> 00:14:35,346 +delegate yourself. +还有 delegate + +348 +00:14:35,348 --> 00:14:37,147 +Again, usually to your controller, but +通常来说连接的是你的 controller + +349 +00:14:37,149 --> 00:14:40,450 +you could wire up something else but 99% of the time you +但是你也可以连接其他东西 + +350 +00:14:40,452 --> 00:14:42,952 +make your controller be the delegate in dataSource for +但是 99% 的情况下,让你的 controller 成为 UI 中 view 的 delegate 和 dataSource + +351 +00:14:42,954 --> 00:14:45,254 +things in the view, just like you did in your calculator. +就像你在 Calculator 中做的一样 + +352 +00:14:46,891 --> 00:14:50,826 +Okay, so you can also edit the attributes of the table view +你也可以编辑 tableview 的属性 + +353 +00:14:50,828 --> 00:14:52,928 +if you just click on the table view, now, +如果你点击 tableview + +354 +00:14:52,930 --> 00:14:56,931 +when you're clicking on things in a table view sometimes you +当你点击的时候,有时你想点击 cell + +355 +00:14:56,933 --> 00:15:00,068 +want the cell, sometimes you want the table view, +有时想点击 table view + +356 +00:15:00,070 --> 00:15:01,669 +sometimes you want the controller. +又是你想点 controller + +357 +00:15:01,671 --> 00:15:04,638 +So you want to remember that trick I was telling you about, +所以你需要记住我之前告诉你的小技巧 + +358 +00:15:04,640 --> 00:15:07,541 +Ctrl + shift and left-click will let you pick something +Ctrl + shift 然后左键单击,可以让你选择某个东西 + +359 +00:15:07,543 --> 00:15:10,310 +under the mouse, multi-layers deep, okay. +在其他层 UI 元素也可以选择 + +360 +00:15:10,312 --> 00:15:11,844 +I'll show you again in the demo. +在 demo 中我会再次展示 + +361 +00:15:13,448 --> 00:15:15,180 +But you want to remember that trick when you're working +当你在使用 table view 的时候 + +362 +00:15:15,182 --> 00:15:16,799 +with table views. +你需要记住这个技巧 + +363 +00:15:16,800 --> 00:15:18,417 +So, if you click on the table view, not the cells, +如果你点击 tableview, 而不是 cell + +364 +00:15:18,419 --> 00:15:20,169 +not the controller, but +和 controller + +365 +00:15:20,170 --> 00:15:21,920 +the actual table view, then you can obviously inspect it. +你就可以检查它的属性 + +366 +00:15:21,922 --> 00:15:23,421 +And so, you can look in there and +你可以看到 + +367 +00:15:23,423 --> 00:15:25,956 +see all the various things that you can inspect +对于 table view 来说 + +368 +00:15:25,958 --> 00:15:28,158 +about the table view. +各种不同的属性 + +369 +00:15:28,160 --> 00:15:29,826 +One thing that's important to set about the table view +其中之一需要设置的是 tableview 的类型 + +370 +00:15:29,828 --> 00:15:31,828 +is whether it's plain or grouped. +是 plain 还是 grouped + +371 +00:15:31,830 --> 00:15:34,230 +Okay, so this one that you're seeing is plain. +现在你们看到的是 plain + +372 +00:15:34,232 --> 00:15:36,032 +Here I'm going to switch it over to be grouped. +在这里我把它变成 grouped + +373 +00:15:36,034 --> 00:15:37,367 +Now it's grouped, +现在它变了 + +374 +00:15:37,368 --> 00:15:38,701 +you can see in the storyboard it will look grouped, +在 storyboard 中,它看起来就是 grouped + +375 +00:15:38,703 --> 00:15:40,068 +all right. +好的 + +376 +00:15:40,070 --> 00:15:43,071 +Another really important thing you can set about the table +另一个重要的东西可以设置的是 + +377 +00:15:43,073 --> 00:15:48,242 +view is whether the cells in it are static, or dynamic. +它 cell 的类型是 static 还是 dynamic 的 + +378 +00:15:48,244 --> 00:15:49,343 +So let's talk about static first. +我们先来探讨一下 static + +379 +00:15:49,345 --> 00:15:51,044 +So here I'm going to switch to static. +现在我把它变成 static + +380 +00:15:51,046 --> 00:15:55,114 +Static means that these cells in here are determined in +static 表示,这些 cell 的显示是在 + +381 +00:15:55,116 --> 00:15:56,449 +the story board. +stroybard 中设置的 + +382 +00:15:56,451 --> 00:15:58,517 +So you can drag in buttons, and labels, +所以你可以拽进来 buttons, labels + +383 +00:15:58,519 --> 00:15:59,985 +whatever you want in there. +你需要的任何 + +384 +00:15:59,987 --> 00:16:03,388 +Just like, almost like it's just an open area view. +就像是一个开放区域的 view + +385 +00:16:03,390 --> 00:16:04,555 +You can just drag them in there, +你可以拖拽 + +386 +00:16:04,557 --> 00:16:07,391 +the table will help group them for you. +table 将会帮你将它们分组 + +387 +00:16:07,393 --> 00:16:10,494 +But you can then set outlets to your controller from them. +随后你可以给它们设置 outlets + +388 +00:16:10,496 --> 00:16:13,196 +It's really almost just like it's partitioning the space +这就好像 table 在为你 + +389 +00:16:13,198 --> 00:16:14,030 +for you, okay? +分割区域 + +390 +00:16:14,032 --> 00:16:16,699 +So that's the static table view. +这就是 static + +391 +00:16:16,701 --> 00:16:18,901 +And so whatever cells you see here in story board, +你在 storyboard 中看到的 + +392 +00:16:18,903 --> 00:16:20,369 +that's what you're going to see in your UI, +就是你在 app 启动以后看到的 + +393 +00:16:20,371 --> 00:16:22,437 +no more cells than that because it's static. +不会有变化,因为它是 static 的 + +394 +00:16:22,439 --> 00:16:23,889 +Okay? + +395 +00:16:23,890 --> 00:16:25,340 +So it's almost just a way of grouping things. +所以这只是一种给东西分组的方式 + +396 +00:16:25,342 --> 00:16:27,075 +So again, this is like the settings app. +这就像是在设置 app 中 + +397 +00:16:27,077 --> 00:16:28,610 +In the settings app, +在这里 + +398 +00:16:28,611 --> 00:16:30,144 +pretty much it's always the same thing in the UI, +它总是这同一种类型的 UI + +399 +00:16:30,146 --> 00:16:32,446 +that's not, you know dynamic. +这不是 dynamic 的 + +400 +00:16:32,448 --> 00:16:35,282 +It can be that some settings let you set. +设置总是一样的 + +401 +00:16:35,284 --> 00:16:36,416 +Does things for different apps. +为不同的 app 处理事情 + +402 +00:16:36,418 --> 00:16:37,984 +And so maybe the list of apps can grow. +也许 app 的列表会增长 + +403 +00:16:37,986 --> 00:16:40,686 +So that may be a combination of the things going +所以这里会是一系列 app + +404 +00:16:40,688 --> 00:16:41,920 +on in there. +的集合 + +405 +00:16:41,922 --> 00:16:44,656 +But usually static table view is static. +但通常来说 static table view 是静态的 + +406 +00:16:44,658 --> 00:16:46,608 +Okay? + +407 +00:16:46,609 --> 00:16:48,559 +Now, the other side is dynamic table view. +另一方面是 dynamic table view + +408 +00:16:48,562 --> 00:16:52,530 +Now in a dynamic table view, these cells that you see. +在 dynamic table view 中 + +409 +00:16:52,532 --> 00:16:55,633 +Oh by the way, we almost always use dynamic in plane. +我们使用 + +410 +00:16:55,635 --> 00:16:57,468 +In the plain style. + plain style + +411 +00:16:58,904 --> 00:17:02,972 +These rows that you see are not, what you build in +你们看到的这些行不是在 + +412 +00:17:02,974 --> 00:17:06,109 +the storyboard is not what's gonna appear in that one row. +storyboard 中建立的 + +413 +00:17:06,111 --> 00:17:09,278 +You're actually building a template or a prototype. +你只需要搭建一个模板,或者一个原型 + +414 +00:17:09,280 --> 00:17:12,481 +And if it needs 10,000 rows to show your iPod things, +如果它需要用 10000 行来显示你 iPod 中的歌曲 + +415 +00:17:12,483 --> 00:17:14,316 +it's gonna make that row 10,000 times. +它会创建那个行 10000 次 + +416 +00:17:15,619 --> 00:17:17,085 +Okay? + +417 +00:17:17,086 --> 00:17:18,552 +You see what I mean by you making a template out of it. +你可以创建一个模板 + +418 +00:17:18,555 --> 00:17:20,921 +You're making a prototype that's gonna be +你制作的原型会被 + +419 +00:17:20,923 --> 00:17:22,456 +replicated, okay? +一遍又一遍地复制 + +420 +00:17:22,458 --> 00:17:24,725 +So that's a very big difference there, +Dynamic 模式的原型与 static 的 + +421 +00:17:24,727 --> 00:17:29,662 +between static and these prototypes, the dynamic mode. +情况是非常不同的 + +422 +00:17:30,698 --> 00:17:34,233 +In either case, the cells themselves can be selected. +在每种情况下,cell 本身都是可以选中的 + +423 +00:17:34,235 --> 00:17:35,867 +You click on those. +你只需要单击它 + +424 +00:17:35,869 --> 00:17:37,235 +And you can see that cell's selected. +你可以看到它被选中了 + +425 +00:17:37,237 --> 00:17:40,004 +You can barely tell because it only has the small little +你很难看出它被选中了,因为它只有一个 + +426 +00:17:40,006 --> 00:17:40,705 +square there. +小方块在那里 + +427 +00:17:42,008 --> 00:17:44,241 +Resizing square that chose this selected. +一个改变大小的方块 + +428 +00:17:44,243 --> 00:17:46,242 +But when you select the cell, you can choose its type. +但是当你选中 cell 的时候,你可以选择它的类型 + +429 +00:17:46,244 --> 00:17:49,579 +Like here I'll change this cell to be subtitle type. +在这里我把它改成 subtitle + +430 +00:17:49,581 --> 00:17:52,214 +So now it's that subtitle style. +现在就是 subtitle 类型了 + +431 +00:17:52,216 --> 00:17:54,383 +Okay? + +432 +00:17:54,384 --> 00:17:56,551 +You can also change the little symbol that appears on +你也可以修改在每行右边显示的 + +433 +00:17:56,554 --> 00:17:59,021 +the right side of the row. +符号 + +434 +00:17:59,023 --> 00:18:00,221 +Here's a very special one called +这一个非常特殊 + +435 +00:18:00,223 --> 00:18:01,856 +the Detail Disclosure symbol. +叫做 Detail Disclosure + +436 +00:18:01,858 --> 00:18:03,491 +Okay? There's also, +在这 + +437 +00:18:03,492 --> 00:18:05,125 +you can put check marks over there and other things. +也可以放置 check mark 或者其他东西 + +438 +00:18:05,128 --> 00:18:08,362 +We'll talk about Detail Disclosure a little bit later +在这时候我会介绍 Detail Disclosure + +439 +00:18:08,364 --> 00:18:11,231 +because it's one that, if you click on, it can actually do +因为在这一行你点击它和点击这行的其他部分 + +440 +00:18:11,233 --> 00:18:13,933 +a different thing than if you click on the rest of the row. +产生的效果是不同 + +441 +00:18:13,935 --> 00:18:17,003 +So it's kind of, add a little ancillary UI to that row. +这对于那一行来说是一种辅助的 UI + +442 +00:18:18,205 --> 00:18:22,173 +So I'm gonna go back to non detail disclosure there. +我现在把 Detail Disclosure 取消 + +443 +00:18:23,276 --> 00:18:26,510 +Now we talked about the cell style, subtitle, +现在我来介绍 Cell 的类型,subtitle + +444 +00:18:26,512 --> 00:18:27,728 +and all those. +还有其他的类型 + +445 +00:18:27,729 --> 00:18:28,945 +But let's talk about this custom style. +我们先来看看这个 custom 类型 + +446 +00:18:28,948 --> 00:18:31,381 +What if I wanna build a custom prototype that's gonna be +如果我想制作自定义的原型 + +447 +00:18:31,383 --> 00:18:35,351 +replicated for my entire table view? +让我的整个 table view 复制它,该怎么做 + +448 +00:18:35,353 --> 00:18:38,621 +And you select the style to be custom. +把 cell 的类型变成 custom + +449 +00:18:38,623 --> 00:18:40,255 +See up there in the upper right? +在右上角 + +450 +00:18:40,257 --> 00:18:44,026 +And now it can just resize this cell to whatever size I +现在我就可以把它变成我任意想修改的大小 + +451 +00:18:44,028 --> 00:18:48,063 +want and I can go grab, you know, I don't know, +我可以拽一个 label 出来 + +452 +00:18:48,065 --> 00:18:51,632 +a label let's say and pull it out, drop it in there. +把它放到这里 + +453 +00:18:51,634 --> 00:18:56,036 +You definitely want to use auto layout here because I'm +你当然想使用 Auto Layout + +454 +00:18:56,038 --> 00:18:59,239 +gonna talk about how you can make the height of the cell +我也会告诉你,怎样使得 cell 的高度适应 + +455 +00:18:59,241 --> 00:19:02,442 +adjust to whatever content is in there, but if you don't +里面的内容 + +456 +00:19:02,444 --> 00:19:05,011 +set up the outer layout constraints, it's not gonna +但是如果你不设置好 Auto Layout + +457 +00:19:05,013 --> 00:19:08,781 +know what it can squish down and what it can't, et cetera. +它不会知道它自己应该被压缩到什么程度(高度是多少) + +458 +00:19:08,783 --> 00:19:11,783 +So you drag it out there and, +现在 + +459 +00:19:11,785 --> 00:19:14,319 +now you have the UI that you want. +你已经得到了想要的 UI + +460 +00:19:14,321 --> 00:19:15,787 +And you can have multiple labels, +你也可以放置多个 label + +461 +00:19:15,789 --> 00:19:16,654 +whatever you want in here. +放置什么都可以 + +462 +00:19:16,656 --> 00:19:18,222 +Text fields. +Text Field + +463 +00:19:18,223 --> 00:19:19,789 +Anything you can put in your view you can put here. +所有你能放进 view 的你都可以放到这里 + +464 +00:19:20,859 --> 00:19:24,127 +But when it comes to wiring up the outlets, +但是到了连接 outlet 的时候 + +465 +00:19:24,129 --> 00:19:26,963 +you can see that I can't wire up an outlet or action +你可以看到,我不能在 controller 中设置 outlet 或者 action + +466 +00:19:26,965 --> 00:19:31,433 +to my controller, because I might have 10,000 cells. +因为我可能有 10000 个 cell + +467 +00:19:31,435 --> 00:19:34,269 +Okay, so the way that that works is you actually create +所以你需要给这个 cell + +468 +00:19:34,271 --> 00:19:37,038 +a custom subclass of this cell. +创建一个自定义的子类 + +469 +00:19:37,040 --> 00:19:39,407 +So this cell is a UITableViewCell. +这个 cell 的类型是 UITableViewCell + +470 +00:19:39,409 --> 00:19:42,543 +UITableViewCell is just a special subclass of UI view. +UITableViewCell 是 UIView 的子类 + +471 +00:19:42,545 --> 00:19:45,346 +Okay, that's what the cell is, and so if you want to have +如果你想要对于每个 cell + +472 +00:19:45,348 --> 00:19:48,048 +outlets and actions per cell, you're going to create +建立 outlet 和 action + +473 +00:19:48,050 --> 00:19:50,650 +a custom sub class of this UITableViewCell and +你需要创建 UITableViewCell 的子类 + +474 +00:19:50,652 --> 00:19:53,052 +that's where the outlets and actions are going to be. +这个子类就是 outlet 和 action 放置的位置 + +475 +00:19:53,054 --> 00:19:55,187 +Okay and then for every row that's visible, +对于每一个可见的行 + +476 +00:19:55,189 --> 00:19:57,173 +you're gonna have this +你都会有这个 UITableViewCell + +477 +00:19:57,174 --> 00:19:59,158 +UITableViewCell and you'll be able to get actions +你可以从这里的按钮获取动作 + +478 +00:19:59,160 --> 00:20:03,228 +from buttons in there, or have outlets to set things. +或者设置 outlet + +479 +00:20:03,230 --> 00:20:06,297 +So, you do that with the identity inspector just like +所以,在 identity inspector 做的事情 + +480 +00:20:06,299 --> 00:20:07,865 +you set the class of something else, right? +就像你给其他东西设置类一样 + +481 +00:20:07,867 --> 00:20:10,434 +I select a cell and I go over to identity inspector. +我选中一个 cell,去到 identity inspector + +482 +00:20:10,436 --> 00:20:13,103 +I need to create a UITableViewCell subclass. +我需要创建一个 UITableViewCell 的子类 + +483 +00:20:13,105 --> 00:20:16,506 +So I go to new file, and here I want the subclass +所以,我创建一个新文件 + +484 +00:20:16,508 --> 00:20:20,176 +of to say UITableViewCell, not UITableView controller. +选择 UITableViewCell 的子类,而不是 UITableViewController + +485 +00:20:20,178 --> 00:20:23,079 +Okay so I create a subclass of UITableViewCell. +我创建了 UITableViewCell 的子类 + +486 +00:20:23,081 --> 00:20:26,015 +I set it at in the identity inspector to be my table view +在 identity inspector 中,设置为 Cell 的类 + +487 +00:20:26,017 --> 00:20:29,418 +cell and now I can wire up these outlets and +现在,我就能在我自定义的类中 + +488 +00:20:29,420 --> 00:20:31,386 +actions in here two outlets and +设置 outlet + +489 +00:20:31,388 --> 00:20:34,889 +actions in my custom subclass of UITableViewCell. +还有 action 了 + +490 +00:20:34,891 --> 00:20:36,374 +Okay. +OKay. + +491 +00:20:36,375 --> 00:20:37,858 +And so I just bring them up side by side and +打开 Assistant Editor,让它们并排显示 + +492 +00:20:37,860 --> 00:20:41,328 +assistant editor just control drag over to them. +CTRL-drag 设置出口 + +493 +00:20:41,330 --> 00:20:43,630 +Sometimes it's a bit of a pain to get the table of U cells +有些时候,右边不会自动 + +494 +00:20:43,632 --> 00:20:46,366 +subclass in the right-hand side of the assistant editor. +显示 UITableViewCell 的子类 + +495 +00:20:46,368 --> 00:20:49,535 +Automatic, seems like it eventually figures it out and +这次貌似是起了作用 + +496 +00:20:49,537 --> 00:20:50,770 +starts working. + +497 +00:20:50,772 --> 00:20:52,071 +But a lot of times it won't. +但是大部分时间,它不会正常工作 + +498 +00:20:52,073 --> 00:20:55,507 +So you have to do manual to get that cell on the right. +你需要手动设置右边显示的类 + +499 +00:20:55,509 --> 00:20:57,976 +This is where you bring up your. +这就是你创建的 + +500 +00:20:57,978 --> 00:20:58,943 +Subclass code. +子类的代码 + +501 +00:20:58,945 --> 00:21:01,045 +Then you can just control drag to create, +然后,你可以 ctrl-drag + +502 +00:21:01,047 --> 00:21:03,514 +for example here, an outlet to this label. +创建这个 label 的 outlet + +503 +00:21:03,516 --> 00:21:05,449 +And again, remember that you're doing this for +记住,这是 cell 的雏形 + +504 +00:21:05,451 --> 00:21:07,150 +a prototype here, these are dynamic. +这些是动态显示的 + +505 +00:21:07,152 --> 00:21:08,868 +And so this whole thing, +所以 cell 的所有东西 + +506 +00:21:08,869 --> 00:21:10,585 +it's going to be replicated over and over for every row. +都会被每一行所复制 + +507 +00:21:11,756 --> 00:21:13,439 +Okay? Each row is +每一行 + +508 +00:21:13,440 --> 00:21:15,123 +going to have it's own UI table U cell instance. +都会有它自己的 UITableViewCell 实例 + +509 +00:21:15,126 --> 00:21:16,725 +And thus its own outlets. +它自己的 outlet + +510 +00:21:16,727 --> 00:21:18,293 +And when it sends an action, +当它发送 action 的时候 + +511 +00:21:18,294 --> 00:21:19,860 +it's gonna send an action just to its instance.' +会发送到自己的实例那里 + +512 +00:21:19,863 --> 00:21:22,063 +Okay, now you might be freaking out a little bit +你可能现在被吓到了 + +513 +00:21:23,132 --> 00:21:27,134 +about that, thinking well I've got this UITableViewCell, +如果我有 10000 个 + +514 +00:21:27,136 --> 00:21:30,303 +it's a UIView, what if I have 10,000 of them? +UITableViewCell 会发生什么? + +515 +00:21:30,305 --> 00:21:32,072 +That's gonna be a problem. +这可能是个问题 + +516 +00:21:32,074 --> 00:21:34,040 +But we're gonna talk about how that's +但是我一会儿会告诉你,为什么在 UITableView 中 + +517 +00:21:34,042 --> 00:21:35,775 +not a problem in the UITableView in a minute here. +这不是个问题 + +518 +00:21:37,445 --> 00:21:40,879 +So how do we hook up to this stuff in code? +我怎么通过代码关联这些东西 + +519 +00:21:40,881 --> 00:21:43,314 +How do we load those cells up? +我怎样载入这些 cell + +520 +00:21:43,316 --> 00:21:46,818 +How do we tell it how many iPod songs I've got? +我怎样通知 cell,我 iPod 中有多少首歌曲? + +521 +00:21:46,820 --> 00:21:49,086 +And you do all that with this data source and +你们可以通过 Data Source 和 Delegate + +522 +00:21:49,088 --> 00:21:50,738 +delegates, okay? +来解决这些问题 + +523 +00:21:50,739 --> 00:21:52,389 +The data source is the one that's responsible for +Data Source 为 cell + +524 +00:21:52,391 --> 00:21:53,423 +the data. +的数据负责 + +525 +00:21:53,425 --> 00:21:55,191 +In other words, what's in the cells. +换句话说,cell 中有什么 + +526 +00:21:55,193 --> 00:21:56,893 +And the delegate is really responsible for +Delegate 为 cell 如何显示 + +527 +00:21:56,895 --> 00:21:58,260 +how it's all displayed, +而负责 + +528 +00:21:58,262 --> 00:22:00,229 +the configuration of the table, et cetera. +Table 的 形状之类的 + +529 +00:22:01,999 --> 00:22:04,933 +UITableViewController also, as I said, +UITableViewController 把它自己设置为 + +530 +00:22:04,935 --> 00:22:07,001 +it sets itself as the data source and delegate. +data source 和 delegate + +531 +00:22:07,003 --> 00:22:10,371 +It also has a property called TableView, +它也有一个 tableview 的属性 + +532 +00:22:10,373 --> 00:22:13,140 +which is the table view inside itself. +就是它内部的 tableview + +533 +00:22:13,142 --> 00:22:16,810 +So you can, at any time inside your controller +所以你可以在任何时候 + +534 +00:22:16,812 --> 00:22:19,312 +get at the TableView with tis TableView thing. +在 controller 中获取 tableview + +535 +00:22:19,314 --> 00:22:23,082 +Okay? [COUGH] All right, so what do +所以 + +536 +00:22:23,084 --> 00:22:26,285 +we need to do in implementing this data source protocol? +为了实现 data source 协议,我么需要做什么? + +537 +00:22:26,287 --> 00:22:28,320 +Well this data source protocol you're gonna implement +在 table 是动态的时候,你需要 + +538 +00:22:28,322 --> 00:22:31,323 +any time the table is dynamic, okay? +实现 data source 协议 + +539 +00:22:31,325 --> 00:22:34,492 +And there's three really important questions that +在这个协议中,你需要实现 + +540 +00:22:34,494 --> 00:22:36,094 +are answered by this protocol. +三个很重要的方法 + +541 +00:22:36,096 --> 00:22:38,863 +One is, how many sections are in the table? +table 分为几个 section? + +542 +00:22:38,865 --> 00:22:41,198 +The next is, how many rows are in a given section? +第二个是,在指定的 section 中,有几行? + +543 +00:22:41,200 --> 00:22:44,768 +And the third thing is, give me a UITableViewCell, or +第三个是,给它一个 UITableViewCell 或者它的子类 + +544 +00:22:44,770 --> 00:22:48,438 +subclass thereof, to display this row. +来显示这一行 + +545 +00:22:49,507 --> 00:22:50,873 +Okay those are the three main things. +这是三个主要的问题 + +546 +00:22:50,875 --> 00:22:52,407 +There's other things in the data sort of protocol but +在 data source 协议中还有其他方法 + +547 +00:22:52,409 --> 00:22:54,376 +these are the three main ones, It makes sense, right? +但是这三个是最主要的方法 + +548 +00:22:54,378 --> 00:22:56,077 +That we're trying to load up our table. +通过它们可以向 table 载入数据 + +549 +00:22:56,079 --> 00:22:57,645 +Data sources providing the data +Data source 提供数据 + +550 +00:22:57,647 --> 00:22:58,912 +that's the way it does it. +这就是它的方式 + +551 +00:22:58,914 --> 00:23:01,248 +So, the first two are exactly what you would think, so +前两个很容易想也很容易实现 + +552 +00:23:01,250 --> 00:23:03,817 +those are easy, so let's talk about how do I give +我们来看看如何给 tableview 一个 UITableViewCell + +553 +00:23:04,853 --> 00:23:09,154 +the table view a UITableViewCell to draw. +进行绘制 + +554 +00:23:09,156 --> 00:23:10,288 +A given row. +对于一个给定的行 + +555 +00:23:10,290 --> 00:23:13,358 +And you do that with this method. +通过这个方法 + +556 +00:23:13,360 --> 00:23:17,161 +I was telling before, 10,000 rows, don't worry. +对于 10000 个行的情况,不必担心 + +557 +00:23:17,163 --> 00:23:20,097 +The UITableViewCells, the reason 10,000 is going to work +UITableViewCell 对于这 10000 个行也能很好地工作 + +558 +00:23:20,099 --> 00:23:22,733 +is because we're only going to create UITableViewCells for +因为它为可见的行 + +559 +00:23:22,735 --> 00:23:23,900 +the visible rows. +创建 UITableViewCell + +560 +00:23:23,902 --> 00:23:28,204 +If I've 10,000 iPod songs, I can only see seven or +如果我有 10000 首歌曲 + +561 +00:23:28,206 --> 00:23:29,472 +eight of them on screen at a time, +在屏幕上,一次只能看到7,8首 + +562 +00:23:29,474 --> 00:23:32,474 +I'm only gonna have seven UITableViewCell instances. +那我只会有7个 UITableViewCell 的实例 + +563 +00:23:32,476 --> 00:23:35,243 +But what that means is they're getting reused. +这就意味着,这些 cell 是可以复用的 + +564 +00:23:35,245 --> 00:23:38,013 +As you scroll down, they're getting, the ones that +当你向下滑动的时候,滑出屏幕的 cell + +565 +00:23:38,015 --> 00:23:40,748 +are scrolling off the screen are getting put into a reuse +会被放入一个重复使用的 cell 队列中 + +566 +00:23:40,750 --> 00:23:41,949 +queue basically. + +567 +00:23:41,951 --> 00:23:44,852 +And when a new one comes on screen, it reuses it. +当一个新的出现在屏幕中时,就复用它 + +568 +00:23:44,854 --> 00:23:46,587 +Okay? + +569 +00:23:46,588 --> 00:23:48,321 +It either eases it or creates a new one by copying that +它通过拷贝 storyboard 中的原型 + +570 +00:23:48,323 --> 00:23:50,390 +prototype in your storyboard, okay? +或者释放或者创建 cell + +571 +00:23:50,392 --> 00:23:51,858 +But it's not gonna make 10,000. +但是它不会创建 10000 个 + +572 +00:23:51,860 --> 00:23:55,394 +It's only gonna make enough for the visible rows. +它只会创建能看到的那么多 + +573 +00:23:55,396 --> 00:23:59,498 +Now that has ramifications for multi-threadedness. +对于多线程来说 + +574 +00:23:59,500 --> 00:24:02,334 +Because if you have a row, and it appears, and +比如你有一行,它出现了 + +575 +00:24:02,336 --> 00:24:04,836 +you need to go fetch something on the network to draw it, +需要一些网络资源来绘制 + +576 +00:24:04,838 --> 00:24:08,172 +and you start to fetch, and then the user scrolls away, +你开始获取资源,但是用户把它滑走了 + +577 +00:24:08,174 --> 00:24:10,574 +when that fetch comes back, that you're no longer, +当资源获取到以后 + +578 +00:24:10,576 --> 00:24:15,412 +that row no longer wants that thing, cuz that row is gonna +那一行不在需要这些资源了 + +579 +00:24:15,414 --> 00:24:19,348 +be reused to display something else, understand? +因为那一行需要展示其他内容了 + +580 +00:24:19,350 --> 00:24:20,883 +So be careful with multi-threadedness +所以在使用多线程的时候小心一点 + +581 +00:24:20,885 --> 00:24:23,819 +in TableViews because those rows, the UITableViewCells, +在 UITableView 中 + +582 +00:24:23,821 --> 00:24:27,655 +are being constantly reused. +这些 UITableViewCell 都是被重复使用的 + +583 +00:24:27,657 --> 00:24:29,974 +All right, so + + +584 +00:24:29,975 --> 00:24:32,292 +here is the method that the UITableView is going to send, +这是 UITableView 发送消息的方法 + +585 +00:24:32,295 --> 00:24:36,496 +it's UITableViewDataSource implementing protocol object, +它发送给 UITableViewDataSource 协议的对象 + +586 +00:24:36,498 --> 00:24:38,832 +which is gonna be your controller, +就是你的 controller + +587 +00:24:38,834 --> 00:24:41,034 +to say give me UITableViewCell. +用于给它提供 UITableViewCell + +588 +00:24:41,036 --> 00:24:45,437 +It's called TableViewCell for row at index path, okay? +它的方法名是 cellForRowAtIndexPath: + +589 +00:24:45,439 --> 00:24:47,305 +And you can see it returned to UITableViewCell. +它的返回值是一个 UITableViewCell + +590 +00:24:47,307 --> 00:24:51,176 +Obviously, it could return a custom subclass thereof. +当然也可以返回自定义的 UITableViewCell 子类 + +591 +00:24:51,178 --> 00:24:53,644 +And the argument there, index path, and +参数是 indexPath + +592 +00:24:53,646 --> 00:24:56,213 +in this index path, it's just a simple little container +它只是一个和简单的小容器 + +593 +00:24:56,215 --> 00:24:58,015 +that contains the section and +里面放 tableView 需要 cell 的 + +594 +00:24:58,017 --> 00:25:03,019 +row that it wants the table view cell for, 'kay? +section 和 row + +595 +00:25:03,021 --> 00:25:04,954 +So you're gonna use that information like this. +你可以这样使用这个参数 + +596 +00:25:04,956 --> 00:25:08,324 +You have some internal data structure that's arranged +你有一些内置的数据对象 + +597 +00:25:08,326 --> 00:25:10,325 +by the sections and rows, 'kay. +通过段和行来划分 + +598 +00:25:10,327 --> 00:25:13,161 +I don't know what it looks like, but you're just going to +为了显示这一行 + +599 +00:25:13,163 --> 00:25:17,198 +get the data for this row by accessing that internal data +你需要获取内部的数据 + +600 +00:25:17,200 --> 00:25:19,100 +structure, might not be as simple as this, +可能不会像我写得这么简单 + +601 +00:25:19,102 --> 00:25:22,469 +this is like an array of arrays, sections and rows +我这里使用的是二维数组 + +602 +00:25:22,471 --> 00:25:24,805 +although the demo I'm gonna do is gonna do it that way, but +虽然我 demo 也是这么写的 + +603 +00:25:24,807 --> 00:25:26,840 +it could be anything that lets you get your data. +但是你怎样获取数据都可以 + +604 +00:25:27,809 --> 00:25:31,610 +Once you have your data, then you're going to get a cell, +一旦你获取完数据,你需要获取一个 cell + +605 +00:25:31,612 --> 00:25:34,880 +a UITableViewCell or subclass there of and you're gonna load +UITableViewCell 或者它的子类 + +606 +00:25:34,882 --> 00:25:39,484 +it up with that data and it's gonna display, make sense? +为了显示,你需要把数据载入其中 + +607 +00:25:39,486 --> 00:25:41,552 +So let's talk about how you get that cell. +我来告诉你如何得到 cell + +608 +00:25:41,554 --> 00:25:44,622 +'Kay how am I get that cell that I wanna load up with my +我如何获得在那个 indexPath.row + +609 +00:25:44,624 --> 00:25:47,958 +data at that indexPath.row. +可以载入数据的 cell 呢? + +610 +00:25:47,960 --> 00:25:50,327 +So to do this I'm gonna bring the UI back but +为了实现,我需要回到 UI + +611 +00:25:50,329 --> 00:25:52,128 +I'm gonna keep this code there too. +但我也需要把代码放到这里显示 + +612 +00:25:52,130 --> 00:25:56,666 +Okay, so let's have both the code and the UI on screen +所以我让代码和 UI 同时显示 + +613 +00:25:56,668 --> 00:25:59,268 +at the same time here so you can see what's going on. +你们就能知道发生了什么 + +614 +00:25:59,270 --> 00:26:01,737 +So, the way I get a cell +我获取 cell 的方式 + +615 +00:26:01,739 --> 00:26:04,239 +is I'm gonna call this function in table view, called +是在 tableView 调用一个函数 + +616 +00:26:04,241 --> 00:26:08,076 +dequeueReusableCellWithIdenti- fier, 'kay? +叫做 dequeueReusableCellWithIdentifier: + +617 +00:26:08,078 --> 00:26:10,745 +Now, this is going to reuse the cell if possible, or +如果可能,它会复用 cell + +618 +00:26:10,747 --> 00:26:14,014 +if not, it's gonna create one by using your prototype +如果不行,它通过 storyboard 中的原型 + +619 +00:26:14,016 --> 00:26:15,482 +in the storyboard. +创建一个 + +620 +00:26:15,484 --> 00:26:18,351 +Now you tell it which prototype to use, because your +现在你是告诉它使用哪个原型 + +621 +00:26:18,353 --> 00:26:21,087 +table view can actually have multiple prototypes. +因为你的 tableview 可能会有多种原型 + +622 +00:26:21,089 --> 00:26:23,422 +So you tell it by using the argument there, +你通过这个参数 + +623 +00:26:23,424 --> 00:26:26,191 +the first argument the identifier, which you also +这个 identifier 参数 + +624 +00:26:26,193 --> 00:26:28,860 +need to fill out in the UI, in the storyboard. +你也需要把它填入 storyboard 中 + +625 +00:26:28,862 --> 00:26:30,895 +And you just inspect the cell, and +检查 cell + +626 +00:26:30,897 --> 00:26:33,598 +there'll be a field there called identifier. +有一个区域是 identifier + +627 +00:26:33,600 --> 00:26:35,533 +And you just fill in that identifier and +向其中填入内容 + +628 +00:26:35,535 --> 00:26:36,767 +that's what's using your code so +在代码中也要填入相同的内容 + +629 +00:26:36,769 --> 00:26:39,603 +this is what links your code to which prototype +它能使你的代码和 storyboard 中 cell 的原型相关联 + +630 +00:26:39,605 --> 00:26:42,372 +cell your going to make a copy of to use, +你就可以得到 cell 的拷贝,来使用它了 + +631 +00:26:42,374 --> 00:26:45,808 +'kay, but it's only going to make a new copy if it can't +但是它在找不到跳出屏幕可复用 cell 的时候 + +632 +00:26:45,810 --> 00:26:48,044 +find one to reuse that went off screen. +就会创建一份新的拷贝 + +633 +00:26:49,246 --> 00:26:51,279 +Everyone make sense there, good? +懂了吗? + +634 +00:26:52,249 --> 00:26:55,550 +Okay, so that's how I get the cell that I wanna use. +这就是如何得到我想要的 cell 的方法 + +635 +00:26:55,552 --> 00:27:00,454 +Notice that that cell comes back as any object, 'kay, even +注意,返回 cell 的类型是 AnyObject + +636 +00:27:00,456 --> 00:27:03,256 +though it's a UITableViewCell, it's historical reasons it +虽然它应该返回一个 UITableViewCell + +637 +00:27:03,258 --> 00:27:05,458 +really should come back as a UITableViewCell. +但是出于某些历史原因,它没有 + +638 +00:27:05,460 --> 00:27:09,328 +But you're gonna have to cast it to a UITableViewCell, or +你需要把它转型成 UITableViewCell + +639 +00:27:09,330 --> 00:27:10,696 +subclass thereof. +或者它的子类 + +640 +00:27:10,698 --> 00:27:16,101 +So, for example, if this prototype cell was, +如果原型 cell 类型是 + +641 +00:27:16,103 --> 00:27:19,604 +you know, like, subtitle or basic or something like that, +basic 或者 subtitle 之类的 + +642 +00:27:19,606 --> 00:27:22,640 +it wasn't a custom one, then I'm gonna dequeue it +它不是自定的 + +643 +00:27:22,642 --> 00:27:26,243 +as a UITableViewCell, and then I am gonna use the API of +我就可以把它按照 UITableViewCell 类型给取出来 + +644 +00:27:26,245 --> 00:27:29,780 +UITableViewCell to load it up, and if you look at +通过 UITableViewCell 给它载入 + +645 +00:27:29,782 --> 00:27:32,349 +the UITableViewCell doesn't have a lot in it. +其实 UITableViewCell 类内部没有很多东西 + +646 +00:27:32,351 --> 00:27:34,817 +It has a text label, which is the big text, and +它有一个 textLabel,就是比较大的标题 + +647 +00:27:34,819 --> 00:27:37,620 +a detailed text label which is the little text. +detailedTextLabel 是比较小的文字 + +648 +00:27:37,622 --> 00:27:39,855 +It also actually will let you put in an image there, +它也允许你向其中载入图片 + +649 +00:27:39,857 --> 00:27:42,457 +it has image view property, and +它有一个 imageView 的属性 + +650 +00:27:42,459 --> 00:27:44,493 +you could just load this up. +可以通过它载入 + +651 +00:27:44,494 --> 00:27:46,528 +So here I've loaded up the big text with the word title and +在这里,我把大点的文字设置成了 "title" + +652 +00:27:46,530 --> 00:27:48,229 +the little text with the word subtitle. +小点得文字设置成 "subtitle" + +653 +00:27:48,231 --> 00:27:50,297 +That would happen in every single row, but +每一行都会这样 + +654 +00:27:50,299 --> 00:27:53,233 +usually I would put my data in there, 'kay? +通常我会把数据放到那里 + +655 +00:27:53,235 --> 00:27:56,937 +From my internal data structure there. +从我内部的数据结构中 + +656 +00:27:56,939 --> 00:27:58,438 +Now what if I have a custom cell? +如果我的 cell 是自定义的呢? + +657 +00:27:58,440 --> 00:28:02,442 +Well if I have a custom cell, then that dequeue thing, +如果是这样,那这个 dequeued + +658 +00:28:02,444 --> 00:28:06,345 +okay, here I'm hooking up the custom cell there with +在这里 + +659 +00:28:06,347 --> 00:28:09,748 +the identifier, the dequeue thing would be my +我把两个 identifier 关联起来 + +660 +00:28:09,750 --> 00:28:13,185 +UITableViewCell subclass, right? +我应该把 dequeued 转型成 UITableViewCell 的子类 + +661 +00:28:13,187 --> 00:28:16,888 +And instead of doing cell dot text label dot whatever, +在这里我不会 .textLabel + +662 +00:28:16,890 --> 00:28:21,625 +I would call the public API of my UITable of UText, UTable, +我会调用我 UITableViewCell 子类 + +663 +00:28:21,627 --> 00:28:23,627 +UCell subclass, right? +的公共 API + +664 +00:28:23,629 --> 00:28:26,863 +It has some public API to set its, whatever, +它会有一些公共 API + +665 +00:28:26,865 --> 00:28:30,900 +it's displaying and you would call that, make sense? +来设置它自己,懂了吗? + +666 +00:28:30,902 --> 00:28:33,969 +Question about that? +有问题吗? + +667 +00:28:33,971 --> 00:28:39,775 +Okay, so, that's how you get the cell. +这就是你获取 cell 的方法 + +668 +00:28:39,777 --> 00:28:43,811 +How does the data source report how many sections and +data source 怎样报告 + +669 +00:28:43,813 --> 00:28:45,496 +rows to use? +有多少段,多少行呢? + +670 +00:28:45,497 --> 00:28:47,180 +Really simple, these two data source methods number of +非常简单,只需要实现 data source 的两个方法 + +671 +00:28:47,183 --> 00:28:50,284 +sections in TableView and number of rows and +numberOfSectionsInTableView 还有 + +672 +00:28:50,286 --> 00:28:53,186 +section, so you just implement those methods, and +numberOfRowsInSection + +673 +00:28:53,188 --> 00:28:57,190 +you return the value, the appropriate value there. +返回适当的值就可以了 + +674 +00:28:57,192 --> 00:29:00,192 +The number of sections by default is 1, so +如果你不实现 + +675 +00:29:00,194 --> 00:29:02,761 +if you don't implement the number of sections in table +numberOfSectionsInTableView + +676 +00:29:02,763 --> 00:29:05,430 +view you'll get 1 section, and +默认会得到 1 段 + +677 +00:29:05,432 --> 00:29:07,799 +1 big section with as many rows as you want. +一个很大段,里面有多少行都可以 + +678 +00:29:07,801 --> 00:29:09,534 +However, there's no default for +然而 numberOfRowsInSection + +679 +00:29:09,536 --> 00:29:10,935 +the method number of rows in section. +没有默认值 + +680 +00:29:10,937 --> 00:29:12,770 +This is the required method in this protocol, +在这个协议中 + +681 +00:29:12,772 --> 00:29:13,704 +you have to implement it. +这个方法必须实现 + +682 +00:29:13,706 --> 00:29:16,156 +Obviously, the table, +显然 + +683 +00:29:16,157 --> 00:29:18,607 +you have to know how many rows are in each section, 'kay? +table 必须知道在每一段里有多少行 + +684 +00:29:18,610 --> 00:29:21,110 +Cell for row in the next path also is required for +对于动态的 table, + +685 +00:29:21,112 --> 00:29:22,378 +dynamic tables. +cellForRowAtIndexPath 也是必须要实现的方法 + +686 +00:29:22,380 --> 00:29:23,812 +If you have a static table, +如果是静态的 table 就不需要实现 + +687 +00:29:23,814 --> 00:29:26,415 +you don't have to implement any of these cuz a static +它知道有多少段 + +688 +00:29:26,417 --> 00:29:28,016 +table it knows how many rows and +多少行 + +689 +00:29:28,018 --> 00:29:30,251 +sections there are, cuz you set it up in the storyboard. +因为你已经在 storyboard 中设置好了 + +690 +00:29:30,253 --> 00:29:32,386 +It doesn't need the cell for row in the next path, +它不需要实现 cellForRowAtIndexPath + +691 +00:29:32,388 --> 00:29:34,722 +because it can get it right out of the storyboard and +因为它可以从 storyboard 获取 + +692 +00:29:34,724 --> 00:29:35,989 +there's no reuse happening or +对于静态 table 来说 + +693 +00:29:35,991 --> 00:29:38,591 +any of that stuff in a static table, okay? +也没有复用之类的事情发生 + +694 +00:29:38,593 --> 00:29:44,497 +All right, so, in summary, the way you load up a UITableView +所以总得来说,载入 UITableView 的方式 + +695 +00:29:44,499 --> 00:29:47,299 +is you implement the data source, almost always in your +是实现 data source,几乎都在 controller 中 + +696 +00:29:47,301 --> 00:29:50,035 +controller, you just say how many sections there are, and +你需要告诉它,有多少段 + +697 +00:29:50,037 --> 00:29:51,469 +how many rows in each section. +每一段有多少行 + +698 +00:29:51,471 --> 00:29:54,455 +Then, you implement cell row and +接着实现 cellForRowAtIndexPath + +699 +00:29:54,456 --> 00:29:57,440 +index path by dequeuing cells, loading them up with the data +把 cell 取出队列 + +700 +00:29:57,443 --> 00:30:01,411 +at that section and row and returning it, that's it. +把它们装入数据然后返回,就是这样 + +701 +00:30:01,413 --> 00:30:02,345 +That's how table view works. +table view 就是这样实现的 + +702 +00:30:02,347 --> 00:30:04,213 +It's pretty straightforward. +这很容易理解 + +703 +00:30:04,215 --> 00:30:06,582 +But you can see the power of this simple protocol +但是,你可以看到这简单代理协议 API + +704 +00:30:06,584 --> 00:30:10,085 +delegation based API allows you to handle 10,000 +可以让你处理 10000 个 cell 的威力 + +705 +00:30:10,087 --> 00:30:12,954 +cells because you've got that reuse going on, +因为你可以复用这些 cell + +706 +00:30:12,956 --> 00:30:15,824 +without a lot of work from you, the programmer. +不需要程序编写者来做很多工作 + +707 +00:30:15,826 --> 00:30:18,159 +'Kay, all your work is really just manage your model, +你的工作只要管理好 model 就可以了 + +708 +00:30:18,161 --> 00:30:20,695 +get your data ready so that when the section row is asked +当某一段的某一行需要数据时 + +709 +00:30:20,697 --> 00:30:22,129 +for you can load up the cell. +为它的载入做好准备 + +710 +00:30:23,799 --> 00:30:27,600 +Okay, section titles, you know, like when I showed you +段的标题,就像我刚才展示给你的 + +711 +00:30:27,602 --> 00:30:30,970 +the one that had Japan and the Netherlands, those titles +Japan 和 Netherlands + +712 +00:30:30,972 --> 00:30:33,539 +are considered part of the table views data and so +这些标题是 table view 的 data 部分 + +713 +00:30:33,541 --> 00:30:36,108 +it is the data source that provides them by implementing +data source 提供这些内容 + +714 +00:30:36,110 --> 00:30:39,778 +table view title for header in section or title for foot or +通过 tableView:titleForHeaderInSection: 或者 tableView:titleForFooterInSection: + +715 +00:30:39,780 --> 00:30:43,415 +in section, and it just returns a string. +它们返回 String + +716 +00:30:43,417 --> 00:30:46,351 +If a string is not sufficient to show your title you can +如果 String 也不能满足展示标题的需求 + +717 +00:30:46,353 --> 00:30:48,586 +delegate involved then, not the data source, but +你也可以实现 UITableView 的代理方法 + +718 +00:30:48,588 --> 00:30:51,488 +the delegate, and it can provide a UI view. +它可以提供一个 UIView + +719 +00:30:51,490 --> 00:30:54,291 +Even if it provides UI view probably you're gonna use your +即使它提供了 UIView + +720 +00:30:54,293 --> 00:30:58,494 +data sources as your model to load up that UI view anyway, +你也需要使用 data source 作为 model 来载入那个 UIView + +721 +00:30:58,496 --> 00:31:02,264 +so since the data source and delegate are pretty much +data souce 和 delegate 非常类似 + +722 +00:31:02,266 --> 00:31:04,400 +the same thing, it's a fine distinction there, +这里是一个很好的区分 + +723 +00:31:04,402 --> 00:31:06,768 +but you should be clear about it in your mind. +你脑海中应该清楚这些 + +724 +00:31:06,770 --> 00:31:09,704 +So, there are a bunch of other methods in the protocol, +在协议中也有其他方法 + +725 +00:31:09,706 --> 00:31:12,073 +most of them are about deleting rows or +它们大部分都是关于删除行 + +726 +00:31:12,075 --> 00:31:14,241 +inserting rows, or moving rows. +插入行,或者移动行 + +727 +00:31:14,243 --> 00:31:16,677 +Now, why would the data source be involved in those things? +为什么 data source 需要包含这些东西? + +728 +00:31:16,679 --> 00:31:18,645 +Well, if I delete a row, +如果我删除了某一行 + +729 +00:31:18,647 --> 00:31:22,115 +I have to delete that data in the model right? +我也需要删除 model 中的那个 data + +730 +00:31:22,117 --> 00:31:23,983 +If I move the rows around and +如果我移动某一行 + +731 +00:31:23,985 --> 00:31:27,620 +the order of the rows is reflecting something in +移动完成后,也会对 model 中的数据造成影响 + +732 +00:31:27,622 --> 00:31:32,157 +the model, then I need to move it in the model as well, 'kay? +我也需要移动 model 中的数据 + +733 +00:31:32,159 --> 00:31:33,858 +So that's why the data source gets involved there, +这就是 data source 有这些方法的原因 + +734 +00:31:33,860 --> 00:31:36,861 +and you can look that up in the documentation there. +你可以查看一下这部分的文档 + +735 +00:31:38,130 --> 00:31:39,496 +All right, how about segueing? +那么 segue 怎么解决? + +736 +00:31:39,498 --> 00:31:41,364 +What happens when someone touches on a row? +当用户点击了一行会发生什么? + +737 +00:31:41,366 --> 00:31:44,834 +Well, if I'm in a navigation controller especially, +如果在 navigation controller 中 + +738 +00:31:44,836 --> 00:31:48,371 +I'd like to segue way off to some other view controller, +你想跳转到其他 view controller 中 + +739 +00:31:48,373 --> 00:31:51,106 +and you do that just by control-dragging. +你只需要 Ctrl+drag 就可以了 + +740 +00:31:51,108 --> 00:31:53,842 +So you just Ctrl+drag from the prototype, or +你从原型 Ctrl+drag + +741 +00:31:53,844 --> 00:31:57,212 +in a static thing, you can control from a static one, but +静态 cell 也可以 + +742 +00:31:57,214 --> 00:32:00,081 +you Ctrl+drag from the prototype, and then you +如果你从原型 cell Ctrl+drag + +743 +00:32:00,083 --> 00:32:03,684 +just set the segue type, show, or show detail, whatever. +设置一下 segue 的类型,show 或者 show detail 之类的 + +744 +00:32:03,686 --> 00:32:07,388 +[COUGH] And then you, oh, yes, if you have that little detail +如果你添加了 detail disclosure + +745 +00:32:07,390 --> 00:32:10,490 +disclosure I told you about, that special little +那个右边的小图标 + +746 +00:32:10,492 --> 00:32:14,227 +right-handed icon, you can Ctrl+drag from it, as well, +你也可以从它 Ctrl+drag + +747 +00:32:14,229 --> 00:32:17,830 +and you'll see that you can choose the accessory action. +你可以选择 accessory action + +748 +00:32:17,832 --> 00:32:20,399 +So each row can actually send two different segues. +每一行可以发起两种不同的 segue + +749 +00:32:20,401 --> 00:32:22,735 +One if you click on the row, itself, and +一种是点击行本身 + +750 +00:32:22,737 --> 00:32:26,104 +then one if you click on that little round circle, 'kay? +另一种是点击右侧的小圆圈 + +751 +00:32:26,106 --> 00:32:29,140 +[COUGH] Either way, you just set the identifier of +不管哪一种,你设置 segue 的 identifier + +752 +00:32:29,142 --> 00:32:32,910 +the segue as usual, and then implement prepareForSegue. +然后实现 prepareForSegue + +753 +00:32:32,912 --> 00:32:35,780 +But let's think about as we prepareForSegue, cuz I've got +在实现 prepareForSegue 的时候 + +754 +00:32:35,782 --> 00:32:38,415 +this prototype row and I've got 10,000 of them, +我是在原型 cell 中,我有 10000 行 + +755 +00:32:38,417 --> 00:32:41,151 +when I segue I've got to know which row caused that segue, +我不知道哪一行引发了 segue + +756 +00:32:41,153 --> 00:32:43,653 +which of the 10,000 rows, so how do I do that? +我该怎么判断? + +757 +00:32:43,655 --> 00:32:44,987 +So let's look at prepareForSegue. +让我们一起看看 prepareForSegue 方法 + +758 +00:32:44,989 --> 00:32:48,224 +This is a typical prepareForSegue in +在 table view controller 中 + +759 +00:32:48,226 --> 00:32:51,794 +a table view controller, [COUGH] and it looks, +这是一个典型的 prepareForSegue 方法 + +760 +00:32:51,796 --> 00:32:54,696 +all the stuff in green is all the same as any other one, so +绿色的代码跟其他 prepareForSegue 是一样的 + +761 +00:32:54,698 --> 00:32:56,865 +you don't even really have to look at that code. +你不需要看那部分 + +762 +00:32:56,867 --> 00:32:59,300 +But the yellow there, the sender +但是黄色的代码 + +763 +00:32:59,302 --> 00:33:02,370 +is the first time we've used the sender in prepareForSegue, +我们第一次在 prepareForSegue 使用 sender + +764 +00:33:02,372 --> 00:33:07,240 +and that sender is going to be the UITableViewCell of the row +sender 将是你从哪行 + +765 +00:33:07,242 --> 00:33:09,442 +that you're segueing from, 'kay? +segue 而来的 UITableViewCell + +766 +00:33:09,444 --> 00:33:11,144 +That's the magic. +这就是神奇的地方 + +767 +00:33:11,146 --> 00:33:13,079 +Now it's any object, so +现在它是 AnyObject + +768 +00:33:13,081 --> 00:33:16,982 +you're going to want to cast it using as to be either +你需要用 as 把它转型成 + +769 +00:33:16,984 --> 00:33:19,785 +UITableViewCell or your subclass thereof, right? +UITableViewCell 或者你自定义的子类 + +770 +00:33:19,787 --> 00:33:22,921 +So now you've got the cell that you're segueing from. +现在你获取了 cell + +771 +00:33:22,923 --> 00:33:25,690 +Now a lot of times you'll want to get the index path +大部分情况,你想要获取 cell 所在的 indexPath + +772 +00:33:25,692 --> 00:33:27,758 +of it now, the NSIndexPath to section and +NSIndexPath 中的 section 和 row + +773 +00:33:27,760 --> 00:33:30,627 +row because your data, your model is going to be +因为你的 model 会根据 section 和 row + +774 +00:33:30,629 --> 00:33:32,629 +indexed usually by section and row. +而建立索引 + +775 +00:33:32,631 --> 00:33:33,830 +So you're gonna use this method, +所以你需要使用这个方法 + +776 +00:33:33,832 --> 00:33:36,532 +indexPathForCell, which you pass the cell to, but +indexPathForCell 传入一个 cell + +777 +00:33:36,534 --> 00:33:39,235 +you have to cast it first, you can't pass it as any object, +你需要先将它转型,你不能传入 AnyObject + +778 +00:33:39,237 --> 00:33:41,170 +you have to pass it as a UITableView cell. +需要是 UITableViewCell 类型的 + +779 +00:33:41,172 --> 00:33:45,473 +And now, once you have that thing, you can do your normal +一旦你得到了它,就可以做正常的 segue + +780 +00:33:45,475 --> 00:33:48,242 +segueing, so, you're gonna get the destinationViewController +你需要获取 destinationViewController + +781 +00:33:48,244 --> 00:33:52,346 +that you're segueing to, as whatever class it is. +不管它是什么类 + +782 +00:33:52,348 --> 00:33:54,982 +Then you're gonna use the public API of that scene you're +接着你要使用那个场景的公开 API + +783 +00:33:54,984 --> 00:33:58,752 +segueing to, to set it up using the data at this section +在这个 section 和 row 使用数据 + +784 +00:33:58,754 --> 00:34:02,088 +and row of the cell that was clicked on, right? +为 segue 做好准备 + +785 +00:34:02,090 --> 00:34:06,659 +Okie-doke, all right, so +好的 + +786 +00:34:06,661 --> 00:34:09,728 +that's all the UITableView data source, that's getting +这就是 UITableView 的 data source + +787 +00:34:09,730 --> 00:34:12,497 +the data into the table, segueing, all that business. +把数据载入 table,segue 之类的工作 + +788 +00:34:13,567 --> 00:34:16,467 +Let's talk about the UITableViewDelegate, okay? +现在我们看一下 UITableViewDelegate + +789 +00:34:16,469 --> 00:34:19,303 +So UITableViewDelegate controls how the thing is +UITableViewDelegate 控制 + +790 +00:34:19,305 --> 00:34:21,805 +displayed, not the data but how it's displayed, so +table 如何显示 + +791 +00:34:21,807 --> 00:34:23,040 +obviously common for +它们也是 table view + +792 +00:34:23,042 --> 00:34:26,343 +them to both be the controller of the table view. +的控制器 + +793 +00:34:26,345 --> 00:34:29,112 +The delegate lets you observe what's going on inside +delegate 可以让你监视 + +794 +00:34:29,114 --> 00:34:30,513 +the table. +table 内部发生了什么 + +795 +00:34:30,515 --> 00:34:33,449 +For example, you could find out when a row was clicked +例如,当一行被点击的时候 + +796 +00:34:33,451 --> 00:34:35,067 +on with the delegate. +你可以获取到通知 + +797 +00:34:35,068 --> 00:34:36,684 +When a row is clicked on, you could segue or +当一行被点击的时候 + +798 +00:34:36,687 --> 00:34:39,587 +you can just find out from the delegate tableView, +你可以 segue 到其他 view + +799 +00:34:39,589 --> 00:34:41,456 +didSelectRowAtIndexPath, and +你也可以在 didSelectRowAtIndexPath 获取到 + +800 +00:34:41,458 --> 00:34:43,858 +it's gonna tell you the section and row. +它会告诉你 section 和 row + +801 +00:34:43,860 --> 00:34:45,225 +Index paths give you section and row, +indexPath 会给你点击 cell 的 + +802 +00:34:45,227 --> 00:34:47,127 +remember, of what you clicked on. +section 和 row + +803 +00:34:47,129 --> 00:34:49,796 +You can do whatever you want at that point, 'kay? +在那一刻你想怎么做都可以 + +804 +00:34:49,798 --> 00:34:52,265 +You could manually segue in code here, for example, or +你也可以用代码手动 segue + +805 +00:34:52,267 --> 00:34:55,267 +you could do something else. +或者做一些其它东西 + +806 +00:34:56,270 --> 00:34:57,802 +That little detail disclosure thing, +那个小的 detail disclosure + +807 +00:34:57,804 --> 00:35:00,772 +you can segue from it, or the delegate will get a message, +你可以从它 segue,你也会获取到 + +808 +00:35:00,774 --> 00:35:04,342 +accessoryButtonTappedForRowWi- thIndexPath, and +accessoryButtonTappedForRowWithIndexPath: 消息 + +809 +00:35:04,344 --> 00:35:06,777 +you can find out about it that way too. +这种方式也可以获取到 + +810 +00:35:06,779 --> 00:35:08,345 +Okay, so clicking on rows whether you click on +点击 row 或 + +811 +00:35:08,347 --> 00:35:10,413 +the little detail thing or the row itself, you can just +点击 detail disclosure + +812 +00:35:10,415 --> 00:35:13,249 +find out about if you don't want to segue directly. +如果你不想直接 segue 也可以获取到 + +813 +00:35:14,985 --> 00:35:17,285 +Tons of other stuff in the tableViewDelegate, +在 tableViewDelegate 有很多东西 + +814 +00:35:17,287 --> 00:35:19,454 +you can just look in the documentation. +直接看文档就可以了 + +815 +00:35:19,456 --> 00:35:22,590 +It also can be involved in the editing part, +delegate 也包含编辑的部分 + +816 +00:35:22,592 --> 00:35:24,892 +especially the re-display part of editing. +尤其是编辑后重新显示 + +817 +00:35:26,095 --> 00:35:28,528 +So you can take a look at that. +你也可以看一看 + +818 +00:35:28,530 --> 00:35:31,031 +All right, back to UITableView itself, +回到 UITableView 它本身 + +819 +00:35:31,033 --> 00:35:32,732 +what if your model changes? +如果你的 model 发生变化了呢? + +820 +00:35:32,734 --> 00:35:35,768 +You've done all the stuff to implement the data source, you +你实现了 data source 的所有方法 + +821 +00:35:35,770 --> 00:35:39,004 +loaded up your 10,000 cells, what happens if new songs got +载入了 10000 个 cell,如果向曲库中添加了新的歌曲 + +822 +00:35:39,006 --> 00:35:41,807 +added to your iPod library and you need to re-display? +需要刷新显示该怎么做? + +823 +00:35:41,809 --> 00:35:44,576 +Well, you can send a message to your table view, +你可以向 table view 发送一个消息 + +824 +00:35:44,578 --> 00:35:46,595 +reloadData. +reloadData + +825 +00:35:46,596 --> 00:35:48,613 +And it will go and send numberOfSectionsInTableView +它会发送 numberOfSectionsInTableView + +826 +00:35:48,615 --> 00:35:51,549 +and numberOfRowsInSection for each section and +numberOfRowsInSection + +827 +00:35:51,551 --> 00:35:55,052 +call cellForRowAtIndexPath for all the visible cells and +并且对每一个可见的 cell 调用 cellForRowAtIndexPath + +828 +00:35:55,054 --> 00:35:57,087 +reload up all your data, 'kay? +重新载入所有的数据 + +829 +00:35:57,089 --> 00:36:00,724 +Now that might be a lot of work for 10,000 iPod things so +对于 10000 条数据这工作量可能有点大 + +830 +00:36:00,726 --> 00:36:04,093 +you might wanna just reload a small part of it if you can, +所以你也许会只想载入一小部分 + +831 +00:36:04,095 --> 00:36:07,697 +and then you can use things like reloadRowsAtIndexPaths. +你可以使用 reloadRowsAtIndexPaths 方法 + +832 +00:36:07,699 --> 00:36:10,099 +You just give it an array of index paths and +传递给它 indexPath 的一个数组 + +833 +00:36:10,101 --> 00:36:12,501 +it'll only reload those cells, 'kay? +它只会重新载入这些 cell + +834 +00:36:12,503 --> 00:36:14,736 +So that's what happens when your model changes. +当 model 改变时 + +835 +00:36:15,905 --> 00:36:17,705 +What about the height of rows? +row 的高度该怎么办? + +836 +00:36:17,707 --> 00:36:20,040 +So the height of rows, the rows are gonna be the height +row 的高度会是你在 storyboard 中设定的高度 + +837 +00:36:20,042 --> 00:36:24,111 +they are in the story board unless, in your code, +除非在你的代码中 + +838 +00:36:24,113 --> 00:36:28,348 +you change the height to be UITableViewAutomaticDimension. +把高度设置为 UITableViewAutomaticDimension + +839 +00:36:28,350 --> 00:36:31,317 +If you do that, then it's gonna use the autolayout to +如果这么做,它会使用 autolayout + +840 +00:36:31,319 --> 00:36:33,218 +figure out how high each row is, so +调整每一行的高度 + +841 +00:36:33,220 --> 00:36:35,420 +every row could be a different height. +每一行都可能是不同的高度 + +842 +00:36:35,422 --> 00:36:38,456 +'Kay, if you use that automatic dimension, +如果你设置了 AutomaticDimension + +843 +00:36:38,458 --> 00:36:41,726 +you're gonna wanna set an estimatedRowHeight, +你也需要设置 estimatedRowHeight + +844 +00:36:41,728 --> 00:36:44,595 +because the table view is a scroll view, and +因为 table view 是 scroll view + +845 +00:36:44,597 --> 00:36:48,432 +it kinda wants to know how big its content size is, right? +所以它需要知道 + +846 +00:36:48,434 --> 00:36:49,733 +'Kay, remember, from scroll view, +它内容的尺寸是多少 + +847 +00:36:49,735 --> 00:36:51,501 +the content size, so, it kinda wants to know that. +它需要知道这些 + +848 +00:36:51,503 --> 00:36:54,070 +So it really helps to have an estimatedRowHeight so +所以 estimatedRowHeight 是很有帮助的 + +849 +00:36:54,072 --> 00:36:56,005 +it can kinda guess at what the size is and +它可以获取 size 的大小 + +850 +00:36:56,007 --> 00:36:58,674 +then as you start scrolling down, it'll adjust it. +当你滑动的时候,它会调整高度 + +851 +00:36:58,676 --> 00:37:02,877 +It's very good at doing that. +它非常擅长做这些 + +852 +00:37:02,879 --> 00:37:04,912 +So if you ever use automatic dimension, +如果你曾经使用过 AutomaticDimension + +853 +00:37:04,914 --> 00:37:06,747 +use estimatedRowHeight, 'kay? +记得使用 estimatedRowHeight + +854 +00:37:06,749 --> 00:37:09,483 +Now you can also have your delegate report, +你可以让 delegate + +855 +00:37:09,485 --> 00:37:12,152 +calculate and report the height of each row +计算每一行的高度 + +856 +00:37:12,154 --> 00:37:15,922 +using heightForRowAtIndexPath, 'kay, or there's also +使用 heightForRowAtIndexPath + +857 +00:37:15,924 --> 00:37:18,457 +estimatedHeightForRowAtIndexP- ath. +也可以用 estimatedHeightForRowAtIndexPath + +858 +00:37:18,459 --> 00:37:19,892 +You can implement either of those. +实现其中之一 + +859 +00:37:19,894 --> 00:37:22,861 +And that's a way that maybe you can calculate the row +这种方式你可以计算 row 的高度 + +860 +00:37:22,863 --> 00:37:25,730 +height without having to do the full auto-layout +而不需要做完整的 + +861 +00:37:25,732 --> 00:37:27,365 +calculation or something. +autolayout 计算之类的 + +862 +00:37:27,367 --> 00:37:30,968 +Or you can estimate it better than just a fixed estimated, +你可以先估计而不是使用固定的值 + +863 +00:37:30,970 --> 00:37:34,805 +your delegate might be smarter than that, so you can do that. +delegate 比较有效,你可以这么做 + +864 +00:37:34,807 --> 00:37:39,109 +Okay, so, dozens of other methods in UITableView itself, +UITableView 还有许多方法 + +865 +00:37:39,111 --> 00:37:41,377 +things like scrolling to a row, +例如,滑动到某一行 + +866 +00:37:41,379 --> 00:37:45,247 +you wanna scroll right down to a row or you want to manage +你也许想要滑动到某一行,或者 + +867 +00:37:45,249 --> 00:37:49,218 +whether multiple rows can be selected at the same time. +是否允许多行被同时选中 + +868 +00:37:49,220 --> 00:37:53,388 +Those kind of things are all controllable by methods in +这些方法都被 UITableView 自己控制着 + +869 +00:37:53,390 --> 00:37:57,859 +UITableView itself, not in the delegate or data source. +不是在 delegate 或 data source 中 + +870 +00:37:57,861 --> 00:38:00,995 +Okay, so that's it. +就是这样 + +871 +00:38:00,997 --> 00:38:04,131 +As usual, a demo's worth 1,000 words, so +一个 demo 胜千言 + +872 +00:38:04,133 --> 00:38:06,867 +let's do a little UITableView demo here. +我们一起来做一个 UITableView 的例子 + +873 +00:38:06,869 --> 00:38:09,269 +What we're gonna do is we're gonna build an app +我们做的是搭建一个 app + +874 +00:38:09,271 --> 00:38:11,838 +that searches for something in Twitter and +可以搜索 Twitter 中的文字 + +875 +00:38:11,840 --> 00:38:16,342 +shows us all the tweets that match, 'kay? +并且展示给我们所有匹配的 tweets + +876 +00:38:16,344 --> 00:38:17,109 +Should be easy. +应该会很简单 + +877 +00:38:18,211 --> 00:38:19,477 +Let's see if there's +一起来看看 + +878 +00:38:19,478 --> 00:38:20,744 +anything else here to talk about coming up. +近期的安排 + +879 +00:38:21,781 --> 00:38:25,816 +Oh, yeah, your Assignment 4 is gonna go out, +Assignment 4 快要截止了 + +880 +00:38:25,818 --> 00:38:28,719 +might post it right after lecture today, probably, but +也许在下课之后发布 + +881 +00:38:28,721 --> 00:38:30,520 +you have until next Wednesday on that one. +下周三之前你需要交上来 + +882 +00:38:30,522 --> 00:38:32,321 +It's gonna be a table view-based thing. +会是一个有关 tableview 的东西 + +883 +00:38:33,358 --> 00:38:36,025 +On Wednesday of this week, I'm gonna go over the requirements +这周三,我会告诉大家 + +884 +00:38:36,027 --> 00:38:37,626 +for your final project. +你们最后的项目需要做点什么 + +885 +00:38:37,628 --> 00:38:39,094 +And then also, I'm gonna cover a whole bunch of other +在这之后,我也会讲些内容 + +886 +00:38:39,096 --> 00:38:42,697 +things like alerts, unwind segues, timers and if I have +关于 alerts,unwind segues, timers + +887 +00:38:42,699 --> 00:38:44,865 +time on Wednesday, I'll actually start on animation, +如果还有时间,我会开始讲 animation + +888 +00:38:44,867 --> 00:38:47,167 +which is gonna be our next major topic. +我们下一步的主要话题 + +889 +00:38:47,169 --> 00:38:51,571 +Friday's section is an awesome one for +周五的部分是很赞的 + +890 +00:38:51,573 --> 00:38:53,239 +this week which is UICollectionView. +UICollectionView + +891 +00:38:53,241 --> 00:38:56,308 +So UICollectionView is kind of like a tableView, except for +UICollectionView 很像 tableview + +892 +00:38:56,310 --> 00:38:58,777 +instead of them being in a strict list, +它不会是一个严格的 list + +893 +00:38:58,779 --> 00:39:01,380 +it can be kind of arranged how you want on screen, +而是让屏幕的内容怎样被安排 + +894 +00:39:01,382 --> 00:39:04,382 +'kay, could be two-dimensional grid or whatever. +可以是二维的格子之类的 + +895 +00:39:04,384 --> 00:39:08,086 +So it's a much more flexible version of UITableView. +它是 UITableView 更灵活的一个版本 + +896 +00:39:08,088 --> 00:39:11,255 +And then next Monday, remember, no lecture, +下周一,没课 + +897 +00:39:11,257 --> 00:39:12,022 +we have a holiday. +是假期 + +898 +00:39:13,692 --> 00:39:16,559 +Okay, so let's go to building new apps, +好的,开始写新 app + +899 +00:39:16,561 --> 00:39:19,062 +I'm gonna say create new project. +新建一个项目 + +900 +00:39:20,031 --> 00:39:24,499 +Single view, I'm gonna call this Smashtag, 'kay? +单视图,起名为 Smashtag + +901 +00:39:26,336 --> 00:39:27,902 +Put it in our normal place here. +放到往常的位置 + +902 +00:39:29,038 --> 00:39:32,039 +I'm gonna move this stuff out of the way as I always do, +把这些放到其它地方 + +903 +00:39:32,041 --> 00:39:36,176 +we're not gonna work on any of that today, okay? +今天我们不会涉及这些文件 + +904 +00:39:36,178 --> 00:39:38,511 +So I just have my storyboard here. +打开 storyboard + +905 +00:39:38,513 --> 00:39:40,112 +It's got this one controller and +有一个 controller + +906 +00:39:40,114 --> 00:39:42,348 +I'm actually gonna delete this controller. +实际上我要把它删掉 + +907 +00:39:42,350 --> 00:39:43,999 +All right, so +好的 + +908 +00:39:44,000 --> 00:39:45,649 +now we have a completely empty storyboard, and +现在我们有一个空白的 storyboard + +909 +00:39:45,652 --> 00:39:48,820 +I'm gonna start by dragging in a UITableViewController. +拽进来一个 + +910 +00:39:48,822 --> 00:39:51,089 +So let's go grab a UITableViewController. +UITableViewController + +911 +00:39:51,091 --> 00:39:52,456 +It's right near the top. +在控件栏里 + +912 +00:39:52,458 --> 00:39:54,692 +Of our object palette here. +它在上面的位置 + +913 +00:39:54,694 --> 00:39:55,992 +So I'm gonna drag this out. +把它拽出来 + +914 +00:39:55,994 --> 00:39:57,861 +There it is. I'm also gonna embed +我把它放入 + +915 +00:39:57,863 --> 00:40:00,029 +it in a Navigation Controller. +Navigation Controller + +916 +00:40:00,031 --> 00:40:01,964 +Okay? + +917 +00:40:01,966 --> 00:40:05,167 +Because someday I might want to click on my tweets in here +因为也许以后我会点击某一条 tweet + +918 +00:40:05,169 --> 00:40:06,568 +and have it show more information, +然后需要它展示给我更多信息 + +919 +00:40:06,570 --> 00:40:08,803 +like maybe in your assignment four, perhaps. +也许在你们的第四次作业里 + +920 +00:40:10,407 --> 00:40:11,939 +All right, so we have this table, your controller. +所以我们有了这个 table,你的 controller + +921 +00:40:11,941 --> 00:40:14,008 +It really doesn't make sense to have a controller without +如果 controller 没有一个自定义的子类 + +922 +00:40:14,010 --> 00:40:17,177 +a custom view controller subclass, of course, +会显得很没有意义 + +923 +00:40:17,179 --> 00:40:19,746 +as you well know from all your assignments so far. +到目前为止我们都没有自己定义 + +924 +00:40:19,748 --> 00:40:24,750 +So let's go ahead and create a custom subclass here. +现在我们创建一个吧 + +925 +00:40:24,752 --> 00:40:25,951 +So we'll do File > New. +File > New + +926 +00:40:28,422 --> 00:40:30,889 +And hit iOS > Source > Cocoa Touch Class. +选择 iOS > Source > Cocoa Touch Class + +927 +00:40:30,891 --> 00:40:32,790 +Here I'm gonna be very careful to say I want +在这,我小心点 + +928 +00:40:32,792 --> 00:40:34,325 +a UITableViewController. +选中 UITableViewController + +929 +00:40:34,327 --> 00:40:37,394 +And I'm gonna call this TweetTableViewController. +起名为 TweetTableViewController + +930 +00:40:37,396 --> 00:40:38,161 +Cuz that's what's gonna show. +因为它会显示这些内容 + +931 +00:40:38,163 --> 00:40:39,195 +It's gonna show tweets. +会显示 tweets + +932 +00:40:40,131 --> 00:40:41,497 +Okay? And we'll put it in +把它放到以往 + +933 +00:40:41,499 --> 00:40:45,000 +the normal place where you put everything. +放置的地方 + +934 +00:40:45,002 --> 00:40:46,167 +Here it is. +这就是它 + +935 +00:40:46,169 --> 00:40:48,036 +I'll actually leave the code in here, +实际上我会把这些代码留在这里 + +936 +00:40:48,038 --> 00:40:49,870 +all this commented out stuff. +这些注释掉的代码 + +937 +00:40:49,872 --> 00:40:52,439 +Because some of this stuff is kinda interesting, for +因为有一些还是挺有意思的 + +938 +00:40:52,441 --> 00:40:55,409 +you to learn about how to do things like deleting rows, and +你们可以学到 + +939 +00:40:55,411 --> 00:40:56,609 +stuff like that, in the table view. +如何删除 row 之类的东西 + +940 +00:40:56,611 --> 00:40:59,946 +So, in here is the data source methods and +这里是 data source 方法 + +941 +00:40:59,948 --> 00:41:00,880 +we're gonna go implement those. +我们将要实现这些 + +942 +00:41:00,882 --> 00:41:02,448 +So I'll leave this stuff in here. +我把这些都留着 + +943 +00:41:02,450 --> 00:41:04,349 +I'm just gonna get rid of didReceiveMemoryWarning, +只删除 didReceiveMemoryWarning + +944 +00:41:04,351 --> 00:41:06,484 +because we're not gonna deal with that. +因为我们不会处理这些 + +945 +00:41:06,486 --> 00:41:07,618 +Okay? + +946 +00:41:07,620 --> 00:41:11,889 +So here we go, here's our code right here. +这就是我们的代码 + +947 +00:41:13,292 --> 00:41:16,159 +Let's talk about the model of our, oh, +我们先来探讨一下 model + +948 +00:41:16,161 --> 00:41:18,161 +sorry, one more thing before we do that. +抱歉,在这之前 + +949 +00:41:18,163 --> 00:41:20,996 +Let's go back to our storyboard and +先回到 storyboard + +950 +00:41:20,998 --> 00:41:27,669 +make sure we set this to be a TweetTableViewController. +确认我们把类设置为 TweetTableViewController + +951 +00:41:27,671 --> 00:41:30,105 +Okay, so I'm just in the identity inspector here. +在 identity inspector + +952 +00:41:30,107 --> 00:41:31,639 +That's a common thing to forget to do. +忘记做这件事情很正常 + +953 +00:41:31,641 --> 00:41:33,607 +You'll notice immediately when you start trying to +在连接 outlet 的时候 + +954 +00:41:33,609 --> 00:41:34,541 +wire things up. +你就会发现了 + +955 +00:41:34,543 --> 00:41:36,576 +Oh, that's not gonna work. +咦?怎么不起作用? + +956 +00:41:36,578 --> 00:41:38,478 +But anyway, common thing to forget there. +总的来说这挺容易忘记的 + +957 +00:41:38,480 --> 00:41:40,897 +All right, so +好的 + +958 +00:41:40,898 --> 00:41:43,315 +let's talk about the model of this table view controller. +讨论一下这个 table view controller 的 model + +959 +00:41:43,318 --> 00:41:45,017 +And what it's gonna be is, +实际上 model + +960 +00:41:45,019 --> 00:41:48,754 +it's actually gonna be an array of tweets. +应该是一个 tweets 的数组 + +961 +00:41:48,756 --> 00:41:53,458 +But it's really gonna be an array of array of tweets. +但它应该是一个 tweets 的二维数组 + +962 +00:41:54,828 --> 00:41:57,595 +Okay, why am I gonna make this an array of an array? +为什么我要把它设置为二维数组 + +963 +00:41:57,597 --> 00:42:00,364 +Okay, it's because I'm gonna have multiple sections. +因为我会有多个 section + +964 +00:42:00,366 --> 00:42:01,798 +Each section in my table view, +在 table 中的每一个 section + +965 +00:42:01,800 --> 00:42:03,933 +they're not gonna have headers or anything. +它们不会有标题之类的 + +966 +00:42:03,935 --> 00:42:08,404 +Each section is just gonna be a new batch of tweets, okay? +每一个 section 只是会一组新的 tweets + +967 +00:42:08,406 --> 00:42:10,005 +So, every time I get a new batch of tweets, +每一次我获取一组新 tweets + +968 +00:42:10,007 --> 00:42:11,239 +because you know how Twitter is, +因为你们知道 + +969 +00:42:11,241 --> 00:42:12,807 +things are always happening on Twitter, +Twitter 上总会时刻产生 + +970 +00:42:12,809 --> 00:42:14,909 +there's always new tweets being put on there. +新的推文 + +971 +00:42:14,911 --> 00:42:16,477 +You want to be able to constantly be seeing +你想不断地看到 + +972 +00:42:16,479 --> 00:42:17,945 +the latest ones, and so +最新的 + +973 +00:42:17,947 --> 00:42:20,180 +I'm going to be fetching them every once in a while and +我会时不时地获取它们 + +974 +00:42:20,182 --> 00:42:24,817 +I'll just throw them in to my array of array of tweets. +把它们放入 tweets 的二维数组里 + +975 +00:42:24,819 --> 00:42:26,585 +That's why I'm making an array of arrays. +这就是二维数组的原因 + +976 +00:42:26,587 --> 00:42:28,387 +Everyone understand that, why I'm doing that? +都懂了吧? + +977 +00:42:29,423 --> 00:42:32,524 +So each array inside is a different section +所以其中的每一个数组 + +978 +00:42:32,526 --> 00:42:33,157 +in the table view. +都是 tableview 中不同的 section + +979 +00:42:34,260 --> 00:42:35,793 +Now what's a tweet? +什么是一条 tweet + +980 +00:42:35,795 --> 00:42:37,127 +'Kay, I got this thing tweet here. +这里有一个 tweet + +981 +00:42:37,129 --> 00:42:38,345 +What is that? +它是什么 + +982 +00:42:38,346 --> 00:42:39,562 +Well, I'm gonna give you the code to do that. +在这里我会给你代码 + +983 +00:42:39,564 --> 00:42:42,131 +I'm gonna give you these Twitter files right here so +我会给你这些 Twitter 文件 + +984 +00:42:42,133 --> 00:42:45,768 +you can just drag them in to your project here. +你可以直接拖拽到工程里 + +985 +00:42:46,937 --> 00:42:48,870 +And, what do these things look like? +代码是什么样的? + +986 +00:42:48,872 --> 00:42:50,605 +Let's take a look at them. +我们看一眼 + +987 +00:42:50,607 --> 00:42:52,907 +So there's these four classes in here. +这里有四个类 + +988 +00:42:52,909 --> 00:42:56,510 +TwitterRequest is the class you use to actually request +TwitterRequest 是你从 Twitter + +989 +00:42:56,512 --> 00:42:57,977 +tweets from Twitter. +请求 tweets 的类 + +990 +00:42:57,979 --> 00:43:00,380 +And I'm gonna show you how to use that in this demo. +我会告诉你们怎样在 demo 中使用 + +991 +00:43:00,382 --> 00:43:03,549 +Tweet is the things that come back. +Tweet 是请求后返回的东西 + +992 +00:43:03,551 --> 00:43:05,368 +So, Twitter +TwitterRequest + +993 +00:43:05,369 --> 00:43:07,186 +requests are gonna give you an array of tweets, basically. +会返回给你一组 tweets + +994 +00:43:07,188 --> 00:43:08,787 +You're gonna tell it what to search for, +你告诉它你想搜索什么 + +995 +00:43:08,789 --> 00:43:09,821 +it's gonna give you an array of tweets. +它会返回给你一组 tweets + +996 +00:43:09,823 --> 00:43:10,722 +It could not be simpler. +很简单 + +997 +00:43:11,691 --> 00:43:14,425 +Tweets have some, you know, +Tweets 内部有 + +998 +00:43:14,427 --> 00:43:17,160 +things like the text of the tweet, when it was created. +发布时候的文字 + +999 +00:43:17,162 --> 00:43:21,031 +It also has things like, the hashtags and URLs and +也有 # 和 URL + +1000 +00:43:21,033 --> 00:43:25,001 +users that were mentioned inside the tweet, okay? +tweet 中提及的用户 + +1001 +00:43:25,003 --> 00:43:27,336 +So things like the user has its own little class here, +User 有它自己的类 + +1002 +00:43:27,338 --> 00:43:29,738 +User, that just has screen name, et cetera. +内部有 screen name 等成员 + +1003 +00:43:29,740 --> 00:43:31,540 +So these classes, you don't really +对于这些类 + +1004 +00:43:31,542 --> 00:43:33,508 +need to call any methods in any of them except for +你只需要调用 + +1005 +00:43:33,510 --> 00:43:35,977 +TwitterRequest to actually do the search. +TwitterRequest 的方法就可以搜索了 + +1006 +00:43:35,979 --> 00:43:37,778 +The other ones are just like bags of +其他的那些只是装数据的容器 + +1007 +00:43:37,780 --> 00:43:39,947 +things that are holding things like about the users, +就像 User 中的 + +1008 +00:43:39,949 --> 00:43:41,682 +user name, things like that. +userName 之类的 + +1009 +00:43:41,684 --> 00:43:44,417 +Okay, so it's pretty easy to use this little thing. +使用它们非常简单 + +1010 +00:43:44,419 --> 00:43:47,587 +So, now we have tweets in here so this makes sense. +现在我们已经有 tweets 了 + +1011 +00:43:47,589 --> 00:43:49,455 +We've got our nice model. +我们有了个不错的 model + +1012 +00:43:51,125 --> 00:43:53,625 +So, let's go ahead and make a request. +现在我们做一次请求 + +1013 +00:43:53,627 --> 00:43:56,194 +Let's see what the code looks like to make a request to +一起来看看如何向 Twitter + +1014 +00:43:56,196 --> 00:43:57,662 +Twitter. +提交一次请求 + +1015 +00:43:57,663 --> 00:43:59,129 +And I'm going to do that here in my viewDidLoad. +我会在 viewDidLoad 中处理 + +1016 +00:43:59,132 --> 00:44:01,566 +Okay? + +1017 +00:44:01,567 --> 00:44:04,001 +Let's go ahead and leave the rest of the comments in there. +把这些注释留在这里 + +1018 +00:44:04,003 --> 00:44:08,005 +And, so all I need to do, to do this is create a request. +我需要做的就是提出一次请求 + +1019 +00:44:08,007 --> 00:44:11,708 +So I'm gonna let a request equal TwitterRequest. +let request = TwitterRequest + +1020 +00:44:11,710 --> 00:44:15,345 +So I'm gonna have to use one of TwitterRequest's +使用 TwitterRequest 中的 + +1021 +00:44:15,347 --> 00:44:16,779 +constructors here. +一个构造函数 + +1022 +00:44:16,781 --> 00:44:20,782 +And I'm gonna use the one that lets me specify a search. +我使用能够让我搜索的那个 + +1023 +00:44:20,784 --> 00:44:22,167 +Okay? + +1024 +00:44:22,168 --> 00:44:23,551 +So, I'm gonna search, let's say, +我将进行一次搜索 + +1025 +00:44:23,553 --> 00:44:26,387 +we'll start out just searching for #Stanford. +先从 #Stanford 开始 + +1026 +00:44:26,389 --> 00:44:28,522 +That's a good one to start with. +不错的开始 + +1027 +00:44:28,524 --> 00:44:32,059 +And, a count is how many tweets I want to get +我要搜索多少条 + +1028 +00:44:32,061 --> 00:44:34,127 +in this request, so I'm gonna just do 100. +在这里填 100 + +1029 +00:44:34,129 --> 00:44:36,529 +And these other things are optional, so +其它的东西都不是必须的 + +1030 +00:44:36,531 --> 00:44:37,497 +I won't even specify them. +所以我不需要填 + +1031 +00:44:37,499 --> 00:44:38,831 +Whatever they are is what they are. +它们是什么就是什么吧 + +1032 +00:44:40,101 --> 00:44:41,267 +Okay? + +1033 +00:44:41,268 --> 00:44:42,434 +So now I've got my Twitter request. +现在我有了一个 request + +1034 +00:44:42,436 --> 00:44:43,868 +I'm just gonna execute it. +我直接执行它 + +1035 +00:44:43,870 --> 00:44:46,404 +I do that by calling this method in the Twitter request +我通过它的一个方法 + +1036 +00:44:46,406 --> 00:44:48,272 +called fetchTweets. +fetchTweets 来执行 + +1037 +00:44:48,274 --> 00:44:53,443 +Now fetchTweets takes one argument which is a handler. +fetchTweets 需要一个 handler 的参数 + +1038 +00:44:53,445 --> 00:44:54,878 +Okay? A closure basically, +实际上是一个闭包 + +1039 +00:44:54,880 --> 00:44:57,180 +we're gonna specify here, okay? +在这里指定的 + +1040 +00:44:57,182 --> 00:45:00,182 +That gives back the array of tweets. +它返回一组 tweets + +1041 +00:45:00,184 --> 00:45:01,517 +You see how it's giving the array of +你们看到它给一组 tweets + +1042 +00:45:01,519 --> 00:45:02,918 +tweets as the argument? +做为参数了吧 + +1043 +00:45:02,919 --> 00:45:04,318 +So that's going to be the argument in a handler. +它将会是 handler 的参数 + +1044 +00:45:04,321 --> 00:45:08,723 +So, I'm actually gonna use the trailing closure notation here +为了完成,在这里 + +1045 +00:45:08,725 --> 00:45:09,790 +to do this. +我使用尾随闭包 + +1046 +00:45:09,792 --> 00:45:12,826 +And so, this is asking me, what do you want, +这里问我,你需要什么 + +1047 +00:45:12,828 --> 00:45:15,128 +I just double-clicked on that by the way, it's asking me, +刚才我双击了这里 + +1048 +00:45:15,130 --> 00:45:16,663 +what do you want to call this variable? +它问我,你想叫这个变量什么 + +1049 +00:45:16,665 --> 00:45:19,866 +So this is my new tweets that are coming back. +返回的是新推文,所以起名为 newTweets + +1050 +00:45:19,868 --> 00:45:21,567 +Okay? And so, inside here I can +在内部 + +1051 +00:45:21,569 --> 00:45:23,202 +just do whatever I want with my new tweets. +我可以对 newTweets 做任何我想做的事情 + +1052 +00:45:23,204 --> 00:45:25,671 +Well, what I want to do is very easy. +我想做的事情很简单 + +1053 +00:45:25,673 --> 00:45:28,073 +If there are any of these new tweets, +如果有 newTweets + +1054 +00:45:28,075 --> 00:45:31,909 +because maybe it couldn't find any, but if there are any, +因为它可能搜索不到 + +1055 +00:45:31,911 --> 00:45:34,712 +then I'm just going to say self.tweets. +如果有的话,self.tweets + +1056 +00:45:34,714 --> 00:45:37,381 +Now I have to say, if I don't say self, you know it's gonna +我必须加 self,因为它在闭包内部 + +1057 +00:45:37,383 --> 00:45:39,716 +complain because this is inside a closure. +不加会出错 + +1058 +00:45:39,718 --> 00:45:46,356 +I'm going to say tweets.insert the new tweets atIndex 0. +tweets.insert(newTweets, atIndex: 0) + +1059 +00:45:46,358 --> 00:45:48,324 +So I'm going to put it as the first section +所以我把它放入 tableview 的 + +1060 +00:45:48,326 --> 00:45:49,525 +in my table view. +第一个 section 中 + +1061 +00:45:49,527 --> 00:45:50,959 +Okay? Remember, Tweets is +记住,Tweets 是二维数组 + +1062 +00:45:50,961 --> 00:45:53,862 +an array of arrays, and each one is a section. +每一个数组是一个 section + +1063 +00:45:53,864 --> 00:45:55,530 +So I'm going to put it in section zero +所以我把它放入了 + +1064 +00:45:56,799 --> 00:45:58,265 +of my tweets right there. +第 0 个 section + +1065 +00:45:58,266 --> 00:45:59,732 +You can see it's complaining because this is +你可以看到这里出错了 + +1066 +00:45:59,735 --> 00:46:02,803 +inside a closure, and it wants me to put self in front so +因为这是在闭包内部 + +1067 +00:46:02,805 --> 00:46:06,039 +that I'm clear about the fact that I'm capturing self. +我清楚的知道我在捕获 self + +1068 +00:46:06,041 --> 00:46:08,007 +Now that's not gonna be a problem in this case, but +在这种情况之下,这不是问题 + +1069 +00:46:08,009 --> 00:46:10,309 +it's always something you should think about, as whether +但是你需要思考这些问题 + +1070 +00:46:10,311 --> 00:46:13,245 +you're capturing something that points back to it. +你是否需要捕获指向它自己的变量 + +1071 +00:46:13,247 --> 00:46:15,714 +Then I'm gonna reload my table view, okay? +接着,我会重新载入 tableView + +1072 +00:46:15,716 --> 00:46:18,249 +So I'm just gonna say, tableView.reloadData and +tableView.reloadData + +1073 +00:46:18,251 --> 00:46:20,785 +that's gonna cause my whole table to get reloaded. +这会让我的整个 table 重新载入 + +1074 +00:46:21,821 --> 00:46:24,655 +Now again, I could try and just reload this one section, +我可以只载入这个 section 的部分 + +1075 +00:46:24,657 --> 00:46:26,423 +section zero, that probably would be better but +第 0 个 section,这样也许会好一些 + +1076 +00:46:26,425 --> 00:46:27,590 +I'm just doing a demo here so +但是我是在做 demo + +1077 +00:46:27,592 --> 00:46:29,142 +I'm gonna reload my whole table. +我只重载我的整个 table 就好了 + +1078 +00:46:29,143 --> 00:46:30,693 +Its not that expensive to reload my table anyway. +但是重载我的整个 table 不会开销很大 + +1079 +00:46:32,063 --> 00:46:33,095 +Okay? + +1080 +00:46:33,096 --> 00:46:34,128 +It's that simple. +就是这么简单 + +1081 +00:46:34,131 --> 00:46:35,330 +That's all that's necessary. +需要做的只有这些 + +1082 +00:46:35,332 --> 00:46:41,068 +Now, can anyone see what might be a problem with this, +你们能看到这其中的问题吗? + +1083 +00:46:41,070 --> 00:46:42,836 +conceptually? +概念性的 + +1084 +00:46:42,838 --> 00:46:44,771 +When do you think this is called? +你们认为这部分什么时候被调用 + +1085 +00:46:47,442 --> 00:46:50,009 +Sometime later, right? +隔一段时间以后,对吧 + +1086 +00:46:50,011 --> 00:46:53,946 +I'm requesting tweets, I don't want to block my main queue. +我在请求推文,我不想阻塞主线程 + +1087 +00:46:53,948 --> 00:46:57,949 +So fetchTweets goes off and fetches it on the network and +fetchTweets 需要依靠网络执行 + +1088 +00:46:57,951 --> 00:47:00,585 +when they come back, it calls you back later. +当数据返回的呃时候,它会在之后调用这些 + +1089 +00:47:03,589 --> 00:47:05,322 +Not on the main queue, okay? +不是在主线程中 + +1090 +00:47:05,323 --> 00:47:07,056 +So, we cannot actually execute this code like this +所以我们不能像这样执行这部分代码 + +1091 +00:47:07,059 --> 00:47:10,827 +because this is UI code and so +因为这是 UI 代码 + +1092 +00:47:10,829 --> 00:47:12,629 +it can't be done off the main queue. +必须在主线程执行 + +1093 +00:47:12,631 --> 00:47:17,166 +So, here we have to dispatch this back to the main queue. +所以我们需要回到主线程 + +1094 +00:47:20,438 --> 00:47:23,472 +Okay, I may do the same thing here. +在这里也使用 + +1095 +00:47:23,474 --> 00:47:27,376 +My trailing closure notation. +尾随闭包 + +1096 +00:47:27,378 --> 00:47:35,583 +Like this, so I'm gonna put this inside here, like that. +我把这些放到这里面 + +1097 +00:47:36,719 --> 00:47:39,553 +Okay, everyone understand why I had to dispatch this back to +每个人都明白为何我需要回到 + +1098 +00:47:39,555 --> 00:47:40,754 +the main queue? +主线程了吗? + +1099 +00:47:40,756 --> 00:47:42,956 +Because this is an asynchronous API. +因为这是异步的 API + +1100 +00:47:42,958 --> 00:47:45,058 +FetchTweets is an asynchronous API, and +FetchTweets 是异步的 API + +1101 +00:47:45,060 --> 00:47:47,727 +you're gonna see APIs in iOS that are like this one. +你们也会在 iOS 中看到类似的 API + +1102 +00:47:47,729 --> 00:47:49,395 +This is an API I wrote, but. +这是我写的 + +1103 +00:47:49,397 --> 00:47:52,264 +iOS is going to have them too, where you're going to give it +但是 iOS 也会有类似这种 + +1104 +00:47:52,266 --> 00:47:54,833 +a handler and it's going to call that handler back off +一个 handler,在之后被调用 + +1105 +00:47:54,835 --> 00:47:57,135 +the main queue, sometime in the future. +在主线程之外 + +1106 +00:47:57,137 --> 00:48:00,071 +Okay? So this is a multi-threaded API. +这是多线程的 API + +1107 +00:48:00,073 --> 00:48:01,805 +Okay, but that's all I need to do. +但是这就是我需要做的 + +1108 +00:48:01,807 --> 00:48:02,472 +Simple as that. +就是这么简单 + +1109 +00:48:02,474 --> 00:48:04,241 +When it comes back, +当它返回的时候 + +1110 +00:48:04,242 --> 00:48:06,009 +I'm just going to dispatch it back to the main queue and +我只需要回到主线程 + +1111 +00:48:06,011 --> 00:48:06,709 +reload my data. +重新载入数据就可以了 + +1112 +00:48:06,711 --> 00:48:08,211 +Question? >> Sorry, +有问题吗? + +1113 +00:48:08,212 --> 00:48:09,712 +what would happen if you didn't have the [INAUDIBLE]? +「学生提问」 + +1114 +00:48:09,714 --> 00:48:11,480 +>> Yes, so the question, what if I didn't put this in here? +问题是,如果我没有回到主线程会发生什么? + +1115 +00:48:11,482 --> 00:48:14,449 +And the answer is strange things. +答案是,奇怪的事情会发生 + +1116 +00:48:14,451 --> 00:48:18,086 +Your UI would draw weird, things would get out of sync, +UI 可能会变得很奇怪,东西可能不会同步 + +1117 +00:48:18,088 --> 00:48:22,556 +probably your app might crash, lots of bad things, okay? +也许你的 app 会崩溃,很多奇怪的事情 + +1118 +00:48:22,558 --> 00:48:24,124 +So don't ever do it, it's bad. +所以别这么做,很不好 + +1119 +00:48:26,228 --> 00:48:31,798 +Okay, so now, we have our data loaded up into our model. +好,我们的数据已经载入 model 中了 + +1120 +00:48:31,800 --> 00:48:35,234 +Okay, in view did load we loaded up our model with some +在 viewDidLoad 中,我们载入了 + +1121 +00:48:35,236 --> 00:48:37,736 +data from a search, #Stanford here. +搜索 #Stanford 的数据 + +1122 +00:48:37,738 --> 00:48:39,738 +How did we get our model into the table? +我们怎样把 model 载入 table 中呢? + +1123 +00:48:39,740 --> 00:48:42,741 +Where we're going to go down to this UI table view data +来到 UITableViewDataSource + +1124 +00:48:42,743 --> 00:48:43,541 +source here. +这里 + +1125 +00:48:43,543 --> 00:48:45,393 +By the way, +顺便说一句 + +1126 +00:48:45,394 --> 00:48:47,244 +I'm going to change this to UITableViewDataSource. +我要把这里换成 UITableViewDataSource + +1127 +00:48:47,246 --> 00:48:49,880 +I like doing that. +我喜欢这么做 + +1128 +00:48:49,881 --> 00:48:52,515 +I don't think I've shown you this comment, // MARK:. +我应该没有给你展示 "// MARK": 这种注释 + +1129 +00:48:52,518 --> 00:48:53,783 +Have I showed you that? +我给你们展示过了吗? + +1130 +00:48:53,785 --> 00:48:56,786 +Okay, if you put a // MARK:, then up here, +如果你在这里放 // MARK: + +1131 +00:48:56,788 --> 00:48:59,855 +see where it says TweetTableViewController? +在这里 TweetTableViewController + +1132 +00:48:59,857 --> 00:49:03,158 +If you click on this, it will show you all your methods and +如果你点击它,它会帮你把这些方法 + +1133 +00:49:03,160 --> 00:49:05,427 +it will arrange them into groups. +分成组 + +1134 +00:49:05,429 --> 00:49:06,561 +See this? +看到了吗? + +1135 +00:49:06,563 --> 00:49:08,896 +This is this word right here. +在这里是这个词 + +1136 +00:49:08,898 --> 00:49:11,415 +Okay? So it's a really great +使用它来组织你的代码 + +1137 +00:49:11,416 --> 00:49:13,933 +way to kind of organize your code using these marks. +是一种很棒的方式 + +1138 +00:49:13,936 --> 00:49:16,420 +So like, for example, +例如这里 + +1139 +00:49:16,421 --> 00:49:18,905 +I've put another mark up here, this is a common one I do. +我再放一个 // MARK: + +1140 +00:49:18,907 --> 00:49:24,544 +Which is, View Controller Lifecycle. +注释 View Controller Lifecycle + +1141 +00:49:25,580 --> 00:49:27,646 +Okay now, when I click in here, see? +当我点击这里 + +1142 +00:49:27,648 --> 00:49:29,348 +I got View Controller Lifecycle. +我可以看到 View Controller Lifecycle + +1143 +00:49:29,350 --> 00:49:30,348 +I got my data source. +也能看到 data source + +1144 +00:49:30,350 --> 00:49:32,984 +Pretty cool, huh? +很酷,是吧? + +1145 +00:49:32,986 --> 00:49:34,185 +All right. So +好的 + +1146 +00:49:34,186 --> 00:49:35,385 +here's my data source methods. +这是我的 data source 方法 + +1147 +00:49:35,388 --> 00:49:37,154 +Here's number of sections. +这个是 numberOfSections + +1148 +00:49:37,156 --> 00:49:39,823 +So how many sections do we have? +我们有多少个 section? + +1149 +00:49:39,825 --> 00:49:45,795 +Okay, number of sections is tweets.count. +section 的数量是 tweets.count + +1150 +00:49:45,797 --> 00:49:48,597 +Because tweets is an array of arrays, right? +因为 tweets 是二维数组 + +1151 +00:49:48,599 --> 00:49:50,933 +In each array in there is this different section. +其中每一个数组都是一个不同的 section + +1152 +00:49:50,935 --> 00:49:52,134 +So how many sections are there? +这里有多少个 section 呢? + +1153 +00:49:52,136 --> 00:49:53,735 +However many things are in the tweets, +就看我 tweets 有几个 + +1154 +00:49:53,737 --> 00:49:55,203 +my tweets model up here. +我上面的 tweets model + +1155 +00:49:56,205 --> 00:49:57,438 +Okay? So that's easy. +这很容易 + +1156 +00:49:57,440 --> 00:49:58,656 +How about this? +这个怎么办? + +1157 +00:49:58,657 --> 00:49:59,873 +How many rows are in each section? +在每一个 section 有多少 row 呢? + +1158 +00:49:59,875 --> 00:50:04,444 +Okay, well that's just tweets[indexPath.section]. +tweets[indexPath.section] + +1159 +00:50:04,446 --> 00:50:07,146 +Actually not even indexPath, +实际上不是 indexPath + +1160 +00:50:07,147 --> 00:50:09,847 +they just put maybe the section, [section].count. +而是 [section].count + +1161 +00:50:09,850 --> 00:50:10,816 +All right, so it's asking me, for +这个方法问我 + +1162 +00:50:10,818 --> 00:50:13,018 +this section, how many rows are there? +对于这个 section,它内部有多少 row 呢 + +1163 +00:50:13,020 --> 00:50:14,752 +Well, I'm just going to get the tweets +我获取到那个 section 的 tweets + +1164 +00:50:14,754 --> 00:50:17,088 +that are in that section, and tell you how many there are. +然后返回其中的数量 + +1165 +00:50:18,090 --> 00:50:19,623 +Okay, so far this UI table, +到目前为止 + +1166 +00:50:19,625 --> 00:50:21,124 +it's pretty easy to implement, huh? +还是很容易实现的 + +1167 +00:50:21,126 --> 00:50:22,825 +Okay. How about this one, +但是这个方法呢? + +1168 +00:50:22,827 --> 00:50:25,261 +cellForRowAtIndexPath. + + +1169 +00:50:25,263 --> 00:50:27,529 +So we've got to do this dequeue reusable cell, +我们需要先从队列取出一个可以复用的 cell + +1170 +00:50:27,531 --> 00:50:29,297 +it automatically puts it in there. +代码自动生成了 + +1171 +00:50:29,299 --> 00:50:31,266 +We need a reuseIdentifier here. +我们需要一个 reuseIdentifier + +1172 +00:50:31,268 --> 00:50:35,436 +I'm going to be a good coder and +我有很好的编程习惯 + +1173 +00:50:35,438 --> 00:50:40,574 +say private struct Storyboard static +private struct Storyboard + +1174 +00:50:40,576 --> 00:50:45,545 +let CellReuseIdentifier equals and +static let CellReuseIdentifier = + +1175 +00:50:45,547 --> 00:50:48,847 +we'll say "Tweet". +"Tweet" + +1176 +00:50:50,050 --> 00:50:51,983 +And then I'm going to put that here instead of this thing. +然后把它放到这里 + +1177 +00:50:51,985 --> 00:50:56,387 +Storyboard.CellResuseIdentif- ier. + +1178 +00:50:56,389 --> 00:50:59,990 +Okay so, but we have to put this string in the storyboard +我们也需要把这个 string 放到 storyboard + +1179 +00:50:59,992 --> 00:51:03,393 +for the prototype we want to use to build this cell. +中的 cell 原型里 + +1180 +00:51:03,395 --> 00:51:05,628 +So let's do that, let's go back to our storyboard here. +回到 storyboard + +1181 +00:51:06,664 --> 00:51:07,963 +Okay. Here's our table view. +这是我们的 tableView + +1182 +00:51:07,965 --> 00:51:11,233 +I'm going to click to select this row and again, +点击它,选中这一行 + +1183 +00:51:11,235 --> 00:51:15,337 +I can use control shift and click to pick the controller, +我可以 Ctrl+shift+click 选择 controller 中的 + +1184 +00:51:15,339 --> 00:51:18,506 +the table view, the cell, or even the views inside. +table view, cell, 或者是其中的 view + +1185 +00:51:18,508 --> 00:51:21,275 +So I want this cell here, so I have this cell selected. +我想选择这个 cell + +1186 +00:51:21,277 --> 00:51:23,044 +I'm just going to inspect this, and +检查它的属性 + +1187 +00:51:23,046 --> 00:51:24,211 +right here you see identifier. +在这里有 identifier + +1188 +00:51:24,213 --> 00:51:25,912 +I'm going to say tweet. +把它设置为 Tweet + +1189 +00:51:25,914 --> 00:51:29,582 +And that says whenever I dequeue a reusable cell's +这的意思就是 + +1190 +00:51:29,584 --> 00:51:32,952 +tweet, this is the kind of cell I mean, okay? +每一次我从队列取 cell 的时候,我想要的是它 + +1191 +00:51:32,954 --> 00:51:34,420 +We'll configure that in a second. +稍后再设置一下 + +1192 +00:51:35,723 --> 00:51:40,558 +So here we have the cell that's been +在这里我们已经有了 + +1193 +00:51:40,560 --> 00:51:43,094 +reused or pulled out of there. +取出来的 cell + +1194 +00:51:43,096 --> 00:51:44,128 +Now we just need to configure it. +现在我们需要设置一下它 + +1195 +00:51:44,130 --> 00:51:46,964 +And since this is currently a normal cell, +因为它现在是一个普通的 cell + +1196 +00:51:46,966 --> 00:51:49,366 +just a regular cell not a subclass. +而不是子类 + +1197 +00:51:49,368 --> 00:51:53,202 +I'm going to use those things textLabel.text to set +我把 textLabel.text + +1198 +00:51:53,204 --> 00:51:55,705 +the title. +当做 title + +1199 +00:51:55,706 --> 00:51:58,207 +Let's set the title to the actual tweet, okay? +我们把 title 设置为 tweet + +1200 +00:51:58,209 --> 00:51:59,941 +So we'll have the big text be the tweet. +把大点的标题设置为 tweet + +1201 +00:51:59,943 --> 00:52:01,076 +We'll have the little text. +我也会使用小点的标题 + +1202 +00:52:01,078 --> 00:52:04,278 +Let's go back, let's go back to our storyboard. +回到 storyboard + +1203 +00:52:05,448 --> 00:52:08,782 +This cell, let's make this cell's type be subtitle. +把 cell 的类型 + +1204 +00:52:10,985 --> 00:52:13,586 +Let's make this be a subtitle style, right? +设置为 subtitle + +1205 +00:52:13,588 --> 00:52:16,021 +Where you got the big text and the little text. +这样就可以获得大标题的小标题 + +1206 +00:52:16,023 --> 00:52:18,023 +So I'm going to make the big text be the text of the tweet, +大标题设置为推文 + +1207 +00:52:18,025 --> 00:52:20,258 +and the little text be the user who tweeted it. +小标题设置为作者 + +1208 +00:52:20,260 --> 00:52:21,659 +It's not very good UI, +虽然不是很好的 UI + +1209 +00:52:21,661 --> 00:52:23,294 +but we'll make it better in a minute. +但是之后我会把它调整好的 + +1210 +00:52:25,064 --> 00:52:28,465 +All right, so probably want to do question mark here in case +在这里我需要放一个问号以防它是 nil + +1211 +00:52:28,467 --> 00:52:30,100 +that's nil because it's optional. +因为它是 Optional + +1212 +00:52:31,269 --> 00:52:34,437 +So, I need to basically have find the tweet +我现在需要找到这一行的 tweet + +1213 +00:52:34,439 --> 00:52:39,307 +that's in this row, and then just specify the tweet's text. +然后获取它的 text + +1214 +00:52:39,309 --> 00:52:41,910 +So, how do I get the tweet that's in this row, +我怎样获取这一行的 tweet 呢 + +1215 +00:52:41,912 --> 00:52:43,678 +let tweet equal something? +let tweet = + +1216 +00:52:43,680 --> 00:52:50,417 +Well, that's just going to be my tweets[indexPath.section] +让它等于 + +1217 +00:52:50,419 --> 00:52:53,787 +[indexPath.row]. +tweets[indexPath.section][indexPath.row] + +1218 +00:52:53,789 --> 00:52:56,122 +Okay, this is my model and +这是我的 model + +1219 +00:52:56,124 --> 00:52:58,858 +I'm just indexing into it by section and row. +我通过 section 和 row 找到 tweet + +1220 +00:52:58,860 --> 00:53:02,161 +Right, this is the index path that I was asked right here to +这里就是我为了得到指定 row 的 cell 的 + +1221 +00:53:02,163 --> 00:53:04,296 +get the cell for row in next path. +indexPath + +1222 +00:53:04,298 --> 00:53:07,249 +So now I've got the tweet. +现在我得到了 tweet + +1223 +00:53:07,250 --> 00:53:10,201 +So make its text, and now I'll say detailTextLabel?.text is +让 detailTextLabel?.text = + +1224 +00:53:10,203 --> 00:53:12,837 +the tweet.user.screenname, or +tweet.user.screenname + +1225 +00:53:12,839 --> 00:53:16,640 +that's actually their real name, what the heck. +它实际上是用户的真名 + +1226 +00:53:16,642 --> 00:53:18,709 +Okay? + +1227 +00:53:18,711 --> 00:53:21,177 +Everybody understand what I'm doing here in +在 cellForRowAtIndexPath 做的事情 + +1228 +00:53:21,179 --> 00:53:22,712 +cellForRowAtIndexPath? +大家都明白了吗 + +1229 +00:53:22,714 --> 00:53:25,314 +Just return a UI table U cell that's +返回一个为了显示在 cell 里的 + +1230 +00:53:25,316 --> 00:53:27,983 +going to use to draw that row. +UITableViewCell 就可以了 + +1231 +00:53:27,985 --> 00:53:29,351 +So that's all we need to do. +这就是我们需要做的 + +1232 +00:53:29,353 --> 00:53:33,254 +So let's go ahead and run, and hopefully this will work. +运行一下程序,希望能吸作用 + +1233 +00:53:33,256 --> 00:53:34,188 +Oh, okay. + +1234 +00:53:34,190 --> 00:53:36,590 +So here is the unreachable +出现的问题是 + +1235 +00:53:36,592 --> 00:53:39,259 +entry point in your storyboard, okay? +storyboard 没有入口 + +1236 +00:53:39,261 --> 00:53:44,630 +That's because we need to have the entry point come in here, +因为我们需要设置起始点 + +1237 +00:53:44,632 --> 00:53:47,366 +so I'm going to select this navigation controller and +选择 navigation controller + +1238 +00:53:47,368 --> 00:53:48,667 +go over here to. +来到这里 + +1239 +00:53:50,404 --> 00:53:50,969 +Sorry. + +1240 +00:53:52,038 --> 00:53:55,306 +Select it as the initial view controller, +把它设置为初始的 View Controller + +1241 +00:53:55,308 --> 00:53:57,091 +put that little arrow there. +这里放了一个小箭头 + +1242 +00:53:57,092 --> 00:53:58,875 +Okay, now it will probably work a lot better. +现在应该没什么问题了 + +1243 +00:54:01,079 --> 00:54:03,346 +All right here, so it wants to access my Twitter account, +它需要接入我的 Twitter 账户 + +1244 +00:54:03,348 --> 00:54:04,714 +sure, go for it. +当然,选择 OK + +1245 +00:54:04,716 --> 00:54:05,965 +There it is. +好了 + +1246 +00:54:05,966 --> 00:54:07,215 +Wow, that was super easy. +非常简单 + +1247 +00:54:07,218 --> 00:54:08,850 +We got all our tweets there now. +我们已经获取了全部的 tweets + +1248 +00:54:08,852 --> 00:54:10,385 +This is a pretty bad UI. +这 UI 很差 + +1249 +00:54:10,387 --> 00:54:12,253 +I mean, Twitter's already pretty limited, +Twitter 已经限制字数为 + +1250 +00:54:12,255 --> 00:54:13,354 +140 characters. +140 个了 + +1251 +00:54:13,356 --> 00:54:15,422 +This is not even that many, okay, so +这不算多 + +1252 +00:54:15,424 --> 00:54:16,423 +these are all cut off. +但是我们这里还是不够显示的 + +1253 +00:54:16,425 --> 00:54:18,625 +So this is really not a good UI. +所以这 UI 很不好 + +1254 +00:54:18,627 --> 00:54:21,394 +What we really want is to be able to build a nice, +我们想要为每一个 tweet + +1255 +00:54:21,396 --> 00:54:26,131 +custom UI in here for every tweet to show the screen name, +搭建一个自定义的 UI,可以显示昵称 + +1256 +00:54:26,133 --> 00:54:28,767 +maybe the image of the person who posted it, +也可以显示作者的头像 + +1257 +00:54:28,769 --> 00:54:30,769 +that kind of stuff in here. +之类的东西 + +1258 +00:54:30,771 --> 00:54:33,471 +So let's go enhance our UI to do that. +我们来丰富一下我们的 UI + +1259 +00:54:33,473 --> 00:54:36,140 +>> [COUGH] >> All right. + +1260 +00:54:36,142 --> 00:54:37,107 +Now, how do we do that? +该怎么做呢? + +1261 +00:54:38,544 --> 00:54:43,212 +Well, this cell right here needs to. +这边的这个 cell 需要... + +1262 +00:54:43,214 --> 00:54:47,049 +Actually, you know, it's time? +呃? + +1263 +00:54:47,051 --> 00:54:48,984 +I'm going to do one other thing first. +我先做另外一件事 + +1264 +00:54:48,986 --> 00:54:51,586 +Right now, it's only searching for #Stanford. +现在它只能搜索 #Stanford + +1265 +00:54:51,588 --> 00:54:53,488 +Let's make it so +给它添加一个 + +1266 +00:54:53,490 --> 00:54:56,758 +we can type in what it's searching for, okay? +输入搜索的功能 + +1267 +00:54:56,760 --> 00:54:58,959 +Setup is always looking for #Stanford, +目前只能搜索 #Stanford + +1268 +00:54:58,961 --> 00:55:01,395 +let's go put a search field in here. +在这里放一个搜索区域 + +1269 +00:55:01,397 --> 00:55:04,598 +So, I'm going to put that search field as the table +把它作为 table view 的 标题 + +1270 +00:55:04,600 --> 00:55:07,200 +view's header, remember I said the table view had a header? +记得我说过 table view 有标题吗? + +1271 +00:55:07,202 --> 00:55:09,452 +So I'm going to put that there. +所以我要把它放到那里 + +1272 +00:55:09,453 --> 00:55:11,703 +So I'm just going to go grab a text field, typeable +我拽进来一个 + +1273 +00:55:11,706 --> 00:55:13,973 +in text field like we've talked about, here it is. +text field + +1274 +00:55:13,975 --> 00:55:15,507 +I'm just going to drag it right +把它放到 table view 的 + +1275 +00:55:15,509 --> 00:55:17,709 +up here at the top of the table view. +顶部 + +1276 +00:55:17,711 --> 00:55:19,294 +Okay, here it is right here. +现在它在这里 + +1277 +00:55:19,295 --> 00:55:20,878 +I'm going to make the font a little bigger, +把字体调大一些 + +1278 +00:55:20,881 --> 00:55:24,382 +20 point font right there. +设置为 20 + +1279 +00:55:24,384 --> 00:55:27,051 +I can also do things like put a placeholder text in here, so +我也可以在其中放入占空的文字 + +1280 +00:55:27,053 --> 00:55:29,186 +when it's empty it kind of tells people what to do. +所以用户就知道它是用来做什么的了 + +1281 +00:55:29,188 --> 00:55:34,024 +So this is a Twitter search query right there. +设置为 Twitter search query + +1282 +00:55:34,026 --> 00:55:36,192 +So they know what to do. +所以用户就知道该怎么做了 + +1283 +00:55:36,194 --> 00:55:39,528 +And, then I can just wire up to this header view using +现在我可以把这个 header view + +1284 +00:55:39,530 --> 00:55:41,730 +normal outlets. +设置 outlet + +1285 +00:55:41,731 --> 00:55:43,931 +So let's go ahead and wire this up to our table view. +现在把它们连接起来 + +1286 +00:55:43,934 --> 00:55:48,003 +I'll just control drag to probably a little. +Ctrl+drag + +1287 +00:55:48,005 --> 00:55:48,770 +Higher up here. +高一点 + +1288 +00:55:48,772 --> 00:55:50,037 +Yeah, right in there. +就是这 + +1289 +00:55:50,039 --> 00:55:54,441 +This outlet, I'm going to call it my searchTextField. +这个 outlet,起名为 searchTextField + +1290 +00:55:55,444 --> 00:55:56,209 +Okay? There it is. +好了 + +1291 +00:55:56,211 --> 00:55:57,243 +My searchTextField. +searchTextField + +1292 +00:55:57,245 --> 00:56:02,280 +Let's go back here. +回到这里 + +1293 +00:56:02,282 --> 00:56:03,648 +All right. + +1294 +00:56:03,650 --> 00:56:05,416 +So here's our searchTextField right here. +这里是 searchTextField + +1295 +00:56:07,186 --> 00:56:10,821 +Now, when this searchTextField is set by IOS, I'm gonna set +当这个 searchTextField 被系统设置好以后 + +1296 +00:56:10,823 --> 00:56:14,024 +myself as its delegate so I can start doing some of those +我要把自己设置为它的 delegate + +1297 +00:56:14,026 --> 00:56:16,826 +UITextField delegate things we talked about. +所以我就可以进行一些之前讲到的 UITextField delegate 操作 + +1298 +00:56:16,828 --> 00:56:19,362 +So I'm going to say here, +在这里 + +1299 +00:56:19,364 --> 00:56:23,966 +searchTextField dot delegate equals self. +searchTextField.delegate = self + +1300 +00:56:23,968 --> 00:56:25,834 +Okay. Now it's gonna complain +现在它开始抱怨 + +1301 +00:56:25,836 --> 00:56:30,071 +because I don't implement the UITextField delegate protocol. +因为我还没有实现 UITextField 的代理协议 + +1302 +00:56:30,073 --> 00:56:36,010 +So I'm gonna say, okay, sure, UITextFieldDelegate. +所以在这里添加 UITextFieldDelegate + +1303 +00:56:36,012 --> 00:56:37,678 +So now I'm the UITextFieldDelegate, so +现在我是 UITextField 的 delegate + +1304 +00:56:37,680 --> 00:56:41,481 +now I can implement some of those UITextFieldDelegate +我现在可以实现 UITextFieldDelegate + +1305 +00:56:41,483 --> 00:56:42,214 +things. +的某些方法了 + +1306 +00:56:42,216 --> 00:56:43,449 +What's this one? +这个问题是? + +1307 +00:56:43,451 --> 00:56:45,117 +Oh, sorry, yes. +抱歉 + +1308 +00:56:45,119 --> 00:56:48,620 +We want this in the did set. +它应该在 didSet 里 + +1309 +00:56:48,622 --> 00:56:50,688 +I was trying to make that a computed property. +我想把它设置为计算属性 + +1310 +00:56:50,690 --> 00:56:51,489 +Okay. + +1311 +00:56:51,491 --> 00:56:52,923 +So that's the did set. +这就是 didSet + +1312 +00:56:52,925 --> 00:56:53,890 +All right. + +1313 +00:56:53,892 --> 00:56:57,761 +So inside there we want to do something. +在这里我需要做点什么 + +1314 +00:56:57,763 --> 00:57:02,198 +Right now our search is hard wired here to be #Stanford, so +现在我们的搜索内容是固定的 #Stanford + +1315 +00:57:02,200 --> 00:57:04,600 +let's make it so it's not hard wired anymore. +把它不设置为固定的内容 + +1316 +00:57:04,602 --> 00:57:06,068 +Okay? Let's have it search for +让它搜索 + +1317 +00:57:06,070 --> 00:57:08,103 +some search text. +searchText + +1318 +00:57:08,105 --> 00:57:10,188 +Okay? + +1319 +00:57:10,189 --> 00:57:12,272 +So I'm going to make a var up here, searchText, +定义一个变量 searchText + +1320 +00:57:12,275 --> 00:57:15,009 +which is gonna be a String. +String 类型的 + +1321 +00:57:15,011 --> 00:57:16,610 +We'll make it optional so +设置为 optional + +1322 +00:57:16,612 --> 00:57:19,046 +you don't have to set the string here. +你不需要在这里先设置好 + +1323 +00:57:19,048 --> 00:57:20,647 +Okay. + +1324 +00:57:20,649 --> 00:57:22,648 +I get into that quite a bit, don't I? +我被缠住了 + +1325 +00:57:22,650 --> 00:57:26,252 +It's because I got sticky keys on, and it gets stick. +因为我开启了粘滞键 + +1326 +00:57:26,254 --> 00:57:29,021 +Okay, and we'll still have the default be Stanford. +默认的搜索内容仍然是 Stanford + +1327 +00:57:30,824 --> 00:57:33,524 +Okay, and we're gonna need some didset in here. +在这里需要 didSet + +1328 +00:57:33,526 --> 00:57:34,925 +So here's our searchText. +这就是 searchText + +1329 +00:57:34,927 --> 00:57:36,627 +And down here since it can be an optional, +既然它是 optional + +1330 +00:57:36,629 --> 00:57:40,830 +I'm gonna say if the searchText does not equal nil +我就需要判断它是不是 nil + +1331 +00:57:40,832 --> 00:57:42,732 +because I don't want to search for nil. +因为我不想什么搜索 nil + +1332 +00:57:42,734 --> 00:57:43,833 +That makes no sense. +这很有道理 + +1333 +00:57:49,273 --> 00:57:52,340 +Okay. And this I'm gonna unwrap. +在这里,解包 + +1334 +00:57:52,342 --> 00:57:54,843 +All right. So + +1335 +00:57:54,844 --> 00:57:57,345 +now I've got the searchText, and we can search for it. +获取了 searchText,我们可以进行搜素了 + +1336 +00:57:57,347 --> 00:58:00,348 +All right, we'll wait to do that in a second here. +等会再处理这个 + +1337 +00:58:00,350 --> 00:58:04,584 +[SOUND] All right. + +1338 +00:58:04,586 --> 00:58:05,952 +Okay, so I got a searchText. +现在我有了 searchText + +1339 +00:58:05,954 --> 00:58:08,354 +Now let's go back down to our searchTextField right here. +回到 searchTextField + +1340 +00:58:08,356 --> 00:58:10,322 +When that searchTextField is first connected, +当 searchTextField 第一次连接好以后 + +1341 +00:58:10,324 --> 00:58:11,790 +I'm gonna set myself the delegate. +把我自己设置为它的 delegate + +1342 +00:58:11,792 --> 00:58:16,061 +I'm also going to set my searchTextField's text +我也需要把 searchTextField 的文字 + +1343 +00:58:16,063 --> 00:58:17,462 +equal to my searchText. +设置为 searchText + +1344 +00:58:18,765 --> 00:58:20,898 +Okay, so just in case someone set my searchText, +以防其他人设置了我的 searchText + +1345 +00:58:20,900 --> 00:58:23,767 +because I left searchText public. +因为我把 searchText 定为公有的 + +1346 +00:58:23,769 --> 00:58:24,935 +Okay? + +1347 +00:58:24,936 --> 00:58:26,102 +Okay? So if someone set it before my +以防某人在 outlet 设置好之前 + +1348 +00:58:26,104 --> 00:58:27,937 +outlets got set this would pick it up later, +设置了 searchText + +1349 +00:58:27,939 --> 00:58:28,537 +so that's good. +还不错 + +1350 +00:58:29,807 --> 00:58:31,673 +Now let's implement this delegate method. +现在,让我们实现这个代理方法 + +1351 +00:58:31,675 --> 00:58:33,742 +So, the one I'm going to implement is this +我将要实现的是 + +1352 +00:58:33,744 --> 00:58:35,209 +textFieldShouldReturn. + +1353 +00:58:35,211 --> 00:58:38,112 +You can see there's quite a few textField things here. +你可以看到这里有好几个 textField 相关的 + +1354 +00:58:38,114 --> 00:58:40,481 +So I'm gonna do this one, textFieldShouldReturn. +我处理这个,textFieldShouldReturn + +1355 +00:58:40,483 --> 00:58:43,383 +And, so this happens when someone clicks on the return +在点击了 textField 的 return 键之后 + +1356 +00:58:43,385 --> 00:58:45,652 +key of my text field. +这个方法被调用 + +1357 +00:58:45,654 --> 00:58:48,321 +So what is the return key of my text field going to be? +textField 的 retrun 键应该是什么呢? + +1358 +00:58:48,323 --> 00:58:49,622 +That's configurable so +这是可以设置的 + +1359 +00:58:49,624 --> 00:58:52,624 +if I edit this, if I inspect this text field, +我检查 textField 属性 + +1360 +00:58:52,626 --> 00:58:56,128 +I can actually control a lot about the keyboard right here. +我可以设置不同种键盘的类型 + +1361 +00:58:56,130 --> 00:58:59,731 +So I'm gonna make this keyboard type be Twitter. +我把这个键盘类型设置为 Twitter + +1362 +00:58:59,733 --> 00:59:02,066 +There's actually one for entering Twitter searches. +这是为了输入 Twitter 搜索使用的 + +1363 +00:59:02,068 --> 00:59:03,334 +Okay? + +1364 +00:59:03,336 --> 00:59:05,302 +All right? + +1365 +00:59:05,304 --> 00:59:10,073 +So now somebody clicked the go button or +某人点击了 go 按钮 + +1366 +00:59:10,075 --> 00:59:12,675 +the search or whatever that's gonna be in that keyboard. +不论是键盘中哪种类型的 return 键 + +1367 +00:59:12,677 --> 00:59:14,010 +What am I gonna do about that? +我们应该怎么做 + +1368 +00:59:15,079 --> 00:59:19,180 +Well for one thing I want to resign first responders. +首先,我要不做第一响应者 + +1369 +00:59:19,182 --> 00:59:22,650 +So if this textField that's sending this to me +如果发送给我这个消息的 textField 是 + +1370 +00:59:22,652 --> 00:59:25,519 +is my searchTextField, which it should be, +searchTextField,也应该是 + +1371 +00:59:25,521 --> 00:59:27,621 +cuz that's the only one I have. +因为我只有这一个 + +1372 +00:59:27,623 --> 00:59:30,223 +Then I'm going to have my textField +接着我就会让 textField + +1373 +00:59:30,225 --> 00:59:31,491 +resignFirstResponder. + +1374 +00:59:31,493 --> 00:59:34,260 +That means dismiss the keyboard. +这意味着,隐藏键盘 + +1375 +00:59:34,262 --> 00:59:37,263 +If you don't do this, it will send this. +如果你不这么做,它会发送这个 + +1376 +00:59:37,265 --> 00:59:39,732 +But it's gonna leave that keyboard up assuming that +但是键盘不会被隐藏 + +1377 +00:59:39,734 --> 00:59:41,433 +maybe they wanna type another search right away. +也许用户还想输入其他搜索 + +1378 +00:59:41,435 --> 00:59:42,767 +But here, I want it to go away so +但是在这,我想把键盘隐藏起来 + +1379 +00:59:42,769 --> 00:59:45,970 +they can see the results underneath it. +用户就可以看到下面的结果了 + +1380 +00:59:45,972 --> 00:59:47,038 +M'kay? + +1381 +00:59:47,040 --> 00:59:50,207 +So, what else do we need to do in here? +在这里我们还需要做什么? + +1382 +00:59:50,209 --> 00:59:53,543 +Well, then we just need to set our searchText +接着,把 searchText 设置为 + +1383 +00:59:53,545 --> 00:59:55,712 +equal to the text that's in the textField. +textField 中的 text + +1384 +00:59:57,982 --> 00:59:59,632 +Okay? + +1385 +00:59:59,633 --> 01:00:01,283 +So someone hits search, I'm gonna set my search text up +用户点击了 search,我把 search text 设置好 + +1386 +01:00:01,285 --> 01:00:03,852 +here equal to the thing is in there. +等于搜索框中的内容 + +1387 +01:00:03,854 --> 01:00:06,654 +And then I have to return true or false, whether or +我需要 return true 或者 false + +1388 +01:00:06,656 --> 01:00:09,323 +not I want to let this return key do what it normally does, +我是否让 return 键 + +1389 +01:00:09,325 --> 01:00:10,257 +which is fine. +做它往常做的事情 + +1390 +01:00:10,259 --> 01:00:11,558 +I don't have target action set up so +我没有建立 target action + +1391 +01:00:11,560 --> 01:00:13,226 +it's not going to do anything anyway, but +所以它不会做任何事 + +1392 +01:00:13,228 --> 01:00:14,327 +we'll go ahead and say true. +我们在这里返回 true 就好了 + +1393 +01:00:16,231 --> 01:00:19,899 +Okay, now when my searchText gets set here, +当 searchText 设置好了以后 + +1394 +01:00:19,901 --> 01:00:24,136 +I need to react to that by doing a new search. +我需要有所回应,做一次搜索 + +1395 +01:00:24,138 --> 01:00:26,971 +So I'm going to go here in my searchText. +去到 searchText + +1396 +01:00:26,973 --> 01:00:30,174 +And whenever my searchText is set, +无论何时 searchText 被设定 + +1397 +01:00:30,176 --> 01:00:35,646 +I'm going to basically clear out my table and then refresh. +我需要清空 table,然后刷新 + +1398 +01:00:35,648 --> 01:00:40,483 +So, let's go ahead and say tweets, removeAll. +tweets.removeAll + +1399 +01:00:40,485 --> 01:00:43,186 +Okay, so I'm gonna remove all my tweets that I have because +我要删除所有的 tweets + +1400 +01:00:43,188 --> 01:00:44,887 +I'm dong a new search. +因为我执行了一次新的搜索 + +1401 +01:00:44,889 --> 01:00:47,790 +Then I'm gonna reload the tableView here, +接着我需要重新载入 tableView + +1402 +01:00:47,792 --> 01:00:49,991 +reloadData in the tableView. +在 tableView 中重新载入 + +1403 +01:00:49,993 --> 01:00:51,993 +That's gonna blank out the tableView, +这会让我的 tableView 变成空白 + +1404 +01:00:51,995 --> 01:00:55,029 +cuz I just set all my tweets to nothing. +因为我把 tweets 都删掉了 + +1405 +01:00:55,031 --> 01:00:56,964 +Removed them all, and then I'm reloading, so it's gonna clear +然后重新载入数据,这样会把 table 清空 + +1406 +01:00:56,966 --> 01:00:58,732 +out my table view while I'm doing my search. +当我执行搜索的时候 + +1407 +01:00:58,734 --> 01:01:02,669 +Remember my search might take a minute if I'm on cellular. +记得,如果我用流量的时候,搜索可能持续一分钟 + +1408 +01:01:02,671 --> 01:01:04,504 +So I don't want to be sitting there with the old results, +所以我不想留着上次的结果 + +1409 +01:01:04,506 --> 01:01:06,506 +that'd be confusing, so I'm just gonna clear out my table. +这会让用户疑惑,所以我需要清空 table + +1410 +01:01:07,608 --> 01:01:09,475 +And then I got to refresh my data. +然后我需要刷新数据 + +1411 +01:01:09,477 --> 01:01:13,378 +So I'm going to call refresh and +我会调用 refresh + +1412 +01:01:13,380 --> 01:01:18,850 +take this code out of here and put it in another +然后把这些代码放入 + +1413 +01:01:18,852 --> 01:01:23,854 +method called refresh, func refresh. +refresh 方法里 + +1414 +01:01:25,124 --> 01:01:27,257 +Okay, I'm gonna do the same thing I was doing before. +像以前一样做得一样 + +1415 +01:01:27,259 --> 01:01:30,393 +I'm just gonna call it both in viewDidLoad when I start up +在 viewDidLoad 里调用 + +1416 +01:01:30,395 --> 01:01:33,329 +and also anytime someone changes my searchText. +还有当某人改变了 searchText 的时候 + +1417 +01:01:33,331 --> 01:01:34,963 +In my searchText also, +在 searchText 里 + +1418 +01:01:34,965 --> 01:01:38,767 +if someone sets my searchText externally, I'm going +如果某人在外部改变了 searchText + +1419 +01:01:38,769 --> 01:01:42,470 +to update my searchTextField also if it's around. +我也会更新 searchTextField + +1420 +01:01:45,041 --> 01:01:47,374 +Okay, so that way if someone's using my public API and +如果有人调用我的公共 API + +1421 +01:01:47,376 --> 01:01:49,776 +sets my search field, it'll appear in the text field. +并且设置了 searchText + +1422 +01:01:49,778 --> 01:01:51,411 +I want it to show up in that searchTextField. +我希望它显示在 searchTextField 里 + +1423 +01:01:51,413 --> 01:01:54,814 +All right, let's see if I got everything here. +看看是否一切正常 + +1424 +01:01:54,816 --> 01:01:55,748 +This works. +好用了 + +1425 +01:01:55,750 --> 01:01:57,016 +All right, here we have a #stanford. +这里显示了 #stanford + +1426 +01:01:57,018 --> 01:01:57,683 +That worked. +起作用了 + +1427 +01:01:57,685 --> 01:01:59,184 +We searched here. +我们在这里搜索了 + +1428 +01:01:59,186 --> 01:02:04,422 +So maybe we could search for, I don't know, #grammys? +我们也可以搜索一下 #grammys + +1429 +01:02:04,424 --> 01:02:05,689 +And there, we got stuff about the Grammys. +我们得到了有关格莱美的推文 + +1430 +01:02:07,026 --> 01:02:09,159 +Okay? So that's good. +还不错 + +1431 +01:02:09,161 --> 01:02:10,760 +We got searching going. +search 已经完成了 + +1432 +01:02:10,762 --> 01:02:12,528 +So now, let's go back to do what I was gonna do, +我们回到我刚才想做的事情 + +1433 +01:02:12,530 --> 01:02:15,931 +which is let's make that row be a lot better than just +完善 cell 的 UI + +1434 +01:02:15,933 --> 01:02:20,301 +the tweet cut off and then the person who did the tweet. +以显示完整推文还有用户 + +1435 +01:02:20,303 --> 01:02:22,036 +Let's make it a much better UI. +一起制作一个更精良的 UI + +1436 +01:02:22,038 --> 01:02:23,804 +So we're gonna do that with custom cells. +我们会使用自定义的 cell + +1437 +01:02:23,806 --> 01:02:27,775 +So I'm just going to select this cell right here, okay, +我选择这里的 cell + +1438 +01:02:27,777 --> 01:02:30,811 +and change it from being a Subtitle cell to being +把它从 Subtitle 改成 + +1439 +01:02:30,813 --> 01:02:31,644 +a Custom cell. +Custom + +1440 +01:02:33,248 --> 01:02:34,113 +Okay? + +1441 +01:02:34,115 --> 01:02:36,081 +And then inside this Custom cell, +在这个 cell 内部 + +1442 +01:02:36,083 --> 01:02:38,150 +I'm gonna build whatever UI I want. +我就可以制作想要的 UI 了 + +1443 +01:02:38,152 --> 01:02:40,985 +And I'm gonna be able to wire up its outlets and +我也可以通过 UITableViewCell 的子类 + +1444 +01:02:40,987 --> 01:02:43,688 +actions to a subclass of UITableViewCell. +设置 outlet 还有 action + +1445 +01:02:43,690 --> 01:02:46,423 +So let's create that subclass of UITableViewCell. +新建一个 UITableViewCell 子类 + +1446 +01:02:48,360 --> 01:02:50,127 +All right? Again, + +1447 +01:02:50,128 --> 01:02:51,895 +iOS source Cocoa Touch class, this time we don't want +iOS - source - Cocoa Touch Class + +1448 +01:02:51,897 --> 01:02:55,465 +Controller, we want UITableViewCell. +这次我们选择 UITableViewCell + +1449 +01:02:55,467 --> 01:02:58,367 +I'm gonna call this a TweetTableViewCell, +命名为 TweetTableViewCell + +1450 +01:02:58,369 --> 01:03:01,103 +because it shows a tweet, 'kay? +因为它显示 tweet + +1451 +01:03:01,105 --> 01:03:02,838 +Put it in the same place I always put everything. +把文件放到一贯放的位置 + +1452 +01:03:02,840 --> 01:03:04,906 +[COUGH] Here's what it looks like. +它内部是这样的 + +1453 +01:03:04,908 --> 01:03:07,041 +I'm gonna delete these, 'kay? +把这些删去 + +1454 +01:03:08,144 --> 01:03:11,912 +So inside here is where I'm going to put all the code that +在这里,就是为了更新这个自定义 UI + +1455 +01:03:11,914 --> 01:03:16,750 +updates this custom UI that I'm gonna build over here. +放置代码的地方 + +1456 +01:03:16,752 --> 01:03:18,584 +Here's gonna be our custom cell. +这是我们的自定义 cell + +1457 +01:03:18,586 --> 01:03:22,054 +Here's gonna be the code for it, 'kay, our UITableViewCell. +这里是它的代码 + +1458 +01:03:22,056 --> 01:03:23,088 +All right? + +1459 +01:03:23,090 --> 01:03:24,556 +All right. + +1460 +01:03:24,557 --> 01:03:26,023 +So let's set this cells right here, +先设置一下这个 cell + +1461 +01:03:26,026 --> 01:03:30,428 +the identifier of this cell to be our TweetTableViewCell. +把它的类设置为 TweetTableViewCell + +1462 +01:03:31,464 --> 01:03:34,297 +Ok, if you forget this step then obviously you won't be +如果你忘记了这一步 + +1463 +01:03:34,299 --> 01:03:36,333 +able to control drag between these two. +在这两个地方你就不能 Ctrl+drag 了 + +1464 +01:03:36,335 --> 01:03:38,034 +And then lets go ahead and build this UI, +现在来建立 UI + +1465 +01:03:38,036 --> 01:03:40,336 +actually we'll go ahead and get full screen for that. +让它占据整个屏幕 + +1466 +01:03:40,338 --> 01:03:41,270 +I'm gonna build this UI. +现在来搭建 UI + +1467 +01:03:41,272 --> 01:03:43,538 +What do I want this UI to look like? +我想让它变成什么样子呢 + +1468 +01:03:43,540 --> 01:03:46,641 +Okay well, I want it to have. +我需要它有几个 label + +1469 +01:03:46,643 --> 01:03:50,378 +Some labels, obviously, for like the person who, +用于显示发推的用户 + +1470 +01:03:50,380 --> 01:03:53,047 +sent the tweet and the tweet itself and +还有推文本身 + +1471 +01:03:53,049 --> 01:03:57,317 +I'd also like to have an image of the person who tweeted it. +我也想要一个图片来显示发推用户的头像 + +1472 +01:03:57,319 --> 01:03:59,586 +So I want an image view, there as well. +所以我需要一个 imageView + +1473 +01:03:59,588 --> 01:04:03,789 +And I'm going to arrange all this, this ImageView, +安排一下它们的布局 + +1474 +01:04:03,791 --> 01:04:05,691 +I want it to always be a fixed size. +这个 ImageView 我希望它是固定的大小 + +1475 +01:04:05,693 --> 01:04:09,194 +I'm gonna have it be 48 by 48, that's big enough to kinda see +48 * 48,足够看清楚了 + +1476 +01:04:09,196 --> 01:04:11,329 +it, but not big enough that it's dominating the space. +但是没有太占据这部分的空火箭 + +1477 +01:04:11,331 --> 01:04:12,463 +Because this is going to be, +因为 + +1478 +01:04:12,465 --> 01:04:13,998 +each row each row is going to be a tweet, +每一行都是一条推文 + +1479 +01:04:14,000 --> 01:04:17,534 +I want to get as many of them on screen as I can. +我希望一次在屏幕上多看到一些推特 + +1480 +01:04:17,536 --> 01:04:19,803 +So, I'm gonna set this thing to be 48 by 48. +所以我把它设置为 48 * 48 + +1481 +01:04:19,805 --> 01:04:22,872 +I could use the dimensions inspector here to do that. +我可以使用 dimensions inspector 来设置 + +1482 +01:04:22,874 --> 01:04:23,673 +48 by 48. +48 * 48 + +1483 +01:04:23,675 --> 01:04:25,241 +There it is. +好了 + +1484 +01:04:26,210 --> 01:04:28,276 +I'm gonna put this in the upper corner here. +把它放到左上角 + +1485 +01:04:28,278 --> 01:04:30,979 +I'm gonna do the auto layout for this really fast. +快速进行 Auto Layout + +1486 +01:04:30,981 --> 01:04:32,780 +Okay? Because you're hopefully guys +我希望你们已经 + +1487 +01:04:32,782 --> 01:04:34,281 +are getting familiar with that. +熟悉了 + +1488 +01:04:34,283 --> 01:04:36,116 +And also we've got time constraints here so +而且我们也没多少时间了 + +1489 +01:04:36,118 --> 01:04:38,418 +I'm gonna put this thing in the upper corner. +把它放到左上角 + +1490 +01:04:38,420 --> 01:04:39,419 +Top space. +设置 Top Space + +1491 +01:04:40,622 --> 01:04:42,388 +And leading space over there. +Leading Space + +1492 +01:04:42,390 --> 01:04:45,524 +I'm also going to fix its width and height. +固定它的宽度和高度 + +1493 +01:04:45,526 --> 01:04:48,160 +You can drag something onto itself and +你可以拽向它自己 + +1494 +01:04:48,162 --> 01:04:51,763 +then set things like aspect ratio or width and height. +然后设置宽高比,宽度高度之类的 + +1495 +01:04:51,765 --> 01:04:52,797 +Okay? + +1496 +01:04:52,798 --> 01:04:53,830 +So I've set its width and height so that's good. +我设置好了它的高度和宽度,还不错 + +1497 +01:04:53,833 --> 01:04:55,065 +That guy seems to be happy there. +对它的设置已经完成了 + +1498 +01:04:55,067 --> 01:04:56,867 +I don't see any yellow. +我没有看到黄线 + +1499 +01:04:56,869 --> 01:05:00,053 +Let's put this guy. +来放置它 + +1500 +01:05:00,054 --> 01:05:03,238 +This is going to be the name of the person who is tweeting. +它显示推文的作者 + +1501 +01:05:03,241 --> 01:05:04,857 +Okay. + +1502 +01:05:04,858 --> 01:05:06,474 +So I want that to be the whole width, right here, +我希望它占据整个宽度 + +1503 +01:05:06,477 --> 01:05:10,245 +and let's go ahead and hook that up so +来设置它的 + +1504 +01:05:10,247 --> 01:05:11,947 +that it's hooked up to this thing. +Auto Layout + +1505 +01:05:11,949 --> 01:05:15,350 +I'm going to hook up just the horizontal spacing there. +设置与 imageView 的 horizontal spacing + +1506 +01:05:16,319 --> 01:05:17,718 +Let's also hook this up to the top, +把它连接到顶部 + +1507 +01:05:17,720 --> 01:05:21,488 +and let's hook this over to the right. +右边连接到尾部 + +1508 +01:05:21,490 --> 01:05:22,622 +Okay, so we've got that one hooked up. +它已经设置完毕了 + +1509 +01:05:22,624 --> 01:05:23,923 +That one seems happy. +没有黄线,很好 + +1510 +01:05:23,925 --> 01:05:26,625 +Okay, this one is going to be the actual tweet. +这个 label 用来显示推文 + +1511 +01:05:26,627 --> 01:05:29,028 +Now, this one I want to be kinda big, okay, +我想让这个大一点 + +1512 +01:05:29,030 --> 01:05:31,930 +I want it to use a lot of space here. +我想让它占据这里的大部分空间 + +1513 +01:05:31,932 --> 01:05:35,933 +And, normally in a label, if you have more than one line, +通常对于一个 Label 来说,如果内容超出一行 + +1514 +01:05:35,935 --> 01:05:38,169 +it just draws one line and dot dot dot. +它只显示一行,后面的内容省略掉 + +1515 +01:05:38,171 --> 01:05:40,170 +Have you noticed that? +你们注意到了吗 + +1516 +01:05:40,172 --> 01:05:41,672 +So, there is actually a way in label, +在 label 的 + +1517 +01:05:41,674 --> 01:05:44,107 +if you inspect label, to say wrap. +属性里 + +1518 +01:05:44,109 --> 01:05:46,776 +And the way you do that is by saying how many lines you +你可以声明你需要它显示多少行 + +1519 +01:05:46,778 --> 01:05:51,380 +want, and if you specify zero as the lines you want, +如果是 0 的话 + +1520 +01:05:51,382 --> 01:05:53,982 +it'll use as many lines as it needs. +就显示它需要显示的行数 + +1521 +01:05:53,984 --> 01:05:57,552 +So it's kind of a cute way of doing that. +这种解决方式还是挺可爱的 + +1522 +01:05:57,554 --> 01:06:00,655 +Another thing about these labels is they are currently +当前的另一个问题是 + +1523 +01:06:00,657 --> 01:06:02,089 +the system font. +这些 label 使用的是系统字体 + +1524 +01:06:02,091 --> 01:06:04,024 +That is bad. +这很不好 + +1525 +01:06:04,026 --> 01:06:06,593 +Why is it bad that those are the system font? +为什么使用系统字体很不好 + +1526 +01:06:06,595 --> 01:06:09,863 +Because the system font is not for the user's content. +因为系统字体不能适用 user's content + +1527 +01:06:09,865 --> 01:06:11,931 +Okay, I talked about this in one of the lectures. +我在之前讲过 + +1528 +01:06:11,933 --> 01:06:15,568 +User's content, you want to use the preferred font, which +你需要使用首选的字体 + +1529 +01:06:15,570 --> 01:06:19,404 +you can get to by picking this little typeface here and +选择这个小字形图标 + +1530 +01:06:19,406 --> 01:06:21,439 +going down to text styles. +去到 text styles + +1531 +01:06:21,441 --> 01:06:23,374 +So this is the tweet itself so +这是推文,类似于正文 + +1532 +01:06:23,376 --> 01:06:26,744 +that's kind of the body of the user's information here. +所以应该使用 body + +1533 +01:06:26,746 --> 01:06:31,081 +And this one which is the user who tweeted it. +对于这个,发推的用户 + +1534 +01:06:31,083 --> 01:06:33,516 +That's kind of like a header or a caption or +它类似于标题 + +1535 +01:06:33,518 --> 01:06:35,285 +header at the top. +顶部的标题 + +1536 +01:06:35,286 --> 01:06:37,053 +So I'm gonna pick Headline Style for that. +所以我选择 Headline + +1537 +01:06:37,055 --> 01:06:40,056 +So these fonts are going to be picked by the system +这些字体会被系统选择 + +1538 +01:06:40,058 --> 01:06:41,123 +to look nice. +以较好地方式呈现 + +1539 +01:06:41,125 --> 01:06:43,492 +Also if the user goes into Settings. +当用户在设置中 + +1540 +01:06:43,494 --> 01:06:46,761 +And changes their preferred font size, +改变了首选字体的大小 + +1541 +01:06:46,763 --> 01:06:48,029 +these will get bigger. +这些也会相应变大 + +1542 +01:06:48,031 --> 01:06:50,364 +And since I'm gonna build my UI to be flexible, +我为了让 UI 更有适应性 + +1543 +01:06:50,366 --> 01:06:53,834 +my cells will just get bigger in that case, or smaller. +cell 在那种情况下会变大或者变小 + +1544 +01:06:53,836 --> 01:06:55,302 +So it's all gonna happen automatically. +这些都是自动发生的 + +1545 +01:06:55,304 --> 01:06:57,871 +I don't have to actually do anything to make that happen, +我实际上不需要做什么事情 + +1546 +01:06:57,873 --> 01:07:00,340 +except for do my auto layout right. +我做好 Auto Layout 就足够了 + +1547 +01:07:01,409 --> 01:07:02,708 +Okay, so I got that one. +它已经放好了 + +1548 +01:07:02,710 --> 01:07:06,144 +Let's go ahead and Control + drag this one up to here. +Ctrl+drag 设置它的 layout + +1549 +01:07:06,146 --> 01:07:08,413 +Here I'm going to set both the vertical spacing. +在这里选择 vertical spacing + +1550 +01:07:08,415 --> 01:07:11,315 +I'm also going to line up these left edges. +还有,我希望它们的左边 + +1551 +01:07:11,317 --> 01:07:14,752 +Make sure the left edges of these two line up together. +是对齐的 + +1552 +01:07:15,721 --> 01:07:18,288 +I want this edge to be here. +右边在这儿 + +1553 +01:07:18,290 --> 01:07:20,423 +I want this one to be, oops. +这里,喔 + +1554 +01:07:22,626 --> 01:07:25,761 +Down to the bottom here. +去到底部 + +1555 +01:07:25,763 --> 01:07:26,628 +I think that's probably good. +我认为看起来还不错 + +1556 +01:07:26,630 --> 01:07:27,729 +Let's see if I forgot anything. +看看我是否忘记了什么 + +1557 +01:07:27,731 --> 01:07:29,280 +Oh yeah. + +1558 +01:07:29,281 --> 01:07:30,830 +Two views are vertically ambiguous. +两个 view 在垂直方向有歧义 + +1559 +01:07:30,833 --> 01:07:31,832 +Okay? These two views +这两个 view + +1560 +01:07:31,834 --> 01:07:33,533 +it says are vertically ambiguous. +在垂直方向引发歧义 + +1561 +01:07:33,535 --> 01:07:35,835 +That's again, our friend, the hugging. +再一次,需要我们的好朋友,hugging + +1562 +01:07:35,837 --> 01:07:37,387 +Okay? + +1563 +01:07:37,388 --> 01:07:38,938 +One of these two, these are both labels. +它俩都是 label + +1564 +01:07:38,940 --> 01:07:41,574 +They both want to hug exactly the same amount. +它们 hug 的数值都是相同的 + +1565 +01:07:41,576 --> 01:07:44,443 +If I look at them, you can see they both have a hugging +它们垂直方向的 Hug 优先级 + +1566 +01:07:44,445 --> 01:07:45,677 +priority vertically of 251, 251 and 251. +都是 251 + +1567 +01:07:45,679 --> 01:07:50,648 +So I have to pick one of these that's not gonna hug. +所以我选择其中一个让它 hug 优先级没那么高 + +1568 +01:07:50,650 --> 01:07:51,882 +Now it's not gonna matter here, +在这里不是问题 + +1569 +01:07:51,884 --> 01:07:55,419 +actually, because my whole row is going to hug, so +因为我们整个 row 都会 hug + +1570 +01:07:55,421 --> 01:07:57,187 +there both going to get to hug. +所以这俩 label 也都会 hug + +1571 +01:07:57,189 --> 01:08:00,457 +But, I still have to pick one that has priority for hugging, +但是我仍然需要调整其中一个的 hug 优先级 + +1572 +01:08:00,459 --> 01:08:04,493 +so I'm gonna make the big one here be less likely to hug. +把这个大一点的 hug 优先级调小一点 + +1573 +01:08:04,495 --> 01:08:05,994 +So as soon as I change that, +我更改完成后 + +1574 +01:08:05,996 --> 01:08:09,131 +now you can see only frames are the problem. +只有 frame 是问题了 + +1575 +01:08:09,133 --> 01:08:10,899 +So let's go here and update our frames. +所以我们更新一下 frame + +1576 +01:08:14,404 --> 01:08:17,838 +Okay, so it looks good, it's all looking good in there. +看起来还不错 + +1577 +01:08:17,840 --> 01:08:19,807 +I actually was going to also put a little thing +我也想在这里放个 Label + +1578 +01:08:19,809 --> 01:08:21,241 +here that says the time of the Tweet but +显示 tweet 的时间 + +1579 +01:08:21,243 --> 01:08:23,176 +I'm going to skip that for time. +但是时间已经不够了,我就不做了 + +1580 +01:08:23,178 --> 01:08:26,079 +I'll do it in the code I post, I'll put it in there though. +我会放到发布的代码里 + +1581 +01:08:26,081 --> 01:08:28,948 +All right, so we've got this UI kind of looking the way we +我们已经得到了 + +1582 +01:08:28,950 --> 01:08:31,150 +want it to look. +想要的 UI + +1583 +01:08:31,152 --> 01:08:34,152 +How are we going to hook it up to our table view cell? +我们怎么把它们和 tableViewCell 连接起来呢 + +1584 +01:08:34,154 --> 01:08:36,888 +Well, we're gonna do just like we do anything else. +就像之前做的一样 + +1585 +01:08:36,890 --> 01:08:38,523 +Control dragging. +Ctrl+drag + +1586 +01:08:38,525 --> 01:08:40,524 +All right, so we've got our UI here. +所以我们得到了 UI + +1587 +01:08:40,526 --> 01:08:42,659 +Let's hook up let's say our image view, so +把 imageView 连接起来 + +1588 +01:08:42,661 --> 01:08:44,594 +I'm gonna drag this in here. +把它拽过来 + +1589 +01:08:44,596 --> 01:08:47,530 +This is going to be called my TweetImageView. +命名为 tweetImageView + +1590 +01:08:47,532 --> 01:08:48,965 +Going to show that. +显示出来了 + +1591 +01:08:48,967 --> 01:08:52,735 +And then, I'm going to drag this one, which is going to be +接着把它拽过来 + +1592 +01:08:52,737 --> 01:08:58,106 +my tweetScreenName, I think I called that. +命名为 tweetScreenName + +1593 +01:08:58,108 --> 01:09:01,576 +And this is going to be the actual tweet text. +这个作为显示推文的 + +1594 +01:09:01,578 --> 01:09:05,679 +tweetTextLabel. +起名为 tweetTextLabel + +1595 +01:09:05,681 --> 01:09:07,131 +Okay. + +1596 +01:09:07,132 --> 01:09:08,582 +So I got my outlets in here, and so +我已经设置好了 outlet + +1597 +01:09:08,584 --> 01:09:12,819 +now I just need the code that makes all these outlets get +现在我需要通过代码,当某人设置了 tweet + +1598 +01:09:12,821 --> 01:09:15,221 +updated when someone sets the tweet. +我需要更新 UI + +1599 +01:09:15,223 --> 01:09:17,823 +So I need some public API, which is going to be a tweet. +所以我需要一些公共 API,一个 tweet 变量 + +1600 +01:09:17,825 --> 01:09:19,891 +Okay. This is going to be the public +它是我 TweetTableViewCell + +1601 +01:09:19,893 --> 01:09:22,060 +API of my TweetTableViewCell, +的公共 API + +1602 +01:09:22,062 --> 01:09:26,330 +it's what I'm going to use in my self erode index path. +我需要在 cellForRowAtIndexPath 调用 + +1603 +01:09:26,332 --> 01:09:27,931 +To set that up. +把它设置好 + +1604 +01:09:27,933 --> 01:09:29,633 +So when the tweet is set, +当 tweet 被设置的时候 + +1605 +01:09:29,635 --> 01:09:32,969 +let's do a didSet right here and update our UI. +这里加个 didSet 更新 UI + +1606 +01:09:32,971 --> 01:09:36,806 +Okay, and in updateUI, +在 updateUI 中 + +1607 +01:09:36,808 --> 01:09:41,610 +then I'm going to do all this. +我会做这些 + +1608 +01:09:43,480 --> 01:09:45,613 +So that's what I'm going to do. +我会做这些事情 + +1609 +01:09:45,615 --> 01:09:48,215 +Tweet created a label I decided we're going to save +为了节省时间 + +1610 +01:09:48,217 --> 01:09:50,468 +some time and not do that but +tweetCreatedLabel 就不做了 + +1611 +01:09:50,469 --> 01:09:52,720 +I'll uncomment this out and put that in when I post this. +当我发布代码的时候不会注释这些 + +1612 +01:09:52,722 --> 01:09:56,223 +But all this does here is just sets the tweet's label +这里做的,就是设置好 tweetLabel + +1613 +01:09:56,225 --> 01:09:58,191 +text label to the tweet's text. +设置为 tweet 的 text + +1614 +01:09:58,193 --> 01:10:00,426 +It sets to screen name to the user and +把 tweetScrrenName 设置为 user + +1615 +01:10:00,428 --> 01:10:04,463 +it sets the profile image to the users profile image here. +设置 profileImage 为用户的 头像 + +1616 +01:10:04,465 --> 01:10:06,599 +Okay? + +1617 +01:10:06,600 --> 01:10:08,734 +Now, notice this one right here, blocks the main thread. +注意这里,阻塞了主线程 + +1618 +01:10:09,703 --> 01:10:11,936 +So, in your homework, one of the required tasks is, +在你们的作业中,必须要完成的任务是 + +1619 +01:10:11,938 --> 01:10:13,170 +you can't block the main threads, so +不能阻塞主线程 + +1620 +01:10:13,172 --> 01:10:15,806 +you better fix this, okay? +所以你最好修复这个问题 + +1621 +01:10:15,808 --> 01:10:18,141 +I'm not gonna fix it, but you, you had better. +我不会修改它,但是你们必须得修改 + +1622 +01:10:18,143 --> 01:10:20,010 +And anywhere else you block the main thread, +所有阻塞主线程的地方 + +1623 +01:10:20,012 --> 01:10:21,878 +you're gonna fix, okay? +你都得修复 + +1624 +01:10:24,015 --> 01:10:27,416 +All right, so now, all we need to do is go back to our +现在回到 controller 里 + +1625 +01:10:27,418 --> 01:10:31,253 +controller right here and now our self erode index path is +cellForRowAtIndexPath 方法会有一点不同 + +1626 +01:10:31,255 --> 01:10:34,823 +going to be a little bit different because our thing is +因为 cell 不再是 UITableViewCell + +1627 +01:10:34,825 --> 01:10:39,193 +not a UITableViewCell anymore, it's a TweetTableViewCell. +而是 TweetTableViewCell + +1628 +01:10:40,463 --> 01:10:42,295 +And we're not going to do these things right here, +我们不会在这里做这些 + +1629 +01:10:42,297 --> 01:10:44,364 +the detail label and the text label. +detail label 还有 text label + +1630 +01:10:44,366 --> 01:10:46,599 +Instead we're going to set that public API. +而是调用公共 API + +1631 +01:10:46,601 --> 01:10:53,105 +Which is cell.tweet = the tweet, which is actually this. +也就是 cell.tweet = tweet + +1632 +01:10:53,107 --> 01:10:55,741 +So actually, I'll make my code look nice and go like that, +我让我的代码看起来整洁一些 + +1633 +01:10:55,743 --> 01:10:58,910 +get rid of that, get rid of that. +去掉这些,这些 + +1634 +01:10:58,912 --> 01:11:00,745 +So actually our code got simpler here, +实际上代码在这里变得更干净了 + +1635 +01:11:00,747 --> 01:11:02,580 +because we transfer a lot of the responsibility +因为我们把大量的显示 cell 的工作 + +1636 +01:11:02,582 --> 01:11:06,450 +to display the thing into our tweetTableView cell, +放到了 tweetTableViewCell 中 + +1637 +01:11:06,452 --> 01:11:08,485 +which is over here, all right? +也就是在这里 + +1638 +01:11:08,487 --> 01:11:11,721 +Everyone understand we're configuring this cell by using +我们通过公共 API + +1639 +01:11:11,723 --> 01:11:13,489 +this public API. +来配置这个 cell + +1640 +01:11:13,491 --> 01:11:14,390 +It's gonna update its UI, +它会更新它的 UI + +1641 +01:11:14,392 --> 01:11:17,059 +which is gonna set all these outlets. +把所有的 outlet 设置好 + +1642 +01:11:17,061 --> 01:11:17,959 +Everyone cool with that? +都懂了吧? + +1643 +01:11:19,362 --> 01:11:21,095 +All right, let's see if I forgot anything. +让我们看看我又没有往后急什么 + +1644 +01:11:23,732 --> 01:11:25,198 +All right, look at this. +看 + +1645 +01:11:25,200 --> 01:11:27,000 +Okay, this is looking a little better. +看起来好多了 + +1646 +01:11:27,002 --> 01:11:28,434 +It's still not quite right. +但还是不太对 + +1647 +01:11:28,436 --> 01:11:31,670 +Because look, all these rows are the same height. +因为所有的 row 都是相同的高度 + +1648 +01:11:31,672 --> 01:11:33,772 +Even if the tweet inside is small. +即使其中的推文很短 + +1649 +01:11:33,774 --> 01:11:35,240 +Okay? + +1650 +01:11:35,242 --> 01:11:36,441 +So why is that happening? +为什么会这样呢 + +1651 +01:11:36,443 --> 01:11:40,244 +Well that's been happening because by default, +因为默认的情况 + +1652 +01:11:40,246 --> 01:11:43,113 +if you look in the storyboard, okay, +打开 storyboard + +1653 +01:11:43,115 --> 01:11:46,016 +if you take a particular cell here,. +点击这个 cell + +1654 +01:11:46,018 --> 01:11:48,952 +Okay, Ctrl+Shift, pick the cell, and +Ctrl+Shift 选择 cell + +1655 +01:11:48,954 --> 01:11:53,289 +you inspect right here, you'll see its row height is fixed, +在右侧,你可以看到它的高度是固定的 + +1656 +01:11:53,291 --> 01:11:55,924 +okay, fixed to 162 points high. +162 高 + +1657 +01:11:55,926 --> 01:11:57,225 +And I don't want that. +我不想要这样 + +1658 +01:11:57,227 --> 01:11:59,561 +I want this basically to be the estimate, +这个 162 + +1659 +01:11:59,563 --> 01:12:02,130 +this 162 I want to be an estimate, but I want +是估计的值 + +1660 +01:12:02,132 --> 01:12:05,166 +it to actually calculate it using the auto-layout. +但是我想通过 auto layout 计算它的高度 + +1661 +01:12:05,168 --> 01:12:09,236 +So I'm going to fix that in here. +所以我在这里修复这个问题 + +1662 +01:12:09,238 --> 01:12:10,470 +I'll do it in viewDidLoad. +在 viewDidLoad 中 + +1663 +01:12:10,472 --> 01:12:11,871 +Where's my viewDidLoad? +跑哪去了 + +1664 +01:12:11,873 --> 01:12:13,372 +Up here. +在这里 + +1665 +01:12:13,374 --> 01:12:20,345 +I'm going to say that my tableView's estimatedRowHeight +tableView.estimatedRowHeight + +1666 +01:12:20,347 --> 01:12:24,816 +equals the tableView's rowHeight. + = tableView.rowHeight + +1667 +01:12:24,818 --> 01:12:27,685 +So that's the height it has coming out of the storyboard. +这是 storyboard 中出现的高度 + +1668 +01:12:27,687 --> 01:12:31,955 +And then I'll reset the tableView's rowHeight, +接着我重新设置 tableView.rowHeigth + +1669 +01:12:31,957 --> 01:12:35,258 +to UITableViewAutomaticDimension. + = UITableViewAutomaticDimension + +1670 +01:12:35,260 --> 01:12:37,160 +Okay? + +1671 +01:12:37,161 --> 01:12:39,061 +So when you set the rowHeight to this automatic dimension, +当你设置为这个值的时候 + +1672 +01:12:39,064 --> 01:12:40,629 +that means calculate the size. +这意味着计算它的尺寸 + +1673 +01:12:40,631 --> 01:12:44,033 +But it's gonna use whatever rowHeight is in the storyboard +但是它会把 storyboard 的值 + +1674 +01:12:44,035 --> 01:12:44,966 +as an estimate. +当做估计值 + +1675 +01:12:44,968 --> 01:12:46,701 +Okay. So, see if that works. +一起看看好用了槑 + +1676 +01:12:46,703 --> 01:12:49,437 +Now, if I got my, yeah, it looks like it works fine. +看起来不错 + +1677 +01:12:49,439 --> 01:12:51,272 +You see, this one's nice and small. +这个看起来很小很不错 + +1678 +01:12:51,274 --> 01:12:52,072 +This one's larger. +这个大一些 + +1679 +01:12:52,074 --> 01:12:54,641 +Et cetera. + +1680 +01:12:54,643 --> 01:12:55,942 +Okay. + +1681 +01:12:55,944 --> 01:12:57,477 +Was there something there I'm going to have to bleep +这里有需要在 iTunes U + +1682 +01:12:57,479 --> 01:12:58,944 +out on iTunes U or something? +中打码的内容吗? + +1683 +01:12:58,946 --> 01:12:59,812 +I don't know. +我不知道 + +1684 +01:12:59,814 --> 01:13:00,579 +Be careful there. +还是注意点 + +1685 +01:13:01,615 --> 01:13:05,049 +Oh, look at this, let's see, look at that. +看这个 + +1686 +01:13:05,051 --> 01:13:05,849 +Nice, okay. + +1687 +01:13:05,851 --> 01:13:09,870 +>> [LAUGH]. + +1688 +01:13:09,871 --> 01:13:13,890 +>> Now, your homework, your homework, Jessie, +你们的作业,Jessie~ + +1689 +01:13:13,892 --> 01:13:18,961 +is going to be a couple of things. +有几项内容 + +1690 +01:13:18,963 --> 01:13:20,996 +One, to highlight all these mentions. +一,高亮这些 @ + +1691 +01:13:20,998 --> 01:13:24,232 +The hashtags, users, etc. +# 等等 + +1692 +01:13:24,234 --> 01:13:25,967 +And also, when you click on one, +当你点击其中一条推文的时候 + +1693 +01:13:25,969 --> 01:13:29,003 +you're going to segue to a new table view you're going to +你需要跳转到一个新的 tableView + +1694 +01:13:29,005 --> 01:13:32,106 +write that's going to show all the images that are attached +显示推文附带的所有图片 + +1695 +01:13:32,108 --> 01:13:33,774 +and all those hashtags, etc. +所有 # + +1696 +01:13:33,776 --> 01:13:36,810 +And then you'll be able to click on those again to keep +然后你可以点击这些 + +1697 +01:13:36,812 --> 01:13:37,644 +navigating. +继续跳转 + +1698 +01:13:37,646 --> 01:13:39,629 +Okay? + +1699 +01:13:39,630 --> 01:13:41,613 +That's the base of your assignment. +这是你们作业的基本要求 + +1700 +01:13:41,616 --> 01:13:43,482 +Okay? + +1701 +01:13:43,484 --> 01:13:46,118 +Now, the last thing I'm going to show here is +最后一件事 + +1702 +01:13:46,120 --> 01:13:48,754 +how to basically refresh this table, because tweets +是如何刷新 table + +1703 +01:13:48,756 --> 01:13:52,290 +are always happening as we notice right here from Jessie. +因为人们时刻发送推文,就像 Jessie + +1704 +01:13:52,292 --> 01:13:54,359 +Maybe Jessie's still tweeting, I don't know. +也许 Jessie 还在发推,我不知道 + +1705 +01:13:54,361 --> 01:13:57,194 +We can't see the rest of her things without quitting our +如果不退出重新进入 app + +1706 +01:13:57,196 --> 01:13:59,280 +app and restarting. +就看不到她新发的推 + +1707 +01:13:59,281 --> 01:14:01,365 +So what I want to be able to do is pull down on my table +我希望做的,就是下拉刷新 + +1708 +01:14:01,367 --> 01:14:04,568 +view and have a little spinner come up up here. +上面会有一个旋转的指针 + +1709 +01:14:04,570 --> 01:14:06,102 +And have it fetch again. +让它继续获取推文 + +1710 +01:14:06,104 --> 01:14:09,806 +And when it's done, add that to my list. +当完成的时候,添加到我的 model 中 + +1711 +01:14:09,808 --> 01:14:11,941 +So that's what we're gonna do right here. +我们需要做这些 + +1712 +01:14:11,943 --> 01:14:13,909 +First of all, how do you get that spinner? +首先,怎样能获得等待的圆圈 + +1713 +01:14:13,911 --> 01:14:15,143 +Okay? Real easy. +很简单 + +1714 +01:14:15,145 --> 01:14:16,578 +You go to your storyboard. +打开 storyboard + +1715 +01:14:16,580 --> 01:14:18,312 +You click your table view. +点击 tableview + +1716 +01:14:18,314 --> 01:14:19,580 +Okay? You go over here +打开这里 + +1717 +01:14:19,582 --> 01:14:20,614 +to inspect it. +检查它 + +1718 +01:14:21,950 --> 01:14:23,416 +All right. And then the inspector, +在这其中 + +1719 +01:14:23,418 --> 01:14:26,085 +actually you inspect the controller. +实际上你在检查 controller + +1720 +01:14:26,087 --> 01:14:27,653 +You look right here, it says, refreshing. +看这里,写着 refreshing + +1721 +01:14:27,655 --> 01:14:29,555 +See, it says, refreshing disabled. +现在是关闭的 + +1722 +01:14:29,557 --> 01:14:31,690 +That means refreshing is not allowed in this table, so +这意味着这个 table 不能下拉刷新 + +1723 +01:14:31,692 --> 01:14:33,258 +I'm going to enable that. +把这个功能开启 + +1724 +01:14:33,260 --> 01:14:34,759 +Now, nothing appears to have happened. +表面上什么也没发生 + +1725 +01:14:34,761 --> 01:14:36,127 +You don't see the little spinner +你没看到小圆圈 + +1726 +01:14:36,129 --> 01:14:38,395 +appear here on the storyboard. +出现在 storyboard 中 + +1727 +01:14:38,397 --> 01:14:39,830 +The place it actually appears +它出现的位置是在 + +1728 +01:14:39,832 --> 01:14:41,931 +is over here on the document outline. +这里的 document outline + +1729 +01:14:41,933 --> 01:14:43,132 +There it is right there. +在这里 + +1730 +01:14:43,134 --> 01:14:44,233 +Okay? That's the refresh control. +它是 refresh control + +1731 +01:14:44,235 --> 01:14:46,669 +Now, that refresh control is a normal control. +现在这个 refresh control 是一个普通的 control + +1732 +01:14:46,671 --> 01:14:50,372 +You can Ctrl+drag from it to create an action, +你可以 Ctrl+drag 创建一个 action + +1733 +01:14:50,374 --> 01:14:51,573 +which is exactly what I'm going to do. +我也会这么做 + +1734 +01:14:51,575 --> 01:14:57,978 +I'm going to put that action right in my controller. +把它放到 controller 中 + +1735 +01:14:57,980 --> 01:14:58,812 +So here's my controller. +打开 controller + +1736 +01:14:58,814 --> 01:15:00,380 +Let's put it, +把它放到 + +1737 +01:15:00,382 --> 01:15:02,882 +we're going to put it up towards the top here. +上面这里 + +1738 +01:15:02,884 --> 01:15:04,217 +Maybe right here. +这里 + +1739 +01:15:04,219 --> 01:15:06,118 +Okay. So I'm going to Ctrl+drag +Ctrl+drag + +1740 +01:15:06,120 --> 01:15:09,688 +from the document outline, okay, over here. +从 document outline 拖动 + +1741 +01:15:09,690 --> 01:15:10,756 +And it's going to be an action. +新建一个 action + +1742 +01:15:10,758 --> 01:15:13,525 +I'm going to call it refresh. +起名为 refresh + +1743 +01:15:13,527 --> 01:15:16,327 +It's going to have an argument which is this refresh control +参数是这个 refresh control + +1744 +01:15:16,329 --> 01:15:18,446 +itself. +它本身 + +1745 +01:15:18,447 --> 01:15:20,564 +You can also get this refresh control by calling the method +你可以通过调用 refresh + +1746 +01:15:20,566 --> 01:15:22,499 +refresh, or the property refresh control, +获取 refresh control + +1747 +01:15:22,501 --> 01:15:24,601 +in UITableViewController. +在 UITableViewController 中 + +1748 +01:15:24,603 --> 01:15:26,520 +So here it is, +在这里 + +1749 +01:15:26,521 --> 01:15:28,438 +this is what's going to get called every time we refresh. +我们每次刷新,这里都会被调用 + +1750 +01:15:28,440 --> 01:15:30,540 +So just to show you what refreshing looks like +让你们看看刷新在 UI 中 + +1751 +01:15:30,542 --> 01:15:31,958 +in the UI. +是什么效果 + +1752 +01:15:31,959 --> 01:15:33,375 +It looks like this. +它看起来是这样 + +1753 +01:15:33,378 --> 01:15:34,777 +So here it is, I want to refresh. +我想刷新 + +1754 +01:15:34,779 --> 01:15:35,944 +See that little spinner? +看到小圆圈了吗 + +1755 +01:15:35,946 --> 01:15:37,312 +And I let go, and it's spinning. +松手,它开始转动 + +1756 +01:15:37,314 --> 01:15:40,014 +Now, it never stops spinning here because +它永远不会停止 + +1757 +01:15:40,016 --> 01:15:41,349 +I don't do anything. +因为我没有做任何事 + +1758 +01:15:41,351 --> 01:15:43,017 +So it doesn't know when I'm done. +所以我完成以后它并不知道 + +1759 +01:15:43,019 --> 01:15:46,119 +So what do we want to do when this refresh happens? +所以当刷新动作发生的时候,我们该做什么 + +1760 +01:15:46,121 --> 01:15:50,656 +Well, actually, we want to take that search, whatever +实际上我们需要再搜索一次 + +1761 +01:15:50,658 --> 01:15:55,060 +the last search we did here for tweets, and we wanna get +我们上次一搜索的 tweet + +1762 +01:15:55,062 --> 01:15:58,030 +a follow on search that says, give me more of those. +我们想根据上次搜索,再进行一次 + +1763 +01:15:58,032 --> 01:16:00,265 +Well, TwitterRequest that I provided for +在 TwitterRequest 中我提供了一个 + +1764 +01:16:00,267 --> 01:16:03,134 +you has a nice property that if you give it a request that +不错的属性 + +1765 +01:16:03,136 --> 01:16:04,602 +you've already successfully made, +如果你再次搜索已经搜索过的 + +1766 +01:16:04,604 --> 01:16:06,770 +it'll give you a request to get more. +它会再给你一个 request 获得更多 tweets + +1767 +01:16:06,772 --> 01:16:08,338 +Okay? So that's exactly what we're +我们也会 + +1768 +01:16:08,340 --> 01:16:09,740 +gonna do. +这么做 + +1769 +01:16:09,741 --> 01:16:11,141 +I'm gonna add a couple of new properties. +添加几个属性 + +1770 +01:16:11,143 --> 01:16:17,179 +One is called my lastSuccessfulRequest. +一个叫做 lastSuccessfulRequest + +1771 +01:16:17,181 --> 01:16:19,415 +Okay? + +1772 +01:16:19,416 --> 01:16:21,650 +Which is gonna be a TwitterRequest. +类型是 TwitterRequest + +1773 +01:16:22,686 --> 01:16:26,320 +'Kay, so that's gonna be the last one I successfully did, +就是我上次成功执行的请求 + +1774 +01:16:26,322 --> 01:16:27,321 +and I'm gonna have another one, +再添加另外一个 + +1775 +01:16:27,323 --> 01:16:29,957 +which is my nextRequestToAttempt, +起名为 + +1776 +01:16:29,959 --> 01:16:31,275 +that's what I called it. +nextRequestToAttempt + +1777 +01:16:31,276 --> 01:16:32,592 +That's also gonna be a TwitterRequest. +类型也是 TwitterRequest + +1778 +01:16:34,663 --> 01:16:37,497 +And this one is actually gonna be a calculated property, +它会是一个计算属性 + +1779 +01:16:37,499 --> 01:16:39,665 +because I'm gonna be able to calculate the next one +因为我会根据上一次的请求 + +1780 +01:16:39,667 --> 01:16:40,933 +based on the last one. +计算下一次的请求 + +1781 +01:16:40,935 --> 01:16:44,836 +So that's simple, I say if I had a last successful request, +很简单,如果上一次请求不是 nil + +1782 +01:16:44,838 --> 01:16:47,972 +okay, that's, oh, sorry, let's say if I don't have one. +抱歉,如果上一次成功请求是 nil + +1783 +01:16:47,974 --> 01:16:49,941 +If I don't have a last successful request, +也就是没有上一次成功请求 + +1784 +01:16:49,943 --> 01:16:51,142 +then let's make one. +然后我会执行一次 + +1785 +01:16:51,144 --> 01:16:52,543 +We have that right here, +这里有 + +1786 +01:16:52,545 --> 01:16:55,612 +so I'm going to put this line right here. +把它放到这里 + +1787 +01:16:55,614 --> 01:16:58,648 +So this TwitterRequest right here, this search, +如果 searchText 不是 nil + +1788 +01:16:58,650 --> 01:17:04,653 +I'm going to make that be my +我们就把它当做 + +1789 +01:17:04,655 --> 01:17:08,090 +request if the search text is not nil. +下一次的请求 + +1790 +01:17:08,092 --> 01:17:13,728 +Then I'm going to return that as my next request to attempt. +把它返回 + +1791 +01:17:13,730 --> 01:17:15,830 +And here I'm just going to do request, +在这,令 request = + +1792 +01:17:15,832 --> 01:17:17,665 +next RequestToAttempt. +nextRequestToAttempt + +1793 +01:17:17,667 --> 01:17:19,366 +So this place where I was fetching before, +这是我之前获取的位置 + +1794 +01:17:19,368 --> 01:17:22,602 +instead of always fetching the search text, instead I'm going +我们会执行 nextRequestAttempt 而不是根据 + +1795 +01:17:22,604 --> 01:17:25,205 +to do nextRequestAttempt, which, if we've never had +seartchText 而进行搜索 + +1796 +01:17:25,207 --> 01:17:28,207 +a successful request, is going to be that same search. +如果没有上一次成功的搜索,那这一次新的搜索 + +1797 +01:17:28,209 --> 01:17:32,178 +But if we have successfully requested something, +如果上一次成功了 + +1798 +01:17:32,180 --> 01:17:36,615 +then I'm going to return our last successful request's +我们就返回 + +1799 +01:17:36,617 --> 01:17:38,183 +requestForNewer. +lastSuccessfulRequest?.requestForNewer + +1800 +01:17:38,185 --> 01:17:39,584 +Okay? + +1801 +01:17:39,586 --> 01:17:41,552 +And this exclamation point, +这里应该是感叹号 + +1802 +01:17:41,554 --> 01:17:45,389 +because I already checked that to make sure it's not nil. +因为我已经检查过确保它不是 nil + +1803 +01:17:45,391 --> 01:17:48,324 +Okay, everyone got that? +每个人都懂了吗 + +1804 +01:17:48,326 --> 01:17:50,626 +What's the problem here? +这里有什么问题 + +1805 +01:17:50,628 --> 01:17:55,964 +lastSuccessfulRequest!.requestForNewer. + +1806 +01:17:55,966 --> 01:17:58,300 +Oh, yeah, let's make this be an optional right here. +把它变成 optional + +1807 +01:17:59,336 --> 01:18:00,335 +Okay? So + +1808 +01:18:00,336 --> 01:18:01,335 +that can be an optional too. +它也可以是 optional 的 + +1809 +01:18:01,338 --> 01:18:02,670 +And since that can be an optional, +既然它可以是 optional + +1810 +01:18:02,672 --> 01:18:04,839 +we'd better check it here. +我们最好在这里检查一下 + +1811 +01:18:04,840 --> 01:18:07,007 +If we can find a request, then we'll do this. +如果 request 不是 nil,执行下面这些 + +1812 +01:18:12,681 --> 01:18:14,447 +Well, you pay the price if you press the wrong key. +你必须为按错键付出代价 + +1813 +01:18:14,449 --> 01:18:16,382 +Okay, luckily, we have undo. +还好我们有取消 + +1814 +01:18:16,384 --> 01:18:18,550 +Okay, so there we go. +好了 + +1815 +01:18:18,552 --> 01:18:19,551 +So that's it. +就是这样 + +1816 +01:18:19,552 --> 01:18:20,551 +So now we are also doing it. +有一点点 + +1817 +01:18:20,554 --> 01:18:24,355 +Now, the only thing here is, +小问题 + +1818 +01:18:24,357 --> 01:18:28,359 +otherwise we'll return nil. +否则,返回 nil + +1819 +01:18:28,361 --> 01:18:30,427 +The only thing here that we need to do is, +我们还有一件事需要做 + +1820 +01:18:30,429 --> 01:18:33,730 +every time our search changes, we need to set our +每一次搜索改变了以后,需要把 + +1821 +01:18:33,732 --> 01:18:37,533 +lastSuccessfulRequest equal to nil. +lastSuccessfulRequest 设置为 nil + +1822 +01:18:37,535 --> 01:18:38,868 +Okay? + +1823 +01:18:38,869 --> 01:18:40,202 +Cuz we, as soon as we're searching something new, +因为当我们搜索新的内容的时候 + +1824 +01:18:40,204 --> 01:18:41,903 +now our last request doesn't matter, so +lastSuccessfulRequest 就不重要了 + +1825 +01:18:41,905 --> 01:18:43,271 +we're gonna set it to nil. +所以设置为 nil + +1826 +01:18:43,273 --> 01:18:46,074 +And that's gonna cause this next request to make +这就会引发 request + +1827 +01:18:46,076 --> 01:18:47,208 +a new search. +执行一次新的搜索 + +1828 +01:18:48,711 --> 01:18:50,477 +Okay? And then the last thing we +最后一件事儿 + +1829 +01:18:50,479 --> 01:18:52,979 +need to do is turn off that little spinner. +就是停止小圆圈 + +1830 +01:18:52,981 --> 01:18:54,114 +Okay? + +1831 +01:18:54,115 --> 01:18:55,248 +So where are we gonna turn off the spinner? +我们在哪里关闭 spinner + +1832 +01:18:55,250 --> 01:18:59,818 +Well, if we go off to do some searching, then when we +如果我们执行了一些搜索,结果返回了 + +1833 +01:18:59,820 --> 01:19:03,689 +come back, we can have our refresh control turn off. +我们就可以把 refresh control 关闭 + +1834 +01:19:03,691 --> 01:19:07,759 +I'm gonna move this right down here into that target action, +把这些挪到 target action 中 + +1835 +01:19:08,761 --> 01:19:10,327 +okay, because I'll have my refresh control then. +因为这里有 refresh control + +1836 +01:19:10,329 --> 01:19:13,296 +So I'm gonna say sender?.endRefreshing. +这里,sender?.endRefreshing + +1837 +01:19:13,298 --> 01:19:15,598 +Is that what it's called? +是这么写的吗? + +1838 +01:19:15,600 --> 01:19:17,400 +Oh, yeah, endRefreshing. +哦,是 + +1839 +01:19:17,402 --> 01:19:19,201 +Let's go ahead and make this an optional. +把它变成 optional + +1840 +01:19:19,203 --> 01:19:21,337 +Which you're allowed to do for a target action argument, +target action 的参数允许你这么做 + +1841 +01:19:21,339 --> 01:19:22,237 +make that an optional. +把它变成 optional + +1842 +01:19:23,240 --> 01:19:24,489 +I'm gonna say that. +我会这样写 + +1843 +01:19:24,490 --> 01:19:25,739 +The reason I'm gonna do that is because I still want +我这样做的原因是 + +1844 +01:19:25,742 --> 01:19:27,008 +refresh to work. +我仍然想让 refresh 工作 + +1845 +01:19:27,010 --> 01:19:29,677 +When we call refresh from code, I still want that to +从代码中调用 refresh 的时候,仍然想让它工作 + +1846 +01:19:29,679 --> 01:19:33,380 +work, and I'm gonna do that by calling this refresh here +我可以在 refresh 里调用 refresh + +1847 +01:19:33,382 --> 01:19:36,049 +with my refreshControl as an argument. +把 refreshControl 作为参数 + +1848 +01:19:36,051 --> 01:19:37,717 +So I'm just calling this one. +调用它 + +1849 +01:19:37,719 --> 01:19:39,385 +You see the little organization I did there? +看到我在这里对代码的组织了吗 + +1850 +01:19:40,554 --> 01:19:42,821 +And in fact, if we call from code, +实际上,如果通过代码调用的时候 + +1851 +01:19:42,823 --> 01:19:44,989 +I want that spinner to start spinning. +我希望 spinner 开始旋转 + +1852 +01:19:44,991 --> 01:19:49,027 +So I'm gonna say, if my refresh control is not nil, +如果 refreshControl 不是 nil + +1853 +01:19:49,029 --> 01:19:51,595 +in other words, unless someone's calling refresh +换句话说,如果某人调用了 refresh + +1854 +01:19:51,597 --> 01:19:53,864 +before my outlets are even hooked up, +在 outlet 连接好之前 + +1855 +01:19:53,866 --> 01:19:58,835 +then I'm going to start my thing spinning. +我就让 spinning 开始旋转 + +1856 +01:19:58,837 --> 01:20:02,972 +So I'm gonna say refreshControl?.beginRefresh- +refreshControl?.beginRefreshing + +1857 +01:20:02,974 --> 01:20:03,505 +ing. + +1858 +01:20:03,507 --> 01:20:05,273 +Okay? + +1859 +01:20:05,275 --> 01:20:07,776 +So here I'm beginning it refreshing in code. +在这里,我通过代码调用 refresh + +1860 +01:20:07,778 --> 01:20:09,911 +Okay, here it's being sent target action. +这里调用 target action + +1861 +01:20:09,913 --> 01:20:11,278 +So it's beginning by itself. +让它自己刷新 + +1862 +01:20:11,280 --> 01:20:12,613 +And either way, I'm ending it. +每一种方式,我都结束它的旋转 + +1863 +01:20:12,615 --> 01:20:15,148 +Now, what if their search text is nil? +如果 searchText 是 nil 怎么办 + +1864 +01:20:15,150 --> 01:20:17,684 +Then I also want to end refreshing. +我也想结束刷新 + +1865 +01:20:19,087 --> 01:20:20,719 +Because I can't actually search. +因为我不能执行搜索 + +1866 +01:20:22,656 --> 01:20:23,722 +And everyone understands that +每个人都明白吧 + +1867 +01:20:23,724 --> 01:20:25,857 +this is not gonna get called and this, right? +这里不会被调用 + +1868 +01:20:25,859 --> 01:20:28,092 +Because this is being called, +因为这是在另外一个线程 + +1869 +01:20:28,094 --> 01:20:31,495 +dispatched from another thread, okay? +被调用的 + +1870 +01:20:33,265 --> 01:20:34,430 +This needs to be else. +这里需要添加 else + +1871 +01:20:37,468 --> 01:20:40,202 +Okay, so this is only going to get called if this is not +只有在它不是 nil 的时候 + +1872 +01:20:40,204 --> 01:20:42,771 +nil, okay? +它才会被调用 + +1873 +01:20:43,840 --> 01:20:45,139 +All right, let's see if this all works. +让我们看看这些会不会有效 + +1874 +01:20:47,343 --> 01:20:48,592 +All right, so that worked. +它工作了! + +1875 +01:20:48,593 --> 01:20:49,842 +Did you see that little thing spinning when I +你发现了第一次启动时的那个 + +1876 +01:20:49,845 --> 01:20:51,512 +first launched? +转动的 spinning 了吗? + +1877 +01:20:51,513 --> 01:20:53,180 +So it worked to call it from code, that's cool. +所以从代码调用它是没问题的,酷 + +1878 +01:20:53,182 --> 01:20:54,164 +Oh, look at that. +看! + +1879 +01:20:54,165 --> 01:20:55,147 +Now, I hope you guys will be nice to me, +我希望你们对我好一点~ + +1880 +01:20:55,150 --> 01:20:56,549 +you're not putting something. +不放某些东西上去 + +1881 +01:20:56,551 --> 01:20:58,551 +There we go, we're getting more stuff. +我们获得了更多推文 + +1882 +01:20:58,553 --> 01:20:59,118 +Okay? + +1883 +01:21:00,554 --> 01:21:02,153 +Now, just to be careful here, keep refreshing. +持续刷新 + +1884 +01:21:02,155 --> 01:21:03,688 +In fact, let's try something else. +实际上,试一些其他关键字 + +1885 +01:21:04,824 --> 01:21:05,956 +Let's try grammys again. +再试试 grammys + +1886 +01:21:05,958 --> 01:21:07,824 +Maybe people are still tweeting about the Grammys. +也许人们还在发布关于格莱美的推文 + +1887 +01:21:07,826 --> 01:21:08,725 +Okay, so here we go. +好的 + +1888 +01:21:09,828 --> 01:21:11,694 +There we go. +没问题 + +1889 +01:21:11,695 --> 01:21:13,561 +See how we're getting newer ones each time we refresh? +每一次刷新我们都会得新的推文 + +1890 +01:21:13,564 --> 01:21:16,498 +Or maybe we could do gswhoops. +我们可以试试 gswhoops + +1891 +01:21:16,500 --> 01:21:18,066 +I think the Warriors are playing right now. +可能 Warriors 正在打比赛 + +1892 +01:21:19,736 --> 01:21:21,569 +There we go. +好的 + +1893 +01:21:21,571 --> 01:21:22,720 +Okay? + +1894 +01:21:22,721 --> 01:21:23,870 +Well, nobody's too excited about it, though, +看来大家对它不怎么感冒 + +1895 +01:21:23,873 --> 01:21:24,805 +cuz they're not tweeting. +因为他们没在发推 + +1896 +01:21:24,807 --> 01:21:27,374 +All right, so that's it. +好的,就是这样 + +1897 +01:21:27,376 --> 01:21:28,441 +That's all I wanted to do. +这就是我想做的 + +1898 +01:21:28,443 --> 01:21:30,243 +So you will get to start with this code +在完成作业时候 + +1899 +01:21:30,245 --> 01:21:32,111 +when you do your assignment. +你需要接着我的代码写 + +1900 +01:21:32,113 --> 01:21:33,979 +Sorry for going a little long. +可能有点拖堂了 + +1901 +01:21:33,981 --> 01:21:35,213 +I'm here if you have questions. +如果你们有问题,来这里找我 + +1902 +01:21:36,249 --> 01:21:36,280 +>> For more, please visit us at stanford.edu. diff --git a/subtitles/11. Unwind Segues, Alerts, Timers, View Animation.srt b/subtitles/11. Unwind Segues, Alerts, Timers, View Animation.srt new file mode 100644 index 0000000..7ff21d0 --- /dev/null +++ b/subtitles/11. Unwind Segues, Alerts, Timers, View Animation.srt @@ -0,0 +1,8944 @@ +1 +00:00:00,001 --> 00:00:04,703 +[MUSIC] + +2 +00:00:04,705 --> 00:00:08,239 +Stanford University. + +3 +00:00:08,241 --> 00:00:12,776 +>> Okay, welcome to Lecture Number 11 of +欢迎来到斯坦福大学 2015 年冬季 CS193P + +4 +00:00:12,778 --> 00:00:17,180 +Stanford CS193P Winter 2015. +第 11 课 + +5 +00:00:17,182 --> 00:00:21,417 +And today, we have a few topics to talk about. +今天我们将会聊到几个话题 + +6 +00:00:21,419 --> 00:00:23,385 +I'm gonna start off by talking to you about your final +我会从你们的最终项目要求讲起 + +7 +00:00:23,387 --> 00:00:24,786 +project requirements. + +8 +00:00:25,989 --> 00:00:28,089 +You know? + +9 +00:00:28,090 --> 00:00:30,190 +All the details of what you need to do, and by when. +你们需要做什么,什么时候完成等等一切细节 + +10 +00:00:30,193 --> 00:00:33,627 +Then we're gonna go over some topics briefly. +然后我们会短暂地带过一些主题 + +11 +00:00:33,629 --> 00:00:35,496 +I'll get through as many of these as I +我将会在这段时间中讲尽可能多的内容 + +12 +00:00:35,498 --> 00:00:37,064 +can fit the time of. + +13 +00:00:37,066 --> 00:00:38,431 +I might not, especially, the last one, +特别是这个,最后这个, + +14 +00:00:38,433 --> 00:00:40,366 +probably won't get to. +我或许不会讲到, + +15 +00:00:40,367 --> 00:00:42,300 +But that's okay, I'll just start off the lecture next +但没关系,下一周我会继续讲 + +16 +00:00:42,303 --> 00:00:44,937 +week because we don't have lecture on Monday. +因为周一我们没有课 + +17 +00:00:44,939 --> 00:00:47,740 +So next Wednesday will be our next lecture. +那么下个星期三就是我们下一次课程 + +18 +00:00:47,742 --> 00:00:49,241 +All right, so start right into these +好了,进入我们 + +19 +00:00:49,243 --> 00:00:52,143 +final project requirements and feel free to stop and ask me +最终项目的要求讲解,如果我没说清楚,或者你有不明白的地方 + +20 +00:00:52,145 --> 00:00:55,880 +questions if I say something or you don't understand it. +大家可以在任何时候问我 + +21 +00:00:55,882 --> 00:00:59,150 +We ask everyone to submit a proposal for +对于接下来我们要做的事, + +22 +00:00:59,152 --> 00:01:00,818 +what they're going to do. +我会让大家提交一个提议 + +23 +00:01:00,820 --> 00:01:03,220 +And it's a simple proposal, +一个很简单的申请 + +24 +00:01:03,222 --> 00:01:06,056 +I am going to show you a sample proposal in a minute or +我马上会给你看一个简单的申请 + +25 +00:01:06,058 --> 00:01:08,524 +two so you can get an idea of what a proposal looks like. +这样你就知道一个申请到底是指什么 + +26 +00:01:10,695 --> 00:01:14,629 +Proposals, and please submit them in PDF format only, +这个申请,请大家使用 PDF 格式的文件提交 + +27 +00:01:14,631 --> 00:01:17,699 +not just sending them in an email or in Word format or +不要只是通过 email 或者 Wrod 格式 + +28 +00:01:17,701 --> 00:01:18,399 +something like that. +之类的东西发送 + +29 +00:01:18,401 --> 00:01:19,767 +Please, PDF. +PDF,谢谢 + +30 +00:01:19,769 --> 00:01:20,968 +And the proposal, +这个申请 + +31 +00:01:20,970 --> 00:01:22,803 +really you can have two big sections in it. +需要有两个模块在其中 + +32 +00:01:22,805 --> 00:01:25,105 +One is what you're doing, obviously, and +当然了,第一,你要干嘛 + +33 +00:01:25,107 --> 00:01:28,908 +then another one is what parts of iOS you're going to use. +另一个模块就是列出你将会使用 iOS 中什么模块 + +34 +00:01:28,910 --> 00:01:30,209 +And again I'm gonna show you +我马上就会给你展示 + +35 +00:01:30,211 --> 00:01:31,610 +an example of that in a second. +一个例子 + +36 +00:01:32,979 --> 00:01:35,580 +The project is going to be due on Friday the 13th. +这个项目需要在13号星期五之前提交 + +37 +00:01:35,582 --> 00:01:40,351 +[SOUND] Be ready for that, midnight on that day, +准备好,在那一天的午夜之前 + +38 +00:01:40,353 --> 00:01:42,519 +Pacific Time, yes. +太平洋时间,当然了 + +39 +00:01:42,521 --> 00:01:44,621 +Use the normal submission process, +使用通常的提交流程 + +40 +00:01:44,623 --> 00:01:48,157 +there'll be an option in there for the final project. +在最终项目中会有一个注意事项 + +41 +00:01:48,159 --> 00:01:50,393 +You can't use any free late days. +你不能使用延迟提交的权利 + +42 +00:01:50,395 --> 00:01:53,328 +We're already totally pushing this out to as late as we can +我们已经把这个时间推迟到了 + +43 +00:01:53,330 --> 00:01:54,930 +and still get them all graded and +刚好能够提交成绩的时间 + +44 +00:01:54,932 --> 00:01:57,332 +by the time we have to get the grades submitted. +到了时间我们就会提交所有的成绩 + +45 +00:01:57,334 --> 00:02:02,436 +So lateness is very highly penalized. +所以晚交作业的后果是很严重的 + +46 +00:02:02,438 --> 00:02:04,338 +Basically one letter grade per day +迟交一天降低一个字母等级 + +47 +00:02:05,307 --> 00:02:07,374 +because we just can't afford it to be late. +我们确实不能承担晚交的后果了 + +48 +00:02:07,376 --> 00:02:08,942 +Okay? So +好吗? + +49 +00:02:08,943 --> 00:02:10,509 +if you have any free late days late +如果你有任何延迟时间 + +50 +00:02:10,512 --> 00:02:11,844 +use them on assignments four and +请在作业四或者 + +51 +00:02:11,846 --> 00:02:14,947 +five because you cannot use them on the final project. +作业五阶段使用,因为你不能在最终项目中使用了 + +52 +00:02:14,949 --> 00:02:16,748 +I can't grant extensions. +我不会允许延迟 + +53 +00:02:16,750 --> 00:02:19,250 +There's just really no time for extensions. +已经没有时间延迟了 + +54 +00:02:19,252 --> 00:02:22,820 +So basically submit whatever you have on Friday the 13th +总的来说,你必须在十三号星期五提交 + +55 +00:02:22,822 --> 00:02:24,205 +and see what happens. +然后等待结果 + +56 +00:02:24,206 --> 00:02:25,589 +If you don't like Friday the 13th, +如果你不喜欢十三号的周五(黑色星期五) + +57 +00:02:25,591 --> 00:02:28,959 +you can submit in on the 12th, that'd be fine. +那你可以在十二号提交,这样也可以 + +58 +00:02:28,961 --> 00:02:31,595 +This is a three week-long project, right? +这是一个为期三周的项目 + +59 +00:02:31,597 --> 00:02:33,563 +It's not due until, basically what, four and +从现在到提交的时间,有大概,四到 + +60 +00:02:33,565 --> 00:02:35,582 +a half weeks from today. +四周半的样子 + +61 +00:02:35,583 --> 00:02:37,600 +But you need a week to think about what you're gonna do. +但你需要一周的时间来思考你要怎么做 + +62 +00:02:37,602 --> 00:02:39,168 +You still have a couple of assignments left. +你还有几个作业需要做 + +63 +00:02:39,170 --> 00:02:42,204 +So it's basically a three week-long project. +所以这就是一个三周时长的项目 + +64 +00:02:42,206 --> 00:02:44,072 +So even though last minute if you're in an emergency it +即使在最后一秒你有紧急情况 + +65 +00:02:44,074 --> 00:02:45,674 +should hurt you too bad. +那也应该是你受伤得非常严重才行 + +66 +00:02:45,676 --> 00:02:47,408 +So plan accordingly. +所以做好规划 + +67 +00:02:47,410 --> 00:02:49,744 +Start early and try to get it done early. +早点开始,并且尝试着尽快结束 + +68 +00:02:49,746 --> 00:02:51,512 +That way, if you have a problems, +这样的话,即使你遇到了问题 + +69 +00:02:51,514 --> 00:02:53,880 +you'll have time to go track things down. +你仍然有时间去究根结底 + +70 +00:02:53,882 --> 00:02:56,716 +If you don't start until the last week of the three week +如果你直到第三周的最后一周才开始 + +71 +00:02:56,718 --> 00:02:58,785 +project, your project's not going to turn out that good. +我可以保证, + +72 +00:02:58,787 --> 00:03:01,087 +I can pretty much guarantee that. +你的项目质量不会太好 + +73 +00:03:01,089 --> 00:03:03,389 +People often ask, +同学们总是问 + +74 +00:03:03,391 --> 00:03:05,590 +can we work in teams on this final project? +我们可以组队完成最终项目吗? + +75 +00:03:05,592 --> 00:03:08,360 +And the answer is generally no, but +通常这个答案是 —— 不 + +76 +00:03:08,362 --> 00:03:11,129 +I do allow teams of two only +但我确实会允许两人组队 + +77 +00:03:11,131 --> 00:03:13,931 +in these very specific circumstances here: Both +在这种特定的情况下 + +78 +00:03:13,933 --> 00:03:16,400 +students have to be taking the course passment credit. +当两个学生必须拥有足够的学分 + +79 +00:03:16,402 --> 00:03:19,202 +The homework grades for both students have to be +并且两个学生在作业分数上 + +80 +00:03:19,204 --> 00:03:22,405 +substantially similar and good. +要水平相当 + +81 +00:03:22,407 --> 00:03:25,641 +No team can consist of anyone who's +不允许有队伍中存在着 + +82 +00:03:25,643 --> 00:03:29,078 +basically been struggling in the course so far. +其中一个学生一直在这门课程中挣扎的情况 + +83 +00:03:29,080 --> 00:03:31,647 +You have to submit a proposal and +你必须提交申请 + +84 +00:03:31,649 --> 00:03:34,016 +your proposal has to be explicitly approved. +你的申请需要被明确地批准才行 + +85 +00:03:34,018 --> 00:03:36,384 +The rest of you are going to submit a proposal and +其余的人都需要提交申请并且 + +86 +00:03:36,386 --> 00:03:38,319 +we're going to give you feedback on it. +我们会给你反馈 + +87 +00:03:38,321 --> 00:03:40,755 +But there's no process whereby we have to say yes this is +这没有一个标准告诉你 + +88 +00:03:40,757 --> 00:03:42,523 +approved, now go forward. +我们是如何批准的 + +89 +00:03:42,525 --> 00:03:43,757 +You're just gonna get feedback. +你只会获得反馈 + +90 +00:03:43,759 --> 00:03:45,125 +But if you're doing the team of two, +但如果你要成立两人小组 + +91 +00:03:45,127 --> 00:03:47,460 +you do have to get it explicitly approved. +那么你必须要得到明确的批准才行 + +92 +00:03:47,462 --> 00:03:50,429 +And of course, that proposal would have to cover six weeks +当然了,这个申请必须包含六周的工时 + +93 +00:03:50,431 --> 00:03:53,365 +of homework time worth of work because there's two of you. +毕竟有两个人 + +94 +00:03:53,367 --> 00:03:54,166 +Okay? So, that's twice as +清楚了吗? + +95 +00:03:54,168 --> 00:03:54,866 +much in there. +这是两倍的时间 + +96 +00:03:58,905 --> 00:04:01,906 +The proposal also not only is gonna have to show the things +这个申请不仅需要包含 + +97 +00:04:01,908 --> 00:04:03,440 +I'm gonna talk about later but +我接下来会讲到的东西 + +98 +00:04:03,442 --> 00:04:05,976 +it also has to include who's gonna do what. +并且要包含谁要做什么 + +99 +00:04:05,978 --> 00:04:08,478 +And I really strongly encourage you to break up +并且我强烈建议你分开 + +100 +00:04:08,480 --> 00:04:10,747 +the work that's going to be happening among two people +两个人的工作的 + +101 +00:04:10,749 --> 00:04:12,448 +along class boundaries. +类的边界 + +102 +00:04:12,450 --> 00:04:15,517 +So, this class is being written by Joe, and +比如这个类由 Joe 完成 + +103 +00:04:15,519 --> 00:04:17,452 +this class is being written by Jane. +这个类由 Jane 完成 + +104 +00:04:17,454 --> 00:04:19,587 +Okay? So it's very clear who's doing +这样非常清晰地表明谁将会做什么 + +105 +00:04:19,589 --> 00:04:22,457 +what, as opposed to oh, we worked together on this. +而不是相反,让我们共同完成这个。 + +106 +00:04:22,459 --> 00:04:25,026 +And then it's hard for us to tell who actually understands +而且这样对于我们来说也很难分清楚 + +107 +00:04:25,028 --> 00:04:27,327 +what in here, okay? +到底谁才弄明白了 + +108 +00:04:27,329 --> 00:04:29,096 +Then when you submit your code, +然后当你提交代码的时候 + +109 +00:04:29,098 --> 00:04:31,831 +you have to follow that up with a clear delineation, +必须伴有清晰的解释 + +110 +00:04:31,833 --> 00:04:34,300 +this person did this, this person did that. +这个人做了这个,这个人做了那个 + +111 +00:04:34,302 --> 00:04:36,969 +And again hopefully, that this class was written by this +并且希望大家注明,这个类是由这个人完成 + +112 +00:04:36,971 --> 00:04:39,638 +person, this class was was written by that person. +那个类是由另一个人完成 + +113 +00:04:39,640 --> 00:04:42,140 +So we don't end up with very many teams of two every +这样,由于我们严格的要求 + +114 +00:04:42,142 --> 00:04:44,175 +quarter, because of these strict requirements. +应该也不会有太多人组队了吧 + +115 +00:04:44,177 --> 00:04:47,078 +But if you wanna try and give it a try, you want to submit +如果你仍然想要尝试一下 + +116 +00:04:47,080 --> 00:04:49,113 +your proposal as soon as you can put it together, +那么请尽快提交你们的申请 + +117 +00:04:49,115 --> 00:04:50,748 +like in the next couple days. +比如接下来的几天 + +118 +00:04:50,750 --> 00:04:52,816 +And start getting your grader to give you feedback +我们会尽快根据你的等级来给你反馈 + +119 +00:04:52,818 --> 00:04:55,452 +on it as soon as possible so you can iterate and +这样你就可以尽快地思考 + +120 +00:04:55,454 --> 00:04:58,454 +make sure that you have something that's workable. +确保你有值得做的东西 + +121 +00:04:58,456 --> 00:04:59,639 +Okay? +好吗? + +122 +00:04:59,640 --> 00:05:00,823 +Otherwise, I strongly recommend kind of +否则,我强烈推荐 + +123 +00:05:00,825 --> 00:05:02,208 +individual work. +独立工作 + +124 +00:05:02,209 --> 00:05:03,592 +I mean, this course is about learning to be an iOS +我的意思是,这堂课程是关于学习如何成为 iOS 开发者的 + +125 +00:05:03,594 --> 00:05:06,361 +developer and if you want us to be able to measure your +如果你想要我们正确地衡量你是否合格 + +126 +00:05:06,363 --> 00:05:10,732 +success at that learning process, it's individual work. +那就独立工作 + +127 +00:05:10,734 --> 00:05:12,466 +Okay? Now, understand that when +好吗?但要知道当你终将要 + +128 +00:05:12,468 --> 00:05:13,701 +you go out into the real world, +进入现实社会 + +129 +00:05:13,703 --> 00:05:15,335 +programming is never individual work. +编程从来不是独立工作 + +130 +00:05:15,337 --> 00:05:19,005 +It's almost, I mean, 5% of what's going on in the world, +大多数情况下,我的意思是,可能有5%的情况下, + +131 +00:05:19,007 --> 00:05:21,708 +programming wise, is some individual work, okay? +会需要你独立工作 + +132 +00:05:21,710 --> 00:05:23,442 +95%, you're working in teams. +另外95%的情况下,你会团队协作 + +133 +00:05:23,444 --> 00:05:24,877 +And I wish I had more than ten weeks so +我希望我多出十周的时间 + +134 +00:05:24,879 --> 00:05:27,612 +we could work on working in teams. +这样我们可以以团队的形式工作 + +135 +00:05:27,614 --> 00:05:29,580 +But we just don't have time for that, unfortunately. +但不幸的是,我们确实没有那么多时间 + +136 +00:05:31,050 --> 00:05:33,484 +All right? +好吗? + +137 +00:05:33,485 --> 00:05:35,919 +You'll be graded based on your proper use of the iOS SD case. +你的成绩会根据你使用 iOS SDK 的熟练程度 + +138 +00:05:35,921 --> 00:05:37,120 +So don't hack. +所以不要使用 Hack 的方式 + +139 +00:05:37,122 --> 00:05:38,855 +Okay? Make sure you understand. +好吗?确保你弄懂了 + +140 +00:05:38,857 --> 00:05:41,824 +You read the documentation of the classes you're using and +你需要阅读使用的类的相关文档 + +141 +00:05:41,826 --> 00:05:43,492 +you use them properly. +确保正确使用 + +142 +00:05:43,494 --> 00:05:47,896 +The other thing I'm gonna say is that breadth is very, +另外我要说,广度非常 + +143 +00:05:47,898 --> 00:05:50,749 +very important. +非常重要 + +144 +00:05:50,750 --> 00:05:53,601 +Breadth meaning show me as much of the iOS API as you +广度意味着你要尽可能地向我展示你会的 iOS API + +145 +00:05:53,603 --> 00:05:56,036 +can, rather than going really really deep and +而不是针对某一个方面做得非常深入 + +146 +00:05:56,038 --> 00:05:58,038 +doing one thing really, really, really well. +非常非常好 + +147 +00:05:58,040 --> 00:06:00,073 +Some people are graphics wizes and +有的同学擅长图形学 + +148 +00:06:00,075 --> 00:06:02,308 +they go do these incredible graphics apps. +他们做的那些图形应用非常棒 + +149 +00:06:02,310 --> 00:06:03,509 +And I say to them well, +但我对他们说 + +150 +00:06:03,511 --> 00:06:05,077 +if this had been a graphics course, +如果这是图形学课程 + +151 +00:06:05,079 --> 00:06:06,311 +you'd have gotten an A plus. +那么你会得到一个 A+ 的成绩 + +152 +00:06:06,313 --> 00:06:08,513 +But unfortunately, it's an iOS Development course, and +但不幸的是,这是 iOS 开发课程 + +153 +00:06:08,515 --> 00:06:10,048 +you didn't show me much iOS. +而你没有向我展示足够多的 iOS 相关内容 + +154 +00:06:10,050 --> 00:06:11,615 +You just showed me only the graphics part. +你只向我展示了图形学相关的部分 + +155 +00:06:11,617 --> 00:06:13,283 +I don't know whether you can do table views and +我不知道你是否会使用 table views + +156 +00:06:13,285 --> 00:06:13,984 +all these other things. +或者其他的东西 + +157 +00:06:13,986 --> 00:06:15,251 +What's going on? +到底怎么回事? + +158 +00:06:15,253 --> 00:06:17,286 +So breadth is extremely important. +所以,广度极其重要 + +159 +00:06:17,288 --> 00:06:19,288 +It's probably the most important. +或许这是最重要的部分 + +160 +00:06:19,289 --> 00:06:21,289 +And then the second thing is we're gonna ask you to do one +第二重要的是,我们会要求你做一个 + +161 +00:06:21,292 --> 00:06:24,626 +significant feature that I did not teach in lecture. +很重要的功能,而我没有在课堂上教过 + +162 +00:06:24,628 --> 00:06:26,928 +And that's because iOS is huge. +这是由于 iOS 非常庞大 + +163 +00:06:26,930 --> 00:06:29,964 +I only teach the tiniest little fraction of it. +我只能教授极其小的一部分 + +164 +00:06:29,966 --> 00:06:32,567 +I really just teach things that teach you the concepts +我是教了你一些概念而已 + +165 +00:06:32,569 --> 00:06:34,201 +you need to learn other things in iOS. +你需要学习 iOS 的其他方面 + +166 +00:06:34,203 --> 00:06:37,104 +So you really need to show that you can go to +所以你需要展示你可以利用好文档 + +167 +00:06:37,106 --> 00:06:38,705 +the documentation, go on the internet, +利用好互联网 + +168 +00:06:38,707 --> 00:06:41,775 +figure out how to do something substantial on iOS without me +弄明白如何做一些重要的模块 + +169 +00:06:41,777 --> 00:06:44,911 +basically showing you and giving you a demo of it, etc. +在没有我向你展示,或者给你 demo 的情况下 + +170 +00:06:44,913 --> 00:06:46,812 +So I put them in yellow there because those are really +这也是为什么我把这些标记为黄色 + +171 +00:06:46,814 --> 00:06:49,815 +the two most important things to get right. +这两项是最为重要的事情 + +172 +00:06:50,984 --> 00:06:54,085 +You don't wanna get stuck down a rat hole, where you +你一定不想白费功夫 + +173 +00:06:54,087 --> 00:06:56,587 +just spend two of your three weeks kind of chasing after +花费两周的时间去费力追赶 + +174 +00:06:56,589 --> 00:06:58,856 +one thing that never really pans out and +那些并不是很重要的事情 + +175 +00:06:58,858 --> 00:07:01,158 +now you only have a week left to do a lot of breadth. +而你只有一周的时间来扩展广度 + +176 +00:07:01,160 --> 00:07:02,692 +So if you start doing something and you're just +如果你开始做某个你非常喜欢的东西,但你的表现为 + +177 +00:07:02,694 --> 00:07:04,293 +like, God I completely don't understand this or +啊,我完全不知道这个东西到底 + +178 +00:07:04,295 --> 00:07:05,494 +I can't figure this out. +是怎么弄的 + +179 +00:07:05,496 --> 00:07:06,595 +Just cut and run. +那就直接丢弃 + +180 +00:07:06,597 --> 00:07:09,064 +Go pick something else, +去重新选一个 + +181 +00:07:09,065 --> 00:07:11,532 +some other feature you can put in your application instead. +选择另外你可以放在应用中的功能 + +182 +00:07:11,535 --> 00:07:13,134 +Notice that I don't say anything here that +注意我并不是说 + +183 +00:07:13,136 --> 00:07:15,403 +you're going to be graded on how cool your app is. +你会因为你的应用有多酷而得到高分 + +184 +00:07:15,405 --> 00:07:17,138 +Or how ready for the app store it is, or +或者已经在 app store 中准备得如何了 + +185 +00:07:17,140 --> 00:07:18,539 +how much money it's going to make. +或者这个应用将会赚多少钱 + +186 +00:07:18,541 --> 00:07:20,307 +None of those things are part of the requirements. +这些并不是要求中的一部分 + +187 +00:07:20,309 --> 00:07:22,575 +This is an academic course, +这是一门学术课程 + +188 +00:07:22,577 --> 00:07:25,111 +you're trying to show me your iOS capabilities. +你要向我展示你的 iOS 开发能力 + +189 +00:07:25,113 --> 00:07:27,246 +That's the number one requirement, okay? +这才是最主要的标准,好吗? + +190 +00:07:27,248 --> 00:07:29,915 +Now, if after this course you want to then +如果在这门课结束后你想要那样做 + +191 +00:07:29,917 --> 00:07:32,751 +take some features out maybe that you threw in just to show +那就拿出那些那些你只是向我展示你知道 + +192 +00:07:32,753 --> 00:07:34,953 +me that you knew how to do something in iOS. +如何在 iOS 中完成的功能 + +193 +00:07:34,955 --> 00:07:36,621 +Or if you wanna add some features because +或者你想要加入一些功能 + +194 +00:07:36,623 --> 00:07:38,422 +there was something too complicated to do through. +因为那样才是完整的流程 + +195 +00:07:38,424 --> 00:07:40,290 +Hey, that and more power to you. +嘿,那都是你的权利 + +196 +00:07:40,292 --> 00:07:41,858 +Many, many final projects have +有许多许多的最终项目 + +197 +00:07:41,860 --> 00:07:43,693 +eventually ended up on the App Store. +最后都提交到了 App Store 上 + +198 +00:07:43,695 --> 00:07:45,928 +But that is nothing to do with the requirements. +但并没有符合要求 + +199 +00:07:45,930 --> 00:07:47,063 +Not even, you know, +一点也没有 + +200 +00:07:47,065 --> 00:07:49,031 +mention this part of what you're supposed to do. +你知道,应该做的部分 + +201 +00:07:49,033 --> 00:07:51,733 +Okay, I don't even care about that. +我完全不在乎那些 + +202 +00:07:51,735 --> 00:07:53,401 +Okay? The scope of the project, +这个项目的完成范围 + +203 +00:07:53,403 --> 00:07:54,836 +like how much work it is. +比如能够完成多少工作 + +204 +00:07:54,838 --> 00:07:57,471 +It should be three weeks of homework worth of work. +应该在三周作业工作量的范围内 + +205 +00:07:57,473 --> 00:08:00,674 +Especially three of the last weeks of homework, because +特别是这最后三周的作业 + +206 +00:08:00,676 --> 00:08:03,844 +you're supposed to know iOS by the end of this quarter. +你应该知道 iOS 在这个季度结束 + +207 +00:08:03,846 --> 00:08:06,579 +So if you took, take a combination of assignment +如果你合理地完成了作业 + +208 +00:08:06,581 --> 00:08:10,116 +three, four, and five which is the graphing calculator, and +三,四,五 也就是图形计算器 + +209 +00:08:10,118 --> 00:08:12,985 +then the smash tag that you're working on now, and +然后你正在做的「smash tag」 + +210 +00:08:12,987 --> 00:08:15,454 +there's gonna be an animation base thing, +而且接下来还有动画相关的内容 + +211 +00:08:15,456 --> 00:08:17,856 +you take that much worth of homework work, +如果你完成了所有的家庭作业 + +212 +00:08:17,858 --> 00:08:21,259 +that's about how much your final project should be. +那就是你的最终作业 + +213 +00:08:21,261 --> 00:08:23,861 +Okay, maybe even slightly more because some of the stuff that +好吧,或许更多一点 + +214 +00:08:23,863 --> 00:08:25,096 +you're gonna put in your final project, +那你将会安稳度过你的最终项目 + +215 +00:08:25,098 --> 00:08:27,331 +you already know how to do it in the assignments. +你已经知道怎么完成要求 + +216 +00:08:27,333 --> 00:08:31,335 +So it should be easy peasy for you, 'kay? +这对你来说是很简单的 + +217 +00:08:31,337 --> 00:08:33,703 +Just a reminder that everyone pass no credit or +只要记得,你不会得到学分和成绩 + +218 +00:08:33,705 --> 00:08:36,539 +letter grade you have to pass both the homework and +除非你完成了家庭作业 + +219 +00:08:36,541 --> 00:08:38,007 +the final projects separately. +和最终项目 + +220 +00:08:38,009 --> 00:08:41,877 +At Stanford a passing grade is a c minus or better, 'kay? +在斯坦福及格等级是 C- 或者更好 + +221 +00:08:41,879 --> 00:08:45,580 +So we will tell you if you have not passed the homework +我们会告诉你是否通过了家庭作业的考核 + +222 +00:08:45,582 --> 00:08:48,316 +portion once we've finished grading homework assignment +当我们完成了作业任务的评分 + +223 +00:08:48,318 --> 00:08:49,617 +five, 'kay? +好吗? + +224 +00:08:49,619 --> 00:08:52,286 +So then you can just stop work on the final project at that +如果你没有,那你也不需要完成最终项目了 + +225 +00:08:52,288 --> 00:08:53,253 +point, all right? +好吗? + +226 +00:08:53,255 --> 00:08:54,855 +[SOUND]. + +227 +00:08:54,857 --> 00:08:56,056 +>> [LAUGH]. >> Well, + +228 +00:08:56,057 --> 00:08:57,256 +you can keep working on it if you want, but you're not gonna +好啦,只要你想,你可以继续做 + +229 +00:08:57,259 --> 00:09:00,159 +pass the course if you don't pass that part, okay? +但你不会通过这门课,如果你没有通过作业部分 + +230 +00:09:01,295 --> 00:09:03,295 +'Kay, question about the scope? +对于这部分有问题吗? + +231 +00:09:03,297 --> 00:09:04,930 +Scope is important. +这部分非常重要 + +232 +00:09:04,931 --> 00:09:06,564 +It's one of the things people fall down on. +这也是许多人失败了的原因 + +233 +00:09:06,566 --> 00:09:08,199 +They basically submit something that's kinda +他们只是提交了大概 + +234 +00:09:08,201 --> 00:09:10,935 +two weeks of work, and so two weeks of work, +两周的成果 + +235 +00:09:10,937 --> 00:09:13,437 +that's two-thirds of the, for total points. +那就只有三分之二的成绩 + +236 +00:09:13,439 --> 00:09:14,838 +That's not a very good grade, so +这不是非常好成绩 + +237 +00:09:14,840 --> 00:09:18,041 +you wanna make sure you get your scope right there. +如果你想要确保你的成绩正确 + +238 +00:09:18,043 --> 00:09:20,977 +[SOUND] Do not just regurgitate your homework +那就不要只是简单地完成你的家庭作业好吗? + +239 +00:09:20,979 --> 00:09:22,478 +assignments, okay? + +240 +00:09:22,480 --> 00:09:26,081 +I do not want to see smash tag too, okay? +我不想看到「smash tag」 + +241 +00:09:26,083 --> 00:09:28,517 +And every quarter it seems like I always get a handful of +每一个季度我都会收到很多人的作业 + +242 +00:09:28,519 --> 00:09:31,419 +people who can't really think of something to do so +他们完全想不到应该做什么 + +243 +00:09:31,421 --> 00:09:36,057 +they basically just take smash tag or maybe the last homework +所以只是把「smash tag」 + +244 +00:09:36,059 --> 00:09:39,259 +assignment and they just kinda change the names and, +或者只是把最后一个作业修改了一下名字 + +245 +00:09:39,261 --> 00:09:41,528 +you know, it's very, very similar. +你懂的,非常非常相似 + +246 +00:09:41,530 --> 00:09:43,330 +Don't do that, okay? +请别这样做,好吗? + +247 +00:09:43,331 --> 00:09:45,131 +Cuz then you'll have just shown us that you already what +那样就是你在向我们重复展示你 + +248 +00:09:45,133 --> 00:09:46,132 +you've already shown us, +之前在家庭作业中 + +249 +00:09:46,134 --> 00:09:47,500 +which is you know how to do the homework. +已经展示过的东西 + +250 +00:09:47,502 --> 00:09:50,135 +Okay, great, we already, yeah, know how to do the homework. +好吗? 我们已经知道你懂家庭作业怎么做的了 + +251 +00:09:50,137 --> 00:09:51,987 +Now show us different. +请向我们展示一些不一样的东西 + +252 +00:09:51,988 --> 00:09:53,838 +Basically one thing to think about is you wannna start your +基本上你需要从草图开始 + +253 +00:09:53,841 --> 00:09:55,206 +final project from scratch. +思考你的最终项目 + +254 +00:09:55,208 --> 00:09:56,874 +You don't wanna start it with Smashtag and +你不会想要从「smashtag」开始 + +255 +00:09:56,876 --> 00:09:58,809 +then start changing it or with assignment five and +然后修改添加任务五 + +256 +00:09:58,811 --> 00:10:00,577 +then start changing it or with a calculator and +或者是从修改一个计算器开始 + +257 +00:10:00,579 --> 00:10:01,745 +then just start changing it. + +258 +00:10:01,747 --> 00:10:04,981 +Start from scratch, 'kay, that will help emphasize +从零开始,这样才会加强印象 + +259 +00:10:04,983 --> 00:10:07,650 +you don't wanna just turn in a regurgitation of the homework +你不会想要只是重复家庭作业任务的 + +260 +00:10:07,652 --> 00:10:09,218 +assignment and in fact, +而事实上 + +261 +00:10:09,220 --> 00:10:11,887 +whatever you do in your final project, try to do things +无论你要在最终项目中做什么 + +262 +00:10:11,889 --> 00:10:13,989 +a little differently than we did them in the assignments. +尝试着做一点与之前作业不一样的东西 + +263 +00:10:13,991 --> 00:10:16,291 +Cuz if you do something exactly the same way we +因为你做了与作业相同的时, + +264 +00:10:16,293 --> 00:10:18,159 +did it in the assignment, like if you had a table view, and +比如你有一个 table view + +265 +00:10:18,161 --> 00:10:20,494 +if data structure is exactly the way we did it for +然后数据结构与我们之前完成的作业一样 + +266 +00:10:20,496 --> 00:10:22,262 +the assignment, it's kinda like, well, +这就像 + +267 +00:10:22,264 --> 00:10:25,098 +we already knew they could do that, so don't do that, 'kay. +我们已经知道这些东西可以做什么了 + +268 +00:10:25,100 --> 00:10:27,534 +Pick a different instructor, something more interesting, +选择不同的控件,其他有趣的东西 + +269 +00:10:27,536 --> 00:10:30,636 +do a couple more features in table view, +在 table view 中多尝试一些功能 + +270 +00:10:30,638 --> 00:10:33,339 +do things that are maybe extra credit in the homework, +做稍微超出家庭作业的东西 + +271 +00:10:33,341 --> 00:10:36,508 +do those in your final project, those kinda things to +在你的最终项目中这样做 + +272 +00:10:36,510 --> 00:10:38,176 +get some difference between your homework. +与你的家庭作业区分开来 + +273 +00:10:38,178 --> 00:10:42,180 +>> But, I guess I'm afraid that, how do I know what's, +>> 但,我怎么知道 + +274 +00:10:42,182 --> 00:10:43,614 +you know, different, and what's like a hack, +>> 区别,比如什么是 hack + +275 +00:10:43,616 --> 00:10:46,250 +like if I make my priority the structure, like a linguist, +>> 我对结构进行优先级排列就像语言学家那样 + +276 +00:10:46,252 --> 00:10:47,818 +for example, is that like a hack? +>> 这样属于 hack 吗? + +277 +00:10:47,820 --> 00:10:48,852 +Or is that okay to use? +或者说可以这样用吗? + +278 +00:10:48,854 --> 00:10:50,670 +>> Okay, so the question is, +问题是 + +279 +00:10:50,671 --> 00:10:52,487 +how do I know, if I do something different than what +我怎么知道,我做的东西是否不同于 + +280 +00:10:52,490 --> 00:10:53,789 +was talked about in lecture, +我们在课堂中接触到的东西 + +281 +00:10:53,791 --> 00:10:56,191 +if I'm not now doing hackery, okay? +如果我不是,那属于 hack 吗? + +282 +00:10:56,193 --> 00:10:57,376 +And the answer is, well, +好吧,答案是 + +283 +00:10:57,377 --> 00:10:58,560 +you're going to have to figure that out, +你需要弄明白界限 + +284 +00:10:58,562 --> 00:11:00,795 +because when you go out into the real world and +因为当你在现实世界中, + +285 +00:11:00,797 --> 00:11:03,564 +build iOS apps, you need to not be a hacker, and the way +创建 iOS 应用时,你要避免成为一个 hacker + +286 +00:11:03,566 --> 00:11:05,900 +you figure those things out is by reading the documentation. +你需要通过阅读文档来弄明白这些东西 + +287 +00:11:05,902 --> 00:11:07,768 +If you read the documentation of a method and it says, +如果你在文档中读到某个方法 + +288 +00:11:07,770 --> 00:11:09,102 +this method works this way, and +是这样使用的 + +289 +00:11:09,104 --> 00:11:11,905 +you use it that way, then you're not hacking, okay? +你也是这样使用的,那么你就不是在 hack + +290 +00:11:11,907 --> 00:11:13,539 +If you go out on the internet, and it says, oh, +如果你在网上搜到某个方法,上面写,哦 + +291 +00:11:13,541 --> 00:11:15,641 +you can call this private method with this thing and +你可以调用这个私有方法,它会解决问题 + +292 +00:11:15,643 --> 00:11:18,277 +it'll work, then now you're staring to hack, right? +那么你就是在 hack,好吗? + +293 +00:11:18,279 --> 00:11:20,078 +Or if you just don't read the documentation and +或者你没有阅读文档 + +294 +00:11:20,080 --> 00:11:22,881 +just start typing things in until they work, okay? +并且只是在码字直到解决问题 + +295 +00:11:22,883 --> 00:11:26,684 +I used to have a great GIF, I don't have it now, where it's +我以前有个很棒的 GIF 动画,现在没有了 + +296 +00:11:26,686 --> 00:11:28,686 +just this GIF of this guy just banging on the keyboard and +这个 GIF 显示的这个男人在用头撞击键盘 + +297 +00:11:28,688 --> 00:11:31,155 +then banging his head until he's just a bloody mess, and +直到血肉横飞 + +298 +00:11:31,157 --> 00:11:34,057 +that's a programming approach that doesn't scale very well. +这种编程方法就不太好 + +299 +00:11:34,059 --> 00:11:36,026 +So, you know, you'll know if you're hacking, +所以,你会知道的,你会知道你在 hack + +300 +00:11:36,028 --> 00:11:37,978 +it'll be clear. +这界限非常清楚 + +301 +00:11:37,979 --> 00:11:39,929 +You can always ask your TAs, there'll still be office hours +你也可以询问你的 TA,接下来的季度中 + +302 +00:11:39,931 --> 00:11:42,698 +all for the rest of the quarter, you can, you know, +的所有工作时间他们都会在,你可以 + +303 +00:11:42,700 --> 00:11:45,200 +go find out if you're hacking. +去询问他们,你是否在 hack + +304 +00:11:45,202 --> 00:11:47,202 +All right, so some examples of bad projects, +好了,这就是在项目中出现的坏的例子 + +305 +00:11:47,204 --> 00:11:48,970 +we already talked about Smashtag two, +我们已经谈过了「Smashtag」 + +306 +00:11:51,107 --> 00:11:52,340 +that's a bad project. +那也是一个糟糕的项目 + +307 +00:11:52,341 --> 00:11:53,574 +Another bad project is one that has very little breadth, +另一种糟糕的项目是只有一点点广度 + +308 +00:11:53,576 --> 00:11:57,711 +like it's lots of MVCs being segued to each other but +比如有很多的 MVC 结构在其中 + +309 +00:11:57,713 --> 00:11:59,279 +all the MVCs are basically the same. +但所有的 MVC 几乎都是一样的 + +310 +00:11:59,281 --> 00:12:01,647 +A bunch of buttons and text fields and labels and +一大堆按钮,输入框,文本框 + +311 +00:12:01,649 --> 00:12:03,949 +that's it, there's no table views in there, +没了,没有列表 + +312 +00:12:03,951 --> 00:12:08,620 +there's no animation, there's no custom view with drawRect, +没有动画效果,没有使用了 drawRect 的自定义视图 + +313 +00:12:08,622 --> 00:12:09,771 +you see what I'm saying? +你明白我的意思了吗? + +314 +00:12:09,772 --> 00:12:10,921 +It's all just the same thing over and over or +这就是不停地重复 + +315 +00:12:10,924 --> 00:12:12,223 +vice versa with the table views. +反之亦然,列表 + +316 +00:12:12,225 --> 00:12:13,958 +It's table view, after table view, after table view, +这个页面是列表,然后又是列表,又是列表 + +317 +00:12:13,960 --> 00:12:15,259 +after table view, and there's nothing else, +又是列表,其他什么也没有 + +318 +00:12:15,261 --> 00:12:16,694 +just table views. +就只是列表 + +319 +00:12:16,695 --> 00:12:18,128 +That's all that's in it, the whole app is table views. +这就是所有的东西,整个应用就是一堆列表 + +320 +00:12:20,532 --> 00:12:22,232 +Those are bad apps. +这些就属于糟糕的应用 + +321 +00:12:22,233 --> 00:12:23,933 +An animated game, like you're doing a game that's all video +一个动效游戏,就像你玩的那些电视游戏一样 + +322 +00:12:23,935 --> 00:12:26,802 +game, a guy running around and shooting bullets and all that +一个男人在那跑来跑去,不停地射击 + +323 +00:12:26,804 --> 00:12:30,639 +stuff, that's bad too, because where's the table views? +永远都这样,这也很糟糕,因为列表在哪去了? + +324 +00:12:30,641 --> 00:12:33,075 +And it shows me that you know the animation stuff, great! +你向我展示你知道动画效果,很好 + +325 +00:12:33,077 --> 00:12:35,443 +But I need to see all the rest, text fields and +但我需要看到其他的东西 + +326 +00:12:35,445 --> 00:12:38,746 +labels and segues, where's that if it's just this +如果只看到一个男人在屏幕上跑跑跳跳, + +327 +00:12:38,748 --> 00:12:42,249 +one screen where the guy is running around jumping, okay. +那标签,界面跳转,这些东西哪里去了? + +328 +00:12:42,251 --> 00:12:45,119 +Another one is some cool mathematical thing or +你通过你的 PhD 研究,制作了一个与数学相关 + +329 +00:12:45,121 --> 00:12:47,954 +an image filter that uses your PhD research +或者与图形处理相关 + +330 +00:12:47,956 --> 00:12:49,823 +to calculate something. +的东西 + +331 +00:12:49,825 --> 00:12:52,792 +That's great that you worked your PhD research in there, +你融入了你 Phd 中的研究,这样很棒 + +332 +00:12:52,794 --> 00:12:55,661 +except for that's 90% or 80% of what you did, and +但如果其中90%或者80%都和那些相关 + +333 +00:12:55,663 --> 00:12:57,529 +you're gonna get an F in this class, +那么你将会在这堂课上拿到一个 F + +334 +00:12:57,531 --> 00:12:59,998 +because only 20% is going to be iOS stuff. +因为只有20%的内容与 iOS 相关 + +335 +00:13:00,000 --> 00:13:02,434 +You want it to be the other way around, 90% iOS and +你需要颠倒过来,要90%的内容与 iOS 相关 + +336 +00:13:02,436 --> 00:13:05,036 +then you can only spend 10% of your time on doing, +然后你可以留10%的内容 + +337 +00:13:05,038 --> 00:13:07,738 +putting your PhD stuff in there or +把你 Phd 相关的东西放进去 + +338 +00:13:07,740 --> 00:13:11,875 +some in network resource or whatever, that's fine. +网络研究或者随便什么,都可以 + +339 +00:13:11,877 --> 00:13:13,977 +The aesthetics of your UI do matter. +你对 UI 的审美同样重要 + +340 +00:13:13,979 --> 00:13:15,278 +Okay, we don't want these junky, +我们不想要看到那些 + +341 +00:13:15,280 --> 00:13:16,946 +totally crappy looking things but +非常糟糕的东西 + +342 +00:13:16,948 --> 00:13:19,081 +I don't expect you to be graphic designers. +当然我也没有期望你变身为图形设计师 + +343 +00:13:19,083 --> 00:13:20,449 +You're programmers. +你是程序员 + +344 +00:13:20,451 --> 00:13:21,649 +So that just basically means, +所以,这就意味着 + +345 +00:13:21,651 --> 00:13:24,919 +you know, do your auto layout nicely, line things up. +你懂的,用好 auto layout,排列整齐一点 + +346 +00:13:24,921 --> 00:13:27,054 +You know, those dash blue lines help you line things +你知道的,蓝色辅助线条帮助你排列元素整齐 + +347 +00:13:27,056 --> 00:13:28,389 +up so things should look nice. +这样东西会看起来好一些 + +348 +00:13:28,391 --> 00:13:30,557 +Also, don't be afraid to go out on the internet, +当然了,不要害怕使用网上的资源 + +349 +00:13:30,559 --> 00:13:33,026 +find some nice icon or something do in there. +找一些好看的图标或者其他的东西放进去 + +350 +00:13:33,028 --> 00:13:34,961 +You're really not even gonna have to worry about, +你也不需要担心那些 + +351 +00:13:34,963 --> 00:13:37,029 +do I have the rights to use this icon, +我有版权使用这个图标吗 这类的问题 + +352 +00:13:37,031 --> 00:13:39,031 +because it's only for your personal work. +因为这只是你的个人项目 + +353 +00:13:39,033 --> 00:13:40,666 +You're not gonna be shipping it on the App Store. +你不需要把它提交到 App Store 上去 + +354 +00:13:40,668 --> 00:13:42,334 +If you do ship in the App Store, +如果你要提交到 App Store + +355 +00:13:42,335 --> 00:13:44,001 +you have to change your icons, or either buy them, +那么你就需要修改图标,或者买下那些东西 + +356 +00:13:44,004 --> 00:13:46,838 +or use stuff that's free to use, all that but for this, +或者使用免费的资源,除此之外 + +357 +00:13:46,840 --> 00:13:49,674 +you don't have to worry about that, so we do wanna see it. +你不需要担心这些事 + +358 +00:13:49,676 --> 00:13:52,242 +By the same token this is not a human, +同样,这也不是人机 + +359 +00:13:52,244 --> 00:13:55,245 +computer human interface class, okay? +人机交互课程,好吗? + +360 +00:13:55,247 --> 00:13:57,580 +So an app's not gonna be a primary thing. +对这个应用来说并不是最主要的事情 + +361 +00:13:57,582 --> 00:14:00,550 +I just want to make sure you don't turn into much of junk, +我只是不希望你做出来的东西太糟糕 + +362 +00:14:00,552 --> 00:14:03,419 +'kay, you wouldn't want that either. +你肯定也不希望 + +363 +00:14:03,421 --> 00:14:06,455 +You're final project has to work on hardware, 'kay? +你的最终项目必须在真机上运行 + +364 +00:14:06,457 --> 00:14:08,457 +And you have to demonstrate that to us. +并且你需要向我们展示 + +365 +00:14:08,459 --> 00:14:10,025 +So you're gonna have a final presentation which I'm +关于最终展示,我马上会说到 + +366 +00:14:10,027 --> 00:14:12,593 +gonna talk about in a second, and if you do a live demo +但只要你把最终项目的 Demo + +367 +00:14:12,595 --> 00:14:15,363 +on hardware, then you've satisfied that requirement. +运行在真机上了,那你就满足了这个要求 + +368 +00:14:15,365 --> 00:14:18,432 +If you don't, then you need to show your TA, +如果你不会,那么你需要向你的 TA 展示 + +369 +00:14:18,434 --> 00:14:21,368 +usually they'll hang around after the final project, +通常来说在最终项目时期他们都在 + +370 +00:14:21,370 --> 00:14:25,038 +final presentation slot, or you could show it to them any +最终展示,或者你可以在此之前向他们展示 + +371 +00:14:25,040 --> 00:14:28,041 +time before that, in office hours or whatever. +在工作时间或者随便什么时候 + +372 +00:14:28,043 --> 00:14:29,842 +Show them your app working. +向他们展示你的成果 + +373 +00:14:29,844 --> 00:14:31,210 +So that's the important part. +这是最重要的部分 + +374 +00:14:31,212 --> 00:14:32,611 +You can't just be simulator only. +你不能只使用模拟器 + +375 +00:14:32,613 --> 00:14:33,845 +And you're gonna notice that assignment, +注意这个要求 + +376 +00:14:33,847 --> 00:14:36,714 +I don't know if I made assignment four be +我忘了是否有要求四 + +377 +00:14:36,716 --> 00:14:38,182 +hardware required, I guess not, but +硬件要求,或许没有 + +378 +00:14:38,184 --> 00:14:39,583 +assignment five will definitely be, +但要求五肯定会是 + +379 +00:14:39,585 --> 00:14:44,854 +this must work on hardware, 'kay? +项目要能够运行在真机上 + +380 +00:14:44,856 --> 00:14:46,723 +Yeah, this is kind of a reiteration of my theory four +Yeah,这可能是对于我之前要求的重申 + +381 +00:14:46,725 --> 00:14:50,026 +but don't get side-tracked on non-iOS code. +不要过于专注在非 iOS 代码上 + +382 +00:14:50,028 --> 00:14:53,028 +If you have something like a database that you're gonna use +如果你需要一个数据库用于登录或者什么, + +383 +00:14:53,030 --> 00:14:55,697 +or a login, a lot of people want to do a social networking +有很多人想要做一个社交网络应用 + +384 +00:14:55,699 --> 00:14:57,499 +app which is great and you have to have a login, +当然如果有个登录功能是很棒的 + +385 +00:14:57,501 --> 00:15:00,468 +or something like that, you know, you can fake it. +但你也可以尝试着假装 + +386 +00:15:00,470 --> 00:15:02,403 +Fake the login, just have three users, and +一个假的登录,有三个默认用户账户 + +387 +00:15:02,405 --> 00:15:03,237 +that's all, right? +这样就可以了 + +388 +00:15:03,239 --> 00:15:04,855 +And it's some, + + +389 +00:15:04,856 --> 00:15:06,472 +as long as you do it in a nice object-oriented way, +只要你面向对象完成得很好 + +390 +00:15:06,475 --> 00:15:09,209 +where that faked backend is its own object somewhere, or +有一个假的后台或者其他什么东西 + +391 +00:15:09,211 --> 00:15:12,078 +whatever, that's the way you wanna do it, because again, +这就是你应该做的,再说一次 + +392 +00:15:12,080 --> 00:15:14,613 +you wanna focus all your time on showing me as much +你需要全力专注于向我展示 + +393 +00:15:14,615 --> 00:15:17,483 +iOS usage as you can cram in there, 'kay? +你知道的 iOS 相关代码,好吗? + +394 +00:15:17,485 --> 00:15:20,018 +So if you waste a week, hooking up to a network +如果你花了一个礼拜的时间,去配置网络服务 + +395 +00:15:20,020 --> 00:15:22,854 +server you've wasted a week, okay, now you have to cram +你就浪费了一周,好吗?那你就必须 + +396 +00:15:22,856 --> 00:15:24,922 +three weeks of iOS programming and coding into two weeks so +把三周时间的 iOS 编程,变成只有其中两周编程 + +397 +00:15:24,924 --> 00:15:29,326 +don't do that, 'kay, so be careful there. +注意不要那样做 + +398 +00:15:29,328 --> 00:15:30,594 +All right, presentation, +好了,展示 + +399 +00:15:30,596 --> 00:15:32,395 +this presentation I mentioned, so there's so +我之前提到过的展示 + +400 +00:15:32,397 --> 00:15:35,865 +many of you this quarter, this is the max we've ever had. +这个学期有很多人,这就是我们能争取到的 + +401 +00:15:35,867 --> 00:15:37,133 +Normally we have a two-minute +通常我们有两分钟的 + +402 +00:15:37,135 --> 00:15:39,001 +presentation where you get up here for two minutes and +展示时间,你上去然后展示两分钟 + +403 +00:15:39,003 --> 00:15:41,770 +you have to just basically tell us all about your app. +你需要简单地向我们介绍你的应用 + +404 +00:15:41,772 --> 00:15:44,005 +I call it sometimes the venture capitalist pitch, +我有时候把这个称为企业资本展示 + +405 +00:15:44,007 --> 00:15:46,808 +imagining a venture capitalist here, and you're trying to get +想象有一个企业家在那坐着,你要尝试着 + +406 +00:15:46,810 --> 00:15:48,943 +them to invest in your company to build this app. +让他们投资你的公司来开发这款应用 + +407 +00:15:48,945 --> 00:15:51,745 +You wanna put your app in the best light and show it off, +你需要用最好的灯光来展示 + +408 +00:15:51,747 --> 00:15:53,914 +and you wanna show off all aspects of it, so +你要展示应用的方方面面 + +409 +00:15:53,916 --> 00:15:55,315 +should give a screenshot. +展示一个好看的截屏 + +410 +00:15:55,317 --> 00:15:57,650 +Do a live demo if you dare. +最好做一个 Demo + +411 +00:15:57,652 --> 00:16:02,087 +You can see I do live demos and they can be perilous. +你之前也看到我展示 Demo,这样做可能会很冒险 + +412 +00:16:02,089 --> 00:16:04,089 +Somehow, you know, pitch your app to us. +使用你喜欢的方式,向我们推荐你的 App + +413 +00:16:04,091 --> 00:16:06,624 +So, unfortunately we only get 90 seconds because they're so +因为我们的学生很多,所以每个人只有90秒的时间 + +414 +00:16:06,626 --> 00:16:08,209 +many of you. + +415 +00:16:08,210 --> 00:16:09,793 +We only got three hour slot and didn't really want it to +一共只有三个小时,也不想要 + +416 +00:16:09,796 --> 00:16:14,164 +spill over too much into the alternate final slot. +在最终项目展示的时候超出这个时间 + +417 +00:16:14,166 --> 00:16:15,966 +So 90 seconds. That doesn't seem like a long +所以90秒钟,虽然感觉不是很长的时间 + +418 +00:16:15,968 --> 00:16:18,335 +time but actually you can say a lot in 90 seconds. +但实际上在这90秒内你已经可以描述很多东西了 + +419 +00:16:18,337 --> 00:16:19,653 +' Kay. + +420 +00:16:19,654 --> 00:16:20,970 +If you're, if you're very focused on what +如果你有很多想要说的东西 + +421 +00:16:20,972 --> 00:16:23,105 +you have to say, you can show your basically, +那么你需要在 + +422 +00:16:23,107 --> 00:16:25,274 +your entire UI in about 30 seconds. +30秒内展示整个 UI + +423 +00:16:25,276 --> 00:16:29,244 +Yeah? >> [INAUDIBLE] + +424 +00:16:29,246 --> 00:16:30,878 +>> Yeah so I think I say on here. +我认为你可以这样理解 + +425 +00:16:31,914 --> 00:16:32,913 +Maybe I get to second. +我有两分钟时间 + +426 +00:16:32,915 --> 00:16:35,115 +The question is can I just make a video and +问题是,是否我可以做一个视频 + +427 +00:16:35,117 --> 00:16:36,216 +get up here and press play? +然后上来播放 + +428 +00:16:36,218 --> 00:16:37,884 +And the answer is no, 'Kay? +答案是,不 + +429 +00:16:38,953 --> 00:16:41,587 +I want you guys to have the experience of standing up in +我需要你们体验站到上面来 + +430 +00:16:41,589 --> 00:16:44,056 +front of your peers and having to talk to them. +面对你的同学们,向他们描述 + +431 +00:16:44,058 --> 00:16:48,193 +That's a very, very important skill in your life, okay? +对于你的人生来说,这是非常非常重要的一个技能 + +432 +00:16:48,195 --> 00:16:50,561 +And so you need to do that, so no pressing play, 'Kay? +所以你必须这样做,不能只是按下播放按钮 + +433 +00:16:52,965 --> 00:16:56,900 +I need your slides before, because I'm going to put all +在演讲前我需要你的幻灯片,因为我会把 + +434 +00:16:56,902 --> 00:16:59,836 +the slides in one big thing so we can race through this. +幻灯片放在大屏幕上,这样我们才能加快速度 + +435 +00:16:59,838 --> 00:17:01,738 +Okay, we got to get to a hundred people, +我们会有上百人在这里 + +436 +00:17:01,740 --> 00:17:04,540 +90 seconds each with like 10 seconds in between. +每个人有90秒钟时间,10秒的间隔时间 + +437 +00:17:04,542 --> 00:17:05,908 +We're going to have to be really racing through. +所以我们需要争分夺秒 + +438 +00:17:05,910 --> 00:17:07,509 +So you're gonna give me all your slides, +所以需要你给我你的幻灯片 + +439 +00:17:07,511 --> 00:17:09,678 +I'm going to put them all in one gigantic presentation and +我会把它们放在一个巨大的屏幕上 + +440 +00:17:09,680 --> 00:17:11,813 +we're just going to be clicking through the slides, +然后我们会浏览这些幻灯片 + +441 +00:17:11,815 --> 00:17:15,216 +person after person will have any switching time. +一个接一个地切换 + +442 +00:17:15,218 --> 00:17:16,650 +Please make your slides, +请做好幻灯片 + +443 +00:17:16,652 --> 00:17:20,220 +you haven't noticed by now, wide screen, okay? +你还没有注意到,这里会有个大屏幕,好吗 + +444 +00:17:20,222 --> 00:17:22,022 +1280x720. Do not send me 1024x768 or +1280x720,不要提交 1024x768 或者 + +445 +00:17:22,024 --> 00:17:23,189 +800x600 slides. +800 x 600 的幻灯片 + +446 +00:17:23,191 --> 00:17:27,893 +They will look funny, 'Kay? +这样看起来会很搞笑 + +447 +00:17:27,895 --> 00:17:31,697 +The slides are due to me the day after your final +这些幻灯片可以在最终项目之后的一天提交给我 + +448 +00:17:31,699 --> 00:17:33,665 +project is due, so you can get your final project in and +所以你可以先准备好你的最终项目 + +449 +00:17:33,667 --> 00:17:36,467 +then spend the next day if you wanna fax, you know, +然后再隔一天时间传送给我 + +450 +00:17:36,469 --> 00:17:39,704 +craft your presentation, do some screenshots or whatever. +如果你想要好好雕琢你的展示,做一些截屏什么的 + +451 +00:17:39,706 --> 00:17:42,473 +Whatever you present, though, in terms of slides or +无论你想展示什么,就幻灯片或者 UI 来说 + +452 +00:17:42,475 --> 00:17:45,542 +UI on that second day, should be what you turned in. +应该和你提交的一样 + +453 +00:17:45,544 --> 00:17:48,611 +So don't spend Saturday adding more graphics and +所以不要在周六又向里面添加了一些图片 + +454 +00:17:48,613 --> 00:17:50,196 +all that stuff and +或者其他的东西 + +455 +00:17:50,197 --> 00:17:51,780 +then putting up slides that are not what your app is. +然后你的幻灯片和你提交的应用不一样 + +456 +00:17:51,783 --> 00:17:52,682 +'Kay? + +457 +00:17:52,684 --> 00:17:53,882 +Your app is the presentation +你的应用就是展示 + +458 +00:17:53,884 --> 00:17:55,650 +you give has to be the app you turned in. +你展示的东西必须和你提交的一样 + +459 +00:17:56,720 --> 00:17:57,285 +Make sense? +有道理吧 + +460 +00:17:57,287 --> 00:18:00,688 +You submit the slides also using a normal process. +同样也是通过普通流程来提交你的幻灯片 + +461 +00:18:00,690 --> 00:18:02,623 +There'll be a different submit target for that, +他们会有一个不同的提交目标 + +462 +00:18:02,625 --> 00:18:04,725 +final project slides, it'll be called. +叫做最终项目幻灯片 + +463 +00:18:04,727 --> 00:18:09,562 +And so, yes, that's the way you do that. +好了,这就是你应该做的 + +464 +00:18:09,564 --> 00:18:11,831 +Now, I know some of you have a conflict with the final exam, +我知道你们当中有的人会和期末考试有冲突 + +465 +00:18:11,833 --> 00:18:13,532 +although I don't really know how that's supposed to happen, +我也不知道为什么会发生这样的事 + +466 +00:18:13,534 --> 00:18:14,933 +because all the final exams are supposed to +因为期末考试之间不应该 + +467 +00:18:14,935 --> 00:18:16,034 +not conflict with each other. +有冲突 + +468 +00:18:16,035 --> 00:18:17,134 +But I know you guys have other things, +但我知道你们有其他的事情 + +469 +00:18:17,137 --> 00:18:19,203 +you're in the GSB or something else. +你的 GSB 或者其他的课程 + +470 +00:18:19,205 --> 00:18:21,505 +So I am gonna have an alternate final slot if you +所以我将会另外给你一个最终展示时间 + +471 +00:18:21,507 --> 00:18:24,608 +want, which is on the very last lecture of this course. +如果你需要的话,这个时间是最后一堂课 + +472 +00:18:24,610 --> 00:18:26,443 +So you can do your presentation then if +你可以在那个时候展示 + +473 +00:18:26,445 --> 00:18:27,744 +you prefer. +如果你愿意的话 + +474 +00:18:27,746 --> 00:18:29,112 +And there will be a sign up for that but +这将会需要登记一下 + +475 +00:18:29,114 --> 00:18:30,997 +it will be really easy. +但应该会非常简单 + +476 +00:18:30,998 --> 00:18:32,881 +I'll announce it on Piazza a couple weeks before. +我会提前几个星期在走廊上张贴出来 + +477 +00:18:32,884 --> 00:18:33,683 +Okay? + +478 +00:18:33,684 --> 00:18:34,483 +If you do the alternate time, +如果你选择在另一个时间 + +479 +00:18:34,485 --> 00:18:36,318 +obviously I need your slide sooner. +很明显我就需要你的幻灯片了提前一些 + +480 +00:18:36,320 --> 00:18:39,621 +So I need them by the Monday before actually. +我需要在实际时间的周一就拿到 + +481 +00:18:39,623 --> 00:18:42,423 +Now in that case, you still get to turn your stuff in +在这样的情况下,你仍然可以在周五提交 + +482 +00:18:42,425 --> 00:18:44,592 +by the Friday, so you're gonna have to be making your +你的应用,也就是说你需要提前准备好 + +483 +00:18:44,594 --> 00:18:47,861 +presentation out of your apps not done yet maybe. +要展示的东西,在你的应用完成之前 + +484 +00:18:47,863 --> 00:18:49,463 +So, but you just gotta do the best you can if you +所以如果你想要提前展示,那就只好尽最大的努力了 + +485 +00:18:49,465 --> 00:18:50,063 +wanna go early. + +486 +00:18:51,533 --> 00:18:52,798 +Okay? But presenting early has no +但提前展示不会影响 + +487 +00:18:52,800 --> 00:18:54,400 +effect on when the actual thing is due. +到最终的时间 + +488 +00:18:54,402 --> 00:18:57,836 +It's still due on Friday the 13th. +最终时间仍然是13号星期五 + +489 +00:18:57,838 --> 00:18:58,403 +Okay? + +490 +00:18:59,972 --> 00:19:01,839 +The quality of your presentation, +关于你的演讲质量 + +491 +00:19:01,841 --> 00:19:03,006 +people say oh does it matter? +有人问,哦,那个重要吗? + +492 +00:19:03,008 --> 00:19:04,207 +Yes, of course it matters. +当然重要 + +493 +00:19:04,209 --> 00:19:05,809 +Okay? It matters for +这个对于你 + +494 +00:19:05,810 --> 00:19:07,410 +you and your experience here at Stanford is to be giving +以及你在斯坦福的经验,这应该是一个 + +495 +00:19:07,412 --> 00:19:08,878 +good presentations. +好的演讲 + +496 +00:19:08,880 --> 00:19:10,446 +Does it matter to your final grade? +而且也确实会影响到你的最终成绩 + +497 +00:19:10,448 --> 00:19:11,713 +Yeah, a tiny little bit. +一点点 + +498 +00:19:11,715 --> 00:19:13,748 +If you come up here and you totally bomb. +如果你上来了,然后脑子一片空白 + +499 +00:19:13,750 --> 00:19:16,150 +If you do a live demo and it's a complete mess, +如果你做了一个现场演示,但演讲完全就是一团糟 + +500 +00:19:16,152 --> 00:19:18,352 +we're not gonna go oh, that's a B for that guy. +我们也不会噢,给这家伙一个 B + +501 +00:19:18,354 --> 00:19:20,854 +No. But, still we want, +不会的,但仍然我们希望 + +502 +00:19:20,856 --> 00:19:23,123 +you can kind of impress us if you come up and +你可以让我们影响深刻,如果你上来 + +503 +00:19:23,125 --> 00:19:25,358 +do a really great demo and it really shows our graph well, +然后做了一个很棒的 demo,并且也向我们展示了很好看的图片 + +504 +00:19:25,360 --> 00:19:27,126 +we're more likely to walk away going wow, +我们将会表现为 Wow + +505 +00:19:27,128 --> 00:19:29,095 +that was a little better app than I thought. +这个应用或许比我想象的要好一些呢 + +506 +00:19:29,097 --> 00:19:29,795 +Okay? + +507 +00:19:29,797 --> 00:19:31,830 +But, if you come up here and +但如果你上来 + +508 +00:19:31,831 --> 00:19:33,864 +you're terrible, then we might be like, which app was that? +然后表现得很糟糕,我们就会表现为 这是哪个应用来着? + +509 +00:19:33,867 --> 00:19:35,200 +I thought that was terrible. +我觉得这很糟糕 + +510 +00:19:35,202 --> 00:19:37,285 +Okay? So, +好吗 + +511 +00:19:37,286 --> 00:19:39,369 +it matters a little because it gives us an impression, so. +这确实很重要,如果你让我们印象深刻了 + +512 +00:19:39,372 --> 00:19:42,573 +And that 90 seconds is going to be strictly enforced. +然后90秒钟会是强制性限制 + +513 +00:19:42,575 --> 00:19:44,508 +I'm literally going to say okay thank you, +当时间到了我会直接告诉你 + +514 +00:19:44,510 --> 00:19:47,344 +right at 90 seconds cause we just can not afford to go over +好了谢谢 因为人数的关系 + +515 +00:19:47,346 --> 00:19:50,347 +too many people. +我们不能延长时间 + +516 +00:19:50,349 --> 00:19:52,982 +Yeah, question, should I do a live demo? +好了,问题是,是否我应该做一个现场演示 + +517 +00:19:52,984 --> 00:19:54,850 +I love live demos as you can tell, +看的出来我非常喜欢现场演示 + +518 +00:19:54,852 --> 00:19:56,652 +I do a live demo almost every single lecture. +几乎每一堂课我都会做现场演示 + +519 +00:19:57,621 --> 00:19:59,254 +But I know that for some people, it's like, oh, +但我知道对于有的人来说,这就像 + +520 +00:19:59,256 --> 00:20:00,755 +it's a little scary, it might not work, +这有点可怕,或许不会成功 + +521 +00:20:00,757 --> 00:20:02,323 +especially if you're going out on the network, +特别是如果你将要使用到网络 + +522 +00:20:02,325 --> 00:20:05,159 +maybe you can't get the network or something. +或许你不能连上网络或者其他的事 + +523 +00:20:05,161 --> 00:20:06,761 +So, it's dangerous. +这样看起来很危险 + +524 +00:20:06,762 --> 00:20:08,362 +So, what I recommend is, live demos are pretty effective, +所以,我的建议是,现场演示非常有效 + +525 +00:20:08,364 --> 00:20:09,729 +so, you know, try and +你懂的,尝试一下 + +526 +00:20:09,731 --> 00:20:13,166 +put a live demo together if you can but have a backup. +做一个现场演示,但如果可以的话准备好备用计划 + +527 +00:20:13,168 --> 00:20:14,900 +If you get up here to do your live demo, it's like, +如果你上来准备现场演示 + +528 +00:20:14,902 --> 00:20:16,001 +it won't project. +这不会部署成功 + +529 +00:20:16,003 --> 00:20:17,736 +Your device won't project. +你的设备不能部署 + +530 +00:20:17,738 --> 00:20:19,137 +Or the network doesn't work. +或者网络无法连接 + +531 +00:20:19,139 --> 00:20:21,005 +Or you have audio and it's not working. +或者你有一个音频但没有播放 + +532 +00:20:21,007 --> 00:20:22,440 +Then just switch to your Keynote. +那就直接切换到你的 Keynote + +533 +00:20:22,442 --> 00:20:26,377 +So have your Keynote slides as back up if you're gonna +让你的 Keynote 幻灯片回来 + +534 +00:20:26,379 --> 00:20:30,647 +go live demo, is my recommendation, 'Kay? +这就是我推荐的方式,如果你要做现场演示的话 + +535 +00:20:30,649 --> 00:20:32,015 +All right, so the proposal. +好了,申请表 + +536 +00:20:32,017 --> 00:20:33,683 +Sample proposal. +申请表示例 + +537 +00:20:33,685 --> 00:20:36,452 +Here I'm just gonna show you what one would look like so +我将会向你展示一下 + +538 +00:20:36,454 --> 00:20:37,786 +you can kinda get an idea. +这样你就知道这到底是什么 + +539 +00:20:37,788 --> 00:20:40,388 +My sample proposal is I'm gonna build a Shakespeare +我的申请表示例是我将要做一个「Shakespeare Director」 + +540 +00:20:40,390 --> 00:20:41,723 +director app. +应用 + +541 +00:20:41,725 --> 00:20:45,659 +So I'm a director of a Shakespearean play, and +我是莎士比亚戏剧的导演 + +542 +00:20:45,661 --> 00:20:50,464 +I'm gonna have this nice iPad app to help me do that and +我需要这个 iPad app 帮助我 + +543 +00:20:50,466 --> 00:20:51,631 +help my actors. +帮助我的演员 + +544 +00:20:51,633 --> 00:20:55,134 +And so it's basically going to have a table for +基本上里面会有一个列表 + +545 +00:20:55,136 --> 00:20:56,502 +choosing a Shakespearean play. +用来选择莎士比亚的戏剧 + +546 +00:20:56,504 --> 00:20:58,937 +So you can pick a play, the one you're doing. +你可以选择其中一部,你要用的那部 + +547 +00:20:58,939 --> 00:21:02,341 +And then it will let you lay out, you're the director, so +然后它会让你布局,你是导演 + +548 +00:21:02,343 --> 00:21:03,708 +you're gonna lay out the blocking, +你需要对舞台进行布局 + +549 +00:21:03,710 --> 00:21:05,810 +which is where everyone stands on stage, +这就是所有人站在舞台上 + +550 +00:21:05,812 --> 00:21:07,511 +on a little kind of graphical stage. +在一个小的平面舞台上 + +551 +00:21:07,513 --> 00:21:08,779 +So I'm gonna have a drawRect there. +我将会在这里使用 drawRect + +552 +00:21:08,781 --> 00:21:11,448 +I'm gonna have gesture, so I can move things around. +这里会用到手势,这样我才能移动这些东西 + +553 +00:21:11,450 --> 00:21:13,650 +It's also gonna have a dialog learning mode, +这里会有一个台词学习模式 + +554 +00:21:13,652 --> 00:21:17,020 +where it's going to show the dialog line by line +用来一行一行地展示台词 + +555 +00:21:17,022 --> 00:21:19,689 +so that actors can have their own iPad maybe while they're +这样演员们可以在他们的 iPad 上 + +556 +00:21:19,691 --> 00:21:20,556 +learning their lines. +学习台词 + +557 +00:21:20,558 --> 00:21:22,290 +And they'll see their blocking and +与此同时,他们也能看到舞台的布局 + +558 +00:21:22,292 --> 00:21:23,858 +their lines right there at the same time. +以及他们的台词 + +559 +00:21:23,860 --> 00:21:26,527 +And they'll also be able to record the other people's +然后这会录下来这些人的台词 + +560 +00:21:26,529 --> 00:21:27,661 +lines, so it'll prompt them. +这样可以即时的提醒他们 + +561 +00:21:27,663 --> 00:21:29,163 +So that they can sit there and +这样他们就可以坐在那 + +562 +00:21:29,165 --> 00:21:31,031 +learn their lines and all that. +学习台词和其他的东西 + +563 +00:21:31,033 --> 00:21:32,399 +So you can see, it's a pretty cool app, right? +你可以感受到,这是一个很酷的应用对吧 + +564 +00:21:32,401 --> 00:21:33,666 +It's pretty good idea. +是个很棒的点子 + +565 +00:21:33,668 --> 00:21:37,203 +I'm basically explaining what it does in my proposal. +我就是在申请表中解释我将要干嘛 + +566 +00:21:37,205 --> 00:21:39,505 +I'm talking about limitations, though, +我会说到限制 + +567 +00:21:39,507 --> 00:21:42,507 +like I'm saying that my custom view is only going to be +比如我会说我的自定义视图只会是 + +568 +00:21:42,509 --> 00:21:45,877 +rectangles and circles and I'll let them set color. +方形和圆形然后我们设置他们的颜色 + +569 +00:21:45,879 --> 00:21:49,414 +So, the people are not going to be really great graphics. +所以,人不会是非常好看的图形 + +570 +00:21:49,416 --> 00:21:51,082 +I'm just saying that I don't want to spend all my time +我不想花费大量的时间在 + +571 +00:21:51,084 --> 00:21:52,883 +doing that, so I'm just gonna make my, when I lay +这上面,所以我只会将就做一个,当我排列好 + +572 +00:21:52,885 --> 00:21:54,918 +out where everyone is on stage it's just gonna be block. +舞台上的所有人,这些人就只是方块 + +573 +00:21:54,920 --> 00:21:57,070 +See? So, I'm kind +看到了吗?我在 + +574 +00:21:57,071 --> 00:21:59,221 +of explaining my proposal that I realize because if I don't +解释我的申请,然后我意识到,如果我不把这个放在这 + +575 +00:21:59,224 --> 00:22:01,457 +put that in here, then your TA's going to feedback and +那么你的 TA 将会给予一个反馈 + +576 +00:22:01,459 --> 00:22:03,659 +say, whoa, you're gonna have this whole blocking thing? +你需要这样一个舞台的东西? + +577 +00:22:03,661 --> 00:22:04,960 +How complicated is that gonna be? +这个东西会有多复杂? + +578 +00:22:04,962 --> 00:22:05,761 +What are you gonna allow? +你需要怎么实现? + +579 +00:22:05,763 --> 00:22:07,507 +You see what I mean? +明白我的意思了吗? + +580 +00:22:07,508 --> 00:22:09,252 +So this heads that off by saying, okay, +所以只是把要做的事列出来 + +581 +00:22:09,253 --> 00:22:10,997 +I understand that mostly I'm focusing on doing draw rec and +我知道大多是的情况下我需要专注于 drawRect + +582 +00:22:11,001 --> 00:22:13,101 +gestures and things like that. +手势等等 + +583 +00:22:13,103 --> 00:22:15,336 +That's what I'm trying to show you with this feature. +这也是我将要向你展示的功能 + +584 +00:22:16,872 --> 00:22:19,039 +But I'm saying here that I'm gonna be able to let you +但我的意思是,我允许你 + +585 +00:22:19,041 --> 00:22:22,108 +take a photo of a person and put that in a rectangle so +让一张人的照片在那个方块中 + +586 +00:22:22,110 --> 00:22:23,776 +that when you're blocking you can at least have +当你在布局舞台的时候,至少你可以 + +587 +00:22:23,778 --> 00:22:26,679 +pictures of the people, maybe in their nice costumes. +有一些人的照片,甚至穿着好看的服装 + +588 +00:22:26,681 --> 00:22:30,649 +And I'm telling you other things here, you know, +而且我将告诉你另外一件事 + +589 +00:22:30,651 --> 00:22:33,618 +that sound recording sound is going to be possible. +第 +第二个录音的点子几乎不可能实现 + +590 +00:22:33,620 --> 00:22:36,087 +I notice that I mention that it's iPad only. +我注意到我之前说了这只是个 iPad 应用 + +591 +00:22:36,089 --> 00:22:38,189 +Now, when I say iPad only there, +当我说只支持 iPad 的时候 + +592 +00:22:38,191 --> 00:22:40,558 +that hurts breadth, okay? +其实就丧失了一些广度 + +593 +00:22:40,560 --> 00:22:42,659 +Because an app that works on both iPhone and +因为一个应用能够在 iPhone 和 iPad + +594 +00:22:42,661 --> 00:22:45,996 +iPad has more breadth although it's pretty easy to make +运行将会拥有更大的广度,并且要让应用支持 + +595 +00:22:45,998 --> 00:22:47,497 +an app that's just kinda works on both. +也非常简单 + +596 +00:22:47,499 --> 00:22:49,432 +But you still have to make sure the adaptations +但你还是需要确保在旋转屏幕的时候 + +597 +00:22:49,434 --> 00:22:52,068 +are working maybe and that when it rotates in both sides, +自适应功能是支持的 + +598 +00:22:52,070 --> 00:22:53,135 +it does the right thing. +这样才是对的 + +599 +00:22:53,137 --> 00:22:53,969 +So it's a little more work. +所以这就是多余的一点工作量 + +600 +00:22:53,971 --> 00:22:55,570 +So you just lost breadth. +你也会损失广度 + +601 +00:22:55,572 --> 00:22:57,672 +I lost breadth by saying, iPad only. +我在说出只支持 iPad 的时候,损失了广度 + +602 +00:22:57,674 --> 00:23:00,374 +But I decided that this app just doesn't make sense +但我觉得这个应用如果没有 iPad 的话 + +603 +00:23:00,376 --> 00:23:02,026 +without iPad. +就完全不合理 + +604 +00:23:02,027 --> 00:23:03,677 +Although i could, I could decide that maybe the blocking +所以我就觉得,我觉得或许舞台 + +605 +00:23:03,679 --> 00:23:06,313 +part is not on the iPhone version just the dialog +这个功能不应该出现在 iPhone 的版本上 + +606 +00:23:06,315 --> 00:23:08,381 +warnings cause I could imagine the actors standing +当然我可以想象一群演员站在那 + +607 +00:23:08,383 --> 00:23:11,017 +here with just their iPhone learning their lines or +只有他们的 iPhone 然后学习台词 + +608 +00:23:11,019 --> 00:23:13,586 +whatever so I could, I could if I needed the breath, +或者,如果我愿意,我需要一点广度 + +609 +00:23:13,588 --> 00:23:14,520 +I could add that back in. +那么我就把这个功能加回来 + +610 +00:23:14,522 --> 00:23:17,122 +Okay, to here section one, +这个部分就这样 + +611 +00:23:17,124 --> 00:23:18,423 +where I'm explaining what I'm doing. +之前就是在解释我将要做什么 + +612 +00:23:18,425 --> 00:23:21,292 +Now here's section two, here's all the iOS API +现在是第二部分,这里全是 iOS API + +613 +00:23:21,294 --> 00:23:22,827 +that I'm gonna use to implement that. +我将要实现的 + +614 +00:23:22,829 --> 00:23:25,262 +I'm using TableView as a custom TableView cell. +我要使用 TableView 及自定义 TableView Cell + +615 +00:23:25,264 --> 00:23:27,631 +A UIView with drawRect. +一个使用 drawRect 的 UIView + +616 +00:23:27,633 --> 00:23:28,698 +The camera. +摄像头 + +617 +00:23:28,700 --> 00:23:29,899 +Popovers. +Popovers + +618 +00:23:29,901 --> 00:23:31,600 +I'm using scroll view to zoom in around in +我将会使用 ScrollView 用来缩放 + +619 +00:23:31,602 --> 00:23:33,452 +the blocking view. +这个舞台 + +620 +00:23:33,453 --> 00:23:35,303 +I'm using AVFoundation to do the recording of the sound. +我要使用 AVFoundation 来录音 + +621 +00:23:35,306 --> 00:23:36,738 +I'm using timers. +我要使用 NSTimers + +622 +00:23:36,740 --> 00:23:38,707 +I'm gonna use a thing called Core Data, which is an object +我会使用一个叫做 Core Data 的东西,就是一个 + +623 +00:23:38,709 --> 00:23:40,575 +oriented database to store my data in there. +面向对象的数据库用于存放我的数据 + +624 +00:23:40,577 --> 00:23:42,309 +That would be a not covered in lecture feature, +这个不会包含在课程中 + +625 +00:23:42,311 --> 00:23:44,745 +cuz we're not covering that in lecture this quarter. +因为在这学期我们不会讲到相关内容 + +626 +00:23:44,747 --> 00:23:45,746 +I'm also gonna make it so +我需要使用这个这样我才能 + +627 +00:23:45,748 --> 00:23:47,347 +I can print out my blocking on a printer. +在打印机上打印出我的舞台 + +628 +00:23:47,349 --> 00:23:49,749 +That's also not covered in lecture [SOUND], okay? +这些东西不会包含在课程中 + +629 +00:23:49,751 --> 00:23:50,950 +So there I'm doing substantial +这里我重标记了 + +630 +00:23:50,952 --> 00:23:52,284 +not covering in lecture futures. +不会包含在未来的课程当中 + +631 +00:23:52,286 --> 00:23:55,020 +I'm making it really care what they are in my proposal and +在我的申请里我解释得很明白了 + +632 +00:23:55,022 --> 00:23:57,689 +I'm talking about all the other things I'm gonna do. +我将会说到我将会做的其他所有的东西 + +633 +00:23:57,691 --> 00:23:59,524 +'Kay? + +634 +00:23:59,526 --> 00:24:02,426 +That help you understand what's going on there? +这样可以帮助你理解 + +635 +00:24:02,428 --> 00:24:04,361 +Proposals. +申请表 + +636 +00:24:04,363 --> 00:24:07,831 +Okay, so you submit those proposals as soon as possible, +好的,请尽快提交你们的申请表 + +637 +00:24:07,833 --> 00:24:10,734 +but really no later than next Tuesday, please, +并且请尽量不要超过下周二,谢谢 + +638 +00:24:10,736 --> 00:24:15,071 +to your grading TA, whoever graded your last assignment. +提交给你的打分 TA,那个给你上次任务打分的人 + +639 +00:24:15,073 --> 00:24:17,339 +And they have a lot of you to read, so they'll, +他们会有很多的申请表需要处理 + +640 +00:24:17,341 --> 00:24:20,108 +as quickly as they can, get some feedback to you. +当然,他们也会在最快的时间内给你反馈 + +641 +00:24:20,110 --> 00:24:23,511 +If you don't give it to us by next Tuesday, you know, +如果你没有在下周二之前提交给我们 + +642 +00:24:23,513 --> 00:24:25,480 +still going to be beneficial for you to send it to us. +你仍然能够从我们这里得到一些好处 + +643 +00:24:25,482 --> 00:24:27,181 +It's just that there's going to be less and less time for +只是越晚就越少的时间让我们来 + +644 +00:24:27,183 --> 00:24:28,716 +us to give you any feedback, and +给你任何反馈 + +645 +00:24:28,717 --> 00:24:30,250 +you're going to have to already have gotten started +而且你可能已经开始了 + +646 +00:24:30,252 --> 00:24:32,452 +pretty soon, by the end of next week, let's say. +在下周周末 + +647 +00:24:32,454 --> 00:24:34,988 +You're probably really want to get started. +你或许非常想要开始 + +648 +00:24:34,990 --> 00:24:37,256 +So it's really your own thing. +所以,这其实完全在你 + +649 +00:24:37,258 --> 00:24:40,126 +And again though it's not, you don't have to get it approved +重申一次,你不需要在得到批准后 + +650 +00:24:40,128 --> 00:24:45,263 +to start on your project, +再开始你的项目 + +651 +00:24:45,265 --> 00:24:48,166 +unless you're the two-man team, you do. +除非你是在二人小组中 + +652 +00:24:48,168 --> 00:24:49,551 +You don't have to get approval, but +你不需要获得批准 + +653 +00:24:49,552 --> 00:24:50,935 +you really do wanna get that TA feedback. +但你可能会需要 TA 的反馈 + +654 +00:24:50,937 --> 00:24:53,904 +Cuz you don't wanna start off on a trajectory where the TAs +因为你肯定不想从一个 TA 们觉得 + +655 +00:24:53,906 --> 00:24:56,674 +are like, you're not likely to end up with much of a very +不太好的项目开始 + +656 +00:24:56,676 --> 00:24:58,875 +good project here, cuz there's not gonna be enough breadth, +或许没有足够的广度 + +657 +00:24:58,877 --> 00:25:00,677 +or I don't understand what your not covering lecture +或许我没有明白你是否已经把课堂中的内容 + +658 +00:25:00,679 --> 00:25:03,446 +feature is, or it's not a good enough one, or whatever. +包含进去了,或者这个项目不够好,或者其他 + +659 +00:25:03,448 --> 00:25:07,016 +Now, the other thing to note is that proposal is completely +另一个需要注意的是,申请表完全不是绑定的 + +660 +00:25:07,018 --> 00:25:08,150 +non-binding, except for +除了 + +661 +00:25:08,152 --> 00:25:09,651 +a little bit with a two-man team. +两人小组 + +662 +00:25:09,653 --> 00:25:12,420 +But for everyone else, it's not really binding either way. +但对于其他的人来说,没有绑定的意思 + +663 +00:25:12,422 --> 00:25:15,289 +So if what you turn in is completely +所以如果你最后提交的项目 + +664 +00:25:15,291 --> 00:25:17,792 +different that your proposal, that's fine, okay? +完全不同于你的申请表,这样也可以,好吗 + +665 +00:25:17,794 --> 00:25:19,259 +We're not gonna go back and say, hey wait, +我们也不会翻出你的申请表然后说 + +666 +00:25:19,261 --> 00:25:20,827 +you said in your proposal you're gonna do it. +等等,你在你的申请表里面说你将会做这个 + +667 +00:25:20,829 --> 00:25:22,128 +No, we will not say that. +不,我们永远不会这样说 + +668 +00:25:22,130 --> 00:25:23,363 +But vice versa, too. +但相反的 + +669 +00:25:23,365 --> 00:25:24,730 +If we say in your proposal, +如果我们在你的申请表里说 + +670 +00:25:24,732 --> 00:25:27,466 +oh yeah, doing core data for that, +恩,就要这样使用 Core Data + +671 +00:25:27,468 --> 00:25:29,501 +that sounds like a good not covered in lecture feature. +这样听起来不错,但并没有在课堂中讲过 + +672 +00:25:29,503 --> 00:25:31,102 +And then you go to implement it, and +然后你在实现的过程中 + +673 +00:25:31,104 --> 00:25:34,839 +you do such a trivial version of core data that's not +你只是使用了 Core Data 的一小部分 + +674 +00:25:34,841 --> 00:25:37,541 +substantive enough, we still might ding you and say hey, +并且不会产生显著的效果,我们仍然可能会提示你 + +675 +00:25:37,543 --> 00:25:39,610 +that was not a substantial not covered in lecture feature. +这样并不是很有效,而且也没有包含在课程中 + +676 +00:25:39,612 --> 00:25:41,812 +In other words, your proposal is not graded. +换句话说,你的申请表并不会计分 + +677 +00:25:41,814 --> 00:25:44,814 +It's no part of the grade, we'll never look at it again, +这并不是成绩的一部分,我们也不会再看第二次 + +678 +00:25:44,816 --> 00:25:47,483 +it's just to get you started on the right track. +这只是用于让你有一个正确的开始 + +679 +00:25:47,485 --> 00:25:49,618 +You are still responsible for delivering all +你仍然需要负责实现 + +680 +00:25:49,620 --> 00:25:52,054 +the requirements that I talked about today in your final +我今天提到的所有的任务要求 + +681 +00:25:52,056 --> 00:25:54,189 +project, regardless of what's happening with your proposal. +无论你的申请表得到什么反馈 + +682 +00:25:54,191 --> 00:25:56,024 +So it cuts both ways. +这样两方都受到制约 + +683 +00:25:56,025 --> 00:25:57,858 +We won't hold it against you, and, you know, but +我们不会用来反对你,而你 + +684 +00:25:57,861 --> 00:26:00,795 +you can't come back and say but you said that was okay. +你也不能回来告诉我们说,你之前说这样可以啊 + +685 +00:26:00,797 --> 00:26:02,730 +All right? +好吗? + +686 +00:26:02,732 --> 00:26:04,598 +Make sense? +这样有道理吧 + +687 +00:26:04,600 --> 00:26:06,967 +Okay. + +688 +00:26:06,969 --> 00:26:09,069 +Last thing I want to talk about is collaboration. +关于合作我最后说一下 + +689 +00:26:09,071 --> 00:26:11,070 +So people ask me okay, but +有人问我 + +690 +00:26:11,072 --> 00:26:15,174 +can I work with someone else not in this class on it? +我能否和某个不在这堂课中的人协作? + +691 +00:26:15,176 --> 00:26:16,441 +And the answer is absolutely you can, +答案是,当然可以 + +692 +00:26:16,443 --> 00:26:18,009 +in fact I strongly encourage that. +事实上我非常鼓励你这样 + +693 +00:26:18,011 --> 00:26:19,444 +In fact, last quarter +事实上,上个学期 + +694 +00:26:19,446 --> 00:26:21,412 +I had a thing where it was a requirement +我就有个要求 + +695 +00:26:21,414 --> 00:26:25,782 +to go find somebody to work with outside of this class. +就是去班级之外找一个人 + +696 +00:26:25,784 --> 00:26:27,417 +When I say that, be very careful, +需要注意的是,这个人 + +697 +00:26:27,419 --> 00:26:29,619 +I mean non-coding help. +我指的是非代码相关的帮助 + +698 +00:26:29,621 --> 00:26:31,204 +Okay? +好吗? + +699 +00:26:31,205 --> 00:26:32,788 +You can get someone to help you like a marketing person, +你可以找一个懂市场的家伙来帮助你 + +700 +00:26:32,790 --> 00:26:35,357 +or a salesperson, or somebody who is kind of +或者推销员,或者某个 + +701 +00:26:35,359 --> 00:26:38,894 +a business development person, or an idea man, okay, or +属于商业开发的家伙,或者一个点子男 + +702 +00:26:38,896 --> 00:26:41,196 +idea woman, who's going to give you an idea. +点子女,一个能够提供给你好的主意的人 + +703 +00:26:41,198 --> 00:26:43,598 +That's fine for someone else to give you the idea. +有一个人提供想法,这样是可以的 + +704 +00:26:43,600 --> 00:26:46,801 +But you've gotta totally be the coder and +但你要作为那个写代码的人 + +705 +00:26:46,803 --> 00:26:48,869 +architect of the solution, okay? +并且设计出解决方案来 + +706 +00:26:48,871 --> 00:26:51,171 +Because you are in an iOS development class so +因为你在 iOS 开发课程中 + +707 +00:26:51,173 --> 00:26:55,241 +you gotta do the iOS development part of it, okay? +所以你需要负责 iOS 开发的部分 + +708 +00:26:55,243 --> 00:26:58,311 +Now, that other person who's helping you could also help +你找来的人可以提供 + +709 +00:26:58,313 --> 00:26:59,845 +you with things, maybe giving you assets, +一些帮助,给你一些资源 + +710 +00:26:59,847 --> 00:27:01,647 +maybe they could give you some images or +必须他们可以给你一些图片 + +711 +00:27:01,649 --> 00:27:04,216 +they might give you access to a database or something, +或者他们可以给你一些数据方面的资源 + +712 +00:27:04,218 --> 00:27:06,451 +or some network server that you're gonna oh, +或许是一些你需要的网络服务 + +713 +00:27:06,453 --> 00:27:07,852 +perfectly fair game. +公平的游戏 + +714 +00:27:07,854 --> 00:27:09,854 +It's just they cannot help you with the actual +限制就是不能让他们来帮你 + +715 +00:27:09,856 --> 00:27:11,121 +coding of your app. +写代码 + +716 +00:27:11,123 --> 00:27:13,156 +And it can't be someone else in the class either. +而且这个人也不能在我们的课堂中 + +717 +00:27:13,158 --> 00:27:14,290 +Okay? It's gotta be someone +好吗?这个人必须是 + +718 +00:27:14,292 --> 00:27:15,158 +outside of this class. +在课堂以外的人 + +719 +00:27:16,928 --> 00:27:18,327 +Okay? + +720 +00:27:18,329 --> 00:27:21,296 +So I do have two people here, two Stanford affiliates, +比如这里有两个人,两个斯坦福的人 + +721 +00:27:21,298 --> 00:27:22,597 +who are going to get up and +他们在谈论 + +722 +00:27:22,599 --> 00:27:24,999 +talk a little bit about what they're doing. +他们想要做的事 + +723 +00:27:25,001 --> 00:27:27,034 +And if you like what they're doing, +而你很喜欢他们的想法 + +724 +00:27:27,036 --> 00:27:28,535 +then you can contact them, +那么你可以联系他们 + +725 +00:27:28,537 --> 00:27:32,005 +and maybe they would be your outside idea man or woman. +或许他们会是你在外部的想法来源 + +726 +00:27:32,007 --> 00:27:34,874 +And you could work with with them to +你也可以和他们一起工作 + +727 +00:27:34,876 --> 00:27:37,310 +understand more what they want. +知道他们到底想要什么 + +728 +00:27:37,311 --> 00:27:39,745 +Now what they want might not be suitable, +他们现在想要的东西或许不适合 + +729 +00:27:39,748 --> 00:27:42,348 +exactly, for a final project, because you know what +比如对于最终项目来说,因为你知道 + +730 +00:27:42,350 --> 00:27:44,116 +the requirements are, you've seen them all today. +要求有那些,你今天已经看到了所有的要求 + +731 +00:27:44,118 --> 00:27:46,752 +They're specific academic requirements, and +这些全都属于学术要求 + +732 +00:27:46,754 --> 00:27:48,219 +you got to meet those. +你也必须达成这些要求 + +733 +00:27:48,221 --> 00:27:51,422 +But by the same token, what you do, +但与此同时,你要做的 + +734 +00:27:51,424 --> 00:27:54,258 +what their idea is might help guide you towards +他们的点子或者会引导你 + +735 +00:27:54,260 --> 00:27:56,593 +putting together a lot of good features, and vice versa. +扩展出非常多好的功能,反之亦然 + +736 +00:27:56,595 --> 00:27:58,829 +If you work with these people and +如果你和一些人工作 + +737 +00:27:58,831 --> 00:28:01,264 +you find out this is great, this is really interesting +你觉得他们的想法很棒,很有意思 + +738 +00:28:01,266 --> 00:28:03,199 +maybe then after the class is over you can say okay, +或许你可以在课程结束之后 + +739 +00:28:03,201 --> 00:28:04,700 +well now let's work together and +再与他们合作 + +740 +00:28:04,702 --> 00:28:07,169 +go do something really what we want to do, +去做一些真正有意思的东西 + +741 +00:28:07,171 --> 00:28:09,037 +based the specs of what the requirements are. +而不是依照要求做的东西 + +742 +00:28:09,039 --> 00:28:09,971 +That make sense? +很合理吧? + +743 +00:28:11,574 --> 00:28:15,643 +So back to learning about iOS itself. +让我们回到 iOS 的学习中 + +744 +00:28:15,645 --> 00:28:19,079 +The next thing I'm going to talk about is the unwind +下一个我们要说到的东西是 unwind + +745 +00:28:19,081 --> 00:28:20,464 +segue. +segue + +746 +00:28:20,465 --> 00:28:21,848 +Now this is kind of a weird thing, +这是一个很奇怪的东西 + +747 +00:28:21,850 --> 00:28:25,284 +because I talked to you about all this stuff about segues, +因为之前告诉过你们 segues 是什么 + +748 +00:28:25,286 --> 00:28:27,319 +and then the unwind comes along and +现在来了个 unwind + +749 +00:28:27,321 --> 00:28:30,322 +unwinds a little bit of your knowledge about it. +unwinds 你应该知道一点点 + +750 +00:28:30,324 --> 00:28:33,625 +The most important difference of an unwind segue versus all +它与你知道的那些 segues 最重要的区别就是 + +751 +00:28:33,627 --> 00:28:35,727 +those other segues that you know, the show segue and +show segue 和 pop over segue + +752 +00:28:35,729 --> 00:28:40,031 +the pop over segue is that it does not create a new MVC. +不会创建一个新的 MVC + +753 +00:28:40,033 --> 00:28:42,399 +It is the only segue that does not, +它唯一一种不会这样的 + +754 +00:28:42,401 --> 00:28:46,269 +in the process of seguing, create a new instance of MVC. +在 segue 的过程中,创建一个新的 MVC + +755 +00:28:46,271 --> 00:28:48,872 +Okay? +好吗 + +756 +00:28:48,873 --> 00:28:51,474 +It can only segue to an MVC that either directly or +他只能 segue 到一个 MVC 或者 + +757 +00:28:51,476 --> 00:28:55,310 +indirectly presented the current MVC. +间接地展示当前的 MVC + +758 +00:28:55,312 --> 00:28:59,014 +So the MVC that wants to unwind to another MVC has to +所以 MVC 需要解开另一个已经被 + +759 +00:28:59,016 --> 00:29:03,017 +have been presented directly or indirectly by that. +直接展示或者间接展示的 MVC + +760 +00:29:03,019 --> 00:29:04,819 +So what's it good for? +这样做有什么好处呢? + +761 +00:29:04,821 --> 00:29:06,320 +What does this unwind tell you, +解开的是什么东西 + +762 +00:29:06,322 --> 00:29:07,754 +what do we ever use it for? +我们什么时候会用到呢? + +763 +00:29:07,756 --> 00:29:09,639 +Well, it's really good for +好了,这就是一个非常好的时刻 + +764 +00:29:09,640 --> 00:29:11,523 +jumping back the stack of the navigation controller. +回到之前学习的 navigation controller 栈中 + +765 +00:29:11,526 --> 00:29:13,426 +All right, so you got the navigation controller. +好的,你有一个 navigation controller + +766 +00:29:13,428 --> 00:29:16,529 +You've got six cards, you know, things stacked on there, +你有六张卡牌,你知道,有一叠在那 + +767 +00:29:16,531 --> 00:29:17,930 +and you want to jump back to number two, +你需要返回到第二张 + +768 +00:29:17,932 --> 00:29:20,365 +or all the way back to number one. +或者一直返回到第一张卡牌 + +769 +00:29:20,367 --> 00:29:22,334 +Okay? +好吗 + +770 +00:29:22,335 --> 00:29:24,302 +Well, in the navigation controller, each card down +在 navigation controller 中,每一张卡 + +771 +00:29:24,304 --> 00:29:27,872 +is considered to have been presented by the previous one. +是被前一张卡片展示出来的 + +772 +00:29:27,874 --> 00:29:30,508 +So it falls into this unwind segue thing where directly or +所以,unwind segue 能做的就是让你直接或者 + +773 +00:29:30,510 --> 00:29:32,042 +indirectly you can go back up. +间接地回到之前的位置 + +774 +00:29:32,044 --> 00:29:33,143 +Unwind up. +解开连接 + +775 +00:29:33,144 --> 00:29:34,243 +So that's one good thing about it. +所以这是它的一个优点 + +776 +00:29:34,246 --> 00:29:38,248 +Another one is you have an MVC that's modally presented. +另一个是,你有一个 MVC 并且是通过 modal 的方式展示的 + +777 +00:29:38,250 --> 00:29:41,050 +Now again, I haven't talked really too much about modal +其实我还没有怎么说过 modal 类型的 + +778 +00:29:41,052 --> 00:29:42,368 +presentation. +展示 + +779 +00:29:42,369 --> 00:29:43,685 +I'm going to talk a little bit more about it today. +我今天就会讲到一点 + +780 +00:29:43,688 --> 00:29:45,854 +But modal, I told you what modal is though. +但 modal,我告诉你 modal 是什么 + +781 +00:29:45,856 --> 00:29:49,291 +Modal segue means take over the entire screen. +Modal segue 的意思就是取代整个屏幕 + +782 +00:29:49,293 --> 00:29:51,993 +Even a pop over is basically modal, because when +pop over 就是一种 modal,因为 + +783 +00:29:51,995 --> 00:29:53,995 +a popover's up you can't do anything except for +每当一个 popover 展示出来,除了这个 popover + +784 +00:29:53,997 --> 00:29:55,530 +what's in that popover. +其他的东西你都无法操作 + +785 +00:29:55,531 --> 00:29:57,064 +The only other thing you can do is dismiss the popover by +你能够做的操作就是通过点击某处,来 dismiss + +786 +00:29:57,066 --> 00:29:57,898 +clicking somewhere else. +popover + +787 +00:29:57,900 --> 00:29:59,717 +So that's kind of modal. +这就是 modal + +788 +00:29:59,718 --> 00:30:01,535 +It puts your app in a mode where you can only work +他会让你的 app 进入某种模式,你只能操作 + +789 +00:30:01,537 --> 00:30:03,604 +in that one space. +这个区域 + +790 +00:30:03,605 --> 00:30:05,672 +So a lot of the time when a modal segue comes up +所以在大多数情况下,在使用了 model segue 视图显示在 + +791 +00:30:05,674 --> 00:30:09,442 +on the screen, when it's done it wants to +屏幕上并且通过它我们得到了想要的 + +792 +00:30:09,444 --> 00:30:14,546 +communicate some results back to whoever presented it, okay? +交互结果之后,就需要重新回到之前 present 的界面 + +793 +00:30:14,548 --> 00:30:15,781 +So an unwind would be great for +所以 unwind 在这里使用再不过了 + +794 +00:30:15,783 --> 00:30:18,149 +that because the only other alternative would be, like, +因为这里另一个关联就是 + +795 +00:30:18,151 --> 00:30:20,351 +delegation. +委托 + +796 +00:30:20,352 --> 00:30:22,552 +And, yes, you can have an MVC delegate back to another MVC, +是的,你也可以通过 MVC 委托回到另一个 MVC 中 + +797 +00:30:22,555 --> 00:30:25,122 +because we remember that delegation is our view, +因为我们记得委托的是我们的视图 + +798 +00:30:25,124 --> 00:30:28,158 +talking back blind to our controller. +回到之前绑定的控制器中 + +799 +00:30:28,160 --> 00:30:31,028 +And remember that an MVC can be part of the view of another +但需要记住的是,一个 MVC 也可以是另一个 MVC 中的 View + +800 +00:30:31,030 --> 00:30:33,830 +MVC, so it's legal to use delegation. +所以使用委托也是可以的 + +801 +00:30:33,832 --> 00:30:35,932 +But unwind, it's just a lot easier. +但 unwind,就会让事情变得更简单 + +802 +00:30:35,934 --> 00:30:40,836 +Okay, unwind provides a little pipe for the modal segue to +unwind 会提供一些方法让 modal segue + +803 +00:30:40,838 --> 00:30:43,605 +unwind back to the one that presented it and +与之前 present 的控制器交流或者解绑 + +804 +00:30:43,607 --> 00:30:47,408 +communicate with it, okay, by segueing to it, basically. +好吧,基本上是通过 segue 来做到这一点的 + +805 +00:30:47,410 --> 00:30:48,442 +All right. +好了 + +806 +00:30:48,444 --> 00:30:49,443 +So how does it work? +它是怎么使用的呢 + +807 +00:30:49,445 --> 00:30:52,913 +Instead of Ctrl+dragging +之前的从另一个 + +808 +00:30:52,915 --> 00:30:56,449 +from something to another MVC, okay? +MVC Ctrl+拖动 不同 + +809 +00:30:56,451 --> 00:30:59,519 +You can't really Ctrl+drag to the presenter. +你不能在 presenter 那里 Ctrl+拖动 + +810 +00:30:59,521 --> 00:31:02,188 +It might be in weird places in your storyboard. +这样在你的 storyboard 里面会很奇怪 + +811 +00:31:02,190 --> 00:31:04,423 +It might not make sense. +完全没有道理 + +812 +00:31:04,424 --> 00:31:06,657 +So instead, you Ctrl+drag to this little button at the top +以此代替,你可以在所有的 view controller 上 Ctrl+拖动这个 + +813 +00:31:06,660 --> 00:31:09,961 +of every view controller which is called the Exit icon. +有 Exit 图标的小按钮 + +814 +00:31:09,963 --> 00:31:12,664 +You see it there, it has the word exit. +你能够看到有个 Exit 在那 + +815 +00:31:12,666 --> 00:31:16,267 +And when you Ctrl+drag to that exit, okay, to make the segue, +然后然你 Ctrl+拖动到那个按钮的时候,创建了 segue + +816 +00:31:16,269 --> 00:31:19,136 +it's gonna say, okay, where do you wanna segue to? +它会提示,你想要 segue 到哪里? + +817 +00:31:19,138 --> 00:31:22,039 +And instead of specifying a particular MVC, +与之前不同,不是指定特定的 MVC + +818 +00:31:22,041 --> 00:31:26,076 +you specify a special IBAction, okay? +你需要指定特定的一个 IBAction 控件 + +819 +00:31:26,078 --> 00:31:29,579 +So my IBAction here I only wanna have is go back. +所以在我的 IBAction 这里我想要让他返回上一级 + +820 +00:31:29,581 --> 00:31:31,948 +All right, that's the name of an IBAction method, +好了,这是 IBAction 方法的名字 + +821 +00:31:31,950 --> 00:31:35,417 +somewhere in some MVC out there. +在某个 MVC 里面 + +822 +00:31:35,419 --> 00:31:36,985 +Okay? + +823 +00:31:36,986 --> 00:31:38,552 +Now what's special about it is the argument of it, +特别之处在于参数 + +824 +00:31:38,555 --> 00:31:39,921 +is a UI storyboard segue. +他是一个 UIStoryboard segue + +825 +00:31:39,923 --> 00:31:42,757 +The same argument that's given to prepare for segue, okay, +与 prepareForSegue 的参数相同 + +826 +00:31:42,759 --> 00:31:43,775 +UI storyboard segue. +UIStoryboardSegue + +827 +00:31:43,776 --> 00:31:44,792 +That's what makes it special. +这就是其特别之处 + +828 +00:31:44,794 --> 00:31:49,396 +So when you add an IBAction method to any MVC and +当你在任何一个 MVC 中添加了 IBAction 方法 + +829 +00:31:49,398 --> 00:31:52,098 +the argument of it is a UI storyboard segue, +如果它的参数是 UIStoryboardSegue + +830 +00:31:52,100 --> 00:31:54,300 +then when people Ctrl+drag to their exit, +当大家 Ctrl+拖动到退出按钮的时候 + +831 +00:31:54,302 --> 00:31:56,502 +they'll see it in this list, okay? +他们会看到这些方法出来列表中 + +832 +00:31:56,504 --> 00:31:57,936 +So it can be any MVC anywhere. +所以他们可以在任何一个 MVC 中 + +833 +00:31:57,938 --> 00:32:00,872 +Now of course if you try to unwind, and +当然如果你现在尝试着 unwind + +834 +00:32:00,874 --> 00:32:03,241 +you pick a method in an MVC, and +你选择了 MVC 中的一个方法 + +835 +00:32:03,243 --> 00:32:07,211 +no MVC presented you that implements that method. +那么在 MVC 中你实现的这个方法 + +836 +00:32:07,213 --> 00:32:09,780 +Then the unwind segue's gonna do nothing, okay? +unwind segue 不会有任何效果 + +837 +00:32:09,782 --> 00:32:12,249 +Because it's not gonna be able to find a presenter who +因为它没有办法找到实现了 + +838 +00:32:12,251 --> 00:32:14,284 +implements this method, okay? +这个方法的 presenter + +839 +00:32:14,286 --> 00:32:16,419 +So, but let's say you do have a presenter. +但这么说吧,你有一个 presenter + +840 +00:32:16,421 --> 00:32:18,621 +Let's say you're in a navigation controller and +假设你在一个 navigation controller 中 + +841 +00:32:18,623 --> 00:32:22,458 +somebody who put you on screen has this method. +然后把你展示在屏幕上的某人有这个方法 + +842 +00:32:22,460 --> 00:32:24,143 +Go back. +回去 + +843 +00:32:24,144 --> 00:32:25,827 +You see it takes a UI story board segue there. +你看到一个 UIStoryboardSegue + +844 +00:32:25,829 --> 00:32:29,064 +Then if I wire up my unwind segue to that then I am +如果我连接了我的 unwind segue + +845 +00:32:29,066 --> 00:32:31,666 +basically going to be segueing back to that presenter. +那么我就可以 segue 回到那个 presenter + +846 +00:32:32,735 --> 00:32:35,869 +Okay, so that's how you hook it up, basically. +基本上这就是如何连接的 + +847 +00:32:35,871 --> 00:32:39,506 +All right, now what happens once you get this hooked up? +好,那么当你连接这些东西之后会发生什么呢 + +848 +00:32:41,176 --> 00:32:43,042 +So there has to be IBAction and +这里有个 IBAction + +849 +00:32:43,044 --> 00:32:45,344 +there has to be UIStoryboardSegue. +他们必须要有 UIStoryboardSegue 作为参数 + +850 +00:32:45,346 --> 00:32:48,380 +Okay, otherwise IX code will not be able to detect +否则 Xcode 不能检测到 + +851 +00:32:50,950 --> 00:32:54,752 +that possible unwind. +那些可以使用的 unwind + +852 +00:32:54,754 --> 00:32:57,654 +Okay, so when you segue, it is a normal segue +好了,当你 segue 的时候,这就是在 prepareForSegue: 中的 + +853 +00:32:57,656 --> 00:33:00,424 +in that you get to prepare for segue, right? +一个普通的 segue 对吧 + +854 +00:33:00,426 --> 00:33:03,593 +So the guy on the right there, he gets to implement +在右边的这个家伙,他实现了 + +855 +00:33:03,595 --> 00:33:06,529 +prepareForSegue and when the unwind happens to his little +prepareForSegue 然后当 unwind 在他的退出按钮按下时 + +856 +00:33:06,531 --> 00:33:08,397 +exit button, and he starts looking for +他就会开始寻找那个 + +857 +00:33:08,399 --> 00:33:10,866 +that go back method somewhere in a presenter. +把他展示出来的类 + +858 +00:33:11,835 --> 00:33:13,885 +He's going to get to prepare. +他就会得到 prepare + +859 +00:33:13,886 --> 00:33:15,936 +So you just implement normal prepareForSegue inside of +如果你就是实现了 prepareForSegue 的那个人 + +860 +00:33:15,939 --> 00:33:20,108 +that guy, and the presenter, okay, is gonna get prepared. +作为展示者,就会需要准备好 + +861 +00:33:20,110 --> 00:33:22,510 +And then the presenter's also going to have this go back +然后在 presenter 准备好了之后 + +862 +00:33:22,512 --> 00:33:25,245 +method called after he's prepared. +他就会拥有这个方法 + +863 +00:33:25,247 --> 00:33:26,246 +Okay? + +864 +00:33:26,248 --> 00:33:29,449 +So the presenter gets really prepared, kinda, +当一个 presenter 确实准备好了 + +865 +00:33:29,451 --> 00:33:31,017 +or gets information twice. +他会得到两次这样的信息 + +866 +00:33:31,019 --> 00:33:34,086 +It gets it once when it's preparedForSegue, because +第一次就是 preparedForSegue + +867 +00:33:34,088 --> 00:33:37,823 +it's the destination MVC and it's going to get prepared. +因为这就是 MVC 的目的,它就会准备好 + +868 +00:33:38,959 --> 00:33:41,259 +Now it's already here so it's already pretty prepared but +现在它已经准备好了 + +869 +00:33:41,261 --> 00:33:42,760 +maybe it gets prepared more. +但或许它需要再准备一下 + +870 +00:33:42,762 --> 00:33:44,895 +And then when the Segue happens, +然后当 segue 发生了 + +871 +00:33:44,897 --> 00:33:46,797 +go back will be called. +goBack 方法会被调用 + +872 +00:33:46,799 --> 00:33:49,733 +And in the Segue that's passed as the argument there, +并且在这个 segue 参数这里 + +873 +00:33:49,735 --> 00:33:53,602 +the presenter can find out who is segueing to me, and +presenter 可以知道是谁在向我 segue + +874 +00:33:53,604 --> 00:33:54,903 +what are they communicating to me? +到底是谁在向我联系 + +875 +00:33:54,905 --> 00:33:56,204 +What do they want to communicate to me, +为什么他们要与我交流 + +876 +00:33:56,206 --> 00:33:58,373 +in fact they can talk too, it uses public API to get +他们也确实可以交流,可以使用公共方法 + +877 +00:33:58,375 --> 00:33:59,841 +whatever information they want. +获得他们想知道的任何信息 + +878 +00:33:59,843 --> 00:34:02,910 +So basically it creates a link. +基本上会创建一个连接 + +879 +00:34:02,912 --> 00:34:05,813 +So you will be dismissed in the process. +你可以在这个过程中 dismiss + +880 +00:34:05,815 --> 00:34:08,415 +When you unwind, when the user clicks on whatever you +当然你 unwind 当用户点击了任何你 + +881 +00:34:08,417 --> 00:34:12,352 +control-dragged to that exit button, after this happens +之前 control-拖动到退出按钮的控件 + +882 +00:34:12,354 --> 00:34:15,187 +you're gonna get always get dismissed. +那么你就会消失掉 + +883 +00:34:16,156 --> 00:34:17,255 +Okay? So +那么 + +884 +00:34:17,256 --> 00:34:18,355 +if you're in the navigation controller, +如果你在 navigation controller 里面 + +885 +00:34:18,358 --> 00:34:20,858 +the navigation will pop back up to the presenter. +这个 navigation 将会返回到展示它的那个类那里 + +886 +00:34:20,860 --> 00:34:22,393 +If you're modal, you will go away, +如果你是通过 modal 的方式展示你会消失 + +887 +00:34:22,395 --> 00:34:24,695 +you'll stop taking over the whole screen. +不再接管整个屏幕 + +888 +00:34:24,697 --> 00:34:26,580 +Okay? + +889 +00:34:26,581 --> 00:34:28,464 +So you are gonna unwind, that's why we kind of call it +如果你要 unwind,这也是为什么我们叫他 + +890 +00:34:28,467 --> 00:34:33,703 +unwinding, you're wound up and now you kind of get unwound. +unwinding,你们会解开之间的联系 + +891 +00:34:33,705 --> 00:34:34,937 +So yeah, so Modal segues, +好了,Modal segues + +892 +00:34:34,939 --> 00:34:38,273 +navigation controllers, exactly the same mechanism. +导航控制,基本上是相同的机制 + +893 +00:34:38,275 --> 00:34:39,474 +All right, so that's it for unwind, +好了,这就是 unwind + +894 +00:34:39,476 --> 00:34:41,326 +it's as simple as that. +就是这么简单 + +895 +00:34:41,327 --> 00:34:43,177 +You could possibly use unwind in your assignment +你可以根据你的需求 + +896 +00:34:43,180 --> 00:34:44,312 +four if you want. +尽情地使用 unwind + +897 +00:34:44,314 --> 00:34:47,682 +I talk about it in the required task and the hints. +我会在附加任务中提到,并且有提示 + +898 +00:34:47,684 --> 00:34:49,383 +It's not a required task, +这并不是一个必做的任务 + +899 +00:34:49,385 --> 00:34:52,219 +it's just a way you could do it, okay? +这只是一个选项而已 + +900 +00:34:52,221 --> 00:34:54,587 +And you can decide whether you wanna use an unwind or not. +你可以选择使用或者不使用 unwind + +901 +00:34:54,589 --> 00:34:56,989 +It would be a good experience for you to use an unwind. +如果你要使用 unwind 的话,这会是一个很好的例子 + +902 +00:34:56,991 --> 00:34:59,258 +Question. >> Is the default background +学生提问 + +903 +00:34:59,260 --> 00:35:03,061 +in the navigation controller actually doing that? + +904 +00:35:03,063 --> 00:35:03,962 +>> Yes. The question is, +>> 好的,问题是 + +905 +00:35:03,964 --> 00:35:06,130 +is the back button unwinding? +是否回退按钮在处理 unwind + +906 +00:35:06,132 --> 00:35:07,698 +And the answer is no. +答案是不 + +907 +00:35:07,700 --> 00:35:11,568 +That back button is wired to a method navigation controller, +回退按钮只是连接了 navigation controller 中的方法 + +908 +00:35:11,570 --> 00:35:13,670 +called pop view controller. +叫做 pop view controller + +909 +00:35:13,672 --> 00:35:14,955 +And it just pops up, +它只是弹出了 + +910 +00:35:14,956 --> 00:35:16,239 +so it doesn't get to do any of the unwinding. +所以并没有参与到 unwind 当中来 + +911 +00:35:16,241 --> 00:35:18,941 +It doesn't get to be prepared, you don't get the, +它没有得到准备,而且你也不会 + +912 +00:35:18,943 --> 00:35:21,343 +you don't have to implement that action with the, +你也不需要实现这个方法 + +913 +00:35:21,345 --> 00:35:24,479 +so it's no, the answer is no [COUGH]. +所以不,答案是不 + +914 +00:35:24,481 --> 00:35:26,014 +Okay any other questions about unwind? +好了,有其他与 unwind 相关的问题吗? + +915 +00:35:27,917 --> 00:35:29,216 +Okay, next topic. +好了,下一个话题 + +916 +00:35:29,218 --> 00:35:31,552 +Alerts and Action Sheets, okay? +Alerts 和 Action Sheets +Alerts 和 Action Sheets + +917 +00:35:31,554 --> 00:35:34,388 +So there are two kinds of "pop up and +在 iOS 中可以使用两种用来 + +918 +00:35:34,390 --> 00:35:37,657 +ask the user something" mechanisms in iOS. +请求用户选择的弹出框 + +919 +00:35:37,659 --> 00:35:40,426 +One is called an alert, and one is called an action sheet. +一种叫做 Alert,另一种叫 Action sheet + +920 +00:35:40,428 --> 00:35:44,596 +And they use, actually, exactly the same API. +而他们两的使用方法,基本上相同 + +921 +00:35:44,598 --> 00:35:47,132 +You set them up in exactly the same way and +你通过同样的方式来设置他们 + +922 +00:35:47,134 --> 00:35:48,933 +I'm gonna show you how that works. +我马上会向你演示如何操作 + +923 +00:35:48,935 --> 00:35:50,468 +What's the difference between the two? +那么这两个东西之间有什么区别呢? + +924 +00:35:50,470 --> 00:35:51,769 +Okay. Alerts, first of all, +好,Alerts,但首先 + +925 +00:35:51,771 --> 00:35:52,870 +they pop in the middle of the screen. +它们都会直接弹出出现在屏幕的中央 + +926 +00:35:52,872 --> 00:35:54,188 +They're both modal. +他们都是 modal 的形式 + +927 +00:35:54,189 --> 00:35:55,505 +Okay? They're both basically modal +他们基本上就是最基础的 modal + +928 +00:35:55,507 --> 00:35:56,806 +view controllers. +view controller + +929 +00:35:56,808 --> 00:35:59,075 +Okay? They're just kind of +他们只是有另一种显示的样式 + +930 +00:35:59,077 --> 00:36:01,143 +drawn in a certain way, but they're really just a modal +但其实他们就是 + +931 +00:36:01,145 --> 00:36:03,178 +view controller because they both take over the screen. +view controller,因为他们两都会掌管屏幕 + +932 +00:36:04,548 --> 00:36:06,614 +But the alerts takes over the screen and +但 alerts 会接管屏幕并且 + +933 +00:36:06,616 --> 00:36:09,083 +comes up right in the middle. +直接出现在中央 + +934 +00:36:09,085 --> 00:36:11,819 +And usually alert is gonna ask you a question, +而且通常 Alert 会向你问一些问题 + +935 +00:36:11,821 --> 00:36:15,355 +ask the user a question where there is only, kind of, one or +向用户询问那些只有一到两个 + +936 +00:36:15,357 --> 00:36:16,189 +two answers. +答案的问题 + +937 +00:36:16,191 --> 00:36:18,858 +Like yes no, or do this cancel, or +比如是或者否,或者要么取消 + +938 +00:36:18,860 --> 00:36:20,659 +something like that. +要么做那个 + +939 +00:36:20,661 --> 00:36:23,462 +An alert also, by the way, can also have a text field, so +同时,一个 alert 会有一个文本输入框 + +940 +00:36:23,464 --> 00:36:24,996 +it could be like log in and +可以是登录 + +941 +00:36:24,998 --> 00:36:26,931 +you have to type your password in there. +然后你可以在那输入你的密码 + +942 +00:36:26,933 --> 00:36:29,267 +Okay or maybe even user name and password. +甚至用户名和密码 + +943 +00:36:29,269 --> 00:36:30,968 +So it can collect text. +所以它可以可以收集文本 + +944 +00:36:30,970 --> 00:36:32,770 +Action sheet cannot collect text from the user, +Action sheet 就不能从用户那收集文本 + +945 +00:36:32,772 --> 00:36:34,771 +only the alert can do that. +只有 Alert 可以这样做 + +946 +00:36:34,773 --> 00:36:37,407 +But if you had a question that had more than two answers to +但如果你有超过两个答案的问题 + +947 +00:36:37,409 --> 00:36:40,710 +it you're probably going to use an action sheet. +那么你最好选择使用 Action sheet + +948 +00:36:40,712 --> 00:36:43,212 +Okay, so an action sheet. +好,Action sheet + +949 +00:36:43,214 --> 00:36:45,014 +It presents on screen a little differently. +它在屏幕上的样子稍微有点不同 + +950 +00:36:45,016 --> 00:36:46,348 +It doesn't come up in the middle of the screen +它不会像 Alert 那样出现在 + +951 +00:36:46,350 --> 00:36:48,100 +like an alert. +屏幕的正中间 + +952 +00:36:48,101 --> 00:36:49,851 +It usually slides up from the bottom on an iPhone. +它同样从 iPhone 的底部滑出 + +953 +00:36:49,853 --> 00:36:53,254 +On an IPad we usually put it up in a popover and +在 iPad 上我们通常会把它作为 popover 的形式出现 + +954 +00:36:53,256 --> 00:36:56,023 +I'm going to show you how we do that in a moment. +我待会会向你展示是怎么做的 + +955 +00:36:56,025 --> 00:36:59,493 +An action sheet is sometimes referred to as a branching +一个 Action Sheet 就是某种集结了一堆选项 + +956 +00:36:59,495 --> 00:37:01,995 +decision sheet, so where you're basically making +的表单,也就是说你可以在用户需要在三到四个选项中 + +957 +00:37:01,997 --> 00:37:04,531 +a branching decision where the user wants to +选择其中一件的时候 + +958 +00:37:04,533 --> 00:37:07,600 +do one of three or four things and you're kind of picking +你可以通过它列出这一堆选项 + +959 +00:37:07,602 --> 00:37:10,436 +which one you're going to do, and you're gonna head down +你可以把这个操作 + +960 +00:37:10,438 --> 00:37:11,770 +that direction inside your app, okay? +内置在你的应用中 + +961 +00:37:12,806 --> 00:37:16,041 +So I think by example +我想通过例子 + +962 +00:37:16,043 --> 00:37:18,076 +is the easiest way to kind of see the difference here. +才是看出区别的最简单的方式 + +963 +00:37:18,078 --> 00:37:21,679 +So, I took our Cassini out that we wrote, and I added a +在这里可以看到我们之前画的 Cassini 飞船,然后我在右上角 + +964 +00:37:21,681 --> 00:37:25,082 +little button on the top that actually controls Cassini. +添加了一个小按钮来控制 Cassini + +965 +00:37:25,084 --> 00:37:29,586 +Okay, it'll redeploy Cassini off to different places, okay, +它可以重新部署 Cassini 飞到其他的地方 + +966 +00:37:29,588 --> 00:37:31,954 +Saturn or can send it off to Titan or +土星或者泰坦 + +967 +00:37:31,956 --> 00:37:34,990 +send it towards the sun, or whatever. +或者让它朝着太阳飞等等 + +968 +00:37:34,992 --> 00:37:36,658 +Okay so I added that little redeploy button. +好了我添加的这个小小的重新部署按钮 + +969 +00:37:36,660 --> 00:37:38,493 +You see it up in the right hand corner there? +你可以在右上角看到它吧 + +970 +00:37:38,495 --> 00:37:39,861 +It says redeploy. +上面写着重新部署 + +971 +00:37:39,863 --> 00:37:43,464 +So part of my implementation of allowing the scene to be +所以我的实现想法是通过 Action sheet 和 Alert + +972 +00:37:43,466 --> 00:37:46,200 +redeployed, I use an action sheet and an alert. +来重新部署场景 + +973 +00:37:46,202 --> 00:37:47,785 +Okay? + +974 +00:37:47,786 --> 00:37:49,369 +So here's the action sheet I used. +这里是一个 Action sheet + +975 +00:37:49,372 --> 00:37:51,772 +When you click that redeploy button, it's gonna put up an +当你点击那个重新部署按钮,它会弹出一个 + +976 +00:37:51,774 --> 00:37:54,874 +action sheet that says where do you wanna send Cassini to? +Action sheet 问你你想让 Cassini 去哪里? + +977 +00:37:54,876 --> 00:37:56,776 +I'm sure the Cassini guys have an app just like this, +我敢肯定控制 Cassini 的家伙肯定也有一个像这样的 App + +978 +00:37:56,778 --> 00:37:58,611 +it's how Cassini is controlled. +这一定就是 Cassini 被控制的方式 + +979 +00:37:58,613 --> 00:38:02,381 +But, our app only lets them send it to Saturn, or +但,我们的应用只允许我们让它去土星或者 + +980 +00:38:02,383 --> 00:38:06,985 +Titan, moon of, is that a moon of Jupiter, I guess? +泰坦,卫星,那是木星的卫星吗?我猜的 + +981 +00:38:06,987 --> 00:38:09,854 +Or they can go take a closeup of the sun, +或者它可以到离太阳很近的地方 + +982 +00:38:09,856 --> 00:38:11,689 +which is going to destroy Cassini. +这样做会摧毁掉 Cassini + +983 +00:38:11,691 --> 00:38:13,757 +Okay? Because it's too hot there. +因为那里太热了 + +984 +00:38:13,759 --> 00:38:15,592 +Or they can cancel. +或者他们可以取消 + +985 +00:38:15,593 --> 00:38:17,426 +So that's the action sheet that I invented. +这就是我创建的 Action sheet + +986 +00:38:17,429 --> 00:38:20,663 +And then if you decide you want to go somewhere, +如果你决定好了你想要去哪里 + +987 +00:38:20,665 --> 00:38:23,633 +then I put up an alert that says oh, if you want to send +那么我就会弹出一个 Alert 问你,嘿,如果你想要让 + +988 +00:38:23,635 --> 00:38:27,670 +Cassini to Titan, you need to login and give your guidance +Cassini 去泰坦,那么你需要登录并且交出 + +989 +00:38:27,672 --> 00:38:30,539 +system control password or something, okay? +你的导航系统密码或随便什么 + +990 +00:38:30,541 --> 00:38:32,540 +So this is my alert, okay? +所以这就是我的 Alert + +991 +00:38:32,542 --> 00:38:34,042 +So we're going to look at the code, +我们将要看一下代码 + +992 +00:38:34,044 --> 00:38:37,711 +how I did this action sheet and alert. +我是怎么实现这个 Action sheet 和 Alert 的 + +993 +00:38:37,713 --> 00:38:39,697 +Okay? So + +994 +00:38:39,698 --> 00:38:41,682 +let's start with the action sheet. +让我们从 Action sheet 开始 + +995 +00:38:41,684 --> 00:38:44,317 +Now the code for both looks incredibly similar, so +这两个东西的代码看起来惊人地相似 + +996 +00:38:44,319 --> 00:38:45,852 +what I'm teaching you here about action sheet, +所以我现在教你的 action sheeet + +997 +00:38:45,854 --> 00:38:48,254 +almost can be 100% applying to the alert. +几乎完全可以用在 alert 上 + +998 +00:38:48,256 --> 00:38:49,455 +But basically in either case, +对于两种方案来说 + +999 +00:38:49,457 --> 00:38:52,257 +you create an instance of a UIAlertController. +你都是在创建一个 UIAlertController 的实例 + +1000 +00:38:52,259 --> 00:38:54,659 +This is just a UI view controller, okay. +这就是一个 UIViewController + +1001 +00:38:54,661 --> 00:38:58,162 +It's a sub class of a UI view controller [SOUND] that, +它是 UIViewController 的子类 + +1002 +00:38:58,164 --> 00:39:00,598 +you know, gets presented modally. +你懂的, + +1003 +00:39:00,600 --> 00:39:01,732 +And that's basically it. +基本上就是这样 + +1004 +00:39:01,734 --> 00:39:03,700 +Okay, alerts and actions are basically a sub class of +Alerts 和 Actions 基本上就是 UIViewController + +1005 +00:39:03,702 --> 00:39:05,268 +UI view controllers that get presented modally. +被以 modal 的形式展示了出来 + +1006 +00:39:05,270 --> 00:39:08,137 +They just happen to draw on these particular ways. +他们只是被某种特殊的实行画了出来 + +1007 +00:39:08,139 --> 00:39:09,939 +When you create your view control, you're going to give +当你创建 view controller 的时候,你需要给出一个 + +1008 +00:39:09,941 --> 00:39:12,875 +the title that you can see where the title Redeploy +标题,你可以在 action sheet 的最上面 + +1009 +00:39:12,877 --> 00:39:16,544 +Cassini appears there in my action sheet right at the top. +看到有个标题 "Redeploy Cassini" + +1010 +00:39:16,546 --> 00:39:18,580 +And then the message, +然后是信息 + +1011 +00:39:18,581 --> 00:39:20,615 +which will appear right below it in non bold. +会在标题下面以非粗体的形式展示 + +1012 +00:39:20,617 --> 00:39:22,550 +That's actually probably using preferred fonts. +这是可能就是使用的 preferred fonts + +1013 +00:39:22,552 --> 00:39:24,585 +So that's probably actually like a headline font and +这可能就是大标题粗体 + +1014 +00:39:24,587 --> 00:39:27,187 +a body font I'm guessing. +字号,我猜 + +1015 +00:39:27,189 --> 00:39:29,222 +And then you specify the preferred style. +但后你需要指定一个样式 + +1016 +00:39:29,224 --> 00:39:31,224 +So this is how you decide whether it's an action sheet +这里就是你决定显示为 action sheet + +1017 +00:39:31,226 --> 00:39:32,291 +or an alert. +还是 alert + +1018 +00:39:32,293 --> 00:39:33,525 +So here I'm doing action sheet so +那么我将选择 action sheet + +1019 +00:39:33,527 --> 00:39:35,927 +I say UIAlertController style action sheet. +我填上 UIAlertController 样式 Action sheet + +1020 +00:39:35,929 --> 00:39:37,462 +So that means I'm making an action sheet. +这就以为着我要制作一个 Action sheet + +1021 +00:39:37,464 --> 00:39:38,647 +So that's it. +就是这样 + +1022 +00:39:38,648 --> 00:39:39,831 +I create my view controller. +我创建了我自己的 View Controller + +1023 +00:39:39,833 --> 00:39:45,035 +Now I need to add some items into there like orbit Saturn, +现在我需要添加一些选项,比如土星轨道 + +1024 +00:39:45,037 --> 00:39:48,505 +explore Titan, close up of Sun, cancel. +勘探泰坦,靠近太阳,取消 + +1025 +00:39:48,507 --> 00:39:50,190 +How do I do that? +我要怎么做呢? + +1026 +00:39:50,191 --> 00:39:51,874 +I do that by calling the method addAction on the alert +我通过 alert 来调用方法 addAction + +1027 +00:39:51,877 --> 00:39:54,043 +on this view controller I just created. +在这个我刚刚创建的 view controller 上 + +1028 +00:39:54,045 --> 00:39:56,345 +And the argument to that is a UIAlertAction, +参数就是 UIAlertAction + +1029 +00:39:56,347 --> 00:39:59,214 +which is another class that I'm going to create, which +这就是另一个我将要创建的类 + +1030 +00:39:59,216 --> 00:40:02,117 +really just kind of collects all of the information about +这基本上就是专门为了收集信息 + +1031 +00:40:02,119 --> 00:40:03,284 +a particular action. +的一个类 + +1032 +00:40:03,286 --> 00:40:05,887 +So here is how UIAlertAction looks like. +好了,这就是 UIAlertAction 的样子 + +1033 +00:40:05,889 --> 00:40:07,088 +It's got a title. +它需要一个标题 + +1034 +00:40:07,090 --> 00:40:09,890 +That's like Orbit Saturn there or Explore Titan, +比如土星轨道或这探索泰坦 + +1035 +00:40:09,892 --> 00:40:11,324 +that's the title. +这就是标题 + +1036 +00:40:11,326 --> 00:40:12,292 +It's got a style. +它需要样式 + +1037 +00:40:12,294 --> 00:40:13,526 +We'll talk about that in a second. +我们待会再来讲这个 + +1038 +00:40:13,528 --> 00:40:15,928 +And then it's got a handler, okay? +它还需要一个 handler + +1039 +00:40:15,930 --> 00:40:17,763 +So here, you're starting to see closures again in +这里,你又会看到闭包出现在 + +1040 +00:40:17,765 --> 00:40:18,864 +the iOS API. +iOS API 中 + +1041 +00:40:18,866 --> 00:40:20,965 +This handler is just a closure, okay? +这个 handler 就是闭包 + +1042 +00:40:20,967 --> 00:40:23,801 +The argument is gonna be this action itself, so +这个参数就是这个 action 本身 + +1043 +00:40:23,803 --> 00:40:25,369 +it's basically like sender. +基本上就像 sender 一样 + +1044 +00:40:25,371 --> 00:40:28,238 +And inside this closure, you can do whatever you wanna do +在这个闭包里面,当点击这个 action 的时候 + +1045 +00:40:28,240 --> 00:40:30,340 +when they click on that particular action, +你可以做任何你想要做的事情 + +1046 +00:40:30,342 --> 00:40:31,608 +like Orbit Saturn. +比如土星轨道 + +1047 +00:40:31,610 --> 00:40:33,776 +So the code in there would probably go off and +在代码里面可能会是 + +1048 +00:40:33,778 --> 00:40:38,013 +send Cassini instructions to go Orbit Saturn, okay? +给 Cassini 发送命令,去土星轨道 + +1049 +00:40:38,015 --> 00:40:39,581 +So let's look at an example of one of these. +我们来看一个例子 + +1050 +00:40:39,583 --> 00:40:40,982 +Let's look at Orbit Saturn. +来看看土星轨道 + +1051 +00:40:40,984 --> 00:40:44,652 +The title is Orbit Saturn, the style is default, okay? +标题就是土星轨道,样式为默认 + +1052 +00:40:44,654 --> 00:40:46,587 +We'll talk about some other styles in a second here, but +等一下我们会讲到其他的样式 + +1053 +00:40:46,589 --> 00:40:48,522 +default is just the default line, +但现在就填默认样式 + +1054 +00:40:48,524 --> 00:40:50,957 +this blue colored text right there, like Orbit Saturn, +像土星轨道,探索泰坦这样,这种蓝色的文字, + +1055 +00:40:50,959 --> 00:40:53,793 +Explore Titan, they're both that. +他们两就属于默认样式 + +1056 +00:40:53,795 --> 00:40:55,445 +And then the closure I'm +然后是闭包 + +1057 +00:40:55,446 --> 00:40:57,096 +gonna put is just to go into orbit around Saturn. +我将会直接进入土星环形轨道 + +1058 +00:40:57,098 --> 00:40:59,932 +And similarly, Explore Titan would look exactly the same, +同样的,探索泰坦也使用 + +1059 +00:40:59,934 --> 00:41:02,134 +also default style. +完全相同的默认样式 + +1060 +00:41:02,136 --> 00:41:05,904 +And maybe Cassini's mission was I think to orbit Saturn or +我想的 Cassini 的任务是 + +1061 +00:41:05,906 --> 00:41:07,172 +go to Saturn. +去土星 + +1062 +00:41:07,173 --> 00:41:08,439 +So maybe if you're gonna switch it over to going to +或许你可以修改为去 + +1063 +00:41:08,441 --> 00:41:11,709 +Titan then you have to log in and do your guidance password. +泰坦,然后你需要登录并且输入你的导航密码 + +1064 +00:41:11,711 --> 00:41:13,677 +Otherwise, you can always send Cassini back to +除此之外,你也可以让 Cassini 回去或者去 + +1065 +00:41:13,679 --> 00:41:15,145 +Saturn, I guess. +土星,我猜 + +1066 +00:41:15,147 --> 00:41:16,279 +Okay. +好了 + +1067 +00:41:16,281 --> 00:41:19,082 +So there's the example of the default actions. +这就是默认 actions 的例子 + +1068 +00:41:19,084 --> 00:41:21,484 +So let's look at the next one, that Closeup of Sun. +让我们来看看下一个,靠近太阳 + +1069 +00:41:21,486 --> 00:41:24,820 +So the Closeup of Sun is almost exactly the same except +靠近太阳也几乎与刚才一样 + +1070 +00:41:24,822 --> 00:41:28,223 +for its style is not default, it's .Destructive. +除了它的样式不是默认,而是 .Destructive + +1071 +00:41:29,225 --> 00:41:31,025 +Okay? +好吗 + +1072 +00:41:31,026 --> 00:41:32,826 +So .Destructive makes it show up in red. +.Destructive 会让文字变成红色 + +1073 +00:41:32,829 --> 00:41:34,995 +So anything that's gonna really damage something, +所以任何会造成损害的事情 + +1074 +00:41:34,997 --> 00:41:38,465 +like delete this entry, or something like that, +比如删除这个实例,或者其他的东西 + +1075 +00:41:38,467 --> 00:41:41,868 +you can make it .Destructive and it will show up in red. +你就可以使用 .Destructive 然后它就会显示为红色 + +1076 +00:41:41,870 --> 00:41:43,486 +Okay. + +1077 +00:41:43,487 --> 00:41:45,103 +Otherwise, it's exactly the same as the other ones. +除此之外还有另一个样式 + +1078 +00:41:45,106 --> 00:41:48,707 +And then the Cancel one also has a special thing, .Cancel. +对于取消来说,也有一个特殊的东西 .Cancel + +1079 +00:41:48,709 --> 00:41:49,541 +All right? +好吧 + +1080 +00:41:49,543 --> 00:41:52,343 +And you can see that Cancel is +你可以看到取消 + +1081 +00:41:52,345 --> 00:41:54,412 +kinda separated from the rest of em? +是与其他选项分开的 + +1082 +00:41:54,414 --> 00:41:56,747 +It's down at the bottom, it's got a little extra space. +它在最下面,并且有额外的一点空间 + +1083 +00:41:56,749 --> 00:41:58,849 +That's pretty much the only difference between Cancel, +这基本上就是取消样式的唯一区别了 + +1084 +00:41:58,851 --> 00:42:01,484 +cuz you still get a closure there you get to execute, +因为你仍然可以在点击它的时候 + +1085 +00:42:01,486 --> 00:42:02,485 +when it's clicked on. +执行一个闭包 + +1086 +00:42:04,222 --> 00:42:06,022 +Okay, so that's it. +好了,就是这样 + +1087 +00:42:06,023 --> 00:42:07,823 +So, alerts couldn't be any simpler to create, okay? +Alerts 已经不能更简单了 + +1088 +00:42:07,825 --> 00:42:10,258 +So that's how you create this view controller and +这就是你怎么创建这个 view controller 并且 + +1089 +00:42:10,260 --> 00:42:11,960 +configure it with its actions. +配置它的行为 + +1090 +00:42:11,962 --> 00:42:13,594 +Now, how do we put this thing on screen? +现在,我们应该怎么把它放在屏幕上呢 + +1091 +00:42:13,596 --> 00:42:15,529 +How do we get this alert to actually slide up +我们怎么才能让这个 alert 从 + +1092 +00:42:15,531 --> 00:42:16,614 +from the bottom? +底部滑上去呢 + +1093 +00:42:16,615 --> 00:42:17,698 +Well, it's just a UIViewController, +它其实就是 UIViewController + +1094 +00:42:17,700 --> 00:42:19,066 +we're gonna present it modally. +我们只要通过 modal 的方式来 present + +1095 +00:42:19,068 --> 00:42:21,801 +So, there's a method in UIViewController called +好,在 UIViewController 中有一个方法叫做 + +1096 +00:42:21,803 --> 00:42:23,102 +presentViewController. +presentViewConroller + +1097 +00:42:23,104 --> 00:42:24,437 +I haven't really talked about it cause +我还没有怎么说过它 + +1098 +00:42:24,439 --> 00:42:26,505 +we haven't talked about modal presentation. +因为我们还没有谈过 model 的展示方式 + +1099 +00:42:26,507 --> 00:42:28,407 +But all presentViewController is, +但 presentViewController 的作用就是这个 + +1100 +00:42:28,409 --> 00:42:31,276 +it presents a view controller on screen. +让一个 view controller 展示在屏幕上 + +1101 +00:42:31,278 --> 00:42:33,444 +And if it's a modal view controller like alerts are, +而且如果它是一个 modal view controller 比如 alert + +1102 +00:42:33,446 --> 00:42:34,545 +it'll appear modally. +它就会 modal 的方式出现 + +1103 +00:42:35,648 --> 00:42:37,314 +Okay? It only has three arguments +懂了吗,它只有三个参数 + +1104 +00:42:37,316 --> 00:42:40,684 +which is the UIViewController to present, +展示哪个 UIViewController + +1105 +00:42:40,686 --> 00:42:44,687 +whether to animate it so in the case of the action sheet, +是否执行动画,我们这里是 action sheet + +1106 +00:42:44,689 --> 00:42:46,655 +it slides up from the bottom. +所以它会从底部划上去 + +1107 +00:42:46,657 --> 00:42:48,557 +And then you also get a closure there, +然后你会得到一个闭包 + +1108 +00:42:48,559 --> 00:42:52,327 +completion, which will get called, this is closure, +completion,它会被调用,这是个闭包 + +1109 +00:42:52,329 --> 00:42:53,928 +it takes no arguments, returns nothing. +没有参数,也不需要返回任何东西 + +1110 +00:42:53,930 --> 00:42:55,396 +It'll have when it's done. +执行完成就完了 + +1111 +00:42:55,398 --> 00:42:58,565 +So when that thing has been finally presented on screen +当某个东西最终被展示到了屏幕上 + +1112 +00:42:58,567 --> 00:43:00,000 +and done its animation, boom, +完成了它的动画, BOOM + +1113 +00:43:00,002 --> 00:43:01,801 +you'll get your completion called. +你的 completion 会被调用 + +1114 +00:43:01,803 --> 00:43:03,770 +You almost never do anything there. +你几乎不会在这里做任何事 + +1115 +00:43:03,772 --> 00:43:05,338 +It's really, doesn't make a lot of sense. +这也确实没有什么道理 + +1116 +00:43:05,340 --> 00:43:07,740 +The things already up, it's doing its business. +东西已经被展示出来了,那么就已经完成了工作 + +1117 +00:43:07,742 --> 00:43:09,941 +There's really no business for you, as its presenter, +作为它的展示者,在这个时刻 + +1118 +00:43:09,943 --> 00:43:12,544 +to be doing at that point, but you could, okay? +这里已经没有事情需要你来做了,但你有这个选项 + +1119 +00:43:13,813 --> 00:43:16,747 +So that's it, UIAlerts are just UIViewController. +好了,就是这样, UIAlerts 就是 UIViewController + +1120 +00:43:16,749 --> 00:43:19,750 +Just add actions to them, then you present them. +只是添加一些动作,然后你展示他们 + +1121 +00:43:19,752 --> 00:43:24,821 +Now, what about this action sheet thing though on an iPad? +现在要说的是,这个 Action sheet 在 iPad 上是怎么作用的呢? + +1122 +00:43:25,824 --> 00:43:28,357 +Okay? So here's same app in iPad and +在 iPad 上有这么一个相同的应用 + +1123 +00:43:28,359 --> 00:43:30,492 +I got that redeploy button up there in the right. +右上角仍然有一个重新部署按钮 + +1124 +00:43:30,494 --> 00:43:32,861 +Now look what happens when I do redeploy in the iPad. +来看看当我在 iPad 上按下重新部署 + +1125 +00:43:34,030 --> 00:43:35,396 +Same thing. +同样的 + +1126 +00:43:35,398 --> 00:43:37,865 +But it shows up in a popover. +但它展示为弹出框 + +1127 +00:43:38,834 --> 00:43:39,733 +Okay? It doesn't +它没有 + +1128 +00:43:39,735 --> 00:43:41,268 +slide up from the bottom. +从底部滑上来 + +1129 +00:43:41,269 --> 00:43:42,802 +It wouldn't look very good if it slid up from the bottom. +从底部滑上来也不会很好看 + +1130 +00:43:42,804 --> 00:43:45,938 +It would either be kinda silly narrow, or +这样会有点狭窄样子 + +1131 +00:43:45,940 --> 00:43:48,907 +it would be so fat and wide it would look ridiculous. +或者会看起来很宽很胖,看起来很荒谬 + +1132 +00:43:48,909 --> 00:43:51,443 +It makes much more sense to put it in a popover like that. +作为弹出框的形式来出来要合理得多 + +1133 +00:43:51,445 --> 00:43:54,879 +Notice that the popover is different in one big way. +从另一个方面来说弹出框也是不同的 + +1134 +00:43:54,881 --> 00:43:57,015 +No cancel button, okay? +没有取消按钮 + +1135 +00:43:57,017 --> 00:43:58,983 +And that's because you don't need a cancel button to +你也不需要一个取消按钮 + +1136 +00:43:58,985 --> 00:44:00,250 +cancel a popover. +来取消弹出框 + +1137 +00:44:00,252 --> 00:44:03,086 +A popover is modal, and if you click anywhere else in your +一个弹出框是 modal 的形式,如果你在应用的任何一个地方点击了 + +1138 +00:44:03,088 --> 00:44:05,488 +app, boom, it's gonna cancel that popover. +BOOM,它就会取消这个弹出框 + +1139 +00:44:05,490 --> 00:44:09,092 +But if you have a cancel action, like this one does, +但如果你有一个取消的 action,就像这个一样 + +1140 +00:44:09,094 --> 00:44:11,394 +its actions still will be called, +那么 action 仍然会被调用 + +1141 +00:44:11,396 --> 00:44:13,862 +even in the popover cancel case. +即使是弹出框取消这样的情况 + +1142 +00:44:13,864 --> 00:44:15,614 +Okay? + +1143 +00:44:15,615 --> 00:44:17,365 +So that cancel thing is kind of still in play, +所以取消操作仍然会存在 + +1144 +00:44:17,368 --> 00:44:18,733 +it's just that you access it differently. +只是另一种方式 + +1145 +00:44:18,735 --> 00:44:20,668 +Instead of hitting the Cancel button like the bottom of +不是像 iPhone 应用那样点击底部的取消按钮 + +1146 +00:44:20,670 --> 00:44:22,937 +the iPhone version, you just click somewhere else and +而是点击其他的地方 + +1147 +00:44:22,939 --> 00:44:23,771 +make the popover go away. +来让弹出框消失 + +1148 +00:44:25,107 --> 00:44:26,172 +Everyone understand that? +大家明白了吗? + +1149 +00:44:26,174 --> 00:44:27,907 +All right, but how do we make this work? +好了,但现在我们要怎么让这个运行呢? + +1150 +00:44:27,909 --> 00:44:31,677 +Because this is not quite enough information +因为目前来看没有足够的信息 + +1151 +00:44:31,679 --> 00:44:34,112 +to present that popover, okay? +来展示这个弹出框,对吧 + +1152 +00:44:34,114 --> 00:44:36,247 +That popover needs one really important piece of +这个弹出框需要一个非常重要的信息 + +1153 +00:44:36,249 --> 00:44:39,183 +information, which is who is popping me up? +那就是,谁让我弹出的? + +1154 +00:44:39,185 --> 00:44:40,985 +Because you see it has that little white triangle +因为你看这里顶部有一个白色的小三角形 + +1155 +00:44:40,987 --> 00:44:43,320 +at the top that's pointing to redeploy? +指着重新部署按钮对吧 + +1156 +00:44:43,322 --> 00:44:46,189 +So nowhere here are we saying, oh, Mr. +那就是我们在某个地方说,弹出框先生 + +1157 +00:44:46,191 --> 00:44:49,759 +Popover, point to that redeploy button, okay? +指着那个重新部署按钮吧 + +1158 +00:44:49,761 --> 00:44:51,294 +So we need to say that. +所以我们需要这样说 + +1159 +00:44:51,296 --> 00:44:55,131 +So that means when we put any action sheet up and it's +这也意味着当我们把一个弹出框 + +1160 +00:44:55,133 --> 00:44:59,134 +gonna happen on an iPad where there might be a popover. +放在 iPad 上时,我们需要告诉它在哪里弹出 + +1161 +00:44:59,136 --> 00:45:00,869 +We need to get a hold of the popover +我们需要获取到这个悬浮 + +1162 +00:45:00,871 --> 00:45:02,403 +presentation controller. +展示的 controller + +1163 +00:45:02,405 --> 00:45:05,473 +The same one we got ahold of, back when we were doing +与在之前那个应用中同样的获取方式 + +1164 +00:45:05,475 --> 00:45:09,509 +the popover in the previous app, the psychologist app. +那个心理学应用 + +1165 +00:45:09,511 --> 00:45:11,478 +Same popover presentation controller. +同样的弹出弹出框 + +1166 +00:45:11,480 --> 00:45:13,379 +We need to get it and we just need to tell it, +我们需要获取它,并且我们要告诉它 + +1167 +00:45:13,381 --> 00:45:15,014 +here's the button that's presenting you, so +这里有个按钮,就是它要弹出你 + +1168 +00:45:15,016 --> 00:45:16,615 +you can point to it. +所以你可以指着它 + +1169 +00:45:16,617 --> 00:45:17,315 +Okay? +对吧 + +1170 +00:45:17,317 --> 00:45:18,416 +So we do that like this. +我们就这么做 + +1171 +00:45:19,686 --> 00:45:21,736 +First of all, +首先 + +1172 +00:45:21,737 --> 00:45:23,787 +just have to say that the alerts presentation style, +告诉 alert 的展示样式 + +1173 +00:45:23,790 --> 00:45:27,558 +its modal presentation style, is popover presentation style. +是 modal 展示样式,这就是弹出框展示样式 + +1174 +00:45:27,560 --> 00:45:30,360 +If we don't tell it that, then it will never make a popover +如果我们不告诉它,那么它也永远不会成为一个 + +1175 +00:45:30,362 --> 00:45:31,695 +presentation controller. +悬浮展示控制器 + +1176 +00:45:31,697 --> 00:45:34,797 +So we can't tell it anything cause it won't exist. +由于其不存在那么我们就什么都不能做 + +1177 +00:45:34,799 --> 00:45:37,667 +But once we say that this UIViewController +一旦我们说,这是一个 UIViewController + +1178 +00:45:37,669 --> 00:45:40,536 +modalPresentationStyle is a popover, now we can say okay, +modalPresentationStyle 就是弹出框,那么就可以了 + +1179 +00:45:40,538 --> 00:45:43,105 +well give me the popover presentation controller. +它就会给我们一个悬浮展示 controller + +1180 +00:45:43,107 --> 00:45:45,073 +And the BarButtonItem, +还有 BarButtonItem + +1181 +00:45:45,075 --> 00:45:48,509 +which is that redeploy up there is this. +这就是重新部署按钮 + +1182 +00:45:48,511 --> 00:45:51,812 +And so I point it to the redeployBarButtonItem, and +所以我填写 redeployBarButtonItem + +1183 +00:45:51,814 --> 00:45:55,682 +now when it pops over, when it gets presented modally here, +当它被以 modal 的方式展示时,就会从那里弹出 + +1184 +00:45:55,684 --> 00:45:57,717 +using a popover presentation, +使用 popover presentation + +1185 +00:45:57,719 --> 00:46:00,653 +it will point to the redeployButton, okay? +它会指着重新部署按钮 + +1186 +00:46:02,556 --> 00:46:05,991 +The cool thing is because of adaptive UIs, +这也是非常酷的一个东西,因为它的 UI 是自适应的 + +1187 +00:46:05,993 --> 00:46:07,726 +which we talked about back then, +我们之前谈到过 + +1188 +00:46:07,728 --> 00:46:10,828 +is that this code works exactly the same on iPhone. +这段代码同样可以在 iPhone 上使用 + +1189 +00:46:12,098 --> 00:46:14,898 +So if you put in those three lines to make the popover +你添加的这三行让弹出框运行的代码 + +1190 +00:46:14,900 --> 00:46:17,000 +work, it won't effect the iPhone at all. +完全不会影响到 iPhone + +1191 +00:46:17,002 --> 00:46:21,470 +Because the iPhone already adapts popovers to present +因为 iPhone 已经自适应了弹出框 + +1192 +00:46:21,472 --> 00:46:23,172 +over the whole screen, remember? +为整个屏幕,记得吗 + +1193 +00:46:23,174 --> 00:46:25,807 +And in fact, we had to go do some work in psychologists +事实上我们在心理学应用中做了一些额外的工作 + +1194 +00:46:25,809 --> 00:46:29,377 +to stop it from doing that adapting. +来让它不要自适应 + +1195 +00:46:29,379 --> 00:46:31,612 +So that it would show up in a little popover on the phone. +所以这样会展示一个弹出框在手机上 + +1196 +00:46:31,614 --> 00:46:33,047 +But if you don't do any of that work, +但如果你什么也不做 + +1197 +00:46:33,049 --> 00:46:35,883 +then by default it shows just like this. +默认它就会这样显示 + +1198 +00:46:35,885 --> 00:46:37,751 +Until it takes over the whole screen on the iPhone. +直到它掌控整个 iPhone 屏幕 + +1199 +00:46:37,753 --> 00:46:40,620 +So that's why setting the modal presentation style to +所以,自适应,这就是为什么我们设置了 modal presentation 样式 + +1200 +00:46:40,622 --> 00:46:43,723 +popover still works on the iPhone because it adapts. +但在 iPhone 上仍然起效的原因 + +1201 +00:46:45,226 --> 00:46:46,291 +Okay? + +1202 +00:46:46,293 --> 00:46:47,258 +Any questions about that? +有任何问题吗? + +1203 +00:46:47,260 --> 00:46:48,726 +So that's how you do an action sheet. +这就是你使用 Action Sheet 的方式 + +1204 +00:46:48,728 --> 00:46:51,595 +You're gonna do the same body of code you see right there +在你所有的 Action sheet 中你都需要使用 + +1205 +00:46:51,597 --> 00:46:53,030 +for every action sheet you ever do. +这些同样的代码 + +1206 +00:46:54,466 --> 00:46:56,566 +All right, now, let's go talk about the alert. +好了, 现在让我们来谈谈 Alert + +1207 +00:46:56,568 --> 00:46:57,767 +Okay. + +1208 +00:46:57,768 --> 00:46:58,967 +The only difference in creating the view controller +唯一的不同就是,当你在创建 view controller 的时候 + +1209 +00:46:58,970 --> 00:47:01,771 +is you say that its style is alert instead of action sheet. +你需要设置它的样式为 alert 而不是 action sheet + +1210 +00:47:01,773 --> 00:47:03,472 +Otherwise, it's exactly the same. +除此之外,其他的都一模一样 + +1211 +00:47:03,474 --> 00:47:05,474 +Okay, iPad different text here, +好了,iPad 有一点不同的文本 + +1212 +00:47:05,476 --> 00:47:07,709 +obviously login required and please enter your Cassini +很明显当你在进入 Cassini 的导航系统时 + +1213 +00:47:07,711 --> 00:47:10,745 +guidance system password instead of the other things. +你需要登录输入密码 + +1214 +00:47:10,747 --> 00:47:12,580 +But, otherwise I'm just changing +但除此之外就只需要修改 + +1215 +00:47:12,582 --> 00:47:14,181 +the style to be alert. +样式为 alert + +1216 +00:47:14,183 --> 00:47:15,782 +I do the same thing with adding actions. +添加 action 也是同样的方式 + +1217 +00:47:15,784 --> 00:47:18,118 +So, here I'm gonna add the Cancel button. +这里我们要添加一个取消按钮 + +1218 +00:47:18,120 --> 00:47:21,020 +Okay, I'm gonna add the Login button. +好的,我还要添加一个登录按钮 + +1219 +00:47:21,022 --> 00:47:23,689 +Now the interesting thing about the Login button is when +有趣的部分来了,当我点击这个登录按钮的时候 + +1220 +00:47:23,691 --> 00:47:27,325 +I login I wanna get the text out of that text field +我想要一个文本输入框弹出来 + +1221 +00:47:28,362 --> 00:47:31,595 +to use as a password for my guidance system, okay? +问我要登录导航系统的密码 + +1222 +00:47:32,898 --> 00:47:35,232 +So how am I gonna do that, okay. +这就是我要做的 + +1223 +00:47:35,234 --> 00:47:36,633 +Well first of all we're gonna ask, +首先我们需要问的是 + +1224 +00:47:36,635 --> 00:47:38,668 +how do I put that text field there? +我怎么才能在这里放一个文本输入框? + +1225 +00:47:38,670 --> 00:47:40,336 +Okay, I've gotta put that text field in my alert. +好了已经放了一个文本输入框在我的 Alert 里 + +1226 +00:47:40,338 --> 00:47:42,638 +So here's how we put a text field in alert. +这就是我们如何把输入框放在 Alert 中 + +1227 +00:47:42,640 --> 00:47:45,440 +Use simple method addTextFieldWithConfiguration- +使用了一个很简单的方法 addTextFieldWithConfigurationHandler + +1228 +00:47:45,442 --> 00:47:47,709 +Handler, okay? +对吧 + +1229 +00:47:47,710 --> 00:47:49,977 +When you call that, it adds the text field to the alert +当你调用它时,它就会给 Alert 添加一个输入框 + +1230 +00:47:49,980 --> 00:47:52,380 +and it calls this closure so +然后它会调用这个闭包函数 + +1231 +00:47:52,382 --> 00:47:54,715 +that you can configure the text field however you want. +这样你才能配置这个输入框为你想要的样式 + +1232 +00:47:54,717 --> 00:47:55,816 +So here my text field, +这就是我的输入框 + +1233 +00:47:55,818 --> 00:47:58,151 +I configured it to say Guidance System Password +我配置它显示"导航系统密码" + +1234 +00:47:58,153 --> 00:48:00,587 +as the place holder text there in the background. +在这里作为文字占位符 + +1235 +00:48:00,589 --> 00:48:02,155 +Remember in the smash tag, +记得这个标签 + +1236 +00:48:02,157 --> 00:48:04,890 +I had my search field say Twitter Search Query. +之前有一个搜索输入框显示搜索 Twitter + +1237 +00:48:04,892 --> 00:48:06,442 +Well, here I'm having +在之类我们需要显示 + +1238 +00:48:06,443 --> 00:48:07,993 +this one say Guidance System Password in the background. +导航系统密码 + +1239 +00:48:07,995 --> 00:48:09,645 +And that's it. +就是这样 + +1240 +00:48:09,646 --> 00:48:11,296 +So I could do other things to set the font or +我也可以做一些其他的事,比如设置字体 + +1241 +00:48:11,298 --> 00:48:14,332 +whatever I want of the text field there. +或者其他我可以对输入框做的事 + +1242 +00:48:14,334 --> 00:48:15,767 +And you can call +你可以调用 + +1243 +00:48:15,768 --> 00:48:17,201 +addTextFieldWithConfiguration- Handler more than once and +addTextFieldWithConfiguration 多次来添加 + +1244 +00:48:17,203 --> 00:48:18,736 +then you'll get more than one text field. +不止一个输入框 + +1245 +00:48:18,738 --> 00:48:22,973 +So you could have a login and a password field. +这样你就可以有登录和密码输入框 + +1246 +00:48:22,975 --> 00:48:24,308 +Now. + +1247 +00:48:24,309 --> 00:48:25,642 +This is great, I've got the text field in there. +很棒,我们有一个输入框了 + +1248 +00:48:25,644 --> 00:48:28,211 +When I click log in inside the action for +当我在 action 中点击了 login + +1249 +00:48:28,213 --> 00:48:31,714 +log in, how do I get the text out of that text field, okay? +我应该怎么获取这些文字呢 + +1250 +00:48:31,716 --> 00:48:34,350 +Well, that looks slightly more complicated than you might +这会看起来比你想像的稍微复杂一点 + +1251 +00:48:34,352 --> 00:48:35,484 +like, it looks like this. +看起来像这样 + +1252 +00:48:35,486 --> 00:48:39,320 +I'm going to let TF, which is going to be a pointer to that +我需要使用 let tf,这会指向刚才那个 + +1253 +00:48:39,322 --> 00:48:43,958 +text field equal alert.text fields. +输入框,= alert.textfields + +1254 +00:48:43,960 --> 00:48:47,227 +Which is an array of any object +这会是一个可能为任何元素在里面的 + +1255 +00:48:47,229 --> 00:48:50,230 +in its optional array, okay? +optionanl 数组 + +1256 +00:48:50,232 --> 00:48:53,166 +So, since it's an array, since it's optional, +由于它是一个数组,由于它是可选的 + +1257 +00:48:53,168 --> 00:48:54,834 +I'm gonna put a question mark there so +我需要在这里加上一个 ? + +1258 +00:48:54,836 --> 00:48:57,603 +that I can do this optional chaining and just fail. +这样我才能使用这个 optional chaininng,而且可能失败 + +1259 +00:48:57,605 --> 00:49:00,506 +So TF, let TF, that could be nil, +因为 let tf 可能为 nil + +1260 +00:49:00,508 --> 00:49:03,175 +that could end up being nil. +这个可能为 nil + +1261 +00:49:03,177 --> 00:49:05,110 +That's a question mark, and then I'm gonna say .first. +这是一个 ? 然后我要加上 .first + +1262 +00:49:05,112 --> 00:49:07,562 +If you remember an array, +如果你记得 array 中的这个方法 + +1263 +00:49:07,563 --> 00:49:10,013 +the method .first returns the first thing in the array +.first 返回数组中第一个元素 + +1264 +00:49:10,016 --> 00:49:11,615 +if the array has anything in it. +如果数组中有东西的话 + +1265 +00:49:11,617 --> 00:49:12,683 +If not, it returns nil. +如果没有返回 nil + +1266 +00:49:13,619 --> 00:49:14,751 +So that's a great way to get something, +这就是一个很好的办法来获取元素 + +1267 +00:49:14,753 --> 00:49:16,652 +the first thing out of an array and +在不检查数组中是否有东西的情况下 + +1268 +00:49:16,654 --> 00:49:18,721 +not have to check to see if anything's in the array. +获取数组中的第一个元素 + +1269 +00:49:18,723 --> 00:49:20,889 +And it'll just return nil if there's nothing in the array. +如果没有东西的话,就会返回 nil + +1270 +00:49:22,059 --> 00:49:24,626 +And then I've got to cast it to a text field because I told +然后我需要转换为 text field 因为 + +1271 +00:49:24,628 --> 00:49:26,594 +you it was an array of any object. +我之前说过这是一个 anyObject 泛型的数组 + +1272 +00:49:26,596 --> 00:49:28,396 +Why is it an array of any object? +为什么泛型为 anyObject? + +1273 +00:49:28,398 --> 00:49:30,364 +Don't ask, historical reasons. +别在意,历史原因 + +1274 +00:49:30,366 --> 00:49:32,566 +It's a way objective C cat does things, +这是之前 Objective-C 中遗留的东西 + +1275 +00:49:32,568 --> 00:49:35,035 +it's not quite as expressive as Swift. +它没有 Swift 这样丰富的表现力 + +1276 +00:49:35,037 --> 00:49:36,636 +But, anyway, too bad. +但,也不糟糕 + +1277 +00:49:36,638 --> 00:49:37,570 +So you do this as ?, +所以你使用的这个 as ? + +1278 +00:49:37,572 --> 00:49:39,539 +so that also could return nil. +它仍然可能返回 nil + +1279 +00:49:39,540 --> 00:49:41,507 +So, it's three different things that could return nil, +所以这里有三个东西可能返回 nil + +1280 +00:49:41,509 --> 00:49:44,076 +but if they don't, then I'm gonna get text field back. +但如果它们没有,我就会得到输入框 + +1281 +00:49:44,078 --> 00:49:45,961 +And if I get a text field back, +当我获取到这个输入框的时候 + +1282 +00:49:45,962 --> 00:49:47,845 +then I can just take the text out of the text field and +我就可以把文本从输入框中取出 + +1283 +00:49:47,848 --> 00:49:50,281 +log in. +然后登录 + +1284 +00:49:50,283 --> 00:49:50,848 +Okay? + +1285 +00:49:52,251 --> 00:49:53,784 +Any questions about that? +有人有问题吗? + +1286 +00:49:53,786 --> 00:49:55,118 +I know it's a little convoluted getting +我知道取出输入框 + +1287 +00:49:55,120 --> 00:49:56,019 +that text field out of there. +这里有点绕 + +1288 +00:49:56,021 --> 00:49:57,787 +All right? + +1289 +00:49:57,789 --> 00:50:01,557 +So that's it for alerts. +好,这就是 Alert + +1290 +00:50:01,559 --> 00:50:04,926 +Then you just present view controller exactly the same +然后你需要像之前那样 presentViewController + +1291 +00:50:04,928 --> 00:50:09,364 +as we did for action sheet or any other modal view. +就像我们对 Action sheet 和其他的 modal view 做得那样 + +1292 +00:50:09,366 --> 00:50:11,465 +And how about an iPad? +那 iPad 上呢? + +1293 +00:50:11,467 --> 00:50:12,867 +An iPad? +一个 iPad? + +1294 +00:50:12,868 --> 00:50:14,268 +It looks exactly the same. +它看起来一模一样 + +1295 +00:50:14,270 --> 00:50:15,502 +Takes over the whole screen. +接管整个屏幕 + +1296 +00:50:15,504 --> 00:50:19,972 +No need to do any popover business with alerts on iPad. +在 iPad 上 Alert 不需要做额外的操作 + +1297 +00:50:19,974 --> 00:50:22,008 +Okay. + +1298 +00:50:22,009 --> 00:50:24,043 +So that's alerts and action sheets. +这就是 Alerts 和 Action sheets + +1299 +00:50:24,045 --> 00:50:25,978 +Just UIV controls that you're presenting modally +就是你 modal 地展示一个 UIViewController + +1300 +00:50:25,980 --> 00:50:26,645 +that's all they are. +这就是全部了 + +1301 +00:50:26,647 --> 00:50:28,680 +All right. +好了 + +1302 +00:50:28,682 --> 00:50:33,351 +Next topic, NSTimer. +下一个话题,NSTimer + +1303 +00:50:33,353 --> 00:50:35,853 +So NSTimer is a way to set up a timer +NSTimer 是一种设置定时器的东西 + +1304 +00:50:35,855 --> 00:50:40,090 +that will call a method periodically, okay? +可以周期性地调用一个方法 + +1305 +00:50:40,092 --> 00:50:42,358 +Now, it uses technology called RunLoop, +它使用的技术叫做 RunLoop + +1306 +00:50:42,360 --> 00:50:43,859 +which we're not going to talk about. +我们不会讲这个东西 + +1307 +00:50:43,861 --> 00:50:47,196 +So suffice it to say, for you, in this course, +在这个课堂中,对于你们来说只要知道 + +1308 +00:50:47,198 --> 00:50:50,432 +you always have to use timers on the main queue, okay? +永远在主队列中使用定时器就行了 + +1309 +00:50:50,434 --> 00:50:52,334 +Because the main queue has a run loop. +因为主队列有 run loop + +1310 +00:50:52,336 --> 00:50:54,268 +You can actually have run loops on other queues, +你其实可以在其他队列使用 run loop + +1311 +00:50:54,270 --> 00:50:56,737 +other threads, but we're not gonna talk about that. +在其他线程,但我们不会讲这个东西 + +1312 +00:50:56,739 --> 00:51:01,308 +So, main queue for you, NSTimer main queue. +所以主队列,NSTimer 主队列 + +1313 +00:51:01,310 --> 00:51:06,379 +And, so this timer, it's not really a real-time timer. +而且,这个定时器,其实并不是实时的计时器 + +1314 +00:51:06,381 --> 00:51:08,748 +If you say go off every two seconds, +你写每两秒启动一次 + +1315 +00:51:08,750 --> 00:51:12,250 +it's not going to go off every 2.00000 seconds. +它其实并不会每2.00000秒执行一次 + +1316 +00:51:12,252 --> 00:51:13,284 +And why is that? +这是为什么呢? + +1317 +00:51:13,286 --> 00:51:16,154 +Because basically it's just putting things, +因为它只是放置事件 + +1318 +00:51:16,156 --> 00:51:19,056 +it's kind of like it's putting things on the main queue but +就像它放置一些事件在主队列中, + +1319 +00:51:19,058 --> 00:51:20,958 +not, not quite the same. +不,也不完全一样 + +1320 +00:51:20,960 --> 00:51:23,827 +The runloop helps process things that are happening, +runloop 会帮助执行让事件发生 + +1321 +00:51:23,829 --> 00:51:27,864 +like interrupts or data that becomes available or whatever. +就像打断或者数据有效或者其他 + +1322 +00:51:27,866 --> 00:51:29,765 +And it can't run in real-time, +但它不能实时执行 + +1323 +00:51:29,767 --> 00:51:32,501 +because other things are on the main queue running. +因为其他的事件也在主队列中执行 + +1324 +00:51:32,503 --> 00:51:33,852 +Okay? Other +其他的代码 + +1325 +00:51:33,853 --> 00:51:35,202 +blocks of code and stuff. +或者什么东西 + +1326 +00:51:35,205 --> 00:51:36,838 +So we can't quite guarantee it. +所以我们不能保证 + +1327 +00:51:36,840 --> 00:51:38,072 +But it has a high priority, so, +但它确实有很高的优先级,所以 + +1328 +00:51:38,074 --> 00:51:40,741 +as soon as the main queue becomes available, after +只要主队列空闲下来了 + +1329 +00:51:40,743 --> 00:51:44,178 +2.0000 seconds has happened, it's gonna call your method. +在2.000000秒之后,它就会调用你的方法 + +1330 +00:51:44,180 --> 00:51:46,413 +Okay, but it's not a real time programming thing. +但这确实不是实时编码的 + +1331 +00:51:46,415 --> 00:51:49,015 +I mentioned that for those of you who are like systems +我提起这个是为了那些喜欢研究系统的并且 + +1332 +00:51:49,017 --> 00:51:51,651 +OS people and you're used to real time API. +熟悉实时 API 的人 + +1333 +00:51:51,653 --> 00:51:53,386 +This is not real time but it's really, really, +这不是实时的,但它确实非常非常 + +1334 +00:51:53,388 --> 00:51:55,188 +really close to real time. +非常接近实时 + +1335 +00:51:55,189 --> 00:51:56,989 +As long as you don't have any big things on your main queue +不要在你的主队列中处理一些笨重的 + +1336 +00:51:56,991 --> 00:52:00,058 +that are blocking it up which you shouldn't have any +会阻塞线程的事件,这样就没有 + +1337 +00:52:00,060 --> 00:52:00,792 +way, right? +什么办法了 + +1338 +00:52:00,794 --> 00:52:03,594 +Never block your main queue. +永远不要阻塞你的主线程 + +1339 +00:52:03,596 --> 00:52:06,330 +Then your timer's pretty much gonna run when you want. +那么你的定时器基本上就会按照你期待的方式运行 + +1340 +00:52:06,332 --> 00:52:07,965 +Okay? + +1341 +00:52:07,966 --> 00:52:09,599 +Now this is not used for animation. +这也并不是用来制作动画的 + +1342 +00:52:09,602 --> 00:52:12,602 +We're going to talk all about animation later today and +我们待会以及下周一整周 + +1343 +00:52:12,604 --> 00:52:13,603 +all of next week. +都会讲动画 + +1344 +00:52:13,605 --> 00:52:15,238 +And your assignment five is +而且你的第五个任务也完全是 + +1345 +00:52:15,240 --> 00:52:16,939 +going to be all about animation. +与动画相关的 + +1346 +00:52:16,941 --> 00:52:19,775 +Timer is more like a complement to animation. +但定时器对于动画来说更像一个补充的东西 + +1347 +00:52:19,777 --> 00:52:21,843 +Because when you're animating things sometimes you do want +当你在执行动画的时候,你想要 + +1348 +00:52:21,845 --> 00:52:23,395 +to do things. +做一些其他的事情 + +1349 +00:52:23,396 --> 00:52:24,946 +Something every second or every two seconds. +一些每秒或每两秒执行的事 + +1350 +00:52:24,948 --> 00:52:26,080 +You're really not going to be, like, +但你不会 + +1351 +00:52:26,082 --> 00:52:28,282 +doing something every 60th of a second. +每六十分之一秒做一次 + +1352 +00:52:28,284 --> 00:52:29,049 +Okay? 60 frames per +六十帧每秒 + +1353 +00:52:29,051 --> 00:52:30,901 +second animation, +的动画 + +1354 +00:52:30,902 --> 00:52:32,752 +you'd never do that with a timer, it's not for that. +你永远也不要通过定时器来做这个,它并不是用来做这个的 + +1355 +00:52:32,755 --> 00:52:33,871 +Okay? +好吗 + +1356 +00:52:33,872 --> 00:52:34,988 +It's just for things like, maybe, +它只是用来,比如 + +1357 +00:52:34,990 --> 00:52:38,524 +you have something where you have a score in a game and +你在游戏中有一个什么比分 + +1358 +00:52:38,526 --> 00:52:40,593 +you update the score every second. +你需要每秒更新一次 + +1359 +00:52:40,595 --> 00:52:42,061 +Okay? + +1360 +00:52:42,062 --> 00:52:43,528 +So that you're not constantly changing it, +这样不需要自己频繁地去改变 + +1361 +00:52:43,531 --> 00:52:44,763 +something like that. +类似这样 + +1362 +00:52:44,765 --> 00:52:46,631 +It's that kind of thing. +这种事 + +1363 +00:52:46,633 --> 00:52:47,965 +It's used for that kinda thing. +它是用来做这种事的 + +1364 +00:52:47,967 --> 00:52:50,067 +So run loops we're not going to talk about that. +所以我们不会讲到 run loop + +1365 +00:52:50,069 --> 00:52:52,336 +Okay so how do you fire off one of these timers? +你怎么知道如何启动其中一个定时器呢 + +1366 +00:52:52,338 --> 00:52:54,738 +How do you make it work? +你怎么才能让它生效? + +1367 +00:52:54,739 --> 00:52:57,139 +Well you do it with a class function in NSTimer. +你只需要调用 NSTimer 的一个类方法 + +1368 +00:52:57,142 --> 00:53:00,710 +It's called a scheduled timer with time interval. +叫做 scheduledTimerWithTimeInterval + +1369 +00:53:00,712 --> 00:53:02,695 +Now be careful. +注意 + +1370 +00:53:02,696 --> 00:53:04,679 +There are four methods in NSTime but it looked very, +在 NSTimer 中有四个方法,但它们长得 + +1371 +00:53:04,682 --> 00:53:05,914 +very similar to this. +和这个很像 + +1372 +00:53:05,916 --> 00:53:08,033 +Okay? But +但 + +1373 +00:53:08,034 --> 00:53:10,151 +this is the one you want with this set of arguments [SOUND]. +这才是你需要的 + +1374 +00:53:10,154 --> 00:53:11,986 +And the arguments are just, +它的参数就是 + +1375 +00:53:11,988 --> 00:53:15,323 +the first one is how many seconds between firings? +第一个就是启动的间隔时间 + +1376 +00:53:15,325 --> 00:53:18,159 +How many seconds do you want to wait each time before you +你希望它在调用了一次方法之后,等待多少秒 + +1377 +00:53:18,161 --> 00:53:19,893 +call this method again? +再调用这个方法 + +1378 +00:53:19,895 --> 00:53:22,462 +The target is, who you gonna send the message to? +target 是,你希望向谁发送消息 + +1379 +00:53:22,464 --> 00:53:24,831 +It can be any object. +它可以是任何对象 + +1380 +00:53:24,833 --> 00:53:27,867 +Okay? + +1381 +00:53:27,868 --> 00:53:30,902 +Remember, any object is not a struct or an enum. +记住,任何对象不是指 struct 或者 enum + +1382 +00:53:30,905 --> 00:53:36,008 +Although, things like string and number, those are. +虽然像 string 和 number 这种他们是 + +1383 +00:53:36,010 --> 00:53:38,209 +You're not gonna solve puzzles anyway but +但你不能这样做 + +1384 +00:53:38,211 --> 00:53:40,878 +those are essentially any object because they're +它们本质上是 anyObject 这是由于它们与 NSString + +1385 +00:53:40,880 --> 00:53:42,346 +bridging over to NS String. +有桥接 + +1386 +00:53:42,348 --> 00:53:44,715 +But anyway, any object, okay, is any object, +除此之外,任何对象,anyObject + +1387 +00:53:44,717 --> 00:53:47,984 +any class basically, and then selector is just +基本上任何类,然后 selector 是 + +1388 +00:53:47,986 --> 00:53:52,255 +the method to call when the timer goes off. +你需要定时器执行的方法 + +1389 +00:53:52,257 --> 00:53:54,924 +User info is just like a cookie that you can +userInfo 就类似于 cookie,你可以 + +1390 +00:53:54,926 --> 00:53:57,493 +hand off here and then every time it fires you'll be giving +在这里存入,然后每次调用的时候,你都可以 + +1391 +00:53:57,495 --> 00:53:58,860 +that thing back. +把它取回来 + +1392 +00:53:58,862 --> 00:54:01,429 +So, it's just kind of a way of passing this argument off +这样就可以传递参数 + +1393 +00:54:01,431 --> 00:54:04,332 +to your, so you don't have to keep it in a class, +你不需要把它保存在类中 + +1394 +00:54:04,334 --> 00:54:06,100 +in a variable in your class or anything like that. +以变量的形式存在你的类中,或者其他的方法 + +1395 +00:54:06,102 --> 00:54:07,334 +You can just hand it off. +你可以只是存进去 + +1396 +00:54:07,336 --> 00:54:09,703 +It's like context for the timer. +就像定时器的上下文 + +1397 +00:54:09,705 --> 00:54:13,239 +And then repeat is whether this thing just does it once, +然后 repeat 就是这个定时器是否只执行一次 + +1398 +00:54:13,241 --> 00:54:16,442 +or it keeps doing it every however many seconds. +还是每隔几秒执行一次 + +1399 +00:54:16,444 --> 00:54:19,111 +Is it a repeating timer, or is it just a one time +它是重复执行的定时器还是只在未来执行 + +1400 +00:54:19,113 --> 00:54:22,348 +do something in the future, and I showed you a way to do +一次任务,上次我用 dispatch 向你展示了一种 + +1401 +00:54:22,350 --> 00:54:25,450 +one time thing in the future with dispatch last time, so +在未来只执行一次任务的的方法 + +1402 +00:54:25,452 --> 00:54:27,552 +this will be another way to do something once. +这是另一个在未来执行的方法 + +1403 +00:54:29,389 --> 00:54:30,788 +Here's an example of calling it. +这里有一个使用的例子 + +1404 +00:54:30,790 --> 00:54:32,289 +So here I have a timer. +我有一个定时器 + +1405 +00:54:32,291 --> 00:54:34,157 +It's gonna go off every two seconds. +它会每隔两秒调用一次 + +1406 +00:54:34,159 --> 00:54:37,126 +It's gonna send this message to myself called fire. +它会每隔两秒向自身发送一次消息 + +1407 +00:54:37,128 --> 00:54:40,296 +Notice that, that method can be any name you want, +注意,这个方法可以是任何你想要的方法 + +1408 +00:54:40,298 --> 00:54:42,197 +except it has to have a colon there, +除了,你必须在这里加上一个冒号 + +1409 +00:54:42,199 --> 00:54:44,499 +because it's going to have an argument. +因为它需要一个参数 + +1410 +00:54:44,501 --> 00:54:46,434 +I told you that when you're specifying the name of +之前我有提到过,当你需要指定一个方法的时候 + +1411 +00:54:46,436 --> 00:54:48,936 +a method, if it has an argument, +如果它有参数 + +1412 +00:54:48,938 --> 00:54:50,237 +you have to put a colon on the end. +那么你就必须添加一个冒号在最后 + +1413 +00:54:51,407 --> 00:54:52,773 +OK. Otherwise it +否则 + +1414 +00:54:52,775 --> 00:54:56,609 +thinks it's the method fire without an argument. +它会去执行没有参数的方法 + +1415 +00:54:56,611 --> 00:54:58,678 +And then userInfo on passing nil. +那么 userInfo 就不会被传递 + +1416 +00:54:58,680 --> 00:55:00,713 +I don't really want any information, +我确实不需要什么信息 + +1417 +00:55:00,715 --> 00:55:03,682 +I could pass anything, any object I wanted there. +我可以传入任何我想要的参数,任何对象 + +1418 +00:55:03,684 --> 00:55:05,583 +And then repeats equals true means it's going to fire +repeats = true 意思是它会每隔 + +1419 +00:55:05,585 --> 00:55:06,918 +every two seconds. +两秒执行一次 + +1420 +00:55:06,919 --> 00:55:08,252 +It's going to fire in two seconds from now, and +它会从现在开始两秒执行一次 + +1421 +00:55:08,254 --> 00:55:10,054 +two seconds after that, and two seconds after that. +两秒后再执行一次,过两秒再执行 + +1422 +00:55:11,290 --> 00:55:14,658 +Repeat it forever until I invalidate it, okay? +一直不断重复直到我销毁了它 + +1423 +00:55:14,660 --> 00:55:17,627 +So let's look now at the fire timer thing. +让我们来看看执行定时器的东西 + +1424 +00:55:17,629 --> 00:55:19,162 +It looks like this. +它看起来像这样 + +1425 +00:55:19,164 --> 00:55:22,665 +You can basically do whatever you want in there. +你可以在里面做任何事情 + +1426 +00:55:22,667 --> 00:55:24,033 +You're on the main queue so +你在主队列,所以 + +1427 +00:55:24,035 --> 00:55:26,368 +you can do UI in here or whatever. +你可以设置 UI 或者其他的事 + +1428 +00:55:26,370 --> 00:55:28,436 +If you pass some user info, you can get it +如果你传入了 userInfo,那么你可以通过 + +1429 +00:55:28,438 --> 00:55:32,006 +out of the timer by saying the timer.userinfo. +定时器得到,使用 timer.userInfo + +1430 +00:55:32,008 --> 00:55:35,309 +Now you've got that info. +现在你就获得了那个信息 + +1431 +00:55:35,311 --> 00:55:36,811 +Okay? + +1432 +00:55:36,812 --> 00:55:38,312 +Super simple to use these timers. +使用定时器非常简单 + +1433 +00:55:38,314 --> 00:55:40,480 +If you wanna stop a timer that's repeating, +如果你想要让定时器停止重复 + +1434 +00:55:40,482 --> 00:55:42,215 +it's going off every two seconds and you wanna stop it, +它会每隔两秒执行一次,而你想要停止 + +1435 +00:55:42,217 --> 00:55:43,850 +you just send it the message, invalidate. +你只需要向它发送一个消息,销毁 + +1436 +00:55:43,852 --> 00:55:47,119 +If you say timer.invalidate, it will stop. +如果你调用 timer.invalidate 它就会停止 + +1437 +00:55:48,822 --> 00:55:49,387 +Okay? + +1438 +00:55:49,389 --> 00:55:52,924 +Another thing you can do to make your system perform +你还可以通过使用 tolerance 来让系统性能 + +1439 +00:55:52,926 --> 00:55:54,692 +better is put a tolerance in there. +更好一些 + +1440 +00:55:54,694 --> 00:55:57,394 +What a tolerance says, is if my two, if I'm +tolerance 的作用是,比如我 + +1441 +00:55:57,396 --> 00:56:00,997 +setting something to go off every two minutes let's say. +设置了一个定时器它会每两分钟执行一次 + +1442 +00:56:00,999 --> 00:56:02,832 +Okay? + +1443 +00:56:02,833 --> 00:56:04,666 +When the two minutes is up do I have to do it right away? +当两分钟到了它会立刻执行对吧? + +1444 +00:56:04,669 --> 00:56:07,103 +Or can I wait five or ten seconds? +或者我可以等待五或者十秒 + +1445 +00:56:07,105 --> 00:56:08,871 +If you let the system wait five or +如果你让系统等待五或者十秒 + +1446 +00:56:08,873 --> 00:56:12,007 +ten seconds, it could pick an optimal time to call your, +它会选择一个时间来调用你 + +1447 +00:56:12,009 --> 00:56:15,276 +a more optimal time, anyway, to call your timer. +在一个更合适的时间,来执行你的定时器 + +1448 +00:56:15,278 --> 00:56:18,846 +So, my strong recommendation is, try to give a tolerance. +所以我的建议是使用 tolerance + +1449 +00:56:18,848 --> 00:56:20,815 +A tolerance is just a number of seconds that you're +tolerance 只是设置一个以秒为单位的时间 + +1450 +00:56:20,817 --> 00:56:22,850 +willing to wait after it would normally fire. +在执行事件之前的等待 + +1451 +00:56:22,852 --> 00:56:26,920 +Try to give a tolerance of like maybe 10% of your timer. +尝试给 tolerance 比如定时器十分之一的时间 + +1452 +00:56:26,922 --> 00:56:28,354 +So if you have a two second timer, +比如你有一个2秒的定时器 + +1453 +00:56:28,356 --> 00:56:29,855 +give it a tolerance of 0.2 seconds or +给它的 tolerance 0.2 秒或者 + +1454 +00:56:29,857 --> 00:56:32,741 +something like that. +类似的值 + +1455 +00:56:32,742 --> 00:56:35,626 +It'll let the system pick a more efficient time to run. +这样会让系统选择一个更为高效的时间来执行 + +1456 +00:56:35,629 --> 00:56:40,298 +Like, for example, if your app, we didn't +举个例子,如果你的应用 + +1457 +00:56:40,300 --> 00:56:43,801 +really explain how this works, but your device can kind of +我们没有解释到底这个是怎么工作的 + +1458 +00:56:43,803 --> 00:56:46,270 +go to sleep a little bit when nothing's happening. +但如果你的应用可以在没有事情的时候闲置一下 + +1459 +00:56:46,272 --> 00:56:49,139 +Nothing's drawing on screen, no network activity. +没有在屏幕上画图,没有发送网络请求 + +1460 +00:56:49,141 --> 00:56:51,941 +So it can kind of go into a little lower power state, and +这样系统就可以进入一个短暂的低功耗状态 + +1461 +00:56:51,943 --> 00:56:54,410 +then it comes back awake every once in awhile. +然后它每隔一会就会恢复 + +1462 +00:56:54,412 --> 00:56:56,545 +Well, if you give it a little tolerant, +所以如果你设置了一会 tolerant + +1463 +00:56:56,547 --> 00:56:59,148 +it might be able to kind of go into that low power state and +系统就可以进入低功耗状态 + +1464 +00:56:59,150 --> 00:57:01,883 +then come back up in that little window. +然后再回来 + +1465 +00:57:01,885 --> 00:57:03,969 +But if you don't give it a tolerance, +如果你不设置 tolerance + +1466 +00:57:03,970 --> 00:57:06,054 +it might have to stay awake to make sure it hits that timer, +那么它就会一直保持唤醒的状态,以确保定时器的触发 + +1467 +00:57:06,056 --> 00:57:06,754 +the one you wanted. +就像你想的那样 + +1468 +00:57:06,756 --> 00:57:08,222 +You see? +你明白了吗? + +1469 +00:57:08,223 --> 00:57:09,689 +So the tolerance is exactly what it sounds like. +所以 tolerance 就是听上去的那个意思,容忍误差 + +1470 +00:57:09,692 --> 00:57:12,760 +A little bit of tolerance, give the system a little +一点点误差可以让系统更好地 + +1471 +00:57:12,762 --> 00:57:15,862 +better chance to manage your battery and all that. +管理你的系统及其他 + +1472 +00:57:15,864 --> 00:57:17,964 +Okay? + +1473 +00:57:17,966 --> 00:57:20,633 +If you give it tolerance, it's not going to drift. +如果设置了 tolerance,它也并不会滞后 + +1474 +00:57:20,635 --> 00:57:23,302 +In other words, if you give a tolerance 2 minute timer and +换句话说,如果你设置了两分钟的定时器 + +1475 +00:57:23,304 --> 00:57:24,970 +you let it go an extra 10 seconds and +然后你让它执行了十秒 + +1476 +00:57:24,972 --> 00:57:27,539 +it waits an extra 8 seconds, the next one is not going to +然后等待八秒,下一次定时器触发并不会 + +1477 +00:57:27,541 --> 00:57:29,874 +be 2 minutes after that 2 minutes and 8 seconds. +是在两分钟加两分钟加八分钟之后 + +1478 +00:57:29,876 --> 00:57:31,776 +It's still going to be 2 minutes after the first +它仍然会在第一次执行之后的的两分钟 + +1479 +00:57:31,778 --> 00:57:32,677 +2 minutes. +再次触发 + +1480 +00:57:32,678 --> 00:57:33,577 +Do you see what I'm saying? +你明白我的意思了吗 + +1481 +00:57:33,579 --> 00:57:35,596 +Within the tolerance. +在容忍误差的情况下 + +1482 +00:57:35,597 --> 00:57:37,614 +So it's going to stay on a schedule of every two minutes, +它仍然会保持两分钟的计划 + +1483 +00:57:37,616 --> 00:57:40,183 +even if it waits a little bit on one or two or three. +即使它会等待一两秒 + +1484 +00:57:40,185 --> 00:57:40,884 +It doesn't drift. +但它不会延后 + +1485 +00:57:43,088 --> 00:57:43,819 +Okay, that's timer. +好了,这就是定时器 + +1486 +00:57:45,256 --> 00:57:46,822 +Okay. Any questions about that? +有人有相关的问题吗? + +1487 +00:57:46,824 --> 00:57:49,791 +It's a pretty cool little guy. +这是个非常有趣的东西 + +1488 +00:57:49,793 --> 00:57:50,425 +All right. +好了 + +1489 +00:57:50,427 --> 00:57:52,177 +Animation. +动画 + +1490 +00:57:52,178 --> 00:57:53,928 +So, this is kind of Intro to Animation, +这堂课最后的十分钟将 + +1491 +00:57:53,930 --> 00:57:55,796 +this last ten minutes of today's lecture. +只是介绍一下动画 + +1492 +00:57:57,599 --> 00:58:01,367 +So, let me talk a little bit about the kinds of animation +让我们来聊一下到底有哪几种动画 + +1493 +00:58:01,369 --> 00:58:02,902 +that you can do in iOS. +你可以在 iOS 中使用 + +1494 +00:58:02,904 --> 00:58:06,271 +One is to animate the properties of a view. +一个是使 view 的属性执行动画 + +1495 +00:58:06,273 --> 00:58:08,573 +And that's what we're going to talk about today. +这也是我们今天将会谈到的 + +1496 +00:58:08,575 --> 00:58:09,941 +So that's one kind of animation. +这是一种动画 + +1497 +00:58:10,977 --> 00:58:14,378 +Another one is animation of view controller transitions, +另一种是 view controller 转场 + +1498 +00:58:14,380 --> 00:58:16,246 +like in a navigation controller, +比如在 navigation controller + +1499 +00:58:16,248 --> 00:58:19,449 +when you transition to the next card on the stack or +当你从栈中转场到另一张卡 + +1500 +00:58:19,451 --> 00:58:20,767 +something like that. +类似于这样 + +1501 +00:58:20,768 --> 00:58:22,084 +Or even a modal view controller like the UI alert, +或者说 modal view controller 比如 UIAlert + +1502 +00:58:22,087 --> 00:58:24,620 +or the action sheet that slides up from the bottom. +或 Action sheet 从底部滑出 + +1503 +00:58:24,622 --> 00:58:26,856 +Okay, that's another kind of animation, obviously. +明显这又是另一种动画 + +1504 +00:58:26,858 --> 00:58:29,158 +Okay we're not going to talk about view controller +我们不会在这节课中讲到 view controller + +1505 +00:58:29,160 --> 00:58:30,859 +transition animation in this class. +转场动画 + +1506 +00:58:30,861 --> 00:58:33,028 +It's not really that terribly difficult, but +这也不是很难,只是 + +1507 +00:58:33,030 --> 00:58:35,363 +it's just like I got to pick things to talk about and +我总要选择一些东西来讲,但这个东西没有 + +1508 +00:58:35,365 --> 00:58:37,665 +that one, we're not going to talk about, okay? +被选中,所以我们不会讲这个东西 + +1509 +00:58:37,667 --> 00:58:41,068 +But there is infrastructure for doing that. +这有基础设置用来完成 + +1510 +00:58:41,070 --> 00:58:43,670 +There's also something called Core Animation. +还有另一种动画叫做 Core Animation + +1511 +00:58:43,672 --> 00:58:46,773 +Okay, Core Animation is this incredibly powerful animation +Core Animation 是在 UIView Core Animation 动画 + +1512 +00:58:46,775 --> 00:58:49,375 +engine that underlies +底层的一种 + +1513 +00:58:49,377 --> 00:58:52,144 +all of this UIView animation that's going on. +非常强大的动画引擎 + +1514 +00:58:53,214 --> 00:58:56,915 +And Core Animation can animate arbitrary properties +而且 Core Animation 可以操纵大量属性执行动画 + +1515 +00:58:56,917 --> 00:58:57,749 +over time. + +1516 +00:58:57,751 --> 00:59:00,117 +And it knows how to juggle them and +而且它知道应该在何时 + +1517 +00:59:00,119 --> 00:59:03,454 +knows how to present them on screen over time. +展示在屏幕上 + +1518 +00:59:03,456 --> 00:59:04,888 +It's really super powerful. +它真的非常强大 + +1519 +00:59:04,890 --> 00:59:06,222 +Unfortunately, I can't talk about that either. +但不幸的是,同样我也不会讲这个 + +1520 +00:59:06,224 --> 00:59:08,224 +Okay. Don't have time for that. +没有这么多时间 + +1521 +00:59:08,226 --> 00:59:10,826 +But if you're going to do something serious animation +但如果你想要在视图中创造一些真正的动画 + +1522 +00:59:10,828 --> 00:59:13,796 +inside views and you're not going to use the next kind I'm +那么你不会想要使用我接下来将要将的 + +1523 +00:59:13,798 --> 00:59:16,365 +going to talk about, Core Animation, know that it's +动画。Core Animation + +1524 +00:59:16,367 --> 00:59:19,367 +there because you will eventually have to learn it. +这个东西你最终还是要学的 + +1525 +00:59:19,369 --> 00:59:19,934 +Okay. + +1526 +00:59:20,970 --> 00:59:23,504 +And the last one's called dynamic animation. +好了,最后一种动画叫做力学动画 + +1527 +00:59:23,506 --> 00:59:26,039 +That's physics-based animation. +这是基于物理引擎的动画 + +1528 +00:59:26,041 --> 00:59:30,643 +So that's giving views gravity and collision boundaries and +它会赋予视图重力和碰撞 + +1529 +00:59:30,645 --> 00:59:34,279 +other behaviors like friction and density, and +还有其他的行为比如摩擦力和密度 + +1530 +00:59:34,281 --> 00:59:35,714 +then saying, go. +然后执行 + +1531 +00:59:35,716 --> 00:59:36,965 +Okay? And + +1532 +00:59:36,966 --> 00:59:38,215 +then they'll just behave, okay. +它们就会运转 + +1533 +00:59:38,218 --> 00:59:41,252 +So that's dynamic behavior based animation, and +所以这就是力学表现动画 + +1534 +00:59:41,254 --> 00:59:43,320 +that's what we're going to talk about on Wednesday. +我们将会在周三的时候讲到 + +1535 +00:59:43,322 --> 00:59:44,621 +And that's what your assignment five is +这也是你任务五 + +1536 +00:59:44,623 --> 00:59:45,689 +mostly going to be about. +大部分要使用的东西 + +1537 +00:59:45,691 --> 00:59:47,524 +Assignment five's going to do a little bit of +任务五会有一些视图动画,我会在 + +1538 +00:59:47,526 --> 00:59:49,959 +view animation, which I'm going to talk about today, and +这周讲一些 + +1539 +00:59:49,961 --> 00:59:51,360 +then a lot of dynamic animation. +然后很多的力学动画 + +1540 +00:59:51,362 --> 00:59:52,578 +Okay? + +1541 +00:59:52,579 --> 00:59:53,795 +And why do we have dynamic animation? +什么我们需要力学动画? + +1542 +00:59:53,798 --> 00:59:55,597 +Why do we have this physics thing? +为什么我们需要这个物理的东西 + +1543 +00:59:55,599 --> 00:59:59,867 +If you ever watch an iPhone app, you know, +如果你曾经使用过 iPhone 应用 + +1544 +00:59:59,869 --> 01:00:04,238 +if you flip things up and let them drop down. +如果你拨动了某个东西然后让它们坠落 + +1545 +01:00:04,240 --> 01:00:06,873 +Don't do it now, but if you get your iPhones out and +不要现在做啦,但你如果你已经把 iPhone 拿出来了 + +1546 +01:00:06,875 --> 01:00:09,509 +you go to the very front, even if it's locked, and +你在解锁界面,即使它是锁住的 + +1547 +01:00:09,511 --> 01:00:12,145 +you pull down your notifications, you'll notice +然后你下拉你的通知窗口,你可以发现 + +1548 +01:00:12,147 --> 01:00:15,681 +they will kind of hit the bottom and bounce a little. +它们会撞击底部然后弹起来一点 + +1549 +01:00:15,683 --> 01:00:16,949 +Okay? +对吧 + +1550 +01:00:16,950 --> 01:00:18,216 +It won't just kind of pull it down and +它不会只是下拉 + +1551 +01:00:18,218 --> 01:00:20,118 +it won't just go clunk, it goes boom. +不会只是哐当到底部 + +1552 +01:00:20,120 --> 01:00:20,918 +Okay? It kind of gives +它展示一个 + +1553 +01:00:20,920 --> 01:00:21,919 +a soft landing. +柔软地着落 + +1554 +01:00:21,921 --> 01:00:23,520 +And that kind of animation turns out to +这种动画效果 + +1555 +01:00:23,522 --> 01:00:25,756 +be surprisingly important for the user experience. +对于用户体验来说非常重要 + +1556 +01:00:25,758 --> 01:00:28,224 +It makes the user feel a little more like oh, yeah, +这会让用户感觉,就像 + +1557 +01:00:28,226 --> 01:00:30,927 +it's kind of giving a constant warm fuzzy feeling about +它会给你一种非常温暖毛茸茸的感觉 + +1558 +01:00:30,929 --> 01:00:33,863 +what's going on, as opposed to feeling like a computer that +而不是感觉就像机器 + +1559 +01:00:33,865 --> 01:00:36,398 +is slamming things around, okay. +在直接碰地执行 + +1560 +01:00:36,400 --> 01:00:38,500 +So, dynamic animation is really important for +所以力学动画是非常重要的 + +1561 +01:00:38,502 --> 01:00:42,770 +giving that really kind of homey feel to your UI. +可以让你的 UI 有一种熟悉的感觉 + +1562 +01:00:42,772 --> 01:00:44,071 +Warm feel, okay? +温暖的感觉 + +1563 +01:00:44,073 --> 01:00:46,840 +So that's why we spend a lecture on it next time. +这就是为什么我们下一节课会讲这个 + +1564 +01:00:47,810 --> 01:00:50,343 +All right, so let's talk about animating view properties. +让了让我们来讲讲视图属性的动画 + +1565 +01:00:50,345 --> 01:00:54,080 +Only certain properties can be animated at the UIView level. +视图只有部分属性可以用来执行动画 + +1566 +01:00:54,082 --> 01:00:55,915 +If you go down to Core Animation, you can do more, +如果你用 Core Animation,那么可以使用更多 + +1567 +01:00:55,917 --> 01:00:57,349 +but at UIView level, +但在 UIView 这个层次 + +1568 +01:00:57,351 --> 01:01:00,686 +you can really, the three that are most important to animate +你只能操作三种最主要的动画 + +1569 +01:01:00,688 --> 01:01:04,322 +are the frame, that means moving your view around. +frame,这意味这你可以让你的视图到处移动 + +1570 +01:01:04,324 --> 01:01:07,558 +The transform, that means rotating your view or +transform,这意味着你可以旋转你的视图 + +1571 +01:01:07,560 --> 01:01:10,127 +scaling it in and out. +或者让它变大变小 + +1572 +01:01:10,129 --> 01:01:12,529 +And the opacity, the alpha. +然后是透明度,alpha + +1573 +01:01:12,531 --> 01:01:14,298 +Okay. + +1574 +01:01:14,299 --> 01:01:16,066 +So you can use this kind of animation to +你可以使用这种动画 + +1575 +01:01:16,068 --> 01:01:20,803 +fade things out using the alpha or to move around, +来让东西淡出或者让它到处移动 + +1576 +01:01:20,805 --> 01:01:22,938 +although they won't move with this nice physics base. +虽然它们并不会移动那么真实 + +1577 +01:01:22,940 --> 01:01:25,207 +So I kind of recommend the dynamic animation for +所以我推荐使用力学动画来操作 + +1578 +01:01:25,209 --> 01:01:27,242 +moving things. +移动 + +1579 +01:01:27,243 --> 01:01:29,276 +But it's really nice for alpha for fading things around, or +但这个用来执行渐隐渐现的动画还是很不错的 + +1580 +01:01:29,279 --> 01:01:30,812 +if you're going to have rotating views, +以及如果你需要旋转视图 + +1581 +01:01:30,814 --> 01:01:31,813 +views that rotate. +视图被旋转 + +1582 +01:01:33,783 --> 01:01:37,484 +So how do we do this animation with these properties? +那么我们应该怎么操作属性呢? + +1583 +01:01:37,486 --> 01:01:42,322 +It's done with class methods on UIView and closures, okay? +它使用 UIView 带有闭包函数的方法 + +1584 +01:01:42,324 --> 01:01:43,456 +So you have this class method. +你可以看到这个类方法 + +1585 +01:01:43,458 --> 01:01:46,559 +You basically say what kind of animation you want, +你基本上就是调用你想要的动画 + +1586 +01:01:46,561 --> 01:01:48,360 +how long you want it to take, things like that. +你想要它执行多久,类似于这样 + +1587 +01:01:48,362 --> 01:01:49,995 +And then you just provide a closure, and +然后你可以得到一个闭包 + +1588 +01:01:49,997 --> 01:01:52,464 +inside that closure you change these properties, frame, +在这个闭包中你可以修改这些属性,frame + +1589 +01:01:52,466 --> 01:01:53,731 +transform, alpha. +transform,alpha + +1590 +01:01:53,733 --> 01:01:55,066 +Just change them. +修改它们 + +1591 +01:01:55,068 --> 01:01:55,766 +Okay? + +1592 +01:01:55,768 --> 01:01:56,800 +And then the system +然后系统会 + +1593 +01:01:56,802 --> 01:01:59,002 +will animate those changes over time. +在指定时间内对它们执行动画 + +1594 +01:01:59,004 --> 01:02:00,203 +Simple as that. +就这么简单 + +1595 +01:02:00,205 --> 01:02:01,570 +So here's what the method looks like. +这就是一个方法的样子 + +1596 +01:02:01,572 --> 01:02:02,871 +It's called animateWithDuration. + +1597 +01:02:02,873 --> 01:02:04,439 +There's a few different kinds of it, but + +1598 +01:02:04,441 --> 01:02:05,740 +this is the basic one. +这是最基础的 + +1599 +01:02:05,742 --> 01:02:07,008 +You can see that it takes a duration. +你可以看到它接受一个 duration + +1600 +01:02:07,010 --> 01:02:08,809 +That's how long the animation is going to take. +这就是动画会执行的时长 + +1601 +01:02:08,811 --> 01:02:09,943 +A delay is wait. +delay 是等待 + +1602 +01:02:09,945 --> 01:02:12,079 +Should I wait to start this animation? +比如我是否应该等会执行这个动画 + +1603 +01:02:12,081 --> 01:02:14,080 +Options, we'll talk about those later. +Optinos,待会我们会说到这个 + +1604 +01:02:14,082 --> 01:02:16,516 +Then the block, okay? +然后是 block + +1605 +01:02:16,518 --> 01:02:19,518 +Takes no arguments, returns no arguments there, that closure. +这个闭包没有参数,也不返回参数 + +1606 +01:02:19,520 --> 01:02:23,022 +That's where you're going to change those view properties. +这里就是你修改这些视图属性的地方 + +1607 +01:02:23,024 --> 01:02:25,257 +And it also has a completion closure. +然后它也有一个代表完成的闭包 + +1608 +01:02:25,259 --> 01:02:27,525 +When it's done animating, the animation actually completed, +当动画执行完成的时候,动画完全执行完毕 + +1609 +01:02:27,527 --> 01:02:29,260 +it will call this and it'll let you know whether +它就会调用这个,它会让你知道 + +1610 +01:02:29,262 --> 01:02:31,562 +the animation finished or whether it was interrupted by +动画是否执行完成了,还是被另一个 + +1611 +01:02:31,564 --> 01:02:34,965 +another animation that tried to change that same property. +尝试着修改同样属性的动画给中断了 + +1612 +01:02:34,967 --> 01:02:38,268 +Okay, because you can have multiple animations going off +因为你可以同时执行多个 + +1613 +01:02:38,270 --> 01:02:39,269 +at the same time. +动画 + +1614 +01:02:39,271 --> 01:02:40,303 +All right? So what does it look like to +这就是如何使用 + +1615 +01:02:40,305 --> 01:02:41,137 +call this? +调用这个 + +1616 +01:02:41,139 --> 01:02:42,338 +Here's an example. +这里是一个例子 + +1617 +01:02:42,340 --> 01:02:45,841 +So this is going to, two seconds from now, +它会从现在开始执行两秒 + +1618 +01:02:45,843 --> 01:02:48,710 +start fading my view out over three seconds. +从三秒钟淡出我的视图开始 + +1619 +01:02:48,712 --> 01:02:50,345 +And when it's done fading out, +当它完成淡出之后 + +1620 +01:02:50,347 --> 01:02:52,079 +it's going to remove it from the super view. +它就会把视图从父视图中移除 + +1621 +01:02:53,382 --> 01:02:54,748 +Okay? That's what this one +就只是这一行 + +1622 +01:02:54,750 --> 01:02:56,683 +line of code does, okay? +代码的作用 + +1623 +01:02:56,685 --> 01:02:58,551 +It's got, I guess it's more than one of code, +它有,好吧我猜不止一行代码 + +1624 +01:02:58,553 --> 01:02:59,652 +cuz you've got the closures in there. +因为这里有个闭包 + +1625 +01:02:59,654 --> 01:03:02,421 +But it's what it does, okay? +但它就是这样 + +1626 +01:03:02,423 --> 01:03:06,024 +So you can see here that I say I want three seconds, for +你可看到我写了我想要执行三秒 + +1627 +01:03:06,026 --> 01:03:06,958 +it to take three seconds, but +它就会执行三秒 + +1628 +01:03:06,960 --> 01:03:08,159 +I want it to start in two seconds, so +但我想要它在两秒钟后开始 + +1629 +01:03:08,161 --> 01:03:09,527 +you're going to take five seconds total. +所以这里一共是五秒 + +1630 +01:03:09,529 --> 01:03:11,962 +Okay, it's not going to do anything for the first two. +它在开头的两秒什么都不会做 + +1631 +01:03:11,964 --> 01:03:13,764 +And then in my block, I just change my alpha. +然后在 block 里面我修改了 alpha + +1632 +01:03:14,866 --> 01:03:16,766 +Right? From 1, which it started out, +对吧,从1开始, + +1633 +01:03:16,768 --> 01:03:20,502 +I have an if that says only do this if I'm fully opaque. +我需要它完全消失 + +1634 +01:03:20,504 --> 01:03:21,470 +So I just set it to zero. +所以我设置为0 + +1635 +01:03:21,472 --> 01:03:23,388 +That's all I have to do. +这就是全部了 + +1636 +01:03:23,389 --> 01:03:25,305 +And then in my completion block, if I finished, +然后在 completion block 里 + +1637 +01:03:25,308 --> 01:03:28,209 +that's the if $0, that's the finish thing. +如果完成了动画,if $0 这就是是否完成 + +1638 +01:03:28,211 --> 01:03:29,360 +If I finish, +如果完成了 + +1639 +01:03:29,361 --> 01:03:30,510 +then I'm going to remove myself from the super view. +那么从父视图中移除自己 + +1640 +01:03:30,513 --> 01:03:33,580 +But if someone else animated alpha in between, +但如果在某个地方有另一个操作 alpha 的动画 + +1641 +01:03:33,582 --> 01:03:35,248 +then I'm not going to remove myself from super view. +那么我就不应该移除自己了 + +1642 +01:03:35,250 --> 01:03:36,616 +Which makes sense, right? +很合理对吧 + +1643 +01:03:36,617 --> 01:03:37,983 +Because they probably changed the alpha to something +因为它们可能把 alpha 修改为 + +1644 +01:03:37,986 --> 01:03:40,253 +nonzero, okay? +非0的值了 + +1645 +01:03:40,255 --> 01:03:42,922 +Now, a very important thing to understand about animation, +现在,理解动画非常重要的是 + +1646 +01:03:42,924 --> 01:03:46,258 +all animation that's going on, is when you make changes, +所有的动画,当你修改的属性的时候 + +1647 +01:03:46,260 --> 01:03:48,460 +they happen immediately. +它们都是立即生效的 + +1648 +01:03:48,462 --> 01:03:52,296 +The animation is just showing it to the user over time. +动画只是用来给用户展示的 + +1649 +01:03:52,298 --> 01:03:54,031 +Okay? So in this code, +所以在这里代码里 + +1650 +01:03:54,033 --> 01:03:58,402 +when I print myView.alpha equals myView.alpha, +当我输出 myView.alpha 等于 myView.alpha + +1651 +01:03:58,404 --> 01:04:03,239 +that is going to print zero, because that closure changed +它会打印0,因为在闭包中已经修改为 + +1652 +01:04:03,241 --> 01:04:06,242 +it to zero and it does it right away. +0了,所以它会立刻生效 + +1653 +01:04:06,244 --> 01:04:07,976 +Okay. Even though the user doesn't +即使用户还没有在屏幕上 + +1654 +01:04:07,978 --> 01:04:09,711 +get to see it on screen for five seconds, +看到五秒的动画 + +1655 +01:04:09,713 --> 01:04:11,380 +that's irrelevant. +这也并不重要 + +1656 +01:04:11,381 --> 01:04:13,048 +The fact is, I just changed my alpha to zero. +事实就是,我已经修改了 alpha 为 0 + +1657 +01:04:14,451 --> 01:04:16,317 +Okay. It's very important to +这对于理解来说非常重要 + +1658 +01:04:16,318 --> 01:04:18,184 +understand and it will take some wrapping your head around +可能会困扰你 + +1659 +01:04:18,187 --> 01:04:20,187 +until you really understand and work with it. +知道你完全明白它到底是怎么运作的了 + +1660 +01:04:20,189 --> 01:04:22,989 +But it's a little bit like multithreaded programming to +这就有点像多线程编程 + +1661 +01:04:22,991 --> 01:04:23,690 +understand. +明白了吗 + +1662 +01:04:23,692 --> 01:04:25,759 +But really, +但事实上 + +1663 +01:04:25,760 --> 01:04:27,827 +all animation is presenting it to the user over time. +所有的动画呈现给用户的时间 + +1664 +01:04:27,829 --> 01:04:29,128 +It's not changing it over time. +并不是真正修改其值的时间 + +1665 +01:04:30,598 --> 01:04:33,732 +Okay? All right. +好了 + +1666 +01:04:33,734 --> 01:04:34,566 +So that's it. +就是这样 + +1667 +01:04:34,568 --> 01:04:36,567 +That's how view animation works. +这就是视图动画的使用方法 + +1668 +01:04:36,569 --> 01:04:37,435 +Here's all the options. +现在来说说 options + +1669 +01:04:37,437 --> 01:04:38,702 +There's billions of them here. +这里有数十亿个选项 + +1670 +01:04:39,738 --> 01:04:41,071 +You can change the curve. +你可以修改曲线 + +1671 +01:04:41,073 --> 01:04:44,807 +So CurseEaseInEaseOut means that it starts slowly and +比如 CurseEaseInEaseOut 的意思是一开始慢速 + +1672 +01:04:44,809 --> 01:04:47,510 +then speeds up to normal and then slows back down again. +然后加速到正常速度,最后又慢下来 + +1673 +01:04:47,512 --> 01:04:48,811 +So my fade, that's the way it worked. +比如我的淡出,它就会这样 + +1674 +01:04:48,813 --> 01:04:50,412 +It would start fading out slowly and +它会先淡出得很慢 + +1675 +01:04:50,414 --> 01:04:53,048 +then normal speed and then at the very end when it's fading +然后正常速度,然后在最后 + +1676 +01:04:53,050 --> 01:04:54,549 +out, fade out a little slower. +又淡出得慢一点 + +1677 +01:04:54,551 --> 01:04:56,050 +Okay? + +1678 +01:04:56,052 --> 01:04:57,351 +You can also, +你也可以自己试 + +1679 +01:04:57,352 --> 01:04:58,651 +I don't have time to show you all these things, but +我没有时间来向你展示全部的效果 + +1680 +01:04:58,654 --> 01:05:00,387 +you can look at all these things. +但你可以自己试试 + +1681 +01:05:00,388 --> 01:05:02,121 +BeginFromCurrentState is an interesting one because I just +BeginFromCurrentState 是一个很有意思的东西 + +1682 +01:05:02,124 --> 01:05:05,458 +told you that the change happens immediately. +我刚才告诉你们,属性会立刻发生 + +1683 +01:05:05,460 --> 01:05:08,361 +But if you issued another animation that changed +但如果你又另一个动画也在改变 + +1684 +01:05:08,363 --> 01:05:11,464 +the alpha and you had this BeginFromCurrentState on, +alpha 然后你设置了 BeginFromCurrentState + +1685 +01:05:11,466 --> 01:05:14,966 +then that animation would pick up wherever any other +那么动画会从你当前动画 + +1686 +01:05:14,968 --> 01:05:16,067 +animation is. +开始执行 + +1687 +01:05:16,069 --> 01:05:18,202 +So that other animation might be partway +所以其他的动画或许 + +1688 +01:05:18,204 --> 01:05:19,604 +through doing the alpha. +直接变化透明度 + +1689 +01:05:19,605 --> 01:05:21,005 +And then I do another animation with this +然后我使用另一个设置了 BeginFromCurrentState + +1690 +01:05:21,007 --> 01:05:23,307 +BeginFromCurrentState and it's not going to start with it +它并不会从0开始变化 + +1691 +01:05:23,309 --> 01:05:25,442 +at zero, which is what alpha is now. +虽然现在属性的值就是0 + +1692 +01:05:25,444 --> 01:05:28,645 +It's going to pick up the partial, okay? +它会从当前部分开始 + +1693 +01:05:28,647 --> 01:05:31,381 +So that's one way where you can actually kind of over time +这也是一个你可以获取到当前值的方法 + +1694 +01:05:31,383 --> 01:05:33,282 +get the value, by issuing another animation. +通过另一个动画 + +1695 +01:05:35,286 --> 01:05:37,285 +Remember, all these animations are happening in another +记住,所有的动画都发生在另一个线程的 + +1696 +01:05:37,287 --> 01:05:38,720 +thread off the main queue. +而不是主队列 + +1697 +01:05:38,722 --> 01:05:42,656 +They're all happening out of time for you, okay? +执行的时间并不取决于你 + +1698 +01:05:42,658 --> 01:05:44,892 +When you send that last line of code, +当你执行到最后一行代码的时候 + +1699 +01:05:44,894 --> 01:05:47,127 +alpha immediately went to zero and you're on your way. +alpha 会立刻变为 0 + +1700 +01:05:47,129 --> 01:05:48,996 +Your code is still going. +你的代码也继续执行 + +1701 +01:05:48,997 --> 01:05:50,864 +The fact that things are happening on screen over time, +在屏幕上发生的一切会随着时间推移 + +1702 +01:05:50,866 --> 01:05:53,933 +it's kind of not relevant to you. +这和你没有什么关系 + +1703 +01:05:53,935 --> 01:05:55,167 +It's relevant to your user though. +这和你的用户有关系 + +1704 +01:05:56,337 --> 01:05:56,902 +Okay? + +1705 +01:05:58,605 --> 01:06:01,406 +Sometimes you want to change an entire view and +有时你想要改变整个视图 + +1706 +01:06:01,408 --> 01:06:03,674 +you can do that as well. +你可以可以 + +1707 +01:06:03,676 --> 01:06:07,144 +I'll give you an example here of a playing card. +我们会给你一个例子展示如果改变 card + +1708 +01:06:07,146 --> 01:06:09,346 +So if I had a playing card that has a back and a front. +如果我有前后两张卡 + +1709 +01:06:09,348 --> 01:06:11,781 +I might want to flip that card over. +我或许会想要反转卡牌 + +1710 +01:06:11,783 --> 01:06:13,416 +Okay, so I wanna change everything in the view. +所以我想要在视图中改变这一切 + +1711 +01:06:13,418 --> 01:06:15,351 +I wanna redraw the view basically, but +我想要重画这个视图 + +1712 +01:06:15,353 --> 01:06:16,385 +I want it to flip over. +我想要它翻转 + +1713 +01:06:16,387 --> 01:06:18,320 +I don't want it to just boop change, +我不想要它只是 BOOM 一下改变 + +1714 +01:06:18,322 --> 01:06:21,489 +I want it to have an animation where it flips over. +我想要有一个动画它可以翻转过来 + +1715 +01:06:21,491 --> 01:06:24,392 +So you can do flips over and curls up and dissolves, okay, +所以你可以翻转,卷曲和溶解 + +1716 +01:06:24,394 --> 01:06:26,294 +you can do all those. +你可以做这些操作 + +1717 +01:06:26,295 --> 01:06:28,195 +The way you do that is with a different UIView class +要做到这些你需要使用 UIView 的另一个类方法 + +1718 +01:06:28,197 --> 01:06:30,297 +method called transitionWithView. +叫做 transitionWithView + +1719 +01:06:30,299 --> 01:06:32,966 +You just give it the view, the playing card view or whatever. +你给它一个视图,一张卡片或者其他的东西 + +1720 +01:06:32,968 --> 01:06:35,068 +You tell how long you want the animation to take. +你需要告诉它动画执行多久 + +1721 +01:06:35,070 --> 01:06:37,470 +What kind of thing you want like flipping or +你要想什么样的动画,是翻转还是 + +1722 +01:06:37,472 --> 01:06:38,804 +dissolving or whatever. +溶解还是其他什么 + +1723 +01:06:38,806 --> 01:06:39,905 +You give it the animation. +你可以让它执行动画 + +1724 +01:06:39,907 --> 01:06:42,507 +Inside that animation you're changing your view, +在动画中你要改变你的视图 + +1725 +01:06:42,509 --> 01:06:44,109 +changing the attributes in your view. +改变你视图的参数 + +1726 +01:06:44,111 --> 01:06:45,810 +Like, if you had your calculator and +比如你有你的计算器 + +1727 +01:06:45,812 --> 01:06:49,647 +you wanted to change from one graph to another. +你想要从一个图表修改为另一种 + +1728 +01:06:49,649 --> 01:06:51,181 +In here you would change the graph. +在这里你修改图表 + +1729 +01:06:51,183 --> 01:06:53,817 +Okay, you would change it so when it draws the next time, +好了,这样下一次它会绘图 + +1730 +01:06:53,819 --> 01:06:55,285 +we draw something different. +我们画一点不同的东西 + +1731 +01:06:55,287 --> 01:06:58,788 +And then it would animate it, dissolve it, or whatever and +然后它会执行动画,溶解或者其他的 + +1732 +01:06:58,790 --> 01:07:00,589 +show the new version. +然后展示新的样式 + +1733 +01:07:00,591 --> 01:07:02,491 +In this closure you're changing anything you want +在闭包中你要可以修改任何东西 + +1734 +01:07:02,493 --> 01:07:05,494 +about the view, any attributes, any properties. +关于视图的,任何属性,任何参数 + +1735 +01:07:05,496 --> 01:07:08,363 +So the next time it draws, it will draw differently and +这样下一次绘制的时候,它就会绘制另一种样子 + +1736 +01:07:08,365 --> 01:07:11,632 +then this animation will kind of interpolate between those +然后动画也会插入这两种状态 + +1737 +01:07:11,634 --> 01:07:14,502 +two states, doing a flip or dissolve or whatever. +比如翻转或者溶解或者其他 + +1738 +01:07:14,504 --> 01:07:15,969 +So that's another kind of thing. +这又是另一个东西了 + +1739 +01:07:15,971 --> 01:07:17,204 +Now this one you're probably going to be +这个你可能只有在家庭作业的 + +1740 +01:07:17,206 --> 01:07:18,772 +doing in your homework. +时候来做了 + +1741 +01:07:18,774 --> 01:07:21,607 +Okay, I think I asked you explicitly to do some sort of +我想我会让你明确地做一种 + +1742 +01:07:21,609 --> 01:07:23,075 +animation like this. +这样的动画效果 + +1743 +01:07:24,512 --> 01:07:26,845 +Either this one or the last one, either one. +这个或者上一个,两者之一 + +1744 +01:07:26,847 --> 01:07:28,480 +So yeah, here's the playing card example. +好了,这就是卡片动画的例子 + +1745 +01:07:28,482 --> 01:07:31,282 +You can see in the closure I'm just changing the card to +你可以看到闭包我 + +1746 +01:07:31,284 --> 01:07:32,166 +be face up. +连接了两张卡 + +1747 +01:07:32,167 --> 01:07:33,049 +And so the next time it draws, +这样下一次它开始绘制 + +1748 +01:07:33,052 --> 01:07:34,184 +it's going to draw differently. +它就会绘制另一种样式 + +1749 +01:07:35,187 --> 01:07:36,219 +Okay? + +1750 +01:07:36,220 --> 01:07:37,252 +And again, this happens immediately. +再说一次,这个会立刻发生 + +1751 +01:07:37,255 --> 01:07:39,856 +That card is face up equals not card is face up. +面朝上的卡片等于没有面朝上的卡片 + +1752 +01:07:39,858 --> 01:07:40,756 +That happens instantly, +因为变化会立刻发生 + +1753 +01:07:40,758 --> 01:07:42,858 +as soon as I call this method, okay? +只要我调用了这个方法 + +1754 +01:07:42,860 --> 01:07:45,494 +It's just that over time, on screen, it will happen. +它会随着时间改变显示 + +1755 +01:07:46,430 --> 01:07:47,695 +But it happened immediately, right there. +但它是的变化是即刻的 + +1756 +01:07:47,697 --> 01:07:49,797 +If the next line, I say if card is face up, +如果下一行我写卡面朝上 + +1757 +01:07:49,799 --> 01:07:52,333 +it's going to be the changed value, okay? +它也会修改值 + +1758 +01:07:52,335 --> 01:07:54,601 +These transitionWithView methods, +这些 transitionWithViewAnimatedWithDuration + +1759 +01:07:54,603 --> 01:07:56,970 +animated with duration, they return immediately. +它们是立刻返回的 + +1760 +01:07:56,972 --> 01:07:58,104 +They do what's in the enclosure and +它们执行闭包中的东西 + +1761 +01:07:58,106 --> 01:07:58,804 +return immediately. +并且立刻返回 + +1762 +01:08:01,709 --> 01:08:02,273 +Okay? + +1763 +01:08:03,810 --> 01:08:05,943 +If you're animating changes to the view hierarchy, +如果想要你在视图层级中有任何动画的改变 + +1764 +01:08:05,945 --> 01:08:07,344 +like you're hiding views or +比如隐藏视图或者 + +1765 +01:08:07,346 --> 01:08:09,546 +removing them from super view and that's all you're doing, +从父类那里移除视图都可以 + +1766 +01:08:09,548 --> 01:08:11,214 +and you want them to flip over and +你想要翻转 + +1767 +01:08:11,216 --> 01:08:14,650 +go away, then you can use this transitionFromView to view. +然后离开,你可以用 transitionFromViewToView + +1768 +01:08:14,652 --> 01:08:15,451 +Okay? Otherwise it's +除此之外 + +1769 +01:08:15,453 --> 01:08:17,270 +exactly the same. +其他都是一样的 + +1770 +01:08:17,271 --> 01:08:19,088 +It's just for things that change the view hierarchy but +它只是改变视图层级 + +1771 +01:08:19,090 --> 01:08:20,589 +it's basically the same. +但其他的都是一样的 + +1772 +01:08:20,591 --> 01:08:22,257 +So there's no closure there because +所以这里没有闭包 + +1773 +01:08:22,259 --> 01:08:24,192 +the change you're making is change in the view hierarchy. +是由于你改变的是视图层级 + +1774 +01:08:24,194 --> 01:08:25,526 +You're not changing card that's face up, +你不是在改变卡片是否面朝上 + +1775 +01:08:25,528 --> 01:08:27,428 +you're actually changing whether the view is +你在改变的是视图是否 + +1776 +01:08:27,430 --> 01:08:28,695 +in the hierarchy anymore. +仍然在层级中 + +1777 +01:08:30,365 --> 01:08:32,965 +Yeah. >> I'm just wondering, so. +>> 学生提问 + +1778 +01:08:32,967 --> 01:08:35,935 +If you want to specify several of the [INAUDIBLE]. +>> 学生提问 + +1779 +01:08:35,937 --> 01:08:37,469 +>> Yeah. +好 + +1780 +01:08:37,471 --> 01:08:39,371 +>> [INAUDIBLE]. + +1781 +01:08:39,373 --> 01:08:43,007 +>> Yeah. + +1782 +01:08:43,009 --> 01:08:46,344 +>> No, they are. + +1783 +01:08:46,346 --> 01:08:48,779 +That's a good question in this particular API. +对于这个特殊的 API 来说是个好问题 + +1784 +01:08:48,781 --> 01:08:51,281 +Ask me on Piazza and I'll try and +待会在走廊上来问我 + +1785 +01:08:51,283 --> 01:08:55,351 +some APIs you specify as an array, some APIs different. +我会试着用一些 API,一些 API 不同 + +1786 +01:08:55,353 --> 01:08:57,720 +It depends but most times, Swift is an eNom, +根据情况而定,但 Swift 是 enum + +1787 +01:08:57,722 --> 01:09:01,123 +so you are doing something like that or combining them, +你可以这样做或者把它们结合起来 + +1788 +01:09:01,125 --> 01:09:03,625 +so ask me on Piazza. +待会下来问我 + +1789 +01:09:03,627 --> 01:09:04,292 +Okay. + +1790 +01:09:04,294 --> 01:09:05,426 +So that's it for today. +这就是今天的全部内容 + +1791 +01:09:05,428 --> 01:09:07,078 +On Friday, +在周五 + +1792 +01:09:07,079 --> 01:09:08,729 +we have a great section which is UICollectionView. +我们会有一个很棒的部分关于 UICollectionView + +1793 +01:09:08,731 --> 01:09:11,398 +It's great because UICollectionView is very +很棒是因为 UICollectionView 非常 + +1794 +01:09:11,400 --> 01:09:12,599 +similar to UITableView. +类似与 UITableView + +1795 +01:09:12,601 --> 01:09:15,101 +You'll really understand UITableView +你会理解 UITableView 的 + +1796 +01:09:15,103 --> 01:09:18,004 +if you go do look at this UICollectionView one. +如果你看了这个 UICollectionView + +1797 +01:09:18,006 --> 01:09:20,172 +Monday's a holiday and the next week I'm going to start +周一是节日,然后下周我会开始讲 + +1798 +01:09:20,174 --> 01:09:21,674 +on that physics-based animation. +基于物理的动画 + +1799 +01:09:21,676 --> 01:09:24,409 +>> [COUGH] >> Thank you very much. +>> 谢谢大家 + +1800 +01:09:27,313 --> 01:09:27,344 +>> For more, please visit us at stanford.edu. +>> 想了解更多,请登录 stanford.edu \ No newline at end of file diff --git a/subtitles/12. Dynamic Animation.srt b/subtitles/12. Dynamic Animation.srt new file mode 100644 index 0000000..a88dc14 --- /dev/null +++ b/subtitles/12. Dynamic Animation.srt @@ -0,0 +1,8967 @@ +1 +00:00:00,001 --> 00:00:04,569 +[MUSIC] +[音乐] + +2 +00:00:04,571 --> 00:00:07,705 +Stanford University. +斯坦福大学 + +3 +00:00:07,707 --> 00:00:11,809 +>> Okay, well, welcome to lecture 12 of Stanford CS193P +欢迎来到 CS193P 课程的第12讲 + +4 +00:00:11,811 --> 00:00:13,243 +winter of 2015. +这是 CS193P 在2015年冬季的课程 + +5 +00:00:13,245 --> 00:00:16,513 +Today we're going to talk about a different kind +今天我们想要聊一些与上周 + +6 +00:00:16,515 --> 00:00:17,880 +of animation than we talked about last week, +讲的不一样的动画效果 + +7 +00:00:17,882 --> 00:00:20,549 +which is physics-based dynamic animation, it's called. +叫做,物理动态动画效果(Physics-based Dynamic Animation) + +8 +00:00:20,551 --> 00:00:22,418 +And then I'm going to do a big demo of that, +然后我会做一个大的 Demo + +9 +00:00:22,420 --> 00:00:24,119 +which is called Dropit. +这个 Demo 我想称之为 Dropit + +10 +00:00:24,121 --> 00:00:26,254 +First of all, let me say that what we're, +首先 + +11 +00:00:26,256 --> 00:00:30,158 +our topic this week is dynamic animation. +我们这周的话题就是动态动画效果 + +12 +00:00:30,160 --> 00:00:31,959 +So it's a different kind of animation than we saw +这与我们上周讲到的动画效果 + +13 +00:00:31,961 --> 00:00:33,127 +last week. +有相当的不同 + +14 +00:00:33,129 --> 00:00:34,961 +It's a physics-based thing. +它是基于物理效果的 + +15 +00:00:34,963 --> 00:00:36,963 +Now we're gonna have some fun with it, +因为是与真实世界的物理效果相同 + +16 +00:00:36,965 --> 00:00:38,564 +this physics-based thing. +所以我们能够在这上面做一些有趣的事情 + +17 +00:00:38,566 --> 00:00:40,333 +And you're gonna write a game with it. +同时,你们会用这个来编写一个游戏 + +18 +00:00:40,335 --> 00:00:43,102 +Yeah, I'm not sure you would really use it for that. +当然,我并不确定你肯定会用到它 + +19 +00:00:43,104 --> 00:00:44,670 +It's more for things like this. +但是更多类似于这种的东西 + +20 +00:00:44,672 --> 00:00:46,604 +You see how when I slide this up, +比如现在,我上拉 Control Center + +21 +00:00:46,606 --> 00:00:49,374 +it kind of bounces a little and wiggles? +在最后的时刻,它会有一个晃动的弹跳效果 + +22 +00:00:49,376 --> 00:00:52,109 +See? It doesn't just kind of solid +看到了吗?这个动画并不是 + +23 +00:00:52,111 --> 00:00:55,679 +go up and stop, it kind of bounces off the top. +我直接上拉 Control Center,然后它就停止在最高的点上了 + +24 +00:00:55,681 --> 00:00:58,515 +Basically what's happening there is that there's gravity +通常,我们会说,这里有一个仿重力 + +25 +00:00:58,517 --> 00:00:59,783 +pointing up. + +26 +00:00:59,785 --> 00:01:01,168 +Okay? +明白了吗? + +27 +00:01:01,169 --> 00:01:02,552 +And then there's a little bit of elasticity, and +同时,这里会有一点点的弹性 + +28 +00:01:02,554 --> 00:01:06,055 +that view it's just being allowed to fall up and +所以,这个视图被允许向上滑动 + +29 +00:01:06,057 --> 00:01:07,723 +bounce off the bottom. +并在到达起顶部的时候有一个弹跳效果 + +30 +00:01:07,725 --> 00:01:09,091 +Okay? And that's what we're going to +明白了吗? + +31 +00:01:09,093 --> 00:01:12,360 +learn how to do today is have gravity and bouncing and +这也就是我们今天想要学习的内容,如何让一个视图 + +32 +00:01:12,362 --> 00:01:14,429 +all this kind of physics behavior. +拥有类似的重力效果和弹跳效果,等等类似的物理动画效果 + +33 +00:01:14,431 --> 00:01:16,230 +But instead of just doing something, you know, +但是,我们并不想通过一些平时很无聊的 Demo 来学习 + +34 +00:01:16,232 --> 00:01:19,366 +boring like this, we're going to make a game out of it. +取而代之的是,我们想要通过这个做一个游戏 + +35 +00:01:19,368 --> 00:01:21,968 +The game we're going to make is Breakout. +这个游戏我们想称之为 Breakout + +36 +00:01:21,970 --> 00:01:26,339 +Or Brickout, sometimes people call it. +或者有些人喜欢称之为 Brickout + +37 +00:01:27,375 --> 00:01:31,243 +The point is to learn all the APIs of this physics-based +这个游戏的目的是,学习所有基于这个物理动态引擎 + +38 +00:01:31,245 --> 00:01:33,212 +dynamic engine. +的 API + +39 +00:01:33,213 --> 00:01:35,180 +But to have some fun along the way, so I've actually made +想要让这个过程是非常有趣的,我制定了 + +40 +00:01:35,182 --> 00:01:38,683 +the requirements for the game itself be pretty light, okay? +一部分很小的对游戏的要求 + +41 +00:01:38,685 --> 00:01:40,985 +It just basically has to do the basics of the game, and +最基础的是,必须符合游戏的规则 + +42 +00:01:40,987 --> 00:01:43,787 +then giving you a lot of room to maneuver on kind of the fun +其他的地方就留给你们自由发挥的空间 + +43 +00:01:43,789 --> 00:01:45,589 +features of the game, so. +你们肯定会很喜欢的 + +44 +00:01:45,591 --> 00:01:48,191 +So dynamic animation is different +好的,动态动画效果与我们上周 + +45 +00:01:48,193 --> 00:01:49,859 +than the animation we talked about last week. +讲的动画效果是不太一样的 + +46 +00:01:49,861 --> 00:01:51,861 +Last week, we were talking about taking certain view +上周我们讲的是,取一些特定的视图属性 + +47 +00:01:51,863 --> 00:01:54,563 +properties and animating them over time. +并根据时间来让它动起来 + +48 +00:01:54,565 --> 00:01:57,366 +Or perhaps animating an entire change to a view +类似于,将一个视图像卡片一样翻转过来的操作 + +49 +00:01:57,368 --> 00:02:00,301 +like a flipping over a card by flipping the whole + +50 +00:02:00,303 --> 00:02:01,436 +view over, okay? + +51 +00:02:01,438 --> 00:02:03,671 +Or cross-dissolving the entire view. +还有,Cross-Dissolving 整个视图这样的动画效果 + +52 +00:02:03,673 --> 00:02:06,840 +This is more where we're going to have our views, and +但是我们这周讲的是 + +53 +00:02:06,842 --> 00:02:08,642 +we're going to have them moving around on screen. +我们如何在屏幕上移动这些视图 + +54 +00:02:08,644 --> 00:02:10,377 +Maybe running up against other things and +有可能这些视图于其他的视图之间相互影响 + +55 +00:02:10,379 --> 00:02:12,745 +bouncing a little bit, that kind of stuff. +产生一些弹跳效果等类似的东西 + +56 +00:02:13,681 --> 00:02:15,381 +The way you make this stuff work, okay, +然而你想做出这样的动画效果 + +57 +00:02:15,383 --> 00:02:16,715 +it's a multi-step process. +要经历很多个步骤 + +58 +00:02:16,717 --> 00:02:18,166 +The firs thing is, +首先要做的是 + +59 +00:02:18,167 --> 00:02:19,616 +you're going to need a UIDynamicAnimator. +你需要一个 UIDynamicAnimator + +60 +00:02:19,619 --> 00:02:22,220 +That's the class that really drives the whole thing, so +这是驱动这些物理动画效果的本源 + +61 +00:02:22,222 --> 00:02:23,788 +you need one of those. +所以你需要一个 UIDynamicAnimator 的实例 + +62 +00:02:23,790 --> 00:02:27,424 +And you'll only have one for any animation that's going on. +如果你需要一种类似的动画效果,那你就需要一个它的实例 + +63 +00:02:27,426 --> 00:02:29,993 +You can have multiple UIDynamicAnimators if you had, +你可以同时有多个 UIDynamicAnimator 的实例 + +64 +00:02:29,995 --> 00:02:32,028 +for example, another view doing some animation at +比如,同时有另外的一个视图拥有其他的物理动画效果 + +65 +00:02:32,030 --> 00:02:32,962 +the same time. + +66 +00:02:32,964 --> 00:02:34,897 +But within your own view, +但是在你自己的视图里面 + +67 +00:02:34,898 --> 00:02:36,831 +you're probably just gonna have this one animator. +你可能只需要一个 UIDynamicAnimator 的实例 + +68 +00:02:36,834 --> 00:02:38,233 +So you're gonna create this animator, +首先,你已经创建好了这个 UIDynamicAnimator + +69 +00:02:38,235 --> 00:02:41,770 +then you're gonna add dynamic behaviors to it. +然后你要做的是,向它之上添加一些动态的行为 + +70 +00:02:41,772 --> 00:02:44,005 +So behaviors are like gravity and +比如类似于重力的行为 + +71 +00:02:44,007 --> 00:02:46,774 +collision and things attached to each other. +或者是碰撞,或是附加在一起的效果 + +72 +00:02:46,776 --> 00:02:49,343 +It's how the things inside are going to behave, 'Kay? +这就是你的 UIDynamicAnimator 中的视图相互之间影响的行为,明白了吗? + +73 +00:02:49,345 --> 00:02:52,179 +And these are basically physics-based descriptions of +这就是描述了这些视图物理行为的东西 + +74 +00:02:52,181 --> 00:02:53,814 +how they're going to behave. + +75 +00:02:53,816 --> 00:02:55,082 +And then, of course, +当然,接下来 + +76 +00:02:55,083 --> 00:02:56,349 +there's the things that are going to be animated, +就是,想要受这些动画影响的视图 + +77 +00:02:56,351 --> 00:02:59,752 +which for our purposes are always gonna be UIViews. +目前我们只会用到 UIView 的实例 + +78 +00:02:59,754 --> 00:03:01,237 +Okay? +明白了吗? + +79 +00:03:01,238 --> 00:03:02,721 +These UIViews, DynamicItems, +这些视图,Dynamic Items + +80 +00:03:02,723 --> 00:03:04,690 +they are going to be affected by the gravity and +将会受其他对象的重力、碰撞 + +81 +00:03:04,692 --> 00:03:07,559 +the collisions and all those things. +或者其他的效果 + +82 +00:03:07,561 --> 00:03:08,092 +Okay? +明白了吗? + +83 +00:03:08,094 --> 00:03:09,060 +That's it. +就这些步骤 + +84 +00:03:09,062 --> 00:03:10,461 +Just create the dynamic animator, +简单的说,先创建 UIDynamicAnimator 实例 + +85 +00:03:10,463 --> 00:03:12,396 +create the behaviors you want and +然后定义你想要的行为 + +86 +00:03:12,397 --> 00:03:14,330 +configure them, add the items to the behaviors, bam. +设置受影响的对象,将这些对象加到这个行为中 + +87 +00:03:14,333 --> 00:03:16,132 +It'll just start automatically animating. +然后,视图就自动动起来了 + +88 +00:03:16,134 --> 00:03:17,633 +And if you remove an item from an behavior, +同样的,当你从一个行为中移走了一个对象 + +89 +00:03:17,635 --> 00:03:19,001 +it'll stop animating. +它就停止了它的动画效果 + +90 +00:03:19,003 --> 00:03:19,668 +Okay? +明白了吗? + +91 +00:03:19,670 --> 00:03:20,535 +Simple as that. +就是如此的简单 + +92 +00:03:20,537 --> 00:03:22,137 +So let's look at the steps. +让我们看一下这些步骤的代码 + +93 +00:03:22,139 --> 00:03:25,373 +The first step is you need to create a UIDynamicAnimator, +首先的第一步,创建一个 UIDynamicAnimator 的实例 + +94 +00:03:25,375 --> 00:03:27,608 +and the dynamic animators we're going to use, +我们这里想要使用的是 animator 变量 + +95 +00:03:27,610 --> 00:03:30,444 +I'm only going to talk about ones that animate views. +这里我们只会使用到视图 + +96 +00:03:30,446 --> 00:03:32,646 +You can actually use an animator to animate arbitrary +当然你还可以对一些抽象的东西做动画效果 + +97 +00:03:32,648 --> 00:03:33,313 +things. + +98 +00:03:33,315 --> 00:03:34,514 +Okay? +明白了吗? + +99 +00:03:34,515 --> 00:03:35,714 +Not even graphical things. +不一定是要图形上的东西 + +100 +00:03:35,717 --> 00:03:38,317 +But we're only gonna talk about animating views. +但是这里我们只会讲到视图的动画 + +101 +00:03:38,319 --> 00:03:40,302 +Okay? +明白了吗? + +102 +00:03:40,303 --> 00:03:42,286 +So when we create a dynamic animator that animates views, +我们已经创建了一个 UIDynamicAnimator 来让我们的视图动起来 + +103 +00:03:42,289 --> 00:03:45,390 +we have to specify the top-level +我们必须指定最顶层的 UIView + +104 +00:03:45,392 --> 00:03:48,927 +UIView, the view at the top of the view hierarchy where our +也就是在视图系统中最顶层的那个视图 + +105 +00:03:48,929 --> 00:03:50,061 +animations are occurring in. +所有动画效果发生在这里面 + +106 +00:03:50,063 --> 00:03:52,930 +Now animations can occur anywhere deep +现在,动画效果就可以在视图系统中的任意一个地方 + +107 +00:03:52,932 --> 00:03:54,765 +down that view hierarchy you want. +其作用了 + +108 +00:03:54,767 --> 00:03:57,034 +But we have specified the top-level view. +所以我们需要指定最顶层的那个视图 + +109 +00:03:57,036 --> 00:03:59,669 +So, in other words, any view that this dynamic animator's +换言之,UIDynamicAnimator 所有的动画效果都会 + +110 +00:03:59,671 --> 00:04:04,540 +going to animate has to be a subview or subview of +是这个 Reference View 的子视图,或者是子视图的子视图 + +111 +00:04:04,542 --> 00:04:07,142 +a subview of a subview of this reference view. + +112 +00:04:07,144 --> 00:04:08,810 +Okay? So that's the only argument +明白了吗? + +113 +00:04:08,812 --> 00:04:11,479 +you have to provide when you create a dynamic animator. +这就是你创建 UIDynamicAnimator 实例唯一需要的参数 + +114 +00:04:13,116 --> 00:04:14,348 +Then you create these behaviors. +接下来我们创建一些行为 + +115 +00:04:14,350 --> 00:04:17,417 +Behaviors are these concrete subclasses of +行为是一些 UIDynamicBehavior 的子类 + +116 +00:04:17,419 --> 00:04:19,019 +UIDynamicBehavior. + +117 +00:04:19,021 --> 00:04:21,120 +And so there's like UIGravityBehavior, +比如说 UIGravityBehavior + +118 +00:04:21,122 --> 00:04:23,689 +just say UIGravityBehavior, takes no arguments. +接受0个参数 + +119 +00:04:23,691 --> 00:04:25,024 +And in CollisionBehavior, +在 CollisionBehavior 中 + +120 +00:04:25,026 --> 00:04:27,259 +I'm going to talk about all of these behaviors you can do, +我将会讨论所有你能做的行为 + +121 +00:04:27,261 --> 00:04:30,161 +and you just add them with the method addBehavior +你只需要使用 addBehavior 来添加它们 + +122 +00:04:30,163 --> 00:04:31,229 +to your animator. +到你的动画器(animator)中 + +123 +00:04:31,231 --> 00:04:32,363 +Simple enough. +足够简单了吧 + +124 +00:04:32,365 --> 00:04:34,932 +And then you add the DynamicItems which are gonna +随后你会在这之上添加 DynamicItem + +125 +00:04:34,934 --> 00:04:35,866 +be UIViews. +它们应该是 UIView + +126 +00:04:35,868 --> 00:04:37,734 +Okay? UIDynamicItems +明白了吗? + +127 +00:04:37,736 --> 00:04:39,736 +are really just a protocol I'm gonna talk about in a second, +我等下会讲,UIDynamicItems 只是一个协议 + +128 +00:04:39,738 --> 00:04:42,238 +but UIView implements that protocol. +但是 UIView 实现了这个协议 + +129 +00:04:42,240 --> 00:04:45,774 +But you just add these items using the method addItem on +但是你目前不用管这些,你只需要用 UIDynamicBehavior 的 addItem + +130 +00:04:45,776 --> 00:04:47,575 +UIDynamicBehavior. +把这些东西添加进来就可以了 + +131 +00:04:47,577 --> 00:04:49,444 +So you see how I'm adding the items to the behavior. +这样你就可以看到我时如何给 item 添加行为的 + +132 +00:04:49,446 --> 00:04:51,278 +So you don't add the items to the animator, +不是把这些东西添加到动画器中 + +133 +00:04:51,280 --> 00:04:52,613 +you add the items to the behavior. +而是将这些东西添加到行为中 + +134 +00:04:52,615 --> 00:04:55,215 +You add the behaviors to the animator. +然后把行为添加到动画器里 + +135 +00:04:55,217 --> 00:04:57,000 +Okay? +明白了吗? + +136 +00:04:57,001 --> 00:04:58,784 +So in this case up here, item1, +在这里,item1 + +137 +00:04:58,787 --> 00:05:02,955 +I added it to gravity and collider. +我把它添加给了 gravity 和 collider + +138 +00:05:02,957 --> 00:05:05,124 +So item1 is going to be affected by the gravity, +所以 item1 将会受其他对象的重力 + +139 +00:05:05,126 --> 00:05:07,659 +and it's also going to collide with whatever +和碰撞的设置所影响 + +140 +00:05:07,661 --> 00:05:09,227 +the collider sets up. + +141 +00:05:09,229 --> 00:05:11,295 +Item2, is affected by the gravity, but +item2 将会受其他对象的重力所影响 + +142 +00:05:11,297 --> 00:05:13,397 +it will not collide with whatever's in the collider. +但是不会受到碰撞效果的影响 + +143 +00:05:13,399 --> 00:05:15,933 +It also won't collide with item1, they would pass right +item2 不会与 item1 相碰撞,它们会相互穿过彼此 + +144 +00:05:15,935 --> 00:05:18,869 +through each other, because it's not part of the collider. +因为这不受碰撞效果的影响 + +145 +00:05:18,871 --> 00:05:21,171 +Okay, so if you want things to interact with each other, +所以,如果你想要这两者相互产生互动的话 + +146 +00:05:21,173 --> 00:05:22,839 +they have to both be a part of the same behavior. +它们都必须添加到一个相同的行为 + +147 +00:05:25,109 --> 00:05:28,043 +Okay, that protocol is talking about UIDynamicItems +好的,这个协议讲的是 UIView + +148 +00:05:28,045 --> 00:05:29,811 +that UIView implements. +实现的 UIDynamicItems + +149 +00:05:29,813 --> 00:05:34,415 +It just has three properties, actually, bounds. +它有三个属性,bounds + +150 +00:05:34,417 --> 00:05:35,983 +This is read-only, so +这个属性是只读的 + +151 +00:05:35,985 --> 00:05:40,320 +the animator cannot animate the size of something. +动画器无法改变一个东西的大小 + +152 +00:05:40,322 --> 00:05:41,755 +Okay? Because +这是因为 + +153 +00:05:41,756 --> 00:05:43,189 +the bounds part of the protocol is read-only. +这个协议实现的 bounds 部分是只读的 + +154 +00:05:44,292 --> 00:05:46,959 +So the two animatable properties are the center, so +另外两个可以被动画改变的属性是,center + +155 +00:05:46,961 --> 00:05:48,193 +that's the position of the thing. +这定义了一个对象的位置 + +156 +00:05:48,195 --> 00:05:50,362 +So you can see animators moving things all over +你可以看到动画效果将对象的位置移动来移动去 + +157 +00:05:50,364 --> 00:05:52,263 +the place, that's mostly what they do. +这也就是常用的一些动画 + +158 +00:05:52,265 --> 00:05:55,700 +And then also a transform, which is AffineTransform. +还有一个 transform 属性,它是 AffineTransform 类型的 + +159 +00:05:55,702 --> 00:05:57,601 +Now notice that view UIView already have +现在,注意到 UIView 已经拥有了这三个属性 + +160 +00:05:57,603 --> 00:05:59,703 +all three of these properties, so you didn't even have to +你不需要做任何事情去实现这个协议了 + +161 +00:05:59,705 --> 00:06:01,271 +do anything to implement this protocol. + +162 +00:06:02,374 --> 00:06:03,406 +That AffineTransform, +我顺便说一下,这里的 AffineTransform + +163 +00:06:03,408 --> 00:06:05,141 +by the way, is only used for rotation. +是用于旋转的 + +164 +00:06:06,077 --> 00:06:08,777 +So basically, the animator can rotate the view, or +大致你可以理解为,这个动画器能够旋转这个视图 + +165 +00:06:08,779 --> 00:06:10,211 +he can position it. +或者重新定位这个视图 + +166 +00:06:10,213 --> 00:06:13,147 +That's something that the animator can do. +这就是动画器能够做到 + +167 +00:06:13,149 --> 00:06:16,684 +Okay, now if you change the center or the transform, +好的,现在,如果你想改变一个视图的中心或者使其变形 + +168 +00:06:16,686 --> 00:06:18,285 +like you change the frame or +就像你改变了视图的 frame 或 + +169 +00:06:18,287 --> 00:06:20,654 +the center of the view to move it and +视图的中心使其移动位置 + +170 +00:06:20,656 --> 00:06:23,423 +the animator has a hold of it, you gotta tell the animator +你告诉拥有这个对象的动画器 + +171 +00:06:23,425 --> 00:06:26,459 +you did that by calling updateItemUsingCurrentState. +你使用一个叫做 updateItemUsingCurrentState 的方法 + +172 +00:06:26,461 --> 00:06:28,060 +You just pass the view. +传入视图 + +173 +00:06:28,062 --> 00:06:29,278 +Okay? +明白了吗? + +174 +00:06:29,279 --> 00:06:30,495 +And so the animator can say, oh, that thing moved. +然后,动画器会知道,这个东西移动了 + +175 +00:06:30,498 --> 00:06:32,064 +And it will update its internal state +它会从开始的地方更新内部状态 + +176 +00:06:32,066 --> 00:06:33,431 +to start from wherever that thing is. +无论这个东西的位置是哪里 + +177 +00:06:33,433 --> 00:06:35,233 +Does that make sense? +我这么说能明白吗? + +178 +00:06:35,235 --> 00:06:38,069 +Obviously, if you and the animator are fighting over +显然的,你和动画器正在争抢 + +179 +00:06:38,071 --> 00:06:41,638 +who's positioning a view, you have to at least communicate, +重新定位一个视图的所有权,你需要协调好这个 + +180 +00:06:41,640 --> 00:06:42,973 +and this is how you do it. +上面的就是你如何做的过程 + +181 +00:06:42,975 --> 00:06:43,673 +Okay? +明白了吗? + +182 +00:06:43,675 --> 00:06:44,874 +Simple enough. +就是如此的简单 + +183 +00:06:44,876 --> 00:06:45,941 +All right. So let's talk about some of +好的,让我们再谈谈另外的一些效果 + +184 +00:06:45,943 --> 00:06:47,276 +these behaviors, the concrete behavior. +凝聚(concrete)的行为 + +185 +00:06:47,278 --> 00:06:50,479 +So gravity is very simple behavior. +重力行为非常的简单 + +186 +00:06:50,481 --> 00:06:52,147 +It just has an angle. +就设置一个角度 + +187 +00:06:52,149 --> 00:06:54,549 +So you can have the gravity be going up the screen or +之后你就可以在屏幕上看到重力的效果 + +188 +00:06:54,551 --> 00:06:56,751 +down the screen or to the left or to the right or +无论是从左到右的重力效果还是 + +189 +00:06:56,753 --> 00:06:59,820 +any angle you want, and it has a magnitude. +你想要的任意的角度 + +190 +00:06:59,822 --> 00:07:02,139 +Okay? So +明白了吗? + +191 +00:07:02,140 --> 00:07:04,457 +the magnitude is in the scale where 1.0 is 1,000 +这里的大小(magnitude)的比例是 1.0:1000 + +192 +00:07:04,460 --> 00:07:07,127 +points per second per second. +1000 像素点每二次方秒 + +193 +00:07:07,129 --> 00:07:08,912 +'Kay? + +194 +00:07:08,913 --> 00:07:10,696 +You all know that gravity is an acceleration. +你们都知道重力是一种加速度 + +195 +00:07:10,699 --> 00:07:13,199 +The acceleration due to gravity on Earth is 9.8 +这个加速度在地球上是 9.8 米每平方秒 + +196 +00:07:13,201 --> 00:07:15,000 +meters per second squared. + +197 +00:07:15,002 --> 00:07:18,837 +And the acceleration due to gravity in these behaviors is +这里的重力加速度是 1000 点每平方米秒 + +198 +00:07:18,839 --> 00:07:21,572 +1,000 points per second squared. + +199 +00:07:21,574 --> 00:07:23,240 +'Kay? You can also set this +明白了吗?当然你可以用一个向量设置 + +200 +00:07:23,242 --> 00:07:25,109 +as a vector, but angle and magnitude +但是角度和大小 + +201 +00:07:25,111 --> 00:07:27,144 +are probably the easiest way to understand this. +会是一个最简单的弄懂它的方法 + +202 +00:07:27,146 --> 00:07:29,079 +So you just set the gravity. +只要设置好重力 + +203 +00:07:29,080 --> 00:07:31,013 +Now any item you add will start accelerating in +任意的对象在这个方向上就有一个加速度 + +204 +00:07:31,016 --> 00:07:31,948 +that direction. + +205 +00:07:31,950 --> 00:07:33,500 +The instance you add it, +你添加的那个实例 + +206 +00:07:33,501 --> 00:07:35,051 +it's gonna start accelerating in that direction, +会在这个方向上有一个加速度 + +207 +00:07:35,053 --> 00:07:37,319 +just like gravity were pulling on it. +就好像重力正在拉它的样子 + +208 +00:07:37,321 --> 00:07:38,820 +'Kay? + +209 +00:07:38,822 --> 00:07:40,622 +Then there's attachment behaviors. +还有一些附属(attachment)行为的动画效果 + +210 +00:07:40,624 --> 00:07:43,891 +So attachments you can attach two items, or +对于附属行为,你可以添加两个对象 + +211 +00:07:43,893 --> 00:07:46,994 +you can attach an item to an anchor point. +或者将这两个对象添加到同一个锚点 + +212 +00:07:46,996 --> 00:07:49,163 +Okay? That item still going to be +明白了吗?这个东西仍旧会被其他的动作所影响 + +213 +00:07:49,165 --> 00:07:52,733 +affected by all the other behaviors like gravity, so +比如说重力 + +214 +00:07:52,735 --> 00:07:54,167 +if I attached a view. +但是,当我将一个视图,附属 + +215 +00:07:54,169 --> 00:07:56,235 +To an anchor point, like this. +到一个锚点,就像这样 + +216 +00:07:56,237 --> 00:07:57,970 +And there was gravity on the view. +由于这个视图上有重力的影响 + +217 +00:07:57,972 --> 00:07:59,805 +It would swing down like this and +它会像这样摆动下来 + +218 +00:07:59,807 --> 00:08:02,140 +stop if there was gravity down, right? +然后停止,就像重力的作用那样 + +219 +00:08:02,142 --> 00:08:03,408 +'Cuz the gravity would be pulling it down. +因为重力正在拉这个视图 + +220 +00:08:03,410 --> 00:08:05,243 +But the attachment would be holding onto it. +但是附属却是保持的效果 + +221 +00:08:05,245 --> 00:08:07,478 +Does that make sense? +我这么说能明白吗? + +222 +00:08:07,480 --> 00:08:08,846 +So the attachment basically. +所以说,附属的行为基本上是 + +223 +00:08:08,848 --> 00:08:10,814 +But it's like a bar that's attached. +好比附着在一个栏(bar)上 + +224 +00:08:10,816 --> 00:08:12,982 +That bar could be springy also. +这个栏是有弹性的 + +225 +00:08:12,984 --> 00:08:15,685 +So if it was a springy bar attachment, then the gravity +如果是附属在一个弹性的栏上,那么重力会把这个视图向下拉 + +226 +00:08:15,687 --> 00:08:18,087 +would pull it down, and it would spring like this. +然后这个视图会在栏附近弹来弹去 + +227 +00:08:19,090 --> 00:08:20,288 +So you can get a little springy and +你可以得到一个小小的弹性效果 + +228 +00:08:20,290 --> 00:08:24,292 +you can control the dampening and all that as well. +而且你可以控制这个弹性效果反馈的程度 + +229 +00:08:24,294 --> 00:08:25,893 +You can also control the distance between +同样可以控制这两个东西之间的距离 + +230 +00:08:25,895 --> 00:08:28,095 +those two things. + +231 +00:08:28,096 --> 00:08:30,296 +By the way, that distance is settable while it's animating, +顺便说一句,这个距离在进行动画的时候还是可以设置的 + +232 +00:08:30,299 --> 00:08:31,932 +so this thing might be pulling down and +比方说,这个东西正在被往下拉的时候 + +233 +00:08:31,934 --> 00:08:33,500 +you might be changing the length and +你改变了它的长度 + +234 +00:08:33,502 --> 00:08:34,901 +it might swing way down and +这样它就会向下摆动 + +235 +00:08:34,903 --> 00:08:36,635 +then you might pull it back up. +接着,你有可能向上拉动了一下,它就会向上摆动 + +236 +00:08:36,637 --> 00:08:38,404 +So you can control all this stuff. +你可以控制这一切 + +237 +00:08:38,406 --> 00:08:40,389 +All these things like that, +类似这样的东西 + +238 +00:08:40,390 --> 00:08:42,373 +even the anchor point can move while it's animating. +甚至说是,锚点在进行动画的时候都是可以被改变的 + +239 +00:08:42,376 --> 00:08:44,642 +And we're gonna actually do that in the demo. +我们会在 Demo 里实现一下 + +240 +00:08:44,644 --> 00:08:47,879 +So it's incredibly flexible what you can do when you +所以在动画进行的过程中 + +241 +00:08:47,881 --> 00:08:51,148 +can change the attributes of these behaviors on the fly, +这些属性都是非常自由可调节的 + +242 +00:08:51,150 --> 00:08:53,750 +while things are happening with gestures or whatever. +当涉及到手势或者其他类似的东西时 + +243 +00:08:55,620 --> 00:08:57,854 +Collision behavior is an awesome behavior. +碰撞效果就非常起作用了 + +244 +00:08:57,856 --> 00:08:59,588 +You're gonna use that very often. +你会在之后频繁地使用它 + +245 +00:09:01,058 --> 00:09:04,593 +It can basically control collisions between items. +它能够控制对象之间的碰撞 + +246 +00:09:04,595 --> 00:09:07,328 +And also, between items and a boundary. +还可以控制对象和一个边界之间的碰撞 + +247 +00:09:07,330 --> 00:09:09,197 +And you can set up as many boundaries as you want. +这里的意思是,你可以设置类似的多个边界 + +248 +00:09:09,199 --> 00:09:10,882 +So, for your assignment five, +所以,你们的作业五 + +249 +00:09:10,883 --> 00:09:12,566 +where you're gonna be doing this brickout game or +你会做一个叫 Brickout 或者是 Breakout 的游戏 + +250 +00:09:12,568 --> 00:09:13,734 +breakout game. + +251 +00:09:13,736 --> 00:09:15,669 +You're probably gonna wanna use boundaries for +你大概会为你的砖头用到边界这个属性 + +252 +00:09:15,671 --> 00:09:17,137 +all your bricks. + +253 +00:09:17,139 --> 00:09:19,706 +You're not gonna, they'll be UI views cuz you've got to +由于它们是 UIView,所以你需要手动绘制出它们 + +254 +00:09:19,708 --> 00:09:22,575 +draw them, but you won't be having those UI views +但是你不希望这些视图参与到碰撞效果之中去 + +255 +00:09:22,577 --> 00:09:25,244 +participate in the collisions, cuz then the bricks would +因为这些砖最后会相互之间飞来飞去,满屏幕都是 + +256 +00:09:25,246 --> 00:09:27,379 +start flying into each other, all over the place. + +257 +00:09:27,381 --> 00:09:29,981 +You just want them to kind of be fixed boundaries, so +你想要的,应该是一个固定的边界 + +258 +00:09:29,983 --> 00:09:31,215 +that when the ball hits them, +当球击中它们的时候 + +259 +00:09:31,217 --> 00:09:34,151 +then that view animates itself disappearing, okay? +某个砖的边界才会消失,然后触发碰撞效果,明白了吗? + +260 +00:09:35,454 --> 00:09:37,587 +So the way you set these boundaries, +所以你设置这些边界 + +261 +00:09:37,589 --> 00:09:39,088 +there's really two ways. +这里会有两个方法 + +262 +00:09:39,090 --> 00:09:43,759 +One is you can set a Bezier path, any Bezier path, and it +一个是,你可以设置一个 UIBezierPath,任意一种贝塞尔曲线 + +263 +00:09:43,761 --> 00:09:46,795 +will use that Bezier path as the outer edges of a boundary. +然后,它会使用这个贝塞尔曲线当作它的外部边界 + +264 +00:09:46,797 --> 00:09:48,513 +'Kay. +明白了吗? + +265 +00:09:48,514 --> 00:09:50,230 +It could be a rectangle or a circle, could be a line. +它可以是一个矩形或者是一个圆形,甚至是一条直线 + +266 +00:09:50,233 --> 00:09:53,067 +And you just, things that hit the line bounce off of it. +你只需要,当东西碰到它的时候,弹回去 + +267 +00:09:54,270 --> 00:09:57,171 +Or you can set this translatesReferenceBoundsInto- +或者你可以设置 translatesReferenceBoundsIntoBoundary + +268 +00:09:57,173 --> 00:10:00,307 +Boundary, set that to true, and then the outer edges +方法,设置它为真,然后 + +269 +00:10:00,309 --> 00:10:03,777 +of the animated reference view will be a boundary. +动画对象的所有的外边框,就会变成一个边界 + +270 +00:10:03,779 --> 00:10:05,712 +Now, you can't use that for your homework, +你在你的作业中不能使用它 + +271 +00:10:05,713 --> 00:10:07,646 +because of course, the bottom one has to fall through. +因为,最底下的那个砖必须是掉下来的 + +272 +00:10:07,649 --> 00:10:10,616 +If your bouncing ball gets past the paddle, it falls off. +如果你的球穿过去了,它会掉下来 + +273 +00:10:11,618 --> 00:10:13,051 +So you'll have to use lines. +这里你只能使用贝塞尔曲线中的线段 + +274 +00:10:13,053 --> 00:10:14,485 +Bezier curve that's line two, +线段的贝塞尔曲线 + +275 +00:10:14,487 --> 00:10:17,588 +line two, line two or whatever. + +276 +00:10:17,590 --> 00:10:19,523 +Okay? When you add a boundary +明白了吗?当你添加一个边界的时候 + +277 +00:10:19,525 --> 00:10:21,024 +you give it an identifier. +你要给它一个标识符 + +278 +00:10:21,026 --> 00:10:23,927 +Now, that identifier is an NSCopying. +这里的标识符是一个遵循 NSCopying 协议的对象 + +279 +00:10:23,929 --> 00:10:28,764 +So NSCopying is a protocol that is implemented by +NSCopying 是一个协议,被 NSString + +280 +00:10:28,766 --> 00:10:33,835 +NSString, NSNumber, +NSNumber 所实现的 + +281 +00:10:33,837 --> 00:10:36,538 +things like that, so that means String and +其他的类也可能实现了这个协议,但是这代表 + +282 +00:10:36,540 --> 00:10:39,840 +Int/Double also can be used as the identifier for a boundary. +String 类型和 Int/Double 类型都可以作用一个边界的标识符 + +283 +00:10:40,910 --> 00:10:44,177 +So when you hit a boundary you get this message. +当你触碰到一个边界的时候,你会得到这个消息 + +284 +00:10:44,179 --> 00:10:46,780 +You want to se yourself to be the UI collision behaviors +你想要在碰撞的行为中设置你自己为代理 + +285 +00:10:46,782 --> 00:10:48,832 +delegate. + +286 +00:10:48,833 --> 00:10:50,883 +And when a boundary is hit, it will send this message, +当一个边界被触及的时候,它会发送这个消息 + +287 +00:10:50,885 --> 00:10:52,418 +it actually has a few other messages, +事实上,还有另外一些消息代理可以发送的 + +288 +00:10:52,420 --> 00:10:55,954 +to its delegates saying, there was a collision +当一个对象和一个边界发生碰撞的时候 + +289 +00:10:55,956 --> 00:10:59,091 +between an item and a boundary or between two items. +或者是两个对象之间发生的时候 + +290 +00:10:59,093 --> 00:11:02,260 +And it's going to pass back that boundary identifier. +代理将会传递这个标识符 + +291 +00:11:02,262 --> 00:11:03,628 +You see that boundary identifier, so +你看到这里第三个参数了吗? + +292 +00:11:03,630 --> 00:11:04,962 +the third argument there in this +“边界的标识符”(BoundaryIdentifier) + +293 +00:11:04,964 --> 00:11:08,365 +method that it's gonna call in its delegate, and +它会在代理中去调用这个东西 + +294 +00:11:08,367 --> 00:11:11,468 +you have to cast that thing, cuz it'll be an NSCopying. +因为这是一个遵循 NSCopying 协议的对象,所以你需要做一个类型转换 + +295 +00:11:11,470 --> 00:11:13,403 +So you got to cast it to be a string or number or +所以你将它转换成一个字符串或者是一个数字 + +296 +00:11:13,405 --> 00:11:16,039 +whatever you put in, cast it to be that back. +这么说吧,你设置标识符的参数是什么类型的,这里你就转换成什么类型的 + +297 +00:11:16,041 --> 00:11:17,457 +Okay? +明白了吗? + +298 +00:11:17,458 --> 00:11:18,874 +So it's a little small thing to understand is that +这里你需要明白一点点类型转换的东西 + +299 +00:11:18,876 --> 00:11:20,576 +casting behavior. + +300 +00:11:20,578 --> 00:11:22,611 +Okay? + +301 +00:11:22,612 --> 00:11:24,645 +So that's simple collisions. +这是简单的碰撞效果 + +302 +00:11:26,449 --> 00:11:29,150 +The snap behavior is used a lot in UI. +在用户交互中,Snap 行为经常被使用到 + +303 +00:11:29,152 --> 00:11:31,185 +You won't be using this in your homework but +但是你在这个作业中并不会使用到它 + +304 +00:11:31,187 --> 00:11:33,437 +it's actually used a lot. +但在其他地方,它经常会被使用 + +305 +00:11:33,438 --> 00:11:35,688 +It's essentially, you could imagine that you set up four +而且是很基本的。 + +306 +00:11:35,691 --> 00:11:40,426 +springs on the corner of a view in a new location. +你可以想象,你在屏幕的四个角设置了弹性效果 + +307 +00:11:40,428 --> 00:11:43,662 +The thing will fly to that space +当这个对象移动到空间的另外一个位置的时候 + +308 +00:11:43,664 --> 00:11:45,597 +in the middle of the four springs and +发生了碰撞 + +309 +00:11:45,599 --> 00:11:47,833 +then the springs will kind of oscillate. +然后这个弹性效果就会触发类似于震荡一样的效果 + +310 +00:11:47,835 --> 00:11:49,134 +So snap behavior is basically, +举例说,Snap 行为 + +311 +00:11:49,136 --> 00:11:52,170 +move to here, with a little bit of oscillation. +移到某个地方,发生了碰撞 + +312 +00:11:52,172 --> 00:11:54,171 +Okay, boing, kind of snapping. +然后震荡。这就是 Snap 行为 + +313 +00:11:54,173 --> 00:11:55,456 +Okay, but +明白了吗? + +314 +00:11:55,457 --> 00:11:56,740 +snapping in a way that doesn't disconcert the user, +但是 Snap 行为在某种程度上说,它并不会让用户分心 + +315 +00:11:56,742 --> 00:11:59,026 +where things just like, moving. +因为东西就像,移动 + +316 +00:11:59,027 --> 00:12:01,311 +It flies across the screen, and then wiggles a little bit. +然后摇动了一下下 + +317 +00:12:01,313 --> 00:12:03,296 +So let the user know, +所以,用户知道 + +318 +00:12:03,297 --> 00:12:05,280 +there's a little thing just got positioned here. +东西已经到了这个位置了 + +319 +00:12:05,283 --> 00:12:07,850 +So, you just specify the point you want it to snap to, and +实现这个,你只需要指定你想要 Snap 到的点 + +320 +00:12:07,852 --> 00:12:10,519 +the item you want to snap, and it will zoom over there. +以及,哪个对象你想要产生 Snap 动作,就够了 + +321 +00:12:10,521 --> 00:12:13,489 +Okay, and you can control how much the springs spring. +同样你可以控制这个震荡的效果 + +322 +00:12:13,491 --> 00:12:15,857 +Is it a big movement or just kinda a small movement? +是一个比较大的振幅呢还是一个比较小的振幅 + +323 +00:12:15,859 --> 00:12:18,493 +You can control the damping with that +通过同样设置这里的 damping 属性 + +324 +00:12:18,495 --> 00:12:19,293 +property there, damping. + +325 +00:12:19,295 --> 00:12:22,329 +Then there's a push behavior. +另外,还有一个 Push 行为 + +326 +00:12:22,331 --> 00:12:26,900 +A push behavior means push on this thing in a certain +一个 Push 行为,代表的意思是,把这个东西推向一个特定的角度 + +327 +00:12:26,902 --> 00:12:31,437 +angle and magnitude, kind of like gravity. +或者是一个力度,有点类似于重力 + +328 +00:12:31,439 --> 00:12:32,738 +The big difference between push and +但是 Push 和重力效果最大的区别就是 + +329 +00:12:32,740 --> 00:12:34,440 +gravity, two differences. +两个地方 + +330 +00:12:34,442 --> 00:12:37,609 +One, a push can be a one time push, all right. +一个是,Push 行为可以是一个一次性的效果 + +331 +00:12:37,611 --> 00:12:41,413 +Just instantaneous push, or it can be a continuous push +也可以是一个持续性、连续的效果 + +332 +00:12:41,415 --> 00:12:44,048 +which is not like gravity cuz it's not accelerating. +不像重力的地方是,它并不会加速 + +333 +00:12:44,050 --> 00:12:46,584 +It's just a continuous velocity. +它是以一个恒定的速度 + +334 +00:12:46,586 --> 00:12:47,551 +Okay? You understand the difference +明白了吗? + +335 +00:12:47,553 --> 00:12:49,686 +between acceleration and velocity. +你明白加速度和速度之间的区别吗? + +336 +00:12:49,688 --> 00:12:52,789 +So push would be, if you had a continuous push it would be +如果你有一个持续性的 Push 行为 + +337 +00:12:52,791 --> 00:12:55,591 +a constant velocity. +那么被 Push 的对象会有一个恒定的速度 + +338 +00:12:55,593 --> 00:12:56,892 +Okay? + +339 +00:12:56,894 --> 00:12:59,962 +Now one thing about push behavior that's interesting is +另外一个关于 Push 行为的很有意思的事情是 + +340 +00:12:59,964 --> 00:13:02,764 +when you push, you add this behavior to your animator, +当你 Push 的时候,你把这个行为添加到你的动画器中 + +341 +00:13:02,766 --> 00:13:06,134 +it'll cause the items that are in it to be pushed. +它会影响所有被添加到这个动画器里的东西 + +342 +00:13:06,136 --> 00:13:07,902 +And then it just kind of sits around there. +然而它并没有任何实质性的功能 + +343 +00:13:07,904 --> 00:13:10,071 +Wasted if it's not a continuous push. +白白占用我们的资源,如果它不是一个持续性的 Push 行为的话 + +344 +00:13:10,073 --> 00:13:12,106 +And sits there, wasting memory. + +345 +00:13:12,107 --> 00:13:14,140 +And I'm going to talk about in a few slides how we can +我会在之后的一些幻灯片中谈到这个问题 + +346 +00:13:14,143 --> 00:13:15,575 +get that memory back. +如何拿回这些占用的资源 + +347 +00:13:15,577 --> 00:13:18,478 +Okay, and we'll have to do a little memory cycle +好的,这里我们还需要做一个小小的内存循环保护 + +348 +00:13:18,480 --> 00:13:20,297 +protection there. + +349 +00:13:20,298 --> 00:13:22,115 +Now, there's a special kind of behavior, +有一种非常特别的行为 + +350 +00:13:22,117 --> 00:13:23,783 +called a dynamic item behavior. +称作动态对象行为 + +351 +00:13:23,785 --> 00:13:26,118 +Don't be confused by dynamic behavior, +不要被动态行为(Dynamic Behavior)这个词所迷惑 + +352 +00:13:26,120 --> 00:13:28,286 +which is the super class of all behaviors. +这是所有行为的父类 + +353 +00:13:28,288 --> 00:13:29,854 +And dynamic item behavior, +动态行为 + +354 +00:13:29,856 --> 00:13:35,126 +which is a sub-class of UIDynamicBehavior. +本身是一个 UIDynamicBehavior 的子类 + +355 +00:13:35,128 --> 00:13:37,928 +Item behavior says how does this item or +对象行为描述了被添加这个行为的对象 + +356 +00:13:37,930 --> 00:13:39,830 +any of the items added to this behavior, +或者是一些对象是怎么样的 + +357 +00:13:39,832 --> 00:13:43,333 +how do they behave when other behaviors make them interact? +它们会和另外的一些行为如何交互 + +358 +00:13:43,335 --> 00:13:46,169 +So this is when something smashes into a wall in +举例来说,如果一个东西撞到一个墙上 + +359 +00:13:46,171 --> 00:13:50,973 +a collider, in a collision behavior, how springy is it? +这是一个碰撞效果,然而它的弹性程度是怎么样的? + +360 +00:13:50,975 --> 00:13:51,640 +Can it spin? +这个东西能够旋转吗? + +361 +00:13:52,642 --> 00:13:54,676 +Okay? + +362 +00:13:54,677 --> 00:13:56,711 +Or does it have to stay un-rotated? +或者说,它是不是应该保持角度不做旋转? + +363 +00:13:56,713 --> 00:13:58,446 +Those kind of things +如此如此的这一些东西 + +364 +00:13:58,447 --> 00:14:00,180 +are all specified by this UIDynamicItemBehavior. +都由这个 UIDynamicItemBehavior 所指定 + +365 +00:14:00,183 --> 00:14:02,049 +So very often you'll have a gravity behavior, +通常来说,你会有一个重力行为 + +366 +00:14:02,051 --> 00:14:03,016 +a collider behavior. +一个碰撞行为 + +367 +00:14:03,018 --> 00:14:04,217 +You'll also have a dynamic +你还会需要一个动态对象行为 + +368 +00:14:04,219 --> 00:14:06,886 +item behavior to describe how much springiness is. +来描述这个的弹性程度 + +369 +00:14:06,888 --> 00:14:08,254 +You can, it also does density, +你还可以描述密度 + +370 +00:14:08,256 --> 00:14:10,389 +resistance, other things I haven't mentioned here. +强度,或者另外一些这里我没有提及的东西 + +371 +00:14:10,391 --> 00:14:11,623 +You can look in the documentation. +都可以在文档里找到 + +372 +00:14:11,625 --> 00:14:14,225 +But it's kind of all the things you would expect if you +然而,当你需要一个物理引擎的时候,你才需要了解这些东西 + +373 +00:14:14,227 --> 00:14:16,928 +had a physics-based engine, you need to set the kind of +你需要设置所有这些属性 + +374 +00:14:16,930 --> 00:14:20,464 +attributes, the physical attributes of an item. +对象的物理属性 + +375 +00:14:20,466 --> 00:14:23,367 +This dynamic item behavior also can report to you +动态对象行为还可以告诉你 + +376 +00:14:23,369 --> 00:14:26,870 +the current linear velocity and +当前对象的线速度 + +377 +00:14:26,872 --> 00:14:29,472 +angular velocity of this item. +和角速度 + +378 +00:14:29,474 --> 00:14:31,140 +So at any time, if you want to know, +任意时刻都可以获取到 + +379 +00:14:31,142 --> 00:14:34,076 +how fast is this thing moving and in what direction? +这样你就可以知道这个东西移动多块、什么方向 + +380 +00:14:34,078 --> 00:14:35,411 +You can get its linear velocity. +通过获取其线速度 + +381 +00:14:35,413 --> 00:14:37,079 +Or if you want to know how fast is this thing is +而你可以知道这个东西是否在旋转 + +382 +00:14:37,081 --> 00:14:39,981 +spinning, if at all, you can get its angular velocity. +通过获取其角速度 + +383 +00:14:41,051 --> 00:14:45,285 +And you can also add velocity to it in a certain direction. +甚至说,你还可以在一个特定的方向上添加一个速度 + +384 +00:14:45,287 --> 00:14:46,820 +So if you had something that was moving, and +我们假想一下,你有一个正在移动的东西 + +385 +00:14:46,822 --> 00:14:48,621 +you wanted to stop it, you could. +你想让它停下,你可以添加一个反方向的速度 + +386 +00:14:48,623 --> 00:14:50,723 +And then if you wanted to continue, +如果你想要让停止的对象继续运动 + +387 +00:14:50,725 --> 00:14:52,158 +you could add the velocity back. +你把这个速度加回来 + +388 +00:14:53,160 --> 00:14:55,193 +Just saying is all. +就是如此 + +389 +00:14:55,195 --> 00:14:56,428 +Okay. +好的 + +390 +00:14:56,429 --> 00:14:57,662 +So that's a dynamic behavior. +这就是动态行为 + +391 +00:14:57,664 --> 00:14:59,330 +Now, that's dynamic item behavior. +现在,这是动态对象行为 + +392 +00:14:59,332 --> 00:15:00,965 +Now here's UIDynamicBehavior. +这里是 UIDynamicBehavior + +393 +00:15:00,967 --> 00:15:04,201 +This is the superclass of all of these behaviors. +是所有这些行为的父类 + +394 +00:15:04,203 --> 00:15:05,936 +And it's kind of an interesting superclass, +这是一个很有趣的父类 + +395 +00:15:05,938 --> 00:15:08,138 +because you can actually create a subclass. +因为,你可以创建一个其子类 + +396 +00:15:08,140 --> 00:15:10,773 +And in the invitation of the subclass you add +在创建的子类中,你可以添加子行为 + +397 +00:15:10,775 --> 00:15:12,942 +child behaviors, you add other behaviors so +你可以添加其他的行为 + +398 +00:15:12,944 --> 00:15:15,110 +you can have a composite behavior. +这样你就可以拥有一个复合行为 + +399 +00:15:15,112 --> 00:15:16,445 +This is very common to do. +这是非常常见的做法 + +400 +00:15:16,447 --> 00:15:18,297 +When you have three or +当在一个相同集合的对象中 + +401 +00:15:18,298 --> 00:15:20,148 +four different behaviors all working on the same set +你想对它们所有添加三个或者是四个的行为 + +402 +00:15:20,150 --> 00:15:20,782 +of items. + +403 +00:15:20,784 --> 00:15:22,667 +A lot of times, +经常 + +404 +00:15:22,668 --> 00:15:24,551 +you'll create a subclass in UI dynamic behavior, and in +你会选择创建一个 UIDynamicBehavior 的子类 + +405 +00:15:24,554 --> 00:15:28,088 +the init method, you'll call this method addChildBehavior, +在初始化方法中,你调用这个方法 addChildBehavior + +406 +00:15:28,090 --> 00:15:31,391 +and you'll add a gravity of collider, item behavior. +你可以添加一个重力、碰撞或者是动态对象行为 + +407 +00:15:31,393 --> 00:15:32,815 +You see what I mean? +你知道我的意思了吗? + +408 +00:15:32,816 --> 00:15:34,238 +You'll add them as child behaviors. +你可以将它们添加为子行为 + +409 +00:15:34,239 --> 00:15:35,661 +And now, this behavior will do all the things that those +现在,这个行为就达到所有你添加的行为的效果了 + +410 +00:15:35,664 --> 00:15:36,295 +behaviors did. + +411 +00:15:38,032 --> 00:15:39,181 +Okay? So, +明白了吗? + +412 +00:15:39,182 --> 00:15:40,331 +you'll have a kind of a big combined behavior. +所以,你会拥有一个非常庞大的行为 + +413 +00:15:40,334 --> 00:15:41,800 +And I'll do that in the demo, so +我会在 Demo 里演示一下 + +414 +00:15:41,802 --> 00:15:43,335 +you can see what that looks like. +你可以知道具体是怎么操作的 + +415 +00:15:43,337 --> 00:15:48,906 +All behaviors, know the dynamic animator they're in. +接下来,所有的行为 + +416 +00:15:48,908 --> 00:15:52,042 +And a behavior can only be in one dynamic animator at +一次只能在一个动画器中 + +417 +00:15:52,044 --> 00:15:53,644 +a time. + +418 +00:15:53,645 --> 00:15:55,245 +So it has a property called dynamicAnimator. +这里有一个称作 dynamicAnimator 的属性 + +419 +00:15:55,247 --> 00:15:56,646 +And it's read-only. +只读的 + +420 +00:15:56,648 --> 00:15:58,381 +And it will tell you. +它会告诉你这些 + +421 +00:15:58,383 --> 00:16:01,250 +You can ask a collider who's animating +你可以询问一个碰撞行为谁正在进行动画效果 + +422 +00:16:01,252 --> 00:16:03,919 +right now, and it will tell you that the dynamicAnimator +它会返回给你正在动画的 dynamicAnimator + +423 +00:16:03,921 --> 00:16:05,020 +is animating it. + +424 +00:16:05,022 --> 00:16:08,123 +Also, all dynamic behaviors will be sent +同样,当所有的动态行为被移动到另外一个不同的动画器中 + +425 +00:16:08,125 --> 00:16:10,625 +the message will be moved to animator +它们将会发送一个消息 + +426 +00:16:10,627 --> 00:16:13,060 +when they are going to switch to a different animator. +willMovedToAnimator + +427 +00:16:13,062 --> 00:16:15,696 +Especially this is switching form not having an animator +尤其是从没有动画器中切换到有动画器的时候 + +428 +00:16:15,698 --> 00:16:16,763 +to having one. + +429 +00:16:16,765 --> 00:16:19,632 +Or from having one to not having one anymore. +或者是从有动画器中切换到没有动画器的时候 + +430 +00:16:19,634 --> 00:16:21,067 +Okay? +明白了吗? + +431 +00:16:21,069 --> 00:16:23,269 +That should be UIDynamicAnimator, +这里会有一个问号,所以是一个可选类型的 + +432 +00:16:23,271 --> 00:16:25,404 +question mark, that's an optional. +UIDynamicAnimator + +433 +00:16:25,406 --> 00:16:27,172 +Okay? Cuz it might be said, +明白了吗?因为我们可能会这么调用 + +434 +00:16:27,174 --> 00:16:29,074 +will move to animator nil, +willMoveToAnimator(nil) + +435 +00:16:29,076 --> 00:16:32,710 +which means you're being taken out of an animator. +也就是说,我们从一个动画器中移除它 + +436 +00:16:32,712 --> 00:16:36,847 +Okay, very important property on UIDynamicBehavior called +在 UIDynamicBehavior 里,有一个非常重要的属性叫 + +437 +00:16:36,849 --> 00:16:38,281 +action. +action + +438 +00:16:38,283 --> 00:16:41,818 +Action is a function, takes no arguments, returns nothing. +action 是一个没有参数的函数,并且不返回值 + +439 +00:16:41,820 --> 00:16:46,722 +99.999% of the time it's set with a closure, okay? +99.999% 的情况下,它通过一个闭包来设值 + +440 +00:16:46,724 --> 00:16:50,492 +And this piece of code will be executed every time this +然后,每次这个行为发生在其对象上的时候 + +441 +00:16:50,494 --> 00:16:54,562 +behavior acts upon its items. +这一小段代码都会执行 + +442 +00:16:54,564 --> 00:16:55,813 +'Kay? + +443 +00:16:55,814 --> 00:16:57,063 +That means it's called a lot. +这代表,这个方法会被多次调用 + +444 +00:16:57,066 --> 00:16:58,365 +Okay? +明白了吗? + +445 +00:16:58,367 --> 00:17:00,467 +Imagine a gravity behavior, +想象一个重力行为 + +446 +00:17:00,469 --> 00:17:03,737 +it's constantly accelerating something. +它以一个恒定的加速度在加速一个对象 + +447 +00:17:03,739 --> 00:17:05,371 +So it's constantly acting upon it. +也就是说它持续地 “act” + +448 +00:17:05,373 --> 00:17:07,573 +So it's constantly gonna be calling this. +所以它持续地调用这个方法 + +449 +00:17:07,575 --> 00:17:09,475 +So whatever code you put here, +无论你放在闭包里是什么样的代码,它都会持续调用 + +450 +00:17:09,477 --> 00:17:12,778 +an action wants to be really efficient, okay? +一个 action 要做到非常高效 + +451 +00:17:12,780 --> 00:17:15,246 +It wants to be very small, very compact. +同时长度需要非常短小精悍 + +452 +00:17:15,248 --> 00:17:17,348 +This is a place to do some optimization, +这里是需要做一些优化的 + +453 +00:17:17,350 --> 00:17:19,216 +have a data structure where you can store things, so +比如用一个数据结构去保存一些参数 + +454 +00:17:19,218 --> 00:17:20,517 +you don't have to calculate things so much. +以至于你不需要重新计算它们 + +455 +00:17:20,519 --> 00:17:22,686 +Cuz this is going to get called a lot, all right? +因为切记,这会被多次调用 + +456 +00:17:22,688 --> 00:17:24,254 +And you'll want your animations to be smooth, +你想要你的动画效果非常的顺畅 + +457 +00:17:24,256 --> 00:17:27,090 +you don't want them to be bogged down with something +你不希望它们在每一次交互的时候 + +458 +00:17:27,092 --> 00:17:30,192 +heavy going on every single time it interacts, okay? +都进行大量的运算,然后卡住不动了 + +459 +00:17:31,762 --> 00:17:35,130 +One thing to be careful about this action method, +关于 action 方法需要非常小心的一点是 + +460 +00:17:35,132 --> 00:17:38,299 +is that it is a property on the behavior, so +这是行为上的一个属性 + +461 +00:17:38,301 --> 00:17:41,135 +if that action method's code refers to the behavior, +所以如果 action 的代码里参考了这个行为的话 + +462 +00:17:41,137 --> 00:17:43,437 +you're going to have a memory cycle, and +你会形成一个 retain cycle + +463 +00:17:43,439 --> 00:17:46,173 +so you need to do that unowned thing, +你需要将参考的类型编程 unowned + +464 +00:17:46,175 --> 00:17:49,743 +the capture list that we were taking about. +我们在捕获列表里讨论过这个 + +465 +00:17:49,745 --> 00:17:52,945 +You have to do that to break the memory cycle, this is +你需要用捕获列表打破 retain cycle + +466 +00:17:52,947 --> 00:17:55,748 +the case where you've got a property on an object and +这个技术通常是用于,当你对一个对象中有一个属性的时候 + +467 +00:17:55,750 --> 00:17:58,050 +the implementation of the closure that you assign often +而且你对这个属性赋值一个闭包,这个闭包的实现中你通常 + +468 +00:17:58,052 --> 00:18:00,218 +refers back to the property. +又参考这个属性本身 + +469 +00:18:00,220 --> 00:18:01,686 +To the thing that the property is on, + + +470 +00:18:01,688 --> 00:18:03,121 +so be careful about that, +所以对这个小心点 + +471 +00:18:03,123 --> 00:18:07,591 +let me show you a quick demo about that in a slide or two. +这个我稍后会快速做一个 Demo 给你们了解一下 + +472 +00:18:07,593 --> 00:18:10,327 +The UIDynamicAnimator, it also has a delegate. +UIDynamicAnimator 同时拥有一个代理对象 + +473 +00:18:10,329 --> 00:18:11,461 +Just like the CollisionBehavior +就像碰撞行为一样 + +474 +00:18:11,463 --> 00:18:13,796 +has a delegate, the animator has a delegate, and +动画器有一个代理对象 + +475 +00:18:13,798 --> 00:18:15,264 +it'll tell you only two things. +它会告诉你两件事情 + +476 +00:18:15,266 --> 00:18:19,068 +It'll tell you when the animation has reached stasis. +首先,它会告诉你动画器是否已经停止 + +477 +00:18:19,070 --> 00:18:23,505 +In other words, none of the behaviors need to do anything. +换言之,没有另外的行为会继续产生了 + +478 +00:18:23,507 --> 00:18:24,606 +Okay? +明白了吗? + +479 +00:18:24,607 --> 00:18:25,706 +Nothing is happening in the animator. +没有东西会在动画器中发生了 + +480 +00:18:25,709 --> 00:18:27,608 +Everything is still, and +所有的对象都是出于静止的状态 + +481 +00:18:27,610 --> 00:18:30,210 +then it'll tell you when that's changed. +同样的,当这些改变的时候,它同样会告诉你 + +482 +00:18:30,212 --> 00:18:30,911 +Okay? And now, things +当它告诉你的时候 + +483 +00:18:30,913 --> 00:18:32,279 +are animating again. +这代表,对象又动起来了 + +484 +00:18:32,280 --> 00:18:33,646 +So every time it pauses, it'll tell you. +所以,每一次动画暂停的时候,它都会告诉你 + +485 +00:18:33,648 --> 00:18:35,782 +And then, every time it continues, it'll tell you. +每一次动画继续的时候,它也会告诉你 + +486 +00:18:35,784 --> 00:18:37,717 +So that way you can tell what's going on. +通过这种方式,你能知道正在发生什么事情 + +487 +00:18:39,854 --> 00:18:43,155 +When you design something that uses this stuff is, +当你设计利用这个功能的时候 + +488 +00:18:43,157 --> 00:18:45,557 +you want it to reach stasis. +你想要它停止 + +489 +00:18:45,559 --> 00:18:47,492 +You don't ever want it to be just constantly +你不想要它始终在动画 + +490 +00:18:47,494 --> 00:18:49,344 +animating, right? +对吧? + +491 +00:18:49,345 --> 00:18:51,195 +You want it to try and reach stasis, if possible. +你想要它在可能的情况下,达到静止状态 + +492 +00:18:51,197 --> 00:18:53,130 +'Kay, now there might be cases where you actually +另外,还有一种情况,这种情况下 + +493 +00:18:53,132 --> 00:18:55,732 +are constantly animating, something's spinning, and +你想要你的动画是持续性的,就像什么东西旋转一样 + +494 +00:18:55,734 --> 00:18:57,534 +it's constantly spinning. +你希望它一直保持旋转 + +495 +00:18:57,536 --> 00:19:01,704 +Okay, but you wanna design the system, unless that's really +你想要设计这个系统,除非你执意不要 + +496 +00:19:01,706 --> 00:19:05,574 +what you intend, you don't want things, classic one is. +不想要这些东西,你想用一个比较传统的做法 + +497 +00:19:05,576 --> 00:19:07,476 +You have something with CollisionBehaviors. +你有一些个碰撞效果 + +498 +00:19:07,478 --> 00:19:10,779 +The thing flies off screen outside of the collision area, +当对象越过屏幕边缘,越过碰撞区域的时候 + +499 +00:19:10,781 --> 00:19:13,982 +and then now it's flying off into outer space, and +他向外层的空间飞过去 + +500 +00:19:13,984 --> 00:19:16,417 +it's gonna continue to animate forever +它会持续动画,直到它飞过上千万的 point + +501 +00:19:16,419 --> 00:19:19,553 +as it flies billions of points away, okay. + +502 +00:19:19,555 --> 00:19:22,189 +It's never gonna stop, so you got to be careful about that. +它永远不会停止,这是你需要关心的情况 + +503 +00:19:22,191 --> 00:19:25,525 +When things go outside of the area that you're animating, +当对象在你动画区域之外发生的时候 + +504 +00:19:25,527 --> 00:19:27,127 +they don't stop animating. +它们并不会停止动画 + +505 +00:19:27,129 --> 00:19:29,195 +You need to notice that and +你需要注意到这个问题 + +506 +00:19:29,197 --> 00:19:32,064 +take that thing out of the behaviors, so that they're no +然后你需要从这些对象上移除这些行为 + +507 +00:19:32,066 --> 00:19:35,300 +longer being accelerated off into nowhere or whatever. +好让它们不再被持续加速了 + +508 +00:19:35,302 --> 00:19:36,134 +Okay? +明白了吗? + +509 +00:19:36,135 --> 00:19:36,967 +So be careful about that. +所以关心一下这个点 + +510 +00:19:36,970 --> 00:19:38,536 +That can happen in your assignment, of course. +在你们的作业中可能会发生这样的事情 + +511 +00:19:38,538 --> 00:19:41,239 +Because the bouncing ball goes off the bottom, +因为当一个弹性的小球越过底部的时候 + +512 +00:19:41,241 --> 00:19:42,457 +it'll just keep going. +它就会一直保持动画 + +513 +00:19:42,458 --> 00:19:43,674 +Okay? Keep getting animated and +一直一直 + +514 +00:19:43,676 --> 00:19:45,209 +never reach stasis. +永远不会达到一个停止的状态 + +515 +00:19:45,211 --> 00:19:47,010 +Unless you notice that and +除非你意识到这个问题 + +516 +00:19:47,012 --> 00:19:49,079 +take the ball out of the view hierarchy probably. +并且将小球从视图体系中移走 + +517 +00:19:49,081 --> 00:19:50,780 +And also away from the behaviors. +同样也从行为中移走 + +518 +00:19:51,883 --> 00:19:55,651 +By the way, don't ever put a view into a behavior, +这里我想另外说一句,永远不要将一个视图放在一个行为中 + +519 +00:19:55,653 --> 00:19:59,254 +okay, when that view is not on the view hierarchy +好的,当一个视图不在动画器的参考视图的视图体系中 +520 +00:19:59,256 --> 00:20:01,856 +of the reference view of the animator. + +521 +00:20:01,858 --> 00:20:04,292 +Obviously, the animator wants to animate the thing, and +很明显的,动画器想要让某个对象动起来 + +522 +00:20:04,294 --> 00:20:06,927 +if it's not in its view hierarchy, like it's in any +如果某个对象不在它的视图体系中 + +523 +00:20:06,929 --> 00:20:08,362 +view hierarchy or it's in a different one, +比如某个对象在不同的一个视图体系中 + +524 +00:20:08,364 --> 00:20:10,664 +the animator will basically crash your program and +这个动画器就会使你的程序崩溃 + +525 +00:20:10,666 --> 00:20:11,731 +I tried to animated something, +永远不要对不在你的视图体系中的对象进行动画操作 + +526 +00:20:11,733 --> 00:20:13,099 +it's not in my view hierarchy anywhere. + +527 +00:20:14,135 --> 00:20:16,051 +So don't do that. +不要这么做 + +528 +00:20:16,052 --> 00:20:17,968 +Also, don't animate things that are size 00. +同样,不要对一个大小为 (0,0) 的对象动画 + +529 +00:20:19,139 --> 00:20:20,216 +Okay. +明白了吗? + +530 +00:20:20,217 --> 00:20:21,294 +It really doesn't make and +这么做非常的不合理 + +531 +00:20:21,295 --> 00:20:22,372 +sense to do that because it's not visible anyway, +因为它并不是一个可见的对象 + +532 +00:20:22,375 --> 00:20:23,607 +but don't do that. +所以不要尝试这么做 + +533 +00:20:23,609 --> 00:20:24,641 +Animator doesn't like that either. +动画器也是如此 + +534 +00:20:25,844 --> 00:20:29,279 +All right, quick sample here of memory cycle avoidance. +好的,另外这里有一个 retain cycle 的样例 + +535 +00:20:29,281 --> 00:20:31,647 +I was talking about that action method. +还记得我之前讲过的 action 方法吗? + +536 +00:20:31,649 --> 00:20:34,016 +So here, I'm creating a pushBehavior, and +这里,我创建一个 Push 行为 + +537 +00:20:34,018 --> 00:20:35,217 +I told you the pushBehavior, +我之前说过 + +538 +00:20:35,219 --> 00:20:37,886 +if it's instantaneous, it just sits around. +如果不是持续性的话会没有任何的效果 + +539 +00:20:37,888 --> 00:20:39,587 +Because the way you make a push happen is +你真正实现一个 Push 动画应该是 + +540 +00:20:39,589 --> 00:20:42,123 +you create a pushBehavior, and you add it to an animator. +创建一个 Push 行为,然后添加到一个动画器 + +541 +00:20:42,125 --> 00:20:45,626 +As soon as you add it, it's gonna push any of its items. +只要你一添加,它就会推动任何一个对象 + +542 +00:20:45,628 --> 00:20:47,478 +Okay? +明白了吗? + +543 +00:20:47,479 --> 00:20:49,329 +Well, after it's done, if it's an instantaneous push, not +如果这个动画完成的话,如果这不是一个持续性的 Push + +544 +00:20:49,331 --> 00:20:51,631 +continuous, but instantaneous, well, it just sits there. +这些东西就会停止 + +545 +00:20:51,633 --> 00:20:53,266 +Cuz it's been added to the animator. +但是由于 Push 行为被添加到了一个动画器 + +546 +00:20:53,268 --> 00:20:54,767 +So it's just wasting space. +所以它只会白白浪费空间 + +547 +00:20:54,769 --> 00:20:58,237 +So one of the way you can do this is in the pushBehavior's +有一个方法可以让你在 Push 行为中的 action 方法做的 + +548 +00:20:58,239 --> 00:21:01,139 +action, which I told you is called whenever the behavior +换言之,也就是每次这个行为在一个对象上被调用的时候 + +549 +00:21:01,141 --> 00:21:02,707 +acts on something. + +550 +00:21:02,709 --> 00:21:06,144 +So after the pushBehavior acts and instantaneously pushes, +所以当一个 Push 行为非持续性推动的时候 + +551 +00:21:06,146 --> 00:21:09,280 +well, you could just remove the thing from its animator. +你将它从一个动画器中移除 + +552 +00:21:09,282 --> 00:21:11,782 +And I told you every behavior knows the animator it's in, so +我告诉过你,每一个行为都知道它属于哪个动画器 + +553 +00:21:11,784 --> 00:21:13,417 +that's easy you can just do that one +所以这里并不难做到 + +554 +00:21:13,419 --> 00:21:16,119 +line of code in yellow there, pushBehavior, dynamicAnimator, +这里黄色行的代码,pushBehavior.dynamicAnimator! + +555 +00:21:16,121 --> 00:21:19,255 +removeBehavior, pushBehavior myself, okay. +pushBehavior.dynamicAnimator!.removeBehavior(pushBehavior) + +556 +00:21:19,257 --> 00:21:22,658 +But in that closure, I'm referring to myself, +在这个闭包中参考了对象自身 + +557 +00:21:22,660 --> 00:21:25,327 +pushBehavior because removing myself, okay. +即 pushBehavior + +558 +00:21:25,329 --> 00:21:27,329 +I'm also referring to myself because I'm getting my +另外我参考自身是因为我正在获取我自己的 dynamicAnimator + +559 +00:21:27,331 --> 00:21:29,130 +own dynamicAnimator. + +560 +00:21:29,132 --> 00:21:30,765 +So this is bad. +这样做是很糟的 + +561 +00:21:30,766 --> 00:21:32,399 +This is gonna cause a memory cycle here because +这会在闭包中产生一个 retain cycle + +562 +00:21:32,402 --> 00:21:34,235 +that action closure. + +563 +00:21:34,237 --> 00:21:36,470 +Right? It is gonna stay in memory, +对吗?它会一直呆在内存里 + +564 +00:21:36,472 --> 00:21:39,439 +because the action property is pointing to it. +因为 action 属性指向了它 + +565 +00:21:39,441 --> 00:21:41,808 +And this push behavior is gonna stay in memory, +另外这个 Push 行为也会保留在内存中 + +566 +00:21:41,810 --> 00:21:43,843 +because that closure is pointing to it. +因为这个闭包正在指向它 + +567 +00:21:43,845 --> 00:21:46,379 +So since they're both pointing to each other, +当它们两个互相引用的时候 + +568 +00:21:46,381 --> 00:21:47,780 +there's always gonna be a pointer to them. +它们之间始终有一个指针指向对方 + +569 +00:21:47,782 --> 00:21:49,748 +They'll always stay in memory forever. +所以它们就会永远呆在内存中了 + +570 +00:21:49,750 --> 00:21:52,017 +And I mean forever and ever. +注意我这里用的词是“永远” + +571 +00:21:52,019 --> 00:21:53,017 +Okay? If you can't, +明白了吗? + +572 +00:21:53,019 --> 00:21:54,318 +no way to get rid of them. +没有打破这个循环引用关系的方式 + +573 +00:21:54,320 --> 00:21:55,552 +So how do we fix that? +如何修复这个问题? + +574 +00:21:55,554 --> 00:21:57,387 +We put that unowned in there. +我们在这里写上 unowned + +575 +00:21:57,389 --> 00:22:00,323 +So we put this capture list here, say that pushBehavior +我们在这里放置一个捕获列表 + +576 +00:22:00,325 --> 00:22:04,627 +inside my closure is unowned, meaning don't capture it. +表示,Push 行为在我的闭包中是不会被强引用的,所以不要捕获它 + +577 +00:22:04,629 --> 00:22:07,596 +I promise that it will be there when you want to use it, +“我保证这个指针在你想使用的时候都是有效且存在的” + +578 +00:22:07,598 --> 00:22:08,930 +Mr. Closure says. +Mr. 闭包这么说 + +579 +00:22:08,932 --> 00:22:11,800 +You do not have to capture it and keep it in memory. +你不需要捕获并在内存中保存它 + +580 +00:22:11,802 --> 00:22:13,518 +Okay? And we know that's fine. +明白了吗?我们只要知道这么做没问题 + +581 +00:22:13,519 --> 00:22:15,235 +Because obviously, the action wouldn't even be called if +因为很明显的,如果视图的 Push 行为都不存在的时候 + +582 +00:22:15,238 --> 00:22:16,604 +the view's pushBehavior didn't exist. +action 永远不会被调用 + +583 +00:22:16,606 --> 00:22:17,971 +So this is good. +这就很不错 + +584 +00:22:17,973 --> 00:22:19,006 +This code's for sure going to work. +这段代码肯定能正常运行 + +585 +00:22:20,175 --> 00:22:21,274 +Okay? You have to do this a lot +你将来会在 action 中经常这么做 + +586 +00:22:21,276 --> 00:22:22,408 +with actions. + +587 +00:22:22,409 --> 00:22:23,541 +And you'll probably have to do this in your assignment, +另外你们可能会在你们的作业中会用到这个 + +588 +00:22:23,544 --> 00:22:25,277 +when you use an action. + +589 +00:22:25,279 --> 00:22:27,446 +Okay? And I encourage you to try and +我鼓励你去尝试 + +590 +00:22:27,448 --> 00:22:29,080 +make your pushBehavior do this as well. +并让你的 Push 行为这么做 + +591 +00:22:29,082 --> 00:22:31,849 +It's not a required task, but get your pushBehavior to clean +这不是一个必需的要求,但是这可以让你的 Push 行为 + +592 +00:22:31,851 --> 00:22:33,517 +itself up after it's done pushing. +在完成它的使命之后自己清理干净自己 + +593 +00:22:34,920 --> 00:22:36,053 +All right, so let's do this demo. +好的,让我们开始 Demo + +594 +00:22:39,458 --> 00:22:40,623 +Any questions about all that? +对以上的东西还有什么疑问吗? + +595 +00:22:41,726 --> 00:22:43,359 +Again, feel free to interrupt me. +再说一遍,请不要害怕打断我,勇敢提出问题 + +596 +00:22:43,361 --> 00:22:46,561 +Coming up this week, Friday, we're going to learn +这个周五,我们想要 + +597 +00:22:46,563 --> 00:22:49,064 +about the Parse framework, which is a way to +学习解析框架 + +598 +00:22:49,066 --> 00:22:51,132 +basically store your data on the network. +这是你处理网络数据的基础 + +599 +00:22:52,769 --> 00:22:55,302 +So for if you're building some sort of final project, or +如果你已经在着手做大作业了 + +600 +00:22:55,304 --> 00:22:57,504 +you wanna back end or something, +或者需要后端处理 + +601 +00:22:57,506 --> 00:23:02,975 +Parse is really simple, nice asynchronous using blocks. +Parse 是一个非常简单的,使用异步 block + +602 +00:23:02,977 --> 00:23:04,944 +Closure's a way to do that. +方式处理的 + +603 +00:23:04,946 --> 00:23:06,011 +And then next week, +下一周 + +604 +00:23:06,013 --> 00:23:07,813 +we're gonna talk about a variety of topics. +我们将讨论多个问题 + +605 +00:23:07,815 --> 00:23:10,382 +We're finally gonna talk about modal segue way a little bit +最后会讨论些模态的 segue + +606 +00:23:10,384 --> 00:23:11,916 +and the application life cycle. +还有应用程序生命周期 + +607 +00:23:12,919 --> 00:23:15,252 +And core motion, +还有 Core Motion + +608 +00:23:15,253 --> 00:23:17,586 +which is the gyro and accelerometer and that stuff. +陀螺仪,加速器之类的东西 + +609 +00:23:18,890 --> 00:23:19,455 +Okay? + +610 +00:23:19,457 --> 00:23:22,892 +I believe we'll have just enough time for this demo. +我认为剩下的时间够做这个 demo + +611 +00:23:22,894 --> 00:23:27,329 +If I run a little long, you guys know what to do. +如果我时间花得久了些,你们知道该怎么做 + +612 +00:23:27,331 --> 00:23:29,330 +So let's start here. +从这开始 + +613 +00:23:29,332 --> 00:23:30,465 +Create new project. +创建一个新工程 + +614 +00:23:31,467 --> 00:23:33,634 +We always use single view in this class, +单视图应用 + +615 +00:23:33,636 --> 00:23:34,868 +we'll call it DropIt. +起名为 DropIt + +616 +00:23:34,870 --> 00:23:36,202 +We're dropping some things. +我们将会往下掉落些东西 + +617 +00:23:36,204 --> 00:23:38,838 +I'll put it in the same place we always put it. +把它放在这里 + +618 +00:23:38,840 --> 00:23:41,974 +Here we go. +好了 + +619 +00:23:41,975 --> 00:23:45,109 +Now I'm going to clean up this stuff. +把工程清理一下 + +620 +00:23:45,112 --> 00:23:47,979 +Okay, I don't need this view controller, I'm going to have +我不需要这个视图控制器 + +621 +00:23:47,981 --> 00:23:50,615 +a custom view controller, we're not gonna use the one. +我需要一个自定义的 + +622 +00:23:50,617 --> 00:23:52,216 +I don't like the name of this, I'm not gonna use. +我不喜欢这个名字 + +623 +00:23:52,218 --> 00:23:55,319 +This one. +我不会用这个 + +624 +00:23:55,320 --> 00:23:58,421 +My story board right here, I'm going to right off +这个是 StoryBoard + +625 +00:23:58,424 --> 00:24:04,127 +the bat create a new subclass for my view controller. +我现在新建一个视图控制器的子类 + +626 +00:24:04,129 --> 00:24:05,995 +So it's going to be a UIViewController. +类型是 UIViewController + +627 +00:24:05,997 --> 00:24:08,630 +I'm gonna call it DropitViewController. +起名为 DropitViewController + +628 +00:24:10,934 --> 00:24:12,434 +Probably could have renamed that other thing. +应该给它起个更好听的名字 + +629 +00:24:12,436 --> 00:24:14,569 +It probably would have been just as good. +不过这个也行 + +630 +00:24:14,571 --> 00:24:16,037 +So here's Dropit. +好了 + +631 +00:24:16,039 --> 00:24:19,907 +I'm gonna get rid of all this in here. +把这些去掉 + +632 +00:24:19,909 --> 00:24:25,879 +In my storyboard, let's set the class here to be Dropit. +在 storyboard 中,把类设置为 Dropit + +633 +00:24:25,881 --> 00:24:29,282 +The only UI that my Dropit is gonna have is a custom view, +在 Dropit 中唯一的 UI 会是一个自定义视图 + +634 +00:24:29,284 --> 00:24:32,685 +and actually, I'm gonna start out with a generic view. +我先创建一个一般的视图 + +635 +00:24:32,687 --> 00:24:34,853 +In your homework assignments, you might be able to get away, +在作业里你们可能会用别的方式 + +636 +00:24:34,855 --> 00:24:37,356 +depending on how you architect things, with the generic +取决于你们怎样通过一般的视图来包含砖块还有球 + +637 +00:24:37,358 --> 00:24:41,359 +view here to contain your bricks and bouncing ball. +来搭建界面 + +638 +00:24:41,361 --> 00:24:43,444 +So I'm going to have this. +所以我使用一般视图 + +639 +00:24:43,445 --> 00:24:45,528 +I'm gonna make sure that my constraints are set here. +设置一下约束 + +640 +00:24:45,531 --> 00:24:48,832 +So let's Reset to Suggested Constraints. +使用建议的约束 + +641 +00:24:48,834 --> 00:24:50,250 +I always like to check them, +在这里检查一下 + +642 +00:24:50,251 --> 00:24:51,667 +make sure there's no magic numbers or anything. +确保没有任何魔法数字 + +643 +00:24:51,670 --> 00:24:53,336 +That all looks good to me. +看起来还可以 + +644 +00:24:53,338 --> 00:24:58,574 +I'm gonna create a outlet to this thing, right there. +为它创建 outlet + +645 +00:24:58,576 --> 00:25:01,910 +I'm gonna call that my game view, so this is going to be +把它叫做 gameView + +646 +00:25:01,912 --> 00:25:04,746 +the view that contains my little Dropit game. +这就是包含 Dropit 这个小游戏的 View + +647 +00:25:04,748 --> 00:25:08,049 +It's not much of a game, but kind of a game. +算不上游戏,但也有点游戏的意思 + +648 +00:25:08,051 --> 00:25:09,450 +All right, so there we go. +好的 + +649 +00:25:09,452 --> 00:25:12,653 +So, what is my Dropit going to do here? +Dropit 将要做些什么呢 + +650 +00:25:12,655 --> 00:25:18,191 +It's going to, along the top of my view, I'm +在视图的顶部 + +651 +00:25:18,193 --> 00:25:22,062 +going to drop little squares, okay, right along the top. +我会向下掉落小方块 + +652 +00:25:22,064 --> 00:25:23,896 +So first let's just get them dropped along the top. +所以首先,先让它从顶部掉落砖块 + +653 +00:25:23,898 --> 00:25:26,365 +And then I'm going to add some gravity, and +为它们添加重力效果 + +654 +00:25:26,367 --> 00:25:28,267 +they're going to drop and fall. +让它们掉落下来 + +655 +00:25:28,269 --> 00:25:29,034 +Okay? That's why + +656 +00:25:29,036 --> 00:25:29,768 +they're called drops. +这就是起名为 drops 的原因 + +657 +00:25:29,770 --> 00:25:31,236 +They're going to fall down. +它们将会掉落 + +658 +00:25:31,237 --> 00:25:32,703 +So I'm gonna put these drops along the top, and +先让它们在顶部显示 + +659 +00:25:32,706 --> 00:25:34,672 +then later we'll add some gravity. +随后添加重力效果 + +660 +00:25:34,674 --> 00:25:38,842 +So let's go ahead and do the, putting them along the top +现在开始做这些 + +661 +00:25:38,844 --> 00:25:42,545 +first, pretty straightforward to do. +把它们放到上边 + +662 +00:25:42,547 --> 00:25:47,149 +So, I'm going to have the drops be evenly spaced along +现在开始设置方块的尺寸之类的 + +663 +00:25:47,151 --> 00:25:50,019 +the top, and I'm going to have a public variable, or +我设置一个公有变量 + +664 +00:25:50,021 --> 00:25:53,255 +whatever you want to call it, called dropsPerRow. +起名为 dropsPerRow + +665 +00:25:54,257 --> 00:25:56,557 +It's just gonna be an integer that says how many of these +是一个整型的 + +666 +00:25:56,559 --> 00:25:58,059 +little squares go across the top. +表示在顶部有多少方块 + +667 +00:25:58,061 --> 00:26:00,227 +And so I'll do ten but I can set it to whatever I want. +先设置为10,也可以设置为任何数值 + +668 +00:26:00,229 --> 00:26:01,762 +I like my UI to be configurable. +我希望我的 UI 是可以调整的 + +669 +00:26:01,764 --> 00:26:04,497 +Of course in your homework you're gonna want that because +在你们的作业里,你们也得这么做 + +670 +00:26:04,499 --> 00:26:06,966 +part of your homework is to add a settings panel, but +因为因为需要一个设置界面 + +671 +00:26:06,968 --> 00:26:08,768 +you set a lot of configurable things. +设置一些可以调整的东西 + +672 +00:26:08,770 --> 00:26:11,437 +So you want to design your code to not be hard-coded all +你不能一直把代码写得这么死 + +673 +00:26:11,439 --> 00:26:13,122 +the time. + +674 +00:26:13,123 --> 00:26:14,806 +So here I'm going to make this to be number I can set. +所以在这里我把它调整一个可以设置的数 + +675 +00:26:14,808 --> 00:26:18,276 +And that lets me have a drop size, okay, +再来一个变量,dropSize + +676 +00:26:18,278 --> 00:26:21,045 +which is going to be the size of each drop. +是每一个方块的尺寸 + +677 +00:26:21,047 --> 00:26:22,446 +And I'm gonna calculate that as well. +这是通过计算得到的 + +678 +00:26:22,448 --> 00:26:23,947 +I'm gonna have it be a calculator property, +它是一个计算属性 + +679 +00:26:23,949 --> 00:26:26,283 +based on this dropsPerRow. +基于 dropsPerRow 的 + +680 +00:26:26,285 --> 00:26:28,184 +I'm gonna have it be square. +它们都是方块 + +681 +00:26:28,186 --> 00:26:30,687 +So we'll have the width and height be the same. +所以长和宽都是相同的 + +682 +00:26:30,689 --> 00:26:34,657 +And I'm gonna make it equal to the gameView's bounds +让它等于 + +683 +00:26:34,659 --> 00:26:38,260 +dot size dot width, divided by the dropsPerRow. +gameView.bounds.size.width 除以 dropsPerRow + +684 +00:26:38,262 --> 00:26:43,798 +So I'm just gonna take my width, +取出游戏视图的宽 + +685 +00:26:43,800 --> 00:26:46,467 +available width of my view, and just divide it up evenly, +除以一共有的方块的数量 + +686 +00:26:46,469 --> 00:26:50,071 +so that the drops exactly fill the space. +方块就能完整地填满 + +687 +00:26:50,073 --> 00:26:55,442 +And so now I can return a CGSize that +现在我就可以返回一个 CGSize + +688 +00:26:55,444 --> 00:26:58,878 +is both this width and this height. +包含相同的长和宽 + +689 +00:26:58,880 --> 00:27:00,913 +Okay, so now I know my drop size. +现在我知道了 dropSize + +690 +00:27:00,915 --> 00:27:05,651 +I'm going to add a gesture, which is the tap gesture. +现在添加一个单击手势 + +691 +00:27:05,653 --> 00:27:07,603 +When I put a tap gesture, +当我单击的时候 + +692 +00:27:07,604 --> 00:27:09,554 +I'm gonna put one of these drops into my view. +我就在视图中放入个方块 + +693 +00:27:09,556 --> 00:27:10,989 +So let's do that. +开始实现 + +694 +00:27:10,991 --> 00:27:12,790 +Let's go here to drag and +向视图中 + +695 +00:27:12,792 --> 00:27:17,761 +drop gesture out here, tap gesture right here. +拖入一个单击手势 + +696 +00:27:17,763 --> 00:27:20,397 +So I'm gonna drag this on here, and +放到这里 + +697 +00:27:20,399 --> 00:27:22,599 +bring up my document outline. +打开 document outline + +698 +00:27:22,601 --> 00:27:24,200 +Here's my tap gesture right here. +这里是单击手势 + +699 +00:27:24,202 --> 00:27:25,568 +So I'm gonna control drag. +CTRL-拖动 + +700 +00:27:25,570 --> 00:27:29,438 +I'm gonna call this gesture drop. +把它起名为 drop + +701 +00:27:29,440 --> 00:27:31,540 +It's a good name cuz that's what it does. +这是一个好名字,因为这表明它完成的动作 + +702 +00:27:31,542 --> 00:27:34,175 +It drops one of these things. +它会向下掉落一个方块 + +703 +00:27:34,177 --> 00:27:35,743 +Connect it. So here it is. +连接,好了 + +704 +00:27:35,745 --> 00:27:38,245 +I could put the code to do all the dropping here, but +我可以把所有的掉落代码写在这里 + +705 +00:27:38,247 --> 00:27:40,847 +I'm actually going to put it in another method. +但实际上我会在另一个方法中实现 + +706 +00:27:41,983 --> 00:27:43,316 +Call drop. +叫做 drop + +707 +00:27:43,318 --> 00:27:44,917 +Just because it's not necessarily something +因为不止单击手势可以 + +708 +00:27:44,919 --> 00:27:46,185 +that could only be done by gesture. +激活向下掉落 + +709 +00:27:46,187 --> 00:27:49,454 +Maybe programmatically one could drop things as well. +也许你还会通过代码来向下掉落 + +710 +00:27:49,456 --> 00:27:53,058 +So I don't really want to put inside that gesture. +所以我不想把它放到手势操作里 + +711 +00:27:53,060 --> 00:27:55,326 +So all the gesture you're gonna do is do this drop. +手势需要做的就是这个 drop 方法 + +712 +00:27:55,328 --> 00:27:57,461 +The drop just needs to figure out where the drop is, +drop 方法需要做的时,计算 drop 的位置 + +713 +00:27:57,463 --> 00:28:01,064 +so let's get, actually let's make more space here first. +先弄出一些空间 + +714 +00:28:03,635 --> 00:28:06,703 +This, I need a lot more space than that. +需要大一点地方 + +715 +00:28:06,705 --> 00:28:08,270 +Okay, so we need to figure out where the drop is. +需要弄清楚方块的位置 + +716 +00:28:08,272 --> 00:28:10,506 +So I'm going to make it's frame, which is really easy. +创建它的 frame,很简单 + +717 +00:28:10,508 --> 00:28:13,208 +I'm just gonna first of all, +首先 + +718 +00:28:13,210 --> 00:28:16,311 +create one that is at zero, zero. +我现在0,0点创建一个 + +719 +00:28:16,313 --> 00:28:20,981 +Use this nice CGPointZero by the way, which is zero, zero. +使用 CGPointZero 参数为0,0 + +720 +00:28:20,983 --> 00:28:22,783 +And the size is, of course, our dropSize. +size 当然是 dropSize + +721 +00:28:25,120 --> 00:28:27,053 +So now I've got drop at zero, zero. +现在在0,0点有了一个方块 + +722 +00:28:27,055 --> 00:28:30,923 +And now, I move it along somewhere along there. +现在把它移动到别处 + +723 +00:28:30,925 --> 00:28:35,594 +So, I'm gonna move it to frame dot origin dot x equals +令它的 frame.origin.x + +724 +00:28:35,596 --> 00:28:38,830 +CGFloat dot random, dropsPerRow. +等于 CGFloat.random(dropsPerRow) + +725 +00:28:38,832 --> 00:28:41,299 +And you're probably like whoa, CGFloat dot random, +你可能会说,哇,CGFloat.random + +726 +00:28:41,301 --> 00:28:43,367 +you didn't tell me about that cool function. +你没有跟我讲过这个很酷的方法 + +727 +00:28:43,369 --> 00:28:45,936 +Well, that's because there's no such function, but +这是因为没有这个函数 + +728 +00:28:45,938 --> 00:28:49,739 +I'm gonna write that function right now, really quick. +我现在来快速实现这个函数 + +729 +00:28:49,741 --> 00:28:50,873 +There it is. +好了 + +730 +00:28:50,875 --> 00:28:51,707 +Okay? + +731 +00:28:51,709 --> 00:28:52,941 +So all it does is, +这就是它做的事情 + +732 +00:28:52,943 --> 00:28:56,878 +it just uses arc4random to create a random float +使用 arc4random 创建一个随机的 float + +733 +00:28:56,880 --> 00:28:59,647 +between zero and one less than this maximum. +在0和最大值之间 + +734 +00:28:59,649 --> 00:29:02,417 +So here I'm gonna get a random float between zero and +在这我得到了一个在0和dropsPerRow-1之间 + +735 +00:29:02,419 --> 00:29:04,485 +dropsPerRow minus one. +的一个随机的 float + +736 +00:29:04,487 --> 00:29:06,120 +Okay, that's cool. +很酷吧 + +737 +00:29:06,122 --> 00:29:08,989 +And then I'm gonna multiply that by times dropSize dot +现在将它与 dropSize.width 相乘 + +738 +00:29:08,991 --> 00:29:10,457 +width cuz I'm gonna move it off. +把它移动到这里 + +739 +00:29:10,459 --> 00:29:12,658 +So I just took my drop, and I made it over. +我把它创建,将它移动 + +740 +00:29:12,660 --> 00:29:14,527 +And it would be in a certain spot, so +它将在某个位置上 + +741 +00:29:14,529 --> 00:29:16,128 +I'm gonna create my dropView. +所以我现在创建 dropView + +742 +00:29:16,130 --> 00:29:17,696 +It's just gonna be UIView. +类型是 UIView + +743 +00:29:17,698 --> 00:29:20,031 +I'm gonna use the frame initializer here, +使用 frame 的构造器 + +744 +00:29:20,033 --> 00:29:22,533 +use that frame I just created above. +上面创建的那个 + +745 +00:29:22,535 --> 00:29:27,404 +I'm gonna set the dropView's background color to be UIColor +把背景颜色设置为随机的 + +746 +00:29:27,406 --> 00:29:31,875 +random, another thing I added down here below. +我在下面已经添加这个方法了 + +747 +00:29:31,877 --> 00:29:36,112 +Just picked one of five random colors there in my rote. +在五个里面选择一个 + +748 +00:29:36,114 --> 00:29:37,563 +Notice, by the way, +主意 + +749 +00:29:37,564 --> 00:29:39,013 +that when I added these extensions to UIFloat and +当我给 CGFloat 和 UIColor 添加 extension 的时候 + +750 +00:29:39,016 --> 00:29:40,849 +UIColor, I made them private. +是私有的 + +751 +00:29:40,851 --> 00:29:42,851 +That means only I can use them. +这表明只有我能使用它们 + +752 +00:29:42,853 --> 00:29:45,887 +But it also means the name won't conflict with someone +也意味着命名不会冲突 + +753 +00:29:45,889 --> 00:29:48,756 +else if someone else writes their own CGFloat dot random +如果其他人也写了一个 参数为 Int 的 CGFloat.random + +754 +00:29:48,758 --> 00:29:50,024 +that takes an int. + +755 +00:29:50,026 --> 00:29:51,758 +Theirs will work in their file, and +它们的会在它们的文件里有效 + +756 +00:29:51,760 --> 00:29:52,759 +mine will work in my file. +我的会在我这里有效 + +757 +00:29:52,761 --> 00:29:55,028 +Okay, so it's private to this file. +对这个文件来说它是私有的 + +758 +00:29:55,030 --> 00:29:56,729 +So that's one nice thing about extensions, +这是 extension 的一个比较好的特性 + +759 +00:29:56,731 --> 00:29:59,831 +you can kind of control the privacy of extensions. +你可以控制 extension 的公私有性 + +760 +00:30:00,801 --> 00:30:02,834 +So there I have my dropView. +现在我有了 dropView + +761 +00:30:02,835 --> 00:30:04,868 +Now I'm just gonna add it to my gameView, addSubview. +我把它添加到 gameView 上,通过 addSubview + +762 +00:30:04,871 --> 00:30:07,471 +We really haven't had you doing addSubview. +我们之前还没用过 addSubView + +763 +00:30:07,473 --> 00:30:10,607 +But cuz you've been doing all the views in your storyboard. +因为之前都是在 stroyboard 中添加视图 + +764 +00:30:10,609 --> 00:30:12,609 +But in your homework you're going to be adding your +但在作业中,你将使用 addSubView + +765 +00:30:12,611 --> 00:30:16,246 +bricks, views, and all that stuff, using addSubview. +来添加砖块,视图之类的视图 + +766 +00:30:16,248 --> 00:30:17,680 +Probably your storyboard's just going to be +也许你的 storyboard + +767 +00:30:17,682 --> 00:30:18,731 +completely blank. +会是完全空白的 + +768 +00:30:18,732 --> 00:30:19,781 +Or maybe you might have the score and +也许你还有显示分数 + +769 +00:30:19,784 --> 00:30:21,751 +some other things in there. +和其他东西 + +770 +00:30:21,752 --> 00:30:23,719 +But the bricks and the paddle, and ball, +但是砖块和球之类的东西 + +771 +00:30:23,721 --> 00:30:24,986 +that's all going to be added. +都需要通过这种方式添加 + +772 +00:30:24,988 --> 00:30:26,288 +You're gonna add with addSubview. +使用 addSubView + +773 +00:30:26,289 --> 00:30:27,589 +That's part of what this assignment is about. +这是这次作业的部分内容 + +774 +00:30:27,591 --> 00:30:30,324 +So you get some experience creating and +所以你们会获得一些 + +775 +00:30:30,326 --> 00:30:31,926 +adding views in code. +通过代码添加视图的经验 + +776 +00:30:31,928 --> 00:30:32,993 +Okay? So that's what we're doing. +这就是我们在做的事情 + +777 +00:30:32,995 --> 00:30:35,128 +So let's go see what this looks like. +让我们看看效果 + +778 +00:30:35,130 --> 00:30:38,198 +Hopefully when we tap we'll get a random square along +希望在点击过后 + +779 +00:30:38,200 --> 00:30:41,167 +the top of our view here. +一个方块会出现在顶部 + +780 +00:30:41,169 --> 00:30:42,201 +So tap, we got one. +所以点击,有了一个 + +781 +00:30:42,203 --> 00:30:43,602 +Good, we're getting them. +好的,我们已经做到了 + +782 +00:30:43,604 --> 00:30:45,937 +So here I'm tapping them, this is great. +我一直点击,很棒 + +783 +00:30:45,939 --> 00:30:48,106 +Okay, so we're adding these things along the top, +我们已经在顶部添加了这些 + +784 +00:30:48,108 --> 00:30:50,041 +now I'm gonna add gravity. +现在我来添加重力效果 + +785 +00:30:50,043 --> 00:30:51,776 +Okay, I'm going to add a gravitational field, and +添加一个重力场 + +786 +00:30:51,778 --> 00:30:53,177 +it's going to apply to all these things. +它会适应所有的物体 + +787 +00:30:53,179 --> 00:30:55,412 +It's going to pull them all down to the bottom of +会将它们拉到屏幕的底部 + +788 +00:30:55,414 --> 00:30:56,046 +the screen. + +789 +00:30:56,048 --> 00:30:57,080 +Okay? + +790 +00:30:57,082 --> 00:30:59,682 +So these all will just fall down. +它们都会掉落下来 + +791 +00:30:59,684 --> 00:31:03,385 +Turns out this very, very easy to do, okay? +然而实现起来很简单 + +792 +00:31:03,387 --> 00:31:06,822 +All I need to do is create a gravitational field so +创建一个重力场 + +793 +00:31:06,824 --> 00:31:12,360 +I'm going to say, let gravity equal a UIGravityBehaviour. +let gravity = UIGravityBehaviour + +794 +00:31:12,362 --> 00:31:14,628 +Okay, so boom, I have a UIGravityBehavior. +boom,我有了一个 UIGravityBehavior + +795 +00:31:14,630 --> 00:31:18,332 +I'm gonna take the default magnitude and direction which +默认的方向是向下 + +796 +00:31:18,334 --> 00:31:21,735 +is down, at a thousand points per second per second. +速度是1000点/秒/秒 + +797 +00:31:21,737 --> 00:31:23,603 +So that's perfectly fine to me. +对于我来说不错 + +798 +00:31:23,605 --> 00:31:26,806 +Of course I also need a dynamic animator. +当然我还需要一个 dynamic animator + +799 +00:31:26,808 --> 00:31:28,207 +Okay? + +800 +00:31:28,208 --> 00:31:29,607 +So I'm going to create a dynamic animator here. +在这里创建一个 + +801 +00:31:31,245 --> 00:31:38,616 +Now, I wanna say this, referenceView is gameView. +设置它的 referenceView 为 gameView + +802 +00:31:38,618 --> 00:31:39,283 +Okay? But I'm not gonna +但是现在这种 + +803 +00:31:39,285 --> 00:31:41,802 +be able to do this. +方式不行 + +804 +00:31:41,803 --> 00:31:44,320 +Now, a lot of you tripped into this, on your, assignments. +好多人都在作业里被这一点困住了 + +805 +00:31:44,323 --> 00:31:45,989 +I saw on Piazza, a lot of questions about this. +我看到 Piazza 上有好多关于这个的问题 + +806 +00:31:45,991 --> 00:31:47,591 +You're, like, oh, what, what's going on here? +到底发生了什么? + +807 +00:31:47,593 --> 00:31:49,659 +And you click this warning, and it says, +点击一下错误 + +808 +00:31:49,661 --> 00:31:50,960 +gameView is not a part of. +它说 + +809 +00:31:50,962 --> 00:31:54,030 +DropitViewController, of course it is, it's right here. +gameView 不是 DropitViewController 的一部分,当然是,它就在这里 + +810 +00:31:54,032 --> 00:31:56,598 +What the heck is going on? +到底发生了什么? + +811 +00:31:56,600 --> 00:31:59,134 +And hopefully all of you have figured out that +希望你们都发现了 + +812 +00:31:59,136 --> 00:32:00,602 +the reason that's happening is because +发生这种错误的原因是 + +813 +00:32:00,604 --> 00:32:03,638 +I'm in the middle of initializing here. +我在构造 + +814 +00:32:03,640 --> 00:32:07,208 +Okay, this is initializing this variable. +这里在构造这个变量 + +815 +00:32:07,210 --> 00:32:09,877 +And you cannot access your own properties and +但你不能在这里引用属性和方法 + +816 +00:32:09,879 --> 00:32:12,746 +methods until you're fully initialized. +直到你被完整构造出来 + +817 +00:32:12,748 --> 00:32:14,614 +So obviously, you can't access them while you're +所以显然 + +818 +00:32:14,616 --> 00:32:16,916 +initializing, by definition, so that's the problem. +在这里你不能引用 gameView,这是个问题 + +819 +00:32:16,918 --> 00:32:18,751 +So, how do I get out of this conundrum? +怎样能去掉这个错误 + +820 +00:32:18,753 --> 00:32:22,154 +Because UIDyanmicAnimator needs this game view +因为 UIDyanmicAnimator 需要这个 gameView + +821 +00:32:22,156 --> 00:32:23,956 +as its reference. +作为引用 + +822 +00:32:23,957 --> 00:32:25,757 +Well, one thing is, I could make this an optional and +我可以把它设置为 optional + +823 +00:32:25,759 --> 00:32:28,927 +set to nil, and then the view did load, when I know that's +在 viewDidLoad 方法中 + +824 +00:32:28,929 --> 00:32:32,030 +set I could set the, I could create the animator there. +创建 animator + +825 +00:32:32,032 --> 00:32:33,297 +Yeah, you could do that. +你可以这样做 + +826 +00:32:33,299 --> 00:32:35,599 +Another way to do it is using a lazy. +另一种方式是使用 lazy + +827 +00:32:35,601 --> 00:32:38,552 +Variable. So + +828 +00:32:38,553 --> 00:32:41,504 +I'm gonna make this var lazy and I'm gonna set its initial +把这个变量变为 lazy + +829 +00:32:41,506 --> 00:32:46,075 +value equal to the result of executing a closure. +把它的初始化变为一个闭包的执行结果 + +830 +00:32:47,611 --> 00:32:49,244 +Okay. + +831 +00:32:49,246 --> 00:32:51,312 +So, this is not gonna happen, +这里不会调用 + +832 +00:32:51,314 --> 00:32:53,848 +this is not going to get initialized, +这里不会初始化 + +833 +00:32:53,850 --> 00:32:57,385 +until someone actually asks for this animator. +知道某人引用这个 animator + +834 +00:32:57,387 --> 00:33:00,421 +And once they ask for it, I'm gonna execute this closure +一旦别处引用,这个闭包将被执行 + +835 +00:33:00,423 --> 00:33:02,456 +by just having the closure with parentheses. +这个带括号的闭包 + +836 +00:33:02,458 --> 00:33:05,125 +It takes no arguments, so I just call it with parentheses. +没有参数,所以只要有括号就可以 + +837 +00:33:05,127 --> 00:33:06,859 +And it's going to execute this closure. +它将会执行这个闭包 + +838 +00:33:06,861 --> 00:33:10,429 +Now, this closure better return a UIDynamicAnimator. +这个闭包最好返回一个 UIDyanmicAnimator + +839 +00:33:10,431 --> 00:33:12,598 +Okay, because I'm setting it equal to the result. +因为我把它设置为闭包的返回结果 + +840 +00:33:12,600 --> 00:33:18,136 +And in fact, it's going to, because I'm gonna say, let +实际上 + +841 +00:33:18,138 --> 00:33:23,240 +lazilyCreatedDynamicAnimator equal that, okay? +let UIDyanmicAnimator = + +842 +00:33:23,242 --> 00:33:24,441 +Now, this is inside a closure. +现在是在闭包内部 + +843 +00:33:24,443 --> 00:33:28,078 +So I'm gonna want to say self.gameView, right? +所以需要添加 self + +844 +00:33:28,080 --> 00:33:31,014 +And then I'm just going to return +接着 + +845 +00:33:31,016 --> 00:33:34,117 +lazilyCreatedDynamicAnimator. +返回 lazilyCreatedDynamicAnimator + +846 +00:33:34,119 --> 00:33:34,917 +Okay? + +847 +00:33:34,919 --> 00:33:38,320 +This kind of solves the problem. +解决了问题 + +848 +00:33:38,322 --> 00:33:39,654 +Okay? I don't have any warnings, +没有警告 + +849 +00:33:39,656 --> 00:33:42,891 +but you gotta be careful you better not call this +但是你得注意 + +850 +00:33:42,893 --> 00:33:44,192 +before this gets set. +最好别在它被设置好之前调用它 + +851 +00:33:45,261 --> 00:33:46,994 +Because this is going to be nill, you're +因为它会是 nil + +852 +00:33:46,996 --> 00:33:49,062 +going to have a reference view nill, your animator is +它的引用视图为 nil + +853 +00:33:49,064 --> 00:33:50,964 +going to get created with no reference view. +你的 animator 将不会有引用视图 + +854 +00:33:50,966 --> 00:33:52,899 +It ain't going to work. +它不会工作的 + +855 +00:33:52,901 --> 00:33:54,317 +Okay? + +856 +00:33:54,318 --> 00:33:55,734 +So you gotta be careful about when you call this. +所以在调用的时候得注意一下 + +857 +00:33:55,737 --> 00:33:57,436 +Okay? When you access this property. +当你引用这个属性的时候 + +858 +00:33:57,438 --> 00:33:58,970 +So I'm not gonna act as this property until I +所以在 viewDidLoad 之前,我不会引用这个变量 + +859 +00:33:58,972 --> 00:34:01,206 +get to viewDidLoad, cuz then I'll know +因为我知道 + +860 +00:34:01,208 --> 00:34:04,208 +that this outlet right here has been set. +这个 outlet 已经被设置好了 + +861 +00:34:04,210 --> 00:34:05,927 +Okay? + +862 +00:34:05,928 --> 00:34:07,645 +So let's go ahead and do viewDidLoad, in fact. +现在来实现 viewDidLoad + +863 +00:34:07,647 --> 00:34:11,048 +So in viewDidLoad, all I'm gonna do is. +在这里需要做的是 + +864 +00:34:12,551 --> 00:34:15,651 +Say animator, add behavior gravity. +animator.addBehavior(gravity) + +865 +00:34:16,620 --> 00:34:19,521 +So now, I have a gravitational field, +所以现在,我有了重力场 + +866 +00:34:19,523 --> 00:34:22,157 +I've added it to an animator, so an animator is now going to +把它添加到了 animator 里,所以 animator 现在会 + +867 +00:34:22,159 --> 00:34:24,792 +be animating the behavior of items in there. +发动里面所有的特性 + +868 +00:34:24,794 --> 00:34:27,395 +The only thing I need to do is say +我在这里只要指明 + +869 +00:34:27,397 --> 00:34:30,297 +which items are affected by gravity. +哪个物体被重力影响 + +870 +00:34:30,299 --> 00:34:31,431 +So I'm gonna go right down and +所以到这里 + +871 +00:34:31,433 --> 00:34:36,402 +say, gravity add item, my drop view. +gravity.addItem(dropView) + +872 +00:34:36,404 --> 00:34:39,839 +Now the instance I say this, the instancy animator, +这个 animator 的实例 + +873 +00:34:39,841 --> 00:34:43,375 +the instance the behavior gets added to the animator, all +behavior 被添加到了 animator 中 + +874 +00:34:43,377 --> 00:34:46,978 +items in that gravity field are going to start animating. +所有 gravity 中的物体都会开始动画 + +875 +00:34:46,980 --> 00:34:49,514 +Now I can add those items later and then they'll start +添加了之后,它们就会动画 + +876 +00:34:49,516 --> 00:34:52,383 +animating, I can take them out and it'll stop animating. +移除了之后,它们就会停止 + +877 +00:34:52,385 --> 00:34:54,585 +It's all instantaneous, okay. +这些都是瞬间发生的 + +878 +00:34:54,587 --> 00:34:57,354 +So if I run now, since I have an animator and +如果现在运行,我有了 animator 和 + +879 +00:34:57,356 --> 00:34:58,889 +a gravitational field and +重力场 + +880 +00:34:58,891 --> 00:35:02,492 +I put the items in there, they fall, okay. +我把方块放进去,它们就会掉落 + +881 +00:35:02,494 --> 00:35:03,944 +Now they're accelerating. +它们在加速 + +882 +00:35:03,945 --> 00:35:05,395 +See how they're getting faster and faster at the bottom? +它们会在底部变得越来越快 + +883 +00:35:05,397 --> 00:35:06,495 +They're accelerating due to gravity and +这是因为重力 + +884 +00:35:06,497 --> 00:35:08,997 +I can have as many of them as I want. +我可以添加任意多个 + +885 +00:35:08,999 --> 00:35:12,768 +Okay and they will accelerate. +它们都会加速 + +886 +00:35:12,770 --> 00:35:15,236 +They'll all be accelerating their own +它们都会以自己的 + +887 +00:35:15,238 --> 00:35:17,005 +gravitational acceleration. +重力加速度加速 + +888 +00:35:17,007 --> 00:35:18,773 +Okay now this is great except for +都不错,只是 + +889 +00:35:18,775 --> 00:35:21,075 +they're just falling off the end and they're gone. +它们掉出了屏幕 + +890 +00:35:21,077 --> 00:35:23,343 +And really what I want is for them to stay on screen. +我想要它们呆在屏幕上 + +891 +00:35:23,345 --> 00:35:26,079 +So I'm gonna create a collision behavior where +所以我添加碰撞属性 + +892 +00:35:26,081 --> 00:35:30,282 +the edges of my reference view here are going to. +在屏幕的底部 + +893 +00:35:30,284 --> 00:35:33,419 +Stop these things and they are gonna bounce off okay? +这会使得它们停在那里,并弹起 + +894 +00:35:33,421 --> 00:35:36,521 +So they are going to collide, again really easy to do, +它们将会碰撞,很容易实现 + +895 +00:35:36,523 --> 00:35:39,524 +I'm just gonna go up here and create a collision behavior. +在上面,创建一个碰撞特性 + +896 +00:35:39,526 --> 00:35:40,725 +I'm gonna do these same thing here and +和这里完成的工作一样 + +897 +00:35:40,727 --> 00:35:42,093 +do a lazy version of this and +一个 lazy 版本的 + +898 +00:35:42,095 --> 00:35:43,527 +I'll show you why I'm doing that. +你们也知道为什么要这样做 + +899 +00:35:43,529 --> 00:35:45,195 +I'm gonna call it my collider. +起名为 collider + +900 +00:35:45,197 --> 00:35:48,264 +It's a UI collision behavior. +类型为 UICollisionBehavior + +901 +00:35:49,267 --> 00:35:55,137 +I'm gonna set it equal to executing a closure. +把它设置为闭包执行的结果 + +902 +00:35:55,139 --> 00:36:01,376 +I'll say let my lazilyCreatedCollider +let lazilyCreatedCollider + +903 +00:36:01,378 --> 00:36:06,146 +equal UICollisionBehavior. += UICollisionBehavior + +904 +00:36:06,148 --> 00:36:07,080 +Okay? + +905 +00:36:07,082 --> 00:36:07,814 +And. + +906 +00:36:09,517 --> 00:36:12,051 +Then, oops. +哦 + +907 +00:36:12,053 --> 00:36:14,687 +Don't want that there cuz I'm not creating it there. +不在这里加括号,因为不在这里创建 + +908 +00:36:14,689 --> 00:36:16,555 +There we go. +好了 + +909 +00:36:16,557 --> 00:36:19,424 +So, now, the reason I did this is not because I have this +我没有调用那个构造器 + +910 +00:36:19,426 --> 00:36:21,859 +reference view problem or anything like that. +是因为 + +911 +00:36:21,861 --> 00:36:24,495 +It's just that I wanna configure this thing. +我想设置一下它的某些属性 + +912 +00:36:24,497 --> 00:36:25,680 +Okay? + +913 +00:36:25,681 --> 00:36:26,864 +And one thing I wanna configure here is +其中一个是 + +914 +00:36:26,866 --> 00:36:30,400 +that I want it to translate the reference bounds. +把屏幕的边界变为边界 + +915 +00:36:30,402 --> 00:36:31,901 +Into a boundary. + +916 +00:36:31,903 --> 00:36:34,670 +That means the edges of my reference view are going to +这意味着 referenceView + +917 +00:36:34,672 --> 00:36:36,789 +be a boundary. +将会变为边界 + +918 +00:36:36,790 --> 00:36:38,907 +So, anything, any items that are in this collider will +在这个 collider 中的任何物体 + +919 +00:36:38,909 --> 00:36:41,143 +bounce off of that, those bounds. +都会在边界弹起来 + +920 +00:36:41,145 --> 00:36:41,743 +Okay? + +921 +00:36:41,745 --> 00:36:42,877 +And now I'll return. +然后,返回它 + +922 +00:36:42,879 --> 00:36:45,479 +So here you can see two different reasons. +所以你可以看到利用闭包使用 lazy + +923 +00:36:45,481 --> 00:36:49,249 +That I've used for using this lazy with the closure. +有两种不同的原因 + +924 +00:36:49,251 --> 00:36:51,501 +One is, +一个是 + +925 +00:36:51,502 --> 00:36:53,752 +there was something I couldn't access during initialization, +在构造期间有一些东西不能饮用 + +926 +00:36:53,755 --> 00:36:57,623 +another one is I wanted to initialize some state, okay? +另一个是构造完毕后设置它的一些属性 + +927 +00:36:57,625 --> 00:37:01,593 +Those are both valid reasons to do this lazy business. +这些都是使用 lazy 的正当理由 + +928 +00:37:01,595 --> 00:37:02,995 +Okay? + +929 +00:37:02,996 --> 00:37:04,396 +So, I need to add that to the animator. +我需要把它添加到 animator 中 + +930 +00:37:06,433 --> 00:37:10,535 +Collider and of course I need, if I want these drops +如果我想让这些方块碰撞 + +931 +00:37:10,537 --> 00:37:13,471 +to collide, they need to be added to the collider as well. +需要将他们放入 collider 中 + +932 +00:37:13,473 --> 00:37:16,740 +Okay? + +933 +00:37:16,742 --> 00:37:17,874 +And that's it. +好了 + +934 +00:37:17,876 --> 00:37:21,077 +That's all, again, this stuff is amazingly simple, +这些东西非常精简 + +935 +00:37:21,079 --> 00:37:24,980 +you just add the behaviors and things will start behaving. +你只需要添加 behavior 就会起作用 + +936 +00:37:24,982 --> 00:37:26,382 +Okay? So let's watch. +看看效果 + +937 +00:37:26,384 --> 00:37:27,582 +What happens here. +发生了什么 + +938 +00:37:27,584 --> 00:37:28,216 +So we drop one in. +掉落一个 + +939 +00:37:28,218 --> 00:37:29,050 +Oh see? +看到了吗 + +940 +00:37:29,052 --> 00:37:30,317 +Bounce at the bottom. +在底部弹起 + +941 +00:37:30,319 --> 00:37:33,354 +Didn't bounce very much, it's not a very big bounce, but +没弹起很高,但是它 + +942 +00:37:33,356 --> 00:37:34,855 +it did bounce. +的确弹起来了 + +943 +00:37:34,856 --> 00:37:36,355 +We're gonna make it bounce some more in a minute here. +一会我们会让它弹地高一点 + +944 +00:37:36,358 --> 00:37:38,024 +But again, if I send a whole bunch of them down, +如果多掉落一些 + +945 +00:37:38,026 --> 00:37:40,059 +not only do they bounce off the bottom, +它们不止会在底部弹起 + +946 +00:37:40,061 --> 00:37:42,361 +they'll bounce off of each other a little bit, too. +它们之间也会这样 + +947 +00:37:42,363 --> 00:37:44,430 +And they also can rotate. +它们也可以旋转 + +948 +00:37:44,432 --> 00:37:46,365 +So if I send too many of them down here, and +如果我掉落太多 + +949 +00:37:46,367 --> 00:37:49,067 +if they're getting a little, oh, look. +它们就会 + +950 +00:37:49,069 --> 00:37:50,468 +Oh no! +哦 + +951 +00:37:50,470 --> 00:37:52,970 +Okay, oh no, it's collapsed. +发生跌落了 + +952 +00:37:52,972 --> 00:37:55,906 +Okay, so these things are allowed to tilt and rotate and +这些东西都会倾斜,旋转 + +953 +00:37:55,908 --> 00:37:57,407 +they can all just collapse and fall down. +跌落 + +954 +00:37:58,510 --> 00:37:59,509 +Okay? + +955 +00:37:59,511 --> 00:38:00,676 +Cuz that's the physics of them. +这是它们的物理属性 + +956 +00:38:00,678 --> 00:38:02,878 +When they bounce, they might hit a little ledge and +当弹起的时候,可能会碰到边角 + +957 +00:38:02,880 --> 00:38:07,115 +boom, since they can rotate, they'll tilt and tip over. +旋转,倾斜 + +958 +00:38:07,117 --> 00:38:07,682 +Okay? + +959 +00:38:09,585 --> 00:38:11,051 +All right, so that's that. +就是这样 + +960 +00:38:11,053 --> 00:38:16,489 +Now what if I had my game here, and I wanted to not +如果我的游戏是这样 + +961 +00:38:16,491 --> 00:38:19,192 +have them tilt like that, I wanted them to stay in their +我不想让它们倾斜 + +962 +00:38:19,194 --> 00:38:21,994 +nice neat rows, and also I want them to bounce more. +我想让它们在列中直直地排列,而且弹起更高 + +963 +00:38:21,996 --> 00:38:23,829 +I don't want such a little tiny bounce, +现在的弹跳太不给力了 + +964 +00:38:23,831 --> 00:38:24,830 +that's not very exciting. +一点也不爽 + +965 +00:38:24,832 --> 00:38:26,531 +I want a big old bounce okay? +我需要一个大跳! + +966 +00:38:26,533 --> 00:38:27,699 +Off each other and off the bottom. +在它们之间还有屏幕底部 + +967 +00:38:27,701 --> 00:38:28,966 +So how would I do that? +怎样实现呢? + +968 +00:38:28,968 --> 00:38:32,136 +Well I would add a dynamic item behavior that we +我可以添加一个 behavior + +969 +00:38:32,138 --> 00:38:34,671 +talked about in lecture, but it started to get the point +但是现在 behavior 太多了 + +970 +00:38:34,673 --> 00:38:37,474 +here where I have an awful lot of different behaviors acting +这些 behavior 都在这些方块上起作用 + +971 +00:38:37,476 --> 00:38:39,242 +on each of these drops. + +972 +00:38:39,244 --> 00:38:41,310 +So this is the time where I'm probably like, +所以,我现在想 + +973 +00:38:41,312 --> 00:38:45,113 +I wanna create my own dynamic behavior that is a composite +创建一个自己的 dynamic behavior + +974 +00:38:45,115 --> 00:38:46,314 +of all these things. +把所有的东西添加到那里边 + +975 +00:38:46,316 --> 00:38:47,682 +The collider, the gravity, +碰撞,重力 + +976 +00:38:47,684 --> 00:38:50,785 +and the bounciness and the don't rotate. +弹跳,不旋转等等 + +977 +00:38:50,787 --> 00:38:52,386 +All that, so I want it all kind of in one thing. +把所有的东西放入其中 + +978 +00:38:52,388 --> 00:38:53,553 +So, let's do that. +动手实现吧 + +979 +00:38:53,555 --> 00:38:55,789 +We'll just do that by creating a new file here. +创建一个新文件 + +980 +00:38:55,791 --> 00:38:58,558 +New > File. + +981 +00:38:58,560 --> 00:39:00,693 +And it's a Cocoa Touch class. +Cocoa Touch 类 + +982 +00:39:00,695 --> 00:39:04,229 +It's gonna be a UIDynamicBehavior subclass, +UIDynamicBehavior 子类 + +983 +00:39:04,231 --> 00:39:04,796 +okay? + +984 +00:39:04,798 --> 00:39:06,364 +I'm gonna call it. +起名为 + +985 +00:39:06,366 --> 00:39:08,265 +DropitBehavior, because that's what it is. +DropitBehavior + +986 +00:39:08,267 --> 00:39:11,135 +It's the behavior for these Dropit things. +它是给 Dropit 提供 behavior + +987 +00:39:11,137 --> 00:39:12,235 +So I could call DropitBehavior. +所以起名为 DropitBehavior + +988 +00:39:12,237 --> 00:39:13,570 +I could maybe call it DropBehavior, +也可以起名为 DropBehavior + +989 +00:39:13,572 --> 00:39:14,604 +I like it DropitBehavior, +但是我喜欢 DropitBehavior + +990 +00:39:14,606 --> 00:39:16,806 +cuz it's really the behavior of my whole, +因为它是为我这个 Dropit 游戏 + +991 +00:39:16,808 --> 00:39:19,641 +all the things participating in my Dropit game here. +提供 behavior 的东西 + +992 +00:39:19,643 --> 00:39:21,510 +So here's a DropitBehavior. +这就是 DropitBehavior + +993 +00:39:21,512 --> 00:39:23,611 +Doesn't have anything in it to start. +没有什么东西 + +994 +00:39:23,613 --> 00:39:26,214 +And all I'm gonna do is basically take +我现在将这些东西 + +995 +00:39:26,216 --> 00:39:28,449 +these things like gravity and collider. +gravity 和 collider + +996 +00:39:28,451 --> 00:39:35,355 +Out of here, okay, and put him over in here like that. +取出来,放到这里 + +997 +00:39:35,357 --> 00:39:38,642 +Oops, sorry. +抱歉 + +998 +00:39:38,643 --> 00:39:41,928 +And then I'm going to override init from UIDynamicBehavior, +然后,重写 UIDynamicBehavior 的 init 方法 + +999 +00:39:41,930 --> 00:39:43,062 +right? + +1000 +00:39:43,063 --> 00:39:44,195 +This is a subclass of UIDynamicBehavior. +这是 UIDynamicBehavior 子类 + +1001 +00:39:44,198 --> 00:39:46,231 +So I'll call super init. +所以在 init 中调用 super.init + +1002 +00:39:46,233 --> 00:39:50,268 +And then all I'm gonna do is add child behaviors for +在这里调用 addChildBehavior + +1003 +00:39:50,270 --> 00:39:52,387 +gravity. +参数是 graviry + +1004 +00:39:52,388 --> 00:39:54,505 +And add a child behavior for the collider. +然后是 collider + +1005 +00:39:54,507 --> 00:39:57,475 +Okay, so now that I've added these behaviors, +现在我添加了这些 behavior + +1006 +00:39:57,477 --> 00:40:01,411 +now my dropit behavior behaves like those things do combined. +我的方块是这个 behavior 的结合 + +1007 +00:40:02,647 --> 00:40:04,036 +Okay? + +1008 +00:40:04,037 --> 00:40:05,426 +Cuz they're children behavior of me. +因为这是我的子特性 + +1009 +00:40:05,427 --> 00:40:06,816 +So this is a awesome way to create a powerful behavior +这是创建强大 behavior 的一种很好的方式 + +1010 +00:40:06,818 --> 00:40:09,218 +just by taking other powerful behaviors. +在其中添加其他强大的 behavior 就好了 + +1011 +00:40:09,220 --> 00:40:13,422 +I'm also gonna have an addDrop function here, +再添加一个 addDrop 方法 + +1012 +00:40:13,424 --> 00:40:17,659 +that takes a drop, which is gonna be UIView, one of these +参数是一个 drop 类型是 UIView + +1013 +00:40:17,661 --> 00:40:22,230 +things that we're creating, and I'm going to add the drop +在这里把它添加到 + +1014 +00:40:23,666 --> 00:40:28,568 +as items to both my gravity and my collider. +gravity 和 colider 的 item 中 + +1015 +00:40:30,806 --> 00:40:32,238 +And in fact, and +实际上 + +1016 +00:40:32,240 --> 00:40:35,174 +this is debatable whether this is kind of the architecture +这里也是可以探讨的 + +1017 +00:40:35,176 --> 00:40:39,044 +one would want, but I'm gonna actually manage the view +也就是构架的问题 + +1018 +00:40:39,046 --> 00:40:41,913 +whether it's in the view hierarchy or not, here. +但是我想在这里把这个 view 添加到 + +1019 +00:40:41,915 --> 00:40:46,984 +So I'm going to add this drop to my reference view +reference view 的子视图里 + +1020 +00:40:46,986 --> 00:40:49,720 +whenever you call addDrop in my behavior. +当你调用我的 behavior 的 addDrop + +1021 +00:40:49,722 --> 00:40:53,390 +So I know the dynamic animator I'm in, all right, +我知道我在哪个 dynamic animator 中 + +1022 +00:40:53,392 --> 00:40:55,258 +because I'm a behavior. +因为我是一个 behavior + +1023 +00:40:55,260 --> 00:40:58,061 +I might be nil, but might not, and +我可能是 nil 也可能不是 + +1024 +00:40:58,063 --> 00:41:01,731 +I know the reference view for that dynamic animator. +我知道 dynamic animator 的引用视图 + +1025 +00:41:01,733 --> 00:41:04,099 +That might be nil but probably not. +可能是 nil 也可能不是 + +1026 +00:41:04,101 --> 00:41:06,668 +And so from there, I can add SubviewThisDrop. +所以在这里,我把 drop 添加为子视图 + +1027 +00:41:08,738 --> 00:41:12,239 +So if you call addDrop on this drop behavior, it will add it +所以当你调用这个 drop behavior 的 addDrop 时 + +1028 +00:41:12,241 --> 00:41:15,909 +to the reference view and then add it to its behaviors. +它会把 drop 添加到引用视图里,然后添加到 behaviors 里面 + +1029 +00:41:15,911 --> 00:41:17,644 +And same thing, I could have a removeDrop. +我也可以添加一个 removeDrop 方法 + +1030 +00:41:17,646 --> 00:41:23,116 +All right, which takes a UI view and it does the opposite. +参数相同,做的事情相反 + +1031 +00:41:23,118 --> 00:41:26,552 +So, gravity.removeItem, the drop. +gravity.removeItem 参数为 drop + +1032 +00:41:26,554 --> 00:41:29,221 +Collider.removeItem, the drop. +Collider.removeItem + +1033 +00:41:29,223 --> 00:41:32,290 +And drop.removeFromSuperView. +drop.removeFromSuperView + +1034 +00:41:32,292 --> 00:41:35,193 +Okay? + +1035 +00:41:35,195 --> 00:41:38,062 +So now I have this nice class right here, +现在有了一个不错的类 + +1036 +00:41:38,064 --> 00:41:39,296 +which is a behavior, and +是一个 behavior + +1037 +00:41:39,298 --> 00:41:42,399 +it replaces all those behavioral things over here. +它代替了这些所有 + +1038 +00:41:42,401 --> 00:41:45,369 +So, instead of animating behavior and +为了取代 animator 和分开的 gravity + +1039 +00:41:45,371 --> 00:41:49,639 +gravity separately, I can just create a dropItBehavior +我只需创建一个 dropItBehavior + +1040 +00:41:49,641 --> 00:41:54,877 +equals DropItBehavior, okay, so just create one of those. +只创建一个 + +1041 +00:41:54,879 --> 00:41:58,146 +And it could even probably even say let here, okay? +也可以设置为常量 + +1042 +00:41:58,148 --> 00:41:59,681 +And then in addBehavior, +在 addBehavior 中 + +1043 +00:41:59,683 --> 00:42:02,950 +I can just say add the dropItBehavior. +只需要添加 dropItBehavior + +1044 +00:42:02,952 --> 00:42:03,851 +Okay? So I don't need to +我不需要再添加 + +1045 +00:42:03,853 --> 00:42:05,152 +add the collider separately, +collider 了 + +1046 +00:42:05,154 --> 00:42:07,554 +just do the drop behavior and same thing down here. +这里也是 + +1047 +00:42:07,556 --> 00:42:11,725 +All three of these things, adding the subview, +这里的操作 + +1048 +00:42:11,727 --> 00:42:17,396 +those all are just replaced by saying dropitBehavior.addDrop, +可以改成 dropitBehavior.addDrop + +1049 +00:42:17,398 --> 00:42:19,031 +and the drop view. +参数为 dropView + +1050 +00:42:19,033 --> 00:42:20,499 +'Kay? So you can see my +你可以看到 + +1051 +00:42:20,501 --> 00:42:23,768 +code here has gotten much more focused on kind of, +这里的代码变得更清晰了 + +1052 +00:42:23,770 --> 00:42:25,169 +what we're doing and +专注于我们的业务 + +1053 +00:42:25,171 --> 00:42:27,838 +the behaviors have been moved off into the behavior code. +behavior 的代码被移到了别处 + +1054 +00:42:27,840 --> 00:42:30,374 +Now let's run this to make sure we didn't break anything +运行测试一下 + +1055 +00:42:30,376 --> 00:42:34,110 +by doing that, and it looks like we're in good shape. +看起来 OK + +1056 +00:42:34,112 --> 00:42:35,295 +Okay? + +1057 +00:42:35,296 --> 00:42:36,479 +But these things can still tilt. +但是这些东西还是会倾斜 + +1058 +00:42:36,481 --> 00:42:40,216 +They're still, you know, getting out of their little +它们仍然弹出了规定列 + +1059 +00:42:40,218 --> 00:42:42,451 +columns, and they're also not bouncing very much. +并且也没弹那么高 + +1060 +00:42:42,453 --> 00:42:44,319 +So let's get back to fixing that. +回到那里,实现它 + +1061 +00:42:44,321 --> 00:42:46,254 +And now, whenever I wanna add a new behavior, +现在,无论何时我想添加一个新的 behavior + +1062 +00:42:46,256 --> 00:42:48,489 +I'm gonna add it in this behavior class. +只要在这个类修改就可以了 + +1063 +00:42:49,525 --> 00:42:51,325 +So, what kind of behavior is that? +什么类型的 behavior + +1064 +00:42:51,327 --> 00:42:53,527 +I'm gonna do lazy var again here. +再来一个 lazy 变量 + +1065 +00:42:53,529 --> 00:42:56,429 +I'm gonna call it my dropBehavior, +起名为 dropBehavior + +1066 +00:42:56,431 --> 00:43:00,099 +it's a UIDynamicItemBehavior. +类型为 UIDynamicItemBehavior + +1067 +00:43:00,101 --> 00:43:01,667 +Okay? I'm gonna do the same +同样的黑魔法 + +1068 +00:43:01,669 --> 00:43:05,604 +magical trick, it's not that magical, and +其实也没那么神奇 + +1069 +00:43:05,606 --> 00:43:10,809 +I'm going to say let a lazilyCreatedDropBehavior. +let lazilyCreatedDropBehavior + +1070 +00:43:10,811 --> 00:43:12,310 +I'm just using this name to +起这个名字是为了 + +1071 +00:43:12,312 --> 00:43:14,612 +really make it clear to you what's happening here. +让你们理解这里发生了什么 + +1072 +00:43:14,614 --> 00:43:19,983 +It's a UIDynamicItemBehavior and I'm doing this again cuz +它的类型是 UIDynamicItemBehavior + +1073 +00:43:19,985 --> 00:43:22,585 +I want to configure it just like I did for the collider. +我这样做,是想和设置 collider 一样,设置它 + +1074 +00:43:22,587 --> 00:43:25,154 +And so let's do it so that things can't rotate. +在这里让方块不再旋转 + +1075 +00:43:25,156 --> 00:43:28,524 +So one of the things you can do is allowsRotation false. +把 allowsRotation 设置为 false + +1076 +00:43:28,526 --> 00:43:29,875 +'Kay? + +1077 +00:43:29,876 --> 00:43:31,225 +Another thing you can do is the bounciness, +另一件事是弹跳高度 + +1078 +00:43:31,228 --> 00:43:32,927 +which is the elasticity. +就是 elasticity + +1079 +00:43:32,929 --> 00:43:35,663 +So I'm gonna set the elasticity to about 0.75. +设置成 0.75 + +1080 +00:43:35,665 --> 00:43:39,700 +Elasticity of 1.0 is perfect elasticity. +设置为 1.0 是完全失重 + +1081 +00:43:39,702 --> 00:43:41,902 +So a thing bounces off something, it will have the +弹跳的时候 + +1082 +00:43:41,904 --> 00:43:46,039 +same amount of energy coming off as it had coming in, 'kay? +能量完全不损失 + +1083 +00:43:46,041 --> 00:43:47,373 +Perfect [INAUDIBLE], so 0.7, +完全失重 + +1084 +00:43:47,375 --> 00:43:49,241 +these things will eventually settle down. +0.75表示这些东西最终会安定下来 + +1085 +00:43:50,544 --> 00:43:52,010 +Okay? So there's that, +好了 + +1086 +00:43:52,012 --> 00:43:55,346 +we will return our lazilyCreatedDropBehavior +返回 lazilyCreatedDropBehavior + +1087 +00:43:55,348 --> 00:43:55,913 +here. + +1088 +00:43:55,915 --> 00:43:58,882 +And so all we need to do to make that work, again, +还需要做的事情是 + +1089 +00:43:58,884 --> 00:44:00,717 +is add it as a child behavior here. +把它添加为 child behavior + +1090 +00:44:00,719 --> 00:44:06,089 +Oops, drop behavior, and +dropBehavior + +1091 +00:44:06,091 --> 00:44:10,526 +also make sure that we add any drops to it aswell. +确保把 drop 也添加了 + +1092 +00:44:10,528 --> 00:44:13,462 +DropBehavior.addItem, the drop, and +DropBehavior.addItem 参数为 drop + +1093 +00:44:13,464 --> 00:44:15,130 +same thing down here. +下面也是一样 + +1094 +00:44:16,066 --> 00:44:19,233 +DropBehavior.removeItem, the drop. +DropBehavior.removeItem 参数 drop + +1095 +00:44:19,235 --> 00:44:21,135 +Okay? + +1096 +00:44:21,136 --> 00:44:23,036 +So we don't have to change anything in the other place. +在其它地方我们不需要改变 + +1097 +00:44:23,039 --> 00:44:25,372 +Okay, back over here, we change nothing, +回到这里,什么也不改 + +1098 +00:44:25,374 --> 00:44:27,474 +because we're only changing behaviors here. +因为我们只需要改变 behavior + +1099 +00:44:27,476 --> 00:44:30,276 +So this code has delegated all its behavior off to +这个代码把所有的 behavior 交给了 + +1100 +00:44:30,278 --> 00:44:32,028 +the dropIt behavior. +DropItBehavior + +1101 +00:44:32,029 --> 00:44:33,779 +Question? >> [INAUDIBLE] How come like, +[学生提问] + +1102 +00:44:33,781 --> 00:44:36,782 +we can, I guess, use the lazy variables in our init if +[学生提问] + +1103 +00:44:36,784 --> 00:44:40,686 +they're not created until init is finished, you know? +[学生提问] + +1104 +00:44:40,688 --> 00:44:44,022 +>> Well, it's, so the question is how can I do this, +问题是 + +1105 +00:44:44,024 --> 00:44:46,107 +basically? + +1106 +00:44:46,108 --> 00:44:48,191 +How am I allowed, during initialization, to, you know, +我怎么可以在初始化的时候这样做呢? + +1107 +00:44:48,194 --> 00:44:49,360 +not have this set? +先不让它被设定好 + +1108 +00:44:49,362 --> 00:44:50,728 +And well, and the answer is, +答案是 + +1109 +00:44:50,730 --> 00:44:52,262 +it's a feature of the language. +这是语言的特性 + +1110 +00:44:52,264 --> 00:44:56,232 +It will suspend the rule that says that all things must be +它会延缓初始化的过程 + +1111 +00:44:56,234 --> 00:45:00,102 +initialized as long as you've set it to something that +直到你开始引用它 + +1112 +00:45:00,104 --> 00:45:02,738 +can be you know, determined later. +在之后初始化 + +1113 +00:45:02,740 --> 00:45:05,307 +So lazy variables, if they're marked lazy, +对于 lazy 变量 + +1114 +00:45:05,309 --> 00:45:07,976 +they don't have to be initialized at init time. +在初始化的时候,它们不需要被初始化 + +1115 +00:45:07,978 --> 00:45:09,477 +That's what lazy means, +这就是 lazy 的意思 + +1116 +00:45:09,479 --> 00:45:12,279 +does not have to be initialized at init time. +不需要在初始化的时候被初始化 + +1117 +00:45:12,281 --> 00:45:13,914 +But the first time someone accesses it, +直到某人引用它 + +1118 +00:45:13,916 --> 00:45:16,116 +it's going to be initialized, even if it wasn't a closure. +它才会被初始化,即使它不是闭包 + +1119 +00:45:16,118 --> 00:45:18,752 +Even if we set it to be equal to something else, +即使我们把它设置为等于其它东西 + +1120 +00:45:18,754 --> 00:45:22,621 +that would happen at the time someone accesses it. +它会在某人引用它的时候被创建 + +1121 +00:45:22,623 --> 00:45:23,822 +That's going to have to be, +这就表明 + +1122 +00:45:23,824 --> 00:45:26,558 +by definition, after the full initialization. +在完全初始化之后 + +1123 +00:45:26,560 --> 00:45:29,060 +Because no one can access any properties until full +因为在完全初始化完毕之前 + +1124 +00:45:29,062 --> 00:45:29,727 +initialization. +没人可以引用属性 + +1125 +00:45:29,729 --> 00:45:31,629 +Make sense? +听懂了吗 + +1126 +00:45:31,631 --> 00:45:33,281 +Okay? + +1127 +00:45:33,282 --> 00:45:34,932 +If you have more questions I could cover it more, but +如果你还有问题,我也可以再说一些 + +1128 +00:45:34,934 --> 00:45:36,733 +that's the basic deal on the lazies. +这是 lazy 最基本的特点 + +1129 +00:45:36,735 --> 00:45:37,867 +Yeah? + +1130 +00:45:37,869 --> 00:45:41,904 +So previous to that there were some small gaps, +[学生提问] + +1131 +00:45:41,906 --> 00:45:46,475 +S and Q, sets the size of the general view to be equal to +[学生提问] + +1132 +00:45:46,477 --> 00:45:51,413 +the size of the whole content divided by like [INAUDIBLE]. +[学生提问] + +1133 +00:45:51,415 --> 00:45:53,314 +>> There were no gaps along top. +在顶部没有间隔 + +1134 +00:45:53,316 --> 00:45:54,749 +It was only when they started falling and +它只有在掉落并且 + +1135 +00:45:54,751 --> 00:45:57,217 +tilting a little that they made gaps between each other. +倾斜一点的时候它们之间才有间隔 + +1136 +00:45:58,253 --> 00:45:59,552 +Watch, okay? +看 + +1137 +00:45:59,554 --> 00:46:02,521 +So here, look how much springier now we are. +现在看起来多有弹性 + +1138 +00:46:02,523 --> 00:46:04,857 +And also notice they can't tilt, so +现在也不能倾斜了 + +1139 +00:46:04,859 --> 00:46:06,358 +they stay in their columns. +它们就在固定的列中 + +1140 +00:46:06,360 --> 00:46:07,792 +You're gonna see there's no gaps now. +之间没有间隔了 + +1141 +00:46:08,795 --> 00:46:11,295 +Okay, it was only the tilting that was causing them to +只有倾斜会让 + +1142 +00:46:11,297 --> 00:46:12,963 +have gaps. +它们之间产生间隔 + +1143 +00:46:12,964 --> 00:46:14,630 +So, you can send these things down, +让它们掉落 + +1144 +00:46:14,631 --> 00:46:16,297 +there bouncing off each other and also off the bottom. +它们会在底部和彼此之间弹跳 + +1145 +00:46:17,502 --> 00:46:19,869 +Okay? And they eventually +最后 + +1146 +00:46:19,871 --> 00:46:20,703 +settle into stasis. +它们会停下来 + +1147 +00:46:22,406 --> 00:46:22,971 +Okay? + +1148 +00:46:24,307 --> 00:46:25,807 +Everybody got that? +每个人都懂了吗 + +1149 +00:46:25,809 --> 00:46:27,525 +All right? The next thing we're gonna do +下一步要做的是 + +1150 +00:46:27,526 --> 00:46:29,242 +in our fun game is, we're going to do a Tetris-like +做一个像俄罗斯方块一样类似的效果 + +1151 +00:46:29,245 --> 00:46:34,047 +thing, which is, when a row is fully clear, question? +当一行满了以后,消除 + +1152 +00:46:34,049 --> 00:46:36,266 +Yeah? >> Why +[学生提问] + +1153 +00:46:36,267 --> 00:46:38,484 +are all the boxes completely aligned horizontally? +[学生提问] + +1154 +00:46:38,487 --> 00:46:39,786 +>> Why are they completely aligned horizontally? +它们在水平方向是对齐的吗? + +1155 +00:46:39,788 --> 00:46:40,887 +>> Well, they're not. +它们不是 + +1156 +00:46:40,888 --> 00:46:41,987 +Like, some of them are a little higher. +有一些高一点 + +1157 +00:46:41,989 --> 00:46:43,589 +>> Oh, yeah, why are there slight differences? +为什么有轻微的差异 + +1158 +00:46:43,591 --> 00:46:48,193 +Well, I'm not a 100% sure of why that is. +我不是百分百确定 + +1159 +00:46:48,195 --> 00:46:52,730 +I think it's because, and don't quote me on this 100%, +我认为 + +1160 +00:46:52,732 --> 00:46:54,932 +but I think it's because when the thing is animating, +当它们在做动画效果是 + +1161 +00:46:54,934 --> 00:46:57,901 +it's not animating on integer boundaries, okay? +分界线不是整数 + +1162 +00:46:57,903 --> 00:47:00,970 +And I think the things can slightly overlap by tiny +它们的一小部分 + +1163 +00:47:00,972 --> 00:47:01,604 +fractions. +会重叠 + +1164 +00:47:01,606 --> 00:47:03,840 +But it's enough for +这足以让它们 + +1165 +00:47:03,841 --> 00:47:06,075 +one or more to draw slightly one pixel or point off. +在绘图的时候产生一个像素或点的偏差 + +1166 +00:47:06,077 --> 00:47:06,642 +That make sense? +有道理吧 + +1167 +00:47:07,778 --> 00:47:08,543 +But that's a good question. +好问题 + +1168 +00:47:08,545 --> 00:47:10,629 +I've noticed that as well, and +我也注意到了 + +1169 +00:47:10,630 --> 00:47:12,714 +it's like right in here, see those two guys right there? +看这里的这两个 + +1170 +00:47:12,716 --> 00:47:13,614 +Slightly different. +有轻微的不同 + +1171 +00:47:14,617 --> 00:47:15,849 +So yeah, good question there. +好问题 + +1172 +00:47:17,085 --> 00:47:19,419 +All right, back to where we were here. +回到我们这里 + +1173 +00:47:20,588 --> 00:47:23,188 +So what I wanna do is remove a whole row when +我想做的是 + +1174 +00:47:23,190 --> 00:47:27,125 +a row is complete and when my animation settles down. +当稳定下来以后,一行被填满了,把这行消掉 + +1175 +00:47:27,127 --> 00:47:30,261 +Okay, when my animation stops, pauses, and +当动画停止的时候 + +1176 +00:47:30,263 --> 00:47:33,164 +a whole row is full, I want to remove it. +一行满了,把这行去掉 + +1177 +00:47:33,166 --> 00:47:36,067 +Okay? So how am I gonna do that? +该怎样实现 + +1178 +00:47:36,068 --> 00:47:38,969 +Well, I have a nice function called removeCompletedRow +创建一个新方法 removeCompletedRow + +1179 +00:47:38,971 --> 00:47:44,341 +which I'm gonna type in really fast, again, here it is. +快速输入 + +1180 +00:47:44,343 --> 00:47:45,508 +Don't worry about this, +别担心 + +1181 +00:47:45,510 --> 00:47:47,109 +you can look at this after lecture. +在课后你也可以看到这个 + +1182 +00:47:47,111 --> 00:47:50,079 +It's not doing anything except for looking for +它只做一些 + +1183 +00:47:50,081 --> 00:47:53,615 +rows that are full, and when it finds a row that's full, +寻找哪一行是满的,然后遍历这一行 + +1184 +00:47:53,617 --> 00:47:56,084 +it goes through and calls removeDraw. +调用 removeDrop + +1185 +00:47:56,086 --> 00:47:58,586 +Right, in my dropping behavior on all of the things +对于我 drop behavior 中的 + +1186 +00:47:58,588 --> 00:47:59,186 +in the row. +每一个 + +1187 +00:47:59,188 --> 00:47:59,820 +That's all it does. +这就是它做的 + +1188 +00:47:59,822 --> 00:48:02,289 +Okay? + +1189 +00:48:02,290 --> 00:48:04,757 +All this is just finding the ones that are all in a row, or +这是寻找一行中 + +1190 +00:48:04,760 --> 00:48:07,293 +that complete a row or mostly complete a row. +是满的那种情况 + +1191 +00:48:07,295 --> 00:48:09,629 +It allows a little bit of gaps in there. +它允许其中有一些小小的间隔 + +1192 +00:48:09,631 --> 00:48:10,629 +And then this just removes it. +接着,移除它 + +1193 +00:48:10,631 --> 00:48:12,097 +It only removes one row though. +它只会删除一行 + +1194 +00:48:12,099 --> 00:48:13,799 +It starts at the bottom, +从底部开始 + +1195 +00:48:13,801 --> 00:48:15,867 +starts going up til it finds a row and then it removes it. +找到一行删除一行 + +1196 +00:48:15,869 --> 00:48:16,501 +So it only does one. +一次一行 + +1197 +00:48:17,603 --> 00:48:19,820 +All right? + +1198 +00:48:19,821 --> 00:48:22,038 +Now, how do we get this remover completed row called? +我们在哪里调用这个方法? + +1199 +00:48:22,041 --> 00:48:24,108 +Okay, well, + +1200 +00:48:24,109 --> 00:48:26,176 +I'm gonna call it when the animation settles down. +我将在动画停下来的时候调用 + +1201 +00:48:26,178 --> 00:48:29,112 +And I told you that I can find that out using my dynamic +我们可以使用 dynamic animator 的代理方法 + +1202 +00:48:29,114 --> 00:48:30,580 +animator's delegate. + +1203 +00:48:30,582 --> 00:48:34,216 +So, here's my dynamic animator right here being created. +这是我创建的 dynamic animator + +1204 +00:48:34,218 --> 00:48:36,251 +I'm actually just right here gonna say. +把它的代理 + +1205 +00:48:36,253 --> 00:48:40,989 +Make my dynamic animator's delegate, be myself. +设置为我自己 + +1206 +00:48:40,991 --> 00:48:42,623 +Okay? And of course we know that's +当然 + +1207 +00:48:42,625 --> 00:48:43,991 +going to cause an error. +这会引发一个错误 + +1208 +00:48:43,993 --> 00:48:45,526 +Right here. And that error is, +在这里 + +1209 +00:48:45,528 --> 00:48:48,428 +you don't implement the UIDynamicAnimatorDelegate +错误是没有实现 UIDynamicAnimatorDelegate 的协议 + +1210 +00:48:48,430 --> 00:48:49,095 +protocol. + +1211 +00:48:49,097 --> 00:48:52,198 +So okay, no problem. +没问题 + +1212 +00:48:52,200 --> 00:48:53,499 +UIDynamicAnimatorDelegate. + +1213 +00:48:53,501 --> 00:48:54,199 +Okay? + +1214 +00:48:54,201 --> 00:48:55,767 +Problem solved. +问题解决 + +1215 +00:48:55,769 --> 00:48:58,269 +There's only two methods in that protocol. +协议中只有两个方法 + +1216 +00:48:58,271 --> 00:48:59,137 +They're both optional. +都是可选的 + +1217 +00:48:59,139 --> 00:49:00,871 +You don't have to implement them. +不需要都实现 + +1218 +00:49:00,873 --> 00:49:04,708 +The one we want is dynamicAnimatorDidPause. +其中之一是 dynamicAnimatorDidPause + +1219 +00:49:04,710 --> 00:49:06,710 +See, here's the two methods. +这是这两个方法 + +1220 +00:49:06,712 --> 00:49:08,144 +We want this one, DidPause. +我需要这个 + +1221 +00:49:08,146 --> 00:49:09,679 +So when it pauses, in other words, +当它停下来的时候 + +1222 +00:49:09,681 --> 00:49:13,482 +it's reached stasis, for now anyway, it's gonna pause. +换句话说,停滞的时候 + +1223 +00:49:13,484 --> 00:49:17,118 +And when it pauses, I'm going to remove CompletedRow and +停下来的时候,调用 removeCompletedRow + +1224 +00:49:17,120 --> 00:49:18,019 +that's it. +就是这样 + +1225 +00:49:19,188 --> 00:49:20,487 +Nothing else required. +不需要其他 + +1226 +00:49:20,489 --> 00:49:21,555 +So we'll see if that works. +看看有没有效果 + +1227 +00:49:23,291 --> 00:49:24,991 +Alright, so put a bunch of drops down here. +掉一堆方块下去 + +1228 +00:49:24,993 --> 00:49:29,962 +Now if it comes to stasis but there is no completed +当它停下来 + +1229 +00:49:29,964 --> 00:49:32,631 +row which there isn't because there's gaps in this row, +我们还没有完成一行 + +1230 +00:49:32,633 --> 00:49:34,650 +it does nothing. +所以它什么都没做 + +1231 +00:49:34,651 --> 00:49:36,668 +But if I throw some more down here, enough that it completes +再放下一些 + +1232 +00:49:36,670 --> 00:49:39,470 +a row, which this is going to complete a row. +完成了一行 + +1233 +00:49:39,472 --> 00:49:42,440 +Okay. Once it settles and pauses, +当它停下来的时候 + +1234 +00:49:42,442 --> 00:49:46,576 +then it will remove the drops and the other ones will fall. +它会移除这一行,其他的将会掉落下来 + +1235 +00:49:46,578 --> 00:49:47,544 +Okay? + +1236 +00:49:47,545 --> 00:49:48,511 +Now, the two things to notice here. +有两点值得注意 + +1237 +00:49:48,513 --> 00:49:50,079 +One, it waited till we paused. +一,它等到完全停下来 + +1238 +00:49:50,081 --> 00:49:51,013 +That was cool. +这很酷 + +1239 +00:49:51,015 --> 00:49:52,781 +Two, after it removed them, +二,移除它们以后 + +1240 +00:49:52,783 --> 00:49:54,950 +everything else started animating again. +所有的东西又再次开始动画 + +1241 +00:49:54,952 --> 00:49:57,118 +Because nothing was underneath them. +因为它们下面没有东西 + +1242 +00:49:57,120 --> 00:50:00,855 +Gravity kept pulling them down and they fell. +重力使它们下坠 + +1243 +00:50:00,857 --> 00:50:02,189 +Okay? I didn't do anything +我什么都没做 + +1244 +00:50:02,191 --> 00:50:03,490 +to say keep going. +“继续”啊之类的也没有 + +1245 +00:50:03,492 --> 00:50:06,126 +It's just as soon as the gravity could work on those +直到重力发现它可以工作了 + +1246 +00:50:06,128 --> 00:50:08,027 +things, they started working. +它就会工作 + +1247 +00:50:08,029 --> 00:50:09,295 +Okay? It's important to notice +对于 behavior + +1248 +00:50:09,297 --> 00:50:11,263 +the animator, even if it's paused, +即使动画停止了 + +1249 +00:50:11,265 --> 00:50:14,132 +it's always waiting for a behavior to do something. +它也在等着时机,看能不能做一些是事情 + +1250 +00:50:14,134 --> 00:50:14,699 +Okay? + +1251 +00:50:15,635 --> 00:50:16,934 +So that's cool, +这很酷 + +1252 +00:50:16,935 --> 00:50:18,234 +and this happens even if I have multiple rows, so +如果我有多行 + +1253 +00:50:18,237 --> 00:50:20,404 +let's just make it so there's a whole bunch of rows. +多掉一些,填充多行 + +1254 +00:50:20,406 --> 00:50:21,471 +That are complete and +完成了 + +1255 +00:50:22,774 --> 00:50:27,043 +you'll see that it will remove a row and +你会发现它会先移除一行 + +1256 +00:50:27,045 --> 00:50:29,278 +then it will pause again and it'll just remove another row. +然后它会再次暂停,移除另一行 + +1257 +00:50:29,280 --> 00:50:34,516 +Okay, and you know, +你知道 + +1258 +00:50:34,518 --> 00:50:36,951 +depending on how many things are stacked up and +取决于这个方块是怎样罗列起来的 + +1259 +00:50:36,953 --> 00:50:38,953 +how it does, you'll have different response to it. +会造成不同的反应 + +1260 +00:50:38,955 --> 00:50:40,254 +Okay? + +1261 +00:50:40,256 --> 00:50:42,489 +Now, let's go back and make it so +回到这里 + +1262 +00:50:42,491 --> 00:50:44,758 +they can rotate and let's see what happens again. +如果让它们可以旋转呢,会发生什么 + +1263 +00:50:44,760 --> 00:50:46,426 +So, how can we make it rotate? +如何让它们旋转 + +1264 +00:50:46,428 --> 00:50:47,827 +Trivial. +这一点 + +1265 +00:50:47,828 --> 00:50:49,227 +We just go back to here and just turn this, +来到这里 + +1266 +00:50:49,230 --> 00:50:54,032 +allows rotation, back to true, which is the default, okay? +把它改为默认的 true + +1267 +00:50:54,034 --> 00:50:54,733 +And run again. +再次运行 + +1268 +00:50:56,036 --> 00:50:57,535 +'Kay. + +1269 +00:50:57,537 --> 00:50:58,969 +So let's put a bunch of them down here again. +多掉下来一些 + +1270 +00:50:58,971 --> 00:51:01,038 +Now they're gonna start banging into the edges of each +它们会到处碰装 + +1271 +00:51:01,040 --> 00:51:02,772 +other, and they'll start rotating and +会开始旋转 + +1272 +00:51:02,774 --> 00:51:05,575 +bouncing around all over the place, right? +到处弹跳 + +1273 +00:51:05,577 --> 00:51:07,910 +But they're still filling up rows. +但它们还会填满一行 + +1274 +00:51:07,912 --> 00:51:08,944 +'Kay? + +1275 +00:51:08,946 --> 00:51:10,012 +'Kay? + +1276 +00:51:10,014 --> 00:51:11,446 +See? They're kinda bouncing around? +它们还会弹起 + +1277 +00:51:16,586 --> 00:51:17,618 +There we go. +好啦 + +1278 +00:51:17,620 --> 00:51:18,652 +Okay. Too big of +这中间 + +1279 +00:51:18,653 --> 00:51:19,685 +a gap on that last one. +间隔太大了 + +1280 +00:51:19,688 --> 00:51:21,955 +And if I put more down here, I'll get again. +如果再放一些,会消掉的 + +1281 +00:51:21,957 --> 00:51:23,122 +Okay? + +1282 +00:51:23,124 --> 00:51:24,474 +Everybody cool with that? +都懂了吗 + +1283 +00:51:24,475 --> 00:51:25,825 +Understand what's going on there with that pausing +理解暂停那一下发生的事情 + +1284 +00:51:25,827 --> 00:51:27,426 +business and the fact that the animator is +还有 animator 一直试图 + +1285 +00:51:27,428 --> 00:51:28,994 +always trying to continue animating? +继续动画 + +1286 +00:51:28,996 --> 00:51:29,861 +Okay. + +1287 +00:51:29,863 --> 00:51:32,530 +All right. + +1288 +00:51:32,532 --> 00:51:34,665 +The next thing, I think we have time for +下一项内容,应该还有时间 + +1289 +00:51:34,667 --> 00:51:37,567 +both of these things, the next thing we're gonna do is +下一项 + +1290 +00:51:40,205 --> 00:51:42,605 +let's talk about this collider a little more right now. +我们深入讨论一下碰撞 + +1291 +00:51:42,607 --> 00:51:45,341 +The collider is only colliding with each other and +现在它只会彼此碰撞 + +1292 +00:51:45,343 --> 00:51:47,076 +colliding with the walls. +还有和墙碰撞 + +1293 +00:51:47,078 --> 00:51:49,444 +What if I wanna put something right, like a big, +如果我想在其中添加一个大的 + +1294 +00:51:49,446 --> 00:51:52,347 +I'm gonna put a circle right in the center of my. +圆形,在 view 的中间 + +1295 +00:51:52,349 --> 00:51:55,216 +View and have the things hit that and bounce off. +使得方块撞击它,然后弹开 + +1296 +00:51:55,218 --> 00:51:57,752 +So how do I create an arbitrary boundary, basically? +我怎样能够创建一个任意的边界呢 + +1297 +00:51:57,754 --> 00:52:00,087 +Well, the boundaries are created using bezier paths, +可以通过 berizerpath 来创建边界 + +1298 +00:52:00,089 --> 00:52:01,188 +as I said. + +1299 +00:52:01,190 --> 00:52:03,723 +And you can create a boundary, +你可以创建一个边界 + +1300 +00:52:03,725 --> 00:52:06,125 +it doesn't have to have any graphical representation. +它不有任何图形代表 + +1301 +00:52:06,127 --> 00:52:07,526 +So, in fact, I'm gonna start by doing that. +现在开始 + +1302 +00:52:07,528 --> 00:52:10,796 +So I'm gonna go to my drop it behavior right here. +回到这个类中 + +1303 +00:52:10,798 --> 00:52:14,333 +And I'm gonna make public a method, I'm gonna create +写一个共有方法 + +1304 +00:52:14,335 --> 00:52:17,235 +a public method to add a boundary, okay? +用它创建一个边界 + +1305 +00:52:17,237 --> 00:52:19,771 +So I'm gonna call it addBarrier actually cause +起名为 addBarrier + +1306 +00:52:19,773 --> 00:52:21,772 +it's gonna add a barrier somewhere, +因为它会在某处 + +1307 +00:52:21,774 --> 00:52:25,709 +a barrier to these things coming down or whatever. +添加一个 Barrier + +1308 +00:52:25,711 --> 00:52:29,746 +I'm going to call this, these things need to be named. +这个边界需要被命名 + +1309 +00:52:29,748 --> 00:52:31,547 +Remember I told you about the. +还记得吗 + +1310 +00:52:31,549 --> 00:52:33,816 +Barrier, or the boundaries. +barrier 或者是边界 + +1311 +00:52:33,818 --> 00:52:36,585 +They have like an integer, or a string, or whatever. +它们需要有一个 integer 或者 string 类型的名字 + +1312 +00:52:36,587 --> 00:52:38,987 +So I'm going to use a string to name these things. +在这里我用 stirng + +1313 +00:52:38,989 --> 00:52:41,523 +So I'm going to pass in a Bezier path, +传入一个 bezierpath + +1314 +00:52:41,525 --> 00:52:43,791 +and I'm going to name it. +需要起名 + +1315 +00:52:43,793 --> 00:52:45,926 +So I'm going to have an argument called name. +所以需要一个 name 参数 + +1316 +00:52:47,196 --> 00:52:48,429 +Okay? And + +1317 +00:52:48,430 --> 00:52:49,663 +I'm just going to call the colliders things and +调用 collider + +1318 +00:52:49,665 --> 00:52:54,300 +you're going to remove any old boundary with that name. +利用 name 参数去除之前旧的边界 + +1319 +00:52:54,302 --> 00:52:57,570 +And then I'm just gonna add a new boundary,'kay? +然后再添加一个新的边界 + +1320 +00:52:57,572 --> 00:53:00,773 +Look at that name and that path. +看这个 name 还有 path + +1321 +00:53:00,775 --> 00:53:02,158 +That's all I'm doing. +这就是我在做的事情 + +1322 +00:53:02,159 --> 00:53:03,542 +I'm just kind of making a nice simple method here +在这里定义了一个方法 + +1323 +00:53:03,544 --> 00:53:04,909 +that removes the old one and adds the new one. +去掉之前旧的,然后添加一个新的 + +1324 +00:53:04,911 --> 00:53:06,577 +So, it only, + +1325 +00:53:06,579 --> 00:53:09,046 +there's only gonna be one barrier with that name, and +它只会利用这一个名字定义一个 barrier + +1326 +00:53:09,048 --> 00:53:11,982 +I can move it any time by just saying add barrier,'kay? +我可以在任何时候移动它通过调用 addBarrier + +1327 +00:53:11,984 --> 00:53:13,950 +So add barrier removes the old version of it. +然后 Barrier 就可以移除它的旧版本 + +1328 +00:53:13,952 --> 00:53:14,884 +So that's add barrier. +这就是这个方法 + +1329 +00:53:14,886 --> 00:53:16,586 +[COUGH] And so. + +1330 +00:53:16,588 --> 00:53:18,954 +We can put that barrier in there. +我们可以把 barrier 放在这里 + +1331 +00:53:18,956 --> 00:53:20,255 +Invisibly. +不可见的 + +1332 +00:53:20,257 --> 00:53:24,426 +Let's put it maybe in our view did layout sub views. +可以放进 viewDidLayoutSubViews 方法中 + +1333 +00:53:24,428 --> 00:53:26,160 +So every time we change our bounds, +任何时候改变 bounds 的时候 + +1334 +00:53:26,162 --> 00:53:29,330 +we'll move this barrier to the very center of that. +我们改变 barrier 到 view 的中央 + +1335 +00:53:29,332 --> 00:53:32,366 +So I'm going to override view did layout sub views here. +所以我在这里重写 viewDidLayoutSubViews + +1336 +00:53:32,368 --> 00:53:36,836 +Super ob views did labs sub views I want it right in +super.viewDidLayoutSubViews + +1337 +00:53:36,838 --> 00:53:41,774 +the center, so I'm gonna, well let's have the size of it be, +我希望它在最中间 + +1338 +00:53:41,776 --> 00:53:44,043 +how about the same size as a drop? +它的尺寸设置为和方块的尺寸一样怎么样 + +1339 +00:53:44,045 --> 00:53:45,111 +Just to be simple. +只是为了简单 + +1340 +00:53:45,112 --> 00:53:46,178 +Okay, I'm gonna have this barrier that I'm gonna put in +把和方块一样尺寸的 barrier + +1341 +00:53:46,180 --> 00:53:48,446 +the middle be the same size as a drop. +放到 view 的中间 + +1342 +00:53:48,448 --> 00:53:53,150 +I'm gonna have the origin of it be. +让它的 origin + +1343 +00:53:53,152 --> 00:53:55,386 +I keep this. + +1344 +00:53:55,388 --> 00:53:59,422 +Let's put it in the middle, so that's a game view, bounds, +因为要放在中间,所以等于 + +1345 +00:53:59,424 --> 00:54:07,963 +mid-x minus the barrier's size. +gameView.bounds.midX-BarrierSize.width/2 + +1346 +00:54:07,965 --> 00:54:10,265 +Barrier-size dot width divided by two, and + +1347 +00:54:10,267 --> 00:54:12,167 +then the game view's. + +1348 +00:54:12,169 --> 00:54:13,335 +Bounds mid-Y, + +1349 +00:54:13,337 --> 00:54:17,071 +minus the barriers size dot height divided by two. +gameView.bounds.midY-BarrierSize.height/2 + +1350 +00:54:17,073 --> 00:54:20,374 +So I'm just putting it in the middle,'kay? +把它放到中间 + +1351 +00:54:22,011 --> 00:54:26,112 +So let's let this UI Bezier path that we're gonna create +开始创建 UIBezierPath + +1352 +00:54:26,114 --> 00:54:28,047 +just be UI Bezier path. +let path = UIBezierPath + +1353 +00:54:28,049 --> 00:54:31,316 +We'll make it a circle using oval in rect,'kay, and +使用 ovalInRect 构造器 + +1354 +00:54:31,318 --> 00:54:32,984 +we'll make a CG rect. +创建一个 CGRect + +1355 +00:54:32,986 --> 00:54:36,354 +Which is the barrier origin and the barrier size. +参数是 barrierOrigin 和 barrierSize + +1356 +00:54:40,226 --> 00:54:42,760 +Okay so everybody understand I created a Besian path, +我创建了一个 bezierPaht + +1357 +00:54:42,762 --> 00:54:45,462 +that's a circle right in the middle that's the same size as +是一个在屏幕中央和方块尺寸一致的 + +1358 +00:54:45,464 --> 00:54:46,863 +a drop, okay? +圆形 + +1359 +00:54:46,865 --> 00:54:50,600 +And then I'm just going to tell my dropit behavior, +然后我通知 dropItBehavior + +1360 +00:54:50,602 --> 00:54:51,634 +add this barrier. +来添加这个 barrier + +1361 +00:54:53,104 --> 00:54:54,069 +And we'll call this barrier. +调用这个 barrier + +1362 +00:54:54,071 --> 00:54:55,704 +Let's be good coders again. +让我们成为一个好程序员! + +1363 +00:54:55,706 --> 00:54:56,771 +Let's say struct. +struct + +1364 +00:54:56,773 --> 00:54:59,140 +We'll call these path names. +PathNames + +1365 +00:54:59,142 --> 00:55:01,175 +Static. + +1366 +00:55:01,177 --> 00:55:07,781 +We'll call this one middle barrier or something. +把它起名为 MiddleBarrier + +1367 +00:55:09,517 --> 00:55:12,451 +This is gonna be the string we use so here we'll go. +这将会是我们使用的 string + +1368 +00:55:12,453 --> 00:55:16,054 +Path name dot middle barrier. +PathName.MiddleBarrier + +1369 +00:55:16,056 --> 00:55:17,539 +Okay? + +1370 +00:55:17,540 --> 00:55:19,023 +So I can add this barrier right here and +我在这里添加barrier + +1371 +00:55:19,026 --> 00:55:20,909 +that's all I need to do. +这是我需要做的全部工作 + +1372 +00:55:20,910 --> 00:55:22,793 +Once you add the barrier, the collider is already colliding +一旦你添加了 barrier + +1373 +00:55:22,796 --> 00:55:24,662 +so it's going to make things collide with it. +其他的物体就可以和它撞击 + +1374 +00:55:24,664 --> 00:55:26,296 +So let's see what this looks like. +让我们看看效果 + +1375 +00:55:26,298 --> 00:55:27,620 +Okay? + +1376 +00:55:27,621 --> 00:55:28,943 +see if we can tell. +看我们能不能看出来 + +1377 +00:55:28,944 --> 00:55:30,266 +Oh, do you see things bouncing away from the middle there? +看到物体被从中间弹开了吗 + +1378 +00:55:30,269 --> 00:55:31,167 +See that? +看到了吗 + +1379 +00:55:31,169 --> 00:55:32,669 +[SOUND] Okay? + +1380 +00:55:32,671 --> 00:55:36,638 +But it's a little bit bad because we can't see it. +有一点不好,就是我们看不到它 + +1381 +00:55:36,640 --> 00:55:38,073 +I'd like to see this barrier. +我想看到它 + +1382 +00:55:38,075 --> 00:55:39,541 +But that's an independent thing. +但是那是一个独立的东西 + +1383 +00:55:39,543 --> 00:55:41,676 +Seeing it versus it being there is different. +看到它和它在那里,是不同的 + +1384 +00:55:41,678 --> 00:55:44,445 +So to see it I'm actually gonna make my background +为了看到它 + +1385 +00:55:44,447 --> 00:55:46,063 +view right here. +我需要创建背景视图 + +1386 +00:55:46,064 --> 00:55:47,680 +Instead of being a generic UI view I'm gonna make it +这次不是一般的视图,而是 + +1387 +00:55:47,683 --> 00:55:50,283 +be a view that can draw Bezier paths. +可以画 bezierpath 的视图 + +1388 +00:55:50,285 --> 00:55:51,852 +Okay? Now, + +1389 +00:55:51,853 --> 00:55:53,420 +this is surprisingly simple to do. +这也很贱但 + +1390 +00:55:53,422 --> 00:55:54,520 +Okay? + +1391 +00:55:54,522 --> 00:55:56,889 +I'm just going to create a UI view. +创建一个 UIView 的 + +1392 +00:55:56,891 --> 00:55:59,892 +Subclass, UI view. +子类 + +1393 +00:55:59,894 --> 00:56:02,894 +I'm going to call it BezierPathsView and it's +起名为 BezierPathsView + +1394 +00:56:02,896 --> 00:56:06,531 +going to basically draw as many bezier paths as you want. +你可以在上面画任意多的 bezierpath + +1395 +00:56:06,533 --> 00:56:12,403 +They'll also be named, just like the boundaries are named. +这里也需要 name,就像边界有 name 一样 + +1396 +00:56:12,405 --> 00:56:13,888 +Okay? And + +1397 +00:56:13,889 --> 00:56:15,372 +I'm going to do this by saying var bezierPaths, +var bezierPahts + +1398 +00:56:15,374 --> 00:56:17,941 +these are my Bézier paths I'm going to have. +这里装我们 bezierpath + +1399 +00:56:17,943 --> 00:56:22,645 +It's just going to be a dictionary with strings as +类型是 string 为 key + +1400 +00:56:22,647 --> 00:56:27,616 +the keys and UIBezierPaths as the argument, okay? +UIBezierPath 为参数的字典 + +1401 +00:56:27,618 --> 00:56:29,151 +I'm going to, by the way, +顺便地 + +1402 +00:56:29,153 --> 00:56:32,487 +I haven't been doing private in the demo for expediency. +在 demo 中我还没有使用过 privte + +1403 +00:56:32,489 --> 00:56:34,288 +But, again, private is important and here, +在这里,privete 是很重要的 + +1404 +00:56:34,290 --> 00:56:36,457 +I am going to do the right privacy. +我将使用正确的公私有属性 + +1405 +00:56:36,459 --> 00:56:39,293 +So now, I'm going to have a function called, +创建一个方法 + +1406 +00:56:39,295 --> 00:56:40,811 +what did I call it? +起名为什么来着 + +1407 +00:56:40,812 --> 00:56:42,328 +Add path or something like that? +addPath 之类的? + +1408 +00:56:42,331 --> 00:56:44,097 +Yeah, setPath. +哦,setPath + +1409 +00:56:44,099 --> 00:56:46,666 +SetPath, and it's going to take a path, +参数是 UIBezierPath 类型的 + +1410 +00:56:46,668 --> 00:56:48,367 +which is a UI Bézier path. +path + +1411 +00:56:48,369 --> 00:56:50,969 +It's going to be optional because we're going to allow +它是可选的,因为我们可以允许你通过这个方法 + +1412 +00:56:50,971 --> 00:56:52,537 +you to clear out paths if you want, +清掉 path 如果你想的话 + +1413 +00:56:52,539 --> 00:56:54,773 +and then it's also going to let them be named. +然后需要 name 参数 + +1414 +00:56:56,009 --> 00:56:58,075 +And I'm just going to put it in that dictionary, +把它们放入字典中 + +1415 +00:56:58,077 --> 00:57:00,377 +just going to say Bézier paths. +bezierPahts[name] = path + +1416 +00:57:00,379 --> 00:57:03,847 +Path sub name equals the path. + +1417 +00:57:03,849 --> 00:57:07,183 +And of course, I just changed my model basically, so +刚刚改变了模型 + +1418 +00:57:07,185 --> 00:57:09,585 +I'm going to just setNeedsDisplay. +所以现在需要调用 setNeedsDisplay + +1419 +00:57:09,587 --> 00:57:13,322 +Okay? Then, to draw this, for +画出它们 + +1420 +00:57:13,324 --> 00:57:20,962 +underscore path in my bezierPaths, path.stroke. +for (_, path) in bezierPahts + +1421 +00:57:20,964 --> 00:57:23,181 +Okay, that's it. +path.stroke + +1422 +00:57:23,182 --> 00:57:25,399 +This is the entire implementation of this view. +这是整个 view 的实现 + +1423 +00:57:25,402 --> 00:57:26,134 +Okay? It's just going to +它将会以 + +1424 +00:57:26,136 --> 00:57:27,201 +stroke them in black. +空白的方式画出 + +1425 +00:57:27,203 --> 00:57:28,769 +We could add colors and all this stuff, but +我们也可以添加颜色 + +1426 +00:57:28,771 --> 00:57:30,437 +we're just going to stroke them all in black. +但空白的就行了 + +1427 +00:57:30,439 --> 00:57:32,038 +This is a numeration of a dictionary, +这是个字典的遍历 + +1428 +00:57:32,040 --> 00:57:33,690 +hopefully you recognize that. +希望你们看出来了 + +1429 +00:57:33,691 --> 00:57:35,341 +I don't care what the name is here while I'm doing this, +我不管 name 是什么 + +1430 +00:57:35,343 --> 00:57:36,575 +I only care the name because +我需要 name 是因为 + +1431 +00:57:36,577 --> 00:57:38,677 +I want to keep them unique is all. +我想让它们每个都是独一无二的 + +1432 +00:57:38,679 --> 00:57:41,130 +Okay? + +1433 +00:57:41,131 --> 00:57:43,582 +So now what I'm going to do is go back to my storyboard, and +现在回到 storyboard + +1434 +00:57:43,584 --> 00:57:45,583 +instead of this being a generic view, +换掉这个一般的视图 + +1435 +00:57:45,585 --> 00:57:48,219 +I'm going to go to the identity inspector, and +去到 identity inspector + +1436 +00:57:48,221 --> 00:57:50,888 +turn it into a BezierPathsView. +把它变成 BezierPathsView + +1437 +00:57:50,890 --> 00:57:54,258 +And also in my DropIt controller over here, +在 DropIt 控制器中 + +1438 +00:57:54,260 --> 00:57:57,160 +I'm going to change this outlet from being a generic +把这个出口从一般的 view 改为 + +1439 +00:57:57,162 --> 00:57:59,062 +UIView from being a BezierPathsView. +BezierPathsView + +1440 +00:57:59,064 --> 00:58:02,231 +So now the view that I'm doing all this animation is in +现在这个 view 既可以动画 + +1441 +00:58:02,233 --> 00:58:05,001 +can draw arbitrary Bézier paths, okay? +又能画任意的 bezierpath + +1442 +00:58:05,003 --> 00:58:06,201 +Very convenient because +非常方便 + +1443 +00:58:06,203 --> 00:58:08,070 +I'm going to have it draw that circle. +我可以让它画圆 + +1444 +00:58:08,072 --> 00:58:10,638 +Okay, that circle that we're having the collider do, +在这里的圆 + +1445 +00:58:10,640 --> 00:58:11,906 +which is right here. +让它产生碰撞 + +1446 +00:58:11,907 --> 00:58:13,173 +And I can do that with one line of code. +一行代码就可以实现 + +1447 +00:58:13,176 --> 00:58:16,444 +I'm just going to say gameView addPath, +gameView.setPath + +1448 +00:58:16,446 --> 00:58:21,314 +or setPath, the same path, and I'll use even the same name, +和上面相同的 path 和 name + +1449 +00:58:21,316 --> 00:58:24,351 +PathNames.MiddleBarrier, okay. + +1450 +00:58:24,353 --> 00:58:27,220 +The good thing now is every time viewDidLayoutSubview is +好的一面就是每次 viewDidLayoutSubview + +1451 +00:58:27,222 --> 00:58:28,921 +called, it'll replace, you know, +被调用 + +1452 +00:58:28,923 --> 00:58:32,324 +it'll move it to the middle and redraw it. +它就会移动到中间然后重新绘制 + +1453 +00:58:32,326 --> 00:58:33,225 +Okay? So let's now take +现在看看效果 + +1454 +00:58:33,227 --> 00:58:33,925 +a look at this. + +1455 +00:58:33,927 --> 00:58:36,527 +[COUGH] There it is. +好了 + +1456 +00:58:36,529 --> 00:58:37,328 +Now, we can see it. +现在能看到了 + +1457 +00:58:37,330 --> 00:58:39,063 +It's still a barrier, +它仍然是一个 barrier + +1458 +00:58:39,065 --> 00:58:42,732 +like it was before, so something hit it, come on. +和之前一样 + +1459 +00:58:42,734 --> 00:58:44,300 +There we go, boom, okay? +其他东西也会撞到它 + +1460 +00:58:44,302 --> 00:58:46,102 +And, you know, it's a complete barrier. +它是个完整的 barrier + +1461 +00:58:46,104 --> 00:58:50,138 +And it actually is along that Bézier path. +它实际上是沿着这个 bezierpath + +1462 +00:58:50,140 --> 00:58:52,140 +It's not, you know, the square containing it. +而不是这个圆圈包含着它 + +1463 +00:58:52,142 --> 00:58:53,742 +It is actually on it. +它实际上在边缘上 + +1464 +00:58:53,743 --> 00:58:55,343 +So if I fill up this thing all the way to where it starts +如果我把这里填满 + +1465 +00:58:55,345 --> 00:58:56,628 +getting to that, + +1466 +00:58:56,629 --> 00:58:57,912 +you'll start seeing them tip right up against. +你会看到它们完整地贴着它 + +1467 +00:58:57,914 --> 00:59:01,448 +Do you see how they pile right up against it, there? +看到了吗? + +1468 +00:59:01,450 --> 00:59:02,015 +Okay? + +1469 +00:59:03,118 --> 00:59:05,017 +So you can have an arbitrary Bézier path there. +所以你可以绘制任意的 bezierPath + +1470 +00:59:06,487 --> 00:59:07,486 +Okay? And if I rotate. +如果我旋转 + +1471 +00:59:08,522 --> 00:59:10,321 +Okay, it'll put it in the middle. +它将会出现在中间 + +1472 +00:59:10,323 --> 00:59:11,822 +Okay, it zoomed it out a little bit but +它放大了一点 + +1473 +00:59:11,824 --> 00:59:14,792 +some of the things fell off the edge when I rotated that. +有一些东西在我旋转之后掉出了屏幕 + +1474 +00:59:14,794 --> 00:59:16,727 +Got to be careful of that in your game too. +在游戏里也应该注意一下 + +1475 +00:59:16,729 --> 00:59:19,329 +When you rotate, +当你旋转的时候 + +1476 +00:59:19,330 --> 00:59:21,930 +if your bouncing ball is not in the middle area then, +如果你的球不在屏幕的中间部分 + +1477 +00:59:21,933 --> 00:59:24,033 +it's going to be outside the boundary and so +它会跳出边界 + +1478 +00:59:24,035 --> 00:59:27,502 +it's going to fly off into outer space forever, okay? +它会一直飞,飞到外太空的 + +1479 +00:59:28,872 --> 00:59:30,838 +Okay, so that's how we do barriers. +我们就是这么处理 barrier 的 + +1480 +00:59:30,840 --> 00:59:32,273 +And you're going to have your bricks are going to +你们也会创建砖块 + +1481 +00:59:32,275 --> 00:59:34,659 +be probably not round, +也许不是圆形的 + +1482 +00:59:34,660 --> 00:59:37,044 +well they could be round if you want, and you can put as +如果是圆的也可以 + +1483 +00:59:37,046 --> 00:59:40,213 +many of these little barriers as you want up here, okay? +你可以放任意多个障碍物在上面 + +1484 +00:59:40,215 --> 00:59:42,248 +And when you hit one of these, that delegate method, +当你击中其中一个的时候,代理方法 + +1485 +00:59:42,250 --> 00:59:43,816 +you're going to set yourselves a collision delegate. +你需要先设置代理 + +1486 +00:59:43,818 --> 00:59:46,285 +I don't really have time to do that, but, +我没有时间演示了 + +1487 +00:59:46,287 --> 00:59:50,889 +you know, you could make it do something, flash or +但你你可以制造一些效果 + +1488 +00:59:50,891 --> 00:59:53,258 +animate, whatever is required by the required tasks. +闪或者动,作业的一部分内容 + +1489 +00:59:54,461 --> 00:59:56,927 +Okay, the last kind of behavior I'm going to show you +最后一个 behavior 我要介绍给你们的是 + +1490 +00:59:56,929 --> 00:59:58,262 +is an attachment behavior. +attachment behavior + +1491 +00:59:58,264 --> 01:00:01,098 +So, the way I'm going to do this attachment, +使用它的方式是 + +1492 +01:00:01,100 --> 01:00:03,366 +let me show you here, is when a drop comes down, +当方块掉落下来 + +1493 +01:00:03,368 --> 01:00:06,002 +I'm going to be able to grab onto it with +我会抓住它 + +1494 +01:00:06,004 --> 01:00:09,338 +a piece of string, or more like a metal rod. +就像抓住一跟金属棒一样 + +1495 +01:00:09,340 --> 01:00:11,974 +Grab onto it and I can move it around, okay? +抓住它到处移动 + +1496 +01:00:11,976 --> 01:00:14,976 +Swing it around in a circle and let it fly if I want. +让它转圈,或者让它飞走 + +1497 +01:00:16,079 --> 01:00:17,395 +So, that's what I'm going to do. +我将会这样实现 + +1498 +01:00:17,396 --> 01:00:18,712 +I'm going to do that with an attachment behavior. +利用 attachment behavior + +1499 +01:00:18,715 --> 01:00:21,382 +I'm just going to create an attachment from where I start +先在拖动手势进行的时候 + +1500 +01:00:21,384 --> 01:00:25,252 +my pan to the middle of the drop, the currently +创建一个 attachment behavior 在方块中间 + +1501 +01:00:25,254 --> 01:00:28,988 +dropping drop, or the last dropped drop, basically. +正在掉落的或者最后一个掉落的 + +1502 +01:00:28,990 --> 01:00:30,723 +And then as I pan around, +在我滑动的时候 + +1503 +01:00:30,725 --> 01:00:33,258 +I'm just going to move the anchor point. +我会移动它的锚点 + +1504 +01:00:33,260 --> 01:00:36,194 +And because animation is all happy instantaneously, it's +因为动画发生在瞬间 + +1505 +01:00:36,196 --> 01:00:39,197 +just going to all magically animate to adapt to the fact +所以所有的动画都会神奇般地随着我改变它 + +1506 +01:00:39,199 --> 01:00:42,833 +that I'm moving the anchor point of this attachment. +的锚点而有效果 + +1507 +01:00:42,835 --> 01:00:44,085 +Okay? + +1508 +01:00:44,086 --> 01:00:45,336 +And all the other behaviors are still going to work on it, +其他的 behavior 还是会有效 + +1509 +01:00:45,338 --> 01:00:47,337 +the gravity, the collisions, +重力还有碰撞 + +1510 +01:00:47,339 --> 01:00:48,571 +all still going to work on that thing. +都会起作用 + +1511 +01:00:48,573 --> 01:00:50,306 +The attachment's just going to be another behavior. +连接是另外一个特性 + +1512 +01:00:50,308 --> 01:00:52,608 +Now I'm going to put this attachment in the controller +我会在控制器里添加这个attachment + +1513 +01:00:52,610 --> 01:00:54,443 +right here instead of in the behavior, just so +而不是在 behavior 中 + +1514 +01:00:54,445 --> 01:00:57,813 +you can see it all happening a little better. +这样你们看得效果更好 + +1515 +01:00:57,815 --> 01:01:00,715 +So let's do this kind of in multiple steps here. +这中间有几步过程 + +1516 +01:01:00,717 --> 01:01:03,818 +Let's go ahead and do the gesture first. +先添加手势 + +1517 +01:01:03,820 --> 01:01:07,088 +Okay, so to do the behavior, I need an attachment behavior, +为了实现这个 behavior,我需要一个 attachment behavior + +1518 +01:01:07,090 --> 01:01:09,590 +so I'm going to create an attachment behavior here, +所以我需要在这里创建一个 attachment behavior + +1519 +01:01:09,592 --> 01:01:11,758 +UI attachment behavior. +类型是 UIAttachmentBehavior + +1520 +01:01:11,760 --> 01:01:14,527 +Now, this one's going to be an optional because I only have +它是可选型的,因为只有我在 + +1521 +01:01:14,529 --> 01:01:16,829 +this attachment when I'm panning. +拖动的时候才会有这个属性 + +1522 +01:01:16,831 --> 01:01:18,397 +Okay? I don't have this attach, +我没有这个 attach + +1523 +01:01:18,399 --> 01:01:21,133 +it's nil basically, if I'm not currently attached to +它是 nil 的,如果我没拖着什么到处晃 + +1524 +01:01:21,135 --> 01:01:25,837 +something and panning around, whereas the dropping behavior +然而 drop behavior + +1525 +01:01:25,839 --> 01:01:27,605 +is happening all the time. +会一直存在 + +1526 +01:01:27,607 --> 01:01:29,057 +Okay? + +1527 +01:01:29,058 --> 01:01:30,508 +Again, I could put this attachment behavior +我可以把 attachment behavior + +1528 +01:01:30,510 --> 01:01:31,475 +in the dropping behavior. +放在 drop behavior 里 + +1529 +01:01:31,477 --> 01:01:32,993 +I could do that. +我可以这么做 + +1530 +01:01:32,994 --> 01:01:34,510 +I'm not going to, for kind of seeing it on screen, +但我不会这么做 + +1531 +01:01:34,513 --> 01:01:38,148 +the code on screen issue, but I could put it over there. +把它放到这里看起来更清楚 + +1532 +01:01:38,150 --> 01:01:39,015 +So I'm going to put it here. +所以我把它放到这里 + +1533 +01:01:39,017 --> 01:01:40,550 +So I have this attachment. +所以我有了 attachment + +1534 +01:01:40,551 --> 01:01:42,084 +We're going to have to do some things with this attachment in +一会儿再对这个 attachment 做些事情 + +1535 +01:01:42,086 --> 01:01:44,420 +a second, but let's just say we have this attachment. +但是现在我们已经有了这个 attachment + +1536 +01:01:44,422 --> 01:01:47,122 +Let's go add that pan gesture. +现在添加拖动手势 + +1537 +01:01:47,124 --> 01:01:50,792 +Okay, so we'll go over here, we'll go to our storyboard. +去到 storyboard + +1538 +01:01:50,794 --> 01:01:53,027 +Here's our storyboard right here. +这里就是 + +1539 +01:01:53,029 --> 01:01:55,096 +Let's go down and find pan. +找到 pan + +1540 +01:01:55,098 --> 01:01:56,063 +Where is it? +在哪呢 + +1541 +01:01:56,065 --> 01:01:58,365 +Pan? Right here. +在这 + +1542 +01:01:58,367 --> 01:01:59,966 +So let's add pan to this thing. +给它添加 pan 手势 + +1543 +01:01:59,968 --> 01:02:01,734 +Here's pan in the document outline. +在 document outline 有 pan + +1544 +01:02:02,737 --> 01:02:05,204 +Let's go ahead and +现在为 pan gesture + +1545 +01:02:05,205 --> 01:02:07,672 +put the pan gesture down here by the drop gesture, I guess. +设置出口 + +1546 +01:02:07,675 --> 01:02:09,741 +Okay, put her right there, okay, +放到这里 + +1547 +01:02:09,743 --> 01:02:13,645 +it's an action, we'll call it grabDrop. +它是一个 action,起名为 grabDrop + +1548 +01:02:13,647 --> 01:02:14,779 +Okay, because that's what it's going to do, +这就是它将要做的事情 + +1549 +01:02:14,781 --> 01:02:17,781 +it's going to grab onto a drop okay, here it is. +它将会捕获一个方块 + +1550 +01:02:19,118 --> 01:02:22,385 +All right that's all we need to do in our UI here. +在 UI 这里只需要做这些工作 + +1551 +01:02:22,387 --> 01:02:26,722 +Let's go back to our drop the controller. +回到控制器中 + +1552 +01:02:26,724 --> 01:02:29,591 +All right, so how are we going to implement this grab drop? +我们将如何实现这个方法呢 + +1553 +01:02:29,593 --> 01:02:30,892 +All right, we have that attachment, +我们有了 attachment + +1554 +01:02:30,894 --> 01:02:33,795 +basically all we need to do is, when we first start +我们需要做的时 + +1555 +01:02:33,797 --> 01:02:36,464 +our gesture, we need to create that attachment. +当手势开始的时候,创建 attachment + +1556 +01:02:36,466 --> 01:02:37,765 +Then as it moves, +移动的时候 + +1557 +01:02:37,766 --> 01:02:39,065 +we're just going to move that anchor point. +改变锚点的位置 + +1558 +01:02:39,068 --> 01:02:40,100 +And when it ends, +结束的时候 + +1559 +01:02:40,102 --> 01:02:42,602 +we're going to set the attachment back to nil. +把 attachment 设置为 nil + +1560 +01:02:42,604 --> 01:02:45,505 +So, this is incredibly easy to do. +实现起来很容易 + +1561 +01:02:45,507 --> 01:02:46,906 +You're finding all this, I hope, +希望你们都理解 + +1562 +01:02:46,908 --> 01:02:48,274 +to be pretty straightforward to do. +这很容易理解 + +1563 +01:02:48,276 --> 01:02:50,442 +It's a pretty amazing and powerful system. +iOS 是个非常强大的系统 + +1564 +01:02:50,444 --> 01:02:51,977 +But in this hand gesture, first, +在 pan gesture 中 + +1565 +01:02:51,979 --> 01:02:53,712 +I'm going to get the point. +首先,获取点 + +1566 +01:02:53,714 --> 01:02:55,913 +Okay? The gesture point, +手势的点 + +1567 +01:02:55,915 --> 01:02:59,116 +that is just the sender's location in our gainView. +它就是 sender.locationInView 参数为 gameView + +1568 +01:03:02,555 --> 01:03:05,722 +All right, so now I know where that pan is. +所以现在我知道了手势在哪里 + +1569 +01:03:05,724 --> 01:03:09,225 +And I'm just going to switch on what state we're in with +现在我需要判断这个手势 + +1570 +01:03:09,227 --> 01:03:11,227 +this gesture. +所处的状态 + +1571 +01:03:11,228 --> 01:03:13,228 +And if we're in began, so if the thing just began, +如果刚开始 + +1572 +01:03:13,231 --> 01:03:14,763 +then I'm just going to create the attachment. +我们需要创建这个 attachment + +1573 +01:03:14,765 --> 01:03:18,500 +So I'm going to say attachment equals UIAttachmentBehavior. +attachment = UIAttachmentBehavior + +1574 +01:03:18,502 --> 01:03:20,669 +Now, here's all the ways you can attach things. +这里是所有的构造方法 + +1575 +01:03:20,671 --> 01:03:22,804 +You can attach between two items, between an item and +你可以在两个物体之间连接,在一个物体和一个锚点上连接 + +1576 +01:03:22,806 --> 01:03:23,771 +an anchor. + +1577 +01:03:23,773 --> 01:03:26,106 +You can even attach between two items or +你也可以连接一个物体 + +1578 +01:03:26,108 --> 01:03:29,543 +an anchor with offset from the center, which is kind of a fun +以及一个锚点中心的偏移,这个很有趣 + +1579 +01:03:29,545 --> 01:03:32,679 +one because if it can rotate, then as it spins around, +因为它可以旋转 + +1580 +01:03:32,681 --> 01:03:35,181 +it will be spinning around because the attachment's not +attachment 并不是死死地 + +1581 +01:03:35,183 --> 01:03:36,382 +dead in the center, right? +呆在原点 + +1582 +01:03:36,384 --> 01:03:38,617 +It's right off onto the side. +它会在边上有一个偏移 + +1583 +01:03:38,619 --> 01:03:39,851 +It's not in the middle of the square. +不会再方块的中间 + +1584 +01:03:39,853 --> 01:03:41,820 +It might be in the corner and so it kind of rotates. +它也许在角落,所以可以旋转 + +1585 +01:03:41,822 --> 01:03:43,238 +So that's kind of fun. +还是很有趣的 + +1586 +01:03:43,239 --> 01:03:44,655 +But, we're just going to do to the center here. +在这里我只会实现在中间的 + +1587 +01:03:44,657 --> 01:03:47,591 +And so, we need to attach the item. +我们需要 attach 物体 + +1588 +01:03:47,593 --> 01:03:49,860 +So we want this one right here to the anchor. +我们选择这个 attachedToAnchor + +1589 +01:03:49,862 --> 01:03:51,061 +This is the one we want. +这是我们需要的 + +1590 +01:03:51,063 --> 01:03:53,363 +So the item, what item are we attaching to? +item,我们需要 attach 什么东西 + +1591 +01:03:53,365 --> 01:03:55,498 +Well, we're attaching to the last. +我们将要 attach 最后一个 + +1592 +01:03:55,500 --> 01:03:57,033 +DroppedView. +掉落的方块 + +1593 +01:03:57,035 --> 01:03:59,535 +So I'm gonna have to create a LastDroppedView, +我会创建一个 LastDroppedView + +1594 +01:03:59,537 --> 01:04:01,603 +which will have to go implement. +一会儿实现 + +1595 +01:04:01,605 --> 01:04:03,572 +And what anchor? +哪一点? + +1596 +01:04:03,573 --> 01:04:05,540 +Well, I'm gonna anchor it to the gesturePoint, 'kay? +把它设置为手势的那一点 + +1597 +01:04:05,542 --> 01:04:07,141 +Wherever that pan gesture is. +手势在哪,那一点就在哪 + +1598 +01:04:07,143 --> 01:04:08,709 +So let's do this lastDroppedView. +现在来处理 lastDroppedView + +1599 +01:04:08,711 --> 01:04:10,544 +That's easy. +这很简单 + +1600 +01:04:10,545 --> 01:04:12,378 +We'll just say var lastDroppedView. +创建 lastDroppedView + +1601 +01:04:12,381 --> 01:04:15,415 +It's a UIView that can be nil if we're not currently +类型是 UIView,它可以使 nil 如果现在还没有 + +1602 +01:04:15,417 --> 01:04:17,184 +dropping. +掉落的 + +1603 +01:04:17,185 --> 01:04:18,952 +And then down here in drop or we drop something, +在这里,掉落的时候 + +1604 +01:04:18,954 --> 01:04:21,721 +I'm just gonna say that the lastDroppedView equals to +把 lastDroppedView 等于 + +1605 +01:04:21,723 --> 01:04:23,389 +the dropView. +dropView + +1606 +01:04:23,390 --> 01:04:25,056 +'Kay, so I'm just keeping track of the lastDroppedView. +所以我在跟踪这个 lastDroppedView + +1607 +01:04:26,193 --> 01:04:28,460 +'Kay, that make sense? +能说得通吧 + +1608 +01:04:28,462 --> 01:04:31,463 +An exclamation point, yeah. +一个感叹号 + +1609 +01:04:31,465 --> 01:04:32,730 +No, we don't want that. +不,我不要这样 + +1610 +01:04:32,732 --> 01:04:36,734 +We want to say. +我们... + +1611 +01:04:36,736 --> 01:04:39,103 +And actually, I guess we'll always have last drop view. +实际上,我认为我们会一直拥有 lastDropView + +1612 +01:04:39,105 --> 01:04:42,572 +This is the kind of one where it's like, if let there, or +这里应该使用 if let + +1613 +01:04:42,574 --> 01:04:44,074 +do I just wanna do it. +或者直接解包 + +1614 +01:04:44,076 --> 01:04:45,241 +Actually, I'm just gonna if let. +实际上我会使用 if let + +1615 +01:04:45,243 --> 01:04:46,709 +I just wanna be careful here in case for +我想在这里小心一点 + +1616 +01:04:46,711 --> 01:04:48,043 +some reason the last drop view isn't around. +以防这个 lastDropView 不存在 + +1617 +01:04:48,045 --> 01:04:52,814 +So I'm gonna say if we can let the viewToAttachTo equal +if let viewToAttachTo = + +1618 +01:04:52,816 --> 01:04:54,849 +the lastDroppedView, +lastDroppedView + +1619 +01:04:54,851 --> 01:04:57,251 +then we will start this attachment business. +然后我会开始 attachment 的创建 + +1620 +01:04:59,521 --> 01:05:02,655 +'Kay, it'll be safe there, because we might change +现在这里安全了 + +1621 +01:05:02,657 --> 01:05:04,724 +something in the future where we don't always set the last +因为我们可能再以后 + +1622 +01:05:04,726 --> 01:05:07,093 +drop view to something, so I wanna be careful there. +不总是设置 lastDropView,所以需要小心点 + +1623 +01:05:07,095 --> 01:05:09,094 +[COUGH] So, we have the attachment. +所以现在有了 attachment + +1624 +01:05:09,096 --> 01:05:11,630 +By the way, I'm also gonna put a feature of my game that once +游戏中还会添加一个特性 + +1625 +01:05:11,632 --> 01:05:14,165 +you grab onto something, you can't grab onto it again. +如果你抓住了某个东西,你不能再次抓住它 + +1626 +01:05:14,167 --> 01:05:16,267 +Like, if you grab onto it and let it go. +如果你抓住了它,然后放手 + +1627 +01:05:16,269 --> 01:05:18,002 +I'm not gonna let you grab onto it again because I might +我不会再让你抓住它 + +1628 +01:05:18,004 --> 01:05:20,571 +wanna eventually turn this into a game where you have to +因为我想把这个游戏变成 + +1629 +01:05:20,573 --> 01:05:23,206 +like, line the things up into perfect stacks or +把这些方块排成一列 + +1630 +01:05:23,208 --> 01:05:25,342 +something like that, and +之类的 + +1631 +01:05:25,343 --> 01:05:27,477 +so I can put something in here like this to make my +增加的这个特性 + +1632 +01:05:27,479 --> 01:05:29,312 +game a little more challenging where I can't constantly be +让游戏更有挑战性一点 + +1633 +01:05:29,314 --> 01:05:33,048 +just regrabbing it until I get exactly where I want, okay. +我不能一直松开抓住,直到调整为我想要的地方 + +1634 +01:05:33,050 --> 01:05:34,917 +So that's it. +好的 + +1635 +01:05:34,918 --> 01:05:36,785 +All I have to do in began is create that attachment and +在 .began 只需要做这些事情 + +1636 +01:05:36,787 --> 01:05:37,986 +then if things change. +如果手势改变了 + +1637 +01:05:37,988 --> 01:05:42,123 +[SOUND] All I have to do is change that anchor point. +我需要做的只有改变锚点 + +1638 +01:05:42,125 --> 01:05:43,957 +That's the attachment's anchorPoint, and +这是 attachment 的锚点 + +1639 +01:05:43,959 --> 01:05:46,093 +if the attachment is nil, this will just do nothing. +如果 attachment 是 nil,这什么都不会做 + +1640 +01:05:46,095 --> 01:05:47,160 +That's fine. +这没关系 + +1641 +01:05:47,162 --> 01:05:48,594 +So that's the gesturePoint. +这是 gesturePoint + +1642 +01:05:48,596 --> 01:05:52,031 +And when it's all over, 'kay, the span is just gonna say +当手势结束的时候 + +1643 +01:05:52,033 --> 01:05:54,667 +attachment equals nil, [COUGH] okay? +把 attachment 设置为 nil + +1644 +01:05:54,669 --> 01:05:57,069 +All done. +完成 + +1645 +01:05:57,070 --> 01:05:59,470 +So, and of course, we have the default case, +当然,还有 default + +1646 +01:05:59,473 --> 01:06:04,475 +all the things like the Pan failed or +手势不完整等等 + +1647 +01:06:04,477 --> 01:06:06,444 +whatever, I'm just gonna do nothing in that case. +在这个 case 什么都不做 + +1648 +01:06:06,446 --> 01:06:08,179 +That's probably not, +其实也不是 + +1649 +01:06:08,180 --> 01:06:09,913 +actually, I probably should be doing something here if, +如果我在一个手势的中间 + +1650 +01:06:09,915 --> 01:06:11,415 +like if I was in the middle of this and +突然间一个电话打进来了 + +1651 +01:06:11,417 --> 01:06:13,650 +a phone call came in and my Pan failed, +手势没有完成 + +1652 +01:06:13,652 --> 01:06:17,120 +I probably should be doing attachment equals nil. +我也许应该把 attachment 设置为 nil + +1653 +01:06:17,122 --> 01:06:19,422 +'Kay, so probably attachment equals nil should be +所以在 default 中 + +1654 +01:06:19,424 --> 01:06:21,924 +the default case, but I haven't really analyzed that. +应该吧 attachment 设置为 nil,但我没有分析过 + +1655 +01:06:21,926 --> 01:06:24,059 +I haven't done that full design, but +我没有做完整的设计 + +1656 +01:06:24,061 --> 01:06:27,495 +that's something you obviously wanna think about if you're +如果你们需要搭建什么,这些东西 + +1657 +01:06:27,497 --> 01:06:28,763 +building something. +是你需要考虑的 + +1658 +01:06:28,765 --> 01:06:32,199 +Okay, [COUGH] now this attachment we're creating it, +好的,attachment 创建完了 + +1659 +01:06:32,201 --> 01:06:35,235 +but notice we never added to the dynamic animator. +但我们没有把它添加到 dynamic animator 里 + +1660 +01:06:35,237 --> 01:06:37,771 +So this attachment is not ever actually going to be animated. +所以这个 attachment 不会有效果 + +1661 +01:06:37,773 --> 01:06:41,307 +So where we're gonna do that, I'm actually gonna do that in +应该在哪里处理呢 + +1662 +01:06:41,309 --> 01:06:46,212 +the will set and did set of the attachment. +应该在 attachment 的 willSet 和 didSet 里 + +1663 +01:06:47,181 --> 01:06:49,781 +So in the will set, 'kay, that's this +在 willSet 中 + +1664 +01:06:49,783 --> 01:06:52,350 +attachment is about to be set to something new, I'm gonna +attachment 需要设置到新的物体上了 + +1665 +01:06:52,352 --> 01:06:58,389 +tell my animator to remove the existing attachment. +我要告诉 animator 把存在的 attachment 去掉 + +1666 +01:06:58,391 --> 01:07:00,958 +So if there's an attachment behavior that's existing right +如果现在上面有一个 attachment behavior + +1667 +01:07:00,960 --> 01:07:05,395 +now, remove it, and similarly, as long as [COUGH] I +删掉它 + +1668 +01:07:05,397 --> 01:07:09,432 +am setting this to non-nil, if attachment is at nil, okay, so +在 didSet 中 + +1669 +01:07:09,434 --> 01:07:11,567 +if the attachment is not nil, then, +如果 attachment 不是 nil + +1670 +01:07:11,569 --> 01:07:14,002 +my animator can have the behavior of the attachment. +我的 animator 就可以拥有这个 attachment 特性 + +1671 +01:07:14,004 --> 01:07:16,471 +Okay, this is getting pretty bad, okay. +这里有点错误 + +1672 +01:07:16,473 --> 01:07:17,105 +Got it? +明白了吗? + +1673 +01:07:17,107 --> 01:07:17,972 +Sorry about that. +抱歉 + +1674 +01:07:17,974 --> 01:07:19,073 +So, get that? +明白了? + +1675 +01:07:19,075 --> 01:07:21,275 +What I'm doing there? +我在这里做了什么 + +1676 +01:07:21,276 --> 01:07:23,476 +I'm basically adding and removing from the animator as +在 attachment 被设置的时候 + +1677 +01:07:23,479 --> 01:07:25,879 +the attachment is set, or not set. +我只在 animator 里添加和删除了 attachment + +1678 +01:07:25,881 --> 01:07:28,948 +Now, we can go ahead and run this now, and I'm going to, +现在开始运行程序 + +1679 +01:07:28,950 --> 01:07:31,183 +we're not gonna be able to see it though, +但是现在还看不到连接 + +1680 +01:07:31,185 --> 01:07:34,386 +because we're not setting any Bezier path in our view, but +因为我们没在 view 中设置 bezierpath + +1681 +01:07:34,388 --> 01:07:37,422 +let's go ahead and look at it, see what it looks like. +但是我们看看效果 + +1682 +01:07:38,625 --> 01:07:39,690 +Okay, so here's a drop. +掉落一个 + +1683 +01:07:39,692 --> 01:07:40,991 +I grabbed it. +抓住它 + +1684 +01:07:40,993 --> 01:07:43,527 +Okay, so if you can kind of imagine, +想象一下 + +1685 +01:07:43,529 --> 01:07:46,363 +I can even like, balance it on it's little stick. +就像把它放在一个棍上,让它保持平衡 + +1686 +01:07:46,365 --> 01:07:47,397 +>> [LAUGH]. + +1687 +01:07:47,399 --> 01:07:49,416 +>> So you can see I'm at there. +所以你们能看到,我在这里 + +1688 +01:07:49,417 --> 01:07:51,434 +And if I let it go, or I can just bounce it off this thing. +如果甩动它,让它撞击这个 + +1689 +01:07:51,436 --> 01:07:52,267 +'Kay, it's still attached. +它仍然连接着 + +1690 +01:07:53,237 --> 01:07:53,835 +All right, see that. +好的 + +1691 +01:07:55,005 --> 01:07:57,505 +And I can let it go, and it'll bounce, 'kay? +我松手,它仍然会弹跳 + +1692 +01:07:57,507 --> 01:07:59,206 +I can grab the next one. +我可以抓住下一个 + +1693 +01:07:59,208 --> 01:08:01,608 +Now, it would be nicer if we could see this +如果能看到 + +1694 +01:08:01,610 --> 01:08:05,078 +little attachment wire that's on here, right? +它们之间的连线就好了 + +1695 +01:08:05,080 --> 01:08:08,281 +And we can, because we have this nice view that makes it +我们也可以这么做 + +1696 +01:08:08,283 --> 01:08:09,148 +easier to show a path. +因为我们的 view 让显示 bezierPath 更容易 + +1697 +01:08:09,150 --> 01:08:10,733 +So really, + +1698 +01:08:10,734 --> 01:08:12,317 +what we need to do is we just need to say let path equal +let path = UIBezierPath + +1699 +01:08:12,319 --> 01:08:17,655 +UIBezierPath, and then we just need to say gameView, +gameView.addPath + +1700 +01:08:17,657 --> 01:08:20,958 +addPath, this path, which we're gonna have to create, +我们创建的这个 path + +1701 +01:08:20,960 --> 01:08:23,127 +and then again, we need a name for it, so +我们还是需要一个 name + +1702 +01:08:23,129 --> 01:08:26,764 +we'll call this the attachment path name. +我们给它起名为 Attachment + +1703 +01:08:26,766 --> 01:08:33,203 +Attachment, like that, 'kay, so a pathNames.Attachment. +PathNames.Attachment + +1704 +01:08:33,205 --> 01:08:35,705 +'Kay, so really all we need to do is create +我们需要做的就是创建这条 + +1705 +01:08:35,707 --> 01:08:37,807 +that path in here. +BezierPath + +1706 +01:08:37,809 --> 01:08:41,977 +'Kay, the path between the attachment point and +attachment 点和 + +1707 +01:08:41,979 --> 01:08:43,178 +the set path. +抱歉,setPath + +1708 +01:08:43,180 --> 01:08:46,214 +[SOUND] Okay, we just need to create this path, +我们只需要创建这个 path + +1709 +01:08:46,216 --> 01:08:49,183 +that goes from the attachment anchor point, +从 attachment 的锚点 + +1710 +01:08:49,185 --> 01:08:50,918 +to the middle of the view. +到 view 的中间点 + +1711 +01:08:50,920 --> 01:08:53,420 +Well, okay, we need to find that view. +我们需要先找到这个 view + +1712 +01:08:53,422 --> 01:08:54,888 +So, how do we get the view? +我们怎么能找到呢 + +1713 +01:08:54,890 --> 01:08:57,457 +All behaviors, most of them anyway +所有的 behavior,基本都 + +1714 +01:08:57,459 --> 01:09:01,227 +can tell you the items that they're currently animating. +基本都可以告诉你它们正在 animate 的东西 + +1715 +01:09:01,229 --> 01:09:03,762 +All right, they're affecting the behavior of and +attached behavior 可以 + +1716 +01:09:03,764 --> 01:09:06,031 +attached behaviors can do that. +获取得到 + +1717 +01:09:06,033 --> 01:09:11,669 +[SOUND] So, I'm gonna say if the attachedView equals and +if attachedView = + +1718 +01:09:11,671 --> 01:09:13,838 +how am I gonna get it? +如何获取呢 + +1719 +01:09:13,840 --> 01:09:19,409 +I'm gonna get it by asking the attachments for its items. +获取 attachment.items + +1720 +01:09:19,411 --> 01:09:22,412 +That's all the things that it is attaching, could be two +这是它正在连接的所有东西 + +1721 +01:09:22,414 --> 01:09:24,981 +items, could be one item, in our case gonna be one. +可以使两个也可以是一个,在这里是一个 + +1722 +01:09:24,983 --> 01:09:27,216 +Since it's one I'm just gonna get the first one. +因为它只有一个,所以我获取第一个 + +1723 +01:09:27,218 --> 01:09:31,186 +First is a array method, 'kay? +first 是一个数组的方法 + +1724 +01:09:31,188 --> 01:09:34,189 +And I'm gonna make sure that it's UIView, +我要确保它是个 UIView + +1725 +01:09:34,191 --> 01:09:37,091 +it's going to be UIView, but, I'm gonna +它也会是一个 UIView + +1726 +01:09:37,093 --> 01:09:41,228 +make sure it's a UIView so I'm gonna do if let here, 'kay? +但是我得确保,所以在这里进行 if let + +1727 +01:09:41,230 --> 01:09:44,898 +So now I know that I've got the attached view that's going +所以我获取到了连接到的视图 + +1728 +01:09:44,900 --> 01:09:48,702 +on, it's in here. +在这里 + +1729 +01:09:48,704 --> 01:09:51,104 +So now I can make a connection between these two things. +所以我现在可以在它们之间做一个连接 + +1730 +01:09:51,106 --> 01:09:53,906 +I can just say path.moveToPoint, +path.moveToPoint + +1731 +01:09:53,908 --> 01:09:58,777 +I'll move to the anchor point, so that's the attachment's +移动到锚点,attachments 的锚点 + +1732 +01:09:58,779 --> 01:10:03,548 +anchorPoint, and then I'm going to path.addLineTo, and +接着,path.addLienTo + +1733 +01:10:03,550 --> 01:10:08,318 +I'm just going to add a line to the attachedView's center. +然后把连接视图的中心点传进去 + +1734 +01:10:08,320 --> 01:10:11,388 +'Kay, so we got that. +所以我们获取到了 + +1735 +01:10:12,891 --> 01:10:14,824 +The only thing about this is, +但出现的问题时 + +1736 +01:10:14,826 --> 01:10:17,893 +this is only going to work once. +这只会调用一次 + +1737 +01:10:17,895 --> 01:10:20,529 +When did set happens of the attachment. +在 attachment 的 didSet 发生的时候 + +1738 +01:10:20,531 --> 01:10:22,997 +When I first create that thing it's gonna draw that line, +当第一次创建它的时候,这条线会出现 + +1739 +01:10:22,999 --> 01:10:25,366 +that's great but what if line of that moving it around? +但是在移动的时候呢 + +1740 +01:10:25,368 --> 01:10:27,702 +'Kay, when I move it around the anchor point moves so +当我移动的时候,锚点移动了 + +1741 +01:10:27,704 --> 01:10:29,770 +this is gonna be no good anymore. +所以这就不好了 + +1742 +01:10:29,772 --> 01:10:34,174 +So, I actually have to put this code inside of +所以我需要把这些代码放到 + +1743 +01:10:34,176 --> 01:10:38,377 +the attachment's action, 'kay? +attachment.action 里 + +1744 +01:10:38,379 --> 01:10:42,348 +So the action is just closure, once we put it inside +action 就是一个闭包 + +1745 +01:10:42,350 --> 01:10:46,451 +a closure we're gonna have to do self dots in here. +所以我们需要在这里添加 self + +1746 +01:10:46,453 --> 01:10:49,287 +So we can be obvious that we are capturing self +我们很清楚,当我们这么做的时候 + +1747 +01:10:49,289 --> 01:10:50,654 +when we do this. +是在捕获 self + +1748 +01:10:50,656 --> 01:10:53,624 +Here's another self dot that we need, and here's another +这里也需要 + +1749 +01:10:53,626 --> 01:10:58,795 +self dot and this we'll say question mark, okay? +这里也需要,添加问号 + +1750 +01:10:59,798 --> 01:11:00,963 +So here we have this action, so +所以这里我们有了这个 action + +1751 +01:11:00,965 --> 01:11:04,066 +this is good, but, and this will work. +很好,这也会有效 + +1752 +01:11:04,068 --> 01:11:06,334 +Let's go ahead and run this. +运行起来试试看 + +1753 +01:11:09,139 --> 01:11:12,173 +'Kay, so grabby dots so you can see it works, right. +抓住一个,可以看到它起作用了 + +1754 +01:11:12,175 --> 01:11:16,109 +It's showing the connection there, but +它显示了连接 + +1755 +01:11:16,111 --> 01:11:17,310 +it doesn't clean up. +但是它没有被清理 + +1756 +01:11:17,312 --> 01:11:19,212 +That's no good, 'kay? +这就不好了 + +1757 +01:11:19,214 --> 01:11:21,213 +And so what's going on here? +发生了什么 + +1758 +01:11:21,215 --> 01:11:22,281 +'Kay, let's fix two problems. +让我们一起改 bug + +1759 +01:11:22,283 --> 01:11:23,782 +One, this cleanup, is no good. +一,这里需要清理 + +1760 +01:11:23,784 --> 01:11:26,584 +That's just because in will set right here, +这是因为在 willSet 里 + +1761 +01:11:26,586 --> 01:11:31,756 +we need to tell our gameView to +我们需要告诉 gameView + +1762 +01:11:31,758 --> 01:11:37,027 +set that path to nil, for that name, the path name. +把 path 设置为 nil,对于这个 pathName + +1763 +01:11:37,029 --> 01:11:39,646 +Attachment, right? +这个 attachment + +1764 +01:11:39,647 --> 01:11:42,264 +Every time we set a new one, we need to delete the old one. +每一次我们设置一个新的,我们需要删除旧的 + +1765 +01:11:42,267 --> 01:11:45,034 +The other thing is we got the memory cycle problem here. +另一个问题是,在这里有了内存的循环引用 + +1766 +01:11:45,036 --> 01:11:46,635 +[SOUND] Right? +对吧 + +1767 +01:11:46,637 --> 01:11:49,171 +Because this attachment, which self points to, so +因为 self 指向 attachment + +1768 +01:11:49,173 --> 01:11:50,672 +self points to attachment. + + +1769 +01:11:50,674 --> 01:11:51,873 +Attachment has the action. +attachments 有 action + +1770 +01:11:51,875 --> 01:11:54,342 +The action points back to self, 'kay? +在 action 中又指向了 self + +1771 +01:11:54,344 --> 01:11:56,877 +'Kay, here's to using it here the attachment itself. +在这里又指向了自己 + +1772 +01:11:56,879 --> 01:11:58,145 +But it's pointing back to self, so +但是它指向了它自己 + +1773 +01:11:58,147 --> 01:11:59,546 +we got a memory cycle here. +所以我们有了循环引用 + +1774 +01:11:59,548 --> 01:12:03,249 +So we have to say, that inside here, self, +所以在这个闭包里 + +1775 +01:12:03,251 --> 01:12:09,055 +should be unowned, in this closure, 'kay? +self 应当为 unowned + +1776 +01:12:09,057 --> 01:12:11,557 +And that means that the system will not +这表明,系统不会为了这个闭包有效 + +1777 +01:12:11,559 --> 01:12:14,626 +keep self in memory in order to make this closure work. +而一直把 self 留在内存里 + +1778 +01:12:14,628 --> 01:12:16,728 +It will assume the self is always gonna be there, +它将会假设,self 是一直存在的 + +1779 +01:12:16,730 --> 01:12:19,263 +which it is always gonna be, because if there's no self, +其实它也是一直存在的 + +1780 +01:12:19,265 --> 01:12:20,398 +there's no attachment. +因为没有 self 就没有 attachment + +1781 +01:12:20,400 --> 01:12:22,800 +If there's no attachment, there's no action, so +没有 attachment 就没有 action + +1782 +01:12:22,802 --> 01:12:25,302 +then there's no closure, 'kay? +当然也就没有闭包了 + +1783 +01:12:25,304 --> 01:12:26,536 +So we broke that memory cycle here. +所以在这里打破了循环 + +1784 +01:12:26,538 --> 01:12:29,939 +All right, so that fixes both of these problems. +问题都改好了 + +1785 +01:12:29,941 --> 01:12:32,375 +So here we go, +跑起来 + +1786 +01:12:32,376 --> 01:12:34,810 +drop one, swing it around, well, bang it on here. +掉下来一个,旋转它 + +1787 +01:12:34,812 --> 01:12:35,644 +Woops. +哦~ + +1788 +01:12:35,646 --> 01:12:36,411 +Like that. +像这样 + +1789 +01:12:36,413 --> 01:12:37,712 +Let go. +松手 + +1790 +01:12:37,714 --> 01:12:40,448 +'Kay, put a whole bunch of these down here. +多放几个 + +1791 +01:12:40,450 --> 01:12:43,283 +'Kay, now notice that it, let's say I have enough of +我们注意到 + +1792 +01:12:43,285 --> 01:12:45,485 +these things to make a row disappear, but +我们有足够多的东西来让一行小时 + +1793 +01:12:45,487 --> 01:12:48,588 +if I drag onto this and I'm animating, see, the row won't +如果我拽住一个 + +1794 +01:12:48,590 --> 01:12:52,024 +disappear because we're never coming to stasis here, 'kay? +行不会消失,因为没有到稳定的状态 + +1795 +01:12:52,993 --> 01:12:54,559 +But if I let it come to stasis, +但如果我让它稳定下来 + +1796 +01:12:54,561 --> 01:12:56,428 +then we don't have a complete row. +我们还没有完整的一行 + +1797 +01:12:56,430 --> 01:12:58,563 +Okay, let's get it clear row. +让它清除一行 + +1798 +01:12:58,565 --> 01:13:01,098 +[SOUND] There we go. +好的 + +1799 +01:13:01,100 --> 01:13:03,000 +We got one, 'kay? +我们有了一行 + +1800 +01:13:03,002 --> 01:13:04,368 +So now we got a complete row there, +有了一个完整的一行 + +1801 +01:13:04,370 --> 01:13:06,403 +the third one up from the bottom. +倒数第三行 + +1802 +01:13:06,405 --> 01:13:10,539 +And as long we do this, it's not gonna come to stasis, +只要我们这样做,它就不会是稳定状态 + +1803 +01:13:10,541 --> 01:13:13,175 +not gonna pause, not gonna do it, +不会暂停,不会消除 + +1804 +01:13:13,177 --> 01:13:17,412 +but if we let go, settles down, now it'll do, 'kay? +如果我们松手,安定下来,现在就会消除了 + +1805 +01:13:17,414 --> 01:13:19,881 +All right, so that's it for that demo. +demo 做完了 + +1806 +01:13:19,883 --> 01:13:22,650 +I should got to show you a lot of different behaviours there. +我应该展现给你许多不同的 behaviour + +1807 +01:13:22,652 --> 01:13:24,284 +I didn't show you push behaviour, +我还没有展示 push + +1808 +01:13:24,286 --> 01:13:26,920 +which you're gonna need for your assignment. +你们作业中需要使用到 + +1809 +01:13:26,922 --> 01:13:28,988 +I didn't show you snap behaviour which is very +还有 snap + +1810 +01:13:28,990 --> 01:13:31,391 +commonly used in the UI, but you don't need it for +在 UI 中非常常用 + +1811 +01:13:31,393 --> 01:13:34,060 +your assignment, so I didn't show that one, but +但是作业中不需要,所以我没展示 + +1812 +01:13:34,062 --> 01:13:36,195 +I showed you the collider and the gravity. +但是我展示了 collider 还有 gravity + +1813 +01:13:36,197 --> 01:13:39,064 +The gravity is an optional one in your assignment, you might +在作业中 gravity 是可选的 + +1814 +01:13:39,066 --> 01:13:41,066 +wanna use gravity, it could be fun, totally up to you. +你可以使用,会很有趣,根据你来 + +1815 +01:13:41,068 --> 01:13:43,534 +[SOUND] But that's it. +好的 + +1816 +01:13:43,536 --> 01:13:45,169 +So, good luck with assignment five, and +祝你们作业完成地愉快 + +1817 +01:13:45,171 --> 01:13:47,271 +if you have any questions, I'll be here as usual. +如果有问题,过来找我 + +1818 +01:13:48,374 --> 01:13:48,405 +>> For more, please visit us at Stanford.edu. diff --git a/subtitles/13. Application Lifecycle and Core Motion.srt b/subtitles/13. Application Lifecycle and Core Motion.srt new file mode 100644 index 0000000..c371dce --- /dev/null +++ b/subtitles/13. Application Lifecycle and Core Motion.srt @@ -0,0 +1,8834 @@ +1 +00:00:00,001 --> 00:00:01,033 +[MUSIC] + +2 +00:00:01,035 --> 00:00:01,599 +Stanford University. + +3 +00:00:04,938 --> 00:00:10,341 +>> All right, well, welcome to Lecture 13 of CS193P, +欢迎来到 CS193P 13课 + +4 +00:00:10,343 --> 00:00:12,976 +Winter 2015. +2015冬季 + +5 +00:00:12,978 --> 00:00:15,311 +Today, we have three major topics. +今天,我们有三个主题 + +6 +00:00:15,313 --> 00:00:18,047 +One which is the Application Lifecycle, which is all about +一个是应用生命周期,这讲的全部都是关于 + +7 +00:00:18,049 --> 00:00:20,783 +we talked about the View Controller Lifecycle. +视图控制器生命周期 + +8 +00:00:21,852 --> 00:00:24,286 +Where your view controller kinda is born, +在你的视图控制器生成的地方 + +9 +00:00:24,288 --> 00:00:26,121 +does a bunch of things and then, dies. +同时有许多东西产生,然后消亡 + +10 +00:00:26,123 --> 00:00:28,690 +Well, the same things happen for the whole application. +在整个应用程序中也发生同样的事情 + +11 +00:00:28,692 --> 00:00:30,257 +So we'll talk about that. +因此我们将讨论这个 + +12 +00:00:30,259 --> 00:00:32,860 +And then, I'm going to talk about Core Motion, +然后,我们将讲 Core Motion + +13 +00:00:32,862 --> 00:00:35,562 +which is figuring out what the device is doing. +这个是找出设备在做什么 + +14 +00:00:35,564 --> 00:00:39,532 +Gyro, and accelerometer, magnetometers, +陀螺仪,加速器,地磁仪 + +15 +00:00:39,534 --> 00:00:40,666 +all that business. +类似那样的东西 + +16 +00:00:40,668 --> 00:00:43,535 +And then, I'm going to talk about persistence, +然后,我将要讲解持久化 + +17 +00:00:43,537 --> 00:00:46,571 +which is making things be stored on the internal hard +就是把数据存储在你的设备中的 + +18 +00:00:46,573 --> 00:00:47,806 +disk of your device. +内置硬盘 + +19 +00:00:47,808 --> 00:00:50,241 +Of course, it's flash memory, but +当然,这是闪存,但 + +20 +00:00:50,243 --> 00:00:53,911 +basically it acts a hard disk, a Unix file system even. +基本上它扮演了硬盘的角色,设置一个 Unix 文件系统 + +21 +00:00:53,913 --> 00:00:57,114 +So we talk about how we do that. +因此,我们将讲解我们如何实现这些 + +22 +00:00:57,116 --> 00:00:58,382 +All right, so let's jump right +让我们从应用生命周期 + +23 +00:00:58,384 --> 00:00:59,849 +into the application life cycle. +开始 + +24 +00:00:59,851 --> 00:01:02,485 +But we first, I need to give you a little side +但首先,我需要给你们一小点 + +25 +00:01:03,921 --> 00:01:06,288 +lecture here on NSNotification. +关于 NSNotification 方面的课程 + +26 +00:01:06,290 --> 00:01:08,723 +And we actually saw this briefly +实际上,当我讲解键盘时我们看到 + +27 +00:01:08,725 --> 00:01:10,825 +when I was talking about the keyboards. +过这个 + +28 +00:01:10,827 --> 00:01:13,427 +And you get this notification when the keyboards show up. +当键盘出现时你们得到这个通知 + +29 +00:01:13,429 --> 00:01:15,929 +But I decided I'm going to take a couple of slides here +但我决定将带几个幻灯片 + +30 +00:01:15,931 --> 00:01:17,698 +and just talk about NSNotification and +然后只讲 NSNotification + +31 +00:01:17,700 --> 00:01:19,299 +how it works. +还有它怎么运作 + +32 +00:01:19,300 --> 00:01:20,899 +Because it's actually a fairly important part. +因为它真的是很重要的一部分 + +33 +00:01:20,902 --> 00:01:22,519 +Not fairly important, +不是很重要 + +34 +00:01:22,520 --> 00:01:24,137 +somewhat important part of the MVC model. +MVC 模式中比较重要的一部分 + +35 +00:01:24,139 --> 00:01:26,505 +So if you remember back to our MVC slides. +因此如果你们回忆起我们的 MVC 幻灯片 + +36 +00:01:26,507 --> 00:01:29,074 +I had a little kinda thing that looked like a radio +我有一个小东西,它看起来像一个 + +37 +00:01:29,076 --> 00:01:30,459 +station. +电台 + +38 +00:01:30,460 --> 00:01:31,843 +It was broadcasting from the model. +它从模型中被发送出去 + +39 +00:01:31,845 --> 00:01:34,045 +And then the controller would tune into that radio station +然后控制器将调频到电台 + +40 +00:01:34,047 --> 00:01:36,814 +to find out that changes were happening in the model. +找出在模型中所发生的变化 + +41 +00:01:36,816 --> 00:01:38,115 +Well that's, + +42 +00:01:38,117 --> 00:01:41,352 +one of the things that make that happen is NSNotification. +让这些事情发生的其中之一是 NSNotification + +43 +00:01:41,354 --> 00:01:43,387 +And so, it's the radio station or +它是电台或者 + +44 +00:01:43,389 --> 00:01:47,023 +one of the ways of doing the radio station in MVC. +在 MVC 中处理电台的途径之一 + +45 +00:01:47,025 --> 00:01:51,627 +And it's really for model to controller communication or +这实际是模型到控制器的通讯或者 + +46 +00:01:51,629 --> 00:01:54,363 +sometimes global to controller. +有时是全局对控制器 + +47 +00:01:54,365 --> 00:01:57,232 +Cuz sometimes things happen globally in your entire +因为有时事情发生你的整个应用的全局 + +48 +00:01:57,234 --> 00:01:59,701 +application, as we're gonna see in the demo today. +正如我们今天要看到的 demo + +49 +00:01:59,703 --> 00:02:01,669 +And you need to kinda broadcast that this global +你需要广播这个全局的 + +50 +00:02:01,671 --> 00:02:02,920 +thing is happening. +事情正在发生 + +51 +00:02:02,921 --> 00:02:04,170 +And then particular view controllers might +然后特定视图控制器可能 + +52 +00:02:04,173 --> 00:02:05,305 +be interested in that. +对这有兴趣 + +53 +00:02:05,307 --> 00:02:07,074 +They'll sign up to listen to that radio station and +他们将注册监听电台然后 + +54 +00:02:07,076 --> 00:02:10,410 +they'll find out that global thing has happened. +他们讲发现所发生的全局的事情 + +55 +00:02:10,412 --> 00:02:11,978 +So how does it work? +这是如何工作的? + +56 +00:02:11,980 --> 00:02:13,446 +It's super simple. +它超级简单 + +57 +00:02:13,448 --> 00:02:16,048 +There is a class called NSNotificationCenter +这里有一个类叫做 NSNotificationCenter + +58 +00:02:16,050 --> 00:02:18,483 +it has a class function called defaultCenter. +它有一个类函数叫做 defaultCenter + +59 +00:02:18,485 --> 00:02:20,268 +You get that, +你们得到这个 + +60 +00:02:20,269 --> 00:02:22,052 +that's this kinda shared notification center. +它类似共享消息中心 + +61 +00:02:22,055 --> 00:02:24,989 +And you just send a message to it called addObserver +你只需发送一个消息给它,它叫做 + +62 +00:02:24,991 --> 00:02:26,157 +for name. +addObserverForName + +63 +00:02:26,159 --> 00:02:28,692 +And you specify the name of the radio station you +然后你指定你想收听的 + +64 +00:02:28,694 --> 00:02:30,027 +wanna listen to. +电台的名字 + +65 +00:02:30,029 --> 00:02:31,545 +Okay. + +66 +00:02:31,546 --> 00:02:33,062 +It has a couple other arguments which are, +它有其他几个参数,这些是 + +67 +00:02:33,065 --> 00:02:34,965 +is object. +对象 + +68 +00:02:34,966 --> 00:02:36,866 +Object is who's the broadcaster. +Object 就是发送广播者 + +69 +00:02:36,868 --> 00:02:40,102 +Who are you interested in broadcasts on this +你们谁对这个电台发送的 + +70 +00:02:40,104 --> 00:02:41,721 +radio station from? +广播感兴趣 + +71 +00:02:41,722 --> 00:02:43,339 +And you can just put nil there if you're interested +你可以置 nil 值,如果你对该电台 + +72 +00:02:43,341 --> 00:02:46,174 +when anybody broadcasts on that radio station. +中任何人发送的广播都感兴趣的话 + +73 +00:02:46,176 --> 00:02:48,176 +But sometimes you'll specify I'm only interested if +但有时,你要指定只对这个 + +74 +00:02:48,178 --> 00:02:50,745 +this guy broadcasts on this radio station. +电台中的这个广播感兴趣 + +75 +00:02:50,747 --> 00:02:53,647 +And then, notice that there's a queue. +然后,注意这里有一个队列 + +76 +00:02:53,649 --> 00:02:55,849 +And then a closure right after it. +然后它后面有一个闭包 + +77 +00:02:55,851 --> 00:02:56,850 +Okay. Queue and a closure. +队列是一个闭包 + +78 +00:02:56,852 --> 00:02:58,084 +So the queue is just saying +因此这个队列只是 + +79 +00:02:58,086 --> 00:03:00,987 +what queue you want after this closure to be executed on. +这个闭包执行之后你想要哪个队列 + +80 +00:03:00,989 --> 00:03:03,489 +I think if you put nil there you get I think +我想如果你在这个放 nil,你将得到 + +81 +00:03:03,491 --> 00:03:04,823 +the main queue. +主队列 + +82 +00:03:04,825 --> 00:03:07,359 +Possibly the current queue, but maybe the main queue. +也可能是当前队列,或者主队列 + +83 +00:03:07,361 --> 00:03:09,094 +But might as well just put it in there. +但可能也只是把它放在那里 + +84 +00:03:09,096 --> 00:03:10,895 +Now notice NSOperationQueue, +现在注意 NSOperationQueue + +85 +00:03:10,897 --> 00:03:13,931 +I briefly mentioned that earlier in the quarter too. +我刚才简要提到了这个 + +86 +00:03:13,933 --> 00:03:18,869 +You're used to dispatch_queue_t, that thing. +你们熟悉 dispatch_queue_t + +87 +00:03:18,871 --> 00:03:23,539 +NSOperationQueue is just kinda an object oriented API on top +NSOperationQueue 类似一个在分发工作中 + +88 +00:03:23,541 --> 00:03:26,375 +of the whole dispatching business. +顶端的面向对象的 API + +89 +00:03:26,377 --> 00:03:28,577 +GCD, Grand Central Dispatch. +GCD,Grand Central Dispatch + +90 +00:03:28,579 --> 00:03:32,881 +So, it's very thin layer looks almost exactly the same. +因此,它是非常轻的一层,看起来几乎是一样的 + +91 +00:03:32,883 --> 00:03:35,450 +But object oriented APIs usually will ask for +但面向对象的 API 们通常会请求 + +92 +00:03:35,452 --> 00:03:37,518 +a NSOperationQueue. +NSOperationQueue + +93 +00:03:37,520 --> 00:03:40,754 +That has a couple of class functions like main queue, +有许多类函数,比如主队列 + +94 +00:03:40,756 --> 00:03:42,789 +where you can get the main queue. +在那里你可以获取主队列 + +95 +00:03:42,791 --> 00:03:44,891 +And you can create your own queues by just saying +你可以创建你自己的队列 + +96 +00:03:44,893 --> 00:03:46,492 +NSOperationQueue open parentheses +NSOperationQueue 左括号 + +97 +00:03:46,494 --> 00:03:48,961 +close parentheses to initialize it. +右括号进行初始化 + +98 +00:03:48,963 --> 00:03:50,262 +So anyway, specify the queue you want. +不管怎样,指定你想要的队列 + +99 +00:03:50,264 --> 00:03:52,330 +And then, what's gonna happen is, +然后,将要发生的是 + +100 +00:03:52,332 --> 00:03:54,866 +if anyone broadcasts on that radio station, +如果有人在那个电台上发送广播 + +101 +00:03:54,868 --> 00:03:58,136 +the following closure is going to be executed. +下面的这个闭包将被执行 + +102 +00:03:58,138 --> 00:03:59,937 +And that closure only has one argument there, +这个闭包只有一个参数 + +103 +00:03:59,939 --> 00:04:02,473 +which is an NSNotification. +即 NSNotification + +104 +00:04:02,475 --> 00:04:04,808 +That NSNotification has a few fields in it. +NSNotification 里面有几个字段 + +105 +00:04:04,810 --> 00:04:06,910 +But the really only interesting field is +但真正有趣的字段是 + +106 +00:04:06,912 --> 00:04:09,612 +the field called userInfo. +userInfo + +107 +00:04:09,614 --> 00:04:11,313 +And the userInfo is just a dictionary. +userInfo 是一个字典 + +108 +00:04:11,315 --> 00:04:14,850 +The dictionary of kinda old style, Objective-C dictionary +这个字典有点老的风格,Objective-C 字典 + +109 +00:04:14,852 --> 00:04:18,720 +with NSObject as the keys, AnyObject as the values. +keys 是 NSObject, values 是 AnyObject + +110 +00:04:18,722 --> 00:04:22,123 +And every radio station it broadcasts +任何一个它广播的电台 + +111 +00:04:22,125 --> 00:04:24,525 +is going to have kinda different userInfo. +都有点不一样的 userInfo + +112 +00:04:24,527 --> 00:04:26,827 +And when you go and look at the documentation for +当你开始,查找关于电台的 + +113 +00:04:26,829 --> 00:04:27,861 +that radio station. +文档 + +114 +00:04:27,863 --> 00:04:29,529 +Which is going to tell you the name, +这将告诉你名字 + +115 +00:04:29,531 --> 00:04:31,664 +that you're going to addObserver for name. +就是你将调用的 addObserverForName 中的名字. + +116 +00:04:31,666 --> 00:04:34,233 +It's also going to tell you what it provides you in +它也将告诉你 userInfo 中 + +117 +00:04:34,235 --> 00:04:35,701 +it's userInfo. +提供了哪些信息 + +118 +00:04:35,703 --> 00:04:38,404 +Okay, so let's look at an example of doing this. +让我们看一个例子来做这个 + +119 +00:04:38,406 --> 00:04:40,872 +So you can kinda make it more concrete. +你们可以将这个变得更具体化 + +120 +00:04:40,874 --> 00:04:45,743 +Which is finding out when the user changes their text size. +这个将发现用户改变他们的文本大小 + +121 +00:04:45,745 --> 00:04:48,913 +So in Settings, here I'm just in Settings on a phone. +在设置里,这里我只是在一个手机中的设置中 + +122 +00:04:48,915 --> 00:04:52,549 +If I go to General Settings right here and +如果我到通用设置 + +123 +00:04:52,551 --> 00:04:58,021 +I go down to Accessibility, then I go down to Larger Text. +然后我到下层的 Accessibility,然后我到下一层的更大文本 + +124 +00:04:58,023 --> 00:05:00,857 +You can see there's this slider here, which I can +你们可以看到这里的滑动条,通过这个我可以 + +125 +00:05:00,859 --> 00:05:04,960 +use to set the size of the text that I want in my apps. +设置我的应用里面的文本大小 + +126 +00:05:04,962 --> 00:05:08,230 +Well, if you have an app that has text in it, or +如果你们有一个有文本的应用,或者 + +127 +00:05:08,232 --> 00:05:12,266 +that is sized depending on the setting of this, +它的大小依赖于这个设置 + +128 +00:05:12,268 --> 00:05:14,268 +you might want to react to that. +你可能要采取相应的措施 + +129 +00:05:14,270 --> 00:05:17,805 +Well the way you get notified of that is you get +你得到这个通知的方式是你 + +130 +00:05:17,807 --> 00:05:19,740 +a broadcast on a radio station. +在一个电台收到广播 + +131 +00:05:19,742 --> 00:05:22,942 +The radio station is called the UI content size category +这个电台叫做 UI content size 类别 + +132 +00:05:22,944 --> 00:05:25,845 +did change notification radio station, 'kay? +确实改变了电台的通知,对吧? + +133 +00:05:25,847 --> 00:05:27,213 +That's the name of it. +这是它的名字 + +134 +00:05:27,215 --> 00:05:29,481 +Radio station is just something I use. +电台就是我使用的东西 + +135 +00:05:29,483 --> 00:05:31,450 +It's not really called radio station, okay? +实际上它不叫电台 + +136 +00:05:31,452 --> 00:05:33,485 +So, that's the name of it, and +因此,这是它的名字 + +137 +00:05:33,487 --> 00:05:36,354 +it's sent out by the UIApplication object. +它是通过 UIApplication 对象发送的 + +138 +00:05:36,356 --> 00:05:38,189 +Of which there's this one shared application, +这是一个共享的应用 + +139 +00:05:38,191 --> 00:05:40,057 +which you get by calling that method right there, +你通过调用那个方法来获得 + +140 +00:05:40,059 --> 00:05:41,358 +sharedApplication. +共享应用 + +141 +00:05:41,360 --> 00:05:44,961 +And I wanna hear about this on the main queue, okay? +我想在主队列中收到这个? + +142 +00:05:44,963 --> 00:05:46,529 +So I have my block. +所以我有自己的 block + +143 +00:05:46,531 --> 00:05:47,896 +It gets this notification argument. +它取得这个通知的参数 + +144 +00:05:47,898 --> 00:05:50,432 +Inside the notification argument there's the userInfo. +在通知参数中,这是 userInfo + +145 +00:05:50,434 --> 00:05:54,535 +And it turns out this radio station, when it broadcasts, +结果是这个电台,当它广播时 + +146 +00:05:54,537 --> 00:05:56,370 +the userInfo contains the +userInfo 包含 + +147 +00:05:56,372 --> 00:05:59,206 +UIContentSizeCategoryNewValue- Key. +UIContentSizeCategoryNewValue 键 + +148 +00:05:59,208 --> 00:06:01,775 +And if I get that key out of the dictionary, +如果我从字典中取出这个键 + +149 +00:06:01,777 --> 00:06:03,410 +the value I get is the size. +我得到的值便是(文本)大小 + +150 +00:06:03,412 --> 00:06:06,746 +And there's a bunch of enums or strings for +还有很多枚举或者字符串 + +151 +00:06:06,748 --> 00:06:09,882 +it like UIContentSizeCategorySmall or +比如 UIContentSizeCategorySmall 或者 + +152 +00:06:09,884 --> 00:06:13,185 +UIContentSizeExtraLarge or whatever. +UIContentSizeExtraLarge 或任何其它的 + +153 +00:06:13,187 --> 00:06:15,354 +So that's how you get it. +这就是你怎么得到它 + +154 +00:06:15,356 --> 00:06:18,056 +And so this could come at anytime because the user could +这个可能随时都会广播,因为用户 + +155 +00:06:18,058 --> 00:06:20,558 +go to settings and set this at anytime. +可能在任何时候在设置中设置这个值 + +156 +00:06:20,560 --> 00:06:23,127 +And you'll just get this closure executed. +然后这个闭包将被执行 + +157 +00:06:23,129 --> 00:06:25,863 +And it can be executed multiple times once you +一旦你注册这个,它可能 + +158 +00:06:25,865 --> 00:06:28,766 +register this. +被执行很多次 + +159 +00:06:28,767 --> 00:06:31,668 +Then it's going to get called whenever that thing changes. +当文本大小改变时这个都会被调用 + +160 +00:06:31,670 --> 00:06:32,902 +That make sense? +有道理吧? + +161 +00:06:32,904 --> 00:06:36,805 +So there's a lot of radio stations in iOS. +在 iOS 中有很多电台 + +162 +00:06:36,807 --> 00:06:38,407 +We're going to talk about Core Data, +我们将谈谈 Core Data + +163 +00:06:38,409 --> 00:06:40,275 +object-oriented database for example. +举个例子,面向对象的数据库 + +164 +00:06:40,277 --> 00:06:42,510 +That got some very important notifications where it tells +当你的数据库中有数据改变时 + +165 +00:06:42,512 --> 00:06:44,145 +you that things have changed in the database. +你会收到一些非常重要的通知 + +166 +00:06:44,147 --> 00:06:45,846 +That's the classic model. +这是经典的模型 + +167 +00:06:45,848 --> 00:06:47,180 +Communicating to the controllers. +和控制器通讯 + +168 +00:06:47,182 --> 00:06:49,082 +And I'm going to do a little demo where we're gonna +我要做个小例子,当我们 + +169 +00:06:49,084 --> 00:06:51,317 +broadcast on our own radio station. +在我们的电台中广播 + +170 +00:06:51,319 --> 00:06:53,185 +And I'm missing a slide in here, +这里我少了一个幻灯片 + +171 +00:06:53,187 --> 00:06:55,721 +I noticed, which is how to broadcast. +我注意到了,就是怎样广播 + +172 +00:06:55,723 --> 00:06:57,456 +But broadcasting is very easy, +但广播是非常简单的 + +173 +00:06:57,458 --> 00:07:00,458 +you just create one of these NSNotification objects. +你只需要创建这些 NSNotification 对象中的一个 + +174 +00:07:00,460 --> 00:07:02,493 +And then, you ask the defaultCenter, +然后,你询问 defaultCenter + +175 +00:07:02,495 --> 00:07:03,627 +postNotification. +defaultCenter + +176 +00:07:03,629 --> 00:07:05,496 +So it's a method in the defaultCenter called +这个是 defaultCenter 中一个叫做 + +177 +00:07:05,498 --> 00:07:07,431 +postNotification, you just give it a notification, +postNotification 的方法,你只需给它一个通知 + +178 +00:07:07,433 --> 00:07:09,966 +it'll broadcast it, simple as that. +它将广播它,就这样简单 + +179 +00:07:09,968 --> 00:07:12,568 +So we'll see that in the demo as well. +我们也会在例子中看到这个 + +180 +00:07:12,570 --> 00:07:14,303 +Okay, so that's notifications. +这就是通知 + +181 +00:07:14,305 --> 00:07:15,804 +And they're important in the application +他们在应用的生命周期中 + +182 +00:07:15,806 --> 00:07:17,105 +life cycle as you're going to see. +很重要,马上你们就会看到了 + +183 +00:07:17,107 --> 00:07:20,475 +So let's talk about the application life cycle. +让我们谈谈应用生命周期 + +184 +00:07:20,477 --> 00:07:23,277 +Really your application gets launched. +当你的应用启动时 + +185 +00:07:23,279 --> 00:07:24,712 +The user is using it. +用户就在使用它 + +186 +00:07:24,714 --> 00:07:26,814 +Then the user clicks to go to a different app. +然后用户切换到另一个不同应用 + +187 +00:07:26,816 --> 00:07:29,049 +And they come back to your app. +然后他们再返回到你的应用 + +188 +00:07:29,051 --> 00:07:31,918 +Maybe, your app starts using a lot of memory. +也许,你的应用启动时使用了很多内存 + +189 +00:07:31,920 --> 00:07:34,454 +Or does something else, that the system doesn't like. +或者做了其他系统不喜欢的事情 + +190 +00:07:34,456 --> 00:07:37,723 +Or the phone runs out of power. +或者手机没电了 + +191 +00:07:37,725 --> 00:07:40,025 +And you get killed, okay? +你的应用被杀掉了 + +192 +00:07:40,027 --> 00:07:42,060 +And so, that's kinda the life cycle. +这就是生命周期 + +193 +00:07:42,062 --> 00:07:43,295 +And you go back and +然后你的应用在前台 + +194 +00:07:43,296 --> 00:07:44,529 +forth between being in the foreground, +来回使用 + +195 +00:07:44,531 --> 00:07:45,697 +which means the user's using you. +也就是用户在使用你的应用 + +196 +00:07:45,699 --> 00:07:46,964 +And being in the background, +然后在后台 + +197 +00:07:46,966 --> 00:07:48,932 +which means the user's using something else. +这意味中用户在使用其他的应用 + +198 +00:07:48,934 --> 00:07:51,301 +That's the green versus blue in this picture. +这就是这张图中绿色与蓝色部分 + +199 +00:07:51,303 --> 00:07:53,870 +But you transition from these states in a very orderly +但你在这些状态中以一个非常有序的方式 + +200 +00:07:53,872 --> 00:07:54,888 +fashion. +过渡 + +201 +00:07:54,889 --> 00:07:55,905 +And we're going to talk about that transition. +我们将谈谈这个转变 + +202 +00:07:55,907 --> 00:07:56,605 +So. + +203 +00:07:56,607 --> 00:07:58,073 +In the green area, so +在绿色区域 + +204 +00:07:58,074 --> 00:07:59,540 +you start out not running, that's at the top. +开始应用没有运行,这就是顶部 + +205 +00:07:59,543 --> 00:08:01,443 +Obviously, your app is not even running at all. +显然,你的应用甚至都没有运行 + +206 +00:08:01,445 --> 00:08:03,011 +Okay? Then you move to this +然后你移到这个 + +207 +00:08:03,013 --> 00:08:06,747 +foreground state where you're, you start out inactive, +前台状态,你开始活跃 + +208 +00:08:06,749 --> 00:08:08,716 +which means you're running. +这意味着你开始运行 + +209 +00:08:08,718 --> 00:08:10,083 +Your code is running, but +你的代码正在运行,但是 + +210 +00:08:10,085 --> 00:08:12,018 +you're not getting any UI events. +你并没有得到任何 UI 事件 + +211 +00:08:12,020 --> 00:08:13,486 +Okay. You're not really displayed +实际上你没有在屏幕上 + +212 +00:08:13,488 --> 00:08:14,920 +onscreen and getting touch events yet. +显示,也没有得到触摸事件 + +213 +00:08:14,922 --> 00:08:16,855 +But you started up, you started running. +但你启动了,你开始运行 + +214 +00:08:16,857 --> 00:08:19,458 +Then you move to this state where you're active, +然后你移到这个状态,在这里你是活跃的 + +215 +00:08:19,460 --> 00:08:21,726 +which is your view controller is on screen, +这里你的控制器将在屏幕上显示 + +216 +00:08:21,728 --> 00:08:23,261 +it's getting touch events. +你得到了触摸事件 + +217 +00:08:23,263 --> 00:08:24,695 +This is normal mode. +这是正常的模式 + +218 +00:08:24,697 --> 00:08:26,319 +Okay? + +219 +00:08:26,320 --> 00:08:27,942 +This is what you're used to. +这就是你已经习惯的 + +220 +00:08:27,943 --> 00:08:29,565 +This is where you are most of the time that your code +当你的代码运行时,这就是你大部分时候所在 + +221 +00:08:29,568 --> 00:08:31,268 +is running. +的地方 + +222 +00:08:31,269 --> 00:08:32,969 +But if the user clicks on another app, +但当用户点击另一个应用 + +223 +00:08:32,971 --> 00:08:36,439 +then you can move to this state called the background +你可以移到这个叫做后台的状态 + +224 +00:08:36,441 --> 00:08:39,275 +where you'll run for a very brief period. +在这里你运行很短的时间 + +225 +00:08:39,277 --> 00:08:41,243 +I could be incredibly brief and +我可以难以置信的简单 + +226 +00:08:41,245 --> 00:08:43,479 +then your code just stops running. +然后你的代码将停止运行 + +227 +00:08:43,481 --> 00:08:46,048 +Now you're not, you haven't been killed, but +现在你没有,你的应用还没被杀掉 + +228 +00:08:46,050 --> 00:08:47,449 +your code is not running. +但你的代码没有运行 + +229 +00:08:47,451 --> 00:08:49,050 +So there's nothing you can do in this state. +在这个状态下你什么也做不了 + +230 +00:08:49,052 --> 00:08:51,118 +Now when you transition to this background, +当你切换到后台时 + +231 +00:08:51,120 --> 00:08:52,686 +you can ask for a little more time. +你可以请求多一点的时间 + +232 +00:08:52,688 --> 00:08:55,188 +But if you don't, you kinda quickly go to the state +但如果你没有,你将很快转换到 + +233 +00:08:55,190 --> 00:08:56,623 +where you're not running. +你没运行的状态 + +234 +00:08:56,625 --> 00:08:58,175 +Okay. + +235 +00:08:58,176 --> 00:08:59,726 +That's the suspended state down at the bottom. +这是在底部的挂起状态 + +236 +00:08:59,728 --> 00:09:02,395 +So you stay in this blue area for a short amount of time, +因此你在蓝色区域停留很短的时间 + +237 +00:09:02,397 --> 00:09:03,629 +this background state. +这个后台状态 + +238 +00:09:03,631 --> 00:09:06,565 +Now you can be put into this blue area other times too. +你可能在其他时候被放置在这个蓝色区域 + +239 +00:09:06,567 --> 00:09:08,767 +Like there's a way to tell the system, hey, +比如有种方式告诉系统 + +240 +00:09:08,769 --> 00:09:10,702 +I want to wake up every once in a while and +我想要隔一段时间就被唤醒 + +241 +00:09:10,704 --> 00:09:12,837 +go and fetch something from the internet. +去从网络中请求一些数据 + +242 +00:09:12,839 --> 00:09:14,772 +So that when the user does launch my app or +因此当用户启动我的应用或者 + +243 +00:09:14,774 --> 00:09:16,173 +bring it to the foreground, +把它带到前台时 + +244 +00:09:16,175 --> 00:09:18,308 +I have got the latest information for them. +我已经为他们获取了最新的信息 + +245 +00:09:18,310 --> 00:09:19,826 +Okay? + +246 +00:09:19,827 --> 00:09:21,343 +So the system can wake you up in the background. +系统可以在后台唤醒你 + +247 +00:09:21,346 --> 00:09:24,180 +You'll run for a very short amount of time while you go do +你可以运行非常短的时间,当你 + +248 +00:09:24,182 --> 00:09:27,149 +this little fetch and then you go back to suspended state. +需要获取一些数据,然后你回到挂起状态 + +249 +00:09:27,151 --> 00:09:29,151 +Okay? + +250 +00:09:29,152 --> 00:09:31,152 +Now, while you're in the suspended state, okay? +当你在挂起状态时 + +251 +00:09:31,155 --> 00:09:34,522 +Down here and your code is not running at all. +在下面的这里,你的代码根本没有运行 + +252 +00:09:34,524 --> 00:09:37,025 +None of your code is being executed and +你的代码并没有被执行 + +253 +00:09:37,027 --> 00:09:39,026 +you could be killed from here. +你的应用可能在这里被杀死 + +254 +00:09:39,028 --> 00:09:42,162 +So you wanna be careful when you move from the background +因此你需要小心,当你从后台状态转换到 + +255 +00:09:42,164 --> 00:09:45,198 +state to the suspended state to clean everything up and +挂起状态,保证清理了所有东西并且 + +256 +00:09:45,200 --> 00:09:47,334 +get everything ready for your death. +做好应用挂掉的准备 + +257 +00:09:47,336 --> 00:09:48,101 +Okay? + +258 +00:09:48,103 --> 00:09:49,268 +Cuz you might get killed. +因为你的应用可能被杀死 + +259 +00:09:49,270 --> 00:09:51,837 +That's rare to get killed, but you could. +应用很少会被杀死,但却是可能的 + +260 +00:09:51,839 --> 00:09:53,289 +Okay? + +261 +00:09:53,290 --> 00:09:54,740 +So you have to think of being in suspended state as +所以你要考虑到在挂起状态,当 + +262 +00:09:54,742 --> 00:09:56,975 +I'm suspended and I could be killed at any moment. +我的应用挂起时,它随时可能被杀死 + +263 +00:09:56,977 --> 00:09:59,277 +So [LAUGH] you can't run any code when you're gonna be +当你的应用被杀死时,你不能运行任何代码 + +264 +00:09:59,279 --> 00:10:01,746 +killed, so you better clean that up when you're passing +所以你最好清理应用,当你在后台 + +265 +00:10:01,748 --> 00:10:04,048 +through the back, creating through a background. +时,在后台创建一些东西 + +266 +00:10:04,050 --> 00:10:05,383 +Okay. + +267 +00:10:05,384 --> 00:10:06,717 +So let's talk about how you find out, +让我们谈谈你如何发现 + +268 +00:10:06,719 --> 00:10:09,552 +as you move through and you can only pass along the orange +当你转换状态,你只能沿着这些桔色的线 + +269 +00:10:09,554 --> 00:10:11,187 +lines to get from these states. +转换到这些状态 + +270 +00:10:11,189 --> 00:10:12,572 +Okay? So + +271 +00:10:12,573 --> 00:10:13,956 +when you come out of the background, +当你从后台返回时 + +272 +00:10:13,958 --> 00:10:16,959 +you briefly will be inactive and then go to active. +你从短暂的非活跃状态转换到活跃状态 + +273 +00:10:16,961 --> 00:10:18,694 +Right? + +274 +00:10:18,695 --> 00:10:20,428 +So let's talk about how we pass through. +让我们谈谈如何做这种转换 + +275 +00:10:20,431 --> 00:10:23,999 +So launching is just a matter of moving into the foreground, +启动只是转换到前台的事情 + +276 +00:10:24,001 --> 00:10:26,567 +briefly inactive and then you're active. +短暂的不活跃,然后你的应用变成活跃状态 + +277 +00:10:26,569 --> 00:10:28,936 +That's your application being launched. +这样你的应用被启动了 + +278 +00:10:28,938 --> 00:10:32,806 +Switching to another app is you started out active, +切换到另一个应用,你不再活跃 + +279 +00:10:32,808 --> 00:10:35,008 +you go inactive for a moment. +一会你就变成不活跃 + +280 +00:10:35,010 --> 00:10:38,077 +You come around, you're in background for a moment and +你的应用苏醒过来,当其他的应用在运行时 + +281 +00:10:38,079 --> 00:10:41,047 +then you go suspended while the other app gets to run. +一会你就在后台然后转换到挂起状态 + +282 +00:10:41,049 --> 00:10:43,266 +Okay? + +283 +00:10:43,267 --> 00:10:45,484 +So that's the flow of switching to another app. +这就是切换到另一个应用的过程 + +284 +00:10:45,486 --> 00:10:47,853 +Okay? + +285 +00:10:47,854 --> 00:10:50,221 +Now every time you make a transition along these orange +每次你沿着这些桔色的线做 + +286 +00:10:50,223 --> 00:10:52,190 +lines, you get notified. +转换,你都会收到通知 + +287 +00:10:52,192 --> 00:10:55,526 +So let's talk about, for example, own's, +让我们谈谈,比如,我们自己的应用 + +288 +00:10:55,528 --> 00:10:56,894 +of course killed. +当然被杀掉 + +289 +00:10:56,896 --> 00:10:58,362 +You can be killed, your code won't run. +你可能被杀掉,你的代码不会运行 + +290 +00:10:58,364 --> 00:11:01,865 +Be careful, be ready. +准备好,小心点 + +291 +00:11:01,867 --> 00:11:02,799 +All right. So let's talk about +让我们谈谈 + +292 +00:11:02,801 --> 00:11:04,768 +these transitions. +这些转换 + +293 +00:11:04,769 --> 00:11:06,736 +So right there, the little yellow circle is talking about +在那里,这个小黄圆圈 + +294 +00:11:06,738 --> 00:11:09,705 +moving into this inactive state from not running. +从未运行转换到这个不活跃的状态 + +295 +00:11:09,707 --> 00:11:11,006 +Okay? When that happens, +当这发生时 + +296 +00:11:11,008 --> 00:11:13,541 +you get sent this message to your application delegate. +你发送这个消息给你的应用代理 + +297 +00:11:13,543 --> 00:11:16,944 +You remember that AppDelegate file that I always drag out of +你们记得这个 AppDelegate 文件吗?每次在我的例子开始时 + +298 +00:11:16,946 --> 00:11:20,081 +the way every single time at the beginning of my demos? +我经常把它拖拽到其他地方 + +299 +00:11:20,083 --> 00:11:22,883 +Well, that file is an interesting file. +这个文件是个有趣的文件 + +300 +00:11:22,885 --> 00:11:25,118 +It actually has a class in it called your AppDelegate. +实际上它有一个类,叫做 AppDelegate + +301 +00:11:25,120 --> 00:11:28,154 +Your AppDelegate is the delegate of your UI +你的 AppDelegate 是你的 UI 应用对象的 + +302 +00:11:28,156 --> 00:11:31,924 +application object and the UI application object, +代理,是 UI 应用对象 + +303 +00:11:31,926 --> 00:11:33,625 +you never subclass it. +你从不继承它 + +304 +00:11:33,627 --> 00:11:36,094 +If you want to customize its behavior, you do so +如果你需要定制它的行为,你在 AppDelegate + +305 +00:11:36,096 --> 00:11:38,563 +by implementing methods in the AppDelegate. +中实现方法 + +306 +00:11:38,565 --> 00:11:40,631 +So one of the methods you can get sent, +其中一个方法,你可以发送 + +307 +00:11:40,633 --> 00:11:43,701 +one of the delegate protocol methods for an application +应用代理其中一个代理协议方法是 + +308 +00:11:43,703 --> 00:11:47,104 +delegate is application did finish launching with options. +application didFinishLaunchingWithOptions + +309 +00:11:47,106 --> 00:11:48,939 +And that gives you a dictionary, +这个方法给你一个字典 + +310 +00:11:48,941 --> 00:11:50,974 +which we'll talk about in a second. +一会我们将谈到这个 + +311 +00:11:50,976 --> 00:11:52,241 +And so that, so +因此 + +312 +00:11:52,243 --> 00:11:56,879 +you're always gonna know the first time you startup from +你总是第一时间知道你的应用 + +313 +00:11:56,881 --> 00:12:01,549 +not being running at all to being in this inactive state. +从未运行转换到这个不活跃状态 + +314 +00:12:01,551 --> 00:12:03,951 +Now what's in the [INAUDIBLE] by the way, +[INAUDIBLE] 是什么,顺便说下 + +315 +00:12:03,953 --> 00:12:06,587 +you get all these messages sent to you to your +你在你的 AppDelegate 中获得所有 + +316 +00:12:06,589 --> 00:12:09,590 +AppDelegate, but you also a get a notification. +这些信息,但你也得到一个通知 + +317 +00:12:09,592 --> 00:12:11,224 +That we were talking about in previous slide. +就是我们在上个幻灯片中谈到的 + +318 +00:12:11,226 --> 00:12:13,093 +So you can sign up to listen to the radio station. +你可以注册收听这个电台 + +319 +00:12:13,095 --> 00:12:15,628 +UI application did finish launching notification and +UIApplicationDidFinishLauningNotification 然后 + +320 +00:12:15,630 --> 00:12:18,531 +when you launch, you'll get a message on the radio station. +当你启动时,你将在电台中得到一个消息 + +321 +00:12:18,533 --> 00:12:20,666 +Now that's only gonna happen once per launching of your +显然,这只会在你每次启动应用时 + +322 +00:12:20,668 --> 00:12:22,201 +app, obviously. +发生 + +323 +00:12:22,202 --> 00:12:23,735 +And the user info in that notification, +在通知中的 userInfo + +324 +00:12:23,737 --> 00:12:27,271 +of course contains the same dictionary that's being passed +当然包含了它在这个方法中将被传递的 + +325 +00:12:27,273 --> 00:12:28,239 +to this method. +字典 + +326 +00:12:28,241 --> 00:12:29,840 +Okay? + +327 +00:12:29,842 --> 00:12:32,009 +So what's the difference between these two? +这两个有什么区别? + +328 +00:12:32,011 --> 00:12:35,879 +Well, you know, if you put the code in your AppDelegate to +你们知道的,当你在 AppDelegate 中写代码 + +329 +00:12:35,881 --> 00:12:39,148 +find out that you've been launched, you know, +来判断你是否被启动了,你们知道的 + +330 +00:12:39,150 --> 00:12:41,217 +it kinda has to be global code. +这类似于全局代码 + +331 +00:12:41,219 --> 00:12:43,236 +Right? Because you're just, +对吧?因为你刚刚 + +332 +00:12:43,237 --> 00:12:45,254 +it's in you AppDelegate, it's kind of in this global place. +在你的 AppDelegate 中,在这个全局的地方 + +333 +00:12:45,256 --> 00:12:48,623 +Whereas if a particular view controller wanted to find out, +如果有一个特别的视图控制器需要被发现 + +334 +00:12:48,625 --> 00:12:49,891 +oh, I just launched. +我(控制器)刚刚启动 + +335 +00:12:49,893 --> 00:12:51,276 +Okay? + +336 +00:12:51,277 --> 00:12:52,660 +It can have its code in itself, so +它内部可以有自己的代码 + +337 +00:12:52,662 --> 00:12:54,695 +it can be more object oriented. +它可以更面向对象 + +338 +00:12:54,697 --> 00:12:56,313 +Right? + +339 +00:12:56,314 --> 00:12:57,930 +It can have its reaction to launching be just in itself, +它可以在内部对启动做出反应 + +340 +00:12:57,933 --> 00:13:00,133 +it doesn't have to be talking to some global thing +它不需要和全局的东西进行通信 + +341 +00:13:00,135 --> 00:13:02,235 +like the AppDelegate. +比如 AppDelegate + +342 +00:13:02,236 --> 00:13:04,336 +And in general, you wanna be careful about the AppDelegate, +一般的,使用 AppDelegate 时你需要小心点 + +343 +00:13:04,339 --> 00:13:05,805 +cuz it is a global resource. +因为它是全局资源 + +344 +00:13:05,807 --> 00:13:08,040 +And as you know, from all your computer science training. +你们知道的,在你们的计算机科学知识中 + +345 +00:13:08,042 --> 00:13:09,742 +Globals can be bad. +全局是不好的 + +346 +00:13:09,744 --> 00:13:11,293 +Okay? + +347 +00:13:11,294 --> 00:13:12,843 +Globals are generally not the way you wanna communicate +全局通常不是你想交流信息的方式 + +348 +00:13:12,846 --> 00:13:14,879 +information, but some things are global. +当有些东西是全局的 + +349 +00:13:14,881 --> 00:13:16,314 +Okay? + +350 +00:13:16,315 --> 00:13:17,748 +Like when we talk about core motion and the phone, +比如当我们谈论 core motion 和手机 + +351 +00:13:17,751 --> 00:13:20,418 +there's only one gyro, there's only one accelerometer. +只有一个陀螺仪,只有一个加速计 + +352 +00:13:20,420 --> 00:13:21,885 +That is global, okay? +这就是全局 + +353 +00:13:21,887 --> 00:13:25,989 +To your entire device, certainly to your entire app. +你的整个设备,当然,你的整个应用 + +354 +00:13:25,991 --> 00:13:27,057 +Okay. + +355 +00:13:27,058 --> 00:13:28,124 +So some things are global, but +因此有些东西是全局的 + +356 +00:13:28,126 --> 00:13:30,726 +don't use global variables basically through your +但别使用全局变量,在你的 + +357 +00:13:30,728 --> 00:13:32,461 +AppDelegate to circumvent that. +AppDelegate 中别使用 + +358 +00:13:32,463 --> 00:13:33,462 +All right. + +359 +00:13:33,463 --> 00:13:34,462 +So what's in this past dictionary, +在这个传递的字典中有什么 + +360 +00:13:34,465 --> 00:13:35,630 +this dictionary that you get? +你获取的这个字典? + +361 +00:13:35,632 --> 00:13:37,865 +It's basically gonna tell you why you were launched. +基本上它会告诉你你为什么被启动了 + +362 +00:13:37,867 --> 00:13:38,966 +Okay? + +363 +00:13:38,968 --> 00:13:41,835 +Cuz you can get launched for a lot of reasons. +因为你可能由于很多原因被启动 + +364 +00:13:41,837 --> 00:13:43,904 +The user might have just clicked on you, okay? +用户可能只是点击了你的应用 + +365 +00:13:43,906 --> 00:13:45,505 +And launch you, but +然后启动了应用 + +366 +00:13:45,507 --> 00:13:49,975 +it might be a situation where someone air dropped a file of +但也可能是这种情况,有人通过 AirDrop 传送了一个 + +367 +00:13:49,977 --> 00:13:53,145 +a certain type that you know how to open. +你知道怎么打开的文件 + +368 +00:13:53,147 --> 00:13:56,381 +And the system will launch you to open that file, +因此系统将启动你来打开这个文件 + +369 +00:13:56,383 --> 00:13:57,782 +which is kinda cool. +这非常酷 + +370 +00:13:57,784 --> 00:13:59,951 +We're gonna hopefully do air drop in our demo today. +我们将在今天的例子中讲解 AirDrop + +371 +00:13:59,953 --> 00:14:03,154 +You might have setup some boundaries, and +你们可能创建了一些边界 + +372 +00:14:03,156 --> 00:14:06,523 +your phone moved into that part of the world. +当你们的手机移动到这个世界的这个部分 + +373 +00:14:06,525 --> 00:14:10,027 +So, it's possible to actually setup s big region and say, +实际上,有可能创建一个很大的区域 + +374 +00:14:10,029 --> 00:14:13,029 +when this device comes in this region, run my app. +当这个设备到达这个区域时,运行我的应用 + +375 +00:14:13,031 --> 00:14:14,297 +Okay? + +376 +00:14:14,299 --> 00:14:17,466 +And if your app is not running, it will get launched. +如果你的应用没有运行,它将被启动 + +377 +00:14:17,468 --> 00:14:19,668 +Okay? + +378 +00:14:19,669 --> 00:14:21,869 +To go deal with the fact that you just moved near the dry +处理这些情况,当你移动到干洗机附近时 + +379 +00:14:21,872 --> 00:14:23,989 +cleaners or +或者 + +380 +00:14:23,990 --> 00:14:26,107 +whatever you put in there as one of your regions. +你的区域中的任何一个地方 + +381 +00:14:26,110 --> 00:14:29,277 +In iOS8, you can start an activity like editing a file +在 iOS8,你可以开始一个活动,在一个设备中 + +382 +00:14:29,279 --> 00:14:32,580 +on one device, like your Mac and then walk out the door and +编辑一个文件,比如你的 Mac,然后走出门 + +383 +00:14:32,582 --> 00:14:34,949 +pull out your phone and keep editing it. +然后取出你的手机,继续编辑这个文件 + +384 +00:14:34,951 --> 00:14:36,484 +Okay? So, + +385 +00:14:36,485 --> 00:14:38,018 +it's kind of like you can continue activities, so +这有点类似于你的活动可以持续性地进行 + +386 +00:14:38,020 --> 00:14:40,320 +you might get launched to continue an activity. +你可能由于继续一个活动而被启动 + +387 +00:14:40,322 --> 00:14:42,522 +Okay? You could get launched, +你可能被启动 + +388 +00:14:42,524 --> 00:14:45,224 +because a push notification arrives. +由于一个推送通知到达 + +389 +00:14:45,226 --> 00:14:46,859 +Do you know what a push notification is? +你们知道什么是推送通知吗? + +390 +00:14:46,861 --> 00:14:50,662 +Basically, this service where third parties can send you +基本上,使用这个服务,第三方可以给你 + +391 +00:14:50,664 --> 00:14:51,863 +notifications. +发送通知 + +392 +00:14:51,865 --> 00:14:54,832 +So for example, if you're playing a game, +比如,如果你在玩一个游戏 + +393 +00:14:54,834 --> 00:14:57,902 +maybe its a turn based game and its your turn. +它可能是一个轮流制的游戏,现在轮到你 + +394 +00:14:57,904 --> 00:15:00,070 +You can go to push notification and +你可以在推送通知 + +395 +00:15:00,072 --> 00:15:02,806 +it might launch the game to take your turn. +它可能启动这个游戏开始 + +396 +00:15:02,808 --> 00:15:04,040 +Okay? + +397 +00:15:04,042 --> 00:15:05,742 +So a lot of reasoning could be launched and +有很多原因都可以启动应用 + +398 +00:15:05,744 --> 00:15:08,210 +that dictionary is going to contain information about why. +这个字典将包含为何启动的信息 + +399 +00:15:08,212 --> 00:15:09,578 +All right? + +400 +00:15:09,580 --> 00:15:13,181 +Now, it used to be that an application didn't finish +它习惯于应用启动并没有带 + +401 +00:15:13,183 --> 00:15:16,651 +launching with options, you would build your UI. +options,你可以创建你的 UI + +402 +00:15:16,653 --> 00:15:18,119 +So you'd instantiate a split view, +你要初始化一个 split 视图 + +403 +00:15:18,121 --> 00:15:19,987 +you'd instantiate a navigation controller. +你必须初始化一个 navigation controller + +404 +00:15:19,989 --> 00:15:21,121 +You'd put in there with a master. +你要在里面放一个 master + +405 +00:15:21,123 --> 00:15:22,556 +You'd put to create your view controller. +你需要在其中创建你的视图控制器 + +406 +00:15:22,558 --> 00:15:23,624 +Okay. + +407 +00:15:23,625 --> 00:15:24,691 +We don't do any of that anymore and +我们不要再做任何更多的事情 + +408 +00:15:24,693 --> 00:15:27,493 +when you're searching on the internet for how to do things, +当你在网上搜索如何实现一些东西时 + +409 +00:15:27,495 --> 00:15:30,029 +you're probably gonna find some old stuff that says, +你很有可能找到一些旧的说法 + +410 +00:15:30,031 --> 00:15:32,831 +put this in application did finish launching with options. +把这些放在 ApplicationDidFinishLaunchingWithOptions + +411 +00:15:32,833 --> 00:15:34,833 +I'm generally a fan of not putting that kind +基本上我不会把这类代码放在 + +412 +00:15:34,835 --> 00:15:37,569 +of code in application did finish launching with options. +ApplicationDidFinishLaunchingWithOptions + +413 +00:15:37,571 --> 00:15:39,003 +It's really not what it's for. +它不是为了做这些事情 + +414 +00:15:39,005 --> 00:15:40,772 +It's more for +它是为了 + +415 +00:15:40,773 --> 00:15:42,540 +handling all these other kind of global events, +处理所有这些另外的全局事件 + +416 +00:15:42,542 --> 00:15:45,409 +like somebody wants you to open a file or whatever. +比如有人希望你打开一个文件或者其他的任何东西 + +417 +00:15:45,411 --> 00:15:46,521 +Okay? + +418 +00:15:46,522 --> 00:15:47,632 +It's not where you build your UI. +你不应该在这里创建你的 UI + +419 +00:15:47,633 --> 00:15:48,743 +You build your UI in your storyboard as much +你尽可能在你的 storyboard 中 + +420 +00:15:48,747 --> 00:15:49,379 +as possible. +创建 UI + +421 +00:15:49,381 --> 00:15:50,913 +All right? + +422 +00:15:50,915 --> 00:15:52,948 +Okay. + +423 +00:15:52,950 --> 00:15:58,220 +So now you are moving, so you've been active. +现在你移动了,你已经处于活跃状态 + +424 +00:15:58,222 --> 00:15:59,754 +Okay? We haven't talked about this +我们还没谈到这个变成 + +425 +00:15:59,756 --> 00:16:00,588 +getting too active. +活跃状态了 + +426 +00:16:00,590 --> 00:16:02,423 +But let's say you are active now. +但让我们说现在你是活跃的 + +427 +00:16:02,425 --> 00:16:04,825 +And someone clicks on another app. +然后有人点击了另一个应用 + +428 +00:16:04,827 --> 00:16:06,560 +And you go to this inactive state. +然后你到了这个不活跃的状态 + +429 +00:16:06,562 --> 00:16:08,895 +You go from active to inactive. +你从活跃变成不活跃 + +430 +00:16:08,897 --> 00:16:10,029 +You're going to get application will +你将取得 applicationWillResignActive + +431 +00:16:10,031 --> 00:16:11,731 +resign active. + + +432 +00:16:11,732 --> 00:16:13,432 +Now, what do you want to do in this method, +在这个方法中,你想要做什么 + +433 +00:16:13,434 --> 00:16:15,501 +or when you get this notification? +或者什么时候你会收到这个通知? + +434 +00:16:15,503 --> 00:16:18,070 +This is mostly where you want to pause your UI. +大部分时候是在你需要暂停你的 UI + +435 +00:16:18,072 --> 00:16:20,939 +Because you've just gone inactive. +因为你将变成不活跃 + +436 +00:16:20,941 --> 00:16:22,474 +Okay? + +437 +00:16:22,475 --> 00:16:24,008 +It might be that someone's going to come right back to +有可能有人返回你的应用 + +438 +00:16:24,010 --> 00:16:25,409 +you and you want to continue. +你需要继续 + +439 +00:16:25,411 --> 00:16:26,994 +Okay? + +440 +00:16:26,995 --> 00:16:28,578 +So in resign active, you want to pause. +在 ResignActivie 时,你需要暂停 + +441 +00:16:28,581 --> 00:16:31,548 +This is I think of as the pause method. +这就是我认为的暂停方法 + +442 +00:16:31,550 --> 00:16:32,349 +Okay? + +443 +00:16:32,351 --> 00:16:34,685 +You're going from active, +你将从活跃 + +444 +00:16:34,686 --> 00:16:37,020 +where the user is using your to this inactive state, pause. +也就是用户在使用你的应用变成这个不活跃状态,暂停 + +445 +00:16:37,022 --> 00:16:38,421 +Okay? Now you might be on your way +你可能在你转变进入 + +446 +00:16:38,423 --> 00:16:40,089 +to going to into the background, but +后台的过程中,但 + +447 +00:16:40,091 --> 00:16:41,540 +you might not be. +也可能不是 + +448 +00:16:41,541 --> 00:16:42,990 +It might just be that a phone call came in. +有可能有个电话进来了 + +449 +00:16:42,993 --> 00:16:45,160 +When a phone call comes in, kind of the current +当一个电话进来时,类似当前应用 + +450 +00:16:45,162 --> 00:16:46,861 +application gets put in the inactive state, +变成不活跃状态 + +451 +00:16:46,863 --> 00:16:48,095 +you answer the call, and +你接了电话 + +452 +00:16:48,097 --> 00:16:50,230 +when you're done it goes back to being active again. +当你接完电话,返回到活跃状态 + +453 +00:16:51,200 --> 00:16:53,733 +Okay, so you want to pause there. +所以你需要在那里暂停 + +454 +00:16:53,735 --> 00:16:55,535 +Now, what about going back to active? +返回到活跃状态会怎样? + +455 +00:16:55,537 --> 00:16:57,136 +So you were paused and +你被暂停了 + +456 +00:16:57,138 --> 00:17:00,239 +you transitioned to active, or you were launched and +然后你转变到活跃状态,或者你被启动了 + +457 +00:17:00,241 --> 00:17:02,040 +you transitioned all the way to active. +你转变到活跃状态 + +458 +00:17:02,042 --> 00:17:04,342 +This is where you want to, kind of, unpause. +这里你想要不暂停 + +459 +00:17:04,344 --> 00:17:05,877 +So this is where you +在这里你 + +460 +00:17:05,879 --> 00:17:08,412 +would undo whatever you did in Resign. +将撤销你在 Resign 中做的事情 + +461 +00:17:08,414 --> 00:17:11,348 +So Resign and BecomeActive obviously are paired. +所以 Resign 和 BecomeActive 显然是一对的 + +462 +00:17:11,350 --> 00:17:14,117 +Resign, you can kinda think as pause my state. +Resign,你可以认为暂停我的状态 + +463 +00:17:14,119 --> 00:17:16,853 +And BecomeActive, you can think of as resume my state. +而 BecomeActive,你可以认为重新开始我的状态 + +464 +00:17:16,855 --> 00:17:18,054 +Now, of course, when you're launching for +当然,当你第一次启动时 + +465 +00:17:18,056 --> 00:17:20,923 +the first time, you go through the Inactive state. +你会经历不活跃状态 + +466 +00:17:20,925 --> 00:17:23,659 +You never resigned Active, so you never paused. +你从不 resignedActive,所以你从不暂停 + +467 +00:17:23,661 --> 00:17:25,627 +So there's never, no reason to resume. +这里永不,也没有理由重新开始 + +468 +00:17:25,629 --> 00:17:27,162 +Okay? You still might do some +你仍需要做在那种情况下 + +469 +00:17:27,164 --> 00:17:29,597 +of the things you do to resume in that case. +重新开始的一些事情 + +470 +00:17:29,599 --> 00:17:32,266 +But obviously that combination can happen. +但显然,这种组合可能发生 + +471 +00:17:33,269 --> 00:17:34,468 +All right. So what about this state? +这种状态下会怎样? + +472 +00:17:34,470 --> 00:17:37,537 +So now you've gone to background. +现在你进入后台 + +473 +00:17:37,539 --> 00:17:39,205 +So if they clicked on some other app, +如果他们点击其他的应用 + +474 +00:17:39,207 --> 00:17:40,139 +you go into the background. +你将进入后台 + +475 +00:17:40,141 --> 00:17:42,341 +Remember, you only go in here briefly. +记住,你只短暂地在这里 + +476 +00:17:42,343 --> 00:17:43,575 +Okay? This is where you wanna +在这里你需要做好应对危机的 + +477 +00:17:43,577 --> 00:17:46,344 +batten down the hatches and prepare for your death. +准备,为你(应用)的死亡做好准备 + +478 +00:17:46,346 --> 00:17:47,479 +Okay? + +479 +00:17:47,480 --> 00:17:48,613 +Because you could sit in background for +因为你可能在后台停留了 + +480 +00:17:48,615 --> 00:17:52,216 +just a few fractions of a second, go into suspended, and +一秒钟的一点碎片,便进入挂起状态 + +481 +00:17:52,218 --> 00:17:53,584 +then you could be killed. +然后你(应用)被杀死了 + +482 +00:17:53,586 --> 00:17:54,818 +Okay? Without ever getting chance +甚至没有机会再次 + +483 +00:17:54,820 --> 00:17:56,987 +to run again. +运行 + +484 +00:17:56,988 --> 00:17:59,155 +So going into the background stage application did enter +所以进入后台状态,applicationDidEnterBackground + +485 +00:17:59,157 --> 00:18:00,140 +background. + +486 +00:18:00,141 --> 00:18:01,124 +That's where you want to batten down the hatches, +在这里你需要做好应对危机的准备 + +487 +00:18:01,126 --> 00:18:03,093 +prepare for your own death. +为你(应用)自己的死去做好准备 + +488 +00:18:03,094 --> 00:18:05,061 +Save any unsaved information although you should probably +保存任何未保存的信息,即使你很可能 + +489 +00:18:05,063 --> 00:18:05,627 +be saving that. +正在保存 + +490 +00:18:05,629 --> 00:18:07,379 +Most of you don't. +大部分时候你没有 + +491 +00:18:07,380 --> 00:18:09,130 +Most of the things like here if you start off threads to go +这里的大部分事情,如果你开启线程做一些事情 + +492 +00:18:09,133 --> 00:18:11,266 +do things like you have a background thread that does +比如你有一个后台进程正在保存 + +493 +00:18:11,268 --> 00:18:13,935 +some saving, make sure that thread is finished. +数据,确保这个进程结束了 + +494 +00:18:13,937 --> 00:18:16,937 +And it is possible in DidEnterBackground to ask for +在 DidEnterBackground 中是可能请求 + +495 +00:18:16,939 --> 00:18:18,238 +more time. +多一些时间 + +496 +00:18:18,240 --> 00:18:19,906 +Okay? UI application has a method +UIApplication 有一个方法 + +497 +00:18:19,908 --> 00:18:22,142 +which I'm not gonna talk about, but you can basically +这个方法我还没讲到,但你基本上可以 + +498 +00:18:22,144 --> 00:18:25,812 +start up a background task and get some more time to run in +启动一个后台任务,然后在你进入挂起状态前 + +499 +00:18:25,814 --> 00:18:27,980 +this background stage before you go to suspended. +得到一些更多的时间在后台运行 + +500 +00:18:27,982 --> 00:18:30,182 +If you abuse that. +如果你滥用这个方法 + +501 +00:18:30,184 --> 00:18:32,518 +OKay? + +502 +00:18:32,519 --> 00:18:34,853 +Like you try to stay active forever, or for many minutes, +例如你试图永远留在活跃状态,或者停留很多分钟 + +503 +00:18:34,855 --> 00:18:37,422 +the system will stop granting you that. +系统将阻止让你这么做 + +504 +00:18:37,424 --> 00:18:38,823 +Okay? So don't do that. +所以别做这个 + +505 +00:18:38,825 --> 00:18:40,858 +System expects you, if you as for more time, +系统期待你,如果你请求多些时间 + +506 +00:18:40,860 --> 00:18:42,793 +to quickly get that done with. +快速完成事情 + +507 +00:18:42,795 --> 00:18:44,828 +Or to time out whatever you're doing, do something. +或者暂停任何你正在做的事情,做些事情 + +508 +00:18:44,830 --> 00:18:46,830 +Because when you go to the background it really wants you +因为当你在后台时,实际上它希望你 + +509 +00:18:46,832 --> 00:18:48,364 +to shut up, okay? +停止 + +510 +00:18:48,366 --> 00:18:50,933 +Be quite, because some other app is running right now. +保持安静,因为有其他的应用正在运行 + +511 +00:18:52,136 --> 00:18:55,137 +Okay, so that did DidEnterBackground. +因此 DidEnterBackground + +512 +00:18:55,139 --> 00:18:58,006 +When you get activated again from the background +当你再次从后台中变成活跃状态 + +513 +00:18:58,008 --> 00:19:00,808 +because someone clicked back on you, this is where you can +因为有人点击了你,在这里你可以 + +514 +00:19:00,810 --> 00:19:02,176 +un-batten down the hatches, right? +不用为危机做准备 + +515 +00:19:02,178 --> 00:19:03,410 +This is where you can open things back. +在这里你可以打开一些东西 + +516 +00:19:03,412 --> 00:19:04,762 +Back up a bit. +备份许多 + +517 +00:19:04,763 --> 00:19:06,113 +You're back in the foreground, okay? +你返回到前台 + +518 +00:19:06,115 --> 00:19:07,847 +Maybe if you had something saved or +也许如果你有些东西在保存或者 + +519 +00:19:07,849 --> 00:19:09,982 +you threw away something from the heap, +你从堆中丢掉一些东西 + +520 +00:19:09,984 --> 00:19:11,550 +you can load it back up, et cetera. +你可以把它加载回来,等等 + +521 +00:19:11,552 --> 00:19:14,453 +So, this is kind of getting yourself back to life +这类似于在应对危机之后返回到 + +522 +00:19:14,455 --> 00:19:16,922 +after battening down the hatches, okay? +生存状态 + +523 +00:19:16,924 --> 00:19:17,689 +So, that's it. +这就是全部了 + +524 +00:19:17,691 --> 00:19:18,322 +That's the cycle. +这就是生命周期 + +525 +00:19:18,324 --> 00:19:19,357 +That's how it goes. +这就是它如何运作 + +526 +00:19:19,359 --> 00:19:23,360 +The AppDelegate does a lot more things than just that +AppDelegate 处理了很多事情,不仅仅是 + +527 +00:19:23,362 --> 00:19:24,094 +cycle. +这个周期 + +528 +00:19:25,063 --> 00:19:26,696 +It handles notifications. +它处理通知 + +529 +00:19:27,632 --> 00:19:30,933 +It can do this whole thing, a state restoration. +它可以处理全部事情,一个状态存储 + +530 +00:19:30,935 --> 00:19:33,869 +So there's a way, kind of a mechanism I will say, +这是一种方式,我将会讲的一种机制 + +531 +00:19:33,871 --> 00:19:36,237 +which I don't have time to talk to you about, +这个我没有时间跟你们说更多 + +532 +00:19:36,239 --> 00:19:38,973 +where you can essentially, save the state of your UI, so +在这里你大体上可以保存你的 UI 状态 + +533 +00:19:38,975 --> 00:19:41,108 +that if you do get killed while you're suspended, +因此如果你在挂起时被杀死了 + +534 +00:19:41,110 --> 00:19:42,643 +and you start up again, +然后你再次启动了 + +535 +00:19:42,645 --> 00:19:45,245 +you'll start up in exactly the same place you were +你将从你上次所在的地方重启 + +536 +00:19:45,247 --> 00:19:47,614 +instead of starting up like a fresh app launch. +而不是全新启动一个应用 + +537 +00:19:48,717 --> 00:19:50,916 +So the AppDelegate is how you do all of that. +通过 AppDelegate 你可以做这些 + +538 +00:19:50,918 --> 00:19:51,984 +Look that up. +看这上面的 + +539 +00:19:51,986 --> 00:19:52,951 +Data protection. +数据保护 + +540 +00:19:52,953 --> 00:19:55,604 +There's a mechanism for +这里有一个机制 + +541 +00:19:55,605 --> 00:19:58,256 +saying, hey, the data that my app accesses should be +在手机锁定之后,我的应用访问的数据 + +542 +00:19:58,258 --> 00:20:02,926 +encrypted whenever the phone is locked. +需要加密 + +543 +00:20:02,928 --> 00:20:05,062 +That's great because if someone steals your phone or +这非常棒,因为有人偷了你的手机或者 + +544 +00:20:05,064 --> 00:20:07,464 +tries to break into it, all of the data's encrypted. +试图进入系统,所有数据加密了 + +545 +00:20:07,466 --> 00:20:08,698 +They can't see your data anyway, +他们不可能看到任何数据 + +546 +00:20:08,700 --> 00:20:10,399 +even if they hack into it. +即使他们攻击进入系统 + +547 +00:20:10,401 --> 00:20:14,503 +But you need to find out in your AppDelegate when that +但你需要在你的 AppDelegate 检查什么时候 + +548 +00:20:14,505 --> 00:20:17,773 +gets turned off and back on, so you can find that out. +它关闭和打开了,所以可以找出它们 + +549 +00:20:17,775 --> 00:20:20,608 +Obviously, opening and closing files, right? +显然,打开和关闭文件 + +550 +00:20:20,610 --> 00:20:23,594 +Not opening and closing, +不是打开和关闭 + +551 +00:20:23,595 --> 00:20:26,579 +opening files yourself, files that you know how to open. +你自己打开文件,你知道怎么打开的文件 + +552 +00:20:26,582 --> 00:20:28,682 +The Delegate gets sent a message saying, +代理发送了一条消息,说 + +553 +00:20:28,684 --> 00:20:29,950 +please open this URL. +请打开这个 URL + +554 +00:20:29,952 --> 00:20:31,618 +You have to register with the system for +你需要注册系统,什么样 + +555 +00:20:31,620 --> 00:20:33,453 +what kind of files you know how to do, and +的文件你知道如何打开 + +556 +00:20:33,455 --> 00:20:35,721 +we'll do that in the demo here. +我们要在例子中做这个 + +557 +00:20:35,723 --> 00:20:38,791 +But then this application delegate method is going +但这个应用代理方法将请求 + +558 +00:20:38,793 --> 00:20:40,025 +to ask you to open it. +你打开它 + +559 +00:20:40,027 --> 00:20:42,560 +And then I mentioned background fetching where you +我提到的,在后台获取中 + +560 +00:20:42,562 --> 00:20:45,430 +can, essentially, tell the system you want to wake up +大体上,告诉系统你想要隔一段时间 + +561 +00:20:45,432 --> 00:20:48,632 +every once in a while and do some work in the background. +就被唤醒,然后在后台做些工作 + +562 +00:20:48,634 --> 00:20:49,767 +And that's pretty cool. +这非常酷 + +563 +00:20:49,769 --> 00:20:51,602 +Again, you don't want to abuse it, or +再次,你不要滥用这个方法 + +564 +00:20:51,603 --> 00:20:53,436 +the system will start saying, wow, that guy's really a pig. +否则系统将开始抱怨,这个家伙真是只猪 + +565 +00:20:53,439 --> 00:20:55,205 +Every time I wake him up to run in the background, +每次我在后台唤醒它去运行 + +566 +00:20:55,207 --> 00:20:57,507 +he uses all kinds of battery, so +它使用了所有电量 + +567 +00:20:57,509 --> 00:20:59,575 +I'm going to stop waking him up so much. +因此我将不再唤醒它这么频繁了 + +568 +00:21:01,412 --> 00:21:01,943 +But it can do that. +但它能做这个 + +569 +00:21:01,945 --> 00:21:02,643 +So AppDelegate. +因此 AppDelegate + +570 +00:21:02,645 --> 00:21:03,928 +A lot of stuff in there. +那里有很多事情 + +571 +00:21:03,929 --> 00:21:05,212 +You can just go look at the documentation for it and +你可以只是查阅文档 + +572 +00:21:05,214 --> 00:21:06,780 +see all the things it can do. +看它都能做些什么事情 + +573 +00:21:06,782 --> 00:21:08,648 +Now in addition, question? +还有问题吗? + +574 +00:21:08,650 --> 00:21:12,218 +>> Yeah. I was just wondering, +我刚在想 + +575 +00:21:12,220 --> 00:21:15,288 +I had an app once which had music, and +我有一个播放音乐的应用 + +576 +00:21:15,290 --> 00:21:17,256 +when I pressed the home button or even locked the phone, +当我按下 home 键时,或者锁定了手机 + +577 +00:21:17,258 --> 00:21:19,525 +it would still keep playing. +它还可以继续 + +578 +00:21:19,527 --> 00:21:21,026 +Shouldn't it be like turning that off? +难道你不应该被关闭吗? + +579 +00:21:21,028 --> 00:21:23,628 +>> Yes, the question is, what if I have a music app and +问题是,如果我有一个音乐应用 + +580 +00:21:23,630 --> 00:21:25,096 +I'm playing music and +然后我正在播放音乐 + +581 +00:21:25,098 --> 00:21:28,165 +I switch to another app, how does it keep playing? +然后我切换到另一个应用,它是怎么做到继续播放的? + +582 +00:21:28,167 --> 00:21:30,534 +Well, that's one of the cases where you are allowed to be +这是你被允许在后台运行的 + +583 +00:21:30,536 --> 00:21:31,601 +running in the background. +一个例子 + +584 +00:21:31,603 --> 00:21:33,470 +So that app is running in the background. +因此这个应用在后台运行 + +585 +00:21:33,472 --> 00:21:37,073 +And you have to sign up and kind of requisition your app. +你需要注册,你的应用的要求 + +586 +00:21:37,075 --> 00:21:39,608 +You have to set a capability to do that. +你需要设置一个能力来实现这个 + +587 +00:21:39,610 --> 00:21:41,410 +But you can do it. +但你可以做到这个 + +588 +00:21:41,412 --> 00:21:43,679 +And, you know, if your app is a bad citizen and +你知道的,如果你的应用是个不良公民 + +589 +00:21:43,681 --> 00:21:45,046 +says it's a music playing app but +它是一个音乐播放应用,但 + +590 +00:21:45,048 --> 00:21:46,748 +it's doing other things in the background. +它在后台做了其他事情 + +591 +00:21:46,750 --> 00:21:48,849 +Again, if it starts using a lot of battery, +再次,如果它使用了太多的电量 + +592 +00:21:48,851 --> 00:21:50,017 +it's gonna get killed. +它将被杀死 + +593 +00:21:50,019 --> 00:21:52,152 +Or it's not gonna be given an opportunity. +系统不会给这样一个机会 + +594 +00:21:52,154 --> 00:21:54,754 +You might make it to the app store at the beginning. +你可能在开始的时候在应用商店做到了 + +595 +00:21:54,756 --> 00:21:57,056 +But eventually they'll pull you if you are abusing +但最后他们会下架你的应用,如果你滥用 + +596 +00:21:57,058 --> 00:21:58,457 +the backgrounding mechanisms. +后台机制 + +597 +00:21:58,459 --> 00:22:00,726 +Because there are other ways you can, you know. +因为有其他方式你可以,你知道的 + +598 +00:22:00,728 --> 00:22:03,195 +Voip apps need to be able to stay in the background, +贵宾应用需要能够留在后台 + +599 +00:22:03,197 --> 00:22:04,830 +you're on a phone call. +你在接一个电话 + +600 +00:22:04,831 --> 00:22:06,464 +There are reasons to stay live in the background. +他们有理由留在后台 + +601 +00:22:06,466 --> 00:22:09,467 +Some people think, IOS not really multi-tasking. +有人认为,iOS 不是真正的多任务 + +602 +00:22:09,469 --> 00:22:11,235 +It absolutely is multi-tasking, but +它绝对是多任务,但 + +603 +00:22:11,237 --> 00:22:13,971 +it has a philosophy which is the app +它有一个哲学,也就是用户当前 + +604 +00:22:13,973 --> 00:22:16,540 +that the user is currently interacting with should get +交互的应用应该得到 + +605 +00:22:16,542 --> 00:22:18,742 +almost all of the attention of the device. +设备的绝大部分资源 + +606 +00:22:18,744 --> 00:22:20,043 +That's just its philosophy, +这就是它的哲学 + +607 +00:22:20,045 --> 00:22:21,811 +which I think is a good philosophy. +我认为这是个好的哲学 + +608 +00:22:21,813 --> 00:22:23,045 +So anything that runs in the background, +因此所有在后台运行的东西 + +609 +00:22:23,047 --> 00:22:24,279 +has to really keep it quiet. +需要保持安静 + +610 +00:22:25,282 --> 00:22:29,383 +But music is one where it can play in the background. +但音乐是个可以在后台播放的应用 + +611 +00:22:29,385 --> 00:22:31,151 +So in addition to the Application Delegate, +另外,应用代理 + +612 +00:22:31,153 --> 00:22:32,953 +there's the UI application object itself, +这是 UIApplication 对象 + +613 +00:22:32,955 --> 00:22:35,722 +which is the shared thing you call this class function +就是你在这个函数 sharedApplication + +614 +00:22:35,724 --> 00:22:37,357 +shared application to get it. +中获取的共享对象 + +615 +00:22:37,359 --> 00:22:40,659 +And it manages all the global behavior in your app. +你管理你应用中的所有全局行为 + +616 +00:22:40,661 --> 00:22:42,961 +You don't subclass it. +你不用继承这个类 + +617 +00:22:42,963 --> 00:22:45,630 +But you can send it a lot of messages to do various +但你可以发送很多信息来做各种 + +618 +00:22:45,632 --> 00:22:48,733 +things like open a URL in another app. +事情,比如在另一个应用中打开一个 URL + +619 +00:22:48,735 --> 00:22:51,235 +So we talked about how the delegate is used +我门谈论使用代理在你的应用中 + +620 +00:22:51,237 --> 00:22:53,337 +to open a URL in your own app. +打开一个 URL + +621 +00:22:53,339 --> 00:22:56,607 +You can call this method open URL in application, +你可以调用这个方法在应用中打开 URL + +622 +00:22:56,609 --> 00:22:58,709 +and you did that in your last assignment. +你在你们上次作用中做了这个 + +623 +00:23:00,045 --> 00:23:02,145 +So you can open URL, and +你可以打开 URL + +624 +00:23:02,146 --> 00:23:04,246 +it will figure out what apps on your device handle that. +然后它将找出你设备上的哪个应用可以处理这个 + +625 +00:23:04,249 --> 00:23:06,482 +And it will open that URL up. +然后它将打开这个 URL + +626 +00:23:06,484 --> 00:23:09,885 +You can also register for +你也可以注册推送通知 + +627 +00:23:09,887 --> 00:23:14,556 +push notifications or you can schedule local notifications. +或者你可以安排本地通知 + +628 +00:23:14,558 --> 00:23:16,124 +So local notifications are just +本地通知是类似于 + +629 +00:23:16,126 --> 00:23:17,992 +notifications kind of like push notifications, but +推送通知,但 + +630 +00:23:17,994 --> 00:23:20,461 +they're totally local and they're timed. +它们完全是本地的,它们被计时 + +631 +00:23:20,463 --> 00:23:23,030 +So you say, send this notification to the user at +你会说,在这个时候发送这个通知给用户 + +632 +00:23:23,032 --> 00:23:25,331 +this time and it sends it to them. +然后它发送通知给他们了 + +633 +00:23:25,333 --> 00:23:27,900 +And then push notifications, as we've talked about before, +然后推送通知,就是我们之前谈过的 + +634 +00:23:27,902 --> 00:23:29,602 +are these things that come over the network when it's +通过网络发送的东西,当你 + +635 +00:23:29,604 --> 00:23:31,704 +your turn to play your game, or whatever. +继续玩你的游戏,或者其他任何事情 + +636 +00:23:31,706 --> 00:23:34,373 +So you can register to receive those in scheduled +因此你可以通过 UIApplication 注册接受一些本地 + +637 +00:23:34,375 --> 00:23:37,342 +notifications locally using UIApplication. +计划性的通知 + +638 +00:23:37,344 --> 00:23:40,712 +If you're doing this background fetching thing, +如果你做这个后台获取工作 + +639 +00:23:40,714 --> 00:23:43,414 +there's a very important function called +有一个非常重要的方法叫做 + +640 +00:23:43,416 --> 00:23:45,783 +setMinimumBackgroundFetchInte- rval. +setMinimumBackgroundFetchInterval + +641 +00:23:45,785 --> 00:23:48,518 +That by default is never. +这个默认值是 never + +642 +00:23:48,520 --> 00:23:51,321 +So you might go to all this trouble to say yeah, I want to +但你可能遇到所有这些麻烦,我想要 + +643 +00:23:51,323 --> 00:23:54,290 +do background fetching and all this stuff, and then if you +在后台获取数据,所有这些事情,然后如果你 + +644 +00:23:54,292 --> 00:23:57,126 +don't call this method to set your fetching interval to +没有调用这个方法来设置你的获取间隔为 + +645 +00:23:57,128 --> 00:23:59,995 +something besides never, you'll never get woken up. +某个值而非 never,你永远不会被唤醒 + +646 +00:23:59,997 --> 00:24:03,865 +Usually you set it to minimum, this interval minimum, +通常你设置它为 minimum,这个间隔 minimum + +647 +00:24:03,867 --> 00:24:06,901 +which is like, wake me up as much as you can. +就是尽可能多的唤醒我 + +648 +00:24:06,903 --> 00:24:09,904 +The system is kinda cool for this background fetching. +对于这个后台获取,系统是相当酷的 + +649 +00:24:09,906 --> 00:24:12,139 +It kinda watches when the user uses your app, and +它检测到,当用户使用你的应用时, + +650 +00:24:12,141 --> 00:24:13,640 +the more the user uses your app, +越多用户使用你的应用 + +651 +00:24:13,642 --> 00:24:16,343 +the more it's gonna let the background fetching happen, +它越有可能让后台获取发生 + +652 +00:24:16,345 --> 00:24:18,378 +because it's gonna figure the more it use. +因为它需要计算它使用越多 + +653 +00:24:18,380 --> 00:24:20,346 +It'll even kinda look at times of day. +它甚至一天检查几次 + +654 +00:24:20,348 --> 00:24:23,015 +This person runs this app every morning at 9:00, +这个用户每天早上 9:30 运行这个应用 + +655 +00:24:23,017 --> 00:24:24,783 +between 9:00 and 9:15, so +在 9:00 和 9:15 之间,因此 + +656 +00:24:24,785 --> 00:24:27,686 +we're gonna let this background fetch run at 8:30. +我们需要让后台获取发生在 8:30 + +657 +00:24:27,688 --> 00:24:30,138 +'Kay. + +658 +00:24:30,139 --> 00:24:32,589 +So it's pretty smart system for that. +对于这个,它是个非常聪明的系统 + +659 +00:24:32,592 --> 00:24:34,425 +I told you could ask for more time when you get +我告诉过你们,当你在后台时你可以 + +660 +00:24:34,427 --> 00:24:36,260 +backgrounded, you do that with this method +请求更多的时间,你通过这个方法 + +661 +00:24:36,262 --> 00:24:38,162 +backgroundTaskWithExpirationH- andler. +backgroundTaskWithExpirationHanler 来实现 + +662 +00:24:39,231 --> 00:24:41,431 +And so you get this background task. +因此你得到这个后台任务 + +663 +00:24:41,433 --> 00:24:44,334 +You get to stay alive then until you call end +你可以保持运行,知道你调用 + +664 +00:24:44,336 --> 00:24:45,668 +background task. +endBackgroundTask + +665 +00:24:45,670 --> 00:24:49,304 +If you don't call end background task pretty quickly +如果你在调用 backgroundTaskWithExpirationHandler + +666 +00:24:49,306 --> 00:24:52,674 +after you call backgroundTaskWithExpirationH- +后没有很快调用 endBackgroundTask + +667 +00:24:52,676 --> 00:24:56,611 +andler, it's going to say I give up on you, and kill you. +系统会表示我放弃你了,然后杀死你 + +668 +00:24:56,613 --> 00:24:58,346 +And also the next time you ask for +然后下次你请求后台任务 + +669 +00:24:58,348 --> 00:25:01,181 +a background task with expiration it's gonna say, +超时时,它将 + +670 +00:25:01,183 --> 00:25:04,084 +no I don't give that guy ones, he doesn't end his. +不会给你时间,因为你没有结束这个 + +671 +00:25:04,086 --> 00:25:08,354 +So you gotta really be sure you call end background task +所以你实际需要保证你调用 endBackgroundTask + +672 +00:25:08,356 --> 00:25:10,890 +when you do this other thing. +当你用这个做其他事情 + +673 +00:25:10,892 --> 00:25:16,194 +There's a little spinner if you look at device well, +这里有个小的 spinner,如果你看设备 + +674 +00:25:16,196 --> 00:25:21,532 +maybe we can see it in, I don't know, Safari maybe? +你可以在里面看到这个,我不知道,可能 Safari? + +675 +00:25:21,534 --> 00:25:23,034 +You see the little spinner up there? +你们看到上面的这个 spinner 了吗? + +676 +00:25:23,036 --> 00:25:25,836 +Right by the AT&T whatever, +在 AT&T 旁边 + +677 +00:25:25,838 --> 00:25:30,907 +wireless thing there was a little spinner that spun. +无线的东西,这里有一个小的 spinner 在转动 + +678 +00:25:30,909 --> 00:25:32,709 +That, you can control as well. +这个,你也可以控制 + +679 +00:25:32,711 --> 00:25:33,676 +You can turn that on and +你可以打开或者关闭 + +680 +00:25:33,678 --> 00:25:35,377 +off if your app accesses the network. +如果你的应用访问网络 + +681 +00:25:35,379 --> 00:25:37,979 +Unfortunately, it's a boolean, so if you have multiple +不幸的,它是布尔值,因此如果在 + +682 +00:25:37,981 --> 00:25:40,615 +places in your app that were accessing the network you have +你的应用中有许多地方访问网络,你需要 + +683 +00:25:40,617 --> 00:25:43,017 +to figure out how to turn it on and off appropriately. +知道怎样正确关闭和打开这个 + +684 +00:25:43,019 --> 00:25:44,085 +Yeah? + +685 +00:25:44,086 --> 00:25:45,152 +>> I don't think your phone is plugged in. +我不认为你的手机插进去了 + +686 +00:25:45,154 --> 00:25:46,086 +>> Oh, sorry. + +687 +00:25:46,088 --> 00:25:47,854 +Yeah. Let's see here. +让我们看看这里 + +688 +00:25:47,856 --> 00:25:50,457 +It's plugged in, it just disconnects every time it goes +它插进去了,只是每次它进入 + +689 +00:25:50,459 --> 00:25:53,025 +into sleep mode here. +睡眠状态它就断开连接了 + +690 +00:25:54,729 --> 00:25:57,429 +So, I don't know, let's search for something. +我不知道,让我们搜索一些东西 + +691 +00:25:57,431 --> 00:26:00,565 +Okay, watch the status bar at the top there. +看看顶部的状态栏 + +692 +00:26:00,567 --> 00:26:03,401 +You see how there's that little spinner spinning? +你们看这个小小的 spinner 如何旋转? + +693 +00:26:03,403 --> 00:26:04,168 +Okay? + +694 +00:26:04,170 --> 00:26:05,269 +You can turn that on and off. +你们可以打开和关闭这个 + +695 +00:26:06,605 --> 00:26:08,622 +'Kay? + +696 +00:26:08,623 --> 00:26:10,640 +And yeah keep reminding me if I refer to this and +如果我提到这个而它没有在上面 + +697 +00:26:10,642 --> 00:26:13,343 +it's not up there. +记得提醒我 + +698 +00:26:13,345 --> 00:26:15,644 +You can also find out about things like, +你们也可以发现一些东西,比如 + +699 +00:26:15,646 --> 00:26:18,714 +that preferred content size category notification, +preferredContentSizeCategory 通知 + +700 +00:26:18,716 --> 00:26:21,683 +well you can also just ask UI application what that is +任何时候你都可以请求 UIApplication 给你 + +701 +00:26:21,685 --> 00:26:22,751 +any time you want. +任何你想要的东西 + +702 +00:26:22,753 --> 00:26:24,385 +And you can find out what state you're in, +你可以找出你处于哪个状态 + +703 +00:26:24,387 --> 00:26:26,253 +are you in the foreground, or in the background, +你是在前台,还是在后台 + +704 +00:26:26,255 --> 00:26:27,321 +are you active, inactive? +你是活跃的,还是不活跃的? + +705 +00:26:27,323 --> 00:26:29,723 +You can find all that out as well. +你可以知道所有这些 + +706 +00:26:29,725 --> 00:26:34,594 +So U application has a lot of cool stuff in it as well. +因此 UIApplication 自己也有许多很酷的东西 + +707 +00:26:34,596 --> 00:26:39,932 +So there's another interesting thing called Info.plist. +这里有另外一个有趣的东西叫做 Info.plist + +708 +00:26:39,934 --> 00:26:41,900 +Dot plist because it's a property list. +.plist,因为它是个属性列表 + +709 +00:26:41,902 --> 00:26:44,436 +You remember a property list is any combination of +你们记得一个属性列表是字典、数组 + +710 +00:26:44,438 --> 00:26:47,905 +dictionaries and arrays and strings and dates, in datas. +字符串、日期的任何组合 + +711 +00:26:47,907 --> 00:26:51,942 +And Info.plist contains a lot of settings in your app. +Info.plist 包含很多你应用的设置 + +712 +00:26:51,944 --> 00:26:54,144 +And you can actually click on it directly. +实际上你可以直接点击它 + +713 +00:26:54,146 --> 00:26:57,714 +It's in that supporting files area and you'll see it. +它在这个 supporting files 区域,你可以看到 + +714 +00:26:57,716 --> 00:27:00,917 +What you're seeing up here is the x code's property list +你在这里看到的东西是 Xcode 的属性列表 + +715 +00:27:00,919 --> 00:27:03,953 +editor, which lets you edit an arbitrary property list as +编辑器,它让你编辑你看到的 + +716 +00:27:03,955 --> 00:27:05,087 +you can see there. +任意属性列表 + +717 +00:27:05,089 --> 00:27:06,822 +And it'll show you all the kinda setting, +你可以看到所有的设置 + +718 +00:27:06,824 --> 00:27:08,189 +some of the settings of your app. +一些你应用的设置 + +719 +00:27:08,191 --> 00:27:10,191 +You can even look at this in XML format. +你甚至可以以 XML 格式查看它 + +720 +00:27:10,193 --> 00:27:11,726 +If you right click on it and +如果你右击这个,然后 + +721 +00:27:11,728 --> 00:27:14,495 +switch to source code mode you can see it in XML. +切换到源代码模式,你可以以 XML 格式查看它 + +722 +00:27:14,497 --> 00:27:20,934 +So this is that exact same property list in XML, raw XML. +因此这个是 XML 格式的完全一样的属性列表,裸 XML + +723 +00:27:20,936 --> 00:27:23,202 +But you usually edit the Info.plist things in +但通常地你在 Info.plist 中编辑属性 + +724 +00:27:23,204 --> 00:27:25,738 +the project settings, which you get by clicking on +设置,你通过点击导航栏的左上角 + +725 +00:27:25,740 --> 00:27:28,107 +the project in the upper left of the navigator. +的 project 来做设置 + +726 +00:27:28,109 --> 00:27:29,808 +You see I've clicked on it there. +你们看已经点击了它 + +727 +00:27:29,810 --> 00:27:32,010 +And then you can see there's General Settings. +你们可以看到这里是 General 设置 + +728 +00:27:32,012 --> 00:27:35,213 +So, for example, things like what device orientations you +比如,比如你的应用支持的设备方向 + +729 +00:27:35,215 --> 00:27:38,716 +support, portrait or portrait upside-down, or landscape left +垂直或者垂直上下,或者水平左 + +730 +00:27:38,718 --> 00:27:41,518 +and right, which you can see there's a UI for there, +和右,这里是 UI + +731 +00:27:41,520 --> 00:27:44,054 +that's gonna set things in your Info.plist. +这会设置你的 Info.plist 里的东西 + +732 +00:27:44,056 --> 00:27:45,105 +'Kay? + +733 +00:27:45,106 --> 00:27:46,155 +Now I'm gonna do a demo today and +今天我要开始做一个例子 + +734 +00:27:46,158 --> 00:27:49,092 +in the demo I'm gonna add some stuff to make my application +在例子中,我将添加一些东西,让我的应用 + +735 +00:27:49,094 --> 00:27:51,193 +know about a certain document type. +知道怎么打开某种类型的文档 + +736 +00:27:51,195 --> 00:27:53,929 +I'm actually gonna do it by editing the Info.plist +实际上,我直接编辑 Info.plist 来实现 + +737 +00:27:53,931 --> 00:27:56,832 +directly, because it's a lot faster and, you know, +这个,因为这会很快,你们知道的 + +738 +00:27:56,834 --> 00:27:58,967 +we're gonna be time constrained here. +我们这里有时间限制 + +739 +00:27:58,969 --> 00:28:01,686 +But you usually wouldn't do that. +但通常你们不这么做 + +740 +00:28:01,687 --> 00:28:04,404 +Usually you would be clicking settings here in your project +通常,你们会点击你们项目的设置 UI + +741 +00:28:04,407 --> 00:28:05,957 +settings UI. +里的设置来实现 + +742 +00:28:05,958 --> 00:28:07,508 +So the Info.plist you can kinda look through and +所以 Info.plist 你们可以看看 + +743 +00:28:07,510 --> 00:28:08,442 +see what's in there. +它里面都有什么 + +744 +00:28:08,444 --> 00:28:10,710 +A lot of that stuff's kind of arcane, +有许多东西比较晦涩难懂 + +745 +00:28:10,712 --> 00:28:13,913 +you don't really even, hardly even know what it is. +你们甚至不知道它是什么 + +746 +00:28:13,915 --> 00:28:14,914 +It's just for the application. +它只是为了应用 + +747 +00:28:14,916 --> 00:28:17,416 +But there are some things in there that +但有些东西是 + +748 +00:28:17,418 --> 00:28:19,084 +are pretty important, pretty obvious, +非常重要,非常明显的 + +749 +00:28:19,086 --> 00:28:24,122 +like what document types do I recognize, things like that. +比如我认识的 document types,类似这类的 + +750 +00:28:24,124 --> 00:28:26,491 +Okay, capabilities. +capabilities + +751 +00:28:26,492 --> 00:28:28,859 +So, some features in your app, quite a few actually, +你的应用的一些特征,实际上有很多 + +752 +00:28:28,861 --> 00:28:30,260 +require enabling. +要求 enabling + +753 +00:28:30,262 --> 00:28:31,845 +In other words, +换句话说 + +754 +00:28:31,846 --> 00:28:33,429 +you can't use them in your app until you enable them. +你在应用中不能使用它们直到你 enable 它们 + +755 +00:28:33,432 --> 00:28:37,100 +Now, most of these are server features like iCloud or +它们大部分是服务特征比如 iCloud 或者 + +756 +00:28:37,102 --> 00:28:40,269 +Game Center, or they're interoperability features, +Game Center,或他们是互用性特征 + +757 +00:28:40,271 --> 00:28:42,037 +where you're gonna be inter-operating with other +你将和系统的其他部分做内部交互 + +758 +00:28:42,039 --> 00:28:44,740 +parts of the system like the Passbook or things like that. +比如 Passbook 或者类似的东西 + +759 +00:28:44,742 --> 00:28:46,425 +Okay? + +760 +00:28:46,426 --> 00:28:48,109 +So you turn these on in Project Settings under +所以你在 Project Settings 中的 Capabilities + +761 +00:28:48,111 --> 00:28:48,910 +Capabilities. +下把这些功能打开 + +762 +00:28:48,912 --> 00:28:50,478 +You get this list right here. +你有这个列表 + +763 +00:28:50,480 --> 00:28:54,815 +This is the current list as of the time I took the screen +这个是我几天前屏幕截图的 + +764 +00:28:54,817 --> 00:28:56,449 +shot a few days ago. +列表 + +765 +00:28:56,451 --> 00:28:59,485 +And you just switch those little switches, +你们可以改变这些 switches + +766 +00:28:59,487 --> 00:29:03,022 +the on off switches, on or off to enable this. +开关 switches,开或关来 enable 这个 + +767 +00:29:03,024 --> 00:29:05,958 +Kind of a little bit of a warning about here is that +这里有一个小小的警告, + +768 +00:29:05,960 --> 00:29:09,194 +some of these things, the server based technologies +这些东西中的一些,基于服务的技术 + +769 +00:29:09,196 --> 00:29:11,496 +require a normal developer program. +要求一个正常的开发者程序 + +770 +00:29:11,498 --> 00:29:14,699 +The free University program that some of you are on, +你们中有些是免费的通用项目 + +771 +00:29:14,701 --> 00:29:16,701 +doesn't really support that. +实际上并不支持这个 + +772 +00:29:16,703 --> 00:29:19,169 +So if you wanted to do some of these things for +所以如果你们想在你们的期末项目中 + +773 +00:29:19,171 --> 00:29:20,370 +your final project, +做这些设置 + +774 +00:29:20,372 --> 00:29:23,373 +you might have to join the actual developer program. +你们可能需要加入实际的开发者项目 + +775 +00:29:23,375 --> 00:29:25,575 +'Kay, so this is an FYI there. +这是 FYI + +776 +00:29:27,245 --> 00:29:29,278 +If you click on the little triangle to the left of any of +如果你们点击这些东西的左边的 + +777 +00:29:29,280 --> 00:29:30,846 +these things, it'll actually give you +三角形,实际上它会给你一个 + +778 +00:29:30,848 --> 00:29:33,581 +a little description of what the heck this thing is. +小小的描述,告诉你这个东西到底是什么玩意 + +779 +00:29:33,583 --> 00:29:35,583 +'Kay? + +780 +00:29:35,584 --> 00:29:37,584 +So you can click on maybe In-App purchases and +你可以点击,也许是应用内购买 + +781 +00:29:37,587 --> 00:29:41,855 +it'll tell you, oh, this is what enables you to, the user +它会告诉你,这个能够让你做什么,用户 + +782 +00:29:41,857 --> 00:29:45,559 +to buy things to extend your app internally, etc. +在你应用内可以买东西 + +783 +00:29:45,561 --> 00:29:48,161 +So I encourage you to look through all these things and +我建议你们浏览所有这些东西 + +784 +00:29:48,163 --> 00:29:49,362 +see what's available. +看他们都能做什么 + +785 +00:29:49,364 --> 00:29:51,197 +It kinda gives you a feeling for +这有点像给你一种感觉 + +786 +00:29:51,199 --> 00:29:54,566 +how much stuff there is in iOS and how little we can really +在 iOS 中有许多东西,但在这门课程的 + +787 +00:29:54,568 --> 00:29:58,070 +cover in just basically nine weeks of this course. +九周里我们只能涉及很少一部分 + +788 +00:29:58,072 --> 00:30:01,706 +But, it's still kind of fun to look at what's in here. +但依然有趣,来看看这里有什么 + +789 +00:30:01,708 --> 00:30:03,007 +Okay? + +790 +00:30:03,009 --> 00:30:05,809 +And these capabilities, sorry, question back there. +这些 capabilities,抱歉,有问题? + +791 +00:30:05,811 --> 00:30:08,779 +>> So for the app [INAUDIBLE] map to run your app, +对于你应用中的应用地图 + +792 +00:30:08,781 --> 00:30:11,181 +would that be supported in this, or +它能否支持这个,或 + +793 +00:30:11,183 --> 00:30:15,017 +do you have to do a different thing to create another map? +你需要创建另一个应用来做不一样的事情? + +794 +00:30:15,019 --> 00:30:17,119 +>> So you're talking about maps? +你在问地图? + +795 +00:30:17,121 --> 00:30:20,989 +So the question is, if I want to use a third party map +问题是,如果我使用第三方的地图 + +796 +00:30:20,991 --> 00:30:25,293 +API or something, do I need to enable this or something? +API 或者其他的,我是否需要打开这个或者其他? + +797 +00:30:25,295 --> 00:30:26,761 +No. This is just enabling what +不,这只是使你的应用 + +798 +00:30:26,763 --> 00:30:29,129 +your app can do, what it's capabilities are. +能够做一些事情,它的 capabilities 是什么 + +799 +00:30:29,131 --> 00:30:32,466 +So for example if you're a map providing app, you would go +比如,如果你是个提供地图的应用,你就要在 + +800 +00:30:32,468 --> 00:30:35,769 +here and enable your, you know, turn it on and all that. +这里打开功能,还有所有这些 + +801 +00:30:35,771 --> 00:30:38,271 +You see what I'm saying? +你明白我所说的吗? + +802 +00:30:38,272 --> 00:30:40,772 +The end-user, they benefit from whatever capabilities +最终用户,他们从这些应用创建时注册的 + +803 +00:30:40,775 --> 00:30:43,275 +these apps have signed up for when they were built. +任何 capabilities 中受益 + +804 +00:30:43,277 --> 00:30:45,044 +Right? So this is a build setting +这是个 build 设置 + +805 +00:30:45,046 --> 00:30:47,213 +essentially. +很重要 + +806 +00:30:47,214 --> 00:30:49,381 +And it has a little bit to do with the coordination of your +这和你的 bundle identifier 的协调性有点相关 + +807 +00:30:49,383 --> 00:30:53,017 +bundle identifier with what's going on at Apple servers and +在苹果服务器做了什么还有 + +808 +00:30:53,019 --> 00:30:54,385 +all that stuff. +所有这些东西 + +809 +00:30:54,387 --> 00:30:57,221 +So it's more than just turning it on, there's sometimes, +这不仅仅是打开它,有时候 + +810 +00:30:57,223 --> 00:31:00,623 +there's some payload that has to be kind of arranged. +有些负荷需要被管理 + +811 +00:31:02,193 --> 00:31:04,677 +All right? + +812 +00:31:04,678 --> 00:31:07,162 +So the demo I'm gonna do here is kinda setting us up for +所以这里我要做的例子,是为了周三 + +813 +00:31:07,164 --> 00:31:09,214 +Wednesday. +创建的 + +814 +00:31:09,215 --> 00:31:11,265 +I'm gonna show you how to do AirDrop to drop something into +我将给你演示如何使用 AirDrop 从 Mac + +815 +00:31:11,268 --> 00:31:13,401 +your app, 'kay, from the Mac. +拖一些东西到你们的应用, + +816 +00:31:13,403 --> 00:31:15,186 +Which is really kinda cool, +这非常酷 + +817 +00:31:15,187 --> 00:31:16,970 +because you got this iPhone and let's say you wanna import +因为你们有这个 iPhone,让我们假设你想要导入 + +818 +00:31:16,973 --> 00:31:19,073 +something, you know, an image or, +一些东西,你们知道的,一张图片或 + +819 +00:31:19,075 --> 00:31:23,143 +you know, any kind of file, a pdf file even, whatever. +你们知道的,任何文件,pdf 文件,甚至任何其它的 + +820 +00:31:23,145 --> 00:31:25,379 +You'd like to be able to just basically drag it, drag and +你们想要能够拖拽它,拖拽然后 + +821 +00:31:25,381 --> 00:31:27,514 +drop it from your desktop. +从你的桌面上拖放 + +822 +00:31:27,516 --> 00:31:30,750 +So the example I'm gonna do here is on Wednesday, +这里这个例子,我将在周三做 + +823 +00:31:30,752 --> 00:31:34,053 +I'm gonna build an app that if you go on vacation, and, +我要创建一个应用,如果你们在度假 + +824 +00:31:34,055 --> 00:31:36,455 +let's say, you take a bunch of photos that are, +你们拍了很多照片 + +825 +00:31:36,457 --> 00:31:40,525 +have GPS tags on them, and maybe you even go hiking, +这些照片有 GPS 标签,甚至也许你们去滑雪 + +826 +00:31:40,527 --> 00:31:43,061 +and you have a little GPS monitor, +你们有一个小的 GPS 显示器 + +827 +00:31:43,063 --> 00:31:45,730 +or let the iPhone keep track of where you go, and +让 iPhone 追踪你的足迹 + +828 +00:31:45,732 --> 00:31:49,499 +you wanna draw the track of where you hiked, or whatever. +你想要画出你滑雪的轨迹,或其它任何东西 + +829 +00:31:49,501 --> 00:31:50,801 +Okay? + +830 +00:31:50,802 --> 00:31:52,102 +So we're gonna build an app on Wednesday that does both of +我们将在周三创建一个应用,能够做 + +831 +00:31:52,104 --> 00:31:54,321 +those things. +这两种事情 + +832 +00:31:54,322 --> 00:31:56,539 +Let's you take some information about photos and +你们获取了照片的一些信息 + +833 +00:31:56,541 --> 00:32:00,209 +their location or a track and draw them on a map. +它们的地点或轨迹,然后在地图上画出 + +834 +00:32:00,211 --> 00:32:01,143 +Okay? + +835 +00:32:01,145 --> 00:32:02,444 +Now to do that app, +现在开始做这个应用 + +836 +00:32:02,446 --> 00:32:05,546 +we need to import that vacation information. +我们需要导入度假信息 + +837 +00:32:05,548 --> 00:32:06,814 +Okay? I went on vacation, +我在度假中 + +838 +00:32:06,816 --> 00:32:08,299 +I need the info. +我需要这个信息 + +839 +00:32:08,300 --> 00:32:09,783 +And we're gonna do that with AirDrop and +我们通过 AirDrop 来实现 + +840 +00:32:09,785 --> 00:32:12,352 +we're gonna to do it, air dropping GPX files. +我们要做这个,空中拖拽 GPX 文件 + +841 +00:32:12,354 --> 00:32:16,289 +A GPX file is a file that just has a list of GPS coordinate +一个 GPX 文件是这样的文件,它有 GPS 坐标相关信息的列表 + +842 +00:32:16,291 --> 00:32:20,192 +related information, like waypoints that you were at +比如你停下拍照的地点 + +843 +00:32:20,194 --> 00:32:22,394 +where you maybe took a photo and + +844 +00:32:22,396 --> 00:32:25,330 +the track if you took a hike or whatever. +或你滑雪的轨迹,或任何其它的 + +845 +00:32:25,332 --> 00:32:27,599 +So that's called a GPX file, +这叫做 GPX 文件 + +846 +00:32:27,601 --> 00:32:30,702 +it's just kind of a public file format. +这只是一个公共文件格式 + +847 +00:32:30,704 --> 00:32:35,472 +It's XML, but it's XML with a certain extension, GPX. +它是 XML,但是带了点扩展的 XML,GPX + +848 +00:32:35,474 --> 00:32:38,875 +And I'm gonna show you how you can make it, so you can just +我将演示你们可以做到的,你们可以 + +849 +00:32:38,877 --> 00:32:41,878 +drag a GPX file into your iPhone app from your Mac. +从 Mac 电脑从拖一个 GPX 文件到你们的 iPhone 应用中 + +850 +00:32:41,880 --> 00:32:43,913 +Okay? + +851 +00:32:43,914 --> 00:32:45,947 +So let's first talk about how that's gonna work here. +首先,让我说说这是如何工作的 + +852 +00:32:45,950 --> 00:32:49,785 +So on the Mac, you just go here to AirDrop. +在 Mac 上,你只需要到这里 AirDrop + +853 +00:32:49,787 --> 00:32:53,422 +You've probably, how many people have used AirDrop for +你们可能,许多人已经使用过 AirDrop? + +854 +00:32:53,424 --> 00:32:54,189 +anything? + +855 +00:32:54,191 --> 00:32:54,989 +About only by half, okay. +只用了一半 + +856 +00:32:54,991 --> 00:32:55,957 +Interesting. +很有趣 + +857 +00:32:55,958 --> 00:32:56,924 +So AirDrop's really cool. +AirDrop 相当酷 + +858 +00:32:56,926 --> 00:32:59,526 +So we got a lot of people here with various devices. +这里我们有许多人有不同的设备 + +859 +00:32:59,528 --> 00:33:02,896 +And here, I'm gonna turn this guy on and you're +这里,我要把这个家伙打开,你们 + +860 +00:33:02,898 --> 00:33:07,233 +gonna see that he shows up right here, CS192p iPhone6+. +将看到它在这里出现,CS192p iPhone6+ + +861 +00:33:07,235 --> 00:33:09,652 +Can you see that? +你们可以看到吗? + +862 +00:33:09,653 --> 00:33:12,070 +And so if I have a file, like my Vacation.gpx right here, +如果我有一个文件,比如我的 Vacation.gpx + +863 +00:33:12,073 --> 00:33:13,772 +you see this is a GPX file. +你们可以看到这是个 GPX 文件 + +864 +00:33:13,774 --> 00:33:17,776 +I can actually just drag and drop it onto here. +实际上我可以拖拽,然后拖到这上面去 + +865 +00:33:17,778 --> 00:33:20,445 +Okay. To transfer it to my Mac or +把它从我们的 Mac 传输到 + +866 +00:33:20,447 --> 00:33:21,746 +to my iPhone. +我的 iPhone上 + +867 +00:33:21,748 --> 00:33:25,649 +But when I do that, sorry. +但当我做这个时,抱歉 + +868 +00:33:25,651 --> 00:33:27,450 +Cancel. +取消 + +869 +00:33:27,452 --> 00:33:30,420 +Its too bad this drops all the time, +一直这样拖放很糟糕 + +870 +00:33:30,422 --> 00:33:32,688 +its a little bit annoying. +有点恼人 + +871 +00:33:32,690 --> 00:33:36,058 +So, I'm gonna drag it again. +我再次拖放 + +872 +00:33:36,060 --> 00:33:37,459 +Okay. + +873 +00:33:37,461 --> 00:33:38,526 +Drag it on here. +从这里拖放 + +874 +00:33:38,528 --> 00:33:41,128 +So what happens right now is it says, oh, +现在发生了什么,它说 + +875 +00:33:41,130 --> 00:33:44,832 +AirDrop someone wants to drag this GPX file to your Mac, but +AirDrop 有人想要拖这个 GPX 文件到你的 Mac 上,但 + +876 +00:33:44,834 --> 00:33:47,134 +you have no app that can handle this. +你没有一个应用可以处理这个 + +877 +00:33:47,136 --> 00:33:48,335 +So it's saying, +所以它表示 + +878 +00:33:48,337 --> 00:33:51,437 +do you want to go to the App Store to get an app? +你想要到应用商店下载一个应用? + +879 +00:33:51,439 --> 00:33:53,339 +Which I don't want to go to the App Store, +但我不想到应用商店 + +880 +00:33:53,341 --> 00:33:55,607 +I want to write my own app that handles GPX files. +我想要编写我自己的应用来处理这 GPX 文件 + +881 +00:33:55,609 --> 00:33:56,942 +So that's what we're gonna do. +这就是我们将要做的 + +882 +00:33:56,944 --> 00:34:01,813 +We're gonna write our own app here to handle GPX files. +这里我们要写我们自己的应用来处理这个 GPX 文件 + +883 +00:34:01,815 --> 00:34:05,116 +All right. So let's go to Xcode. +好吧,我们打开 Xcode + +884 +00:34:05,118 --> 00:34:08,018 +So we're gonna create a new project here. +这里我们要创建一个新的项目 + +885 +00:34:08,020 --> 00:34:09,953 +Now this project is going to show you how to do +这个项目要向你们演示如何处理 + +886 +00:34:09,955 --> 00:34:11,655 +the AirDrop. +AirDrop + +887 +00:34:11,656 --> 00:34:13,356 +I'm also gonna show you how to do notifications. +我会向你们演示如何处理通知 + +888 +00:34:13,358 --> 00:34:14,857 +Okay? Cuz that's an important thing +明白如何做也是很重要 + +889 +00:34:14,859 --> 00:34:16,225 +to understand how to do as well. +的事情 + +890 +00:34:16,227 --> 00:34:20,429 +So, I'm gonna call this app Tracks, because it keeps track +我称这个我为 Tracks 应用,因为你保持纪录 + +891 +00:34:20,431 --> 00:34:22,797 +of where you go on your vacations or +你度假中的路径或 + +892 +00:34:22,799 --> 00:34:24,532 +whatever with GPX file. +任何 GPX 文件 + +893 +00:34:24,534 --> 00:34:27,301 +So we call we're gonna put it in the place we always put +我们要把它放在我们经常放 + +894 +00:34:27,303 --> 00:34:27,968 +everything. +的地方 + +895 +00:34:27,970 --> 00:34:28,969 +Okay. + +896 +00:34:28,971 --> 00:34:31,304 +Here it is, right here. +这就是了,这里 + +897 +00:34:31,306 --> 00:34:34,207 +I am not going to move the AppDelegate out of the way +这次我不移动 AppDelegate + +898 +00:34:34,209 --> 00:34:35,308 +this time. + +899 +00:34:35,309 --> 00:34:36,408 +Okay? So the first time, yehey. +第一次, + +900 +00:34:36,411 --> 00:34:37,943 +We get to actually do something with +我们实际在我们的 AppDelegate + +901 +00:34:37,945 --> 00:34:38,944 +our AppDelegate, but +做些事情,但 + +902 +00:34:38,946 --> 00:34:40,845 +I'm gonna move those things out of the way. +我要把这些东西移出 + +903 +00:34:40,847 --> 00:34:43,981 +But we're gonna sneak in there and look at info.plist, so +但我们溜到这里,看看 info.plist + +904 +00:34:43,983 --> 00:34:45,750 +kind of get both of those things. +有这两者 + +905 +00:34:45,752 --> 00:34:47,335 +All right. + +906 +00:34:47,336 --> 00:34:48,919 +So here's our ViewController. +这是我们的 ViewController + +907 +00:34:48,921 --> 00:34:51,622 +How do we want to do this? +我们要怎么处理这个? + +908 +00:34:51,623 --> 00:34:54,324 +Well, the most important thing we need to do to make our app +要让我们的应用可以处理 GPX 文件最重要的事情是 + +909 +00:34:54,326 --> 00:34:58,928 +be air droppable for GPX is to register with our app that we +我们需要注册我们的应用 + +910 +00:34:58,930 --> 00:35:00,863 +know what a GPX file is. +我们知道 GPX 文件是什么 + +911 +00:35:00,865 --> 00:35:02,898 +Okay? + +912 +00:35:02,899 --> 00:35:04,932 +And we can do this in our project settings over here +我们可以在 Info 中做这个 + +913 +00:35:04,935 --> 00:35:06,685 +in Info. +设置 + +914 +00:35:06,686 --> 00:35:08,436 +You see down here at the bottom of Projects and +你们看项目的底部 + +915 +00:35:08,439 --> 00:35:10,038 +Info is Document Types. +Info 是一个文档类型 + +916 +00:35:10,040 --> 00:35:12,440 +So these are all the types of documents I know about. +这些是我知道的所有文档类型 + +917 +00:35:12,442 --> 00:35:14,642 +And then also Imported UTIs. +你们也有导入的 UTIs + +918 +00:35:14,644 --> 00:35:19,046 +These are all the basically URL like descriptions of +它们基本上是类似文件描述的 + +919 +00:35:19,048 --> 00:35:20,147 +a file. +URL + +920 +00:35:20,148 --> 00:35:21,247 +So I kind of need to do both of those things. +我要处理这两个 + +921 +00:35:21,249 --> 00:35:24,550 +I need to describe what a GPX file is. +我需要描述 GPX 文件是什么 + +922 +00:35:24,552 --> 00:35:27,119 +And then I just say, yes, that's a type I support. +我设置,这是我支持的文件类型 + +923 +00:35:27,121 --> 00:35:30,122 +Now, I can do all this by clicking the plus sign +我点击这里的加号 + +924 +00:35:30,124 --> 00:35:31,123 +here and here. +来做这个设置 + +925 +00:35:31,125 --> 00:35:32,924 +But I want to show you another demo. +我想演示另一个例子 + +926 +00:35:32,926 --> 00:35:35,259 +So, I'm gonna do this is kind of fast mode, +这个我要快一点演示 + +927 +00:35:35,261 --> 00:35:38,329 +which I'm just gonna go to the Info.plist, because this +我打开 Info.plist,因为这个 + +928 +00:35:38,331 --> 00:35:41,131 +information's going to be put in the Info.plist. +信息要放在 Info.plist + +929 +00:35:41,133 --> 00:35:44,368 +And I'm gonna edit it in source mode. +我要以源码形式编辑它 + +930 +00:35:44,370 --> 00:35:45,735 +So I'm just going here and saying, +我在这里, + +931 +00:35:45,737 --> 00:35:47,554 +edit it as Source Code. +以源码形式编辑 + +932 +00:35:47,555 --> 00:35:49,372 +Now you can see it's an XML file here. +你们可以看到这是个 XML 文件 + +933 +00:35:49,374 --> 00:35:53,475 +And I actually prepped all of the stuff necessary here, +实际上,我布置了作业,所有这里需要的东西 + +934 +00:35:53,477 --> 00:35:57,179 +which you can look through later at your leisure. +你们有空的时候可以浏览下 + +935 +00:35:57,181 --> 00:35:59,948 +Wait, for GPX files, but you can see +等等,对于 GPX 文件,但你们可以看到 + +936 +00:35:59,950 --> 00:36:04,385 +it's basically that I say that it's got file name extent, +它基本上,扩展了文件名 + +937 +00:36:04,387 --> 00:36:07,954 +file extensions GPX, but that it is a XML file. +GPX 文件扩展,但它是一个 XML 文件 + +938 +00:36:07,956 --> 00:36:09,823 +All right. + +939 +00:36:09,824 --> 00:36:11,691 +And then up here, I'm saying, the documents I support. +这上面,我支持的文档 + +940 +00:36:11,693 --> 00:36:16,295 +I support this, which is my own private GPX type and +我支持这个,这是我自己的私人 GPX 类型 + +941 +00:36:16,297 --> 00:36:20,199 +then that's linked to the type down here. +它关联到下面这个类型 + +942 +00:36:20,201 --> 00:36:24,969 +So, I'm just gonna copy this and go over here. +我要拷贝这个,然后到上面这里 + +943 +00:36:24,971 --> 00:36:26,504 +And actually, +实际上 + +944 +00:36:26,506 --> 00:36:31,575 +just paste it right at the bottom of this down here. +在这下面底部粘贴 + +945 +00:36:31,577 --> 00:36:32,642 +Paste. +粘贴 + +946 +00:36:32,644 --> 00:36:34,211 +Okay. + +947 +00:36:34,212 --> 00:36:35,779 +So, I basically put that stuff in there. +我基本上把这个东西放到这里了 + +948 +00:36:35,781 --> 00:36:38,648 +I can even go back to Property List mode and +我甚至可以回到属性列表模式 + +949 +00:36:38,650 --> 00:36:41,851 +you can see that it added it here at the bottom. +你们可以看到,它在底部添加了这个 + +950 +00:36:41,853 --> 00:36:42,484 +Okay. + +951 +00:36:42,486 --> 00:36:45,487 +So here's my types. +这是我的类型 + +952 +00:36:45,489 --> 00:36:47,222 +And if I go back to my Project Settings, +如果我回到我的项目设置 + +953 +00:36:47,224 --> 00:36:48,423 +I can see them here as well. +我也可以在这里看到 + +954 +00:36:48,425 --> 00:36:51,125 +I can see now I have one document type, +我可以看到现在我有一个文档类型 + +955 +00:36:51,127 --> 00:36:53,794 +it's a GPX file and I can import GPX. +它是一个 GPX 文件,我可以导入 GPX + +956 +00:36:53,796 --> 00:36:56,930 +So that's the key thing you need to do to make AirDrop +这是你让 AirDrop 工作需要做的关键的事情 + +957 +00:36:56,932 --> 00:36:59,733 +work, it's just define the document type you +它定义了你愿意被拖放的 + +958 +00:36:59,735 --> 00:37:01,901 +are willing to have dropped on you. +文档类型 + +959 +00:37:01,903 --> 00:37:03,836 +Okay? + +960 +00:37:03,837 --> 00:37:05,770 +Now, once you've defined that, now the system, +一旦你定义了,现在系统 + +961 +00:37:05,773 --> 00:37:08,374 +any time someone wants to open a GPX file, +任何时候有人想打开 GPX 文件 + +962 +00:37:08,376 --> 00:37:11,243 +they're gonna ask me if I can do it in my app and +它们会询问我是否能在我的应用中处理这个 + +963 +00:37:11,245 --> 00:37:13,678 +they do that here in the AppDelegate. +他们在 AppDlegate 中做这个事情 + +964 +00:37:13,680 --> 00:37:16,014 +Now you can see the AppDelegate kind of gives you +现在你们可以看到 AppDelegate 给你 + +965 +00:37:16,016 --> 00:37:18,315 +stubs for didFinishLaunchingWithOptions, +didFinishLaunchingWithOptions 的东西 + +966 +00:37:18,317 --> 00:37:21,552 +ResignActive, EnterBackground, Foreground, even gives you +ResignActive,EnterBackground,Foreground,甚至给你 + +967 +00:37:21,554 --> 00:37:24,554 +a little explanation of when you're supposed to use those. +一个什么时候你应该使用这些的小解释 + +968 +00:37:24,556 --> 00:37:26,289 +We're not going to use any of those, so +我们不使用这里的任何东西 + +969 +00:37:26,291 --> 00:37:27,390 +I'm gonna delete that. +我要删除这些 + +970 +00:37:27,392 --> 00:37:29,542 +Okay? + +971 +00:37:29,543 --> 00:37:31,693 +So you can go look at that in any app that you build, +你可以在任何你创建的应用中看看这个 + +972 +00:37:31,696 --> 00:37:36,098 +it's always going to put that, oops, those in there, so +它总是把这些放在这里 + +973 +00:37:36,100 --> 00:37:38,433 +that you can find out about it. +你们可以找出它们 + +974 +00:37:38,435 --> 00:37:40,468 +Don't ever delete this thing, though. +永远不要删除这个 + +975 +00:37:40,470 --> 00:37:42,303 +[LAUGH] Var window. +Var window + +976 +00:37:42,305 --> 00:37:46,406 +The AppDelegate has a pointer to the window where all your +这个 AppDelegate 有个指针指向你的所有 + +977 +00:37:46,408 --> 00:37:47,407 +UI is. +UI 所在的 window + +978 +00:37:47,408 --> 00:37:48,407 +And it needs to have that. +它需要有这个 + +979 +00:37:48,410 --> 00:37:50,910 +It gets set when the storyboard gets loaded. +当 storyboard 加载时,这个 window 被设置 + +980 +00:37:50,912 --> 00:37:54,347 +It is possible to reach into your UI here through this +通过这个访问你的 UI 是可能的 + +981 +00:37:54,349 --> 00:37:57,683 +thing and start talking to your ViewControllers. +然后开始和你的 ViewControllers 通讯 + +982 +00:37:57,685 --> 00:37:59,685 +I recommend against that. +我不建议这么做 + +983 +00:37:59,687 --> 00:38:01,036 +Okay? + +984 +00:38:01,037 --> 00:38:02,386 +You do not want to be reaching down into there, +你不会想在这里做这些 + +985 +00:38:02,389 --> 00:38:04,422 +because if you ever went into your storyboard and +因为如果你曾在你的 storyboard + +986 +00:38:04,424 --> 00:38:06,390 +changed whether something was in a split view or +改变任何在 split view 或 + +987 +00:38:06,392 --> 00:38:08,959 +in navigation controller, now this code's going to break, +navigation controller 的任何东西,现在这些代码就被破坏了 + +988 +00:38:08,961 --> 00:38:10,293 +it's not going to work. +它不会工作 + +989 +00:38:10,295 --> 00:38:13,963 +And it also is not very object orientated in that MVCs should +这一点都不面向对象, MVC 应该 + +990 +00:38:13,965 --> 00:38:15,264 +be their own thing and +做它们自己的事情 + +991 +00:38:15,266 --> 00:38:17,599 +they should kind of work on their own. +它们应该只做它们自己的事情 + +992 +00:38:17,601 --> 00:38:20,836 +They shouldn't need some outside intervention to be +它们不应该有外部打断 + +993 +00:38:20,838 --> 00:38:24,105 +coming in and talking to them to make them work, okay? +进来然后告诉它们让它们工作 + +994 +00:38:24,107 --> 00:38:26,507 +You want to think of MVCs as these objects, +这些对象你们要想想 MVC + +995 +00:38:26,509 --> 00:38:28,509 +essentially kind of meta objects, +元对象非常重要 + +996 +00:38:28,511 --> 00:38:31,445 +even though they're made up swift objects inside. +即使他们在内部创建 swift 对象 + +997 +00:38:31,447 --> 00:38:34,648 +But they have an API and they work on their own. +但它们有一个 API,它们自己可以工作 + +998 +00:38:34,650 --> 00:38:35,448 +They're independent. +它们是独立的 + +999 +00:38:35,450 --> 00:38:36,949 +They do what they do, +它们做自己可以做的 + +1000 +00:38:36,951 --> 00:38:40,953 +just like any other well designed object oriented API. +就像任何其他设计良好的面向对象 API + +1001 +00:38:40,955 --> 00:38:43,021 +All right. So the method that we want to +我们在 AppDelegate 中要实现的方法 + +1002 +00:38:43,023 --> 00:38:46,458 +implement in our AppDelegate to open a URL is called +是打开一个 URL,叫做 application: handleOpenURL + +1003 +00:38:46,460 --> 00:38:50,061 +application handle OpenURL, you see it right here. +这里你们可以看到 + +1004 +00:38:50,063 --> 00:38:51,629 +There's a lot of other things you can see. +你们可以看到很多东西 + +1005 +00:38:51,631 --> 00:38:53,330 +There's, look at all these things. +这里,看这所有东西 + +1006 +00:38:53,332 --> 00:38:56,633 +Many, many things we can do here. +我们可以在这里做很多事情 + +1007 +00:38:56,635 --> 00:38:59,135 +But we want handle open URL. +但我们想要 handleOpenURL + +1008 +00:38:59,137 --> 00:39:01,571 +And all we need to do and handle OpenURL, +所有我需要做的事 handleOpenURL + +1009 +00:39:01,573 --> 00:39:03,639 +we got this URL is go deal with it. +我们获得这个需要处理的 URL + +1010 +00:39:03,641 --> 00:39:06,508 +So right now, I'm just going to print it out. +现在,我只是把它输出 + +1011 +00:39:06,510 --> 00:39:11,513 +So I'm gonna say, url equals url. +我要说, url 等于 url + +1012 +00:39:11,515 --> 00:39:12,931 +Okay? Just so + +1013 +00:39:12,932 --> 00:39:14,348 +we can see that our AirDrop is working. +我们可以看到我们的 AirDrop 工作了 + +1014 +00:39:14,351 --> 00:39:17,618 +And then you return true or false, whether you handled it. +然后你返回 true 或 false,你是否处理了它 + +1015 +00:39:17,620 --> 00:39:19,219 +So since all I'm going to do is print it out, +既然我要输出这个 + +1016 +00:39:19,221 --> 00:39:20,120 +I'm gonna say, true. +我要返回 true + +1017 +00:39:20,122 --> 00:39:21,721 +Yes, I handled it. +是的,我处理了它 + +1018 +00:39:21,723 --> 00:39:22,889 +Okay? + +1019 +00:39:22,891 --> 00:39:24,323 +So that's all I'm gonna do first here. +这是所有我首先要处理的 + +1020 +00:39:24,325 --> 00:39:27,092 +We're gonna run just that and then I'm gonna do another +我要运行这个,一会我需要处理一些 + +1021 +00:39:27,094 --> 00:39:29,261 +thing with notifications in a second here. +通知 + +1022 +00:39:29,263 --> 00:39:31,429 +So here's called tracks. +这个叫做 tracks + +1023 +00:39:31,431 --> 00:39:36,500 +I'm running it on the device here, as you can see. +我在设备上运行这个,你们可以看到 + +1024 +00:39:36,502 --> 00:39:39,903 +Now the first time my app is installed where it is saying, +第一次我的应用安装了,它说 + +1025 +00:39:39,905 --> 00:39:43,073 +it can handle these new types, the system's going to +它可以处理这些新的类型,系统将会 + +1026 +00:39:43,075 --> 00:39:45,508 +recognize, oh, this guy handles GPX. +识别,这个家伙可以处理 GPX + +1027 +00:39:45,510 --> 00:39:46,676 +Okay? So here's my app, +这就是我的应用 + +1028 +00:39:46,678 --> 00:39:49,045 +it didn't do anything, but it did register itself. +它没有做任何事情,但它注册了它自己 + +1029 +00:39:49,047 --> 00:39:53,815 +So now, I'm gonna go over here to my AirDrop again and +现在,我在这里,我的 AirDrop + +1030 +00:39:53,817 --> 00:39:56,885 +going to, hope this guy shows up. +希望这个家伙会出现 + +1031 +00:39:56,887 --> 00:39:58,886 +So let's go back to our app here. +让我们回到我们的应用 + +1032 +00:39:58,888 --> 00:40:02,356 +We're gonna run our app. +我们要运行我们的应用 + +1033 +00:40:02,358 --> 00:40:04,091 +It's registered itself. +它注册了它自己 + +1034 +00:40:04,093 --> 00:40:06,526 +It says, oh yes, I handle GPX files. +他说,我可以处理 GPX 文件 + +1035 +00:40:06,528 --> 00:40:10,230 +So now, if I take a GPX file here, like this, and +现在,我放了一个 GPX 文件,比如这个 + +1036 +00:40:10,232 --> 00:40:14,467 +drag it on, okay, does the same thing, it transferred +然后拖放它,做同样的事情,它传输了 + +1037 +00:40:14,469 --> 00:40:17,936 +over, but notice the difference this time. +但注意这次的不同 + +1038 +00:40:17,938 --> 00:40:21,573 +Okay, this time it doesn't say get app, it says, do you +这次它没有说要下载一个应用,它说,你要在 + +1039 +00:40:21,575 --> 00:40:25,543 +accept it in tracks, because I'm running tracks right now. +tracks 中接受它?因为我现在正运行着 tracks + +1040 +00:40:25,545 --> 00:40:27,278 +So I'll say, yeah, I accept it. +我说,是的,我接受它 + +1041 +00:40:27,280 --> 00:40:30,948 +And when I do, we're going to watch our console here +当我这么做时,我们要观察我们的 console + +1042 +00:40:30,950 --> 00:40:33,617 +and its going to say at the bottom, its going to print out +它在底部,在文件被传输之后 + +1043 +00:40:33,619 --> 00:40:36,553 +the URL of the file after its been transferred. +它输出了这个文件的URL + +1044 +00:40:36,555 --> 00:40:40,690 +So I hit accept and sure enough, right here, you see, +因此我点击接受,非常确定的,这里,你们看到 + +1045 +00:40:40,692 --> 00:40:42,758 +it's created this URL. +它输出了这个 URL + +1046 +00:40:42,760 --> 00:40:46,695 +So it's put it in this place in my sandbox called documents +它把这个文件放在我的沙盒中,叫做 + +1047 +00:40:46,697 --> 00:40:49,798 +inbox vacation.gpx which we're going to talk about, +Documents/inbox/vacation.gpx,这个我们将要谈谈 + +1048 +00:40:49,800 --> 00:40:53,401 +the file system, a little later in this demo. +系统文件,一会在这个例子中 + +1049 +00:40:53,403 --> 00:40:55,936 +So, this file, GPX, was transferred over, +这个文件,GPX,被传输了 + +1050 +00:40:55,938 --> 00:41:01,475 +put on the local hard disk, flash drive of our phone, +放在本地的硬盘上,我们手机的闪存上 + +1051 +00:41:01,477 --> 00:41:03,243 +and made available to this app. +在这个应用中可用了 + +1052 +00:41:03,245 --> 00:41:05,945 +So now, I can open this URL up and do whatever I want. +现在,我可以打开这个 URL,做任何我想做的 + +1053 +00:41:05,947 --> 00:41:09,982 +So that's it, super simple to do AirDrop, it's just a matter +这就是了,AirDrop 超级简单,它只是 + +1054 +00:41:09,984 --> 00:41:12,084 +of registering those document types. +要注册这些文档类型的事情 + +1055 +00:41:12,086 --> 00:41:14,419 +But, in real world here now, +但在现实世界中 + +1056 +00:41:14,421 --> 00:41:17,855 +if I had dragged the GPX file on my document, I really need +如果我已经拖放了 GPX 文件,我实际需要 + +1057 +00:41:17,857 --> 00:41:22,159 +an NVC somewhere that can display this GPX file. +一个某处的 NVC 能够显示这个 GPX 文件 + +1058 +00:41:22,161 --> 00:41:24,428 +Okay? + +1059 +00:41:24,429 --> 00:41:26,696 +Now, I guess I could go look at my window, and try and +我觉得我可以看看我的 window,尝试 + +1060 +00:41:26,699 --> 00:41:28,832 +look in a split view inside a navigation controller, and +在 navigation controller 中的 split view + +1061 +00:41:28,834 --> 00:41:31,734 +find a view controller that can handle this GPX file, but +找一个视图控制器来处理这个 GPX 文件 + +1062 +00:41:31,736 --> 00:41:33,369 +that would be really, really bad. +但这非常非常糟糕 + +1063 +00:41:33,371 --> 00:41:35,904 +Really what I want to do is just have a radio station +实际上我需要的是有一个电台 + +1064 +00:41:35,906 --> 00:41:39,274 +that says, anybody who wants to find out when a GPX file +任何人想要知道什么时候一个 GPX 文件 + +1065 +00:41:39,276 --> 00:41:42,177 +has been loaded into this app, listen to this radio station. +已被加载到这个应用中,收听这个电台 + +1066 +00:41:42,179 --> 00:41:44,345 +And then we're going to send a message on the radio station +现在我们要在这个电台中发送一条消息 + +1067 +00:41:44,347 --> 00:41:45,680 +saying, up, one arrived. +有一个(文件)到达了 + +1068 +00:41:46,716 --> 00:41:48,749 +Okay, so that's how we're going to do this. +这就是我们如何处理这个 + +1069 +00:41:49,918 --> 00:41:52,285 +So let's start with the posting side, +让我们从发布消息开始 + +1070 +00:41:52,287 --> 00:41:55,254 +where we're going to post on the radio station. +这里我们将要在电台中发布 + +1071 +00:41:55,256 --> 00:41:58,457 +Now, when you have a radio station, +当你有一个电台时 + +1072 +00:41:58,459 --> 00:42:02,494 +you need to have a name for that radio station. +你需要给这个电台一个名字 + +1073 +00:42:02,496 --> 00:42:06,064 +I'm just going to create that as this kind of global struct. +我以全局结构体来创建这个 + +1074 +00:42:06,066 --> 00:42:09,434 +I'm going to call it static let. +我称这个为 static let + +1075 +00:42:09,436 --> 00:42:11,802 +I'll call this GPXURL. +我叫它为 GPXURL + +1076 +00:42:11,804 --> 00:42:14,071 +Actually, we'll call it notification. +实际上,我们称它为通知 + +1077 +00:42:15,407 --> 00:42:17,607 +So this is just a string which is the name of the radio +所以这只是这个电台名字的字符串 + +1078 +00:42:17,609 --> 00:42:21,544 +station, which we'll call the GPXURL Radio Station or +我们称之为 GPXURL 电台或者 + +1079 +00:42:21,546 --> 00:42:23,145 +something like that. +类似的东西 + +1080 +00:42:23,147 --> 00:42:25,681 +Okay? + +1081 +00:42:25,682 --> 00:42:28,216 +And so, all I need to do to post on this radio station, +我所需要的是在这个电台中发布 + +1082 +00:42:28,218 --> 00:42:30,651 +whatever, is to get that center, +任何,它获取 center + +1083 +00:42:30,653 --> 00:42:36,123 +the NS notification center, default center. +NSNotificationCenter.defaultCenter + +1084 +00:42:36,125 --> 00:42:37,691 +So now I have the center, because I have to have +现在我有这个 center,因为我有这个 + +1085 +00:42:37,693 --> 00:42:40,527 +the notification center to either post or receive. +通知中心发送或接受消息 + +1086 +00:42:40,529 --> 00:42:45,398 +And then, I just need to create a notification, +然后,我只需要创建一个通知 + +1087 +00:42:45,400 --> 00:42:47,199 +which I do by saying NS notification. +我要说 NSNotification + +1088 +00:42:47,201 --> 00:42:49,401 +And if you look at the creation of it, +如果你看这个通知的创建方法 + +1089 +00:42:50,704 --> 00:42:53,271 +you can create it with user info or not. +你可以带 userInfo 或不带来创建它 + +1090 +00:42:53,273 --> 00:42:55,439 +And I do want user info because, +我需要 userInfo,因为 + +1091 +00:42:55,441 --> 00:42:58,442 +when I send out on my radio station, I'm going to send +当我在我的电台发送消息时,我将在我的 + +1092 +00:42:58,444 --> 00:43:03,580 +the URL along as part of my user info, okay? +userInfo 中发送 URL + +1093 +00:43:03,582 --> 00:43:05,348 +So I want this one, and +我需要这个 + +1094 +00:43:05,350 --> 00:43:09,685 +the name of it is GPXURL.notification. +它的名字是 GPXURL.notification + +1095 +00:43:09,687 --> 00:43:14,089 +The object is myself, I'm the one sending on this station. +这个对象是我自己,我自己在这个电台发送消息 + +1096 +00:43:14,091 --> 00:43:16,357 +And user info is going to be. +userInfo 是 + +1097 +00:43:16,359 --> 00:43:20,127 +Well I need the key, GPXURL.key. +我需要这个键,GPXURL.key + +1098 +00:43:20,129 --> 00:43:21,895 +We'll have to define that. +我们需要定义这个 + +1099 +00:43:21,897 --> 00:43:24,731 +And the value is this URL that was just passed through. +这个 URL 的值会被传递 + +1100 +00:43:25,867 --> 00:43:27,966 +There's no space here. +这里没有空间 + +1101 +00:43:27,968 --> 00:43:30,402 +Maybe we'll go to a larger font here. +也许我们需要更大的字体 + +1102 +00:43:30,404 --> 00:43:33,405 +How about this? +这样如何? + +1103 +00:43:33,407 --> 00:43:35,773 +That better? +好一点了? + +1104 +00:43:35,775 --> 00:43:36,607 +Okay. + +1105 +00:43:36,609 --> 00:43:38,375 +So I need to define this key, so +我需要定义这个 key + +1106 +00:43:38,377 --> 00:43:40,944 +I'll put that up here as well. +我也把它放在这上面 + +1107 +00:43:40,945 --> 00:43:43,512 +Static let the Key and this is just a key in that dictionary, +static let key,这只是这个字典中的一个键 + +1108 +00:43:43,515 --> 00:43:48,117 +that user info dictionary, so I'll call this GPXURL URL +这个 userInfo 字典,我称之为 GPXURL URL Key + +1109 +00:43:48,119 --> 00:43:49,852 +key or something, I can call it whatever I want, +或其他的,我可以命名它为任何我想要的 + +1110 +00:43:49,854 --> 00:43:54,322 +it just has to be a unique key inside this user info thing. +你只需要在 userInfo 中有一个唯一的键 + +1111 +00:43:54,324 --> 00:43:57,459 +Okay, so, I've created the notification, +因此,我已经创建了这个通知 + +1112 +00:43:57,461 --> 00:44:00,962 +now I just tell the center post that notification. +现在我要告诉 center,发送这个通知 + +1113 +00:44:00,964 --> 00:44:02,830 +Okay, notification, and +通知,然后 + +1114 +00:44:02,832 --> 00:44:06,333 +that's going to broadcast on that radio station. +它会在电台中广播 + +1115 +00:44:06,335 --> 00:44:09,803 +So, anyone who's listening is going to find out when a URL +任何在收听的人都会发现一个 URL + +1116 +00:44:09,805 --> 00:44:12,472 +gets dropped into this app. +已经被载入这个应用中 + +1117 +00:44:12,474 --> 00:44:14,207 +So now, how do we listen to the radio station? +现在,我们如何收听这个电台? + +1118 +00:44:14,209 --> 00:44:15,708 +Well, who wants to listen? +谁想收听? + +1119 +00:44:15,710 --> 00:44:19,178 +It's going to be this view controller over here. +这会是这里的视图控制器 + +1120 +00:44:19,180 --> 00:44:22,514 +So, I've got my storyboard right here and let's put +这里有我的 storyboard,让我们在 + +1121 +00:44:22,516 --> 00:44:26,017 +something in our storyboard like, how about a text view. +里面放一些东西,比如 text view + +1122 +00:44:26,019 --> 00:44:27,318 +Where's the text view? +text view 在哪里? + +1123 +00:44:28,321 --> 00:44:29,953 +Here it is. So I'm going to drag this text +这里,我将要把这个 text view + +1124 +00:44:29,955 --> 00:44:35,825 +view in here, put this somewhere, maybe right there. +拖到这里,也许这里 + +1125 +00:44:35,827 --> 00:44:41,197 +Okay, let's make sure we do our constraints, sorry, set +让我们确保我们的 constraints,抱歉,设置 + +1126 +00:44:41,199 --> 00:44:47,669 +the constraints, let's take a look at these constraints. +constraints,让我看看这里的 constraints + +1127 +00:44:47,671 --> 00:44:50,638 +Actually, I'm going to have the top space be +实际上,我想要顶部的空间为 + +1128 +00:44:50,640 --> 00:44:53,174 +the standard value away. +标准值 + +1129 +00:44:53,176 --> 00:44:53,774 +Okay? + +1130 +00:44:53,776 --> 00:44:55,275 +So I've got this text. +我有了这个 text view + +1131 +00:44:55,277 --> 00:44:56,710 +Let's get that out of there. +我们把这个拿出来 + +1132 +00:44:56,712 --> 00:44:57,811 +I've got this nice text field. +我有这个很好的 text field + +1133 +00:44:57,813 --> 00:44:59,112 +Let's go ahead and create an outlet for +让我们继续,创建一个 outlet + +1134 +00:44:59,114 --> 00:45:03,315 +that into our view controllers, control drag. +到我们的视图控制器,control 拖拽 + +1135 +00:45:03,317 --> 00:45:05,817 +I'll call that textview, okay? +我命名这个 textview + +1136 +00:45:05,819 --> 00:45:07,251 +We don't need any of this. +我不需要这些 + +1137 +00:45:10,023 --> 00:45:11,021 +Okay? + +1138 +00:45:11,023 --> 00:45:12,122 +So, that's that. +这就是了 + +1139 +00:45:12,124 --> 00:45:14,357 +So, we've got our text view outlet right here. +这里我们有我们的 textview outlet + +1140 +00:45:14,359 --> 00:45:17,360 +Now, all I'm going to do is when that radio station +现在我们要做的是,当电台发送广播时 + +1141 +00:45:17,362 --> 00:45:21,397 +broadcasts, I'm going to put the URL into that text view. +我要把这个 URL 放到这个 textview 中 + +1142 +00:45:21,399 --> 00:45:23,465 +Okay now, on Wednesday, we'll do much more. +现在,周三,我们会做更多 + +1143 +00:45:23,467 --> 00:45:25,133 +We'll put a map and we'll draw all this stuff, but here, +我们会放一个地图,我们将在这里把所有东西都画出 + +1144 +00:45:25,135 --> 00:45:27,185 +that's all I'm going to do. +这是我所有要做到 + +1145 +00:45:27,186 --> 00:45:29,236 +So, I'm going to put this in viewDidLoad, +我要把这个放在 viewDidLoad + +1146 +00:45:29,239 --> 00:45:31,005 +super.viewDidLoad. +super.viewDidLoad + +1147 +00:45:31,007 --> 00:45:32,006 +Don't forget, by the way, +不要忘记,顺便提下 + +1148 +00:45:32,008 --> 00:45:33,707 +in your view controller life cycle methods, +在你们的视图控制器的生命周期方法中 + +1149 +00:45:33,709 --> 00:45:34,741 +you need to call super. +你需要调用 super + +1150 +00:45:34,743 --> 00:45:38,077 +I noticed a few of you not doing that. +我注意到你们中有些人没有这么做 + +1151 +00:45:38,079 --> 00:45:42,948 +So, to make this work, I'm just going to get my center, +为了让这个工作,我只是获取我的 center + +1152 +00:45:42,950 --> 00:45:47,252 +NSNotificationCenter, default center. +NSNotificationCenter.defaultCenter + +1153 +00:45:47,254 --> 00:45:49,887 +[SOUND] Default center. + DefaultCenter + +1154 +00:45:49,889 --> 00:45:51,322 +Okay, I've got the center. +我获取了这个 center + +1155 +00:45:51,324 --> 00:45:54,658 +You remember that I need a cue to put it on. +你们记得我需要一个线程来放置这个 + +1156 +00:45:54,660 --> 00:45:56,660 +So I'm going to do it on the main cue. +我要在主线程中做这个 + +1157 +00:45:56,662 --> 00:46:02,165 +So, I'm going to do NSOperationQueue.mainQueue. +我要处理 NSOperationQueue.mainQueue + +1158 +00:46:02,167 --> 00:46:05,601 +And, I'm looking for this URL broadcast +我从 appDelegate 寻找 URL 广播 + +1159 +00:46:05,603 --> 00:46:09,204 +from the app delegate, which I can get by saying +通过 UIApplication.sharedApplication().delegate 来 + +1160 +00:46:09,206 --> 00:46:14,075 +UIApplication.sharedApplicati- on().delegate, because the app +获取代理,因为 AppDelegate 只是一个 + +1161 +00:46:14,077 --> 00:46:16,444 +delegate is just the delegate of UI applications. +UIApplication 的代理 + +1162 +00:46:16,446 --> 00:46:20,014 +So, now I have all the information I need to do this. +现在我有需要的所有信息 + +1163 +00:46:20,016 --> 00:46:21,648 +I'll make this even wider. +我要把这个变宽一些 + +1164 +00:46:21,650 --> 00:46:25,385 +And I'm just going to center, add observer for name. +我要在 center,addObserverForName + +1165 +00:46:25,387 --> 00:46:27,821 +So here's the add observer for the name, right here. +这是 addObserverForName, 这里 + +1166 +00:46:27,823 --> 00:46:31,024 +Just the one we want, the one that has a block at the end. +这就是我们想要的,这个在结尾有一个 block + +1167 +00:46:31,026 --> 00:46:34,860 +The one we want is GPXURL.Notification. +我们要的是 GPXURL.Notification + +1168 +00:46:34,862 --> 00:46:37,863 +We're interested when the app delegate sends it. +我们感兴趣的是 appDelegate 发送这个通知 + +1169 +00:46:37,865 --> 00:46:40,032 +We want the queue to be that main queue. +我们想要的队列是主队列 + +1170 +00:46:40,034 --> 00:46:45,770 +And we're going to use our nice swift thing +我们要使用我们好用的 swift 的东西 + +1171 +00:46:45,772 --> 00:46:51,542 +where we can put a closure after a method like this. +这里,我们可以像这样在一个方法后放一个闭包 + +1172 +00:46:51,544 --> 00:46:52,342 +Okay? + +1173 +00:46:52,344 --> 00:46:54,310 +Here's the notification, right? +这是 notification + +1174 +00:46:54,312 --> 00:46:56,012 +So we'll just say notification, +所以我们就写 notification + +1175 +00:46:56,014 --> 00:46:58,514 +actually don't even need to put this +实际上我们甚至不需要把这个 + +1176 +00:46:58,516 --> 00:47:00,616 +void business in there. +空的东西放在这里 + +1177 +00:47:00,618 --> 00:47:01,983 +So there's the notification. +这是 notification + +1178 +00:47:01,985 --> 00:47:05,153 +So inside here, this is going to be called every time that +在这里面,每次电台发送广播时 + +1179 +00:47:05,155 --> 00:47:06,220 +radio station broadcasts, +这个都会被调用 + +1180 +00:47:06,222 --> 00:47:09,023 +in other words every time a URL is dropped in. +换句话说,每次一个 URL 被放入时 + +1181 +00:47:09,025 --> 00:47:11,125 +And so, all I"m going to do here is I'm going to say, +这里我所要做的是,我要说 + +1182 +00:47:12,261 --> 00:47:19,699 +if let the URL equal the notification?.userInfo and +if let url = notification?.userInfo,然后 + +1183 +00:47:19,701 --> 00:47:22,702 +we'll look up in there the GPXURL.key, and +我们在这里检查 GPXURL.Key,然后 + +1184 +00:47:22,704 --> 00:47:24,269 +notice I had to put some question marks in there +注意这里我写了几个问号 + +1185 +00:47:24,271 --> 00:47:26,371 +because some of these are optionals. +因为他们中的一些是 optionals(类型) + +1186 +00:47:26,373 --> 00:47:29,074 +Okay, this is probably not actually an optional. +这个很可能不是 optional + +1187 +00:47:29,076 --> 00:47:33,744 +But, and then, that is an NSURL because, remember, +但,然后,这是一个 NSURL,因为记住 + +1188 +00:47:33,746 --> 00:47:38,148 +that this user info dictionary, the values are any +这个 userInfo 字典,它的值是任何 + +1189 +00:47:38,150 --> 00:47:43,219 +object, so I have to cast it to what I actually want. +对象,所以我需要把它转换成我实际需要的 + +1190 +00:47:43,221 --> 00:47:46,455 +And now, I'm just going to say +现在,我让 + +1191 +00:47:46,457 --> 00:47:51,827 +self.textView.text equals Received this URL. +self.textView.text = "Receive \(url)" + +1192 +00:47:51,829 --> 00:47:55,030 +Okay? + +1193 +00:47:55,032 --> 00:47:56,831 +Any questions about that? +这里有问题吗? + +1194 +00:47:56,833 --> 00:48:02,169 +So now, when I run this Trax,. +现在,当我运行这个 Trax + +1195 +00:48:02,171 --> 00:48:04,871 +Instead of it putting it on the console, +不是把它(URL)输出在 console,而是 + +1196 +00:48:04,873 --> 00:48:07,807 +it's gonna actually put it in the content, +输出在 content 上 + +1197 +00:48:07,809 --> 00:48:09,475 +that text view of track. +track 的 textView 上 + +1198 +00:48:09,477 --> 00:48:11,811 +So let's go over here again. +让我们再到这里 + +1199 +00:48:11,813 --> 00:48:13,412 +Luckily this time it's showing. +幸运地,这次它出现了 + +1200 +00:48:13,414 --> 00:48:14,312 +There we go. +开始了 + +1201 +00:48:14,314 --> 00:48:15,347 +So let's go over here. +让我们到这里 + +1202 +00:48:15,348 --> 00:48:16,381 +I'm just going to drag it on here. +我要把它拖放到这里 + +1203 +00:48:17,884 --> 00:48:19,784 +Okay, it's asking me if I want to accept it again. +它又问我是否要接受它 + +1204 +00:48:19,786 --> 00:48:21,118 +I'm gonna say Accept. +我接受了 + +1205 +00:48:21,120 --> 00:48:21,685 +And there it is. +这就是了 + +1206 +00:48:21,687 --> 00:48:23,553 +It puts it on there. +它把它(URL)输出在这里了 + +1207 +00:48:24,723 --> 00:48:28,991 +Okay, now interesting see it says it's Vacation-1.gpx +看,有趣的是,这次它输出 Vacation-1.gpx + +1208 +00:48:28,993 --> 00:48:31,226 +this time, where it was just vacation before. +之前它只是 vacation + +1209 +00:48:31,228 --> 00:48:35,963 +And if I drag it on again, it's gonna be Vacation-2. +如果我再次拖放,它将会是 Vacation-2 + +1210 +00:48:35,965 --> 00:48:38,199 +Okay, so it's collecting these things. +所以它在收集这些东西 + +1211 +00:48:38,201 --> 00:48:39,367 +See Vacation-2? +看,Vacation-2? + +1212 +00:48:39,368 --> 00:48:40,534 +So now I actually have three of these things that +实际上,现在我有三个这样的文件 + +1213 +00:48:40,536 --> 00:48:41,768 +I've dragged in three times. +我拖放三次了 + +1214 +00:48:43,071 --> 00:48:45,038 +Okay? + +1215 +00:48:45,039 --> 00:48:47,006 +So you can see now how this ViewController right here +现在你们可以看到这里的 ViewController + +1216 +00:48:47,008 --> 00:48:50,242 +in an object-oriented way is very self-contained. +以一种面向对象的方式,非常独立的 + +1217 +00:48:50,244 --> 00:48:53,846 +It displays GPX files somehow, and all it does is sign up to +它以某种方式显示 GPX 文件,它所做的是注册 + +1218 +00:48:53,848 --> 00:48:56,581 +the radio station that says I received one. +电台,它在收听这个文件 + +1219 +00:48:56,583 --> 00:48:58,049 +And then it goes and does what it does. +然后它走了,做它该做的 + +1220 +00:48:58,051 --> 00:49:00,551 +And again on Wednesday we'll actually draw the map. +周三,我们会绘制这个地图 + +1221 +00:49:01,854 --> 00:49:03,220 +Okay? + +1222 +00:49:03,222 --> 00:49:04,054 +Any question about that? +这里有问题吗? + +1223 +00:49:06,191 --> 00:49:07,356 +All righty, that is it. +好吧,这就是了 + +1224 +00:49:07,358 --> 00:49:08,891 +Back to our slides. +回到我们的幻灯片 + +1225 +00:49:10,828 --> 00:49:14,262 +Where's my slides here? +我的幻灯片在哪里,这里? + +1226 +00:49:14,264 --> 00:49:18,933 +Slides, okay, all right. +幻灯片,好的 + +1227 +00:49:18,935 --> 00:49:22,036 +So the next thing we'll talk about is core motion. +接下来我们要谈论的是 core motion + +1228 +00:49:22,038 --> 00:49:26,406 +So core motion is what's happening with the hardware. +core motion 是硬件在做什么 + +1229 +00:49:26,408 --> 00:49:30,176 +And the primary inputs to that are the accelerometer, +最主要的输入是,加速计 + +1230 +00:49:30,178 --> 00:49:32,278 +the gyro, and the magnetometer. +陀螺仪,磁力计 + +1231 +00:49:32,280 --> 00:49:34,046 +Not all devices have all those things. +不是所有的设备都有这三样东西 + +1232 +00:49:34,048 --> 00:49:35,647 +Newer devices have them all. +新的设备都有这三个 + +1233 +00:49:35,649 --> 00:49:39,718 +But older devices, some of them don't have it. +但老设备,有一些是没有这些的 + +1234 +00:49:39,720 --> 00:49:42,186 +The class that you use to get all the information about this +你们使用的获取这些信息的类 + +1235 +00:49:42,188 --> 00:49:45,690 +is called CMMotionManager, so CM is core motion. +叫做 CMMotionManager,所以 CM 是 core motion + +1236 +00:49:45,692 --> 00:49:48,992 +That's the name of the framework this is all in. +这是这个框架的名字,所有东西都在这里面 + +1237 +00:49:48,994 --> 00:49:52,529 +And so the motion manager, you really only want to have +所以 motion manager,在每个应用中你实际 + +1238 +00:49:52,531 --> 00:49:56,632 +one of these per app, because you only have one gyro, okay, +只需要它们中的一个,因为你只有一个陀螺仪 + +1239 +00:49:56,634 --> 00:49:59,435 +and one accelerometer, one magnetometer. +一个加速计,一个磁力计 + +1240 +00:49:59,437 --> 00:50:01,003 +So you really want one of these. +所以你实际要它们中的一个 + +1241 +00:50:01,004 --> 00:50:02,570 +So you want to put it in some global space and share it, +如果你想要把它放在一些全局空间并分享它 + +1242 +00:50:02,573 --> 00:50:05,240 +like maybe your app delegate would be a good place. +也许你的 appDelegate 是一个好的地方 + +1243 +00:50:05,242 --> 00:50:06,641 +The way you use the motion manager, +你使用 motion manager 的方式 + +1244 +00:50:06,643 --> 00:50:08,042 +there's really two ways to do it. +实际上有两种方式使用它 + +1245 +00:50:08,044 --> 00:50:11,312 +Polling, which is, you create one of these motion managers. +Polling,这个是,你创建这些 motion manager 中的一个 + +1246 +00:50:11,314 --> 00:50:13,547 +You check to see what hardware is available like, +你检查哪个硬件可以使用 + +1247 +00:50:13,549 --> 00:50:15,749 +is accelerometer available, gyro, or whatever. +比如加速计可用,还是陀螺仪,还是其他任何的 + +1248 +00:50:15,751 --> 00:50:19,085 +And then you just start asking for the value over and over. +然后你开始不停的询问这个值 + +1249 +00:50:19,087 --> 00:50:20,820 +Usually, we don't do it that way. +一般的,我们不这么用 + +1250 +00:50:20,822 --> 00:50:21,887 +We do it the second way, +我们使用第二种方式 + +1251 +00:50:21,889 --> 00:50:24,690 +which is, we check to see what's available. +也就是,我们检查哪个可用 + +1252 +00:50:24,692 --> 00:50:27,559 +And then if it's available, we say how often we want to +然后如果它可用,我们会说我们想要多久 + +1253 +00:50:27,561 --> 00:50:30,962 +receive an update, 'kay, how often we want to get +收到一个更新,比如我们想要加速计 + +1254 +00:50:30,964 --> 00:50:33,331 +the acceleration from the accelerometer for example. +加速多频繁 + +1255 +00:50:33,333 --> 00:50:36,033 +And then you register a closure, 'kay, +然后,你注册一个闭包 + +1256 +00:50:36,035 --> 00:50:39,169 +a block of code, that will get called each time. +一个代码块,它每次都会被调用 + +1257 +00:50:39,171 --> 00:50:41,772 +'Kay, so that's a much more sensible way to do this than +这种方式要比 polling 来得明智些 + +1258 +00:50:41,774 --> 00:50:44,440 +polling, and so that's the way we're going to do this. +这就是我们要使用的方式 + +1259 +00:50:45,843 --> 00:50:47,343 +Notice that I had mentioned checking +注意,我提到了检查它的 + +1260 +00:50:47,345 --> 00:50:49,378 +the availability of it. +可用性 + +1261 +00:50:49,379 --> 00:50:51,412 +Well, because some devices don't have a gyro, for +因为有些设备并没有一个陀螺仪 + +1262 +00:50:51,415 --> 00:50:52,614 +example, you have to check. +你必须检查 + +1263 +00:50:52,616 --> 00:50:55,550 +And you do that by just asking the motion manager, +你只需要询问 motion manager + +1264 +00:50:55,552 --> 00:50:57,551 +accelerometer Available? +加速计是否可用? + +1265 +00:50:57,553 --> 00:51:00,054 +And that will return true if it's available and +然后如果可用它会返回真 + +1266 +00:51:00,056 --> 00:51:01,455 +false if it's not. +否则返回假 + +1267 +00:51:01,457 --> 00:51:05,091 +Okay, you can do that for all the different hardware things. +所有不同的硬件你都可以使用这种方式 + +1268 +00:51:05,093 --> 00:51:10,329 +Then you start the motion manager reporting to you. +然后 motion manager 开始向你发送报告 + +1269 +00:51:10,331 --> 00:51:14,833 +Now, again, if you're polling, you can just say start update. +再次,如果你使用 polling,你只需要开始更新 + +1270 +00:51:14,835 --> 00:51:17,002 +And then it will start updating it, and +然后它就会开始更新它 + +1271 +00:51:17,004 --> 00:51:19,504 +you can ask for the value at any time. +你可以在任何时候请求值 + +1272 +00:51:19,506 --> 00:51:20,604 +Okay? But we don't usually do +但通常我们不 + +1273 +00:51:20,606 --> 00:51:21,872 +it that way. +这么做 + +1274 +00:51:21,874 --> 00:51:23,573 +We'll talk about that in a second. +一会我们会谈到 + +1275 +00:51:23,575 --> 00:51:26,676 +And you can also find out whether the device is +你也可以检查当前设备是否在 + +1276 +00:51:26,678 --> 00:51:29,479 +actually looking at the accelerometer right now, +查看加速计 + +1277 +00:51:29,481 --> 00:51:32,281 +if anybody's interested in it, by saying accelerometer +如果有人对它感兴趣,也就是说加速计当前是 + +1278 +00:51:32,283 --> 00:51:35,417 +Active, or gyro Active, deviceMotion Active. +活跃的,或者陀螺仪或 deviceMotion 是活跃的 + +1279 +00:51:35,419 --> 00:51:37,586 +We'll talk about deviceMotion in a second, what that is. +一会我们谈谈 deviceMotion 是什么 + +1280 +00:51:38,689 --> 00:51:39,954 +And you can stop it also, and +你也可以停止它 + +1281 +00:51:39,956 --> 00:51:42,990 +it's very important to stop it because this thing +停止它是非常重要的,因为这东西 + +1282 +00:51:42,992 --> 00:51:46,694 +uses a lot of battery, okay, so you do not want this +消耗很多电量,你并不想用它 + +1283 +00:51:46,696 --> 00:51:48,762 +happening unless you're actually using the data. +除非你真的需要这个数据 + +1284 +00:51:48,764 --> 00:51:50,864 +That is very important to understand, +理解这点非常重要 + +1285 +00:51:50,866 --> 00:51:53,399 +and that's true of the GPS location stuff as well, +GPS 定位也是一样的 + +1286 +00:51:53,401 --> 00:51:55,201 +which we're gonna talk about on Wednesday. +我们周三来讲这个 + +1287 +00:51:55,203 --> 00:51:56,635 +You really want to turn this stuff off if +实际上你需要关闭这个,如果你 + +1288 +00:51:56,637 --> 00:51:58,620 +you're not using it. +没使用它 + +1289 +00:51:58,621 --> 00:52:00,604 +You do that with just saying, stop whatever Updates. +要关闭它,你只要停止任何更新 + +1290 +00:52:00,607 --> 00:52:01,773 +Okay? And that's true whether you're +不管你是使用 polling 或 + +1291 +00:52:01,775 --> 00:52:04,175 +polling or whether you're using the block-based one. +block-based 方式,都是可行的 + +1292 +00:52:05,945 --> 00:52:08,979 +All right, so let's look at the data structures here. +让我们看看这里的数据结构 + +1293 +00:52:08,981 --> 00:52:10,698 +They're very, very simple. +它们非常,非常简单 + +1294 +00:52:10,699 --> 00:52:12,416 +So, when you get acceleration data, it comes as x, y, +当你收集数据时,它们会是在 g 中的 x,y,z + +1295 +00:52:12,418 --> 00:52:16,219 +z in g, g meaning acceleration due to gravity. +g 代表重力加速度 + +1296 +00:52:16,221 --> 00:52:18,388 +All right? + +1297 +00:52:18,389 --> 00:52:20,556 +So If I have this phone sitting flat right here, +如果我让这个手机平躺在这里 + +1298 +00:52:20,558 --> 00:52:25,160 +it's going to be having the z-axis this way so it can tell +那么 z 轴会是这样,它会告诉你这样 + +1299 +00:52:25,162 --> 00:52:29,197 +you this way and then y is this way and x is this way. +y 是这样,x 是这样 + +1300 +00:52:29,199 --> 00:52:31,366 +So if you were to move it this way you'd get a lot of x +如果你以这种方式移动它,你会得到很多的 x + +1301 +00:52:31,368 --> 00:52:32,867 +acceleration and deceleration. +加速和减速 + +1302 +00:52:32,869 --> 00:52:34,735 +If you move it this way you're gonna get a lot of z +如果你这样移动,你会得到很多的 z + +1303 +00:52:34,737 --> 00:52:36,403 +acceleration, deceleration. +加速,减速 + +1304 +00:52:36,405 --> 00:52:38,805 +And if you just get the acceleration data directly, +如果你只是直接获取加速度数据 + +1305 +00:52:38,807 --> 00:52:40,840 +it includes the acceleration due to gravity. +它包含由于重力引起的加速度 + +1306 +00:52:40,842 --> 00:52:44,910 +So this phone right here, z is going to be 1.0 right now. +所以这里的这个手机,现在 z 会是1.0 + +1307 +00:52:44,912 --> 00:52:47,179 +'Kay? + +1308 +00:52:47,180 --> 00:52:49,447 +If I turn it this way now, x is gonna be 1.0. +如果我把它变成这样,x 会是 1.0 + +1309 +00:52:49,449 --> 00:52:51,049 +'Kay? + +1310 +00:52:51,050 --> 00:52:52,650 +Cuz it's got acceleration due to gravity. +因为它获取了重力加速度 + +1311 +00:52:52,651 --> 00:52:54,251 +Now if you have a gyro, you can get the acceleration +如果你有一个陀螺仪,没有重力你可以获取 + +1312 +00:52:54,254 --> 00:52:56,387 +without gravity, and we'll talk about that in a second. +加速度,一会我谈这个 + +1313 +00:52:56,389 --> 00:52:59,189 +If you get the gyro information, +如果你获取陀螺仪信息 + +1314 +00:52:59,191 --> 00:53:01,358 +then it's going to tell you about rotation rate. +它会告诉你转速 + +1315 +00:53:01,360 --> 00:53:04,094 +And it's going to tell you how fast the device +它会告诉你设备在 x,y,z 方向的 + +1316 +00:53:04,096 --> 00:53:07,497 +is rotating in the x, y, or z directions. +转速有多快 + +1317 +00:53:07,499 --> 00:53:10,666 +Okay, that's what a gyro tells you, is the rate of rotation. +这是陀螺仪会告诉你的,转速 + +1318 +00:53:12,102 --> 00:53:15,437 +The magnetometer is going to tell you +磁力计会告诉你 + +1319 +00:53:15,439 --> 00:53:17,171 +basically the magnetic field, +磁场 + +1320 +00:53:17,173 --> 00:53:21,008 +around your device, in each of the directions. +在你设备周围,每个方向上的 + +1321 +00:53:21,010 --> 00:53:22,242 +Okay. + +1322 +00:53:22,244 --> 00:53:23,476 +That's what a magnetometer does. +这是磁力计所做的 + +1323 +00:53:23,478 --> 00:53:24,994 +It tells you magnetic field. +它告诉你磁场 + +1324 +00:53:24,995 --> 00:53:26,511 +That's how you can detect where true north is, +这是你怎么辨别真北在哪个方位上 + +1325 +00:53:26,514 --> 00:53:29,448 +for example. +举个例子 + +1326 +00:53:29,450 --> 00:53:32,584 +Now there's a very interesting one which is +现在有一个非常有趣的,就是 + +1327 +00:53:32,586 --> 00:53:34,920 +CMDeviceMotion, okay? +CMDeviceMotion + +1328 +00:53:34,922 --> 00:53:38,123 +So it's another thing like accelerometer, gyro, or +这是和加速计,陀螺仪或 + +1329 +00:53:38,125 --> 00:53:39,708 +magnetometer. +磁力计相同的另一个东西 + +1330 +00:53:39,709 --> 00:53:41,292 +But the CMDeviceMotion is actually a combination +CMDeviceMotion 实际上是这三者的 + +1331 +00:53:41,294 --> 00:53:42,493 +of those things. +结合 + +1332 +00:53:42,495 --> 00:53:45,195 +So for CMDeviceMotion, if you ask for +对于 CMDeviceMotion,如果你请求 + +1333 +00:53:45,197 --> 00:53:48,398 +CMDeviceMotion updates, when you get to gravity, +CMDeviceMotion 更新,当你取得重力时 + +1334 +00:53:48,400 --> 00:53:49,733 +it's going to give you gravity. +它会给你重力 + +1335 +00:53:50,735 --> 00:53:54,336 +It's going to give you the user acceleration +没有重力它则给你用户加速度 + +1336 +00:53:54,338 --> 00:53:55,604 +without gravity. + +1337 +00:53:55,605 --> 00:53:56,871 +In other words, it will separate gravity out, so +换句话说,它将区分重力 + +1338 +00:53:56,874 --> 00:53:59,541 +you can find out where gravity is, where that's pointing. +所以你能找到重力在哪里,它指向哪里 + +1339 +00:53:59,543 --> 00:54:01,576 +Right? Where is gravity pointing and +重力指向哪里 + +1340 +00:54:01,578 --> 00:54:03,577 +where is the user accelerating, separated? +用户在哪里加速,两者分开 + +1341 +00:54:03,579 --> 00:54:06,213 +And it can do that because it has the gyro. +它能这么做是因为它有陀螺仪 + +1342 +00:54:06,215 --> 00:54:08,182 +Right? So + +1343 +00:54:08,183 --> 00:54:10,150 +it know what's happening this way, so it can tell you +它知道这种方式下会发生什么,它能告诉你 + +1344 +00:54:10,152 --> 00:54:13,086 +what's acceleration and what's rotation. +加速度是什么,什么在旋转 + +1345 +00:54:13,088 --> 00:54:14,087 +Okay? And similarly, for +类似地,对于 + +1346 +00:54:14,089 --> 00:54:15,354 +the rotation, +转向 + +1347 +00:54:15,356 --> 00:54:18,390 +it can give you unbiased data about the rotation. +它能给你转向有关的客观数据 + +1348 +00:54:18,392 --> 00:54:20,926 +Okay? Because it knows fixed points. +因为它知道固定的点 + +1349 +00:54:20,928 --> 00:54:22,660 +Maybe the magnetometer, for example, +比如,可能是磁力计 + +1350 +00:54:22,662 --> 00:54:24,462 +can tell us fixed points. +能告诉我们固定的点 + +1351 +00:54:24,464 --> 00:54:27,131 +And, so now you can get the attitude of your device +现在你能获取你的设备 + +1352 +00:54:27,133 --> 00:54:28,632 +with roll, pitch, and yaw. +滚动,投掷,偏航方向 + +1353 +00:54:28,634 --> 00:54:29,733 +You all know what that is? +你们都知道这是什么吗? + +1354 +00:54:29,735 --> 00:54:31,167 +It's, kind of, an airplane thing. +它是类似于飞行 + +1355 +00:54:31,169 --> 00:54:35,705 +Right, so roll is how much you're rolling the device, +滚动是指你如何滚动你的设备 + +1356 +00:54:35,707 --> 00:54:37,573 +pitch is how much you're pitching it up and +投掷是你将它放的多上和多 + +1357 +00:54:37,575 --> 00:54:38,640 +down, right? +下 + +1358 +00:54:38,642 --> 00:54:40,308 +And then, yaw is, +然后,偏航是 + +1359 +00:54:40,309 --> 00:54:41,975 +kinda, how much you're rotating this direction. +类似,你如何转动这个设备 + +1360 +00:54:41,978 --> 00:54:45,546 +So it can give you that pure information unbiased if it has +它能给你客观的纯粹信息,如果你同时有 + +1361 +00:54:45,548 --> 00:54:48,249 +both the accelerometer, so it knows where down is, for +加速计,通过这个它知道下方在哪里, + +1362 +00:54:48,251 --> 00:54:49,783 +example, or magnetometer. +或磁力计 + +1363 +00:54:49,785 --> 00:54:51,852 +And gyro has them all, can combine them. +磁力计拥有这全部,能够组合它们 + +1364 +00:54:51,854 --> 00:54:54,988 +So CMDeviceMotion is a really powerful mechanism to +CMDeviceMotion 真的是一种获取实际数据的 + +1365 +00:54:54,990 --> 00:54:56,522 +kinda get real data. +强大的机制 + +1366 +00:54:56,524 --> 00:54:59,425 +And same thing with magnetic field, okay? +磁场也是一样的 + +1367 +00:55:00,894 --> 00:55:04,329 +So how do you do this with not polling? +没有 polling 你怎么处理这个? + +1368 +00:55:04,331 --> 00:55:06,564 +You do this registering a block. +你们注册一个 block 来实现 + +1369 +00:55:06,566 --> 00:55:09,033 +You just say, for example, for accelerometer, +你们可以,比如,对于加速计 + +1370 +00:55:09,035 --> 00:55:11,402 +startAccelerometerUpdatesToQu- eue. +startAccelerometerUpdatesToQueue + +1371 +00:55:11,404 --> 00:55:13,236 +You give it queue, like the main queue, for +你可以给它队列,像主队列,比如 + +1372 +00:55:13,238 --> 00:55:15,939 +example, where you want this block to execute. +你想让这个代码块在哪里执行 + +1373 +00:55:15,941 --> 00:55:18,975 +And then you give it the handler, and the handler just +然后你给它 handler,这个 handler 需要一个 + +1374 +00:55:18,977 --> 00:55:22,645 +takes an argument which is the data, the accelerometer data, +数据参数,也就是加速度数据 + +1375 +00:55:22,647 --> 00:55:24,847 +and an error, if it got some sort of error. +还有一个 error,如果它获取了某些错误 + +1376 +00:55:24,849 --> 00:55:26,148 +And you can get errors. +你们可以得到错误 + +1377 +00:55:26,150 --> 00:55:30,752 +And similar for the gyro, similar for the DeviceMotion. +陀螺仪也是一样的,还有 DeviceMotion + +1378 +00:55:30,754 --> 00:55:34,088 +And some of the errors you can get are things like +你能获取的一些错误是,比如 + +1379 +00:55:34,090 --> 00:55:36,557 +this activity is not authorized. +这个活动没有被授权 + +1380 +00:55:36,559 --> 00:55:38,892 +Because the user can actually go into their settings on your +因为用户实际上可以去设备的设置里 + +1381 +00:55:38,894 --> 00:55:41,661 +device and say I don't want this app to +我不想让这个应用从我这 + +1382 +00:55:42,664 --> 00:55:44,630 +get motion information from me. +获取设备运动信息 + +1383 +00:55:45,599 --> 00:55:50,001 +Okay, and other errors there, like requires movement. +其他的错误,比如要求移动 + +1384 +00:55:50,003 --> 00:55:52,170 +Obviously if you're asking for device motion and +显然,如果你请求设备运动 + +1385 +00:55:52,172 --> 00:55:54,705 +the device is sitting on the tabletop, it's not moving. +然而设备躺在桌面上,它没有移动 + +1386 +00:55:54,707 --> 00:55:58,242 +It can't give you any information. +它不能给你任何信息 + +1387 +00:55:58,244 --> 00:56:01,011 +You set the rate at which this closure is gonna be +你要设置这个闭包将被调用的频率 + +1388 +00:56:01,013 --> 00:56:03,747 +called by set accelerometerUpdateInterval to +可以通过设置 accelerometerUpdateInterval 为 + +1389 +00:56:03,749 --> 00:56:06,816 +whatever you want or deviceMotionUpdateInterval to +任何你想要的值,或 deviceMotionUpdateInterval + +1390 +00:56:06,818 --> 00:56:09,552 +whatever you want as you might expect. +为任何你想要的值,你所期待的 + +1391 +00:56:09,554 --> 00:56:11,320 +It's in seconds, all right? +单位是秒 + +1392 +00:56:11,322 --> 00:56:14,289 +So, you don't wanna set this to high a rate. +你并不想设置这个为高频 + +1393 +00:56:14,291 --> 00:56:15,690 +Like if you set this higher then, +如果你设置的过高 + +1394 +00:56:16,826 --> 00:56:19,727 +maybe 30 to 60 hertz, it really can't +可能30到60赫兹,它实际上不能 + +1395 +00:56:19,729 --> 00:56:22,229 +barely even give you that information that fast. +这么频繁的向你提供信息 + +1396 +00:56:22,231 --> 00:56:24,464 +And you're gonna be calling your block a lot more and +你想要大量调用你的代码块 + +1397 +00:56:24,466 --> 00:56:27,067 +you're gonna be using a lot of power. +你将会使用很多电量 + +1398 +00:56:27,069 --> 00:56:30,136 +And so you really want to be careful to kinda do this at +所以这样做你要非常小心 + +1399 +00:56:30,138 --> 00:56:33,305 +a rate that gives you smooth response for whatever you're, +以一个它能给你任何你想要的及时响应的频率 + +1400 +00:56:33,307 --> 00:56:35,674 +however you're reacting, but not overly. +然而你会反应,但不过度 + +1401 +00:56:35,676 --> 00:56:37,342 +In fact, you might get a smoother response if you +实际上,如果你降低这个值 + +1402 +00:56:37,344 --> 00:56:38,276 +slow it down a little. +也许你会得到一个更顺畅的体验 + +1403 +00:56:38,278 --> 00:56:39,210 +'Kay? + +1404 +00:56:39,212 --> 00:56:40,745 +Cuz if try to update too much, +因为如果更新太频繁 + +1405 +00:56:40,747 --> 00:56:41,745 +it might be a little too choppy. +可能有一些波动 + +1406 +00:56:41,747 --> 00:56:44,748 +So be careful with that update interval. +所以对于这个更新间隔要小心点 + +1407 +00:56:44,750 --> 00:56:49,452 +You can call that start gyro update with this handler +你可以多次调用这个,开始更新陀螺仪 + +1408 +00:56:49,454 --> 00:56:51,821 +multiple times and have multiple blocks going on, and +然后有许多 block 在进行中 + +1409 +00:56:51,823 --> 00:56:53,255 +that's perfectly legal. +这非常合理 + +1410 +00:56:53,257 --> 00:56:55,223 +'Kay? Even though you only have one +即使你只有一个陀螺仪 + +1411 +00:56:55,225 --> 00:56:58,526 +gyro, the motion manager can still call multiple different +只要你想,MotionManager 仍然可以有许多不同 + +1412 +00:56:58,528 --> 00:56:59,627 +blocks if you want. +block + +1413 +00:56:59,629 --> 00:57:01,062 +Okay, or accelerometer. +或者加速计 + +1414 +00:57:01,064 --> 00:57:03,731 +Any time I use an example, gyro, accelerometer, +任何时候我使用一个,陀螺仪,加速计 + +1415 +00:57:03,733 --> 00:57:06,066 +magnetometer, device motion, they're all exactly the same. +磁力计,deviceMotion,它们完全一样 + +1416 +00:57:07,736 --> 00:57:10,670 +Okay, so, the demo I have for this is called Bouncer, +关于这个的例子叫做 Bouncer + +1417 +00:57:10,672 --> 00:57:14,440 +and what we're going to do is we are going to do a dynamic +我们将要做的是,一个动画 + +1418 +00:57:14,442 --> 00:57:18,910 +animation, but we're gonna use real gravity, as the gravity. +但我们要使用真的重力,重力 + +1419 +00:57:18,912 --> 00:57:21,680 +'Kay, we're gonna hook up a gravity behavior to +我们要把一个重力行为挂钩到 + +1420 +00:57:21,682 --> 00:57:23,281 +actual real gravity. +现实中真的重力 + +1421 +00:57:23,283 --> 00:57:24,115 +'Kay? + +1422 +00:57:24,117 --> 00:57:26,216 +So how do we do that? +我们要怎么做呢? + +1423 +00:57:26,218 --> 00:57:29,186 +[SOUND] We're not actually gonna hook it up to real +我们实际并不是把它和 + +1424 +00:57:29,188 --> 00:57:31,221 +gravity. +真的重力挂钩 + +1425 +00:57:31,222 --> 00:57:33,255 +We're gonna hook it up to real device acceleration. +我们要把它和真的设备加速度挂钩 + +1426 +00:57:33,258 --> 00:57:36,025 +So the user can kinda move it around and +用户可以这样移动设备 + +1427 +00:57:36,027 --> 00:57:37,693 +also will be using gravity as well. +也会使用重力 + +1428 +00:57:37,695 --> 00:57:40,129 +So as I move my device around, +所以当我移动我的设备 + +1429 +00:57:40,131 --> 00:57:42,964 +I'm going to be having my dynamic animator affected by +我将让我的动画被 + +1430 +00:57:42,966 --> 00:57:46,534 +whatever acceleration the device is going through. +设备的任何加速影响 + +1431 +00:57:46,536 --> 00:57:48,035 +All right. + +1432 +00:57:48,037 --> 00:57:50,570 +So let's go here to Bouncer. +让我们创建 Bouncer + +1433 +00:57:52,174 --> 00:57:56,509 +It's a new project again, it's iOS apps, +一个新的项目,这是 iOS 应用 + +1434 +00:57:56,511 --> 00:57:59,011 +single view, Bouncer. +singleView,Bouncer + +1435 +00:57:59,013 --> 00:58:02,681 +Okay, and put it in the place that we always do. +把它放在我们经常放的地方 + +1436 +00:58:02,683 --> 00:58:04,616 +Now, one thing I'm gonna do for +关于 Bouncer 我要做的一件事情是 + +1437 +00:58:04,618 --> 00:58:07,318 +Bouncer to make it a little easier on myself, +让他简单些 + +1438 +00:58:07,320 --> 00:58:11,122 +is I'm gonna make Bouncer not work in landscape mode. +我不让 Bouncer 在水平模式可用 + +1439 +00:58:11,124 --> 00:58:12,089 +I'm sure you'd like to do this for +我确信你们在作业中也会这样做 + +1440 +00:58:12,091 --> 00:58:13,557 +your homework assignment, as well. + +1441 +00:58:14,626 --> 00:58:16,926 +But we are just going to make a portrait only. +我们只是做一个垂直模式的 + +1442 +00:58:16,928 --> 00:58:19,128 +Just to make the code a little simpler, cuz it's a demo. +让代码简单点,因为这是个例子 + +1443 +00:58:19,130 --> 00:58:20,996 +But we usually wouldn't do that in an app, +但在一个应用中我们通常不这么做 + +1444 +00:58:20,998 --> 00:58:22,330 +making it not work in landscape. +水平模式不能工作 + +1445 +00:58:22,332 --> 00:58:24,198 +Users kinda don't like that very much. +用户不会喜欢这样的 + +1446 +00:58:26,169 --> 00:58:27,067 +Okay. So, + +1447 +00:58:27,069 --> 00:58:29,436 +I'm going to start right off the bat +我们开始 + +1448 +00:58:29,438 --> 00:58:32,505 +by creating a dynamic behavior, okay? +创建一个动画 + +1449 +00:58:32,507 --> 00:58:34,907 +Just like we did in the last one. +就像我们上次做的那样 + +1450 +00:58:34,909 --> 00:58:36,776 +So it's gonna be UiDynamicBahavior. +这会是 UiDynamicBahavior + +1451 +00:58:36,778 --> 00:58:40,279 +I'm gonna call it BouncerBehavior, 'kay? +我称之为 BouncerBehavior + +1452 +00:58:40,281 --> 00:58:44,349 +Cause I wanna capsulate all the behavior of the bouncer +因为我想要在一个类中封装 bouncer 的所有行为 + +1453 +00:58:44,351 --> 00:58:48,586 +into one class just like we did in Drop It, okay? +就像我们在 DropIt 中做的 + +1454 +00:58:48,588 --> 00:58:50,287 +So here our BouncerBehavior. +这是我们的 BouncerBehavior + +1455 +00:58:50,289 --> 00:58:53,190 +I'm going to cheat and go over to DropIt. +我们要作弊下,在 DropIt + +1456 +00:58:53,192 --> 00:58:57,727 +And steal a lot of the code out of there, so +从那里偷一些代码 + +1457 +00:58:57,729 --> 00:59:01,597 +let's go over to DropItBehavior. +让我们找到 DropItBehavior + +1458 +00:59:01,599 --> 00:59:05,001 +Here's DropItBehavior, so I'm gonna actually copy the whole +这是 DropItBehavior,我要拷贝着全部 + +1459 +00:59:05,003 --> 00:59:06,602 +thing and paste it over here. +代码,粘贴到这里 + +1460 +00:59:06,604 --> 00:59:08,403 +[SOUND] 'Kay? + +1461 +00:59:08,405 --> 00:59:13,274 +Now the differences between drop it and +dropIt 和 我的 BouncerBehavior + +1462 +00:59:13,276 --> 00:59:18,445 +my bouncing behavior are kinda twofold. +不同处是双重的 + +1463 +00:59:18,447 --> 00:59:20,180 +Well, really, one major difference again is +实际上,一个主要的区别是 + +1464 +00:59:20,182 --> 00:59:22,415 +the gravity is gonna be driven by real gravity. +gravity 是被现实重力驱动的 + +1465 +00:59:22,417 --> 00:59:25,451 +But also I want the elasticity to be a little bit higher. +但我也想让 elasticity 大一些 + +1466 +00:59:25,453 --> 00:59:28,454 +Also, as some of you have noticed, you really want +你们有些已经注意到了,你真的想关掉 + +1467 +00:59:28,456 --> 00:59:35,060 +the friction to be off, and the resistance to be off. +friction,还有 resistance + +1468 +00:59:35,062 --> 00:59:37,629 +Okay, you probably want that true for your breakout as +很可能你也想让你的突破是真的 + +1469 +00:59:37,631 --> 00:59:39,530 +well, cuz you want the thing to bounce around and +因为你想让这个东西反弹 + +1470 +00:59:39,532 --> 00:59:40,731 +flow naturally. +并自然跳动 + +1471 +00:59:40,733 --> 00:59:41,565 +So we do that. +所有我们做这个 + +1472 +00:59:41,567 --> 00:59:43,150 +The other thing, too, +另一件事情 + +1473 +00:59:43,151 --> 00:59:44,734 +is I don't really wanna call these things drops, +我不想叫这些东西 drop + +1474 +00:59:44,737 --> 00:59:47,237 +because bouncer, they're not really dropping. +因为 bouncer,它们实际上并不下落 + +1475 +00:59:47,239 --> 00:59:48,555 +They're kinda bouncing around. +它们弹跳着的 + +1476 +00:59:48,556 --> 00:59:49,872 +They're just little blocks that are bouncing around. +它们是弹跳的小方块 + +1477 +00:59:49,874 --> 00:59:51,907 +So I'm gonna change those things. +我要修改这些东西 + +1478 +00:59:51,909 --> 00:59:54,143 +I'm gonna do Find and Replace in project here. +我要在项目中查找和替换 + +1479 +00:59:54,145 --> 00:59:57,312 +And hopefully you've found this little gem. +希望你已经发现这个小宝石 + +1480 +00:59:57,314 --> 01:00:02,283 +And I'm gonna replace drop with block. +我要替换 drop 为 block + +1481 +01:00:02,285 --> 01:00:05,119 +So I wanna call these things blocks instead of drops. +我要称这些东西为 blocks 而不是 drops + +1482 +01:00:05,121 --> 01:00:06,887 +So I'm just gonna Replace All. +我要替换全部 + +1483 +01:00:06,889 --> 01:00:09,990 +We don't wanna do snapshots. +我不想做快照 + +1484 +01:00:09,992 --> 01:00:12,225 +I'll do it for both cases. +两种情况我都要替换 + +1485 +01:00:12,227 --> 01:00:15,461 +Upper and lower case, Replace All. +大小写,替换全部 + +1486 +01:00:15,463 --> 01:00:18,597 +So now I have this block, +现在我有这个 block + +1487 +01:00:18,599 --> 01:00:20,799 +this bouncer behavior that works on blocks. +这个 BouncerBehavior 在 block 工作 + +1488 +01:00:20,801 --> 01:00:23,835 +You see addBlock, removeBlock. +你们看到 addBlock,removeBlock + +1489 +01:00:23,837 --> 01:00:26,237 +But otherwise, pretty much the same. +除此之外,几乎是相同的 + +1490 +01:00:26,239 --> 01:00:28,539 +'Kay. I'm just gonna tie its gravity +我要把它的重力和 + +1491 +01:00:28,541 --> 01:00:29,607 +to the accelerometer. +加速计绑定起来 + +1492 +01:00:30,676 --> 01:00:31,675 +Okay? + +1493 +01:00:31,677 --> 01:00:33,777 +Everyone cool with where I am so far? +每个人都理解这些了吗? + +1494 +01:00:33,779 --> 01:00:37,113 +So let's go to, and I'm just gonna do this all +让我们,我要在这个视图控制器中 + +1495 +01:00:37,115 --> 01:00:38,948 +in this view controller right here. +做所有这些 + +1496 +01:00:38,950 --> 01:00:40,683 +I'm not gonna create a game view or +我不想创建一个游戏视图或 + +1497 +01:00:40,685 --> 01:00:43,485 +do all those things because we only have ten minutes left. +做所有这些东西,因为我们只剩10分钟了 + +1498 +01:00:43,487 --> 01:00:45,286 +Wanna be able to do this whole demo. +想要让这个例子可用 + +1499 +01:00:45,288 --> 01:00:47,488 +So I'm just going to put it all in the top level view of +我要把它们都放在我的视图控制器的 + +1500 +01:00:47,490 --> 01:00:49,090 +my view controller, +最顶层 + +1501 +01:00:49,091 --> 01:00:50,691 +which you would never do, you don't usually wanna draw +这是你们永不会做的,你们通常不在你们的 + +1502 +01:00:50,693 --> 01:00:53,060 +directly in the top level view of your view controller. +视图控制器的顶层绘制这些 + +1503 +01:00:53,062 --> 01:00:55,729 +The top level view of your view controller is for +你们视图控制器的顶层是给 + +1504 +01:00:55,731 --> 01:00:58,331 +subviews, okay, you put subviews in there. +子视图的,你们在那里放子视图 + +1505 +01:00:58,333 --> 01:01:01,968 +But I'm gonna draw straight in there, +但我要直接在这里绘制 + +1506 +01:01:01,970 --> 01:01:06,305 +my bouncing ball, just for expediency sake. +我的弹跳球,仅仅是权宜之计 + +1507 +01:01:07,441 --> 01:01:11,876 +So I need a bouncer, which is my bouncer behavior, 'kay, so +如果我需要一个 bouncer,也就是我的 bouncerBehavior + +1508 +01:01:11,878 --> 01:01:13,811 +that's just one of those things I just created, +这是我刚刚创建的其中一个东西 + +1509 +01:01:13,813 --> 01:01:15,813 +all right, that has the gravity and +它有重力 + +1510 +01:01:15,815 --> 01:01:17,264 +collision behaviors and +collisionBehaviors 和 + +1511 +01:01:17,265 --> 01:01:18,714 +all that stuff that I stole from drop it. +我从 dropIt 中偷来的所有东西 + +1512 +01:01:18,717 --> 01:01:21,317 +And of course, I need an animator. +当然,我需要一个 animator + +1513 +01:01:22,320 --> 01:01:24,687 +So I'm gonna create a UIDynamicAnimator. +我要创建一个 UIDynamicAnimator + +1514 +01:01:25,623 --> 01:01:27,656 +And do the same thing I did before which +和之前做的一样, + +1515 +01:01:27,658 --> 01:01:31,926 +is UIDynamicAnimator, referenceView. +是 UIDynamicAnimator,referenceView + +1516 +01:01:31,928 --> 01:01:33,461 +Self.view. + +1517 +01:01:33,463 --> 01:01:34,628 +Okay? Instead of game view into +不是在 self.view 中的 + +1518 +01:01:34,630 --> 01:01:36,747 +self.view. +gameView + +1519 +01:01:36,748 --> 01:01:38,865 +So I'm creating that lazy as we did before, so +我以 lazy 方式创建这个,和之前做的一样 + +1520 +01:01:38,867 --> 01:01:43,169 +I need to make this closure be executed to do this, okay? +为了这样我需要这个闭包被执行 + +1521 +01:01:43,171 --> 01:01:45,037 +It's the same as drop it. +这和 dropIt 一样 + +1522 +01:01:45,039 --> 01:01:46,638 +Oops, this is, must be colon. +这个,必须是冒号 + +1523 +01:01:47,741 --> 01:01:49,191 +All right? + +1524 +01:01:49,192 --> 01:01:50,642 +So now I've got my bouncer and animator, so +现在我有我的 bouncer 和 animator + +1525 +01:01:50,644 --> 01:01:52,810 +I'm just going to in viewDidLoad. +我要在 viewDidLoad 中 + +1526 +01:01:52,812 --> 01:02:00,017 +I'm just gonna say animator, addBehavior, the bouncer. +我输入 animator.addBehavior(bouncer) + +1527 +01:02:00,019 --> 01:02:03,053 +'Kay? So now I've got this going. +现在我有这个东西 + +1528 +01:02:03,055 --> 01:02:06,022 +Course, super.viewDidLoad, I just talked about that, +当然,super.viewDidLoad,我刚才说过的 + +1529 +01:02:06,024 --> 01:02:07,657 +so don't wanna do that. +不要这么做 + +1530 +01:02:07,659 --> 01:02:08,224 +All right? + +1531 +01:02:08,226 --> 01:02:08,991 +So there we go. +现在我们开始 + +1532 +01:02:08,993 --> 01:02:10,726 +So now we've got an animator. +我们有一个 animator + +1533 +01:02:10,728 --> 01:02:14,295 +Anything we add now to the bouncer is going to start +现在我们在 bouncer 中添加的任何东西都会被 + +1534 +01:02:14,297 --> 01:02:17,098 +being affected by the bouncer behavior. +bouncerBehavior 所影响 + +1535 +01:02:17,100 --> 01:02:18,833 +If you, which we mostly stole from DropIt. +如果你们,我们从 DropIt 偷的大部分代码 + +1536 +01:02:18,835 --> 01:02:20,534 +All right, so how many? +多少呢? + +1537 +01:02:20,536 --> 01:02:22,502 +Well, I'm gonna just add a block, +现在我只要添加一个方块 + +1538 +01:02:22,504 --> 01:02:26,006 +a little red block to my view which +一个小的红色方块到我的视图中 + +1539 +01:02:26,008 --> 01:02:29,609 +I'm gonna then be controlling with the accelerometer. +这个视图和加速计控制 + +1540 +01:02:29,611 --> 01:02:32,244 +So let's have a little function here called addBlock. +让我们写一个小的函数叫做 addBlock + +1541 +01:02:32,246 --> 01:02:35,147 +It's going to return a UIView. +它返回一个 UIView + +1542 +01:02:35,149 --> 01:02:38,483 +Okay, there's a block that I'm gonna add here, so +这是我要在这里添加的 block + +1543 +01:02:38,485 --> 01:02:43,087 +let's create a new UIView, and its frame. +让我们创建一个新的 UIView,还有它的 frame + +1544 +01:02:43,089 --> 01:02:44,422 +Let's start out. +让我们开始 + +1545 +01:02:44,424 --> 01:02:46,290 +Let's do CGRect. +让我们做 CGRect + +1546 +01:02:46,292 --> 01:02:50,560 +We'll have its origin be CGPoint.zeroPoint, +我们有它的原点 CGPoint.zeroPoint + +1547 +01:02:50,562 --> 01:02:52,995 +then I'll move it in the second to the right place. +一会我要把它移动到正确的地方 + +1548 +01:02:52,997 --> 01:02:54,964 +And we probably want a constant here for +这里我们可能需要一个方块 + +1549 +01:02:54,966 --> 01:02:56,065 +the block size. +大小的常量 + +1550 +01:02:56,067 --> 01:03:01,102 +So let's put a constant here, struct Constants. +这里我们放一个常量,结构常量 + +1551 +01:03:02,205 --> 01:03:05,139 +I really take the extra time to do this constants thing +我真的需要额外的时间来处理这个 constants + +1552 +01:03:05,141 --> 01:03:07,975 +because you really don't wanna have magic numbers spread +因为我们不想让魔术数字在你们的 + +1553 +01:03:07,977 --> 01:03:09,576 +all out through all your code, okay? +代码中到处泛滥 + +1554 +01:03:09,578 --> 01:03:13,146 +You really wanna have your constants put into structs or +你真的需要把你的常量放在结构体或 + +1555 +01:03:13,148 --> 01:03:16,349 +grouped, or name space or something to get them so +组,或名字空间或管理它们的东西 + +1556 +01:03:16,351 --> 01:03:19,352 +that they're not scattered about your code. +这样它们不会分散在你们的代码中 + +1557 +01:03:19,354 --> 01:03:21,487 +Otherwise, people won't know what's really going on. +否则,人们不知道发生了什么 + +1558 +01:03:21,489 --> 01:03:24,756 +So, I'm gonna let BlockSize equal CGSize. +我要让 BlockSize 等于 CGSize + +1559 +01:03:25,692 --> 01:03:27,692 +We'll just have block be 40 by 40. +我们有一个 40*40 的方块 + +1560 +01:03:27,694 --> 01:03:30,627 +That's a good starting size. +这是一个好的初始大小 + +1561 +01:03:30,629 --> 01:03:33,030 +We can see if we don't like it later. +我可以看一会我们是否喜欢它 + +1562 +01:03:33,032 --> 01:03:35,265 +So now, let's move the block to where we want, and +现在,让我们把方块移动到我们想要它的地方 + +1563 +01:03:35,267 --> 01:03:36,566 +I'm gonna start the block out +我想要在视图的中心 + +1564 +01:03:36,568 --> 01:03:37,967 +right in the center of the view. +开始这个方块 + +1565 +01:03:37,969 --> 01:03:43,338 +So that's just CGPoint, and, we'll say, +这个是 CGPoint,我们 + +1566 +01:03:43,340 --> 01:03:49,110 +view.bounds.midX and view.bounds.midY. +view.bounds.midX 和 view.bounds.midY + +1567 +01:03:49,112 --> 01:03:52,980 +Again, notice that I'm using the bounds, not the frame. +再次,注意我正在使用 bounds,不是 frame + +1568 +01:03:52,982 --> 01:03:54,381 +The frame would be my views, +frame 会是我的视图 + +1569 +01:03:54,383 --> 01:03:56,683 +super view which like the window or something. +父视图比如 window 或者其它 + +1570 +01:03:56,685 --> 01:03:58,951 +So I'd only use frame there. +这里我只使用 frame + +1571 +01:03:58,953 --> 01:04:02,421 +Then we'll add that SubView(block), and +然后我们要添加这个 subView(block) + +1572 +01:04:02,423 --> 01:04:05,124 +we'll return the block. +我们将返回 block + +1573 +01:04:05,126 --> 01:04:08,193 +Okay, so now I have a way of basically +现在我们已经基本上添加方块 + +1574 +01:04:08,195 --> 01:04:12,597 +adding a block to the center of my view, okay? +到我的视图中心 + +1575 +01:04:12,599 --> 01:04:17,301 +So now that I have that, let's go ahead and add the block. +现在我有这个,让我们继续,添加方块 + +1576 +01:04:17,303 --> 01:04:19,036 +And I'm gonna do that, +我要做这个 + +1577 +01:04:19,037 --> 01:04:20,770 +I'm gonna add that block in my viewDidAppear. +我要在我的 viewDidAppear 添加这个方块 + +1578 +01:04:20,773 --> 01:04:23,673 +So as soon as my view appears if the block has not +一旦我的视图出现了,如果方块还没被加入 + +1579 +01:04:23,675 --> 01:04:25,108 +been added, I'm gonna add it. +我将添加它 + +1580 +01:04:25,110 --> 01:04:26,275 +Okay, and that's a common thing, +这是常有的事 + +1581 +01:04:26,277 --> 01:04:29,211 +again, to wait until view did appear to do something, +再次,等到视图出现再做一些事情 + +1582 +01:04:29,213 --> 01:04:32,614 +because you don't want to waste your time doing it until +因为你不想浪费时间,知道 + +1583 +01:04:32,616 --> 01:04:33,848 +it's actually gonna be on screen. +它真的在屏幕上出现了 + +1584 +01:04:33,850 --> 01:04:35,983 +So in view did appear, here. +在 viewDidAppear,这里 + +1585 +01:04:35,985 --> 01:04:38,519 +I'm gonna call super dot view did appear. +我要调用 super.viewDidAppear + +1586 +01:04:40,489 --> 01:04:43,790 +And I need a little variable for my block. +我需要给我的 block 加一个小的变量 + +1587 +01:04:43,792 --> 01:04:47,160 +I'm going to make it be red, so +我要让它为红色 + +1588 +01:04:47,162 --> 01:04:49,095 +I'm going to call it red block. +我要称它为 redBlock + +1589 +01:04:51,198 --> 01:04:54,800 +UIView, okay it's an optional, it starts out nil. +UIView,它是可选类型,开始它为 nil + +1590 +01:04:54,802 --> 01:04:59,937 +And if my red block has not set yet, so if it equals nil. +我的 redBlock 还没被赋值,所以如果它等于 nil + +1591 +01:04:59,939 --> 01:05:01,605 +Let em create my red block just by +让我们创建我的 redBlock + +1592 +01:05:01,607 --> 01:05:03,507 +saying red block equals ab block, +让 redBlock 等于 addBlock + +1593 +01:05:03,509 --> 01:05:05,876 +which is that function I just called, so now I created it. +就是我刚才调用的函数,现在我创建它了 + +1594 +01:05:05,878 --> 01:05:09,679 +We're gonna make my red block be red by Just setting it to +我们要让我的 redBlock 为红色的,让它的 + +1595 +01:05:09,681 --> 01:05:14,150 +background color equal to UI color red color. +backgroundColor 等于 UIColor.redColor() + +1596 +01:05:14,152 --> 01:05:15,451 +So I created this red block. +我创建了这个 redBlock + +1597 +01:05:18,555 --> 01:05:20,655 +I'm gonna add Red Block to the bouncer. +我要添加 redBlock 到 bouncer + +1598 +01:05:22,825 --> 01:05:24,324 +And it should start bouncing. +它应该开始弹跳 + +1599 +01:05:24,326 --> 01:05:25,859 +So let's go take a look. +让我们看下 + +1600 +01:05:25,861 --> 01:05:27,694 +This is all we really need to do. +这是我们要做的全部了 + +1601 +01:05:27,696 --> 01:05:32,932 +We need to, exclamation point there, okay? +这里需要感叹号 + +1602 +01:05:32,934 --> 01:05:35,267 +So, that should be all that is necessary to make this thing +这是让这个发生的全部需要做的事情 + +1603 +01:05:35,269 --> 01:05:37,302 +happen, so let's go ahead and run this, all right? +让我们继续,运行这个,对吧? + +1604 +01:05:37,304 --> 01:05:39,021 +Just in time, there's Bouncer. +很及时,这是 Bouncer + +1605 +01:05:39,022 --> 01:05:40,739 +And sure enough, bouncer is bouncing. +非常确定,bouncer 在弹跳 + +1606 +01:05:40,741 --> 01:05:44,108 +Okay, now, it's bouncing exactly like drop it, +现在,它弹跳得完全像丢下它一样 + +1607 +01:05:44,110 --> 01:05:46,644 +because I stole drop it's behavior out of drop it, +因为我偷了 DropIt 中的丢下它的 behavior 代码 + +1608 +01:05:46,646 --> 01:05:48,112 +and so it's just like that. +所以这就像扔掉它一样 + +1609 +01:05:48,114 --> 01:05:51,014 +Now, if I move the phone, I pick the phone up here, and +如果我移动手机,这里我拿起手机 + +1610 +01:05:51,016 --> 01:05:52,816 +I'm moving it around, nothing happens. +我四处移动它,什么也没有发生 + +1611 +01:05:52,818 --> 01:05:54,017 +It doesn't do anything, right, +它什么也没做 + +1612 +01:05:54,019 --> 01:05:57,153 +because gravity is just set to be down at the bottom of +因为重力被设置为屏幕底部向下 + +1613 +01:05:57,155 --> 01:05:59,455 +the screen which is the default for gravity behavior. +这是默认的重力行为 + +1614 +01:05:59,457 --> 01:06:02,324 +So what we want to do here is link the acceleration of +我们需要的是,把设备的加速度,加速计 + +1615 +01:06:02,326 --> 01:06:06,728 +the device, the accelerometer to the gravity, okay? +和重力关联 + +1616 +01:06:06,730 --> 01:06:08,529 +So that when I tilt it this way, +这样当我这样倾斜它 + +1617 +01:06:08,531 --> 01:06:09,797 +this thing will slide down that way. +这个东西会像那样滑动 + +1618 +01:06:09,799 --> 01:06:11,665 +And if I tilt it this way, it'll slide over that way, and +如果我这样倾斜,它会那样滑动 + +1619 +01:06:11,667 --> 01:06:13,466 +I'll kind of, I can move it around that way. +我会那样,以那种方式移动它 + +1620 +01:06:13,468 --> 01:06:15,535 +All right, so how do we do that? +我们怎样做呢? + +1621 +01:06:15,537 --> 01:06:16,869 +It's quite simple, actually. +实际上,这非常简单 + +1622 +01:06:16,871 --> 01:06:19,304 +First thing we need is a motion manager. +首先,我们需要 motionManager + +1623 +01:06:19,306 --> 01:06:22,040 +And I told you that really wants to be a global thing +我告诉过你们,这个需要你们应用 + +1624 +01:06:22,042 --> 01:06:23,592 +in your app. +的全局东西 + +1625 +01:06:23,593 --> 01:06:25,143 +So I'm gonna put it in a global place, +我要把它放在全局的地方 + +1626 +01:06:25,145 --> 01:06:26,878 +which is my app delegate. +在我的 appDelegate 中 + +1627 +01:06:26,880 --> 01:06:29,613 +So I'm actually gonna go over to my app delegate and +实际上我要到我的 appDelegate,然后 + +1628 +01:06:29,615 --> 01:06:30,914 +get rid of all of this. +删掉所有这些 + +1629 +01:06:33,485 --> 01:06:35,435 +Okay? + +1630 +01:06:35,436 --> 01:06:37,386 +And I'm gonna put a struct in here which +我要在这里添加一个结构体 + +1631 +01:06:37,389 --> 01:06:41,657 +I'm gonna call Motion and I'm going to have a static in here +我称之为 Motion,我要在这里有一个 static + +1632 +01:06:41,659 --> 01:06:46,628 +which is the Manager equals CM Motion Manager. +manager 等于 CMMotionManager + +1633 +01:06:46,630 --> 01:06:47,762 +Now look, I'm trying to type, +现在看看,我尝试输入 + +1634 +01:06:47,764 --> 01:06:49,864 +how come Xcode's not helping me here? +为什么 Xcode 在这里没有给我提示? + +1635 +01:06:49,866 --> 01:06:52,933 +Well that's because the motion stuff is in a different +这是因为,motion 这个东西是一个不同的 + +1636 +01:06:52,935 --> 01:06:57,037 +framework that has to be imported, okay? +框架,需要被导入 + +1637 +01:06:57,039 --> 01:06:58,171 +So you have to import +所以你需要导入 + +1638 +01:06:58,173 --> 01:07:00,406 +core motion if you want to use any of that. +CoreMotion,如果你需要使用任何这些功能 + +1639 +01:07:00,408 --> 01:07:02,742 +As soon as you do that, +一旦你导入了 + +1640 +01:07:02,743 --> 01:07:05,077 +it's going to start escape completing here, all right? +它就开始在这里自动完成了 + +1641 +01:07:05,079 --> 01:07:08,080 +So I could put other things in this motion struct if I had, +我可以在这个 motion 中放其它东西,如果我有 + +1642 +01:07:08,082 --> 01:07:10,682 +maybe I wanted the rate at which I'm asking for +也许我想要让这个速度为全局的, + +1643 +01:07:10,684 --> 01:07:12,350 +these things to be global. +我请求这些东西的速度 + +1644 +01:07:12,351 --> 01:07:14,017 +Maybe I'll put that as a constant in here as well. +也许这里我需要一个常量 + +1645 +01:07:15,054 --> 01:07:16,520 +But here I'm just gonna have the manager. +但这里我只是有一个 manager + +1646 +01:07:16,522 --> 01:07:19,890 +So everybody in my app who's gonna use motion +所以在我的应用中的每个想要使用 motion 的人 + +1647 +01:07:19,892 --> 01:07:23,660 +needs to ask the app delegate for this motion manager. +需要向 appDelegate 请求这个 motionManager + +1648 +01:07:23,662 --> 01:07:26,929 +And that way they'll all be using the same one, okay? +这样,他们就会使用同一个 + +1649 +01:07:26,931 --> 01:07:29,498 +Now I could have put this struct actually outside of +现在我可以把这个结构体放在 + +1650 +01:07:29,500 --> 01:07:32,835 +the app delegate and just said motion.manager and +appDelegate 的外部,然后让 motion.manager + +1651 +01:07:32,837 --> 01:07:34,620 +had that be it. +等于它 + +1652 +01:07:34,621 --> 01:07:36,404 +But here I actually want to kind of explicitly make it +但这里,实际上我想明确的说清楚 + +1653 +01:07:36,407 --> 01:07:38,606 +clear that when you are in this app. +当你们在这个应用中 + +1654 +01:07:38,608 --> 01:07:42,210 +This is where this app gets its motion manager, 'kay? +这是这个应用获取它的 motionManager 的地方 + +1655 +01:07:42,212 --> 01:07:44,011 +And that might seem non-object-oriented, +这个看起来可能不那么面向对象 + +1656 +01:07:44,013 --> 01:07:47,281 +except that for again, this is a global resource. +除了这个,这个是全局的资源 + +1657 +01:07:47,283 --> 01:07:50,784 +We want to explicitly be sharing it, okay? +我想要明确的分享这个资源 + +1658 +01:07:50,786 --> 01:07:52,652 +So, that's why I put it in my AppDelegate. +这是为什么我把它放在我的 AppDelegate 中 + +1659 +01:07:53,755 --> 01:07:55,888 +So, now I can get it, here. +现在我可以获取它 + +1660 +01:07:55,890 --> 01:07:57,089 +I'm gonna say, +我要 + +1661 +01:07:57,091 --> 01:08:01,726 +let motionManager equal my AppDelegate.Motion.Manager. +let motionManger 等于我的 AppDelegate.Motion.Manager + +1662 +01:08:01,728 --> 01:08:04,328 +Notice I made it capital because it's essentially +注意我让它大写,因为它本质上 + +1663 +01:08:04,330 --> 01:08:05,162 +a constant. +是一个常数 + +1664 +01:08:06,098 --> 01:08:08,665 +Motion.Manager is essentially a constant. +Motion.Manager 本质是个常量 + +1665 +01:08:09,768 --> 01:08:11,934 +And so I'm going set the update in a roll. +现在我设置更新 + +1666 +01:08:11,936 --> 01:08:14,170 +Well first of all I have to always check to make sure +首先我需要检查,确保 + +1667 +01:08:14,172 --> 01:08:16,038 +I have an accelerometer, it might be working on +我有一个加速计,它可能在一个 + +1668 +01:08:16,040 --> 01:08:17,739 +a device without it so I'm going to say. +没有它的设备工作,我要让 + +1669 +01:08:17,741 --> 01:08:22,543 +Motion manager, accelerometer available, sometimes people +motionManager,accelerometerAvailabel,有时人们 + +1670 +01:08:22,545 --> 01:08:26,013 +escape complete and they end up putting here active and +通过自动完成,他们把 activie 放在这里 + +1671 +01:08:26,015 --> 01:08:27,581 +they're like, why doesn't this work? +然后他们会很奇怪,为什么这不工作了 + +1672 +01:08:27,583 --> 01:08:30,684 +Okay, active is whether it's actively reporting +activie 是它是否积极报告 + +1673 +01:08:30,686 --> 01:08:32,919 +the accelerometer. +加速计 + +1674 +01:08:32,921 --> 01:08:34,987 +Available is whether the hardware is actually +Available 是这个硬件是否真的可用 + +1675 +01:08:34,989 --> 01:08:36,255 +available, so be careful there. +这里要小心 + +1676 +01:08:38,426 --> 01:08:41,159 +So if it's available then I'm just going to +如果它可用,然后我要开始 + +1677 +01:08:41,161 --> 01:08:43,261 +start getting updates. +获取更新 + +1678 +01:08:43,262 --> 01:08:45,362 +So again I'm gonna go wide here, motionManager, +再次,我要把这个变宽,motionmanager + +1679 +01:08:45,365 --> 01:08:49,433 +startAccelerometerUpdatesToQu- eue, which is right here, +startAccelerometerUpdatesToQueue,这里 + +1680 +01:08:49,435 --> 01:08:50,801 +this one, okay. +这个 + +1681 +01:08:50,803 --> 01:08:53,937 +I have to specify what queue I want these updates to come on, +我要明确我想要这些更新发生在哪个队列中 + +1682 +01:08:53,939 --> 01:08:57,407 +so I'm gonna do NSOperationQueue mainQueue. +所以我需要 NSOperationQueue.mainQueue() + +1683 +01:08:57,409 --> 01:09:02,478 +And, again, I'm gonna do the swift, put the last argument, +再次,我需要处理 swift,让最后一个参数 + +1684 +01:09:02,480 --> 01:09:06,848 +if it's a closure, outside of the parentheses thing. +如果它是一个闭包,在括号外面 + +1685 +01:09:06,850 --> 01:09:09,517 +I think there might be a way to do that with some clicking +我想可能有种点击魔法能做到这点 + +1686 +01:09:09,519 --> 01:09:11,152 +magic, but, anyway, here it is. +但,不管怎样,这就是了 + +1687 +01:09:11,154 --> 01:09:14,755 +Put that up here. +把这放在这里 + +1688 +01:09:14,757 --> 01:09:15,622 +Oh, I see why. +我明白为什么了 + +1689 +01:09:15,624 --> 01:09:17,023 +Okay. + +1690 +01:09:17,025 --> 01:09:20,026 +So here is the closure, right here. +这里是闭包 + +1691 +01:09:20,028 --> 01:09:24,563 +And the argument is just the data, so I'm going to call +这个参数是 data,我将要使用这个 + +1692 +01:09:24,565 --> 01:09:26,732 +that one data, that's the accelerometer data. +data,这个是加速计的数据 + +1693 +01:09:26,734 --> 01:09:30,335 +And the error, I'm going to ignore the errors here. +这个 error,这里我要忽略错误 + +1694 +01:09:30,337 --> 01:09:32,170 +Probably you shouldn't ignore the errors, but +你们可能不应该忽略这些错误,但 + +1695 +01:09:32,172 --> 01:09:35,139 +in bouncer if I get an error I'm just not going to be +在 bouncer 中,如果我获取了一个错误,我不会设置 + +1696 +01:09:35,141 --> 01:09:36,424 +setting the gravity. +重力 + +1697 +01:09:36,425 --> 01:09:37,708 +But there's nothing for me to do, so +这里我也没什么可以做的 + +1698 +01:09:37,710 --> 01:09:40,277 +I'm just going to ignore that error, okay? +所以我要忽略这个错误 + +1699 +01:09:40,279 --> 01:09:43,146 +And, in fact, can I undo that? +但实际上,我可以撤销吗 + +1700 +01:09:43,148 --> 01:09:46,315 +And say error while you're already inside, okay? +当你们已经在里面,这个错误 + +1701 +01:09:47,618 --> 01:09:50,019 +So here I am. +我在这里 + +1702 +01:09:50,020 --> 01:09:52,421 +Now I just need to set the bouncer behavior's gravity +我需要设置这个 bouncer 的行为重力 + +1703 +01:09:52,423 --> 01:09:56,691 +equal to this accelerometer data that I got right here, +等于这里我获取的这个加速计的数据 + +1704 +01:09:56,693 --> 01:09:58,793 +which turns out to be very, +这个会非常 + +1705 +01:09:58,795 --> 01:10:01,729 +very simple since they're both in G. +非常简单,因为它们都在 G 中 + +1706 +01:10:01,731 --> 01:10:05,332 +They're in the same units, so it's easy to do. +它们有相同的单位,很好处理 + +1707 +01:10:05,334 --> 01:10:08,902 +I'm just going to say bouncer.gravity, +我要让 bouncer.gravity + +1708 +01:10:08,904 --> 01:10:13,439 +which is my gravity behavior, .gravityDirection, +我的重力行为,.gravityDirection + +1709 +01:10:13,441 --> 01:10:15,874 +which is a CGVector. +这个是一个 CGVector + +1710 +01:10:15,876 --> 01:10:19,578 +Okay, so CGVector has doubles or floats. +CGVector 有 doubles 或 floats + +1711 +01:10:19,580 --> 01:10:23,248 +The data from cell rom is actually doubles, not floats. +这个从单元 rom 中来的数据实际是 doubles,不是 floats + +1712 +01:10:23,250 --> 01:10:26,551 +So I'm gonna set it as, this as double. +我要让它为 double + +1713 +01:10:26,553 --> 01:10:30,754 +And it's just the data's acceleration in x. +它只是这个 data.acceleration.x + +1714 +01:10:30,756 --> 01:10:34,224 +I'm gonna set that to be the gravity's acceleration, +我要让等于重力的加速度 + + +1715 +01:10:34,226 --> 01:10:35,792 +essentially, in x. +根本是,x 值 + +1716 +01:10:35,794 --> 01:10:39,929 +And same thing for y, except for y, since zero is up and +y 也是一样的,除了 y,因为向上是0,然后 + +1717 +01:10:39,931 --> 01:10:41,830 +I want positive. +我想要正值 + +1718 +01:10:42,800 --> 01:10:45,734 +Gravity be down, I'm going to say minus data +重力向下,我需要负的 data.acceleration.y + +1719 +01:10:45,736 --> 01:10:50,037 +acceleration y, okay? + +1720 +01:10:50,039 --> 01:10:51,572 +So that's it, +这就是了 + +1721 +01:10:51,574 --> 01:10:55,608 +I've just set the acceleration due to gravity in the animator +我已经根据设备的加速度动画 + +1722 +01:10:55,610 --> 01:10:59,679 +to the acceleration of the device, okay? +设置重力加速度 + +1723 +01:10:59,681 --> 01:11:01,980 +Now one very important thing to do is, +现在一个非常重要的事情是 + +1724 +01:11:01,982 --> 01:11:03,882 +I'm starting updates. +我要开始更新 + +1725 +01:11:03,884 --> 01:11:06,618 +Never put code in the start update unless you put some +永远不要在开始更新中放代码,除非你要 + +1726 +01:11:06,620 --> 01:11:09,454 +code somewhere to stop it, okay? +在某些地方停止它 + +1727 +01:11:09,456 --> 01:11:11,406 +And the place to stop here, +在这里停止 + +1728 +01:11:11,407 --> 01:11:13,357 +since I'm doing this in the view did appear the obvious +既然我在 viewDidAppear 中做这个 + +1729 +01:11:13,359 --> 01:11:17,127 +place to stop it is view will disappear, okay? +停止它的地方是在 viewWillDisappear + +1730 +01:11:18,330 --> 01:11:22,165 +So whenever this view goes off screen it will stop being +每次这个视图消失在屏幕上了,它将停止 + +1731 +01:11:22,167 --> 01:11:24,033 +the eyesore that I'm on which is exactly what I'm on. +我所在的碍眼的东西 + +1732 +01:11:24,035 --> 01:11:27,620 +So here I just say. +这里我只是表示 + +1733 +01:11:27,621 --> 01:11:31,206 +AppDelegate.Motion.Manager.st- opAccelerometerUpdates. +AppDelegate.Motion.Manager.stopAccelerometerUpdates + +1734 +01:11:31,208 --> 01:11:33,408 +And if it comes back on screen, +如果它返回在屏幕上了 + +1735 +01:11:33,410 --> 01:11:37,445 +they'll start up again because it's view to appear, okay? +它们就又开始了,因为这个视图出现了 + +1736 +01:11:37,447 --> 01:11:40,281 +So if I had like a settings tab and I was going back and +如果我有一个设置选项卡,我来回出现 + +1737 +01:11:40,283 --> 01:11:41,315 +forth, it would turn it on and +它将打开和关闭它 + +1738 +01:11:41,317 --> 01:11:45,185 +off as we went back and forth, okay? +因为我反复出现和消失 + +1739 +01:11:45,187 --> 01:11:48,154 +So, see how this works. +看看这是如何工作的 + +1740 +01:11:53,194 --> 01:11:55,961 +All right, here's our bouncer, okay? +这是我们的 bouncer + +1741 +01:11:55,963 --> 01:11:59,531 +And see how if I tilt it up, it goes this way. +如果我向上倾斜它会怎样,它会以这种方式跳动 + +1742 +01:11:59,533 --> 01:12:02,066 +And, now, I'm tilting it down, it's going down. +现在,我向下倾斜它,它会向下 + +1743 +01:12:03,369 --> 01:12:06,670 +Right, left, right? +向左,向右? + +1744 +01:12:08,106 --> 01:12:11,140 +And that can even kinda use it to get it going faster and +通过加速度甚至可以让他们 + +1745 +01:12:11,142 --> 01:12:13,242 +faster by using the acceleration. +动的越来越快 + +1746 +01:12:17,814 --> 01:12:19,731 +Okay? + +1747 +01:12:19,732 --> 01:12:21,649 +So you could imagine, I think we might even have made it +如果你们可以想象,我想我们甚至可以 + +1748 +01:12:21,651 --> 01:12:25,019 +extra credit, make it make your paddle in Breakout. +给它额外的学分,让它突破你们的桨 + +1749 +01:12:25,021 --> 01:12:27,454 +Be accelerometer based, right? +基于加速计 + +1750 +01:12:27,456 --> 01:12:28,722 +I get the paddle going there. +这里我有一个桨 + +1751 +01:12:28,724 --> 01:12:32,759 +Or make the bouncing ball in break out be effected by the. +或者让这个弹跳球被影响作出突破 + +1752 +01:12:32,761 --> 01:12:35,127 +I mean probably not this much effect. +我的意思是可能没这么多效果 + +1753 +01:12:35,129 --> 01:12:37,730 +You know, full gravitational effect but somewhat. +你们知道的,全重力影响,但有些 + +1754 +01:12:37,732 --> 01:12:41,333 +And if I set this down, although this table, I think, +如果我放下这个,平放在桌上,我想 + +1755 +01:12:41,335 --> 01:12:43,635 +is tilted a little this way, but. +它会这样一点点倾斜,但 + +1756 +01:12:43,637 --> 01:12:44,719 +See what happens? +看发生了什么? + +1757 +01:12:44,720 --> 01:12:45,802 +You can see it settling down. +你们可以看到它安定下来了 + +1758 +01:12:45,805 --> 01:12:48,105 +It's setting down a little because my elasticity is not +它慢慢下来了,因为我的 elasticity + +1759 +01:12:48,107 --> 01:12:50,674 +one, it's .85. +不是1,它是0.85 + +1760 +01:12:50,676 --> 01:12:56,279 +So all these bounce offs are not getting full effect. +但所有这个 bounce 关闭不会获取全部的效果 + +1761 +01:12:56,281 --> 01:12:59,215 +How do you slow this down, there, okay? +你们如何减慢这个下落? + +1762 +01:13:00,618 --> 01:13:02,250 +Any questions about that? +有问题吗? + +1763 +01:13:02,252 --> 01:13:03,818 +Now I was, I had on the agenda, +现在我得说下课程安排 + +1764 +01:13:03,820 --> 01:13:05,687 +which I obviously didn't even get close to talking to. +显然我不太想提这个 + +1765 +01:13:05,689 --> 01:13:07,521 +I knew it was going to be a time constraint, +但这里有时间限制 + +1766 +01:13:07,523 --> 01:13:09,056 +is persistence. +是持久性 + +1767 +01:13:09,058 --> 01:13:10,590 +I'm actually going to wait, and +实际上我将等 + +1768 +01:13:10,592 --> 01:13:12,425 +talk about that next Monday. +到下周一再谈这个 + +1769 +01:13:12,427 --> 01:13:15,094 +On Wednesday, we're going to do MapKits. +周三,我们要讲 MapKits + +1770 +01:13:15,096 --> 01:13:18,531 +This Friday, the section is on AppleWatch. +这周五,是 AppleWatch 部分 + +1771 +01:13:18,533 --> 01:13:21,066 +Okay, so that should be a fun one. +这会非常有趣 + +1772 +01:13:21,068 --> 01:13:23,001 +And then next week, in addition to persistence, +下周,除了持久性 + +1773 +01:13:23,003 --> 01:13:24,336 +I'll be doing modal segueway. +我要做 modal segueway + +1774 +01:13:24,338 --> 01:13:26,137 +Which you already pretty much know how to do because it's +这个你们已经非常清楚怎么做了,因为 + +1775 +01:13:26,139 --> 01:13:29,006 +just alerts for example, or just like mobile segueways. +它只是一个警告的例子,或就像手机 segueways + +1776 +01:13:29,008 --> 01:13:31,008 +But also talk about the camera and then, +但也会谈谈相机,然后 + +1777 +01:13:31,010 --> 01:13:32,409 +if we have time next week, we'll talk +如果我们下周有时间,我们将 + +1778 +01:13:32,411 --> 01:13:34,611 +about internationalization of your apps. +讲解你们应用的国际化 + +1779 +01:13:34,613 --> 01:13:37,880 +It's really important to open your app up to large markets. +这对于你们应用打开一个更大的市场是非常重要的 + +1780 +01:13:37,882 --> 01:13:39,148 +And then settings, +然后设置 + +1781 +01:13:39,150 --> 01:13:42,251 +how to do settings inside the settings app, et cetera. +在应用设置中如何做设置,等等 + +1782 +01:13:42,253 --> 01:13:43,552 +So we got a lot of stuff to talk about. +我们有很多东西需要讲解 + +1783 +01:13:43,554 --> 01:13:45,453 +I'll trying to get to as much of it as I can in +我将在最后的几次课程中 + +1784 +01:13:45,455 --> 01:13:47,755 +the last few lectures here, all right? +尽可能多的讲解这些 + +1785 +01:13:47,757 --> 01:13:49,423 +If you have questions, I'm here as usual. +如果你们有问题,我像往常一样在这里 + +1786 +01:13:51,060 --> 01:13:51,091 +>> For more, please visit us at standford.edu. +更多的,请访问 standford.edu diff --git a/subtitles/14. Core Location and MapKit.srt b/subtitles/14. Core Location and MapKit.srt new file mode 100644 index 0000000..2ddd9c5 --- /dev/null +++ b/subtitles/14. Core Location and MapKit.srt @@ -0,0 +1,8942 @@ + +1 +00:00:00,001 --> 00:00:04,602 +[MUSIC] +[音乐] + +2 +00:00:04,604 --> 00:00:06,971 +Stanford University. +斯坦福大学 + + +3 +00:00:13,579 --> 00:00:16,080 +>> Okay, well, + + +4 +00:00:16,081 --> 00:00:18,582 +welcome to lecture number 14 of Stanford CS193p. +欢迎来到斯坦福大学 CS193P 第14课。 + +5 +00:00:18,584 --> 00:00:23,252 +It's winter of 2015 and today we're gonna talk +2015冬季学期,今天我们要讨论手机 + +6 +00:00:23,254 --> 00:00:26,589 +about how your phone can find out where it is, +定位的问题, + +7 +00:00:26,591 --> 00:00:30,325 +where it is in the world or where it is on the planet. +手机如何得知在这个星球上的位置。 + +8 +00:00:30,327 --> 00:00:33,095 +And there's really two parts to that: Core Location which +这个技术由两部分组成:CoreLocation框架和 + +9 +00:00:33,097 --> 00:00:34,029 +is one framework and + + +10 +00:00:34,031 --> 00:00:35,963 +then MapKit which is another framework. +MapKit框架。 + +11 +00:00:35,965 --> 00:00:39,100 +And so Core Location is the kind of the guts of it, +CoreLocation是这个技术的底层,是一个没有UI部分 + +12 +00:00:39,102 --> 00:00:42,870 +the non-UI underlying part of it and then MapKit is the user +的框架,而MapKit是UI层面的框架, + +13 +00:00:42,872 --> 00:00:45,806 +interface, how we're gonna present. +用于把地图上的信息 + +14 +00:00:45,808 --> 00:00:49,476 +This information about where we are on a map to the user. +展现给用户。 + +15 +00:00:49,478 --> 00:00:52,111 +And so I'm gonna try and blast through these slides as +我会尽快讲完课件,之后我们会一起 + +16 +00:00:52,113 --> 00:00:54,814 +quickly as I can so I can get to a demo. +做一个demo。 + +17 +00:00:54,816 --> 00:00:56,815 +Because you learn a lot from the demo, I think, +我觉得你们会从demo学到更多的东西, + +18 +00:00:56,817 --> 00:00:58,350 +seeing it in practice. +从实际操作中学到更多。 + +19 +00:00:58,352 --> 00:01:03,054 +And in my demo, I'm gonna show a map, obviously, and +在这个demo里,我们要展示一个地图,然后 + +20 +00:01:03,056 --> 00:01:06,357 +then I'm gonna put some waypoints on it, and we'll +在地图上放置一些路径点,然后我们会学到如何从地图界面 + +21 +00:01:06,359 --> 00:01:10,827 +learn how we can segue from a map to show more information. +跳转出去以看到更多的信息。 + +22 +00:01:10,829 --> 00:01:14,497 +And then if I have time, we will show how to do overlays, +如果还有时间的话,我们会做一些覆盖层, + +23 +00:01:14,499 --> 00:01:16,899 +which is something that sits on top of the map, and +实际上就是一些覆盖在地图上面的图层,当地图 + +24 +00:01:16,901 --> 00:01:18,434 +as the map zooms in and moves around, +缩放或者移动的时候, + +25 +00:01:18,436 --> 00:01:19,568 +the overlay stays with it. +覆盖层会跟着一起动。 + +26 +00:01:19,570 --> 00:01:22,437 +So it might be your route through traffic, or +比如沿着交通道路的路线,在我们的demo里 + +27 +00:01:22,439 --> 00:01:25,507 +in our case we're going to have a vacation, and +我们会计划我们的假期, + +28 +00:01:25,509 --> 00:01:28,576 +we're gonna say where we went on our vacation. +制定假期要去的地方。 + +29 +00:01:28,578 --> 00:01:30,011 +All right? + +30 +00:01:30,013 --> 00:01:32,246 +All right, so let's talk about Core Location, +好,下边我们来讲CoreLocation。 + +31 +00:01:32,248 --> 00:01:33,980 +this underlying part. +底层的部分。 + +32 +00:01:33,982 --> 00:01:36,516 +It's just a framework for managing your location and +这是一个管理你位置和方向 + +33 +00:01:36,518 --> 00:01:37,684 +your heading, okay? +的框架。 + +34 +00:01:37,686 --> 00:01:41,620 +What direction you're pointing and where you are. +你朝着哪个方向以及你在哪。 + +35 +00:01:41,622 --> 00:01:44,156 +And it has no user interface in Core Location, okay? +在CoreLocation里并没有UI的部分。 + +36 +00:01:44,158 --> 00:01:47,159 +This is all purely managing the location themselves. +只是单纯的管理位置的信息而已。 + +37 +00:01:47,161 --> 00:01:50,462 +And the basic object that represents a location is +用于代表位置的基本对象叫做 + +38 +00:01:50,464 --> 00:01:52,330 +called the CLLocation, right? +CLLocation。 + +39 +00:01:52,332 --> 00:01:53,898 +CL for Core Location. +CL就是CoreLocation的意思。 + +40 +00:01:53,900 --> 00:01:56,000 +And then location because it's the location. +叫location因为它代表一个位置。 + +41 +00:01:56,002 --> 00:01:58,235 +And it has the properties you would imagine. +它有你能想象到的所有属性,比如 + +42 +00:01:58,237 --> 00:02:01,438 +Coordinate, altitude, horizontal and +关于这个位置的坐标,高度, + +43 +00:02:01,440 --> 00:02:04,774 +vertical accuracy of the measurement of this location. +水平或者垂直的精度, + +44 +00:02:04,776 --> 00:02:07,143 +Time stamp, speed. +时间戳,速度 + +45 +00:02:07,145 --> 00:02:08,544 +Course, where you're headed. +当然,还有你的方向。 + +46 +00:02:08,546 --> 00:02:09,544 +Those kind of things. +所有的这些东西。 + +47 +00:02:11,148 --> 00:02:14,515 +And the main thing about the location, of course, +当然对于位置来说最重要的 + +48 +00:02:14,517 --> 00:02:16,317 +is a latitude and longitude. +属性就是经纬度。 + +49 +00:02:16,319 --> 00:02:18,018 +And it gives you a latitude and longitude. +它会给你一个经纬度信息。 + +50 +00:02:18,020 --> 00:02:19,853 +But you notice, +但是要注意, + +51 +00:02:19,854 --> 00:02:21,687 +I say, where, approximately, is this location? +这只是一个近似的信息。 + +52 +00:02:21,690 --> 00:02:23,523 +Because. + +53 +00:02:23,524 --> 00:02:25,357 +No location object is necessarily gonna be +因为目前并没有定位的设备可以告诉你现在 + +54 +00:02:25,360 --> 00:02:27,727 +right exactly where you are because we don't have any +所处的准确位置,所以 + +55 +00:02:27,729 --> 00:02:28,894 +location measuring + +56 +00:02:28,896 --> 00:02:31,363 +hardware that can tell you exactly where you are. +位置的对象不会是完全准确的。 + +57 +00:02:31,365 --> 00:02:33,965 +I mean GPS is pretty darn good, very close. +我的意思是说GPS非常好,已经很接近正确的位置了。 + +58 +00:02:33,967 --> 00:02:35,667 +But there are other ways which we're gonna talk about, +但是我们要讨论的是另外的方式, + +59 +00:02:35,669 --> 00:02:38,036 +about measuring where you are that are much less accurate. +用一个相对低的精确度去计算位置。 + +60 +00:02:38,038 --> 00:02:41,072 +So a CLLocationCoordinate2D. +这个属性CLLocationCoordinate2D, + +61 +00:02:41,074 --> 00:02:43,307 +2-D meaning it's on the ground, +2D意思是在地上的位置, + +62 +00:02:43,309 --> 00:02:44,641 +not including your altitude. +不包括高度。 + +63 +00:02:45,944 --> 00:02:48,344 +Is an approximate latitude and longitude. +是一个近似的经纬度。 + +64 +00:02:48,346 --> 00:02:50,112 +And we'll talk a little bit about that accuracy and +之后我们会说一点关于精确度以及 + +65 +00:02:50,114 --> 00:02:51,547 +how we know what it is. +如果获取精确度的问题。 + +66 +00:02:51,549 --> 00:02:58,186 +And then your altitude is a separate variable, altitude. +高度是另外一个变量,altitude。 + +67 +00:02:58,188 --> 00:03:01,155 +And so the accuracy +精确度 + +68 +00:03:01,157 --> 00:03:04,291 +is measured in both horizontal and vertical space, right, for +是用来同时衡量水平和垂直空间的, + +69 +00:03:04,293 --> 00:03:07,261 +altitude and for your horizontal position. +也就是水平的位置以及垂直的高度。 + +70 +00:03:07,263 --> 00:03:10,597 +And, it's not like your accuracy is a percent +精确度并不是一个百分比的数值或者类似 + +71 +00:03:10,599 --> 00:03:11,931 +accuracy, or something like that. +的东西。 + +72 +00:03:11,933 --> 00:03:15,902 +It's really just one of these key pre-defined terms up here. +它实际上是一组预定义好的信息。 + +73 +00:03:15,904 --> 00:03:19,372 +So, the most accurate is called best for navigation, +最高的精度叫做 BestForNavigation。 + +74 +00:03:19,374 --> 00:03:22,608 +and that's certainly gonna use GPS to find that, and +这个精度肯定需要使用GPS,它的意思是 + +75 +00:03:22,610 --> 00:03:25,010 +that's the kind of thing where you're driving in your car, +当你开车用导航的时候,你肯定 + +76 +00:03:25,012 --> 00:03:26,211 +and you don't wanna miss a turn. +不希望错过转弯的路口。 + +77 +00:03:26,213 --> 00:03:30,147 +So that's. Really accurate location +所以,需要非常高的精度 + +78 +00:03:30,149 --> 00:03:31,248 +finding. + +79 +00:03:31,250 --> 00:03:32,582 +To get this, +去达到这个目的。 + +80 +00:03:32,584 --> 00:03:34,818 +you're gonna wanna have your phone plugged in, okay? +在这个精度,你需要让你的手机保持充电状态。 + +81 +00:03:34,820 --> 00:03:38,154 +Because more accuracy takes more power. +因为精度越高越费电。 + +82 +00:03:38,156 --> 00:03:39,655 +Talk about that in a second. +一会儿会详细说这个。 + +83 +00:03:39,657 --> 00:03:40,956 +Then there's just best, +这个最高的精度 + +84 +00:03:40,958 --> 00:03:42,657 +which is kind of probably gonna use GPS. +要用到GPS, + +85 +00:03:42,659 --> 00:03:44,826 +And then there's nearest ten meters. +这个10米附近的精度。 + +86 +00:03:44,828 --> 00:03:47,595 +Probably a mix, of maybe GPS and WiFi. +可能是GPS和wifi混用的, + +87 +00:03:47,597 --> 00:03:49,497 +Then there is hundred meters is probably mostly +这个百米附近的精度可能只用到 + +88 +00:03:49,499 --> 00:03:51,131 +gonna be using WiFi. +wifi。 + +89 +00:03:51,133 --> 00:03:54,101 +Then there's kilometers and three kilometers, that's gonna +一公里以内和三公里以内的精度,会用到 + +90 +00:03:54,103 --> 00:03:57,470 +be using cell towers to find out where you are. +基站来确定你的位置。 + +91 +00:03:57,472 --> 00:03:59,639 +Okay? This is kind of the groups or +明白了吗?精度实际上是一个 + +92 +00:03:59,641 --> 00:04:02,341 +the categories of accuracy. +预定义好的组。 + +93 +00:04:02,343 --> 00:04:05,144 +More accuracy means more power. +更高的精度就更费电。 + +94 +00:04:05,146 --> 00:04:09,514 +Because the communication with cell towers is pretty low. +跟基站通讯耗电非常低, + +95 +00:04:09,516 --> 00:04:11,382 +Your phone's doing it all the time anyway. +手机会一直跟基站通讯。 + +96 +00:04:11,384 --> 00:04:13,617 +And so it's a pretty low power activity. +这是一个耗电很低的活动。 + +97 +00:04:13,619 --> 00:04:15,586 +WiFi is pretty good. +wifi就有点费电了, + +98 +00:04:15,588 --> 00:04:18,221 +It's got a big database of all the WiFi nodes or +全世界所有的wifi节点以及wifi区域 + +99 +00:04:18,223 --> 00:04:21,057 +many of the WiFi zones in the world. +是一个非常大的数据库。 + +100 +00:04:21,059 --> 00:04:23,726 +And so if it sees you close to some of them, +如果你靠近它们, + +101 +00:04:23,728 --> 00:04:27,697 +it can triangulate your location pretty accurately. +它们可以通过三角定位以一个很高的精度确定你的位置。 + +102 +00:04:27,699 --> 00:04:29,331 +Like at a place like Stanford where there's +比如在斯坦福大学这个有无数个wifi + +103 +00:04:29,333 --> 00:04:31,767 +just billions of WiFi nodes everywhere. +节点的地方。 + +104 +00:04:31,769 --> 00:04:35,036 +It's pretty darn accurate, and kind of pretty low power, +地位会非常准确而且不是很耗电, + +105 +00:04:35,038 --> 00:04:36,471 +not super low power. +但也不是最省电的。 + +106 +00:04:36,473 --> 00:04:37,738 +And then there's GPS. +最后是GPS, + +107 +00:04:37,740 --> 00:04:39,707 +Obviously super accurate. +这个是最精确的。 + +108 +00:04:39,709 --> 00:04:41,475 +It doesn't work everywhere. +但不是在哪都能用。 + +109 +00:04:41,477 --> 00:04:45,278 +If you're underground or in a well-shielded building, +如果你在地下或者在屏蔽非常好的建筑物里, + +110 +00:04:45,280 --> 00:04:47,413 +you're not gonna get GPS, of course. +GPS就不能用了。 + +111 +00:04:47,415 --> 00:04:48,881 +But where it does work, +但是在能用的时候, + +112 +00:04:48,883 --> 00:04:51,483 +it's very accurate, but it uses a lot of power. +定位会非常精确,同时也会非常费电。 + +113 +00:04:51,485 --> 00:04:53,185 +Okay, it's gonna drain your battery. +电池很快就会被耗干。 + +114 +00:04:53,187 --> 00:04:55,587 +And when you talk about any kind of location app, +当我们谈到关于位置的app时, + +115 +00:04:55,589 --> 00:04:57,288 +you're talking about the battery, okay? +实际上我们在谈的是电池。 + +116 +00:04:57,290 --> 00:05:00,324 +Because if your app does a lot of location stuff and +如果你的app做了跟多定位的事儿,但是你没仔细的 + +117 +00:05:00,326 --> 00:05:01,658 +you're not careful with it, +设计的话, + +118 +00:05:01,660 --> 00:05:03,360 +people are gonna run your app for a few weeks and +用户很可能在用了你的app几周以后说: + +119 +00:05:03,362 --> 00:05:05,161 +they're gonna say, oh, I had to delete that app. +”哦,我得删了这个app,电池用的 + +120 +00:05:05,163 --> 00:05:07,864 +My battery would just run down right away. +太快了。“ + +121 +00:05:07,866 --> 00:05:09,616 +Okay? + +122 +00:05:09,617 --> 00:05:11,367 +So you have to be careful with doing location +所以做定位功能的时候要特别小心, + +123 +00:05:11,369 --> 00:05:13,235 +vis-a-vis power. +能耗的问题。 + +124 +00:05:13,237 --> 00:05:16,405 +And we'll talk a little bit about that down the road here. +我们一会儿会再讲一些这个问题。 + +125 +00:05:16,407 --> 00:05:19,341 +So speed, the speed is your instantaneous speed. +下面说速度,速度指的是你的瞬时速度。 + +126 +00:05:19,343 --> 00:05:20,509 +It's not like your average +并不是在一段时间内 + +127 +00:05:20,510 --> 00:05:21,676 +speed over the last however long. +你的平均速度。 + +128 +00:05:21,678 --> 00:05:23,711 +It's like you know, + + +129 +00:05:23,712 --> 00:05:25,745 +it's between last measurements it's telling you your speed. +大意就是在两次取值之间的速度。 + +130 +00:05:25,748 --> 00:05:27,881 +So it's kind of good for driving, +在开车的时候会 + +131 +00:05:27,883 --> 00:05:29,816 +like you're driving around, it wouldn't be that great for +非常有用,但是在走路的时候就 + +132 +00:05:29,818 --> 00:05:32,018 +walking around, that kind of thing. +不是那么有意义了。 + +133 +00:05:32,020 --> 00:05:33,453 +Course is just going to be. +course代表方向, + +134 +00:05:33,455 --> 00:05:35,355 +It's probably. + +135 +00:05:35,356 --> 00:05:37,256 +I think you can use some magnetometers, so +这可能是磁力计的术语,来表示 + +136 +00:05:37,258 --> 00:05:38,957 +it's actually kind of an idea of where you're headed. +你面朝哪个方向。 + +137 +00:05:38,959 --> 00:05:41,259 +But it's also mostly just looking at your track. +但是可能它更倾向于你运动轨迹的方向。 + +138 +00:05:41,261 --> 00:05:42,627 +Right? Measuring your locations and +测量你的位置然后判断 + +139 +00:05:42,629 --> 00:05:45,163 +seeing, well, you're generally headed in this direction. +你前进的大致方向。 + +140 +00:05:45,165 --> 00:05:46,664 +And then time stamps, obviously,. +下边是时间戳, + +141 +00:05:46,666 --> 00:05:49,500 +Time stamps are more important than you think because +时间戳这个属性比你想象的要重要因为当你 + +142 +00:05:49,502 --> 00:05:51,385 +as you ask for +想要得到你的位置 + +143 +00:05:51,386 --> 00:05:53,269 +location you're not gonna get location instantaneously. +的时候,这个操作不是瞬间完成的。 + +144 +00:05:53,272 --> 00:05:54,504 +Okay, it might take a little delay. +可能会有一些延迟。 + +145 +00:05:54,506 --> 00:05:57,473 +You walk under something that blocks you from GPS and +你可能会走到一些东西的下边阻塞了GPS,过一会儿才会开始获取 + +146 +00:05:57,475 --> 00:05:59,675 +it comes back, or you walk between WiFi nodes. +位置,或者你穿行于不同的wifi节点, + +147 +00:05:59,677 --> 00:06:01,810 +It picked up one, drops another. +系统识别出一个,又弃掉了另一个。 + +148 +00:06:01,812 --> 00:06:06,181 +So these locations can come in not in a nice even stream. +所以获取位置可能不是一个实时的操作。 + +149 +00:06:06,183 --> 00:06:08,449 +So you sometimes have to look at the time stamp to see well +你可能需要查看时间戳检查这个位置信息是什么时候获取的, + +150 +00:06:08,451 --> 00:06:11,318 +how old is this location, is this you know, a minute ago? +一分钟以前还是 + +151 +00:06:11,320 --> 00:06:12,720 +Or is this just like a second ago? +一秒之前? + +152 +00:06:14,023 --> 00:06:17,524 +So how do you get one of these CLLocation objects? +那么我们如何得到CLLocation对象呢? + +153 +00:06:17,526 --> 00:06:20,626 +You get them from a CLLocationManager, okay? +通过 CLLocationManager。 + +154 +00:06:20,628 --> 00:06:23,228 +Now a CLLocationManager kind of like. +CLLocationManager 就好像是, + +155 +00:06:24,865 --> 00:06:27,399 +Core motions manager in a way. +在某种程度上类似CoreMotion manager。 + +156 +00:06:27,401 --> 00:06:32,103 +You know, there's really only one GPS in the system. +系统里只有一个GPS, + +157 +00:06:32,105 --> 00:06:35,272 +But we don't usually do the same thing where we share this +但是我们不像CoreMotion那样之用一个 + +158 +00:06:35,274 --> 00:06:38,709 +one core motion manager. +manager。 + +159 +00:06:38,711 --> 00:06:42,278 +You can have different core location managers. +我们可以用多个 CLLocationManager 。 + +160 +00:06:42,280 --> 00:06:44,914 +But there are things you're gonna set on it that are gonna +但是设置它的时候可能会改变 + +161 +00:06:44,916 --> 00:06:46,882 +effect a little bit about how the hardware works. +一点硬件的工作方式。 + +162 +00:06:46,884 --> 00:06:49,184 +And you'll see how that goes a little bit. +你会看到是怎么改变的。 + +163 +00:06:49,186 --> 00:06:51,319 +One thing that's cool about CoreLocationmanager +CLLocationManager 有一个很棒的功能就是它可以 + +164 +00:06:51,321 --> 00:06:53,221 +is you can simulate from Xcode. +在Xcode里模拟位置。 + +165 +00:06:53,223 --> 00:06:55,390 +If you go down to the bottom bar of Xcode there, +在Xcode下边的状态条这里, + +166 +00:06:55,392 --> 00:06:57,425 +you'll see there's like a little arrow thing. +有一个小箭头。 + +167 +00:06:57,427 --> 00:06:58,325 +And if you click on that, +点这个小箭头, + +168 +00:06:58,327 --> 00:07:02,929 +it gives you a menu of GPX entries. +会有一些GPX入口。 + +169 +00:07:02,931 --> 00:07:05,531 +GPX, the same kind of GPX that we're doing with tracks. +GPX就是我们在做轨迹的时候的GPX。 + +170 +00:07:06,601 --> 00:07:07,966 +Which are just locations on the planet and +是一些地球上的位置, + +171 +00:07:07,968 --> 00:07:10,035 +you pick one and +你选其中的一个 + +172 +00:07:10,036 --> 00:07:12,103 +it'll make your phone seem like it's in Mumbai and so +模拟你的手机在孟买, + +173 +00:07:12,106 --> 00:07:14,906 +you can see if your app works when it thinks it's in Mumbai. +所以你可以测试你的app是不是能正确的显示位置在孟买。 + +174 +00:07:14,908 --> 00:07:19,443 +So that's kind of a fun part of it. +这个功能挺有趣的。 + +175 +00:07:19,445 --> 00:07:22,279 +The CLLocationManager works a lot like the Core motion +CLLocationManager 运作方式非常像 CoreMotionManager。 + +176 +00:07:22,281 --> 00:07:23,647 +manager. + +177 +00:07:23,649 --> 00:07:25,682 +You check to see if the hardware exists first +先检查是不是有相应的硬件, + +178 +00:07:25,684 --> 00:07:27,250 +because not all phones have +因为不是所有的手机 + +179 +00:07:27,252 --> 00:07:30,052 +all kinds of updating that you would want. +都有定位的硬件。 + +180 +00:07:30,054 --> 00:07:32,254 +Then you're gonna create an instance and +然后就想往常一下创建一个实例并且设置 + +181 +00:07:32,256 --> 00:07:35,457 +set a delegate, usually, okay. +代理。 + +182 +00:07:35,459 --> 00:07:38,193 +Then you configure it to what you want, and +然后你就可以按需求设置它,然后 + +183 +00:07:38,195 --> 00:07:40,561 +then it's gonna start sending you delegate messages. +它就开始发送代理信息。 + +184 +00:07:40,563 --> 00:07:41,729 +So it's a little different than Core Motion. +有一点和CoreMotion不一样。 + +185 +00:07:41,731 --> 00:07:43,931 +You don't use a block-based thing. +没有block。 + +186 +00:07:43,933 --> 00:07:46,199 +You have a delegate, and it's gonna be just sending you +它只是通过代理给你发送 + +187 +00:07:46,201 --> 00:07:48,668 +delegate messages, saying, hey, here's some locations +代理信息,告诉你:嘿,给你这些从上次通讯到现在 + +188 +00:07:48,670 --> 00:07:50,436 +I've gathered since last I talked to you. +的位置信息 + +189 +00:07:50,438 --> 00:07:53,772 +And it is gonna send those to you in kind of a steady +它会通过一个稳定的流向你发送信息。 + +190 +00:07:53,774 --> 00:07:55,274 +stream. + +191 +00:07:55,275 --> 00:07:56,775 +Now, you want to monitor your location, but +如果你希望监控你的位置,有几种 + +192 +00:07:56,777 --> 00:08:00,278 +there's different ways to monitor your location. +不同的方式。 + +193 +00:08:00,280 --> 00:08:02,297 +There's, kind of, +首先是 + +194 +00:08:02,298 --> 00:08:04,315 +continual updates where, based on a certain accuracy like, +基于一个特定的精确度,提供持续的更新, + +195 +00:08:04,317 --> 00:08:07,251 +I want to know exactly where I am all the time, okay? +我希望一直得到我的精确位置。 + +196 +00:08:07,253 --> 00:08:09,086 +It'll be constantly looking at the GPS and +它会持续的通过GPS获取位置 + +197 +00:08:09,088 --> 00:08:10,187 +trying to get your location and +并且尽快 + +198 +00:08:10,189 --> 00:08:13,490 +sending them to you as fast as you can. +发送给你。 + +199 +00:08:13,492 --> 00:08:15,275 +Or you might say, well, +或者你只是希望我在 + +200 +00:08:15,276 --> 00:08:17,059 +I wanna know where I am within a kilometer. +一公里之内的大概位置。 + +201 +00:08:17,062 --> 00:08:19,195 +I just wanna have the general region I'm in. +只是希望知道我是不是在一个区域里。 + +202 +00:08:19,197 --> 00:08:21,296 +Well then, you know, as you switch cell towers or +然后它会切换到基站, + +203 +00:08:21,298 --> 00:08:23,331 +something like that, it might send you an update saying, oh, +并且通知你和之前你所处的 + +204 +00:08:23,333 --> 00:08:25,667 +you're a little different place than you were before. +位置不同。 + +205 +00:08:25,669 --> 00:08:27,969 +So, you set the accuracy you want and +也就是说,设置好精确度,它 + +206 +00:08:27,971 --> 00:08:29,103 +then it'll start giving you updates. +就是持续的更新。 + +207 +00:08:29,105 --> 00:08:30,738 +So, that's one way. +这是一种方式。 + +208 +00:08:30,740 --> 00:08:33,774 +There's also a really cool way to say, only tell me when +还有一种更酷的方式,只是在我的位置有 + +209 +00:08:33,776 --> 00:08:36,376 +a significant change in location happened. +显著的改变时通知我。 + +210 +00:08:36,378 --> 00:08:38,411 +And we'll talk about what significant means. +一会儿我们会说这个“显著”是什么意思。 + +211 +00:08:38,413 --> 00:08:40,112 +You can also set regions. +你还可以设置区域。 + +212 +00:08:40,114 --> 00:08:42,648 +Like, here's a circular area on the planet. +就是地球上的一个圆形。 + +213 +00:08:42,650 --> 00:08:44,349 +When I go into this area, or +当我走进这个圆形或者走出 + +214 +00:08:44,351 --> 00:08:46,584 +out of this area, send me an update. +的时候,发送给我一个更新。 + +215 +00:08:46,586 --> 00:08:48,353 +So, that's kind of cool. +这个是非常酷的。 + +216 +00:08:48,354 --> 00:08:50,121 +So, if you had an app that's, like, reminder app, and +如果你有一个类似提醒的app, + +217 +00:08:50,123 --> 00:08:52,223 +it was gonna remind you to pick up the dry cleaning. +它会提醒你取干洗的衣服。 + +218 +00:08:52,225 --> 00:08:54,091 +Well, if you drove through the circle where the, +当你开到干洗店附近的区域时, + +219 +00:08:54,093 --> 00:08:56,727 +around the dry cleaner, maybe it would give you an alert. +它就会给你一个提醒。 + +220 +00:08:56,729 --> 00:08:59,229 +Oh, don't forget to pick up the dry cleaning, okay? +别忘了取干洗的衣服。 + +221 +00:08:59,231 --> 00:09:00,863 +So, you can do that with regions. +你可以通过划定区域来实现这个功能。 + +222 +00:09:00,865 --> 00:09:04,767 +And then, you can also monitor your heading. +你也可以监控你的方向。 + +223 +00:09:04,769 --> 00:09:07,803 +Maybe just to make sure you're turned the right way if you're +可以用来确定走路的时候 + +224 +00:09:07,805 --> 00:09:09,738 +walking or something, I don't know. +是不是拐了正确的弯 + +225 +00:09:09,740 --> 00:09:16,477 +Okay, the part where you have to, is that better? +在获取硬件。。。。。现在声音好点了吗? + +226 +00:09:16,479 --> 00:09:19,380 +The part where you have to ask what hardware you have, +在获取硬件信息的时候, + +227 +00:09:19,382 --> 00:09:22,416 +there's a lot of class functions in CLLocationManager +有很多CLLocationManager的类方法要用到。 + +228 +00:09:22,418 --> 00:09:23,750 +that you're gonna use. + +229 +00:09:23,752 --> 00:09:25,485 +I'm not gonna go into all of them in detail. +我不会把它们都讲一遍。 + +230 +00:09:25,487 --> 00:09:28,755 +But, the various kinds of monitoring you'll wanna do, +这里会有不同的监控方式选择, + +231 +00:09:28,757 --> 00:09:31,290 +like, significant change monitoring, or +比如,显著位置变更监控或者 + +232 +00:09:31,292 --> 00:09:34,760 +region monitoring, or just location services in general. +地区监控,或者只是普通的位置服务。 + +233 +00:09:34,762 --> 00:09:37,496 +Because the user might be a little paranoid about your +用户可能对于你获取他们的位置信息 + +234 +00:09:37,498 --> 00:09:39,497 +getting their location. +不舒服。 + +235 +00:09:39,499 --> 00:09:40,765 +And so, they could turn that off. +所以他们可能会关掉这个服务。 + +236 +00:09:40,767 --> 00:09:42,933 +So, you have to call this, like thing, like, +你需要调用 locationServicesEnabled来查看 + +237 +00:09:42,935 --> 00:09:46,236 +locationServicesEnabled to find out, is it enabled? +位置服务是不是开启了。 + +238 +00:09:46,238 --> 00:09:48,038 +All right, can I even do it? +看我是不是允许获取位置。 + +239 +00:09:48,040 --> 00:09:50,674 +And, there's also an authorizationStatus, too. +还有这个authorizationStatus方法。 + +240 +00:09:50,676 --> 00:09:52,442 +Be careful of the authorizationStatus, +注意它的Restricted选项。 + +241 +00:09:52,444 --> 00:09:54,344 +Restricted. + +242 +00:09:54,345 --> 00:09:56,245 +Okay, Restricted basically means Denied but, it's denied +Restricted基本上等同于拒绝,它通过用户不能 + +243 +00:09:56,247 --> 00:09:59,214 +in a way where there's nothing the user can do about it. +改变的方式拒绝定位服务。 + +244 +00:09:59,216 --> 00:10:02,284 +So, either parental controls or blocking it, or +比如有上级的控制或者阻塞,又比如当你 + +245 +00:10:02,286 --> 00:10:03,551 +maybe you're in an enterprise, +在一个企业里, + +246 +00:10:03,553 --> 00:10:06,854 +a company that blocks it, okay, on your phone. +公司屏蔽了位置服务, + +247 +00:10:06,856 --> 00:10:07,922 +So, in that case, +在这种情况下, + +248 +00:10:07,924 --> 00:10:09,556 +you don't want to put up an alert that says, +你不希望弹出一个警告说, + +249 +00:10:09,558 --> 00:10:11,658 +you're blocking me from getting location, +“你不允许我获取位置,请开启服务“ + +250 +00:10:11,660 --> 00:10:13,059 +please enable it, because they can't, +因为他们做不到, + +251 +00:10:13,061 --> 00:10:16,029 +there's nothing they can do, that's different than Denied. +他们什么都做不了,这就是跟拒绝服务的区别。 + +252 +00:10:16,031 --> 00:10:17,797 +Okay? And that's true, +所以, + +253 +00:10:17,798 --> 00:10:19,564 +not just in location services but in general, watch out for +不只是位置服务,大部分的服务都要注意 + +254 +00:10:19,567 --> 00:10:22,968 +the authorization status of Restricted versus Denied. +Restricted 和 Denied的区别。 + +255 +00:10:25,272 --> 00:10:28,840 +So, to get the information, you can just ask it, okay? +我们发出请求之后就可以获取信息。 + +256 +00:10:28,842 --> 00:10:31,776 +What's my current, to the best of your knowledge, +我目前的位置信息是 + +257 +00:10:31,778 --> 00:10:33,711 +information about my location? +什么样的? + +258 +00:10:33,713 --> 00:10:35,345 +So it'll give you a CL location. +它会返回一个CLLocation。 + +259 +00:10:35,347 --> 00:10:36,579 +It's like, this is where you are. +表示你所处的位置。 + +260 +00:10:36,581 --> 00:10:38,147 +And it'll be time stamped, you can check it, +是带有时间戳的。 + +261 +00:10:38,149 --> 00:10:40,716 +things like that. + +262 +00:10:40,717 --> 00:10:43,284 +But, before we can do any of this, get any information out +但是在我们从CLLocationManager获取信息之前, + +263 +00:10:43,287 --> 00:10:47,256 +of the locationManager, we have to get authorization from +我们需要得到系统,实际上是 + +264 +00:10:47,258 --> 00:10:49,958 +the system, really from the user to do that. +用户的授权。 + +265 +00:10:49,960 --> 00:10:52,594 +And, you can do that in one or two different ways. +你可以通过两种方式获取授权。 + +266 +00:10:52,596 --> 00:10:53,761 +One, is you can +第一种是 + +267 +00:10:53,763 --> 00:10:57,465 +request authorization to only access the location info +仅在你的app是当前活动的app时候启动 + +268 +00:10:57,467 --> 00:10:59,900 +while your application is the active app, that's +定位服务,这就是 + +269 +00:10:59,902 --> 00:11:02,302 +requestWhenInUseAuthorization(). +requestWhenInUseAuthorization()方法。 + +270 +00:11:02,304 --> 00:11:05,305 +Or you can request to be able to access the user location +或者你可以申请在任何时候都获取位置, + +271 +00:11:05,307 --> 00:11:07,807 +at anytime, even if you're running in the background. +即使你的app在后台的时候。 + +272 +00:11:07,809 --> 00:11:10,976 +If you're using some of the significant change monitoring +当你使用显著位置变更监控的时候, + + +273 +00:11:10,978 --> 00:11:14,346 +that we're gonna talk about in a few slides, +我们后边的幻灯片会讲这个。 + +274 +00:11:14,348 --> 00:11:16,848 +then you'll need this kind of authorization. +这时就需要这种授权。 + +275 +00:11:16,850 --> 00:11:18,316 +So, this authorization, +使用上边这两种方法 + +276 +00:11:18,317 --> 00:11:19,783 +when you request it with one of these methods, +获得授权的操作都是 + +277 +00:11:19,786 --> 00:11:21,652 +happens asynchronously. +异步的。 + +278 +00:11:21,654 --> 00:11:23,487 +That's because it's probably gonna put up a panel to +因为可能会给用户展示一个界面。 + +279 +00:11:23,489 --> 00:11:25,673 +the user saying, + +280 +00:11:25,674 --> 00:11:27,858 +this application wants to look at your device's location. +比如“这个程序想要使用你设备的位置, + +281 +00:11:27,860 --> 00:11:29,626 +Is that okay? +可以吗?” + +282 +00:11:29,628 --> 00:11:33,496 +And so, you're gonna find out about this authorization via +你可以通过一个代理方法查看你的 + +283 +00:11:33,498 --> 00:11:34,997 +a delegate method. +权限状态。 + +284 +00:11:34,999 --> 00:11:37,132 +And we'll talk about the locationManager's delegate +我们一会儿会具体讨论 CLLocationManager 的代理。 + +285 +00:11:37,134 --> 00:11:38,500 +in a moment. + +286 +00:11:38,501 --> 00:11:39,867 +But, you can look up in the documentation, +你可以去官方文档查看 + +287 +00:11:39,870 --> 00:11:41,553 +the name of the method. +方法的名字。 + +288 +00:11:41,554 --> 00:11:43,237 +It's basically gonna tell you what your authorization status +它会在你权限发生变化的时候 + +289 +00:11:43,240 --> 00:11:45,640 +when your authorization status changes. +通知你权限的状态。 + +290 +00:11:45,642 --> 00:11:49,210 +Now, until that authorization is granted by the user, +在用户给你授权之前, + +291 +00:11:49,212 --> 00:11:51,078 +your authorizationStatus, +你的授权状态 + +292 +00:11:51,080 --> 00:11:52,979 +which is a method we talked about in the previous slide, +就是前边我们看到的那个方法 + +293 +00:11:52,981 --> 00:11:56,049 +there, will be in this NotDetermined state. +会返回 NotDetermined 状态。 + +294 +00:11:56,051 --> 00:11:57,283 +And if you're in the NotDetermined state, +如果你在这个状态下, + +295 +00:11:57,285 --> 00:11:59,852 +then you won't be able to get +你不允许获取任何关于 + +296 +00:11:59,854 --> 00:12:01,887 +any information about the user's location. +用户位置的信息。 + +297 +00:12:03,090 --> 00:12:05,757 +Now, for any of this requesting authorization to +要使授权申请生效,你需要 + +298 +00:12:05,759 --> 00:12:09,894 +work, you need to add a key, one of these two keys, +在Info.plist文件里加入一个键,在这两个键 + +299 +00:12:09,896 --> 00:12:13,664 +to your Info.plist file. +里二选一。 + +300 +00:12:13,666 --> 00:12:16,466 +So, just the one of these keys just has to exist. +这两个键必须得有一个。 + +301 +00:12:16,468 --> 00:12:17,751 +If neither of them exist, +如果都没有, + +302 +00:12:17,752 --> 00:12:19,035 +then you won't be able to get any locations. +就不能获取位置信息。 + +303 +00:12:19,037 --> 00:12:20,670 +So, it just has to exist. +所以,必须得有一个才行。 + +304 +00:12:20,672 --> 00:12:22,104 +It doesn't have have certain value. +不需要有一个特定的值, + +305 +00:12:22,106 --> 00:12:24,340 +Just the key has to be there. +只要键在那就行了。 + +306 +00:12:24,342 --> 00:12:27,542 +To add a key to your Info.plist, you can just click +要在Info.plist里加一个键,需要点击 + +307 +00:12:27,544 --> 00:12:30,178 +on your Info.plist in your navigator and +这个文件,然后 + +308 +00:12:30,180 --> 00:12:33,381 +then right-click in an open in the Info.plist and +在打开的文件里右键点击,在弹出的 + +309 +00:12:33,383 --> 00:12:37,651 +choose Add Row from the little context menu that appears. +菜单里选“添加行”。 + +310 +00:12:37,653 --> 00:12:39,069 +And so obviously, +显然你需要 + +311 +00:12:39,070 --> 00:12:40,486 +you want to put the key here that matches up with the kind +添加与你之前通过代码获得的授权 + +312 +00:12:40,489 --> 00:12:43,556 +of authorization that you're gonna request in your code. +相匹配的键。 + +313 +00:12:43,558 --> 00:12:47,326 +And so, once you've done that and once you have gotten +当你成功向用户申请到 + +314 +00:12:47,328 --> 00:12:51,730 +the authorization from user, then you'll be able to, for +权限以后,你可以,比如说,要求 + +315 +00:12:51,732 --> 00:12:54,800 +example, ask the locationManager for +CLLocationManager 通过location 提供 + +316 +00:12:54,802 --> 00:12:58,570 +the current location using the location property. +目前的位置。 + +317 +00:12:58,572 --> 00:13:00,405 +But we usually don't pull like that. +但是实际上我们不这么做。 + +318 +00:13:00,407 --> 00:13:01,505 +Just like in current motion. +在CoreMotion里才会这么做。 + +319 +00:13:01,507 --> 00:13:03,474 +It's kind of bad programming to pull. +这是一种不太好的方式。 + +320 +00:13:03,476 --> 00:13:06,076 +We want it to tell us when it has something interesting. +我们只希望在它得到我们想要的信息的时候通知我们。 + +321 +00:13:06,078 --> 00:13:10,013 +So we set the desiredAccuracy with this CLLocationManager +所以我们需要在 CLLocationManager 里设置 desiredAccuracy + +322 +00:13:10,015 --> 00:13:12,081 +property, desiredAccuracy, and you just set it. +属性。 + +323 +00:13:12,083 --> 00:13:13,849 +It's one of those things I talked about before, +这个就是我们之前谈到的精确度属性, + +324 +00:13:13,851 --> 00:13:16,418 +kilometer or BestForNavigation or whatever. +BestForNavigation或者在几公里之内等等。 + +325 +00:13:16,420 --> 00:13:19,321 +You can also take a distance filter which is, +你还可以设置 distanceFilter, + +326 +00:13:19,323 --> 00:13:22,057 +don't tell me about location changes unless I move more +在我移动了这些距离的时候给我 + +327 +00:13:22,059 --> 00:13:23,725 +than a certain amount, okay? +更新位置。 + +328 +00:13:23,727 --> 00:13:27,628 +A meter, ten meters, 100 meters, a kilometer, whatever. +一米,10米,100米,1公里什么的。 + +329 +00:13:27,630 --> 00:13:30,297 +So, you set those two things up and +设置好这两个属性,然后 + +330 +00:13:30,299 --> 00:13:32,799 +then you just say, okay, start updating my location. +你可以让它开始更新我的位置。 + +331 +00:13:33,902 --> 00:13:36,869 +And it's gonna start sending you delegate messages +它就会开始发送位置的 + +332 +00:13:36,871 --> 00:13:38,504 +with your location. +代理信息。 + +333 +00:13:38,506 --> 00:13:41,039 +And the delegate message method looks like this, +代理信息的方法就像这样, + +334 +00:13:41,041 --> 00:13:43,074 +locationManager CLLocationManager, +locationManager CLLocationManager + +335 +00:13:43,076 --> 00:13:45,376 +that's the sender, didUpdateLocations. +这个是发送人,didUpdateLocations。 + +336 +00:13:45,378 --> 00:13:48,346 +Now, notice that that's an array of locations. +注意看,返回的是位置的数组。 + +337 +00:13:48,348 --> 00:13:49,880 +That's not just a single location. +并不是一个单独的位置。 + +338 +00:13:49,882 --> 00:13:51,314 +Hey, your location changed. +在你位置发生改变的时候返回数组, + +339 +00:13:51,316 --> 00:13:52,182 +Why does that happen? +为什么会这样? + +340 +00:13:52,184 --> 00:13:55,451 +Well, the new phone hardware +这是因为最新的 + +341 +00:13:55,453 --> 00:13:59,255 +is incredible when it comes to measuring your location. +定位硬件非常先进。 + +342 +00:13:59,257 --> 00:14:01,323 +And it can, even when it's off, okay, +在你的手机关闭,或者屏幕不亮, + +343 +00:14:01,325 --> 00:14:03,892 +when the thing powers, the screen powers down, and it's +或者电量不足, + +344 +00:14:03,894 --> 00:14:08,162 +kind of in a low power state, it's essentially sleeping. +实际上也就是在休眠的状态下。 + +345 +00:14:08,164 --> 00:14:10,898 +The GPS thing could still be recording your location. +GPS依然可以记录你的位置信息。 + +346 +00:14:10,900 --> 00:14:13,500 +So, you go for a hike, put your phone in your pocket. +比如你正在远足,手机在你的口袋里。 + +347 +00:14:13,502 --> 00:14:15,168 +You're walking for miles. +你走了挺远的路。 + +348 +00:14:15,170 --> 00:14:18,171 +You don't want your phone awake and using battery, okay? +这时候你不希望你的手机一直是激活状态消耗电量,对吧? + +349 +00:14:18,173 --> 00:14:19,472 +You want it to sleep but +你希望它处于休眠状态 + +350 +00:14:19,474 --> 00:14:21,674 +you still want to record where you went. +但是依然可以记录你的位置。 + +351 +00:14:21,676 --> 00:14:24,209 +Okay, cuz you're, you know, fitness tracking or +就像健身记录什么的。 + +352 +00:14:24,211 --> 00:14:25,243 +something like that. + +353 +00:14:25,245 --> 00:14:26,828 +And it can do that. +手机可以做到这一点。 + +354 +00:14:26,829 --> 00:14:28,412 +So fitness tracking apps will use that mechanism. +所以健身类的app会用到这个机制。 + +355 +00:14:28,415 --> 00:14:30,682 +So, what happens here is, +用这个机制, + +356 +00:14:30,684 --> 00:14:33,284 +the fitness tracking app can basically set itself up. +这个健身app就可以自动的做好配置。 + +357 +00:14:33,286 --> 00:14:35,552 +It says okay, well after the person has moved a certain +当用户移动特定的距离或者间隔 + +358 +00:14:35,554 --> 00:14:38,488 +amount or a certain amount of time happens, +特定的时间时, + +359 +00:14:38,490 --> 00:14:39,789 +please tell me where they've been. +更新位置。 + +360 +00:14:39,791 --> 00:14:41,324 +And you'll get this update and +然后你就可以拿到这些更新, + +361 +00:14:41,326 --> 00:14:43,659 +it'll have a bunch of locations in there. +这就是为什么会有很多位置更新给你。 + +362 +00:14:43,661 --> 00:14:45,361 +Right, again, all time stamped, all telling you. +而且都加上了时间戳。 + +363 +00:14:45,363 --> 00:14:49,131 +So, these things are building up in the chip, the GPS chip. +这个机制是定制在GPS芯片里的。 + +364 +00:14:49,133 --> 00:14:51,399 +And then the chip reports them in mass. +定制好以后芯片就可以批量更新。 + +365 +00:14:51,401 --> 00:14:53,434 +It's really a pretty amazing technology for +这确实是个非常赞的技术,既省电还 + +366 +00:14:53,436 --> 00:14:57,004 +keeping your battery alive and still being able to record. +可以持续的记录位置信息。 + +367 +00:14:57,006 --> 00:14:59,340 +And this is similar kind of stuff for heading. +记录方向也差不多。 + +368 +00:14:59,342 --> 00:15:02,676 +You can get reports from the locationManager, +你可以从location manager那得到更新。 + +369 +00:15:02,678 --> 00:15:06,546 +tell me what my heading is, it's changing, tell me. +告诉我现在的方向,如果方向改变,再通知我。 + +370 +00:15:06,548 --> 00:15:08,948 +Errors can happen, okay? +错误是经常出现的。 + +371 +00:15:08,950 --> 00:15:11,016 +And this is a case, you know, you notice in demos, +你会注意到在demo里,我没什么时间写代码去 + +372 +00:15:11,018 --> 00:15:13,018 +I don't have time to write code to check errors. +做错误检查。 + +373 +00:15:13,020 --> 00:15:14,019 +Sometimes errors are more +很多时候检查错误是 + +374 +00:15:14,021 --> 00:15:15,520 +important to check than others. +非常重要的。 + +375 +00:15:15,522 --> 00:15:18,489 +With location, it's pretty important to check, because, +尤其是在位置服务里,因为有可能发生这种情况,比如 + +376 +00:15:18,491 --> 00:15:20,891 +things can happen, like, you're using the app and +你在使用一个可以报告位置的app。 + +377 +00:15:20,893 --> 00:15:21,925 +it's reporting a location. + +378 +00:15:21,927 --> 00:15:23,577 +And then, all of a sudden, +然后,突然用户觉得: + +379 +00:15:23,578 --> 00:15:25,228 +the user says, I don't like this app knowing where I am. +我不希望这个app能知道我在哪。 + +380 +00:15:25,230 --> 00:15:26,662 +And he goes and turns it off. +他就关了这个功能。 + +381 +00:15:26,664 --> 00:15:29,999 +Okay, it turns off the location authorization. +他在app寻找位置的时候 + +382 +00:15:30,001 --> 00:15:31,684 +So, right in the middle, +就取消了这个app的位置权限。 + +383 +00:15:31,685 --> 00:15:33,368 +you can get something, ErrorDenied. +你就会得到一个ErrorDenied错误。 + +384 +00:15:33,371 --> 00:15:35,037 +Okay, you can get yourself denied. +用户可以自己关掉它。 + +385 +00:15:35,039 --> 00:15:37,372 +You can also get HeadingFailures if your +在磁力计被干扰的时候, + +386 +00:15:37,374 --> 00:15:41,108 +magnetometer's being interfered with, obviously. +你也有可能会得到一个HeadingFailures + +387 +00:15:41,110 --> 00:15:42,676 +You can get LocationUnknown, +在什么都找不到的时候,也许会得到 + +388 +00:15:42,678 --> 00:15:45,345 +where it just hasn't been able to see anything yet, +一个LocationUnknown错误, + +389 +00:15:45,347 --> 00:15:48,114 +it's trying but it wants to let you know it's trying. +系统在尝试但是它希望你能知道它在尝试。 + +390 +00:15:48,116 --> 00:15:50,116 +So after a certain amount of time with it not being able +所以当过了一段时间它没找到的时候, + +391 +00:15:50,118 --> 00:15:51,384 +to get it, it'll send you that. +它会给你发送这个错误信息。 + +392 +00:15:51,386 --> 00:15:54,886 +So, you want to pay attention to the errors there. +你们应该警惕这些错误。 + +393 +00:15:54,888 --> 00:15:57,222 +All right. + +394 +00:15:57,224 --> 00:16:00,058 +So, when your app is in the background, +继续,当你的app在后台的时候, + +395 +00:16:00,060 --> 00:16:02,793 +you can actually still get updates. +你依然可以得到更新。 + +396 +00:16:02,795 --> 00:16:04,395 +This is one of the few times when your +这是为数不多的app可以在后台可以 + +397 +00:16:04,397 --> 00:16:06,697 +app gets to do things in the background. +做的事。 + +398 +00:16:06,699 --> 00:16:10,133 +You have to turn a capability on, in that capabilities thing +你可以把它打开,就是打开上次说到的 + +399 +00:16:10,135 --> 00:16:14,704 +I talked about last time to do this. +那个功能。 + +400 +00:16:15,773 --> 00:16:16,938 +And there's a way to basically say, +还有一种方式就是把app从后台 + +401 +00:16:16,940 --> 00:16:18,073 +just wake me up in the background and +唤醒然后查看 + +402 +00:16:18,075 --> 00:16:20,442 +tell me what's going on. +更新。 + +403 +00:16:20,443 --> 00:16:22,810 +But really, there's two good ways, kind of bigger-ranged +实际上有两种更好的得到更新的办法, + +404 +00:16:22,812 --> 00:16:25,646 +ways, to get notified of things happening. +他们的范围更广一些。 + +405 +00:16:25,648 --> 00:16:28,882 +And that's the significant thing and the region thing. +这就是“显著”和区域这两个东西。 + +406 +00:16:28,884 --> 00:16:31,118 +So, the significant changes one, you just say, +第一个是显著变更的,你只需要告诉系统, + +407 +00:16:31,120 --> 00:16:32,819 +start monitoring significant changes. +开始监控显著的位置变更。 + +408 +00:16:32,821 --> 00:16:34,821 +Now, when you say that. +当你这么通知app的时候 + +409 +00:16:34,823 --> 00:16:37,290 +Okay? It's going to +它会开始监控 + +410 +00:16:37,291 --> 00:16:39,758 +start monitoring it for you forever until you say stop. +如果你不喊停它就不停下来。 + +411 +00:16:39,761 --> 00:16:43,162 +And this is gonna work even if your app is not launched, +甚至在app没启动的时候它也在监控。 + +412 +00:16:43,164 --> 00:16:45,063 +let alone if it's in the background. +不管它是不是在后台。 + +413 +00:16:45,065 --> 00:16:47,299 +Okay? And so when significant +也就是说,当有显著的位置变化 + +414 +00:16:47,300 --> 00:16:49,534 +changes occur, your app will be launched in the background. +发生的时候,你的app会在后台启动。 + +415 +00:16:49,536 --> 00:16:51,736 +And you'll have a little bit of time to chew on the fact +系统会需要一点时间来启动并获取 + +416 +00:16:51,738 --> 00:16:53,270 +that the significant change. +显著的位置变更, + +417 +00:16:53,272 --> 00:16:55,406 +Or if your app is running, but in the background, +或者你的app正运行在后台, + +418 +00:16:55,408 --> 00:16:58,508 +it will still get notified of these signficant changes. +它依然会收集这些变更。 + +419 +00:16:58,510 --> 00:17:01,111 +Okay, now the only thing is, you clearly +不过,在你不打算让你的app + +420 +00:17:01,113 --> 00:17:03,746 +want to turn this off if your app is not actually gonna +对这些变更做处理的时候,显然你希望 + +421 +00:17:03,748 --> 00:17:06,315 +do anything when these significant changes come in. +关掉这个功能。 + +422 +00:17:06,317 --> 00:17:07,783 +But it's a pretty cool system. +但是这确实是个非常酷的系统。 + +423 +00:17:07,785 --> 00:17:08,984 +And it's very low power. +而且非常省电。 + +424 +00:17:08,986 --> 00:17:11,753 +It's basically only large changes kind of the change +因为基本上只有很大的位置改变导致你切换 + +425 +00:17:11,755 --> 00:17:13,321 +where you move to a different cell tower, +了一个基站的时候才会发送消息, + +426 +00:17:13,323 --> 00:17:14,989 +those kind of low power, +我们知道通过基站来定位是 + +427 +00:17:14,991 --> 00:17:16,690 +measuring your location things. +非常省电的。 + +428 +00:17:16,692 --> 00:17:19,626 +But it can be really a cool thing to wake up every once in +它也可以每隔一段时间唤醒app然后 + +429 +00:17:19,628 --> 00:17:20,827 +a while and say, okay, where am I? +报告位置。 + +430 +00:17:20,829 --> 00:17:22,562 +If my app is location-based so +如果我的app是基于位置设计的, + +431 +00:17:22,564 --> 00:17:26,665 +I'm gonna check something out, it's quite interesting. +我就可以根据位置进行响应,非常好的系统。 + +432 +00:17:26,667 --> 00:17:28,667 +And you get notified by the delegate when these +当位置变更时,Location Manager的代理会 + +433 +00:17:28,669 --> 00:17:30,735 +significant changes happen. +给你发送消息。 + +434 +00:17:30,737 --> 00:17:32,170 +And if you get launched, +在app启动的时候, + +435 +00:17:32,172 --> 00:17:34,805 +then your didFinishLaunchingWithOptions. +会调用 didFinishLaunchingWithOptions方法。 + +436 +00:17:34,807 --> 00:17:37,341 +That little dictionary that we talked about is gonna have +这个方法里有一个字典的参数,这个字典会有 + +437 +00:17:37,343 --> 00:17:38,475 +a key in there. +一个键。 + +438 +00:17:38,477 --> 00:17:41,544 +That'll tell you UIApplicationLaunchOptionsLoc- +就是 UIApplicationLaunchOptionsLocactionKey, + +439 +00:17:41,546 --> 00:17:43,980 +ationKey, saying you got launched because +这个说明你的app启动时由于一个显著位置 + +440 +00:17:43,982 --> 00:17:47,016 +a significant, you know, a location event happened, so +变更导致的,你需要去 + +441 +00:17:47,018 --> 00:17:48,584 +you should go check your location, +查看当前的位置然后 + +442 +00:17:48,586 --> 00:17:50,085 +go do something right now. +做出响应。 + +443 +00:17:50,087 --> 00:17:50,652 +Okay? + +444 +00:17:51,688 --> 00:17:52,586 +Make sense? +明白了吗? + +445 +00:17:52,588 --> 00:17:53,954 +So that's a pretty cool system. +非常酷的系统。 + +446 +00:17:53,956 --> 00:17:56,089 +And the very similar one is the region one, +区域也是非常类似的。 + +447 +00:17:56,091 --> 00:17:58,792 +like the dry cleaner example I was telling you about. +我们刚才提到过干洗店app的例子。 + +448 +00:17:58,794 --> 00:18:00,827 +And you can create regions. +你可以建立一个区域。 + +449 +00:18:00,829 --> 00:18:03,596 +Really there's only two, I think there's only two regions +目前系统可用的区域类型应该是 + +450 +00:18:03,598 --> 00:18:04,830 +in the system currently. +只有两种。 + +451 +00:18:04,832 --> 00:18:06,198 +Circular region, +一种是圆形区域。 + +452 +00:18:06,200 --> 00:18:09,267 +which is a circle around some latitude and longitude. +就是一个地图上的圆圈。 + +453 +00:18:09,269 --> 00:18:10,802 +And then a beacon region. +然后是灯塔区域。 + +454 +00:18:10,804 --> 00:18:14,138 +So a circular region, you define like this right here. +在圆形区域里,你可以这样定义。 + +455 +00:18:14,140 --> 00:18:16,173 +We just say the center and the radius, and +定义它的中心和半径,然后定义 + +456 +00:18:16,175 --> 00:18:17,274 +you give it an identifier. +一个标识。 + +457 +00:18:17,276 --> 00:18:18,842 +Now you want the identifier. +标识是必要的, + +458 +00:18:18,844 --> 00:18:20,677 +Because, again, +因为 + +459 +00:18:20,678 --> 00:18:22,511 +this is gonna work when your app's not running, okay? +你需要在你的app没启动或者在后台 + +460 +00:18:22,514 --> 00:18:23,646 +Or when your app's in the background. +的时候也能监控区域。 + +461 +00:18:23,648 --> 00:18:24,913 +So you're gonna get woken up. +你需要特定的时候唤醒app。 + +462 +00:18:24,915 --> 00:18:26,815 +And when it wakes up, it needs to say, +app被唤醒的时候就会通知你, + +463 +00:18:26,817 --> 00:18:29,084 +oh, this is the region that you walked into. +你刚刚走进了你预设的区域。 + +464 +00:18:29,086 --> 00:18:30,518 +The significant change is only when +显著位置变化的通知只会在位置变化的 + +465 +00:18:30,520 --> 00:18:31,752 +a significant change happen. +时候发送。 + +466 +00:18:31,754 --> 00:18:33,270 +But, here, you, +但是在这里。 + +467 +00:18:33,271 --> 00:18:34,787 +it's gonna tell you which region you walked in or +系统会通知你走进或走出了 + +468 +00:18:34,790 --> 00:18:36,189 +out of. +哪一个区域。 + +469 +00:18:36,191 --> 00:18:41,427 +A beacon region is when you are near another iOS device. +灯塔区域指的是你是否靠近另外一台iOS设备。 + +470 +00:18:41,429 --> 00:18:43,496 +That is giving off a beacon. +这台设备就是所谓的灯塔。 + +471 +00:18:43,498 --> 00:18:45,998 +Now I'm not gonna talk about how you can make your iOS +在这里我不打算讲如何让你的iOS设备实现 + +472 +00:18:46,000 --> 00:18:47,800 +device do that. +这一点。 + +473 +00:18:47,801 --> 00:18:49,601 +It's pretty cool, requires a little bit of Bluetooth and +这个非常赞,需要一些蓝牙技术,但是有点 + +474 +00:18:49,603 --> 00:18:52,404 +stuff like that, so beyond the scope of this course. +超出我们这个课程的范围。 + +475 +00:18:52,406 --> 00:18:55,273 +But the way you monitor for whether you've come in +但是判断你是否进入了一个灯塔的范围,用的就是 + +476 +00:18:55,275 --> 00:19:00,444 +range of a beacon is using this region monitoring system. +咱们说的这个区域监控系统。 + +477 +00:19:00,446 --> 00:19:03,580 +And so, when you go into a region or out of a region, +当你走进或者走出区域的时候, + +478 +00:19:03,582 --> 00:19:06,049 +you get exit or enter or exit region. +相应的代理方法就会被调用。 + +479 +00:19:06,051 --> 00:19:09,385 +And when you go into a beacon area, whether it's a beacon +无论是灯塔区域还是圆形区域, + +480 +00:19:09,387 --> 00:19:12,755 +area or a circular region, you'll get this same thing. +都会调用同样的方法。 + +481 +00:19:12,757 --> 00:19:16,225 +And you can also get fail, you know, errors, and so +有时候也会失败,会得到错误,要记得在代码里 + +482 +00:19:16,227 --> 00:19:19,127 +you wanna make sure you check those as well. +检查错误。 + +483 +00:19:19,129 --> 00:19:23,297 +And since these regions that you're monitoring can work +因为在你的app不运行的时候也可以监控 + +484 +00:19:23,299 --> 00:19:26,634 +when you're not running, they have names. +区域,所以它们都有名字。 + +485 +00:19:26,636 --> 00:19:29,903 +And you can find out all the regions you're currently +你可以在CLLocationManager的monitoredRegions属性里找到 + +486 +00:19:29,905 --> 00:19:33,573 +monitoring by calling this CLLocationManager property, +所有你目前正在监控的区域。 + +487 +00:19:33,575 --> 00:19:34,874 +monitoredRegions. + +488 +00:19:34,876 --> 00:19:36,008 +Now, that's an NSSet. +这是一个NSSet类型的属性。 + +489 +00:19:36,010 --> 00:19:38,243 +We haven't really talked about NSSet. +我们之前没讲过NSSet。 + +490 +00:19:38,245 --> 00:19:41,813 +But an NSSet, kind of like an unordered array. +NSSet类似是一种无序的数组。 + +491 +00:19:41,815 --> 00:19:44,382 +The items in there are uniqued. +里边的元素都是唯一的。 + +492 +00:19:44,384 --> 00:19:47,752 +It's a set, basically, in terms of mathematical sense, +在数学上讲,这是一个集合。 + +493 +00:19:47,754 --> 00:19:49,070 +kind of a set. +类似集合的东西。 + +494 +00:19:49,071 --> 00:19:50,387 +And so you just look in there and find out what these +你只需要查看这个属性就可以知道你目前正在 + +495 +00:19:50,390 --> 00:19:51,955 +regions are that you're currently monitoring. +监控哪些区域。 + +496 +00:19:52,891 --> 00:19:54,357 +Okay? And + +497 +00:19:54,358 --> 00:19:55,824 +you can stop monitoring certain regions or +你也可以停止监控某一个区域或者添加更多的 + +498 +00:19:55,827 --> 00:19:57,327 +add more regions or whatever. +监控区域。 + +499 +00:19:57,328 --> 00:19:58,828 +There is a limit to the number of regions you can monitor. +可以监控区域的数量是有限制的, + +500 +00:19:58,830 --> 00:19:59,729 +It's big, though. +尽管这个数量很大。 + +501 +00:19:59,731 --> 00:20:01,363 +Yeah? >> When you have a beacon +提问:可以监控一个正在 + +502 +00:20:01,365 --> 00:20:03,899 +can you find our where the beacon is cycling? +移动的灯塔吗? + +503 +00:20:03,901 --> 00:20:07,435 +>> Yeah, so the question is, if I'm in a beacon region, +好,问题是,当我在灯塔区域的时候, + +504 +00:20:07,437 --> 00:20:09,771 +I think, do I have a slide on that? +我想想是不是有个幻灯片讲这个 + +505 +00:20:10,840 --> 00:20:14,408 +I'll get to the beacons in a second. +我们一会儿马上就讲灯塔了。 + +506 +00:20:14,410 --> 00:20:18,578 +So the region monitoring distance. +监控区域的大小也是有限制的。 + +507 +00:20:20,415 --> 00:20:22,948 +This is a gettable var, a read-only var. +这里有一个只读的变量。 + +508 +00:20:22,950 --> 00:20:25,784 +It'll tell you what is the biggest area you can monitor, +这个变量告诉你可以监控距离的最大范围, + +509 +00:20:25,786 --> 00:20:28,754 +so you can't really say, tell me when I'm at Stanford, and +所以你不能说,监控我是不是在斯坦福大学里,因为 + +510 +00:20:28,756 --> 00:20:30,121 +have this gigantic region. +这个区域太大了。 + +511 +00:20:30,123 --> 00:20:34,592 +Okay, there is a limit, and this will tell you what it is. +大小是有限制的,可以通过这个变量知道这个限制。 + +512 +00:20:35,728 --> 00:20:37,127 +So the beacons, +下边说灯塔, + +513 +00:20:37,129 --> 00:20:40,697 +they can detect the range from the beacon. +系统可以检测到与灯塔之间的距离。 + +514 +00:20:40,699 --> 00:20:42,165 +So it's just kind of what you're asking for. +就跟你刚才问的差不多。 + +515 +00:20:42,167 --> 00:20:44,100 +As you move around, you can tell. +你只要一动,系统就会告诉你 + +516 +00:20:44,101 --> 00:20:46,034 +Are you kind of intensely close to the beacon or kind of +现在是离灯塔很近还是中等距离还是 + +517 +00:20:46,037 --> 00:20:48,771 +a medium or are you kind of far away from the beacon? +离的很远。 + +518 +00:20:48,773 --> 00:20:50,972 +And so you just say startRanging this +你需要调用这个方法。 + +519 +00:20:50,974 --> 00:20:52,207 +BeaconsInRegion. +startRangingBeaconInRegion. + +520 +00:20:52,209 --> 00:20:55,009 +And you'll get this didRangeBeacons in region. +然后你就会收到didRangeBeacons这个代理方法发送的信息。 + +521 +00:20:55,011 --> 00:20:57,878 +And it will tell you whether you're immediate, near, or +这个方法会告诉你距离灯塔是近,中等距离 + +522 +00:20:57,880 --> 00:20:59,713 +far to the range. +还是远。 + +523 +00:20:59,714 --> 00:21:01,547 +So it's not really telling you like, direction but it's +但是它不会告诉你方向,但是会告诉你 + +524 +00:21:01,550 --> 00:21:04,551 +telling you, you know, close, near, far so that's good. +距离,应该够用了。 + +525 +00:21:04,553 --> 00:21:08,554 +Like I said being a beacon requires you to do some stuff +我刚才说了,要成为一个灯塔需要用到 + +526 +00:21:08,556 --> 00:21:11,123 +in the Core Bluetooth Framework. +Core Bluetooth框架的技术。 + +527 +00:21:11,125 --> 00:21:12,725 +We're not going to talk about that. +我们这个课上不会讲。 + +528 +00:21:12,727 --> 00:21:16,028 +You'd have to have this globally unique ID for +你必须给你的灯塔一个全局唯一 + +529 +00:21:16,030 --> 00:21:17,179 +your beacon. +的ID。 + +530 +00:21:17,180 --> 00:21:18,329 +You have to register with Apple basically. +你需要去苹果注册这个ID。 + +531 +00:21:18,331 --> 00:21:19,530 +This is your beacon. +这就是你的灯塔。 + +532 +00:21:19,532 --> 00:21:22,633 +It's not just something you just turn it on, +不是说打开设备就可以 + +533 +00:21:22,635 --> 00:21:24,134 +start sending out a beacon. +当作一个灯塔了。 + +534 +00:21:24,136 --> 00:21:26,870 +You kind of have to identify your beacon. +你需要注册你的灯塔。 + +535 +00:21:26,872 --> 00:21:28,872 +So that's it for core location. +前边讲的就是Core Location的内容。 + +536 +00:21:28,874 --> 00:21:30,306 +That's the underpinnings. +底层的东西。 + +537 +00:21:30,308 --> 00:21:32,842 +And now we're gonna talk about the UI side of this, +现在我们讲UI层面的东西, + +538 +00:21:32,844 --> 00:21:34,743 +which is called MapKit. +也就是MapKit。 + +539 +00:21:34,745 --> 00:21:36,712 +Okay? + +540 +00:21:36,713 --> 00:21:38,680 +And MapKit, fundamentally, displays a map. +MapKit简单来说,就是展示地图。 + +541 +00:21:38,682 --> 00:21:39,414 +Okay? + +542 +00:21:39,416 --> 00:21:41,115 +It's basically a UIView, +它是一个UIView。 + +543 +00:21:41,117 --> 00:21:43,517 +MKMapview is a UIView subclass. +MKMapView是UIView的子类。 + +544 +00:21:43,519 --> 00:21:46,920 +And it displays a map of wherever you are on Earth. +它会展示你在地球上的位置。 + +545 +00:21:46,922 --> 00:21:48,822 +Okay? And it's using this Apple Maps +它用的是苹果地图的技术 + +546 +00:21:48,824 --> 00:21:53,593 +technology to display either a satellite image like this or +来显示卫星图片或者街道名, + +547 +00:21:53,595 --> 00:21:57,129 +just streets and roads, or an overlap, like this one is, +路名,或者一个像这样的覆盖层,可以显示卫星图片和街道名字 + +548 +00:21:57,131 --> 00:21:59,732 +of satellite image and the names of roads, et cetera. +什么的。 + +549 +00:21:59,734 --> 00:22:02,301 +Okay? + +550 +00:22:02,302 --> 00:22:04,869 +Now, on this map it has what are called annotations. +地图上会有一些注释点。 + +551 +00:22:04,871 --> 00:22:06,337 +That's what makes a pin on the app. +就是app里的大头针。 + +552 +00:22:06,339 --> 00:22:09,273 +This is a very important term to understand, an annotation. +注释点是一个非常重要的概念。 + +553 +00:22:09,275 --> 00:22:11,875 +An annotation is a point on the map. +注释点就是地图上的一个点。 + +554 +00:22:11,877 --> 00:22:12,709 +Okay? + +555 +00:22:12,711 --> 00:22:14,411 +Now, an annotation is simple. +注释点很简单。 + +556 +00:22:14,413 --> 00:22:17,080 +It's just a protocol, and it has three things in it. +只是一个协议而已,需要实现三个属性。 + +557 +00:22:17,082 --> 00:22:19,615 +Coordinate, which is the latitude and longitude, so +第一个是坐标,也就是经纬度, + +558 +00:22:19,617 --> 00:22:22,584 +that CLLocationCoordinate2D thing we saw earlier, and +也就是我们之前看到的CLLocationCoordinate2D类型,然后 + +559 +00:22:22,586 --> 00:22:23,752 +then title and subtitle. +就是标题和副标题。 + +560 +00:22:23,754 --> 00:22:26,087 +So, here this one you're seeing here, +现在你看见的这个注释点, + +561 +00:22:26,089 --> 00:22:29,123 +the title is Venice, Italy, and it has no subtitle. +标题是“意大利,威尼斯”,没有副标题。 + +562 +00:22:29,125 --> 00:22:31,859 +The subtitle would appear as a little smaller +副标题就是在标题下边小一点的字, + +563 +00:22:31,861 --> 00:22:34,995 +text underneath, so it has no subtitle there. +在这里没有副标题。 + +564 +00:22:34,997 --> 00:22:35,863 +Okay? + +565 +00:22:35,864 --> 00:22:36,730 +Now you have these annotations, +现在你有了这些注释点, + +566 +00:22:36,732 --> 00:22:38,164 +you need to display them. +你需要把它们显示在地图上。 + +567 +00:22:38,166 --> 00:22:42,635 +Now they're displayed with MKAnnotationView subclasses. +它们是通过MKAnnotationView的子类来显示的。 + +568 +00:22:42,637 --> 00:22:43,235 +Okay? + +569 +00:22:43,237 --> 00:22:44,970 +Make sense? +明白吗? + +570 +00:22:44,971 --> 00:22:46,704 +MKAnnotations being displayed with MKAnnotationViews. +MKAnnotations需要通过 MKAnnotationViews显示。 + +571 +00:22:46,707 --> 00:22:49,541 +And MKPinAnnotationView, which is what you see here, +MKPinAnnotationView,就像你刚才看见的那样,像 + +572 +00:22:49,543 --> 00:22:50,375 +looks like a pin. +个大头针。 + +573 +00:22:50,377 --> 00:22:54,345 +Now you can write your own MKAnnotationView subclasses +你可以自己写MKAnnotationView的子类,这样就可以在某个位置 + +574 +00:22:54,347 --> 00:22:56,747 +and draw whatever you want at that location. +上画任何你想要的效果。 + +575 +00:22:56,749 --> 00:22:59,383 +But most times people are using the MKPinAnnotationView +但是大多数的时候人们都会用MKPinAnnotationView,因为 + +576 +00:22:59,385 --> 00:23:01,518 +so it's showing up as pins. +它长的像大头针。 + +577 +00:23:01,520 --> 00:23:05,488 +Now when you click on the pin, another view comes up, +当你点大头针的时候,另外一个视图就会跳出来, + +578 +00:23:05,490 --> 00:23:09,592 +this white view right here called the pin's callout. +这个白色的视图叫做大头针的标注。 + +579 +00:23:09,594 --> 00:23:12,761 +Okay, now don't get confused between the MKAnnotationView +不要把它跟大头针也就是MKAnnotationView + +580 +00:23:12,763 --> 00:23:14,363 +which is the pin. +弄混了。 + +581 +00:23:14,365 --> 00:23:15,797 +That's what the MKAnnotationView, +这个是MKAnnotationView, + +582 +00:23:15,799 --> 00:23:16,597 +it draws a pin. +它在地图上绘制一个大头针。 + +583 +00:23:17,834 --> 00:23:21,001 +This is a different thing called a callout. +标注是完全不同的东西。 + +584 +00:23:21,003 --> 00:23:22,669 +People get confused between the two because there's +大家经常把这两个东西搞混,因为不能直接访问这个 + +585 +00:23:22,671 --> 00:23:25,105 +really no pointer to that callout view, you don't, +标注视图, + +586 +00:23:25,107 --> 00:23:29,008 +you know, interact with that callout view directly. +我们不能直接与标注视图进行交互。 + +587 +00:23:29,010 --> 00:23:32,578 +Instead what you're able to do is set the left and +但是我们可以设置左右两个 + +588 +00:23:32,580 --> 00:23:34,380 +right accessory views. +辅助视图。 + +589 +00:23:34,382 --> 00:23:36,114 +So here we got a left accessory view, +这里是一个左辅助视图。 + +590 +00:23:36,116 --> 00:23:37,315 +which is a little image, and +是一个小图片,右辅助视图是一个 + +591 +00:23:37,317 --> 00:23:39,417 +the right accessory view is a little button. +小按钮。 + +592 +00:23:39,419 --> 00:23:40,651 +You can set those. +你可以设置它们。 + +593 +00:23:40,653 --> 00:23:42,486 +But you don't interact with the view. +但是你不能与这个视图交互。 + +594 +00:23:42,488 --> 00:23:44,354 +So, but that's a callout view, and +这个标注视图只会在 + +595 +00:23:44,356 --> 00:23:46,322 +it only shows when you click on the pin. +你点大头针的时候才会弹出来。 + +596 +00:23:46,324 --> 00:23:48,124 +If you click on the pin, it shows the callout view. +如果你点击大头针,标注视图就出来了。 + +597 +00:23:48,126 --> 00:23:50,443 +Now again, +再说一次, + +598 +00:23:50,444 --> 00:23:52,761 +if you're doing your own MKAnnotationView subclass. +如果你自己实现MKAnnotationView的子类。 + +599 +00:23:52,764 --> 00:23:54,430 +Doesn't draw a pin, it draws something else. +你不打算绘制一个大头针而是别的什么。 + +600 +00:23:54,432 --> 00:23:55,997 +You could have your own callout, +你可以设计自己的标注, + +601 +00:23:55,999 --> 00:23:57,332 +you can put your own view up, +你可以把自己设计的视图放上去。 + +602 +00:23:57,334 --> 00:23:59,133 +whatever you feel like you need to do. +你自己喜欢的。 + +603 +00:23:59,135 --> 00:24:01,302 +But if you're using the pin-based one, +但是如果你用一个大头针, + +604 +00:24:01,304 --> 00:24:04,138 +this is the flexibility you have, is to do that left and +你就只能设置这些东西,左右两个 + +605 +00:24:04,140 --> 00:24:06,139 +right callout accessory. +辅助视图。 + +606 +00:24:06,141 --> 00:24:08,541 +Okay, that's what you're allowed to do. +这是你唯一能做的。 + +607 +00:24:08,543 --> 00:24:10,760 +'Kay, so + +608 +00:24:10,761 --> 00:24:12,978 +in the demo, I'm going to show all of this ability here. +一会儿在demo里,我会给你们演示都能做什么。 + +609 +00:24:13,914 --> 00:24:17,949 +So you create a MKMapView just by, +你能从故事板里直接拖一个 + +610 +00:24:17,951 --> 00:24:21,386 +usually by dragging it out in storyboard of course. +MKMapView出来。 + +611 +00:24:21,388 --> 00:24:22,620 +Just like you create, you know, +就跟你拖文字视图或者图片视图 + +612 +00:24:22,622 --> 00:24:24,305 +a text view or an image view, +一样。 + +613 +00:24:24,306 --> 00:24:25,989 +just drag it on out and size it to where you want. +拖进来然后设置大小。 + +614 +00:24:25,992 --> 00:24:29,659 +But you can say MKMapView parenthesis, parenthesis and +你也可以通过 MKMapView() 来 + +615 +00:24:29,661 --> 00:24:30,994 +initialize one. +初始化。 + +616 +00:24:30,996 --> 00:24:34,497 +You can say MKMapView frame colon whatever cuz it's +你也可以写 MKMapView(frame:),因为它就是一个UIView + +617 +00:24:34,499 --> 00:24:35,898 +a UIView. +而已。 + +618 +00:24:35,899 --> 00:24:37,298 +One thing that's important about using MapKit, +要使用MapKit最重要的就是别忘了导入 + +619 +00:24:37,301 --> 00:24:38,500 +you have to import MapKit. +MapKit。 + +620 +00:24:39,503 --> 00:24:41,253 +Okay? + +621 +00:24:41,254 --> 00:24:43,004 +If you don't import MapKit, you're not gonna see any of +如果不导入,这些东西你就都 + +622 +00:24:43,006 --> 00:24:44,905 +the symbols so don't forget that piece. +不能用,千万别忘了。 + +623 +00:24:44,907 --> 00:24:46,473 +It'll be pretty obvious when you start typing, +你自己写代码的时候应该能挺容易就发现, + +624 +00:24:46,475 --> 00:24:48,809 +it's like woah, MKMap it won't escape complete. +因为你写MKMap的时候没有自动补全。 + +625 +00:24:48,811 --> 00:24:50,576 +Well, it's because you didn't import MapKit. +这时你就知道是忘了导入。 + +626 +00:24:52,780 --> 00:24:55,114 +The annotations that are on there, +地图上的注释点, + +627 +00:24:55,116 --> 00:24:57,783 +all the places where the pins are, that's just an array, +也就是那些大头针,实际上是一个数组。 + +628 +00:24:57,785 --> 00:25:01,086 +okay, an array of MKAnnotation. +一个MKAnnotation的数组。 + +629 +00:25:01,088 --> 00:25:03,821 +Now, I'm putting them in these slides as +在幻灯片里我写的是MKAnnotation + +630 +00:25:03,823 --> 00:25:05,156 +array of MKAnnotation. +的数组。 + +631 +00:25:05,158 --> 00:25:06,990 +It's actually, as you might guess, +事实上,你可能已经猜到了, + +632 +00:25:06,992 --> 00:25:10,126 +an array of any object, okay, for historical reasons. +它是AnyObject的数组,因为各种历史原因。 + +633 +00:25:11,229 --> 00:25:13,562 +But you cannot pass anything except for +但是你不能把MKAnnotation以外的东西 + +634 +00:25:13,564 --> 00:25:15,764 +an MKAnnotation into these things. +存进这个数组。 + +635 +00:25:15,766 --> 00:25:19,668 +So I've changed the code on my slides to just be +所以我在幻灯片里改成了MKAnnotation + +636 +00:25:19,670 --> 00:25:20,868 +array of MKAnnotation. +的数组。 + +637 +00:25:20,870 --> 00:25:24,071 +Cuz that's what it is, it's an array of MKAnnotation. +因为它本来就是MKAnnotation的数组。 + +638 +00:25:24,073 --> 00:25:24,638 +Okay? + +639 +00:25:25,808 --> 00:25:29,576 +Now notice that that's get only. +你注意到了这个属性是只读的。 + +640 +00:25:29,578 --> 00:25:31,728 +So we'll talk about how you set +一会儿我们会讲如何设置注释点, + +641 +00:25:31,729 --> 00:25:33,879 +the annotations in a second, but that's how you get them. +但是在这你只能读取, + +642 +00:25:33,882 --> 00:25:36,515 +The protocol, as I talked about, coordinate, title, and +前边我说的协议,就是坐标,标题, + +643 +00:25:36,517 --> 00:25:37,466 +subtitle. +副标题那个东西。 + +644 +00:25:37,467 --> 00:25:38,416 +Notice that the title and +注意看标题和副标题 + +645 +00:25:38,419 --> 00:25:40,952 +subtitle are optional strings, okay. +都是可选的字符串。 + +646 +00:25:40,954 --> 00:25:42,587 +But you really wanna set that title. +但是你必须得设置一个标题, + +647 +00:25:42,589 --> 00:25:44,155 +If you don't set the title, +如果不设, + +648 +00:25:44,157 --> 00:25:45,589 +pretty much everything's gonna be messed up. +就全乱套了。 + +649 +00:25:45,591 --> 00:25:47,791 +So don't let that title be nil. +所以千万不要让标题为空。 + +650 +00:25:47,793 --> 00:25:49,226 +Okay? The subtitle can be nil, but +副标题可以为空,但是标题 + +651 +00:25:49,228 --> 00:25:50,126 +don't let the title be nil. +不可以。 + +652 +00:25:51,529 --> 00:25:54,063 +And then CLLocationCoordinate2D you +CLLocationCoordinate2D,这个之前你们 + +653 +00:25:54,065 --> 00:25:55,798 +know what that is from earlier slides, +已经看到过了, + +654 +00:25:55,800 --> 00:25:57,332 +that's just the latitude and longitude. +就是经纬度而已。 + +655 +00:25:58,435 --> 00:26:00,368 +Okay, so + +656 +00:26:00,369 --> 00:26:02,302 +how do we add annotations since that thing is read-only? +既然注释点是只读的,那我们怎么添加呢? + +657 +00:26:02,305 --> 00:26:04,638 +Well, with methods like addAnnotation and +可以通过addAnnotation和addAnnotations方法, + +658 +00:26:04,640 --> 00:26:07,041 +addAnnotations, and removeAnnotation and +通过removeAnnotation和removeAnnotations + +659 +00:26:07,043 --> 00:26:08,241 +removeAnnotations. +删除。 + +660 +00:26:08,243 --> 00:26:10,093 +Okay? + +661 +00:26:10,094 --> 00:26:11,944 +And the reason it does that that way is it just wants to +这样做的原因是系统就可以知道你加了 + +662 +00:26:11,947 --> 00:26:13,379 +know when you add an annotation, so +新的注释点以便于它 + +663 +00:26:13,381 --> 00:26:14,914 +it can update the map. +更新地图。 + +664 +00:26:14,916 --> 00:26:15,614 +Okay. + +665 +00:26:15,616 --> 00:26:16,281 +Simple as that. +很简单。 + +666 +00:26:17,584 --> 00:26:20,618 +It is generally a good idea, if you know what all your +如果设计时你就知道你所有的注释点,你最好提前就把它们 + +667 +00:26:20,620 --> 00:26:23,487 +annotations are, to add them up front. +都添加了。 + +668 +00:26:23,489 --> 00:26:25,289 +Okay? As opposed to kind of trying +这个好像跟用户现在在哪个位置, + +669 +00:26:25,291 --> 00:26:27,124 +to watch where the user is on the map, and +然后在地图上插一个大头针 + +670 +00:26:27,126 --> 00:26:28,525 +add them as you go. +有点相悖。 + +671 +00:26:28,527 --> 00:26:31,227 +Because you're gonna find that the map +这么做是因为地图视图跟表格视图一样 + +672 +00:26:31,229 --> 00:26:35,130 +view is smart like table view, and it reuses those pins. +聪明,它们可以复用大头针。 + +673 +00:26:35,132 --> 00:26:36,849 +Okay? So, + +674 +00:26:36,850 --> 00:26:38,567 +if you have a thousand annotations, +如果你有一千个注释点, + +675 +00:26:38,569 --> 00:26:41,569 +annotations are small, the views are big and +注释点很小,但是它的视图很大很耗能, + +676 +00:26:41,571 --> 00:26:46,007 +expensive, but map view is going to manage that for you. +但是地图视图会帮你管理它们。 + +677 +00:26:46,009 --> 00:26:47,508 +Okay? So unless you +除非你在一个 + +678 +00:26:47,510 --> 00:26:50,744 +have a ton of annotations in a very small space and somehow, +非常小的区域有非常多的注释点, + +679 +00:26:50,746 --> 00:26:53,813 +you filter them to show the user only some of them, +你应该过滤掉一些,给用户展示一部分, + +680 +00:26:53,815 --> 00:26:55,381 +you might as well put all your annotations in there. +不过也有可能你想把它们都展示给客户。 + +681 +00:26:55,383 --> 00:26:57,983 +And let the map view be smart about showing which pins +地图视图会很聪明的知道在现在的地图上 + +682 +00:26:57,985 --> 00:27:00,119 +are are visible at the, where the map is showing. +展示哪些大头针, + +683 +00:27:00,121 --> 00:27:01,553 +And then, as it scrolls around, +如果用户滚动地图, + +684 +00:27:01,555 --> 00:27:05,790 +it'll reuse the pins and be efficient about it. +它就会复用大头针以提高效率。 + +685 +00:27:05,792 --> 00:27:06,957 +Okay? + +686 +00:27:06,959 --> 00:27:11,661 +When you have an annotation, +当你有一个注释点, + +687 +00:27:11,663 --> 00:27:12,929 +what does it look like on the map? +它在地图上是什么样的呢? + +688 +00:27:12,931 --> 00:27:14,831 +Well, that depends on the MKAnnotationView +这个取决于用来显示它的 + +689 +00:27:14,833 --> 00:27:16,065 +that's displaying it. +MKAnnotationView + +690 +00:27:16,067 --> 00:27:18,334 +But again, the pins are usually how we do it, and +但是,通常我们都用大头针, + +691 +00:27:18,336 --> 00:27:19,634 +it looks like a pin. + +692 +00:27:19,636 --> 00:27:22,671 +You can set the color, it can be purple or blue or red, +你可以设置它的颜色,紫色蓝色或者红色, + +693 +00:27:22,673 --> 00:27:24,272 +I think. + +694 +00:27:24,273 --> 00:27:25,872 +And you can even set the image of that pin if you don't want +你甚至可以把大头针的图片换掉如果你不希望它看起来 + +695 +00:27:25,875 --> 00:27:27,825 +it to look like a pin, but +像个大头针,但是你希望 + +696 +00:27:27,826 --> 00:27:29,776 +you still want all the rest of behavior of the pin annotation +其他的特性都跟大头针注释点一样, + +697 +00:27:29,779 --> 00:27:30,978 +view like that callout. +比如标注视图。 + +698 +00:27:30,980 --> 00:27:33,364 +Then you can change, +你可以换图片, + +699 +00:27:33,365 --> 00:27:35,749 +there's a property in there, you can change the image. +有一个属性,可以换图片。 + +700 +00:27:35,751 --> 00:27:39,886 +When you touch on a pin, what happens? +如果你点击一个大头针会发生什么呢? + +701 +00:27:39,888 --> 00:27:41,120 +'Kay? Well one thing is, +首先就是, + +702 +00:27:41,122 --> 00:27:44,056 +if it's a pin annotation view, and as long as showing +如果这是一个大头针注释点,有一个canShowCallout属性让你确定 + +703 +00:27:44,058 --> 00:27:47,192 +callouts is allowed, there's a can show callout property. +是不是允许弹出标注视图。 + +704 +00:27:47,194 --> 00:27:49,260 +Then it's gonna put that callout up. +如果允许,标注视图就弹出来。 + +705 +00:27:49,262 --> 00:27:50,428 +Okay? + +706 +00:27:50,430 --> 00:27:52,196 +So that's one thing that happens. +这是首先会发生的事儿。 + +707 +00:27:52,198 --> 00:27:54,131 +The other thing that happens when you touch it is that +另外一个点击时会发生的事情就是调用 + +708 +00:27:54,133 --> 00:27:55,599 +your map view's delegate +地图视图的代理方法。 + +709 +00:27:55,601 --> 00:27:58,768 +gets sent the message didSelectAnnotationView. +didSelectAnnotationView + +710 +00:27:58,770 --> 00:28:00,136 +So you get told oh, +在这里系统就会知道 + +711 +00:28:00,138 --> 00:28:03,339 +this person clicked on this annotation view. +有人点击了注释点视图, + +712 +00:28:03,341 --> 00:28:05,374 +And you can find out from the annotation view +你可以从这个方法的注释视图参数得知是哪个 + +713 +00:28:05,376 --> 00:28:07,075 +which annotation that represents. +注释点被点击了。 + +714 +00:28:09,179 --> 00:28:10,411 +Okay? + +715 +00:28:10,413 --> 00:28:13,914 +Remember that the callout is built +要记住标注视图在大头针生成的时候就已经 + +716 +00:28:13,916 --> 00:28:17,351 +at the time that the pin is built, that view hierarchy. +通过视图继承关系生成了。 + +717 +00:28:17,353 --> 00:28:20,320 +But you wouldn't want to do something expensive there, +所以在这个时候不要做非常消耗性能的事。 + +718 +00:28:20,322 --> 00:28:21,821 +like for example, fetch that image, +比如抓取图片什么的, + +719 +00:28:21,823 --> 00:28:23,923 +that little picture of Venice there. +那个威尼斯的小图片。 + +720 +00:28:23,925 --> 00:28:25,624 +I wouldn't want to fetch that from the network or +我希望这个图片只在注释点被点击的时候 + +721 +00:28:25,626 --> 00:28:27,959 +something until it actually got clicked on. +才会开始从网络抓取。 + +722 +00:28:27,961 --> 00:28:30,795 +Because that callout +因为如果没人点注释点的话,有可能 + +723 +00:28:30,797 --> 00:28:32,597 +may never be shown if no one ever clicks on it. +标注视图永远都不会弹出来。 + +724 +00:28:32,599 --> 00:28:36,233 +So, what a waste to fetch that image before then. +所以在那之前就抓取图片非常浪费。 + +725 +00:28:36,235 --> 00:28:37,985 +Okay? But you're still gonna wanna +但是标注视图的左辅助视图 + +726 +00:28:37,986 --> 00:28:39,736 +put the UIImageView as the left call out accessory. +依然是一个图片视图, + +727 +00:28:39,739 --> 00:28:40,704 +You're just not gonna put any +你只是在注释点被点击之前不 + +728 +00:28:40,706 --> 00:28:42,839 +image in it till someone clicks on it. +加载图片而已。 + +729 +00:28:44,376 --> 00:28:47,243 +So, how are these MKAnnotationViews created and +这些MKAnnotationViews是怎么加载而且跟你的注释点 + +730 +00:28:47,245 --> 00:28:49,445 +associated with annotation? +数组联系起来的呢? + +731 +00:28:49,447 --> 00:28:52,981 +'Kay, it's very similar to table view, so this is a lot +跟表格视图非常类似,尤其是跟表格视图的 + +732 +00:28:52,983 --> 00:28:56,217 +like table view's self or row in index path. +self或者indexPath的行很类似。 + +733 +00:28:56,219 --> 00:28:59,187 +Okay, it's called viewForAnnotation, so it's +我们调用viewForAnnotation方法, + +734 +00:28:59,189 --> 00:29:01,689 +gonna give you an annotation and say create me a view. +它会在参数里给你提供一个注释点然后你需要为它建一个视图。 + +735 +00:29:01,691 --> 00:29:03,824 +The first thing you're gonna try to do is dequeue +首先你需要尝试把一个复用的视图从队列 + +736 +00:29:03,826 --> 00:29:05,792 +a reusable one. +取出。 + +737 +00:29:05,794 --> 00:29:07,994 +So that's like you do in table view. +跟你在表格视图里做的一样。 + +738 +00:29:07,996 --> 00:29:09,062 +And, but this time, +但是这次 + +739 +00:29:09,064 --> 00:29:11,197 +if you can't find one, which is possible, +如果找不到,这是有可能的, + +740 +00:29:11,199 --> 00:29:14,166 +because there's no prototypes like there is in table view. +因为跟表格视图不同的是这里是没有原型的。 + +741 +00:29:14,168 --> 00:29:16,034 +There's nothing in the storyboard that's +我们没有从故事板里加载一个 + +742 +00:29:16,036 --> 00:29:17,402 +gonna make it create one. +进来。 + +743 +00:29:17,404 --> 00:29:20,405 +So you have to check to see if view does equal nil, +所以你必须要检查视图是不是为空, + +744 +00:29:20,407 --> 00:29:22,239 +then you're gonna have to create a pin annotation view. +然后就要新建一个大头针视图。 + +745 +00:29:22,241 --> 00:29:23,540 +But when you create it, +新建的时候, + +746 +00:29:23,542 --> 00:29:26,043 +there's two arguments to its initialize there. +它的初始化器有两个参数。 + +747 +00:29:26,045 --> 00:29:27,677 +One is the annotation, but +第一个是注释点,第二个 + +748 +00:29:27,679 --> 00:29:30,046 +another one is that reuse identifier. +是复用标识。 + +749 +00:29:30,048 --> 00:29:33,149 +And that makes it so the next time you come around that pin +这样可以使这个视图在屏幕外的时候 + +750 +00:29:33,151 --> 00:29:35,751 +might be reused if it went off screen. +可以被复用。 + +751 +00:29:35,753 --> 00:29:36,852 +So this is how this works. +在没有原型的时候我们 + +752 +00:29:36,854 --> 00:29:38,319 +There's no prototypes, +都是这么做的。 + +753 +00:29:38,321 --> 00:29:41,622 +you have to kind of create the prototypes in code here if you +如果你不能从复用队列中取到一个的话,你就要用代码新建一个 + +754 +00:29:41,624 --> 00:29:43,758 +can't get a dequeued reusable one. +原型。 + +755 +00:29:44,860 --> 00:29:46,660 +And then you're usually gonna say whether +然后下面就需要设置是不是允许 + +756 +00:29:46,662 --> 00:29:47,761 +you can show a callout. +弹出标识视图。 + +757 +00:29:47,763 --> 00:29:49,128 +If you're using a pin annotation view, +如果你用的是大头针视图, + +758 +00:29:49,130 --> 00:29:52,198 +you're gonna say yes or no on the canShowCallout. +你需要设置canShowCallout的值。 + +759 +00:29:52,200 --> 00:29:55,768 +And then, now you've got ahold of an MKAnnotationView. +这是你就持有了一个MKAnnotationView + +760 +00:29:55,770 --> 00:29:59,237 +You're going to get it ready to display, +下边要准备让它显示在屏幕上, + +761 +00:29:59,239 --> 00:30:01,706 +mostly by setting the annotation. +最重要的肯定是设置它的注释点。 + +762 +00:30:01,708 --> 00:30:03,108 +Okay? + +763 +00:30:03,109 --> 00:30:04,509 +But also, you might set up those left and +你也有可能需要设置它标识视图的左右 + +764 +00:30:04,511 --> 00:30:07,178 +right callout accessory views. +辅助视图。 + +765 +00:30:07,180 --> 00:30:09,380 +So that's basically it, okay? +然后就差不多了。 + +766 +00:30:09,382 --> 00:30:10,814 +And then you just return the MKAnnotationView. +然后就返回这个 MKAnnotationView。 + +767 +00:30:10,816 --> 00:30:14,851 +So it looks a lot like self or row in index path. +非常类似于indexPath的行。 + +768 +00:30:14,853 --> 00:30:17,086 +MKAnnotationView has some interesting properties. +MKAnnotationView有一些有趣的属性, + +769 +00:30:17,088 --> 00:30:20,256 +Like I said, you can set the image, that is the pin. +你可以给它设置图片,默认是个大头针。 + +770 +00:30:20,258 --> 00:30:22,074 +You've got this left and +你也可以设置标识视图的 + +771 +00:30:22,075 --> 00:30:23,891 +rightCalloutAccessoryView that you can set to an image view, +左右辅助视图,图片视图或者 + +772 +00:30:23,894 --> 00:30:25,327 +button, whatever you want. +一个按钮,什么都行。 + +773 +00:30:25,329 --> 00:30:27,128 +You can enable and disable it. +你可以激活或者隐藏它。 + +774 +00:30:27,130 --> 00:30:30,565 +You can have a center offset, because with the pin, people +你还可以设置中心偏移量,因为人们一般习惯于点击 + +775 +00:30:30,567 --> 00:30:33,200 +are gonna be clicking on the head of the pin, but the pin +大头针的头部,而大头针在地图上的点实际上是它的底部, + +776 +00:30:33,202 --> 00:30:36,503 +is actually pointed into the earth at a different spot. +跟头部并不是一个点, + +777 +00:30:36,505 --> 00:30:38,138 +So there's a little offset there. +是有一些偏移的。 + +778 +00:30:38,140 --> 00:30:39,706 +And you can even have draggable pins. +你还可以设置可拖拽的大头针。 + +779 +00:30:39,708 --> 00:30:43,209 +But if you have a draggable pin, then your MKAnnotations +但是如果你的大头针可以拖拽,那么你就需要实现注释点 + +780 +00:30:43,211 --> 00:30:46,746 +need to also implement to the setter for coordinate. +坐标的setter方法。 + +781 +00:30:46,748 --> 00:30:48,047 +Not just the getter for coordinate, but +不能只有getter,也需要 + +782 +00:30:48,049 --> 00:30:49,114 +the setter as well. +setter。 + +783 +00:30:51,484 --> 00:30:52,883 +Okay? + +784 +00:30:52,885 --> 00:30:57,054 +So, it's kind of a cool feature if one of the callout +有个很酷的特性就是如果你的标识视图的辅助视图,无论 + +785 +00:30:57,056 --> 00:30:58,788 +accessory views, either the left or +左右,是一个UIControl, + +786 +00:30:58,790 --> 00:31:03,092 +right is a UI Control, like a UIButton usually. +通常是按钮。 + +787 +00:31:03,094 --> 00:31:06,528 +Then, when it's touched, when the callout is touched, you'll +当它被点击的时候,地图视图的代理方法 + +788 +00:31:06,530 --> 00:31:10,666 +get this mapView method, calloutAccessoryControlTapped. +calloutAccessoryControlTapped就会被调用。 + +789 +00:31:10,668 --> 00:31:13,501 +So that's a really cool way to basically do target action +这是一个非常好的处理目标动作的方式。 + +790 +00:31:13,503 --> 00:31:16,471 +like thing, when someone clicks on the callout. +就是当有人点击标识视图的时候, + +791 +00:31:16,473 --> 00:31:17,638 +Okay? Not on the pin, but +并不是大头针, + +792 +00:31:17,640 --> 00:31:18,923 +on the callout code. + +793 +00:31:18,924 --> 00:31:20,207 +They click on the pin first, the callout comes out. +如果先点击大头针,标识视图才会出来。 + +794 +00:31:20,209 --> 00:31:21,942 +Now if you click on the callout, +现在如果你再点击标识视图, + +795 +00:31:21,944 --> 00:31:23,743 +if you put a UI control in there, +如果那上边有一个UIControl, + +796 +00:31:23,745 --> 00:31:25,311 +you'll get this message. +就会调用这个方法。 + +797 +00:31:25,312 --> 00:31:26,878 +And then you can go do something, like segue. +在这个方法里你就可以做一些类似于跳转的操作。 + +798 +00:31:26,881 --> 00:31:28,814 +Which is what we're gonna do in our demo. +一会儿我们的demo里就会这么做。 + +799 +00:31:28,816 --> 00:31:33,685 +Okay, so, I said that in didSelectAnnotationView, +我前边说过在didSelectAnnotationView方法里, + +800 +00:31:33,687 --> 00:31:35,420 +which it gets called when the pin gets clicked on, +当大头针被点击的时候会调用, + +801 +00:31:35,422 --> 00:31:37,288 +this is where you might wanna load up an image. +你需要在这里加载图片。 + +802 +00:31:37,290 --> 00:31:39,957 +So here's what an example of that might look like. +这里就是一个例子。 + +803 +00:31:39,959 --> 00:31:42,593 +I'm here in didSelectAnnotationView. +我在didSelectAnnotationView方法里。 + +804 +00:31:42,595 --> 00:31:45,295 +I'm saying, is the leftCalloutAccessoryView +我先检查标识视图的左辅助视图是否是 + +805 +00:31:45,297 --> 00:31:47,547 +a UIImageView? +一个图片视图? + +806 +00:31:47,548 --> 00:31:49,798 +If it is, then I'm gonna set its image to something, and +如果是的话,我要设置它的图片,在这里 + +807 +00:31:49,801 --> 00:31:53,002 +I might probably start a download in another thread +我可能要在另外一个线程开始下载。 + +808 +00:31:53,004 --> 00:31:54,236 +here, okay? + + +809 +00:31:54,238 --> 00:31:56,605 +In my demo of course, as you, as I'm famous for, +在我的demo里,你们应该知道, + +810 +00:31:56,607 --> 00:31:58,641 +I'm just gonna. +我肯定会先 + +811 +00:31:58,642 --> 00:32:00,676 +Block the main thread and make a call, but you don't need to +阻塞住主线程,但是你不需要再看这种代码了, + +812 +00:32:00,678 --> 00:32:03,812 +see that code, you've done it yourself numerous times, +你自己肯定已经做过很多次这种 + +813 +00:32:03,814 --> 00:32:05,297 +to go do a fetch. +抓取操作了。 + +814 +00:32:05,298 --> 00:32:06,781 +Now, If you do a fetch in another thread, +如果你在另外的线程里下载图片, + +815 +00:32:06,783 --> 00:32:08,082 +when it comes back, +当它回调的时候, + +816 +00:32:08,084 --> 00:32:11,285 +make sure that this annotation view is still associated with +要确定这个注释点视图依然关联着这个注释点, + +817 +00:32:11,287 --> 00:32:13,754 +that annotation, because it gets reused. +因为它有可能被复用。 + +818 +00:32:14,956 --> 00:32:16,356 +'Kay, everybody understand that? +大家都明白这个问题吗? + +819 +00:32:16,358 --> 00:32:17,857 +Raise your hand if you understand +如果明白我刚才说的复用的 + +820 +00:32:17,859 --> 00:32:19,825 +what I'm talking about with this reuse. +问题的话就举手。 + +821 +00:32:21,461 --> 00:32:23,278 +Okay? + +822 +00:32:23,279 --> 00:32:25,096 +How many people understood that in table views, +有多少人理解表格视图里 + +823 +00:32:25,098 --> 00:32:26,297 +the cells got reused? +单元格的复用? + +824 +00:32:27,666 --> 00:32:29,750 +'Kay, 100% of the people. +好,所有人都明白。 + +825 +00:32:29,751 --> 00:32:31,835 +So in a table view, if you went off and fetched an image, +在表格视图里,如果你去另外一个线程下载图片, + +826 +00:32:31,837 --> 00:32:34,771 +and it came back, isn't it possible that image would no +当他回调的时候,这个图片可能就不是加载在刚才的 + +827 +00:32:34,773 --> 00:32:37,206 +longer be associated with that cell? +那个单元格里了。 + +828 +00:32:37,208 --> 00:32:40,009 +Okay, everyone, raise your hand if you understand that? +如果能理解就举手。 + +829 +00:32:40,011 --> 00:32:41,210 +Okay, everybody understands that. +好,大家都理解了。 + +830 +00:32:41,212 --> 00:32:42,711 +Same thing here, okay? +这里也是一样的, + +831 +00:32:42,713 --> 00:32:47,315 +If you click on a map pin, and the callout comes up, and +如果你点了一个大头针,标识视图出来了, + +832 +00:32:47,317 --> 00:32:50,217 +you start a download for that little callout, and +然后你开始为标识视图下载图片,可能会用 + +833 +00:32:50,219 --> 00:32:51,518 +then it takes a long time, and +很长的时间, + +834 +00:32:51,520 --> 00:32:53,020 +meanwhile they click on another pin and +这时你又点了另外一个大头针,然后地图 + +835 +00:32:53,022 --> 00:32:54,821 +scroll us to another place on the map, +滚动到了另外一个位置, + +836 +00:32:54,823 --> 00:32:55,988 +that thing might be reused. +前边的那个大头针可能被复用了。 + +837 +00:32:55,990 --> 00:32:57,223 +And now the image comes back, and +这时图片下载好了, + +838 +00:32:57,225 --> 00:32:59,091 +it's no longer applicable there. +那么图片显示在这就是错的了。 + +839 +00:32:59,093 --> 00:32:59,991 +Okay? + +840 +00:32:59,993 --> 00:33:01,693 +So now we all understand, okay. +大家都明白了,对吧? + +841 +00:33:01,695 --> 00:33:04,262 +[LAUGH] I'm glad I went through that. +我很高兴我把这部分讲明白了。 + +842 +00:33:04,264 --> 00:33:05,296 +All right. + +843 +00:33:05,298 --> 00:33:06,948 +The map view. +好了,继续讲地图视图。 + +844 +00:33:06,949 --> 00:33:08,599 +How do you configure the map view's display with map type? +怎么配置地图的类型呢? + +845 +00:33:08,601 --> 00:33:10,634 +You just say whether it's satellite, a hybrid view, or +它是卫星视图,混合视图还是 + +846 +00:33:10,636 --> 00:33:12,102 +the standard street view. +标准的街道视图呢? + +847 +00:33:13,304 --> 00:33:15,538 +You can show things like the user current location. +你可以展示用户当前位置。 + +848 +00:33:15,540 --> 00:33:18,440 +If you say showUserCurrentLocation true, +如果你把showUserCurrentLocation设置为true, + +849 +00:33:18,442 --> 00:33:21,243 +then it's gonna put a little pin on there that always shows +就会有一个小个的大头针显示你当前的位置, + +850 +00:33:21,245 --> 00:33:23,211 +where you are, the user of the phone. +手机用户的位置。 + +851 +00:33:23,213 --> 00:33:25,180 +Okay, which is kinda fun. +很挺有趣的。 + +852 +00:33:25,181 --> 00:33:27,148 +And you can find out whether that's currently showing and +你可以设置当前位置是不是在地图上,以及 + +853 +00:33:27,150 --> 00:33:28,582 +what the user's location is. +用户的位置信息。 + +854 +00:33:28,584 --> 00:33:32,819 +The user's location comes back as an MKUserLocation, which +用户的位置信息返回类型是MKUserLocation,这是一个 + +855 +00:33:32,821 --> 00:33:36,589 +is an MK annotation so it has coordinate and all that. +MKAnnotation,所以它有坐标和别的。 + +856 +00:33:37,725 --> 00:33:40,759 +It's just for the user, so you know it's for the user. +这是给用户用的。 + +857 +00:33:40,761 --> 00:33:44,096 +You can also restrict the interaction with the map. +你还可以限制地图的交互。 + +858 +00:33:44,098 --> 00:33:46,498 +You might not want the person scrolling or +你可能不希望用户滚动地图或者 + +859 +00:33:46,500 --> 00:33:48,166 +going out of a certain area. +离开一个特定的区域。 + +860 +00:33:48,168 --> 00:33:50,034 +And you can control that by turning on and +你可以控制这些行为通过开关 + +861 +00:33:50,036 --> 00:33:51,602 +off the scrolling and zooming. +滚动和缩放。 + +862 +00:33:51,604 --> 00:33:54,137 +You can also turn off the pitching. +你还可以关掉拉伸手势。 + +863 +00:33:54,139 --> 00:33:55,472 +The Apple maps is a 3D. +苹果的地图是3D的, + +864 +00:33:55,474 --> 00:33:57,173 +Kind of a pseudo 3D thing, right? +其实是一种伪3D。 + +865 +00:33:57,175 --> 00:33:58,774 +Where you can tilt your camera up so +你可以把视角调高,这样就可以 + +866 +00:33:58,776 --> 00:34:00,275 +that you're looking down. +往下看。 + +867 +00:34:00,277 --> 00:34:02,494 +You can see the buildings. +可以看见建筑。 + +868 +00:34:02,495 --> 00:34:04,712 +You've probably all seen that, so you can control whether +你可能以前见过,所以你可以控制是不是允许用户这样做,或者 + +869 +00:34:04,715 --> 00:34:07,082 +that's allowed or whether it's gonna be a 2D map only. +只是显示一个2D的地图而已。 + +870 +00:34:07,084 --> 00:34:10,118 +And same thing rotation, do you always want north up or +转动也是一样的,你可能希望北面一直是朝上的,或者 + +871 +00:34:10,120 --> 00:34:12,420 +do you want to allow the user to turn north off to the side. +你允许用户调整方向。 + +872 +00:34:12,422 --> 00:34:16,723 +For that 3D thing, that kind of pseudo 3D, you can control +在3D的地图里,其实就是伪3D,你可以控制 + +873 +00:34:16,725 --> 00:34:20,860 +the camera which is like where the camera, how high it is, +视角的高度, + +874 +00:34:20,862 --> 00:34:24,897 +how steep it's looking, down that kind of stuff. +向下看的角度等等。 + +875 +00:34:24,899 --> 00:34:28,100 +Using an MKMapCamera you can just specify +用MKMapCamera你可以调整 + +876 +00:34:28,102 --> 00:34:30,468 +the coordinates of the camera. +视角的坐标。 + +877 +00:34:30,470 --> 00:34:33,604 +And the altitude is eyeAltitude, okay, +高度就是眼睛的高度。 + +878 +00:34:33,606 --> 00:34:35,206 +where it's looking from. +是从哪里往下看的。 + +879 +00:34:35,208 --> 00:34:37,608 +So, that's kinda cool. +这个非常酷。 + +880 +00:34:37,610 --> 00:34:40,310 +You can also control what part of the map is showing with +你还可以通过MKCoordinateRegion控制显示地图的哪个部分。 + +881 +00:34:40,312 --> 00:34:42,212 +the MKCoordinateRegion. + +882 +00:34:42,214 --> 00:34:45,682 +So an MKCoordinateRegion is just a CLLocationCoordinate2D, +MKCoordinateRegion就是一个CLLocationCoordinate2D + +883 +00:34:45,684 --> 00:34:46,982 +that's a spot on the map. +地图上的一个点。 + +884 +00:34:46,984 --> 00:34:49,885 +And then an MKCoordinateSpan which is latitude and +MKCoordinateSpan是围绕这个点的经纬度 + +885 +00:34:49,887 --> 00:34:52,454 +longitude distance around that, okay? +距离。 + +886 +00:34:52,456 --> 00:34:54,656 +And that's what it's gonna use to show the map. +这个就是我们需要显示在地图上的部分。 + +887 +00:34:54,658 --> 00:34:57,325 +Of course the map has a certain aspect ratio which +当然我们还需要维护一个高宽比 + +888 +00:34:57,327 --> 00:34:58,459 +it's going to maintain. +的值。 + +889 +00:34:58,461 --> 00:34:59,644 +So it's gonna try and +设置好以后,它会按照这个值尽可能 + +890 +00:34:59,645 --> 00:35:00,828 +show this region as best as possible, +的展示这个区域。 + +891 +00:35:00,830 --> 00:35:02,796 +I think it shows the entire region, so +我认为它会展示整个区域。 + +892 +00:35:02,798 --> 00:35:05,865 +there might be a little extra stuff depending on the aspect +可能会有一些多余的部分,这个取决于你屏幕或者 + +893 +00:35:05,867 --> 00:35:09,502 +ration of your screen or the view, versus the aspect ratio +视图的高宽比对比你需要显示区域 + +894 +00:35:09,504 --> 00:35:10,970 +that you're requesting in the region. +的高宽比。 + +895 +00:35:12,406 --> 00:35:14,539 +You can also just set the center coordinate. +你也可以直接设置区域中心的坐标。 + +896 +00:35:14,541 --> 00:35:15,940 +Like where do you want the center of the map is. +类似于你希望地图的中心的位置。 + +897 +00:35:15,942 --> 00:35:17,308 +If you don't care if it's size, +如果你不关心地图的大小, + +898 +00:35:17,310 --> 00:35:19,443 +you just want to zoom it to a certain spot, you can do that. +你可以让地图缩放到展示一个特定的点。 + +899 +00:35:19,445 --> 00:35:21,045 +It could be animated. +这个动作可以是动画形式的。 + +900 +00:35:21,047 --> 00:35:22,479 +You can also show annotation. +你还可以展示注释点。 + +901 +00:35:22,481 --> 00:35:25,949 +So you can say, make sure these five annotations are all +你可以让5个注释点都显示在屏幕上, + +902 +00:35:25,951 --> 00:35:29,686 +on screen and it'll figure out a region to collect them. +系统会定义一个区域包含他们。 + +903 +00:35:29,688 --> 00:35:32,588 +So, pretty cool way to control all that. +非常酷。 + +904 +00:35:32,590 --> 00:35:35,858 +There's lots of kind of functions and +这里还有很多方法和函数可以用来 + +905 +00:35:35,860 --> 00:35:39,594 +methods to convert from various coordinate spaces, +转换不同的坐标空间, + +906 +00:35:39,596 --> 00:35:43,264 +like the map has a coordinate system, okay? +比如地图有一个坐标系统。 + +907 +00:35:43,266 --> 00:35:47,868 +The world has a latitude and longitude coordinate system. +我们的地球也有一个经纬度的坐标系统。 + +908 +00:35:47,870 --> 00:35:49,803 +The view has a, you know, +在视图边界的内部,也有 + +909 +00:35:49,805 --> 00:35:51,872 +inside this bounds coordinate system. +坐标系统。 + +910 +00:35:51,874 --> 00:35:53,573 +And those three things are different. +很明显这三个系统是完全不同的。 + +911 +00:35:53,575 --> 00:35:56,126 +Obviously. + +912 +00:35:56,127 --> 00:35:58,678 +And so you can translate between those things. +你可以在他们三者之间转换。 + +913 +00:35:58,680 --> 00:36:02,014 +You understand why the world, the map is different because +你们知道为什么地球和地图的坐标系统不同吗? + +914 +00:36:02,016 --> 00:36:04,917 +the map is a projection, right, of the earth. +地图是地球在平面上的投射,而地球 + +915 +00:36:04,919 --> 00:36:06,885 +The earth is a big sphere. +是一个巨大的球体。 + +916 +00:36:06,887 --> 00:36:08,353 +In case you didn't know it's round. +不是圆形的。 + +917 +00:36:08,355 --> 00:36:11,422 +And so when you flatten it out into a flat screen it kind of, +所以当它被平铺在一个屏幕上的时候,它就会被 + +918 +00:36:11,424 --> 00:36:12,423 +you know, bends out. +弯曲。 + +919 +00:36:12,425 --> 00:36:16,226 +So you need to map that ,and so those, +所以需要建立它们的对应关系。 + +920 +00:36:16,228 --> 00:36:18,161 +that's why the coordinate system's not exactly the same +这就是为什么我们说起视图内坐标系统的时候 + +921 +00:36:19,231 --> 00:36:21,597 +as if you're talking about the view coordinate system. +会有不同的系统。 + +922 +00:36:21,599 --> 00:36:25,568 +So go look through the documentation there's probably +如果你去看文档的话,会发现大概有25个函数以及 + +923 +00:36:25,570 --> 00:36:28,937 +25 different functions, and probably another dozen or so +10几个函数 + +924 +00:36:28,939 --> 00:36:30,439 +methods that will convert back and +用来来回转换这些 + +925 +00:36:30,441 --> 00:36:34,909 +forth between all these things. +坐标系统。 + +926 +00:36:34,911 --> 00:36:37,812 +Another map view delegate method +地图视图的另外一个非常有趣的 + +927 +00:36:37,814 --> 00:36:41,315 +which is kind of interesting is didChangeRegionAnimated. +代理方法是didChangeRegionAnimated。 + +928 +00:36:41,317 --> 00:36:44,751 +So, this is telling you that the region that it's showing +它会告诉你现在显示在地图里的区域变化了 + +929 +00:36:44,753 --> 00:36:48,221 +in the map changed and I've finished animating it. +而且我已经完成了切换动画。 + +930 +00:36:48,223 --> 00:36:49,856 +Now why do you want to know that? +为什么我们需要知道这个呢? + +931 +00:36:49,858 --> 00:36:51,157 +Well because sometimes you wanna +因为有些时候你需要 + +932 +00:36:51,159 --> 00:36:54,293 +do what's called animation chaining in the map view. +调用地图视图的动画链。 + +933 +00:36:54,295 --> 00:36:56,328 +So let's say you're looking at New York City, and +举个例子,如果你的地图现在显示的是纽约市, + +934 +00:36:56,330 --> 00:36:59,597 +you wanna switch the user over to looking at San Francisco. +你想切换到旧金山, + +935 +00:36:59,599 --> 00:37:02,467 +Well you could just say set region San Francisco. +你可以把当前区域设置成旧金山。 + +936 +00:37:02,469 --> 00:37:05,002 +And it would [SOUND] zoom over there really fast. +这样地图就会呼的一下快速的平移过去。 + +937 +00:37:05,004 --> 00:37:07,104 +So fast that you wouldn't see anything in between. +快的你根本看不清中间的东西。 + +938 +00:37:07,106 --> 00:37:10,173 +You wouldn't see Kansas or anything on the way, okay? +比如你不会看见中间的堪萨斯。 + +939 +00:37:10,175 --> 00:37:13,143 +But a better way to do it would be to zoom out to show +一个更好的办法就是先把地图放大,展示整个美国, + +940 +00:37:13,145 --> 00:37:16,879 +the whole United States and then zoom in to San Francisco. +然后再缩小到旧金山。 + +941 +00:37:16,881 --> 00:37:17,980 +Right? + +942 +00:37:17,982 --> 00:37:19,247 +See how that would look better? +这样会更好一些对吧? + +943 +00:37:19,249 --> 00:37:21,616 +You're up in New York, up to the United States and +现在是纽约,放大到整个美国,在 + +944 +00:37:21,618 --> 00:37:23,351 +down to San Francisco. +缩小到旧金山。 + +945 +00:37:23,352 --> 00:37:25,085 +Well the way to do that is you set your region to be +这么做的方法就是把你的区域设置成整个美国, + +946 +00:37:25,088 --> 00:37:26,887 +the entire United States, and +然后动画完成的时候这个 + +947 +00:37:26,889 --> 00:37:29,189 +when that animation finishes you'll get this. +方法就会调用。 + +948 +00:37:29,191 --> 00:37:30,924 +And now you set your region to be San Francisco. +这时你把区域再设置成旧金山。 + +949 +00:37:30,926 --> 00:37:32,926 +Simple chaining. +简单的动画链。 + +950 +00:37:32,928 --> 00:37:35,862 +Okay? +明白了吧? + +951 +00:37:35,864 --> 00:37:39,131 +Searching for places in the world by name. +还可以用名字搜索世界上的地点。 + +952 +00:37:39,133 --> 00:37:40,899 +So this is a really cool feature, +这个非常酷。 + +953 +00:37:40,901 --> 00:37:43,201 +where you can actually look things up by name. +因为可以通过名字来找地方。 + +954 +00:37:43,203 --> 00:37:45,537 +So you could, for example, have a query like, +你可以做一个查询,比如这样, + +955 +00:37:45,539 --> 00:37:48,706 +show me Ike's, which, I guess, is not gonna work any more. +我搜索 "Ike",我估计应该找不到什么地方。 + +956 +00:37:48,708 --> 00:37:52,176 +But you should say show me Ike's and +你可以用"Ike"建立一个 + +957 +00:37:52,178 --> 00:37:54,411 +you create this query that has an n there and +查询然后再建立一个 + +958 +00:37:54,413 --> 00:37:57,180 +then you create an MKLocalSearch. +MKLocalSearch + +959 +00:37:57,182 --> 00:37:59,282 +And you give it that request and +你把查询赋给它,然后它就会 + +960 +00:37:59,284 --> 00:38:02,685 +it will fire off a thread to go out on the network, +在另外一个线程开始使用网络查询。 + +961 +00:38:02,687 --> 00:38:05,788 +look up Ike's somewhere in some database, and +在数据库里查询 Ike,然后返回 + +962 +00:38:05,790 --> 00:38:09,158 +return information about where it is to you, and +相关的信息, + +963 +00:38:09,160 --> 00:38:11,727 +it'll return to you on this other thread. +同样也会在另外一个线程返回给你。 + +964 +00:38:11,729 --> 00:38:14,462 +I believe the, all right, I'm sorry, in this closure. +我相信,哦对不起,在闭包里返回给你。 + +965 +00:38:14,464 --> 00:38:16,731 +And I believe this closure executes on the main queue, +我相信这个闭包是在主线程执行的, + +966 +00:38:16,733 --> 00:38:20,001 +because this is all UI stuff so that closure you don't have +因为我们这个框架都是关于UI的,所以这个闭包你不需要担心 + +967 +00:38:20,003 --> 00:38:21,769 +to worry about it being on a different queue. +它是在另外一个线程执行的。 + +968 +00:38:21,771 --> 00:38:24,838 +So it can execute this closure with the response it got and +这个闭包会返回查询结果然后 + +969 +00:38:24,840 --> 00:38:26,373 +then you can put it on your map. +你就可以把它们放到地图上了。 + +970 +00:38:26,375 --> 00:38:29,075 +It gives you an MKPlacemark, it actually gives you +它会返回一个MKPlacemark ,实际上是一个MKMapItem包含一个 + +971 +00:38:29,077 --> 00:38:32,178 +an MKMapItem and inside that there's an MKPlacemark. +MKPlacemark + +972 +00:38:32,180 --> 00:38:33,445 +An MKPlacemark +MKPlacemark里面包含 + +973 +00:38:33,447 --> 00:38:35,647 +gives you more than just the latitude and longitude. +经纬度, + +974 +00:38:35,649 --> 00:38:38,249 +It gives you the name of the location, Ike's, and +位置的名字,邮编 + +975 +00:38:38,251 --> 00:38:40,952 +the postal code, the region it's in, and all that stuff. +它所在的区域等等, + +976 +00:38:40,954 --> 00:38:44,755 +So, it's kind of a super location thing. +就好像是一个超级的位置信息。 + +977 +00:38:44,757 --> 00:38:48,559 +And, if you have a map item, and you're not showing maps in +如果你有一个 MKMapItem,但是在你的app里没有显示地图 + +978 +00:38:48,561 --> 00:38:50,761 +your app, you can actually open it up in the maps app by +的功能,那么你可以通过调用 openInMapsWithLaunchOptions 方法 + +979 +00:38:50,763 --> 00:38:53,763 +saying openInMapsWithLaunchOptions. +来在一个地图app里打开它。 + +980 +00:38:53,765 --> 00:38:55,732 +And you give these various options like, +你可以传递很多的选项,比如 + +981 +00:38:55,734 --> 00:38:57,784 +do you want to show traffic? +你是否希望现实交通, + +982 +00:38:57,785 --> 00:38:59,835 +Okay, this is a, some kind of driving thing, you want to +这是与驾驶有关的, 你可以显示交通或者别的什么, + +983 +00:38:59,837 --> 00:39:01,603 +show traffic or whatever, you put the options in there. +把你需要的选项传递过去就好了。 + +984 +00:39:01,605 --> 00:39:07,108 +And the map item will display on the maps app, okay? +然后这个item就会显示在地图app里。 + +985 +00:39:07,110 --> 00:39:08,843 +So that's local searching. +这个是位置搜索。 + +986 +00:39:08,845 --> 00:39:11,412 +You can also get a similar thing for directions, +关于方向,也有一些类似的东西。 + +987 +00:39:11,414 --> 00:39:15,816 +you wanna go from one place to another and +你希望从一个地方去到另外一个地方, + +988 +00:39:15,818 --> 00:39:18,585 +it will send you back some routes that you can get there. +它会返回给你路线。 + +989 +00:39:18,587 --> 00:39:21,554 +One, two, three routes maybe, and +可能是一条两条三条路线, + +990 +00:39:21,556 --> 00:39:24,023 +it'll also even give you a drawing. +而且会画在地图上。 + +991 +00:39:24,025 --> 00:39:25,491 +A thing called an MKPolyline +这种路线叫做MKPolyline。 + +992 +00:39:25,493 --> 00:39:27,459 +which I'm gonna talk about in a second. +我一会儿会讲到这个。 + +993 +00:39:27,461 --> 00:39:30,028 +That you can overlay onto the map to show the route. +你可以在地图上绘制路线了。 + +994 +00:39:30,030 --> 00:39:31,429 +So that's kinda cool. +非常酷。 + +995 +00:39:31,431 --> 00:39:33,964 +'Kay and this also asynchronous just like +这个跟刚才讲的位置搜索一样都是 + +996 +00:39:33,966 --> 00:39:38,368 +the last local search was. +异步的。 + +997 +00:39:38,370 --> 00:39:40,020 +Okay. + +998 +00:39:40,021 --> 00:39:41,671 +So let's talk about those overlays, like MKPolyline, +下面我们来讲覆盖层,比如MKPolyline, + +999 +00:39:41,673 --> 00:39:42,505 +that shows the root. +那个显示路线的东西。 + +1000 +00:39:42,507 --> 00:39:43,873 +How do you do overlays? +我们怎么去绘制覆盖层? + +1001 +00:39:43,875 --> 00:39:46,308 +Overlays look very much like annotations. +覆盖层跟注释点很像。 + +1002 +00:39:46,310 --> 00:39:51,613 +In fact, the MKOverlay protocol is a subclass, +实际上,MKOverlay 是 MKAnnotation 的子类, + +1003 +00:39:51,615 --> 00:39:55,750 +or sub protocol of the MKAnnotation. +或者说子协议。 + +1004 +00:39:55,752 --> 00:39:58,852 +So, an MKOverlay has everything MKAnotation has, +所以 MKAnnotation 有 MKAnotation 所有的元素, + +1005 +00:39:58,854 --> 00:39:59,753 +coordinates. +比如坐标。 + +1006 +00:39:59,755 --> 00:40:02,255 +Which is the center of the overlay. +坐标就是覆盖层的中心。 + +1007 +00:40:02,257 --> 00:40:03,990 +And then the title and a subtitle. +然后就是标题和副标题。 + +1008 +00:40:03,992 --> 00:40:06,525 +And it also adds boundingMapRect. +还有boundingMapRect属性。 + +1009 +00:40:06,527 --> 00:40:09,161 +So that's the rectangle that contains this overlay. +这是包含整个覆盖层的矩形。 + +1010 +00:40:09,163 --> 00:40:11,080 +'Kay? + +1011 +00:40:11,081 --> 00:40:12,998 +So, if you're driving from San Francisco to San Jose. +如果你开车从旧金山到圣何塞。 + +1012 +00:40:13,000 --> 00:40:14,399 +It contains that. +那这个矩形就应该包括它们。 + +1013 +00:40:14,401 --> 00:40:17,602 +It also has a method that you can ask it, +这里还有一个方法你可以知道是否与 + +1014 +00:40:17,604 --> 00:40:20,404 +do you intersect this other Rect. +传入矩形有交叉。 + +1015 +00:40:20,406 --> 00:40:23,674 +Now if you don't implement that method in your MKOverlay +如果你不在MKOverlay协议里实现这个方法, + +1016 +00:40:23,676 --> 00:40:26,710 +protocol, it'll just use the boundingMapRect, and +那么它就只会用boundingMapRect,然后检查是不是 + +1017 +00:40:26,712 --> 00:40:28,411 +see if you intersect that. +跟这个矩形有交叉。 + +1018 +00:40:28,413 --> 00:40:29,645 +But you can actually have so if your, +但是如果你想要知道你的路线是不是 + +1019 +00:40:29,647 --> 00:40:32,548 +if you wanna see if the actual root intersects it, +经过某一区域,那么你就可以实现这个方法。 + +1020 +00:40:32,550 --> 00:40:35,984 +then you can actually see if it intersects, as opposed to +然后你就可以检查它是不是跟某个矩形有交叉,而不是去检查它是不是被 + +1021 +00:40:35,986 --> 00:40:38,954 +whether the rectangle contains it, which is kind of a gross +包含在某一个矩形里,那样只是很粗略的 + +1022 +00:40:38,956 --> 00:40:41,489 +estimate of whether it intersects. +估计。 + +1023 +00:40:41,491 --> 00:40:44,158 +So, just like with an annotation, you have view for +跟注释点一样,注释点可以自定义视图。 + +1024 +00:40:44,160 --> 00:40:45,810 +annotation. + +1025 +00:40:45,811 --> 00:40:47,461 +You have the same thing, for overlays. +覆盖层也是一样的。 + +1026 +00:40:47,463 --> 00:40:49,129 +You can actually have view for overlay. +你也可以给覆盖层自定义视图。 + +1027 +00:40:49,131 --> 00:40:52,265 +But usually, what we do is use renderer for overlay. +但是通常我们都会重新渲染覆盖层。 + +1028 +00:40:52,267 --> 00:40:54,200 +So an MKOverlayRenderer, +这里就会用到 MKOverlayRenderer 。 + +1029 +00:40:54,202 --> 00:40:58,204 +is something that knows how to draw an overlay on the map. +它可以知道如何在地图上绘制覆盖层。 + +1030 +00:40:58,206 --> 00:40:59,304 +Okay? + +1031 +00:40:59,306 --> 00:41:01,473 +And so usually you have to render for +通常我们需要返回一个渲染用来渲染 + +1032 +00:41:01,475 --> 00:41:03,241 +overlay and we're gonna return to renderer. +覆盖层。 + +1033 +00:41:03,243 --> 00:41:05,076 +Now we could write our own renderers. +我们可以实现自己的渲染, + +1034 +00:41:05,078 --> 00:41:07,878 +It's just a sub-class of MKOverlayRenderer but +通过实现 MKOverlayRenderer 的子类,但是一般我们 + +1035 +00:41:07,880 --> 00:41:11,548 +usually we're gonna be using a overlay that's built in like +我们都会用系统自带的渲染,比如MKPolyLineRenderer + +1036 +00:41:11,550 --> 00:41:14,818 +MKPolyLineRenderer which is for drawing that route along +是用来画路线的。 + +1037 +00:41:14,820 --> 00:41:18,355 +the roads or MKCircleRenderer which renders circles. +MKCircleRenderer 用来渲染圆形。 + +1038 +00:41:18,357 --> 00:41:20,990 +Or MKPolylineRenderer. +或者 MKPolylineRenderer + +1039 +00:41:20,992 --> 00:41:23,159 +Which, PolygonRenderer, rather. +不对,是 PolygonRenderer + +1040 +00:41:23,161 --> 00:41:25,260 +Which is going to render some polygon. +用来渲染多边形。 + +1041 +00:41:25,262 --> 00:41:27,729 +Arbitrary Bezier polygon. +用贝塞尔曲线绘制的任意多边形。 + +1042 +00:41:27,731 --> 00:41:29,964 +Or even the MKTileOverlayRenderer. +甚至是MKTileOverlayRenderer, + +1043 +00:41:29,966 --> 00:41:32,767 +Which will render tiled images. +可以渲染平铺的图片。 + +1044 +00:41:32,769 --> 00:41:35,970 +And you can use the last one there to replace the Apple +你们可以用这个把苹果的地图替换成 + +1045 +00:41:35,972 --> 00:41:37,438 +maps with your own map. +自己的地图。 + +1046 +00:41:37,440 --> 00:41:38,839 +So people have done some pretty cool apps. +有人做了一些很酷的app。 + +1047 +00:41:38,841 --> 00:41:42,242 +We've had ancient maps, some ancient mariner maps. +他们做了一些古地图,古代的航海图。 + +1048 +00:41:42,244 --> 00:41:43,944 +You know and +你现在知道了 + +1049 +00:41:43,945 --> 00:41:45,645 +they would actually over, you know use the tower renderer to +他们实际上是用最后的这种方式渲染,从而达到用自己的地图代替苹果 + +1050 +00:41:45,647 --> 00:41:47,346 +put that in the place of Apple maps. +自带地图的目的。 + +1051 +00:41:47,348 --> 00:41:49,248 +So they're still getting all the same feature of the Apple +所以这些地图都有跟苹果地图完全一样的特性比如 + +1052 +00:41:49,250 --> 00:41:51,750 +maps where they can zoom around, set the region, but +缩放,设置区域,但是它们的背景 + +1053 +00:41:51,752 --> 00:41:54,352 +they're using these kind of cool ancient maps +用的是非常酷的古代地图。 + +1054 +00:41:54,354 --> 00:41:56,521 +as the the background. + +1055 +00:41:56,523 --> 00:41:59,490 +And they showed things like people who sail around +这样他们的app就可以记录人们的路线, + +1056 +00:41:59,492 --> 00:42:01,191 +the world and they showed their track but +但是这些路线确显示在古代的地图上, + +1057 +00:42:01,193 --> 00:42:03,493 +overlayed on these ancient maps which is kinda cool. +非常酷对吧。 + +1058 +00:42:03,495 --> 00:42:05,295 +So you can do all of that. +这个就可以通过渲染实现。 + +1059 +00:42:05,297 --> 00:42:07,630 +So all of these things, circles, +所有这些圆形,线型, + +1060 +00:42:07,632 --> 00:42:11,167 +polylines, polygons they have their own renderers. +多边形,它们都有自带的渲染。 + +1061 +00:42:11,169 --> 00:42:12,501 +You don't have to write your own renderer. +你不需要写自己的渲染。 + +1062 +00:42:12,503 --> 00:42:15,303 +You just have to create an MKPolyline which we're maybe +我们一会儿可能会在demo里就会建立一个 + +1063 +00:42:15,305 --> 00:42:16,822 +gonna do on the demo. +MKPolyline 渲染。 + +1064 +00:42:16,823 --> 00:42:18,340 +I don't think we'll have time for that but we might. +也许没时间做这个了不过也是有可能的。 + +1065 +00:42:19,642 --> 00:42:21,475 +And the, then you just use this as the renderer. +你只需要调用这些自带的渲染就可以了。 + +1066 +00:42:22,445 --> 00:42:23,944 +And that's it. + +1067 +00:42:23,946 --> 00:42:25,879 +All right. So it's time for the demo. +好了,开始今天的demo。 + +1068 +00:42:25,881 --> 00:42:31,884 +So what I'm gonna do is I'm going to load up a GPX file. +今天我们要做的就是加载一个GPX文件。 + +1069 +00:42:31,886 --> 00:42:33,552 +I have a parser, a GPX parser, +我有一个GPX解析器。 + +1070 +00:42:33,554 --> 00:42:36,254 +that I've written that just parses the GPX file. +是我以前写的用来解析GPX文件的东西。 + +1071 +00:42:36,256 --> 00:42:38,023 +And really it just returns two things. +它实际上返回两个东西。 + +1072 +00:42:38,025 --> 00:42:41,526 +Waypoints, which are just, you know, latitude and +一个是路点,你懂得,就是经纬度, + +1073 +00:42:41,528 --> 00:42:45,262 +longitude, with possibly some hyperlinks to images or +还有可能有图片的链接或者别的什么。 + +1074 +00:42:45,264 --> 00:42:46,129 +other things like that. +比如 + +1075 +00:42:46,131 --> 00:42:47,697 +Timestamp. +时间戳。 + +1076 +00:42:47,699 --> 00:42:49,799 +And then it also returns what are called Trax. +还会返回我们叫做 Trax 的东西。 + +1077 +00:42:49,801 --> 00:42:54,069 +And a track is just a bunch of fixes, a bunch of waypoints +实际上就是很多带有时间戳的路点。 + +1078 +00:42:54,071 --> 00:42:56,672 +with timestamps that show when you went on a trax. +用来显示我们运动的轨迹。 + +1079 +00:42:56,674 --> 00:42:58,039 +So that's it. +就是这些。 + +1080 +00:42:58,041 --> 00:42:59,307 +The overlays, if we had time for +覆盖层,如果有时间的话我们可能 + +1081 +00:42:59,309 --> 00:43:01,342 +if which I don't think we're going to. +会做一下,不过很可能没时间。 + +1082 +00:43:01,344 --> 00:43:03,711 +We might would be the trax. +我们会做一下trax。 + +1083 +00:43:03,713 --> 00:43:06,013 +And then these pins would be the waypoints, +地图上的大头针就是路点, + +1084 +00:43:06,015 --> 00:43:07,380 +just these waypoints. +我们刚才说到的路点。 + +1085 +00:43:07,382 --> 00:43:08,815 +Okay? + +1086 +00:43:08,817 --> 00:43:11,817 +So the waypoints inside the trax, we can't fix this. +在trax里的路点我们叫做 fix。 + +1087 +00:43:11,819 --> 00:43:13,986 +Just so we're not confused about the difference. +这样就不会有名称上的混淆。 + +1088 +00:43:13,988 --> 00:43:15,654 +So waypoint is a stand alone waypoint, +路点就指的是单独的路点。 + +1089 +00:43:15,656 --> 00:43:16,654 +that's gonna be a pin. +就是地图上的大头针。 + +1090 +00:43:16,656 --> 00:43:18,823 +The fixes are inside the track. +fix 就是trax内部的路点。 + +1091 +00:43:18,825 --> 00:43:21,209 +Okay? + +1092 +00:43:21,210 --> 00:43:23,594 +And so, because I won't get back the slides, Friday, +今天我们不会再回到幻灯片了,周五会有 + +1093 +00:43:23,596 --> 00:43:25,495 +section, Apple Watch +Apple Watch的内容。 + +1094 +00:43:25,497 --> 00:43:28,598 +And then next week, all kinds of topics I'm gonna cover +下周,我会谈到包括持久性存储在内的幻灯片上的 + +1095 +00:43:28,600 --> 00:43:29,999 +next week including persistence, +话题。 + +1096 +00:43:30,001 --> 00:43:31,834 +which I didn't get to on Monday. +应该周一讲的但是没讲。 + +1097 +00:43:31,836 --> 00:43:35,537 +But on other things not even on this list I'll probably +不过在这里边没有的东西可能也会 + +1098 +00:43:35,539 --> 00:43:36,671 +ment, get into. +涉及。 + +1099 +00:43:36,673 --> 00:43:38,306 +All right. + +1100 +00:43:38,308 --> 00:43:41,975 +So, we actually have Trax started so +我们前边已经开始做 Trax 了, + +1101 +00:43:41,977 --> 00:43:43,844 +let's go back to Trax. +所以我们回来继续。 + +1102 +00:43:43,846 --> 00:43:45,512 +This was pretty much where we left off. +现在这里跟我们上次留下的差不多。 + +1103 +00:43:45,514 --> 00:43:48,314 +The only thing I changed about this is I renamed my view +唯一变的东西应该就是我把原来简单的 viewController 重命名成了 + +1104 +00:43:48,316 --> 00:43:51,050 +controller to be GPXviewcontroller instead of +GPXviewcontroller 。 + +1105 +00:43:51,052 --> 00:43:52,851 +just plain viewcontroller. + +1106 +00:43:52,853 --> 00:43:55,420 +And I also put the GPX parser code in here, +我还把我写的GPX的解析器相关代码放了进来。 + +1107 +00:43:55,422 --> 00:43:57,489 +which I'm gonna show you in a second. +一会儿就给你们看。 + +1108 +00:43:57,491 --> 00:43:59,457 +Otherwise you can see we still have this app delegate. +这里你看到的是 app delegate。 + +1109 +00:43:59,459 --> 00:44:02,393 +We're posting this notification here. +我们在这里发布了一个通知。 + +1110 +00:44:02,395 --> 00:44:04,862 +And now here's my GPXController.swift. +这里是我们的 GPXController.swift 。 + +1111 +00:44:04,864 --> 00:44:06,063 +And I'm getting, + +1112 +00:44:06,065 --> 00:44:08,164 +I took out the little text view that was in here. +我把之前加过的文本视图去掉了。 + +1113 +00:44:09,100 --> 00:44:11,400 +And so here I'm adding the observer and +在这里我加了一个观察者来监听 + +1114 +00:44:11,402 --> 00:44:12,735 +I'm getting notified. +这个通知。 + +1115 +00:44:12,737 --> 00:44:17,439 +So in here we are going to just have to take this URL, +这里我们可以取到一个URL。 + +1116 +00:44:17,441 --> 00:44:18,940 +it's a URL for a GPX file. +这是GPX文件的URL 。 + +1117 +00:44:18,942 --> 00:44:20,641 +So we're gonna use this GPX parser that I +这里我们要用到我之前说过的 + +1118 +00:44:20,643 --> 00:44:22,143 +was talking about. +GPX解析器。 + +1119 +00:44:22,144 --> 00:44:23,644 +To parse it, get the waypoints out of there. +来解析,得到路点的信息。 + +1120 +00:44:23,646 --> 00:44:25,178 +Then we're gonna put those waypoints on the map. +然后我们就可以把路点放到地图上了。 + +1121 +00:44:25,180 --> 00:44:26,312 +That's the first thing we're gonna do. +这是我们首先要做的事儿。 + +1122 +00:44:26,314 --> 00:44:27,914 +And if we have time, which we won't, +如果我们还有时间,不过应该是没有, + +1123 +00:44:27,916 --> 00:44:30,883 +we're gonna get the trax out and make an overlay of that. +我们要把trax取出来,然后在地图上做一个覆盖层。 + +1124 +00:44:30,885 --> 00:44:33,052 +But let's focus on the waypoints. +现在,我们先来做路点。 + +1125 +00:44:33,054 --> 00:44:35,721 +So, how are we gonna do this? +我们要怎么做呢? + +1126 +00:44:35,723 --> 00:44:37,856 +First of all, I'm actually take a timeout and +首先我们要先把路点放下,做一些 + +1127 +00:44:37,858 --> 00:44:40,491 +write my, do my user interface for this. +UI方面的工作。 + +1128 +00:44:40,493 --> 00:44:42,310 +Okay? + +1129 +00:44:42,311 --> 00:44:44,128 +So let's go over to our storyboard, over here, +切换到我们的故事板。 + +1130 +00:44:44,130 --> 00:44:48,865 +and in my storyboard I've already changed this to be +在故事板里我已经把这个视图控制器从 ViewController 改成了 + +1131 +00:44:48,867 --> 00:44:51,668 +a GPX ViewController, instead of a view controller. +GPXViewController。 + +1132 +00:44:51,670 --> 00:44:54,804 +And I'm just gonna drag a map out, so I'm gonna go down here +我现在要拖出一个地图,找到下边的对象栏, + +1133 +00:44:54,806 --> 00:44:59,074 +to my object palette here, I'm gonna search for map. +搜索地图。 + +1134 +00:45:00,544 --> 00:45:02,094 +There it is. +在这。 + +1135 +00:45:02,095 --> 00:45:03,645 +I'm gonna drag a map out and I'm just gonna put it in here. +把地图拖出来放在这。 + +1136 +00:45:03,647 --> 00:45:07,448 +Let's go ahead and put it in the right spot. +放到正确的位置上。 + +1137 +00:45:07,450 --> 00:45:09,950 +We'll put it right filling in the whole screen. +让它填满整个屏幕。 + +1138 +00:45:09,952 --> 00:45:12,386 +Let's do our constraints. +现在开始加约束。 + +1139 +00:45:12,388 --> 00:45:14,921 +Let's double check that our constraints look good. +再来复查一下约束是不是OK了。 + +1140 +00:45:16,091 --> 00:45:17,356 +Yeah. No magic numbers. +好的,没有魔法数字。 + +1141 +00:45:17,358 --> 00:45:18,557 +That all looks good to me. +看起来没什么问题了。 + +1142 +00:45:19,526 --> 00:45:21,292 +Let's create an outlet to it, so +然后建一个outlet。 + +1143 +00:45:21,294 --> 00:45:24,062 +I'm just gonna control drag into my controller here. +把地图 ctrl + 拖拽到我的视图控制器。 + +1144 +00:45:24,064 --> 00:45:25,396 +I'm gonna call this my mapView. +起名叫 mapView. + +1145 +00:45:25,398 --> 00:45:27,197 +All right? + +1146 +00:45:27,199 --> 00:45:30,500 +So now we're nice and hooked up to our user interface. +现在UI都正确的连接起来了。 + +1147 +00:45:30,502 --> 00:45:32,869 +And notice that we have an error here right away. +不过我们这里有一个错误。 + +1148 +00:45:32,871 --> 00:45:35,071 +That's because I have to. +那是因为我还没导入 + +1149 +00:45:35,073 --> 00:45:37,373 +Import MapKit. +MapKit。 + +1150 +00:45:37,375 --> 00:45:41,743 +Okay, if I don't import MapKit I don't get any of that +如果我不导入MapKit的话,我就不能得到这些字符。 + +1151 +00:45:41,745 --> 00:45:45,146 +symbology, the map, map, MapKit symbols. +地图相关的字符。 + +1152 +00:45:45,148 --> 00:45:46,247 +Okay? Now + +1153 +00:45:46,249 --> 00:45:48,182 +when the mapView outlet gets set, +当我们地图视图的outlet连接好, + +1154 +00:45:48,184 --> 00:45:50,617 +that's a good time to actually configure our mapView. +这是一个配置地图视图很好的时机。 + +1155 +00:45:50,619 --> 00:45:53,086 +And what do we need to configure that mapView? +我们要怎么配置呢? + +1156 +00:45:53,088 --> 00:45:56,823 +Not much, I'm just gonna say that I want the map type. +没有太多东西,我只需要定义地图的类型为 + +1157 +00:45:56,825 --> 00:45:58,057 +To be the satellite. +卫星。 + +1158 +00:45:59,794 --> 00:46:03,095 +And I'm also going to set the map views delegate +然后把它的代理设置为self。 + +1159 +00:46:03,097 --> 00:46:06,498 +to be myself because as you saw in the slides +因为从幻灯片你们知道有很多东西需要 + +1160 +00:46:06,500 --> 00:46:09,667 +a lot of things we need to do with the map views delegate. +地图视图的代理去做。 + +1161 +00:46:09,669 --> 00:46:13,904 +So I have to say I'm an MKMapViewDelegate. +在这里加上 MKMapViewDelegate 。 + +1162 +00:46:13,906 --> 00:46:14,938 +Okay? + +1163 +00:46:14,940 --> 00:46:16,573 +Let's make our screen bigger. +把屏幕弄大一点。 + +1164 +00:46:20,044 --> 00:46:20,743 +Okay. + +1165 +00:46:20,745 --> 00:46:21,710 +What else we've got. +这又是什么错误。 + +1166 +00:46:21,712 --> 00:46:22,977 +Oh yes, all right. +哦,对了, + +1167 +00:46:22,979 --> 00:46:26,380 +This is in the didSet of this. +配置应该在didSet里。 + +1168 +00:46:29,051 --> 00:46:30,601 +All right. +好了。 + +1169 +00:46:30,602 --> 00:46:32,152 +So as soon as that outlet is set, we're gonna make our +当我们的outlet连接好以后,地图就会被设置成 + +1170 +00:46:32,154 --> 00:46:34,821 +mapView satellite only, [INAUDIBLE] no roads over it. +卫星模式,看不到路名什么的。 + +1171 +00:46:34,823 --> 00:46:35,922 +And we're [INAUDIBLE]. +然后我们[听不清]。 + +1172 +00:46:35,924 --> 00:46:37,723 +Now this is something probably we'd wanna +在地图模式这里我们后边可能会需要加一个 + +1173 +00:46:37,725 --> 00:46:39,458 +set with a segmented control maybe, +选择控制器。 + +1174 +00:46:39,460 --> 00:46:42,294 +because it has three options of some like that. +因为事实上应该有3个选项。 + +1175 +00:46:42,296 --> 00:46:45,096 +But here, I'm just gonna have the satellite only. +但是这里就设置成卫星。 + +1176 +00:46:46,232 --> 00:46:49,433 +Now, the next thing that I need is my public API, +下边我需要设置我的公共API。 + +1177 +00:46:49,435 --> 00:46:52,503 +basically, for my GPX viewcontroller, and I'm gonna have +对于我的GPX视图控制器来说,我的公共API就是 + +1178 +00:46:52,505 --> 00:46:57,707 +my public API be that you can set a GPX URL on me. +GPX文件的URL。 + +1179 +00:46:58,877 --> 00:47:02,111 +And if you set GPX URL, I'm gonna load it up and +如果这个URL设置了,我就要把它加载进来以显示 + +1180 +00:47:02,113 --> 00:47:04,279 +show you the waypoints and trax. +路点和路径。 + +1181 +00:47:04,281 --> 00:47:06,348 +Okay? That's basically the way +明白了吗?基本上就是这么 + +1182 +00:47:06,350 --> 00:47:07,549 +my thing works. +做的。 + +1183 +00:47:07,551 --> 00:47:09,083 +So what is this gonna look like? +那我要具体怎么做呢? + +1184 +00:47:09,085 --> 00:47:10,918 +Well, let's do the didSet in here, so +我们在didSet这里做,每次 + +1185 +00:47:10,920 --> 00:47:14,955 +anytime someone sets the URL, we need to load it up. +有人设置这个URL的时候,我就要加载这个文件。 + +1186 +00:47:14,957 --> 00:47:19,959 +So I'm gonna say if the URL that they gave me is not nil,. +这里我要写如果给我的URL不为空。 + +1187 +00:47:21,096 --> 00:47:24,263 +Then I'm going to parse it, so I'm gonna use this new, +我就要解析它,这里我用到了新的GPX类, + +1188 +00:47:24,265 --> 00:47:26,865 +this class, GPX, which I'll show you in a second. +一会儿我会给你们看这个类。 + +1189 +00:47:26,867 --> 00:47:28,834 +And it has a method called parse, and +它里面有一个parse方法, + +1190 +00:47:28,836 --> 00:47:30,535 +you can see that parse takes a URL, +接受一个url的参数,和一个 + +1191 +00:47:30,537 --> 00:47:32,003 +and then a completion handler. +完成的回调。 + +1192 +00:47:32,005 --> 00:47:35,506 +Because parsing that GPX, it does need another thread. +因为解析GPX文件需要在另外一个进程进行。 + +1193 +00:47:35,508 --> 00:47:37,474 +Okay. And then when it's done, +当它完成解析的时候, + +1194 +00:47:37,476 --> 00:47:39,242 +it calls the completion handler here. +这个回调就会执行。 + +1195 +00:47:39,244 --> 00:47:41,111 +So I'll pass the URL. +把我们的URL传进去。 + +1196 +00:47:41,113 --> 00:47:43,479 +And we'll do the completion handler. +现在写回调。 + +1197 +00:47:43,481 --> 00:47:45,147 +And I don't even need any of this. +参数这里我都不需要了。 + +1198 +00:47:45,149 --> 00:47:47,649 +I'll use dollar zero instead of this. +我要用$0来表示。 + +1199 +00:47:47,651 --> 00:47:49,151 +I haven't been doing that in the demos but +以前在demo里我没这么做过,不过在这 + +1200 +00:47:49,153 --> 00:47:50,085 +I'm going to do it here. +要这么写。 + +1201 +00:47:50,087 --> 00:47:52,086 +So dollar zero is the GPX so +$0是GPX类型的。 + +1202 +00:47:52,088 --> 00:47:55,289 +it creates an instance of this GPX class. +这个方法会创建一个GPX类的实例。 + +1203 +00:47:55,291 --> 00:47:59,259 +So let's go take a look at that GPX class over here. +现在我们来看一下GPX这个类。 + +1204 +00:47:59,261 --> 00:48:01,461 +Put it in Supporting Files, here it is. +应该在supporting files里,在这。 + +1205 +00:48:01,463 --> 00:48:04,230 +It's a simple class, GPX. +这是个很简单的类,GPS。 + +1206 +00:48:04,232 --> 00:48:07,867 +It has waypoints, an array of waypoints, an array of tracks. +它有一个路点的数组,轨迹的数组, + +1207 +00:48:07,869 --> 00:48:09,134 +Routes are just like tracks, +路径跟轨迹很像, + +1208 +00:48:09,136 --> 00:48:11,603 +but they're more like a driving route kind of thing. +不过路径更像是给开车的人用的。 + +1209 +00:48:11,605 --> 00:48:13,672 +So we're not gonna do anything with this. +这里我们不会用到。 + +1210 +00:48:13,674 --> 00:48:14,872 +So it's just waypoints and tracks. +只用到路点和轨迹。 + +1211 +00:48:14,874 --> 00:48:16,207 +We're gonna put these with pins, and +我们要把路点用大头针显示在地图上,把轨迹 + +1212 +00:48:16,209 --> 00:48:18,709 +we're gonna do this with overlays, time permitting. +用覆盖层显示在地图上,如果有时间的话。 + +1213 +00:48:18,711 --> 00:48:20,277 +Okay, and mostly it's just a parser. +总体来说这就是一个解析器。 + +1214 +00:48:20,279 --> 00:48:21,578 +It's an HTML parser, see, +HTML的解析器,看到了没? + +1215 +00:48:21,580 --> 00:48:25,548 +it's parsing various HTML hoo-hahs here. +可以解析各种HTML。 + +1216 +00:48:25,550 --> 00:48:27,650 +Here's the track that it return, which you can see is +这里是返回的轨迹,你能看到实际上就是一个 + +1217 +00:48:27,652 --> 00:48:30,986 +basically just an array of waypoints, okay. +路点的数组。 + +1218 +00:48:30,988 --> 00:48:33,522 +Column fixes, but it's an array of waypoints. +名字叫fixes,实际上是路点的数组。 + +1219 +00:48:33,524 --> 00:48:34,656 +Here's a Waypoint. +这里就是路点。 + +1220 +00:48:34,658 --> 00:48:37,125 +Waypoint is just the latitude and longitude. +路点里有经纬度。 + +1221 +00:48:37,127 --> 00:48:39,427 +Also, it has info about that point, +还有关于这个点的信息。 + +1222 +00:48:39,429 --> 00:48:41,261 +just kind of interesting info. +就是一些有意思的信息。 + +1223 +00:48:41,263 --> 00:48:43,196 +It inherits from this class Entry, +它是从Entry类继承来的。 + +1224 +00:48:43,198 --> 00:48:45,131 +which is a basic entry which has the name. +这是一个含有名字属性的基本入口。 + +1225 +00:48:45,133 --> 00:48:48,501 +So the waypoints also have names as well. +所以路点也有名字。 + +1226 +00:48:48,503 --> 00:48:50,503 +And also, waypoints can have links. +另外,路点也可以包含链接。 + +1227 +00:48:50,505 --> 00:48:55,073 +So links are just, you know, URL references, basically. +链接就是URL的信息。 + +1228 +00:48:55,075 --> 00:48:57,442 +And you can get the URL, and +你可以得到URL以及 + +1229 +00:48:57,444 --> 00:49:00,812 +you can also get the type of thing it is. +URL内容的类型。 + +1230 +00:49:00,814 --> 00:49:03,948 +And so we're gonna use that to get thumbnails versus regular. +我们可以用它得到缩略图或者常规的图片。 + +1231 +00:49:03,950 --> 00:49:06,450 +All right, so back to our code here. +好了,回到我们的代码。 + +1232 +00:49:07,552 --> 00:49:08,518 +We've parsed this URL. +我们解析了这个URL。 + +1233 +00:49:08,520 --> 00:49:10,286 +And we've got the completion handler. +我们也有了这个回调。 + +1234 +00:49:10,288 --> 00:49:14,690 +By the way, I always like to user our nice Swift +这里我非常喜欢用swift语法里 + +1235 +00:49:16,560 --> 00:49:19,961 +closure as the last argument thing. +尾闭包。 + +1236 +00:49:19,963 --> 00:49:22,764 +So I'm parsing it, and +这里,我解析了, + +1237 +00:49:22,765 --> 00:49:25,566 +I'm just gonna say, if I was able to successfully parse it. +如果解析成功。 + +1238 +00:49:25,568 --> 00:49:29,769 +So the thing that was passed to me, this $0. +这个GPX就会传递给我。这个$0。 + +1239 +00:49:29,771 --> 00:49:33,806 +Okay? And that was not nil, okay. +如果不为空。 + +1240 +00:49:33,808 --> 00:49:36,942 +Then I'm going to work on it. +我就要处理它。 + +1241 +00:49:36,944 --> 00:49:38,744 +And what am I gonna do to work on it? +我要怎么处理它呢? + +1242 +00:49:38,746 --> 00:49:40,645 +Well, let's do the waypoints first. +我们现在处理路点。 + +1243 +00:49:40,647 --> 00:49:43,214 +I'm just gonna call a method handleWaypoints. +这里我会调用一个 handleWaypoints 方法。 + +1244 +00:49:43,216 --> 00:49:46,283 +So I'm gonna handle the GPX's waypoints. +用来处理GPX的路点。 + +1245 +00:49:46,285 --> 00:49:49,319 +Remember, that's just an array of that Waypoint class. +还记得他们就是路点的数组吧。 + +1246 +00:49:49,321 --> 00:49:51,221 +That's all it is. +就这样。 + +1247 +00:49:51,223 --> 00:49:54,524 +Also, by the way, when someone sets a new URL on me, +当然,如果有新的URL传进来, + +1248 +00:49:54,526 --> 00:49:58,260 +I'm gonna clear all my existing waypoints off my map. +我要清理掉所有在地图上存在的路点。 + +1249 +00:49:59,764 --> 00:50:01,330 +Okay? + +1250 +00:50:01,331 --> 00:50:02,897 +So I just need to implement these two methods, +我现在需要实现这两个方法。 + +1251 +00:50:02,900 --> 00:50:04,899 +clearWaypoints and handleWaypoints. +clearWaypoints 和 handleWaypoints。 + +1252 +00:50:04,901 --> 00:50:06,534 +What do I need to do that? +我要怎么做呢? + +1253 +00:50:06,536 --> 00:50:08,969 +Let's do clearWaypoints first. +咱们先来实现 clearWaypoints。 + +1254 +00:50:08,971 --> 00:50:11,538 +Really easy, clearWaypoints. +非常容易。 + +1255 +00:50:13,175 --> 00:50:15,141 +I just need, this is private. +这个是私有的。 + +1256 +00:50:15,143 --> 00:50:18,644 +I'll try to do the privates today or remember to do that. +我今天试着把私有都注明。 + +1257 +00:50:18,646 --> 00:50:21,080 +So clearWaypoints, I'm just going to, +clearWaypoints,我只需要, + +1258 +00:50:21,082 --> 00:50:25,717 +if my mapView has any annotations, because remember, +如果我的地图视图有注释点的话,你们应该记得,注释点这个属性是 + +1259 +00:50:25,719 --> 00:50:28,453 +annotations is the array of annotations. +注释点的数组。 + +1260 +00:50:28,455 --> 00:50:33,357 +If that's not nil, then I'm going to, oops, I typed then. +如果不为空,我就要,哦。我居然打了then。 + +1261 +00:50:33,359 --> 00:50:36,059 +[LAUGH] mapView.annotation. +mapView.annotation + +1262 +00:50:36,061 --> 00:50:37,627 +Oh, sorry, remove annotations. +啊,不好意思,移除注释点。 + +1263 +00:50:37,629 --> 00:50:41,164 +I'm just gonna remove all the annotations in that case. +我这里要删掉所有的注释点。 + +1264 +00:50:41,166 --> 00:50:43,432 +mapView.annotations. +mapView.annotations. + +1265 +00:50:43,434 --> 00:50:45,100 +And here's an interesting thing, +这里有个有趣的东西, + +1266 +00:50:45,102 --> 00:50:47,703 +okay, I want to remove those annotations. +我想要删除这些注释点。 + +1267 +00:50:47,705 --> 00:50:50,071 +And we've got a lot of any object going in here. +我这里得到的是很多的anyObject。 + +1268 +00:50:50,073 --> 00:50:54,075 +So I'm gonna make this annotations as MKAnnotation. +所以这里我需要类型转换成MKAnnotation。 + +1269 +00:50:54,077 --> 00:50:57,678 +Just so you remember that these annotations are always +所以要记住这里注释点的类型永远 + +1270 +00:50:57,680 --> 00:50:59,813 +arrays of MKAnnotation there. +都是MKAnnotation。 + +1271 +00:50:59,815 --> 00:51:00,647 +Okay? + +1272 +00:51:00,649 --> 00:51:01,981 +So that's clearing them, +好,这里就是清除它们, + +1273 +00:51:01,983 --> 00:51:04,317 +nothing necessary besides that to clear them. +除了清除啥也不用做。 + +1274 +00:51:04,319 --> 00:51:05,851 +How about handling them? +那么如何处理它们呢? + +1275 +00:51:05,853 --> 00:51:07,753 +Well, this is gonna be pretty amazing. +好吧,处理的时候非常酷炫。 + +1276 +00:51:07,755 --> 00:51:10,622 +But handling them is almost just as easy. +但是也是非常简单的。 + +1277 +00:51:10,624 --> 00:51:15,460 +So handleWaypoints is going to be this array of waypoints, +参数就是路点的数组。 + +1278 +00:51:15,462 --> 00:51:17,962 +take an of waypoints. + +1279 +00:51:17,964 --> 00:51:21,398 +So these waypoints are GPX.Waypoint. +类型是 GPX.Waypoint。 + +1280 +00:51:21,400 --> 00:51:26,469 +That's the type of thing that this GPX object returns. +这个是GPX解析器返回的类型。 + +1281 +00:51:26,471 --> 00:51:29,739 +And we are just going to say, +这里我们写 + +1282 +00:51:29,741 --> 00:51:35,044 +mapView.addAnnotations, the waypoints. +mapView.addAnnotations,那些路点。 + +1283 +00:51:35,046 --> 00:51:37,913 +And, we're also gonna say, mapView, +然后展示这些 + +1284 +00:51:37,915 --> 00:51:41,049 +show the annotations of these waypoints. +路点。 + +1285 +00:51:42,151 --> 00:51:43,717 +And do that in an animated fashion. +用动画的形式。 + +1286 +00:51:43,719 --> 00:51:46,520 +Now, this, you're gonna look at this and +你现在看见这个肯定会问, + +1287 +00:51:46,522 --> 00:51:47,987 +say, can it be this simple? +就这么简单吗? + +1288 +00:51:47,989 --> 00:51:50,156 +And in fact, it can be this simple. +事实上就是这么简单。 + +1289 +00:51:50,158 --> 00:51:52,992 +Let's make this is self. +在这加上self。 + +1290 +00:51:52,994 --> 00:51:57,696 +It can be this simple, as long as this is an MKAnnotation. +因为这是一个 MKAnnotation,所以简单。 + +1291 +00:51:57,698 --> 00:52:00,282 +Do you see? +看见没? + +1292 +00:52:00,283 --> 00:52:02,867 +I'm passing to addAnnotations this array, so these things +我在addAnnotations方法里传入了这个数组,所以数组里的元素应该 + +1293 +00:52:02,869 --> 00:52:06,270 +better be MKAnnotations, which they are not. +是MKAnnotations,但事实上它们不是。 + +1294 +00:52:06,272 --> 00:52:08,305 +Because they just come from this GPX parser, +因为它们来自GPX解析器。 + +1295 +00:52:08,307 --> 00:52:10,107 +it doesn't know anything about MK. +解析器不会知道MK的东西。 + +1296 +00:52:10,109 --> 00:52:12,576 +It's a generic GPX parser, it doesn't, +它只是一个泛型的GPX解析器。 + +1297 +00:52:12,578 --> 00:52:14,944 +it's not a MapKit parser or anything, it's just generic. +它不是为MapKit或者其他什么东西做解析的,它只是泛型的解析器。 + +1298 +00:52:14,946 --> 00:52:17,714 +So we have to some how make this +所以我们需要给它实现 + +1299 +00:52:17,716 --> 00:52:19,882 +implement the MKAnnotation protocol. +MKAnnotation协议。 + +1300 +00:52:19,884 --> 00:52:23,252 +And we talked about how we can use an extension +我们之前讲过如何用扩展使得一个类 + +1301 +00:52:23,254 --> 00:52:26,188 +to make a class implement a protocol, and +遵守某个协议,这就是 + +1302 +00:52:26,190 --> 00:52:27,655 +that's exactly what we're gonna do. +我们现在要做的。 + +1303 +00:52:27,657 --> 00:52:29,657 +So I'm gonna create a new file here. +这里我们新建一个文件。 + +1304 +00:52:30,860 --> 00:52:33,394 +Okay? + +1305 +00:52:33,395 --> 00:52:35,929 +I'm gonna call it MKGPX, cuz it's gonna have all the things +起名字叫MKGPX,因为我需要扩展所有的 + +1306 +00:52:35,931 --> 00:52:38,532 +I want to extend these GPX classes so +GXP类,让它们遵守协议,使它们可以 + +1307 +00:52:38,534 --> 00:52:41,534 +they work with MapKit, MK, all right. +与MapKit兼容。 + +1308 +00:52:41,536 --> 00:52:43,503 +So MKGPX, here it is. +建好了。 + +1309 +00:52:43,505 --> 00:52:44,670 +Instead of importing Foundation, +这里不再导入Foundation了。 + +1310 +00:52:44,672 --> 00:52:46,605 +I'm gonna import MapKit, +而是导入MapKit。 + +1311 +00:52:46,606 --> 00:52:48,539 +because these are all going to be things about MapKit. +因为我们要做的事儿都是跟MapKit相关的。 + +1312 +00:52:48,542 --> 00:52:54,245 +And so I'm just gonna have an extension of GPX.Waypoint, +这里我写一个GPX.Waypoint的扩展。 + +1313 +00:52:54,247 --> 00:52:56,881 +and that extension is going to implement +让这个扩展实现 + +1314 +00:52:56,883 --> 00:52:58,582 +MKAnnotation protocol. +MKAnnotation协议。 + +1315 +00:53:00,353 --> 00:53:01,718 +Okay? So this is what I was talking +这就是我以前讲过的 + +1316 +00:53:01,720 --> 00:53:03,720 +about before where you can do this. +如何去实现协议。 + +1317 +00:53:03,722 --> 00:53:06,289 +This really makes your code simple +这让你给一个对象实现协议的时候 + +1318 +00:53:06,291 --> 00:53:08,557 +to be able to make an object implement another protocol, +的代码非常易懂。 + +1319 +00:53:08,559 --> 00:53:10,726 +as long as you can do it without any storage, +因为这都是跟存储无关的事。 + +1320 +00:53:10,728 --> 00:53:12,527 +because of course, extensions can't have any storage. +当然,扩展也不能做存储相关的事儿。 + +1321 +00:53:12,529 --> 00:53:14,295 +But here we can easily do that. +后边就很容易了。 + +1322 +00:53:14,297 --> 00:53:17,999 +So, the three things, remember, are coordinate, +我们要实现3个属性,首先是坐标, + +1323 +00:53:18,001 --> 00:53:20,768 +which is a CLLocationCoordinate2D. +也就是一个CLLocationCoordinate2D。 + +1324 +00:53:20,770 --> 00:53:23,270 +And title, which is a optional string, but +然后是标题,一个可选的字符串, + +1325 +00:53:23,272 --> 00:53:25,605 +we never want that to be non-optional. +我们从来不想让它变成非可选的。 + +1326 +00:53:25,607 --> 00:53:28,108 +And subtitle, which is also an optional string. +副标题也是一个可选的字符串。 + +1327 +00:53:28,110 --> 00:53:29,976 +So these are the three things we have to implement +如果我们希望这个东西变成MKAnnotation,就要实现 + +1328 +00:53:29,978 --> 00:53:33,912 +if we want this thing to be an MKAnnotation. +这三个属性。 + +1329 +00:53:33,914 --> 00:53:35,814 +So let's do that, super simple. +咱们开始吧,超级简单。 + +1330 +00:53:35,816 --> 00:53:39,284 +Here we're just gonna return a CLLocationCoordinate2D, +这里我们会返回一个 CLLocationCoordinate2D + +1331 +00:53:39,286 --> 00:53:41,886 +with the latitude being our latitude. +经度就是我们类里自己的经度。 + +1332 +00:53:41,888 --> 00:53:44,689 +Okay? This is just a property in +这只是类里的一个属性而已。 + +1333 +00:53:44,691 --> 00:53:50,494 +this, the latitude, and longitude being the longitude. +纬度就是用类里面的纬度。 + +1334 +00:53:50,496 --> 00:53:51,395 +Okay? + +1335 +00:53:51,396 --> 00:53:52,295 +So I just created a new one of these. +我这里新建了一个对象, + +1336 +00:53:52,297 --> 00:53:54,430 +This is just calling its initializer. +调用了它的初始化器。 + +1337 +00:53:54,432 --> 00:53:56,432 +And I just pass my own latitude and longitude, +传入了我自己的经纬度。 + +1338 +00:53:56,434 --> 00:53:58,100 +could not be any simpler. +非常简单。 + +1339 +00:53:58,102 --> 00:54:00,736 +The title is also just as simple. +标题也很简单。 + +1340 +00:54:00,738 --> 00:54:03,304 +I'm gonna return my own name. +我只需要返回我自己的name属性。 + +1341 +00:54:04,407 --> 00:54:05,840 +I showed you in the code there, +我刚才给你们看代码了。 + +1342 +00:54:05,842 --> 00:54:09,576 +that GPX.Waypoints, they know their name, okay? +GPX.Waypoints有名字的属性。 + +1343 +00:54:09,578 --> 00:54:11,244 +We call it title in MKAnnotation, +我们把它当做MKAnnotation里的标题。 + +1344 +00:54:11,246 --> 00:54:12,345 +they call it name. +在类里我们叫名字。 + +1345 +00:54:12,347 --> 00:54:14,781 +And similarly here, there's return info, +副标题也差不多,我们返回info。 + +1346 +00:54:14,783 --> 00:54:18,283 +which is just the information about this waypoint. +就是关于这个路点的信息。 + +1347 +00:54:19,253 --> 00:54:24,622 +Back here, in our GPXViewController, +现在回到我们的GPXViewController + +1348 +00:54:24,624 --> 00:54:28,892 +we have to, when we get the URL, +当我们拿到URL的时候, + +1349 +00:54:28,894 --> 00:54:33,463 +we forgot to set our model here to be +哦,我们忘了在这设置我们的模型了, + +1350 +00:54:33,465 --> 00:54:37,500 +this URL here, that's all. +设置一下就好了。 + +1351 +00:54:48,746 --> 00:54:50,996 +Okay. + +1352 +00:54:50,997 --> 00:54:53,247 +So here's Stanford, we'll drag, this, +这是斯坦福大学,我们拖到这, + +1353 +00:54:53,250 --> 00:54:58,753 +this is just a GPX file with some, hello, there we go. +这就是一个GPX文件,哦,这里, + +1354 +00:54:58,755 --> 00:55:00,688 +Accept. With some Stanford locations. +点接受,包含一些斯坦福大学的地点。 + +1355 +00:55:00,690 --> 00:55:03,390 +And you can see, they just put them on there as pins. +你可以看到,放置了一些大头针。 + +1356 +00:55:03,392 --> 00:55:04,257 +Okay? + +1357 +00:55:04,259 --> 00:55:05,992 +And I can even click on them. +我能点击它们。 + +1358 +00:55:05,994 --> 00:55:09,662 +If I tap them, I get the callout, and it has the name. +如果我点击他们,标识视图就弹出来了,看到了名字。 + +1359 +00:55:09,664 --> 00:55:10,830 +Okay? Some of them even have +有一些大头针还有 + +1360 +00:55:10,832 --> 00:55:12,564 +a little info. +详细一点的信息。 + +1361 +00:55:12,566 --> 00:55:13,532 +Okay. Green Library, +Green Library, + +1362 +00:55:13,534 --> 00:55:14,599 +get your study on. +信息是get your study on + +1363 +00:55:14,601 --> 00:55:15,833 +Or here's Meyer. +这是Meyer + +1364 +00:55:15,835 --> 00:55:17,034 +Meyer Library, rest in peace. +Meyer图书馆,在平静中安息。 + +1365 +00:55:17,036 --> 00:55:18,802 +>> [LAUGH]. + +1366 +00:55:18,804 --> 00:55:20,170 +>> So that's that one. + +1367 +00:55:20,172 --> 00:55:21,204 +Let's drag a different one out, +我们拖另外一个文件进来。 + +1368 +00:55:21,206 --> 00:55:22,405 +let's get our vacation here. +我们开始度假了。 + +1369 +00:55:22,407 --> 00:55:25,007 +So this one's got a lot more stuff. +这个东西会多一些。 + +1370 +00:55:25,009 --> 00:55:25,574 +We see that. +看看这个。 + +1371 +00:55:25,576 --> 00:55:27,993 +We accept that one. +我们接受一下这个。 + +1372 +00:55:27,994 --> 00:55:30,411 +It clears out our old pins, loads up this new GPX file, +它清理了我们以前的大头针,加载了新的GPX文件。 + +1373 +00:55:30,414 --> 00:55:33,181 +and shows us a whole bunch of pins on here. +给我们加了一些新的大头针。 + +1374 +00:55:33,183 --> 00:55:34,882 +So let's see where the heck we are in the world. +看看到底是哪。 + +1375 +00:55:34,884 --> 00:55:36,250 +So I'm gonna zoom out. +缩小一点看看。 + +1376 +00:55:36,252 --> 00:55:37,551 +All right. Somewhere in the middle of +把它们居中。 + +1377 +00:55:37,553 --> 00:55:38,819 +nowhere here. + +1378 +00:55:38,821 --> 00:55:40,153 +What the heck, where are we? +哦,这是哪。 + +1379 +00:55:40,155 --> 00:55:42,955 +Oh, we're not even in the United States, +我们貌似不在美国了, + +1380 +00:55:42,957 --> 00:55:44,390 +we're in Canada somewhere. +好像是加拿大的什么地方。 + +1381 +00:55:44,392 --> 00:55:45,791 +Okay, so we're up there in Canada. +我们现在在加拿大。 + +1382 +00:55:45,793 --> 00:55:47,576 +All right, + +1383 +00:55:47,577 --> 00:55:49,360 +I'm just pinching to zoom here right on the map app. +我缩放一下, + +1384 +00:55:49,363 --> 00:55:50,995 +And we've got all these pins. +这样能看到所有的大头针了。 + +1385 +00:55:50,997 --> 00:55:53,598 +And these pins we can click on, and +我们可以点击这些大头针, + +1386 +00:55:53,600 --> 00:55:56,667 +some of them have titles and subtitles. +有一些有标题和副标题。 + +1387 +00:55:56,669 --> 00:55:58,068 +But this is kind of cool. +很酷。 + +1388 +00:55:58,070 --> 00:56:02,272 +This looks like a pretty incredible country here in. +这好像是个很不错的地方 + +1389 +00:56:02,274 --> 00:56:04,007 +Canada and it's referring to things like, + +1390 +00:56:04,009 --> 00:56:06,142 +look at this, views are spectacular even from here. +看这,还挺壮观的。 + +1391 +00:56:06,144 --> 00:56:08,844 +It'll be awfully cool if we could see those views with +要是我们能看到这些地方的照片就 + +1392 +00:56:08,846 --> 00:56:10,062 +some photos. +更酷了。 + +1393 +00:56:10,063 --> 00:56:11,279 +And so that's what we're going to do next. +这就是我们下边要做的事儿。 + +1394 +00:56:11,281 --> 00:56:14,982 +So, on these call outs, I'm going to add a left accessory +在这些弹出的标识视图里,我要加一个左辅助视图, + +1395 +00:56:14,984 --> 00:56:16,717 +view, which is a UI image. +也就是一个图片视图。 + +1396 +00:56:16,719 --> 00:56:20,688 +Which is gonna have a thumbnail of the photo that is +给它加上在GPX文件里,某个路点自己的链接以 + +1397 +00:56:20,690 --> 00:56:26,059 +in the GPX file that's linked to this particular waypoint. +显示图片。 + +1398 +00:56:26,061 --> 00:56:28,828 +Notice that we're getting these pins and this callout, +注意我们现在能看到这些大头针和标识视图, + +1399 +00:56:28,830 --> 00:56:30,429 +and I haven't implemented that method, +但是我还没实现mapView.viewForAnnotation方法, + +1400 +00:56:30,431 --> 00:56:33,132 +mapView.viewForAnnotation, remember that? +记得吗? + +1401 +00:56:33,134 --> 00:56:35,100 +So if you don't implement that method at all, +如果你不实现这个方法, + +1402 +00:56:35,102 --> 00:56:38,503 +all you get is pins, red pins, and +那么你能用的就是大头针,红色的大头针和 + +1403 +00:56:38,505 --> 00:56:41,406 +all you get is a callout with the title and subtitle. +带有标题和副标题的标识视图。 + +1404 +00:56:41,408 --> 00:56:42,506 +That's all you get. +你只能得到这些默认的组件。 + +1405 +00:56:42,508 --> 00:56:43,974 +So if you want anything more, +如果你还需要更多东西, + +1406 +00:56:43,976 --> 00:56:46,877 +like a thumbnail, you have to do that yourself. +比如缩略图,那么你就要自己实现。 + +1407 +00:56:46,879 --> 00:56:49,813 +So we're gonna do that ourselves by implementing that +我们现在要自己来实现这个方法。 + +1408 +00:56:49,815 --> 00:56:52,915 +method, so let's put that right down here. +现在开始。 + +1409 +00:56:52,917 --> 00:56:54,750 +And it's called mapView viewForAnnotation. +我写mapView的时候,你会看到 + +1410 +00:56:54,752 --> 00:56:57,920 +You can see that mapView has a lot, a lot, +有很多很多的 + +1411 +00:56:57,922 --> 00:56:59,888 +lot of delegate methods. +代理方法。 + +1412 +00:56:59,890 --> 00:57:02,223 +It can do an enormous amount of things here, +它们可以做各种事。 + +1413 +00:57:02,225 --> 00:57:05,026 +from the overlays, and all that stuff the animation +覆盖层,动画, + +1414 +00:57:05,028 --> 00:57:07,995 +other things, the regions coming, going, all that. +区域,等等等等。 + +1415 +00:57:07,997 --> 00:57:11,231 +So we want, if we can find it here, +我们需要找到viewForAnnotation方法, + +1416 +00:57:11,233 --> 00:57:14,401 +viewForAnnotation, there it is. +在这呢。 + + +1417 +00:57:14,403 --> 00:57:16,536 +Okay, mapView, viewForAnnotation, +mapView,viewForAnnotation + +1418 +00:57:16,538 --> 00:57:18,755 +here it is right here. +找到了,在这呢。 + +1419 +00:57:18,756 --> 00:57:20,973 +All we have to do is what we talked about in the slides. +现在我们要做的就是我刚才幻灯片里讲到的。 + +1420 +00:57:20,975 --> 00:57:28,447 +Frst of all, I'll say var view equals mapView.dequeue. +首先,我们写 var view = mapView.dequeue. + +1421 +00:57:28,449 --> 00:57:29,314 +So I'm gonna dequeue. +这里需要重用。 + +1422 +00:57:29,316 --> 00:57:31,416 +Now, I need an identifier here? +我需要一个标识。 + +1423 +00:57:31,418 --> 00:57:33,951 +I actually think I have a bunch of constants. +啊,我之前应该写了很多常量。 + +1424 +00:57:35,154 --> 00:57:36,586 +Yeah, I did do that. +啊,在这呢。 + +1425 +00:57:36,588 --> 00:57:38,822 +Okay, so here's a bunch of constants, +这里是一些常量。 + +1426 +00:57:38,824 --> 00:57:41,958 +don't worry about most of them, we're not gonna get to +大多数我们都不需要去管,按照计划, + +1427 +00:57:41,960 --> 00:57:45,027 +most of this stuff today, which is kind of planned. +今天我们只用到很少的一部分, + +1428 +00:57:45,029 --> 00:57:48,630 +But I do have this annotation reuse identifier. +这里有注释点的重用标识。 + +1429 +00:57:48,632 --> 00:57:49,397 +So I'm gonna use that. +我要用它。 + +1430 +00:57:49,399 --> 00:57:52,567 +Constants dot annotation. +Constants.annotation + +1431 +00:57:52,569 --> 00:57:55,202 +Hey, by the way, one thing I'm seeing some of you do. +哦,对了,这里顺便说一下,我看到你们有些人会那么做。 + +1432 +00:57:55,204 --> 00:57:59,306 +Constants, you all know that all types +在Swift里,所有的类型和常量都需要以 + +1433 +00:57:59,308 --> 00:58:01,708 +need to be capitalized in Swift. +大写开头。 + +1434 +00:58:01,710 --> 00:58:02,776 +Right? + +1435 +00:58:02,777 --> 00:58:03,843 +So class is structs. +类啊,结构体什么的。 + +1436 +00:58:03,845 --> 00:58:06,912 +You should really capitalize constants as well. +常量也是需要大写的。 + +1437 +00:58:06,914 --> 00:58:09,098 +I'm seeing a lot of you do lowercase. +我看到你们有些人小写了。 + +1438 +00:58:09,099 --> 00:58:11,283 +It's kinda confusing to people when they see a lowercase they +人们如果见到小写会误认为这是属性,他们 + +1439 +00:58:11,285 --> 00:58:14,119 +think it's a property and they're wondering, oh, +就会好奇它是不是有setter和getter。 + +1440 +00:58:14,121 --> 00:58:15,754 +is this settable, gettable? + +1441 +00:58:15,756 --> 00:58:17,555 +Or if you capitalize it, they're gonna say, +如果你首字母大写了,他们就明白 + +1442 +00:58:17,557 --> 00:58:19,590 +oh, all right, this is must be a constant or to type or +这可能是个常量或者类型什么的。 + +1443 +00:58:19,592 --> 00:58:20,758 +something. + +1444 +00:58:20,760 --> 00:58:23,694 +So please, you know, capital letter for +所以,要注意,首字母大写 + +1445 +00:58:23,696 --> 00:58:26,295 +things that represent constants. +表示常量。 + +1446 +00:58:27,432 --> 00:58:28,864 +All right, so I get this view. +继续,我现在得到了这个视图。 + +1447 +00:58:28,866 --> 00:58:31,199 +Now if there's no de-queues-able, +如果不是重用得到的, + +1448 +00:58:31,201 --> 00:58:34,202 +if you can't de-queue a annotation +如果不能重用,我就要 + +1449 +00:58:34,204 --> 00:58:36,004 +view then I have to create it myself. +自己建一个。 + +1450 +00:58:36,006 --> 00:58:39,073 +So if this view is nil, then I have to create it. +所以这里写,如果视图为空,我就要新建一个。 + +1451 +00:58:39,075 --> 00:58:42,809 +And I'm just gonna create it by saying MKPinAnnotationView. +这里写MKPinAnnotationView。 + +1452 +00:58:42,811 --> 00:58:44,978 +I'm gonna create one of those. +我要新建一个MKPinAnnotationView。 + +1453 +00:58:44,980 --> 00:58:48,147 +I'm gonna use this constructor, annotation. +我要用这个构造器,传入注释点。 + +1454 +00:58:48,149 --> 00:58:51,350 +The reuse identifier is the Constants.Annotation. +重用标识是Constants.Annotation + +1455 +00:58:51,352 --> 00:58:54,420 +Since I'm using the same reuse identifier as here, +这里我用了同样的标识。 + +1456 +00:58:54,422 --> 00:58:58,089 +then in the future this view could get reused. +所以之后这个视图就可以被重用了。 + +1457 +00:58:59,125 --> 00:59:00,624 +I want this to show call out so +这里我需要它能弹出标识视图, + +1458 +00:59:00,626 --> 00:59:02,693 +I'm gonna have canShowCallout equals true. +所以写canShowCallout = true。 + +1459 +00:59:03,729 --> 00:59:05,195 +Okay? It's good. + + +1460 +00:59:05,197 --> 00:59:07,697 +Now let's set the annotation equal to annotation. +现在我们设置它的注释点。 + +1461 +00:59:07,699 --> 00:59:10,233 +Now you might say, oh, +这里你可能会说,哦, + +1462 +00:59:10,234 --> 00:59:12,768 +well look when I constructed this, I already did this. +在我新建这个视图的时候我就已经传入注释点了。 + +1463 +00:59:12,770 --> 00:59:14,920 +So that's true. +没错。 + +1464 +00:59:14,921 --> 00:59:17,071 +We could for example put this in an else, if you want that. +我们也可以把它写在else里,如果你想的话。 + +1465 +00:59:17,074 --> 00:59:19,674 +It's a little different than a slide. +这么写跟幻灯片有点不一样。 + +1466 +00:59:19,676 --> 00:59:22,210 +But if we dequeued we wanna make sure we set +但是我们重用的时候肯定希望可以正确的 + +1467 +00:59:22,212 --> 00:59:26,480 +the annotation to this annotation that was passed in. +传递注释点。 + +1468 +00:59:26,482 --> 00:59:28,248 +Because we're reusing this thing, okay? +因为我们需要重用。 + +1469 +00:59:28,250 --> 00:59:29,683 +So that's an important thing. +这个很重要。 + +1470 +00:59:29,684 --> 00:59:31,117 +Sometimes people forget this and they're like, hm, +有些人忘了设置,所以他们会 + +1471 +00:59:31,119 --> 00:59:32,485 +my annotations, when they get reused, +发现当他们的视图重用的时候, + +1472 +00:59:32,487 --> 00:59:33,786 +they keep showing the old annotation. +它还在显示之前的注释点。 + +1473 +00:59:33,788 --> 00:59:36,989 +Well, now you know why. +现在你知道为什么会犯这种错误了。 + +1474 +00:59:36,991 --> 00:59:38,824 +And then we can just return this view. +到这里我们可以直接返回这个视图了。 + +1475 +00:59:39,860 --> 00:59:42,593 +So this code that we have right here +我们在这刚刚写的代码,实际上 + +1476 +00:59:42,595 --> 00:59:44,328 +is essentially what you get for free. +我们是可以不写的。 + +1477 +00:59:44,330 --> 00:59:47,398 +If you don't implement this method, this is what you get. +如果我们不实现这个方法,系统就会自动为你写这些代码。 + +1478 +00:59:47,400 --> 00:59:48,432 +Okay? + +1479 +00:59:48,434 --> 00:59:51,001 +And actually, I'm gonna put something here. +所以实际上,我还需要加更多东西。 + +1480 +00:59:51,003 --> 00:59:52,703 +I'm gonna make it so +啊,我觉得 + +1481 +00:59:52,704 --> 00:59:54,404 +we don't have to do the airdrop all the time. +我们不必一直开着 airDrop。 + +1482 +00:59:54,406 --> 00:59:55,571 +Okay. In viewDidLoad, +好了,在viewDidLoad里。 + +1483 +00:59:55,573 --> 00:59:57,539 +I'm going to load up the URL. +我要加载URL。 + +1484 +00:59:57,541 --> 01:00:05,347 +I'm gonna say, gpxURL equals NSURL string. +这里我写 gxpURL = NSURL(String:)。 + +1485 +01:00:05,349 --> 01:00:11,652 +I'm gonna do http://www.stanford.edu/vacat- +http://www.stanford.edu/vacation.gpx. + +1486 +01:00:11,654 --> 01:00:12,986 +ion.gpx. + +1487 +01:00:12,988 --> 01:00:14,888 +So we'll just load it out of there. +我们在通知外直接加载它。 + +1488 +01:00:14,890 --> 01:00:17,691 +That way we can actually run it on here, so +我在这选一下模拟器,我们就能 + +1489 +01:00:17,693 --> 01:00:20,593 +that we can keep it all on screen. +一直让它在屏幕上了。 + +1490 +01:00:20,595 --> 01:00:22,528 +Okay, where was I? +我讲到哪了? + +1491 +01:00:22,530 --> 01:00:24,847 +I was in here. +啊,讲到这了。 + +1492 +01:00:24,848 --> 01:00:27,165 +Okay, so now we basically got the same thing we had +还是原来的大头针。 + +1493 +01:00:27,167 --> 01:00:28,083 +with a pin. + +1494 +01:00:28,084 --> 01:00:29,000 +So if we run this now. +如果我们现在运行一下, + +1495 +01:00:33,272 --> 01:00:34,738 +And we get the exact same thing here, right? +我们得到了一样的东西。 + +1496 +01:00:34,740 --> 01:00:36,940 +We can still click, we've got the panorama. +点一下,我们看到了panorama。 + +1497 +01:00:36,942 --> 01:00:40,243 +So now we wanna add this little left call out. +我们需要给它左边加一个图片。 + +1498 +01:00:40,245 --> 01:00:44,013 +So we build this UI, this leftCalloutAccessoryView UI, +我们要构建这个左辅助视图的UI。 + +1499 +01:00:44,015 --> 01:00:46,649 +in this viewForAnnotation right here. +在viewForAnnotation方法里。 + +1500 +01:00:46,651 --> 01:00:47,850 +And it's very simple to do. +非常简单。 + +1501 +01:00:47,852 --> 01:00:50,069 +We're just gonna say. +只需要写。 + +1502 +01:00:50,070 --> 01:00:52,287 +First of all, we need to only do this for annotations that +首先,我们只需要给是路点类型的注释点加 + +1503 +01:00:52,289 --> 01:00:54,789 +are waypoints because we could have our map have a mix +图片,因为我们可能会有GPX里的其他类型。 + +1504 +01:00:54,791 --> 01:00:57,859 +of these GPX.Waypoints and other things. + +1505 +01:00:57,861 --> 01:01:02,696 +So, I'm gonna say, if I can let waypoint +这里写,if let wayPoint = + +1506 +01:01:02,698 --> 01:01:08,168 +equal this annotation, as a GPX.Waypoint. +annotation,是一个GPX.Waypoint。 + +1507 +01:01:08,170 --> 01:01:09,903 +Okay. + +1508 +01:01:09,904 --> 01:01:11,637 +So if the annotation is a waypoint, then I'm gonna +如果注释点是一个路点,下边我就要 + +1509 +01:01:11,639 --> 01:01:14,940 +check and see if the waypoint has a thumbnailURL, we're +检查它是否包含一个缩略图的URL。 + +1510 +01:01:14,942 --> 01:01:17,743 +gonna have to implement that property in a second here. +我们一会儿要实现这个属性。 + +1511 +01:01:17,745 --> 01:01:21,179 +So if that's not nil, then I'm going to say that the views, +如果URL不为空,那么我的视图, + +1512 +01:01:21,181 --> 01:01:23,715 +annotation leftCalloutAccessoryView +我的注释点的左辅助视图, + +1513 +01:01:23,717 --> 01:01:25,316 +equals a UIImageView. +是一个图片视图。 + +1514 +01:01:26,552 --> 01:01:29,453 +And I'm actually going to give it a default frame which I +我要给它一个默认的大小,我这里正好 + +1515 +01:01:29,455 --> 01:01:30,654 +have a constant for. +有一个常量。 + +1516 +01:01:32,724 --> 01:01:34,824 +No matter what size of the image is, +不管尺寸多大, + +1517 +01:01:34,826 --> 01:01:38,660 +I want the actual size of the imageView to be fixed. +我只是希望图片视图的大小是固定的。 + +1518 +01:01:38,662 --> 01:01:39,961 +And by the way, +如果 + +1519 +01:01:39,963 --> 01:01:43,932 +if this waypoint doesn't have a thumbnail, okay? +这个路点没有缩略图呢? + +1520 +01:01:43,934 --> 01:01:50,338 +And in fact, also if it's not a GPX.Waypoint then I want +或者如果它根本不是一个GPX.Waypoint呢?那么我就希望 + +1521 +01:01:50,340 --> 01:01:52,906 +the leftCallOutAccessoryView to be nil. +它的左辅助视图为空。 + +1522 +01:01:52,908 --> 01:01:55,042 +So, again, you have to think about reuse. +我们还要考虑到重用。 + +1523 +01:01:55,044 --> 01:01:58,178 +Some waypoints are gonna have thumbnail URLs, some not. +有些路点有缩略图的URL有些没有。 + +1524 +01:01:58,180 --> 01:02:01,280 +If you wanna set this to nil, and then only set to an image +所以我们需要把它设为空,只有当有URL的时候,才 + +1525 +01:02:01,282 --> 01:02:03,683 +view, if it actually has a URL. +设置为一个图片视图。 + +1526 +01:02:03,685 --> 01:02:05,751 +So we have to implement this thumbnail URL. +现在我们来实现缩略图的URL。 + +1527 +01:02:05,753 --> 01:02:07,319 +That's pretty easy to do, as well. +这个特别简单。 + +1528 +01:02:07,321 --> 01:02:09,454 +We're gonna do that same little extension here, +我们在刚才那个实现协议的 + +1529 +01:02:09,456 --> 01:02:10,288 +where we put this. +扩展里做。 + +1530 +01:02:11,691 --> 01:02:15,726 +I'm going to have a little kinda helper function here +这里我要写一个辅助方法,叫做 + +1531 +01:02:15,728 --> 01:02:19,729 +which I'm gonna call getImageURLofType. +getImageURLofType + +1532 +01:02:19,731 --> 01:02:21,497 +And it's gonna get a certain type. +参数是一个类型。 + +1533 +01:02:21,499 --> 01:02:25,267 +So, this type is gonna be thumbnail or large image or +类型可以是缩略图或者大图 + +1534 +01:02:25,269 --> 01:02:27,803 +whatever it comes subverted the type +或者别的什么。 + +1535 +01:02:27,805 --> 01:02:30,171 +thing to be thumbnails or images. + +1536 +01:02:30,173 --> 01:02:33,508 +And here I'm just gonna go through the links +然后我遍历一下GPX.Waypoint里的 + +1537 +01:02:33,510 --> 01:02:35,476 +that are in this GPX.Waypoint. +链接。 + +1538 +01:02:35,478 --> 01:02:38,712 +So this is an array in GPX.Waypoint which is of these +这是GPX.Waypoint里一个链接的数组,我们之前 + +1539 +01:02:38,714 --> 01:02:40,280 +link thing we did. +看到过。 + +1540 +01:02:40,282 --> 01:02:44,684 +And if the link's type equals the type that I want, +如果链接的类型是我们想要的, + +1541 +01:02:44,686 --> 01:02:46,786 +thumbnail or +缩略图或者 + +1542 +01:02:46,787 --> 01:02:48,887 +whatever, then I'm gonna return that link's URL. +别的什么,我就返回这个URL。 + +1543 +01:02:48,890 --> 01:02:51,824 +Okay? So + +1544 +01:02:51,825 --> 01:02:54,759 +this a way that I can get the URL, so, +这就是得到URL的方法。 + +1545 +01:02:54,762 --> 01:02:59,931 +yes, so this needs to return NSURL. +啊,对,这里需要返回NSURL类型。 + +1546 +01:02:59,933 --> 01:03:01,098 +Okay? + +1547 +01:03:01,100 --> 01:03:02,900 +And if I can't find it, then I'll return nil, +如果找不到,就返回空。 + +1548 +01:03:02,902 --> 01:03:05,202 +so then it doesn't have an imageURL. +也就是没有合适的URL。 + +1549 +01:03:05,204 --> 01:03:12,809 +So, to implement thumbnail URL, okay, which is the NSURL. +要实现缩略图URL属性 ,这是一个NSURL类型。 + +1550 +01:03:12,811 --> 01:03:14,744 +That's really easy. +这个非常容易。 + +1551 +01:03:14,745 --> 01:03:16,678 +We're just gonna return the get image of type thumbnail. +我们只需要返回getImageURLofType("thumbnail") + +1552 +01:03:18,716 --> 01:03:20,248 +Okay? And we're also gonna have +还有一个图片URL的属性, + +1553 +01:03:20,250 --> 01:03:22,917 +a var for imageURL, which is the actual image, +这是一个真正的图片, + +1554 +01:03:22,919 --> 01:03:25,619 +not the thumbnail, but the actual image. +不是缩略图。 + +1555 +01:03:25,621 --> 01:03:31,158 +And now, we're gonna return getImageURL large image. +这里返回getImageURLofType("large") + +1556 +01:03:33,128 --> 01:03:34,678 +Okay? + +1557 +01:03:34,679 --> 01:03:36,229 +So people understanding what I'm doing here? +大家明白我是怎么做的了吗? + +1558 +01:03:36,231 --> 01:03:37,881 +Okay, this links + +1559 +01:03:37,882 --> 01:03:39,532 +is just something that's in a waypoint that tells you all +这些链接就是包含在路点里的一些 + +1560 +01:03:39,534 --> 01:03:42,101 +the HTTP links that are attached to this waypoint. +关于这个路点的HTTP链接 + +1561 +01:03:42,103 --> 01:03:44,169 +And I'm just looking through them to find either one +我遍历了它们找到我需要的类型, + +1562 +01:03:44,171 --> 01:03:46,170 +that's type thumbnail or one that's type large. +缩略图或者大图。 + +1563 +01:03:48,107 --> 01:03:49,273 +Okay? +明白了吗? + +1564 +01:03:49,275 --> 01:03:51,375 +So now this is working right here. +现在这里也没问题了。 + +1565 +01:03:51,377 --> 01:03:53,610 +So this is the left callout accessory. +这就是左辅助视图。 + +1566 +01:03:53,611 --> 01:03:55,844 +Now, I could actually load that image up right here. +我现在可以在这加载图片了。 + +1567 +01:03:55,847 --> 01:03:58,514 +I could set this accessory views image right here, but +在这加载辅助视图的图片,但是我们 + +1568 +01:03:58,516 --> 01:04:00,433 +we talked about. +讲过, + +1569 +01:04:00,434 --> 01:04:02,351 +We don't wanna do that because right now, +我们不能怎么做因为在这个时候, + +1570 +01:04:02,353 --> 01:04:05,154 +this callout has not been put onscreen. +标识视图还没有显示在屏幕上。 + +1571 +01:04:05,156 --> 01:04:07,322 +This is just the pin being created. +这里只是用来建立大头针的。 + +1572 +01:04:07,324 --> 01:04:09,157 +Okay, I'm creating this left callout exception review, but +这时标识视图还没有生成,所以 + +1573 +01:04:09,159 --> 01:04:10,925 +the actual callout is not being created, +我不能在这设置辅助视图。 + +1574 +01:04:10,927 --> 01:04:13,394 +not being shown, so I don't wanna go fetching things. +所以不能在这个时候抓取图片。 + +1575 +01:04:13,396 --> 01:04:16,030 +But I do actually, want that thing to be fetched, and so +但是我确实希望抓取图片,那么我就要 + +1576 +01:04:16,032 --> 01:04:18,665 +I'm gonna do that in another mapView delegate, +在didSelectAnnotationView这个 + +1577 +01:04:18,667 --> 01:04:20,667 +which is the didSelectAnnotationView. +代理方法里做。 + +1578 +01:04:21,736 --> 01:04:24,570 +Which is somewhere here. +在哪呢? + +1579 +01:04:24,572 --> 01:04:26,839 +There it is, okay. +在这,好 + +1580 +01:04:26,841 --> 01:04:28,707 +So this is, + +1581 +01:04:28,708 --> 01:04:30,574 +if the AnnotationView actually gets selected. +这个方法会在注释点被点击时调用。 + +1582 +01:04:30,577 --> 01:04:33,111 +So, now the callout is gonna go on there. +这个时候标识视图应该在屏幕上了。 + +1583 +01:04:33,113 --> 01:04:33,978 +And I wanna do that. +希望是。 + +1584 +01:04:33,980 --> 01:04:35,513 +So, what do I need to do in here? +那我现在做什么呢? + +1585 +01:04:35,515 --> 01:04:37,081 +Well, again, I need to check and +还要再检查注释点 + +1586 +01:04:37,083 --> 01:04:39,383 +see if this annotation is a waypoint. +是不是一个路点。 + +1587 +01:04:39,385 --> 01:04:40,850 +So I'm gonna say, +这里写, + +1588 +01:04:40,852 --> 01:04:44,520 +if the views.annotation is a GPX.Waypoint。 +如果views.annotation是一个GPX.Waypoint。 + +1589 +01:04:44,522 --> 01:04:47,757 +Cause otherwise it's, there's nothing for me to do here. +如果不是,我就什么都不需要做了。 + +1590 +01:04:47,759 --> 01:04:51,993 +I'm also going to get that ImageView out of there. +我现在还需要取到图片视图, + +1591 +01:04:51,995 --> 01:04:55,196 +So if the thumbnailImageView equals +所以这里写如果thumbnailImageView等于 + +1592 +01:04:55,198 --> 01:05:00,634 +the views.leftCalloutAccessory view, as a UIImageView. +视图的左辅助视图,类型是图片视图。 + +1593 +01:05:02,238 --> 01:05:03,554 +Okay? So + +1594 +01:05:03,555 --> 01:05:04,871 +I was able to get that leftCalloutAccessoryView, and +我就拿到了左辅助视图,现在是一个 + +1595 +01:05:04,873 --> 01:05:06,806 +it turned out to be an ImageView, so that's good. +图片视图,非常好。 + +1596 +01:05:06,808 --> 01:05:07,974 +That should be a question mark. +这里应该是问号。 + +1597 +01:05:09,344 --> 01:05:10,342 +Okay? + +1598 +01:05:10,344 --> 01:05:12,878 +So now I have the ImageView, so now, +我现在有了图片视图。 + +1599 +01:05:12,880 --> 01:05:16,348 +if I can let the imageData equal an NSData, okay, +然后写if let imageData = NSData + +1600 +01:05:16,350 --> 01:05:21,118 +I'm gonna block main thread right here, contentsOfURL. +这里我要阻塞主线程了,contentsOfURL + +1601 +01:05:21,120 --> 01:05:23,954 +And this is the waypoints thumbnailURL. +这里是waypoints.thumbnailURL + +1602 +01:05:23,956 --> 01:05:25,622 +Okay? + +1603 +01:05:25,624 --> 01:05:28,858 +This is blocks main thread! +阻塞了主线程。 + +1604 +01:05:28,860 --> 01:05:31,027 +Yikes, fix that someday. +一会儿再修复它。 + +1605 +01:05:31,029 --> 01:05:35,497 +If let image equals the UIImage with that data. +如果image等于这个data转换的UIImage。 + +1606 +01:05:35,499 --> 01:05:40,101 +So if I get all the way down here, then I can say that +到最下边,我可以写 + +1607 +01:05:40,103 --> 01:05:45,172 +the thumbnailImageViews.image equals that image. +thumbnailImageViews.image = image。 + +1608 +01:05:45,174 --> 01:05:48,275 +Okay? + +1609 +01:05:48,277 --> 01:05:50,277 +All right, does every one understands all these +大家都明白这一大堆if let + +1610 +01:05:50,279 --> 01:05:51,745 +if lets here, to get down there. +了吗? + +1611 +01:05:53,314 --> 01:05:55,881 +And what do we have to initiate here with contentsURL +contentsURL这里出了 + +1612 +01:05:55,883 --> 01:05:57,950 +waypoint.thumbnailURL, oh, sorry. +什么错误? + +1613 +01:05:57,952 --> 01:06:01,353 +[INAUDIBLE] Exclamation point, now I can unwrap this here, +感叹号,现在我可以解包这个可选值了。 + +1614 +01:06:01,355 --> 01:06:04,723 +because I wouldn't even be in this situation of having this +因为如果我没检查缩略图的URL是否存在,我就没 + +1615 +01:06:04,725 --> 01:06:07,258 +leftCalloutAccessory if I hadn't checked +必要去建立这个左辅助视图了。 + +1616 +01:06:07,260 --> 01:06:08,693 +the thumbnailURL here. + +1617 +01:06:08,695 --> 01:06:09,259 +Okay? + +1618 +01:06:11,363 --> 01:06:13,763 +All right, so, let's give it a go here. +咱们来跑一下, + +1619 +01:06:13,765 --> 01:06:20,136 +Now, let's run this. +运行一下看看。 + +1620 +01:06:20,138 --> 01:06:21,970 +>> [COUGH]. >> See if this is working. +看看能不能行。 + +1621 +01:06:21,972 --> 01:06:25,307 +There's our pins here, so let's try this, +这是我们的大头针,试着点一下, + +1622 +01:06:25,309 --> 01:06:28,976 +and sure enough, now we have this little Image View for +现在我们可以看见那个小的 + +1623 +01:06:28,978 --> 01:06:30,444 +all of these things. +图片视图了。 + +1624 +01:06:30,446 --> 01:06:35,349 +Now, this in some ways, has kind of made us +因为可以看见图片,这让我们在某种程度上感到 + +1625 +01:06:35,351 --> 01:06:38,051 +happy because we can see this image, but in some ways, +满意,但是从另一个方面来讲,可能体验会更差, + +1626 +01:06:38,053 --> 01:06:42,121 +it's made it worse because we got these cool images here, +因为我们在这看见了这些非常酷的图片,这让我们更 + +1627 +01:06:42,123 --> 01:06:46,092 +and we'd really love to see them bigger, right? +希望看见大图。 + +1628 +01:06:46,094 --> 01:06:47,426 +So, what we really wanna be able to do is +所以我们现在特别想做的事儿就是可以点击 + +1629 +01:06:47,428 --> 01:06:49,194 +click on this Callout View and +标识视图,然后跳转到一个 + +1630 +01:06:49,196 --> 01:06:53,331 +segue to an Image View that's gonna show us these images +图片视图去展示这些图片的放大版。 + +1631 +01:06:53,333 --> 01:06:56,501 +much larger, so we can scroll around and zoom in on them. +这样我们就可以拖动缩放大图了。 + +1632 +01:06:56,503 --> 01:06:59,770 +We're going to put a little button right here, okay. +我们希望在这放置一个小按钮。 + +1633 +01:06:59,772 --> 01:07:02,172 +It's gonna be a detail disclosure button. +一个显示详细信息的按钮。 + +1634 +01:07:02,174 --> 01:07:04,708 +And we're gonna use that map view delegate method that +当我们点击一个带有按钮的标识视图的时候,一个地图视图的 + +1635 +01:07:04,710 --> 01:07:08,178 +gets called when you tap on a Callout that has a button in +代理方法就会被调用, + +1636 +01:07:08,180 --> 01:07:11,948 +there, and it's going to segue, so let's do that. +然后做一个跳转,我们现在做这个。 + +1637 +01:07:11,950 --> 01:07:14,550 +First we gotta add that little button, so we do that the same +首先我们要先加一个按钮,就写在我们刚才 + +1638 +01:07:14,552 --> 01:07:17,252 +place up here where we did the leftCalloutAccessory. +初始化左辅助视图的地方。 + +1639 +01:07:17,254 --> 01:07:18,954 +We're gonna +这里先写 + +1640 +01:07:18,955 --> 01:07:20,655 +do rightCalloutAccessoryView equals nil. +右辅助视图为空。 + +1641 +01:07:20,657 --> 01:07:24,159 +And if we can let, oh, sorry, we can do, +然后if let,对不起 + +1642 +01:07:24,161 --> 01:07:28,362 +we'll use that if twice so let's put it up there. +我们要用这个if两次所以先放在这。 + +1643 +01:07:28,364 --> 01:07:34,301 +So here we're also gonna say if the waypoints.imageURL +如果 waypoints.imageURL不为空, + +1644 +01:07:34,303 --> 01:07:40,373 +is not nil then we will let the rightCalloutAccessoryView +那么我们就把右辅助视图设置为 + +1645 +01:07:40,375 --> 01:07:44,209 +equal UIButton.buttonWithType, +UIButton.buttonWithType + +1646 +01:07:44,211 --> 01:07:48,179 +UIButtonType.DetailDisclosure. +按钮类型是UIButtonType.DetailDisclosure。 + +1647 +01:07:48,181 --> 01:07:50,048 +And you're not gonna believe this, +你可能不相信, + +1648 +01:07:50,050 --> 01:07:53,517 +but you're gonna have to say here, as UIButton. +但是这里需要写as UIButton。 + +1649 +01:07:53,519 --> 01:07:56,353 +And that's because inexplicably, +由于很难理解的原因, + +1650 +01:07:56,355 --> 01:07:59,623 +this method returns any object, okay? +这个方法会返回anyObject。 + +1651 +01:07:59,625 --> 01:08:02,625 +Don't ask me how that got in there. +不要问我为什么, + +1652 +01:08:02,627 --> 01:08:05,795 +But UIButton.buttonWithType returns any object. +UIButton.buttonWithType 确实返回 anyObject。 + +1653 +01:08:05,797 --> 01:08:08,364 +So we have to cast it to a UIButton. +我们需要转换成 UIButton。 + +1654 +01:08:08,366 --> 01:08:10,733 +Otherwise, it won't even look like it's a UIView so, +不然的话,它可能看起来就不像是一个视图。 + +1655 +01:08:10,735 --> 01:08:12,267 +it's kinda bad but, there you go. +这个比较奇怪,但是没办法。 + +1656 +01:08:13,303 --> 01:08:14,653 +And so now, + +1657 +01:08:14,654 --> 01:08:16,004 +let's do that method I was talking about before. +现在咱们来实现我们前边说过的代理方法, + +1658 +01:08:16,006 --> 01:08:18,439 +The mapView method or the callout is called, +辅助视图点击就会触发的方法。 + +1659 +01:08:18,441 --> 01:08:21,008 +that is right here, the very top one. +在这,找到了,最上面。 + +1660 +01:08:21,010 --> 01:08:23,243 +CalloutAccessoryControlTapped. +CalloutAccessoryControlTapped + +1661 +01:08:23,245 --> 01:08:25,945 +Okay, so this gets called whenever that callout gets +这个方法会在标识视图被点击 + +1662 +01:08:25,947 --> 01:08:27,980 +tapped on with that thing in there. +的时候调用。 + +1663 +01:08:27,982 --> 01:08:32,484 +And inside here, we need to essentially segue. +在这个方法里,我们需要跳转。 + +1664 +01:08:32,486 --> 01:08:33,418 +Right? + +1665 +01:08:33,420 --> 01:08:35,520 +And so how are we gonna segue? +要怎么做这个跳转呢? + +1666 +01:08:35,522 --> 01:08:38,523 +Really, I should be checking here to make sure this is +我们需要在这检查跳转到的我们 + +1667 +01:08:38,525 --> 01:08:39,657 +really the one we want. +需要的地方。 + +1668 +01:08:39,658 --> 01:08:40,790 +But I'm just, in the interest of time, +由于我们只有三分钟了, + +1669 +01:08:40,793 --> 01:08:42,226 +since we have three minutes left. +我们就直接写吧。 + +1670 +01:08:42,228 --> 01:08:44,161 +I'm just gonna show you how we would do the segue. +直接给你们看我是怎么写这个跳转的。 + +1671 +01:08:44,163 --> 01:08:46,696 +And we just say, performSegueWithIdentifier. +我调用performSegueWithIdentifier方法。 + +1672 +01:08:46,698 --> 01:08:49,399 +And we haven't talked too much about seguing from code. +我们之前没怎么说过如何用代码做跳转。 + +1673 +01:08:49,401 --> 01:08:50,934 +Some of you + +1674 +01:08:50,935 --> 01:08:52,468 +did it in the extra credits of the assignments. +我看到你们有些人在作业里这么写。 + +1675 +01:08:52,470 --> 01:08:55,938 +And you might be doing it in your final project. +你们可能需要在期末项目里用到这个。 + +1676 +01:08:55,940 --> 01:08:58,106 +Which you just say, performSegueWithIdentifier. +只需要调用performSegueWithIdentifier 。 + +1677 +01:08:58,108 --> 01:09:01,376 +And you need to have the identifier that's gonna show +这里需要一个跟你故事板里匹配 + +1678 +01:09:01,378 --> 01:09:05,680 +up in the storyboard, which I'm gonna call ShowImage. +的标识,这里我有一个常量ShowImage。 + +1679 +01:09:06,682 --> 01:09:08,982 +And the sender here can be anything you want. +发送者传什么都行。 + +1680 +01:09:08,984 --> 01:09:11,051 +But you really want it to kind of be the thing that is +但是你需要传一个可以让跳转 + +1681 +01:09:11,053 --> 01:09:12,885 +causing this segue to happen. +正确发生的对象。 + +1682 +01:09:12,887 --> 01:09:15,554 +Which here really the AnnotationView. +在这里应该是注释点视图。 + +1683 +01:09:15,556 --> 01:09:17,389 +So I'm gonna pass this AnnotationView, +所以我这里传进来注释点视图。 + +1684 +01:09:17,391 --> 01:09:18,557 +right here as the sender. +作为发送者。 + +1685 +01:09:19,526 --> 01:09:21,926 +Now, that's great. +很好。 + +1686 +01:09:21,928 --> 01:09:24,729 +Do that segue by name, but +通过名字来跳转, + +1687 +01:09:24,731 --> 01:09:26,630 +where does the segue actually get created? +但是我们这个跳转是在哪建立的呢? + +1688 +01:09:26,632 --> 01:09:28,598 +What's the source and destination? +源头和目标是什么呢? + +1689 +01:09:28,600 --> 01:09:31,034 +And that, we still do in our storyboard. +我们依然会在故事板里建。 + +1690 +01:09:31,036 --> 01:09:33,836 +So if I go here to my storyboard. +打开故事板。 + +1691 +01:09:34,772 --> 01:09:38,007 +I still create the segue by Ctrl+dragging. +我还是用ctrl + 拖拽来建立跳转。 + +1692 +01:09:38,009 --> 01:09:38,908 +Okay? + +1693 +01:09:38,909 --> 01:09:39,808 +So let's get imageView. +我们需要一个图片视图。 + +1694 +01:09:39,810 --> 01:09:41,109 +I'm gonna steal it from Cassini. +我要从Cassini里偷一个。 + +1695 +01:09:41,111 --> 01:09:43,444 +Let's go back over to Cassini here. +咱们回来找 Cassini 。 + +1696 +01:09:44,647 --> 01:09:46,947 +We'll go, open up Cassini. +在这,打开 Cassini。 + +1697 +01:09:46,949 --> 01:09:48,782 +Let's grab its ImageView first, +让我们先把图片视图拷贝过来。 + +1698 +01:09:48,784 --> 01:09:50,450 +it's imageViewController. +这是图片视图控制器。 + +1699 +01:09:50,452 --> 01:09:51,718 +All right. + +1700 +01:09:51,720 --> 01:09:55,388 +Let's get this showing its navigator too. +打开文件导航。 + +1701 +01:09:55,390 --> 01:09:58,157 +All right, so I'm gonna grab the ImageViewController and +我现在把图片视图控制器拖 + +1702 +01:09:58,159 --> 01:09:59,175 +bring that in. +过来。 + +1703 +01:09:59,176 --> 01:10:00,192 +It's kind of a supporting file. +放到我们的supporting file里。 + +1704 +01:10:00,194 --> 01:10:01,993 +Copy that in. +拷贝进来。 + +1705 +01:10:01,995 --> 01:10:06,297 +I'm also gonna open up Cassini storyboard and +我还需要打开 Cassini的故事板找到 + +1706 +01:10:06,299 --> 01:10:09,199 +find everything, here it is. +它,在这呢。 + +1707 +01:10:09,201 --> 01:10:12,302 +I'm gonna take this UIViewController, right here. +我需要这个视图控制器。 + +1708 +01:10:12,304 --> 01:10:14,237 +And I'm actually going to copy and +我现在要把它复制粘贴到 + +1709 +01:10:14,239 --> 01:10:16,472 +paste it into my storyboard. +我的故事板里。 + +1710 +01:10:17,809 --> 01:10:18,640 +Where is my storyboard? +我的故事板呢? + +1711 +01:10:18,642 --> 01:10:21,576 +I threw a board down here. +记得在这。 + +1712 +01:10:21,578 --> 01:10:23,078 +Okay? + +1713 +01:10:23,079 --> 01:10:24,579 +So I go in here and paste it. +粘贴进来。 + +1714 +01:10:24,581 --> 01:10:25,646 +Let's see if we can find it. +缩小一下看能不能找到。 + +1715 +01:10:26,683 --> 01:10:28,415 +There it is, okay? +在这,找到了。 + +1716 +01:10:28,417 --> 01:10:31,151 +Now remember, copying and pasting between storyboard is +在不同的故事板之前复制粘贴完全没问题, + +1717 +01:10:31,153 --> 01:10:33,153 +works because it's all done by name, +因为它们都是通过名字记录的。 + +1718 +01:10:33,155 --> 01:10:35,922 +the names of the classes, the names of the outlets, +类的名字,outlet的名字。 + +1719 +01:10:35,924 --> 01:10:36,989 +the name of all that stuff. +所有东西的名字。 + +1720 +01:10:36,991 --> 01:10:38,290 +So that will all work fine here. +所以粘贴过来也可以正常工作。 + +1721 +01:10:39,460 --> 01:10:41,993 +So now we just need to create the segue from this +现在我只需要建一个从这里到 + +1722 +01:10:41,995 --> 01:10:43,628 +ViewController to this one. +这里的跳转。 + +1723 +01:10:43,630 --> 01:10:46,664 +And we're executing it in code, so we don't have to +然后通过代码触发跳转,所以我们就不必从一个 + +1724 +01:10:46,666 --> 01:10:49,600 +Ctrl+drag from a button or something like that. +按钮或者别的什么东西开始拖, + +1725 +01:10:49,602 --> 01:10:51,335 +We're gonna actually Ctrl+drag +我们只需要从视图控制器这里 + +1726 +01:10:51,337 --> 01:10:53,069 +from the ViewController itself. +拖拽就可以了。 + +1727 +01:10:53,071 --> 01:10:56,005 +So, I'm gonna Ctrl+drag from this button, right here, +在这个按钮这ctrl + 拖拽, + +1728 +01:10:56,007 --> 01:10:58,641 +to this ViewController, and create a segue, okay? +到这个视图控制器,建立一个跳转。 + +1729 +01:10:58,643 --> 01:11:00,642 +It's a show segue. +类型是show。 + +1730 +01:11:00,644 --> 01:11:01,910 +I'm gonna inspect it, +在检视器里找到它, + +1731 +01:11:01,912 --> 01:11:05,346 +and set its Identifier here to be Show Image. +把标识设成Show Image。 + +1732 +01:11:06,482 --> 01:11:10,417 +Which is the thing that I used over here in my code. +就是我刚才在代码里用到的标志。 + +1733 +01:11:10,419 --> 01:11:11,951 +Right? That's my Constant here, +是我的一个常量。 + +1734 +01:11:11,953 --> 01:11:13,052 +Show Image. +Show Image + +1735 +01:11:13,054 --> 01:11:15,755 +So that's how you do a segue from code. +这样就实现了用代码跳转。 + +1736 +01:11:15,757 --> 01:11:20,058 +And there was no way for us to do it any other way, because +事实上我们也没有别的办法,因为 + +1737 +01:11:20,060 --> 01:11:23,561 +the little callouts aren't there in the storyboard, so +标识视图不在我们的故事板里,我们不能 + +1738 +01:11:23,563 --> 01:11:25,029 +I can't Ctrl+drag from them. +从它们开始ctrl + 拖拽。 + +1739 +01:11:25,031 --> 01:11:27,198 +So I have to drag from the whole View Controller, and +所以我只能从整个视图控制器开始拖, + +1740 +01:11:27,200 --> 01:11:30,300 +then I use this perform segue with identifier +然后我调用 performSegueWithIdentifier 这个方法 + +1741 +01:11:30,302 --> 01:11:31,768 +to cause it to be fired off. +触发跳转。 + +1742 +01:11:31,770 --> 01:11:33,536 +Now this is a normal segue. +这只是正常的跳转, + +1743 +01:11:33,538 --> 01:11:34,871 +We still have prepareForSegue. +我们依然需要实现 prepareForSegue。 + +1744 +01:11:34,873 --> 01:11:36,356 +Okay? + +1745 +01:11:36,357 --> 01:11:37,840 +We still have to prepare for this segue. +我们依然需要准备这个跳转。 + +1746 +01:11:37,842 --> 01:11:39,475 +And so I'm gonna do that. +我准备实现这个方法。 + +1747 +01:11:39,477 --> 01:11:43,545 +I'm gonna say if the segue's identifier equals +先要写,如果跳转的标识等于 + +1748 +01:11:43,547 --> 01:11:46,314 +Constants.ShowImageSegue. +Constants.ShowImageSegue + +1749 +01:11:47,350 --> 01:11:51,385 +Then if we can get a waypoint out of that view's annotation +现在就要判断注释点是不是一个路点, + +1750 +01:11:51,387 --> 01:11:53,319 +so this watch this okay. +注意看这里。 + +1751 +01:11:53,321 --> 01:11:57,290 +Sender as MKAnnotationView. +Sender as MKAnnotationView. + +1752 +01:11:57,292 --> 01:11:59,425 +So first, we've gotta see if this sender, right here, +首先我们要检查这个发送者是不是一个 + +1753 +01:11:59,427 --> 01:12:01,960 +is the MKAnnotationView, which it should be. +MKAnnotationView,它应该是。 + +1754 +01:12:01,962 --> 01:12:08,433 +If it is, question mark, annotation as a GPX.Waypoint. +如果它是,加问号,as GPX.Waypoint。 + +1755 +01:12:08,435 --> 01:12:10,001 +Okay? So we can do all that. +可以一起做检查。 + +1756 +01:12:10,003 --> 01:12:11,986 +Then we've got the waypoint. +这里我们就得到了路点。 + +1757 +01:12:11,987 --> 01:12:13,970 +So here you can see how this optional chaining. +看到这些可选值是如何链接到一起的了吗? + +1758 +01:12:13,973 --> 01:12:16,040 +Starts with something you've got to be, learned to do. +你应该开始学着这么去做, + +1759 +01:12:16,042 --> 01:12:17,107 +Otherwise, you have so +要不然你就会写 + +1760 +01:12:17,109 --> 01:12:19,476 +many if, lets all the time it's ridiculous. +很多很多的if let,这样代码就比较丑。 + +1761 +01:12:19,478 --> 01:12:22,078 +So you gotta be able to do this kind of thing. +你们应该学着这么写。 + +1762 +01:12:22,080 --> 01:12:23,780 +And so + +1763 +01:12:23,781 --> 01:12:25,481 +waypoint here won't be nil if all that makes it through. +这里路点不为空,后边我们就一直往下写。 + +1764 +01:12:25,483 --> 01:12:29,118 +So I'm gonna then, if I can let my ivc equal +if let ivc等于跳转的目标, + +1765 +01:12:29,120 --> 01:12:33,555 +Segue.destination as an ImageViewController. +它应该是一个图片视图控制器。 + +1766 +01:12:35,825 --> 01:12:37,008 +Okay? + +1767 +01:12:37,009 --> 01:12:38,192 +Then, I'm going to just prepare it. +那我们就准备它。 + +1768 +01:12:38,194 --> 01:12:40,694 +So I'm gonna set its ivc.imageURL equal to +把它的imageURL设置成 + +1769 +01:12:40,696 --> 01:12:42,329 +the waypoints.imageURL. +路点的imageURL 。 + +1770 +01:12:42,331 --> 01:12:45,365 +And I'm also gonna set the image's title to be +还要把图片的标题设置成 + +1771 +01:12:45,367 --> 01:12:47,333 +the waypoint's title name. +路点的标题,名字。 + +1772 +01:12:47,335 --> 01:12:48,317 +[SOUND] Okay? + +1773 +01:12:48,318 --> 01:12:49,300 +So this is just normal prepare for +就是很正常的跳转准备, + +1774 +01:12:49,303 --> 01:12:50,669 +segue here, nothing special. +没有特殊的东西。 + +1775 +01:12:52,306 --> 01:12:53,204 +Everyone understand that? +大家都明白了吗? + +1776 +01:12:54,274 --> 01:12:56,841 +And the last thing I'm gonna do in the storyboard +租后,我要在故事板里 + +1777 +01:12:56,843 --> 01:12:58,742 +here is I'm gonna put all of this stuff +把这些东西都放到 + +1778 +01:12:58,744 --> 01:13:00,777 +in a Navigation Controller. +导航控制器里。 + +1779 +01:13:00,779 --> 01:13:03,313 +So, I'm gonna embed in Navigation Controller. +把它们嵌入导航控制器。 + +1780 +01:13:03,315 --> 01:13:05,882 +All right, so this is what our storyboard looks like, +好了,现在我们的故事板就是这个样子的。 + +1781 +01:13:05,884 --> 01:13:07,383 +right here. +在这。 + +1782 +01:13:07,385 --> 01:13:09,402 +Okay? + +1783 +01:13:09,403 --> 01:13:11,420 +So, now when we click on those little Callouts, +现在如果我们点击标识视图, + +1784 +01:13:11,422 --> 01:13:13,121 +it's going to do this segue, and +就应该触发这个跳转, + +1785 +01:13:13,123 --> 01:13:16,725 +cause Image View to come up with the waypoint's image. +图片视图就会弹出来显示路点的图片。 + +1786 +01:13:16,727 --> 01:13:17,892 +So, let's take a look at that. +咱们来试试。 + +1787 +01:13:21,564 --> 01:13:22,863 +All right, here we go. +运行一下。 + +1788 +01:13:22,865 --> 01:13:26,065 +So, let's go find a nice interesting image here. +现在找一张图片。 + +1789 +01:13:27,435 --> 01:13:29,435 +Maybe this guy, right here. +这个吧,就这个。 + +1790 +01:13:29,437 --> 01:13:30,469 +Okay, nice tracks. +nice tracks + +1791 +01:13:30,471 --> 01:13:32,070 +So, I'm just gonna click on here. +我点这里, + +1792 +01:13:32,072 --> 01:13:34,138 +You actually don't even have to click right on here. +实际上不用点这个按钮, + +1793 +01:13:34,140 --> 01:13:35,840 +I think if you click anywhere in the Callout, +点标识视图哪里都可以。 + +1794 +01:13:35,842 --> 01:13:37,492 +it tends to work. +就应该可以跳转。 + +1795 +01:13:37,493 --> 01:13:39,143 +And you can see that it has segue, +看到了吗?它跳转了。 + +1796 +01:13:39,145 --> 01:13:41,745 +not your Image Views are much nicer than mine. +你自己的图片视图应该比我的好看。 + +1797 +01:13:41,747 --> 01:13:44,481 +Okay, you get rid of the white space and all that stuff. +我这里白边太多了。 + +1798 +01:13:44,483 --> 01:13:45,581 +But it looks like that. +大概就是这样。 + +1799 +01:13:45,583 --> 01:13:50,119 +We could go, let's go out to this one or +我们再找一个, + +1800 +01:13:50,121 --> 01:13:51,720 +maybe, what's a better one? +这个怎么样? + +1801 +01:13:51,722 --> 01:13:54,055 +How about, I think this is a good one. +我觉得这个应该不错。 + +1802 +01:13:54,057 --> 01:13:56,408 +Yeah. + +1803 +01:13:56,409 --> 01:13:58,760 +So this trip was a helicopter skiing trip. +直升机滑雪旅行。 + +1804 +01:13:58,762 --> 01:13:59,860 +There's the helicopter coming in. +看到直升机了。 + +1805 +01:14:01,497 --> 01:14:02,963 +So that's it. +就是这样。 + +1806 +01:14:02,965 --> 01:14:07,200 +Does everyone make sense there, what's going on? +大家都理解这些内容了吗? + +1807 +01:14:07,202 --> 01:14:08,868 +All right, that's it for Maps. +好,以上就是关于地图的内容。 + +1808 +01:14:08,870 --> 01:14:11,570 +See you next week. +下周见。 + +1809 +01:14:11,572 --> 01:14:11,603 +>> For more, please visit us at stanford.edu +更多信息请访问 stanford.edu diff --git a/subtitles/15. Modal Segues.srt b/subtitles/15. Modal Segues.srt new file mode 100644 index 0000000..a22ddf6 --- /dev/null +++ b/subtitles/15. Modal Segues.srt @@ -0,0 +1,9134 @@ + +1 +00:00:00,001 --> 00:00:04,536 +[MUSIC] +欢迎收看斯坦福大学公开课 + +2 +00:00:04,538 --> 00:00:07,672 +Stanford University. +本字幕由志愿者义务贡献 + +3 +00:00:07,674 --> 00:00:12,409 +>> Okay, well, welcome to Lecture 15 of +欢迎参加斯坦福大学 2015 年冬季学期的 + +4 +00:00:12,411 --> 00:00:18,114 +Stanford CS193P Winter of 2015. +CS193P 课程的第15讲。 + +5 +00:00:18,116 --> 00:00:21,951 +So my topic slide today, I actually have topics for +这是今天的幻灯片,实际上这些内容是我们这一周两节课 + +6 +00:00:21,953 --> 00:00:24,353 +this whole week, the two days. +所要讲的内容。 + +7 +00:00:24,355 --> 00:00:29,691 +This is going to be kinda one continuous demonstration. +接着将继续一个 deom 演示 + +8 +00:00:29,693 --> 00:00:31,459 +Where I'm going to go back to the demonstration, +deom 演示完成之后,我会在来讲幻灯片上的内容, + +9 +00:00:31,461 --> 00:00:33,561 +back to the slides, back to the demonstration. +然后在再返回继续 deom 演示。 + +10 +00:00:33,563 --> 00:00:35,263 +Although today, +至于今天, + +11 +00:00:35,264 --> 00:00:36,964 +I'm probably only going to cover that first slide point. +我估计只能讲完幻灯片上第一部分, + +12 +00:00:36,966 --> 00:00:39,733 +And then, I have a demo pretty much the rest of the way. +接着,剩余的大部分时间我会现场做一个 demo 演示。 + +13 +00:00:39,735 --> 00:00:42,035 +If I have time left, which hopefully I do, +如果还有时间剩余,我希望会是这样的, + +14 +00:00:42,037 --> 00:00:43,936 +I will do the slides for the camera. +我会继续讲关于摄像头的部分。 + +15 +00:00:43,938 --> 00:00:46,906 +And then, we can start off on Wednesday with the camera part +这样的话,我们周三就可以直接开始摄像头的 demo 演示, + +16 +00:00:46,908 --> 00:00:50,309 +of the demo and then move on to the rest of the stuff. +然后再接着讲下面的内容。 + +17 +00:00:50,311 --> 00:00:51,977 +But, it's pretty action-packed. +嗯,是挺令人激动的。 + +18 +00:00:51,979 --> 00:00:53,144 +I have a lot of stuff to cover, +我有很多东西需要讲, + +19 +00:00:53,146 --> 00:00:55,213 +especially in today's demo. +特别是今天的 demo 。 + +20 +00:00:55,215 --> 00:00:57,314 +It's gonna be a lot more even than just modal and +将包括很多内容,不仅仅是 model segue (模态segue) + +21 +00:00:57,316 --> 00:00:59,450 +popover segues. +和 popover segue(弹出框segue)。 + +22 +00:00:59,451 --> 00:01:01,585 +I'm gonna talk a little bit more about notifications and +我也会加一些 notification 和 adaptations + +23 +00:01:01,587 --> 00:01:03,553 +adaptations, things like that. +方面的内容。 + +24 +00:01:03,555 --> 00:01:05,221 +So there's a lot to cover. +对,有很多内容呢。 + +25 +00:01:05,223 --> 00:01:08,624 +All right so I'm going to dive in here though with modal +我将从 modal view controllers 开始, + +26 +00:01:08,626 --> 00:01:11,427 +view controllers and I intentionally put off +我是故意将 modal segue(模态segue) + +27 +00:01:11,429 --> 00:01:15,264 +the modal segues until towards the end of the quarter. +放到了这个学期的最后才讲。 + +28 +00:01:15,266 --> 00:01:17,366 +Because when people see it early, they're like, oh, wow, +因为如果你早知道了它,你就会,哇 + +29 +00:01:17,368 --> 00:01:18,867 +I'm just gonna put everything up modally. +我可以在任何地方都用它来搞定。 + +30 +00:01:18,869 --> 00:01:21,069 +It's just so easy to do a modal segue. +modal segue(模态segue)用起来非常简单。 + +31 +00:01:21,071 --> 00:01:22,636 +And it is easy to do a modal segue. +对的,modal segue用起来非常方便。 + +32 +00:01:22,638 --> 00:01:26,239 +But it actually has to be used with care because since it +但是实际上用起来要非常小心,如果用的时候一旦锁住屏幕, + +33 +00:01:26,241 --> 00:01:27,874 +locks up, you're out, +你就完了, + +34 +00:01:27,876 --> 00:01:31,411 +basically until they deal with what's on-screen. +基本上,modal segue(模态segue)主要是用来处理屏幕上的内容。 + +35 +00:01:31,413 --> 00:01:34,847 +The users can kinda be a little bit disturbed by modal. +用户有时反而会被它给弄迷糊了。 + +36 +00:01:37,184 --> 00:01:39,984 +Generally users prefer more free flowing thing where they +一般来说,用户更愿意见到的情况是 + +37 +00:01:39,986 --> 00:01:42,253 +can click on something and then move back and +点击一个地方,就能返回。 + +38 +00:01:42,255 --> 00:01:44,388 +things you know, flow a little better. +这样会更好。 + +39 +00:01:44,390 --> 00:01:47,191 +But there are sometimes when it just doesn't make sense for +但是有时候,你的APP不允许这样, + +40 +00:01:47,193 --> 00:01:49,793 +your app to proceed without stopping the user and +必须要求用户回答一个问题之后, + +41 +00:01:49,795 --> 00:01:52,429 +making them answer a question. +才能正常跳转。 + +42 +00:01:52,431 --> 00:01:55,565 +So modal view controllers is what that's good for. +这时,modal view controller 就是派这个用场的。 + +43 +00:01:55,567 --> 00:01:58,668 +We've already seen modal view controllers, actually. +实际上,我们已经见过 modal view controller 了。 + +44 +00:01:58,670 --> 00:02:01,570 +The alerts, the whole alert and action sheet thing. +alert ,整个 alert 和 action sheet 包括在一起。 + +45 +00:02:01,572 --> 00:02:03,538 +That's nothing more than a UIViewController +它们就是一个 UIViewController 。 + +46 +00:02:03,540 --> 00:02:05,507 +that we put up modally. +我们将其设置为模态化。 + +47 +00:02:05,508 --> 00:02:07,475 +Notice that it took over the screen, didn't let us do +注意到,它在屏幕上之后,除非我们点击了之后, + +48 +00:02:07,477 --> 00:02:11,145 +anything until we responded to the alert of the action seat. +否则我们不能操作其它任何东西。 + +49 +00:02:11,147 --> 00:02:13,748 +And modal view controllers are just creating your own +modal view controller 就是创建了你自己创建的 View Controller + +50 +00:02:13,750 --> 00:02:15,249 +things that pop up and +并且弹出的屏幕上, + +51 +00:02:15,251 --> 00:02:17,050 +don't let the user proceed until you deal with it. +它要求用户必须响应,否则不允许进行其他任何的操作。 + +52 +00:02:17,052 --> 00:02:20,754 +So here's an example of a modal view controller. +这里有一个 modal view controller 的例子。 + +53 +00:02:20,756 --> 00:02:23,122 +Here, I'm in the contacts app. +这里,我在联系人的 app 里。 + +54 +00:02:23,124 --> 00:02:26,659 +And if I tap on that little plus in the corner, +如果你点击右上角的的加号, + +55 +00:02:26,661 --> 00:02:29,228 +it's gonna put up a modal MVC. +这里就会出现一个模态的 MVC. + +56 +00:02:29,230 --> 00:02:32,397 +So I'll tap on it, then modal MVC slides up from the bottom. +接着我点击一下,这个模态的 MVC就从底部滑动出来。 + +57 +00:02:32,399 --> 00:02:36,501 +This is an MVC that lets you add a new contact. +这个 MVC 让你增加一个新的联系人。 + +58 +00:02:36,503 --> 00:02:38,970 +And so that's something that you wanna kinda get it all +这样,你就可以继续 + +59 +00:02:38,972 --> 00:02:39,770 +the way you want. +你想做的。 + +60 +00:02:39,772 --> 00:02:41,238 +And say, okay, add it, +就是说,好,加一个, + +61 +00:02:41,240 --> 00:02:44,574 +rather than it being kinda partially added all the time. +我们是不会一直都需要增加新的联系人。 + +62 +00:02:44,576 --> 00:02:45,942 +So that's why they use modal here. +所以我们这里用模态对话框。 + +63 +00:02:45,944 --> 00:02:47,710 +Although, you could probably even think of a way to do this +尽管,你也可以想到不用模态对话框 + +64 +00:02:47,712 --> 00:02:48,310 +non-modally. +的方法。 + +65 +00:02:48,312 --> 00:02:49,745 +But it's not bad. +但是,这个方法其实不错呀。 + +66 +00:02:49,747 --> 00:02:52,781 +Now notice that there's no back button per se. +注意下,这里是没有返回按钮的。 + +67 +00:02:52,783 --> 00:02:54,082 +But a lot of times where the back +但是大多数时候,我们 + +68 +00:02:54,084 --> 00:02:56,684 +button usually would be is a cancel button, okay. +看到的返回按钮就是取消按钮, + +69 +00:02:56,686 --> 00:02:57,852 +Which will take them back, +一样可以让我们回去,对的! + +70 +00:02:57,854 --> 00:03:00,220 +but it will cancel whatever they're doing in this +这样的话,在模态对话框里,你所做的操作, + +71 +00:03:00,222 --> 00:03:01,889 +modal view controller. +都不会被保存。 + +72 +00:03:01,890 --> 00:03:03,557 +And then, often, in the upper right, there is a button, +嗯,一般情况下,在右上角,这里都会有一个按钮, + +73 +00:03:03,559 --> 00:03:06,359 +a done button, or save button, or something like. +done,或是 save ,或是什么其他名字的。 + +74 +00:03:06,361 --> 00:03:09,562 +That will usually commit the changes in the modal +用来提交我们的内容, + +75 +00:03:10,498 --> 00:03:13,065 +view controller, and then dismiss it, okay. +然后将当前视图从当前的显示中移除。 + +76 +00:03:13,067 --> 00:03:15,500 +Now, this particular modal view controller actually +现在,一个单独的 modal view controller 也是可以 + +77 +00:03:15,502 --> 00:03:18,169 +can put another modal view controller up. +被放在另一个 modal view controller 的上面。 + +78 +00:03:18,171 --> 00:03:19,270 +If you look at this button here, +大家看下这个按钮, + +79 +00:03:19,272 --> 00:03:20,904 +add photo, if you click on it, +add photo,你点击一下它, + +80 +00:03:20,906 --> 00:03:23,106 +it's going to put another modal view controller up. +将会出现另外一个 modal view controller 。 + +81 +00:03:23,108 --> 00:03:25,108 +It slides up from the bottom, +从底部滑出来。 + +82 +00:03:25,110 --> 00:03:27,677 +asking you to pick a photo from your photo library here. +让你从你的相册种选择一张照片, + +83 +00:03:27,679 --> 00:03:29,879 +I don't have any photos so I couldn't do it. +我现在没有照片,所以没法选。 + +84 +00:03:29,881 --> 00:03:32,648 +There's no back button here because you +这里是没有返回按钮的,因为你必须选择一张照片, + +85 +00:03:32,650 --> 00:03:34,516 +either pick a photo or you cancel. +或是你不选。 + +86 +00:03:34,518 --> 00:03:35,650 +Okay, so you don't need a dumb button. +对吧,你不需要一个没用的按钮。 + +87 +00:03:35,652 --> 00:03:38,186 +I would have argued that that cancel button, +我认为过这里的取消按钮, + +88 +00:03:38,188 --> 00:03:39,887 +I kind of feel like should be on the left. +应该是在左边的。 + +89 +00:03:39,889 --> 00:03:42,723 +This is an Apple app, so I guess I'm wrong. +不过这是苹果的官方 App ,所以我想应该是我错了。 + +90 +00:03:42,725 --> 00:03:44,324 +But to me I'm always, +但对于我来说, + +91 +00:03:44,326 --> 00:03:47,460 +kinda looking to the upper left for get me out of here, +我一直认为左上角应该有一个按钮,让我离开, + +92 +00:03:47,462 --> 00:03:50,496 +get me back to what I was before, but anyway. +返回到我之前的页面。 + +93 +00:03:50,498 --> 00:03:54,200 +So if we do hit that cancel button you can see that this +这里,我点击取消按钮,你可以看到 + +94 +00:03:54,202 --> 00:03:57,369 +modal view controller then will dismiss, and +modal view controller 就会被移除了,然后就可以看到 + +95 +00:03:57,371 --> 00:03:58,570 +the other one comes back. +之前的 View Controller。 + +96 +00:03:58,572 --> 00:03:59,871 +And same thing here. +同样的, + +97 +00:03:59,873 --> 00:04:02,874 +Once we're done in here let's say we Cancel or we hit Done, +一旦我们点击了 done ,结果也是 + +98 +00:04:02,876 --> 00:04:03,741 +either way. +一样的。 + +99 +00:04:03,743 --> 00:04:05,109 +And then, this one will dismiss and +也是,当前的内容会被移除,返回 + +100 +00:04:05,111 --> 00:04:06,394 +it goes back to where you were. +之前的页面。 + +101 +00:04:06,395 --> 00:04:07,678 +So that's the way modal view controllers work. +这就是 modal view controoler 的工作方式。 + +102 +00:04:07,680 --> 00:04:10,146 +They just take over the screen, you do something and +它们出现在屏幕上,你进行了一些操作之后,它们 + +103 +00:04:10,148 --> 00:04:11,781 +then when they're done they dismiss. +就会被移除。 + +104 +00:04:11,783 --> 00:04:13,149 +Now there's a lot of different ways for +modal view controller有很多种 + +105 +00:04:13,151 --> 00:04:16,785 +modal view controllers to appear on the screen visually. +不同展现在屏幕上的方式。 + +106 +00:04:16,787 --> 00:04:18,820 +And we will talk about that. +后面我们会谈到。 + +107 +00:04:20,123 --> 00:04:22,890 +So as I said, you want to be careful with these. +不过我要说,你必须要小心使用它们。 + +108 +00:04:22,892 --> 00:04:25,059 +They do block your UI, +它们会阻止你的 UI 响应, + +109 +00:04:25,061 --> 00:04:28,796 +it will be completely only doing this one thing. +你只能完成modal view controller 的处理之后,才能继续。 + +110 +00:04:28,798 --> 00:04:30,781 +Again, sometimes that's what you want. +当然,有些时候,这就是你想要的。 + +111 +00:04:30,782 --> 00:04:32,765 +But don't jump to modal view controllers as your at first +但是,当你需要将你的 MVC 展示到屏幕上时,不要将modal view controller + +112 +00:04:32,768 --> 00:04:35,535 +solution to every time you want to put an MVC on screen. +作为你的第一选择。 + +113 +00:04:35,537 --> 00:04:37,570 +You got navigation controllers, +你可以使用 navigation controller, + +114 +00:04:37,572 --> 00:04:40,873 +you got split views, you got tab bars, stuff like that, +你可以使用 split view ,你可以使用 tab bar 这些方法, + +115 +00:04:40,875 --> 00:04:43,842 +those are usually better solutions if possible. +通常,这些都是更好的解决方案。 + +116 +00:04:44,911 --> 00:04:47,545 +All right, so how do we set up a modal segue? +好吧,那我们如何设置一个 modal segue ? + +117 +00:04:47,547 --> 00:04:48,880 +Very, very simple. +非常非常简单。 + +118 +00:04:48,881 --> 00:04:50,214 +You've got your storyboard, well, +你已经有了 storyboard , + +119 +00:04:50,216 --> 00:04:53,050 +sometimes you'll get a MVC, like the alert MVC in code, +你有一个 MVC , 比如一个 Alert MVC , + +120 +00:04:53,052 --> 00:04:55,652 +and you put it up with that present view controller. +你想把它放到你当前展示的 View Controller 上面。 + +121 +00:04:55,654 --> 00:04:57,020 +And I'll talk about that here in a second. +我下面马上就会讲到这个。 + +122 +00:04:57,022 --> 00:04:58,755 +But if you're doing your own MVC, +但如果你需要处理的是你自己创建的 MVC , + +123 +00:04:58,757 --> 00:05:01,290 +usually it's in your storyboard, you've built +通常是在你的 storyboard 里的 MVC , + +124 +00:05:01,292 --> 00:05:04,059 +the MVC that you want to put up modally in there. +你会希望以模态的形式展示。 + +125 +00:05:04,061 --> 00:05:06,294 +And then you just Ctrl + drag to it. +这样你只需要按住Ctrl通过拖拽就可以完成。 + +126 +00:05:06,296 --> 00:05:09,197 +But instead of saying, show or show detail, +不过这次不选择 show 或者 show detail, + +127 +00:05:09,199 --> 00:05:11,332 +you say present modally, okay? +而是选择 present modally ,懂了吗? + +128 +00:05:11,334 --> 00:05:14,935 +And that's just gonna make your MVC appear on screen and +这就可以让你的 MVC 以模态的形式展现屏幕上, + +129 +00:05:14,937 --> 00:05:17,437 +take over and it's as simple as that. +就这么简单。 + +130 +00:05:18,774 --> 00:05:21,040 +You can inspect the segue. +你可以检查一下这个 segue 。 + +131 +00:05:21,042 --> 00:05:25,344 +Anytime you make a segue you can always inspect it +你任何时候都可以检查 segue, + +132 +00:05:25,346 --> 00:05:28,980 +to set the style of segue modal, +并且将它的类型设置为 modal + +133 +00:05:28,982 --> 00:05:32,450 +or push, or you know, the shows, or whatever. +或是 push ,或是其他的,比如 show 之类的。 + +134 +00:05:32,452 --> 00:05:35,353 +And you can also inspect the style or presentation of +同时你也可以看到 modal 下的不同展示样式 + +135 +00:05:35,355 --> 00:05:38,155 +modal, which we'll show you in a second as well. +我后面也会展示给你们看的。 + +136 +00:05:39,558 --> 00:05:42,359 +So, if you need to present a modal view controller, +好了,如果你需要展示一个 modal view controller , + +137 +00:05:42,361 --> 00:05:45,595 +not from a button, so you want some other action. +但不是通过一个按钮 , 你希望通过其他的 action , + +138 +00:05:45,597 --> 00:05:47,897 +Like, for example, you had a map view and +举个例子,你有一个 map view 然后, + +139 +00:05:47,899 --> 00:05:50,566 +you wanted a call-out button to do a modal thing, +你希望有一个 Call-out(呼出)按钮,实现模态的对话框, + +140 +00:05:50,568 --> 00:05:52,734 +which is what we're gonna do today. +顺便说下,这就是我们今后后面需要做的, + +141 +00:05:52,736 --> 00:05:55,070 +Then you can perform segue from code. +然后你可以在代码里直接调用 segue 。 + +142 +00:05:55,072 --> 00:05:57,405 +You already know how to do that. +你应该已经知道怎么做了, + +143 +00:05:57,407 --> 00:06:00,374 +Or if you actually have the view controller in your hand, +或是你已经有了一个 view controller, + +144 +00:06:00,376 --> 00:06:02,643 +you got it cuz it's an alert view controller. +比如你已经有了一个 alert view controller。 + +145 +00:06:02,645 --> 00:06:05,045 +Or when we do the camera we're gonna understand that +或是一个摄像头的 view controller ,后面我们会讲到关于摄像头的使用, + +146 +00:06:05,047 --> 00:06:07,347 +the camera thing gives us a view controller. +它其实返回给我们的也是一个 view controller 。 + +147 +00:06:07,349 --> 00:06:09,615 +We can actually present the view controller using present +我们都可以将这些 View Controller + +148 +00:06:09,617 --> 00:06:10,817 +view controller. +直接展示出来。 + +149 +00:06:10,818 --> 00:06:12,018 +Same way that we did alerts. +和我们处理 alert 的方式是一样的。 + +150 +00:06:12,020 --> 00:06:13,986 +And that's just going to present it. +接着我们就要把它展示出来。 + +151 +00:06:15,055 --> 00:06:18,523 +How it's presented is actually determined by a property +具体如何展示实际上时取决于当前已经在展示的 view controller + +152 +00:06:18,525 --> 00:06:21,292 +on the view controller that's being presented. +上属性设置。 + +153 +00:06:21,294 --> 00:06:23,427 +So a view controllers gets to say, +所以这个view controller 会被告诉说, + +154 +00:06:23,429 --> 00:06:26,730 +here's how I want to be presented modally, okay. +我是希望用这种样式的以模态的形式展示出来。 + +155 +00:06:26,732 --> 00:06:29,733 +And that property is called modalPresentationStyle and +这里我们把这个属性叫做 modalPresentationStyle ,同时,它是 + +156 +00:06:29,735 --> 00:06:31,167 +it's an enumerated type. +一个枚举类型。 + +157 +00:06:31,169 --> 00:06:33,803 +And here are some of the examples here, FullScreen, +这里有一些例子,比如 FullScreen(全屏), + +158 +00:06:33,805 --> 00:06:34,870 +which is the default, +它是默认值, + +159 +00:06:34,872 --> 00:06:37,606 +where it just comes up over the entire screen. +意思是出现的时候是占满整个屏幕的。 + +160 +00:06:37,608 --> 00:06:39,941 +There's OverFullScreen, which is full screen, but +这里还有一个 OverFullScreen ,也是占满整个屏幕, + +161 +00:06:39,943 --> 00:06:42,744 +it doesn't block out what's underneath. +但它并不阻止下面的屏幕互动。 + +162 +00:06:42,746 --> 00:06:44,445 +Okay, so things show through, +好的,通过这样的操作, + +163 +00:06:44,447 --> 00:06:46,647 +the thing that is coming up on top of shows through. +现在将内容在最上方展示出来了, + +164 +00:06:46,649 --> 00:06:49,249 +Now you can't interact with those things behind cause +而你不能和它下面的元素进行交互的原因是, + +165 +00:06:49,251 --> 00:06:51,284 +you're modal but they do show through. +因为你是一个模态的。 + +166 +00:06:51,286 --> 00:06:53,586 +And then of course a .Popover is essentially, +接着,还有一个是 popover 。 + +167 +00:06:53,588 --> 00:06:56,489 +a modal presentation style cause a popover takes over +这种模式态的展示样式,是一个在屏幕上弹出一个 + +168 +00:06:56,491 --> 00:06:58,091 +the screen also. +窗口。 + +169 +00:06:58,092 --> 00:06:59,692 +It just dimis out the rest, you're working in your popover +它刚好盖住了原来的内容,你只能在你弹出的区域内进行交互。 + +170 +00:06:59,694 --> 00:07:02,528 +if you click anywhere else it makes the popover go away. +如果你点击其他地方,弹出出来的页面就会被移除。 + +171 +00:07:02,530 --> 00:07:04,129 +There's some other ones, like form sheet, +这里还有一些其他的,比如 sheet , + +172 +00:07:04,131 --> 00:07:07,298 +which I'll show you in the demo today for on the iPad. +今天我们会在 iPad 上演示这个 demo 。 + +173 +00:07:07,300 --> 00:07:08,633 +Sometimes you want to present something but +有时,你想展示一些内容, + +174 +00:07:08,635 --> 00:07:09,967 +you don't want it to be gigantic, +但你又不希望它们太大, + +175 +00:07:09,969 --> 00:07:10,968 +filling the whole screen, +以至于占据整个屏幕, + +176 +00:07:10,970 --> 00:07:12,135 +you want it to be a little smaller. +你希望它能够小一点儿。 + +177 +00:07:12,137 --> 00:07:13,737 +So we'll show you how to do that. +我会告诉你怎么做到的。 + +178 +00:07:14,839 --> 00:07:18,040 +You prepare for a modal segue exactly like any other segue. +你需要准备一个 modal segue ,和其他的 segue 一样就可以。 + +179 +00:07:18,042 --> 00:07:21,143 +I didn't even put in any yellow on this slide, +我并没有在幻灯片上做什么特别的标记。 + +180 +00:07:21,145 --> 00:07:25,413 +it's just normal code, there's nothing special there. +都是一些很平常的代码,没有什么特别的。 + +181 +00:07:25,415 --> 00:07:27,215 +Some people ask the question a lot, +有一个问题被问了很多次, + +182 +00:07:27,217 --> 00:07:32,119 +well how do I hear back from my modally segued to MVC. +就是我怎么样才能通过 modally segued 返回到 MVC 。 + +183 +00:07:32,121 --> 00:07:36,189 +So like, in the contacts for example, I added a contact. +就像在联系人这个例子中,我增加了一个联系人。 + +184 +00:07:36,191 --> 00:07:37,824 +Well when the contact is added, +当联系人增加了之后, + +185 +00:07:37,826 --> 00:07:40,793 +how does it communicate back to me, here's the contact. +是如何返回给我,这是一个联系人。 + +186 +00:07:40,795 --> 00:07:45,464 +Well, actually the MVC that put that contact adding thing +好吧,实际上, MVC 增加一个联系人的时候, + +187 +00:07:45,466 --> 00:07:49,767 +up, is probably sharing a model with the other one. +是与其他的“部件”共享了一个模型(model), + +188 +00:07:49,769 --> 00:07:51,635 +Which is to say, the database of contact. +比如,就是一个联系人的数据库。 + +189 +00:07:51,637 --> 00:07:53,337 +So when you hit, add contact and you hit done, +所以当你点击,增加一个联系人之后,点击done(保存), + +190 +00:07:53,339 --> 00:07:55,172 +it probably just puts it in the database, okay. +其实只是将这个内容存到数据库了,理解? + +191 +00:07:55,174 --> 00:07:57,540 +So it doesn't really need to communicate back. +所以这里并不需要一个反馈。 + +192 +00:07:57,542 --> 00:07:59,575 +But if it did need to communicate back, +但如果你确实需要一个反馈, + +193 +00:07:59,577 --> 00:08:01,410 +the way you would do that is Unwind. +你需要通过 Unwind 这种方式来获得。 + +194 +00:08:01,412 --> 00:08:02,461 +Okay. +好了。 + +195 +00:08:02,462 --> 00:08:03,511 +Remember the unwinding segues? +还记得 unwinding segue ? + +196 +00:08:03,514 --> 00:08:06,748 +You would just make the done button or whatever in your +在你的模态对话框里加了一个done(保存)按钮之类的 + +197 +00:08:06,750 --> 00:08:10,585 +modal thing, Ctrl+drag it up to that little exit button. +然后按住Ctrl后将这个按钮拖动到这个exit(退出)按钮上面。 + +198 +00:08:10,587 --> 00:08:13,988 +You define the special storyboard ID action thing and +给这个Action定义一个storyboard ID,然后你就 + +199 +00:08:13,990 --> 00:08:15,773 +you would unwind. +可以 unwind(返回)。 + +200 +00:08:15,774 --> 00:08:17,557 +And that's how you would communicate back. +这样你就可以实现得到反馈了。 + +201 +00:08:17,560 --> 00:08:19,993 +A lot of times though modally presented view controllers +大多数情况下,以模态展示的View Controller, + +202 +00:08:19,995 --> 00:08:22,295 +they do what they do and then you just dismiss them. +完成了他们的“工作”之后,它们就会移除自己。 + +203 +00:08:22,297 --> 00:08:24,998 +Because either they're editing this stuff in real time or +这是因为它们都是在实时的修改模型(Model)的内容或是 + +204 +00:08:25,000 --> 00:08:26,699 +they are sharing the model so +其他共享的模型(model) + +205 +00:08:26,701 --> 00:08:28,968 +they can edit the model directly. +所以,它们是可以直接编辑模型(model)。 + +206 +00:08:28,970 --> 00:08:30,803 +So then they'll just dismiss themselves. +然后它们可以直接移除自己。 + +207 +00:08:30,805 --> 00:08:33,905 +So dismissing without doing anything or +在移除的时候不需要任何反馈(回) + +208 +00:08:33,907 --> 00:08:37,975 +unwinding is pretty much the way that Modally segued to +大多数情况下,模态的segue都是这样 + +209 +00:08:37,977 --> 00:08:40,511 +controllers come off screen. +来移除自己的。 + +210 +00:08:40,513 --> 00:08:41,945 +So how do you dismiss it? +那怎样移除呢? + +211 +00:08:41,947 --> 00:08:44,448 +Well if you unwind it automatically dismisses. +如果你使用unwind的话,就会自动移除, + +212 +00:08:44,450 --> 00:08:46,183 +As you know, +这个你已经知道了。 + +213 +00:08:46,184 --> 00:08:47,917 +unwind always includes a dismissal of whatever +unwind 通常是将当前的内容移除之后, + +214 +00:08:47,919 --> 00:08:49,218 +your controller is being unwound from. +然后返回到指定的Controller上。 + +215 +00:08:49,220 --> 00:08:51,887 +But if you're not unwinding, then you're going to call +但如果你不用使用 unwind 的话,你就需要主动调用 + +216 +00:08:51,889 --> 00:08:55,124 +dismissViewControllerAnimated which takes +dismissViewControllerAnimated这个方法了, + +217 +00:08:55,126 --> 00:08:57,259 +the boolean whether you're gonna animate the dismissal, +你可以设置在移除的时候是否需要动画效果。 + +218 +00:08:57,261 --> 00:08:59,427 +which you're always gonna do, pretty much. +多数情况下,你都会选择有动画效果的。 + +219 +00:08:59,429 --> 00:09:04,131 +And this is sent to the presenting view controller. +接着就返回到原来的 View Controller(弹出MVC的MVC)。 + +220 +00:09:04,133 --> 00:09:05,799 +The view controller that presents you. +你就可以看到l。 + +221 +00:09:05,801 --> 00:09:07,000 +'Kay? That is the thing +懂了吗?这就是说 + +222 +00:09:07,002 --> 00:09:09,336 +that is responsible for dismissing you. +你要负责手动移除了。 + +223 +00:09:09,338 --> 00:09:12,605 +Now if you accidentally send this to the presented +如果你将它设置为被展示的 View Controller, + +224 +00:09:12,607 --> 00:09:15,307 +view controller it's gonna forward it on to its +它就会展示在你当前的 View Controller + +225 +00:09:15,309 --> 00:09:16,942 +presenting view controller. +上面。 + +226 +00:09:16,944 --> 00:09:18,744 +Although it can be a little confusing if +这里可能会有点疑惑的地方, + +227 +00:09:18,746 --> 00:09:21,279 +you have a presented view controller that, itself, has +如果你当前正在展示着一个 view Controller ,然后它上面还有 + +228 +00:09:21,281 --> 00:09:24,682 +presented another one and you say dismiss view controller. +另一个被展示的,而你这时移除 View Controller。 + +229 +00:09:24,684 --> 00:09:27,351 +Well, do you mean to dismiss the thing it presented? +那你是想移除被展示的 + +230 +00:09:27,353 --> 00:09:29,687 +Or dismiss from the thing it was presenting? +还是弹出展示的? + +231 +00:09:29,689 --> 00:09:32,956 +So that's why with the rule is, the presenting +对此,有一个规则,移除视图只针对 + +232 +00:09:32,958 --> 00:09:35,158 +view controller is the one you should send this dismiss to. +当前正在展示的(用户可以看到的)View Controller 。 + +233 +00:09:35,160 --> 00:09:37,827 +So I, personally, think it's wrong code for +而我个人觉得,如果你对一个不在展示状态的 view controller + +234 +00:09:37,829 --> 00:09:40,696 +you to send dismiss view controller to the presented +进行移除的话,本身就是不对的。 + +235 +00:09:40,698 --> 00:09:43,098 +view controller expecting it to dismiss itself. +除非是它自己移除它自己。 + +236 +00:09:43,100 --> 00:09:44,132 +'Kay? +懂了吗? + +237 +00:09:44,134 --> 00:09:46,701 +The presented view controller can get its +一个被弹出View Controller 在任何时候都可以有方法得到 + +238 +00:09:46,703 --> 00:09:49,337 +presenting view controller at any time with the method, or +当初“弹出”它的View Controller 。或通过得到这个“弹出”它的 + +239 +00:09:49,339 --> 00:09:52,073 +the variable, presenting view controller. +view controller 这个变量。 + +240 +00:09:52,075 --> 00:09:53,874 +Okay, every view controller that's being presented +也就是输,任何一个被“弹出”的view controller 都是知道 + +241 +00:09:53,876 --> 00:09:55,809 +knows it's presenting view controller and +是谁“弹出”自己的这个view controller, + +242 +00:09:55,811 --> 00:09:57,344 +then it can just send this message to it. +然后也是可以给它发送消息的。 + +243 +00:09:57,346 --> 00:10:00,079 +So we'll see that in the code of the demo as well. +我们后面的 demo 中也有这部分的代码。 + +244 +00:10:01,549 --> 00:10:04,249 +So how does the modal view controller appear onscreen? +如何将一个模态的view controller 展示到屏幕上? + +245 +00:10:04,251 --> 00:10:06,718 +You've seen it slide up from the bottom, right? +你已经看到它是从下面滑动上来的,对吧? + +246 +00:10:06,720 --> 00:10:09,120 +That's the default modal transition style, +这是默认的模态式的过渡效果, + +247 +00:10:09,122 --> 00:10:10,554 +which is called cover vertical. +我们称之为 "cover vertical"。 + +248 +00:10:10,556 --> 00:10:14,291 +And you, again, the view controller that's being +接着,这个View Controller被“弹”出屏幕上, + +249 +00:10:14,293 --> 00:10:17,494 +presented gets to say how it wants to appear on screen. +就像你所希望的那样。 + +250 +00:10:17,496 --> 00:10:22,331 +And so this is different than, you know, the modal style, +至于区别,在模态的样式上 + +251 +00:10:22,333 --> 00:10:24,000 +like form sheet or something like that. +比如需要提交的表单或是其他。 + +252 +00:10:24,002 --> 00:10:26,335 +This is how the animation happens, 'kay? +这里就可以通过动画效果, + +253 +00:10:26,337 --> 00:10:28,236 +How the actual transmission happens. +完成实际的过渡。 + +254 +00:10:28,238 --> 00:10:29,571 +And so, again, +另外, + +255 +00:10:29,573 --> 00:10:31,673 +there's another property in the view controller that's +在view controller 里还有另外一个属性, + +256 +00:10:31,675 --> 00:10:34,442 +being presented called Modal Transition Style. +叫做 Modal Transition Style 。(出现或离开的样式) + +257 +00:10:34,444 --> 00:10:36,076 +And cover vertical's the default, +默认值是 Cover Vertical , + +258 +00:10:36,078 --> 00:10:38,228 +means slide up from the bottom. +就是说从屏幕到底部滑上来。 + +259 +00:10:38,229 --> 00:10:40,379 +There's also flip horizontal, which will just flip over. +另外还有 flip horizontal ,翻转的效果。 + +260 +00:10:40,382 --> 00:10:43,516 +Okay, take from the old, the view that's presenting view +好的,一个弹出的view controller 和 + +261 +00:10:43,518 --> 00:10:45,318 +controller and the presented view controller, +一个被弹出的 view controller 。 + +262 +00:10:45,320 --> 00:10:47,853 +we'll flip over and exchange places. +我们将会通过翻转的形式来交换他们的位置,完成过渡转换。 + +263 +00:10:47,855 --> 00:10:50,889 +There's also cross dissolve where they'll fade out and +这里还有 Corss dissolve ,意思是一个淡出, + +264 +00:10:50,891 --> 00:10:52,925 +the other one will fade in. +另外一个淡入。 + +265 +00:10:52,926 --> 00:10:54,960 +There's even partial curl where the bottom corner +这里还有一个 Partial curl ,意思是从底下一个角 + +266 +00:10:54,962 --> 00:10:59,997 +will kind of curl up and show the new view controller. +翻起来,然后展示出一个新的 View Controller 。 + +267 +00:10:59,999 --> 00:11:02,566 +That one's a little interesting there because +这里有个很有意思的事情, + +268 +00:11:02,568 --> 00:11:04,702 +once you've done that one, you can't do any more +就是你可以选择任意一种样式, + +269 +00:11:04,704 --> 00:11:06,436 +modal transitions because it would make no sense. +因为实际上它们的意义时相同的。(只是样式不同而已) + +270 +00:11:06,438 --> 00:11:09,572 +You've got this curled up kind of look and then you +你可以看到前面一个View Controller 被卷起, + +271 +00:11:09,574 --> 00:11:12,208 +plant something on top of it, that just breaks the illusion +然后在上面展示内容,就好像 + +272 +00:11:12,210 --> 00:11:14,810 +of this being just a little piece of curled thing that +将内容卷起来了一些 + +273 +00:11:14,812 --> 00:11:17,279 +lifts up to show you this modally presented thing. +以模态(式)的形式展示给你内容, + +274 +00:11:17,281 --> 00:11:20,182 +Obviously the partial curls gonna be small view +很明显,这种形式更适合那种比较小(面积)的 + +275 +00:11:20,184 --> 00:11:21,750 +controllers showing. +view controller的展示。 + +276 +00:11:21,752 --> 00:11:24,719 +It's kind of a fun one though sometimes like in the Maps app +这个很有意思,比如在 地图 APP 里, + +277 +00:11:24,721 --> 00:11:26,754 +if you want to set some setting, so +如果你想做一些设置, + +278 +00:11:26,756 --> 00:11:29,757 +turn traffic on, it'll just curl up the map a little bit, +比如打开交通状况,就会在地图的下面卷起一个小角, + +279 +00:11:29,759 --> 00:11:31,925 +you set your settings, and it curls it back down. +你设置完了之后,就会再“压”回去。 + +280 +00:11:31,927 --> 00:11:32,709 +Okay? +对吧? + +281 +00:11:32,710 --> 00:11:33,492 +So kind of fun though. +挺有意思的。 + +282 +00:11:35,030 --> 00:11:37,797 +All right, so the demo I'm gonna do today it's gonna show +好了,今天我要做的 demo ,将包括前面所有的内容, + +283 +00:11:37,799 --> 00:11:40,499 +you all this stuff, modals, segues, all this stuff. +包括, modals 、 segues 等等。 + +284 +00:11:40,501 --> 00:11:43,068 +It's probably gonna take us most of the rest of +我估计我们后面大部分时间都是在 + +285 +00:11:43,070 --> 00:11:44,769 +the time here. +做这个 demo。 + +286 +00:11:44,771 --> 00:11:48,272 +And I'll try to cover a lot of other things along the way. +我会尽量覆盖我们今天所有学到的内容, + +287 +00:11:48,274 --> 00:11:52,109 +I'm gonna start out by doing some draggable MK annotations. +我们先从做一个可以拖动的 MK annotations(注释)开始。 + +288 +00:11:52,111 --> 00:11:54,778 +I'm also gonna talk much more about notifications cuz, +我也会讲不少关于通知(notifications)的内容。 + +289 +00:11:54,780 --> 00:11:56,246 +really, the only notification we did so +是的,我们现在才开始考虑到 + +290 +00:11:56,248 --> 00:11:58,481 +far was where we notified ourself. +通知(notification)这个内容。 + +291 +00:11:58,483 --> 00:12:01,217 +So I'm gonna show you +我还会给你展示 + +292 +00:12:01,218 --> 00:12:03,952 +a little more sophisticated notification where system, +一些复杂一点的 + +293 +00:12:03,955 --> 00:12:06,789 +another object is notifying us. +系统通知, + +294 +00:12:06,791 --> 00:12:12,527 +Then I'm gonna go back and cover pop-overs some more. +然后我们再继续 pop-over 这些内容。 + +295 +00:12:12,529 --> 00:12:15,963 +We covered a little bit back, way back when, in psychologist +我们会讲各种返回,在psychologist 这个项目里。 + +296 +00:12:15,965 --> 00:12:18,866 +but we're gonna do a little more sophisticated popovers. +但我们会做一些更复杂的 popovers 。 + +297 +00:12:18,868 --> 00:12:21,702 +We're also going to talk more about adaptive behavior, +我们也会继续讲一些关于设备的适配。 + +298 +00:12:21,704 --> 00:12:26,039 +which is to say when you have a modal segue happening, +也就是说当你有一个 modal segue, + +299 +00:12:27,108 --> 00:12:29,408 +what if it's on an iPhone versus an iPad? +它分别在iPhone 和 iPad 上各自是怎么展现的? + +300 +00:12:29,410 --> 00:12:31,377 +It doesn't always wanna look exactly the same. +有些时候是会有不同的展现方式的。 + +301 +00:12:31,379 --> 00:12:34,479 +And so we're actually gonna get involved in making it look +所有这些内容我们都会讲到,了解他们是如何 + +302 +00:12:34,481 --> 00:12:36,081 +how we want. +实现的。 + +303 +00:12:36,082 --> 00:12:37,682 +And as part of that I'm going to show you another thing that +另外,我还有内容要你们讲一下, + +304 +00:12:37,684 --> 00:12:40,918 +I don't have any slides on but it's very easy to use called, +因为它比较简单,所以我就没写到幻灯片上, + +305 +00:12:40,920 --> 00:12:43,087 +which is visual effects. +这个内容就是 visual effects (视觉效果)。 + +306 +00:12:43,089 --> 00:12:44,488 +So there's a way to get visual effects, +有很多种不同的 visual effects (视觉效果) + +307 +00:12:44,490 --> 00:12:47,591 +like blurs and vibrancy, things like that. +比如 blurs 和 vibrancy ,类似这些的。 + +308 +00:12:47,593 --> 00:12:49,610 +So I'll show you that. +我也会给你们展示。 + +309 +00:12:49,611 --> 00:12:51,628 +So you can see, a lot of stuff to go through here. +今天你会看到有很多内容。 + +310 +00:12:51,630 --> 00:12:52,879 +And if we have time, +如果我们还有时间, + +311 +00:12:52,880 --> 00:12:54,129 +we'll get back and do through the slides and the camera. +我们还会来继续看有关摄像头这部分的幻灯片。 + +312 +00:12:55,466 --> 00:12:57,633 +All right so we're gonna go back to Tracks and +好,我们现在回到 Tracks 这个项目上来, + +313 +00:12:57,635 --> 00:13:00,402 +what we're gonna do here in Trax is we are going to make +我们看下,如果我们准备 Tracks 增加一个自己定义的 Waypoints的话, + +314 +00:13:00,404 --> 00:13:02,771 +it so we can add our own Waypoints. +我们该怎么做。 + +315 +00:13:02,773 --> 00:13:05,206 +Right now, Tracks just opens up the GPS file and +现在,Tracks 只是打看一个 GPS 文件,然后 + +316 +00:13:05,208 --> 00:13:07,808 +shows you the Waypoints. +将waypoints展示给你。 + +317 +00:13:07,810 --> 00:13:09,810 +And I'll show you, +我要给你展示的是, + +318 +00:13:09,812 --> 00:13:12,512 +remind us what that looks like in case we've forgotten. +先给大家看下这个项目吧,以免你们有人忘了它的样子。 + +319 +00:13:13,682 --> 00:13:15,548 +All right. Here's our Tracks. +好的,这就是 Tracks 。 + +320 +00:13:15,550 --> 00:13:18,951 +And it shows us these nice waypoints down here. +它上面标志了一些 waypoints(航点)。 + +321 +00:13:18,953 --> 00:13:23,154 +And we have a nice image over here, and we have this little +在上面还有一些图片,并且有一些按钮 + +322 +00:13:23,156 --> 00:13:27,258 +button, disclosure button, which will show us the image +disclosure 按钮,点击这个按钮后,我们可以到 + +323 +00:13:27,260 --> 00:13:28,759 +in more detail where we can scroll around. +进一步的详细内容。 + +324 +00:13:28,761 --> 00:13:30,761 +Well, what we're gonna do now is make it so +现在,如果我们长按的话, + +325 +00:13:30,763 --> 00:13:33,463 +that if we long press, in other words, we press and +长按的意思就是按住,然后保持不放开, + +326 +00:13:33,465 --> 00:13:36,666 +hold, it's gonna drop a pin there for us. +这样,会有一个小的标志“钉”我们的放的位置 + +327 +00:13:36,668 --> 00:13:37,700 +And then we're going to be able to set +我们将给这个小东西加一个名称, + +328 +00:13:37,702 --> 00:13:39,935 +the little thing like Valley Floor there, +比如Valley Floor,或是 + +329 +00:13:39,937 --> 00:13:41,937 +or the views are spectacular even from here. +一些美景之类的。 + +330 +00:13:41,939 --> 00:13:43,838 +We'll be able to set that for our thing. +我们能够自己设置这些内容。 + +331 +00:13:43,840 --> 00:13:45,840 +And we'll even be able to set an image once we learn +在我们后面学了有关摄像头的内容之后, + +332 +00:13:45,842 --> 00:13:48,376 +about how to do the camera next time. +我们还可以设置图片。 + +333 +00:13:49,345 --> 00:13:52,346 +But in order to make this work I'm actually gonna change our +但为了让我们能做到,我实际上稍微做了一点改动, + +334 +00:13:52,348 --> 00:13:56,082 +track slightly, which is right now to see this image in more +现在只有点击进入详情之后才可以看到图片, + +335 +00:13:56,084 --> 00:14:00,419 +detail, I press on this little detail disclosure button. +点击这个小小的展示详情按钮(Detail disclosure button)才能。 + +336 +00:14:00,421 --> 00:14:04,589 +I'm gonna change it so that you click on the image itself. +我会改成你点击这个图片自己,就能看到 + +337 +00:14:04,591 --> 00:14:08,293 +To see the image in more detail so that I can free this +更多的详细内容,这样我就很方便了, + +338 +00:14:08,295 --> 00:14:11,662 +up to be our, we just added a user waypoint and +可以直接加一个航点(waypoint) , + +339 +00:14:11,664 --> 00:14:13,064 +now we want to edit it, button. +如果想编辑它,需要一个编辑按钮。 + +340 +00:14:13,066 --> 00:14:14,631 +'Kay? So this is gonna be our +懂了?这将是一个可以被编辑的 waypoint, + +341 +00:14:14,633 --> 00:14:17,601 +editable user waypoint editing button. +通过这个编辑按钮。 + +342 +00:14:17,603 --> 00:14:19,636 +So I'm gonna make that change real quick. +接着我会先快点的把这个需求完成, + +343 +00:14:19,638 --> 00:14:21,388 +So let's go ahead and do that. +好了,我们开始吧。 + +344 +00:14:21,389 --> 00:14:23,139 +That's really easy to do, it turns out. +这个其实很容易做的,打开项目。 + +345 +00:14:23,141 --> 00:14:29,778 +Right now when we build our callout view right here. +现在我们先创建一个这里需要被调出的 View 。 + +346 +00:14:29,780 --> 00:14:32,347 +'Kay? Here's a view for annotation? +对吧?这是一个注释的 View 。 + +347 +00:14:32,349 --> 00:14:33,648 +Okay? Here's where we +好了,这就是我们需要 + +348 +00:14:33,649 --> 00:14:34,948 +build our callout accessory views. +创建的被调用的详细 View(视图)。 + +349 +00:14:34,951 --> 00:14:37,552 +Instead of using a UIImage view to build it, +之前我们是用一个 UIImage View 实现的,这次我们 + +350 +00:14:37,554 --> 00:14:40,321 +I'm just gonna make it be a UIButton. +使用 UIButton 来实现。 + +351 +00:14:40,323 --> 00:14:42,373 +'Kay? +懂了? + +352 +00:14:42,374 --> 00:14:44,424 +Now, of course, once I make it a UIButton, I also have to +当然,一旦我用了 UIButton ,我也不得不 + +353 +00:14:44,427 --> 00:14:47,661 +make sure that I load this UIButton up properly, so +确保这个 UIButton 可以被正确的加载, + +354 +00:14:47,663 --> 00:14:49,996 +I'm gonna go down here to div select annotation view, +所以我觉得决定先听一下去选择一个 注释的视图, + +355 +00:14:49,998 --> 00:14:52,999 +which is where we currently load up that left callout +这个注释视图在被弹出之后,就是会被 + +356 +00:14:53,001 --> 00:14:54,934 +access review. +展示的。 + +357 +00:14:54,935 --> 00:14:56,868 +I'm gonna change this from being a thumbnail image view +我这里会先把这个缩略图(Image View)改成一个 缩略图的 + +358 +00:14:56,871 --> 00:15:01,573 +to calling it the thumbnail ImageButton +图片式按钮(Image Button)。 + +359 +00:15:01,575 --> 00:15:03,641 +because it's an image button now instead of an image view. +将 Image View 替换成了 Image Button 。 + +360 +00:15:03,643 --> 00:15:08,012 +And of course it's not a UIImageView here, it's a UIButton. +当然了,这里就不是一个UIImageView,而是一个 UIButton 。 + +361 +00:15:08,014 --> 00:15:10,581 +And then the only other thing is you don't set a buttons +这里还有一件事事情你需要做,这样就能让你的按钮看起来 + +362 +00:15:10,583 --> 00:15:13,750 +image by saying dot image equals image. +和图片是一样似的。 + +363 +00:15:13,752 --> 00:15:16,419 +You call a method actually called SetImage. +你需要调用一个方法叫做 SetImage 。 + +364 +00:15:17,522 --> 00:15:19,522 +Image. +Image 。 + +365 +00:15:19,523 --> 00:15:21,523 +And it has, for state, because the button has various states, +因为按钮有很多种不同的状态,所以这里需要指定状态(state), + +366 +00:15:21,525 --> 00:15:24,626 +highlighted states, other kind of states, but we're just +聚焦状态(highlighted states),以及一些其他的状态,但我们 + +367 +00:15:24,628 --> 00:15:27,095 +gonna set it for the normal state of the button. +这里只要设置一个正常的状态(Normal state)就可以了。 + +368 +00:15:27,097 --> 00:15:29,731 +So that's the only change I need to make +这里我重要做这一个改变就 + +369 +00:15:29,733 --> 00:15:30,598 +to make this work. +可以了。 + +370 +00:15:30,599 --> 00:15:31,464 +So let's go take a look at this and +然后我们再过来看下这个能够展示 + +371 +00:15:31,467 --> 00:15:34,568 +here we can comment out now our little +详细内容的这个 + +372 +00:15:34,570 --> 00:15:36,303 +right callout detail thing. +展示详情按钮。 + +373 +00:15:36,305 --> 00:15:37,404 +We don't need that. +我们已经不需要了。 + +374 +00:15:37,406 --> 00:15:38,638 +Bring it back in second here. +直接把它们放到后面就好。 + +375 +00:15:39,674 --> 00:15:41,507 +But here's our things. +但这里还有件问题。 + +376 +00:15:41,509 --> 00:15:43,508 +And so now here when we click it notice we don't have +就是我们现在点击之后,没有了按钮之后 + +377 +00:15:43,510 --> 00:15:46,611 +the detailed disclosure on there anymore cuz I commented +我们也无法从右面“呼唤”出 + +378 +00:15:46,613 --> 00:15:47,745 +that out right here. +详细的页面。 + +379 +00:15:47,747 --> 00:15:49,847 +But this is now a button so +不过现在它已经是一个按钮了, + +380 +00:15:49,849 --> 00:15:53,517 +if I click it now I get to see my image, okay? +所以当我点击的话,我就应该可以看到我们的图片了,对吧? + +381 +00:15:53,519 --> 00:15:55,919 +So I haven't changed the functionality of my app at +到现在我们还有在APP里改过代码, + +382 +00:15:55,921 --> 00:15:58,188 +all, I just kind of moved it to be click on here as +我们只是移动了之后,让它变成可以被点击 + +383 +00:15:58,190 --> 00:16:00,323 +opposed to having the detailed disclosure. +取代了原来的展示详情按钮。 + +384 +00:16:00,325 --> 00:16:01,524 +Okay, everybody cool? +好了,对这个内容, + +385 +00:16:01,526 --> 00:16:03,092 +With that. +大家都理解了? + +386 +00:16:03,094 --> 00:16:04,793 +All right. +好的。 + +387 +00:16:04,795 --> 00:16:06,261 +So, now we've done that. +我们现在已经做好了。 + +388 +00:16:06,263 --> 00:16:09,464 +Now let's make it so that if I long press, +接着让我们来处理“长按”的问题。 + +389 +00:16:09,466 --> 00:16:13,701 +which means press and hold, it drops a new pin, okay. +也就是说点击后,然后保持,这里将会“钉”住一个小标志。 + +390 +00:16:13,703 --> 00:16:15,669 +So how do I do that? +我们该怎么做? + +391 +00:16:15,670 --> 00:16:17,636 +I'm just going to go to my storyboard here. +我们先回到 storyboard 。 + +392 +00:16:17,639 --> 00:16:19,239 +And in my storyboard, +在我的 storyboard 里, + +393 +00:16:19,241 --> 00:16:24,110 +I'm going to add a long press gesture to my map view, here. +我将在我的map view里增加一个长按的手势。 + +394 +00:16:24,112 --> 00:16:27,713 +So let's go down here, pull this up. +好了,让我们来看,把这个拉上去。 + +395 +00:16:27,715 --> 00:16:30,649 +I'm gonna search for, long press. +我来搜一下 long press 。 + +396 +00:16:30,651 --> 00:16:32,518 +There it is, right there. +找到了,就在那里。 + +397 +00:16:32,519 --> 00:16:34,386 +So I'm just going to drag this gesture out onto my map +我讲把这个手势直接拖到我的 + +398 +00:16:34,388 --> 00:16:35,386 +view, okay. +map view 上。 + +399 +00:16:35,388 --> 00:16:37,088 +You can see that it appears over here in my +你能在大纲视图下看到我们刚刚增加的 + +400 +00:16:37,090 --> 00:16:38,856 +document outline. +手势 + +401 +00:16:38,858 --> 00:16:39,990 +Now let's bring up the code. +然后,让我们来看下代码怎么处理。 + +402 +00:16:39,992 --> 00:16:43,159 +Okay, I'll put this right here in the waypoints +好的,我们先找到 waypoints(航点) 的对应的部分, + +403 +00:16:43,161 --> 00:16:44,527 +section right here. +对,就是这里。 + +404 +00:16:44,529 --> 00:16:48,731 +So I'm going to control drag from this long press gesture +让我要从长按这个手势上 按住 ctrl 拖到 + +405 +00:16:48,733 --> 00:16:49,998 +into here. +这里。 + +406 +00:16:50,000 --> 00:16:52,133 +It's going to be gesture. +拖过来的将是一个手势。 + +407 +00:16:52,135 --> 00:16:54,102 +I'm going to call it addWaypoint. +我给它命名为 addwaypoint 。 + +408 +00:16:54,104 --> 00:16:55,936 +It's what it does. +就是这么做的。 + +409 +00:16:55,938 --> 00:16:59,306 +It's got the long press gesture as the argument here. +这里有一个参数是 长按的手势。 + +410 +00:16:59,308 --> 00:17:01,041 +All right, so there's that. +对的,就是这样。 + +411 +00:17:01,043 --> 00:17:02,676 +Let's go back here. +然后我们回到 stroyboard 。 + +412 +00:17:02,678 --> 00:17:05,244 +Let's go up to here, okay. +对,我们继续,可以吧。 + +413 +00:17:05,246 --> 00:17:09,114 +So here is, where is that? +这是,在哪里? + +414 +00:17:09,116 --> 00:17:09,998 +Here it is. +在这里。 + +415 +00:17:09,999 --> 00:17:10,881 +This is the thing I just added, +这就是我刚才加的。 + +416 +00:17:10,884 --> 00:17:12,484 +this LongPressGesture right here. +这个长按的手势就在这里。 + +417 +00:17:13,753 --> 00:17:15,519 +So what do we need to do inside +那我们需要在这个 LongPressGesture 方法 + +418 +00:17:15,521 --> 00:17:17,421 +of this LongPressGesture? +里写些什么呢? + +419 +00:17:17,423 --> 00:17:19,556 +Really not a whole lot to do. +其实没有太多的要写的。 + +420 +00:17:19,558 --> 00:17:23,760 +I'm gonna say if the sender.state, +我这里要写 if sender.state 就可以了。 + +421 +00:17:23,762 --> 00:17:27,329 +that's the state of the gesture, basically. +这个状态是指手势的状态。 + +422 +00:17:27,331 --> 00:17:31,900 +If that equals UIGestureRecognizerState.began, +如果等于 UIGestureRecognizeState.began + +423 +00:17:31,902 --> 00:17:36,337 +now I could do this when this long press starts, +就是长按时间开始, + +424 +00:17:36,339 --> 00:17:38,322 +which is, I'm doing. +也就是,我正在长按。 + +425 +00:17:38,323 --> 00:17:40,306 +Or I could do it when the long press ends. +或是我也可以等长按结束之后来处理。 + +426 +00:17:40,309 --> 00:17:42,976 +And long pressed by the way, you'll get changed, also, +同时,在长按事件中,如果你保持长按的时候向下移动 + +427 +00:17:42,978 --> 00:17:46,279 +as you hold it down, you'll get a change happening. +也会有一个change的事件。 + +428 +00:17:46,281 --> 00:17:48,181 +But I like to do it when I began, +不过我愿意当一发生的时候就处理, + +429 +00:17:48,183 --> 00:17:49,716 +because I want instant feedback. +因为我想要及时的反馈。 + +430 +00:17:49,718 --> 00:17:51,183 +The user holds the long press, +用户长按的时候, + +431 +00:17:51,185 --> 00:17:54,520 +as soon as it's recognized as a long press and begins, boom, +刚刚长按的时候,就能被识别,很快, + +432 +00:17:54,522 --> 00:17:56,355 +we're gonna drop that pin down there. +我就准备在这里“钉”一个小的标志。 + +433 +00:17:56,357 --> 00:17:58,890 +So they don't have to hold their finger any longer and +他们并不需要将手指长按的状态保持太长时间, + +434 +00:17:58,892 --> 00:17:59,924 +they don't have to hold it down and +也不需要在保持长按的时候下移一下 + +435 +00:17:59,926 --> 00:18:01,992 +say, hm, where's that, nothings happening. +然后说,看,什么都没有嘛。 + +436 +00:18:01,994 --> 00:18:05,529 +Okay, so that's why I decided to do it on began here. +这样,我决定在一开始的就处理。 + +437 +00:18:06,565 --> 00:18:10,466 +And to create one we need the coordinates that they clicked +然后根据在他们点击的位置,我们创建一个坐标 + +438 +00:18:10,468 --> 00:18:13,402 +on, right, or that they long pressed, they held down. +对,就是他们长按的地方。 + +439 +00:18:13,404 --> 00:18:17,306 +We need to find out the CL location coordinate 2D. +我们需要得到这个坐标。 + +440 +00:18:17,308 --> 00:18:20,175 +Where in the world they just did that. +在真实的世界中,他们的坐标。 + +441 +00:18:20,177 --> 00:18:23,745 +And to do that we're going to use this method in map view +然后我将用Map View里的一个叫 converPoint的方法,这个方法 + +442 +00:18:23,747 --> 00:18:26,881 +called convertPoint, which takes a point, so +可以传入一个 Point 对象,然后 + +443 +00:18:26,883 --> 00:18:30,551 +let's get the location of the gesture in the map view's +可以让我们得到用户在屏幕上点击的坐标,对应在 Map View 里的坐标系 + +444 +00:18:30,553 --> 00:18:33,320 +coordinate systems, okay. +中对应的坐标。 + +445 +00:18:33,322 --> 00:18:35,789 +And it converts it to the coordinate system of any view +这个方法可以帮助你在任何视图中转化坐标系。 + +446 +00:18:35,791 --> 00:18:37,441 +you want. +这个方法可以帮助你在任何视图中转化成你想要的坐标系。 + +447 +00:18:37,442 --> 00:18:39,092 +Which we're going to actually convert it the mapView's +在这里我们实际是希望将其转为地图视图的 + +448 +00:18:39,094 --> 00:18:43,429 +coordinate system which is not much of a conversion, okay. +坐标系下,这是一个的转换。 + +449 +00:18:43,431 --> 00:18:45,497 +So that creates a view. +接着我们创建一个视图。 + +450 +00:18:45,499 --> 00:18:50,702 +So we've converted this gesture to this coordinate +因为我们已经将手势的坐标转换为地图视图下的坐标, + +451 +00:18:50,704 --> 00:18:54,505 +in the mapView, so now we have a CL location coordinate 2D, +所以我们现在得到了2D坐标系下的 CL 位置。 + +452 +00:18:54,507 --> 00:18:56,040 +here I'll click on this so +这里我点击一下,可以看到这是 + +453 +00:18:56,041 --> 00:18:57,574 +you can see that's a CLLocationCoordinate2D, +CLLocationCoordinate2D 。 + +454 +00:18:57,576 --> 00:18:59,509 +that's where the person pressed down. +也就是在用户按下的位置, + +455 +00:18:59,511 --> 00:19:03,813 +So now I'm just gonna create the waypoint, and we can +我可以直接创建一个 waypoint ,然后我们 + +456 +00:19:03,815 --> 00:19:08,283 +create the waypoint using GPX waypoint, it only has one +就可以使用GPX的waypoint类来创建了,它只有一个构造方法, + +457 +00:19:08,285 --> 00:19:12,687 +constructor which is the latitude and the longitude. +需要传入经度和纬度。 + +458 +00:19:12,689 --> 00:19:14,689 +Okay, so now we've created a waypoint. +好了,现在我们已经创建了一个 waypoint 。 + +459 +00:19:14,691 --> 00:19:17,524 +Maybe we'll set some things in the waypoint, like the name. +我们也可以设置其他的一些信息,比如名称。 + +460 +00:19:17,526 --> 00:19:18,725 +We just dropped this, so +我们就是要放在这里的,因此 + +461 +00:19:18,727 --> 00:19:21,828 +I'm going to call this the waypoint dropped, okay. +因此这个 waypoint 叫做 dropped 。 + +462 +00:19:21,830 --> 00:19:26,432 +And then let's just add this annotation +接着,我们给这个 map view 加上 + +463 +00:19:26,434 --> 00:19:28,934 +to the map view, okay. +annotation 。 + +464 +00:19:28,936 --> 00:19:31,269 +So that's all we need to do to drop something on there. +所以我们需要做的就是在这里放一些内容, + +465 +00:19:31,271 --> 00:19:32,203 +So let's go take a look at that. +那让我们先看一下。 + +466 +00:19:36,509 --> 00:19:38,559 +All right, so here's all our points. +对的,这里是我们所有的标志点。 + +467 +00:19:38,560 --> 00:19:40,610 +And I'm just gonna long press, you see it dropped one there. +然后当我长按之后,你就会看到这里会增加一个。 + +468 +00:19:40,613 --> 00:19:42,579 +And if I click on it, it says, dropped. +然后当我点击的时候,看到这里写着,dropped 。 + +469 +00:19:42,581 --> 00:19:44,247 +Now, I don't have any image associated with. +现在,我们还没有与之关联的图片。 + +470 +00:19:44,249 --> 00:19:47,650 +I don't have any little sub-information info +在这里也没有任何相关的内容。 + +471 +00:19:47,652 --> 00:19:49,585 +field on here. +在这里也没有任何相关的内容。 + +472 +00:19:49,586 --> 00:19:51,519 +So, we need to make it so that it does that. +我们需要增加这些内容。 + +473 +00:19:51,522 --> 00:19:52,688 +But first, I'm going to make it so +不过,首先我们需要让它 + +474 +00:19:52,690 --> 00:19:54,356 +that this can be dragged. +变成可以拖拽的。 + +475 +00:19:54,358 --> 00:19:56,224 +Because what if I dropped it here, and +因为当你在这里放置之后, + +476 +00:19:56,226 --> 00:19:59,127 +then I looked in here closer and I was like, +我可以把地图放大,可以看的更清楚一些。 + +477 +00:19:59,129 --> 00:20:02,063 +oh no I wanted to drop it on the other side of that road. +哦,我想把它拖到这条路的另外一边, + +478 +00:20:02,065 --> 00:20:03,497 +Okay, I can't pick it up. +但我现在不能拖动。 + +479 +00:20:03,499 --> 00:20:06,833 +So I'd like to be able to pick this thing up and move it. +所以我想可以能让它在地图拖动, + +480 +00:20:06,835 --> 00:20:08,435 +So what do we need to do that? +我们要怎么样才能做到呢? + +481 +00:20:08,437 --> 00:20:12,338 +That's very simple as well, we just need to make, +这个也非常简单,我们只需要回到这里, + +482 +00:20:12,340 --> 00:20:16,275 +back here remember, here's our extension to GPX waypoint that +记得吗,这时我们的 GPX 的 Waypoint 的 extension , + +483 +00:20:16,277 --> 00:20:19,778 +we extended so that it would be an MK annotation. +我们为让他可以作为 MK annotation 而进行的扩展(继承)。 + +484 +00:20:19,780 --> 00:20:21,813 +We just need to make this note be a get only, +我们当时将它设置为只读。 + +485 +00:20:21,815 --> 00:20:23,448 +it needs to be set and get. +现在需要设置为可以读也可以写。 + +486 +00:20:23,450 --> 00:20:25,149 +That's really the only thing you need to do to make +只需要这么做,它就可以变成 + +487 +00:20:26,652 --> 00:20:28,118 +something be draggable. +可以拖动的了。 + +488 +00:20:28,120 --> 00:20:30,387 +Now, I'm gonna do that in a separate subclass here. +这里,我将会在写一个单独的子类, + +489 +00:20:30,389 --> 00:20:34,190 +I'm gonna call it EditableWaypoint, okay, +我给它起名为 Editablepoint , + +490 +00:20:34,192 --> 00:20:36,793 +it's a subclass of GPX.Waypoint. +它是 GPX.Waypoint 的子类。 + +491 +00:20:36,795 --> 00:20:42,531 +And all it's going to do is override that var coordinate, +我们就是为了重载变量 coordinate 。 + +492 +00:20:42,533 --> 00:20:46,601 +and it's perfectly fine to override a var +在子类里重载一个var型的变量是完全没有问题的, + +493 +00:20:46,603 --> 00:20:50,138 +in a subclass to turn it into set and get. +然后可以将其设置为可以读也可以写。 + +494 +00:20:50,140 --> 00:20:54,441 +So the get is just gonna return supers version of this, +这里get的方法直接返回super的就可以。 + +495 +00:20:54,443 --> 00:20:56,777 +okay. +好了。 + +496 +00:20:56,779 --> 00:21:01,014 +And our set, all I'm gonna do on my set, is I'm going to set +至于set方法,我们将实现自己的set方法,我将设置 + +497 +00:21:01,016 --> 00:21:04,917 +my latitude equal to the new values latitude. +原来的维度为 newValue 的维度值。 + +498 +00:21:04,919 --> 00:21:07,419 +And I'm gonna set my longitude, +同时我们也设置原来的经度值等于 + +499 +00:21:07,421 --> 00:21:09,387 +equal to the new values longitude. +newValue 的 经度值 + +500 +00:21:09,389 --> 00:21:12,957 +Okay, and remember that latitude and longitude, +好了,记住这里维度值和经度值, + +501 +00:21:12,959 --> 00:21:16,493 +these are just properties in GPX waypoints, okay. +它们是作为 GPX waypoints 类的属性。 + +502 +00:21:17,696 --> 00:21:19,429 +Well it has links, you know, +其他还有比如 links, + +503 +00:21:19,431 --> 00:21:22,131 +to our thumbnail images and all that stuff. +缩略图和其他一些内容。 + +504 +00:21:22,133 --> 00:21:23,532 +But really, the main thing about +但实际上, GPX waypoint 最重要的 + +505 +00:21:23,534 --> 00:21:25,434 +GPX waypoint is just the latitude and longitude. +属性还是经度值和纬度值。 + +506 +00:21:25,436 --> 00:21:28,937 +So now we've made this new class, EditableWaypoint, which +所以我们写了一个新类, EditableWaypoint , + +507 +00:21:28,939 --> 00:21:34,475 +is a GPX waypoint, but it has a settable coordinate, okay. +在原本的基础上,增加了可以设置的坐标。 + +508 +00:21:34,477 --> 00:21:37,545 +So down here, instead of creating a GPX waypoint, +然后在这里,当我们长按的时候,我们将创建一个 EditableWaypoint , + +509 +00:21:37,547 --> 00:21:42,949 +when we long press we're gonna create an editable waypoint, +替换掉原来创建GPX waypoint的方法, + +510 +00:21:42,951 --> 00:21:44,284 +okay. +好了。 + +511 +00:21:44,286 --> 00:21:45,785 +One other thing you need to do though, +另外还有一件你需要做的事情就是 + +512 +00:21:45,787 --> 00:21:49,155 +is that pin annotation, okay, the little +“钉”住一个小的标志, + +513 +00:21:49,157 --> 00:21:52,224 +pin, we need to say that it's draggable, so I'm gonna say +我们需要设置小标志的视图是可以拖动的,我们通过设置 view.draggable 就可以 + +514 +00:21:52,226 --> 00:21:55,627 +view.draggable to set this thing to be draggable. +让它能够拖动了。 + +515 +00:21:55,629 --> 00:21:58,697 +But I'm only going to do that if the annotation +但只有当它是一个 EditableWaypoint 时, + +516 +00:21:58,699 --> 00:22:00,898 +is an editable way point. +我才会把它设置为可拖动的。 + +517 +00:22:02,902 --> 00:22:05,502 +Okay, remember is is kind of like as, but +好的,记住这一点,我们后面需要测试 + +518 +00:22:05,504 --> 00:22:08,204 +you're just testing it to see if it is, +到底是不是这样的。 + +519 +00:22:08,206 --> 00:22:11,374 +rather than casting it to be something else, okay. +还是其他什么情况。 + +520 +00:22:11,376 --> 00:22:12,808 +So that's it. +好了,就这样。 + +521 +00:22:12,810 --> 00:22:14,243 +So, let's go back. +然后让我们回来看下效果。 + +522 +00:22:14,245 --> 00:22:16,678 +Now our user waypoints should be draggable. +现在我们的用户加的 waypoints 应该是可以拖动的了。 + +523 +00:22:16,680 --> 00:22:18,747 +All right, we'll drop one here. +好的,我在这里有一个“钉”住的 。 + +524 +00:22:18,749 --> 00:22:21,683 +And I can pick it up here and move it over onto the other + 我再选中它,将它挪到这条河的另外一边, + +525 +00:22:21,685 --> 00:22:24,285 +side of the river there, okay, anywhere I want. +或是任意的什么地方。 + +526 +00:22:24,287 --> 00:22:27,688 +Notice that these ones down here are not draggable. +注意啊,其他的这些都是不可以拖动的。 + +527 +00:22:27,690 --> 00:22:30,590 +Can't drag them because they're not of class +不能拖动的原因就是因为它们不是 EditableWaypoint 类的对象 + +528 +00:22:30,592 --> 00:22:35,228 +EditableWaypoint, they're just GPX.waypoint, okay? +它们只是 GPX.waypoint ,对吧? + +529 +00:22:35,230 --> 00:22:38,564 +So draggable is really easy to do. +所以拖动实现起来很容易。 + +530 +00:22:38,566 --> 00:22:43,101 +So now I freed up that right detail disclosure call-out, +现在,我们接着处理展示右侧详细内容的, + +531 +00:22:43,103 --> 00:22:46,871 +and we're going to turn that into our edit uneditable +我准备把它加在我们这个 editable Waypoint上, + +532 +00:22:46,873 --> 00:22:48,005 +waypoint, right? +对吧? + +533 +00:22:48,007 --> 00:22:50,507 +Change the name field, change the info field, +需要修改名称的文本框,信息的文本框, + +534 +00:22:50,509 --> 00:22:53,010 +add an image to it, all that stuff. +然后加上一张图片,就这些了。 + +535 +00:22:53,012 --> 00:22:55,679 +That's what we're gonna make that be. +这就是我们需要做的了。 + +536 +00:22:55,681 --> 00:22:57,513 +So let's go back down here. +所以我们回来继续。 + +537 +00:22:57,515 --> 00:22:58,814 +Here's the old code we had for +这时我们之前为 rightCalloutAccessoryView + +538 +00:22:58,816 --> 00:23:01,583 +that rightCalloutAccessoryView, and +写的代码,这里的大部分代码 + +539 +00:23:01,585 --> 00:23:03,485 +I want most of that. +都是需要的。 + +540 +00:23:03,486 --> 00:23:05,386 +But instead of adding that little detailed disclosure +原来这个当 waypoint 上有图片时,我们就会增加一个 + +541 +00:23:05,389 --> 00:23:06,654 +when the waypoint has an image, +查看详细的小按钮。 + +542 +00:23:06,656 --> 00:23:13,294 +I'm gonna do it whenever the annotation is an editable one. +现在我们要改成,如果这是一个可以编辑的航点的注释,就放置这个小按钮。 + +543 +00:23:13,296 --> 00:23:15,997 +So if it's editable, +也就是,如果它是可以编辑的, + +544 +00:23:15,998 --> 00:23:18,699 +I'm gonna put that little detail disclosure there, okay. +我就在这里放一个查看详细的按钮。 + +545 +00:23:18,701 --> 00:23:25,905 +So now, we have to modally segue because this new MVC, +好,我们对这个新的MVC必须使用模态的 Segue, + +546 +00:23:25,907 --> 00:23:28,874 +we're gonna need a new MVC that lets us edit the name and +这个新的MVC可以让用户为这个 waypoint + +547 +00:23:28,876 --> 00:23:31,010 +the image of a waypoint. +编辑名称和图片。 + +548 +00:23:31,012 --> 00:23:32,744 +We're going to do that modally. +我们将用模态的方法。 + +549 +00:23:32,746 --> 00:23:33,945 +We're gonna do a modal segue. +我们需要通过 modal segue 。 + +550 +00:23:33,947 --> 00:23:35,346 +We just learned about modal segues. +刚刚学过的 modal segue 。 + +551 +00:23:35,348 --> 00:23:36,580 +How are we gonna do that? +我们该怎么做呢? + +552 +00:23:36,582 --> 00:23:39,149 +Well this is the rightCalloutAccessoryView +这是 rightCalloutAccessoryView , + +553 +00:23:39,151 --> 00:23:42,719 +here, so I'm gonna go down to where the CalloutAccessoryView +当 CalloutAccessoryView 被点击了, + +554 +00:23:42,721 --> 00:23:45,722 +is tapped, and right now it just always does the show +就会展示一个图片, + +555 +00:23:45,724 --> 00:23:48,958 +image segue way, which I still want it to do if we tapped on +我希望是能点击它,然后出现 + +556 +00:23:48,960 --> 00:23:50,926 +the leftCalloutAccessoryView, +leftCalloutAccessoryView , + +557 +00:23:50,928 --> 00:23:53,996 +but if we tapped on the right one, I want it to edit it. +如果我点击右边的,就可以直接编辑。 + +558 +00:23:53,998 --> 00:23:55,964 +So I'm gonna put a little if-then in here to +所以你这里我就需要写一个 if-then 来达到 + +559 +00:23:55,966 --> 00:23:58,033 +that effect. +这个效果。 + +560 +00:23:58,034 --> 00:24:00,101 +So I'm actually gonna say, if the control that we tapped on. +这里我就是要写,如果我点击了 + +561 +00:24:00,103 --> 00:24:03,471 +As a button which they both should be buttons okay, but +这个按钮,实际它们都应该是按钮,这里我只是 + +562 +00:24:03,473 --> 00:24:05,973 +I'm just gonna make sure here. +我需要确认一下。 + +563 +00:24:05,975 --> 00:24:11,244 +If the button type equals UI button type detail +接着判断 这个按钮的类型是不是 Detail Disclosures , + +564 +00:24:11,246 --> 00:24:13,947 +disclosures, so if it's the detail disclosure button, then +如果这是一个 Detail Disclosure button, + +565 +00:24:13,949 --> 00:24:20,519 +I'm going to do my modal segue to edit my waypoint, okay. +我就使用我的 modal Segue 到编辑我的 waypoint , + +566 +00:24:20,521 --> 00:24:25,023 +Otherwise, I'm going to do a little more of a check here. +否则,我就在这里做一个检查。 + +567 +00:24:25,025 --> 00:24:28,026 +I'm going to say, if the waypoint equals the views +意思就是,如果这个 waypoint 的视图 + +568 +00:24:28,028 --> 00:24:31,963 +annotation as a GPX.Waypoint, +对象的类型是 GPX.Waypoint , + +569 +00:24:31,965 --> 00:24:35,866 +which it should because the only kind of. +现在是现在我们 + +570 +00:24:37,670 --> 00:24:39,302 +An annotation that I even have, +只有一种类型, + +571 +00:24:39,304 --> 00:24:40,970 +aur GPX Waypoint annotations. +GPX Waypoint annotations 。 + +572 +00:24:40,972 --> 00:24:43,873 +But in the future, what if I added something else in there? +但如果在后面,我们增加一些新的类型会怎么样呢? + +573 +00:24:43,875 --> 00:24:45,674 +So I'm just being a little careful. +所以我这里要小心点,多做点事情。 + +574 +00:24:45,676 --> 00:24:50,545 +I'm also gonna say, if the Waypoint.imageURL does +我会说,如果 Waypoint.imageURL 不等于 nil , + +575 +00:24:50,547 --> 00:24:54,415 +not equal nil, cuz if there's no URL in the Waypoint, +也就是是这里 waypoint 没有 URL 这个属性, + +576 +00:24:54,417 --> 00:24:58,519 +then I don't want to segue to that image showing +我就不会把图片展示到 + +577 +00:24:58,521 --> 00:25:00,354 +the image view controller, right? +image view controller 上,对吧? + +578 +00:25:00,356 --> 00:25:03,256 +So, I'm just protecting myself a little bit here to make sure +这样我是为了保护我的程序, + +00:25:03,258 --> 00:25:04,123 +that I actually have it. +确认它确实有这个属性。 + +580 +00:25:04,125 --> 00:25:05,391 +Cuz I might have a thumbnail but +因为我可能有一个缩略图, + +581 +00:25:05,393 --> 00:25:08,227 +I don't have the image, possibly, unlikely. +但我并没有图片,这是有可能的。 + +582 +00:25:08,229 --> 00:25:09,995 +All right. So, how about edit waypoint? +好了,那如果是 edit waypoint 该怎么样呢? + +583 +00:25:09,997 --> 00:25:12,163 +What are we going to do in edit waypoint? +我们后面该怎么做呢? + +584 +00:25:12,165 --> 00:25:14,799 +Well, we're just going to segue. +我需要调用 segue 。 + +585 +00:25:14,801 --> 00:25:19,870 +So I'm going to perform a segue with identifier. +我们将会写 performSsegueWithIdentifier。 + +586 +00:25:19,872 --> 00:25:22,305 +I need a new identifier because I'm not segueing to +我需要一个给这个 segue 设定新的名字,因为原来是“跳转”到 + +587 +00:25:22,307 --> 00:25:25,575 +the image thing, I'm segueing to an editing waypoint thing. +一张图片 ,现在是跳转到一个可以编辑 waypoint 的视图。 + +588 +00:25:25,577 --> 00:25:27,377 +So I have a constant for that, +我这里设置一个常量, + +589 +00:25:27,379 --> 00:25:31,180 +actually, called EditWaypointSegue. +叫做 EditWaypointSegue 。 + +590 +00:25:31,182 --> 00:25:33,399 +Okay. +好的 + +591 +00:25:33,400 --> 00:25:35,617 +So EditWaypointSegue is down in my constants sections here. +现在 EditWaypointSegue 就写在了我们的常量里面了, + +592 +00:25:35,619 --> 00:25:36,751 +It's Edit Waypoint. +就是 Edit Waypoint 。 + +593 +00:25:36,753 --> 00:25:39,220 +Okay, so this is what we're going to have to make sure +好的,这就是保证我们调用的 segue 是我们在storyboad + +594 +00:25:39,222 --> 00:25:41,555 +we put in our storyboard for that segue. +里面增加的那个。 + +595 +00:25:41,557 --> 00:25:43,223 +Just like we put this in our storyboard for +这个就像我们之前在 storyboard 里增加的 + +596 +00:25:43,225 --> 00:25:43,824 +the image segue. +image segue 一样。 + +597 +00:25:43,826 --> 00:25:45,358 +All right. +好的。 + +598 +00:25:45,360 --> 00:25:46,526 +So it's at a waypoint. +这就是在 waypoint 要做的事情。 + +599 +00:25:46,528 --> 00:25:50,229 +And sender, again, we'll have the sender be the view. +接着,sender,我们需要把这个 send 转换为 视图(view)。 + +600 +00:25:50,231 --> 00:25:52,231 +Okay, the annotation view. +对的,应该是一个注释的视图(annotation view)。 + +601 +00:25:52,232 --> 00:25:54,232 +Cuz that's really who's kind of causing this to happen, +这就是我们想要的效果, + +602 +00:25:54,234 --> 00:25:56,968 +cuz we're in its call out so it's the calling it out. +我们“叫“它出来,它就出来。 + +603 +00:25:56,970 --> 00:25:58,369 +Now the other thing I'm going to do here is I'm +接下来我们要做的事情就是 + +604 +00:25:58,371 --> 00:26:02,506 +actually going to deselect this annotation. +当我们不取消选中时, + +605 +00:26:02,508 --> 00:26:04,908 +Probably I would want to unwind, +我们需要“返回”到前一个页面 + +606 +00:26:04,910 --> 00:26:06,209 +come back and reselect it. +并移除它。 + +607 +00:26:06,211 --> 00:26:09,278 +But I want it to be deselected because it's currently showing +并且我希望它变成不非选中状态,因为我想换掉 + +608 +00:26:09,280 --> 00:26:13,549 +the current state of the annotation, +当前正在展示详细信息的 + +609 +00:26:13,551 --> 00:26:17,452 +of the waypoint, and I'm going to be changing that. +这个waypoint,对,我想换一个waypoint看看。 + +610 +00:26:17,454 --> 00:26:20,121 +So when I come back, I don't want it to be there. +所以当我返回时,我希望是这样的。 + +611 +00:26:20,123 --> 00:26:24,292 +Okay, it's showing the old data I wanted to be, +嗯,它把之前的数据展示给我了, + +612 +00:26:24,294 --> 00:26:26,861 +I either want you to have to force you to redisplay it or +我这里必须强制把内容给更新了, + +613 +00:26:26,863 --> 00:26:28,829 +maybe, if I were going to add more code, +为此,我们将多写一点代码。 + +614 +00:26:28,831 --> 00:26:30,497 +I could make it so that it redisplayed. +来让它重新展示一次数据。 + +615 +00:26:30,499 --> 00:26:33,800 +But, in any case, I definitely want this annotation to be +但其实,我真是希望当我要编辑这个注释点时候,它其实是 + +616 +00:26:33,802 --> 00:26:40,139 +deselected when I segue it to go edit it. +非选中状态的。 + +617 +00:26:41,976 --> 00:26:42,675 +Okay? +可以理解? + +618 +00:26:42,676 --> 00:26:43,375 +All right, so that's it. +好了,就这样。 + +619 +00:26:43,377 --> 00:26:45,010 +That's all we need to do here. +我们就需要在这里。 + +620 +00:26:45,012 --> 00:26:47,111 +We just need to go to our storyboard now and +我们先需要去到 Stroyboard 然后创建一个新的MVC, + +621 +00:26:47,113 --> 00:26:51,315 +create that new MVC that edits this thing and add this segue. +来用来编辑这些内容,并且加上一个Segue。 + +622 +00:26:51,317 --> 00:26:52,249 +So let's do that. +好,我们开始吧。 + +623 +00:26:52,251 --> 00:26:55,118 +Let's go to our storyboard, and +先到我们的 Stroyboard , + +624 +00:26:55,120 --> 00:26:57,887 +we're gonna be segueing from our map view again. +我们还是会从我们的 Map View 开始创建一个 Segue, + +625 +00:26:57,889 --> 00:27:00,089 +Inside one of the call-outs we're going to be segueing. +我们需要链接到被呼唤出的视图中的一个。 + +626 +00:27:00,091 --> 00:27:02,324 +So just like we have this segue right here, +嗯,对,我们就是要连接到这里, + +627 +00:27:02,326 --> 00:27:05,894 +that came from this little thing. +连接到这个小东西上。 + +628 +00:27:05,896 --> 00:27:08,430 +Our new one's gonna come from this little guy, too. +我们新的连接讲从这里个小东西开始。 + +629 +00:27:08,432 --> 00:27:10,264 +So let's go ahead and get one. +好,让我们继续来做。 + +630 +00:27:10,266 --> 00:27:13,534 +Let's go down here and add a new view controller. +我要再加一个 View Controller 。 + +631 +00:27:13,536 --> 00:27:15,135 +So I'm creating a brand new view controller. +这里我是创建来一个新的空白的 View Controller 。 + +632 +00:27:15,137 --> 00:27:17,504 +We'll pop it up here. +我把它先放到这里。 + +633 +00:27:17,506 --> 00:27:18,304 +Okay? Move it out of +可以?然后把它往外 + +634 +00:27:18,306 --> 00:27:19,272 +the way a little. +稍微挪一下。 + +635 +00:27:19,274 --> 00:27:20,439 +And I'm gonna segue, +接着我就开始创建 Segue , + +636 +00:27:20,441 --> 00:27:22,608 +just the way I did before, from this thing. +可以之前做的一样,从这个小东西开始, + +637 +00:27:22,610 --> 00:27:24,276 +Control drag. +按住 Ctrl ,然后拖动, + +638 +00:27:24,278 --> 00:27:26,077 +Okay, to segue to this. +好了,连接到这里。 + +639 +00:27:26,079 --> 00:27:28,212 +But this time I'm going to do present modally. +但这次我们希望是以模态的方式。 + +640 +00:27:28,214 --> 00:27:30,981 +Last time we did show, we were in a navigation controller +上次因为我们是在 Navigation Controller 里面, + +641 +00:27:30,983 --> 00:27:32,666 +down there, but we said show. +所以我们可以直接设置为 show 。 + +642 +00:27:32,667 --> 00:27:34,350 +So this time even though I'm in navigation controller, +而这次尽管我们也是在 Navigation Controller 里面, + +643 +00:27:34,353 --> 00:27:36,153 +I'm still going to say present modally, +我们也还是会设置为模态展示, + +644 +00:27:36,155 --> 00:27:38,788 +which is going to cause this new view controller to come up +这样我们就可以让新的 View Controller 出现时 + +645 +00:27:38,790 --> 00:27:39,922 +over the whole screen. +占据整个屏幕。 + +646 +00:27:39,924 --> 00:27:40,956 +Question? >> If you worked in +有问题吗? >> 你现在是 + +647 +00:27:40,958 --> 00:27:42,991 +a navigation controller letter and if not, +Naviation Controller 里面,那如果不是的话, + +648 +00:27:42,993 --> 00:27:44,659 +which one would you suggest using? +我该怎么做呢? + +649 +00:27:44,661 --> 00:27:46,027 +>> Yeah, so the question was, +>> 好的,这个问题是, + +650 +00:27:46,028 --> 00:27:47,394 +if I wasn't in a navigation controller. +如果我不是在 Navgation Controller , + +651 +00:27:47,397 --> 00:27:48,796 +If you look here. +如果是在这里, + +652 +00:27:48,798 --> 00:27:50,598 +See this guy right here? +看到这个位置了? + +653 +00:27:50,599 --> 00:27:52,399 +He's in this navigation controller right here. +它是在 Navigation Controller 的旁边。 + +654 +00:27:52,402 --> 00:27:54,968 +If I weren't in a navigation controller, would it make any +如果我现在不是在 Naviation Controller 里的话,我设置一个 + +655 +00:27:54,970 --> 00:27:57,170 +difference to this modal segue and the answer is no. +modal segue 有什么区别吗?答案是没有区别。 + +656 +00:27:57,172 --> 00:27:59,039 +Modal segues don't care where you are. +Modal segue 不会管你在哪里。 + +657 +00:27:59,041 --> 00:28:02,208 +They're going to take over the screen and show themselves. +它们只是在直接在当前的屏幕上把内容展示出来,仅此而已。 + +658 +00:28:02,210 --> 00:28:04,177 +Okay. +好了。 + +659 +00:28:04,178 --> 00:28:06,145 +And the question of is it better to be or not to be, +这个问题就是做好呢,还是不做好呢? + +660 +00:28:06,147 --> 00:28:08,380 +if you're presenting modal it really doesn't matter. +如果你用模态的方式,不是非常必须的。 + +661 +00:28:08,382 --> 00:28:10,349 +But if you're in a navigation controller it's nice because +如果你还时在 Navigation Controller 里,那就还好,因为你还有 + +662 +00:28:10,351 --> 00:28:13,852 +you can have this kind of segue which is pushing, okay. +一个 Push 的 segue 可以使用。 + +663 +00:28:13,854 --> 00:28:16,421 +And you could argue this whole editing of the waypoint, +你这里可能也会有疑惑,我们编辑 waypoint 的地方 + +664 +00:28:16,423 --> 00:28:17,988 +maybe that should be a push. +也应该是使用 Push 的呀。 + +665 +00:28:17,990 --> 00:28:20,758 +And you go push to a place where you edit it, and then +以 Push 形式的方式展示需要编辑的视图, + +666 +00:28:20,760 --> 00:28:24,261 +you hit save or done, but it's kind of ambiguous then unless. +然后可以点击保存,但这里有一点可能是不明确的。 + +667 +00:28:24,263 --> 00:28:26,329 +When you edit it, you're going to change it live, +当你想想要编辑它时,你就先需要把它激活, + +668 +00:28:26,331 --> 00:28:28,348 +like we're going to do our modal one. +就像我们将要处理我们的模型(modal)。 + +669 +00:28:28,349 --> 00:28:30,366 +So, I'm showing you this to show you modal segues, but +这里,我们是为来给你展示 Modal segue ,但实际上 + +670 +00:28:30,368 --> 00:28:32,368 +I actually, if I were really writing an app, +如果是我自己写APP, + +671 +00:28:32,370 --> 00:28:34,603 +I'd probably push to this and +我会选择用 Push 的方式 + +672 +00:28:34,605 --> 00:28:36,905 +have it be live editing, where if I change something, +并且保持它可以实时编辑,当我修改了什么地方, + +673 +00:28:36,907 --> 00:28:39,607 +it's changing that thing in real time. +这里的内容也跟着实时进行改动。 + +674 +00:28:39,609 --> 00:28:41,943 +Cuz that's how I'm going to do this modal anyway. +这里我要执行处理这个模态对话框的话, + +675 +00:28:41,945 --> 00:28:44,779 +The modals, actually, may be better when you are presenting +实际上,当你展示完成之后,再允许它们变成可编辑的, + +676 +00:28:44,781 --> 00:28:46,513 +something that you're going to allow them to edit, and +这样会更好,然后再处理 + +677 +00:28:46,515 --> 00:28:48,882 +then hit cancel, 'kay? +点击取消, + +678 +00:28:48,884 --> 00:28:50,283 +Versus Save. +和保存。 + +679 +00:28:50,285 --> 00:28:51,684 +That modal might be better for that, but +这样处理会更好点, + +680 +00:28:51,686 --> 00:28:54,320 +here I'm just trying to show you the mechanics of modal. +但现在我将给你们展示的是 模态的机制。 + +681 +00:28:54,322 --> 00:28:56,255 +So here's out modal segue right here. +这里是一个 modal segue , + +682 +00:28:56,257 --> 00:28:58,223 +We gotta make sure we put its identifier, +我先给它取一个名字, + +683 +00:28:58,225 --> 00:29:00,525 +Edit Waypoint, we're gonna call it. +叫Edit Waypoint,我们就这么叫它。 + +684 +00:29:00,527 --> 00:29:02,660 +You can see that segue 写的是 modal. +你可以看到这个 Segue 的类型是 modal。 + +685 +00:29:02,662 --> 00:29:05,262 +And I told you here that you can control things like +我也和你们说过,你可以修改一些信息,比如展示类型 + +686 +00:29:05,264 --> 00:29:07,564 +the presentation style of it. +presentation style 等等 + +687 +00:29:07,566 --> 00:29:09,099 +And I'm going to show you that when we +等下我还会给你们展示如果是在iPad 上的话, + +688 +00:29:09,101 --> 00:29:12,268 +go look at this on an iPad in a moment here. +会是什么样子。 + +689 +00:29:12,270 --> 00:29:14,170 +But for an iPhone it doesn't really matter because it's +但在iPhone上没有什么变化,出现方式 + +690 +00:29:14,172 --> 00:29:15,671 +always going to slide up from the bottom. +一直都是从底部滑上来的。 + +691 +00:29:15,673 --> 00:29:20,142 +That's the way iPhones present modal segues by default. +这个就是 iPhone 的 Modal segues 的默认(展示方式)。 + +692 +00:29:21,445 --> 00:29:23,578 +Okay, so we have this nice thing, so let's go ahead and +好了,我们已经做完了,让我们运行一下 + +693 +00:29:23,580 --> 00:29:24,545 +run this and see what this. +看看效果如何。 + +694 +00:29:25,514 --> 00:29:27,147 +What we made happen here. +运行的效果将会是什么样的。 + +695 +00:29:27,149 --> 00:29:32,118 +All right, so now I'm going to add a new thing here. +哦好的,我还要加一个东西呢。 + +696 +00:29:32,120 --> 00:29:33,552 +It's dragable, right? +它应该是可以被拖动的,对吧? + +697 +00:29:33,554 --> 00:29:35,421 +I can pick it up, put it somewhere else. +我可以选中它,然后把它拖到其他的地方去。 + +698 +00:29:35,423 --> 00:29:37,156 +It's here. It says dropped. +就是这这里,叫做 dropped 。 + +699 +00:29:37,157 --> 00:29:38,890 +And now, when I click on this, notice that these guys, +现在,当我点击这,注意一些内容, + +700 +00:29:38,892 --> 00:29:42,494 +by the way, don't have the editable thing. +它们是不能被编辑的。 + +701 +00:29:42,496 --> 00:29:44,495 +They still have their image, okay? +它们还是用的自己的图片,对吧? + +702 +00:29:44,497 --> 00:29:46,530 +But they don't have, they're editable. +但这些不是多,它们是可以被编辑的。 + +703 +00:29:46,532 --> 00:29:47,998 +But this one has this whole editable, so +这个事可以被编辑的,所以 + +704 +00:29:48,000 --> 00:29:50,634 +I'm going to click on this and we'll see what happens. +我点击一下,看看会发生什么。 + +705 +00:29:50,636 --> 00:29:51,869 +Okay? +对吧? + +706 +00:29:51,870 --> 00:29:53,103 +Perfect. Slides up from the bottom. +完美,从底部滑上来的。 + +707 +00:29:53,105 --> 00:29:55,405 +I'm this modal MVC where I can edit the waypoint. +我现在是在模态的MVC里,我可以直接 waypoint 。 + +708 +00:29:55,407 --> 00:29:59,808 +Now we have a built-in UI to do that, but, here we are. +现在我有内置的 UI 做这些工作,就是它们。 + +709 +00:29:59,810 --> 00:30:01,076 +Kay? +对吧? + +710 +00:30:01,078 --> 00:30:04,479 +So, now we're going to put our UI in here to edit this. +所以我们现在就要在这里放一些控件作为可以编辑的, + +711 +00:30:04,481 --> 00:30:06,447 +So let's do that. +让我们开始吧。 + +712 +00:30:06,449 --> 00:30:08,199 +That's right here. +就在这里。 + +713 +00:30:08,200 --> 00:30:09,950 +It's going to be a pretty simple UI, +这是一个非常简单的 UI 。 + +714 +00:30:09,952 --> 00:30:13,286 +I'm just going to get a couple of text fields out here. +我只需要放一些 Text Field (文本框)就好了。 + +715 +00:30:14,389 --> 00:30:16,622 +Okay, a text field for the name, a text field for +一个保存名称的文本框, + +716 +00:30:16,624 --> 00:30:18,491 +that little info field. +一个保存信息的文本框 + +717 +00:30:18,493 --> 00:30:20,392 +A label for each of those. +然后在前面都为他们加上一个 Label 。 + +718 +00:30:20,394 --> 00:30:22,494 +That's pretty much my entire UI. +这就是我们要的 UI 了。 + +719 +00:30:22,496 --> 00:30:24,629 +One label is called Name. +一个 Label 叫做 Name 。 + +720 +00:30:24,631 --> 00:30:26,864 +I'm gonna add those, it will be my line. +它们应该排在同一行。 + +721 +00:30:26,866 --> 00:30:28,799 +The other one is called, let's call it Info. +另一个我们就叫做 Info 。 + +722 +00:30:28,801 --> 00:30:31,368 +Have that be right aligned. +让它们都对齐好。 + +723 +00:30:31,370 --> 00:30:33,036 +We'll put this up in the corner here and +我们可以点击这个地方,会自动为我们加上 + +724 +00:30:33,038 --> 00:30:37,440 +do all of our auto-layout constraints. +auto-layout 的限制值。 + +725 +00:30:37,442 --> 00:30:38,864 +We'll put that there, +我们这样来放, + +726 +00:30:38,865 --> 00:30:40,287 +we'll put this one up in this corner. +我将把其中一个放在这个角。 + +727 +00:30:40,288 --> 00:30:41,710 +Actually we'll have them align their baselines right there, +实际上我们是让它们都和这 baselines 刚好对齐, + +728 +00:30:41,713 --> 00:30:43,212 +it's a good idea. +这是一个好办法。 + +729 +00:30:43,214 --> 00:30:44,413 +This guy. +这些, + +730 +00:30:44,415 --> 00:30:45,080 +Try and align. +也一样对齐。 + +731 +00:30:45,082 --> 00:30:45,980 +Whoops. +哦。 + +732 +00:30:45,982 --> 00:30:47,548 +Align his baseline if we can. +也和它的 baseline 对齐。 + +733 +00:30:47,550 --> 00:30:49,016 +Yeah, there he is. +对,就是这样。 + +734 +00:30:49,018 --> 00:30:50,951 +Yeah, there we go. +好的,我们继续。 + +735 +00:30:50,953 --> 00:30:52,686 +There and align the baseline. +这里有一条可以对齐的 baseline。 + +736 +00:30:52,688 --> 00:30:55,288 +Let's drag this all the way over here like this. +让我们把其他的内容也拖拽成这样。 + +737 +00:30:56,624 --> 00:30:59,024 +This one over here, we'll try to line these up. +我会让它们可以排成一行。 + +738 +00:30:59,026 --> 00:31:04,429 +Okay, one thing that I want to do here is. +好的,我想这个是这样的。 + +739 +00:31:04,431 --> 00:31:06,898 +So let's just set all our constraints here at all once. +然后让我们一次性的生成我们的限制值(constraints)吧。 + +740 +00:31:06,900 --> 00:31:08,332 +I'm going to do it really quickly. +我下面会很快的把这些做好。 + +741 +00:31:08,334 --> 00:31:09,784 +Again, you've seen so +你们已经看多了很多关于 + +742 +00:31:09,785 --> 00:31:11,235 +many how to layout demos you don't see a little more, +布局的例子,但你们没有看到过,这次 + +743 +00:31:11,237 --> 00:31:13,870 +but I'm going to left this guy to the trailing edge. +我让这个东西和下面的边缘“联系”起来。 + +744 +00:31:13,872 --> 00:31:16,106 +I'm going to hook this guy to the trailing edge. +我将把它们进行“关联”。 + +745 +00:31:16,108 --> 00:31:17,874 +I'm gonna hook this guy to the top. +然后我会把这个东西和顶部进行“关联”。 + +746 +00:31:17,876 --> 00:31:20,710 +I'm gonna hook this guy to the bottom, but +我将把这个东西到关联到底部, + +747 +00:31:20,712 --> 00:31:23,912 +this is kind of an interesting one because I'm going to hook +但有意思的地方是,这个关联后的值是 + +748 +00:31:23,914 --> 00:31:26,381 +him to the bottom with greater than or equal. +大于或等于。 + +749 +00:31:26,383 --> 00:31:29,084 +Because I really just want to make sure that he's +因为我只是想让这个距离的值是从这个值 + +750 +00:31:29,086 --> 00:31:32,286 +the standard value distance away from the bottom or +到底部边缘或是更多一点 + +751 +00:31:32,288 --> 00:31:33,220 +more, okay. +都可以。 + +752 +00:31:33,222 --> 00:31:34,621 +I don't really care, +我并不太在意这个, + +753 +00:31:34,623 --> 00:31:37,324 +I just never want him to smash into the bottom. +我只是希望它能够和底部边缘有一定的距离。 + +754 +00:31:37,326 --> 00:31:38,725 +So we'll do that. +所以我才这么做。 + +755 +00:31:38,726 --> 00:31:40,125 +Let's go ahead and put this one here. +让我们继续,来处理这个 + +756 +00:31:40,128 --> 00:31:41,761 +Leading space. +Leading space。 + +757 +00:31:41,763 --> 00:31:44,296 +This one also, leading. +这个头部的。 + +758 +00:31:44,298 --> 00:31:47,566 +Let's put these two separated by a vertical space. +我们先在垂直距离方向放上两个间隔。 + +759 +00:31:47,568 --> 00:31:49,368 +Let's separate these. +让我们把他们间隔开。 + +760 +00:31:49,370 --> 00:31:50,902 +Let's separate this. +然后把这个也分开。 + +761 +00:31:50,904 --> 00:31:55,573 +I want this one and this one, sorry, this one and this one, +我想把这个和这个,哦,不对,是这个和这个, + +762 +00:31:55,575 --> 00:31:58,676 +to always be lined up their left edges. +一直和他们的左边缘靠齐。 + +763 +00:31:58,678 --> 00:32:01,511 +Right, I don't want this to be ragged edged, +对的,我不想他们和边缘的距离参差不齐的, + +764 +00:32:01,513 --> 00:32:04,814 +so I'm gonna line their left edges up as well. +所以我想也让他们在左侧边缘进行对齐。 + +765 +00:32:04,816 --> 00:32:08,184 +So it looks like we got all of our things except for +这样看起来我们把事情搞定了,处理 + +766 +00:32:08,186 --> 00:32:09,485 +vertical position for name. +这个名字的垂直位置。 + +767 +00:32:09,487 --> 00:32:10,786 +Okay, that's because, +对对,这是因为, + +768 +00:32:10,788 --> 00:32:16,124 +let's line up these baselines, baseline here, baseline here. +我们把他们根据这些 baseline 排成一行后,选择 baseline here , baseline here 。 + +769 +00:32:16,126 --> 00:32:18,860 +All right, so all gone, everything's lined up, okay. +好的,所有的内容都排版好了。 + +770 +00:32:18,862 --> 00:32:20,928 +Wow we didn't even need to update our frames, +我现在只需要更新一下展示就好了, + +771 +00:32:20,930 --> 00:32:23,263 +we have this perfect looking UI here, okay. +我们这个 UI 看起来真是不错呀。 + +772 +00:32:24,766 --> 00:32:27,166 +Sound good? +是不错吧? + +773 +00:32:27,168 --> 00:32:29,802 +All right, now let's wire these text fields up. +好的,然后让我们把这些文本框和代码“链接”起来吧。 + +774 +00:32:29,804 --> 00:32:31,170 +So to wire these text field up, +好,我们现在就开始“链接”。 + +775 +00:32:31,172 --> 00:32:35,640 +we need a custom subclass of UIViewController. +我们先是需要一个 UIViewController 的子类。 + +776 +00:32:35,642 --> 00:32:37,475 +Right, cuz now this is just a generic, +好的,因为现在它还是一个可以通用的, + +777 +00:32:37,477 --> 00:32:38,876 +if we look at its identity inspector, +如果我们在 Inspector 的 Identity 栏目来中看, + +778 +00:32:38,878 --> 00:32:42,246 +it's a generic UIViewController, so +它还是一个通用的 UIViewController, + +779 +00:32:42,248 --> 00:32:44,915 +we need a custom subclass, no problem. +所以我们需要自己定义一个子类, + +780 +00:32:44,917 --> 00:32:46,549 +We'll do that, we know how to do that. +这个我们是知道怎么做的。 + +781 +00:32:47,619 --> 00:32:49,485 +Okay, we're gonna call this our +好的,我们就叫它 + +782 +00:32:49,487 --> 00:32:53,088 +EditWaypointViewController, cuz that's what it does. +EditWaypointViewController ,因为它的功能就是这个 + +783 +00:32:53,090 --> 00:32:55,724 +This MVC that we're putting up, it edits waypoints so +我们现在做的这个 MVC 就是用来编辑 waypoint , + +784 +00:32:55,726 --> 00:32:57,492 +we'll call it EditWaypointViewController. +我们就叫它 EditWaypointViewController 。 + +785 +00:32:58,661 --> 00:32:59,727 +Here it is. +这样就好了。 + +786 +00:32:59,729 --> 00:33:02,062 +Let's go back to our storyboard here. +然后我们回到我们的 storyboard 。 + +787 +00:33:02,064 --> 00:33:05,832 +I'm gonna change this guy's identity to be +我们把它对应的 Identity 改为 + +788 +00:33:05,834 --> 00:33:08,101 +EditWaypointViewController, okay. +EditWaypointViewController,没问题吧。 + +789 +00:33:08,103 --> 00:33:11,771 +So it's on automatic mode here so, we got our thing here. +这里我们得到了一些自动生成的代码。 + +790 +00:33:11,773 --> 00:33:15,341 +I'm going to delete all but viewDidLoad, okay. +我只留下 viewDidLoad ,其他的都删掉。 + +791 +00:33:16,777 --> 00:33:20,078 +Let's go and hook these two things up, these text fields. +然后让我们把按钮和代码直接“关联”起来。 + +792 +00:33:20,080 --> 00:33:21,546 +So, I'm gonna Control-Drag here, +我将按住 Ctrl 然后拖到这里, + +793 +00:33:21,548 --> 00:33:23,047 +we'll call this the nameTextField. +我们就叫它 nameTextField 。 + +794 +00:33:24,450 --> 00:33:28,985 +And we'll drag this one, we'll call it the infoTextField, +我们还会把这个也拖过来,我们就叫它 infoTextField 。 + +795 +00:33:28,987 --> 00:33:30,920 +okay, so there is our UI. +好的,这就是我们的 UI 。 + +796 +00:33:30,922 --> 00:33:34,590 +Now, we need to think a little bit at what's the model for +现在,我们要想一下我们 EditWaypointViewController 的对应的 + +797 +00:33:34,592 --> 00:33:36,225 +our EditWaypointViewController. +模型(Model)的情况。 + +798 +00:33:36,227 --> 00:33:38,393 +Can anyone think of what the model for +你们有谁能可以想到这个用来编辑 waypoint 的 MVC + +799 +00:33:38,395 --> 00:33:41,663 +an MVC that edits a waypoint, what would be its model? +对应的模型应该是什么? + +800 +00:33:46,035 --> 00:33:47,968 +What does it do? +它是用来做什么的呢? + +801 +00:33:47,970 --> 00:33:49,202 +Edits a waypoint, right? +编辑 waypoint ,对吧? + +802 +00:33:50,372 --> 00:33:54,240 +So its model might be a waypoint? +所以这个模型就应该是一个 waypoint ,对吧? + +803 +00:33:55,242 --> 00:33:56,975 +Yes. +是的。 + +804 +00:33:56,976 --> 00:33:58,709 +Let's make it be the waypoint to edit, okay? +我们现在就做一个可以编辑的 waypoint。 + +805 +00:33:58,712 --> 00:34:00,311 +So it's going to be an editable waypoint. +它就将作为一个可以编辑的 waypoint。 + +806 +00:34:00,313 --> 00:34:04,515 +It's gonna be the model for this viewController. +也就是这个视图控制器的模型。 + +807 +00:34:04,517 --> 00:34:06,383 +Anytime you're trying to determine, hm, +在任何时候你想确定你的 + +808 +00:34:06,385 --> 00:34:07,551 +what's my model? +模型是什么? + +809 +00:34:07,553 --> 00:34:09,303 +You always want to think, +你可以这样想, + +810 +00:34:09,304 --> 00:34:11,054 +what does this thing do, what does it operate on? +(这个视图控制器)是做什么的,它要操作什么? + +811 +00:34:11,056 --> 00:34:12,588 +That's usually gonna be its model. +那么它通常就是模型。 + +812 +00:34:12,590 --> 00:34:15,725 +Okay, either how it functions or what it operates on, +对的,如果去对它进行操作或处理的, + +813 +00:34:15,727 --> 00:34:18,293 +that's usually gonna be the model, all right. +那么这个就是模型。 + +814 +00:34:18,295 --> 00:34:19,628 +So this thing edits a waypoint, so +我们现在就是要编辑一个 waypoint, + +815 +00:34:19,630 --> 00:34:24,899 +that's going to be its model. +所以它就是模型。 + +816 +00:34:24,901 --> 00:34:28,736 +So now, let's get some more space here. +现在,我们先把调整一下窗口的位置。 + +817 +00:34:28,738 --> 00:34:32,773 +Let's keep our view and model in sync, okay. +同时可以看到我们的视图和我们模型,好的。 + +818 +00:34:32,775 --> 00:34:34,808 +One of the first things we want to do actually when we +我们首先想要做的是,当我们把模型放到视图里面,希望 + +819 +00:34:34,810 --> 00:34:37,344 +put a model in or add view is keep them in sync, so +保持两者的同步,也就是说 + +820 +00:34:37,346 --> 00:34:40,346 +that they're always reflecting each other. +他们之间的事保持相互“联系”的。 + +821 +00:34:40,348 --> 00:34:45,117 +So let's do that by having here, a div set +所以我们在这里这么来做, + +822 +00:34:45,119 --> 00:34:50,221 +on the model that calls some update UI thing, okay. +在模型上调用更新 UI 的方法。 + +823 +00:34:50,223 --> 00:34:54,258 +And we'll do the exact same thing down here, as well. +我们将在这里也做同样的事情。 + +824 +00:34:54,260 --> 00:34:56,927 +So if you set either text field, +所以如果你在text field里修改了内容, + +825 +00:34:56,929 --> 00:35:00,664 +we're going to update the model. +我们也将会更新模型。 + +826 +00:35:00,666 --> 00:35:03,967 +What did I do wrong here, oh I don't have updateUI. +我们做错了什么吗?我没有 updateUI 这个方法。 + +827 +00:35:03,969 --> 00:35:09,672 +Okay, so let's go ahead and, func updateUI. +好的,让我们先来写 func updateUI 。 + +828 +00:35:09,674 --> 00:35:13,108 +So we've got an updateUI, what do we need to do in updateUI? +好,现在我们有了 updateUI 这个方法了,那我们这个方法要做些什么呢? + +829 +00:35:13,110 --> 00:35:15,677 +Really, we just need to update our text fields from our +实际上,我们只是需要把我们的waypoint的值更新到 + +830 +00:35:15,679 --> 00:35:17,996 +waypoints. +textfield 上就可以了。 + +831 +00:35:17,997 --> 00:35:20,314 +So I'm gonna say, nameTextField.text +所以就应该是, nameTextField.txt + +832 +00:35:20,316 --> 00:35:24,685 += waypointToEdit.name, and += waypointToEdit.name ,和 + +833 +00:35:24,687 --> 00:35:32,359 +the infoTextField.text = waypointToEdit.info. +infoTextField.text = waypointToEdit.info。 + +834 +00:35:32,361 --> 00:35:33,993 +Okay, so that's it. +好来,就这样。 + +835 +00:35:33,995 --> 00:35:38,064 +Let's also update our UI in viewDidLoad, that way, +然后我们在 viewDidLoad 这个方法里也调用一次 updateUI 这个方法。 + +836 +00:35:38,066 --> 00:35:41,633 +if our model got set before our outlets were loaded, +以防止模型在我们的 UI 加载之后被更新过, + +837 +00:35:41,635 --> 00:35:44,803 +this will catch them up to speed, okay. +这样现在就能够保持两者同步了。 + +838 +00:35:44,805 --> 00:35:48,273 +So it's a very common pattern, here, to updateUI +这是一个非常常用的“模式”,当你的模型发生变化的时候,更新你的UI + +839 +00:35:48,275 --> 00:35:51,209 +when your model changes and also update in viewDidLoad. +同时在 viewDidLoad 方法里也更新一次 UI。 + +840 +00:35:51,211 --> 00:35:55,146 +Okay, because remember outlets are not set, unfortunately, +好的,有的时候当我们在为 segue 准备 MVC 的时候, outlets 可能 + +841 +00:35:55,148 --> 00:35:58,382 +sometimes during prepare for segue, for example. +还没有被加载完成,这个会比较麻烦,我们来看下例子。 + +842 +00:35:58,384 --> 00:36:01,685 +okay, so let's see what this looks like. +让我们看到到底会是什么样。 + +843 +00:36:01,687 --> 00:36:04,320 +I'm actually gonna run this one on +因为我要为你展示一下这个特别的 + +844 +00:36:04,322 --> 00:36:06,823 +the phone because I wanna show you +UI 问题,所以我会让程序运行在 + +845 +00:36:06,825 --> 00:36:10,626 +a particular problem we have with this UI so far. +真实的设备上。 + +846 +00:36:15,432 --> 00:36:17,098 +Okay, let me put this on the screen here. +好,让我们把这个放到屏幕上来看。 + +847 +00:36:24,207 --> 00:36:27,841 +Okay, so here's our UI, I'm gonna just tap and +好,这是我们的 UI ,我来把它拖到 + +848 +00:36:27,843 --> 00:36:32,612 +hold to drop here, okay, and now I'm gonna click on it. +这里,让我点击一下它。 + +849 +00:36:32,614 --> 00:36:35,515 +I'm gonna press our new editing button and +我将要点击我们新的这个编辑按钮,然后就可以看到 + +850 +00:36:35,517 --> 00:36:37,016 +here we have our UI. +我们的新的 UI 。 + +851 +00:36:37,018 --> 00:36:38,584 +That's good our UI's appearing. +看,我们的 UI 展示出来了,很好! + +852 +00:36:38,586 --> 00:36:42,220 +A couple of problems here, one, no keyboard. +但这里也有不少问题,首先,没有键盘。 + +853 +00:36:42,222 --> 00:36:43,955 +Okay, our UI has appeared here, but +是的,我们的 UI 展示在这里了, + +854 +00:36:43,957 --> 00:36:45,957 +if there's not keyboard that's not so good, but +但如果这里没有键盘不能输入,肯定是不可以的, + +855 +00:36:45,959 --> 00:36:49,093 +if I touch on a text field it appears. +但如果我一旦点击了 text field 之后,键盘就会出现了。 + +856 +00:36:49,095 --> 00:36:50,494 +Okay, that's kind of good except for +好吧,而比较好的用户体验应该是 + +857 +00:36:50,496 --> 00:36:53,296 +when my the thing first comes up I probably want it to +UI 展示的同时,就能看到 + +858 +00:36:53,298 --> 00:36:55,465 +have a keyboard. +键盘。 + +859 +00:36:55,466 --> 00:36:57,633 +So we're going to put in some code to become first responder +所以我们需要加一点代码,让我们的 text field 作为第一个响应者 + +860 +00:36:57,636 --> 00:36:59,635 +on one of those text fields, okay. +(first responser)。 + +861 +00:36:59,637 --> 00:37:01,003 +Right off the bat. +除了这个问题。 + +862 +00:37:01,005 --> 00:37:02,204 +Another problem is, +另外一个问题是, + +863 +00:37:02,206 --> 00:37:04,673 +I can never make this keyboard go away, okay. +键盘没有办法消失。 + +864 +00:37:04,675 --> 00:37:07,442 +No matter what I press, I press return, click on +无论我按什么,我按过 return 键, + +865 +00:37:07,444 --> 00:37:10,411 +[INAUDIBLE], and I can't make it go away, that's a problem. +我也不能让键盘消失,这是一个问题。 + +866 +00:37:10,413 --> 00:37:14,081 +Now, I don't have anything down at the bottom right now, +现在我在右下角没有任何东西。 + +867 +00:37:14,083 --> 00:37:17,184 +but when we start having an image in our waypoint editor, +但当我们在 waypoint 的编辑(器)里增加了一张图片的话, + +868 +00:37:17,186 --> 00:37:18,952 +then it's gonna cover up that image. +这里也将现实这张图片。 + +869 +00:37:18,954 --> 00:37:20,553 +We need a way for +我需要有一个解决方案, + +870 +00:37:20,555 --> 00:37:23,690 +the return key on the keyboard that I'm pressing down here, +当我点击 return 键之后, + +871 +00:37:23,692 --> 00:37:26,759 +to make these things first responder, okay. +可以放弃第一响应者(first responder)。 + +872 +00:37:26,761 --> 00:37:32,564 +Let's fix those things really quickly, they're easy to fix. +我们可以很快的把这些问题解决掉,解决它们很容易。 + +873 +00:37:33,867 --> 00:37:36,167 +Become first responder, we can just do in viewDidLoad. +成为第一响应者(first responder),我们需要在 viewDidLoad 方法里, + +874 +00:37:36,169 --> 00:37:39,737 +I'm just gonna say, name text field become first responder, +我只需要写上 nameTextField.becomeFirst responder 就可以了 + +875 +00:37:39,739 --> 00:37:42,573 +so as soon as this thing is created it's gonna immediately +也就是说当这个内容刚刚被创建出来,就把 text field 作为 + +876 +00:37:42,575 --> 00:37:46,309 +make that text field be the first responder, okay? +第一响应者 (first responder)。 + +877 +00:37:46,311 --> 00:37:47,844 +So that's easy. +很容易的。 + +878 +00:37:47,846 --> 00:37:52,648 +Making the return key resign first responder requires us +然后让点击 return 键 可以取消当前的第一响应者 (first responder)的话, + +879 +00:37:52,650 --> 00:37:57,452 +to, if you remember from last time, become UI text field +你们是否还记得上一次,增加 UITextField 的 delegates 然后实现了 + +880 +00:37:57,454 --> 00:38:02,456 +delegates, and implement this method, text field should +其中这个方法 textFieldShouldEndEditingOrShouldEndReturn。 + +881 +00:38:02,458 --> 00:38:07,494 +end editing or should end return, here it is, okay. +对,就是它。 + +882 +00:38:07,496 --> 00:38:08,962 +So here, +在这里, + +883 +00:38:08,964 --> 00:38:12,565 +when a text field hits the return key, I'm going to say +当一个 text field “监测”到点击了 return 键,我就会写 + +884 +00:38:12,567 --> 00:38:14,867 +textField.resignFirstResponder. +textField.resignFirstResponder。 + +885 +00:38:16,203 --> 00:38:20,138 +And then we'll let it do whatever it normally does. +这就是我们通常情况下的做法。 + +886 +00:38:20,140 --> 00:38:22,307 +Okay, so that solves both of those problems. +好了,这样就把两个问题都解决了。 + +887 +00:38:23,343 --> 00:38:25,676 +Oh, whoops, one quick thing we need to do before +好的,在我们“验证“之前,我们还有一件 + +888 +00:38:25,678 --> 00:38:27,411 +we do that is, +事情需要做。 + +889 +00:38:27,413 --> 00:38:30,747 +if we're gonna have this text field delegate method called, +如果调用了这个代理的方法 + +890 +00:38:30,749 --> 00:38:35,351 +we need to obviously make, oh, I did this totally wrong. +我们需要显式的做。。。我做错了。 + +891 +00:38:35,353 --> 00:38:36,652 +Sorry. +抱歉。 + +892 +00:38:36,653 --> 00:38:37,952 +This should be, nobody caught me on this, but +这里应该是,没有回调用我,担 + +893 +00:38:37,955 --> 00:38:39,788 +this should be on the model, okay. +它应该是发生在模型上。(模型需要调用的意思) + +894 +00:38:39,790 --> 00:38:41,857 +Add those on the text fields. +这些是在 text field。 + +895 +00:38:41,859 --> 00:38:43,391 +All right, it's the model that wants +对的,应该是模型希望能够更新 UI, + +896 +00:38:43,393 --> 00:38:46,227 +to update the UI not the text fields, okay? +并不是 text field 要更新UI,对吧? + +897 +00:38:46,229 --> 00:38:49,130 +What the text fields want when they're didSet +在设置 textField的的时候,需要设置他的 + +898 +00:38:49,132 --> 00:38:54,668 +is they want to set their delegates equal to self. +deletaget 等于 self 。 + +899 +00:38:54,670 --> 00:38:58,438 +That's what they wanna do, okay. +这就是我们要做的。 + +900 +00:38:58,440 --> 00:38:59,839 +Guys, pay attention. +大家,注意一下。 + +901 +00:38:59,841 --> 00:39:02,508 +I count on you guys to catch me doing these things. +我希望你们看懂了我刚才做的。 + +902 +00:39:02,510 --> 00:39:04,042 +Okay, everyone understand that? +好的,每个人都懂了吗? + +903 +00:39:04,044 --> 00:39:07,078 +The model setting that wants to update the UI, the text +是这个模型希望可以更新 UI ,这个textfield 只是 + +904 +00:39:07,080 --> 00:39:10,281 +field, just want to set themselves as the delegate. +把他们设置为自己的代理(delegate)。 + +905 +00:39:10,283 --> 00:39:12,383 +See, you let me do another thing here. +看,你让我做另外一件事的意思。 + +906 +00:39:13,352 --> 00:39:15,185 +Okay, there we go. +好,那让我们继续。 + +907 +00:39:15,186 --> 00:39:17,019 +So now both text fields have self as their delegate, so +现在两个 text field 都有了他们各自的代理,所以他们 + +908 +00:39:17,022 --> 00:39:20,290 +they're both going to call ShouldReturn, okay. +可以调用 ShouldReturn...这个方法。 + +909 +00:39:20,292 --> 00:39:22,258 +So let's try that. +让我们试试看那就。 + +910 +00:39:29,367 --> 00:39:32,801 +Are we still up there, yes. +我们还是在这里,对对。 + +911 +00:39:32,803 --> 00:39:35,337 +Okay. Again, here I'm gonna add one. +好,我们再增加一个。 + +912 +00:39:35,339 --> 00:39:36,505 +Click here. +点击这里。 + +913 +00:39:36,506 --> 00:39:37,672 +Let's bring up our new MVC. +然后我们到我们新的 MVC 。 + +914 +00:39:37,674 --> 00:39:38,890 +Here it is. +就是这里。 + +915 +00:39:38,891 --> 00:39:40,107 +Keyboard comes up, excellent. +键盘出现了,很好! + +916 +00:39:40,109 --> 00:39:42,476 +And if I hit Return, keyboard goes away. +如果我点击 return 键, 键盘消失了。 + +917 +00:39:42,478 --> 00:39:44,011 +And if I go to Back, it comes back. +如果我点击返回,它就返回来。 + +918 +00:39:44,013 --> 00:39:45,478 +So that's much more control. +这里需要更多的控制。 + +919 +00:39:45,480 --> 00:39:48,014 +And if you're doing this in the simulator, it seems like, +如果你是在模拟器里运行,这个可能看起来 + +920 +00:39:48,016 --> 00:39:49,566 +oh, this is all great. +完全没有问题。 + +921 +00:39:49,567 --> 00:39:51,117 +But then when you run it on the device, you're like, oh, +但如果你是在真机上运行,你就会发现, + +922 +00:39:51,119 --> 00:39:52,551 +well that's not very useable, okay. +好像不是那么好用的。 + +923 +00:39:52,553 --> 00:39:55,487 +So you've got to be careful to make sure things actually +这里你要特别注意,确保你的 App 可以在真机上 + +924 +00:39:55,489 --> 00:39:56,888 +are useable on the device. +正确运行。 + +925 +00:39:56,890 --> 00:39:58,589 +All right. +好的。 + +926 +00:39:58,591 --> 00:40:02,893 +That's that, so now we've kind of set up our UI. +就是这样了,我们已经把我们的 UI 部分完成了。 + +927 +00:40:02,895 --> 00:40:04,928 +But actually, there's one other problem with this. +不过实际上,这里还有另外一个问题。 + +928 +00:40:04,930 --> 00:40:07,230 +Let's go ahead and take a look at this other problem we got. +让我们去看看下另外这个问题, + +929 +00:40:11,469 --> 00:40:15,404 +Which is when I add a thing here is I might type in +当我想增加一个内容的时候,我会输入它的名字, + +930 +00:40:15,406 --> 00:40:19,974 +the name, like I think I put that pin on the golf course +比如我想“钉”在这个地方点点叫做 “glof course” + +931 +00:40:19,976 --> 00:40:21,843 +there or something. +之类的。 + +932 +00:40:21,845 --> 00:40:23,577 +Right? +可以吧? + +933 +00:40:23,579 --> 00:40:31,218 +Golf course, okay, snowed, whatever. +“Golf course”,好的,随便什么名字吧。 + +934 +00:40:31,220 --> 00:40:33,186 +But now there's no way for me to get back. +但这里我却没办法回去了。 + +935 +00:40:33,188 --> 00:40:34,554 +[LAUGH]. +[笑] + +936 +00:40:34,556 --> 00:40:35,321 +You see? +看到了? + +937 +00:40:35,323 --> 00:40:37,340 +How can I get back? +我怎么才能回去? + +938 +00:40:37,341 --> 00:40:39,358 +I've changed the things I want, now I want to get back, +我已经把我需要修改的内容改好了,我想返回, + +939 +00:40:39,360 --> 00:40:40,792 +I want to dismiss this thing and +我想把当前的移除,然后 + +940 +00:40:40,794 --> 00:40:45,830 +get back, so we need some user interface here to get back. +回到前一个界面,所以我们需要增加一个新的 UI 控件让我能够返回。 + +941 +00:40:45,832 --> 00:40:48,799 +The other thing is, when we make changes in these text +另一个问题时,当我在text fields 里面修改了内容之后, + +942 +00:40:48,801 --> 00:40:52,536 +fields, it's not actually changing the waypoint, okay? +并没有在体现在 waypoint 上,对吧? + +943 +00:40:52,538 --> 00:40:54,805 +So we need you to fix both those things. +所以我们需要修改这两个问题。 + +944 +00:40:54,807 --> 00:40:57,140 +So let's fix the changing in the way point. +让我们先修改这个编辑 waypoint 的这个问题。 + +945 +00:40:57,142 --> 00:40:59,742 +Now, this one I'm gonna use notifications for. +这里,我会使用 Notification 来实现。 + +946 +00:40:59,744 --> 00:41:01,177 +Because I want to show you a little bit more +因为我想给你们多展示一下 Notification 的用法。 + +947 +00:41:01,179 --> 00:41:03,345 +about notifications that we really didn't cover +我们上次没有机会 + +948 +00:41:03,347 --> 00:41:05,681 +when we did the notifications last time. +实际使用 Notification 。 + +949 +00:41:05,683 --> 00:41:09,851 +So, text fields it turns out, they have a notification. +这里,当text fields 一出现,这里会一个 Notification 。 + +950 +00:41:09,853 --> 00:41:11,986 +Okay, in fact they have a couple of notifications. +好吧,实际上它时有一组 Notification。 + +951 +00:41:11,988 --> 00:41:13,687 +Three notifications, I think, even. +我记得可能是 三个 Notification + +952 +00:41:13,689 --> 00:41:16,757 +But one of them is ui text field, +其中有一个是 + +953 +00:41:16,759 --> 00:41:19,325 +text did change notification. +UITextfieldTextDidChangeNotification 。 + +954 +00:41:19,327 --> 00:41:22,095 +So you can sign up to hear from a text field whenever its +这样这个 textfield 里的值发生任何变化,你都可以监听。 + +955 +00:41:22,097 --> 00:41:23,462 +text changes. +这样这个 textfield 里的值发生任何变化,你都可以监听。 + +956 +00:41:23,464 --> 00:41:25,130 +Now, that's gonna be really valuable for us, here. +现在有这个 Notification 对我们来说就很有用了。 + +957 +00:41:25,132 --> 00:41:27,532 +Because whenever the text field's text changes, +因为任何时候 text field 里的值发生变化, + +958 +00:41:27,534 --> 00:41:29,734 +we can update our wave point. +我们就可以更新我们的 waypoint 的值 + +959 +00:41:29,736 --> 00:41:30,435 +Right? +对吧? + +960 +00:41:30,437 --> 00:41:31,936 +So, how do we do that? +好,那我们该怎么做? + +961 +00:41:31,938 --> 00:41:34,438 +How do we make that work? +我们怎么来实现这个? + +962 +00:41:34,439 --> 00:41:36,939 +Well, turns out we want to put this in viewDidappear, so +嗯,这里我们会在 viewDidAppear 方法里来写, + +963 +00:41:36,942 --> 00:41:40,677 +in viewDidappear, okay, super.viewDidappear. +在 viewDidAppear ,对,先要调用 super.viewDidAppear 。 + +964 +00:41:42,881 --> 00:41:45,214 +I'm just gonna call a method here, +让我在这里要调用一个方法, + +965 +00:41:45,216 --> 00:41:48,116 +called observeTextFields. +这个方法就叫做 observeTextfield 吧。 + +966 +00:41:49,353 --> 00:41:51,803 +Okay? +可以? + +967 +00:41:51,804 --> 00:41:54,254 +In an ovserveTextfield, I am going to set myself up +在这个 ovserveTextfield 方法里,我将把我自己 + +968 +00:41:54,257 --> 00:41:59,660 +to observe changes made in those text fields. +设置为“监听”这些 textField 的变化的代理对象。 + +969 +00:41:59,662 --> 00:42:01,512 +All right? +对吧? + +970 +00:42:01,513 --> 00:42:03,363 +And, so I'm gonna do that with the notification center, so +所以我要通过 NotificationCenter ,得到center + +971 +00:42:03,365 --> 00:42:06,399 +I'm gonna get my center, which is NS Notification center. +类型是为 NSNotificationCenter + +972 +00:42:06,401 --> 00:42:08,234 +Default center. +Default center 。 + +973 +00:42:08,236 --> 00:42:11,437 +I'm also going to specify the queue I want this on which is, +我还要指明在这个“通知”队列里我们需要的的是哪个, + +974 +00:42:11,439 --> 00:42:14,606 +of course, the main queue, so I'm gonna say, main queue. +这个“队列”就是指主队列。 + +975 +00:42:15,642 --> 00:42:18,610 +And them I'm just gonna say, use that thing we had before, +接着我来写,我们之前也这么做过的, + +976 +00:42:18,612 --> 00:42:22,347 +Center Add Observer, for name which is this. +Center add Observer 参数的名字是 + +977 +00:42:22,349 --> 00:42:26,183 +And the name of this notification is UI Text Field. +这个名字就是 UITextField 的 notification 的这个 + +978 +00:42:26,185 --> 00:42:32,622 +TextDidChangeNotification. +TextDidChangeNotification 方法。 + +979 +00:42:32,624 --> 00:42:34,858 +'Kay? +对吧? + +980 +00:42:34,859 --> 00:42:37,093 +So, so far, this notification is nothing new to you. +到现在为止,关于 Notification 还没有什么新的内容。 + +981 +00:42:37,095 --> 00:42:40,196 +Object is the object I care about if it changes, +这个Object 就是我们需要的被改变内容的对象, + +982 +00:42:40,198 --> 00:42:43,499 +which is, let's say, the name text field, in this case. +也就是说,这里就应该是 nameTextField , + +983 +00:42:43,501 --> 00:42:46,101 +'Kay? +对吧? + +984 +00:42:46,102 --> 00:42:48,702 +Queue is the queue, and the block, okay, I'm gonna do the. +在队列和 block,对的,就是这里 + +985 +00:42:48,705 --> 00:42:50,104 +Our magic trick here of +我将会用一个有点神奇的方法 + +986 +00:42:50,106 --> 00:42:53,274 +closing off the end of that, I'll get rid of that. +关掉这个,我可以来删掉掉这些。 + +987 +00:42:53,276 --> 00:42:55,476 +And then put our block on the end here. +然后把我们的 block 放在这里的最后。 + +988 +00:42:55,478 --> 00:42:59,379 +So here are the argument, I'll just call it notification. +这是参数,我直接调用 notification. + +989 +00:42:59,381 --> 00:43:01,981 +That's the notification that cames back, coming back. +这个notification的返回值。 + +990 +00:43:01,983 --> 00:43:06,085 +And all I wanna do here is if I can let waypoint, +然后我这里就是让 let waypoint 等于 + +991 +00:43:06,087 --> 00:43:09,855 +equal our waypointToEdit. +我们的 waypointToEdit 。 + +992 +00:43:09,857 --> 00:43:12,591 +Okay, so we can get our waypoint. +这样我们就能得到我们的 waypoint 。 + +993 +00:43:12,593 --> 00:43:16,794 +Then, I'm just going to set the waypoint's name +接着我们就只需要nameTextfield的值赋给 + +994 +00:43:16,796 --> 00:43:21,031 +equal to the name text field's text. +waypoint的name就可以了。 + +995 +00:43:21,033 --> 00:43:24,901 +So every time the name text field changes here, +所以每次name text field的值发生了变化, + +996 +00:43:24,903 --> 00:43:26,770 +I'm just going to update the name of our waypoint. +我都会更新我们的 waypoint 的名称属性。 + +997 +00:43:26,772 --> 00:43:28,538 +And exactly the same for the info. +保持内容一直是同步的。 + +998 +00:43:30,141 --> 00:43:32,708 +So all we have to change here is +接着我们也必须对这个info text fields + +999 +00:43:32,710 --> 00:43:34,676 +info text fields coming in here. +也进行相应的修改。 + +1000 +00:43:34,678 --> 00:43:36,644 +And this is going to be updated to info. +这里是要更新 info。 + +1001 +00:43:36,646 --> 00:43:38,913 +And this is the info. +这个是 info。 + +1002 +00:43:40,349 --> 00:43:41,715 +Now so far, so good. +到目前为止,都很好。 + +1003 +00:43:41,717 --> 00:43:43,616 +You're probably like oh, okay it makes sense. +你可能会想,嗯,这个很合理的。 + +1004 +00:43:43,618 --> 00:43:45,718 +You haven't taught us anything new about notification. +关于 notificaton 你已经没有什么可学的了。 + +1005 +00:43:45,720 --> 00:43:47,420 +But there's a very important piece of this +但这里有一个特别重要的地方, + +1006 +00:43:47,422 --> 00:43:48,987 +puzzle right here. +容易出错的地方。 + +1007 +00:43:48,989 --> 00:43:52,691 +What happens when this MBC gets dismissed? +如果一旦 MBC 被移除了,会发生什么? + +1008 +00:43:53,927 --> 00:43:57,328 +These observers are still trying to observe +这些观察者(observers)还在尝试监听 + +1009 +00:43:57,330 --> 00:43:59,363 +those text fields. +这些 text fields 。 + +1010 +00:43:59,364 --> 00:44:01,397 +Even those text fields could be have gone away, +甚至这些 text field 可能已经被移除了。 + +1011 +00:44:01,400 --> 00:44:03,200 +they won't because these closures are gonna keep +这是因为这些 text field 可能还被 + +1012 +00:44:03,202 --> 00:44:04,801 +those text fields in memory. +保存在内存中。 + +1013 +00:44:04,803 --> 00:44:06,402 +And also, self can never go away because +也是这样的,他们自己是永远无法把自己删除的, + +1014 +00:44:06,404 --> 00:44:08,704 +these closures are gonna be keep self in memory. +因为这些“闭包”函数将会一直将它们保存在内存里。 + +1015 +00:44:08,706 --> 00:44:12,241 +So this is a problem, so when you add an observer like this +所以这是一个问题,所以当你在这样的情况下增加一个 观察器(observer) + +1016 +00:44:12,243 --> 00:44:14,509 +and your MVCs ever going to go away, +同时你的 MVC 将会被移除掉, + +1017 +00:44:14,511 --> 00:44:18,780 +which our last MVC never went away, it was the root MVC so +而我们最后的这个 MVC 却一直不会被移除,它是一个根视图控制器(MVC) + +1018 +00:44:18,782 --> 00:44:20,581 +we added that observer for a name. +所以我们这个增加的 observer , + +1019 +00:44:20,583 --> 00:44:22,616 +We probably could just leave it there forever, +我们只能一直将它留在那里了, + +1020 +00:44:22,618 --> 00:44:23,850 +because it's never going to go away. +因为它也是不会移除的。 + +1021 +00:44:23,852 --> 00:44:25,552 +Although good design, +尽管一个好的设计来看, + +1022 +00:44:25,553 --> 00:44:27,253 +maybe even that one would know how to go away. +可能它自己是知道如何将自己移除的。 + +1023 +00:44:27,255 --> 00:44:28,755 +But how do we go away? +但该怎么做呢? + +1024 +00:44:28,757 --> 00:44:33,692 +And the answer is that this returns a little cookie, okay? +方法就是,返回一小段 cookie ,对吧? + +1025 +00:44:33,694 --> 00:44:34,726 +So it returns a cookie. +它是返回一段 cookie 的话。 + +1026 +00:44:34,728 --> 00:44:36,661 +I'm gonna make storage for these two cookies. +我将会讲这些 cookies 保存起来。 + +1027 +00:44:36,663 --> 00:44:40,931 +One I'm gonna call it the name text field observer, and +我讲会调用 nameTextfieldObserver , + +1028 +00:44:40,933 --> 00:44:44,001 +it's a type NSObjectProtocol. +这个对象的(协议)类型是 NSObject Protcol 。 + +1029 +00:44:44,003 --> 00:44:46,870 +So NSObjectProtocol just means it's something +这里 NSObjectProtocol 的意思是,这个对象在“过去”的 + +1030 +00:44:46,872 --> 00:44:49,305 +that used to be an NS object in the old world. +的世界里是被当作 NSObject 对象来看待的。 + +1031 +00:44:49,307 --> 00:44:50,807 +Okay, in the old, objective C world. +这个过去的意思是 ,Objective C 世界的意思。 + +1032 +00:44:50,809 --> 00:44:52,475 +That's all that means for an NS object protocol. +这些具体有关 NSObject Protocol 的具体内容, + +1033 +00:44:52,477 --> 00:44:53,943 +We don't even know, +我们不了解, + +1034 +00:44:53,944 --> 00:44:55,410 +we don't care what's in the NS object protocol for +这里我们也不需要懂, + +1035 +00:44:55,413 --> 00:44:59,247 +the purposes of this, because really, this is just a cookie. +因为实际上,这就是一段 cookie 。 + +1036 +00:44:59,249 --> 00:45:02,417 +It's just something that it gives us that we can give back +这恰好就是我们当我们“沟通”的时候, + +1037 +00:45:02,419 --> 00:45:05,353 +to it when we wanna talk about this thing. +所需要的内容。 + +1038 +00:45:05,355 --> 00:45:06,887 +So, here's this observer, +这个是 观察器 (oberver), + +1039 +00:45:06,889 --> 00:45:11,725 +and I'm gonna say here ntfObserver equals that. +我这里让 ntfObserver 等于这个。 + +1040 +00:45:11,727 --> 00:45:15,662 +I'm gonna say itfObserver equals that. +然后让 itfObserver 等于它。 + +1041 +00:45:15,664 --> 00:45:18,698 +So I've added these observers and I got this cookie back. +我已经增加了这些 observer 同时我也可以获得它返回的 cookie 。 + +1042 +00:45:18,700 --> 00:45:21,033 +Now, when I'm done observing, +一旦当我完成了观察。 + +1043 +00:45:21,035 --> 00:45:24,636 +I need to remove this cookie from the notification center. +我就需要把这段 cookie 从 notificaton cenert 中删除。 + +1044 +00:45:24,638 --> 00:45:28,640 +So I'm gonna do that in view will disappear. +我将在 viewWillDisappear 这个方法里来做这件事。 + +1045 +00:45:29,576 --> 00:45:33,310 +Okay, so, when my view will disappear, okay? +是的,当我们的视图将要消失的时候,对吧? + +1046 +00:45:33,312 --> 00:45:36,146 +I don't need to look at those text fields anymore after I've +我已经不需要在“监控”这些text field了,因为它们马上就不会出现在 + +1047 +00:45:36,148 --> 00:45:38,048 +gone off screen. +屏幕上了。 + +1048 +00:45:38,049 --> 00:45:39,949 +They can't be changing because I'm not even on screen +就是因为我在屏幕上都不会看到它们了,所以它们肯定也不会被 + +1049 +00:45:39,952 --> 00:45:41,084 +right now. +修改了。 + +1050 +00:45:41,086 --> 00:45:42,786 +I'm just gonna say +我只要这些来写, + +1051 +00:45:42,787 --> 00:45:44,487 +NSNotificationCenter.defaultCenter. +NSNotificationCenter.defaultCenter + +1052 +00:45:44,489 --> 00:45:47,523 +Actually, let's check and make sure they're not nil because +这里我们还是要检查下它们是不是nil ,因为这里我设置的这些字段内容 + +1053 +00:45:47,525 --> 00:45:50,125 +see I made these fields optional, so we'll say if. +是 optional 的,所以我要写 if + +1054 +00:45:50,127 --> 00:45:54,262 +Observer if let, let observer equal +Observer if let ,let observer 等于 + +1055 +00:45:54,264 --> 00:45:58,232 +the mean text field observer, than notification center. +这个 text fileld observer ,然后在notification center + +1056 +00:46:02,371 --> 00:46:03,771 +Remove that observer. +中删除这个 observer。 + +1057 +00:46:03,772 --> 00:46:05,172 +So you can see how I've never had to actually look inside +这里你可以看到,我根本没有去看内部发生了什么,或是里面是什么内容, + +1058 +00:46:05,174 --> 00:46:08,208 +and see what this thing is, I don't send it any messages, +我也没有发送任何消息, + +1059 +00:46:08,210 --> 00:46:11,778 +I just get the cookie here and then I pass it along in here. +我只是得到 cookie 然后直接传递到这里。 + +1060 +00:46:11,780 --> 00:46:14,046 +Except for this is observer, because I've lighted it. +除了它是 observer,因为我已经专门“处理”过它。 + +1061 +00:46:14,048 --> 00:46:16,315 +Okay, so that's all we had to do. +好了,这就是全部我们需要做的。 + +1062 +00:46:16,317 --> 00:46:17,766 +Same thing here. +同样的思路。 + +1063 +00:46:17,767 --> 00:46:19,216 +We'll do the same thing with the other cookie. +我们也需要对其他的cookie也做同样的处理。 + +1064 +00:46:19,219 --> 00:46:23,455 +This is the ITF observer, info text field. +这是 ITFObserber ,针对 info text field 。 + +1065 +00:46:23,457 --> 00:46:28,559 +So this pattern by the way, of starting to observe something +顺便说下这种模式,启动一个 observer 都是在 viewDidAppear 方法里调用, + +1066 +00:46:28,561 --> 00:46:31,495 +in view did appear, and then stopping observing from it in +然后停止 观察(observer)都是在 viewWillDisappear + +1067 +00:46:31,497 --> 00:46:33,730 +view will disappear is a very common way to do this. +方法里处理,这是一个比较通用的处理方式。 + +1068 +00:46:34,900 --> 00:46:38,001 +Okay, because usually, any notifications like keyboard +这是因为,通常,任何一个 notification ,比如 键盘的修改, + +1069 +00:46:38,003 --> 00:46:40,870 +will change, or something like that, there's keyboard will +或是其他类似的,这里有一个 keyboardwillAppear 的, + +1070 +00:46:40,872 --> 00:46:42,971 +appear, you don't care about that if you're not on screen. +你是不需要考虑他们是不是已经出现在屏幕上。 + +1071 +00:46:42,973 --> 00:46:45,273 +So there's a perfect place to add and remove this. +所以这是一个非常好的位置用来增加或删除。 + +1072 +00:46:45,275 --> 00:46:49,010 +Does everyone understand what's going on here? +是不是每个人都明白了发生了什么事情吧? + +1073 +00:46:49,012 --> 00:46:50,445 +You add to these notifications so +你增加了这些 notifications ,所以任何时候 + +1074 +00:46:50,447 --> 00:46:51,846 +every time it checks changes, +它有修改的话, + +1075 +00:46:51,848 --> 00:46:53,280 +it's gonna update our way point, but +都会直接更新我们的 waypoint, + +1076 +00:46:53,282 --> 00:46:55,749 +we don't wanna be doing that when we're not on screen. +但我们不希望当我们的内容已经不在屏幕上,它们还继续监控。 + +1077 +00:46:55,751 --> 00:46:57,917 +And we don't wanna have these closures, +我们不需要这些"闭包"程序, + +1078 +00:46:57,919 --> 00:47:00,687 +this closure right here, and this closure right here. +这个“闭包”这里,就是这里。 + +1079 +00:47:00,689 --> 00:47:04,690 +We don't want them keeping self, and this text field +我们不希望他们继续持有当前对象, + +1080 +00:47:04,692 --> 00:47:07,793 +through self, we don't want them keeping them in heap. +我们不希望在堆上还继续保存着它们。 + +1081 +00:47:07,795 --> 00:47:09,194 +When we, when our MVC goes away, +当我们的 MVC 消失了之后, + +1082 +00:47:09,196 --> 00:47:11,396 +we want it to go completely away, out of the heap. +我们希望是全部消失,完全从堆上移除。 + +1083 +00:47:13,066 --> 00:47:14,832 +All right. So that's notification. +好的,那就是 notification。 + +1084 +00:47:14,834 --> 00:47:16,633 +That's your little DL notification code. +那是有关 notification 的一段代码。 + +1085 +00:47:16,635 --> 00:47:18,568 +Now let's fix that other problem, +好,下面让我们来改另外一个问题。 + +1086 +00:47:18,570 --> 00:47:21,637 +the problem where there's no way to dismiss the thing. +这个问题是我们没有办法移除内容。 + +1087 +00:47:21,639 --> 00:47:23,572 +It comes up and we can't dismiss it. +它出现之后,我们没办法移除掉它。 + +1088 +00:47:23,574 --> 00:47:25,007 +And there's a number of ways we could do that. +事实上这里有好几个方法可以解决这个问题。 + +1089 +00:47:25,009 --> 00:47:28,043 +We could put a little Done button down in the middle +我们可以在界面中间放一个 + +1090 +00:47:28,045 --> 00:47:29,778 +somewhere of that UI. +Done 按钮。 + +1091 +00:47:29,780 --> 00:47:34,982 +But actually, I'm going to do it by putting this +但这次,我是会把我们的UI 放到 Navigation Controller 里。 + +1092 +00:47:34,984 --> 00:47:39,219 +user interface in an navigation controller. +但这次,我是会把我们的UI 放到 Navigation Controller 里。 + +1093 +00:47:39,221 --> 00:47:41,354 +Now, why am I gonna put it in navigation controller? +那我为什么要这么做呢? + +1094 +00:47:41,356 --> 00:47:43,106 +Two reasons. +两个理由。 + +1095 +00:47:43,107 --> 00:47:44,857 +One, users are used to the look of navigation controllers +一、在 Navigation Controller 控制器下,用户可以在顶部看到一个 + +1096 +00:47:44,859 --> 00:47:47,827 +being the title bars and maybe there are buttons up there, so +标题条,然后旁边的位置特别适合放一个 + +1097 +00:47:47,829 --> 00:47:49,728 +it's a good place to put a Done button. +Done 的按钮。 + +1098 +00:47:49,730 --> 00:47:52,164 +Also, it gives me a title, okay? +同时我还可以设置一个标题,对吧? + +1099 +00:47:52,166 --> 00:47:53,632 +When this thing came up and +当它一出现,只是一个空白的屏幕 + +1100 +00:47:53,633 --> 00:47:55,099 +it was just a blank screen with these two fields, +上有两个文本框, + +1101 +00:47:55,102 --> 00:47:56,367 +it's a little disconcerting. +看起来有点“囧”呀。 + +1102 +00:47:56,369 --> 00:47:58,219 +What's happening? +会怎么样呢? + +1103 +00:47:58,220 --> 00:48:00,070 +Whereas, if I have a title on top, like, Edit Waypoint, +这里,如果有一个标题在顶部,比如 Edit Waypoint + +1104 +00:48:00,073 --> 00:48:02,306 +it'll be clear what the heck is going on. +将会明确很多。 + +1105 +00:48:02,308 --> 00:48:05,142 +So I'm just gonna select this, right here, and +所以我会选择这个方案,点击这里的 + +1106 +00:48:05,144 --> 00:48:09,012 +do Embed In Navigation Controller. +Embed In Navigation Controller + +1107 +00:48:09,014 --> 00:48:10,246 +'Kay? So +对吧 + +1108 +00:48:10,247 --> 00:48:11,479 +it puts a Navigation Controller. +这里我们放入了一个 Navigation Controller。 + +1109 +00:48:11,482 --> 00:48:15,617 +Now, I can, for example, put a title, Edit Waypoint, in here. +现在,举个例子来说,可以加一个标题, Edit Waypoint ,在这里。 + +1110 +00:48:15,619 --> 00:48:17,886 +And, also, I can have a Done button here. +然后我还可以增加一个 Done 按钮。 + +1111 +00:48:17,888 --> 00:48:21,822 +So let's go ahead and put a Done button in there. +好,那我们现在就在这里加一个 Done 按钮。 + +1112 +00:48:21,824 --> 00:48:24,591 +Down here to Bar Button Item. +往下找, 叫 Bar Button Item 。 + +1113 +00:48:24,593 --> 00:48:26,326 +Here's a Bar Button Item. +就这这里了, Bar Button Item 。 + +1114 +00:48:26,328 --> 00:48:27,861 +We'll put it right here. +我们把它拖到这里。 + +1115 +00:48:27,863 --> 00:48:29,095 +We'll call it Done. +给它命名为 Done 。 + +1116 +00:48:29,097 --> 00:48:32,898 +And then let's go ahead and wire that Done button up. +然后让我们继续把这个按钮和代码连接在一起。 + +1117 +00:48:32,900 --> 00:48:34,433 +Okay. We'll wire it +好的,我想我们还是把它 + +1118 +00:48:34,435 --> 00:48:36,334 +up at the top here, I guess. +链接到代码的最上面这里。 + +1119 +00:48:36,336 --> 00:48:40,171 +Just Ctrl+drag from this right in here. +就是按住 Ctrl 然后拖到这里就好。 + +1120 +00:48:40,173 --> 00:48:43,607 +And, so when we hit Done, all we're going to do is dismiss. +现在我们需要能做到当我们点击了 Done , 我们就能把它移除了。 + +1121 +00:48:43,609 --> 00:48:45,743 +So this is just going to be an action, +所以这个是需要一个 Action 。 + +1122 +00:48:45,745 --> 00:48:48,845 +bar button item action, we'll call it done. +bar button item action ,我们就给它命名为 done 。 + +1123 +00:48:48,847 --> 00:48:51,014 +And, inside this Done, right here. +然后在这个方法里,就是这里。 + +1124 +00:48:51,016 --> 00:48:53,482 +Sorry, we're going to go back to wide. +不好意思,我们要先把屏幕弄宽点。 + +1125 +00:48:54,652 --> 00:48:56,368 +Okay? +可以? + +1126 +00:48:56,369 --> 00:48:58,085 +Inside this done action when the done button is pressed, +当 done 按钮被按下的时候,我们只需要在 done + +1127 +00:48:58,088 --> 00:49:00,555 +I'm just going to say presenting +这个action 方法里,只需要写 + +1128 +00:49:00,557 --> 00:49:02,590 +view controller.dismiss. +viewController.dismiss 。 + +1129 +00:49:02,592 --> 00:49:04,291 +Okay? So, dismiss, +懂了?所以,直接移除, + +1130 +00:49:06,228 --> 00:49:10,430 +I'm asking the presenting view controller who presented me, +我们问当前展示的的视图控制器,谁展示的我。 + +1131 +00:49:10,432 --> 00:49:12,665 +please dismiss whoever you just presented. +然后移除掉当前正在展示的。 + +1132 +00:49:12,667 --> 00:49:16,335 +And, in fact, if my presenting view controller has presented +然后,实际上,如果展示我的视图控制器已经展示了我之后, + +1133 +00:49:16,337 --> 00:49:18,904 +me and I've presented someone else, when I do this dismiss, +然后我又展示里其他的,当我移除了之后, + +1134 +00:49:18,906 --> 00:49:20,238 +it's going to dismiss all of us. +就会将所有内容都移除掉。 + +1135 +00:49:21,241 --> 00:49:21,806 +Okay? +懂了? + +1136 +00:49:23,042 --> 00:49:25,142 +So, yes, we do want to animate it and, no, +是的,这里我还是需要一个动画效果, + +1137 +00:49:25,144 --> 00:49:28,912 +we don't want to find out when the dismiss happens, okay? +当移除了之后,我们就不想看到它了,对吧? + +1138 +00:49:30,949 --> 00:49:32,332 +Okay. So that's it. +好,就是这样了。 + +1139 +00:49:32,333 --> 00:49:33,716 +So that done button will allow us to dismiss. +这里这个 done 按钮就是能够实现移除。 + +1140 +00:49:35,219 --> 00:49:36,184 +All right. So, let's take a look, +好的,这样让我们来看下。 + +1141 +00:49:37,187 --> 00:49:38,919 +see if we fixed those two problems. +看下这两个问题是否被修复了。 + +1142 +00:49:41,757 --> 00:49:44,391 +And we only have one more piece to go to wire this up +我们在这之后已经有了一小部分。 + +1143 +00:49:44,393 --> 00:49:45,025 +after this. +我们在这之后已经有了一小部分。 + +1144 +00:49:47,429 --> 00:49:48,945 +All right. +好的。 + +1145 +00:49:48,946 --> 00:49:50,462 +So, we're going to add, along with the long press, +好,我们先长按,然后增加一个。 + +1146 +00:49:50,465 --> 00:49:52,464 +I'm gonna click, I'm gonna edit it. +我会先点击,然后编辑一下。 + +1147 +00:49:52,466 --> 00:49:54,383 +Here it is. +在这里。 + +1148 +00:49:54,384 --> 00:49:56,301 +Notice now I have this nice title, Edit Waypoint. +就可以看到,我们已经一个标题, Edit Waypoint 。 + +1149 +00:49:56,303 --> 00:50:00,138 +I can set this to be again, golf or something. +我可以重新设置这些内容,golf 或是其他什么内容。 + +1150 +00:50:00,140 --> 00:50:02,840 +I'm not gonna type too much because it's not gonna work +这里我们准备多输入些,因为这样程序是会有问题无法正确进行的, + +1151 +00:50:02,842 --> 00:50:05,009 +and you're going to see why in a moment. +你们马上就会看到了。 + +1152 +00:50:05,011 --> 00:50:06,176 +But here it is. +但现在在这里, + +1153 +00:50:06,178 --> 00:50:07,511 +Okay. We have this, we can return. +好的,我们已经了这个,我们可以返回了。 + +1154 +00:50:07,513 --> 00:50:08,946 +This is great. +这个太好了。 + +1155 +00:50:08,947 --> 00:50:10,380 +Our NBC's exactly what we want. +我们的 NBC 很好帮我们实现了我们想要的。 + +1156 +00:50:10,382 --> 00:50:11,681 +Now, I'm gonna hit Done. +现在,我点击 Done 按钮。 + +1157 +00:50:11,683 --> 00:50:13,049 +It dismisses it. +它已经被移除(消失)了。 + +1158 +00:50:13,051 --> 00:50:16,718 +Now, let's look and oh, it still says Dropped. +现在,让我们再看下,它始终还是被选装的状态。 + +1159 +00:50:16,720 --> 00:50:18,153 +Okay? Why is that? +嗯?为什么会这样? + +1160 +00:50:18,155 --> 00:50:21,255 +That's because we didn't prepare that segue. +这是因为我们没有为这个 segue 准备好。 + +1161 +00:50:21,257 --> 00:50:22,390 +Okay? +对吧? + +1162 +00:50:22,391 --> 00:50:23,524 +And modal segue is like any other segue, +modal seggue 和其他的 segue 一样的, + +1163 +00:50:23,526 --> 00:50:25,309 +if you don't prepare it, +如果你不预先做设置的话, + +1164 +00:50:25,310 --> 00:50:27,093 +it's going to not going to know what it's working on. +它就不知道它该如何工作。 + +1165 +00:50:27,096 --> 00:50:30,263 +So we need to set each modal, which is the waypoint to edit +所以我们需要为这个编辑 waypoint 的模态对话看进行 + +1166 +00:50:30,265 --> 00:50:33,166 +and we do that in prepare for segue. +准备和设置。 + +1167 +00:50:33,168 --> 00:50:34,300 +We already have a prepare for +我们之前已经对 GPXViewConrtoller 的 segue + +1168 +00:50:34,302 --> 00:50:37,069 +segue in our GPX view controller right here. +进行了提前的准备和设置。 + +1169 +00:50:37,071 --> 00:50:40,439 +Prepares for the image viewing 1, so +包括对于图片的浏览的准备,这里 + +1170 +00:50:40,441 --> 00:50:44,509 +we just need to put another else if the segue's +我们是需要另外一个 else if ,来根据segue 的标识符 + +1171 +00:50:44,511 --> 00:50:48,913 +identifier equals our new EditWaypointSegue. +进行判断,看是不是我们的 EditWaypointSegue 。 + +1172 +00:50:50,316 --> 00:50:51,632 +Okay? +对吧? + +1173 +00:50:51,633 --> 00:50:52,949 +And in here, what do we need to do? +在这里,我们该怎么做呢? + +1174 +00:50:52,951 --> 00:50:56,786 +Again, just like any other one, we need to get the thing +是的,就是想另外的一个,我们需要对当前我指的这个 + +1175 +00:50:56,788 --> 00:50:59,956 +we're pointing to, that we're segueing to and set it up. +我们需要跳转过去,然后做设置。 + +1176 +00:50:59,958 --> 00:51:05,828 +So we're going to say if the, I'll go, what did I call it, +所以这里我将会这么写,我想下该叫它什么呢, + +1177 +00:51:05,830 --> 00:51:08,296 +EWVC, okay, EditWaypointViewController. +EWVC ,对的,EditWaypointViewController。 + +1178 +00:51:08,298 --> 00:51:12,400 +If we can let the EditWaypointViewController +如果我们能让 EditWaypointViewController + +1179 +00:51:12,402 --> 00:51:15,770 +equal the segue's destination as and +等于 segue 的跳转过去的目标是 + +1180 +00:51:15,772 --> 00:51:18,772 +EditWaypointViewController. +EditWaypointViewController。 + +1181 +00:51:20,709 --> 00:51:24,677 +Okay, then now we've got this Edit Way View Controller. +这样,我们就能得到这个 EditWaypointViewController , + +1182 +00:51:24,679 --> 00:51:27,880 +We can set the EditWaypointViewControllers, +我就可以设置 EditWaypointViewController 的 wayPoint 属性 + +1183 +00:51:27,882 --> 00:51:30,549 +way point to edit equal to a way point. +等于当前的 waypoint 。 + +1184 +00:51:30,551 --> 00:51:32,484 +So, we need to get our waypoint, +这里我们需要得到我们的 waypoint , + +1185 +00:51:32,486 --> 00:51:34,152 +which I'm actually gonna steal from right here, +就是我们想从这里传递过去的那个 waypoint , + +1186 +00:51:34,154 --> 00:51:36,354 +because we already have a nice line of code that does that. +因为我们已经写过一行很不错的代码,可以做到这个。 + +1187 +00:51:40,726 --> 00:51:41,408 +Okay. +好的。 + +1188 +00:51:41,409 --> 00:51:42,091 +So there's our waypoint. +现在已经有了我们的航点(waypoint)。 + +1189 +00:51:43,461 --> 00:51:47,162 +Now this, oh, sorry, this also. +不是这个,哦,抱歉,是这个。 + +1190 +00:51:47,164 --> 00:51:48,764 +Notice this is complaining. +注意这里已经报错了。 + +1191 +00:51:48,766 --> 00:51:50,949 +See, this says error. +看,这里报错的。 + +1192 +00:51:50,950 --> 00:51:53,133 +I'm trying to set the waypoint to edit to waypoint and +我试着把这个waypoint 设置为可以编辑的 waypoint, + +1193 +00:51:53,136 --> 00:51:57,638 +it's saying GPX waypoint is not an editable waypoint. +然后它说 GPX waypoint 不是 editable waypoint 。 + +1194 +00:51:57,640 --> 00:51:59,340 +Ah-hah. +原来是这样啊。 + +1195 +00:51:59,342 --> 00:52:01,775 +Because we declared Waypoint Edit to be an editable +因为我们定义 waypoint edit 的类型为 editableWaypoint , + +1196 +00:52:01,777 --> 00:52:03,910 +waypoint, which is good, because it edits it, so +这个是没问题点,因为我们需要对它进行编辑,所以用这个类型 + +1197 +00:52:03,912 --> 00:52:06,096 +it better be. +更为贴切。 + +1198 +00:52:06,097 --> 00:52:08,281 +And this is a GPX Waypoint, cuz I copied this line of code +这个是GPXWaypoint ,因为我是从这里把代码拷贝过来的, + +1199 +00:52:08,283 --> 00:52:11,417 +from up here, where we're looking at the image URL. +这个就是我们之前查看的图像URL部分的, + +1200 +00:52:11,419 --> 00:52:13,419 +So really easy fix, though, +所以这个很好修复的。 + +1201 +00:52:13,421 --> 00:52:17,922 +we'll just set this to be an editable waypoint. +我们这里把它设置为一个可以编辑的航点。 + +1202 +00:52:17,924 --> 00:52:19,257 +'Kay? +可以把。 + +1203 +00:52:19,259 --> 00:52:21,058 +Now, this code will not work. +现在这个代码有报错。 + +1204 +00:52:22,194 --> 00:52:25,228 +Any sharp-eyed people know why this won't work. +你们眼尖的同学肯定一眼就能看出问题在哪。 + +1205 +00:52:25,230 --> 00:52:27,930 +It's a problem we've had in other prepare for segues. +这个问题就是我们实际上时给另外一个 seguge 做准备工作的。 + +1206 +00:52:29,967 --> 00:52:31,167 +>> Navigation. +>> Navigation。(导航视图控制器) + +1207 +00:52:31,168 --> 00:52:32,368 +>> Bingo. Bonus points over there. +>> 正确,加10分! + +1208 +00:52:32,370 --> 00:52:35,704 +If I were Aron, I'd be throwing candy at you at this point. +如果我是 Aron , 我肯定会奖励给一块糖的。 + +1209 +00:52:35,706 --> 00:52:37,289 +Yes. +没错。 + +1210 +00:52:37,290 --> 00:52:38,873 +That editable waypoint view controller is +EditableWayViewController是在 + +1211 +00:52:38,875 --> 00:52:40,741 +inside a navigation controller. +NavigationController 的内部的。 + +1212 +00:52:40,743 --> 00:52:43,277 +So the destination view controller is gonna be +所以这个跳转过去的目标视图控制器应该是 + +1213 +00:52:43,279 --> 00:52:44,711 +that navigation controller. +NavigationController 。 + +1214 +00:52:44,713 --> 00:52:47,447 +So this is not gonna work, cuz this is gonna fail, +所以这段代码不能正确工作, + +1215 +00:52:47,449 --> 00:52:48,748 +this as Waypoint finish. +是以传递 waypoint 结束的。 + +1216 +00:52:48,750 --> 00:52:50,816 +Now, we've dealt with this in the past, +现在我们知道,之前我们已经遇到过这样的问题, + +1217 +00:52:50,818 --> 00:52:53,052 +by putting a little if here, whatever. +只要写一小段代码就好了, + +1218 +00:52:53,054 --> 00:52:55,387 +It's so common to want to do that, +这是一个非常常见的情况, + +1219 +00:52:55,389 --> 00:52:59,357 +that actually I usually add an extension +实际上我通常都会扩展(继承) UIViewController + +1220 +00:52:59,359 --> 00:53:02,393 +to UIViewController that does that. +来解决这个问题。 + +1221 +00:53:02,395 --> 00:53:04,461 +I call it content view controller, and +我就叫它 ContentViewControler ,然后 + +1222 +00:53:04,463 --> 00:53:07,964 +all it says is if I'm a navigation controller, +它会记录我们是不是在 Navigation Controller 里面, + +1223 +00:53:07,966 --> 00:53:10,400 +then return my visible view controller. +如果在的话,就返回实际展示的视图控制器。 + +1224 +00:53:10,402 --> 00:53:11,834 +Otherwise return myself. +如果不在的话,就返回自己。 + +1225 +00:53:13,237 --> 00:53:14,236 +Okay. +好的。 + +1226 +00:53:14,238 --> 00:53:15,604 +So this is a nice little trick. +所以这是一个很方便的小技巧。 + +1227 +00:53:15,606 --> 00:53:18,073 +You can now, I can send to any view controller, +现在就可以,给我任何的一个View Controller , + +1228 +00:53:18,075 --> 00:53:20,174 +give me the content view controller. +都能返回给我实际内容的 View Controller 。 + +1229 +00:53:20,176 --> 00:53:21,542 +If you are the content view controller, +如果你就是实际内容的 View Controller , + +1230 +00:53:21,544 --> 00:53:22,810 +you just give me yourself. +你就给我你自己。 + +1231 +00:53:22,812 --> 00:53:23,910 +If you're a navigation controller, +如果你是一个 Navigation Controller , + +1232 +00:53:23,912 --> 00:53:26,146 +then you give me the visible view controller. +你就给我当前正在展示的 View Controller 。 + +1233 +00:53:26,148 --> 00:53:28,648 +So this is a really nice little extension to throw in +在你的 APP 开发中,你用了这个小的扩展(继承)之后,在处理 + +1234 +00:53:28,650 --> 00:53:32,351 +all your apps that are segueing to things that might +segue 跳转的时候,能非常方便的获取实际内容的 ViewController , + +1235 +00:53:32,353 --> 00:53:34,887 +or might not be in navigation controllers. +不用在意它是否在 Navigation Controller 里了。 + +1236 +00:53:34,889 --> 00:53:39,557 +So I use this by saying destinationViewController.con- +这里我就写上 destinationViewController.con- + +1237 +00:53:39,559 --> 00:53:41,626 +tentViewController. +tentViewController ,就可以了。 + +1238 +00:53:41,628 --> 00:53:43,127 +'Kay? +对吧? + +1239 +00:53:43,128 --> 00:53:44,627 +Cuz I added this var to all view controllers. +因为我已经给所有的 View Controller 加上了 var 关键字。 + +1240 +00:53:44,630 --> 00:53:46,063 +In fact, I can do the same thing up here. +事实上,我是对于这个,我们的图片在这里 + +1241 +00:53:47,166 --> 00:53:49,065 +With this one, okay, our image one. +做同样的处理的。 + +1242 +00:53:49,067 --> 00:53:53,536 +So, if we ever put our image, if we were ever transitioning +如果你之前已经放了我们的图片,或是之前之前我们已经改变过图片的显示, + +1243 +00:53:53,538 --> 00:53:56,105 +to show the image and it wrapped in a view controller, +它就已经包括在了 View Controller , + +1244 +00:53:56,107 --> 00:53:57,639 +we could do that as well. +我们也可以这样做。 + +1245 +00:53:57,641 --> 00:54:00,442 +So I almost put this in all of my +所以我把它放到了我所有跳转目标的 + +1246 +00:54:00,444 --> 00:54:01,976 +destination view controller segues. +View Controller 的 segue。 + +1247 +00:54:01,978 --> 00:54:03,844 +Why not? Doesn't hurt, okay. +为什么这么做?不会有什么不好的事情,对的。 + +1248 +00:54:05,214 --> 00:54:05,946 +All right. +没问题。 + +1249 +00:54:05,948 --> 00:54:07,113 +So now this will work. +好,现在它应该是可以正常运行的了。 + +1250 +00:54:07,115 --> 00:54:08,381 +Let's go ahead and run. +让我们运行试试看。 + +1251 +00:54:19,026 --> 00:54:24,963 +Okay, we add, we click, we edit, we go here. +好的,我增加一个,点击,然后编辑,我们到这里了。 + +1252 +00:54:24,965 --> 00:54:27,365 +Oh, notice now it says dropped. +看下,它说它现在写的是 “dropped”。 + +1253 +00:54:27,367 --> 00:54:29,533 +Because we prepared it, so +因为我们已经提前为它设置好了, + +1254 +00:54:29,535 --> 00:54:31,602 +it knows that it's the one that said drop. +所以它知道它自己应该写上 “dropped” 状态。 + +1255 +00:54:31,604 --> 00:54:33,036 +So I'm going to change this. +所以我要修改下这个。 + +1256 +00:54:33,038 --> 00:54:35,305 +Now we'll put back in Golf Course. +然后我现在回到了 Golf Couse 。 + +1257 +00:54:35,307 --> 00:54:37,974 +It's worse typing it in now that it's going to work. +如果可以继续运行的话,我前面的输入是有问题的。 + +1258 +00:54:37,976 --> 00:54:38,741 +Course. +Coures。 + +1259 +00:54:39,744 --> 00:54:41,009 +Okay. And then we could say it's +现在我可以继续输入, + +1260 +00:54:41,011 --> 00:54:46,147 +“under the snow, which it was when” +“under the snow, which it was when“ + +1261 +00:54:46,149 --> 00:54:47,415 +“from this trip.” +”from this trip.” + +1262 +00:54:47,417 --> 00:54:49,016 +Okay, so here we are. +好的,现在我们在这里。 + +1263 +00:54:49,018 --> 00:54:50,650 +We've got this, and we hit done. +我们已经编辑好了,然后点击 done 按钮。 + +1264 +00:54:50,652 --> 00:54:54,220 +And now when we look at our waypoint, it's edited it.' +现在当我们再看我们的航带你,它已经是编辑好了的。 + +1265 +00:54:54,222 --> 00:54:55,221 +Kay? +对吧? + +1266 +00:54:55,223 --> 00:54:57,890 +All right. +非常好。 + +1267 +00:54:57,892 --> 00:55:00,258 +Now, let's look at something else. +然后我们再看看其他的。 + +1268 +00:55:00,260 --> 00:55:03,328 +What's this gonna look like on an iPad? +在iPad上看起来怎么样? + +1269 +00:55:03,330 --> 00:55:06,097 +It looks great on iPhone, really nice, okay. +在 iPhone 上看起来真是不错。 + +1270 +00:55:06,099 --> 00:55:08,466 +But, let's take a look at iPad. +那么,让我们看看在 iPad 上 + +1271 +00:55:08,468 --> 00:55:09,667 +See what that looks like. +效果是怎么样的吧。 + +1272 +00:55:09,669 --> 00:55:11,601 +So I have an iPad here. +这里我有一个 iPad 。 + +1273 +00:55:11,603 --> 00:55:12,936 +It's going to run on that. +在上面直接运行。 + +1274 +00:55:22,880 --> 00:55:23,979 +All right. +好的。 + +1275 +00:55:23,981 --> 00:55:24,880 +There we go. There's an iPad. +我们看下,在这个iPad 。 + +1276 +00:55:24,882 --> 00:55:26,832 +Here's Trax. +这是我们的 APP Trax。 + +1277 +00:55:26,833 --> 00:55:28,783 +Now Trax is incredible on the iPad because +现在 Trax 看起来在 iPad 上的样子有点“出乎意料”, + +1278 +00:55:29,952 --> 00:55:31,618 +it's got such a big screen, +因为它的屏幕太大了。 + +1279 +00:55:31,620 --> 00:55:34,654 +we can really see all of our stuff very clearly. +我可以清楚的看到所有的内容。 + +1280 +00:55:34,656 --> 00:55:38,291 +And especially if we click and want to look at an image. +特别是当我点击这里,想看下这个图片, + +1281 +00:55:38,293 --> 00:55:41,361 +Wow, we got this really nice screen loading it up here, +哇,这个展示效果真是不错呀, + +1282 +00:55:41,363 --> 00:55:42,261 +but, whoa, look at that. +但,哦,看看那里。 + +1283 +00:55:42,263 --> 00:55:43,596 +So it's a gray. +是灰色的。 + +1284 +00:55:43,597 --> 00:55:44,930 +So it's actually quite great. +实际上看起来还是不错的。 + +1285 +00:55:44,932 --> 00:55:48,833 +This is quite a great thing on the iPad. +在 iPad 上看起来效果还是挺不错的。 + +1286 +00:55:48,835 --> 00:55:51,436 +But there's a problem with the iPad. +但在 iPad 上有一个问题。 + +1287 +00:55:51,438 --> 00:55:52,303 +Watch this. +看这里。 + +1288 +00:55:52,305 --> 00:55:53,671 +Let's add. +我们增加一个。 + +1289 +00:55:53,673 --> 00:55:54,338 +Okay. +好的。 + +1290 +00:55:54,340 --> 00:55:57,540 +Click on Dropped > Edit. +点击这个然后编辑。 + +1291 +00:55:57,542 --> 00:56:01,711 +And we've got this humongous thing. +我们会看到一个很搞笑大事情。 + +1292 +00:56:01,713 --> 00:56:05,314 +I mean there's no way we would ever use that much screen real +我的意思是,我们根本没有办法在这个屏幕分辨率上使用 + +1293 +00:56:05,316 --> 00:56:06,782 +estate, okay? +它,对吧? + +1294 +00:56:06,784 --> 00:56:09,718 +So that's really not an appropriate UI. +所以这不是一个合适 UI 。 + +1295 +00:56:09,720 --> 00:56:10,885 +Listen to me carefully. +这里注意一下我说的话。 + +1296 +00:56:10,887 --> 00:56:13,954 +That's not an appropriate UI for an iPad, okay? +这不是一个适应于 iPad 的UI,对吧? + +1297 +00:56:13,956 --> 00:56:16,523 +And I know that some of you, who were putting on your final +我知道你们有些人,在准备最后的大作业的时候, + +1298 +00:56:16,525 --> 00:56:19,426 +project, oh yeah for breadth, I'm supporting the iPad. +也会考虑到,正在支持 iPad 的展示。 + +1299 +00:56:19,428 --> 00:56:21,327 +And all you're doing is doing it on iPhone and +现在你现在做的这些,在 iPhone 上看起来都很好, + +1300 +00:56:21,329 --> 00:56:22,628 +then hoping that this is okay. +然后希望它在 iPad 上也是好的。 + +1301 +00:56:22,630 --> 00:56:23,996 +But this is not okay. +但事实上不是这样的。 + +1302 +00:56:23,998 --> 00:56:25,998 +Okay? This does not look +对吧?这个看起来在 iPad 上展示的 + +1303 +00:56:26,000 --> 00:56:27,633 +on the iPad. +不合适。 + +1304 +00:56:27,634 --> 00:56:29,267 +So if you're gonna say I support the iPad, don't try +所以如果你写这个 APP 支持 iPad ,可是“忽悠”不了我们, + +1305 +00:56:29,269 --> 00:56:31,703 +and swing this one by us, cuz we're just not gonna buy it. +我们是不会买单的。 + +1306 +00:56:31,705 --> 00:56:34,706 +Okay, we're gonna write down, doesn't really support iPad. +好吧,我们只是准备这样做,但实际上我们现在还不能支持 iPad 。 + +1307 +00:56:34,708 --> 00:56:38,208 +All right, so how could we make this UI look more +好吧,那我们想让我们的 UI 能够支持 iPad 该 + +1308 +00:56:38,210 --> 00:56:39,476 +iPad-esque? +怎么做呢? + +1309 +00:56:39,478 --> 00:56:40,844 +Well, there's a couple things we can do. +我们还是要好几件事情。 + +1310 +00:56:40,846 --> 00:56:44,347 +One is, we could go back to our storyboard and +首先,我们要回到我们的 storyboard + +1311 +00:56:44,349 --> 00:56:47,383 +we can change the transition style, +然后改变一下转换的方式。 + +1312 +00:56:47,385 --> 00:56:50,786 +'kay, of this particular segue way that we have down here. +好的,我们需要这个特殊的 segue 。 + +1313 +00:56:50,788 --> 00:56:52,287 +Where is it? +在哪里呢? + +1314 +00:56:52,289 --> 00:56:54,756 +It's over here. +在这里。 + +1315 +00:56:54,758 --> 00:56:55,390 +Here it is. +就是它。 + +1316 +00:56:55,392 --> 00:56:59,093 +If, we can change, it's still modal, but we can change this +这里我们还是把它设置为 modal ,但我们可以改变它的展示样式, + +1317 +00:56:59,095 --> 00:57:01,862 +presentation, for example, to be form sheet. +举个例子,改为 form sheet 。 + +1318 +00:57:01,864 --> 00:57:04,131 +So form sheet, it's iPad only. +这个是只有 iPad 才有的。 + +1319 +00:57:04,133 --> 00:57:07,434 +This will be ignored if you set this on an iPhone. +如果你在 iPhone 上设置的话,将会被直接忽略。 + +1320 +00:57:07,436 --> 00:57:10,703 +The Form sheet looks like this, and +Form sheet 看起来是这个样子的, + +1321 +00:57:10,705 --> 00:57:11,437 +it's a little better. +看起来好多了。 + +1322 +00:57:12,807 --> 00:57:13,905 +It's not enough better for your final project, +你最后的大作业应该要比这个好, + +1323 +00:57:13,907 --> 00:57:16,341 +but it's a little better. +不过现在这个效果在这里。 + +1324 +00:57:16,343 --> 00:57:18,743 +So here's what it looks like. +看起来是这样的。 + +1325 +00:57:23,683 --> 00:57:25,849 +All right, so I'm gonna add one here. +我们会在这里加上一个。 + +1326 +00:57:25,851 --> 00:57:26,883 +Click on it, edit it. +点击这里,编辑它。 + +1327 +00:57:26,885 --> 00:57:30,920 +See the Form sheet, at least it's smaller, okay? +看下这个 Form sheet ,它会更小一点,对吧? + +1328 +00:57:30,922 --> 00:57:32,388 +So it's a little better. +这样会更好点。 + +1329 +00:57:32,390 --> 00:57:33,655 +It doesn't look too bad. +看起来还不错。 + +1330 +00:57:33,657 --> 00:57:35,757 +It's almost good enough. +已经够好的了。 + +1331 +00:57:35,759 --> 00:57:38,960 +But really what the iPad wants is for +但实际上,iPad 上我们一般都是使用 + +1332 +00:57:38,962 --> 00:57:41,963 +that to be in a popover, right? +popover(弹出) 的,对吧? + +1333 +00:57:41,965 --> 00:57:43,898 +I wanna be able to go here. +我想这里也可以这样做。 + +1334 +00:57:43,899 --> 00:57:45,832 +And when I click this little thing, I want a small little +当我点击这里时,我想有一个小一点的 popover 出来, + +1335 +00:57:45,835 --> 00:57:48,802 +popover that just has the name and info field. +里面包括名字和信息的文本框。 + +1336 +00:57:48,804 --> 00:57:51,104 +And if I have an image, make space for an image. +如果我有图片的话,就给图片多“留”些地方。 + +1337 +00:57:51,106 --> 00:57:53,440 +That's the perfect thing for an iPad, okay? +这样在 iPad 上看起来就完美了,对吧? + +1338 +00:57:53,442 --> 00:57:56,676 +So let's turn this baby into a popover. +好,然后让我们把它放到 popover 里。 + +1339 +00:57:56,678 --> 00:57:59,011 +And that's gonna break the heck out of our iPhone one, +这样会让我们在 iPhone 上无法返回。 + +1340 +00:57:59,013 --> 00:58:01,647 +but we're gonna go back and fix that too, okay? +我们这样要回过头来修复这个问题,可以? + +1341 +00:58:01,649 --> 00:58:04,349 +But, first things first, let's make this into a popover. +不过,我们现在最需要的是先把这个改为 popover 。 + +1342 +00:58:04,351 --> 00:58:06,017 +So, how do we make this into a popover? +那我该怎么做呢? + +1343 +00:58:06,019 --> 00:58:08,286 +Well, I'm gonna get rid of this modal segue. +这里我将准备不使用 modal segue 。 + +1344 +00:58:08,288 --> 00:58:09,520 +So here's the modal segue. +好,这里是 modal segue 。 + +1345 +00:58:09,522 --> 00:58:11,288 +Let me zoom out so you can see it. +我缩小一点,你们就能看清楚了。 + +1346 +00:58:11,290 --> 00:58:14,024 +This is the modal segue that segues through this navigation +这个 modal segue 将从 navigation controller + +1347 +00:58:14,026 --> 00:58:15,525 +controller over to here. +跳转到这里。 + +1348 +00:58:16,628 --> 00:58:20,662 +So I'm just going to delete that by hitting delete. +这里我就先选中它,然后删掉。 + +1349 +00:58:20,664 --> 00:58:23,432 +I'm gonna have to move these over +因为我的屏幕不够大, + +1350 +00:58:23,434 --> 00:58:25,734 +closer because I have such a small screen here. +所以这里我不得不先把他们挪得靠近一些。 + +1351 +00:58:25,736 --> 00:58:28,236 +Then I'm gonna zoom in and then I'm just gonna make a new +然后我把它放大,然后就给可以从这里 + +1352 +00:58:28,238 --> 00:58:31,272 +segue from here directly to here. +创建一个新的 segue 。 + +1353 +00:58:31,274 --> 00:58:33,440 +I'm not gonna go through the navigation controller because +这里我是不经过 navigation controller 的,因为我不想 + +1354 +00:58:33,442 --> 00:58:34,374 +I don't want my popover to +我的 popover 里面的内容有一个 + +1355 +00:58:34,376 --> 00:58:35,875 +have a navigation controller title bar. +navigation controller 的标题栏。 + +1356 +00:58:35,877 --> 00:58:37,010 +Totally unnecessary. +因为完全没必要。 + +1357 +00:58:37,012 --> 00:58:39,578 +It's gonna be nice, sleek, little popover. +这样就好了,漂亮,一个小的 popover 。 + +1358 +00:58:39,580 --> 00:58:41,113 +So I'm just gonna go directly to here and +我这里直接就跳转到这里,然后以模态的方式 + +1359 +00:58:41,115 --> 00:58:42,247 +instead of present modally, +直接替换当前展示的内容。 + +1360 +00:58:42,249 --> 00:58:45,283 +I'm going to do popover presentation here. +我这里是以 popover 的方式进行展示的。 + +1361 +00:58:45,285 --> 00:58:47,168 +Okay? +懂了吗? + +1362 +00:58:47,169 --> 00:58:49,052 +Now when you do a popover, you notice I got an error here. +现在,当我打开 popover ,你会发现这里报错了。 + +1363 +00:58:49,055 --> 00:58:50,287 +Okay? +对吧? + +1364 +00:58:50,289 --> 00:58:53,357 +If I click on this and see what this error is, it says, +我们点开这里看下具体是什么错误,它说 + +1365 +00:58:53,359 --> 00:58:56,093 +'Popover segue with no anchor'. +“Popover segue with no anchor” + +1366 +00:58:56,095 --> 00:58:57,327 +Okay? I've got some frames to +嗯?我已经调整了框架(frame) + +1367 +00:58:57,329 --> 00:58:58,394 +adjust here. +在这里 + +1368 +00:58:58,396 --> 00:58:59,695 +And we have this unreachable scene, +因为这个 navigation controller,所以 + +1369 +00:58:59,697 --> 00:59:02,197 +because of this navigation controller, but that's okay. +这里是不能操作的区域,但那里是可以的。 + +1370 +00:59:02,199 --> 00:59:04,266 +It's this popover error with no anchor. +因为没有指定的锚点,所以无法 popover 。 + +1371 +00:59:04,268 --> 00:59:05,500 +So, what does that mean? +这是什么意思呢? + +1372 +00:59:05,502 --> 00:59:08,469 +Well, when you do a popover, the little arrow on +当你要 popover 的时候,这个在popover上的小箭头 + +1373 +00:59:08,471 --> 00:59:11,772 +the popover has gotta know where to point, okay? +就应该已经知道在哪里展示,对吧? + +1374 +00:59:11,774 --> 00:59:13,774 +Sometimes, it points to a bar button. +有些时候,它是指向 bar button 。 + +1375 +00:59:13,776 --> 00:59:16,843 +And here, I'm gonna have it point to the map view. +这里我们是希望它能指向我们的 map view。 + +1376 +00:59:16,845 --> 00:59:18,395 +More specifically, +更进一步说, + +1377 +00:59:18,396 --> 00:59:19,946 +I'm gonna have it point to the little pin. +我是希望它能够指向这个小的标识。 + +1378 +00:59:19,948 --> 00:59:21,748 +Okay? +对吧? + +1379 +00:59:21,749 --> 00:59:23,549 +So if we don't specify that then a popover can't work. +这里如果我们没有指明的话,就无法正常进行popover。 + +1380 +00:59:23,551 --> 00:59:26,435 +So how do we specify that? +那我们该怎么指明呢? + +1381 +00:59:26,436 --> 00:59:29,320 +How do we specify where, when this popover wants to popover +当从这个 view controller 要 popover 的时候,该怎么 + +1382 +00:59:29,323 --> 00:59:32,290 +from this view controller, it shows up? +指明是从哪里? + +1383 +00:59:32,292 --> 00:59:34,526 +Well, one part of it we can do with dragging. +对的,我们需要先通过拖动的方法来完成。 + +1384 +00:59:34,528 --> 00:59:36,060 +You see right here, in the inspector, +看下这里, 在 inspector(检查器)。 + +1385 +00:59:36,062 --> 00:59:39,030 +I've inspected this segue right here. +我已经在这里设置过这个 segue 。 + +1386 +00:59:39,032 --> 00:59:40,431 +I clicked right on here. +我在这里点击。 + +1387 +00:59:40,433 --> 00:59:42,366 +You can see that it says anchor. +你就能看到这里有一个 anchor (锚点)。 + +1388 +00:59:42,368 --> 00:59:44,434 +It says drag to select an anchor. +然后就直接拖到这个锚点。 + +1389 +00:59:44,436 --> 00:59:48,037 +Okay, well, I'm just gonna drag over to my map view, +对对,我从我们的 map view 拖过去的。 + +1390 +00:59:48,039 --> 00:59:50,406 +oops, except for I need to zoom in. +哦,我想我需要放大一些。 + +1391 +00:59:50,408 --> 00:59:51,641 +Okay? So, +好吧, + +1392 +00:59:51,642 --> 00:59:52,875 +I'm just going to select the segue. +现在我们选中了这个 segue 。 + +1393 +00:59:52,877 --> 00:59:55,644 +I'm gonna drag to my map view. +拖到我的 map view。 + +1394 +00:59:55,646 --> 00:59:57,212 +And it says, okay, map view. +对,是的,map view。 + +1395 +00:59:57,214 --> 00:59:57,912 +Great. +好极了。 + +1396 +00:59:57,914 --> 00:59:59,147 +You're good to go. +现在就可以了。 + +1397 +00:59:59,148 --> 01:00:00,381 +And it game me no more error. +已经没有报错信息了。 + +1398 +01:00:00,383 --> 01:00:02,516 +Except for this is not gonna work either because +不过还是不能正常工作, + +1399 +01:00:02,518 --> 01:00:06,453 +I have to say where in the map view I want this to work from. +因为我没有设置从 map view 的哪个位置展示 popover的内容。 + +1400 +01:00:06,455 --> 01:00:08,321 +If I don't say where, it's gonna try and +如果我不写是哪里,它就会从 + +1401 +01:00:08,323 --> 01:00:10,390 +point it to the edge of the map view itself, +map view 的边缘开始。 + +1402 +01:00:10,392 --> 01:00:12,658 +which is gonna be off screen, which is useless. +这样就到屏幕的外面了,看不到,也就没用了。 + +1403 +01:00:12,660 --> 01:00:14,960 +I need to specify a little rectangle inside. +我需要在里面指定一个小些的区域。 + +1404 +01:00:14,962 --> 01:00:16,194 +So how do I do that? +那我该怎么做呢? + +1405 +01:00:16,196 --> 01:00:19,064 +Where do I specify that little rectangle? +我在哪里指定这个小些的区域(矩形)? + +1406 +01:00:19,066 --> 01:00:21,766 +And the answer is it's exactly where we specify +我们必须要配置 popover 的具体 + +1407 +01:00:21,768 --> 01:00:24,869 +anything having to do with configuring a popover. +在哪个位置。 + +1408 +01:00:24,871 --> 01:00:26,670 +Okay and we have already done this in this class but +好的,我们已经把代码写完了,但我们还是忘了些事情 + +1409 +01:00:26,672 --> 01:00:28,138 +you have probably forgotten, but for +我想你们大多数人在最后的大作业中都会 + +1410 +01:00:28,140 --> 01:00:30,573 +your final project many of you are gonna do popovers. +用到 popovers 吧,这里就是提醒一下你们 + +1411 +01:00:30,575 --> 01:00:34,177 +So here is something to remember where you +这些地方不要忘了, + +1412 +01:00:34,179 --> 01:00:35,478 +set things for popover, and +你需要对 popover 进行设置。 + +1413 +01:00:35,480 --> 01:00:40,282 +that is in the prepare for segue for that popover segue. +也就是需要对 popover segue 进行预先的设置。 + +1414 +01:00:40,284 --> 01:00:43,318 +Okay, specifically I'm gonna do it right down here, and +好的,这里我就准备在这里写了, + +1415 +01:00:43,320 --> 01:00:47,421 +you wanna get the popovers presentation controller. +我们是希望得到一个 popover presentation controller 。 + +1416 +01:00:47,423 --> 01:00:48,889 +Okay? And you get the proper +对吧?然后想得到 + +1417 +01:00:48,891 --> 01:00:51,491 +presentation controller just by asking the, +这个 controller 是需要通过名称, + +1418 +01:00:51,493 --> 01:00:55,528 +make sure is it the right name for +这里我们给它命名为 PPC, + +1419 +01:00:55,530 --> 01:00:59,699 +these things that I call that PPC, I think I did yeah. +这样就可以了。 + +1420 +01:00:59,701 --> 01:01:04,336 +You just ask the thing that you're presenting, +你只需要问需要展示的控制器, + +1421 +01:01:04,338 --> 01:01:07,472 +give me your popover presentation controller. +让它给你 popover presentation controller 就可以了。 + +1422 +01:01:07,474 --> 01:01:10,275 +Okay? +对吧? + +1423 +01:01:10,276 --> 01:01:13,077 +But you probably want to if let this, because you want +但你可能会想到,如果我不是 popover 的话, + +1424 +01:01:13,079 --> 01:01:15,779 +your code to work even if it's not in a popover. +我也希望我的代码能够正常工作。 + +1425 +01:01:15,781 --> 01:01:17,647 +If we change this back to be modal, +这里如果我把它改为 modal 方式的返回, + +1426 +01:01:17,649 --> 01:01:19,349 +we'd still want it to work. +它就应该也能正常工作了。 + +1427 +01:01:19,351 --> 01:01:21,050 +If you're not in a popover presentation this +如果你不是 pop presentation 的话,这里就会返回 + +1428 +01:01:21,052 --> 01:01:23,919 +will return nil, so you won't be doing the code in here. +nil,所以这里你就需要写一些代码来处理。 + +1429 +01:01:23,921 --> 01:01:26,588 +So this code is only going to happen if this segue is +这些代码时针对这个 segue 是跳转到 popover controller的才 + +1430 +01:01:26,590 --> 01:01:29,124 +popover controlled. +有用。 + +1431 +01:01:29,126 --> 01:01:32,961 +So popover presentation controller, okay, if you look +至于这个 popover presentation controller ,如果你看过 + +1432 +01:01:32,963 --> 01:01:37,031 +at it in the documentation you can see that it's got, oops, +文档的话 ,哦, + +1433 +01:01:37,033 --> 01:01:39,933 +that's not a very good link to that is it? +这个链接有问题? + +1434 +01:01:40,936 --> 01:01:42,635 +Oh, maybe it doesn't return that. +可能它不能返回了。 + +1435 +01:01:44,205 --> 01:01:46,105 +Wait a minute. [INAUDIBLE] Okay, +等一下,好了,是这个 + +1436 +01:01:46,107 --> 01:01:47,305 +PopoverPresentationController. +PopoverPresentationController。 + +1437 +01:01:47,307 --> 01:01:50,241 +You can see it's got some things here like that source +你可以看到,相关内容的这些 + +1438 +01:01:50,243 --> 01:01:51,909 +view that we wired up. +介绍的。 + +1439 +01:01:51,911 --> 01:01:54,045 +Okay, it's also got sourceRect. +这里还有 getSourceRect。 + +1440 +01:01:54,047 --> 01:01:56,413 +That's the rectangle inside the source view. +是指可以获取内部 source view 的显示区域。 + +1441 +01:01:56,415 --> 01:01:57,748 +Or you can have a bar button item. +或是你也可以在这增加一个 bar button item 。 + +1442 +01:01:57,750 --> 01:02:00,050 +If you have a bar button item, you don't need both of these. +如果你已经有了 bar button item ,你就不需要。 + +1443 +01:02:00,052 --> 01:02:02,251 +We've, so it's kind of either/or. +这是一个可以选择的。 + +1444 +01:02:02,253 --> 01:02:05,054 +And also, it's got a delegate, which we're gonna use to +另外,我们还看到有一个 delegate ,我们可以 + +1445 +01:02:05,056 --> 01:02:08,757 +control our adaptive behavior and a few other things. +使用它来做一些事情。 + +1446 +01:02:08,759 --> 01:02:10,792 +But, so that's what you can configure in +这些就是我们可以在 popoverPresentationController + +1447 +01:02:10,794 --> 01:02:12,360 +the popoverPresentationController. +可以设置的内容。 + +1448 +01:02:12,362 --> 01:02:14,295 +So let's do that sourceRect. +好,让我们先来设置一下 sourceRect 。 + +1449 +01:02:14,297 --> 01:02:15,563 +Okay. +好。 + +1450 +01:02:15,564 --> 01:02:16,830 +So the sourceRect equals. +让这个 sourceRect 等于 + +1451 +01:02:16,833 --> 01:02:18,732 +We want this, basically a rectangle for +这个 annotation view 的类型是 + +1452 +01:02:18,734 --> 01:02:22,702 +that annotation view so I'm going to say here, +MK annotation view, + +1453 +01:02:22,704 --> 01:02:26,406 +the sender as an MK annotation view. +这里我们的显示区域就是针对这个 view 的。 + +1454 +01:02:26,408 --> 01:02:30,909 +Okay, so sender, remember is this sender to the prepare for +好的,这里是否还记得这个 sender 就是 我们传递给 annotation view + +1455 +01:02:30,911 --> 01:02:35,880 +segue which we passed the annotation view as the sender. +用来设置 seguge 的那个。 + +1456 +01:02:35,882 --> 01:02:37,665 +Okay? +对吧? + +1457 +01:02:37,666 --> 01:02:39,449 +So the sender is the pin that's causing all this trouble. +所以这个 sender 就是那个小的标识,也是它造成了这一切的麻烦。 + +1458 +01:02:40,553 --> 01:02:44,888 +And I added a nice method to that called popover SourceRect +这里我准备增加一个方法,命名叫。 + +1459 +01:02:44,890 --> 01:02:46,189 +for coordinate point. +popoverSourceRectForCoordinatePoint + +1460 +01:02:46,191 --> 01:02:50,426 +And you just give it a point, coordinate point. +这里你给定坐标上的点。 + +1461 +01:02:50,428 --> 01:02:52,795 +And so let's calculate that point. +然后我们来计算这个点。 + +1462 +01:02:52,797 --> 01:02:54,396 +I'll show you that method in a second. +我下面就会来给具体写这个方法。 + +1463 +01:02:54,398 --> 01:02:56,331 +So we're going to let the coordinate point. +我们首先让这个坐标下的点。 + +1464 +01:02:56,333 --> 01:02:59,167 +We're going to calculate the coordinate point by getting +我们会通过计算得到这个点的坐标转换为 + +1465 +01:02:59,169 --> 01:03:01,035 +the annotations coordinate and +在注释视图上的坐标,我们是通过 + +1466 +01:03:01,037 --> 01:03:02,269 +using the map view to convert it. +map view 来完成这个转换。 + +1467 +01:03:02,271 --> 01:03:08,475 +So mapView.convertCoordinate, +所以就写 mapView.convertCoordinate, + +1468 +01:03:08,477 --> 01:03:10,777 +and the coordinate is the way points coordinate. +然后这个坐标就是 way point 的坐标。 + +1469 +01:03:12,146 --> 01:03:16,148 +And we're going to convert it to a point in the map view. +我们将会把这个点在 map view 里进行转换。 + +1470 +01:03:16,150 --> 01:03:19,117 +Alright, so here I'm just getting the point of our pin, +好的,这里我们是可以得到我们的这个小标志的坐标, + +1471 +01:03:19,119 --> 01:03:20,719 +where our pin is on the map, and +那我们的坐标在地图的哪里? + +1472 +01:03:20,721 --> 01:03:23,388 +then I'm asking the notation view, please give me +然后我需要问 notation view, 请给我一个区域,在你的坐标系 + +1473 +01:03:23,390 --> 01:03:26,891 +a rectangle that would be good for a popover to point at. +要能刚好可以放下 + +1474 +01:03:26,893 --> 01:03:28,826 +At that coordinate point. +我的 popover 的视图。 + +1475 +01:03:28,828 --> 01:03:31,928 +And this code, this popover thing, is right here. +这段代码,在这个 popover ,在这里。 + +1476 +01:03:31,930 --> 01:03:33,563 +And it's really simple, really. +要做的是非常简单,真的。 + +1477 +01:03:33,565 --> 01:03:36,466 +It just gets the width and height of our frame, +只是需要得到我们的 frame 的宽度和高度。 + +1478 +01:03:36,468 --> 01:03:38,100 +our little pin views frame. +是我们这个小的标识的 frame 。 + +1479 +01:03:38,102 --> 01:03:40,402 +And then it offsets it by the calloutOffset and +然后设置通过 calloutOffset和 centerOffset 设置 + +1480 +01:03:40,404 --> 01:03:41,870 +the centerOffset. +偏移量。 + +1481 +01:03:41,872 --> 01:03:43,271 +Don't worry too much about those. +不用担心太多。 + +1482 +01:03:43,273 --> 01:03:44,505 +But that's all it does. +这样就可以了。 + +1483 +01:03:44,507 --> 01:03:47,208 +So it's basically just putting a frame around itself so +只需要最基本的设置一个 frame,然后我们就 + +1484 +01:03:47,210 --> 01:03:48,642 +that we can have the popover. +可以看到 popover。 + +1485 +01:03:48,644 --> 01:03:50,911 +I just didn't wanna put that code in here and +我是不想把这些代码放到这里,怕影响你们的理解, + +1486 +01:03:50,913 --> 01:03:53,179 +mess it up for you, but that's all it does. +但这样其实就好了。 + +1487 +01:03:53,181 --> 01:03:56,549 +Now, we have this popover source rec. +现在我们已经有了 popover source rect 。(展示区域) + +1488 +01:03:56,551 --> 01:03:57,850 +Let's see what this looks like. +让我们看看效果。 + +1489 +01:03:57,852 --> 01:04:00,652 +This is not gonna quite be what we want, but +这看起来不完全是我们希望的,但我们已经可以看到 + +1490 +01:04:00,654 --> 01:04:02,254 +we're getting there. +它们了。 + +1491 +01:04:09,996 --> 01:04:15,366 +All right, [SOUND] Here we go,' kay? +好的,接着,怎么? + +1492 +01:04:15,368 --> 01:04:17,668 +I'm gonna long press to drop. +我们长按后然后松开。 + +1493 +01:04:17,670 --> 01:04:18,535 +We're gonna edit it. +我们要编辑它。 + +1494 +01:04:19,904 --> 01:04:20,836 +And we got a crash. +哦,我们的程序崩溃了。 + +1495 +01:04:20,838 --> 01:04:23,439 +Okay. And, so why does this crash? +好吧,为什么它会崩溃? + +1496 +01:04:23,441 --> 01:04:26,274 +It's because we forgot to set our segue identifier for +这是因为我们忘了把我们的segue的标识符设置为 + +1497 +01:04:26,276 --> 01:04:28,810 +the popover to edit waypoints, okay? +popover to edit waypoints,对吧? + +1498 +01:04:28,812 --> 01:04:30,111 +Probably you've all seen this. +你们已经可以看到这个报错。 + +1499 +01:04:31,781 --> 01:04:34,248 +No segue with identifier error. +No segue with identifier error。 + +1500 +01:04:34,250 --> 01:04:35,415 +That's easy to fix. +这个很好被修复。 + +1501 +01:04:35,417 --> 01:04:37,484 +Let's go back to our storyboard. +让我们回到我们的 storyboard 。 + +1502 +01:04:38,453 --> 01:04:41,187 +Get our segue inspected. +然后看下我们的 segue 的检查器 + +1503 +01:04:41,189 --> 01:04:42,221 +And sure enough, look at that. +确定了,看这里。 + +1504 +01:04:42,223 --> 01:04:46,224 +Edit Wavepoint. +Edit Wavepoint。 + +1505 +01:04:46,226 --> 01:04:49,361 +All right, sometimes it's good when I forget to do +对的,有些时候看起来是没有问题的,我们忘了做一些事情 + +1506 +01:04:49,363 --> 01:04:52,697 +things like that because you get to see common things. +这是因为我们已经把一些基本的设置完成了。 + +1507 +01:04:52,699 --> 01:04:54,532 +That's a common thing to do, is to forget. +做完这些基本的设置,会忘记的。 + +1508 +01:04:54,534 --> 01:04:56,400 +Either to have the name be different or +比如应该设置不同的名字,或是 + +1509 +01:04:56,402 --> 01:04:58,168 +you forget to put it in entirely. +忘了把它全部修改好。 + +1510 +01:05:00,038 --> 01:05:06,575 +All right, so now, here we go, like that, and Edit. +好,现在,让我们在看看效果,这里,编辑。 + +1511 +01:05:07,545 --> 01:05:08,443 +And we've got a popover. +好,我们可以看到 popover 了。 + +1512 +01:05:08,445 --> 01:05:09,961 +Whoo! +哎! + +1513 +01:05:09,962 --> 01:05:11,478 +It doesn't look very good, though. +看起来还是不太对。 + +1514 +01:05:11,481 --> 01:05:14,115 +Okay. +好吧。 + +1515 +01:05:14,116 --> 01:05:16,750 +So, it's kind of close, but it's gigantic still, and +已经很接近老,但它实在是太大了, + +1516 +01:05:16,753 --> 01:05:18,719 +the whole point of this is to not use so +这个(弹出框)并没有合理的 + +1517 +01:05:18,721 --> 01:05:21,054 +much darn screen real estate. +使用屏幕(没有显示合适的大小)。 + +1518 +01:05:21,056 --> 01:05:22,222 +So why is that happening? +为什么会这样? + +1519 +01:05:22,224 --> 01:05:25,892 +Well, that's because we do nothing to tell the system +好吧,这是因为我们没有告诉 + +1520 +01:05:25,894 --> 01:05:28,294 +what we would like the content size to be here. +我们内容的大小。 + +1521 +01:05:28,296 --> 01:05:30,629 +And if you remember, the last time we did popovers, +如果你还记得,我们最后设置 did popovers 的地方, + +1522 +01:05:30,631 --> 01:05:32,397 +we actually overrode the. +我实际是重写(overrode) + +1523 +01:05:32,399 --> 01:05:34,699 +Property preferred content size and +preferred content size 这个属性,然后是返回 + +1524 +01:05:34,701 --> 01:05:36,801 +return calculated content size. +计算后的 content size 。 + +1525 +01:05:36,803 --> 01:05:37,902 +Here I'm going to do it a different way. +这里,我准备用另外一种方法。 + +1526 +01:05:37,904 --> 01:05:40,270 +I'm gonna actually set the preferred content size. +我会直接设置好这个 preferred conten size。 + +1527 +01:05:40,272 --> 01:05:41,638 +So I'm doing the same thing. +好,我们来做吧。 + +1528 +01:05:41,639 --> 01:05:43,005 +I'm just gonna set it, because it's a var. +我要来设置它,因为它是一个 var 。 + +1529 +01:05:43,008 --> 01:05:44,307 +I can set it, it's a settable var. +我可以直接设置它, + +1530 +01:05:44,309 --> 01:05:45,875 +I don't have to override it. +我不需要直接重写(override)他。 + +1531 +01:05:45,877 --> 01:05:48,244 +So I'm just gonna set it to a size. +所以我会直接设置它的大小。 + +1532 +01:05:48,246 --> 01:05:51,447 +And so, what kind of size would be good there? +那么,这里应该设置多大的会比较合适? + +1533 +01:05:51,449 --> 01:05:54,116 +Let me make some more space. +让我们先多空出一些位置。 + +1534 +01:05:54,118 --> 01:05:58,820 +We're still doing all this inside this popover-specific +我们来在popover的对应的代码来处理 + +1535 +01:05:58,822 --> 01:06:00,555 +code. +这件事。 + +1536 +01:06:00,556 --> 01:06:02,289 +A good size for that would be, height-wise, +我们需要这样一个合适的大小,高度时自动适应的, + +1537 +01:06:02,291 --> 01:06:05,225 +it would be if I just let the auto layout do it. +这个部分可以通过 auto layout 实现。 + +1538 +01:06:05,227 --> 01:06:07,060 +Wouldn't it be cool if I could just find out what +如果我们能通过 auto layout 之后最小的 size 的话 + +1539 +01:06:07,062 --> 01:06:09,729 +the auto layout thought the smallest size was? +那就最好不过了。 + +1540 +01:06:09,731 --> 01:06:10,830 +Turns out, you can do that. +那么事实是,这是可以做到的。 + +1541 +01:06:10,832 --> 01:06:15,501 +Watch this, let minimum size equal +看这里,let minimum size 等于 + +1542 +01:06:15,503 --> 01:06:19,571 +the view controller's view. +这个视图控制的视图。 + +1543 +01:06:19,573 --> 01:06:22,907 +I'm just gonna smash down the view controller view as much +我就准备尽量把这个视图控制器下的视图 + +1544 +01:06:22,909 --> 01:06:24,075 +as possible. +压缩到最小。 + +1545 +01:06:24,077 --> 01:06:25,009 +The name of the method is called +这个方法的名字就叫做 + +1546 +01:06:25,011 --> 01:06:28,245 +systemLayoutFittingSize. +systemLayoutFittingSize。 + +1547 +01:06:28,247 --> 01:06:30,313 +And it takes a size, and +传入的是一个 size , + +1548 +01:06:30,315 --> 01:06:32,615 +that size is the size it's gonna try to fit into. +这个 size 就是我们准备调整的。 + +1549 +01:06:32,617 --> 01:06:34,384 +And there's really two choices here. +这里有两个选择可以考虑。 + +1550 +01:06:34,386 --> 01:06:37,687 +One is, fit it into as small a space as possible, +一个是,调整到一个尽量小多区域里, + +1551 +01:06:37,689 --> 01:06:40,556 +or fit it into as big a space as possible, okay? +或是调整到一个尽量大的区域里,对吧? + +1552 +01:06:40,558 --> 01:06:41,957 +So I'm gonna go for small as possible, +这里我是准备要一个尽量小的区域, + +1553 +01:06:41,959 --> 01:06:43,158 +cuz I want this thing to be small. +因为我想需要内容能够紧凑些。 + +1554 +01:06:43,160 --> 01:06:46,361 +So that UILayoutFittingSizeCompress. +所以这里:UILayoutFittingSizeCompress 。 + +1555 +01:06:46,363 --> 01:06:48,596 +See, there's expanded and compressed. +看这里有 expanded(扩展) 和 compressed(压缩)。 + +1556 +01:06:48,598 --> 01:06:50,130 +So I want the compressed size. +我需要一个压缩后的大小。 + +1557 +01:06:50,132 --> 01:06:54,334 +So this is gonna give me the minimum size that that +它就返回给我一个最小的size, 然后视图控制器也是可以 + +1558 +01:06:54,336 --> 01:06:56,636 +view controller can be by using Auto Layout. +通过 Auto Layout 进行布局。 + +1559 +01:06:57,605 --> 01:06:59,104 +Okay, which is really awesome. +好吧,这个简直太棒了。 + +1560 +01:06:59,106 --> 01:07:01,873 +This is what the table U cells are using to size, +这就是我们在表格的单元格里自动获得内容 + +1561 +01:07:01,875 --> 01:07:04,476 +get the heights automatically with a layout. +高度的方法。 + +1562 +01:07:04,478 --> 01:07:06,445 +It's a really, really great feature. +这真是一个非常非常好的特性。 + +1563 +01:07:06,446 --> 01:07:08,413 +Now, I don't actually want it to be the minimum size in +现在,我并不需要在宽度方面 + +1564 +01:07:08,415 --> 01:07:09,613 +width, though. +也是最小的。 + +1565 +01:07:09,615 --> 01:07:11,281 +Because I wanna have some room for +因为我需要多预留出一部分位置,让用户可以 + +1566 +01:07:11,283 --> 01:07:14,718 +the person to type in the name and the info that they want. +输入名字和相关的内容。 + +1567 +01:07:14,720 --> 01:07:16,353 +So I'm going to pick a size. +我下面来设置这个 size 。 + +1568 +01:07:16,355 --> 01:07:18,488 +It's going to be a constant in my app. +在我的APP里我将定一个常量。 + +1569 +01:07:18,490 --> 01:07:23,258 +So, I'm going to set my preferred content size, +我先设置我的 preferred content size , + +1570 +01:07:23,260 --> 01:07:24,860 +equal CGSize. +等于 CGSize。 + +1571 +01:07:24,862 --> 01:07:29,163 +And the width I want is going to be this constant, +然后我希望宽度是一个常量。 + +1572 +01:07:29,165 --> 01:07:34,234 +constants, whoops, width, constants dot, what did I +常量,哦,宽度,直接用 constants 点(出来) + +1573 +01:07:34,236 --> 01:07:40,407 +call it here, yeah, edit waypoint pop-over width, okay? +可以看到提示,对,edit waypoint pop-over width ,对吧? + +1574 +01:07:40,409 --> 01:07:42,675 +And that the height is gonna be the minimumSize. +然后高度就是 minimumSize.height ,对吧? + +1575 +01:07:42,677 --> 01:07:44,343 +The height, okay? +然后高度就是 minimumSize.height ,对吧? + +1576 +01:07:44,345 --> 01:07:46,311 +So I'm using the minimumSize for the height, but +我这里用minimumSize的高度,同时 + +1577 +01:07:46,313 --> 01:07:50,382 +I'm picking this, which I've set to be 320, which +我处理的时候,它的宽度已经被设置为320,这是一个默认值。 + +1578 +01:07:50,384 --> 01:07:52,917 +is pretty standard width, and a pretty good width. +这个宽度非常好。 + +1579 +01:07:52,919 --> 01:07:55,453 +That's probably about the width of that is now. +因为这恰好就是我们当前的宽度。 + +1580 +01:07:56,556 --> 01:07:58,622 +But by setting preferred content size, +但是在设置首选内容区域的大小时, + +1581 +01:07:58,624 --> 01:08:01,191 +that tells the pop-over machinery +就可以自动计算和 + +1582 +01:08:01,193 --> 01:08:04,361 +to make the pop-over be this size if possible. +设置 pop-over 的区域大小。 + +1583 +01:08:04,363 --> 01:08:06,829 +It's only preferred, it might not be possible, +这只是优先,但不是必须的。 + +1584 +01:08:06,831 --> 01:08:09,065 +cuz the geometry of other views might get in the way, +因为其他的视图可能会相互有影响, + +1585 +01:08:09,067 --> 01:08:10,199 +can't do it, but this is, +可能就无法设置,这种情况下, + +1586 +01:08:10,201 --> 01:08:12,234 +it's going to try to make it this if it can't. +就会继续尝试设置, + +1587 +01:08:12,236 --> 01:08:13,268 +And usually, it can't. +一般情况下,它是不能的 。 + +1588 +01:08:13,270 --> 01:08:15,403 +So, let's go see how this works. +那就让我们看下效果到底如何。 + +1589 +01:08:28,884 --> 01:08:30,250 +Okay, here we go. +好,来,我们看看。 + +1590 +01:08:30,252 --> 01:08:31,418 +Long press. +长按。 + +1591 +01:08:31,420 --> 01:08:32,418 +Top. +上面。 + +1592 +01:08:32,420 --> 01:08:35,538 +Edit. +编辑。 + +1593 +01:08:35,539 --> 01:08:38,657 +Oh awesome okay, and now we can edit this right into +哦,太好来,现在我们就可以刚好在这里进行编辑 + +1594 +01:08:38,659 --> 01:08:43,028 +place here, golf course, +golf course, + +1595 +01:08:43,030 --> 01:08:46,964 +you know, foo. +你们知道的 ,foo。 + +1596 +01:08:46,966 --> 01:08:49,467 +Okay, and it's editing it on the fly, editing as do, so +好的,现在可以直接进行编辑, + +1597 +01:08:49,469 --> 01:08:51,035 +if I click away and +如果我点击离开,然后 + +1598 +01:08:51,037 --> 01:08:54,204 +then click back, I get golf course still, okay? +点击返回,我这里看到的还是 golf course ,对吧? + +1599 +01:08:54,206 --> 01:08:56,272 +And, again, I can always go back, edit it again. +然后,我再回来继续编辑。 + +1600 +01:08:57,375 --> 01:08:59,542 +So this is really looking good. +看起来非常好。 + +1601 +01:08:59,544 --> 01:09:01,377 +It's not quite perfect. +但还不是特别完美。 + +1602 +01:09:01,379 --> 01:09:05,047 +It's kind of, if you look at the arrow that points down, +这里,你看箭头指向的这里, + +1603 +01:09:05,049 --> 01:09:07,215 +it looks like it's kind of see-through, +这里应该能够透过去看到下面, + +1604 +01:09:07,217 --> 01:09:09,283 +but the thing is white. +但现在这里是白的。 + +1605 +01:09:09,285 --> 01:09:10,951 +So, there's no reason that +这是因为 pop-over 需要这里 + +1606 +01:09:10,953 --> 01:09:12,720 +this pop-over needs to be white. +是白色的。 + +1607 +01:09:12,722 --> 01:09:14,988 +It'd be really cool if it kind of, you could see back, +如果我们可以透过这里看到后面的内容, + +1608 +01:09:14,990 --> 01:09:17,924 +see-through it a little bit to what's behind. +这样的话一定很酷。 + +1609 +01:09:17,926 --> 01:09:22,228 +Wouldn't that be kind of more iPhone-ish and kind of iOS-y. +这样的话看起来更想 iOS 自带的程序。 + +1610 +01:09:22,230 --> 01:09:22,961 +So let's do that. +好,我们继续来做。 + +1611 +01:09:22,963 --> 01:09:24,963 +That's trivial to do that. +这些都是些常用的做法。 + +1612 +01:09:24,965 --> 01:09:27,365 +Let's just go into our storyboard and +我们先去到我们的 storyboard ,然后到 + +1613 +01:09:27,367 --> 01:09:30,768 +have our view up here, our little. +我们的视图这里,我们这个 + +1614 +01:09:31,837 --> 01:09:34,037 +Waypoint editing view be transparent. +waypoint 编辑视图是透明的。 + +1615 +01:09:34,039 --> 01:09:36,506 +So I'm just going to select this thing. +我们先选中它, + +1616 +01:09:36,508 --> 01:09:38,875 +Instead of its background being white right here, +然后你可以看到它的背景色变为了白色。 + +1617 +01:09:38,877 --> 01:09:42,745 +I'm going to set it to be clear, okay? +我将把它设置为 clear ,可以? + +1618 +01:09:42,747 --> 01:09:44,046 +So that's going to fix that. +这样就可以修复我们前面的问题了。 + +1619 +01:09:44,048 --> 01:09:45,447 +So let's go see what that looks like. +好,那让我们看下效果如何。 + +1620 +01:10:00,129 --> 01:10:05,265 +All right, and click Edit, okay? +好的,点击编辑,怎么样? + +1621 +01:10:05,267 --> 01:10:06,656 +So you can see, +看到了吧, + +1622 +01:10:06,657 --> 01:10:08,046 +I don't know how well you can see it in that. +我想你们之前肯定没有见过这么好的吧。 + +1623 +01:10:08,047 --> 01:10:09,436 +It might be washed out there, but I can, actually, see, +这里可以看到背后的,是的,你看 + +1624 +01:10:09,438 --> 01:10:15,274 +kind of, a blurred mountains there, scenery behind, okay? +一座山在这里,在这个风景点后面,对吧? + +1625 +01:10:15,276 --> 01:10:17,209 +And it, also, just kinda looks better, +是的,这样看起更好点, + +1626 +01:10:17,211 --> 01:10:19,811 +the text fields stand out a little more. +这样 text field 也显得明显了。 + +1627 +01:10:19,813 --> 01:10:21,946 +It's all, just looks a lot better. +这样就看起来更好了。 + +1628 +01:10:21,948 --> 01:10:26,083 +Okay, now, there's only problem with all of this, +好,现在就只剩下一个问题了, + +1629 +01:10:26,085 --> 01:10:28,352 +which is the iPhone. +就是在 iPhone 下的展示效果。 + +1630 +01:10:28,354 --> 01:10:29,903 +Okay? +对吧? + +1631 +01:10:29,904 --> 01:10:31,453 +Let's see what this looks like on iPhone. +让我们看看在 iPhone 下效果到底如何。 + +1632 +01:10:33,324 --> 01:10:34,724 +Here it is. +这里, + +1633 +01:10:34,726 --> 01:10:36,358 +Nice. Drop one. +好的,选这个。 + +1634 +01:10:36,360 --> 01:10:37,726 +Ooh, yeah, edit. +哦,好的,编辑。 + +1635 +01:10:37,728 --> 01:10:39,160 +Look, yeah. +看! + +1636 +01:10:39,162 --> 01:10:40,345 +Okay. +好的。 + +1637 +01:10:40,346 --> 01:10:41,529 +So that looked absolutely terrible. +这个看起来是太糟糕了。 + +1638 +01:10:41,531 --> 01:10:44,331 +We lost our done button because we took it out of that +因为我们把我们的 done 按钮移出了 navigation controller, + +1639 +01:10:44,333 --> 01:10:45,833 +navigation controller. +我们没有看到我们的 done 按钮。 + +1640 +01:10:45,835 --> 01:10:47,868 +And it's got this background, +所以只看到了是背景, + +1641 +01:10:47,870 --> 01:10:49,969 +just black, there's nothing there. +就是一个黑色的,然后没有任何东西。 + +1642 +01:10:49,971 --> 01:10:51,804 +What's going on here? +那我们下面该怎么做? + +1643 +01:10:51,805 --> 01:10:53,638 +Well, let's try to fix this iPhone thing. +好,让我们来继续修复这个问题。 + +1644 +01:10:53,641 --> 01:10:57,376 +One thing we can fix is that black. +首先,我们得修复这个只看到黑色背景这个问题。 + +1645 +01:10:57,378 --> 01:10:59,411 +The reason that that's coming black, +出现这个问题的原因是,默认的 modal 展示的样式 + +1646 +01:10:59,413 --> 01:11:02,681 +is because the default modal presentation style +都是全屏,也就是说, + +1647 +01:11:02,683 --> 01:11:06,818 +is full screen, which means, take over the whole screen. +会占据整个屏幕的显示区域。 + +1648 +01:11:06,820 --> 01:11:09,754 +And it expects you to draw in the whole screen. +也就是说它希望你以全屏幕作为显示区域。 + +1649 +01:11:09,756 --> 01:11:11,555 +So it's just leaving that area black, +所以这里只保留了一个黑色区域。 + +1650 +01:11:11,557 --> 01:11:13,590 +it's expecting you're gonna draw in that. +它就是希望你可以在这里进行绘图。 + +1651 +01:11:13,592 --> 01:11:17,027 +There's another kind of style which is over full-screen, +这里还有另外一个样式叫做 over full-screen 。 + +1652 +01:11:17,029 --> 01:11:21,597 +which just means draw on top of whatever is behind. +意思就是在背景层的上面进行绘图。 + +1653 +01:11:21,599 --> 01:11:22,998 +So anything that shows through, +所以当前显示的任何东西,你都会看到 + +1654 +01:11:23,000 --> 01:11:24,700 +you'll see what's behind. +它们被显示到下面。 + +1655 +01:11:24,701 --> 01:11:26,401 +And this is what alerts are using, things like that. +这种方式是 alert 用的方式, + +1656 +01:11:26,403 --> 01:11:29,237 +Even the pop-over was using that, it was blurring it, but +如果 pop-over 用这种方式,就会模糊掉下面的内容,但是 + +1657 +01:11:29,239 --> 01:11:30,238 +it was still doing that. +它也会把内容置于下层。 + +1658 +01:11:30,240 --> 01:11:32,606 +So how do we get that to happen? +那我们该如何做呢? + +1659 +01:11:32,608 --> 01:11:33,874 +Okay, well, to do that, +好,我们是可以这样做, + +1660 +01:11:33,876 --> 01:11:36,343 +we actually need to use the pop-over's delegate, +我们需要使用 pop-over 的 delegate , + +1661 +01:11:36,345 --> 01:11:37,377 +which we did before. +我们之前也过的。 + +1662 +01:11:37,379 --> 01:11:40,046 +So I'm going to set the pop-over +我们这里把 pop-over controller的 delegate + +1663 +01:11:40,048 --> 01:11:44,183 +controller's delegate here to be myself, okay? +设置为我们的自己,对吧? + +1664 +01:11:44,185 --> 01:11:49,388 +That means I need to go up here, and say, that I am a,. +这就意味着,我们需要在这里写上, + +1665 +01:11:49,390 --> 01:11:52,790 +UI PopoverPresentationController- +UI PopoverPresentationController- + +1666 +01:11:52,792 --> 01:11:54,759 +Delegate. +Delegate 。 + +1667 +01:11:54,760 --> 01:11:56,727 +Be careful here not to say, UIPopover Controller Delegate, +注意这里,不是写 UIPopover Controller Delegate + +1668 +01:11:56,729 --> 01:11:58,429 +It's PresentationController. +这里是 PresentationController。 + +1669 +01:11:58,431 --> 01:11:59,730 +That thing is old, okay? +之前那个已经是旧的了。 + +1670 +01:11:59,732 --> 01:12:01,564 +It's deprecated even. +已经被标记为过期了。 + +1671 +01:12:01,566 --> 01:12:02,932 +So, it's this one you want, the long one, +所以这里你就需要用这个长的, + +1672 +01:12:02,934 --> 01:12:05,401 +PopoverPresentationController- Delegate. +PopoverPresentationController- Delegate。 + +1673 +01:12:05,403 --> 01:12:06,869 +And once I'm the delegate, +一旦我是作为 delegate 。 + +1674 +01:12:06,871 --> 01:12:11,439 +now I can control that adaptation behavior. +我就可以控制这个 adaptation 的行为。 + +1675 +01:12:11,441 --> 01:12:14,042 +So why is that thing showing up +这就是当它目前显示的方式是modal, + +1676 +01:12:14,044 --> 01:12:16,644 +modal like that when we have it to be a popover? +而需要展示为popover的时候, + +1677 +01:12:16,646 --> 01:12:18,045 +Okay, we changed it to be a popover, +我们就可以直接通过 delegate 把它改为 popover 的原因。 + +1678 +01:12:18,047 --> 01:12:19,346 +why the heck is it showing up modal? +为什么就可以展示为 modal ? + +1679 +01:12:19,348 --> 01:12:21,614 +Well, that's because of this adaptation, +对,就是因为这个 adaptation , + +1680 +01:12:21,616 --> 01:12:24,417 +okay, where the system is adapting to the fact that you +好吧,就是这里系统可以根据实际的情况进行适配,你在 iPhone 不应该用 + +1681 +01:12:24,419 --> 01:12:27,787 +don't usually show popovers on the phone. +popovers 进行展示。 + +1682 +01:12:27,789 --> 01:12:29,121 +You show things full-screen modal. +你应该使用全屏幕的 modal 方式展示。 + +1683 +01:12:29,123 --> 01:12:30,288 +So it's adapting. +这就是适配。 + +1684 +01:12:30,290 --> 01:12:32,724 +So now that we're the delegate, let's go ahead and +现在我们是 delegate ,我们就可以为展示的这个 controller + +1685 +01:12:32,726 --> 01:12:35,126 +implement the adaptive presentations style for +实现这个适配的展示样式 + +1686 +01:12:35,128 --> 01:12:37,695 +presentation controller, delegate method. +的代理方法。 + +1687 +01:12:37,697 --> 01:12:40,297 +Thank God for escape completion there. +谢天谢地,我们总算快做完了。 + +1688 +01:12:40,299 --> 01:12:43,166 +And all we need to do here is return the style, so +我们只是需要在这里返回 style,这里我们将要 + +1689 +01:12:43,168 --> 01:12:46,169 +the modal presentation style I'm gonna return, +返回 modal presentation style 。 + +1690 +01:12:46,171 --> 01:12:49,105 +instead of fullscreen, is, overFullscreen. +将 fullscreen 替换为 overFullscreen。 + +1691 +01:12:49,107 --> 01:12:55,144 +Oops, not over [INAUDIBLE] overFullscreen. +哦,不对, 不是 overFullscreen 。 + +1692 +01:12:55,146 --> 01:12:59,014 +Okay, so let's see what that did. +好的,让我们看下我们的成果。 + +1693 +01:12:59,016 --> 01:13:01,149 +It's going to make it a little better, not a lot better, +将会有一点改进,不过不是很大的改进。 + +1694 +01:13:01,151 --> 01:13:02,283 +but a little better, okay? +总是有点改进,对吧? + +1695 +01:13:03,453 --> 01:13:04,451 +Here we go. Now, +好,我们继续,现在 + +1696 +01:13:04,453 --> 01:13:07,621 +at least we don't have the black, okay? +至少我们看到的不是一片黑了,对吧? + +1697 +01:13:07,623 --> 01:13:10,990 +So we can see through, still not so hot. +我们能看到,还不是我们想看到的。 + +1698 +01:13:12,093 --> 01:13:14,093 +We need that done button back for one thing, +我们需要的一个 done 按钮,可以返回, + +1699 +01:13:14,095 --> 01:13:16,428 +without that done button we're done, okay? +没有这个 done 按钮,我们就没法返回了,对吧? + +1700 +01:13:16,430 --> 01:13:17,929 +So let's get that done button back. +好,现在让我们把这个 done 按钮“弄”回来。 + +1701 +01:13:17,931 --> 01:13:21,232 +And I'm going to do that by implementing another pop over +我会通过实现另外一个 pop over 的代理方法 + +1702 +01:13:21,234 --> 01:13:24,835 +delegate method here which is called, I don't remember what +我现在具体记不得它的名字 + +1703 +01:13:24,837 --> 01:13:27,904 +the thing is even called, oh yes, presentation. +哦,对对,presentation. + +1704 +01:13:29,541 --> 01:13:31,841 +It's this one right here, +就是这个, + +1705 +01:13:31,843 --> 01:13:36,245 +viewControllerForAdapterPresentationStyle, okay? +viewControllerForAdapterPresentationStyle。 + +1706 +01:13:36,247 --> 01:13:39,881 +So this one right here is saying give me a view +这就是我们的视图控制器需要对视图进行 + +1707 +01:13:39,883 --> 01:13:46,254 +controller to display this thing when I adapt, okay? +适配所需要的方法,对吧? + +1708 +01:13:46,256 --> 01:13:47,588 +So what I'm going to do is, +这里我就需要, + +1709 +01:13:47,590 --> 01:13:50,391 +I'm going to give it a navigation controller, and +给它一个 navigation controller ,然后说用 + +1710 +01:13:50,393 --> 01:13:51,825 +tell it to use that instead. +这个来替换 + +1711 +01:13:51,827 --> 01:13:56,129 +So I'm just gonna say return UINavigationController. +所以这里是要写返回 UINavigationController。 + +1712 +01:13:56,131 --> 01:13:58,531 +The root view of the navigation controller wants to +这个 navigation controller 的 根视图(root view) + +1713 +01:13:58,533 --> 01:14:01,600 +be the thing I'm presenting, which I can get from +就是要展示的控制器,我们可以通过传给我们的参数 + +1714 +01:14:01,602 --> 01:14:04,670 +this presentation controller argument that's passed to me. +presentation controller 来获得。 + +1715 +01:14:04,672 --> 01:14:08,039 +That's just controller.presentedViewContr- +只要写 controller.presentedViewController + +1716 +01:14:08,041 --> 01:14:08,639 +oller. +就可以来 + +1717 +01:14:08,641 --> 01:14:12,876 +ViewController, okay? +对吧? + +1718 +01:14:12,878 --> 01:14:14,310 +So that's it. +这样就好了。 + +1719 +01:14:14,312 --> 01:14:20,883 +So let's see what happens now. +让我们看看现在的情况如何。 + +1720 +01:14:20,885 --> 01:14:24,219 +All right, we're here, we go here, we go here, +好,我们在这里,然后继续, + +1721 +01:14:24,221 --> 01:14:26,071 +oh much better. +哦,比之前好多了。 + +1722 +01:14:26,072 --> 01:14:27,922 +Now we have done, it still kind of looks terrible, but +现在我们有了 done 按钮,但看起来样子不太好,但至少我们 + +1723 +01:14:27,925 --> 01:14:29,641 +we have done. +已经有了。 + +1724 +01:14:29,642 --> 01:14:31,358 +So we can say done, oh, excellent, okay. +我们可以说搞定了,太好了。 + +1725 +01:14:31,361 --> 01:14:34,762 +So now, what are we gonna do to fix this see-through thing? +那么接下来,我们该怎么实现可以透过 pop-over 看到下面内容? + +1726 +01:14:34,764 --> 01:14:37,465 +Well, I could just make it white again, +好,我们可以先让它变成白色先, + +1727 +01:14:37,467 --> 01:14:40,901 +because now I'm returning the thing here, that view for +因为这里我们返回的内容,这个视图时 + +1728 +01:14:40,903 --> 01:14:42,235 +controller for adapter present thing. +适配后的控制器的视图。 + +1729 +01:14:42,237 --> 01:14:44,004 +I'm returning the whole thing, I can do anything I want. +我将返回全部内容,这样我就可以做任何我想做的。 + +1730 +01:14:44,006 --> 01:14:45,738 +But what I'm gonna use this to take advantage of is use +这里我准备先利用下这个机会给你们展示一下 + +1731 +01:14:45,740 --> 01:14:49,141 +this chance to show you visual effects like blur. +各种视觉效果的使用,比如 blur 效果。 + +1732 +01:14:49,143 --> 01:14:51,710 +Because we want really the same thing we had on the iPad, +因为这里我们也有一个刚刚在 iPad 上实现的效果模糊效果, + +1733 +01:14:51,712 --> 01:14:54,980 +where the pop-over comes up and it's kind of, you can see +就是当 pop-over 出来之后, + +1734 +01:14:54,982 --> 01:14:56,715 +the background through, but it's a little blurred. +你可以看到它下面的内容,但是稍微有点模糊的 + +1735 +01:14:56,717 --> 01:14:59,017 +We're going to do the same thing here, okay? +这里其实我们是做的同样一件事,对吧? + +1736 +01:14:59,019 --> 01:15:01,419 +It's going to come up, it's going to be white, but +当它出现的时候,它会变成白色, + +1737 +01:15:01,421 --> 01:15:03,854 +a little blur we can see what's in the background. +但我们可以看到它的背景是稍微有点模糊。 + + +1738 +01:15:04,990 --> 01:15:06,856 +So how do we do that? +我们该怎么做呢? + +1739 +01:15:06,858 --> 01:15:08,691 +To do that, we, okay, +这么做,来吧。 + +1740 +01:15:08,693 --> 01:15:12,028 +the way the visual effects work is very simple. +设置 visual effects 的方法非常简单。 + +1741 +01:15:12,030 --> 01:15:14,863 +It's just a view, okay, a visual effect view, +只需要这里,对一个 view , 对 ,visual effect view + +1742 +01:15:14,865 --> 01:15:19,434 +and that view looks what's behinds it, what's behind it, +然后这个视图就看起来是放在后面的,看起来 + +1743 +01:15:19,436 --> 01:15:23,104 +looks at what is behind it, and blurs it, and +像在后面的,然后是模糊的, + +1744 +01:15:23,106 --> 01:15:25,739 +then draws that as itself. +它也是自己负责绘制自己的。 + +1745 +01:15:25,741 --> 01:15:27,941 +It's as simple as that, okay? +这个够简单了吧,对吧? + +1746 +01:15:27,943 --> 01:15:31,344 +It's just, looks what behind you in the view hierarchy, +这里,可以看到在你的 view hierarchy 来看到在后面的, + +1747 +01:15:31,346 --> 01:15:34,047 +even if that's other views, or I don't care what it is, +甚至是有其他视图,都不需要在乎它们, + +1748 +01:15:34,049 --> 01:15:37,983 +it looks at it, creates white or even a dark color and +只是需要设置为白色或是黑色,然后模糊掉, + +1749 +01:15:37,985 --> 01:15:40,586 +then blurs it, and now that's what it draws. +现在它们就可以自己绘制自己了。 + +1750 +01:15:40,588 --> 01:15:43,221 +So all we need to do to make this blur happen is +所以我们需要在 navigation controller 的 view hierarchy + +1751 +01:15:43,223 --> 01:15:47,058 +put a visual effects view right at the top +后面的内容都绘制好之后,然后最顶层的 + +1752 +01:15:47,060 --> 01:15:50,228 +of the navigation controller's view hierarchy +地方增加这个 visual effects ,将显示区域 + +1753 +01:15:50,230 --> 01:15:52,430 +behind everything that it draws. +模糊化。 + +1754 +01:15:52,432 --> 01:15:53,664 +Okay, right at the top. +好,在最顶部。 + +1755 +01:15:53,666 --> 01:15:55,265 +And we know how to insert something at the top of +我们是知道我们在 view hierarchy 中是从顶部插入 + +1756 +01:15:55,267 --> 01:15:56,466 +the view hierarchy, right? +内容的,对吧? + +1757 +01:15:56,468 --> 01:15:59,769 +We just put it at index zero in the subviews list. +我只需要在 subviews 列表中的索引为0的地方处理就可以了。 + +1758 +01:15:59,771 --> 01:16:01,937 +It'll be right in the back. +就刚好是最后面的。 + +1759 +01:16:01,939 --> 01:16:03,639 +Okay, and everything else will be in front. +然后其他内容都是在前面的。 + +1760 +01:16:03,641 --> 01:16:05,474 +Now, if I put it right in the back of the navigation +然后我把它放回到 navigation controller 里面, + +1761 +01:16:05,476 --> 01:16:08,309 +control, the thing that's behind the visual effect view +在它后面显示 visual effect 的视图 + +1762 +01:16:08,311 --> 01:16:10,311 +is gonna be that map view. +就是 map view 。 + +1763 +01:16:10,313 --> 01:16:11,779 +Because it's clear and so, +因为这个很清楚, + +1764 +01:16:11,781 --> 01:16:13,681 +we look back and whoa, there's map view there. +我们看下一下,这里有一个 map view 。 + +1765 +01:16:13,683 --> 01:16:16,483 +So it's gonna blur that, that's exactly what we want. +它会被模糊化,这就是我们希望的。 + +1766 +01:16:16,485 --> 01:16:21,354 +All right, so to do this we just need to say I'm gonna +所以,这里我们就是需要 + +1767 +01:16:21,356 --> 01:16:24,156 +let nav con equal this. +让 nav con 等于这里。 + +1768 +01:16:25,459 --> 01:16:27,692 +Okay, so there's your navigation controller. +这里已经有了 navigation controller 。 + +1769 +01:16:27,694 --> 01:16:32,596 +And then I'm gonna say let a visualEffectView equal +这里我接着让 visualEffectView 等于 + +1770 +01:16:32,598 --> 01:16:34,898 +UIVisualEffectView. +UIVisualEffectView。 + +1771 +01:16:34,900 --> 01:16:38,001 +Okay, that's this view that does what I was talking about. +这个 view 就是我们前面刚刚说过的。 + +1772 +01:16:38,003 --> 01:16:40,070 +And it wants to know what effect you wanna apply. +它需要知道你要让它实现什么样的效果。 + +1773 +01:16:40,072 --> 01:16:43,839 +There's a couple of effects, vibrancy and blur. +这里有很多效果,比如 vibrancy 和 blur。 + +1774 +01:16:43,841 --> 01:16:45,207 +So we're gonna do blur. +这里我们需要的是 blur 。 + +1775 +01:16:45,209 --> 01:16:46,708 +So I want the blur effect. +我们要的是 blur effect 。 + +1776 +01:16:48,445 --> 01:16:53,114 +And the blur effect I want is with style, extra light. +对于blur effect 这个style ,我们还希望有 extra light。 + +1777 +01:16:53,116 --> 01:16:56,483 +So, extra light is a very light colored thing, +extra light 是一个指一个浅的颜色, + +1778 +01:16:56,485 --> 01:16:58,285 +almost white, with the blur in there. +和blur在一起,接近白色。 + +1779 +01:16:58,287 --> 01:17:01,888 +There's also dark and just light. +这里也有浅黑色的。 + +1780 +01:17:01,890 --> 01:17:05,525 +Then I'm going to set the visual effect views frame +我这里准备把 visual effect views的框架设置为 + +1781 +01:17:05,527 --> 01:17:09,362 +equal to the navCon's view.bounds. +navCon的视图的bounds(显示区域)。 + +1782 +01:17:09,364 --> 01:17:13,899 +So I want to totally fill the top level of the navigation +这是因为我想能够完全覆盖住整个 navigation + +1783 +01:17:13,901 --> 01:17:15,133 +controller. +controller 。 + +1784 +01:17:15,135 --> 01:17:18,302 +And then I'm just going to add this +然后我就把它加入到我的 navigation controller + +1785 +01:17:18,304 --> 01:17:21,872 +thing to the view hierarchy of my navigation controller. +这里的 view hierarchy 。 + +1786 +01:17:21,874 --> 01:17:26,743 +VisualEffectView, and I'm gonna put it at index zero. +我准备把这个 VisualEffectView 放倒索引值为0的位置。 + +1787 +01:17:26,745 --> 01:17:29,612 +Okay which means it's in the back of absolutely everything. + +1788 +01:17:29,614 --> 01:17:31,947 +And then I'm going to return the navigation controller. +然后我就可以返回 navigation controller 。 + +1789 +01:17:34,685 --> 01:17:40,355 +Okay, here we go, all right. +好,让我们看下效果吧。 + +1790 +01:17:40,357 --> 01:17:41,289 +Click. +点击 + +1791 +01:17:41,291 --> 01:17:42,223 +Boom. +咚 + +1792 +01:17:42,225 --> 01:17:43,357 +Edit. +编辑。 + +1793 +01:17:43,359 --> 01:17:43,957 +Blur. +模糊的。 + +1794 +01:17:45,327 --> 01:17:46,860 +So this looks pretty good. +看起来非常好。 + +1795 +01:17:46,861 --> 01:17:48,394 +This actually looks slightly better than being all white, +这里看起来比全都是白色的效果要好些了。 + +1796 +01:17:48,396 --> 01:17:51,330 +it kind of gives users a little bit of context to where +至少能够给用户一点信息就是他现在哪里。 + +1797 +01:17:51,332 --> 01:17:52,598 +they were. +至少能够给用户一点信息就是他现在哪里。 + +1798 +01:17:52,600 --> 01:17:54,266 +Still works perfectly fine here. +到现在我们做的都很好。 + +1799 +01:17:54,268 --> 01:18:01,606 +Our favorite golf course, it's under the snow, okay? +我最喜欢的 golf course ,it's under the snow ,对吧? + +1800 +01:18:01,608 --> 01:18:04,508 +Hit done, go here. +点击 done ,继续。 + +1801 +01:18:04,510 --> 01:18:05,743 +It's working. +运行的很好。 + +1802 +01:18:05,745 --> 01:18:08,211 +And just to make sure that we didn't break anything on +这里我们还需要确认我们在 iPad 上也还是像以前一样, + +1803 +01:18:08,213 --> 01:18:10,847 +the iPad, let's go run it over there one more time. +没有被影响到什么,那我就让我们再运行一次。 + +1804 +01:18:12,150 --> 01:18:13,849 +Now, we can't possibly have broken anything here, +好的,我们没有破坏任何东西。 + +1805 +01:18:13,851 --> 01:18:15,951 +because, famous last words, but [LAUGH] we can't, +有名的最后一句话,但是我们没有(幽默的的说法), + +1806 +01:18:15,953 --> 01:18:19,187 +because all we changed was the adaptive stuff. +因为我们所有的修改都是在适配后的内容上。 + +1807 +01:18:19,189 --> 01:18:20,789 +And on the iPad, it doesn't adapt, +而在 iPad 上,我们没有进行适配, + +1808 +01:18:20,791 --> 01:18:23,324 +because the iPad is regular in both width and +因为 iPad 是一个规则的宽度和高度, + +1809 +01:18:23,326 --> 01:18:28,162 +height, it never has to adapt to being in a compact space. +就不需要在对应压缩显示区域后的适配问题。 + +1810 +01:18:28,164 --> 01:18:29,329 +So here we go. +好,我们继续。 + +1811 +01:18:29,331 --> 01:18:29,963 +Click on here. +点击这里。 + +1812 +01:18:31,433 --> 01:18:32,598 +Bingo. +太棒了。 + +1813 +01:18:32,600 --> 01:18:34,400 +Okay, so that's it. +好的,就是这样。 + +1814 +01:18:34,402 --> 01:18:35,400 +Perfect timing. +时间刚刚好。 + +1815 +01:18:35,402 --> 01:18:36,801 +Almost. +差不多吧。 + +1816 +01:18:36,803 --> 01:18:39,537 +Next time, we will pick up with slides that tell you how +下次,我们将先通过幻灯片讲一些关于 + +1817 +01:18:39,539 --> 01:18:41,606 +to do the camera. +摄像头的内容。 + +1818 +01:18:41,607 --> 01:18:43,674 +And then we'll enhance our editor here to let you take +然后我们会继续增强我们编辑器的功能,让你能够通过 + +1819 +01:18:43,676 --> 01:18:45,176 +a picture. +它拍一张照片。 + +1820 +01:18:45,177 --> 01:18:46,677 +And we'll enhance our popover right here, +同时,我们也会增强我们的 popover 的功能。 + +1821 +01:18:46,679 --> 01:18:48,979 +to show the picture right in the pop-over, okay? +能够支持直接显示图片。 + +1822 +01:18:48,981 --> 01:18:50,647 +And then after that we'll talk a little bit about +在这之后,我们会再谈一些关于持久化的内容, + +1823 +01:18:50,649 --> 01:18:53,850 +persistence, and we'll save the image in the file system. +我们将会把图片保存我们的文件系统里。 + +1824 +01:18:53,852 --> 01:18:55,184 +Show you how to do that. +然后你们会知道该如何做到的。 + +1825 +01:18:55,186 --> 01:18:56,752 +Okay, thank you very much. +好的,非常感谢。 + +1826 +01:18:56,754 --> 01:18:58,520 +I'm here if you have any questions as usual. +和平时一样,如果你们有问题可以来问我。 + +1827 +01:19:00,023 --> 01:19:00,054 +>> For more, please visit us at stanford.edu. +想了解更多,请访问 standford.edu 。 diff --git a/subtitles/16. Camera, Persistence, and Embed Segues.srt b/subtitles/16. Camera, Persistence, and Embed Segues.srt new file mode 100644 index 0000000..120e38c --- /dev/null +++ b/subtitles/16. Camera, Persistence, and Embed Segues.srt @@ -0,0 +1,8973 @@ + 1 +00:00:00,001 --> 00:00:04,669 +[MUSIC] +音乐 + +2 +00:00:04,671 --> 00:00:07,638 +Stanford University. +斯坦福大学 + +3 +00:00:07,640 --> 00:00:13,210 +Okay well, welcome to lecture 16 of Stanford CS193p, +好的,欢迎来到斯坦福 CS193p 2015 冬季课程, + +4 +00:00:13,212 --> 00:00:15,178 +winter of 2015. +第16课。 + +5 +00:00:15,180 --> 00:00:16,680 +So today, +今天, + +6 +00:00:16,681 --> 00:00:18,181 +we're going to be talking about three major topics. +我们将要讲到三个主要的主题。 + +7 +00:00:18,183 --> 00:00:21,451 +One is the camera, how to basically take a picture with +第一个是 Camera,怎么样基本的使用相机拍照 + +8 +00:00:21,453 --> 00:00:23,853 +the camera or get video from the camera. +或者使用相机拍摄视频 + +9 +00:00:23,855 --> 00:00:27,823 +Then persistence which is an important topic about how to +接下来是 Persistence,一个重要的话题关于 + +10 +00:00:27,825 --> 00:00:30,625 +store stuff in the flash memory of your phone, +如何往你手机的内存中存储东西, + +11 +00:00:30,627 --> 00:00:33,194 +and a lot of you have already kind of dived into +很多同学已经钻研了这个 + +12 +00:00:33,196 --> 00:00:35,796 +this as part of your final project, but I'm just gonna +在他们的 Final Project 中,但是我仅仅只是 + +13 +00:00:35,798 --> 00:00:38,565 +kind of give you a tour of the various ways that can be done. +给你们介绍一下各种完成这个话题的方法。 + +14 +00:00:38,567 --> 00:00:41,968 +And then the last one is kind of an interesting segue. +最后一个话题是关于一个有趣的 Segue。 + +15 +00:00:41,970 --> 00:00:45,338 +I leave it for last because it's kind of requires you to +我把这个放在最后,因为这是一种需要你们 + +16 +00:00:45,340 --> 00:00:48,408 +be a little bit of a visual thinker, to see what's +有一点以一个视觉思考者的方式(Visual Thinker),来思考 + +17 +00:00:48,410 --> 00:00:51,977 +happening when we do it, but it's called an embed segue, +我们在使用这个 Segue 时发生了什么,这个被叫做 Embed Segue, + +18 +00:00:51,979 --> 00:00:54,546 +which is where we basically take one MVC. +这个基本上就是我们拿一个 MVC, + +19 +00:00:54,548 --> 00:00:59,284 +And we embed its view into another MVC's view hierarchy +然后我们把它的 View 嵌入到另一个 MVC 的 View 中去 + +20 +00:00:59,286 --> 00:01:01,085 +which is kind of fun. +挺有趣的。 + +21 +00:01:01,087 --> 00:01:04,255 +So let's dive in right in to the camera. +好,让我们直接开始进入 Camera + +22 +00:01:04,257 --> 00:01:06,390 +The camera is accessed via this file or +Camera 可通过这个文件或者说 + +23 +00:01:06,392 --> 00:01:09,092 +this class called UIImagePickerController. +这个被叫做 UIImagePickerController 的类来访问。 + +24 +00:01:09,094 --> 00:01:12,696 +It is a UIViewController, sub-class actually of +它是一个 UIViewController,我认为 + +25 +00:01:12,698 --> 00:01:15,231 +UINavigationController, I believe. +它实际上是 UINavigationController 的子类。 + +26 +00:01:15,233 --> 00:01:18,134 +And it's very simple to use. +并且使用起来很简单 + +27 +00:01:18,136 --> 00:01:19,868 +You really just configure it and +你只要配置好它然后 + +28 +00:01:19,870 --> 00:01:21,370 +then you put it up modally. +把它设置成 Modally。 + +29 +00:01:21,372 --> 00:01:22,654 +Okay? + +30 +00:01:22,655 --> 00:01:23,937 +So there's really nothing more to it than that. +真的没有其他要做的了。 + +31 +00:01:23,940 --> 00:01:26,574 +We learned about how to put things up modally last time +我们学习了怎样把东西设置成 Modally,在上次 + +32 +00:01:26,576 --> 00:01:28,175 +with presentViewController. +和 presentViewController 一起。 + +33 +00:01:28,177 --> 00:01:29,977 +That's all you're gonna have to do. +这就是我们要做的所有的事了。 + +34 +00:01:29,979 --> 00:01:32,779 +So, the process of using the UIImagePickerController +所以,使用 UIImagePickerController + +35 +00:01:32,781 --> 00:01:34,514 +to get something from the camera, +来从相机获得某些东西的过程, + +36 +00:01:34,516 --> 00:01:36,849 +is, you create it, and you set its delegate. +就是,你创建一个UIImagePickerController,然后设置它的委托。 + +37 +00:01:36,851 --> 00:01:39,285 +It won't do anything without its delegate, +如果没有委托它不能做任何事, + +38 +00:01:39,287 --> 00:01:40,819 +so you have to set its delegate. +所以你需要设置它的委托。 + +39 +00:01:40,821 --> 00:01:42,354 +Then you're gonna configure it, for you know? +然后你要配置它,比如说 + +40 +00:01:42,356 --> 00:01:44,356 +Do you want just still images or video, or +你只是想要图像或者视频 + +41 +00:01:44,358 --> 00:01:46,358 +that kind of stuff? +这些东西? + +42 +00:01:46,359 --> 00:01:48,359 +Do you want users to be able to edit the pictures they've +你想要用户能够编辑他们 + +43 +00:01:48,361 --> 00:01:49,727 +taken before +以前照的照片 + +44 +00:01:49,728 --> 00:01:51,094 +They import them into your app, etc. +他们导入以前的照片到你的 App,等等 + +45 +00:01:51,097 --> 00:01:53,764 +Then you just present it with presentViewController. +然你你通过 presentViewController 展示出来, + +46 +00:01:53,766 --> 00:01:57,034 +And then you're gonna respond to delegate methods that tell +接下来你将要对委托作出反映,委托告诉你 + +47 +00:01:57,036 --> 00:01:59,936 +you, okay, I took a photo, here's the image data, +我拍了一张照,这是图像的数据, + +48 +00:01:59,938 --> 00:02:02,972 +or the video, the URL of the video, that the user took. +或者是用户拍摄的视频,或者是视频的 URL + +49 +00:02:02,974 --> 00:02:06,342 +So that's pretty much it. +就是这么些。 + +50 +00:02:06,344 --> 00:02:09,028 +Each device. +每个设备, + +51 +00:02:09,029 --> 00:02:11,713 +Kinda has different hardware, although that's becoming less +各种不同的硬件,虽然这个话随着时间的流逝 + +52 +00:02:11,715 --> 00:02:13,815 +and less true as the years go by. +越来越不对了。 + +53 +00:02:13,817 --> 00:02:16,617 +It used to be that there were some iOS devices that didn't +那就是有一些 iOS 设备 + +54 +00:02:16,619 --> 00:02:17,918 +even have a camera at all. +根本就没有相机。 + +55 +00:02:17,920 --> 00:02:21,822 +But certainly there were early on iOS devices that could +不过现在有一些早期的 iOS 设备 + +56 +00:02:21,824 --> 00:02:25,559 +Do still images, but couldn't do video for example. +可以拍照但是不能拍摄视频。 + +57 +00:02:25,561 --> 00:02:29,763 +So as with all the hardware things, whether it's you know, +所以对于这些关于硬件的东西来说,不管是 + +58 +00:02:29,765 --> 00:02:33,599 +Core Motion or any of those things we always wanna ask and +CoreMotion 或者其他的,我们总是会先问问并且 + +59 +00:02:33,601 --> 00:02:35,334 +see what we can do first. +看看我们能干什么。 + +60 +00:02:35,336 --> 00:02:38,503 +So it's very easy for the ImagePickerController it has +这件事对 ImagePickerController 是非常简单的 + +61 +00:02:38,505 --> 00:02:41,573 +a class function called isSourceTypeAvailable +它有一个类方法叫做 isSourceTypeAvailable。 + +62 +00:02:41,575 --> 00:02:45,309 +And there's three different sources for images or +对图像和视频来说,有三个来源 + +63 +00:02:45,311 --> 00:02:47,378 +video to come into your app. +来进入你的 App + +64 +00:02:47,380 --> 00:02:49,246 +One is the camera, obviously. +第一个显然是相机。 + +65 +00:02:49,248 --> 00:02:51,581 +Another one is the saved photos album, +第二个是保存的图片专辑(Photos Album), + +66 +00:02:51,583 --> 00:02:53,916 +that's essentially the camera roll. +这个其实就是 Camera Roll。 + +67 +00:02:53,918 --> 00:02:56,285 +Right, things that they've taken with the camera. +没错,就是那些早就被相机拍下来的东西。 + +68 +00:02:56,287 --> 00:02:57,986 +And then there's the photo library, +最后是 Photo Library, + +69 +00:02:57,988 --> 00:03:00,522 +which is the same thing they see in the photos app, okay. +就是跟你在图片 App 里看到的那个是一个东西。 + +70 +00:03:00,524 --> 00:03:03,224 +So you can kinda pick which one of those things. +所以你可以选择一个来源 + +71 +00:03:03,226 --> 00:03:06,094 +You wanna get your image or video from and +来获得照片或者视频。 + +72 +00:03:06,096 --> 00:03:08,562 +they're a little bit different. +他们有一点点的不同。 + +73 +00:03:08,564 --> 00:03:10,764 +photo library and the saved photos album +Photo Library 和保存的图片专辑(photo album) + +74 +00:03:10,766 --> 00:03:12,666 +are treated pretty much exactly the same, but +基本上可以当作一样来对待 + +75 +00:03:12,668 --> 00:03:14,367 +the camera is a little bit different in how +不过相机在如何展示出方面有一点不同 + +76 +00:03:14,369 --> 00:03:16,703 +it's presented, so we'll talk about that in a moment. +所以让我们来讲一下。 + +77 +00:03:16,705 --> 00:03:20,272 +Once you know your source type then you're gonna say, +一旦你之道了来源的类型,然后你会问, + +78 +00:03:20,274 --> 00:03:23,742 +what are the available media types, image or video. +可用的媒体类型是什么?图片还是视频? + +79 +00:03:23,744 --> 00:03:25,561 +Or both. +或者两个都是。 + +80 +00:03:25,562 --> 00:03:27,379 +Now it's almost not even worth checking for image anymore. +现在你根本不值得去为图片检查。 + +81 +00:03:27,381 --> 00:03:29,614 +Because if you have a camera, it can get an image. +因为你现在的来源是相机,相机可以拍照。 + +82 +00:03:29,616 --> 00:03:32,516 +So, I think it'd probably be okay if you just never even +所以,我觉得这可能是可以的,如果你从不 + +83 +00:03:32,518 --> 00:03:35,185 +called this available media types for source type, +调用这个 availableMediaTypesForSourceType(Camera) 方法 + +84 +00:03:35,187 --> 00:03:36,953 +if you're trying to get. +如果你在试图获得 + +85 +00:03:36,955 --> 00:03:39,489 +An image, okay, because it's gonna be there. +一张图片,因为图片在那会有。 + +86 +00:03:39,491 --> 00:03:41,791 +But if you wanna get video, you definitely should call +不过如果你想要获得视频,你绝对应该调用 + +87 +00:03:41,793 --> 00:03:44,093 +this in case someone has an older iPhone that won't, +这个方法以防某人的旧 iPhone 不能, + +88 +00:03:44,095 --> 00:03:45,194 +doesn't capture video. +无法拍摄视频。 + +89 +00:03:45,196 --> 00:03:49,097 +Now these two types, the kuTTypeImage and +这两个类型,kuTTypeImage 和 + +90 +00:03:49,099 --> 00:03:53,634 +kuTTypeMovie, which are basically strings that +kuTTypeMovie,实际上就是能 + +91 +00:03:53,636 --> 00:03:56,570 +specify these two media types. +区分这两个媒体类型的字符串。 + +92 +00:03:56,572 --> 00:03:58,839 +Strangely, they come from this +奇怪的是,他们来自一个 + +93 +00:03:58,841 --> 00:04:02,009 +Framework that your otherwise never gonna import which is +除了这个情况外你永远不会想导入的 Framework + +94 +00:04:02,011 --> 00:04:04,077 +the mobile core services framework. +就是 MobileCoreServices Framework。 + +95 +00:04:04,079 --> 00:04:08,714 +So if you wanna use those two types right there or +所以如果你想使用这两个类型 + +96 +00:04:08,716 --> 00:04:12,818 +two constants KUTType images and movie. +或者两个常量 KUTTypeImages 和 KUTTypeMovie + + +97 +00:04:12,820 --> 00:04:14,886 +You need to import mobile core services. +你需要导入 MobileCoreServices。 + +98 +00:04:14,888 --> 00:04:16,288 +Okay? + +99 +00:04:16,289 --> 00:04:17,689 +I'm kinda lingering on this one because this is some +我讲这个讲了很久因为这是 + +100 +00:04:17,691 --> 00:04:19,102 +people forget. +一些人经常忘记这事。 + +101 +00:04:19,103 --> 00:04:20,514 +And they're just like what the heck? +然后他们会说一些比如 这是什么鬼错误? + +102 +00:04:20,515 --> 00:04:21,926 +Because if you search in the documentation it's kind of +因为如果你在文档中搜索, + +103 +00:04:21,928 --> 00:04:22,910 +hard to find. +这很难找到说 + +104 +00:04:22,911 --> 00:04:23,893 +That you're supposed to do this. +你应该导入 MobileCoreServices。 + +105 +00:04:23,896 --> 00:04:26,697 +Whatever. +不管怎么说 + +106 +00:04:26,698 --> 00:04:29,499 +So I made a special slide and emphasize it there for you. +所以我做了幻灯片来强调这个事情。 + +107 +00:04:29,501 --> 00:04:32,368 +You can obviously ask UIImagePickerController +你显然可以问 UIImagePickerController 要 + +108 +00:04:32,370 --> 00:04:34,103 +for more detail even than this. +比这更多的细节。 + +109 +00:04:34,105 --> 00:04:36,705 +Is there a camera and what kind of things can it take? +比如是不是摄像头?它可以拍摄什么,图片或者视频? + +110 +00:04:36,707 --> 00:04:40,442 +You can say, is there a front camera? +在比如那是不是前置摄像头? + +111 +00:04:40,444 --> 00:04:41,743 +Is there a rear camera? +是不是后置摄像头? + +112 +00:04:41,745 --> 00:04:44,178 +Which you might care if you have an app that's like selfie +你可能会关心这些如果你的 App + +113 +00:04:44,180 --> 00:04:45,529 +oriented. +可以拿来自拍。 + +114 +00:04:45,530 --> 00:04:46,879 +It might wanna know that there's a front camera. +它可能想知道有没有前置摄像头 + +115 +00:04:46,882 --> 00:04:48,415 +For that. +给它使用。 + +116 +00:04:48,417 --> 00:04:50,950 +And you can also tell whether a flash is available on that +而且你也可以知道闪光灯是否是可以用的 + +117 +00:04:50,952 --> 00:04:52,168 +device, etc. +在这台设备上,等等。 + +118 +00:04:52,169 --> 00:04:53,385 +So there's a bunch of class functions in +所以有一大堆类方法在 + +119 +00:04:53,388 --> 00:04:54,653 +UIImagePickerControllers. +UIImagePickerControllers 中。 + +120 +00:04:54,655 --> 00:04:57,556 +You can find out what's going on. +你能知道发生一些什么。 + +121 +00:04:57,558 --> 00:04:59,991 +So here's the code, typically, +这里是通常用来 + +122 +00:04:59,993 --> 00:05:02,460 +to prepare to present the picker. +准备展示 picker 的代码。 + +123 +00:05:02,462 --> 00:05:04,462 +You're going to create the picker. +你将会创建 picker。 + +124 +00:05:04,464 --> 00:05:06,030 +You're gonna set its delegate. +你将会设置它的委托。 + +125 +00:05:06,032 --> 00:05:08,098 +You're gonna ask if the camera is available. +你将会问它相机是否可用。 + +126 +00:05:08,100 --> 00:05:11,268 +If it is, you're gonna set the source type to be the camera. +如课可用,你就会设置来源为相机。 + +127 +00:05:11,270 --> 00:05:14,704 +Then you're gonna ask and see if, for example in this case, +比如在这个例子中 + +128 +00:05:14,706 --> 00:05:16,739 +I wanna take a movie with my camera. +我想要用相机拍摄视频 + +129 +00:05:16,741 --> 00:05:21,210 +So I'm gonna ask is that kuTTypeMovie available. +所以我问它 kuTTypeMovie 是否可用 + +130 +00:05:21,212 --> 00:05:25,513 +Now, this line of code right there, if availableTypes as +现在,在这的这行代码,if (availableTypes as + +131 +00:05:25,515 --> 00:05:29,283 +NSArray).containsObject(kuTTypeMovie). +NSArray).containsObject(kuTTypeMovie). + +132 +00:05:29,285 --> 00:05:30,584 +That's kind of a weird line of code. +真是一行奇怪的代码 + +133 +00:05:30,586 --> 00:05:31,518 +Really, it doesn't. +它真的没有 + +134 +00:05:31,520 --> 00:05:34,521 +Fit into the swift world very well. +很好的融入 Swift 这个世界 + +135 +00:05:34,523 --> 00:05:36,589 +You just do it. +你只要这样写就好了 + +136 +00:05:36,591 --> 00:05:41,093 +I's an old Objective-C based API. +这是一个 Objective-C 写的旧 API + +137 +00:05:41,095 --> 00:05:45,230 +And kuTTypeMovie is even kind of an older kind of string +而且 kuTTypeMovie 是一种比 + +138 +00:05:45,232 --> 00:05:46,865 +even than NSString. +NSString 还要古老的 String + +139 +00:05:46,867 --> 00:05:48,366 +And, so. +因此 + +140 +00:05:48,368 --> 00:05:50,067 +We kind of have to do this old style thing. +我们会写这种老旧风格的代码 + +141 +00:05:50,069 --> 00:05:53,804 +I'm sure probably somewhere they'll probably come up with +我能肯定可能某些地方以后会推出 + +142 +00:05:53,806 --> 00:05:57,441 +some new API for this whole camera thing that doesn't have +新的 API 来控制这些相机,没有这些 + +143 +00:05:57,443 --> 00:06:00,377 +this old stuff, but for now you have to do that. +老旧的东西,不过现在你只能这么写 + +144 +00:06:00,379 --> 00:06:02,979 +And then you just tell the picker the media types I want +然后你只要告诉 picker 媒体类型。 + +145 +00:06:02,981 --> 00:06:05,114 +the user to be able to take is just a movie, so +我想要用户只能拍视频,所以 + +146 +00:06:05,116 --> 00:06:07,883 +in this case they wouldn't be able to take a still image, +在这个列子里用户不能拍照片 + +147 +00:06:07,885 --> 00:06:10,218 +they would only be able to take a movie, if you. +他们只能拍视频 + +148 +00:06:10,220 --> 00:06:12,721 +Pass an array with just kuTTypeMovie. +只要你传入了一个只有 kuTTypeMovie 的数组 + +149 +00:06:12,723 --> 00:06:13,855 +So that's it. +好。 + +150 +00:06:13,857 --> 00:06:17,058 +You've configured the picker now, you just need to +你已经配置好了 picker,你现在只需要 + +151 +00:06:17,060 --> 00:06:19,993 +present it with that present view controller. +用 presentViewController 把它展示出来 + +152 +00:06:19,995 --> 00:06:22,129 +There are some other things you can kind of configure with +这里还有一些东西你可以配置 + +153 +00:06:22,131 --> 00:06:23,329 +the picker before you put it up. +在你展示 picker 之前 + +154 +00:06:23,331 --> 00:06:24,530 +One is editability. +第一个是 Editability + +155 +00:06:24,532 --> 00:06:26,999 +That's whether you're gonna allow the user to crop. +就是你是否允许用户去切割 + +156 +00:06:27,001 --> 00:06:29,134 +The image or edit the video. +图片或者编辑视频 + +157 +00:06:29,136 --> 00:06:32,237 +There's actually a video editor built in there +那实际上有一个内置的视频编辑器 + +158 +00:06:32,239 --> 00:06:36,007 +that they can edit the video before it returns to your app. +用户可以编辑视频在返回你的 App 之前 + +159 +00:06:36,009 --> 00:06:38,209 +You can also limit video capture, for example, +你也能限制视频的拍摄,比如 + +160 +00:06:38,211 --> 00:06:40,711 +to be lower resolution if you're just doing something +降低分辨率如果你在做 + +161 +00:06:40,713 --> 00:06:43,380 +that's gonna be in a little square somewhere in a webpage, +网页中的小方块 + +162 +00:06:43,382 --> 00:06:44,648 +you can go low resolution. +你可以设置低分辨率 + +163 +00:06:44,650 --> 00:06:45,882 +If it's something that. +如果有某些其他事 + +164 +00:06:45,884 --> 00:06:48,584 +Maybe it's going to be Airplayed to a high resolution +可能是 Airplay 到高分辨率 + +165 +00:06:48,586 --> 00:06:51,053 +device or something like that, and you can go for +的设备之类的东西,你可以 + +166 +00:06:51,055 --> 00:06:52,838 +a higher resolution. +设置高分辨率 + +167 +00:06:52,839 --> 00:06:54,622 +And of course high resolution, you're gonna use more memory. +当然,高分辨率会使用更多的内存 + +168 +00:06:54,625 --> 00:06:57,292 +Etcetera, etcetera, okay? +等等等等 + +169 +00:06:57,294 --> 00:07:00,395 +You present using view controller. +你使用 presentViewController 来展示 + +170 +00:07:00,397 --> 00:07:02,130 +Now, the thing about this is interesting is +一个关于这个的有趣的是 + +171 +00:07:02,132 --> 00:07:03,397 +when you're doing the camera. +当你在相机中时 + +172 +00:07:03,399 --> 00:07:04,898 +You're always gonna present view controller. +你总是会展示 View Controller + +173 +00:07:04,900 --> 00:07:08,101 +It's always gonna be take over the screen even on the iPad. +这总是会占据整个屏幕,就算在 iPad 上也一样 + +174 +00:07:08,103 --> 00:07:09,836 +So on the iPad when you do the camera, +所以当你在 iPad 上使用相机时 + +175 +00:07:09,838 --> 00:07:12,372 +you're gonna have this huge camera taking picture. +你总会得到这个巨大的相机用来拍照 + +176 +00:07:12,374 --> 00:07:13,339 +Okay? + +177 +00:07:13,341 --> 00:07:14,907 +The whole screen is gonna be the camera. +整个屏幕都会变成相机 + +178 +00:07:14,909 --> 00:07:16,141 +However, on the iPad, +然而,在 iPad 上 + +179 +00:07:16,143 --> 00:07:18,977 +if you're just looking at the photo library, okay? +如果你只是在 Photo Library 里查看 + +180 +00:07:18,979 --> 00:07:22,813 +Or the camera roll you want to present that in a pop over. +或者是 Camera Roll,你会展示在一个 Popover 中 + +181 +00:07:22,815 --> 00:07:24,915 +It's only gonna be fairly small, +它们只会有很小 + +182 +00:07:24,917 --> 00:07:27,784 +like the 320 wide by I don't know how high. +大概320宽乘我不知道多高 + +183 +00:07:27,786 --> 00:07:29,552 +600 or something. +600或者别的高度 + +184 +00:07:29,554 --> 00:07:32,655 +So that's really something you're supposed to put in +所以这是你应该放到 + +185 +00:07:32,657 --> 00:07:33,623 +a popover. +Popover 中的 + +186 +00:07:33,624 --> 00:07:34,590 +Now an iPhone, it doesn't matter. +在 iPhone 上,这没什么关系 + +187 +00:07:34,592 --> 00:07:36,859 +In both cases it's gonna be full modal, +两种情况都会是完整的 modal + +188 +00:07:36,861 --> 00:07:38,160 +take over the screen. +占据整个屏幕 + +189 +00:07:38,162 --> 00:07:40,229 +Okay? + +190 +00:07:40,230 --> 00:07:42,297 +Cuz it's just too big to put any other way on the iPhone. +因为用别的方法展示在 iPhone 上都来说都太大了 + +191 +00:07:42,299 --> 00:07:44,733 +Okay? + +192 +00:07:44,734 --> 00:07:47,168 +So, you present this thing, and it sits there on screen, +好,你展示了这个 picker, 它出现在屏幕上 + +193 +00:07:47,170 --> 00:07:50,404 +and then, when the user use this photo, okay, or +然后,用户使用了这张照片,或者 + +194 +00:07:50,406 --> 00:07:53,774 +use this video, this is gonna be called right here, +这个视频,这个会马上被调用 + +195 +00:07:53,776 --> 00:07:57,611 +this delegate method: image picker controller did finish +这个委托方法 image picker controller did finish + +196 +00:07:57,613 --> 00:08:01,447 +picking media with info, and with info dictionary there, +picking media with info, 那里的 info 字典 + +197 +00:08:01,449 --> 00:08:03,649 +has the results of what they did. +有他们做的结果 + +198 +00:08:03,651 --> 00:08:04,784 +And when you get there, +当你到这个时候 + +199 +00:08:04,785 --> 00:08:05,918 +we'll talk about what's in there in a minute. +过一会我们会讲到那有什么 + +200 +00:08:05,920 --> 00:08:09,187 +But when you get this and you get your image, or whatever, +不过当你得到这个并且得到你的图像或者别的什么 + +201 +00:08:09,189 --> 00:08:11,189 +then you wanna dismiss this thing. +然后你想让这个东西消失 + +202 +00:08:11,191 --> 00:08:13,191 +And I've kind of put here a line of code, +我在这放了一行代码 + +203 +00:08:13,193 --> 00:08:16,727 +presentingViewController.dismissViewControllerAnimated +presentingViewController.dismissViewControllerAnimated + +204 +00:08:16,729 --> 00:08:19,430 +Usually you're not putting the presentingViewCcontroller in +通常你不会把 presentingViewCcontroller 放在 + +205 +00:08:19,432 --> 00:08:21,898 +there, because you are the presentingViewController. +这里,因为你就是 presentingViewCcontroller + +206 +00:08:21,900 --> 00:08:23,833 +You just presented this thing. +你只是展示这个东西 + +207 +00:08:23,835 --> 00:08:25,335 +So you wouldn't need that part of it. +所以你不需要这个部分 + +208 +00:08:25,337 --> 00:08:27,503 +But I just wanted to emphasize that again, you dismiss by +不过我要再强调一遍,你消失靠 + +209 +00:08:27,505 --> 00:08:29,805 +sending a message through the presentingViewController, +通过 presentingViewController 发生一个消息 + +210 +00:08:29,807 --> 00:08:31,039 +which is probably gonna be you +这个 presentingViewController 可能是你 + +211 +00:08:31,041 --> 00:08:33,508 +And you'll see in the demo, we're gonna do this, +你将会在 Demo 中看到,我们会做这个 + +212 +00:08:33,510 --> 00:08:35,443 +and we're just gonna call dismiss directly. +并且我们会直接调用 dismiss + +213 +00:08:35,445 --> 00:08:38,079 +We don't have to say presentingViewController. +我们不会在前面加上 presentingViewController + +214 +00:08:38,081 --> 00:08:41,015 +The other delegate method you're gonna get of interest is +另一个你会感兴趣的委托方法是 + +215 +00:08:41,017 --> 00:08:43,183 +imagePickerControllerDidCancel +imagePickerControllerDidCancel + +216 +00:08:43,185 --> 00:08:44,584 +And that means they hit cancel. +这代表用户点击了取消 + +217 +00:08:44,586 --> 00:08:47,387 +So now you don't want to use the image that they were taking +所以现在你不想使用用户之前选择的那张图片了 + +218 +00:08:47,389 --> 00:08:48,587 +whatever + +219 +00:08:48,589 --> 00:08:51,990 +So in that case, you just need to dismiss, 'kay? +所以在这种情况下,你只需要消失 + +220 +00:08:51,992 --> 00:08:53,275 +So that's it. +就是这些 + +221 +00:08:53,276 --> 00:08:54,559 +Those are the two delegates methods you get. +你知道了这两个委托方法 + +222 +00:08:54,561 --> 00:08:57,162 +So let's look in that info dictionary, +好,让我们来看看那个 info 字典 + +223 +00:08:57,164 --> 00:08:58,629 +see what's in there. +看看里面有什么 + +224 +00:08:58,631 --> 00:08:59,930 +All kinds of stuff in there. +里面有各种各样的东西 + +225 +00:08:59,932 --> 00:09:01,498 +There is the image they took, obviously, +里面显然有用户拍摄的影像 + +226 +00:09:01,500 --> 00:09:02,799 +if they're taking a still image. +如果用户拍摄的是照片 + +227 +00:09:02,801 --> 00:09:04,167 +If you allowed editing, +如果你允许编辑 + +228 +00:09:04,169 --> 00:09:07,403 +then it's gonna have also the edited image like cropped, +那里面也将会有被编辑过的照片,比如被剪裁过的, + +229 +00:09:07,405 --> 00:09:10,072 +right, if they picked a different space of it. +如果用户给照片选择了一个不同的大小。 + +230 +00:09:10,074 --> 00:09:11,407 +Also if they cropped it, +如果用户剪裁了照片, + +231 +00:09:11,409 --> 00:09:14,710 +you'll get the rectangle that they chose inside the thing. +你会在这个字典里得到用户选择的矩形。 + +232 +00:09:14,712 --> 00:09:15,944 +If it's a video, +如果用户拍摄的是视频, + +233 +00:09:15,946 --> 00:09:19,147 +then you're gonna get this media URL, okay. +你就会得到这个叫做 MediaURL 的东西, + +234 +00:09:19,149 --> 00:09:21,982 +It's just gonna be URL to some file somewhere in your sandbox, +这个东西就是一个指向你的沙盒里某处的某些文件的 URL, + +235 +00:09:21,984 --> 00:09:25,052 +which I'll talk about sandbox later today. +我今天晚点会讲到沙盒 + +236 +00:09:25,054 --> 00:09:29,056 +It points to the video, 'kay? +它指向用户拍摄的视频 + +237 +00:09:29,058 --> 00:09:32,692 +When you get this image or video you might wanna save it. +当你得到这个照片或者视频你可能会想要保存它。 + +238 +00:09:32,694 --> 00:09:35,094 +We're gonna save it in our demo to a file in the file system +在我们的 Demo 里我们会把它保存到一个文件系统的文件里 + +239 +00:09:35,096 --> 00:09:37,697 +cuz I wanna show you how the file system works. +因为我想要给你展示文件系统是如何工作的。 + +240 +00:09:37,699 --> 00:09:39,064 +But really, most likely, +不过实际上,最最可能的, + +241 +00:09:39,066 --> 00:09:42,267 +you're gonna save it to the device's photo library, 'kay? +你将会把它保存到设备的照片库(Photo Library), + +242 +00:09:42,269 --> 00:09:44,936 +That probably if someone takes a photo and you wanna save it, +如果有人拍了一张照片,你想保存它, + +243 +00:09:44,938 --> 00:09:47,472 +that's likely where you would store, you might store in +照片库可能是你愿意保存它的地方,你可能会把它存到 + +244 +00:09:47,474 --> 00:09:49,740 +the file system but more like in the photo library, +文件系统中不过存到照片库中是更加可能的, + +245 +00:09:49,742 --> 00:09:52,376 +you do all that with this, I'm not gonna, for time reasons, cover that, +你使用这个 ALAssetsLibrary 来做这些事,因为时间原因我不会讲这个 + +246 +00:09:52,378 --> 00:09:54,545 +but, +但是 + +247 +00:09:54,546 --> 00:09:56,713 +You can check out this class ALAssetsLibrary, +你可以去查看这个 ALAssetsLibrary 类, + +248 +00:09:56,715 --> 00:09:59,849 +it's pretty straightforward how you access the assets library, +使用它来访问 AssetsLibrary 是非常直观的, + +249 +00:09:59,851 --> 00:10:02,418 +and you can put things in the photo library there. +并且你可以用它来往照片库中放东西。 + +250 +00:10:02,420 --> 00:10:04,070 +By the way, +顺便说一下, + +251 +00:10:04,071 --> 00:10:05,721 +the UIImagePickerController is kind of an old API, +UIImagePickerController 是一个老旧的 API, + +252 +00:10:05,723 --> 00:10:08,424 +it's a simple way to get things with the camera, +它是一个从相机获取东西的简单方法, + +253 +00:10:08,426 --> 00:10:10,926 +but there's a whole, much more powerful API called AVCaptureDevice, +不过有一个整得来说更强大的 API 叫做 AVCaptureDevice, + +254 +00:10:10,928 --> 00:10:13,995 +especially if you're getting video, +特别是在你获取视频的时候, + +255 +00:10:13,997 --> 00:10:15,763 +you might wanna check into that. +你可能会想要看看这个东西。 + +256 +00:10:15,765 --> 00:10:20,234 +It's kind of a more powerful way to do the stuff that +它是一种更强大的方法来做那些 + +257 +00:10:20,236 --> 00:10:22,669 +the UIImagePicker can do. +UIImagePicker 能做的事。 + +258 +00:10:22,671 --> 00:10:24,304 +So I'm not gonna cover it, but just so +所以我将不会涉及到这个,但是 + +259 +00:10:24,306 --> 00:10:26,423 +you know that it's there. +你们知道有这么个东西了。 + +260 +00:10:26,424 --> 00:10:28,541 +If you're just getting simple image, or just a simple clip of video, +如果你只是获取简单的照片,或者只是获取一段简单的视频 + +261 +00:10:28,543 --> 00:10:31,677 +you're okay with UIImagePickerController, +使用 UIImagePickerController 是可以的, + +262 +00:10:31,679 --> 00:10:34,513 +but if you wanna do more with that, then AVCaptureDevice. +不过如果你想要做的更多,使用 AVCaptureDevice。 + +263 +00:10:34,515 --> 00:10:37,349 +The last thing about your ImagePickingController is that +最后一件事关于 ImagePickingController 就是 + +264 +00:10:37,351 --> 00:10:39,084 +it does support putting overlays. +它支持放置透明层。 + +265 +00:10:39,086 --> 00:10:40,885 +So when that camera is on screen +所以当相机在屏幕上 + +266 +00:10:40,887 --> 00:10:42,853 +and the user's trying to take a picture, +并且用户准备拍一张照片时, + +267 +00:10:42,855 --> 00:10:45,956 +you can have your own controls on there, your own buttons +你可以有自己的控制器放在上面,你自己的按钮 + +268 +00:10:45,958 --> 00:10:48,258 +or whatever you want, using an overlay view. +或者任何你想要的,使用一个 Overlay View。 + +269 +00:10:48,260 --> 00:10:52,862 +The camera is always full screen, of course, so you need +当然相机总是全屏的,所以你需要 + +270 +00:10:52,864 --> 00:10:57,433 +to make sure that the view that you're putting overlay, +确保你放置的透明层, + +271 +00:10:57,435 --> 00:11:01,569 +you know, matches up with that screen's bounds, +你知道的,对齐屏幕的边界, + +272 +00:11:01,571 --> 00:11:05,906 +which you can get using the UIScreen classes bounds. +你能使用 UIScreen 类的 bounds 来获得。 + +273 +00:11:05,908 --> 00:11:10,143 +You might have your controls actually have the take a photo +你可能有让你的控制器有一个拍照 + +274 +00:11:10,145 --> 00:11:11,862 +button. +按钮。 + +275 +00:11:11,863 --> 00:11:13,580 +In which case you might wanna hide the Take a Photo button +在这种情况下你可能想要隐藏本来的拍照按钮 + +276 +00:11:13,582 --> 00:11:16,082 +that comes with the camera, and you can do that with +你可以这么做,让 + +277 +00:11:16,084 --> 00:11:17,950 +showsCameraControls equals false. +showsCameraControls 等于 false。 + +278 +00:11:17,952 --> 00:11:19,852 +And then it won't show its Take a Photo button, but +结果就是本来的拍照按钮不会显示了 + +279 +00:11:19,854 --> 00:11:21,420 +then you better provide one, +不过你最好再提供一个, + +280 +00:11:21,421 --> 00:11:22,987 +because you won't be able to take a picture otherwise. +否则的话你就不能拍照了。 + +281 +00:11:22,990 --> 00:11:26,891 +And then finally, you have this cameraViewTransform. +最后,你看到这个 cameraViewTransform。 + +282 +00:11:26,893 --> 00:11:30,128 +Normally, the camera maybe takes a square picture, or +通常相机也学能拍方的照片 + +283 +00:11:30,130 --> 00:11:33,531 +it might take its picture, in any case, if the aspect ratio +或者它可能,任何情况下,如果纵横比 + +284 +00:11:33,533 --> 00:11:37,034 +doesn't match the aspect ratio of the screen, but you might +和屏幕的纵横比不匹配,但是你可能 + +285 +00:11:37,036 --> 00:11:40,437 +want it to basically take a full, you know, basically take +想要它拍一个完整的,你知道的,就是拍 + +286 +00:11:40,439 --> 00:11:43,540 +the piece of it that is the aspect ratio of the screen. +一张纵横比和屏幕一样的照片。 + +287 +00:11:43,542 --> 00:11:46,309 +And you can do that by controlling the transform of +你可以做这个通过改变 + +288 +00:11:46,311 --> 00:11:47,309 +the cameraView. +相机视图。 + +289 +00:11:47,311 --> 00:11:49,878 +So AffineTransform there, remember, +有个 AffineTransform 在那, 记住 + +290 +00:11:49,880 --> 00:11:52,614 +AffineTransforms are scale, rotation. +AffineTransforms 是大小和旋转。 + +291 +00:11:52,616 --> 00:11:54,215 +In translation, so +在转变中, + +292 +00:11:54,217 --> 00:11:58,419 +you can do the scale there to scale it up if you want to. +所以你能在那里放大它如果你想的话。 + +293 +00:11:58,421 --> 00:12:00,487 +Let's do that, all right. +好的,让我们来试试 + +294 +00:12:00,489 --> 00:12:03,323 +All right, so that is the ImagePickerController, +好的,所以这就是 ImagePickerController, + +295 +00:12:03,325 --> 00:12:05,959 +let's go ahead and go back to our tracked demo and +让我们继续,回到我们的 Trax Demo + +296 +00:12:05,961 --> 00:12:08,494 +use the ImagePickerController to make it, so +使用ImagePickerController来实现它 + +297 +00:12:08,496 --> 00:12:11,464 +that if we have a waypoint, one of our custom waypoints +既然如此如果我们有waypoint,我们自定义waypoint的其中一个 + +298 +00:12:11,466 --> 00:12:13,932 +that we now can edit, that we can add a photo, +那么我们可以编辑它,然后把它添加进photo里 + +299 +00:12:13,934 --> 00:12:16,601 +just by taking a picture with the camera, okay? +仅仅通过使用手机的相机拍摄的照片 + +300 +00:12:16,603 --> 00:12:18,403 +That's what we're gonna do here. +这就是我们接下去要做的 + +301 +00:12:18,405 --> 00:12:20,038 +So let's go back to tracks. +所以让我们先回到Trax Demo + +302 +00:12:20,040 --> 00:12:22,340 +Here we are in tracks. +这是我们的Demo + +303 +00:12:22,342 --> 00:12:24,041 +Just remember where we are here. +先记住我们在哪儿 + +304 +00:12:24,043 --> 00:12:28,478 +We've built this thing that allows us to click on +我们已经建立的这些东西允许我们在地图上点击鼠标 + +305 +00:12:28,480 --> 00:12:31,948 +the map and then we can see the images. +然后我们可以看到图像 + +306 +00:12:31,950 --> 00:12:33,482 +And we can also drop a pin. +我们也可以添加一个大头针 + +307 +00:12:33,484 --> 00:12:36,518 +And when we click on the little detail disclosure, +当我们点击它时会有一些小细节展示出来 + +308 +00:12:36,520 --> 00:12:39,554 +we bring up this little new controller right here, +我们在这儿建立了一个新的controller + +309 +00:12:39,556 --> 00:12:41,923 +where we can edit the name and the info. +在这个controller中我们可以编辑name和info + +310 +00:12:41,925 --> 00:12:45,326 +So what I wanna do here is actually use this nice big +我接下来要做的实际上就是利用这个空间 + +311 +00:12:45,328 --> 00:12:48,729 +space we have at the bottom of our editor to show and +来让我们的编辑者展示和编辑照片 + +312 +00:12:48,731 --> 00:12:52,733 +edit the photo, okay that goes along with this waypoint. +这需要和这个waypoint一起 + +313 +00:12:52,735 --> 00:12:56,370 +Now, you might think the first thing I'm gonna do here is go +现在,你可以能会想,首先我会在这里 + +314 +00:12:56,372 --> 00:13:00,040 +down to my object palette and grab an image view, down here, +拖一个imageview放在这下面 + +315 +00:13:00,042 --> 00:13:02,442 +but I'm not gonna do that, 'kay, and +但我不准备这样做 + +316 +00:13:02,444 --> 00:13:05,845 +I'm gonna show you kind of a little bit of an interesting +我会向你展示一小部分 + +317 +00:13:05,847 --> 00:13:07,479 +trick about ImageViews. +关于imageView有趣的方法 + +318 +00:13:07,481 --> 00:13:11,583 +One thing about ImageViews is that they have an intrinsic +关于imageViews的第一个问题就是他们都有一个固有的size + +319 +00:13:11,585 --> 00:13:13,040 +size. + +320 +00:13:13,041 --> 00:13:14,496 +They're like labels. +类似于label + +321 +00:13:14,497 --> 00:13:15,952 +They want to be the size of their image, okay, for +出于auto layout的目的,他们会和他们的image的size + +322 +00:13:15,955 --> 00:13:17,488 +auto-layout purposes. +保持一致 + +323 +00:13:17,490 --> 00:13:19,456 +They strongly want to be that size. +他们会自动的变成这个size + +324 +00:13:19,458 --> 00:13:20,557 +You have a question, sorry. +[学生提问] + +325 +00:13:20,559 --> 00:13:21,491 +>> [INAUDIBLE]. +声音太小,听不清 + +326 +00:13:21,493 --> 00:13:22,392 +>> No, I'm not. +不,我不会 + +327 +00:13:22,394 --> 00:13:25,428 +Close. +关闭 + +328 +00:13:25,430 --> 00:13:27,830 +Let's see here, close. +我们看这儿 + +329 +00:13:27,832 --> 00:13:31,400 +[INAUDIBLE]. +声音太小,听不清 + +330 +00:13:31,402 --> 00:13:34,069 +So you guys are only gonna get it from, starting from here, +你们可以通过这样,从这里开始 + +331 +00:13:34,071 --> 00:13:35,837 +cuz I'm not gonna go back to the start. +因为我不想回到刚开始的地方 + +332 +00:13:35,839 --> 00:13:41,875 +I'm [INAUDIBLE] much. +声音太小,听不清 + +333 +00:13:41,877 --> 00:13:44,878 +Okay, so if I have auto-layout and I drag an image view in +好的,如果我使用auto layout接着我拖了一个image View进工程里 + +334 +00:13:44,880 --> 00:13:47,847 +there, then when I set the image, it's gonna wanna make +然后当我设置image,由于autolayout,这将会 + +335 +00:13:47,849 --> 00:13:50,683 +the auto layout huge because the image is gonna be big, +让image的size变大 + +336 +00:13:50,685 --> 00:13:53,252 +especially if I have a high resolution photo, so +尤其是在当我有一张分辨率很高的照片时 + +337 +00:13:53,254 --> 00:13:54,787 +I don't want that to happen, +我不希望这样的情况发生 + +338 +00:13:54,789 --> 00:13:57,723 +I want this image view to be the size I say it's gonna be. +我想要这个image View 的size能和我设置的一样 + +339 +00:13:57,725 --> 00:14:01,159 +Basically I want it to use whatever space is available +基本上我想要它的尺寸能在我设置的空间里 + +340 +00:14:01,161 --> 00:14:01,992 +and no more. +不会变大 + +341 +00:14:01,994 --> 00:14:04,661 +So, well, +那么 + +342 +00:14:04,662 --> 00:14:07,329 +kind of a cool way to do this is to use a generic UIView. +使用UIView这个类就是一种很酷的方法来解决这个问题 + +343 +00:14:07,332 --> 00:14:09,299 +So, instead of taking a UIView, +因此,我放一个UIView在这儿 + +344 +00:14:09,301 --> 00:14:11,801 +I'm gonna pull a generic UIView out here. +而不是放一个image View + +345 +00:14:11,803 --> 00:14:14,403 +Now, by the way, when you put a generic UIView out, +顺便说一句,当你拖了一个UIView出来 + +346 +00:14:14,405 --> 00:14:16,905 +sometimes it's hard to see what the heck is going on +有时这是很难在heck上看到的 + +347 +00:14:16,907 --> 00:14:18,440 +because it's white on white. +因为UIView是白色的,背景也是白色的 + +348 +00:14:18,442 --> 00:14:21,409 +So a lot of times when I do that, I think I might have +所以每当我要这样做时 + +349 +00:14:21,411 --> 00:14:24,612 +mentioned this before, I'll just set it to some other +我认为我要先暂时改变UIView的颜色来避免这个问题 + +350 +00:14:24,614 --> 00:14:27,915 +color for a moment, so that while I'm editing it here in +这样做了之后,当我在storyboard编辑它时 + +351 +00:14:27,917 --> 00:14:31,285 +the storyboard I can size it and set up its constraints and +我可以清楚地看到它的尺寸和设置它和其他控件的约束 + +352 +00:14:31,287 --> 00:14:34,454 +all that stuff, and I can kinda see what's going on. +这个过程都可以被很好地观察出来 + +353 +00:14:34,456 --> 00:14:39,025 +Okay, so let's put this thing in reasonable spots over here, +OK,让我们把这个UIView拉伸到合理的位置 + +354 +00:14:39,027 --> 00:14:42,995 +let's set some constraints for it, put some vertical +然后再为它添加一些约束 + +355 +00:14:42,997 --> 00:14:46,598 +spacing to the top there, trailing over to here, +为控件添加一些垂直的约束,拖到这儿 + +356 +00:14:46,600 --> 00:14:50,302 +this guy over to here, and I'll put this one down to +这个控件覆盖在这个范围上,接着我会为它 + +357 +00:14:50,304 --> 00:14:53,471 +the bottom, and we used to have a constraint +添加一个与底部空间的约束 + +358 +00:14:53,473 --> 00:14:57,208 +on this one to the bottom which we want to get rid of. +此时,我们需要放弃一个底部的约束 + +359 +00:14:57,210 --> 00:14:59,143 +Where is that? +这个约束在哪儿呢? + +360 +00:14:59,144 --> 00:15:01,077 +Bottom of space to bottom layup, it's this one. +Bottom of space to bottom layup,就是这个约束 + +361 +00:15:01,080 --> 00:15:03,447 +And, we could also, while we're here, +当然,我们也可以在这里设置 + +362 +00:15:03,449 --> 00:15:05,882 +make sure this is standard value, 'kay? +保证这个约束的值是标准的参数 + +363 +00:15:05,884 --> 00:15:07,116 +So that look's good. +看起来好像没什么问题 + +364 +00:15:07,118 --> 00:15:10,319 +This guy also standard value. +这个约束条件也要设置成标准的参数 + +365 +00:15:10,321 --> 00:15:12,388 +All right. +好的 + +366 +00:15:12,389 --> 00:15:14,456 +So, we've got this UIView in here, and really what we're +现在我们在这里设置好了一个UIView + +367 +00:15:14,458 --> 00:15:16,925 +gonna do is put the UIImageView inside of it. +然后我们的目的是要在里面放一个UIImageView + +368 +00:15:16,927 --> 00:15:19,327 +And I'm gonna manage it manually. +我要手动的操作它 + +369 +00:15:19,329 --> 00:15:22,363 +So I'm gonna size it to the right size +我先按照我在代码里写的那样 + +370 +00:15:22,365 --> 00:15:24,598 +that I want in code, okay? +设置好它正确地size + +371 +00:15:24,600 --> 00:15:27,501 +And that way, it'll never be trying to fight the auto +通过这样,这就不会因为和auto layout的 + +372 +00:15:27,503 --> 00:15:29,736 +layout system to make things really big, +系统冲突而造成控件变得非常的大 + +373 +00:15:29,738 --> 00:15:31,971 +and smash other things off the screen, or +然后把其他的控件挤出了屏幕 + +374 +00:15:31,973 --> 00:15:35,008 +make my popover really gigantic, or things like that. +或是使我的storyboard中得视图变得非常巨大 + +375 +00:15:35,010 --> 00:15:36,175 +'Kay? +理解了吗? + +376 +00:15:36,177 --> 00:15:38,544 +So, let's go ahead and do that. +所以让我们接下去做 + +377 +00:15:38,546 --> 00:15:39,678 +Gonna go over here. +把这两边收起 + +378 +00:15:39,680 --> 00:15:41,330 +I'm gonna go back, +回到代码上 + +379 +00:15:41,331 --> 00:15:42,981 +this is our editable waypoint view controller, +这是我们可编辑的waypoint view controller, + +380 +00:15:42,983 --> 00:15:45,049 +the view controller for this whole thing. +这个view controller 都是为了这个控件而写的 + +381 +00:15:45,051 --> 00:15:49,286 +So I'm gonna go down here, +我们看这个代码的下面几行 + +382 +00:15:49,288 --> 00:15:56,092 +let's create a new little mark for images. +先为这个images创建一个新的标记 + +383 +00:15:56,094 --> 00:15:57,410 +Okay. +好了 + +384 +00:15:57,411 --> 00:15:58,727 +So this'll be our image handling area right here. +这这区域将成为我们处理image的地方 + +385 +00:15:58,730 --> 00:16:02,064 +So I'm gonna control drag from this generic view out here. +所以我先按住control将这个巨大的view拖到代码里 + +386 +00:16:02,066 --> 00:16:06,134 +This is not my ImageView, this is my, what did I call this, +这不是我们创建的imageView,这是我。。。怎么说呢? + +387 +00:16:06,136 --> 00:16:07,035 +container? +容器? + +388 +00:16:07,037 --> 00:16:09,570 +Yeah, ImageViewContainer. +对!ImageView 的容器 + +389 +00:16:09,572 --> 00:16:13,307 +Okay, this is going to be just a generic UIView, see, +好了,这将会是以个巨大的UIView,看, + +390 +00:16:13,309 --> 00:16:15,342 +that contains my image view. +在它里面包含了我的image view + +391 +00:16:15,344 --> 00:16:19,579 +And so my image view is actually gonna be something +通过我写的代码,让我的image view + +392 +00:16:19,581 --> 00:16:21,881 +here that I create in code. +真正发挥它的作用 + +393 +00:16:21,883 --> 00:16:24,983 +I'll just say equals UIImageView, actually. +事实上,他就是一个UIImageView + +394 +00:16:24,985 --> 00:16:28,854 +Okay, so there's my image view and on my didSet here, +好的,这就是我将在didset方法里设置好的image view + +395 +00:16:28,856 --> 00:16:32,791 +when this thing is set, I'll go ahead and put that image +我要让image view显示在这个 + +396 +00:16:32,793 --> 00:16:36,994 +view into this thing by just saying image view controller, +image view container上面通过调用 + +397 +00:16:36,996 --> 00:16:38,028 +add sub view. +addSubvuew方法 + +398 +00:16:38,030 --> 00:16:42,766 +Image view, capitalize this for me. +imageView会调用这个方法 + +399 +00:16:42,768 --> 00:16:48,704 +Okay, so I basically just put that image view in there and. +好的,现在我基本上已经image View放到上面了 + +400 +00:16:48,706 --> 00:16:50,572 +Let's see, what's the problem here? +然后我们看看,这儿有什么问题? + +401 +00:16:50,574 --> 00:16:56,478 +It's, oh, imageViewContainer, yeah, thanks. +应该是imageViewContainer + +402 +00:16:56,480 --> 00:16:58,980 +ImageViewContainer, too used to typing in controller. +应该是imageViewContainer,太容易和controller混淆了 + +403 +00:16:58,982 --> 00:17:02,249 +Let's make this bigger, too, by the way, so +让我们这个放大一点 + +404 +00:17:02,251 --> 00:17:04,351 +we can see what we're doing. +看清楚我们写的代码 + +405 +00:17:04,353 --> 00:17:05,402 +Okay. +好的 + +406 +00:17:05,403 --> 00:17:06,452 +So, everyone see what I did there? +大家都看得清我写的吗? + +407 +00:17:06,455 --> 00:17:08,188 +I just created this generic UI View, +我在这里创建了一个UIView类 + +408 +00:17:08,190 --> 00:17:09,622 +I put the image view in there. +然后放一个imageView在上面 + +409 +00:17:09,624 --> 00:17:11,691 +I'm gonna have to manage the size myself, though. +这样做是因为我不想让imageView的size + +410 +00:17:11,693 --> 00:17:13,425 +I'm not gonna do autolayout in there, et cetera. +与autolayout系统发生冲突 + +411 +00:17:13,427 --> 00:17:16,228 +And, basically, I'm just gonna always set the image +然后,基本上,我就是希望当我设置图片时 + +412 +00:17:16,230 --> 00:17:19,164 +view inside to be the right aspect ratio for my image, but +它的像素是正确地 + +413 +00:17:19,166 --> 00:17:20,865 +no wider than my container view. +而且不会比这个容器还要宽 + +414 +00:17:20,867 --> 00:17:25,102 +And if my overall controller gives me no space for +如果我的容器没有办法放下我的image View + +415 +00:17:25,104 --> 00:17:29,006 +the view image, then I don't get it, okay? +那么我将无法得到它 + +416 +00:17:29,008 --> 00:17:31,808 +And also anytime my image changes I'm going to ask for +当然,当我在任何时间改变了image之后 + +417 +00:17:31,810 --> 00:17:34,544 +more space by resetting my preferred content size. +我会需要更大的空间来重新设置内容变成我想要的size + +418 +00:17:34,546 --> 00:17:36,879 +Remember preferred content size for the pop over? +记住,弹出框中内容的size会改变 + +419 +00:17:36,881 --> 00:17:38,113 +And so I'm going to ask for more space. +然后我会请求更大的空间 + +420 +00:17:38,115 --> 00:17:39,548 +I may or may not get it. +我可能会也可能不会得到它 + +421 +00:17:39,550 --> 00:17:42,817 +Cause pop over might be near the edge, but I'll ask for +因为弹出框可能会靠近容器的边界,但是我将请求空间 + +422 +00:17:42,819 --> 00:17:45,753 +it and we'll see that code in just a second here. +我们马上会看到这部分的代码 + +423 +00:17:45,755 --> 00:17:47,955 +Alright, so I got that. +好的,我先找到这里 + +424 +00:17:47,957 --> 00:17:50,224 +Here is some code. +这就是这一部分代码 + +425 +00:17:50,226 --> 00:17:52,859 +Let's put some code in here to do that. +我们在这里添加一些代码 + +426 +00:17:52,861 --> 00:17:55,995 +I have this extension that I added to my way point +我在我的way point controller中加入这个拓展 + +427 +00:17:55,997 --> 00:17:59,232 +controller and it has this method update image. +然后这个方法会更新image + +428 +00:17:59,234 --> 00:18:02,234 +Now update image, the reason I snippeted this in here instead +现在更新image,我在这里写了一小段而不是把这所有都在你看到之前 + +429 +00:18:02,236 --> 00:18:04,903 +of typing all into you've seen it all before, right? +打出来的原因你后面会知道 + +430 +00:18:04,905 --> 00:18:06,738 +I'm dispatching to another thread, +我使用GCD在另一个线程上进行 + +431 +00:18:06,740 --> 00:18:08,173 +I'm getting the image data. +我正在获取image的数据 + +432 +00:18:08,175 --> 00:18:11,209 +Here I'm getting the URL and getting the image. +在这里我得到了URl和image + +433 +00:18:11,211 --> 00:18:13,811 +I'm dispatching back to the main thread, +然后我调用这个方法回到主线程 + +434 +00:18:13,813 --> 00:18:16,213 +I'm setting the image in my ImageView so +此时设置imageView的image + +435 +00:18:16,215 --> 00:18:19,583 +this is just not worth our time to go through this again. +这样就不会让我们在这个过程上浪费时间 + +436 +00:18:19,585 --> 00:18:21,217 +We've done this two or three times. +我们已经这样做过很多次了 + +437 +00:18:21,219 --> 00:18:24,854 +But I am calling this function here makeRoomForImage, and +当时我将这个函数称作makeRoomForImage + +438 +00:18:24,856 --> 00:18:28,124 +all that makeRoomForImage is, it sees if the image is +然后,如果image比之前的 + +439 +00:18:28,126 --> 00:18:30,492 +any bigger than the last image we had. +image大 + +440 +00:18:30,494 --> 00:18:33,161 +And if so, it updates the preferred content size to +出现了这样的情况,这个函数会调整content的size + +441 +00:18:33,163 --> 00:18:35,130 +give it a little bit of a extra height. +给它一些额外的height + +442 +00:18:35,132 --> 00:18:37,732 +And this extra height might be negative if we just set +但是这样额外的height可能会有一些不好的效果 + +443 +00:18:37,734 --> 00:18:39,333 +the image to nil, for example, +比如说,当我们设置的image为nil + +444 +00:18:39,335 --> 00:18:41,235 +it might try to collapse it back down. +这可能会使content变小 + +445 +00:18:41,237 --> 00:18:44,604 +So again, this is just pertaining to what we prefer +所以,这些都是关于我们愿意让我们的content size + +446 +00:18:44,606 --> 00:18:46,706 +our overall content size to be. +的大小变为什么样 + +447 +00:18:46,708 --> 00:18:49,809 +And if we can get this space then my generic UI view that +倘若我们能够让这个空间比我们在 + +448 +00:18:49,811 --> 00:18:52,278 +contains my image is going to get bigger. +UIVew这个类中的image需要的更大 + +449 +00:18:52,280 --> 00:18:55,848 +And there's going to be more space for me and I can make my +那么我就有更多的空间让UIImageView更大 + +450 +00:18:55,850 --> 00:18:59,117 +UIImageView bigger, see more of my UIImageView. +在更大程度上的看到我的UIImageView + +451 +00:18:59,119 --> 00:18:59,751 +Okay? +懂我意思吗? + +452 +00:18:59,753 --> 00:19:01,403 +So that's it. +因此就是这样 + +453 +00:19:01,404 --> 00:19:03,054 +So we do need to update this image. +所以我们真的需要对这个image进行校正 + +454 +00:19:03,056 --> 00:19:04,855 +We'll do it in updateUI, right? +我们会在updataUI这个函数里处理这些问题 + +455 +00:19:04,857 --> 00:19:08,992 +So we have updateUI up here that updates the text fields, +我们在上面的updateUI函数中已经有了校正text fields的内容 + +456 +00:19:08,994 --> 00:19:12,962 +so we also wanna update our image there in that as well. +然后我们同样在这儿也需要有校正图片的 + +457 +00:19:12,964 --> 00:19:14,163 +Okay, so that's it. +好的,就是这样写 + +458 +00:19:14,165 --> 00:19:17,166 +That's how all that's necessary here to display +这就是为什么保证图片 + +459 +00:19:17,168 --> 00:19:19,234 +the image in my view controller and +在view中展示的size + +460 +00:19:19,236 --> 00:19:20,936 +keep it's size contained. +是非常有必要地 + +461 +00:19:20,938 --> 00:19:24,472 +So let's go ahead and kinda put a test image into our +我们接下去放一张测试的图片 + +462 +00:19:24,474 --> 00:19:27,842 +edited waypoints just to see if this is working. +在我们编辑waypoints的地方,看看它是怎么运作的 + +463 +00:19:27,844 --> 00:19:31,812 +So I'm gonna go back to GPXViewController and +因此,我会回到GPXViewController + +464 +00:19:31,814 --> 00:19:35,982 +where I add a waypoint here by dropping I'm gonna +然后在我addWaypoints的函数里 + +465 +00:19:35,984 --> 00:19:38,018 +say waypoint.links. +写下我叫做waypoint.links + +466 +00:19:38,020 --> 00:19:39,252 +Let's append. +让我们加上它 + +467 +00:19:39,254 --> 00:19:43,255 +I'm gonna append a new GPX link, +我想要添加一个新的GPX link + +468 +00:19:43,257 --> 00:19:49,294 +that's the thing that has the reference to a URL, +这个属性带有一个URL + +469 +00:19:49,296 --> 00:19:54,599 +to the image or whatever and so we'll do http +这个URL会连接到一张图片,然后会在 + +470 +00:19:54,601 --> 00:19:59,336 +CS193p Stanford images panorama. +这个URL上请求这张图片 + +471 +00:19:59,338 --> 00:20:01,071 +Okay. +好了 + +472 +00:20:01,072 --> 00:20:02,805 +I'm just picking one of the ones we had there at random. +我只是在我们有的图片中随机取了一张 + +473 +00:20:02,808 --> 00:20:06,009 +So, now this waypoint has a link, okay? +所以,这个waypoint有了一个link + +474 +00:20:06,011 --> 00:20:09,845 +Just like the waypoints that came out of that GPX file, +就像是从GPX 文件中出现的waypoint一样 + +475 +00:20:09,847 --> 00:20:11,447 +they have links also. +他们同样也有link的属性 + +476 +00:20:11,449 --> 00:20:14,816 +One other thing we're gonna need to do is over here in our +我们还要做的另一件事是在MKGPX中 + +477 +00:20:14,818 --> 00:20:17,519 +MK GPX right here, our EditableWaypoint. +关于EditableWaypoint这个类 + +478 +00:20:17,521 --> 00:20:19,554 +Right now, it gets its thumbnail and +现在,它可以获取到它的thumbnail和image URL + +479 +00:20:19,556 --> 00:20:22,223 +image URL by looking them up by this type thing. +通过这两个条件 + +480 +00:20:22,225 --> 00:20:23,991 +Thumbnail type, large type. +thumbnail的类型中的large类型 + +481 +00:20:23,993 --> 00:20:28,028 +And just for the purpose of the demo, I'm gonna make it +然后仅仅是为了我们demo的目的 + +482 +00:20:28,030 --> 00:20:31,898 +just return the first link in its link list of links. +我让让它返回在以列表形式展示的link中的第一条link + +483 +00:20:31,900 --> 00:20:38,237 +So let's go down here and just say return links.first.URL. +所以我们直接把下面这个改成links.first.url + +484 +00:20:38,239 --> 00:20:40,539 +And then we'll have the thumbnail be the same as +这样之后我们就可以让thumbnail的得到的内容 + +485 +00:20:40,541 --> 00:20:43,241 +the image URL, so it won't have a separate thumbnail. +和image Url获取的一样,这样做也不会出现一个不同的thumbnail + +486 +00:20:43,243 --> 00:20:46,945 +I'm just kinda cheating this really quick so +为了让我们真实快速地在UI中看到图片 + +487 +00:20:46,947 --> 00:20:49,847 +that we can see some image in our UI. +我在这里躲开了一些不必要的设置 + +488 +00:20:49,849 --> 00:20:52,683 +So let's go ahead and run this and see what happens this is +所以让我们接下去运行这个项目看看会发生什么 + +489 +00:20:52,685 --> 00:20:55,519 +for, oh we got, what do we got here, oh sorry override, +噢,报错了! + +490 +00:20:55,521 --> 00:20:56,820 +we gotta override these. +我应该要在前面加上override + +491 +00:20:56,822 --> 00:21:00,423 +Override. +加上override + +492 +00:21:00,425 --> 00:21:02,892 +Okay. +好了 + +493 +00:21:02,894 --> 00:21:04,193 +All right. +编译通过 + +494 +00:21:04,194 --> 00:21:05,493 +So I'm gonna run this here, in the simulator. +让我们看看在模拟器中运行的效果 + +495 +00:21:05,496 --> 00:21:07,896 +We'll switch the device in a second here. +这个设备会很快被打开 + +496 +00:21:07,898 --> 00:21:08,930 +All right. +好了 + +497 +00:21:08,932 --> 00:21:10,432 +So here we are. +这就是我们的模拟器 + +498 +00:21:10,433 --> 00:21:11,933 +You all remember this UI I've got here. +我们都记得这个UI,我刚才设置的 + +499 +00:21:11,935 --> 00:21:14,635 +And I've got these images on the left, for there. +接着我在左边获取了这些图片 + +500 +00:21:14,637 --> 00:21:17,271 +So I'm gonna go ahead and drop one for +我接下来想要通过在这儿用鼠标点击一下 + +501 +00:21:17,273 --> 00:21:19,339 +an editable waypoint here. +获取一个可编辑的waypoint + +502 +00:21:19,341 --> 00:21:21,107 +So I'm gonna click on it, you can see. +我选中它 + +503 +00:21:21,109 --> 00:21:23,042 +And there it is, there's our panorama. +你能看到,这是我们请求的那张叫做panorama的图片 + +504 +00:21:23,044 --> 00:21:25,678 +See, I used that as the default image, and +看到了吗?我将这个图片设置成默认的了 + +505 +00:21:25,680 --> 00:21:29,514 +if I click our editor here, there's panorama, it appears. +然后如果我点击了按钮,这张图片就会出现 + +506 +00:21:29,516 --> 00:21:31,583 +Okay, so, that's kind of fun and +好的,这挺有趣的吧 + +507 +00:21:31,585 --> 00:21:35,286 +notice that that's a very wide aspect ratio, but it only made +然后我们可以注意到这张图的像素虽然很大 + +508 +00:21:35,288 --> 00:21:38,089 +enough space to do that, and so we can edit it. +但我们还是有足够的空间去编辑它 + +509 +00:21:38,091 --> 00:21:41,792 +So, now we want to be able to change this view. +现在,我想要能够修改这个view + +510 +00:21:41,794 --> 00:21:43,026 +We don't want it to be panorama. +我不想要这个图片了 + +511 +00:21:43,028 --> 00:21:46,629 +I only just showed that to show you how this would work. +现在我们只能看到这张图片 + +512 +00:21:46,631 --> 00:21:48,631 +So we need to go back to add some UI, +要想实现这个效果,我们需要回到之前的页面上,然后添加一个ui控件 + +513 +00:21:48,633 --> 00:21:51,934 +some button that lets us take a picture with the camera and +一些可以控制让我们使用相机拍下的照片 + +514 +00:21:51,936 --> 00:21:53,335 +put that here instead. +然后替代这张图片的button + +515 +00:21:53,337 --> 00:21:55,303 +Okay, so that's what we're going to do now. +好的,这是我们接下去要做的 + +516 +00:21:55,305 --> 00:21:57,605 +Let's go to our storyboard here. +首先,我们回到storyboard上 + +517 +00:21:57,607 --> 00:22:00,975 +I'm gonna put that button like right here, I think. +我想要在这右边添加一个按钮 + +518 +00:22:00,977 --> 00:22:02,877 +Let's move this over a little bit and +让我们把这个控件变得小一点 + +519 +00:22:02,879 --> 00:22:04,578 +I'm gonna put it right in here. +把右边的空间留出来 + +520 +00:22:04,580 --> 00:22:06,713 +I have a nice button for that, or image for +然后我要设置一个按钮 + +521 +00:22:06,715 --> 00:22:07,914 +that with the camera. +然后给这个按钮设置这个照相机的图片 + +522 +00:22:07,916 --> 00:22:13,219 +So, let's go ahead and +首先,我们先拖 + +523 +00:22:13,221 --> 00:22:16,422 +get a button. +个button出来 + +524 +00:22:16,424 --> 00:22:18,523 +Okay. +好了 + +525 +00:22:18,525 --> 00:22:22,994 +Here's a button. +这个一个button + +526 +00:22:22,996 --> 00:22:26,097 +Okay so we'll put this button right in here. +然后将这个button放到这边 + +527 +00:22:26,099 --> 00:22:30,334 +Okay I'm going to set this image to be that camera, so +接下来再给这个button设置这个照相机的图片 + +528 +00:22:30,336 --> 00:22:34,270 +let's go ahead and drag that camera image into our +首先,我们先到images.scassets下 + +529 +00:22:34,272 --> 00:22:37,540 +XC assets, so here's our image assets. +将camera这张图片拖进去 + +530 +00:22:37,542 --> 00:22:40,342 +Drag this guy in here. +把它拖到这儿 + +531 +00:22:40,344 --> 00:22:42,544 +Okay. +好了 + +532 +00:22:42,546 --> 00:22:46,280 +We could put higher resolution versions in, et cetera, but +我们可以把它放到更高分辨率的地方,比如2X,3X + +533 +00:22:46,282 --> 00:22:48,049 +we're just gonna use that. +现在我们只要能用就行了 + +534 +00:22:48,051 --> 00:22:50,351 +So let's go to Button here. +所以我们回到button上 + +535 +00:22:50,352 --> 00:22:52,652 +I'm gonna go to the button here and change its image to +我将要把button的图片改成这张camera + +536 +00:22:52,655 --> 00:22:56,556 +be the camera, and I don't want the word button on there, +同时,我不想让button上显示任何文字 + +537 +00:22:56,558 --> 00:22:58,558 +okay, so here's my button. +好了,button就设置好了 + +538 +00:22:58,560 --> 00:23:03,228 +Now we'll do some auto layout here, to get this thing, +接下去,我们要做一些auto layout的工作 + +539 +00:23:03,230 --> 00:23:05,597 +in here. +为button加一些约束 + +540 +00:23:05,598 --> 00:23:07,965 +So I will put this up against this edge. +第一,我要让这个button紧靠着容器的边界 + +541 +00:23:07,968 --> 00:23:11,102 +Let's put something between here the horizontal spacing. +接着,再为它添加一个水平间距的约束 + +542 +00:23:11,104 --> 00:23:14,839 +Let's have these two be center Y. +让这2个控件的中心在Y方向上保持一致 + +543 +00:23:14,841 --> 00:23:17,742 +We had another one in here that we'll have to delete now +我们在这个方向上,我们原先有另一个约束,所以我现在要把它删掉 + +544 +00:23:17,744 --> 00:23:20,411 +because we used to have this thing on this edge, so +因为我们原先在这个控件上添加了靠近边界的约束 + +545 +00:23:20,413 --> 00:23:21,545 +let's go find that. +现在让我们找到这个冲突的约束 + +546 +00:23:21,547 --> 00:23:23,913 +That's trailing space to super view right here. +就是这个trailing Space to SuperView + +547 +00:23:23,915 --> 00:23:28,201 +We'll get rid of that. +将它删掉 + +548 +00:23:28,202 --> 00:23:32,488 +We'll make these to be standard spacing right there. +接下来设置成standard Value + +549 +00:23:32,490 --> 00:23:33,467 +All the rest of it looks like it's standard, +剩下的这些看起来像是标准的 + +550 +00:23:33,468 --> 00:23:34,445 +must have lined them up perfectly there. +一定要将控件完美的约束好 + +551 +00:23:34,446 --> 00:23:35,423 +Any problems, oh, horizontally ambiguous? +仍然存在问题,水平约束不明确 + +552 +00:23:35,426 --> 00:23:38,794 +Okay. +好的 + +553 +00:23:38,795 --> 00:23:42,163 +So this guy wants to hug, the button wants to hug itself +由于按照我们设置的约束条件,button需要变得更宽一些 + +554 +00:23:42,165 --> 00:23:47,802 +because this guy's willing to be as wide as we want. +所以我要调整一下这个button的水平位置 + +555 +00:23:47,804 --> 00:23:50,471 +It doesn't want to hug down but this one does and +由于button不需要向下紧靠,而另一个控件有这个约束条件 + +556 +00:23:50,473 --> 00:23:53,140 +the system has to know who gets the space there. +而我们要告诉系统怎么去分配这个空间 + +557 +00:23:53,142 --> 00:23:54,374 +So now the frames will be different. +所以现在的frame会和以前不一样 + +558 +00:23:54,376 --> 00:23:56,175 +Okay let's go down here, +所以让我们点击下面的按钮 + +559 +00:23:56,177 --> 00:23:59,778 +update our frames make sure everything looks good. +选择update frames 让这些控件彼此的约束条件不冲突 + +560 +00:23:59,780 --> 00:24:00,979 +It does. +好的,这样就没问题了 + +561 +00:24:00,981 --> 00:24:02,047 +Okay, excellent. +太棒了 + +562 +00:24:02,049 --> 00:24:03,648 +So we've added this little button to our UI. +现在我们成功地在我们的UI中加入了这个button + +563 +00:24:03,650 --> 00:24:05,049 +So now we're just gonna have this button. +但现在我们仅仅只是有了这个button + +564 +00:24:05,051 --> 00:24:07,918 +When we click it it's gonna bring up the camera. +当我点击它时,我希望的是能调用系统的相机 + +565 +00:24:07,920 --> 00:24:10,454 +So let's go do that. +所以我们还需要做一些配置 + +566 +00:24:10,456 --> 00:24:14,824 +All right, I'm just gonna control drag from this button +好的,首先,我要先按住control将这个button + +567 +00:24:14,826 --> 00:24:16,692 +right here, and here. +拖到右边的代码中 + +568 +00:24:16,694 --> 00:24:20,629 +And it's gonna be an action, we'll call it Take Photo. +为它绑定一个点击事件,我们将这个方法叫做Take Photo + +569 +00:24:20,631 --> 00:24:21,963 +That's what it does. +点击这个button将会发生的事情 + +570 +00:24:21,965 --> 00:24:25,933 +And we don't need any argument, or anything. +我们不需要在这个方法中传入任何参数 + +571 +00:24:25,935 --> 00:24:27,301 +There's Take Photo. +这是take photo 方法 + +572 +00:24:27,303 --> 00:24:29,970 +So, in here. +在这个里面 + +573 +00:24:29,972 --> 00:24:34,273 +All we need to do is create that picker and present it. +我们需要的是创建一个picker然后在这个页面使用present跳转 + +574 +00:24:34,275 --> 00:24:37,243 +And then we're gonna implement those delegate methods and +接着,我们会实现那些delegate方法 + +575 +00:24:37,245 --> 00:24:38,310 +we'll be good to go. +这样使用起来会很好 + +576 +00:24:38,312 --> 00:24:41,279 +All right, so what do we need to do in here? +那么要想实现这些效果,我们需要在这个方法里写些什么呢? + +577 +00:24:41,281 --> 00:24:43,648 +First I'm gonna check and make sure I have a camera. +首要,我要确保我有一个照相机 + +578 +00:24:43,650 --> 00:24:46,351 +Actually I'm gonna, first I'm gonna go and +事实上,我要先让我们有足够的空间 + +579 +00:24:46,353 --> 00:24:48,285 +give us some space to work with. +来写这些代码 + +580 +00:24:48,287 --> 00:24:49,520 +All right. +好了 + +581 +00:24:49,522 --> 00:24:53,289 +So first I'm gonna check here, and +首先,创建一个if语句 + +582 +00:24:53,291 --> 00:24:56,793 +see UIImagePickerController. +判断UIImagePickerController中 + +583 +00:24:56,795 --> 00:24:58,961 +If I have a camera available, so +是否我有相机 + +584 +00:24:58,963 --> 00:25:02,064 +I'm gonna say source type available camera. +我的意思是,这个路径下的相机是否可用 + +585 +00:25:02,066 --> 00:25:02,731 +Okay? +懂我意思吗? + +586 +00:25:02,733 --> 00:25:04,132 +So if I have a camera, +如果我有相机 + +587 +00:25:04,134 --> 00:25:07,168 +then I'm gonna set my picker's source type. +那么接下来我要设置picker.sourceType + +588 +00:25:07,170 --> 00:25:10,338 +To be the camera. +为.Camera + +589 +00:25:10,340 --> 00:25:13,273 +Okay? +好吗? + +590 +00:25:13,275 --> 00:25:14,274 +What else have we got? +我们还需要设置picker的哪些属性? + +591 +00:25:14,276 --> 00:25:16,009 +Oh, sorry. +喔,抱歉 + +592 +00:25:16,011 --> 00:25:18,077 +I've got to create my picker. +我应该先创建一个picker对象 + +593 +00:25:18,079 --> 00:25:21,513 +So here I'm gonna say let the picker equal UI image picker +所以在这里,我应该先写让picker等于 + +594 +00:25:21,515 --> 00:25:23,766 +controller. +UIImagePickerController + +595 +00:25:23,767 --> 00:25:26,018 +So when you create it, it's just parentheses, parentheses, +这样做只是初始化了这个对象 + +596 +00:25:26,020 --> 00:25:27,886 +you don't have to specify any. +你还没有让他拥有任何特性 + +597 +00:25:27,888 --> 00:25:29,854 +X-ray information when you're creating it. +比如当你创建它 是给它添加一个X-ray信息 + +598 +00:25:29,856 --> 00:25:30,955 +So now I've set the source type. +既然现在我已经设置了它的source type + +599 +00:25:30,957 --> 00:25:34,391 +Now here I would maybe, if I was doing video. +现在在这儿,如果我正在处理的是一段视频 + +600 +00:25:34,393 --> 00:25:38,395 +You know, I would check media types to make sure that media +你懂我意思吗?我应该要确保媒体的类型 + +601 +00:25:38,397 --> 00:25:39,796 +type is available. +是可用的 + +602 +00:25:39,798 --> 00:25:42,732 +And then I would say picker.mediaTypes equals. +所以接下来我会让picker.mediaTypes等于 + +603 +00:25:42,734 --> 00:25:44,166 +And then the types I want. +我需要的类型 + +604 +00:25:44,168 --> 00:25:48,103 +So, in this case I just want image only. +所以,以防万一,我就设置了image类型 + +605 +00:25:48,105 --> 00:25:50,571 +Okay? +懂了吗? + + +606 +00:25:50,573 --> 00:25:55,376 +And then we obviously need the picker to set its delegate to +接下来我们显然要设置picker的delegate + +607 +00:25:55,378 --> 00:25:56,176 +be self. +为self + +608 +00:25:56,178 --> 00:25:57,694 +Okay? +懂吗? + +609 +00:25:57,695 --> 00:25:59,211 +Without the delegate this thing does nothing. +如果没有delegate,这个picker对象什么也做不了 + +610 +00:25:59,214 --> 00:26:03,249 +We could also set some other fun things here like maybe we +我们当然也可以设置一些其他有趣的东西 + +611 +00:26:03,251 --> 00:26:04,450 +allow editing. +比如让它的allow editing + +612 +00:26:04,452 --> 00:26:06,335 +True? +属性为true + +613 +00:26:06,336 --> 00:26:08,219 +So we'll see what that UI looks like. +接下来,我们看下UI会是什么样的 + +614 +00:26:08,222 --> 00:26:12,256 +And then we can just present. +现在我们可以直接使用present来跳转这个页面 + +615 +00:26:12,258 --> 00:26:13,758 +ViewController. +viewController参数 + +616 +00:26:13,760 --> 00:26:14,658 +The picker. +picker + +617 +00:26:14,660 --> 00:26:15,258 +Animated? +是否需要动画? + +618 +00:26:15,260 --> 00:26:17,060 +Yes. +是的 + +619 +00:26:17,061 --> 00:26:18,861 +And, we don't wanna find out that a capture has +现在我们发现 + +620 +00:26:18,864 --> 00:26:19,846 +been put up. +这里报错了 + +621 +00:26:19,847 --> 00:26:20,829 +And, what else do we got in here? +所以我们需要修改一下 + +622 +00:26:20,832 --> 00:26:21,831 +Oh, okay. +噢,好的 + +623 +00:26:21,833 --> 00:26:23,799 +So this is the famous, oh. +这是一个很多人都会犯的错误 + +624 +00:26:23,801 --> 00:26:25,167 +Where does this coming from? +这个类是哪儿来的? + +625 +00:26:25,169 --> 00:26:27,135 +So, we have to come up here. +随意我们需要提前声明一下 + +626 +00:26:27,137 --> 00:26:33,574 +Import MobileCoreServices. +导入MobileCoreServices + +627 +00:26:33,576 --> 00:26:35,209 +That takes care of that. +这是你需要注意的地方 + +628 +00:26:35,211 --> 00:26:37,811 +And this one of course is we don't implement. +这个问题是我们没有声明这个类的代理 + +629 +00:26:37,813 --> 00:26:39,346 +UI Image Picker Controller Delegate. +UIImagePickerController 代理 + +630 +00:26:39,348 --> 00:26:43,549 +Okay, let's do that, UI Image Picker Controller Delegate. +好的,让我添加进去 + +631 +00:26:43,551 --> 00:26:46,552 +Now what's interesting here is that we still have an error +现在有趣的时,我们这样做了之后系统仍然提示有错误 + +632 +00:26:46,554 --> 00:26:49,254 +once we put this UI Image Picker Controller Delegate +尽管我们已经将UIImagePickerControllerDelegate + +633 +00:26:49,256 --> 00:26:49,921 +thing here. +在前面声明了 + +634 +00:26:49,923 --> 00:26:52,324 +It says. +这个错误提示我们 + +635 +00:26:52,325 --> 00:26:54,726 +Wave point controller does not conform to UI navigation +Wavepointcontroller并没有遵照 + +636 +00:26:54,728 --> 00:26:56,360 +controller delegate. +UINavigationcontroller的代理 + +637 +00:26:56,362 --> 00:26:57,494 +Why the heck does it say that? +为什么系统会这样提示呢? + +638 +00:26:57,496 --> 00:26:59,930 +UI navigation hasn't got anything to do with that. +UINavigtiong 并没有得到任何东西 + +639 +00:26:59,932 --> 00:27:02,866 +Well that's because the UI image picker controller is +好吧,这样是因为UIImagePickerController是继承自 + +640 +00:27:02,868 --> 00:27:05,702 +a UI navigation controller, inherits from it, and +UINavightionController + +641 +00:27:05,704 --> 00:27:07,770 +they use the same variable delegate. +他们有相同的变量delegate + +642 +00:27:07,772 --> 00:27:09,589 +To be their delegate. +作为他们的代理对象 + +643 +00:27:09,590 --> 00:27:11,407 +So, we also have to come up here and say that we are a UI +所以,在这里我们不得不也将UINavigationController添加进去 + +644 +00:27:11,409 --> 00:27:14,109 +navigation controller delegate, even though we don't +但是我们实际上并不会 + +645 +00:27:14,111 --> 00:27:16,845 +actually implement any of these methods in the protocol. +使用协议里的任何方法 + +646 +00:27:16,847 --> 00:27:17,445 +That's fine. +这样就好了 + +647 +00:27:17,447 --> 00:27:19,246 +They're all optional. +UINavigationControllerDelegate中的代理方法都是optional的 + +648 +00:27:19,248 --> 00:27:20,881 +Okay? +懂吗? + +649 +00:27:20,882 --> 00:27:22,515 +So, that's a little tricky thing sometimes people don't +所以有时我们可能无法理解但为了避免错误 + +650 +00:27:22,518 --> 00:27:24,017 +understand with the picker, but. +我们不得不使用一些技巧 + +651 +00:27:24,019 --> 00:27:26,286 +You definitely need to do that. +不过我们在这里确实需要这样去做 + +652 +00:27:26,287 --> 00:27:28,554 +So, that's all that's required to put that picker on-screen, +总之,这就是将picker在屏幕上展示,所有需要的代码 + +653 +00:27:28,557 --> 00:27:30,189 +so it's gonna be on-screen and +现在它即将被放到屏幕上 + +654 +00:27:30,191 --> 00:27:32,992 +now we just have to implement those delegate methods. +现在我们仅仅还需要实现一些代理方法 + +655 +00:27:32,994 --> 00:27:34,760 +So, here they are. +让我们看下需要实现哪个方法 + +656 +00:27:34,762 --> 00:27:37,229 +This one, by the way, is deprecated, +这个方法,顺便说下,已经被官方不推荐使用了 + +657 +00:27:37,231 --> 00:27:38,563 +don't use that one. +所以我们不用这个方法 + +658 +00:27:38,565 --> 00:27:40,365 +Here is the one where they pick something, and +这个方法在选中时会被调用 + +659 +00:27:40,367 --> 00:27:41,832 +here is the one where they cancelled. +这个方法取消时会被调用 + +660 +00:27:41,834 --> 00:27:42,900 +Okay? +懂吗? + +661 +00:27:42,901 --> 00:27:43,967 +So let's do the one where they picked. +所以我们先实现当它被选中时调用 + +662 +00:27:43,969 --> 00:27:46,286 +Something, so +这个方法 + +663 +00:27:46,287 --> 00:27:48,604 +I'm just going to say that the image they picked is the info, +我想说的是当图片被选中时image = info + +664 +00:27:48,607 --> 00:27:52,042 +that info dictionary that's being passed along here. +然后info的参数将会作为字典类型被传递 + +665 +00:27:52,044 --> 00:27:54,410 +And there's a bunch of constants in +这是一组在UIImagePickerController中的常量 + +666 +00:27:54,412 --> 00:27:57,847 +UIImagePickerController, and one of them here, +现在我需要的是他们中的一个 + +667 +00:27:57,849 --> 00:28:00,883 +ImagePickerControllerEditedIm- age, so +ImagePickerControllerEditedImage + +668 +00:28:00,885 --> 00:28:04,819 +that's the edited image, and I wanna get it as a UIImage. +这是已经被编辑的图片,然后我现在要让他转化为UIImage + +669 +00:28:04,821 --> 00:28:07,722 +Okay, because this info is, +因为info的value是AnyObject + +670 +00:28:07,724 --> 00:28:12,559 +AnyObject is the value, so I have to cast it here. +所以我们在这需要计算一下 + +671 +00:28:12,561 --> 00:28:16,129 +If I couldn't get the image, okay, the edited image, +如果我不能得到这张被编辑过的图片 + +672 +00:28:16,131 --> 00:28:17,864 +then I'm gonna just try and +那么接下来我将要尝试 + +673 +00:28:17,866 --> 00:28:21,334 +set the image equal to the unedited image, which is the +让这个图片等于未被编辑时的图片 + +674 +00:28:21,336 --> 00:28:24,270 +ImagePickerControllerOriginal- Image. +就是初始时的图片 + +675 +00:28:24,272 --> 00:28:27,773 +As UI image. +作为UIImage的类 + +676 +00:28:27,775 --> 00:28:30,876 +Now you might say, why am I doing this line of code right +现在你可能会问,为什么这行代码是正确地 + +677 +00:28:30,878 --> 00:28:33,945 +here because I'm clearly allowing editing up here. +因为我在之前已经明确地声明了allowing editing为true + +678 +00:28:33,947 --> 00:28:35,580 +Yeah, we're allowing editing today but +是的,今天我们允许编辑 + +679 +00:28:35,582 --> 00:28:37,282 +if I some day just said, eh, +如果我在之前的某一天说过 + +680 +00:28:37,283 --> 00:28:38,983 +I'm not gonna let people edit and I change this to false, +呃,我不想让人们编辑和改变图片 + +681 +00:28:38,985 --> 00:28:40,635 +well, all of the sudden, +好吧,突然就发生了 + +682 +00:28:40,636 --> 00:28:42,286 +this code would break if I didn't have this nice little. +如果不将allowing editing设为true的话 + +683 +00:28:42,288 --> 00:28:43,904 +Thing here. +代码会崩溃 + +684 +00:28:43,905 --> 00:28:45,521 +So I'm thinking ahead a little bit to make it so that +所以我提前做了这个准备 + +685 +00:28:45,524 --> 00:28:48,391 +a change somewhere else in my code won't break me here. +防止我的代码会突然出现崩溃 + +686 +00:28:48,393 --> 00:28:49,559 +Okay? +懂了吗? + +687 +00:28:49,560 --> 00:28:50,726 +And so I've got the image. +好了,接下来我要获取这张图片 + +688 +00:28:50,729 --> 00:28:52,728 +So I'm just gonna set the, +然后开始对它进行一些设置 + +689 +00:28:52,730 --> 00:28:55,330 +my image views image equal to that. +让这个属性等于它 + +690 +00:28:55,332 --> 00:28:57,232 +And I'm gonna make room for it. +然后我再为它设置空间 + +691 +00:28:57,234 --> 00:29:00,068 +Okay, that's this makeRoomForImage that I told +这是我之前说的makeRoomForImage函数 + +692 +00:29:00,070 --> 00:29:01,369 +you I added down here. +我将会执行下面的这些代码 + +693 +00:29:01,371 --> 00:29:02,670 +Okay? +ok? + +694 +00:29:02,672 --> 00:29:04,938 +And that's it. +那么就是这样了 + +695 +00:29:04,940 --> 00:29:06,773 +I've got everything, so I'm just gonna dismiss. +我已经将这一切都下好了,接下来只要dismiss这个view的行了 + +696 +00:29:06,775 --> 00:29:08,141 +And notice, I'm not saying, +在这里要注意 + +697 +00:29:08,143 --> 00:29:10,076 +presenting view controller dismiss here. +我没有说将presentingViewController dismiss掉 + +698 +00:29:10,078 --> 00:29:11,944 +Because I am the presenting view controller. +因为此时的页面就是presentingViewController + +699 +00:29:11,946 --> 00:29:13,712 +So I'm just saying, dismiss true. +我仅仅是设置dismiss为true + +700 +00:29:13,714 --> 00:29:17,549 +And completion. +然后执行completion block + +701 +00:29:17,551 --> 00:29:19,668 +Okay? +懂我意思吗? + +702 +00:29:19,669 --> 00:29:21,786 +We have to do the same thing here for the cancelled case. +我们在取消时调用的代理方法中也要做同样的事情 + +703 +00:29:21,788 --> 00:29:22,486 +Okay? +好嘛 + +704 +00:29:22,488 --> 00:29:24,221 +But in the cancelled case, +只是在在取消时调用的代理方法中 + +705 +00:29:24,223 --> 00:29:27,457 +I'm only gonna do this dismiss right here, okay? +我仅仅需要调用dismiss方法就行了 + +706 +00:29:27,459 --> 00:29:29,693 +Obviously, I'm not gonna grab the image or +很显然,让他们退出以后我想再 + +707 +00:29:29,695 --> 00:29:30,993 +anything if they cancel. +去抓取图片或任何东西 + +708 +00:29:30,995 --> 00:29:32,094 +All right? +好的 + +709 +00:29:32,096 --> 00:29:35,714 +So let's take a look at this. +让我们看下实际运行情况 + +710 +00:29:35,715 --> 00:29:39,333 +Let's look at this, let's go on iPhone 6 plus here. +在这里选择在iPhone 6 plus上运行 + +711 +00:29:39,336 --> 00:29:40,635 +There it is, okay? +运行成功了 + +712 +00:29:40,637 --> 00:29:42,704 +Actually, let's go. +好的,让我们操作看看 + +713 +00:29:42,706 --> 00:29:44,872 +We still have our little panoram in here. +我们仍然可以在这里看到我们之前设置的panoram图片 + +714 +00:29:44,874 --> 00:29:48,042 +Let's go to that really quick. +让我们快点儿回到这张图片的代码上 + +715 +00:29:48,044 --> 00:29:51,712 +That's over here. +找找在哪儿 + +716 +00:29:51,714 --> 00:29:55,849 +So we'll just go back here and we'll comment this out. +所以我们只要回到之前的代码上 然后把这句代码注释掉 + +717 +00:29:55,851 --> 00:30:00,453 +So that if we're testing again in the future we can go +这样做呢,如果我将来我们还要进行测试的时候 + +718 +00:30:00,455 --> 00:30:01,487 +back to it. +我们只要把注释取消掉就好了 + +719 +00:30:01,489 --> 00:30:03,589 +All right. +好了 + +720 +00:30:03,590 --> 00:30:05,690 +But let's get this code back up on the screen here so +接下来还是回到我们之前写完了的代码上 + +721 +00:30:05,693 --> 00:30:06,758 +you can see it. + +722 +00:30:06,760 --> 00:30:08,359 +All right, so here's our photo stuff. +好了,这是我们处理photo的代码 + +723 +00:30:08,361 --> 00:30:13,464 +All right, so +那么接下来 + +724 +00:30:13,466 --> 00:30:20,337 +let's run again. +我们再运行看看 + +725 +00:30:20,339 --> 00:30:22,038 +All right so I'm gonna drop a pin. +好的我想要选中一个大头针 + +726 +00:30:22,040 --> 00:30:24,573 +Notice that we don't have an image right here. +注意在这个上面我们已经没有图片了 + +727 +00:30:24,575 --> 00:30:25,558 +Okay? +发现了吗? + +728 +00:30:25,559 --> 00:30:26,542 +It took away that little test image. +我们已经将那个小测试图片移走了 + +729 +00:30:26,544 --> 00:30:28,377 +And clicking our edit thing and +然后点击我们编辑按钮 + +730 +00:30:28,379 --> 00:30:30,211 +we've got this big space now. +我们跳转到了这个大页面上 + +731 +00:30:30,213 --> 00:30:33,614 +There's that big grey box right there because I set that +这下面有一大块儿灰色的区域 + +732 +00:30:33,616 --> 00:30:35,850 +UI image in my storyboard to be grey. +因为我在storyboard设置了UIImage的背景色是灰色的 + +733 +00:30:35,852 --> 00:30:36,684 +Right? +还记得吗? + +734 +00:30:36,686 --> 00:30:39,419 +So let's go look at that. +所以呢当我们看到它时 + +735 +00:30:39,421 --> 00:30:40,653 +See over here, this is gray. +会发现这会是灰色的 + +736 +00:30:40,655 --> 00:30:42,855 +So really, when I'm shipping, +所以在这里我应该注重这些细节 + +737 +00:30:42,857 --> 00:30:45,157 +I'm obviously gonna go here, and +很显然我要回到storyboard中 + +738 +00:30:45,159 --> 00:30:49,061 +set this back to its standard, which is clear basically. +然后把这个背景色改成透明的 + +739 +00:30:49,063 --> 00:30:50,562 +Okay? +对吗? + +740 +00:30:50,564 --> 00:30:52,797 +Back to our code. +回到我们的代码中 + +741 +00:30:52,799 --> 00:30:53,698 +All right. +好了 + +742 +00:30:53,700 --> 00:30:54,631 +So we're gonna take a photo here. +所以我们将要在这儿拍一张照片 + +743 +00:30:54,633 --> 00:30:56,366 +I'm gonna press that little camera. +我将要点击camera按钮 + +744 +00:30:56,368 --> 00:30:58,068 +Okay, camera. +嗯,camera + +745 +00:30:58,070 --> 00:31:01,137 +And you can see camera comes up right here. +接着你马上就回看到系统的相机被调用了 + +746 +00:31:01,139 --> 00:31:04,674 +And this was helicopter skiing. +我们将要坐直升机和滑雪 + +747 +00:31:04,676 --> 00:31:06,608 +So let's look at our favorite hat. +所以我们看看我们最爱的帽子 + +748 +00:31:06,610 --> 00:31:08,910 +Ski hat, we got our favorite ski hat. +滑雪帽,我们得到了最爱的滑雪帽 + +749 +00:31:08,912 --> 00:31:10,578 +It's R2D2. +它叫R2D2 + +750 +00:31:10,580 --> 00:31:13,314 +Actually it's better than R2D2. +实施上它比R2D2还好 + +751 +00:31:13,316 --> 00:31:15,616 +There a little San Francisco Giants R2D2. +这是一个三藩市巨人队的 + +752 +00:31:15,618 --> 00:31:18,318 +Okay, so we're gonna take this picture. +好的,我们将要拍下这张照片 + +753 +00:31:18,320 --> 00:31:21,621 +Okay, so we can now crop it. +好的,我们可以伸缩和放大这张照片 + +754 +00:31:21,623 --> 00:31:22,706 +Okay? +对吗? + +755 +00:31:22,707 --> 00:31:23,790 +We could zoom in on the really important part. +我们可以放大到真正重要的部位 + +756 +00:31:23,792 --> 00:31:25,024 +All right? +对吗? + +757 +00:31:25,026 --> 00:31:28,160 +And then we can say Use Photo, and it comes back and +然后我们可以使用这张照片,然后回到刚才的页面上 + +758 +00:31:28,162 --> 00:31:30,062 +it appears in our thing here. +这张照片在我们的容器中显示了 + +759 +00:31:30,064 --> 00:31:31,630 +If we take a different picture, +我们夜可以拍摄不同的照片 + +760 +00:31:31,632 --> 00:31:34,599 +maybe if we decide, okay, we want the whole hat, all right, +或许我们想要能显示整张帽子的图片 + +761 +00:31:34,601 --> 00:31:37,101 +we'll zoom out there, and we'll use that photo. +我们可以缩小一下,然后使用这个照片 + +762 +00:31:37,103 --> 00:31:38,369 +We got it, okay? +我们做到了,对吗? + +763 +00:31:38,371 --> 00:31:41,572 +Now, of course, this is not going to save this, so +现在,当然,这样做不会存储这张照片 + +764 +00:31:41,574 --> 00:31:44,875 +as soon as I go away and come back, it's not there and +所以只要我离开这个页面,再选中这个大头针,这张图片不会显示 + +765 +00:31:44,877 --> 00:31:48,478 +that's because we need to save that picture somewhere. +这就需要我们在的操作中添加将图片保存在某地的方法 + +766 +00:31:48,480 --> 00:31:51,647 +And we're gonna save that in the file system with our +那么接下来,我们就要通过接下去的例子 + +767 +00:31:51,649 --> 00:31:54,767 +next demo. +把照片存在我们的文件系统 + +768 +00:31:54,768 --> 00:31:57,886 +Let's take a quick look what this looks like on the iPad. +我们再快速看一下,这个demo在iPad上运行的样子 + +769 +00:31:57,888 --> 00:32:05,660 +Make sure that it works over there as well. +确保demo在iPad上运行也没有问题 + +770 +00:32:05,662 --> 00:32:06,327 +All right. +好的 + +771 +00:32:06,329 --> 00:32:08,496 +So, we'll drop a pin here. +接下来,我在这儿选择一个大头针 + +772 +00:32:08,498 --> 00:32:10,130 +We'll go there. +点击按钮 + +773 +00:32:10,132 --> 00:32:13,033 +Bring up our little popover. +出现一个小的弹出框 + +774 +00:32:13,035 --> 00:32:17,603 +Take a photo, again we get the huge size screen. +点击拍照,我们跳转到了一个巨大尺寸的屏幕上 + +775 +00:32:17,605 --> 00:32:19,338 +We'll have to do front facing camera, +我们不得不使用前置摄像头 + +776 +00:32:19,340 --> 00:32:20,706 +because I got it on this thing. +因为后置摄像头被什么东西遮住了 + +777 +00:32:20,708 --> 00:32:23,775 +Here we go, this R2-D2 hat there. +又来了,这是我们的R2D2帽子 + +778 +00:32:23,777 --> 00:32:25,643 +There we go. +拍下照片 + +779 +00:32:25,645 --> 00:32:26,477 +All right. +好了 + +780 +00:32:26,479 --> 00:32:27,545 +And there it is. +显示正常 + +781 +00:32:27,547 --> 00:32:28,912 +And so we can put it into our little popover, +我们成功将这个照片在弹出框中显示出来了 + +782 +00:32:28,914 --> 00:32:30,414 +which is kind of fun. +看起来挺有趣的 + +783 +00:32:30,415 --> 00:32:31,915 +And because we have that generic UI view, and +然后因为我们先前设置过了这个UIView类 + +784 +00:32:31,917 --> 00:32:34,884 +I asked for a bigger preferred content size, it made some +所以我请求了一个更大更适合内容的尺寸, + +785 +00:32:34,886 --> 00:32:37,820 +more size and then the generic UI image view got bigger. +这样做可以让UIImageView这个类在容器里有足够的尺寸来变大 + +786 +00:32:37,822 --> 00:32:40,923 +And so then I was able to make the image view inside of it +那么接下来我就可以让容器里的ImageView变得 + +787 +00:32:40,925 --> 00:32:41,490 +bigger. +更大 + +788 +00:32:41,492 --> 00:32:43,525 +Okay. +好了 + +789 +00:32:43,527 --> 00:32:45,627 +Excellent. +太棒了 + +790 +00:32:45,628 --> 00:32:47,728 +Okay, let's go back to the slides, and +好的,那么我们接下来回到幻灯片上 + +791 +00:32:47,731 --> 00:32:51,299 +learn a little bit about storing stuff, and +学习一点儿关于存储部分的知识 + +792 +00:32:51,301 --> 00:32:54,835 +then we can come back and store that image. +然后我们就能回到我们的项目上把图片保存起来 + +793 +00:32:54,837 --> 00:32:58,905 +All right, so there are a number of ways to make +这是一些可以把东西存在你设备上 + +794 +00:32:58,907 --> 00:33:01,775 +things persist on your device. +的方法 + +795 +00:33:01,777 --> 00:33:03,810 +In other words, +换句话说 + +796 +00:33:03,811 --> 00:33:05,844 +some data that you want to live forever on your device. +就是一些你想要让它永远存在你设备上的数据 + +797 +00:33:05,847 --> 00:33:07,146 +Okay. Even as your application +比如你退出了应用 + +798 +00:33:07,148 --> 00:33:08,847 +is quit, the phone gets powered off, +手机断电了 + +799 +00:33:08,849 --> 00:33:10,749 +whatever, you want that stuff to exist. +或是什么情况,你想要你的数据仍然存在 + +800 +00:33:10,751 --> 00:33:13,551 +So I'm gonna talk about four different ways. +所以我准备讲讲这4种不同的方式 + +801 +00:33:13,553 --> 00:33:15,186 +You already know one, actually, +事实上,有一种方法你已经知道了 + +802 +00:33:15,188 --> 00:33:16,487 +which is NS user defaults. +就是NSUserDefaults + +803 +00:33:16,489 --> 00:33:17,855 +Okay. +还记得吗? + +804 +00:33:17,856 --> 00:33:19,222 +That's a really simple, kind of small amount. +这主要针对是一种简单的,小数量的数据存储 + +805 +00:33:19,225 --> 00:33:21,425 +This is for bigger data, these four things. +而这4种是针对更大型的数据存储方式 + +806 +00:33:21,427 --> 00:33:24,361 +The first two, I'm just gonna really, briefly pass through. +前两种,我仅仅就简单的介绍一下 + +807 +00:33:24,363 --> 00:33:26,295 +I'm barely even gonna talk about them. +我几乎很少的提及他们 + +808 +00:33:26,297 --> 00:33:29,165 +Because, really, you're certainly not gonna use them, +因为这些技术你以后真的不会去用他们 + +809 +00:33:29,167 --> 00:33:31,133 +I don't think, in your final project. +在你的最终项目里,我不认为 + +810 +00:33:31,135 --> 00:33:35,704 +Maybe some SQL master out there will be doing some SQL +或许一些精通SQL的人会去做一些根SQL相关的 + +811 +00:33:35,706 --> 00:33:37,472 +thing. +事情 + +812 +00:33:37,473 --> 00:33:39,239 +But I don't think anyone will use that. +但我还是不推荐大家去使用 + +813 +00:33:39,242 --> 00:33:41,876 +But then the File System and Core Data, I know a lot of you +但是File System和Core Data,我听到过很多人 + +814 +00:33:41,878 --> 00:33:43,911 +are doing Core Data as your final project. +正在使用Core Data 比如在你们的最终项目里 + +815 +00:33:43,913 --> 00:33:45,045 +And that's a great, +这是很好的 + +816 +00:33:45,046 --> 00:33:46,178 +not covered in lecture thing, by the way. +顺便说一下,不仅仅涉及在课堂上接触的知识 + +817 +00:33:46,181 --> 00:33:47,580 +Even though I'm gonna talk about it today, +尽管我今天我说关于这方面的知识 + +818 +00:33:47,582 --> 00:33:49,148 +that doesn't mean I'm covering it in lecture, +但这并不意味着我能在课堂上把关于这个知识的方方面面都说清楚 + +819 +00:33:49,150 --> 00:33:50,216 +I'm barely gonna talk about it. +我几乎很少能够这样 + +820 +00:33:50,218 --> 00:33:52,584 +But, so I know I lot of you are doing that. +所以,我知道你们很多都会做到提前预习 + +821 +00:33:52,586 --> 00:33:54,086 +And some of you wanna use the File System, also. +当然你们也有一部分想要使用File System + +822 +00:33:54,088 --> 00:33:55,820 +You're reading and writing files from the File System. +在你的文件系统中读或者写数据 + +823 +00:33:55,822 --> 00:33:57,955 +So hopefully, this will get you up to speed there. +总之,我希望为了能在课堂上更好的理解大家都可以提前预习 + +824 +00:33:57,957 --> 00:33:59,490 +So let's talk about Archiving. +那么首先我先介绍一下Archiving + +825 +00:33:59,492 --> 00:34:04,094 +Archiving is a way to store a graph of objects, +Archiving是一种存储一个对象的方式 + +826 +00:34:04,096 --> 00:34:06,029 +okay, on to disc. +是的,在磁盘上 + +827 +00:34:06,031 --> 00:34:08,998 +And those objects don't have to be property lists. +而且被存储的对象不需要有所有属性的目录 + +828 +00:34:09,000 --> 00:34:11,300 +So they don't have to be array, dictionary, date, +所以他们不需要是数组,字典,或是date + +829 +00:34:11,302 --> 00:34:12,852 +whatever. +等类型 + +830 +00:34:12,853 --> 00:34:14,403 +Because that's all we can put in NSUserDefaults, right? +因为他们都可以使用NSUserDefaults来存储对吗? + +831 +00:34:14,405 --> 00:34:16,138 +And NSUserDefaut is for small things. +所以NSUserDefaut是针对小型的数据的 + +832 +00:34:16,140 --> 00:34:19,240 +But if we want to store big things, bigger object graphs, +但是如果我想要存储大型的数据,更大的对象 + +833 +00:34:19,242 --> 00:34:21,109 +and we want a lot more flexibility. +我们就需要一个更灵活的方式 + +834 +00:34:21,111 --> 00:34:23,210 +Well, that's where we use Archiving. +是的,这就是我们使用Archiving的原因 + +835 +00:34:23,212 --> 00:34:27,748 +And, Archiving can archive any tree of objects as long +只要一个对象实现了Archiving的两个方法 + +836 +00:34:27,750 --> 00:34:31,418 +as all of them implement these two methods, +那么使用Archiving就可以存储这个对象的所有分支属性 + +837 +00:34:31,420 --> 00:34:36,288 +encodeWithCoder and an init method that reads themselves +encodeWithCoder 这个函数和 + +838 +00:34:36,290 --> 00:34:38,090 +back in from a coder. +一个用来读取他们自身的init方法 + +839 +00:34:38,092 --> 00:34:40,759 +So encodeWithCoder basically writes them out, +所以encodeWithCoder这个函数基本上就是将他们写出来 + +840 +00:34:40,761 --> 00:34:43,695 +writes themselves out, basically as a dictionary. +基于字典的形式将对象自身写出来 + +841 +00:34:43,697 --> 00:34:46,798 +Okay, and then encode, and then init will instantiate +然后再进行编码,当这些对象需要被读取时 + +842 +00:34:46,800 --> 00:34:48,833 +the object when it gets read back in, +init方法会初始化他们 + +843 +00:34:48,835 --> 00:34:51,235 +reading that stuff from that dictionary. +从字典中读取对象的属性 + +844 +00:34:51,237 --> 00:34:52,602 +So where is this used? +所以这种技术一般会在哪儿用到? + +845 +00:34:52,604 --> 00:34:55,372 +Your storyboard is archived. +storyboard就是运用这种方式存储的 + +846 +00:34:55,374 --> 00:34:57,607 +So all the things in your archive, +你所有的东西都会在这个存档文件中 + +847 +00:34:57,609 --> 00:35:01,177 +all of those ui views, all those ui view controllers, +所有的UIView,UIViewController + +848 +00:35:01,179 --> 00:35:02,811 +they are all encodable. +他们都是可以编码的 + +849 +00:35:02,813 --> 00:35:05,614 +Okay, they implement this NSCoding protocol. +首先,他们实现了NSCoding 协议 + +850 +00:35:05,616 --> 00:35:07,749 +And they all get written out. +然后,他们全被写了下来 + +851 +00:35:07,751 --> 00:35:10,918 +Basically, when the storyboard is saved, this whole object +基本上,当你的storyboard被保存了,整个对象的图表 + +852 +00:35:10,920 --> 00:35:13,988 +graph, the entire thing, all the buttons, everything in +整个对象,所有的button + +853 +00:35:13,990 --> 00:35:16,924 +there gets written out using this Archiving mechanism. +在上面的所有东西,都会基于Archiving机制被写下来 + +854 +00:35:16,926 --> 00:35:20,527 +And that's why we have that weird init thing with UI view +所以这就是为什么我们调用init方法创建一个UIViewController + +855 +00:35:20,529 --> 00:35:23,763 +controller and UI view where there was always this +或是UIView对象时一直会需要一个 + +856 +00:35:23,765 --> 00:35:25,598 +required init coder thing. +叫做init coder的属性 + +857 +00:35:25,600 --> 00:35:27,600 +That's because they participate in this Archiving. +那是因为他们都使用了Archiving机制 + +858 +00:35:27,602 --> 00:35:30,135 +Now, I would not recommend to you if you had a graph of +现在,尽管我不推荐,如果你有对象需要存储 + +859 +00:35:30,137 --> 00:35:32,838 +objects, you know like, I want to make them persist. +你需要让他们持久化 + +860 +00:35:32,840 --> 00:35:34,673 +I think I'll archive them. +我知道我可以使用Archive + +861 +00:35:34,675 --> 00:35:36,425 +I wouldn't do it. +不过我还是不会这么做 + +862 +00:35:36,426 --> 00:35:38,176 +I would use one of the other mechanisms I'm gonna talk +我宁愿使用另外一种我今天不会说的 + +863 +00:35:38,178 --> 00:35:39,861 +about today. +机制 + +864 +00:35:39,862 --> 00:35:41,545 +Okay, this is really is great for story boards and +当然Archiving机制是非常适合storyboard存储的 + +865 +00:35:41,547 --> 00:35:44,081 +it really is the right thing for story boards but +这也确实对storyboard非常好 + +866 +00:35:44,083 --> 00:35:46,166 +I'm not sure that for +但我不确定 + +867 +00:35:46,167 --> 00:35:48,250 +arbitrary data storage if it really makes a lot of sense. +这样主观的对数据保存是否真的有意义 + +868 +00:35:48,253 --> 00:35:50,637 +Okay. +懂了吗? + +869 +00:35:50,638 --> 00:35:53,022 +All right SQL, some of you are database experts and +接下来关于SQL,我知道你们中有一些人是数据库的专家 + +870 +00:35:53,025 --> 00:35:55,324 +there is SQLite on the iPhone. +在iPhone上也会用到SQLite数据库 + +871 +00:35:55,326 --> 00:35:58,060 +SQL is for those of you who are not database experts, +SQL语句是为了帮助那些对数据库不是非常精通的人用的 + +872 +00:35:58,062 --> 00:36:01,063 +SQL is basically a programming language for databases. +SQL是基于数据库的一种编程语言 + +873 +00:36:01,065 --> 00:36:04,599 +Okay, for creating tables and columns and rows and +用于创建表的列和行 + +874 +00:36:04,601 --> 00:36:06,067 +tables and all that. +还有关于表的所有信息 + + +875 +00:36:06,069 --> 00:36:08,903 +And you can, if you have a bunch of code lying around +当然你也可以,如果你有一堆需要使用SQL语句 + +876 +00:36:08,905 --> 00:36:11,072 +that you had to write to a SQL database, +写入数据库的代码 + +877 +00:36:11,074 --> 00:36:13,207 +then you could certainly use SQLite. +接下来你才可以使用SQLite数据库了 + +878 +00:36:13,209 --> 00:36:15,175 +And the next thing I'm gonna talk about, or +接下去我将要说的东西 + +879 +00:36:15,177 --> 00:36:17,744 +the thing I'm gonna talk about the end here, Core Data, +或是我将在这里介绍关于数据库的最后的知识,Core Data, + +880 +00:36:17,746 --> 00:36:19,212 +it uses SQL underneath, okay. +当然,它也是基于SQL的 + +881 +00:36:19,214 --> 00:36:23,015 +It's writing all its data to an SQL database as well. +它也会将所有的数据写入一个SQL数据库 + +882 +00:36:23,017 --> 00:36:25,117 +But probably not gonna access it directly. +但是很有可能不会直接获取这个数据库 + +883 +00:36:25,119 --> 00:36:26,551 +The interface, +这个接口 + +884 +00:36:26,553 --> 00:36:30,988 +the programming interface to SQLite is like a C API. +程序与SQLite连接的接口类似于C语言中的一个API + +885 +00:36:30,990 --> 00:36:34,325 +It'll work in Swift cuz Swift has compatibility with C APIs. +这在Swift中同样有效是因为Swift语言与C的API是兼容的 + +886 +00:36:34,327 --> 00:36:36,994 +But it's a little hard to use cuz it's gonna have +但是这样使用起来可能会有些困难 + +887 +00:36:36,996 --> 00:36:40,063 +weird things like, you know, pointers into memory and +因为这样会出现一些奇怪的东西,比如说 + +888 +00:36:40,065 --> 00:36:42,732 +things like that, that Swift doesn't really, +类似于指针进入内存中的概念,这在Swift语言中是没有这种概念的 + +889 +00:36:42,734 --> 00:36:44,334 +it has ways to adapt to this. +它有其他的途径来实现这种概念 + +890 +00:36:44,336 --> 00:36:46,736 +So that you can do it, but it's not really native, +尽管你还是可以实现这个效果,但这样不是语言原生的 + +891 +00:36:46,738 --> 00:36:48,971 +it's not part of Swift's way of doing things. +这不是Swift语言处理东西的方法 + +892 +00:36:48,973 --> 00:36:52,240 +So it'll be a little odd for those of you who are used to +所以对于那些正在使用Swift或是尝试使用Swift语言 + +893 +00:36:52,242 --> 00:36:55,443 +Swift, to try and program this SQL API using Swift. +来编辑SQL API的人来说,这样会有些奇怪 + +894 +00:36:55,445 --> 00:36:56,511 +But it can be done. +但还是可以做到 + +895 +00:36:56,513 --> 00:36:59,180 +And I'll have to look up how to do it. +所以我将会去改善这种处理方式 + +896 +00:36:59,182 --> 00:37:00,348 +All right. +总而言之 + +897 +00:37:00,349 --> 00:37:01,515 +So the last two things I'm gonna talk about is +我接下去会讲的最后2个概念 + +898 +00:37:01,517 --> 00:37:02,549 +the File System and Core Data. +就是File System和Core Data + +899 +00:37:02,551 --> 00:37:04,684 +So the File System is very simple, okay. +首先File System是非常简单的 + +900 +00:37:04,686 --> 00:37:09,288 +Your device, your iOS device, has a Unix filesystem. +你的设备,只要是使用iOS系统的设备,都有一个基于Unix内核的文件系统 + +901 +00:37:09,290 --> 00:37:13,458 +Okay, because I told you the very first day of this class, +因为我在我们第一天的课上就告诉过你们 + +902 +00:37:13,460 --> 00:37:16,961 +basically Unix is underlying a variant of Unix, +基本上MAC系统、BSD Unix系统都是 + +903 +00:37:16,963 --> 00:37:19,497 +BSD, Mac is underneath all of iOS, +都是基于Unix内核的变种 + +904 +00:37:19,499 --> 00:37:22,767 +it's providing the kinda core OS services. +它提供了部分core OS services层上的服务 + +905 +00:37:22,769 --> 00:37:24,068 +So you have the Unix filesystem there. +所以你的文件系统是基于Unix内核的 + +906 +00:37:24,070 --> 00:37:26,336 +And if you want to store things in the File System, +然后如果你想要使用File Systm来存储数据 + +907 +00:37:26,338 --> 00:37:28,405 +you just store them in this Unix filesystem. +你就是将数据存储到你的Unix系统的文件系统中 + +908 +00:37:28,407 --> 00:37:31,374 +Now, kinda four steps to do that. +那么现在你需要做4步来实现这个操作 + +909 +00:37:31,376 --> 00:37:35,144 +One is you have to get the root path, it's true, +首先,你需要有个根路径 + +910 +00:37:35,146 --> 00:37:38,447 +some URL, file system URL, not HTTP URL, +你将要把文件写入或是读取的路径 + +911 +00:37:38,449 --> 00:37:42,250 +that you're going to write or read from, okay. +这个路径是基于文件系统的URL,不是类似于HTTP请求的URL + +912 +00:37:42,252 --> 00:37:45,053 +So, you basically got to start somewhere in the File System. +所以,你基本上就是把文件存在文件系统的某个地方 + +913 +00:37:45,055 --> 00:37:47,889 +Now, it's a Unix filesystem, of course it starts at slash, +现在,这个一个基于Unix内核的文件系用,当然你将从某个斜线(../)开始 + +914 +00:37:47,891 --> 00:37:49,290 +but you can't write in slash, +但是你不能将文件写入这个斜线下 + +915 +00:37:49,292 --> 00:37:51,258 +that's the, you know, root directory. +因为你应该知道的,斜线是从根目录开始的 + +916 +00:37:51,260 --> 00:37:53,460 +You have to write somewhere down, slash, slash something, +你不得不写在从你开始的地方的目录 + +917 +00:37:53,462 --> 00:37:54,794 +slash something, slash something, +斜线之后的某个斜线下 + +918 +00:37:54,796 --> 00:37:55,962 +that's where you get to start. +类似于../../../ + +919 +00:37:55,964 --> 00:37:58,431 +So finding that root path is the first step and +所以首先设定好根路径是第一步 + +920 +00:37:58,433 --> 00:38:00,165 +we'll show you how to do that. +我会向你展示这是怎么做的 + +921 +00:38:00,167 --> 00:38:03,969 +Then you're gonna append the path components onto that URL. +接下来你就会发现这个URL是由文件路径组成的 + +922 +00:38:03,971 --> 00:38:07,739 +So, if you want to create some directories in that place and +所以,如果你想要先创建某个目录再在目录下存储文件 + +923 +00:38:07,741 --> 00:38:11,042 +then some files, you're gonna be using appends and +你需要使用append方法将路径 + +924 +00:38:11,044 --> 00:38:13,210 +NSURL has some methods to do that. +转换成NSUrl形式 + +925 +00:38:13,212 --> 00:38:16,714 +And then you're going to read and write files from that URL. +然后你就可以通过这个URL读取或是写入这个文件 + +926 +00:38:16,716 --> 00:38:18,148 +And we'll talk about how you do that. +当然我们会谈论关于怎样来实现 + +927 +00:38:18,150 --> 00:38:20,417 +And finally, you're gonna manage the filesystem. +最后,你也可以管理这个文件系统 + +928 +00:38:20,419 --> 00:38:23,920 +You might wanna remove a file, you might wanna rename a file, +比如你想要删除文件,或是重命名一个文件 + +929 +00:38:23,922 --> 00:38:26,922 +you might wanna see what files are in a directory, and +你也可以看在目录下的文件是什么格式的 + +930 +00:38:26,924 --> 00:38:29,892 +that's all done with this class, NSFileManager. +这些操作都可以通过NSFileManager这个类来实现 + +931 +00:38:29,894 --> 00:38:31,226 +Okay. +知道了吗? + +932 +00:38:31,228 --> 00:38:32,144 +So that's it. +所以这个就是 + +933 +00:38:32,145 --> 00:38:33,061 +This is how the File System works. +关于File System是怎样运作的 + +934 +00:38:33,063 --> 00:38:35,763 +So let's look into all of these steps. +让我们回顾一下这整个过程 + +935 +00:38:35,765 --> 00:38:38,432 +So you see this File System, it starts at root. +我们来看这个文件系统, 它以根目录(/)开始 + +936 +00:38:38,434 --> 00:38:40,768 +It's a protected file system, though, so +它是一个被保护的文件系统,所以 + +937 +00:38:40,770 --> 00:38:43,470 +you can't see most of the stuff that's in root, or +在根目录下的大部分东西你看不到, + +938 +00:38:43,472 --> 00:38:45,805 +any of the system directories or whatever. +包括系统目录以及一些别的。 + +939 +00:38:45,807 --> 00:38:48,775 +It's not readable by you. +你无法读取。 + +940 +00:38:48,777 --> 00:38:52,578 +So, there is a part of the Unix filesystem there, though, +但是有一部分 Unix 文件系统, + +941 +00:38:52,580 --> 00:38:56,582 +that is your application's own, it's called its sandbox. +是你的应用拥有的,叫做它的沙盒(sandbox) + +942 +00:38:56,584 --> 00:38:58,550 +Okay, and this is the only place you can write. +好了,这就是你唯一可以写入的地方。 + +943 +00:38:58,552 --> 00:39:01,453 +Some of the places in your own sandbox, you can't even write. +即使是在沙盒里面,有些位置你也不允许写入。 + +944 +00:39:01,455 --> 00:39:03,721 +Like the place where your actual application is, +比如存放应用自身的地方。 + +945 +00:39:03,723 --> 00:39:05,640 +you can't write there. +那里你无法写入。 + +946 +00:39:05,641 --> 00:39:07,558 +So you can't modify [LAUGH] your own code by writing +所以你无法通过修改应用存放的目录 + +947 +00:39:07,560 --> 00:39:09,960 +something in that directory or something. +来改动你的(二进制)代码 + +948 +00:39:09,962 --> 00:39:12,162 +Okay, but many of the directories, +Okay,但是沙盒里的很多目录, + +949 +00:39:12,164 --> 00:39:15,298 +subdirectories of your sandbox, you can write in. +子目录,都允许写入。 + +950 +00:39:15,300 --> 00:39:17,633 +So this is the place where you can write, and +这就是你可以写入的地方, + +951 +00:39:17,635 --> 00:39:19,835 +you can read everything in your sandbox. +而且你可以读取沙盒里面的所有内容。 + +952 +00:39:19,837 --> 00:39:23,072 +Then we'll talk about how you get a URL into your sandbox in +后面我们讨论如何拿到连接到沙盒内部的一个 URL , + +953 +00:39:23,074 --> 00:39:24,540 +a second. +稍等一下。 + +954 +00:39:24,541 --> 00:39:26,007 +Now, why do we do this sandboxing thing? +现在,为什么我们要做这样的沙盒模型呢? + +955 +00:39:26,010 --> 00:39:27,909 +For obvious reasons, for security. +明显的理由是为了安全。 + +956 +00:39:27,911 --> 00:39:30,511 +You don't want to be able to look into other apps and +你不想能够看到别人的 App, + +957 +00:39:30,513 --> 00:39:33,280 +see what's going on over there, and you don't want to +能够看到那里发生了什么;你不想能够 + +958 +00:39:33,282 --> 00:39:35,516 +be able to access the system directories and +访问系统目录并且 + +959 +00:39:35,518 --> 00:39:36,616 +mess up that iPhone. +把 iPhone 搞崩溃。 + +960 +00:39:36,618 --> 00:39:39,152 +So it's completely obvious, but there's one +这显而易见,但沙盒还存在 + +961 +00:39:39,154 --> 00:39:41,721 +slightly non-obvious reason to this sandbox, +一个不那么显而易见的理由, + +962 +00:39:41,723 --> 00:39:44,590 +is that since everything you are ever going to write on +既然你能写入的位置 + +963 +00:39:44,592 --> 00:39:46,425 +the local disk is in this sandbox. +被限制在本地存储的沙盒里, + +964 +00:39:46,427 --> 00:39:50,895 +If the user deletes your app you know, they go over here +那么如果用户删除了你的应用,他们来这 + +965 +00:39:50,897 --> 00:39:55,199 +and hold down until the thing, it's the other one. +长摁直到发生一件事。 + +966 +00:39:55,201 --> 00:39:56,333 +Which one are we showing? +我们显示的是什么(切换投影显示iPad) + +967 +00:39:56,335 --> 00:39:57,100 +Yeah, this one. +嗯,这个。 + +968 +00:39:57,102 --> 00:39:58,468 +See them wiggling there? +看到它们左右摇晃没? + +969 +00:39:58,470 --> 00:40:01,504 +So, if they hold down wiggle, if they were to press x to +所以应用图标长摁开始摇晃后,如果点击叉叉 + +970 +00:40:01,506 --> 00:40:04,273 +delete it, it would delete your entire sandbox. +删掉它,这将会删除整个沙盒。 + +971 +00:40:04,275 --> 00:40:06,542 +So everything you've ever written is gone. +于是你写入的所有东西都没了。 + +972 +00:40:06,544 --> 00:40:07,542 +Okay? + +973 +00:40:07,544 --> 00:40:09,077 +Also, that's true for backup. +这对于备份也是一样。 + +974 +00:40:09,079 --> 00:40:12,246 +If they backup their phone to iTunes U, okay, or +如果用户把他们的手机备份到 iTunes U (口误) + +975 +00:40:12,248 --> 00:40:15,416 +iTunes and iTunes U, iTunes, then it would back +备份到 iTunes, 那将会 + +976 +00:40:15,418 --> 00:40:19,252 +up certain directories in your Sandbox, not all of them. +把沙盒里面的特定目录备份,不是所有的目录。 + +977 +00:40:19,254 --> 00:40:20,320 +Okay? + +978 +00:40:20,322 --> 00:40:22,889 +So, that's another reason to have this Sandbox. +所以,这就是使用沙盒的另一个原因。 + +979 +00:40:22,891 --> 00:40:23,689 +So, what's in there? +那么,那里有什么? + +980 +00:40:23,691 --> 00:40:24,990 +What's in the Sandbox? +沙盒里有什么? + +981 +00:40:24,992 --> 00:40:27,726 +There's various bundles, which are directories. +那里有各种包 (bundle),以目录形式存在。 + +982 +00:40:27,728 --> 00:40:29,961 +There's the application bundle I talked about, +有我刚提到的应用包, + +983 +00:40:29,963 --> 00:40:31,829 +that's where your actual app is, okay? +它就是你的应用的实体,okay? + +984 +00:40:31,831 --> 00:40:33,431 +And everything there is read-only. +里面所有的内容都是只读的。 + +985 +00:40:33,433 --> 00:40:34,832 +All your storyboards in there. +你所有的 storyboard 都在里面。 + +986 +00:40:34,834 --> 00:40:36,900 +If you have JPEGs that are in your image assets, +你的 image assets 里的 jpg 文件, + +987 +00:40:36,902 --> 00:40:37,967 +they're all in there. +也在里面。 + +988 +00:40:37,969 --> 00:40:39,168 +They're all read-only. +统统只读。 + +989 +00:40:39,170 --> 00:40:41,971 +If you put something in there you needed to edit, +如果你想要在里面放置一些需要编辑的东西, + +990 +00:40:41,973 --> 00:40:43,739 +like maybe some SQL database or +比如数据库文件或者 + +991 +00:40:43,741 --> 00:40:46,341 +something you put in there or some data file. +别的数据文件, + +992 +00:40:46,343 --> 00:40:48,943 +You would have to copy it out of the application bundle into +你必须把它从应用包里面复制出来, + +993 +00:40:48,945 --> 00:40:51,279 +one of these other directories in your Sandbox, and +放到沙盒里的一个子目录里面, + +994 +00:40:51,281 --> 00:40:52,646 +then you could edit it there. +然后再去编辑它。 + +995 +00:40:52,648 --> 00:40:54,565 +Okay? + +996 +00:40:54,566 --> 00:40:56,483 +So, you can ship your app with things you're gonna edit, but +这样你就带着你的 App 和将要修改的部分一同发布了, + +997 +00:40:56,485 --> 00:40:59,553 +you just have to copy them out of your application directory. +但是你必须把它复制到应用目录外面去。 + +998 +00:40:59,555 --> 00:41:01,187 +And then, there's also other directories in there. +当然,那里还存在别的目录。 + +999 +00:41:01,189 --> 00:41:04,223 +The documents directory, that's where you should store +Documents 目录,这里是存放 + +1000 +00:41:04,225 --> 00:41:06,659 +what the user perceives as their data, okay? +用户数据的地方。 + +1001 +00:41:06,661 --> 00:41:09,461 +The things they're creating and editing and +用户创建编辑并且拥有的数据, + +1002 +00:41:09,463 --> 00:41:12,531 +owning that they expect to be there all the time. +最好一直都在这个目录下。 + +1003 +00:41:12,533 --> 00:41:14,399 +Even if you don't, kind of, +即使你没有, + +1004 +00:41:14,401 --> 00:41:17,735 +divide it up into a document in your UI, it's still, +从你的 UI 里分离出一个文档,它依然存在。 + +1005 +00:41:17,737 --> 00:41:20,671 +that's what the documents directory is for. +这就是 Documents 目录的作用。 + +1006 +00:41:20,673 --> 00:41:22,406 +There's also a caches directory. +缓存目录。 + +1007 +00:41:22,408 --> 00:41:25,442 +This is for data that you could throw away. +这是存放那些可以被丢弃的数据的地方。 + +1008 +00:41:25,444 --> 00:41:26,976 +So, it's some information you got from +假设你从互联网上下载了一些数据, + +1009 +00:41:26,978 --> 00:41:29,112 +the Internet that you can go back to the Internet, but, +你可以再次访问互联网去下载,但是, + +1010 +00:41:29,114 --> 00:41:31,313 +it might be slow to go to the Internet, so you're going to +再次联网可能会比较慢,所以你希望 + +1011 +00:41:31,315 --> 00:41:33,215 +keep a local copy, but, you could throw it away. +保留一个本地副本,但是,你可以把它丢弃掉。 + +1012 +00:41:33,217 --> 00:41:35,917 +That directory, for example, wouldn't get backed up +这个目录, 不会被备份到 + +1013 +00:41:35,919 --> 00:41:38,520 +to iTunes, okay, if someone plugged their phone in, +iTunes, 在用户接入了他的 iPhone 去备份的时候。 + +1014 +00:41:38,522 --> 00:41:40,888 +because they figure you can recreate it, okay? +因为他们认为你可以重新创建它。 + +1015 +00:41:40,890 --> 00:41:42,189 +And there's a bunch of others, +还有一些别的东西 + +1016 +00:41:42,191 --> 00:41:44,191 +there's about a dozen different directories. +各种不同的目录。 + +1017 +00:41:44,193 --> 00:41:47,728 +And, you find all these directories by looking +你可以在文档中查到所有的目录, + +1018 +00:41:47,730 --> 00:41:52,231 +in the documentation for the term NSSearchPathDirectory. +搜索术语 NSSearchPathDirectory 就行。 + +1019 +00:41:52,233 --> 00:41:54,517 +Okay? + +1020 +00:41:54,518 --> 00:41:56,802 +And, I'll talk about that in a second as well. +我过一会儿再讨论这个。 + +1021 +00:41:56,804 --> 00:42:00,772 +So, how do you get the URL to these special +那么,你怎样获得一个指向 + +1022 +00:42:00,774 --> 00:42:03,742 +directories in your Sandbox? +沙盒里的特定目录的 URL ? + +1023 +00:42:03,744 --> 00:42:05,910 +You do it with this file manager class, +你可以使用文件管理的类, + +1024 +00:42:05,912 --> 00:42:07,178 +this NSFileManager. +也就是 NSFileManager. + +1025 +00:42:07,180 --> 00:42:10,481 +Now, NSFileManager, there's actually a class +现在, NSFileManager 有个类方法 + +1026 +00:42:10,483 --> 00:42:13,283 +function called, DefaultFileManager, +DefaultFileManager, + +1027 +00:42:13,285 --> 00:42:16,419 +that will give you the default NSFileManager. +返回默认的 NSFileManager 实例。 + +1028 +00:42:16,421 --> 00:42:19,655 +The only thing to be a little careful about that one is, +唯一需要稍微注意的是, + +1029 +00:42:19,657 --> 00:42:21,557 +NSFileManager is thread safe. +NSFileManager 是线程安全的。 + +1030 +00:42:21,559 --> 00:42:23,792 +And a lot of times, you might want to read and +许多情况下,你可能会 + +1031 +00:42:23,794 --> 00:42:26,161 +write a very large file in a different thread. +在不同的线程里读写同一个大文件。 + +1032 +00:42:26,163 --> 00:42:27,946 +Okay? + +1033 +00:42:27,947 --> 00:42:29,730 +And NSFileManager is completely thread safe, +NSFileManager 是完全线程安全的, + +1034 +00:42:29,733 --> 00:42:31,716 +but only for +条件是 + +1035 +00:42:31,717 --> 00:42:33,700 +an NSFileManager instance that is created in that thread. +一个 NSFileManager 实例只在创建它的线程里使用。 + +1036 +00:42:33,703 --> 00:42:36,370 +In other words, you should never create an NSFileManager +换句话说,你不应该在一个线程里创建 NSFileManager 实例, + +1037 +00:42:36,372 --> 00:42:38,872 +instance in one thread and then use it in another one. +然后在另一个线程里使用它。 + +1038 +00:42:38,874 --> 00:42:40,440 +That's not thread safe. +这就不再线程安全了。 + +1039 +00:42:40,442 --> 00:42:42,008 +Okay? + +1040 +00:42:42,009 --> 00:42:43,575 +But, even if you're accessing the same files, +但是,即使你访问同样的文件, + +1041 +00:42:43,578 --> 00:42:46,012 +trying to remove or look at the same directories, +删除或者查看同样的目录, + +1042 +00:42:46,014 --> 00:42:47,480 +that's all perfectly fine, +这都是没问题的, + +1043 +00:42:47,482 --> 00:42:49,948 +as long as each thread has its own NSFileManager. +只要每个线程使用它自己的 NSFileManager。 + +1044 +00:42:49,950 --> 00:42:52,551 +So the NSFileManager DefaultFileManager, +所以 NSFileManager 跟 DefaultFileManager, + +1045 +00:42:52,553 --> 00:42:54,886 +you'll see that in the documentation. +你可以查看相关文档。 + +1046 +00:42:54,888 --> 00:42:57,822 +That one is kind of your main thread, DefaultFileManager. +DefaultFileManager 在主线程。 + +1047 +00:42:57,824 --> 00:43:00,224 +If you're only gonna use it on the main queue, +如果你是在 main queue 里使用, + +1048 +00:43:00,226 --> 00:43:01,592 +then you can use that one. +你可以使用 DefaultFileManager。 + +1049 +00:43:01,594 --> 00:43:02,893 +Otherwise, just create an instance. +否则,创建一个实例。 + +1050 +00:43:02,895 --> 00:43:05,095 +It's pretty light-weight to create an instance of +新建 NSFileManager 实例很轻量级, + +1051 +00:43:05,097 --> 00:43:06,763 +NSFileManager just like this, okay, +就像这样。 + +1052 +00:43:06,765 --> 00:43:08,698 +let fileManager equal NSFileManager(). +let fileManager = NSFileManager() + +1053 +00:43:08,700 --> 00:43:11,700 +So, once you have a file manager, then you can send it +一旦你有了一个 fileManager, 你可以给他发送这个消息, + +1054 +00:43:11,702 --> 00:43:14,302 +this message, URLsForDirectory inDomain. +URLsFOrDirectory(:, inDomain:) + +1055 +00:43:14,304 --> 00:43:17,739 +And that will tell you, it gives you, actually, +这会告诉你,返回 + +1056 +00:43:17,741 --> 00:43:20,742 +an array of all the documents directories, +一个 array,里面包含所有的文档目录, + +1057 +00:43:20,744 --> 00:43:22,810 +all the caches directories, +跟缓存目录, + +1058 +00:43:22,812 --> 00:43:25,746 +all the application bundle directories. +以及所有的应用包目录。 + +1059 +00:43:25,748 --> 00:43:27,314 +Now, why is this an array? +为什么这是个 array? + +1060 +00:43:27,316 --> 00:43:29,649 +Well, on iOS, it doesn't matter. +在 iOS 上,没问题。 + +1061 +00:43:29,651 --> 00:43:32,552 +There's always only one thing in this array, okay, and +通常这个 array 里只有一个东西, + +1062 +00:43:32,554 --> 00:43:34,787 +that's the user's documents directory, +就是用户的 Documents 目录, + +1063 +00:43:34,789 --> 00:43:36,555 +the user's cache's directory. +用户的缓存目录。 + +1064 +00:43:36,557 --> 00:43:38,724 +And that's because on iPhone, +因为在 iPhone 上, + +1065 +00:43:38,726 --> 00:43:41,359 +you only have the user's resources. +你只拥有用户的资源。 + +1066 +00:43:41,361 --> 00:43:44,929 +But this API works on a Mac as well, and on the Mac, +不过这个 API 在 Mac 上也能工作, 在 Mac 上, + +1067 +00:43:44,931 --> 00:43:48,232 +you might have the user's document history or +你可能获得用户的文档历史或者 + +1068 +00:43:48,234 --> 00:43:49,933 +a cache's directory. +一个缓存目录。 + +1069 +00:43:49,935 --> 00:43:53,036 +You might have the computers, and then you might even have +你可能拿到多个电脑, 然后你甚至可能拿到 + +1070 +00:43:53,038 --> 00:43:55,372 +the networks, okay, the local networks. +网络信息, 本地网络。 + +1071 +00:43:55,374 --> 00:43:57,240 +That's why you might get multiple of these. +这就是为什么你可能拿到多个数据。 + +1072 +00:43:57,242 --> 00:43:59,675 +So, don't be freaked out by the fact that this returns +所以, 不要被它返回一个 NSURL 的 array 吓到。 + +1073 +00:43:59,677 --> 00:44:02,244 +an array of NSURLs, there's always only going to be one. +通常情况下它只有一个。 + +1074 +00:44:02,246 --> 00:44:04,246 +You can just use the first one in there. +你可以使用里面的第一个元素。 + +1075 +00:44:04,248 --> 00:44:07,716 +And, that is going to be a URL that points to this kind of +这将是一个指向这类目录的 URL, + +1076 +00:44:07,718 --> 00:44:10,585 +directory like the documents directory, or +比如说 Documents 目录 , + +1077 +00:44:10,587 --> 00:44:13,154 +the cache's directory, or whatever. +或者缓存目录,或者别的。 + +1078 +00:44:13,156 --> 00:44:16,657 +And, you specify which one you want with that first argument, +你要指定第一个参数, + +1079 +00:44:16,659 --> 00:44:18,191 +NSSearchPathDirectory. +NSSearchPathDirectory。 + +1080 +00:44:18,193 --> 00:44:21,461 +And, you have to go look in the documentation and +你需要去查看一下文档, + +1081 +00:44:21,463 --> 00:44:24,097 +see what the special names of them are. +看看可选择的名称是什么。 + +1082 +00:44:24,099 --> 00:44:25,898 +But there's, like, NSDocumentsDirectory, +不过,下面几个可用,比如 NSDocumentsDirectory, + +1083 +00:44:25,900 --> 00:44:27,866 +NSCachesDirectory, NSDocumentationDirectory. +NSCachesDirectory, NSDocumentationDirectory. + +1084 +00:44:27,868 --> 00:44:30,702 +By the way, be careful with NSDocumentationDirectory +顺便提一句, 小心 NSDocumentationDirectory 跟 + +1085 +00:44:30,704 --> 00:44:32,337 +versus NSDocumentsDirectory. +NSDocumentsDirectory 的区别。 + +1086 +00:44:32,339 --> 00:44:35,573 +I can't tell you how many final projects people post in +我数不清有多少做最终大作业的人公开抱怨, + +1087 +00:44:35,575 --> 00:44:39,076 +Piazza, and they'll say, I've been trying to write to my +说我尝试写入 NSDocumentsDirectory, + +1088 +00:44:39,078 --> 00:44:42,513 +NSDocumentsDirectory for days but it says not writable. +但是出错了,无法写入。 + +1089 +00:44:42,515 --> 00:44:44,781 +And it's because they've been trying to write to +原因是他们写入的对象, + +1090 +00:44:44,783 --> 00:44:47,350 +the NSDocumentationDirectory, which is read-only. +实际上是 NSDocumentationDirectory, 这是只读的。 + +1091 +00:44:47,352 --> 00:44:49,619 +Okay, that's documentation that ships with your app. +它是跟你的应用一起发布的文档。 + +1092 +00:44:49,621 --> 00:44:52,221 +So be careful with the escape completion there, +所以小心那里的自动完成, + +1093 +00:44:52,223 --> 00:44:54,123 +NSDocuments is the writeable one, +NSDocuments 可写的, + +1094 +00:44:54,125 --> 00:44:56,558 +okay, NSDocumentation is documentation. +NSDocumentation 是文档。 + +1095 +00:44:56,560 --> 00:44:58,193 +All right? + +1096 +00:44:58,195 --> 00:45:00,461 +So, now you have the URL to the root of one of these +所以, 你现在拥有一个指向这些的根目录的 URL, + +1097 +00:45:00,463 --> 00:45:02,496 +things, like the document's directory, +比如存档目录, + +1098 +00:45:02,498 --> 00:45:03,697 +the cache's directory. +缓存目录。 + +1099 +00:45:03,699 --> 00:45:05,766 +And, now you want to write some files in there. +现在你想在里面写入一些文件, + +1100 +00:45:05,768 --> 00:45:09,302 +Well, you're going to use URLs, NSURLs methods, +你可以使用 URL, NSURL 的方法, + +1101 +00:45:09,304 --> 00:45:11,804 +URLByAppendingPathComponent, or +URLByAppendingPathComponent, 或者 + +1102 +00:45:11,806 --> 00:45:14,173 +URLByAppendingPathExtension. +URLByAppendingPathExtension. + +1103 +00:45:14,175 --> 00:45:18,810 +Some extensions like .jpg, or whatever, .doc, +比如 .jpg, .doc 这样的扩展名, + +1104 +00:45:18,812 --> 00:45:22,313 +got some document format of some sort. +拿到一些文档格式信息。 + +1105 +00:45:22,315 --> 00:45:23,981 +And so, that's how you're gonna do that. +这就是你处理的方法。 + +1106 +00:45:23,983 --> 00:45:26,550 +And, by appending multiple path components, +并且, 后面补上多个 path component(目录名外加目录分隔符), + +1107 +00:45:26,552 --> 00:45:29,353 +you can build things inside directories, right? +你就可以在目录里面创建东西。 + +1108 +00:45:29,355 --> 00:45:33,056 +So I can say a path component, today's documents. +比如今天讨论的 path componet, documents. + +1109 +00:45:33,058 --> 00:45:37,060 +And then path component foo, and that would be a directory, +然后再来个 path componet foo, 这会是个目录, + +1110 +00:45:37,062 --> 00:45:40,129 +today's documents, and inside foo, okay? +先是 documents, 然后在 foo 的里面。 + +1111 +00:45:40,131 --> 00:45:41,530 +So that's how you build up the URL. +所以这就是创建一个 URL 的方法。 + +1112 +00:45:41,532 --> 00:45:44,866 +So, once you have a URL, you can find out some things, +一旦你拥有了一个URL, 你可以发现一些事情, + +1113 +00:45:44,868 --> 00:45:47,702 +like, about it, like, is this a file URL, or +比如, 这是一个文件的 URL, + +1114 +00:45:47,704 --> 00:45:49,103 +is this a network URL? +还是一个网络 URL? + +1115 +00:45:49,105 --> 00:45:51,772 +Sometimes, you wanna know that because you're accessing +有时候你想要知道这些,因为 + +1116 +00:45:51,774 --> 00:45:54,141 +an image, and you wanna know whether it's on disk or +在你访问一个图片时,你想要确定它是在本地磁盘上, + +1117 +00:45:54,143 --> 00:45:55,542 +whether it's on the network, +还是在远程网络上。 + +1118 +00:45:55,544 --> 00:45:56,976 +you might put one in the thread. +你可以把它放在线程里面。 + +1119 +00:45:56,978 --> 00:45:58,862 +Cuz some people ask, +因为有些人问, + +1120 +00:45:58,863 --> 00:46:00,747 +should I always access my file system in the thread? +我是不是应该把访问文件系统的代码都放在线程里? + +1121 +00:46:00,749 --> 00:46:02,515 +And the answer is, probably for +答案是,可能 + +1122 +00:46:02,517 --> 00:46:06,051 +small files unless they're, you know, megabyte size files. +对于那些好多MB的大文件需要,小文件不需要。 + +1123 +00:46:06,053 --> 00:46:08,353 +You're probably fine to access them in the main queue. +你在 main queue 里访问这些小文件可能没什么问题。 + +1124 +00:46:08,355 --> 00:46:10,021 +It's pretty fast, that flash memory, +在闪存里速度相当快, + +1125 +00:46:10,023 --> 00:46:11,956 +pretty quick at getting the information back. +很快就拿回数据, + +1126 +00:46:11,958 --> 00:46:13,924 +You probably don't need to do that. +你可能不需要做更多的事情。 + +1127 +00:46:13,926 --> 00:46:16,760 +It couldn't hurt, especially, if you already have +它可能会伤害到体验,特别是,你已经有了 + +1128 +00:46:16,762 --> 00:46:19,496 +the code to deal with the fact that file might be over +处理可能存在远程网络的文件的代码, + +1129 +00:46:19,498 --> 00:46:22,599 +the network, might as well do it for the local file, too. +同时也用它来处理本地文件。 + +1130 +00:46:22,601 --> 00:46:25,468 +There is also a very important method that's a little bit +有个比较重要的方法被掩盖在 + +1131 +00:46:25,470 --> 00:46:28,604 +buried in the documentation called resourceValuesForKeys. +文档之中,叫做 resourceValuesForKeys。 + +1132 +00:46:28,606 --> 00:46:30,773 +This is how you get things like, +这是你用于获取类似 + +1133 +00:46:30,775 --> 00:46:33,108 +when was this file last accessed? +这个文件最后的访问时间的方法。 + +1134 +00:46:33,110 --> 00:46:34,443 +'Kay? + +1135 +00:46:34,444 --> 00:46:35,777 +How big is this file in bytes, 'kay? +也可以获取以byte为单位,文件的大小信息。 + +1136 +00:46:35,779 --> 00:46:39,681 +That's this NSURL thing, resourceValuesForKeys. +这就是 NSURL 的 resourceValuesForKeys 方法的作用。 + +1137 +00:46:39,683 --> 00:46:43,150 +When you give it the keys, like files last change date or +当你指定了类型, 比如文件最后修改日期或者别的 + +1138 +00:46:43,152 --> 00:46:46,553 +whatever, and it's going to return in a dictionary, +相关信息会在返回的字典里提供, + +1139 +00:46:46,555 --> 00:46:49,756 +rather, with those keys you gave and the values for +进一步的,指定更多的类型则返回所有的 + +1140 +00:46:49,758 --> 00:46:51,458 +all those things, 'kay? +相关信息。 + +1141 +00:46:51,460 --> 00:46:52,792 +Permissions, all that stuff. +权限信息啦,等等。 + +1142 +00:46:52,794 --> 00:46:56,062 +resourceValuesForKeys. +resourceValuesForKeys. + +1143 +00:46:56,064 --> 00:46:58,030 +All right, now, I've got a URL, +现在我有了一个 URL, + +1144 +00:46:58,032 --> 00:47:00,132 +I want to write to the file system. +我想要写入到文件系统。 + +1145 +00:47:00,134 --> 00:47:03,801 +How do I write something to the file system given the URL? +这种情况下我如何把一些内容写入文件系统? + +1146 +00:47:03,803 --> 00:47:05,503 +And the answer is usually, +答案通常是, + +1147 +00:47:05,505 --> 00:47:07,738 +you're going to use NSData, okay? +你要使用NSData,okay? + +1148 +00:47:07,740 --> 00:47:10,574 +Might use the property list ones, like NSArray and +也可以使用 property list 支持的类型, 比如 NSArray 跟 + +1149 +00:47:10,576 --> 00:47:13,343 +NSDictionary and write a property list out to it. +NSDictionary 然后输出一个 property list 文件。 + +1150 +00:47:13,345 --> 00:47:16,412 +But you oftentimes can use NSData, cuz you have some +不过你时常得使用NSData, 因为你有一些图像数据或者 + +1151 +00:47:16,414 --> 00:47:19,415 +image data or some other data you want to write out, +其他类型的数据想要输出, + +1152 +00:47:19,417 --> 00:47:21,016 +sound files, something. +比如声音文件,等等。 + +1153 +00:47:21,018 --> 00:47:24,619 +And so, you do that with NSData's method writeToURL, +所以, 你只要调用 NSData 的方法, + +1154 +00:47:24,621 --> 00:47:26,171 +atomically. +writeToURL(NSURL, automically: Bool) + +1155 +00:47:26,172 --> 00:47:27,722 +And so, writeToURL, you just give it a URL. +这样, writeToURL, 你只要提供一个 URL。 + +1156 +00:47:27,724 --> 00:47:30,157 +It will write that file out there. +它就能把文件写到那里去。 + +1157 +00:47:30,159 --> 00:47:34,061 +And the atomically means, write a temporary file, +atomically 参数的意思是,先写一个临时文件, + +1158 +00:47:34,063 --> 00:47:36,730 +and then, remove the old file, and +然后删掉老的文件, + +1159 +00:47:36,732 --> 00:47:39,866 +put the new one in an atomic transaction. +再将新的临时文件移过去,整个过程保持原子级。 + +1160 +00:47:39,868 --> 00:47:41,401 +Okay? + +1161 +00:47:41,402 --> 00:47:42,935 +That way, if something happens in the middle of writing +这样,如果在写文件的过程种发生了什么, + +1162 +00:47:42,937 --> 00:47:44,903 +the file, the file won't be half written. +文件不会是个半成品。 + +1163 +00:47:44,905 --> 00:47:46,872 +Okay? + +1164 +00:47:46,873 --> 00:47:48,840 +It'll be always a completely written file. +它永远是个完整的写入文件。 + +1165 +00:47:48,842 --> 00:47:50,608 +And it'll return a Boolean, +返回的布尔值, + +1166 +00:47:50,610 --> 00:47:52,744 +as to whether that was successful. +表示操作是否成功。 + +1167 +00:47:52,746 --> 00:47:53,995 +Okay? + +1168 +00:47:53,996 --> 00:47:55,245 +So, that's the primary way you're going to write. +这是一个首要的写文件的办法。 + +1169 +00:47:55,248 --> 00:47:56,714 +That's how we're gonna do it in the demo. +也是我们在 demo 里采用的方式。 + +1170 +00:47:56,715 --> 00:47:58,181 +That's the number one way you're going to write. +这是写文件的排行第一的方法。 + +1171 +00:47:58,184 --> 00:48:00,917 +I told you that NSFileManager could do other things, too, +我告诉过你们 NSFileManager 也能做别的事情。 + +1172 +00:48:00,919 --> 00:48:03,319 +manipulate the file system, create directories, +修改文件系统,创建目录, + +1173 +00:48:03,321 --> 00:48:04,370 +things like that. +这类事情。 + +1174 +00:48:04,371 --> 00:48:05,420 +You're gonna have to look at the documentation. +你们必须去查看文档。 + +1175 +00:48:05,423 --> 00:48:06,689 +There's quite a few functions in there. +那里有一些函数。 + +1176 +00:48:06,691 --> 00:48:08,190 +It also has a delegate. +它也有个 delegate。 + +1177 +00:48:08,192 --> 00:48:09,958 +Where it'll let you control things. +可以让你来控制事物。 + +1178 +00:48:09,960 --> 00:48:12,861 +There's like, should write file at path. +比如说应该在某个路径写文件。 + +1179 +00:48:12,863 --> 00:48:16,997 +Something along those lines where it's basically shoulds +沿着这些是否应该发生的线路, + +1180 +00:48:16,999 --> 00:48:20,434 +that you can control whether something happens. +你可以控制一些事情是否发生。 + +1181 +00:48:20,436 --> 00:48:22,869 +And, so you can look all that up on documentations really, +你们可以去查看以上的相关文档, + +1182 +00:48:22,871 --> 00:48:24,971 +it doesn't make sense for me to go over it all here. +我不可能在这里把它们都过一边。 + +1183 +00:48:24,973 --> 00:48:27,206 +>> [COUGH]. + +1184 +00:48:27,208 --> 00:48:30,176 +>> Okay, so that's the file system, and +好了,这些是文件系统。 + +1185 +00:48:30,178 --> 00:48:33,512 +I will be demoing that in a moment in Trax. +待会儿我会在 Trax 里用它们做演示。 + +1186 +00:48:33,514 --> 00:48:35,547 +But first I want to talk about Core Data, +不过首先我要讨论一下 Core Data。 + +1187 +00:48:35,549 --> 00:48:37,082 +the last persistence thing. +最后的持久存储相关内容。 + +1188 +00:48:37,084 --> 00:48:39,250 +How many people here are doing Core Data for +这里有多少人在他们的最终大作业里 + +1189 +00:48:39,252 --> 00:48:40,418 +their final project? +使用了 Core Data? + +1190 +00:48:40,420 --> 00:48:42,920 +Wow, okay, so half of you. +Wow, 一半啊。 + +1191 +00:48:42,922 --> 00:48:44,522 +That's great. +好现象。 + +1192 +00:48:44,523 --> 00:48:46,123 +I'm really, really, really happy about that, +对此我非常非常非常满意。 + +1193 +00:48:46,125 --> 00:48:48,558 +cuz I didn't teach Core Data in detail this quarter. +因为我没有在这学期里教授 Core Data 的细节。 + +1194 +00:48:48,560 --> 00:48:50,126 +So I was hoping a lot of you would do it as your +我希望你们里面的许多人能 + +1195 +00:48:50,128 --> 00:48:51,477 +final project. +在最终大作业里使用它。 + +1196 +00:48:51,478 --> 00:48:52,827 +Cuz Core Data is actually an important thing to know. +因为 Core Data 实际上是个很重要的东西。 + +1197 +00:48:52,830 --> 00:48:54,630 +Not just as a way to store data but +不仅仅是一种存储的方法, + +1198 +00:48:54,632 --> 00:48:57,599 +it's just conceptually understanding a little bit +它也是概念性地了解部分 + +1199 +00:48:57,601 --> 00:49:00,335 +more about how iOS works, and things like that. +iOS 如何工作等相关事情的途径。 + +1200 +00:49:00,337 --> 00:49:03,004 +Core Data, if you can figure out how to do that, +如果你搞定了 Core Data, + +1201 +00:49:03,006 --> 00:49:06,073 +then you understood a little more about how iOS works. +你就了解了更多 iOS 工作的原理。 + +1202 +00:49:06,075 --> 00:49:08,308 +So for those of you who are not doing Core Data, I'll go +所以对于那些不去接触 Core Data 的同学, + +1203 +00:49:08,310 --> 00:49:10,544 +through this quickly since most of you are doing it, but +既然你们多数人会用到它,我会快速过一遍。 + +1204 +00:49:10,546 --> 00:49:12,095 +what is Core Data? +什么是 Core Data ? + +1205 +00:49:12,096 --> 00:49:13,645 +It's basically a way to store your data in a SQL +基本上它是一种把你的数据存放在 + +1206 +00:49:13,648 --> 00:49:16,582 +database, basically, but in a totally object oriented way. +SQL 数据库的方法, 通过一种完全是面向对象的方式。 + +1207 +00:49:16,584 --> 00:49:18,651 +So you don't have to issue any SQL commands or +所以你没必要去写 SQL 命令或者 + +1208 +00:49:18,653 --> 00:49:20,619 +anything like that, create rows and tables. +类似的东西,创建行啊,表啊什么的。 + +1209 +00:49:20,621 --> 00:49:22,487 +It's gonna create all that for you. +它会为你创建这些。 + +1210 +00:49:22,489 --> 00:49:26,724 +It's completely object-oriented API. +它完全是面向对象的 API。 + +1211 +00:49:26,726 --> 00:49:28,492 +It's a very powerful framework in iOS. +这是个非常强大的 iOS 的 framework。 + +1212 +00:49:28,494 --> 00:49:29,844 +It has a lot. +它有很多内容。 + +1213 +00:49:29,845 --> 00:49:31,195 +Most of you are getting it for your final project, +大部分人会在最终大作业里使用它, + +1214 +00:49:31,197 --> 00:49:33,296 +even though you're only going to touch the basic thing of +即使你只接触到非常基本的东西, + +1215 +00:49:33,298 --> 00:49:34,964 +setting properties and creating entities. +比如设置 property 跟创建 entity。 + +1216 +00:49:34,966 --> 00:49:37,567 +But there's a lot of really powerful querying things that. +它含有很多非常强大的查询相关的东西。 + +1217 +00:49:37,569 --> 00:49:40,036 +>> [COUGH]. >> Can happen in there. +可以在这里发生。 + +1218 +00:49:40,037 --> 00:49:42,504 +Most of the things you can do with SQL, you can do up in +你用 SQL 可以完成的大多数事情,都可以 + +1219 +00:49:42,507 --> 00:49:46,608 +the Core Data layer, things like optimistic locking and +在 Core Data 这一层实现。比如说乐观锁以及 + +1220 +00:49:46,610 --> 00:49:48,943 +all that stuff is all doable, so +类似的东西都可以实现, + +1221 +00:49:48,945 --> 00:49:51,612 +it's a pretty powerful mechanism. +所以它是一个非常强大的机制。 + +1222 +00:49:51,614 --> 00:49:52,646 +It is backed by SQL, but +它以 SQL 为基础实现, + +1223 +00:49:52,648 --> 00:49:54,348 +it can also be backed by other things. +它也可以用别的来实现, + +1224 +00:49:54,350 --> 00:49:56,983 +XML, or you could even actually get involved and +比如XML, 甚至你可以 + +1225 +00:49:56,985 --> 00:49:59,052 +store the data in your own format, but +用你自己实现的数据格式来实现, + +1226 +00:49:59,054 --> 00:50:01,020 +that would be very advanced usage. +不过这些是高级用法。 + +1227 +00:50:01,022 --> 00:50:01,887 +So how does it work? +所以它是怎么工作的? + +1228 +00:50:01,889 --> 00:50:03,022 +How does Core Data work, +Core Data 如何工作, + +1229 +00:50:03,024 --> 00:50:05,190 +you create this visual mapping in your schema. +你在你的 schema 里创建可视化的映射。 + +1230 +00:50:05,192 --> 00:50:08,326 +Okay, it's not like the parse that you saw at the Friday +这个不像是几周前的周五课程提到的 parse + +1231 +00:50:08,328 --> 00:50:11,229 +section a couple weeks ago, that's schemaless. +那里没有 shema。 + +1232 +00:50:11,231 --> 00:50:13,698 +It's basically creating its schema on the fly, right? +那基本上就是凭空创建 schema。 + +1233 +00:50:13,700 --> 00:50:16,734 +It creates the rows and tables as you ask for them. +只要你请求,它会创建行和表。 + +1234 +00:50:16,736 --> 00:50:19,169 +This one you define your schema upfront. +这一回你需要预先定义好 schema。 + +1235 +00:50:19,171 --> 00:50:20,737 +What are going to be your objects, +你的对象是什么, + +1236 +00:50:20,739 --> 00:50:23,339 +and what are going to be the object's properties on those +这些对象的属性又是 + +1237 +00:50:23,341 --> 00:50:25,391 +objects. +什么。 + +1238 +00:50:25,392 --> 00:50:27,442 +And then basically tables are kind of like classes if you +基本上一个表就像是一个类, + +1239 +00:50:27,445 --> 00:50:29,278 +want to think of it that way. +如果你想要用这样的方式去考虑。 + +1240 +00:50:29,280 --> 00:50:32,848 +And then the columns and the tables are kind of like vars. +然后表的列(column)就像是实例变量。 + +1241 +00:50:32,850 --> 00:50:36,384 +Okay and then coordinator provides a way to have these +然后 coordinator 提供了访问 + +1242 +00:50:36,386 --> 00:50:40,054 +@NSManaged vars, where literally you just set the var +@NSManaged 变量的方法,字面意思上你设置了变量值 + +1243 +00:50:40,056 --> 00:50:43,924 +and it's gonna be go set the information in the database, +则数据库里相应的信息会被改变, + +1244 +00:50:43,926 --> 00:50:47,795 +and of course you can query on all this stored data as well. +当然你可以查询所有存储的数据。 + +1245 +00:50:47,797 --> 00:50:50,163 +You create the schema with this visual map. +你用可视化映射的方式创建了 schema。 + +1246 +00:50:50,165 --> 00:50:54,667 +You do new file and you create this thing data, which uses the thing data model. +你操作新文件,于是你用 data model 创建了 data。 + +1247 +00:50:54,669 --> 00:50:58,070 +You're gonna get this thing, it kinda looks like this. +你会得到这个,看上去像是这样。 + +1248 +00:50:58,072 --> 00:50:59,989 +Okay? + +1249 +00:50:59,990 --> 00:51:01,907 +It's a graphical, piece of graph paper looking thing, and +它是图像化的,一张类似图纸的东西, + +1250 +00:51:01,909 --> 00:51:04,642 +you can actually create things that look like class like +你实际上可以创建跟类一样的东西,就像这个例子里的 + +1251 +00:51:04,644 --> 00:51:06,177 +photo and photographer here. +photo 跟 photographer 一样。 + +1252 +00:51:06,179 --> 00:51:08,846 +And then you can create the columns in the database, and +然后你可以在数据库里创建列, + +1253 +00:51:08,848 --> 00:51:10,615 +then you can create +然后你可以通过 + +1254 +00:51:10,616 --> 00:51:12,383 +relationships by controlled dragging between them. +拖拽来建立关联。 + +1255 +00:51:12,385 --> 00:51:15,452 +So you're gonna create your schema totally +所以你可以完全用图像化方式 + +1256 +00:51:15,454 --> 00:51:16,953 +graphically there. +来创建 schema。 + +1257 +00:51:16,955 --> 00:51:19,222 +Then you get this UIManagedContext. +然后你要拿到 UIManagedContext。 + +1258 +00:51:19,224 --> 00:51:22,858 +That's kind of your handle, your hook, on your database. +这是你的数据库的handle,或者说hook。 + +1259 +00:51:22,860 --> 00:51:24,593 +There's a couple different ways to do that. +有好几种方式去获得。 + +1260 +00:51:24,595 --> 00:51:27,162 +There's some code that can be generated when you create your +当你创建工程的时候,有一些代码可以自动生成。 + +1261 +00:51:27,164 --> 00:51:29,431 +project, you can click on the Use Core Data button and +你只需要选择 “Use Core Data” 这一选项, + +1262 +00:51:29,433 --> 00:51:31,666 +it will create this code for you in your app delegate, +它就会在 app delegate 里生成相关代码, + +1263 +00:51:31,668 --> 00:51:33,801 +and then you will have a method in your app delegate +你会在 app delegate 里得到一个 + +1264 +00:51:33,803 --> 00:51:35,202 +called managedObjectContext. +名为 managedObjectContext 的方法。 + +1265 +00:51:35,204 --> 00:51:36,903 +Now you have a handle to your database and +现在你有了数据库的一个 handle , + +1266 +00:51:36,905 --> 00:51:38,672 +you can start creating objects in there or +你可以开始在里面创建对象或者 + +1267 +00:51:38,674 --> 00:51:39,972 +setting the values of things. +设置一些东西的值。 + +1268 +00:51:39,974 --> 00:51:41,707 +There's also another class, +另外还存在一个类, + +1269 +00:51:41,709 --> 00:51:44,410 +an important class called UIManagedDocument, +一个叫做 UIManagedDocument 的重要的类, + +1270 +00:51:44,412 --> 00:51:47,512 +it's a way to encapsulate a Core Data database, okay? +它是对于一个 Core Data 数据库的封装。 + +1271 +00:51:47,514 --> 00:51:50,915 +What's really cool about UIManagedDocument, if you use +UIManagedDocument 最酷的一点是,如果你 + +1272 +00:51:50,917 --> 00:51:53,851 +that approach versus the Use Core Data approach, +它的方式,相对于使用 Core Data 方式, + +1273 +00:51:53,853 --> 00:51:56,754 +is that the iCloud side of it becomes a lot easier. +iCloud 的部分变得简单得多。 + +1274 +00:51:56,756 --> 00:51:59,456 +So if you wanted to have your core data database work on +所以如果你想要在 + +1275 +00:51:59,458 --> 00:52:02,225 +iCloud so that I could see it on all my devices, and +iCloud 上使用 Core Data 数据库,以便用户能在所有的设备上 + +1276 +00:52:02,227 --> 00:52:04,627 +it would be automatically synchronized, +自动同步数据, + +1277 +00:52:04,629 --> 00:52:06,863 +then you wanna use UIManagedDocument. +那么你最好使用 UIManagedDocument。 + +1278 +00:52:06,865 --> 00:52:08,898 +So maybe some of you. +可能你们有些人, + +1279 +00:52:08,899 --> 00:52:10,932 +Anybody trying to use UIManagedDocument? +任何人在尝试使用 UIManagedDocument 吗? + +1280 +00:52:10,935 --> 00:52:14,236 +'Kay, so that is kind of like the next step +这有点像是使用 + +1281 +00:52:14,238 --> 00:52:17,439 +you would think about doing in Core Data. +Core Data 后的下一步进阶。 + +1282 +00:52:17,441 --> 00:52:19,541 +All right, so once you have this context, +好了, 一旦你们拿到这个 context, + +1283 +00:52:19,543 --> 00:52:20,742 +the handle on the deck, +甲板(口误)上的 handle, + +1284 +00:52:20,744 --> 00:52:23,144 +on this core data database, you can create objects. +这个 Core Data 数据库的 handle, 你可以创建对象了。 + +1285 +00:52:23,146 --> 00:52:26,213 +You do that with this NSEntityDescription class +你可以使用 NSEntityDescription 类的 + +1286 +00:52:26,215 --> 00:52:29,349 +method called insertNewObjectForEntityForName, +insertNewObjectForEntityForName 方法来实现, + +1287 +00:52:29,351 --> 00:52:32,852 +and you're basically just specifying the name of +基本上你只要设定表的名称, + +1288 +00:52:32,854 --> 00:52:35,254 +the table, which is like a class, and +就像一个类一样, + +1289 +00:52:35,256 --> 00:52:37,990 +you give it the managedObjectContext, and +然后你再给它一个 managedObjectContext, + +1290 +00:52:37,992 --> 00:52:41,893 +it will create a new instance, okay, a new row in that table, +它就会创建一个实例, 或者,表里的一个新的行, + +1291 +00:52:41,895 --> 00:52:44,062 +to use the database terminology. +用数据库术语是这么描述的。 + +1292 +00:52:44,064 --> 00:52:47,098 +And it's gonna return to you this NSManagedObject, or +然后它会把这个 ManagedObject, + +1293 +00:52:47,100 --> 00:52:48,199 +subclass thereof. +或者它的子类返回给你 + +1294 +00:52:48,201 --> 00:52:51,235 +And it's with this NSManagedObject that you +拿着这个 NSManagedObject 你可以 + +1295 +00:52:51,237 --> 00:52:54,538 +can set the columns, set the values in that row. +设置列, 设置那一行的值。 + +1296 +00:52:54,540 --> 00:52:55,605 +You can also fetch, +你也可以查询, + +1297 +00:52:55,607 --> 00:52:58,341 +you create these things called NSFetchRequests. +你创建叫做 NSFetchRequests 的对象。 + +1298 +00:52:58,343 --> 00:53:01,911 +They basically specify what you're looking for, +他们基本上指定了你想要搜索的东西, + +1299 +00:53:01,913 --> 00:53:05,414 +pretty powerful predicates in there for saying, +非常强大的谓语表达,比如 + +1300 +00:53:05,416 --> 00:53:09,151 +well I want all things, all of the rows whose column is +我想要所有的满足以下条件的事物: 所有的行里,它的列 + +1301 +00:53:09,153 --> 00:53:11,820 +called name starts with the letter a. +名称以 a 为首字母。 + +1302 +00:53:11,822 --> 00:53:14,822 +You can do that kind of fetch request and then you issue +你可以做这样的查询请求然后你提交 + +1303 +00:53:14,824 --> 00:53:17,692 +the fetch request and you get it back as an NSArray. +这个查询然后你得到一个 NSArray 的结果。 + +1304 +00:53:17,694 --> 00:53:21,328 +This fetched object thing would be an NSArray, or +这个查询结果是个 NSArray, + +1305 +00:53:21,330 --> 00:53:23,764 +an array of NSManaged object. +一个 NSManaged 对象的数组。 + +1306 +00:53:23,766 --> 00:53:25,031 +Okay? + +1307 +00:53:25,033 --> 00:53:28,801 +And so that's kind of what you can do with a database. +这就是你对一个数据库可以进行的操作。 + +1308 +00:53:28,803 --> 00:53:31,737 +Once you have these objects, these NSManaged objects, +一旦你持有这些对象,这些 NSManaged 对象, + +1309 +00:53:31,739 --> 00:53:34,506 +you can use these two methods, the setValueForKey and +你可以使用这两个方法, setValue(, forKey:) 和 +1310 +00:53:34,508 --> 00:53:36,942 +valueForKey to set and get the values in there. +valueForKey() 来设置跟获得里面的值。 + +1311 +00:53:36,944 --> 00:53:38,977 +Or even better, +或者更好地, + +1312 +00:53:38,978 --> 00:53:41,011 +you can create subclasses of NSManaged objects. +你可以创建 NSManaged 对象的子类。 + +1313 +00:53:41,014 --> 00:53:43,781 +That have these apps on NSManagedObject vars, and +这些拥有跟 NSManaged 对象同样的成员变量, + +1314 +00:53:43,783 --> 00:53:45,916 +Core Data will automatically make it so +Core Data 会自动生成于是 + +1315 +00:53:45,918 --> 00:53:48,719 +that if you set that var, it sets it in the database. +如果你设置了成员变量, 它会改变数据库里对应的值。 + +1316 +00:53:48,721 --> 00:53:50,954 +And if you get that var, +如果你要获取成员变量的值, + +1317 +00:53:50,956 --> 00:53:54,957 +it'll fetch it from the database, okay? +它会从数据库了查找对应的值, okay? + +1318 +00:53:54,959 --> 00:53:59,294 +So, you use normal Swift notation for that. +这里使用了 Swift 的 notation. + +1319 +00:53:59,296 --> 00:54:03,431 +Okay, so that's kinda what Core Data's about in its core. +Okay, 这就是 Core Data 的核心(core)。 + +1320 +00:54:03,433 --> 00:54:06,334 +Pun intended, no pun intended. +一语双关,不是含沙射影。 + +1321 +00:54:06,336 --> 00:54:09,470 +Core Data is also really good at hooking up to table views. +Core Data 同样非常擅长跟 table view 配合。 + +1322 +00:54:09,472 --> 00:54:13,307 +Cuz you can imagine you've got these big tables of data in +想象一下你拿到了一个巨大的 Core Data 的表数据, + +1323 +00:54:13,309 --> 00:54:16,976 +Core Data, and it'd be nice to have a table view that is +那么用一个 table view 去 + +1324 +00:54:16,978 --> 00:54:18,745 +displaying all the rows or +显示所有表里所有的行 + +1325 +00:54:18,747 --> 00:54:21,681 +some subset of the rows based on some query. +或者行的子集,通过一些查询来处理。 + +1326 +00:54:21,683 --> 00:54:25,417 +In the table view, and so there's this class called +在 table view 里,iOS 上存在一个 + +1327 +00:54:25,419 --> 00:54:29,788 +NSFetchedResultsController in iOS, a super simple class. +名为 NSFetchedResultsController 的类, 非常简单的类。 + +1328 +00:54:29,790 --> 00:54:32,390 +It basically, you give it a fetch request, and +它基本上就是,你给它一个查询请求, + +1329 +00:54:32,392 --> 00:54:35,659 +you associate it with a table view, and then that table view +然后给它关联一个 table view, 然后 table view + +1330 +00:54:35,661 --> 00:54:38,662 +will always show what that fetch request would fetch, +就会永远显示查询请求得到的结果, + +1331 +00:54:38,664 --> 00:54:41,298 +even if the database changes out from under it. +即使数据库发生了改变。 + +1332 +00:54:41,300 --> 00:54:43,066 +'Kay, cuz you add something, and +因为你们增加了一些东西, + +1333 +00:54:43,068 --> 00:54:45,868 +the thing you added matches that fetch request, boom, +增加的东西满足查询请求,轰隆, + +1334 +00:54:45,870 --> 00:54:48,337 +it will just automatically appear in the table. +它会自动出现在表里。 + +1335 +00:54:48,339 --> 00:54:51,106 +'Kay, so you don't have to be doing all, basically, +所以你什么都不用做,基本上 + +1336 +00:54:51,108 --> 00:54:54,076 +the FetchedResultController will implement all of your +FetchedResultController 会自动实现所有的 + +1337 +00:54:54,078 --> 00:54:56,211 +UITableViewDatasource methods for you. +UITableViewDatasource 方法。 + +1338 +00:54:56,213 --> 00:54:58,446 +How many rows in table, how many rows in section. +表里有多少行, 每个 section 里有多少 row。 + +1339 +00:54:58,448 --> 00:55:00,514 +Give me the self or own index path. +给我 self 或者 自己的 index path, + +1340 +00:55:00,516 --> 00:55:02,082 +You have to do your own self or +你需要去处理自己的 self + +1341 +00:55:02,084 --> 00:55:04,251 +own index path to do the UI part of it, but +或者 自己的 index path 来绘制相关 UI, + +1342 +00:55:04,253 --> 00:55:07,387 +there's one method in the FetchResultsController that +不过 FetchResultsController 一个方法 + +1343 +00:55:07,389 --> 00:55:10,089 +will tell you which managed object is in this row, +会告诉你在表里的这一行使用了 + +1344 +00:55:10,091 --> 00:55:11,824 +in the table. +哪个 managed 对象。 + +1345 +00:55:11,825 --> 00:55:13,558 +So if you're doing Core Data for your final project and +所以如果你在最终大作业里使用了 Core Data 并且 + +1346 +00:55:13,561 --> 00:55:14,960 +you're doing table views, +采用了 UITableView, + +1347 +00:55:14,962 --> 00:55:18,030 +you definitely want to look up NSFetchedResultsController. +你绝对应该去看一下 NSFetchedResultsController。 + +1348 +00:55:18,032 --> 00:55:19,798 +Okay. + +1349 +00:55:19,800 --> 00:55:21,899 +All right, so the demo that I'm gonna do, +好了,这就是我要去做的演示, + +1350 +00:55:21,901 --> 00:55:24,735 +I'm not gonna demo Core Data, don't have time for that. +我不会去演示 Core Data, 没时间了。 + +1351 +00:55:24,737 --> 00:55:27,104 +So I'm just gonna demo the file system piece. +所以我只会演示文件系统部分。 + +1352 +00:55:27,106 --> 00:55:31,074 +And we're gonna do that by making our waypoint. +我们通过制作我们的 waypoint 来演示。 + +1353 +00:55:31,076 --> 00:55:35,078 +Store the image that we took with the camera as a JPG in +把我们拍摄的相片以 JPG 格式存储到 + +1354 +00:55:35,080 --> 00:55:36,445 +the file system. +文件系统里。 + +1355 +00:55:36,447 --> 00:55:38,280 +And then we'll have a URL to it, +然后我们会有一个指向它的 URL, + +1356 +00:55:38,282 --> 00:55:39,881 +we can update the waypoint. +我们可以更新 waypoint 。 + +1357 +00:55:39,883 --> 00:55:44,018 +And our new edited waypoints will work just like the ones +然后我们新编辑的 waypoint 可以跟 + +1358 +00:55:44,020 --> 00:55:45,820 +that come in a GPX file. +来源于 GPX 文件的 waypoint 一样正常工作。 + +1359 +00:55:45,822 --> 00:55:50,357 +All right, so what do we need to do to do this? +好了,我们需要那些东西? + +1360 +00:55:50,359 --> 00:55:55,261 +Really, all I'm gonna do here when I take a photo, okay, +实际上,我之遥在这里照个相,okay, + +1361 +00:55:55,263 --> 00:55:59,398 +and the information comes back in the delegate, +然后信息通过 delegate 传回来, + +1362 +00:55:59,400 --> 00:56:03,135 +I'm just gonna say saveImageInWaypoint. +我把它命名为 saveImageInWaypoint。 + +1363 +00:56:03,137 --> 00:56:07,672 +'Kay, remember that this MVC, its model. +'Kay, 记住这个 MVC, 它的 model, + +1364 +00:56:07,674 --> 00:56:10,474 +Is the waypoint that we're editing. +是我们要编辑的 waypoint。 + +1365 +00:56:10,476 --> 00:56:12,843 +So, I'm just gonna have a little method here, +我要在这里创建一个小的方法, + +1366 +00:56:12,845 --> 00:56:14,111 +saveImageInWaypoint. +saveImageInWaypoint. + +1367 +00:56:14,113 --> 00:56:19,282 +So let's implement that, saveImageInWaypoint. +所以,我们来实现它。 + +1368 +00:56:19,284 --> 00:56:22,918 +And all we're gonna do here is we have the image, +这里需要做的事情是,我们持有图片, + +1369 +00:56:22,920 --> 00:56:26,922 +we already got it, put it here in our UI view image, so +我们已经拿到了,放在 imageView 的 image 里, + +1370 +00:56:26,924 --> 00:56:29,257 +I'll just get it out of there. +所以我只需要把它从那里取出来。 + +1371 +00:56:29,259 --> 00:56:31,859 +And we're just gonna write it in the file system and +然后我要把它写到文件系统里, + +1372 +00:56:31,861 --> 00:56:34,595 +then we're gonna update the waypoint to use that URL, +然后我们要根据 URL 来更新 waypoint , + +1373 +00:56:34,597 --> 00:56:35,462 +simple as that. +就这么简单。 + +1374 +00:56:35,464 --> 00:56:38,632 +So, if we can get that image, so +如果我们能拿到那个 image, + +1375 +00:56:38,634 --> 00:56:41,668 +if our imageView has an image. +如果 imageView 持有一个 image。 + +1376 +00:56:41,670 --> 00:56:42,402 +Okay? + +1377 +00:56:42,404 --> 00:56:43,903 +Because they could be nil. +因为他们可能是 nil。 + +1378 +00:56:43,905 --> 00:56:46,972 +It might have been set to nil by some means, +它可能因为一些原因而被设置为 nil, + +1379 +00:56:46,974 --> 00:56:50,142 +then I'm gonna get the image data as a JPEG. +我要以 JPEG 格式获取图片数据。 + +1380 +00:56:50,144 --> 00:56:54,145 +And the way you do that, there's this cool function, +为了达到这个目的, 有个酷酷的函数, + +1381 +00:56:54,147 --> 00:56:58,516 +UIImageJPEGRepresentation and you just give it a UIImage. +叫做 UIImageJPEGRepresentation, 你只要给它一个 UIImage。 + +1382 +00:56:58,518 --> 00:56:59,934 +Okay? + +1383 +00:56:59,935 --> 00:57:01,351 +And you give it a compression quality. +然后指定压缩质量。 + +1384 +00:57:01,354 --> 00:57:03,520 +So, I'm gonna do really high compression. +我要使用一个非常高的压缩率。 + +1385 +00:57:03,522 --> 00:57:05,238 +Okay? + +1386 +00:57:05,239 --> 00:57:06,955 +So this is a quality between zero I think, +我猜测这个质量是介于0, + +1387 +00:57:06,958 --> 00:57:10,293 +which is like the most compressed you can do to one, +也就是你可以对图片进行的最大压缩,和1, + +1388 +00:57:10,295 --> 00:57:12,795 +which is like almost no compression. +也就是几乎不做任何压缩,这两个值之间。 + +1389 +00:57:12,797 --> 00:57:14,096 +Okay? + +1390 +00:57:14,098 --> 00:57:15,597 +I think that's the direction it is, +我想这就是它的方向, + +1391 +00:57:15,599 --> 00:57:17,182 +I hope that is what it is. +我希望这就是它的含义。 + +1392 +00:57:17,183 --> 00:57:18,766 +But anyway, so you can look at the documentation for it. +不过你可以去翻阅相关文档。 + +1393 +00:57:18,769 --> 00:57:22,036 +But we're gonna turn our image here +我们在这里转换图片 + +1394 +00:57:22,038 --> 00:57:24,739 +into by doing this in NSData. +为 NSData 格式。 + +1395 +00:57:24,741 --> 00:57:28,275 +So this is going to return in NSData. +它会返回一段 NSData + +1396 +00:57:28,277 --> 00:57:31,678 +If we look at the up here, see that is NSData. + +1397 +00:57:31,680 --> 00:57:33,513 +So, it's gonna turn our image into NSData. +所以,它会把我们的图片转为 NSData。 + +1398 +00:57:33,515 --> 00:57:36,315 +It's kinda the opposite of NSData contents for URL, +它是 NSData 的 contentsForURL 的反面, + +1399 +00:57:36,317 --> 00:57:38,684 +which is the opposite it would take the URL for +这是获得 URL 指向的数据 + +1400 +00:57:38,686 --> 00:57:40,586 +some data and turn it into UIImage. +然后把数据转换为 UIImage。 + +1401 +00:57:40,588 --> 00:57:43,588 +This goes back the other way for JPG. +这个把 JPG 转换回去了。 + +1402 +00:57:43,590 --> 00:57:46,224 +So, if we're able to do that conversion, then I'm +所以,如果我们能做这个转换, 我要 + +1403 +00:57:46,226 --> 00:57:48,860 +gonna get the fileManager here as a local variable. +在这里以 fileManager 为局部变量。 + +1404 +00:57:48,862 --> 00:57:51,962 +I could just constantly, I could use the defaultManager +这里我使用常量, 我要使用 defaultManager + +1405 +00:57:51,964 --> 00:57:54,732 +by defaultManager you see I'm in the main thread. +使用 defaultManager 你明白我在主线程里。 + +1406 +00:57:54,734 --> 00:57:57,701 +But just in case I ever put this in a separate thread or +不过以防万一,我把这个放到别的线程, + +1407 +00:57:57,703 --> 00:58:01,004 +something, I'll go ahead and use an instance of it here. +我要在这里使用它的一个实例。 + +1408 +00:58:01,006 --> 00:58:03,172 +So now I need to get the documents directory, +这里我需要拿到 Documents 目录, + +1409 +00:58:03,174 --> 00:58:04,940 +because these waypoints, really +因为这些 waypoint ,确实是 + +1410 +00:58:04,942 --> 00:58:07,276 +the user perceives them as their document data. +用户的存档数据。 + +1411 +00:58:07,278 --> 00:58:08,610 +That's where you would want to store this. +那个目录就是用来存储这些的。 + +1412 +00:58:08,612 --> 00:58:10,612 +It's not like a cache that we can't ever get back. +这不像是缓存,我们无法重新拿回来。 + +1413 +00:58:10,614 --> 00:58:12,580 +We need that photo if we lose it. +如果我们丢失了图片,我们需要它。 + +1414 +00:58:12,582 --> 00:58:14,949 +It's gone forever. +它永远消失了。 + +1415 +00:58:14,950 --> 00:58:17,317 +So, and again, we might really want to be saving this in +我们可能真的要把它存到 + +1416 +00:58:17,319 --> 00:58:18,719 +the photo library. +相片库。 + +1417 +00:58:18,721 --> 00:58:21,221 +But I'm just trying to demo here how to do the file +不过我正在演示如何处理文件系统, + +1418 +00:58:21,223 --> 00:58:23,489 +system, so that's why we're doing that. +所以这就是我们的处理方式。 + +1419 +00:58:23,491 --> 00:58:26,392 +So, I'm gonna get the documents directory and +所以我要拿到 Documents 目录, + +1420 +00:58:26,394 --> 00:58:28,994 +so here's a nice long line of code for you. +这里有行不错的,长长的代码。 + +1421 +00:58:28,996 --> 00:58:32,464 +Take the fileManager, we're gonna get the URLs for +拿着 fileManager, 然后我们要获得 + +1422 +00:58:32,466 --> 00:58:33,364 +directory. +URLsForDirectory。 + +1423 +00:58:33,366 --> 00:58:36,634 +Okay? + +1424 +00:58:36,635 --> 00:58:39,903 +The directory we want is the DocumentsDirectory and +我们想要获得的目录是 DocumentsDirectory, + +1425 +00:58:39,905 --> 00:58:45,408 +the domain always on the iPhone is the UserDomain. +在 iPhone 上 domain 永远是 UserDomain... + +1426 +00:58:45,410 --> 00:58:47,543 +More space please. +把编辑器调大些。 + +1427 +00:58:47,545 --> 00:58:50,279 +The UserDomainMask here. +这里 UserDomainMask。 + +1428 +00:58:50,281 --> 00:58:51,764 +Okay? + +1429 +00:58:51,765 --> 00:58:53,248 +So that's gonna get this array of URLs and +这将会得到一个 URL 的数组, + +1430 +00:58:53,250 --> 00:58:55,650 +I'm just gonna get the first one out of there. +我会取出数组里的第一个元素。 + +1431 +00:58:55,652 --> 00:58:57,986 +Okay? + +1432 +00:58:57,987 --> 00:59:00,321 +And then I'm gonna make sure that it's cast to URL. +我要确保它被转换成 URL 类型。 + +1433 +00:59:00,323 --> 00:59:04,592 +So, if all of this succeeds, then I got +如果这些都成功了,那么 + +1434 +00:59:04,594 --> 00:59:09,996 +the documents directory and what did I miss here? +我会拿到 Documents 目录。这里我漏掉了什么? + +1435 +00:59:09,998 --> 00:59:14,667 +DocumentsDirectory. +多了个s。 + +1436 +00:59:14,669 --> 00:59:15,568 +There we go. +我们继续。 + +1437 +00:59:15,570 --> 00:59:18,304 +Okay? + +1438 +00:59:18,305 --> 00:59:21,039 +So this will end up being a NSURL that +所以这里最后得到一个 NSURL, + +1439 +00:59:21,041 --> 00:59:25,677 +points to the DocumentDirectory. +指向存档目录。 + +1440 +00:59:25,679 --> 00:59:27,145 +Okay? + +1441 +00:59:27,146 --> 00:59:28,612 +So now I have a DocumentDirectory, +现在我有了存档目录, + +1442 +00:59:28,614 --> 00:59:31,715 +I need a unique name for this photo that I just took. +我需要对我刚拍的照片取个唯一的名字。 + +1443 +00:59:31,717 --> 00:59:34,951 +So, I'm gonna create that by just saying, +我这么实现: + +1444 +00:59:34,953 --> 00:59:38,655 +NSDate.timeIntervalSinceReferenceDate +NSDate.timeIntervalSinceReferenceDate + +1445 +00:59:38,657 --> 00:59:40,590 +So this is just a certain number of seconds. +这是一个关于多少秒的数字, + +1446 +00:59:40,592 --> 00:59:42,892 +This is just a unique number. +是唯一的数字。 + +1447 +00:59:42,894 --> 00:59:44,193 +It's gonna be a double. +double 类型。 + +1448 +00:59:44,195 --> 00:59:47,896 +That unique identifies this photo, because it can't have +这个唯一确认了这张图, 因为你不可能 + +1449 +00:59:47,898 --> 00:59:50,765 +two photos taken at the same instance in time. +用同一实例及时地拍两张照片。 + +1450 +00:59:50,767 --> 00:59:52,200 +So we got that. +所以我们搞定了。 + +1451 +00:59:52,202 --> 00:59:54,886 +And then so +然后 + +1452 +00:59:54,887 --> 00:59:57,571 +I'm gonna let the URL for my photo be the docsDir and then +我要设定我的照片的 URL 为 docsDir 调用 + +1453 +00:59:57,573 --> 01:00:02,642 +URLByAppendingPathComponent and then I'm just gonna create +URLByAppendingPathComponent 方法, 我用 + +1454 +01:00:02,644 --> 01:00:07,347 +a string out of that unique and we'll say that it's a jpg. +这个唯一数字创建字符串,外加 jpg 扩展名作为参数补在后面。 + +1455 +01:00:07,349 --> 01:00:08,147 +Okay? + +1456 +01:00:08,149 --> 01:00:10,582 +So now I've created a URL, +现在我创建了一个 URL, + +1457 +01:00:10,584 --> 01:00:15,320 +which is just this unique string with JPG on the end. +就是这个唯一字符串,以 jpg 结尾的。 + +1458 +01:00:15,322 --> 01:00:17,722 +So now, if I can get the path to that URL. +所以如果我能拿到 URL 指向的路径。 + +1459 +01:00:17,724 --> 01:00:19,557 +So this is gonna take the URL and +这需要拿 URL 转换 + +1460 +01:00:19,559 --> 01:00:21,325 +turn it into a string, okay? +成一个字符串,okay? + +1461 +01:00:21,327 --> 01:00:23,293 +Cuz URLs are in this URL objects. +因为 URL 在这个 URL 对象里。 + +1462 +01:00:23,295 --> 01:00:25,562 +I want the string, you'll see why in a second here. +我需要的是字符串, 你们马上会看到为什么会这样。 + +1463 +01:00:25,564 --> 01:00:29,432 +If I can get that, then I'm gonna take that imageData and +如果能够拿到,我就用 imageData + +1464 +01:00:29,434 --> 01:00:33,435 +write it out to that URL and I'm gonna do it atomically. +向着 URL 输出且要求这是原子级操作。 + +1465 +01:00:33,437 --> 01:00:34,386 +Okay? + +1466 +01:00:34,387 --> 01:00:35,336 +And if that succeeded, +如果成功, + +1467 +01:00:35,339 --> 01:00:37,605 +if I was able to successfully do that, +如果我成功地完成了这些, + +1468 +01:00:37,607 --> 01:00:41,142 +then I can add it to the way point by saying, waypointLink. +那么我可以把它添加到 waypoint,这么实现: waypointLink.. + +1469 +01:00:41,144 --> 01:00:44,945 +And I'm just gonna replace all of my waypoint +我要把我所有的 waypoint 链接 + +1470 +01:00:44,947 --> 01:00:49,349 +links with a GPX.Link, which is href of that path, +用 GPX.Link 来替换。href 参数使用刚才得到的 path, + +1471 +01:00:49,351 --> 01:00:52,152 +the string version of the NSURL. +即前一步获取的 NSURL 的字符串版本。 + +1472 +01:00:52,154 --> 01:00:57,123 +Because GPX.Link, it's a generic GPX parsing thing. +因为 GPX.Link 有一个泛型的 GPX 解析器。 + +1473 +01:00:57,125 --> 01:01:01,493 +It takes strings, it takes URLs as strings here. +它可以接受字符串为参数,也可以接受作为字符串的 URL 为参数。 + +1474 +01:01:01,495 --> 01:01:02,727 +Okay? + +1475 +01:01:02,729 --> 01:01:05,496 +Everyone understand all this code? +大家都看明白所有代码了吗? + +1476 +01:01:05,498 --> 01:01:06,931 +This is typical code for +这是个典型的 + +1477 +01:01:06,933 --> 01:01:09,299 +writing something out into your file. +将一些内容输出到文件的代码。 + +1478 +01:01:09,301 --> 01:01:11,301 +So come into your Sandbox, in this case, +所以去你的沙盒里,在这个例子里, + +1479 +01:01:11,303 --> 01:01:13,103 +the DocumentDirectory of Sandbox. +沙盒的存档目录。 + +1480 +01:01:13,105 --> 01:01:14,404 +All right. + +1481 +01:01:14,405 --> 01:01:15,704 +So let's go ahead and run that. +让我们前进,运行程序。 + +1482 +01:01:15,707 --> 01:01:20,743 +It's good being +最好 + +1483 +01:01:20,745 --> 01:01:26,915 +on the iPhone here. +在 iPhone 上跑下。 + +1484 +01:01:26,917 --> 01:01:29,484 +Okay. + +1485 +01:01:29,485 --> 01:01:32,052 +So let's drop a pin here and can see that we have our +我们在这里钉个大头针,可以看到我们的 + +1486 +01:01:32,055 --> 01:01:35,723 +dropped there and we have no image yet, so +“Dropped” 在那里而且我们还没有图片。 + +1487 +01:01:35,725 --> 01:01:40,326 +let's click on our little i here and get an image. +所以点击这个小小的 “i” 来得到一张图片。 + +1488 +01:01:40,328 --> 01:01:44,330 +So, I'm going to click the camera. +所以,我要点击摄像机。 + +1489 +01:01:44,332 --> 01:01:49,334 +Let's get a picture of our R2D2 hat here. +我们来拍一张 R2D2 帽子的照片。 + +1490 +01:01:49,336 --> 01:01:50,201 +There we go. +继续。 + +1491 +01:01:50,203 --> 01:01:51,803 +And we'll use that photo. +我们使用了这张照片。 + +1492 +01:01:51,805 --> 01:01:53,304 +And now we have our image. +现在我们有了图片。 + +1493 +01:01:53,306 --> 01:01:57,674 +We can even, for example, +我们甚至可以,举个例子, + +1494 +01:01:57,676 --> 01:02:05,815 +change our title here maybe to let's say, R2SF. +在这里改变我们的标题, 比如改成 R2SF。 + +1495 +01:02:05,817 --> 01:02:06,515 +All right? + +1496 +01:02:06,517 --> 01:02:08,567 +And click Done. +点击 Done. + +1497 +01:02:08,568 --> 01:02:10,618 +Now, if we click on our pin, we can see that the image +现在如果我们点击我们的大头针,我们可以看到图片 + +1498 +01:02:10,621 --> 01:02:13,488 +has been saved and we can see it there on the left. +已经被保存,我们能在左边看到它。 + +1499 +01:02:13,490 --> 01:02:17,025 +We can even click on it, scroll around on it. +我们甚至可以点击它,在它上面滚动。 + +1500 +01:02:17,027 --> 01:02:18,025 +Okay? + +1501 +01:02:18,027 --> 01:02:19,727 +Or go back and edit it and +或者回去修改它, + +1502 +01:02:19,729 --> 01:02:22,496 +take a different photo if we wanted to. +如果需要的话,拍一张不同的照片。 + +1503 +01:02:22,498 --> 01:02:24,531 +[SOUND] Okay. + +1504 +01:02:24,533 --> 01:02:29,435 +Now by the way, to make this work I had to make a small +顺便说一句,要使得这个工作,我需要 + +1505 +01:02:29,437 --> 01:02:33,538 +change to the code, which is right here and +对代码做个小改动,就在这里 + +1506 +01:02:33,540 --> 01:02:36,408 +didSelectAnnotationView. +这个 didSelectAnnotationView. + + +1507 +01:02:36,410 --> 01:02:39,510 +We just want to make sure that if we have no call out +我们想要确定我们是不是没有 leftCalloutAccessoryView, + +1508 +01:02:39,512 --> 01:02:43,414 +accessory, because we started without one when we drop a new +因为如果在没有的情况下钉个大头针的话, + +1509 +01:02:43,416 --> 01:02:44,581 +pin, like this. +就像这样。 + +1510 +01:02:44,583 --> 01:02:45,915 +We have no image and so, +我们没有图片, + +1511 +01:02:45,917 --> 01:02:49,052 +it didn't add the left call out accessory in that case. +于是它没有添加 leftCalloutAccessoryView。 + +1512 +01:02:49,054 --> 01:02:51,754 +So just when the annotation's selected, +所以当 annotation 被选择后, + +1513 +01:02:51,756 --> 01:02:54,556 +we're just gonna make sure that it adds it. +我们要确保它被添加上。 + +1514 +01:02:54,558 --> 01:02:55,190 +Okay. + +1515 +01:02:55,192 --> 01:03:00,061 +Back to our slides. +回到讲义。 + +1516 +01:03:00,063 --> 01:03:03,564 +All right. + +1517 +01:03:03,566 --> 01:03:05,783 +Okay. + +1518 +01:03:05,784 --> 01:03:08,001 +So the last thing is Embed Segues. +最后的内容是 Embed Segues + +1519 +01:03:08,003 --> 01:03:11,504 +So, Embed Segues is just taking the view, +Embed Segues 总是将一个 view, + +1520 +01:03:11,506 --> 01:03:14,273 +self.view, basically of an MVC and +self.view, 一个 MVC 的基本要素, + +1521 +01:03:14,275 --> 01:03:16,976 +putting it in another MVC's view. +放到另一个 MVC 的 view 里。 + +1522 +01:03:16,978 --> 01:03:18,945 +Okay? + +1523 +01:03:18,946 --> 01:03:20,913 +So, it's basically embedding one MVC into another. +所以,基本上它是将一个 MBC 内嵌到另一个 MVC。 + +1524 +01:03:20,915 --> 01:03:24,049 +It's a pretty powerful encapsulation technique. +这是个非常强大的封装技术。 + +1525 +01:03:24,051 --> 01:03:25,583 +The way you do it is really easy. +使用它非常简单。 + +1526 +01:03:25,585 --> 01:03:27,519 +In the storyboard, +在 storyboard 里, + +1527 +01:03:27,520 --> 01:03:29,454 +you just drag out this thing called a container view, okay? +你把一个叫做 container view 的东西拽出来, okay? + +1528 +01:03:29,456 --> 01:03:30,388 +You drag the container view out. +把 container view 拽出来。 + +1529 +01:03:30,390 --> 01:03:31,922 +It's gonna be a little view and +它是个小小的 view 并且 + +1530 +01:03:31,924 --> 01:03:34,157 +it's gonna have a little MVC attached to it. +我们会给它附加上一个小小的 MVC。 + +1531 +01:03:34,159 --> 01:03:35,675 +All right. + +1532 +01:03:35,676 --> 01:03:37,192 +So, it looks like this when you drag it out. +当你把它拽出来后,看上去是这个样子。 + +1533 +01:03:37,195 --> 01:03:39,028 +That little grey thing's the container, +小的灰色的东西就是 container, + +1534 +01:03:39,030 --> 01:03:41,330 +that's the thing I dragged out from the storyboard. +这就是我从 storyboard 里拽出来的东西。 + +1535 +01:03:41,332 --> 01:03:44,033 +And then that little arrow there moving, +在闪动的箭头指向的东西, + + +1536 +01:03:44,035 --> 01:03:45,701 +that's the Embed Segue. +就是 Embed Segue。 + +1537 +01:03:45,703 --> 01:03:48,603 +And you can see there's another MVC there and that MVC +你会发现那里有另一个 MVC 而且那个 MVC + +1538 +01:03:48,605 --> 01:03:51,406 +is the one who's self.view is gonna be embedded. +的 self.view 要被内嵌。 + +1539 +01:03:51,408 --> 01:03:53,825 +All right? + +1540 +01:03:53,826 --> 01:03:56,243 +The timing of this, you've got to be a little careful on +在它的过程里, 你要小心 + +1541 +01:03:56,245 --> 01:03:59,113 +prepareForSegue, because this embed all +prepareForSegue, 因为这个内嵌都 + +1542 +01:03:59,115 --> 01:04:02,182 +happens before any outlets are set as usual. +发生在任何 outlets 被正常设置好之前。 + +1543 +01:04:02,184 --> 01:04:03,850 +And so, it's happening very, very early in the game. +而且,它发生的非常非常早。 + +1544 +01:04:03,852 --> 01:04:06,586 +So, usually in our Embed Segue, +所以通常在 Embed Segue 里, + +1545 +01:04:06,588 --> 01:04:09,422 +what we do is we grab onto that MVC. +我们要做的就是抓住那个 MVC。 + +1546 +01:04:09,424 --> 01:04:12,057 +Okay, so that we have a handle to it. +好了, 我们有了它的 handle。 + +1547 +01:04:12,059 --> 01:04:14,426 +We can talk to it. +我们可以跟它交流。 + +1548 +01:04:14,427 --> 01:04:16,794 +We can prepare it, set it up, whatever want later. +我们可以为它准备, 把它装配好,之后任何想做的。 + +1549 +01:04:16,797 --> 01:04:20,198 +So this is best shown by just demonstrating it so +所以这最好是给个证明。 + +1550 +01:04:20,200 --> 01:04:23,735 +I'm gonna demonstrate that by going to Trax. +我会在 Trax 里证明这个。 + +1551 +01:04:23,737 --> 01:04:29,907 +And here's our Trax UI, so Trax right here. +这是我们的 Trax 的 UI, 整个工程。 + +1552 +01:04:29,909 --> 01:04:34,511 +This is our map view right here. +这是我们的 map view。 + +1553 +01:04:34,513 --> 01:04:37,780 +And when we click on the left edge of a call out, +当我们点击(大头钉的) callout 的左侧时, + +1554 +01:04:37,782 --> 01:04:40,916 +it brings up this UI image view controller. +它会调出这个 UI, ImageViewController。 + +1555 +01:04:40,918 --> 01:04:45,054 +Right, which is currently fully contains an image. +它目前就完整地包含了一张图片。 + +1556 +01:04:45,056 --> 01:04:49,024 +And what I'm gonna do is I'm gonna embed in the corner, +我要做的,是在这个角落, + +1557 +01:04:49,026 --> 01:04:53,327 +a little rectangle down here, a little square that contains +矩形的下方, 内嵌一个正方形, + +1558 +01:04:53,329 --> 01:04:57,098 +a little map view, with just the pin for this image. +里面包含一小块 map view 和这张图片对应的大头针。 + +1559 +01:04:57,100 --> 01:04:59,266 +So that when I'm look in the image, +所以当我查看图片时, + +1560 +01:04:59,268 --> 01:05:02,502 +especially on the iPad where I've got a big screen, +特别是在 iPad 这样有大屏幕的设备上, + +1561 +01:05:02,504 --> 01:05:05,739 +I can see some context of where this image was taken. +我能看到这张照片拍摄的位置的一些内容。 + +1562 +01:05:05,741 --> 01:05:07,552 +Right? + +1563 +01:05:07,553 --> 01:05:09,364 +So I'll see them both on time. +我要准时看到它们两个。 + +1564 +01:05:09,365 --> 01:05:11,176 +So I'm basically gonna embed another view controller into +基本上我要把另一个 view controller 内嵌到 + +1565 +01:05:11,179 --> 01:05:12,545 +this guy right here. +这里的这家伙上面。 + +1566 +01:05:12,547 --> 01:05:14,413 +So what do we need to do that? +我们需要做什么来实现? + +1567 +01:05:14,415 --> 01:05:17,549 +The number one thing we need to do when we have an embedded +当我们有了一个内嵌的 view controller 我们首先要做的是, + +1568 +01:05:17,551 --> 01:05:20,218 +view controller is we need to do this segue, and +我们需要处理这个 segue, + +1569 +01:05:20,220 --> 01:05:22,820 +we need this view controller right here to have +我们需要给这里的 view controller 创建一个 + +1570 +01:05:22,822 --> 01:05:24,789 +a little subclass to manage that. +子类来处理。 + +1571 +01:05:24,791 --> 01:05:27,491 +So right now this view controller, as you know, +现在这个 view controller, 你们知道的, + +1572 +01:05:27,493 --> 01:05:29,126 +is an ImageViewController. +是一个 ImageViewController + +1573 +01:05:29,128 --> 01:05:30,794 +So if we select this, +如果我们选择了这个, + +1574 +01:05:30,795 --> 01:05:32,461 +you can see that its class is ImageViewController. +你能看到它的类型是 ImageViewController。 + +1575 +01:05:32,464 --> 01:05:33,763 +So I need to change this. +我需要修改这个。 + +1576 +01:05:33,765 --> 01:05:37,199 +I'm gonna change this to be a waypoint image view +我要把它改成 + +1577 +01:05:37,201 --> 01:05:38,233 +controller. +WaypointImageViewController。 + +1578 +01:05:38,235 --> 01:05:39,685 +Okay? + +1579 +01:05:39,686 --> 01:05:41,136 +So a waypoint image view controller's gonna be +WaypointImageViewController 是 + +1580 +01:05:41,138 --> 01:05:42,770 +a subclass of ImageViewController. +ImageViewController 的子类。 + +1581 +01:05:42,772 --> 01:05:44,538 +So it's gonna do everything this one does. +所以它可以做父类能做的一切事情。 + +1582 +01:05:44,540 --> 01:05:48,809 +Plus it's gonna know about how to manage that embed. +外加如何处理内嵌。 + +1583 +01:05:48,811 --> 01:05:49,509 +Okay? + +1584 +01:05:49,511 --> 01:05:52,111 +So let's create a new class. +我们创建一个新类。 + +1585 +01:05:52,113 --> 01:05:53,746 +All right, the Cocoa Touch Class. +选择 Cocoa Touch Class. + +1586 +01:05:53,748 --> 01:05:57,282 +It's gonna be a subclass of ImageViewController, +它是我们的 ImageViewController, + +1587 +01:05:57,284 --> 01:05:58,650 +one of our classes. +的子类。 + +1588 +01:05:58,652 --> 01:06:03,388 +And I'm gonna call it WaypointImageViewController. +我把它命名为 WaypointImageViewController。 + +1589 +01:06:03,390 --> 01:06:04,388 +Okay. + +1590 +01:06:04,390 --> 01:06:06,357 +Put it in the standard place. +把它放置在标准位置。 + +1591 +01:06:06,359 --> 01:06:09,192 +'Kay here it is, here's our WaypointImageViewController. +好了, 这就是我们的 WaypointImageViewController。 + +1592 +01:06:09,194 --> 01:06:11,861 +This WaypointImageViewController, +这个 WaypointImageViewController, + +1593 +01:06:11,863 --> 01:06:13,730 +its model is the waypoint. +它的 model 是 waypoint + +1594 +01:06:13,732 --> 01:06:15,215 +'Kay? + +1595 +01:06:15,216 --> 01:06:16,699 +This guy's model, did everyone remember what +这家伙的 model,大家都记得 + +1596 +01:06:16,701 --> 01:06:18,367 +ImageViewController's model is? +ImageViewController 的 model 是什么吗? + +1597 +01:06:18,369 --> 01:06:19,968 +It's just an image URL. +它只是个图片 URL。 + +1598 +01:06:19,970 --> 01:06:21,853 +Right? + +1599 +01:06:21,854 --> 01:06:23,737 +So we need a little more powerful model here in our +这里我们需要一个更强大的 model, + +1600 +01:06:23,740 --> 01:06:26,107 +WaypointImageViewCcontroller, so +在 WaypointImageViewController 里, + +1601 +01:06:26,109 --> 01:06:28,442 +I'm just going to have var waypoint. +所以我定义变量 waypoint。 + +1602 +01:06:28,444 --> 01:06:30,310 +It's a GPX Waypoint. +它是 GPX Waypoint 格式的。 + +1603 +01:06:30,312 --> 01:06:33,046 +It'll work with the editable ones or non-editable ones. +它可以支持可编辑的和不可编辑的。 + +1604 +01:06:33,048 --> 01:06:35,415 +And when that waypoint is set, +在 waypoint 变量被设置时, + +1605 +01:06:35,417 --> 01:06:39,418 +I want to make sure that I set my super classes model. +我要确保父类的 model 也被更新。 + +1606 +01:06:39,420 --> 01:06:43,989 +So, I'm gonna say my imageURL equals that +我在这里输入 + +1607 +01:06:43,991 --> 01:06:46,691 +waypoint's imageURL. +imageURL = waypoint?.imageURL + +1608 +01:06:46,693 --> 01:06:47,291 +Okay? + +1609 +01:06:47,293 --> 01:06:50,044 +So, here, +在这里, + +1610 +01:06:50,045 --> 01:06:52,796 +I'm basically setting my super class's URL there. +基本上我设置了父类的 URL。 + +1611 +01:06:52,798 --> 01:06:57,701 +And what are we getting this about here? +这里的错误提示是什么原因? + +1612 +01:06:57,703 --> 01:06:59,736 +Oh, okay, we're not there, okay. +哦,没什么问题。 + +1613 +01:06:59,738 --> 01:07:03,272 +And then I'm also gonna set my title equal to the waypoint's +然后我也要把 title 设置为 waypoint 的 + +1614 +01:07:03,274 --> 01:07:04,606 +name, might as well. +名字, 顺便。 + +1615 +01:07:04,608 --> 01:07:08,677 +And then I'm just gonna update my embedded map, okay, because +然后我要更新我的内嵌的地图,okay,因为 + +1616 +01:07:08,679 --> 01:07:12,147 +the whole point of this guy is he has this embedded map. +这个 view controller 的重点就在于它持有内嵌的地图。 + +1617 +01:07:12,149 --> 01:07:16,183 +So, we'll have a function here called updateEmbeddedMap, and +所以我们在这里实现名为 updateEmbeddedMap 的函数, + +1618 +01:07:16,185 --> 01:07:18,185 +it's going to update that map. +这个函数会更新地图。 + +1619 +01:07:18,187 --> 01:07:21,088 +And we'll talk about how that's going to happen +我们过一会儿再讨论 + +1620 +01:07:21,090 --> 01:07:22,322 +a little bit later. +具体实现。 + +1621 +01:07:22,324 --> 01:07:25,792 +This isn't optional, that's why, okay. +这不是 optional, 这就是原因, okay。 + +1622 +01:07:25,794 --> 01:07:27,026 +All right, so that's it. +就是这样。 + +1623 +01:07:27,028 --> 01:07:29,695 +So that's our waypoint image controller, +这就是我们的 WaypointImageViewController, + +1624 +01:07:29,697 --> 01:07:31,163 +kind of its main thing. +它的主要的事情。 + +1625 +01:07:31,165 --> 01:07:33,865 +So now we need to go back to our storyboard, and +我们需要返回到 storyboard, + +1626 +01:07:33,867 --> 01:07:37,168 +I'm gonna make this image view controller right here be +我要把这里的 ImageViewController + +1627 +01:07:37,170 --> 01:07:39,270 +a waypoint image view controller. +换成 WaypointImageViewController. + +1628 +01:07:39,272 --> 01:07:41,638 +So I'm just gonna go here to its identity and +我们来这里查找它的ID, + +1629 +01:07:41,640 --> 01:07:45,108 +go down here and say now it's a WaypointImageViewController. +往下翻,好了,它是个 WaypointImageViewController。 + +1630 +01:07:45,110 --> 01:07:47,444 +Also, I'm gonna fix this segue. +同样,我要处理这个 segue。 + +1631 +01:07:47,446 --> 01:07:49,278 +This is a segue from our map view. +这是一个来自 map view 的 segue。 + +1632 +01:07:49,280 --> 01:07:54,016 +I'm gonna just fix this one to prepare this guy by giving +我要在 prepare 函数里, + +1633 +01:07:54,018 --> 01:07:55,350 +his way point. +提供它的 waypoint 来解决问题。 + +1634 +01:07:55,352 --> 01:07:59,020 +So that's over here in our GPXViewController, +我们到 GPXViewController 里, + +1635 +01:07:59,022 --> 01:08:00,721 +down here in prepare. +跳到 prepare 函数里。 + +1636 +01:08:00,723 --> 01:08:02,890 +Okay, here's where we're preparing +Okay, 这是我们准备 + +1637 +01:08:02,892 --> 01:08:04,491 +the ImageViewController. +ImageViewController 的地方。 + +1638 +01:08:04,493 --> 01:08:05,258 +Okay? + +1639 +01:08:05,260 --> 01:08:06,959 +So here I'm going to say, +在这里我要输入 + +1640 +01:08:06,961 --> 01:08:10,363 +if I can let the waypoint image view controller equal +if let wivc = + +1641 +01:08:10,365 --> 01:08:12,998 +the segue destinationViewController, +segue.destinationViewController + +1642 +01:08:13,000 --> 01:08:16,735 +contentViewController as a waypoint view controller. +.contentViewController as? WaypointImageViewController。 + +1643 +01:08:16,737 --> 01:08:19,771 +So in other words if it's a waypoint image controller, +还句话说,它确实是 WaypointImageViewController 类型, + +1644 +01:08:19,773 --> 01:08:23,107 +then I'm gonna say waypoint image view controller waypoint +那么我要把它的 waypoint 变量 + +1645 +01:08:23,109 --> 01:08:24,275 +equals my waypoint. +赋值为这里的 waypoint。 + +1646 +01:08:24,277 --> 01:08:26,010 +And actually I'll just go ahead and +实际上我会继续执行,并且 + +1647 +01:08:26,012 --> 01:08:27,978 +leave this other code in here as an else. +把原先的代码作为 else 分支。 + +1648 +01:08:27,980 --> 01:08:30,246 +Else if it's not a waypoint view image controller, +如果它不是 WaypointImageViewController, + +1649 +01:08:30,248 --> 01:08:32,148 +it's just a normal image view controller, +它只是个普通的 ImageViewController, + +1650 +01:08:32,150 --> 01:08:33,749 +we'll still make that work as well. +我们也要让它正常工作。 + +1651 +01:08:33,751 --> 01:08:36,552 +But we could delete this code, and it would work fine now. +不过我们可以删除这段代码, 删除后也能工作正常。 + +1652 +01:08:36,554 --> 01:08:41,489 +But I'll just leave it in there, just for reference. +我还是留着它,作为参考。 + +1653 +01:08:41,491 --> 01:08:43,791 +Okay. + +1654 +01:08:43,792 --> 01:08:46,092 +So now we need to go do this embedding business. +现在我们需要去处理内嵌事务。 + +1655 +01:08:46,095 --> 01:08:47,673 +Okay. + +1656 +01:08:47,674 --> 01:08:49,252 +We need to put this thing in here. +我们需要把这个放到这里。 + +1657 +01:08:49,253 --> 01:08:50,831 +Now one thing I'm gonna advise you to do, when you're doing +现在我要给你们一个建议,当你在实现 + +1658 +01:08:50,833 --> 01:08:53,266 +embedding, and kind of be a little careful of. +内嵌时,要稍微留意的事情, + +1659 +01:08:53,268 --> 01:08:55,802 +Is when you drag out this Container View, +是当你拽出这个 container view, + +1660 +01:08:55,804 --> 01:08:59,472 +which is at the very bottom, by the way, it's gonna want to +顺便说一句,它在最底下,它会成为 + +1661 +01:08:59,474 --> 01:09:02,508 +be a subview of the thing you're dragging it on. +你放下它时碰到的控件的 subview。 + +1662 +01:09:02,510 --> 01:09:05,444 +So it keeps trying here to be a subview of that scroll view, +所以在这里放下会成为那个 scroll view 的 subview, + +1663 +01:09:05,446 --> 01:09:08,046 +and I don't want it to be a subview, a scroll view, +不过我不希望它变成 scroll view 的 subview, + +1664 +01:09:08,048 --> 01:09:09,647 +because I want it to sit on top. +因为我想让它呆在顶层。 + +1665 +01:09:09,649 --> 01:09:11,049 +Okay, I want it to always be there, and +Okay,我希望它在那里一直不动, + +1666 +01:09:11,051 --> 01:09:12,516 +the scroll view is scrolling behind it. +scroll view 则在它后面滚动。 + +1667 +01:09:12,518 --> 01:09:15,119 +I don't want it to be in there scrolling around. +我不希望它被滑走。 + +1668 +01:09:15,121 --> 01:09:17,388 +Okay? + +1669 +01:09:17,389 --> 01:09:19,656 +So it's really a bit of a pain to do that with this in way. +所以这样做确实有点麻烦。 + +1670 +01:09:19,658 --> 01:09:22,559 +So you can just take something like your scroll view, for +所以你可以把那个控件,比如说这个 srollView, + +1671 +01:09:22,561 --> 01:09:25,094 +example, and move it out of the way temporarily. +临时先挪走。 + +1672 +01:09:25,096 --> 01:09:26,796 +So I just moved it out of the way. +所以我把它挪开了。 + +1673 +01:09:26,798 --> 01:09:29,298 +So now I can put my Container View in here. +现在我可以把我的 container view 放在这里。 + +1674 +01:09:29,300 --> 01:09:31,833 +I can put it where I want, probably not +我可以把它放在任何位置,可能不是 + +1675 +01:09:31,835 --> 01:09:35,070 +in the very corner there, something like that. +紧贴着这个角,类似这样。 + +1676 +01:09:35,072 --> 01:09:41,042 +I can do all my auto layout here. +我可以在这里设置 autoLayout。 + +1677 +01:09:41,044 --> 01:09:44,178 +Maybe we'll do this a little, do it higher, yeah, +我们可以在这里调整一下,高一点儿,耶, + +1678 +01:09:44,180 --> 01:09:46,113 +let's do that, bottom space. +设置一下,底边距。 + +1679 +01:09:46,115 --> 01:09:50,983 +Probably, I want this container to be a fixed width +大概,我希望这个 container view 有固定的 + +1680 +01:09:50,985 --> 01:09:52,952 +and height, okay. +宽高。 + +1681 +01:09:52,954 --> 01:09:54,787 +I don't know what width and height I would want. +我不知道我想要的宽高值。 + +1682 +01:09:54,789 --> 01:10:00,158 +Maybe like, I don't know, let's say 200 +可能是,我不知道,先假设是 200 + +1683 +01:10:00,160 --> 01:10:05,296 +by 200, sorry, double-click there. +x 200, 抱歉, 双击那里。 + +1684 +01:10:05,298 --> 01:10:06,563 +So let's make it 200 by 200. +让我们设置它为 200 x 200 的大小。 + +1685 +01:10:06,565 --> 01:10:10,633 +We could make it whatever size we thought was kind of most +我们可以把它设置为任何大小, + +1686 +01:10:10,635 --> 01:10:12,802 +appropriate for this space. +只要我们认为在这里尺寸合适。 + +1687 +01:10:12,804 --> 01:10:15,571 +And then we could put this back, this scroll view back. +然后我们把它放回去,把 scroll view 恢复回来。 + +1688 +01:10:15,573 --> 01:10:18,407 +By the way, if you go over here to the document outline, +顺便说下, 如果你去 document outline 里看看, + +1689 +01:10:18,409 --> 01:10:20,676 +you can see the order in the view hierarchy. +你会发现 view 层级的顺序。 + +1690 +01:10:20,678 --> 01:10:23,411 +Like this would be behind, and +这样会在后面, + +1691 +01:10:23,413 --> 01:10:26,681 +this is in front of everything else. +这样是在最前面。 + +1692 +01:10:26,683 --> 01:10:27,548 +Okay. + +1693 +01:10:27,550 --> 01:10:29,516 +Scroll view the activity indicator and +顺序从后往前是 scroll view,activity indicator, + +1694 +01:10:29,518 --> 01:10:30,717 +this Container View. +container view。 + +1695 +01:10:30,719 --> 01:10:33,453 +Now, I dragged this in here, but if we look oh, +现在,我把这个拽到了这里,但是如果我们仔细看,噢, + +1696 +01:10:33,455 --> 01:10:34,554 +look at down here. +看下面这里。 + +1697 +01:10:34,556 --> 01:10:35,621 +What's this guy? +这是什么? + +1698 +01:10:35,623 --> 01:10:36,755 +Okay. + +1699 +01:10:36,757 --> 01:10:41,593 +See that is the little view controller that could. +这就是那个小小的 view controller。 + +1700 +01:10:41,595 --> 01:10:44,228 +This is the little view controller that is going to, +这是要跳转的小小的 view controller, + +1701 +01:10:44,230 --> 01:10:46,163 +whose self.view is gonna be in here. +他的 self.view 在这里。 + +1702 +01:10:46,165 --> 01:10:48,832 +So let's do this guy right here, and we need a view +我们来实现它,我们需要给它定义一个 + +1703 +01:10:48,834 --> 01:10:51,968 +controller class for this, so I'm going to create that. +view controller,我马上来创建。 + +1704 +01:10:51,970 --> 01:10:55,171 +This is gonna be the world's simplest map view controller. +这会是世界上最简单的 map view controller. + +1705 +01:10:55,173 --> 01:10:59,875 +I'm gonna call it, in fact, SimpleMapViewController. +我干脆把它命名为 SimpleMapViewController。 + +1706 +01:10:59,877 --> 01:11:02,111 +It's gonna be a UIViewController. +它继承 UIViewController。 + +1707 +01:11:02,113 --> 01:11:06,314 +And all this SimpleMapViewController is +SimpleMapViewController 的所有任务 + +1708 +01:11:06,316 --> 01:11:11,485 +going to do is to make its map view outlet be public. +是把它的 map view 的 outlet 公开出来。 + +1709 +01:11:11,487 --> 01:11:14,221 +So that other people can do whatever the heck they want +这样别人就能够做他们想做的任何事情, + +1710 +01:11:14,223 --> 01:11:16,256 +with the map view that's inside of it. +用里面的 map view。 + +1711 +01:11:16,258 --> 01:11:18,591 +So let's put a map view inside of it. +所以我们先 添加一个 map view。 + +1712 +01:11:18,593 --> 01:11:19,892 +Let's go back to our storyboard. +回到 storyboard。 + +1713 +01:11:19,894 --> 01:11:22,661 +Get this little guy right here. +拿到这里的这个小家伙。 + +1714 +01:11:22,663 --> 01:11:25,164 +Okay, I'm gonna, first of all I'm gonna make him be +首先我要把它变成 + +1715 +01:11:25,166 --> 01:11:27,165 +a SimpleMapViewController, like that. +SimpleMapViewController,就像这样。 + +1716 +01:11:27,167 --> 01:11:31,069 +And then I'm going to put a map view, +然后添加一个 map view。 + +1717 +01:11:31,071 --> 01:11:35,005 +which is right here, inside of him. +放在这里,它的内部。 + +1718 +01:11:35,007 --> 01:11:36,139 +Okay? + +1719 +01:11:36,141 --> 01:11:37,974 +Let's go ahead and go, suggested constraints. +我们继续,采用 suggested constraints。 + +1720 +01:11:37,976 --> 01:11:40,843 +Probably, that'll be just fine, yep, +大概这样就挺好的, + +1721 +01:11:40,845 --> 01:11:42,345 +all looks good to me. +一切看上去都很好。 + +1722 +01:11:42,347 --> 01:11:47,683 +And so let's just create an outlet for that. +所以我们来创建它的 outlet。 + +1723 +01:11:47,685 --> 01:11:51,419 +Whoops, get an outlet here, +这里创建 outlet, + +1724 +01:11:51,421 --> 01:11:55,923 +small screen, there we go, okay. +屏幕太小,调到这里,okey。 + +1725 +01:11:55,925 --> 01:11:57,591 +Whoops, SimpleMapViewController, +选择 SimpleMapViewController, + +1726 +01:11:57,593 --> 01:11:59,760 +there it is. +好了。 + +1727 +01:11:59,761 --> 01:12:01,928 +Let's Ctrl+drag here, mapView, 'kay? +我们 Ctrl+拖拽到这里, mapView, okey? + +1728 +01:12:01,930 --> 01:12:03,563 +So that's it. +搞定。 + +1729 +01:12:03,564 --> 01:12:05,197 +That's the entire implementation of this class. +这就是这个类的完整实现。 + +1730 +01:12:05,200 --> 01:12:06,365 +It's just gonna do that. +这样就完成了。 + +1731 +01:12:06,367 --> 01:12:08,133 +It does MapKit, so we have to. +它使用了 MapKit,我们需要声明。 + +1732 +01:12:08,135 --> 01:12:13,304 +Import MapKit, okay, so this just is public and +import MapKit,okay,这就把 map view 公开了, + +1733 +01:12:13,306 --> 01:12:17,575 +we can do whatever we want with this map. +我们可以对它进行任何操作。 + +1734 +01:12:17,577 --> 01:12:19,610 +So, what do we want to do with this map? +那么,我们要对它干什么呢? + +1735 +01:12:19,612 --> 01:12:24,214 +Well, we want this map to show our waypoint in our +我们用它来展示 waypoint, + +1736 +01:12:24,216 --> 01:12:28,151 +waypoint image view controller, okay? +WaypointImageViewController 里的 waypoint。 + +1737 +01:12:28,153 --> 01:12:31,787 +So, that's how we're gonna update this embedded map. +这就是我们在 updateEmbeddedMap 函数里要做的。 + +1738 +01:12:31,789 --> 01:12:34,456 +We're, can access the map view directly. +我们直接访问这而过 mapView, + +1739 +01:12:34,458 --> 01:12:37,626 +But, the one thing we need to do, first, +不过,我们先要做的一件事, + +1740 +01:12:37,628 --> 01:12:40,528 +is we need to do this segue right here. +是我们需要在这里处理这个 segue。 + +1741 +01:12:40,530 --> 01:12:43,031 +So, we need to give this segue an identifier. +我们需要给这个 segue 一个标识符。 + +1742 +01:12:43,033 --> 01:12:47,334 +We'll call it the Embed Map segue. +我们叫它 “Embed Map” segue。 + +1743 +01:12:47,336 --> 01:12:51,237 +And we need to prepare this segue. +我们需要为这个 segue 实现 prepare 函数。 + +1744 +01:12:51,239 --> 01:12:54,540 +And we prepare it here. +我们在这里做实现。 + +1745 +01:12:54,542 --> 01:12:57,176 +We're going to prepare it by just by grabbing that map +prepare 函数里只需要抓取 + +1746 +01:12:57,178 --> 01:12:58,210 +view, okay? +map view, okay? + +1747 +01:12:58,211 --> 01:12:59,243 +Grabbing that controller, actually, +抓取那个 controller, + +1748 +01:12:59,246 --> 01:13:00,479 +than grabbing the map view out of it. +然后抓取里面的 map view。 + +1749 +01:13:00,481 --> 01:13:03,281 +So, I'm gonna prepare for segue here. +这里实现 prepareForSegue 函数。 + +1750 +01:13:03,283 --> 01:13:08,352 +I'm gonna say, if the segue's identifier equals, +输入 if segue.identifier = + +1751 +01:13:08,354 --> 01:13:11,889 +and we'll just, no constant here. +我们这里没有定义常量。 + +1752 +01:13:11,891 --> 01:13:13,023 +We should do one, but we're not gonna do. +我们应该这么处理,不过这次不做了。 + +1753 +01:13:13,025 --> 01:13:15,225 +So, it's the embed segue. +所以,等于 “Embed Segue” + +1754 +01:13:15,227 --> 01:13:19,795 +Then, actually, I'm just gonna create a var here, +然后,好吧,我要在这里创建一个变量, + +1755 +01:13:19,797 --> 01:13:24,333 +which is the SMVC, the simple map view controller. +名字是 smvc, 意思是 SimpleMapViewController。 + +1756 +01:13:24,335 --> 01:13:27,969 +Which is a SimpleMapViewController, +SimpleMapViewController 类型, + +1757 +01:13:27,971 --> 01:13:30,538 +optional. +optional 的。 + +1758 +01:13:30,539 --> 01:13:33,106 +And, I'm just gonna actually set it inside this prepare for +我要在这个 prepareForSegue 函数里给它赋值, + +1759 +01:13:33,109 --> 01:13:35,609 +segue, so, smvc equals the segue's +所以, + +1760 +01:13:35,611 --> 01:13:39,779 +destinationViewController as a SimpleMapViewController. +smvc = segue.destinationViewController as? SimpleMapViewController + +1761 +01:13:39,781 --> 01:13:41,747 +So, in the set prepare for segue, +所以在这个函数里, + +1762 +01:13:41,749 --> 01:13:45,117 +I've just grabbed onto this SimpleMapViewController. +我抓取了一个 SimpleMapViewController。 + +1763 +01:13:45,119 --> 01:13:48,420 +So, now that I have it, okay, let's go ahead and +我拿到了,okay,我们继续 + + +1764 +01:13:48,422 --> 01:13:52,090 +update our embedded map here, and let's do the code for +在这里更新内嵌的地图,我们来实现 + +1765 +01:13:52,092 --> 01:13:53,758 +doing the embedded map. +相关更新代码吧。 + +1766 +01:13:53,760 --> 01:13:54,825 +Very simple. +非常简单。 + +1767 +01:13:54,827 --> 01:13:57,094 +I'm just gonna say, +我只要输入, + +1768 +01:13:57,096 --> 01:14:01,497 +if I can get that map view out of that smvc. +如果我能拿到 smvc 的 map view。 + +1769 +01:14:01,499 --> 01:14:09,371 +Okay, then let's set the map view to be mapType Hybrid. +好了,那么我们就把 map view 的类型设置为 Hybrid。 + +1770 +01:14:09,373 --> 01:14:12,941 +And, then we want to set the map view's annotations. +并且设置 map view 的 annotations。 + +1771 +01:14:12,943 --> 01:14:18,479 +So, let's remove the existing annotations from the map view. +先删除掉现存的所有的 annotations, + +1772 +01:14:18,481 --> 01:14:25,019 +And then, let's MapView.addAnnotation for our way point. +再把 waypoint 加到 map view 里去。 + +1773 +01:14:25,021 --> 01:14:27,688 +Okay, which remember, is an MKAnnotation, so we can do that. +记住 waypoint 是 MKAnnotation 类型,所以我们可以把它作为参数。 + +1774 +01:14:27,690 --> 01:14:29,589 +And then, let's also zoom in on those. +然后,我们放大它。 + +1775 +01:14:29,591 --> 01:14:34,460 +So, showAnnotations, the map view's annotations and yes, +调用 showAnnotations 函数,参数为 mapView.annotations, + +1776 +01:14:34,462 --> 01:14:36,495 +we want it to be animated. +是的,过程需要动画。 + +1777 +01:14:36,497 --> 01:14:38,981 +Okay? + +1778 +01:14:38,982 --> 01:14:41,466 +So, that's gonna update our embedded map. +这就更新了内嵌的地图。 + +1779 +01:14:41,468 --> 01:14:44,469 +Yes, Embed Map. +哦,纠正一下,“Embed Map” + +1780 +01:14:44,471 --> 01:14:47,038 +Okay. + +1781 +01:14:47,039 --> 01:14:49,606 +All right, so, now that we're actually embedding the map and +好了,我们把地图内嵌了, + +1782 +01:14:49,609 --> 01:14:52,142 +doing that actual prepare for segue, +并且为 segue 做了准备工作, + +1783 +01:14:52,144 --> 01:14:53,977 +we should get this to work. +它应该能正常工作。 + +1784 +01:14:53,979 --> 01:14:55,912 +Here we go, and sure enough, there it is. +继续,肯定的,这就是了。 + +1785 +01:14:55,914 --> 01:14:58,214 +And, it's kind of hard to zoom out. +模拟器上的缩小操作有点麻烦。 + +1786 +01:14:58,216 --> 01:15:02,918 +Actually, I'm gonna do this on the actual device +我到真实设备上试一下, + +1787 +01:15:02,920 --> 01:15:06,321 +cuz it's a little easier to pinch. +因为再那上面 pinch 操作更简单。 + +1788 +01:15:06,323 --> 01:15:16,397 +>> [INAUDIBLE]. + +1789 +01:15:18,434 --> 01:15:20,701 +>> Oh, I didn't hit Play. +哦 我没有运行程序。 + +1790 +01:15:20,703 --> 01:15:29,676 +There we +那么 + +1791 +01:15:29,678 --> 01:15:34,814 +go. +走起。 + +1792 +01:15:34,816 --> 01:15:35,781 +All right. + +1793 +01:15:35,783 --> 01:15:38,083 +There we go. +继续。 + +1794 +01:15:38,085 --> 01:15:40,285 +Here or there. +这里或者那里。 + +1795 +01:15:40,287 --> 01:15:42,186 +We should have our nice image here. +我们这里有好看的图片。 + +1796 +01:15:42,188 --> 01:15:46,623 +And inside here, this MVC is a fully operational MVC. +在这里, 这个 MVC 是个完全可操作的 MVC。 + +1797 +01:15:46,625 --> 01:15:47,257 +It can be pinched. +它支持 pinch 操作。 + +1798 +01:15:47,259 --> 01:15:48,425 +It can scroll around. +它可以滚动。 + +1799 +01:15:48,427 --> 01:15:51,594 +It does all the things that it would normally do. +它支持所有正常支持的东西。 + +1800 +01:15:51,596 --> 01:15:55,264 +So, we can actually see that we're in +所以,我们能实际看出来,我们在 + +1801 +01:15:55,266 --> 01:16:00,168 +the Greenbush area of Greenbush Lake, all right? +Greenbush..Greenbush Lake 区域,对吗? + +1802 +01:16:00,170 --> 01:16:03,038 +Okay, and if we rotate or whatever, +Okay, 如果我们旋转或者做别的, + +1803 +01:16:03,040 --> 01:16:06,107 +a lot of layout works on it, et cetera. +layout 工作正常,等等。 + +1804 +01:16:06,109 --> 01:16:07,608 +Okay? + +1805 +01:16:07,610 --> 01:16:08,709 +So, that's embedded segue. +所以,这就是 Embedded Segue。 + +1806 +01:16:08,711 --> 01:16:10,177 +Sorry to run a little bit long. +抱歉拖的有点儿久了 + +1807 +01:16:10,179 --> 01:16:12,278 +If you have any questions, I'll be here as usual. +如果你有任何问题,我会一如既往地在这儿等待你们。 diff --git a/subtitles/17. Internationalization and Settings.srt b/subtitles/17. Internationalization and Settings.srt new file mode 100644 index 0000000..77cfc3c --- /dev/null +++ b/subtitles/17. Internationalization and Settings.srt @@ -0,0 +1,8368 @@ +1 +00:00:00,001 --> 00:00:04,769 +[MUSIC] +音乐 + +2 +00:00:04,771 --> 00:00:08,773 +Stanford University. +斯坦福大学 + +3 +00:00:08,775 --> 00:00:11,709 +>> Okay. Well, welcome to lecture 17, +好的,欢迎来到第 17 课 + +4 +00:00:11,711 --> 00:00:15,178 +Stanford CS193P, winter 2015. +斯坦福 CS193p 2015 + +5 +00:00:15,180 --> 00:00:17,947 +Today, our topics are Internationalization and +今天,我们的课题是国际化和 + +6 +00:00:17,949 --> 00:00:19,349 +Localization. +本地化 + +7 +00:00:19,351 --> 00:00:20,750 +That's making your application so +这可以让你的应用 + +8 +00:00:20,752 --> 00:00:23,552 +you can ship it all around the world in different languages. +使用不同的语言在全世界进行推广 + +9 +00:00:23,554 --> 00:00:26,188 +And then also, kind of a minor topic, +另外还有一个比较小的课题 + +10 +00:00:26,190 --> 00:00:29,824 +settings which is a way that you can add a little bit of +设置,以一种方式添加一些 + +11 +00:00:29,826 --> 00:00:34,428 +UI to the general settings application on the phone. +用户界面在手机上常规的设置 + +12 +00:00:34,430 --> 00:00:36,897 +And I have demos for both of these things. +等下我会有关于这些课题的演示 + +13 +00:00:38,133 --> 00:00:39,483 +All right. So let's talk about +好的,让我们开始讨论 + +14 +00:00:39,484 --> 00:00:40,834 +internationalization and localization. +国际化和本地化 + +15 +00:00:40,836 --> 00:00:42,568 +Those are actually two different things. +这是事实上两个不同的事物 + +16 +00:00:42,570 --> 00:00:43,703 +Okay? Internationalization, +接下来,国际化 + +17 +00:00:43,705 --> 00:00:44,937 +sometimes called I18N. +有时被称为 I18N + +18 +00:00:46,373 --> 00:00:49,174 +Because of 18 letters in there between I and the N. +因为这个单词在 I 和 U 之间有18个单词 + +19 +00:00:49,176 --> 00:00:53,544 +That's the process of making your application localizable. +这是一种方式让你的应用本地化 + +20 +00:00:53,546 --> 00:00:56,313 +And then, localization is the process of actually +然后,本地化是 + +21 +00:00:56,315 --> 00:00:58,382 +translating it to another language. +翻译它成为另外一种语言的过程 + +22 +00:00:58,384 --> 00:01:00,116 +So internationalization. +国际化 + +23 +00:01:00,118 --> 00:01:01,984 +That's work that you do as the developer. +这些工作是你作为开发时所需要做的 + +24 +00:01:01,986 --> 00:01:03,452 +Okay? +接下来 + +25 +00:01:03,453 --> 00:01:04,919 +You have to take your app and do some things to it. +你应该开始你的应用并且本地化 + +26 +00:01:04,922 --> 00:01:07,556 +Not a lot, but some little bit of things. +不需要很多, 但是需要一些东西 + +27 +00:01:07,558 --> 00:01:10,525 +To make all the strings that you have in there be pulled +让你应用里所有的字符串 + +28 +00:01:10,527 --> 00:01:13,395 +out or pullable out of there so +处于被剥离的状态 + +29 +00:01:13,397 --> 00:01:15,596 +that our translator can translate all of them. +以使翻译者可以翻译它们 + +30 +00:01:15,598 --> 00:01:17,798 +And then there's a little bit of formatting as well. +然后它也有一些格式 + +31 +00:01:17,800 --> 00:01:19,433 +Certain things, numbers, dates, +一些东西,数字,数据 + +32 +00:01:19,435 --> 00:01:22,069 +et cetera, look different in different languages so +还有其他的,看起来在不同语言不一样的 + +33 +00:01:22,071 --> 00:01:23,903 +you have to be able to do that. +你们都需要注意一下的 + +34 +00:01:23,905 --> 00:01:26,539 +And then localization is a process that. +本地化就是这样一个过程 + +35 +00:01:26,541 --> 00:01:28,240 +A localization company usually does. +一个本地化公司经常需要做这些 + +36 +00:01:28,242 --> 00:01:29,375 +Someone else does that. +有些其他的公司也会做 + +37 +00:01:29,377 --> 00:01:31,343 +Someone who's fluent in both languages. +有些人精通两种语言 + +38 +00:01:32,679 --> 00:01:34,178 +Maybe even someone who has a little bit of +甚至有些人会一些你应用 + +39 +00:01:34,180 --> 00:01:36,814 +domain knowledge about what your application does. +所需领域的知识 + +40 +00:01:36,816 --> 00:01:38,248 +So if it's a social networking app, +因此如果这是一个社交网络应用 + +41 +00:01:38,250 --> 00:01:40,650 +they're familiar with other social networking apps, so +它们将类似其他社交网络应用,因此 + +42 +00:01:40,652 --> 00:01:43,253 +they kind of know what various words and phrases. +他们了解多种单词与短语 + +43 +00:01:43,255 --> 00:01:46,322 +Would be in a UI like that. +像这所示应用在用户界面上 + +44 +00:01:46,324 --> 00:01:48,257 +And so this is kind of a two step process, and +这是一个两步过程, + +45 +00:01:48,259 --> 00:01:51,193 +so, you're always working on adding new features and +然后你将添加新的特性 + +46 +00:01:51,195 --> 00:01:52,961 +internationalizing those features, and +国际化特性 + +47 +00:01:52,963 --> 00:01:56,464 +the localizer is pretty much kind of always getting a dump +localizer 是一种很好的方式从你那里获得 + +48 +00:01:56,466 --> 00:01:58,132 +of the latest strings from you, and +最新的字符串 + +49 +00:01:58,134 --> 00:02:00,668 +they are translating them and sending back to you and +他们翻译它们并且发送回给你 + +50 +00:02:00,670 --> 00:02:02,369 +you're checking to see if it looks okay in UI. +你将检查并且判断它们在用户界面上是否可行 + +51 +00:02:02,371 --> 00:02:03,837 +You're going back and forth, so +你将来回做这些检查 + +52 +00:02:03,839 --> 00:02:06,439 +it's an iterative process back and forth between you +重复检查的过程往返于 + +53 +00:02:06,441 --> 00:02:09,575 +as the internationalizer and the localizer, +internationalizer 和 localizer 之间 + +54 +00:02:09,577 --> 00:02:11,177 +which is usually some third-party company. +这个通常是一些第三方的公司 + +55 +00:02:11,179 --> 00:02:15,047 +There's plenty of companies out there that do it. +有大量公司在那里做这些工作 + + +56 +00:02:15,049 --> 00:02:17,215 +So, let's talk about your side of it first, +因此让我们讨论你首先要做什么 + +57 +00:02:17,217 --> 00:02:19,084 +the internationalization part. +国际化的部分 + +58 +00:02:19,086 --> 00:02:23,421 +And there's really two places that you have strings +那有两个地方的字符串 + +59 +00:02:23,423 --> 00:02:25,723 +in your code, +在你的代码里 + +60 +00:02:25,724 --> 00:02:28,024 +strings meaning text that is going to appear in the UI. +字符串意味着它将在用户界面显示 + +61 +00:02:28,027 --> 00:02:29,760 +One is in your storyboard. +有一个在你的 storyboard + +62 +00:02:29,762 --> 00:02:33,096 +A lot of strings in there, labels and all that stuff. +一大堆的字符串在那里,标签和大量填充物 + +63 +00:02:33,098 --> 00:02:35,431 +And for storyboards, the way we do internationalization +为了 storyborads,用这个方式做国际化 + +64 +00:02:35,433 --> 00:02:37,233 +there is we. +这是我们 + +65 +00:02:38,336 --> 00:02:40,135 +Xcode knows how to reach in there and +Xcode 知道如何到达那里 + +66 +00:02:40,137 --> 00:02:42,137 +grab all those strings and +并且抓取所有那里的字符串 + +67 +00:02:42,138 --> 00:02:44,138 +pull them out in a way that you can give to a localizer. +将它们放置在你所给予的定位器上 + +68 +00:02:44,141 --> 00:02:46,374 +And then we use Autolayout, +然后我们用 Autolayout + +69 +00:02:46,376 --> 00:02:49,076 +to make sure everything looks nice when these strings +去确认所有看起来良好的,当那些字符串 + +70 +00:02:49,078 --> 00:02:51,912 +come back cuz these strings might be shorter or longer. +返回时,因为这些字符串可能很短或很长 + +71 +00:02:51,914 --> 00:02:55,715 +And so Autolayout is an extremely important part of +Autolayout 是极其重要的部分 + +72 +00:02:55,717 --> 00:02:57,150 +internationalization. +在国际化这方面 + +73 +00:02:57,152 --> 00:02:57,950 +Okay. It's just one word, +当然。它只是一个词 + +74 +00:02:57,952 --> 00:02:59,935 +Autolayout, but +Autolayout,但是 + +75 +00:02:59,936 --> 00:03:01,919 +it encompasses a lot of the work that you have to do. +它包办了很多你不得不做的工作 + +76 +00:03:01,922 --> 00:03:03,455 +Cuz you have to build your UI to be able to +因为你不得不建立你的用户界面使其 + +77 +00:03:03,457 --> 00:03:05,023 +deal with these different length strings. +处理这些不同长度的字符串 + +78 +00:03:05,025 --> 00:03:06,891 +So that's the first part. +这是第一部分 + +79 +00:03:06,893 --> 00:03:10,828 +Now the way you get these strings out of the storyboard, +现在用这个方式你从 storyboard 这里得到这些字符串 + +80 +00:03:10,830 --> 00:03:13,564 +the very first thing you need to do before you do +这是第一件你需要做的事 + +81 +00:03:13,566 --> 00:03:16,066 +any internationalization is register +然后你就用国际化去注册 + +82 +00:03:16,068 --> 00:03:17,767 +localizable languages. +本地化语言 + +83 +00:03:17,769 --> 00:03:20,269 +Languages that you want your app to be able to ship in. +多语言,你想要你的应用发布在什么地方 + +84 +00:03:20,271 --> 00:03:21,570 +Now. This isn't something you have +现在,这不是你一些你得前期做的 + +85 +00:03:21,572 --> 00:03:23,539 +to do upfront and pick them all when you're done, this, +并且当你完成所有工作时也要回过来看的事 + +86 +00:03:23,541 --> 00:03:25,974 +you can always add a new language along the way. +用这种方式你可以一直添加一个新的语言 + +87 +00:03:25,976 --> 00:03:28,576 +But, when you add a new language it's automatically, +但是当你添加一种新語言,它自动地 + +88 +00:03:28,578 --> 00:03:30,178 +the first time you add a new language it's +在你第一次添加一种新語言,它 + +89 +00:03:30,180 --> 00:03:32,213 +automatically going to make your story boards, so +自动地去做你的 storyboard + +90 +00:03:32,215 --> 00:03:34,481 +that their strings can be pulled out. +因此这些字符串会被剥离出来 + +91 +00:03:34,483 --> 00:03:35,382 +Okay. +好的 + +92 +00:03:35,383 --> 00:03:36,282 +This is super easy to do. +这是一个超级简单的方式 + +93 +00:03:36,285 --> 00:03:38,752 +You're just going to click on your project. +你将在你的项目里点击它 + +94 +00:03:38,754 --> 00:03:40,654 +And when you click on your project, +当你在你的项目里点击它 + +95 +00:03:40,655 --> 00:03:42,555 +you're actually gonna want the project, not the target. +你想要这个 project,不是 target + +96 +00:03:42,557 --> 00:03:44,623 +Sometimes when you click on the project in the very upper +有时当你想点击这个 project,可是有点偏左上方 + +97 +00:03:44,625 --> 00:03:47,126 +left of the navigator, it's gonna be selecting the target, +就会选到 target + +98 +00:03:47,128 --> 00:03:49,728 +which is that thing that says autolayout +这是一个写着 autolayout 的东西 + +99 +00:03:49,730 --> 00:03:51,763 +in the second column, the second autolayout down. +在第二列上,第二个自动布局下 + +100 +00:03:51,765 --> 00:03:54,499 +So you want the top one, which is your actual project, and +所以你想的顶部这一个,你当前的项目 + +101 +00:03:54,501 --> 00:03:56,500 +when you do, you're gonna have two tabs across the top, +当你开始做,你将有两个标签横穿顶部 + +102 +00:03:56,502 --> 00:03:58,936 +info and build settings, you see those? +info 和 build settings,你可以看到这些 + +103 +00:03:58,938 --> 00:04:00,570 +And you want to be in the info tab and +你想在这个 info 标签和 + +104 +00:04:00,572 --> 00:04:04,007 +you'll see about halfway down towards the bottom there. +你将看到中间那里往下到底部的那个 + +105 +00:04:04,009 --> 00:04:05,475 +It says localizations and +它是 localizations + +106 +00:04:05,477 --> 00:04:08,711 +there's actually just a list there of languages. +这个实际上是一个语言的列表 + +107 +00:04:08,713 --> 00:04:13,515 +So here my app is going to be localizable into Chinese, +所以这里我的应用将的本地化翻译为 + +108 +00:04:13,517 --> 00:04:14,949 +simplified and traditional. +简体和繁体 + +109 +00:04:14,951 --> 00:04:17,318 +Also into French and Japanese. +也可以翻译为法语和日语 + +110 +00:04:17,320 --> 00:04:18,219 +Okay. So you just keep +好的。因此你只要 + +111 +00:04:18,221 --> 00:04:19,987 +hitting plus button there. +那里的加号键 + +112 +00:04:19,988 --> 00:04:21,754 +It's just gonna ask what language you wanna add and +它会问你想要加什么语言然后帮你 + +113 +00:04:21,757 --> 00:04:22,622 +you add them. +添加他们 + +114 +00:04:22,624 --> 00:04:24,574 +Okay. +好的 + +115 +00:04:24,575 --> 00:04:26,525 +Now, you're gonna see why this is important later. +现在,你之后将看到为什么这个这么重要 + +116 +00:04:28,696 --> 00:04:31,330 +Now once you do this, the storyboards, +现在只要你做这个,这个 storyboards + +117 +00:04:31,332 --> 00:04:33,131 +if you look in the Navigator in your storyboard, +如果你在 storyboard 的导航条上 + +118 +00:04:33,133 --> 00:04:36,167 +it's gonna show all these localizations, right? +它将显示所有的本地化信息 + +119 +00:04:36,169 --> 00:04:38,569 +It's gonna have a list of all the localizations. +它将有所有的本地化信息列表 + +120 +00:04:38,571 --> 00:04:40,738 +If you expand the little storyboard. +如果你扩展这些 storybard + +121 +00:04:40,740 --> 00:04:43,306 +And also if you inspect the storyboard +并且如果你检测这个 storybard + +122 +00:04:44,343 --> 00:04:46,159 +in the file inspector. +在文件检测器这里 + +123 +00:04:46,160 --> 00:04:47,976 +Which is the left most tab in the utilities column there. +在实用列那里最左边的标签 + +124 +00:04:48,913 --> 00:04:50,479 +If you have a storyboard inspected, +如果你有一个 storyboard 的检测器 + +125 +00:04:50,481 --> 00:04:52,948 +it's gonna show you the localizations there too. +它也将向你显示本地化功能 + +126 +00:04:52,950 --> 00:04:54,849 +And so that's a good way to just double check. +当然这是一个很好的方式去仔细检查 + +127 +00:04:54,851 --> 00:04:57,051 +Oh yeah, yeah, I've got all the localizations for +好的好的,我将得到所有这些语言的 + +128 +00:04:57,053 --> 00:04:57,718 +all these languages. +本地化信息 + +129 +00:04:57,720 --> 00:04:58,986 +It's what I expect. +这就是我所期望的 + +130 +00:04:58,988 --> 00:05:00,620 +Usually you don't have to manipulate. +你也不需要去操作 + +131 +00:05:00,622 --> 00:05:02,789 +These two things in any way. +这两个事物任何情况 + +132 +00:05:02,791 --> 00:05:03,656 +It's just there. +它就在那里 + +133 +00:05:03,658 --> 00:05:05,491 +Usually you'll have it closed up. +你也可以将它关闭 + +134 +00:05:05,493 --> 00:05:06,992 +You'll have the little triangle pressed +你有一个三角形按键 + +135 +00:05:06,994 --> 00:05:07,993 +there by the storyboard. +在那个 storyboard 那里 + +136 +00:05:07,995 --> 00:05:09,861 +You won't even see these things. +你将不会再看到这些 + +137 +00:05:09,863 --> 00:05:12,530 +But that's just to show you what's happening +但是这只是当你想做这个时 + +138 +00:05:12,532 --> 00:05:15,433 +when you do that. +将发生的事 + +139 +00:05:15,435 --> 00:05:17,034 +So there are other strings in your app, though, +那里还有你应用的其他的字符串 + +140 +00:05:17,036 --> 00:05:18,835 +besides those storyboard things. +在这里 storyboard 之间 + +141 +00:05:18,837 --> 00:05:20,236 +Things in labels and stuff. +在填充物和标签这里 + +142 +00:05:20,238 --> 00:05:21,270 +There are literal strings. +它们是字面上的字符串 + +143 +00:05:21,272 --> 00:05:24,340 +Strings that in your code you put into the UI. +你代码里的字符串你把它们放到用户界面里 + +144 +00:05:24,342 --> 00:05:27,543 +And the way you localize those is by calling this function +你本地化这些的方式是用一个 + +145 +00:05:27,545 --> 00:05:29,544 +NSLocalizedString, okay? +NSLocalizedString 函数 + +146 +00:05:29,546 --> 00:05:31,312 +Very, very important function. +非常非常重要的函数 + +147 +00:05:31,314 --> 00:05:34,215 +Every single literal string that's ever gonna appear in UI +每一个单一的字符将会显示在用户界面 + +148 +00:05:34,217 --> 00:05:37,685 +needs to be wrapped in a call to NSLocalizedString. +用这个封装的方法 NSLocalizedString + +149 +00:05:37,687 --> 00:05:38,919 +So the arguments to this thing are, +这里的参数是 + +150 +00:05:38,921 --> 00:05:41,054 +the first thing is the key. +第一个是 key + +151 +00:05:41,056 --> 00:05:43,957 +Basically this is the thing that uniquely identifies this +基本上这是唯一方式去验证 + +152 +00:05:43,959 --> 00:05:45,391 +string. +字符 + +153 +00:05:45,393 --> 00:05:47,927 +Okay? +好的 + +154 +00:05:47,928 --> 00:05:50,462 +And this is usually the thing that you want to put on screen +这个通常你想要放到屏幕上的 + +155 +00:05:50,465 --> 00:05:52,331 +in the language of the developer. +开发者语言 + +156 +00:05:52,333 --> 00:05:55,233 +Okay, if English is your language, +当然如果英语是你选中的语言 + +157 +00:05:55,235 --> 00:05:56,735 +then this would be in English. +这将是英语 + +158 +00:05:56,737 --> 00:06:00,204 +If you're, you know, developing an application in. +如果你知道的开发一个应用 + +159 +00:06:00,206 --> 00:06:02,740 +Czechoslovakia and Czech is your language then this string +捷克和捷克语是你选定语言,这里的字符将会是 + +160 +00:06:02,742 --> 00:06:04,241 +would be in Czech, okay? +捷克语 + +161 +00:06:04,243 --> 00:06:06,176 +Or whatever, is that a language, Czech? +无论如何,那是一种语言,捷克语 + +162 +00:06:06,178 --> 00:06:06,743 +I think so. +我认为 + +163 +00:06:07,712 --> 00:06:09,345 +So that's what usually this is. +这就是它通常的情况 + +164 +00:06:09,347 --> 00:06:10,646 +But it wouldn't necessarily be that, +但是它并不是必要的 + +165 +00:06:10,648 --> 00:06:14,349 +because you might have the same word appear two places in +因为你可能想要在两个位置用相同的翻译 + +166 +00:06:14,351 --> 00:06:17,085 +the UI and actually, possibly have different translations. +在这个用户界面上或事实上,可能有不同的翻译 + +167 +00:06:17,087 --> 00:06:19,587 +Because they might mean slightly different things. +因为他们可能意味着些许不同 + +168 +00:06:19,589 --> 00:06:21,989 +So this key might not necessarily. +因此这个 key 并不是必要的 + +169 +00:06:21,991 --> 00:06:24,058 +Be that. +在那里 + +170 +00:06:24,059 --> 00:06:26,126 +If it's not, then the value option, okay? +如果不是,这个值的选择,可否如此 + +171 +00:06:26,128 --> 00:06:29,529 +See the third one or actually fourth one there value, that's +看这第三部分或者事实上第四部分那里的值 + +172 +00:06:29,531 --> 00:06:32,565 +the thing that it will use if it can't find this thing. +那是一个它将使用如果它不能找到这个 + +173 +00:06:32,567 --> 00:06:36,035 +A translator doesn't translate this key. +一个翻译者并不能翻译这些 key + +174 +00:06:36,037 --> 00:06:37,236 +Okay? +好吧 + +175 +00:06:37,237 --> 00:06:38,436 +Now the table name in the bundle, +现在这个在 bundle 里的表名 + +176 +00:06:38,439 --> 00:06:41,239 +that's a way of kind of organizing these localized +这是一种方式去组织这些译文 + +177 +00:06:41,241 --> 00:06:42,107 +strings into groups. +字符串到这个组里 + +178 +00:06:42,109 --> 00:06:44,275 +You can put them in little tables. +你可以把他们放到这些表里 + +179 +00:06:44,277 --> 00:06:45,776 +The bundle thing is more for +这个 bundle 有更多的 对于 + +180 +00:06:45,778 --> 00:06:49,013 +if you're localizing maybe a framework versus your app. +如果你局部化你的框架或者应用 + +181 +00:06:49,015 --> 00:06:53,516 +We'll talk about those two arguments in a second here. +我们等会将讨论这两个参数 + +182 +00:06:53,518 --> 00:06:56,552 +And then the last argument, comment, super important. +这个最后的参数,comment,非常重要 + +183 +00:06:56,554 --> 00:06:59,588 +This is a comment that goes to the translator. +这个 comment 将会发到翻译者那里 + +184 +00:06:59,590 --> 00:07:02,591 +So this tells the translator, this is the context of this. +这个将告诉翻译者,这些是内容 + +185 +00:07:02,593 --> 00:07:05,193 +Now the translator when they're doing the storyboard, +现在这个翻译者当他们在 storyboard 里翻译 + +186 +00:07:05,195 --> 00:07:07,262 +they see your storyboard cuz you're gonna send them your +他们查看你的 storyboard 因为你将发送他们 + +187 +00:07:07,264 --> 00:07:08,129 +storyboard as well. +到 storyboard + +188 +00:07:08,131 --> 00:07:09,864 +So they're gonna see the context. +他们将看到内容 + +189 +00:07:09,866 --> 00:07:12,566 +Oh, this is a label for a field, I get it. +这是 field 的标签,我所得到的 + +190 +00:07:12,568 --> 00:07:15,469 +But here these strings are in your code, and so +但是这里的这些在你的代码里字符串 + +191 +00:07:15,471 --> 00:07:17,637 +they have no idea where this thing's gonna pop in the UI. +他们没有办法在你的用户界面上显示 + +192 +00:07:17,639 --> 00:07:20,139 +So you need to give very good comments here +因此你需要给非常好的注释 + +193 +00:07:20,141 --> 00:07:21,808 +to localize, you know. +去本地化,你懂的 + +194 +00:07:21,809 --> 00:07:23,476 +This is the title I'm gonna work that comes up. +这是一个我等下要将的题目 + +195 +00:07:23,478 --> 00:07:26,278 +When this bad thing happens because the user did this or +当有什么坏事发生,因为用户做这些或者 + +196 +00:07:26,280 --> 00:07:28,747 +whatever, so that they know what the best +任何事,因此他们知道最好的 + +197 +00:07:28,749 --> 00:07:31,316 +translation of that word to put up is. +被提出的翻译 + +198 +00:07:32,285 --> 00:07:34,085 +So in this localized string, you pass these arguments and +因此在这个本地化字符里,你通过这些参数 + +199 +00:07:34,087 --> 00:07:35,185 +it gives you back a string, +然后它给你特定的字符 + +200 +00:07:35,187 --> 00:07:37,688 +and the string it gives you back will either be, +这个它给回你的将不可或缺 + +201 +00:07:37,690 --> 00:07:40,557 +if there's no translation, the value there, or +如果没有这些翻译,这个值 + +202 +00:07:40,559 --> 00:07:42,658 +the key itself if there's no value. +或者这个 key 没有值 + +203 +00:07:42,660 --> 00:07:44,660 +Or it's gonna be the translated string that came +或者它已经被翻译了 + +204 +00:07:44,662 --> 00:07:46,895 +back from the localizer, okay? +它将回到这个 localizer + +205 +00:07:46,897 --> 00:07:48,163 +And then you're gonna use that string. +然后你就可以用这些字符 + +206 +00:07:48,165 --> 00:07:49,581 +You can put it in the UI. +你可以将他们放在用户界面上 + +207 +00:07:49,582 --> 00:07:50,998 +So you wanna wrap every literal string in this. +你想要包裹的每一个字符 + +208 +00:07:51,001 --> 00:07:54,268 +Now most of the time, the table name and +现在大部分的时间,这个 tablename 和 + +209 +00:07:54,270 --> 00:07:56,270 +bundle are defaulted. +bundle 是默认的 + +210 +00:07:56,272 --> 00:07:59,206 +The table name is just gonna be Localizable. +这个表名需要本地化 + +211 +00:07:59,208 --> 00:08:01,942 +Which is where mostly you put all your strings actually in +这是一个你放你所有字符串的地方 + +212 +00:08:01,944 --> 00:08:03,576 +a table called localizable, and +这个表叫做 localizable + +213 +00:08:03,578 --> 00:08:05,578 +the bundle's gonna be your main bundle. +这个 bundle 将作为你主要的 bundle + +214 +00:08:05,580 --> 00:08:07,513 +That means your app, okay? +这意味着你的应用 + +215 +00:08:07,515 --> 00:08:09,915 +Now we haven't talked too much about bundles, but +现在我们不能讨论太多关于 bundle,但是 + +216 +00:08:09,917 --> 00:08:11,316 +when you have frameworks and other things, +当你有框架或者其他的东西时 + +217 +00:08:11,318 --> 00:08:14,185 +you can have other bundles of code in your app. +你的应用可以有其他的 bundle + +218 +00:08:14,187 --> 00:08:16,621 +And they might have their own bundles of strings, but +他们可以有他们自己的字符串 bundle + +219 +00:08:16,623 --> 00:08:19,523 +I'm not gonna really talk about that. +但是我确实不打算现在讨论这个 + +220 +00:08:19,525 --> 00:08:21,258 +I'm just going to say that most of the time you're +我将讲一下大部分时间你将 + +221 +00:08:21,260 --> 00:08:23,627 +just gonna call this version of NSLocalizedString that +使用的 NSLocalizedString 的版本 + +222 +00:08:23,629 --> 00:08:27,063 +only has the key and a comment. +这个是只有 key 和 comment + +223 +00:08:27,065 --> 00:08:28,181 +Okay? +好的 + +224 +00:08:28,182 --> 00:08:29,298 +Because it's gonna use the key as the value +因为它将用这个 key 作为值 + +225 +00:08:29,300 --> 00:08:30,799 +if there's no translation, and +如果他们没有翻译 + +226 +00:08:30,801 --> 00:08:33,902 +you've gotta have that comment to the translator, okay? +你将得到翻译者的注释 + +227 +00:08:33,904 --> 00:08:36,771 +So that 90% of the time you just skip it. +90% 的时间你将略过它 + +228 +00:08:36,773 --> 00:08:39,374 +No NS localized string comma colon around your +不是 NSLocalizedString 注释你的 + +229 +00:08:39,376 --> 00:08:40,274 +literal strings. +字符串 + +230 +00:08:40,276 --> 00:08:41,792 +And that's it. +就酱 + +231 +00:08:41,793 --> 00:08:43,309 +That's all you need to do to get all those little strings +这些所有你所需要的字符串将会被 + +232 +00:08:43,312 --> 00:08:44,344 +to be translatable. +翻译 + +233 +00:08:44,346 --> 00:08:46,713 +All right? +好的 + +234 +00:08:46,715 --> 00:08:49,515 +Now, if you use a format string. +现在如果你使用这个组织好的字符 + +235 +00:08:49,517 --> 00:08:51,150 +So this format string, +这些组织好的字符 + +236 +00:08:51,152 --> 00:08:55,253 +the result is %g or the result is %d, okay? +这个结果是 %g 或者 %d + +237 +00:08:55,255 --> 00:08:56,821 +So you're using a format string. +你将用这些组织好的字符 + +238 +00:08:56,823 --> 00:09:00,391 +You're gonna wanna use this string, class method called +你将想要使用这些字符 + +239 +00:09:00,393 --> 00:09:03,894 +localized string with format to create a string from it. +在被称为 localizedStringWithFormat 的方法里创建字符 + +240 +00:09:03,896 --> 00:09:07,964 +So it takes var args at the end for +它用 var 参数在所有 + +241 +00:09:07,966 --> 00:09:11,768 +all the %ds or %gs or whatever in the string. +%d 或者 %g 末尾或者任何字符里 + +242 +00:09:11,770 --> 00:09:15,004 +And you would want that format string to also be +你想组织好的字符 + +243 +00:09:15,006 --> 00:09:17,006 +NS localized string. +NSLocalizedString + +244 +00:09:17,008 --> 00:09:20,175 +Okay because the words in there, the result is, +因为这个单词在那里,结果在那里 + +245 +00:09:20,177 --> 00:09:22,010 +those need to be translated as well. +这些也需要被翻译 + +246 +00:09:22,012 --> 00:09:25,080 +But the reason you wanna use this localizedStringWithFormat +你想要使用 LocalizedStringWithFormat 的方法的原因是 + +247 +00:09:25,082 --> 00:09:27,648 +is because numbers are not always displayed the same +数字在 + +248 +00:09:27,650 --> 00:09:28,949 +in different languages. +不同语言里显示不一定一样 + +249 +00:09:28,951 --> 00:09:32,753 +So you wanna give the system a chance to display any %gs or +因此你想让这个系统选择显示 %g 或者 + +250 +00:09:32,755 --> 00:09:34,921 +%ds properly in there. +%d 的那些 + +251 +00:09:34,923 --> 00:09:36,222 +You're actually not even gonna +你完全不想 + +252 +00:09:36,224 --> 00:09:37,723 +use this that much because you are gonna +使用这个因为你想 + +253 +00:09:37,725 --> 00:09:40,325 +use a number formatter which I'm gonna talk about. +使用我所说的 number formatter + +254 +00:09:40,327 --> 00:09:42,361 +In a second, and the number formatter does an even more +等一下这个 number formatter 做一个 + +255 +00:09:42,363 --> 00:09:44,562 +powerful job of making sure the number looks good. +很强大的事去确保数字看起来不错 + +256 +00:09:45,732 --> 00:09:48,799 +If you have multiple percent things in there, %d, %g, +如果你有多个 % 的东西在那里,比如 %d,%g + +257 +00:09:48,801 --> 00:09:52,636 +a lot of them, the localizer is able to specify the order. +有很多这些,这个 localizer 将会给他们排序 + +258 +00:09:52,638 --> 00:09:54,771 +Because, as you can imagine, as some languages, +因为,正如你可以想象的,一些语言 + +259 +00:09:54,773 --> 00:09:57,007 +the words might come in a little different order, +这个单词将在不同的序列里出现 + +260 +00:09:57,009 --> 00:09:59,242 +just because of the way phrasing works in a language. +只是因为语言的分词 + +261 +00:09:59,244 --> 00:10:01,310 +And they are able to do that when they translate, so +他们将做这些当他们在翻译的时候 + +262 +00:10:01,312 --> 00:10:02,378 +no worries. +没有什么好担忧的 + +263 +00:10:02,380 --> 00:10:02,944 +There. +在 那里 + +264 +00:10:04,314 --> 00:10:05,646 +All right. So that's strings, +当然,这些字符串 + +265 +00:10:05,648 --> 00:10:08,115 +strings in your storybook, little strings in your code. +在你的 storybook 里的字符串,在你代码里的字符串 + +266 +00:10:08,117 --> 00:10:10,851 +Now, let's talk about formatters. +好,让我讨论一下 formatters + +267 +00:10:10,853 --> 00:10:13,320 +So, formatters work based on a locale. +formatters 是基于本地的 + +268 +00:10:13,322 --> 00:10:16,389 +So there's really two parts of what makes something +这里有两个部分使他们 + +269 +00:10:16,391 --> 00:10:18,725 +localized. +本地化 + +270 +00:10:18,726 --> 00:10:21,060 +One is the language, Japanese or French or whatever. +一个是语言,比如日语法语或者其他的 + +271 +00:10:21,062 --> 00:10:23,596 +But the other is locale. +另外一个是位置 + +272 +00:10:23,598 --> 00:10:26,398 +And the locale is where in the world you are essentially. +位置是你在这个世界上实质上的位置 + +273 +00:10:26,400 --> 00:10:29,134 +So your language might be Spanish but +你的语言可能是西班牙语 + +274 +00:10:29,136 --> 00:10:31,836 +maybe you're in Mexico or maybe you're in Spain or +但是你在墨西哥或者你在西班牙或者 + +275 +00:10:31,838 --> 00:10:33,438 +some other part of the world that speaks Spanish. +一些其他使用西班牙语的地方 + +276 +00:10:33,440 --> 00:10:34,989 +Okay. +好的 + +277 +00:10:34,990 --> 00:10:36,539 +So you would have a different locale, Mexico or +因此你将有不同的位置,墨西哥 + +278 +00:10:36,542 --> 00:10:39,309 +Spain, than your language which might be Spanish. +或者西班牙,然后你的语言将可能是西班牙语 + +279 +00:10:39,311 --> 00:10:40,844 +Okay? So +好的 + +280 +00:10:40,845 --> 00:10:42,378 +the formatters are gonna format things, numbers and +formatters 将会组织这些东西,数字 + +281 +00:10:42,381 --> 00:10:43,580 +dates and stuff. +数据和材料 + +282 +00:10:43,582 --> 00:10:45,481 +Currencies, based on your locale. +货币基于你的位置 + +283 +00:10:46,751 --> 00:10:48,217 +Okay? +好的 + +284 +00:10:48,218 --> 00:10:49,684 +And so what kind of formatters are there? +那里有哪种排版方式 + +285 +00:10:49,687 --> 00:10:51,720 +Well we've already seen number formatter, +好的我们已经看过 number formatter + +286 +00:10:51,722 --> 00:10:53,788 +actually we saw it the very first day of this class. +事实上我们在很早的第一天的课上说过 + +287 +00:10:53,790 --> 00:10:55,923 +Number formatter knows how to take a number and +number formatter 知道怎样排版数字 + +288 +00:10:55,925 --> 00:10:57,558 +turn it into a string. +到字符里 + +289 +00:10:57,560 --> 00:11:01,862 +And we didn't really worry about locale when we +我们不关心位置,当我们 + +290 +00:11:01,864 --> 00:11:03,430 +used it early in the quarter. +在现在使用它的时候 + +291 +00:11:03,432 --> 00:11:05,765 +It was a little advanced topic at that time. +因为现在将这个课题有点高级 + +292 +00:11:05,767 --> 00:11:08,367 +But it was using the locale even though we weren't +但是它会被使用,我们不用担心它 + +293 +00:11:08,369 --> 00:11:10,402 +worrying about it, it was using it. +它会被用 + +294 +00:11:10,404 --> 00:11:12,204 +This number of format will also be used for +这个用来排版数字的也会用来 + +295 +00:11:12,206 --> 00:11:13,872 +formatting currencies. +排版货币 + +296 +00:11:13,874 --> 00:11:16,541 +Okay, your local currencies. +当然你本地的货币 + +297 +00:11:16,543 --> 00:11:18,776 +And then dates is another one. +数据是另一回事 + +298 +00:11:18,778 --> 00:11:21,679 +Dates are displayed myriad different ways across +日期在不同的地方有不同的 + +299 +00:11:21,681 --> 00:11:22,963 +the globe. +排版 + +300 +00:11:22,964 --> 00:11:24,246 +So you definitely need to use a date formatter if you're +所以你需要使用这个 date formatter 如果 + +301 +00:11:24,249 --> 00:11:26,616 +gonna put any kind of date in your UI. +你将放一些日期到你的用户界面上 + +302 +00:11:26,618 --> 00:11:28,718 +There's also date components formatter, so +那里也有一下日期组件的 formatter + +303 +00:11:28,720 --> 00:11:32,188 +date components are like the day of the week, the month. +日期组件就像周天,月天 + +304 +00:11:32,190 --> 00:11:36,325 +Okay, those also are displayed differently across the world. +当然,这些在世界各地有不同的显示方式 + +305 +00:11:36,327 --> 00:11:39,461 +And there's even kind of some fringe formatters you wouldn't +还有一下临界的 formatter 你不需要考虑的 + +306 +00:11:39,463 --> 00:11:42,764 +think but you need to like byte count formatters, okay? +但是你需要知道像这种 count formatter + +307 +00:11:42,766 --> 00:11:47,401 +So if you wanna say 350 kilobytes left of 2 gigabytes. +如果你想说 350 千字节 左边的 2 千兆字节 + +308 +00:11:47,403 --> 00:11:50,237 +Okay, those numbers look a little different in different +好的,那些数字看起来不一样在不同 + +309 +00:11:50,239 --> 00:11:51,305 +languages. +语言里 + +310 +00:11:51,306 --> 00:11:52,372 +You can't just put the number in there and +你不能只是把数字放在那 + +311 +00:11:52,374 --> 00:11:55,275 +put kb after it and expect that to be kilobytes. +放 kb 在那之后和期望那个是千字节 + +312 +00:11:55,277 --> 00:11:57,243 +It's not necessarily gonna be right. +它并不一定是对的 + +313 +00:11:57,245 --> 00:11:59,712 +So the byte count format I can help you with that, and +因此字节计数的 formatter 我可以帮你到这 + +314 +00:11:59,714 --> 00:12:01,847 +then in map kit there's the distance formatter. +然后是地图套件的排版 + +315 +00:12:01,849 --> 00:12:04,216 +So you can specify here's the distance between two places +你可以特定这两个位置的距离 + +316 +00:12:04,218 --> 00:12:06,885 +because that also needs to be localized. +因为它也可以定位 + +317 +00:12:06,887 --> 00:12:08,753 +Health kit also has a number of things. +健康组件也有数字 + +318 +00:12:08,755 --> 00:12:11,288 +Like energy, calories used. +像能量,卡路里 + +319 +00:12:11,290 --> 00:12:13,157 +Those kinds of things. +这些东西 + +320 +00:12:13,159 --> 00:12:16,159 +Some of those are different in different locales. +这些东西在不同位置是不一样的 + +321 +00:12:16,161 --> 00:12:19,229 +So any time you're gonna put a number or +任何时间你将放一个数字或者 + +322 +00:12:19,231 --> 00:12:22,565 +a date on screen, you're gonna wanna see if there's a proper +日期在屏幕上,你想看它是否 + +323 +00:12:22,567 --> 00:12:25,434 +formatter to format this thing, okay? +排版合适 + +324 +00:12:25,436 --> 00:12:26,535 +So how do formatters work? +所以要怎么处理这些格式 + +325 +00:12:26,537 --> 00:12:27,536 +Let's look at a couple of them. +让我们看这一组 + +326 +00:12:27,538 --> 00:12:28,937 +Let's look at NS Number Formatter. +让我们看 NSNumberFormatter 方法 + +327 +00:12:28,939 --> 00:12:30,405 +Now NS Number Formatter. +现在是 NSNumberFormatter + +328 +00:12:30,407 --> 00:12:31,856 +A lot of API there. +有很多的 API + +329 +00:12:31,857 --> 00:12:33,306 +You're really gonna wanna check out the documentation. +你可以去查看一下文档 + +330 +00:12:33,309 --> 00:12:35,943 +But I'm gonna look at the two most basic cases. +但是我想要提一下两个最基础的案例 + +331 +00:12:35,945 --> 00:12:37,778 +One is just displaying a number. +一个是只显示数字 + +332 +00:12:37,780 --> 00:12:39,846 +So you create an NSNumberFormatter +你创建一个 NSNumberFormatter + +333 +00:12:39,848 --> 00:12:41,447 +like we did in the calculator. +正如我们在计算器那里所做的 + +334 +00:12:41,449 --> 00:12:43,883 +Then you set the style of the number. +然后你设置一下数字的类型 + +335 +00:12:43,885 --> 00:12:47,519 +So for example, decimal style or currency style. +比如,十进制或者货币类型 + +336 +00:12:47,521 --> 00:12:50,288 +There's also a style even spell out style that will +这个也有拼写类型 + +337 +00:12:50,290 --> 00:12:53,458 +spell the number out, 3,000, T-H-R-E-E T-H-O-U-S-A-N-D, +拼写这个数字,3000, 3 千 + +338 +00:12:53,460 --> 00:12:57,261 +right it'll set it out as words in the local language. +它会设置它的词作为本地语言 + +339 +00:12:57,263 --> 00:12:58,929 +So there's a few styles in there. +因此那里有一些类型 + +340 +00:13:00,066 --> 00:13:02,165 +Then you can set other things about the formatter, +你可以设置其他的东西关于排版 + +341 +00:13:02,167 --> 00:13:03,933 +how many digits you want before and +你想有多少数字在十进制点的前后, + +342 +00:13:03,935 --> 00:13:06,969 +after the decimal point, how you want rounding to happen, +你想怎么四舍五入 + +343 +00:13:06,971 --> 00:13:08,104 +all that kind of stuff. +所有这些材料 + +344 +00:13:08,106 --> 00:13:09,938 +Set that all up and +设置这些所有的 + +345 +00:13:09,940 --> 00:13:15,110 +then you just call formatter string from number. +然后你只是从数字这里排版这些字符 + +346 +00:13:15,112 --> 00:13:18,012 +You give it the number you want and it will return to you +你给它数字,它返回你 + +347 +00:13:18,014 --> 00:13:21,115 +a string that uses all those attributes that you set up and +字符,使用所有这些属性设置和适应 + +348 +00:13:21,117 --> 00:13:23,150 +be proper for the locale you're in. +你的位置 + +349 +00:13:23,152 --> 00:13:25,986 +Okay? +好的 + +350 +00:13:25,988 --> 00:13:27,137 +So that's that way. +就是这种方式 + +351 +00:13:27,138 --> 00:13:28,287 +And of course, think about the other way. +当然,可以考虑其他方式 + +352 +00:13:28,290 --> 00:13:29,689 +If you're gonna ask the user for +如果你想要问用户 + +353 +00:13:29,691 --> 00:13:33,526 +a number then, you better use a number formatter to parse +一个数字,你最好用数字 formatter 去解析 + +354 +00:13:33,528 --> 00:13:36,295 +that number into a number from a string. +数字,从字符转为数字 + +355 +00:13:36,297 --> 00:13:38,864 +And, that's because, as you know, some parts of the world, +因为你知道,世界上有些国家 + +356 +00:13:38,866 --> 00:13:41,266 +the decimal separator's actually a comma. +十进制里有个逗号 + +357 +00:13:41,268 --> 00:13:43,434 +So if they type three comma two,. +所以如果他们打印三逗号二 + +358 +00:13:43,436 --> 00:13:45,036 +And you don't use a formatter, +然后你不想用这个排版 + +359 +00:13:45,038 --> 00:13:46,170 +you're gonna look at that and say, oh. +你看着然后说,哦 + +360 +00:13:46,172 --> 00:13:47,804 +They want, what do they want, three? +他们想,他们想什么,三个 + +361 +00:13:47,806 --> 00:13:49,806 +Or that's just not even a valid number, right? +或者这甚至不是一个有效的数字,对不对 + +362 +00:13:49,808 --> 00:13:52,508 +But if they type three comma two and they're locale is some +但是如果他们输入 3,2 而然后他们定位是一些 + +363 +00:13:52,510 --> 00:13:54,143 +place where that's the way numbers are expressed, +位置,这些位置是数字表达的方式 + +364 +00:13:54,145 --> 00:13:57,846 +then that's gonna give you 3.2 back out of it, okay? +然后它将给你 3.2,对不对 + +365 +00:13:57,848 --> 00:14:01,449 +So displaying of parsing numbers main job event is for +显示一个解析的数字是主要的事件 + +366 +00:14:01,451 --> 00:14:02,595 +number formatter. +对于这个数字解释器来说 + +367 +00:14:02,596 --> 00:14:03,740 +But there's a lot more in there. +但是那里还有更多的东西 + +368 +00:14:03,741 --> 00:14:04,885 +So you definitely wanna familiarize yourself with +因此你一定想要熟悉一下 + +369 +00:14:04,888 --> 00:14:05,619 +that class. +这些类 + +370 +00:14:06,789 --> 00:14:07,821 +On the date side. +在这个日期这一边 + +371 +00:14:07,823 --> 00:14:10,824 +Okay, formatting dates, very complicated. +当然,排版好这些日期非常复杂 + +372 +00:14:10,826 --> 00:14:13,593 +Okay, how we as humans represent dates, +作为人类,如何表示日期 + +373 +00:14:13,595 --> 00:14:16,195 +we don't do it in a simple way, unfortunately. +不幸的是我们不能用一种简单的方式 + +374 +00:14:16,197 --> 00:14:20,966 +Luckily there's some built in, pretty simple styles for +幸运的是有一些建立的简单的类型 + +375 +00:14:20,968 --> 00:14:22,500 +showing numbers. +去显示数字 + +376 +00:14:22,502 --> 00:14:26,070 +Short style, medium style, long style, full style. +Short 类型,medium 类型,long 类型,full 类型 + +377 +00:14:26,072 --> 00:14:28,939 +And hopefully those will do what you want. +希望这有你想要的 + +378 +00:14:28,941 --> 00:14:31,108 +Cuz if you can use one of those, then the way to +因为如果你用这些的其中一种 + +379 +00:14:31,110 --> 00:14:33,643 +do it is you just create an NS Date Formatter, +这是一种你创建的日期格式的方式 + +380 +00:14:33,645 --> 00:14:36,913 +you set the time style and the date style to be one of these +你设置这个时间类型和日期类型作为这一个的 + +381 +00:14:36,915 --> 00:14:41,150 +kind of styles, and then you just get you string from date. +类型,然后你只要拿到你日期的字符 + +382 +00:14:41,152 --> 00:14:43,886 +And now you'll have a string that you can put in the UI +现在你将有一个字符,你把它放到用户界面里 + +383 +00:14:43,888 --> 00:14:46,688 +that will be fully localized in the local language and +这将用当地语言完全本地化 + +384 +00:14:46,690 --> 00:14:47,822 +in the right locale. +在一个正确的位置 + +385 +00:14:47,824 --> 00:14:50,091 +Okay? +好的 + +386 +00:14:50,093 --> 00:14:52,259 +UIImage, how about images? +UIImage,图片怎么样 + +387 +00:14:52,261 --> 00:14:56,063 +Because some street signs or other things like that might +因为有有些街道标志或者其他一些 + +388 +00:14:56,065 --> 00:14:58,265 +look different in other language. +在其他语言看起来可能不一样的 + +389 +00:14:58,267 --> 00:15:00,633 +And there's a couple of ways to do that. +这里有一系列方式去做到这一点 + +390 +00:15:00,635 --> 00:15:04,771 +If you put the JPEGs or the PNGs directly in your project, +如果你放 JPEG 或者 PNG 的图片到你的项目里 + +391 +00:15:04,773 --> 00:15:07,940 +in other words you don't put them in the images.xcassets +换句话说你不想把他们放到 images.xcassets + +392 +00:15:07,942 --> 00:15:09,642 +thing. +这里 + +393 +00:15:09,643 --> 00:15:11,343 +Then actually those can become localizable files. +事实上这些可以变成本地文件 + +394 +00:15:11,345 --> 00:15:13,979 +And you just click on them, go to the file inspector, and +你只要点击他们,进入文件检查器 + +395 +00:15:13,981 --> 00:15:15,413 +say make this localizable. +把这个变成本地化 + +396 +00:15:15,415 --> 00:15:16,714 +And you can have a different version for +你可以有不同的版本 + +397 +00:15:16,716 --> 00:15:21,051 +every language that you want. +作为你想要的不同语言 + +398 +00:15:21,053 --> 00:15:24,221 +But maybe a better way to do it is put them in your +但是可能一个很好的方式去解决就是把他们放到 + +399 +00:15:24,223 --> 00:15:26,106 +xcassets. +xcassets 这里 + +400 +00:15:26,107 --> 00:15:27,990 +Put all the images from all the languages. +所有语言的图片文件都放这 + +401 +00:15:27,993 --> 00:15:30,560 +And give them names +给他们命名 + +402 +00:15:30,562 --> 00:15:34,329 +that you can then look up using NSLocalizedString. +你可以用 NSLocalizedString 查阅 + +403 +00:15:34,331 --> 00:15:36,198 +Okay? Okay. +好不好?好 + +404 +00:15:36,199 --> 00:15:38,066 +And then your translators can translate the name of stop +你的 translators 可以翻译这些名称,停止标志被 + +405 +00:15:38,068 --> 00:15:41,903 +sign to French stop sign, or something like that. +翻译成法语版本或者其他的语言 + +406 +00:15:41,905 --> 00:15:44,305 +And then that'll be the name in the image.scs. +这些名字会在 images.xcassets 这里 + +407 +00:15:44,307 --> 00:15:46,340 +And then you can use some naming convention to group +然后你可以用这些命名规范去 + +408 +00:15:46,342 --> 00:15:47,574 +them, or whatever you wanna do. +组织他们或者做任何你想做的事 + +409 +00:15:47,576 --> 00:15:50,177 +But that's probably a little bit better way to do it, +这可能有一点好的方式去做它 + +410 +00:15:50,179 --> 00:15:52,445 +because then your translator has a little more +因为你的 translator 能够 + +411 +00:15:52,447 --> 00:15:53,947 +control of it. +控制它 + +412 +00:15:53,948 --> 00:15:55,448 +Now you'll have to coordinate with your translator to +现在你将不得不协调你的翻译器去 + +413 +00:15:55,450 --> 00:15:57,817 +make sure you name the images in your xcassets to match what +确保你的图片名称在你的 xcassets 里匹配 + +414 +00:15:57,819 --> 00:15:59,084 +they've translated them to. +他们的译文 + +415 +00:15:59,086 --> 00:16:02,254 +But still a pretty straight forward way of doing that. +但是这样做仍然是一个非常直接的方式 + +416 +00:16:02,256 --> 00:16:06,224 +Okay, so congratulations. +好的,祝福你 + +417 +00:16:06,226 --> 00:16:07,792 +You've done all those things, right? +你将完成这些,对吧 + +418 +00:16:07,794 --> 00:16:11,295 +You did the story boards, you added the languages, +你在 storyboards 处理,你添加语言 + +419 +00:16:11,297 --> 00:16:15,865 +you used NS localize string, you +你使用 NSLocalizeString 方法 + +420 +00:16:15,867 --> 00:16:18,334 +put the formatters in there, now your app is localizable. +你放这些组排版的在那里,现在你的应用是本地化的 + +421 +00:16:18,336 --> 00:16:19,869 +And now you wanna localize it. +现在你想本地化它 + +422 +00:16:19,871 --> 00:16:21,637 +'Kay, how do you do that? +好的,你想怎么做 + +423 +00:16:21,639 --> 00:16:23,005 +Could not be simpler. +这可不简单 + +424 +00:16:23,007 --> 00:16:25,073 +You just go to the project again, +你只是想再次到项目里 + +425 +00:16:25,075 --> 00:16:27,175 +the same place that you added the languages, and +你添加语言到相同的位置 + +426 +00:16:27,177 --> 00:16:30,544 +from the Editor menu, you just say Export for Localization. +从编辑菜单那里,你只是说导出本地 + +427 +00:16:30,546 --> 00:16:33,313 +And it will export all the languages. +它将导出所有语言 + +428 +00:16:33,315 --> 00:16:35,048 +You can actually select which ones you want, +你事实上选择那个你想要的 + +429 +00:16:35,050 --> 00:16:38,151 +but it'll export all your languages in a format called +但是它将导出所有语言到 + +430 +00:16:38,153 --> 00:16:42,221 +.xliff, 'kay, which is this international file format for +.xliff 文件里,好,这个是国际化文件 + +431 +00:16:42,223 --> 00:16:43,722 +translators, 'kay? +这个翻译器,对吧 + +432 +00:16:43,724 --> 00:16:46,825 +They have tools, translators have tools that read .xliff +他们有工具,translators 有工具去读 .xliff 文件 + +433 +00:16:46,827 --> 00:16:49,494 +files and let them translate, and +让他们翻译 + +434 +00:16:49,496 --> 00:16:53,498 +then they press, you know, send or whatever. +然后点击,你知道到,发送或者其他 + +435 +00:16:53,500 --> 00:16:55,933 +It generates an .xliff with the translations in it. +通常一个 .xliff 文件和译文在那里 + +436 +00:16:55,935 --> 00:16:57,101 +So this is kind of the, +这是一种方式 + +437 +00:16:57,103 --> 00:16:59,903 +you know, industry standard communication mechanism +你懂的,工业标准与机制的通信 + +438 +00:16:59,905 --> 00:17:02,739 +between developers and translators. +在开发者和翻译者之间 + +439 +00:17:02,741 --> 00:17:06,476 +And so Xcode localization will generate them all. +然后 Xcode 本地化将使他们运作 + +440 +00:17:06,478 --> 00:17:09,545 +And then your translator will use their tool, translate it, +然后你的翻译器将使用这些工具,翻译它 + +441 +00:17:09,547 --> 00:17:12,548 +give you an .xliff file back, and you will then, +返回一个 .xliff 文件 + +442 +00:17:12,550 --> 00:17:16,751 +in that same place, say Import Localizations, 'kay? +在一个相同的位置,写着 Import Localizations + +443 +00:17:16,753 --> 00:17:19,153 +You can only import one .xliff at a time. +这个时候你可以导入 .xliff 文件 + +444 +00:17:19,155 --> 00:17:21,655 +A single .xliff can have multiple translations for +一个 .xliff 文件可以多个译文 + +445 +00:17:21,657 --> 00:17:24,892 +multiple languages, by the way, and your translator, +针对多语言,顺便说一下,你的翻译器 + +446 +00:17:24,894 --> 00:17:26,693 +if they're doing ten languages for you, they might give +如果他们将翻译 10 种语言,他们可能 + +447 +00:17:26,695 --> 00:17:28,595 +you one .xliff with all the languages in there. +也就给你一个所有语言的 .xliff 文件 + +448 +00:17:28,597 --> 00:17:30,997 +But anyway, you do import localizations, and +不管咋样,你导入这个文件 + +449 +00:17:30,999 --> 00:17:33,265 +it will import it into your project. +它将导入它到你的项目里 + +450 +00:17:33,267 --> 00:17:34,600 +And what's really cool then, +这真的很酷 + +451 +00:17:34,602 --> 00:17:38,036 +is if you then change some things and export again, +如果你改变这些东西然后再次导出 + +452 +00:17:38,038 --> 00:17:41,973 +all of their translations will get exported, so that you +所有这些译文将被导出 + +453 +00:17:41,975 --> 00:17:44,342 +can just keep going back and forth, import, export, import, +你可以来回切换,导入,导出,导入 + +454 +00:17:44,344 --> 00:17:46,911 +export, and the translators doing the opposite. +导出,translators 可以做这些对立的事 + +455 +00:17:46,913 --> 00:17:49,279 +They're importing what you send, they translate it, +他们将导入你发送的,他们翻译它 + +456 +00:17:49,281 --> 00:17:51,198 +they send it out. +他们再发送 + +457 +00:17:51,199 --> 00:17:53,116 +When you send something new it has all the old work they did, +当你发送一些新的它却还有旧的工作未完成 + +458 +00:17:53,118 --> 00:17:55,719 +becaus export keeps that. +因为它还在做导出的事 + +459 +00:17:55,721 --> 00:17:56,987 +Okay? +对吧 + +460 +00:17:56,988 --> 00:17:58,254 +So it's really super simple system. +这是一个真的超级简单的系统 + +461 +00:17:58,256 --> 00:18:00,907 +It's totally built for +它完全建立在 + +462 +00:18:00,908 --> 00:18:03,559 +that iterative process, really well designed. +迭代过程里,一个非常好的设计 + +463 +00:18:03,561 --> 00:18:08,129 +This is new for iOS 8, they did a great job with this. +这是 iOS 8 的一个新特性,他们做一个非常好的工作 + +464 +00:18:08,131 --> 00:18:09,531 +Okay? So it's just import, +对吧,它只是导入 + +465 +00:18:09,532 --> 00:18:10,932 +export, and that's all it takes, 'kay? +导出,这就得到所有要的结果,对吧 + +466 +00:18:12,068 --> 00:18:16,269 +Once you have a localization back +一旦你返回了一个 localization + +467 +00:18:16,271 --> 00:18:18,638 +you can preview it in really two different places. +你可以预览它在这两个不同的位置 + +468 +00:18:18,640 --> 00:18:20,907 +One, you can preview it in Xcode, and +一处是在 Xcode + +469 +00:18:20,909 --> 00:18:23,342 +I actually showed you this earlier in the quarter. +我前一刻给你展示的 + +470 +00:18:23,344 --> 00:18:27,279 +There's that little preview pane on the right and +这里右边有预览面板 + +471 +00:18:27,281 --> 00:18:29,815 +you can preview it, and in the lower right hand corner of +你可以预览它,在右下角 + +472 +00:18:29,817 --> 00:18:32,617 +the preview pane, it actually has all the languages that you +预览处,它有你可以翻译的 + +473 +00:18:32,619 --> 00:18:33,618 +have translations for. +所有语言 + +474 +00:18:33,620 --> 00:18:34,819 +You just pick it and boom, +你只要拿起来 + +475 +00:18:34,821 --> 00:18:36,387 +right there in Xcode it'll show you. +它将给你演示在 Xcode 那里 + +476 +00:18:36,389 --> 00:18:38,655 +Now that's only gonna show your static story board +现在那里只展示静态的 storyboard + +477 +00:18:38,657 --> 00:18:40,357 +though, it's not showing your app running. +它不会演示你应用运行的状况 + +478 +00:18:40,359 --> 00:18:43,292 +You're not gonna see any of your NS localized strings +你不能看所有 NSLocalized 的字符串 + +479 +00:18:43,294 --> 00:18:44,627 +in there. +在那里 + +480 +00:18:44,628 --> 00:18:45,961 +You're only going to see the translations that were made to +你只能看这个译文 + +481 +00:18:45,963 --> 00:18:47,096 +something in a story board. +由那个 storyboard 制作的译文 + +482 +00:18:48,432 --> 00:18:50,799 +And yeah, notice there's that nice little double length +通知那个双倍长度的 + +483 +00:18:50,801 --> 00:18:52,551 +pseudo language. +伪语言 + +484 +00:18:52,552 --> 00:18:54,302 +That's a good way to make everything really long and +这是一个好的方式去使得每一个事物真实长度和 + +485 +00:18:54,304 --> 00:18:55,403 +make sure everything's fitting. +确保每一件事都合适 + +486 +00:18:55,405 --> 00:18:57,004 +Maybe there's places you're out of layout, +可能那里有那一层外面的位置 + +487 +00:18:57,006 --> 00:18:59,406 +you need to make more room, something like that. +你需要更多的房间,像那些 + +488 +00:18:59,408 --> 00:19:01,141 +So that's kind of a cool, it's not real language, +那种酷,它不是真实的语言 + +489 +00:19:01,143 --> 00:19:03,309 +just doubles the length of every string, but +只是每个字符双倍长度,但是 + +490 +00:19:03,311 --> 00:19:04,643 +it's kinda cool. +它很酷 + +491 +00:19:04,645 --> 00:19:08,113 +The other way, and this is mostly the way you're gonna +另一方面,这是一种方式你将 + +492 +00:19:08,115 --> 00:19:11,917 +test your app is you want to run it using the translations. +测试你的应用并使用你的译文运行它 + +493 +00:19:11,919 --> 00:19:14,285 +Now, it would be a pain in the neck, +现在它将会是一个烦恼 + +494 +00:19:14,287 --> 00:19:16,721 +if every time you wanted to run in Arabic +如果每一次你想运行在阿拉伯语环境下 + +495 +00:19:16,723 --> 00:19:19,890 +you had to go on your device or your simulator. +你不得不继续你的设备或者你的模拟器 + +496 +00:19:19,892 --> 00:19:23,493 +Go over here to, actually, here, let's put this up here, +复习一下,事实上,这里,让我们把这些放这里 + +497 +00:19:23,495 --> 00:19:24,794 +and I'll show you. +然后我将给你演示 + +498 +00:19:28,466 --> 00:19:29,665 +Okay, so here's my device. +好的,这是我的设备 + +499 +00:19:29,667 --> 00:19:32,634 +So if I had to go to Settings and go to, +如果我进入设置然后继续 + +500 +00:19:32,636 --> 00:19:35,437 +I think it's under General. +我想它在通常情况下 + +501 +00:19:35,439 --> 00:19:39,140 +And then go to, where is it. +然后继续,这里 + +502 +00:19:39,142 --> 00:19:40,274 +Language and region. +语言和地区 + +503 +00:19:40,276 --> 00:19:43,010 +And then go over here to my iPhone language, +找一下我们的 iPhone language + +504 +00:19:43,012 --> 00:19:44,611 +go find Arabic in here. +找到阿拉伯语 + +505 +00:19:44,613 --> 00:19:47,146 +If had to do that for all of the ten languages, +如果对所有十种语言做这些 + +506 +00:19:47,148 --> 00:19:50,116 +I would just be going crazy doing that. +我将继续疯狂地做 + +507 +00:19:50,118 --> 00:19:52,351 +So luckily, you don't have to do any of that. +幸运的是,你不得不做这些 + +508 +00:19:52,353 --> 00:19:54,920 +All you have to do is create a scheme. +所有你创建 scheme + +509 +00:19:54,922 --> 00:19:56,688 +'Kay? A run scheme for +对不对,运行的 scheme + +510 +00:19:56,690 --> 00:19:58,923 +your app that sets the language. +给你的应用设置语言 + +511 +00:19:58,925 --> 00:20:00,558 +So the way you create a scheme. +你创建 scheme 的方式 + +512 +00:20:00,560 --> 00:20:04,028 +In the upper left hand corner of Xcode where you click run. +在 Xcode 的左下角,你点击运行的位置 + +513 +00:20:04,030 --> 00:20:07,397 +Right now you only ever see it say the name of your app. +现在你只看到你应用的名称 + +514 +00:20:07,399 --> 00:20:09,833 +But you can actually hold down on that, and +但是你事实上可以保有这些 + +515 +00:20:09,835 --> 00:20:12,735 +there'll be a little menu, and you can say edit scheme. +这里有一些菜单,你可以编辑 scheme + +516 +00:20:12,737 --> 00:20:15,671 +And edit scheme will bring up this thing that you see there, +编辑 scheme 将带给你这些你可以看到的这些 + +517 +00:20:15,673 --> 00:20:19,842 +the big window, and it's going to say what are the settings +这个大窗口,它将显示这些设置 + +518 +00:20:19,844 --> 00:20:22,978 +you want when you build, when you run, when you test, when +你想的当你创建,当你运行,当你测试,当 + +519 +00:20:22,980 --> 00:20:27,348 +you profile this app, when you're stack analyzing, etc. +你描述这些应用,当你分析它们等 + +520 +00:20:27,350 --> 00:20:29,116 +And in the build, in the run section, +在这个建设里,在这个运行状态 + +521 +00:20:29,118 --> 00:20:31,752 +there you can see that there's application language and +你可以看这些应用语言 + +522 +00:20:31,754 --> 00:20:34,905 +application regions. +应用地区 + +523 +00:20:34,906 --> 00:20:38,057 +So you can set those to French or maybe Spanish and Mexico, +因此你可以设置,这些法语或者可能西班牙与和墨西哥语 + +524 +00:20:38,060 --> 00:20:40,360 +if you wanted a locale. +如果你想本地化 + +525 +00:20:40,362 --> 00:20:43,596 +And then, it will make a new entry, okay? +然后你可以创建一个新的条目,对不对 + +526 +00:20:43,598 --> 00:20:45,998 +Sorry, first of all, you duplicate an existing scheme. +对不起,首先,你可以复制这些存在的 scheme + +527 +00:20:46,000 --> 00:20:46,999 +You see that, lower left? +你看这些,左下那里 + +528 +00:20:47,001 --> 00:20:49,034 +Duplicate an existing scheme. +复制一个存在的 scheme + +529 +00:20:49,036 --> 00:20:51,069 +Then you set all these things, and save it, and +然后你设置所有的这些,保存它 + +530 +00:20:51,071 --> 00:20:52,536 +now you have two schemes. +现在你可以有两个 scheme + +531 +00:20:52,538 --> 00:20:54,972 +The original one, that doesn't have a language set, and +这个原始的,不能有语言设置 + +532 +00:20:54,974 --> 00:20:56,173 +the duplicated one. +还有一个复制的 + +533 +00:20:56,175 --> 00:20:57,874 +'Kay, that you've set the language in. +好的,你设置这个语言 + +534 +00:20:57,876 --> 00:20:59,876 +Now if you wanna run in that other language, +现在如果你想运行其他语言 + +535 +00:20:59,878 --> 00:21:04,546 +like French, you just hit that pop-up, pick French, hit run. +像法语,你只要点击 pop-up,点击法语,点击运行 + +536 +00:21:04,548 --> 00:21:06,314 +Okay? And it's gonna run using that +对不对,它将运行 + +537 +00:21:06,316 --> 00:21:08,550 +language and locale. +语言和本地化 + +538 +00:21:08,552 --> 00:21:10,318 +It's really cool, fast way. +它很酷,很快 + +539 +00:21:10,320 --> 00:21:12,553 +You can check ten languages really quick. +你可以检查十种语言 + +540 +00:21:12,555 --> 00:21:15,022 +You add in a new feature or a new translation came back, +你添加一个新的特性或者返回新的译文 + +541 +00:21:15,024 --> 00:21:18,091 +you just click run, check it out, okay. +你可以点击运行,检查它,对不对 + +542 +00:21:18,093 --> 00:21:19,159 +Click run. +点击运行 + +543 +00:21:19,161 --> 00:21:20,927 +Checking out, back and forth, okay? +来回检查,对吧 + +544 +00:21:21,963 --> 00:21:25,697 +So that's how you preview a localization at runtime, 'kay? +那是运行时你怎样预览一个本地化方式,对不对 + +545 +00:21:25,699 --> 00:21:29,834 +And I'll show that in a demo. +我将演示一个 Demo + +546 +00:21:29,836 --> 00:21:32,537 +There's also this little localization debugging switch +那个也是一点本地化测试 + +547 +00:21:32,539 --> 00:21:34,171 +you see in there, and +你在那看到的 + +548 +00:21:34,173 --> 00:21:35,739 +that's going to do a couple of things. +那里有一对东西 + +549 +00:21:35,741 --> 00:21:38,709 +One thing is on localize strings from your story boards +一个是从你的 storyboard 取的本地化字符串 + +550 +00:21:38,711 --> 00:21:42,945 +will show up in all caps in your UI, so that's nice. +显示在你的用户界面上,非常好 + +551 +00:21:42,947 --> 00:21:45,781 +Also things that were not localized, +这个他们没有本地化 + +552 +00:21:45,783 --> 00:21:48,283 +will spit something out on the console, +将在控制台吐出一些东西 + +553 +00:21:48,285 --> 00:21:49,985 +saying this string on localized, okay? +表示这是本地化数据,对不对 + +554 +00:21:51,021 --> 00:21:52,820 +So when you're getting something back from +因此当你得到一些什么 + +555 +00:21:52,822 --> 00:21:55,122 +the localizer you wanna make sure they didn't make any +本地化你要确保他们没有 + +556 +00:21:55,124 --> 00:21:57,825 +mistakes, although the import is gonna find mistakes, +错误,虽然导入将会找到错误 + +557 +00:21:57,827 --> 00:21:59,292 +I'll show you that too in the demo. +我将再次给你演示 + +558 +00:21:59,294 --> 00:22:01,895 +But if there's something else in there, you'll be able to +但是如果那里有一些其他的,你将 + +559 +00:22:01,897 --> 00:22:06,899 +see it with this localization debugging on, 'kay? +看到本地化调试,对不对 + +560 +00:22:06,901 --> 00:22:08,667 +And that's it, 'kay? +就这样,对不对 + +561 +00:22:08,669 --> 00:22:12,971 +So all you gotta do is autolayout, get your localized +所有你做的都是用自动布局,得到你的 + +562 +00:22:12,973 --> 00:22:16,207 +strings in there, use formatters properly, and +本地化字符串,使用适当美化 + +563 +00:22:16,209 --> 00:22:17,441 +you'll be internationalizeable. +你就做到国际化的 + +564 +00:22:17,443 --> 00:22:19,910 +And then it's just question, go hire your localizer. +还有一个问题,你要有个好的翻译工具 + +565 +00:22:21,080 --> 00:22:23,646 +Back and forth with the .xliffs, all right? +来回切换 .xliffs 文件,对不对 + +566 +00:22:23,648 --> 00:22:25,548 +So let me show you what this looks like. +让我给你演示一下是怎样的 + +567 +00:22:28,720 --> 00:22:33,789 +Here, we're going to localize autolayout, okay? +这里,我们定位自动布局,对不对 + +568 +00:22:33,791 --> 00:22:37,092 +Do you remember this app back when we were doing autolayout, +记住这个应用在你做自动布局时返回什么 + +569 +00:22:37,094 --> 00:22:38,659 +looks like this? +像这些 + +570 +00:22:38,661 --> 00:22:41,862 +So we're going to localize this to a number of different +我们将定位这一系列不同的 + +571 +00:22:41,864 --> 00:22:42,896 +languages. +语言 + +572 +00:22:42,898 --> 00:22:44,931 +And I added one feature to this, actually, +然后我将添加一些特性到这里去 + +573 +00:22:44,933 --> 00:22:47,434 +which is this little guy right here Last Login. +就是这小家伙最后登录的位置 + +574 +00:22:47,436 --> 00:22:50,303 +So I just made it when you log in it puts a last log in +放最后登录的日期 + +575 +00:22:50,305 --> 00:22:51,888 +date in here, +在这里 + +576 +00:22:51,889 --> 00:22:53,472 +because it's gonna let us talk about date formatters and +因为我们将讨论这个 date formatter + +577 +00:22:53,474 --> 00:22:57,576 +number formatters, things like that, in here. +number formatter 的问题,就像这样 + +578 +00:22:57,578 --> 00:23:01,279 +But otherwise it works exactly the same as it always is. +但是另外它像它之前运作的方式运作 + +579 +00:23:01,281 --> 00:23:03,148 +We type the username and password, we hit log in, +我们输入用户名和密码,我们点击登录 + +580 +00:23:03,150 --> 00:23:04,549 +we can do change security and +我们可以改变安全性 + +581 +00:23:04,551 --> 00:23:07,151 +it'll change this word right here. +它会在这更改一些词 + +582 +00:23:07,153 --> 00:23:09,019 +And that's it. +就酱 + +583 +00:23:09,021 --> 00:23:13,423 +So, what do we need to do +所以,这就是我们所需要的 + +584 +00:23:13,425 --> 00:23:15,491 +if we want to make this localizable? +如果我们想要这个本地化 + +585 +00:23:15,493 --> 00:23:16,926 +Well the first thing we wanna do +首先我们就要做 + +586 +00:23:16,928 --> 00:23:19,294 +is go up to our project up here. +去到我们项目的这个地方 + +587 +00:23:19,296 --> 00:23:21,163 +And again, you want to be careful here +然后,你将会关心这个地方 + +588 +00:23:21,165 --> 00:23:22,630 +not to have the target selected, +不是这里的 target 选项 + +589 +00:23:22,632 --> 00:23:24,866 +you actually want the project selected, okay. +你想是这个 project 的选项,对吧 + +590 +00:23:24,868 --> 00:23:26,701 +Target, project. +Target,project + +591 +00:23:26,703 --> 00:23:29,370 +In the project selection you're gonna have info and +项目的选项里,你将有 info + +592 +00:23:29,372 --> 00:23:31,104 +build settings. +和 build settings + +593 +00:23:31,106 --> 00:23:33,740 +And, so let's create some localizations, +让我们创建本地化吧 + +594 +00:23:33,742 --> 00:23:35,108 +you see it down here localizations? +你会看到下边这个 localizations + +595 +00:23:35,110 --> 00:23:37,476 +We don't have any currently, it just says English. +我们没有任何当前的语言,它只有英语 + +596 +00:23:37,478 --> 00:23:39,411 +So I'm gonna create some, you know, let's do French. +我将创建一些,你知道的,让我们先用法语 + +597 +00:23:39,413 --> 00:23:41,029 +That's a good one. +这个语言挺好 + +598 +00:23:41,030 --> 00:23:42,646 +And it's saying here, what do you wanna make localizable? +在这里选择,你有什么想做本地化 + +599 +00:23:42,649 --> 00:23:45,650 +And, yes, my storyboard, and also that launch screen, which +对的,我的 storyboard,还有这个启动画面 + +600 +00:23:45,652 --> 00:23:48,052 +we really haven't [LAUGH] talked about in this class. +我们还没有在我们课堂上讨论这个呢 + +601 +00:23:48,054 --> 00:23:49,286 +The launch screen, by the way, +启动画面,顺便说一下 + +602 +00:23:49,288 --> 00:23:51,855 +is just this thing that pops up briefly while your app is +你的应用启动将要运行时 + +603 +00:23:51,857 --> 00:23:52,756 +getting up and running. +短暂显示的东西 + +604 +00:23:52,758 --> 00:23:54,374 +You've probably seen that. +你可能会看到这些 + +605 +00:23:54,375 --> 00:23:55,991 +You can edit it and create, put an image there or +你编辑它创建它,放一张图片在这里 + +606 +00:23:55,994 --> 00:23:57,260 +something like that. +或者其他等 + +607 +00:23:57,262 --> 00:23:59,895 +But that's something you might wanna be localize both, +但是有些是你将本地化的 + +608 +00:23:59,897 --> 00:24:01,296 +it has text or something on it. +它有文本或者其他的东西 + +609 +00:24:01,298 --> 00:24:02,931 +So we gonna leave that. +我们将离开这里 + +610 +00:24:02,933 --> 00:24:03,898 +So there's French. +这是法语 + +611 +00:24:03,900 --> 00:24:07,635 +Let's do, yeah let's do Chinese. +好的,让我们试一下中文 + +612 +00:24:07,637 --> 00:24:09,737 +Let's do traditional also. +试一下这个繁体中文 + +613 +00:24:09,739 --> 00:24:13,407 +Let's do, I don't know. +试一下,我不知道 + +614 +00:24:13,409 --> 00:24:19,278 +How about something Arabic, how about is a good one. +试一下阿拉伯语,试一下其他的怎么样 + +615 +00:24:20,281 --> 00:24:22,247 +How about Japanese? +日语如何 + +616 +00:24:22,249 --> 00:24:23,482 +Yeah, there's Japanese. +好的就日语吧 + +617 +00:24:23,484 --> 00:24:27,185 +So I'm adding a bunch of languages here, and +我将添加一系列语言在这里 + +618 +00:24:28,254 --> 00:24:32,556 +when I now go here to this Editor menu and +当你到这里去编辑菜单 + +619 +00:24:32,558 --> 00:24:35,091 +say Export For Localization. +导出本地化信息 + +620 +00:24:35,093 --> 00:24:37,393 +It's gonna say, where do you wanna put them? +怎么说,你想要放他们到哪里 + +621 +00:24:37,395 --> 00:24:43,132 +I have a directory here called my L10N, my localization one. +我有一个目录叫做 L10N, 我有一个在这 + +622 +00:24:43,134 --> 00:24:45,934 +And, I have this folder called To Localizer. +我有一个文件夹叫做 Localizer + +623 +00:24:45,936 --> 00:24:48,936 +I don't have anything in there right now. +我现在那里什么都没有 + +624 +00:24:50,273 --> 00:24:52,306 +We're gonna put our auto layout stuff in here. +我们将放我们的自动布局的材料在这里 + +625 +00:24:52,308 --> 00:24:54,374 +Here, you see, it's asking what languages you wanna +这里,你看到的,你想要放的 + +626 +00:24:54,376 --> 00:24:56,276 +generate these .xliffs for. +.xliffs 的语言在这里 + +627 +00:24:56,278 --> 00:24:57,477 +So I'm going to hit save. +我要点击保存了 + +628 +00:24:57,479 --> 00:24:59,412 +And it's going to generate .xliffs, +然后它生成 .xliffs 文件 + +629 +00:24:59,414 --> 00:25:02,214 +which we're going to go look at for all of these things. +这个是我们将要查看的所有的这些信息的文件 + +630 +00:25:02,216 --> 00:25:03,565 +Okay? So +对不对 + +631 +00:25:03,566 --> 00:25:04,915 +here's all the files that are going to my localizer. +这里的所有的文件都要放到我的本地化工具那里 + +632 +00:25:04,918 --> 00:25:07,118 +I'm going to send these to my localizer so +我将发送这些到我的 localizer 那 + +633 +00:25:07,120 --> 00:25:08,269 +let's look at one. +让我们看一下这一个 + +634 +00:25:08,270 --> 00:25:09,419 +It really doesn't matter because nothing's been +没问题,因为还没有东西 + +635 +00:25:09,422 --> 00:25:10,588 +localized yet. +被本地化 + +636 +00:25:10,590 --> 00:25:12,190 +But here we go, +但是现在我们要开始做了 + +637 +00:25:12,191 --> 00:25:13,791 +see storyboard, here's all this strings. +看 storyboard,这里所有的字符串 + +638 +00:25:13,793 --> 00:25:15,058 +You recognize these strings? +你认识这些字符串 + +639 +00:25:15,060 --> 00:25:19,062 +Company, last log in, the log in button, user name. +公司,最后的登录,登录按键,用户名 + +640 +00:25:19,064 --> 00:25:21,864 +Name, password, the change security button. +名称,密码,修改安全信息按键 + +641 +00:25:21,866 --> 00:25:24,366 +Those are all the strings that it extracted +这些都是它提取的字符串 + +642 +00:25:24,368 --> 00:25:26,268 +from the storyboard. +从 storyboard 那里提取的 + +643 +00:25:26,270 --> 00:25:31,305 +I send these off to my localizer, +我发送这些到我的本地化工具那 + +644 +00:25:31,307 --> 00:25:35,342 +and they go work on them, and then we get some back. +然后他们一起运作,然后给我们返回信息 + +645 +00:25:35,344 --> 00:25:37,261 +So, okay. +好的 + +646 +00:25:37,262 --> 00:25:39,179 +Look, they just came back from the localizer, here they are. +看,他们只是从 localizer 里返回信息,在这里 + +647 +00:25:39,181 --> 00:25:42,849 +So let's go ahead and take a look at the Japanese one. +让我们继续,看一下日语是咋样的 + +648 +00:25:42,851 --> 00:25:44,751 +So here's the Japanese one right here, +这里是日语 + +649 +00:25:44,753 --> 00:25:46,819 +what does this look like? +他们看起来像什么 + +650 +00:25:46,821 --> 00:25:51,056 +So the localizer has put localizations for +localizer 把每一个本地化的 + +651 +00:25:51,058 --> 00:25:53,491 +each of these things into this X-look. +这些东西变成这样子 + +652 +00:25:53,493 --> 00:25:56,227 +Now they didn't edit it here in text edit [LAUGH], +现在他们不能在文本编辑框编辑它 + +653 +00:25:56,229 --> 00:25:59,397 +they have a tool that lets them do that. +有一个工具可以编辑 + +654 +00:25:59,399 --> 00:26:01,231 +And so let's go ahead and import that. +让我们做下一步,导入这些 + +655 +00:26:01,233 --> 00:26:02,416 +So we go here, and +到这里 + +656 +00:26:02,417 --> 00:26:03,600 +we're going to import this localization for +我们将从本地化工具这导入 + +657 +00:26:03,602 --> 00:26:07,236 +Japanese from the localizer. +关于日语的本地化 + +658 +00:26:07,238 --> 00:26:08,304 +Japanese. +日语 + +659 +00:26:08,306 --> 00:26:08,904 +Okay. +好的 + +660 +00:26:08,906 --> 00:26:10,238 +Oh, there's a problem. +有个问题 + +661 +00:26:10,240 --> 00:26:13,208 +Okay, now if there's no problem, this just loads up. +好的,没有这个问题,这只是加载中 + +662 +00:26:13,210 --> 00:26:14,342 +And you're good to go. +你会擅长做这些 + +663 +00:26:14,344 --> 00:26:16,110 +But here there's a problem. +但是这里还是有问题 + +664 +00:26:16,111 --> 00:26:17,877 +And when there's a problem it shows you in detail +当这个问题给你显示这个细节 + +665 +00:26:17,880 --> 00:26:19,046 +what the problems are. +这个问题是什么 + +666 +00:26:19,048 --> 00:26:23,049 +So here it says there's incoming translation for +这里有一个引进的翻译 + +667 +00:26:23,051 --> 00:26:26,152 +one of the things in IB that was not done. +在 IB 这里的还没完成的 + +668 +00:26:26,154 --> 00:26:27,987 +And you can see it right here, no translation. +你可以在这看到这些,没有翻译 + +669 +00:26:27,989 --> 00:26:30,255 +So they didn't translate the word company. +他们不想翻译这个词 company + +670 +00:26:30,257 --> 00:26:33,692 +Now luckily, company never actually appears in our UI. +幸运的是,company 不会显示在我们的用户界面上 + +671 +00:26:33,694 --> 00:26:35,493 +That's just like the little thing like where you know, +这就像小东西一个,你知道的 + +672 +00:26:35,495 --> 00:26:36,627 +Madison Bumgarner, and +Madison Bumgarner + + +673 +00:26:36,629 --> 00:26:38,562 +it was were old champion San Fransisco Giants. +它是旧金山巨人队的老冠军 + +674 +00:26:38,564 --> 00:26:40,664 +So company always gets replaced with whatever +公司经常被其他用户的公司 + +675 +00:26:40,666 --> 00:26:41,965 +the logged in user's company is. +替代 + +676 +00:26:41,967 --> 00:26:43,633 +So, whew, we're okay. +好的 + +677 +00:26:43,635 --> 00:26:46,436 +But you can see it's showing all the other translations. +你可以看到所有其他的翻译 + +678 +00:26:46,438 --> 00:26:47,370 +And those look good, right? +这些看起来很好,对不对 + +679 +00:26:47,372 --> 00:26:49,271 +So this one, this one, this one. +这一个,这一个和这一个 + +680 +00:26:49,273 --> 00:26:50,605 +It's showing the translations. +它展现这些翻译 + +681 +00:26:50,607 --> 00:26:54,376 +So this will only appear if you've got something where +这个将出现一下如果你得到一个位置 + +682 +00:26:54,378 --> 00:26:57,945 +your translation company failed in their translation. +你翻译公司翻译出错的地方 + +683 +00:26:57,947 --> 00:26:59,564 +In this case, it's okay. +在这种情况下,好的 + +684 +00:26:59,565 --> 00:27:01,182 +So I'm gonna accept this and import it. +我将接受这个设定然后导入它 + +685 +00:27:01,184 --> 00:27:02,416 +Okay? +对不对 + +686 +00:27:02,417 --> 00:27:03,649 +Now I can actually go to my storyboard here and +现在我可以去到我的 storyboard + +687 +00:27:03,652 --> 00:27:06,987 +without even running my app I can make a second +不用运行我的应用,我可以创建第二个 + +688 +00:27:06,989 --> 00:27:09,556 +window here and go down to Preview. +窗口然后预览一下 + +689 +00:27:09,558 --> 00:27:11,457 +So let's preview what our main storyboard's going to +让我们预览我们主要的 storyboard + +690 +00:27:11,459 --> 00:27:12,725 +look like. +看它会是咋样 + +691 +00:27:12,727 --> 00:27:14,493 +Of course, our S is cut off because, +当然,我们的 S 被切开 + +692 +00:27:14,495 --> 00:27:17,429 +if you'll remember from auto layout demo, +如果你记得自动布局那个 Demo + +693 +00:27:17,431 --> 00:27:19,798 +we put that in code. +我们把那部分代码放到这了 + +694 +00:27:19,800 --> 00:27:21,616 +We put a constraint for +我们添加这些约束 + +695 +00:27:21,617 --> 00:27:23,433 +the aspect ratio so that's in code so that's not here. +长宽比,这个代码里没有的 + +696 +00:27:24,370 --> 00:27:27,638 +So here's what it looks like in English, right down here. +这个在英语里看起来像什么 + +697 +00:27:27,640 --> 00:27:29,240 +If I go up here and say, +如果我们到这里 + +698 +00:27:29,241 --> 00:27:30,841 +well tell me what this looks like in Japanese, +好的告诉我在日语里它像什么 + +699 +00:27:30,843 --> 00:27:35,445 +then it will use those translations for Japanese. +当日语环境下时它会用这些翻译 + +700 +00:27:35,447 --> 00:27:37,246 +Now notice company is in all caps, +现在注意这个全部大写的公司 + +701 +00:27:37,248 --> 00:27:39,448 +that's because that was not translated. +因为它没有被翻译 + +702 +00:27:39,450 --> 00:27:43,385 +Notice that they translated the word name to be the same. +注意他们翻译的词 + +703 +00:27:43,387 --> 00:27:44,919 +If we look at the Japanese translation, +如果我们看这个日语翻译 + +704 +00:27:44,921 --> 00:27:49,289 +and we look at what they did for name, which is right here. +我们看这个他们对名称所做的位置 + +705 +00:27:49,291 --> 00:27:52,192 +They said, oh well, there's just no word in Japanese for +他们说,好的,这个只是日语没这个词 + +706 +00:27:52,194 --> 00:27:53,693 +that part of the UI so +在我们的用户界面这部分 + +707 +00:27:53,695 --> 00:27:55,628 +we're just going to leave it in English. +我们只要在英语环境下保留 + +708 +00:27:55,630 --> 00:27:56,929 +Okay? They have that +对不对,他们有 + +709 +00:27:56,931 --> 00:27:58,264 +option to do that. +选择这么做 + +710 +00:27:58,265 --> 00:27:59,598 +But you might say, I don't want that and so +但是你可以说,我不想这样 + +711 +00:27:59,600 --> 00:28:01,299 +you can easily see that here. +你可以很容易看到这里 + +712 +00:28:01,301 --> 00:28:03,702 +Especially with a language like Japanese. +尤其是像日语这种语言 + +713 +00:28:03,704 --> 00:28:06,404 +Versus some western script language like English, +对比西方的一些语言比如说英语 + +714 +00:28:06,406 --> 00:28:07,972 +you can see quickly, oh, whoa, whoops. +你可以很快地看,哦,哇哦 + +715 +00:28:07,974 --> 00:28:09,039 +It's not there. +它不存在 + +716 +00:28:09,041 --> 00:28:10,474 +Okay. So that's great. +好的,挺好 + +717 +00:28:10,476 --> 00:28:12,175 +And if we run our app, +如果我们运行我们的应用 + +718 +00:28:12,177 --> 00:28:13,810 +we could run it in Japanese as well. +我们也可以在日语环境下运行 + +719 +00:28:13,812 --> 00:28:14,961 +And so let's do that. +让我们试一下这样 + +720 +00:28:14,962 --> 00:28:16,111 +Let's do this edit scheme thing. +让我们编辑一下 scheme + +721 +00:28:16,114 --> 00:28:18,981 +So you see, I'm just taking this thing up here that +你看,我们只是正常地把这个东西放这 + +722 +00:28:18,983 --> 00:28:20,482 +normally is always saying autolayout. +然后自动布局 + +723 +00:28:20,484 --> 00:28:22,350 +And I'm gonna say Edit Scheme. +然后编辑 scheme + +724 +00:28:22,352 --> 00:28:24,619 +And when I edit its scheme, I can edit scheme for +当我们编辑这个 scheme,我可以编辑 + +725 +00:28:24,621 --> 00:28:26,387 +lots of different things, building, et cetera. +很多不同的东西,building 或者其他 + +726 +00:28:26,389 --> 00:28:27,788 +But I want it for running. +但是我想它运行 + +727 +00:28:27,790 --> 00:28:29,322 +I wanna edit the scheme for running. +我想编辑这个运行的 scheme + +728 +00:28:29,324 --> 00:28:32,025 +And I'm gonna duplicate this scheme, okay, and +我将先复制这个 scheme,好的 + +729 +00:28:32,027 --> 00:28:36,228 +I'm gonna call this my Japanese scheme right here. +我将写我的日语 scheme 在这里 + +730 +00:28:36,230 --> 00:28:40,232 +And I'm gonna change the Japanese scheme so that. +我将改变这个日语的 scheme + +731 +00:28:40,234 --> 00:28:42,000 +It is Japanese. +日语 + +732 +00:28:42,002 --> 00:28:44,135 +And it's, Japan here. +Japan 在这 + +733 +00:28:44,137 --> 00:28:46,504 +But if we, if it wasn't there, +但是如果我们,如果它不在那 + +734 +00:28:46,506 --> 00:28:47,671 +we could go look for it up here. +我们可以去这边看看 + +735 +00:28:47,673 --> 00:28:49,506 +But here's Japanese. +但是这里是日语 + +736 +00:28:49,508 --> 00:28:52,208 +And so now this is my locale. +现在这算我的场景 + +737 +00:28:52,210 --> 00:28:54,877 +And this is my language, okay? +这是我的语言,对不对 + +738 +00:28:54,879 --> 00:28:56,612 +So now, if I ever wanna run in Japanese, +现在,如果我们想在日语环境下运行 + +739 +00:28:56,614 --> 00:28:57,946 +now that I have this scheme, +现在我有这个 scheme + +740 +00:28:57,948 --> 00:28:59,715 +you see that I have two schemes now. +你看我现在有两个 + +741 +00:28:59,717 --> 00:29:02,817 +Now that I have this Japanese scheme, I can just hit Run +现在我有日语的 scheme,我可以点击运行 + +742 +00:29:02,819 --> 00:29:05,953 +with this scheme selected and it's gonna run in Japanese. +选择 scheme,它将用日语运行 + +743 +00:29:05,955 --> 00:29:11,125 +Let's go ahead and make this smaller. +让我们做下一步,让它变小 + +744 +00:29:11,127 --> 00:29:11,925 +Even smaller. +更小 + +745 +00:29:11,927 --> 00:29:12,792 +Okay. +好的 + +746 +00:29:12,794 --> 00:29:14,827 +So here's our app in Japanese. +这是我们的应用运行在日语环境下 + +747 +00:29:14,829 --> 00:29:17,963 +And maybe we type, oh, and so I'm trying to start to type. +我们输入,哦,我将尝试开始输入 + +748 +00:29:17,965 --> 00:29:19,865 +Notice that in my locale it's even bringing up +注意我的场景 + +749 +00:29:19,867 --> 00:29:21,066 +a Japanese keyboard. +操作这个日语键盘 + +750 +00:29:21,068 --> 00:29:24,336 +I believe I can get an English keyboard here somehow. +我相信我可以用一个英语键盘 + +751 +00:29:24,338 --> 00:29:26,170 +There we go. +来接下来 + +752 +00:29:26,172 --> 00:29:30,808 +So, let's go madbomb and log in. +madbomb 然后登录 + +753 +00:29:30,810 --> 00:29:32,676 +Here it is. +这里 + +754 +00:29:32,677 --> 00:29:34,543 +Notice this is not translated at all. +注意这里没有全部被翻译 + +755 +00:29:34,546 --> 00:29:36,846 +Notice this is not translated. +没有被翻译 + +756 +00:29:36,848 --> 00:29:39,315 +Okay because we put those in our code. +好的因为我们放这些到我们的代码里 + +757 +00:29:39,317 --> 00:29:42,218 +Those are not in our storyboard anyway. +这些没有在我们的 storyboard 里 + +758 +00:29:42,220 --> 00:29:45,020 +So we're part of the ways down making this +用这个方式去 + +759 +00:29:45,022 --> 00:29:45,887 +internationalizeable. +国际化 + +760 +00:29:45,889 --> 00:29:47,689 +We've got our storyboard. +得到我们的 storyboard + +761 +00:29:47,691 --> 00:29:51,225 +So let's take the next step which is those strings, +让哦我们做下一步工作关于这些字符串的 + +762 +00:29:51,227 --> 00:29:54,595 +like the passwords, secure password and oh, +比如密码、安全密码等 + +763 +00:29:54,597 --> 00:29:57,631 +I added one other feature to this app I'll show you. +我添加一个其他的特性到这个应用里,我会给你们演示的 + +764 +00:29:59,034 --> 00:30:00,299 +Try and just make this wide cuz it makes it +试着让这些广泛的因为这个使 + +765 +00:30:00,301 --> 00:30:01,567 +a little bigger for you. +它更大 + +766 +00:30:01,569 --> 00:30:03,369 +It's this. Is if you type a bad user name +这个。如果你输入一个错误的用户名 + +767 +00:30:03,371 --> 00:30:06,071 +and password, it says, Login Error Invalid user name or +和密码,它会说,登录错误无效的用户名或 + +768 +00:30:06,073 --> 00:30:07,272 +password Try Again. +密码请重试 + +769 +00:30:07,274 --> 00:30:11,208 +So this also needs to be localized to Japanese. +这个也需要本地化为日语 + +770 +00:30:11,210 --> 00:30:12,693 +Okay? So +对不对 + +771 +00:30:12,694 --> 00:30:14,177 +we got some strings here to work on, so +我们得到一下字符串去进行下一步 + +772 +00:30:14,180 --> 00:30:16,913 +let's go work on this string and that alert string. +让我们用这些字符和警告信息 + +773 +00:30:18,183 --> 00:30:21,217 +You haven't seen this code in a while but +你没有看到这些代码一段时间了但是 + +774 +00:30:21,219 --> 00:30:22,985 +here's what it looks like. +这就是它所示的那样 + +775 +00:30:22,987 --> 00:30:25,520 +I'll show you all of the code I added, very simple. +我会给你们显示所有的我添加的代码,非常简单 + + +776 +00:30:25,522 --> 00:30:29,957 +I just added this which is doing that last log in thing +我只是添加这些,这些最后登录的 + +777 +00:30:29,959 --> 00:30:32,093 +and I added this. +我添加的 + +778 +00:30:32,095 --> 00:30:33,961 +If the logged in user couldn't be found +如果登录用户找不到 + +779 +00:30:33,963 --> 00:30:35,629 +then I'm gonna put up an alert. +我就会放一个警告 + +780 +00:30:35,631 --> 00:30:36,396 +Okay. Now that you know what +好的,现在你知道的 + +781 +00:30:36,398 --> 00:30:37,614 +alerts are. +会有警告 + +782 +00:30:37,615 --> 00:30:38,831 +You didn't know what alerts were at the time that +你不知道这个时候警告是怎样的 + +783 +00:30:38,833 --> 00:30:40,032 +we wrote this, so I can put it in. +我们写的,我放在那的 + +784 +00:30:40,034 --> 00:30:42,167 +But, now, you certainly do. +但是,现在你可以知道 + +785 +00:30:42,169 --> 00:30:44,119 +Okay? +对不对 + +786 +00:30:44,120 --> 00:30:46,070 +And then, here's where we do that secured password thing. +然后,这里是我们操作安全密码的位置 + +787 +00:30:46,073 --> 00:30:48,540 +This has not changed, from our last demo. +这么没变,和之前的 Demo 一样 + +788 +00:30:48,542 --> 00:30:49,941 +So let's fix this one first. +让我们修复这个先 + +789 +00:30:49,943 --> 00:30:51,108 +This is a pretty simple thing. +这算一个很简单的东西 + +790 +00:30:51,110 --> 00:30:52,910 +We got these two literal strings here, and +我们得到两个字面上的字符串 + +791 +00:30:52,912 --> 00:30:54,678 +we need them to be localizable. +我们需要他们本地化 + +792 +00:30:54,680 --> 00:30:58,848 +So I'm just going to create a little local here, +因此我将创建一个小的本地化的 + +793 +00:30:58,850 --> 00:31:02,851 +which I'm going to use NS localized string for, and +我将用 NSLocalizedString 方法 + +794 +00:31:02,853 --> 00:31:05,153 +you can see here's that long version of it. +你可以看到这里一个长的译文 + +795 +00:31:05,155 --> 00:31:07,489 +And first let's do password. +首先让我们开始做密码的翻译 + +796 +00:31:07,491 --> 00:31:09,857 +So I'm just going to take my literal string and +我将把这个字面上的字符 + +797 +00:31:09,859 --> 00:31:11,425 +plop it right in here. +放那 + +798 +00:31:11,427 --> 00:31:14,261 +I don't need the table or bundle or value. +我不需要表格或者 bundle 或者值 + +799 +00:31:14,263 --> 00:31:16,413 +Okay? +对不对 + +800 +00:31:16,414 --> 00:31:18,564 +And this is going to be a comment to the localizer, this +这个将是翻译器的 comment + +801 +00:31:18,567 --> 00:31:23,503 +is something like, this is a prompt for the users password +像这样,prompt for the users password + +802 +00:31:25,073 --> 00:31:29,274 +when it is not secure i.e. +when it is not secure (i.e. + +803 +00:31:29,276 --> 00:31:31,676 +plain text. +plain text) + +804 +00:31:31,678 --> 00:31:34,512 +Okay, so I'm trying to give the localizer as much +好的,现在我将尝试给一个本地化的内容 + +805 +00:31:35,748 --> 00:31:36,980 +context there, as I can. +在这里,正如我可以的 + +806 +00:31:36,982 --> 00:31:39,549 +May, I might even put a much longer comment, there. +可能我会放一个很长的 comment 在那里 + +807 +00:31:39,551 --> 00:31:42,952 +You really can't go wrong with nice long comments. +你不能弄错用这个长的 comment + +808 +00:31:42,954 --> 00:31:45,955 +And then, the secure password. +然后,安全密码 + +809 +00:31:45,957 --> 00:31:48,557 +We will just do another NS localized string, here. +我们做这些用 NSLocalizedString 方法 + +810 +00:31:48,559 --> 00:31:53,595 +We'll take this secured password thing out of here, +我们把这个安全密码从这里 + +811 +00:31:53,597 --> 00:31:54,829 +put it here. +剪切到这里 + +812 +00:31:54,831 --> 00:31:57,832 +Get rid of all this. +做完这些 + +813 +00:31:57,834 --> 00:32:01,935 +And we'll say, a Prompt for. +写 a Prompt for + +814 +00:32:01,937 --> 00:32:09,709 +An obscured (not plain text) password. +An obscured (not plain text) password + +815 +00:32:09,711 --> 00:32:11,177 +Okay? +对不对 + +816 +00:32:11,179 --> 00:32:12,344 +So that's it. So now, +就酱 + +817 +00:32:12,346 --> 00:32:14,680 +these two locals here are just strings. +这里的本地化只是字符串 + +818 +00:32:14,682 --> 00:32:17,315 +If we look at their type, they're just a string. +如果我们看他们的输入,他们只是字符 + +819 +00:32:17,317 --> 00:32:20,451 +But they've had a chance to be localized by a translator. +但是他们有机会通过翻译进行本地化 + +820 +00:32:20,453 --> 00:32:22,019 +So now I can say, if it's secure, +所以现在我说,如果它是安全的 + +821 +00:32:22,021 --> 00:32:23,487 +return the secured password. +返回安全密码 + +822 +00:32:23,489 --> 00:32:25,689 +If it's not secure, then do the password. +如果它不安全,那就用密码 + +823 +00:32:27,125 --> 00:32:28,357 +Okay, simple as that. +好的,很简单 + +824 +00:32:28,359 --> 00:32:31,160 +And, you can put these things right in line, right here, +你可以放这些东西在这 + +825 +00:32:31,162 --> 00:32:31,727 +if you want. +如果你想 + +826 +00:32:31,729 --> 00:32:33,028 +Okay? +对不对 + +827 +00:32:33,030 --> 00:32:35,530 +We could have even put this, obviously, +显然我们甚至可以放这里 + +828 +00:32:35,532 --> 00:32:38,833 +right here without even having this local, or I guess, +这里不用本地,我猜 + +829 +00:32:38,835 --> 00:32:41,802 +this right here, without having this local, but +在这里,不用本地 + +830 +00:32:41,804 --> 00:32:44,171 +it's kind of nicer to put them in here. +但是它好多放这里 + +831 +00:32:44,173 --> 00:32:45,905 +It starts getting a little hard to read +开始有点难去理解 + +832 +00:32:45,907 --> 00:32:48,441 +if we had all that stuff here, a humongous line of code. +如果文明有所有的这些材料,大量代码 + +833 +00:32:48,443 --> 00:32:50,576 +But, it's perfectly legal. +但是,它是完全合法的 + +834 +00:32:50,578 --> 00:32:52,077 +One thing about these localized strings, +有一件事这些本地字符串 + +835 +00:32:52,079 --> 00:32:54,680 +these do need to be literals, okay? +这些确实需要是常量,对不对 + +836 +00:32:54,682 --> 00:32:56,348 +This and this, they need to be literals. +这个,这个,他们需要是常量 + +837 +00:32:56,350 --> 00:33:00,518 +They can't be themselves variables, okay? +他们不能是变量 + +838 +00:33:00,520 --> 00:33:02,320 +Because, obviously, +因为,显然 + +839 +00:33:02,321 --> 00:33:04,121 +the code is being scanned to extract this out of here. +代码被扫描,提取出去 + +840 +00:33:04,123 --> 00:33:05,689 +All right? +好 + +841 +00:33:05,691 --> 00:33:07,490 +How about our alert down here? +我们的警告怎么样了 + +842 +00:33:07,492 --> 00:33:09,625 +Well, I'm gonna do this a little differently. +我要做一点小小的不同 + +843 +00:33:09,627 --> 00:33:14,830 +I'm going to put the strings into a little constant, +我将放这些字符串到那个 constants + +844 +00:33:14,832 --> 00:33:17,566 +okay, a struct that's kind of like constants. +好的,这个结构像 constants + +845 +00:33:17,568 --> 00:33:19,300 +So, I have my struct alert strings. +因此我有我的结构 AlertStrings + +846 +00:33:19,302 --> 00:33:21,002 +Actually, I have a little struct inside of it called +事实上,我有一个结构在这里叫 + +847 +00:33:21,004 --> 00:33:23,137 +the alert strings for +AlertStrings + +848 +00:33:23,138 --> 00:33:25,271 +the login error alert, cuz I might have multiple alerts. +给登录错误警告,因为我想有多个警告 + +849 +00:33:25,274 --> 00:33:27,207 +And, so then I have a localized string for +然后我有 NSLocalizedString + +850 +00:33:27,209 --> 00:33:29,509 +the title of the alert, a localized string for +警告的标题,警告的信息里的 NSLocalizedString + +851 +00:33:29,511 --> 00:33:31,845 +the message in the alert, and a localized string for +警告的取消按键的 + +852 +00:33:31,847 --> 00:33:33,880 +the dismiss button of the alert, right? +NSLocalizedString,对不对 + +853 +00:33:33,882 --> 00:33:37,016 +Login error, invalid username, try again. +登录错误,无效的用户名,重试 + +854 +00:33:37,018 --> 00:33:40,052 +And again, I've put nice, long description here, so that +然后我放这个放好了,这里详细的描述 + +855 +00:33:40,054 --> 00:33:42,954 +the translator can figure out what the context of this is. +翻译器可以计算出文本的内容 + +856 +00:33:42,956 --> 00:33:46,524 +And then down here, I need to replace these literal +然后放置在这,我需要替换这些文字 + +857 +00:33:46,526 --> 00:33:49,327 +strings with the things from my struct. +根据我的结构上的东西 + +858 +00:33:49,329 --> 00:33:53,997 +So this is the title, this is the message right here. +这是标题,这是信息 + +859 +00:33:53,999 --> 00:33:56,933 +Strings.loginerror.message. +AlertStrings.loginerror.message + + +860 +00:33:56,935 --> 00:33:59,336 +And here is our dismiss button. +这是我们的取消按键 + +861 +00:34:03,941 --> 00:34:06,608 +Okay, so I replace that. +好的,我替换它 + +862 +00:34:06,610 --> 00:34:07,910 +Okay? So now, +好的,现在 + +863 +00:34:07,911 --> 00:34:09,211 +I basically got all my strings, except for +我得到所有我的字符串,除了 + +864 +00:34:09,213 --> 00:34:10,211 +this last login thing, +最后登录的那个 + +865 +00:34:10,213 --> 00:34:12,280 +which we're gonna do in a second here. +我将等下去处理 + +866 +00:34:12,282 --> 00:34:15,616 +I pulled all my strings out into NSLocalizedString. +我放所有我的字符串到 NSLocalizedString + +867 +00:34:15,618 --> 00:34:18,819 +I don't have any other literal strings other than this +我没有其他文本信息 + +868 +00:34:18,821 --> 00:34:20,821 +in my app that appear in the UI. +这些在我应用里的是出现在用户界面上 + +869 +00:34:20,823 --> 00:34:26,526 +So, again, I'm gonna go back to my project, right here. +我将再次回到我的项目,这里 + +870 +00:34:26,528 --> 00:34:30,262 +And, this time I'm going to send +这时候我要再次发送它们 + +871 +00:34:30,264 --> 00:34:32,197 +out to my localizers again. +我的 localizers 目录 + +872 +00:34:32,199 --> 00:34:33,698 +Now, this time when I send out, +现在这个时候当我发过去 + +873 +00:34:33,700 --> 00:34:35,667 +so this is going to the localizer again. +再次到这个 localizers 这里 + +874 +00:34:35,669 --> 00:34:38,836 +So I'm gonna send it out, I can replace these. +我将发送它,我可以替换这些 + +875 +00:34:38,838 --> 00:34:42,239 +If we look at what I sent this time to the localizer, +如果我们看这些我这时候发送到 localizers 里的 + +876 +00:34:42,241 --> 00:34:45,308 +let's look at Japanese, you can see that, look, +看这个日语,你可以发现 + +877 +00:34:45,310 --> 00:34:48,144 +the old things that that localizer did are in there. +旧的在这 + +878 +00:34:48,146 --> 00:34:51,481 +So, that localizer hasn't lost any work. +localizer 没有全部丢失 + +879 +00:34:51,483 --> 00:34:55,818 +But, down here is all the new things that we just added. +但是,所有这些新的东西我们添加的放这 + +880 +00:34:55,820 --> 00:34:59,121 +Invalid username and password, login error, password. +无效的用户名和密码,登录错误,密码 + +881 +00:34:59,123 --> 00:35:01,790 +And, here's my nice comments to tell them what it is. +这里是我写的注释告诉他们那是啥 + +882 +00:35:01,792 --> 00:35:03,091 +So, they'll bring this up in their tool and +因此他们将用工具带这些过来 + +883 +00:35:03,093 --> 00:35:05,192 +they'll translate it, okay? +然后他们将翻译它,对不对 + +884 +00:35:05,194 --> 00:35:06,527 +So, you can how, what I mean by, +你可以怎样,我的意思是 + +885 +00:35:06,529 --> 00:35:08,662 +if we can go back and forth and back and forth? +如果我们可以回去然后过来,然后来回 + +886 +00:35:08,664 --> 00:35:11,164 +So, they translate it and it comes back. +他们翻译它然后返回 + +887 +00:35:11,166 --> 00:35:13,199 +So, here we are from the translator. +这里是从翻译器过来的 + +888 +00:35:15,036 --> 00:35:17,369 +We'll say we did all of our languages. +我们将翻译所有的语言 + +889 +00:35:17,371 --> 00:35:19,471 +So, let's go to a different language here. +让我们去到不同的语言那里 + +890 +00:35:19,473 --> 00:35:22,507 +Let's do Chinese, let's say. +到中文这里 + +891 +00:35:22,509 --> 00:35:25,677 +Let's do traditional Chinese. +繁体中文这 + +892 +00:35:25,679 --> 00:35:28,446 +Okay, so here's what Chinese looks like here. +这里是中文显示的地方 + +893 +00:35:28,448 --> 00:35:30,247 +There's the storyboard. +这算 storyboard + +894 +00:35:30,249 --> 00:35:33,350 +And here, all the literal strings have been +还有这里,所有的文字 + +895 +00:35:33,352 --> 00:35:35,051 +translated, okay? +被翻译的,对不对 + +896 +00:35:35,053 --> 00:35:36,185 +So, let's import that. +让我们导入这些 + +897 +00:35:36,187 --> 00:35:39,755 +So, I'm gonna go here, Import Localizations. +我将到这里,导入 Localizations + +898 +00:35:39,757 --> 00:35:40,989 +From the localizer. +从 localizer 这里 + +899 +00:35:40,991 --> 00:35:43,224 +Want this one. +想这样 + +900 +00:35:43,226 --> 00:35:44,192 +Traditional. +繁体的 + +901 +00:35:44,194 --> 00:35:45,760 +There it is. +像这样 + +902 +00:35:45,761 --> 00:35:47,327 +Again, I'll make another scheme here, okay? +我将再弄一个 scheme 在这里 + +903 +00:35:47,330 --> 00:35:50,997 +This one, I'm gonna call, Chinese Traditional. +这一个,繁体中文 + +904 +00:35:52,167 --> 00:35:54,100 +Let's go ahead in the Run. +在 Run 这里做下一步工作 + +905 +00:35:54,102 --> 00:35:56,335 +We'll change this to Chinese. +我们要把这个改成 Chinese + +906 +00:35:56,337 --> 00:35:59,972 +And, we'll set our location to be China, our locale. +我们要设置我们的位置为 China + +907 +00:35:59,974 --> 00:36:01,640 +Okay? So, now we have one for +好的,现在我们有一个 + +908 +00:36:01,642 --> 00:36:03,008 +Japan and one for China. +给日本用的,一个给中国用的 + +909 +00:36:03,010 --> 00:36:04,676 +Okay? +对不对 + +910 +00:36:04,677 --> 00:36:06,343 +So, let's do this and let's just run. +所以让我们做好这一步,然后运行 + +911 +00:36:09,682 --> 00:36:11,181 +Okay? Gonna make this wider. +好的,让这个更宽 + +912 +00:36:11,183 --> 00:36:13,016 +So, this is, here we have in Chinese now. +现在我们在中文环境下 + +913 +00:36:13,018 --> 00:36:15,352 +Notice that this is working. +注意这个在工作 + +914 +00:36:15,353 --> 00:36:17,687 +Notice the auto-layout is adjusting just like it did in +注意这个自动布局会使它自适应 + +915 +00:36:17,689 --> 00:36:19,706 +English. +就像在英文一样 + +916 +00:36:19,707 --> 00:36:21,724 +If we try to log in, we get our error right here. +如果我们尝试登录,我们在这里就会得到错误提示 + +917 +00:36:23,293 --> 00:36:24,659 +Some of you probably speak Chinese, so +你们当中有的人是说中文的 + +918 +00:36:24,661 --> 00:36:26,294 +hopefully these translations are good. +希望这里的翻译都不错 + +919 +00:36:26,296 --> 00:36:27,495 +I take full responsibility. +我要承担全部责任 + +920 +00:36:27,497 --> 00:36:28,962 +I don't know any Chinese. +我不会中文 + +921 +00:36:28,964 --> 00:36:30,797 +So, I'll take responsibility if they're wrong even though +我要负责如果他们出错了 + +922 +00:36:30,799 --> 00:36:32,132 +I didn't do the translations. +我又不懂得翻译 + +923 +00:36:32,134 --> 00:36:34,334 +But anyway, there's that. +但是无论如何,就酱 + +924 +00:36:34,336 --> 00:36:38,470 +Now if I log in, so let's log in here. +现在如果我登录,所以我们登录到这 + +925 +00:36:38,472 --> 00:36:40,406 +That's MadBum. +这个 MadBum + +926 +00:36:40,407 --> 00:36:42,341 +Okay, I still don't have this thing translated, and +好的,我仍然没有翻译的这个东西 + +927 +00:36:42,343 --> 00:36:43,775 +this is obviously content, +这显然是原来的内容 + +928 +00:36:43,777 --> 00:36:46,277 +so that we're not going to translate Madison Bumgarner. +我们不翻译 Madison Bumgarner + +929 +00:36:46,279 --> 00:36:47,895 +Okay? +对不对 + +930 +00:36:47,896 --> 00:36:49,512 +Although we could I suppose, but we're not going to. +虽然我们可以,但是我们不这么做 + +931 +00:36:49,515 --> 00:36:51,548 +So, this is content just coming out of our database, +这就是从我们的数据库得到的内容 + +932 +00:36:51,550 --> 00:36:52,549 +or whatever. +或者任意其他 + +933 +00:36:52,551 --> 00:36:54,117 +So, this is the last thing we need to do. +这是我们需要做的最后的一件事 + +934 +00:36:54,119 --> 00:36:55,885 +Now, let's look at this last login. +现在让我们看这个最后的登录 + +935 +00:36:55,887 --> 00:36:57,186 +It's pretty bad. +这是非常糟糕的 + +936 +00:36:57,188 --> 00:36:58,520 +Okay? This is bad even in +对不对,这个很糟 + +937 +00:36:58,522 --> 00:36:59,788 +English, okay? +甚至在英语环境下,对不对 + +938 +00:36:59,790 --> 00:37:03,024 +This is really ugly looking time and date. +这实在是难看的时间和日期 + +939 +00:37:03,026 --> 00:37:04,459 +I want this to be much nicer. +我想这个好一点 + +940 +00:37:04,461 --> 00:37:07,478 +I'm gonna have it be, +我想它要这样 + +941 +00:37:07,479 --> 00:37:10,496 +last logged in certain number of days ago at this time. +last logged 显示这个时候的若干天前 + +942 +00:37:10,499 --> 00:37:12,416 +Okay? 12 and +对不对,12 + +943 +00:37:12,417 --> 00:37:14,334 +a half days ago at 4:15 or something like that. +4:15 半天前或者其他 + +944 +00:37:14,336 --> 00:37:16,703 +So, if I do that, I need two things. +如果我这么做,我需要两个东西 + +945 +00:37:16,705 --> 00:37:19,439 +I need to format that time, the time you logged in and +我需要美化一下时间, + +946 +00:37:19,441 --> 00:37:21,140 +I also need to format the number, +我也需要美化一下数字 + +947 +00:37:21,142 --> 00:37:22,675 +how many days ago you logged in. +你登录了多少天 + +948 +00:37:22,677 --> 00:37:24,309 +So, I'm gonna use a number formatter and +我将用 number formatter 工具和 + +949 +00:37:24,311 --> 00:37:26,511 +a date formatter to make that work. +一个 date formatter 工具去做这些事 + +950 +00:37:26,513 --> 00:37:28,012 +Okay? And then I'm also then gonna +好的,然后我也将 + +951 +00:37:28,014 --> 00:37:31,148 +use a format string, you know, something with percent this +用这个去美化字符,你知道的,有些有百分号的 + +952 +00:37:31,150 --> 00:37:33,417 +and then present that in there, to do that. +需要做这些 + +953 +00:37:33,419 --> 00:37:34,852 +And, that string, +这些字符 + +954 +00:37:34,853 --> 00:37:36,286 +of course, as a whole, is gonna be localizable. +当然,总的来说,都会本地化 + +955 +00:37:36,288 --> 00:37:38,455 +So, a lot going on to localize this here, but +因此,很多将要在这里本地化 + +956 +00:37:38,457 --> 00:37:40,957 +you're gonna see the code's not too bad to do that. +但是你将会看到做这些不会太糟糕的代码 + +957 +00:37:40,959 --> 00:37:42,792 +So let's go, whoops. +好的,开始吧 + +958 +00:37:42,794 --> 00:37:46,028 +Let's go back to our controller. +让我们回到我们的控制器 + +959 +00:37:46,030 --> 00:37:48,964 +Here's where that nasty, offending, +这里就是令人讨厌的 + +960 +00:37:48,966 --> 00:37:52,300 +non-internationalized code is right here. +没有国际化的代码 + +961 +00:37:52,302 --> 00:37:55,970 +So, here, this is where I get the last login. +这里就是最后登录的位置 + +962 +00:37:55,972 --> 00:37:57,338 +So this is an NS Date. +这里是 NS 数据 + +963 +00:37:57,340 --> 00:37:58,605 +Right? This last login is +对不对,最后登录 + +964 +00:37:58,607 --> 00:38:01,574 +an NS Date of the last time this guy logged in. +是一个 NS 数据,关于最后登录时间 + +965 +00:38:01,576 --> 00:38:08,114 +And so, I don't really want this badness in here, +所以我真不希望这种不好的东西在这 + +966 +00:38:08,116 --> 00:38:12,984 +so I really wanna say something like, +我想做一些事 + +967 +00:38:12,986 --> 00:38:17,689 +Last Login %@ days ago at %@. +Last Login %@ days ago at %@. + +968 +00:38:17,691 --> 00:38:19,890 +So, I'd really like to say something like that. +我想要这样做 + +969 +00:38:19,892 --> 00:38:21,458 +And, you know, +你知道的 + +970 +00:38:21,460 --> 00:38:24,428 +to do the format, I wanna make sure that I'm doing +为了做这样的格式,我要确保我正在做的 + +971 +00:38:24,430 --> 00:38:27,831 +String.localizedStringWithFor- mat, okay? +String.localizedStringWithFormat 这个方法,对不对 + +972 +00:38:27,833 --> 00:38:29,532 +So, put this format string in here. +放这些格式好的字符在这里 + +973 +00:38:34,071 --> 00:38:35,404 +Okay? And, we need the arguments +好的,我们需要参数 + +974 +00:38:35,406 --> 00:38:39,073 +here that correspond, so we'll call that daysAgo and time. +这里要对应的,我们称它为 daysAgo 还有 time + +975 +00:38:40,143 --> 00:38:42,142 +Those are the two arguments that are correspond to +这里是两个参数对应着 + +976 +00:38:42,144 --> 00:38:44,778 +here and here. +这里和这里 + +977 +00:38:44,779 --> 00:38:47,413 +But, of course, this needs to, itself, be localized. +但是,当然,这些需要的,它自己,本地化 + +978 +00:38:47,416 --> 00:38:50,817 +Okay? So, +对不对 + +979 +00:38:50,818 --> 00:38:54,219 +I'm gonna call this lastLoginFormatString. +我将称他们 lastLoginFormatString + +980 +00:38:54,222 --> 00:38:55,521 +And we will put here let +然后我们将让 lastLoginFormatString = NSLocalizedString + +981 +00:38:58,826 --> 00:39:03,094 +lastLoginFormatString equal NSLocalizedString. +放这里 + +982 +00:39:03,096 --> 00:39:04,895 +And then, I'll put that format string in there. +然后,我将在那里格式化这个字符 + +983 +00:39:04,897 --> 00:39:08,799 +Again, I don't use this. +再次声明,我不想用这个 + +984 +00:39:08,801 --> 00:39:12,936 +In the comment here, we'll say something like, +在 comment 这里,我们会填这些 + +985 +00:39:12,938 --> 00:39:17,607 +Reports the number of days ago and time that the user last +Reports the number of days ago and time that the user last + +986 +00:39:17,609 --> 00:39:21,744 +logged in, or something along those lines to make +logged in,或者其他确保 + +987 +00:39:21,746 --> 00:39:26,481 +sure that the localizer understands what's going on. +本地化器可以理解的 + +988 +00:39:27,851 --> 00:39:28,616 +Okay, so that's it. +好的,就这样 + +989 +00:39:28,618 --> 00:39:30,501 +We've localized that. +我们要本地化啦 + +990 +00:39:30,502 --> 00:39:32,385 +All we have to now is the daysAgo and time. +所有我们现在有的是 daysAgo 和 time + +991 +00:39:32,388 --> 00:39:34,588 +And, these are both going to be strings. +这些都是字符串 + +992 +00:39:34,590 --> 00:39:37,757 +And, we're gonna get each of them by using a formatter. +我们将使用 formatter 得到每一个字符 + +993 +00:39:37,759 --> 00:39:40,259 +So, let's start with the date. +所以,让我们从日期开始 + +994 +00:39:40,261 --> 00:39:42,161 +So, I'm gonna create a date formatter. +我将创建一个 date formatter + +995 +00:39:43,531 --> 00:39:45,063 +NSDateFormatter, okay? +NSDateFormatter 对不对 + +996 +00:39:45,065 --> 00:39:48,033 +If you just create one, no arguments or whatever. +如果你只是创建一个,没有参数或者其他 + +997 +00:39:48,035 --> 00:39:50,535 +And, now we're gonna configure this date formatter to +现在我们将设置这个 date formatter + +998 +00:39:50,537 --> 00:39:51,535 +present the date. +显示日期 + +999 +00:39:51,537 --> 00:39:53,003 +So, I'm gonna say, +我将要说 + +1000 +00:39:53,005 --> 00:39:56,907 +set the timeStyle of the thing to be kind of a short time. +设置短时间类型的 timeStyle + +1001 +00:39:56,909 --> 00:39:59,075 +Okay, this is just saying when you last log in, +好的,这就是最后你登录的东西 + +1002 +00:39:59,077 --> 00:40:01,110 +I don't need the seconds and the time zone. +我不需要秒还有时区 + +1003 +00:40:01,112 --> 00:40:04,480 +I just need, basically, the time is a short time, so +我只是需要,基本上,这个时间是短时间 + +1004 +00:40:04,482 --> 00:40:05,981 +I'm gonna say NSDate. +我要写作 NSDate + +1005 +00:40:05,983 --> 00:40:09,884 +FormatterSTyle.ShortStyle. +FormatterSTyle.ShortStyle. + +1006 +00:40:09,886 --> 00:40:11,386 +So you can see here's the styles. +你可以看到这里的类型 + +1007 +00:40:11,388 --> 00:40:12,019 +Full style. +Full style. + +1008 +00:40:12,021 --> 00:40:12,619 +Long style. +Long style. + +1009 +00:40:12,621 --> 00:40:13,286 +Medium style. +Medium style. + +1010 +00:40:13,288 --> 00:40:15,388 +I'm gonna go short style. +我要选择 short style + +1011 +00:40:15,390 --> 00:40:16,689 +Now, I only want the time. +现在我只是想要时间 + +1012 +00:40:16,691 --> 00:40:18,491 +I don't want the date portion at all. +我不想要日期部分 + +1013 +00:40:18,493 --> 00:40:22,794 +So I'm gonna say dateFormatter.dateStyle equals +然后我要写 dateFormatter.dateStyle = + +1014 +00:40:22,796 --> 00:40:26,397 +NSDateFOrmatterStyle.NoStyle. +NSDateFOrmatterStyle.NoStyle + +1015 +00:40:26,399 --> 00:40:27,799 +Okay, that means, +好的,这意味着 + +1016 +00:40:27,800 --> 00:40:29,200 +don't give me the date portion, I just want the time. +不要给我日期部分。我只要时间 + +1017 +00:40:30,503 --> 00:40:31,735 +Okay? +对不对 + +1018 +00:40:31,737 --> 00:40:33,937 +So now that I've kind of configured this date +现在我只要配置这个 + +1019 +00:40:33,939 --> 00:40:37,807 +formatter, I can let that time string, this thing right here +date formatter,我可以让这个时间字符,在这里的东西 + +1020 +00:40:37,809 --> 00:40:42,311 +that I want this percent at sign to correspond to. +我想要这个百分号与之对应 + +1021 +00:40:42,313 --> 00:40:45,981 +I can say dateFormatter.dateFromString. +我可以写为 dateFormatter.dateFromString + +1022 +00:40:45,983 --> 00:40:47,182 +That's all right, other way around. +就酱,或者其他 + +1023 +00:40:47,184 --> 00:40:52,720 +StringFromDate the lastLogin. +StringFromDate(lastLogin) + +1024 +00:40:52,722 --> 00:40:54,221 +Okay? And that's it. +对不对,就是这样 + +1025 +00:40:54,223 --> 00:40:56,440 +So I've just use the date former. +我只是使用 date formatter + +1026 +00:40:56,441 --> 00:40:58,658 +Now, not only is this going to put this is a nice format for +不只是要放这个 formatter 在这里 + +1027 +00:40:58,660 --> 00:41:01,528 +me for English, it's also going to work in the local +他也在本地化语言里运作 + +1028 +00:41:01,530 --> 00:41:03,029 +language, as you're going to see. +就像你所看见的 + +1029 +00:41:03,998 --> 00:41:05,564 +All right. +好的 + +1030 +00:41:05,565 --> 00:41:07,131 +How about the number, how many days ago? +数字怎么样,多少天之前 + +1031 +00:41:07,134 --> 00:41:09,334 +I said I only want it to be like 3.5. +我说我只是想它看起来像 3.5 + +1032 +00:41:09,336 --> 00:41:13,304 +I don't want it to be logged in 3.5876 days ago. +我不想这个是 3.5876 天之前 + +1033 +00:41:13,306 --> 00:41:15,073 +Okay? +对不对 + +1034 +00:41:15,074 --> 00:41:16,841 +I could maybe just go for three days ago, but +我可以让它是 3 天之前 + +1035 +00:41:16,843 --> 00:41:20,010 +I'm gonna say 3 point one decimal digit just to show you +但是我想写 3 点 加十进制的数字去给你们 + +1036 +00:41:20,012 --> 00:41:21,211 +how to do that. +现在它是咋样的 + +1037 +00:41:21,213 --> 00:41:23,279 +So, let's create a number formatter. +好的,让我们创建一个 number formatter + +1038 +00:41:26,451 --> 00:41:29,919 +And again, we already did this back in the calculator days. +我们已经在计算器那个课里面讲过这个东西了 + +1039 +00:41:29,921 --> 00:41:31,253 +So we create this number formatter. +我们创建这个 number formatter + +1040 +00:41:31,255 --> 00:41:34,156 +Then we're gonna configure it, and the only thing I'm gonna +然后我们将配置它,我所写的就一个 + +1041 +00:41:34,158 --> 00:41:36,891 +say is that I want the maximum number of fraction digits +我想最大的小数部分的数字 + +1042 +00:41:36,893 --> 00:41:37,458 +to be one. +只有一个 + +1043 +00:41:37,460 --> 00:41:38,526 +Okay? +对不对 + +1044 +00:41:38,528 --> 00:41:41,628 +3.5, not 3.5267, okay, just one digit. +3.5,不是 3.5267,好的,就一个数字 + +1045 +00:41:41,630 --> 00:41:45,432 +Then I'm gonna let that daysAgo thing equal +然后我想让 daysAgo = + +1046 +00:41:45,434 --> 00:41:47,567 +the numberFormatter. +numberFormatter + +1047 +00:41:47,569 --> 00:41:50,436 +A string from number. +从数字过来的字符 + +1048 +00:41:50,438 --> 00:41:53,772 +And so, now I just need to take this login date and +现在我只是需要把这个登录日期 + +1049 +00:41:53,774 --> 00:41:55,474 +turn it into the number of days ago. +放到几天前的数字那里 + +1050 +00:41:55,476 --> 00:41:57,326 +Which I can do with +那个我可以处理 + +1051 +00:41:57,327 --> 00:41:59,177 +lastLogin.timeIntervalSince- Now. +lastLogin.timeIntervalSinceNow + +1052 +00:41:59,179 --> 00:42:02,046 +Of course that's negative, okay? +当然这是负数,对不对 + +1053 +00:42:02,048 --> 00:42:04,915 +Cuz that's gonna be in the past. +因为这个是过去的 + +1054 +00:42:04,917 --> 00:42:08,952 +And we'll just divide that times 60, times 60, times 24. +我们也要它除以(60*60*24) + +1055 +00:42:08,954 --> 00:42:10,954 +Which is the number of seconds in a day. +这个代表一天的秒数 + +1056 +00:42:10,956 --> 00:42:13,156 +Because the time intervals are seconds. +因为这个时间间隔是基于秒的 + +1057 +00:42:13,158 --> 00:42:14,290 +Okay? +好吧 + +1058 +00:42:14,292 --> 00:42:16,859 +Make sense? +讲得通 + +1059 +00:42:16,861 --> 00:42:19,127 +All right. +好的 + +1060 +00:42:19,129 --> 00:42:20,762 +What do we got here. +我们到这 + +1061 +00:42:20,764 --> 00:42:22,230 +Oh, exclamation point, yeah. +加一个断点 + +1062 +00:42:22,232 --> 00:42:25,032 +So string from number [INAUDIBLE] is an optional. +数字字符是一个 optional 类型 + +1063 +00:42:25,034 --> 00:42:29,036 +It returns an optional string and you might say why would +它会返回一个 optional 字符,然后你可以说 + +1064 +00:42:29,038 --> 00:42:32,005 +you ever do that because this argument if it's a double, +为什么要这么做因为这个参数可能是双精度类型的 + +1065 +00:42:32,007 --> 00:42:35,175 +it's always gonna be turned into a string. +它一直转为字符 + +1066 +00:42:35,177 --> 00:42:38,277 +But string from number also knows how to deal with +但是数字转为字符的也知道如果处理 + +1067 +00:42:38,279 --> 00:42:39,612 +things such as Booleans and +比如说布尔类型 + +1068 +00:42:39,614 --> 00:42:41,947 +things like that from the old objective C days. +或者其他的旧 Objective C 的类型 + +1069 +00:42:41,949 --> 00:42:43,766 +So that's why. +所以这就是为什么 + +1070 +00:42:43,767 --> 00:42:45,584 +Just so you're pretty safe to always go ahead and +你可以安全地一直往下做 + +1071 +00:42:45,586 --> 00:42:48,186 +unwrap the optional if that gets back if what you're +打开 optional 类型如果它返回如果你通过 + +1072 +00:42:48,188 --> 00:42:51,189 +passing in here is a double or an int. +这个双精度或者数字类型 + +1073 +00:42:51,191 --> 00:42:52,323 +Okay? Or some number. +对不对,或者一些数字 + +1074 +00:42:53,292 --> 00:42:54,558 +Okay? You could do if let if you're +好的,你可以这样做如果你有 + +1075 +00:42:54,560 --> 00:42:55,792 +a little worried about it. +一点担心这个的话 + +1076 +00:42:55,794 --> 00:42:57,260 +But I didn't do that. +但我不会这么做 + +1077 +00:42:57,262 --> 00:42:58,678 +Okay? +好的 + +1078 +00:42:58,679 --> 00:43:00,095 +So there we go. Now we've got the date and +我们继续。现在我们拿到这个日期 + +1079 +00:43:00,098 --> 00:43:00,696 +the time. +和时间 + +1080 +00:43:00,698 --> 00:43:02,631 +And again, like you say, +再次就像你写的哪有 + +1081 +00:43:02,632 --> 00:43:04,565 +localizers won't be able to change the order of these two +localizers 不会改变这两个东西的顺序 + +1082 +00:43:04,568 --> 00:43:06,935 +things if they're a sentence in a different language. +如果他们是一个在不同语言里的句子 + +1083 +00:43:07,937 --> 00:43:09,837 +Makes sense to do that. +做这个有意义 + +1084 +00:43:09,839 --> 00:43:12,306 +All right? +好的 + +1085 +00:43:12,307 --> 00:43:14,774 +Let's go back to our project again. +让我们回到我们的项目 + +1086 +00:43:15,744 --> 00:43:17,710 +Let's go ahead and export this. +继续导出这个 + +1087 +00:43:17,712 --> 00:43:19,745 +Okay? +好的 + +1088 +00:43:19,747 --> 00:43:22,447 +So I export this to localizer. +我导出这个到 localizer + +1089 +00:43:24,818 --> 00:43:26,351 +Replace all that. +替换这里所有的 + +1090 +00:43:26,353 --> 00:43:27,852 +All right. We've sent them out there. +好的,我们把他们发到那里 + +1091 +00:43:27,854 --> 00:43:30,554 +Let's go take a quick look at what that looks like. +让我们快速看一下它变成咋样 + +1092 +00:43:30,556 --> 00:43:34,657 +We'll look at oh, yeah, let's look at French. +看一下,好的,让我们看一下法语 + +1093 +00:43:34,659 --> 00:43:35,958 +Okay, so here's French. +好的,这是法语 + +1094 +00:43:35,960 --> 00:43:37,960 +If we go down, here's the last log in. +向下,这里是最后登录 + +1095 +00:43:37,962 --> 00:43:40,396 +Notice here's the dollar one and dollar two. +注意这个 $1 和 $2 + +1096 +00:43:40,398 --> 00:43:44,532 +That's how they can control which one is which and so +这就是他们怎样控制这个,这个 + +1097 +00:43:44,534 --> 00:43:47,268 +they need to translate though, this into French. +他们需要翻译的,翻译成法语的方式 + +1098 +00:43:47,270 --> 00:43:48,803 +Okay? So +好的 + +1099 +00:43:48,804 --> 00:43:50,337 +let's go ahead and have that happen. +让我们继续看会发生什么 + +1100 +00:43:50,340 --> 00:43:51,238 +Okay. +好的 + +1101 +00:43:51,240 --> 00:43:52,072 +It happened. +它发生了 + +1102 +00:43:52,074 --> 00:43:54,607 +Okay. Now let's load it in. +现在加载它 + +1103 +00:43:54,609 --> 00:43:57,443 +Okay. Import localizations +好的,从我们的 localizer + +1104 +00:43:57,445 --> 00:43:58,844 +from our localizer. +导入 localizations + +1105 +00:43:59,947 --> 00:44:01,713 +Let's go ahead and let's do French. +让我们继续看这个法语 + +1106 +00:44:02,649 --> 00:44:03,214 +Okay? +好的 + +1107 +00:44:04,450 --> 00:44:06,583 +So let's edit a scheme here for French. +让我们给这个法语编辑 scheme + +1108 +00:44:06,585 --> 00:44:09,553 +I always like to do the edit schemes because +我一直喜欢编辑 scheme 因为 + +1109 +00:44:09,555 --> 00:44:11,354 +you're always gonna come back to it. +你总是会回到这 + +1110 +00:44:11,356 --> 00:44:13,856 +It's not like oh, you're only ever gonna run French once. +它不像 oh,你只会运行法语一次 + +1111 +00:44:13,858 --> 00:44:15,057 +You're gonna run it multiple times. +你会运行它很多次 + +1112 +00:44:15,059 --> 00:44:18,560 +So here's French, and we'll make it in France. +这里是法语,我们把它设置为法国 + +1113 +00:44:18,562 --> 00:44:19,160 +Okay. +好的 + +1114 +00:44:19,162 --> 00:44:19,894 +So let's run. +运行一下 + +1115 +00:44:20,863 --> 00:44:22,463 +See if we got this right. +看我们会得到什么 + +1116 +00:44:22,465 --> 00:44:23,430 +Oops. +哦 + +1117 +00:44:23,432 --> 00:44:26,966 +All right, so this all looks like French. +好的,看起来像法语 + +1118 +00:44:26,968 --> 00:44:29,535 +Okay? That looks like in French. +好的,看起来像法语 + +1119 +00:44:29,537 --> 00:44:30,787 +Yeah, there's some French. +好的,这是法语 + +1120 +00:44:30,788 --> 00:44:32,038 +I don't know if it's right French but +我不知道它是否是准确,但是 + +1121 +00:44:32,040 --> 00:44:34,973 +oh, again my keyboard is French. +哦,我的键盘是法语的 + +1122 +00:44:34,975 --> 00:44:37,876 +So let's go ahead and bring up our keyboard so +让我们接下来打开我们的键盘 + +1123 +00:44:37,878 --> 00:44:38,777 +we can see that. +然后你就可以看到这样的 + +1124 +00:44:40,113 --> 00:44:41,496 +Okay? Yeah, +好的 + +1125 +00:44:41,497 --> 00:44:42,880 +we got our French keyboard here. +我们拿到了我们的法语键盘 + +1126 +00:44:42,882 --> 00:44:44,648 +So, I'll type it here. +我会输入点东西 + +1127 +00:44:44,650 --> 00:44:47,084 +Mad, madbum. +Mad,madbum + +1128 +00:44:47,086 --> 00:44:49,252 +Oops. +哦 + +1129 +00:44:49,254 --> 00:44:51,454 +Madbum. +Madbum + +1130 +00:44:51,456 --> 00:44:52,621 +How do I back up? +我要怎么回退 + +1131 +00:44:52,623 --> 00:44:53,956 +There we go. +就这样 + +1132 +00:44:53,957 --> 00:44:55,290 +[LAUGH] Madbum and here we go. +Madbum 我们开始吧 + +1133 +00:44:55,292 --> 00:44:56,925 +Foo. Hopefully, I typed that right, +希望我输入的是对的 + +1134 +00:44:56,927 --> 00:44:58,860 +but there we go. +继续 + +1135 +00:44:58,862 --> 00:44:59,794 +All right. So there's madbum. +好的,这是 madbum + +1136 +00:44:59,796 --> 00:45:07,201 +And you can see [FOREIGN]. +你可以看到 [外语] + +1137 +00:45:07,203 --> 00:45:08,135 +Whatever. +不管咋样 + +1138 +00:45:08,137 --> 00:45:08,968 +Okay? [LAUGH] So +好的 + +1139 +00:45:08,970 --> 00:45:10,470 +there's the time and date and +这是时间和日期 + +1140 +00:45:10,472 --> 00:45:12,271 +you can see it's put a comma there. +你可以看到这个逗号 + +1141 +00:45:12,273 --> 00:45:15,341 +Okay? Not 10.7, but 10, 7. +好的,不是 10.7,是10,7 + +1142 +00:45:15,343 --> 00:45:18,143 +It's like those French have a different word for everything, +这意味着法语没个词都不一样 + +1143 +00:45:18,145 --> 00:45:19,944 +but they also have a different way to put the number there. +但是他们也有不同的方式把这个数字放那里 + +1144 +00:45:21,581 --> 00:45:22,880 +Okay? So there's French. +好的,这是法语 + +1145 +00:45:22,882 --> 00:45:25,382 +Now I'm gonna show you one other language which is kind +现在我将给你显示一个其他有趣的语言 + +1146 +00:45:25,384 --> 00:45:28,085 +of a fun, different, interesting language, +不一样的,有趣的语言 + +1147 +00:45:28,087 --> 00:45:29,519 +which is Arabic. +阿拉伯语 + +1148 +00:45:29,521 --> 00:45:31,654 +So let's go ahead and import Arabic. +让我们接下来导入阿拉伯语 + +1149 +00:45:31,656 --> 00:45:34,590 +Those of you who know anything about +你们谁知道语言的 + +1150 +00:45:34,592 --> 00:45:39,561 +languages will know why this is an interesting language. +应该知道为啥它很有趣 + +1151 +00:45:39,563 --> 00:45:41,296 +So let's duplicate it. +让我们复制它 + +1152 +00:45:41,298 --> 00:45:43,731 +Arabic. +阿拉伯语 + +1153 +00:45:43,733 --> 00:45:45,900 +And okay, it's Arabic. +好的,阿拉伯语 + +1154 +00:45:45,902 --> 00:45:46,667 +We'll have a country. +我们选一个国家 + +1155 +00:45:46,669 --> 00:45:47,701 +We'll have it be Egypt. +选埃及 + +1156 +00:45:47,703 --> 00:45:50,637 +They speak Arabic in Egypt. +他们说阿拉伯语 + +1157 +00:45:50,639 --> 00:45:51,755 +All those okay. +好的 + +1158 +00:45:51,756 --> 00:45:52,872 +So now, let's run this in Arabic. +现在让我们运行一下阿拉伯语 + +1159 +00:45:55,609 --> 00:45:59,111 +And, whoa, it broke my UI. +哇,它打破了我们的用户界面 + +1160 +00:45:59,113 --> 00:46:02,080 +Look at that, it put those things over on the right side. +看那里,它放了什么东西在右边 + +1161 +00:46:03,049 --> 00:46:03,981 +And, what's going on here? +怎么回事 + +1162 +00:46:04,917 --> 00:46:06,716 +This changed securities on the wrong side. +这个改变安全性的错误的一边 + +1163 +00:46:06,718 --> 00:46:08,384 +This was supposed to be over. +这被认为是结束了 + +1164 +00:46:08,386 --> 00:46:11,554 +So, Arabic is a right to left language, right? +因此阿拉伯语从右到左的语言,对吧 + +1165 +00:46:11,556 --> 00:46:14,790 +The text flows from the right hand side of the page to +文本信息从右 + +1166 +00:46:14,792 --> 00:46:15,457 +the left. +到左 + +1167 +00:46:15,459 --> 00:46:17,559 +Not from left to right. +不是从左到右 + +1168 +00:46:17,560 --> 00:46:19,660 +So, not only does that mean the text needs to flow right +所以不只是文本从右到左 + +1169 +00:46:19,663 --> 00:46:22,630 +to left, but my whole UI needs to flow right to left. +我的整个用户界面都从右到左 + +1170 +00:46:22,632 --> 00:46:24,866 +Okay? +对吧 + +1171 +00:46:24,867 --> 00:46:27,101 +So labels need to be on the right with the text going to +标签需要在右边,文本将 + +1172 +00:46:27,103 --> 00:46:28,235 +the left. +在左边 + +1173 +00:46:28,237 --> 00:46:29,870 +Same thing with these buttons. +这些按钮也是同样的道理 + +1174 +00:46:29,872 --> 00:46:30,737 +Okay? They need to go +好的,他们需要 + +1175 +00:46:30,739 --> 00:46:31,371 +for right and left. +从右到左 + +1176 +00:46:31,373 --> 00:46:32,972 +So, this is in here. +在这里 + +1177 +00:46:32,974 --> 00:46:34,073 +I have an English keyboard so +我有一个英语键盘 + +1178 +00:46:34,075 --> 00:46:36,008 +it's gonna be left to right typing here. +它从左到右输入 + +1179 +00:46:36,010 --> 00:46:37,108 +But if I had an Arabic keyboard, +但是如果我有一个阿拉伯键盘 + +1180 +00:46:37,110 --> 00:46:39,243 +it would be typing right to left. +它会从右到左输入 + +1181 +00:46:39,245 --> 00:46:40,644 +So let's go ahead and log in. +接下来登录 + +1182 +00:46:40,646 --> 00:46:41,378 +That's [LAUGH] this one. +就是这个 + +1183 +00:46:41,380 --> 00:46:42,746 +Not this one. +不是装一个 + +1184 +00:46:42,748 --> 00:46:43,613 +There it is. +这一个 + +1185 +00:46:43,615 --> 00:46:45,982 +And here's our last log in. +这里是我们最后登录时间 + +1186 +00:46:45,984 --> 00:46:49,551 +Whatever that is in Arabic and here's the time in Arabic. +不管那个阿拉伯语是什么,这里是阿拉伯语的时间 + +1187 +00:46:50,487 --> 00:46:53,788 +Okay, from right to left, so it's all right to left. +好的,从右到左,所有的都从右到左 + +1188 +00:46:53,790 --> 00:46:55,390 +Okay. +好的 + +1189 +00:46:55,391 --> 00:46:56,991 +Even this got made right to left. +甚至这个也是从右到左 + +1190 +00:46:58,260 --> 00:46:59,159 +Okay. +好的 + +1191 +00:46:59,161 --> 00:47:01,294 +And, that happened automatically. +这些都是自然发生的 + +1192 +00:47:01,296 --> 00:47:04,964 +Notice I didn't absolutely nothing whatsoever +注意我完全没有想这么做 + +1193 +00:47:04,966 --> 00:47:07,733 +in my entire storyboard to make that happen. +在我整个 storyboard 里,它自己发生的 + +1194 +00:47:07,735 --> 00:47:09,601 +But if we look at our constraints, +但是如果我们查看我们的约束 + +1195 +00:47:09,603 --> 00:47:12,170 +like we look at this constraint right here. +我们查看这里的约束 + +1196 +00:47:12,172 --> 00:47:13,405 +This guy. +这家伙 + +1197 +00:47:13,407 --> 00:47:15,073 +Let's look at his constraints. +让我们看一下他的约束 + +1198 +00:47:15,075 --> 00:47:18,075 +You see it's trailing space to super view. +你们看到这个 trailing space to super view + +1199 +00:47:18,077 --> 00:47:18,909 +Trailing space. +Trailing space + +1200 +00:47:18,911 --> 00:47:21,378 +Not right edge to super view. +不是有边缘到 super view + +1201 +00:47:21,380 --> 00:47:22,746 +Trailing space. +Trailing space + +1202 +00:47:22,748 --> 00:47:24,765 +Okay? So that's just +好的,那只是 + +1203 +00:47:24,766 --> 00:47:26,783 +saying that we wanna be attached to the trailing edge. +说我们想接近后边缘 + + +1204 +00:47:26,785 --> 00:47:28,751 +And if we're in a right to left language, +如果我们是从右到左的语言 + +1205 +00:47:28,753 --> 00:47:30,853 +that means the other side. +在意味着另一方面 + +1206 +00:47:30,855 --> 00:47:32,954 +So, this auto layout did the right thing. +这个自动布局做正确的事 + +1207 +00:47:32,956 --> 00:47:35,857 +It attached this edge over to here. +它接近边缘从那里到这里 + +1208 +00:47:35,859 --> 00:47:37,291 +Because this is the trailing edge. +因为这是后边缘 + +1209 +00:47:37,293 --> 00:47:39,393 +Everyone understand that? +每个人都懂吗 + +1210 +00:47:40,662 --> 00:47:42,579 +Okay? +好的 + +1211 +00:47:42,580 --> 00:47:44,497 +So when you go and do a right to left language, probably +所以当你使用从右到左的语言,可能 + +1212 +00:47:44,499 --> 00:47:47,867 +when you run it's not gonna work as nice as this one was. +当你运行它,它不能很好的运作就像这个一样 + +1213 +00:47:47,869 --> 00:47:49,301 +I was actually very. +我实际上上非常确定 + +1214 +00:47:49,303 --> 00:47:51,236 +Pleased that it just worked, okay? +它只是运行了,对吧 + +1215 +00:47:51,238 --> 00:47:53,438 +But sometimes it'll be like oh, oops, +但是有时候它看起来,额 + +1216 +00:47:53,440 --> 00:47:56,141 +I made an assumption there that was also going to be +我做一个假设,它也将 + +1217 +00:47:56,143 --> 00:47:59,043 +left to right, something smashing into each other, +从左到右,互相交错在一起 + +1218 +00:47:59,045 --> 00:48:01,545 +so I really always strongly recommend doing at +因此我一直强烈推荐 + +1219 +00:48:01,547 --> 00:48:04,448 +least one right to left language, Hebrew or Arabic or +至少一个是从右到左的语言,希伯来语或者阿拉伯语或者 + +1220 +00:48:04,450 --> 00:48:07,718 +something that tests out that part of your user interface. +一些你用户界面部分的测试语言 + +1221 +00:48:07,720 --> 00:48:08,718 +Okay? +好吧 + +1222 +00:48:08,720 --> 00:48:10,219 +So that's it for localization. +这就是本地化 + +1223 +00:48:10,221 --> 00:48:12,688 +Pretty powerful system. +非常强大的系统 + +1224 +00:48:12,690 --> 00:48:14,456 +Pretty easy, really, for you. +非常简单,当然,对你们来说 + +1225 +00:48:15,426 --> 00:48:17,826 +Apple's made it actually quite easy for you. +苹果公司把它弄得相当简单对你们来说 + +1226 +00:48:17,828 --> 00:48:21,462 +For the translators, depends, sometimes it's easy for them, +对翻译者,第三方,有时候其他方面都很简单 + +1227 +00:48:21,464 --> 00:48:23,330 +sometimes it's a pain in the neck trying to figure out what +有时它又相当痛苦因为要试图找出 + +1228 +00:48:23,332 --> 00:48:24,832 +it is you're actually trying to +你事实上想要找出的 + +1229 +00:48:24,834 --> 00:48:27,034 +say to them about where this word appears. +在这个单词上显示的 + +1230 +00:48:27,036 --> 00:48:29,135 +You'll get some funny translation back sometimes +你会得到一些有趣的翻译结果 + +1231 +00:48:29,137 --> 00:48:31,070 +when they don't really understand +当他们不能理解 + +1232 +00:48:31,072 --> 00:48:32,204 +what it is you're saying. +你所说的 + +1233 +00:48:34,875 --> 00:48:36,875 +But these underlying system is pretty easy to +但是这些潜在的系统很容易 + +1234 +00:48:36,877 --> 00:48:37,575 +iterate with them. +重复他们 + +1235 +00:48:38,545 --> 00:48:39,276 +Okay. Any questions +对的,任何问题 + +1236 +00:48:39,278 --> 00:48:42,246 +about localization? +关于 localization + +1237 +00:48:42,248 --> 00:48:43,213 +Okay. +好的 + +1238 +00:48:43,215 --> 00:48:47,550 +Let's go back to our slide. +让我们回到我们的 slide + +1239 +00:48:47,552 --> 00:48:48,617 +Oops. +哦 + +1240 +00:48:48,619 --> 00:48:50,819 +Slides are here. All right. +Slides 在这里,好的 + +1241 +00:48:53,056 --> 00:48:54,088 +Okay. +好的 + +1242 +00:48:54,090 --> 00:48:57,458 +So, the next topic is Settings, all right? +下一个课题是设置,对吧 + +1243 +00:48:57,460 --> 00:48:59,993 +So the settings is a. +设置是一个 + +1244 +00:48:59,995 --> 00:49:04,230 +Let's go back here, and let's show this on here. +让我们回到这里,让我们在这里显示 + +1245 +00:49:07,135 --> 00:49:10,269 +Okay, so the settings app, every device has a settings +好的,这个设置应用,每一个设备有一个设置 + +1246 +00:49:10,271 --> 00:49:13,238 +app, it's this little icon right here. +应用,这个小的图标在这里 + +1247 +00:49:13,240 --> 00:49:14,706 +Okay? See that icon right there? +好的,看这个图标 + +1248 +00:49:14,708 --> 00:49:16,941 +So, I'm gonna click on that and this gives settings for +我将点开它然后它会给我整个设备的 + +1249 +00:49:16,943 --> 00:49:18,576 +the whole device. +设置 + +1250 +00:49:18,578 --> 00:49:20,712 +Okay? We were earlier, +好的,我们很快 + +1251 +00:49:20,713 --> 00:49:22,847 +we were looking for example, inside General so that we +我们要看到这个例子,General 里面的 + +1252 +00:49:22,849 --> 00:49:26,450 +could find the Language & Region and all that. +我们可以看到 Language & Region 还有别的 + +1253 +00:49:26,452 --> 00:49:28,885 +But there's more than General settings here. +但是不只是常规设置在这里 + +1254 +00:49:28,887 --> 00:49:31,121 +There's also application specific settings. +这里也有应用的特殊设置 + +1255 +00:49:31,123 --> 00:49:32,355 +You see them right here? +你可以在这看到 + +1256 +00:49:32,356 --> 00:49:33,588 +Mail, Notes, Reminders, Phone. +邮件,便签,备忘,手机 + +1257 +00:49:33,591 --> 00:49:35,791 +Those are settings for those apps. +这些设置对应着这些应用 + +1258 +00:49:35,793 --> 00:49:37,493 +Okay? +对吧 + +1259 +00:49:37,494 --> 00:49:39,194 +And even all the way down at the bottom here, okay? +甚至一路下来都是,对吧 + +1260 +00:49:39,196 --> 00:49:41,463 +There's one of our apps that has setting. +这里有我们应用之一的设置 + +1261 +00:49:41,465 --> 00:49:42,981 +Trax? +Trax + +1262 +00:49:42,982 --> 00:49:44,498 +I don't have, remember doing a settings for Trax. +我没有印象对 Trax 做过设置 + +1263 +00:49:44,501 --> 00:49:47,735 +But that's because Trax used photos library, +但是那个因为 Trax 使用了相片的 library + +1264 +00:49:47,737 --> 00:49:49,203 +used the Camera, etc. +使用照相机等 + +1265 +00:49:49,205 --> 00:49:51,088 +And so +然后 + +1266 +00:49:51,089 --> 00:49:52,972 +it has some settings that were automatically built into it. +它有一些设置自动建立这些 + +1267 +00:49:52,975 --> 00:49:54,758 +Okay? +对吧 + +1268 +00:49:54,759 --> 00:49:56,542 +But what we're gonna do today is add settings, +但是我们将做什么今天去添加设置 + +1269 +00:49:56,545 --> 00:50:00,080 +specific to our app that would have, you know, some setting, +我们应用里特殊的设置,你知道的,一些设置 + +1270 +00:50:00,082 --> 00:50:03,049 +that's just only our app has that setting. +那个只是我们应用有这个设置 + +1271 +00:50:03,051 --> 00:50:05,584 +How do we put the UI in this +我们怎样放这个用户界面到这里 + +1272 +00:50:05,586 --> 00:50:07,653 +general settings app right here? +常规设置应用这里 + +1273 +00:50:07,655 --> 00:50:09,822 +Okay? +好的 + +1274 +00:50:09,823 --> 00:50:11,990 +So in the slide here you can see some examples of some app +在 slide 这里,你可以看到一些应用设置的例子 + +1275 +00:50:11,992 --> 00:50:17,061 +settings, Maps and Safari have lots of settings, et cetera. +地图还有 Safari 有很多设置等 + +1276 +00:50:17,063 --> 00:50:19,864 +You're gonna build this UI using something like +你也可以建立这个用户界面通过 + +1277 +00:50:19,866 --> 00:50:20,764 +Info.plist. +Info.plist 文件 + +1278 +00:50:20,766 --> 00:50:22,165 +okay? [LAUGH] So +好的 + +1279 +00:50:22,167 --> 00:50:25,001 +it's not exactly gonna build this in your storyboard. +不正是在你的 storyboard 上面搭建 + +1280 +00:50:25,003 --> 00:50:26,936 +Okay? Very restricted, +好的,非常多的限制 + +1281 +00:50:26,938 --> 00:50:30,673 +can only do a few things but you can +可以做到一些东西但是你可以 + +1282 +00:50:30,675 --> 00:50:33,876 +build surprisingly a lot of stuff here with switches and +建立惊人地很多东西,这些东西关于开关 + +1283 +00:50:33,878 --> 00:50:35,711 +sliders and text fields. +滑动还有文本输入框 + +1284 +00:50:35,713 --> 00:50:39,580 +But anything that's set in this UI is communicated +但是所有的设置这个用户界面的通过 NSUserDefaults + +1285 +00:50:39,582 --> 00:50:42,483 +to your app via NSUserDefaults. +去与你的应用交流 + +1286 +00:50:42,485 --> 00:50:44,335 +Okay? So +好的 + +1287 +00:50:44,336 --> 00:50:46,186 +basically, this UI in the settings app is just setting +基本地,设置的用户界面只是设置 + +1288 +00:50:46,188 --> 00:50:48,121 +NSUserDefault in your app. +你应用的 NSUserDefault + +1289 +00:50:48,123 --> 00:50:48,922 +That's what it's doing. +这就是它运作的机理 + +1290 +00:50:50,091 --> 00:50:51,124 +Okay? +好的 + +1291 +00:50:51,125 --> 00:50:52,158 +So let's look to see how it works. +让我们看看它怎么工作 + +1292 +00:50:52,160 --> 00:50:56,428 +You add a little settings bundle to your app. +你添加一些 Settings bundle 到你的应用里 + +1293 +00:50:56,430 --> 00:50:58,930 +That's how you get it to display some UI. +你怎样得到它然后显示在用户界面上 + +1294 +00:50:58,932 --> 00:51:00,698 +And you do that by saying New File and +你做这些通过新文件还有 + +1295 +00:51:00,700 --> 00:51:03,034 +you go to this place here, iOS, Resource, and +你到这个地方,iOS,资源还有 + +1296 +00:51:03,036 --> 00:51:05,836 +inside there you'll see, Settings Bundle. +在这里,你将看到,Settings Bundle + +1297 +00:51:05,838 --> 00:51:08,038 +'Kay? You pick Settings Bundle and +好的,你打开 Settings Bundle + +1298 +00:51:08,040 --> 00:51:10,173 +you're gonna get a sample Settings Bundle. +你将得到一个简单的 Settings Bundle + +1299 +00:51:10,175 --> 00:51:11,541 +This is the best thing, for +这是最好的东西,对于 + +1300 +00:51:11,543 --> 00:51:14,043 +something that's barely supported it seems like, +有些东西,它勉强可以支持 + +1301 +00:51:14,045 --> 00:51:15,878 +in some ways, this was the best thing they did. +在一些方式里,这是它做的最好的东西 + +1302 +00:51:15,880 --> 00:51:17,979 +Is they just gave you a sample one, okay? +它只是给你一个例子,对吧 + +1303 +00:51:17,981 --> 00:51:22,750 +And the sample one, at least as of this lecture, that they +然后这个例子,至少在这个课程里,他们 + +1304 +00:51:22,752 --> 00:51:26,320 +give you has a little grouping there with the text field. +给了你一些组包含文本域的 + +1305 +00:51:26,322 --> 00:51:28,722 +A little switch, and a slider. +一个开关,还有滑动器 + +1306 +00:51:28,724 --> 00:51:32,693 +And if you open up the, inside the settings bundle +如果你打开它,进入到 settings bundle + +1307 +00:51:32,695 --> 00:51:35,628 +there's this little file in there called, root.plist, +这里有个文件叫做 root.plist, + +1308 +00:51:35,630 --> 00:51:37,363 +as you'll see. +你看到的 + +1309 +00:51:37,365 --> 00:51:40,866 +And it's just a bunch of property list and +这是一系列属性列表 + +1310 +00:51:40,868 --> 00:51:43,268 +that's describing what's in there. +描述那里有什么的 + +1311 +00:51:43,270 --> 00:51:46,938 +So, let's look at this thing on the right, the UI, and +让我们看一下右边这些东西,用户界面 + +1312 +00:51:46,940 --> 00:51:48,273 +what's corresponding on the left. +左边所对应的东西 + +1313 +00:51:48,275 --> 00:51:51,542 +So look at on the left where it says Item 0 Group +看一下左边这里,它上面写着 + +1314 +00:51:51,544 --> 00:51:52,510 +at the top. +Item 0 Group + +1315 +00:51:52,512 --> 00:51:54,511 +See that's making that little group. +看这是什么创建这些组的 + +1316 +00:51:54,513 --> 00:51:56,179 +The gray group thing. +灰色的组 + +1317 +00:51:56,181 --> 00:51:58,281 +It's just basically a static table view. +它只是基本的静态表格视图 + +1318 +00:51:58,283 --> 00:52:02,284 +And, that is basically causing a static table view +这是基本的要创建的静态表视图 + +1319 +00:52:02,286 --> 00:52:03,719 +section to be created. +部分 + +1320 +00:52:03,721 --> 00:52:05,053 +And, that's the title of it, Group. +这里有个标题 + +1321 +00:52:05,055 --> 00:52:07,455 +And then, see item 1, Text field, name? +然后看这个条目 1,文本域,名称 + +1322 +00:52:07,457 --> 00:52:08,589 +That's got +这个得到 + +1323 +00:52:08,591 --> 00:52:10,524 +things that describe what that text field is. +这个关于文本域是什么的东西 + +1324 +00:52:10,526 --> 00:52:14,128 +It's not just the title of the text field, which is name. +它不只是文本域的标题,它还是名称 + +1325 +00:52:14,130 --> 00:52:17,130 +But it's also things like, what's the default value, and +但是它也有东西像这样,默认值 + +1326 +00:52:17,132 --> 00:52:20,400 +what kind of keyboard should I bring up, a URL keyboard, or, +我会打开的哪种键盘,URL 键盘或者 + +1327 +00:52:20,402 --> 00:52:23,536 +you know, just a normal alphabetic keyboard, +你知道的,只是一个普通的字母键盘 + +1328 +00:52:23,538 --> 00:52:25,438 +or whatever. +或者其他 + +1329 +00:52:25,439 --> 00:52:27,339 +Then you see item two, toggle switch, all right? +然后你看看这个 item 2,开关,对吧 + +1330 +00:52:27,342 --> 00:52:28,674 +It's got the toggle switch there. +这里有个开关 + +1331 +00:52:28,676 --> 00:52:30,809 +Item three, is the slider, you've got the slider. +item 3 是一个滑动器,你会得到这个滑动器 + +1332 +00:52:30,811 --> 00:52:32,210 +Slider very limited. +滑动范围非常有限 + +1333 +00:52:32,212 --> 00:52:34,545 +You can specify an image on the left, and +你可以滑动到左边 + +1334 +00:52:34,547 --> 00:52:35,880 +an image on the right. +也可以滑动到右边 + +1335 +00:52:35,882 --> 00:52:37,448 +Okay? That's the only thing you +好的,这只是一种 + +1336 +00:52:37,450 --> 00:52:39,516 +can kind of customize about the slider. +你可以自定义的滑动器 + +1337 +00:52:39,518 --> 00:52:40,617 +So if you add a minimum, +如果你添加最小值 + +1338 +00:52:40,619 --> 00:52:43,086 +maximum value you have to do it with images. +最大值 + +1339 +00:52:43,088 --> 00:52:44,120 +It is localizable. +当然它是本地化的 + +1340 +00:52:44,122 --> 00:52:45,821 +I'll talk about that in a second. +我马上会讲这一个 + +1341 +00:52:47,024 --> 00:52:50,492 +And if you lookin all of them see number one, two and three, +如果你查看所有的数字1,2,3 + +1342 +00:52:50,494 --> 00:52:52,460 +they have a line there, identifier. +它们有一条线,标识符 + +1343 +00:52:52,462 --> 00:52:54,995 +You see in item one it's called name preference. +你看在 item 1 这里,它叫做 Name Preference + +1344 +00:52:54,997 --> 00:52:57,965 +In item two it's called Enable Preference +在 item 2, 它叫做 Enabled Preference + + +1345 +00:52:57,967 --> 00:53:00,067 +in line three is called Slider Preference. +在 item 3,它叫做 Slider Preference + +1346 +00:53:00,069 --> 00:53:03,336 +That is the name of the NSUserDefault +这是 NSUserDefault 的名称 + +1347 +00:53:03,338 --> 00:53:05,371 +that this is going to be set to, okay? +这个将要被设置,对吧 + +1348 +00:53:05,373 --> 00:53:07,740 +So every time that slider moves it's going to update +每次滑动器移动,它就会更新 + +1349 +00:53:07,742 --> 00:53:10,743 +the slider under bar preference NSUserDefault in +应用里在 bar preference 下面的这个滑动器 + +1350 +00:53:10,745 --> 00:53:13,211 +this app, okay? +对吧 + +1351 +00:53:13,213 --> 00:53:17,348 +So, pretty straight forward and simple actually. +简单粗暴 + +1352 +00:53:17,350 --> 00:53:20,884 +Localization is a pain in the neck for settings. +本地化对设置来说是个难题 + +1353 +00:53:20,886 --> 00:53:21,852 +Okay? Because +对吧,因为 + +1354 +00:53:21,854 --> 00:53:24,688 +the X lift stuff doesn't work with it. +X lift 这个东西不能很好的工作 + +1355 +00:53:24,690 --> 00:53:26,356 +You have to do it all manually. +你不得不手动去做这个事 + +1356 +00:53:26,358 --> 00:53:30,159 +You essentially create these directories inside the setting +你需要在 setting bunlde 里创建三个目录 + +1357 +00:53:30,161 --> 00:53:35,797 +bundle called a two letter code for the language, .lproj. +叫做面向语言的两个字母代码 .lproj 文件 + +1358 +00:53:35,799 --> 00:53:39,434 +And inside there you're gonna put a strings file for +在这里面你将放字符串文件 + +1359 +00:53:39,436 --> 00:53:42,770 +each page of your settings UI. +到每一个你的设置界面里 + +1360 +00:53:42,772 --> 00:53:45,373 +Now in the previous one, we just saw one page. +在预览这里,我们只是看到一个页面 + +1361 +00:53:45,375 --> 00:53:47,708 +But it's actually possible to click and +但是事实上它可能去点击 + +1362 +00:53:47,710 --> 00:53:50,277 +transition into another page of settings, okay? +去翻译设置的其他页面,对吧 + +1363 +00:53:50,279 --> 00:53:51,611 +You see this in a lot of settings. +你可以看到这个在很多设置里面 + +1364 +00:53:51,613 --> 00:53:53,746 +That's where they're kind of going down multiple levels. +那个多层级的 + +1365 +00:53:53,748 --> 00:53:55,198 +So you can do that. +你可以看到这样 + +1366 +00:53:55,199 --> 00:53:56,649 +And so for every level you've gotta have a strings file. +对于每一个层级,你可以看到一个字符串文件 + +1367 +00:53:56,651 --> 00:53:58,817 +The strings file looks like this. +这个字符串文件看起来像这样 + +1368 +00:53:58,819 --> 00:54:01,119 +And you have to send these off to your translator and +你应该发送这些到你的 translator 那里 + +1369 +00:54:01,121 --> 00:54:02,921 +they have to translate them as well, +他们也会翻译好它 + +1370 +00:54:02,923 --> 00:54:04,422 +in addition to the x-lifts. +添加一个 x-lifts 文件 + +1371 +00:54:04,424 --> 00:54:06,524 +So this is a pain. +只是一个难题 + +1372 +00:54:06,526 --> 00:54:08,292 +I'm sure Apple eventually will +我确定 Apple 最终会 + +1373 +00:54:08,294 --> 00:54:09,659 +integrate into the x-lifts system. +集成到 x-lifts 系统里去 + +1374 +00:54:09,661 --> 00:54:13,029 +However, it's a little bit showing you that settings is +然而,显示给你们看的设置 + +1375 +00:54:13,031 --> 00:54:15,531 +not a primary user interface for your app. +并不是你们应用的主要用户界面 + +1376 +00:54:15,533 --> 00:54:17,433 +You really wanna use it sparingly. +你真的应当谨慎使用 + +1377 +00:54:17,435 --> 00:54:20,069 +You don't want people to have to go to Settings unless +你不想别人使用设置除非 + +1378 +00:54:20,071 --> 00:54:23,071 +you know, there's setting something that's really gonna +你知道,有些设置只设置 + +1379 +00:54:23,073 --> 00:54:25,173 +be set once and maybe never changed again. +一次,可能再也不会改变 + +1380 +00:54:25,175 --> 00:54:26,507 +Okay? +好的 + +1381 +00:54:26,509 --> 00:54:28,576 +Or, something that they set and then, +有些东西被设置了 + +1382 +00:54:28,578 --> 00:54:31,378 +it only changes in the future because something big happens. +在未来它只会改变因为发生什么大件事 + +1383 +00:54:31,380 --> 00:54:34,915 +Like, in mail, you set your accounts up once. +就像你的邮件,你设置帐号一次 + +1384 +00:54:34,917 --> 00:54:36,550 +And they only change if you decide +它们只有当你不想 + +1385 +00:54:36,551 --> 00:54:38,184 +not to use that email account or you change your password. +使用这个帐号或者你改变密码的时候需要设置 + +1386 +00:54:38,186 --> 00:54:39,552 +Maybe you have to go back in there. +可能你还会回到这 + +1387 +00:54:39,554 --> 00:54:40,553 +That makes sense for +这样对于不是 + +1388 +00:54:40,554 --> 00:54:41,553 +that to not be in the main user interface. +主要的用户界面才有意义 + +1389 +00:54:41,556 --> 00:54:44,156 +It may be off in settings. +它在设置之外 + +1390 +00:54:44,158 --> 00:54:46,025 +Okay? +对吧 + +1391 +00:54:46,026 --> 00:54:47,893 +But you do not want to have the normal use of your app +但是你不想正常使用你的应用 + +1392 +00:54:47,895 --> 00:54:50,795 +require them to be going to settings all of the time. +都需要去设置什么 + +1393 +00:54:50,797 --> 00:54:51,963 +Okay? If you have a setting that +对吧,如果你设置 + +1394 +00:54:51,965 --> 00:54:54,165 +people are setting +别人也会不断设置 + +1395 +00:54:54,166 --> 00:54:56,366 +constantly you should have UI in your normal app for it. +那你就应该在正常使用应用状态下配置好它 + +1396 +00:54:56,369 --> 00:54:57,801 +'Kay? +对吧 + +1397 +00:54:57,803 --> 00:55:00,437 +This is just UI that you want to kind of get out of the way +这只是用户界面你想要从你的 + +1398 +00:55:00,439 --> 00:55:03,673 +of your main UI because people aren't going there very much. +主要用户界面里剥离开,因为别人不想经常去配置它 + +1399 +00:55:04,742 --> 00:55:05,607 +All right? So that's what +对吧,这就是 + +1400 +00:55:05,609 --> 00:55:06,742 +setting's about. +设置 + +1401 +00:55:06,744 --> 00:55:08,643 +So I'm going to do a demo with settings, +我将给你演示这个设置 + +1402 +00:55:08,645 --> 00:55:11,579 +but since I won't come back to the slides, +回到 slides 之前 + +1403 +00:55:11,581 --> 00:55:13,347 +let's talk about what's coming up here. +让我们讲一下它怎么发生 + +1404 +00:55:13,349 --> 00:55:15,949 +Wednesday is the alternate final as you know +周三是 alternate final,你们知道的 + +1405 +00:55:15,951 --> 00:55:18,452 +I need your slides today if you want to present at +如果你们想要 alternate final 演示 + +1406 +00:55:18,454 --> 00:55:20,020 +that alternate final. +今天你们要给我 slides + +1407 +00:55:20,022 --> 00:55:25,024 +No section on Friday but your final project is due 11:59 and +周五没课,你们的 final project 的期限是 11:59:59 + +1408 +00:55:25,026 --> 00:55:27,426 +59 seconds on Friday night. +周五晚 + +1409 +00:55:27,428 --> 00:55:28,293 +Okay? Pacific time. +好的,美国西部标准时间 + +1410 +00:55:29,329 --> 00:55:32,330 +Saturday your slides are due by midnight. +周六半夜是你们 slides 的期限 + +1411 +00:55:32,332 --> 00:55:33,297 +Okay? +好的 + +1412 +00:55:33,299 --> 00:55:34,765 +Please make your slides 1280 by 720. +请确保你们的 slides 是 1280x720 的 + +1413 +00:55:34,767 --> 00:55:36,166 +Okay? +对吧 + +1414 +00:55:36,168 --> 00:55:37,867 +In other words widescreen format. +换句话说宽屏格式 + +1415 +00:55:37,869 --> 00:55:43,105 +Do not give me those 1024 by 768s or 640 [LAUGH] by 480. +不要给我 1024x768 或者 640x480 + +1416 +00:55:43,107 --> 00:55:44,390 +Okay? +对吧 + +1417 +00:55:44,391 --> 00:55:45,674 +Widescreen just like this, like you see right here +宽度就是这样,就像你们看的的这个 + +1418 +00:55:45,676 --> 00:55:48,643 +because it can be projected right here just like this. +因为它在这的投影刚好 + +1419 +00:55:48,645 --> 00:55:49,210 +Okay? +好的 + +1420 +00:55:49,212 --> 00:55:50,411 +I prefer Keynote. +我用 Keynote + +1421 +00:55:50,413 --> 00:55:53,481 +If you can do Keynote, please do Keynote because +如果你们用 Keynote,那就用 Keynote 因为 + +1422 +00:55:53,483 --> 00:55:56,283 +what you see in Keynote is what I'm gonna get, and +你在 Keynote 所做的 + +1423 +00:55:56,285 --> 00:55:58,685 +what everyone's gonna get when I put it on screen. +这里就怎么显示 + +1424 +00:55:58,687 --> 00:55:59,919 +If you send me a PowerPoint, +如果你发给我 PowerPoint + +1425 +00:55:59,921 --> 00:56:02,255 +Keynote is really good at opening up PowerPoints, but +Keynote 可以很好兼容 PowerPoint + +1426 +00:56:02,257 --> 00:56:03,689 +if you have a weird font in there, +但是有可能会有怪异的字体问题 + +1427 +00:56:03,691 --> 00:56:05,858 +it might get turned into Helvetica or something. +它可能会变成 Helvetica 或其他字体 + +1428 +00:56:05,860 --> 00:56:07,726 +And then it's gonna looks like a mess. +然后看起来有点混乱 + +1429 +00:56:07,728 --> 00:56:09,039 +Okay? +好的 + +1430 +00:56:09,040 --> 00:56:10,351 +So if you can do Keynote, please do, +如果你用 Keynote,好好使用 + +1431 +00:56:10,352 --> 00:56:11,663 +I understand not everyone has a Mac with Keynote. +我理解并不是每一个人的 Mac 都有 Keynote + +1432 +00:56:11,665 --> 00:56:12,830 +Totally understandable. +完全理解 + +1433 +00:56:12,832 --> 00:56:15,866 +So PowerPoint I will accept. +因此 PowerPoint 我也接受 + +1434 +00:56:15,868 --> 00:56:18,335 +But please, if you can do Keynote. +但是,如果可以请用 Keynote + +1435 +00:56:18,337 --> 00:56:20,971 +And then, next week normal exam period. +然后下一周是正常的考试期间 + +1436 +00:56:20,973 --> 00:56:24,874 +I believe it's Thursday of finals week, 12:15 to 3:15. +最后一周的周四 12:15 到 3:15 + +1437 +00:56:24,876 --> 00:56:27,110 +If that's, anyone correct me if I'm wrong, but +如果这样,如果我错了,大家记得纠正我 + +1438 +00:56:27,112 --> 00:56:27,977 +I think that's when it is. +应该没有错吧 + +1439 +00:56:28,946 --> 00:56:30,879 +Then we will do the presentations. +我们那天做展示 + +1440 +00:56:30,881 --> 00:56:32,731 +There's so many of you, +你们这么多人 + +1441 +00:56:32,732 --> 00:56:34,582 +this is the largest enrollment we've ever had, so +这是历年以来最多上这个课的人 + +1442 +00:56:34,584 --> 00:56:36,751 +you'll only get 90 seconds each. +所以你们每个人有 90 秒 + +1443 +00:56:36,753 --> 00:56:39,253 +I know that sounds tight. +我知道这听起来时间很紧 + +1444 +00:56:39,255 --> 00:56:41,155 +If we have a lot of people going Wednesday, +如果我们周三有很多人 + +1445 +00:56:41,157 --> 00:56:43,790 +maybe I'll try and give you an extra ten seconds or +我可以试着给你们额外的 10 秒或者 + +1446 +00:56:43,792 --> 00:56:45,025 +something like that. +什么 + +1447 +00:56:45,027 --> 00:56:47,226 +But if you just do the math, a hundred people, +如果你们都一起上,100多号人 + +1448 +00:56:47,228 --> 00:56:50,596 +three hours, especially with the time to transition, +三个小时,还有交换时间 + +1449 +00:56:50,598 --> 00:56:53,499 +walk up and down and technical problems. +走路和技术问题 + +1450 +00:56:53,501 --> 00:56:55,800 +We really can't give you more than that, unfortunately. +不幸的是我们不能给你们那么多时间 + +1451 +00:56:57,837 --> 00:56:59,337 +Any questions before I do this last demo? +有没有问题 + +1452 +00:56:59,339 --> 00:57:02,006 +And then we'll be done for today. +今天我们就要结束了 + +1453 +00:57:02,008 --> 00:57:03,240 +Okay. +好的 + +1454 +00:57:03,242 --> 00:57:05,408 +So, the way I'm gonna do the Settings bundle, +这是去到我们 Settings bundle 的方式 + +1455 +00:57:05,410 --> 00:57:08,378 +is I'm gonna add a setting to Bouncer. +我需要设置一个 Bouncer + +1456 +00:57:08,380 --> 00:57:09,512 +Remember Bouncer? +记得 Bouncer 吗 + +1457 +00:57:09,514 --> 00:57:12,114 +Thing bouncing, the square, bouncing around? +Thing bouncing,正方形的,活跃的 + +1458 +00:57:12,116 --> 00:57:13,448 +I'm going to make it so +我将要做那个 + +1459 +00:57:13,450 --> 00:57:18,519 +that bouncer, we can set its elasticity in settings. +bouncer,我们可以把它放在设置里 + +1460 +00:57:18,521 --> 00:57:20,021 +Now, elasticity, +现在,灵活性 + +1461 +00:57:20,022 --> 00:57:21,522 +you're probably going to be setting a lot in Bouncer. +你可能会被设置很多在 Bouncer 这里 + +1462 +00:57:21,524 --> 00:57:24,792 +You want to set it to the way you like Bouncer to happen and +你想要设置为你希望的方式 + +1463 +00:57:24,794 --> 00:57:25,859 +you're just going to leave it. +你只要离开它 + +1464 +00:57:25,861 --> 00:57:26,660 +Okay? So +对吧 + +1465 +00:57:26,661 --> 00:57:27,460 +that's what we're going to do. +我们要怎么做 + +1466 +00:57:27,462 --> 00:57:29,328 +So let's go back to Bouncer. +让我们回到 Bouncer + +1467 +00:57:29,330 --> 00:57:30,830 +Here's Bouncer. +这是 Bouncer + +1468 +00:57:30,832 --> 00:57:32,431 +That's where we left it off last time. +这是我们上次留下的 + +1469 +00:57:32,433 --> 00:57:34,499 +I'm gonna run Bouncer here just so +我将运行这个 Bouncer + +1470 +00:57:34,501 --> 00:57:39,203 +that we can remind ourselves what it looks like. +来看看它是什么样 + +1471 +00:57:40,840 --> 00:57:41,972 +All right. So Bouncer, +好的,Bouncer + +1472 +00:57:41,974 --> 00:57:43,707 +remember this thing just bounces off the walls. +记住这个东西只是在墙里的 Bounce + +1473 +00:57:43,709 --> 00:57:46,376 +And it's pretty bouncy. +它是相当有弹性的 + +1474 +00:57:46,378 --> 00:57:47,910 +It's not super bouncy. +这是不是超级有弹性 + +1475 +00:57:47,912 --> 00:57:52,081 +But if I take it up to the top and I just let it fall down. +如果我想要它到顶部,我只要让它掉下来 + +1476 +00:57:52,083 --> 00:57:55,417 +You know, it bounces about half way back up, okay? +你知道的,bounce 大约有一半退减,对吧 + +1477 +00:57:55,419 --> 00:57:57,118 +Slowly bouncing less and less. +跳的越来越慢 + +1478 +00:57:57,120 --> 00:58:00,154 +And that's because we set the elasticity in Bouncer +这是因为我们设置的 + +1479 +00:58:00,156 --> 00:58:02,089 +over here to be 0.85. +弹性在这里是 0.85 + + +1480 +00:58:02,091 --> 00:58:04,458 +So it's not full bouncing, okay? +这不是满弹性,对吧 + +1481 +00:58:04,460 --> 00:58:07,294 +It's 85% bouncing. +85% 的弹性 + +1482 +00:58:07,296 --> 00:58:09,195 +So it's losing energy with each collision, +所以它每次碰撞都减小能量 + +1483 +00:58:09,197 --> 00:58:10,863 +but not too bad. +这没什么不好 + +1484 +00:58:10,865 --> 00:58:13,632 +So this is the thing that we're going to have +这就是我们在这里的 + +1485 +00:58:13,634 --> 00:58:15,184 +set in settings. +设置 + +1486 +00:58:15,185 --> 00:58:16,735 +Instead of being point 85 all the time we're going to set it +替换为 85%,我们要把它设置在 + +1487 +00:58:16,737 --> 00:58:17,302 +in settings. +这个设置里 + +1488 +00:58:18,438 --> 00:58:21,072 +So let's just add a settings bundle to our app. +让我们添加一个 settings bundle + +1489 +00:58:21,074 --> 00:58:24,508 +So we go new file, we go iOS resource, +一个新文件,iOS 资源 + +1490 +00:58:24,510 --> 00:58:25,909 +here's settings bundle right here. +这里是 settings bundle + +1491 +00:58:26,879 --> 00:58:29,145 +Just double click, what do you want to call it? +只是双击,你要怎么称呼它 + +1492 +00:58:29,147 --> 00:58:30,413 +We'll call it settings, +我们叫它设置 + +1493 +00:58:30,415 --> 00:58:33,249 +that what people usually call their settings bundles. +通常人们称它为 settings bundles + +1494 +00:58:33,251 --> 00:58:35,351 +And here it is, our settings bundle right here. +这就是,我们的 settings bundle + +1495 +00:58:35,353 --> 00:58:36,618 +If you click on the bundle itself, +如果你在 bundle 里点击 + +1496 +00:58:36,620 --> 00:58:39,187 +you just get this little lego brick. +你刚刚只是得到这个小小的乐高砖 + +1497 +00:58:39,189 --> 00:58:43,358 +But if you go down here to root.plist, you will see +如果你到这个 root.plist 文件这里,你会看到 + +1498 +00:58:43,360 --> 00:58:47,661 +here is that default one I was showing you in the slide, +这里的默认设置,我在 slide 会给你们展示的 + +1499 +00:58:47,663 --> 00:58:50,030 +that it gives you. +这里直接就有 + +1500 +00:58:50,031 --> 00:58:52,398 +And here is the strings that go along with this plist. +这里就是这个 plist 文件的字符 + +1501 +00:58:52,401 --> 00:58:54,934 +This is what you would send off to your localizer right +这是你将要发送给你的 localizer + +1502 +00:58:54,936 --> 00:58:57,603 +here for this particular plist file. +特殊 plist 文件 + +1503 +00:58:57,605 --> 00:59:03,375 +So we're gonna Run just to see this UI, which has got +我们将要运行它,看这个用户界面 + +1504 +00:59:03,377 --> 00:59:07,712 +a group with a text field and a toggle switch and a slider. +一组文本框还有一个开关和滑动器 + +1505 +00:59:07,714 --> 00:59:10,181 +We're gonna see that in our Settings app. +我们来看我们的设置应用 + +1506 +00:59:10,183 --> 00:59:12,383 +So let's just Run. +让它运行 + +1507 +00:59:12,384 --> 00:59:14,584 +Now, every time you Run, it installs the Settings +现在每一次你运行它,它安装这个 Settings bundle + +1508 +00:59:14,587 --> 00:59:18,689 +bundle into your system. +到你的系统里 + +1509 +00:59:18,691 --> 00:59:20,591 +So here we go. +看下一个 + +1510 +00:59:20,592 --> 00:59:22,492 +We have this thing, it's 0.85, so let's go over to settings. +我们有这个东西,它是 0.85,让我们回到设置 + +1511 +00:59:24,095 --> 00:59:26,495 +Actually, let's make our slide a little easier here, +事实上,让我们的 slide 简单一点 + +1512 +00:59:26,497 --> 00:59:27,529 +a little less swapping around. +少互相交换 + +1513 +00:59:27,531 --> 00:59:29,031 +Let's put Bouncer on this page. +放这个 bouncer 到这个页面 + +1514 +00:59:29,033 --> 00:59:32,300 +Okay? So let's go to settings and +去到设置上 + +1515 +00:59:32,302 --> 00:59:34,602 +now, when we go down to settings, see we got Bouncer. +现在,当我们回到设置这里,看我们的 Bouncer + +1516 +00:59:34,604 --> 00:59:36,037 +Okay, it added things for bouncer and +好的,它为 bouncer 添加了什么 + +1517 +00:59:36,039 --> 00:59:37,438 +if we click on Bouncer. +如果我们点击 bouncer + +1518 +00:59:37,440 --> 00:59:38,405 +There it is. +像这样 + +1519 +00:59:38,407 --> 00:59:40,507 +That name field right here. +在这个文本输入框这里 + +1520 +00:59:40,509 --> 00:59:42,241 +And Enabled in this slider. +激活这个滑动器 + +1521 +00:59:43,611 --> 00:59:45,678 +Okay? So that's a good start. +这是很好的开始 + +1522 +00:59:45,680 --> 00:59:49,114 +Now, let's change this UI right here to be what we want, +让我们改变这个用户界面,让它变成我们想要的样子 + +1523 +00:59:49,116 --> 00:59:51,983 +which is we just really want a slider for elasticity. +我们只是想这个滑动器对应弹性 + +1524 +00:59:51,985 --> 00:59:55,153 +I'm going to keep this group at the top, but instead of +我将把这一组放在顶部 + +1525 +00:59:55,155 --> 00:59:58,122 +calling it group, I'm going to call it Elasticity. +把这个组的名称替换为弹性 + +1526 +00:59:59,191 --> 01:00:01,458 +Elasticity, okay? +弹性,好的 + +1527 +01:00:01,460 --> 01:00:03,326 +And I don't need a text field. +我不想要这个文本框 + +1528 +01:00:03,328 --> 01:00:04,527 +We're not typing a text field. +我们不用输入到文本框里 + +1529 +01:00:04,529 --> 01:00:06,328 +So you can delete things by just hitting +你们可以删除这个东西通过 + +1530 +01:00:06,330 --> 01:00:07,596 +Backspace to delete. +点击 Backspace 这个键 + +1531 +01:00:07,598 --> 01:00:08,897 +Same thing, toggle switch. +同理,开关 + +1532 +01:00:08,899 --> 01:00:10,365 +Delete, I don't want that. +删掉,我不想要这个 + +1533 +01:00:10,367 --> 01:00:11,999 +But I do want the slider. +但是我想要这个滑动器 + +1534 +01:00:12,001 --> 01:00:14,668 +I'm gonna have the default value be the 0.85 +我想要这个默认值是 0.85 + +1535 +01:00:14,670 --> 01:00:16,803 +that we have now. +我们所知道的 + +1536 +01:00:16,805 --> 01:00:19,639 +Let's say the maximum is about 1.1. +让我们写这个最大值 1.1 + +1537 +01:00:19,641 --> 01:00:21,541 +If we start getting to more than 1.1, +如果我们超过 1.1 + +1538 +01:00:21,543 --> 01:00:24,143 +in other words when it bounces off it gains energy, +换句话说,这个 bounce 一直获得能量 + +1539 +01:00:24,145 --> 01:00:27,279 +that thing is going to be ripping around so fast. +它会越来越快 + +1540 +01:00:27,281 --> 01:00:29,514 +So that's the maximum we want to allow. +所以这是我们想要的最大值 + +1541 +01:00:29,516 --> 01:00:31,583 +The minimum, we don't really want zero, +最小值,我不想是 0 + +1542 +01:00:31,585 --> 01:00:33,551 +that would be just death. +因为那样它直接就死掉了 + +1543 +01:00:33,553 --> 01:00:37,755 +So let's make it like 0.5, which is pretty dampened. +所以让我们设置为 0.5,衰减型 + +1544 +01:00:37,757 --> 01:00:41,291 +But not complete death when it hits something, okay? +它不会一碰到东西就停止 + +1545 +01:00:41,293 --> 01:00:45,561 +And then I don't really like this as my NS user default +我不想这个作为我的 NS 用户默认 + +1546 +01:00:45,563 --> 01:00:48,214 +name. +名称 + +1547 +01:00:48,215 --> 01:00:50,866 +I'm gonna call it, how about BouncerBehavior, since that's +我想要叫它,BouncerBehavior 怎么样 + +1548 +01:00:50,868 --> 01:00:54,603 +the class that we're gonna be setting this in, .Elasticity. +正好把它作为 class 名称,.Elasticity + +1549 +01:00:54,605 --> 01:00:58,240 +Okay? It's kind of decent name. +好的,就这个相当好的名称 + +1550 +01:00:58,242 --> 01:01:01,376 +Okay? Comma name spaced name. +好的,停顿名称空格名称 + +1551 +01:01:01,378 --> 01:01:04,579 +So now, we're gonna get a slider +现在,我们将得到滑动器 + +1552 +01:01:04,581 --> 01:01:06,347 +with elasticity as the name of the group. +它有一个组叫作弹性 + +1553 +01:01:06,349 --> 01:01:07,314 +So let's take a look at that. +让我们看一下这个 + +1554 +01:01:11,787 --> 01:01:12,452 +All right. So we go +好的 + +1555 +01:01:12,454 --> 01:01:13,619 +back here to Settings. +回到设置 + +1556 +01:01:14,789 --> 01:01:15,687 +And we look at Bouncer. +我们看这个 Bouncer + +1557 +01:01:15,689 --> 01:01:16,621 +Here it is. Elasticity. +这里,弹性 + +1558 +01:01:16,623 --> 01:01:17,755 +And we've got this on sliders. +我们会在滑动器得到这个 + +1559 +01:01:17,757 --> 01:01:20,825 +Now as I move this slider, it is changing that +现在我移动这个滑动器,它改变了 + +1560 +01:01:20,827 --> 01:01:24,528 +ns user default from 1.1 all the way down to 0.5. +NS 用户默认值从 0.5 到 1.1 + +1561 +01:01:24,530 --> 01:01:26,496 +Okay? 1.1, 0.5, +好的,1.1,0.5 + +1562 +01:01:26,498 --> 01:01:28,264 +and everywhere in between. +在这之间 + +1563 +01:01:28,266 --> 01:01:29,816 +Okay? +好的 + +1564 +01:01:29,817 --> 01:01:31,367 +Now, it's only setting the NS user default at this point. +这只是设置 NS 用户默认值 + +1565 +01:01:31,369 --> 01:01:33,535 +We're not actually looking at the value. +我们没有真正看它的值 + +1566 +01:01:33,537 --> 01:01:35,637 +So when we go back. +当我回过去 + +1567 +01:01:35,639 --> 01:01:38,540 +Sorry. When we go back here to +抱歉,当我们回到这里 + +1568 +01:01:38,542 --> 01:01:40,742 +Bouncer, it's still bouncing along at 0.85, +Bouncer 这里,它仍然是 0.85 + +1569 +01:01:40,744 --> 01:01:43,778 +no matter what I set that to, okay? +无论我怎么设置这个,对吧 + +1570 +01:01:43,780 --> 01:01:47,247 +So now, we need to look at the NS user default and +好,现在我们需要查看 NS user default + +1571 +01:01:47,249 --> 01:01:49,716 +have it change the elasticity. +还有这个改变的弹性 + +1572 +01:01:49,718 --> 01:01:50,917 +We can do that right here. +我们可以在这里做 + +1573 +01:01:51,920 --> 01:01:53,386 +Nice and wide. +好又宽 + +1574 +01:01:53,388 --> 01:01:54,186 +I set a 0.85. +我设置 0.85 + +1575 +01:01:54,188 --> 01:01:57,639 +I'm gonna say, +我将会写 + +1576 +01:01:57,640 --> 01:02:01,091 +NSUserDefaults.standardUserDe- faults().doubleForKey. + +1577 +01:02:01,094 --> 01:02:02,393 +And, we called it Bouncer. +我们称它为 Bouncer + +1578 +01:02:02,395 --> 01:02:05,663 +I should probably have a nice constant for this, +我应该可能会得到一个不变的值 + +1579 +01:02:05,665 --> 01:02:08,432 +but we'll type it in for speed here. +但是我们要输入它的速率 + +1580 +01:02:09,634 --> 01:02:11,134 +To behavior, that elasticity. +行为,弹性 + +1581 +01:02:11,136 --> 01:02:12,435 +Now, this is a double. +现在,这是双倍的 + +1582 +01:02:12,437 --> 01:02:15,671 +And elasticity here is a CGFloat. +还有弹性这里 CGFloat 类型 + +1583 +01:02:15,673 --> 01:02:18,039 +So we need to put that in CGFloat. +我们需要放这个到 CGFloat + +1584 +01:02:20,543 --> 01:02:21,475 +Okay? +好的 + +1585 +01:02:21,477 --> 01:02:22,643 +And so, that's good. +相当好 + +1586 +01:02:22,645 --> 01:02:24,444 +So let's go ahead and now see what happens. +让我们继续看会发生什么 + +1587 +01:02:29,017 --> 01:02:29,982 +Okay. So +好的 + +1588 +01:02:29,984 --> 01:02:33,152 +it looks like we have low elasticity. +看起来我们有一个很低的弹性 + +1589 +01:02:33,154 --> 01:02:35,420 +See how it's barely bouncing? +看它是咋样的弹性 + +1590 +01:02:35,422 --> 01:02:36,788 +'Kay? +好的 + +1591 +01:02:36,790 --> 01:02:39,190 +And so let's go look and see what our elasticity is set to. +回过头看我们的弹性 + +1592 +01:02:40,226 --> 01:02:42,526 +Bouncer, we have it right in the middle. +Bouncer,我们把它放在中间 + +1593 +01:02:42,528 --> 01:02:44,928 +So let's set it to high elasticity. +让我们设置一个高点的弹性 + +1594 +01:02:44,930 --> 01:02:46,730 +And go back and see if that'll work. +回去看它运作状况 + +1595 +01:02:46,732 --> 01:02:47,530 +So we go up to Bouncer. +看回这个 Bouncer + +1596 +01:02:47,532 --> 01:02:49,965 +And, oh. It's still low. +它仍然很慢 + +1597 +01:02:49,967 --> 01:02:51,533 +Well, what's going on? +怎么回事 + +1598 +01:02:51,535 --> 01:02:53,969 +Okay? Why didn't that pick that up? +为什么没有弹起来 + +1599 +01:02:53,971 --> 01:02:59,607 +That's because we only call this once when our app starts. +这是因为我们只是在应用启动时才启用这个设置 + +1600 +01:02:59,609 --> 01:03:02,610 +So whatever the elasticity was in the settings +所以不管它的弹性设置是什么 + +1601 +01:03:02,612 --> 01:03:05,012 +at the time our app launched, that's what we get. +当我们的应用运行,它就是那个弹性 + +1602 +01:03:05,014 --> 01:03:06,447 +And if the user goes and +如果用户回去 + +1603 +01:03:06,448 --> 01:03:07,881 +changes it, it makes no difference. +改变它,它不会有变化 + +1604 +01:03:07,883 --> 01:03:10,483 +So, how do we make it so that the user can go to settings, +所以,要怎么修改,让用户回到修改设置后 + +1605 +01:03:10,485 --> 01:03:11,751 +change the elasticity and come back. +会生效 + +1606 +01:03:11,753 --> 01:03:14,520 +And it will be different in Bouncer without quitting and +Bouncer 不需要退出 + +1607 +01:03:14,522 --> 01:03:16,588 +restarting Bouncer and all that stuff? +然后重启 + +1608 +01:03:16,590 --> 01:03:20,325 +Well, the answer to that is Notifications. +它需要的是通知 + +1609 +01:03:20,327 --> 01:03:23,595 +There's an NS notification you get every time your NS user +这个 NS 通知,你每次用你的 + +1610 +01:03:23,597 --> 01:03:24,562 +defaults change. +NS user defaults 就会改变 + +1611 +01:03:25,498 --> 01:03:27,131 +Okay? That's pretty cool. +很酷 + +1612 +01:03:27,133 --> 01:03:31,634 +So, let's go NS Notification Center, Default Center, +输入 NSNotificationCenter.defaultCenter + +1613 +01:03:31,636 --> 01:03:34,537 +add Observer for name. +addObserverForName. + +1614 +01:03:34,539 --> 01:03:38,574 +The name is NSUserDefaultDidChange, +这个叫 NSUserDefaultDidChange 的方法 + +1615 +01:03:38,576 --> 01:03:39,975 +as you might imagine. +你可以想象 + +1616 +01:03:39,977 --> 01:03:41,743 +okay? + +1617 +01:03:41,744 --> 01:03:43,510 +The object is I don't care, anybody can send me that. +这个对象我不关心,每个人都可以发给我那个 + +1618 +01:03:43,513 --> 01:03:46,381 +The queue, we'll just do the main queue, and using +queue,我们就用 main queue + +1619 +01:03:46,383 --> 01:03:49,316 +block this is what's gonna happen when things change. +usingBlock 有些变化 + +1620 +01:03:49,318 --> 01:03:51,485 +And I'm actually going to do our closing, +事实上回到我们的 + +1621 +01:03:51,487 --> 01:03:56,056 +trailing, closure notation here. +之前通知这里 + +1622 +01:03:56,058 --> 01:03:58,391 +So here's the notification, this getting passed to me, +这个 notification,通过这里 + +1623 +01:03:58,393 --> 01:04:01,193 +I actually don't even need to look at that. +我事实上不需要看到这个 + +1624 +01:04:01,195 --> 01:04:02,961 +And inside here I'm just gonna do this. +在这里我只是做这个 + +1625 +01:04:05,399 --> 01:04:07,082 +Okay. +好的 + +1626 +01:04:07,083 --> 01:04:08,766 +So every time my NSUserDefault change, +每次我们的 NSUserDefault 改变 + +1627 +01:04:08,768 --> 01:04:11,568 +I'm just going to update the elasticity. +我就更新这个弹性 + +1628 +01:04:13,706 --> 01:04:14,704 +Okay. + +1629 +01:04:14,706 --> 01:04:16,973 +Now really, to be a good citizen here, +作为一个好公民 + +1630 +01:04:16,975 --> 01:04:19,475 +I should be doing, let observer equals. +我应该这样做,让这个 observer 等于 + +1631 +01:04:19,477 --> 01:04:21,043 +And somewhere else, I should be doing +其他什么的,我写这个 + +1632 +01:04:21,045 --> 01:04:25,080 +NSNotificationDefaultCenter remove observer, this thing. +NSNotificationDefaultCenter 移除 observer 这个东西 + +1633 +01:04:25,082 --> 01:04:28,683 +But the way our app is right now, pretty much Bouncer +但是我们应用现在这个方式, + +1634 +01:04:28,685 --> 01:04:31,386 +comes up, takes over the screen and never leaves. +发生,接管屏幕还有从不离开 + +1635 +01:04:31,388 --> 01:04:33,921 +So it's probably okay to not be doing that here. +所以在这里它可能还没有做好 + +1636 +01:04:33,923 --> 01:04:36,156 +Besides, it's a demo so we're not going to do it. +此外,我们还有一个演示 + +1637 +01:04:36,158 --> 01:04:37,924 +But generally, when you add an observer, +通常来说,当你们添加一个观察器 + +1638 +01:04:37,926 --> 01:04:39,926 +you want to get that observer cookie back and +你想要得到观察器的 cookie + +1639 +01:04:39,928 --> 01:04:41,728 +you want to remove it somewhere sensible. +你想要删除其他敏感信息 + +1640 +01:04:42,964 --> 01:04:44,363 +All right? So let's see if this works. +好的,让我们看看它怎么工作 + +1641 +01:04:46,666 --> 01:04:48,683 +Okay? Now, +好的现在 + +1642 +01:04:48,684 --> 01:04:50,701 +last time we changed the elasticity to 1.1, I think. +最后一次我们改变这个弹性为 1.1 + +1643 +01:04:50,704 --> 01:04:52,070 +Right. See? So look, +看 + +1644 +01:04:52,071 --> 01:04:53,437 +this guy's gonna go pretty wild, okay? +这家伙看起来有点野 + +1645 +01:04:53,439 --> 01:04:55,839 +He's gaining speed with every bounce. +它每次碰撞都获得新的速度 + +1646 +01:04:55,841 --> 01:04:57,074 +So let's slow him down. +所以,让它慢下来 + +1647 +01:04:57,076 --> 01:04:58,241 +Let's go over into Settings. +让我们回到设置 + +1648 +01:05:00,211 --> 01:05:01,811 +Notice that every time you install it, +注意你安装它的每一次 + +1649 +01:05:01,813 --> 01:05:03,979 +it's gonna install it here. +它会在这里安装 + +1650 +01:05:03,981 --> 01:05:07,449 +So let's change our elasticity from 1.1 down to really slow. +让我们改变这个弹性从 1.1 到实际的慢速度 + +1651 +01:05:08,585 --> 01:05:09,751 +Okay? +好的 + +1652 +01:05:09,752 --> 01:05:10,918 +Now, we can go back to Bouncer and +让我们回到 Bouncer + +1653 +01:05:10,920 --> 01:05:14,287 +the next time Bouncer hits, it slows down, okay? +下一次 Bouncer 碰撞,它减速 + +1654 +01:05:15,223 --> 01:05:16,422 +See that? Almost dead. +看没,快要死了 + +1655 +01:05:17,458 --> 01:05:18,641 +Very little bounce. +非常小的弹力 + +1656 +01:05:18,642 --> 01:05:19,825 +Let's go back and change it again. +让我们回去再改一下 + +1657 +01:05:20,761 --> 01:05:22,460 +Go all the way back up to. +一路回升 + +1658 +01:05:22,462 --> 01:05:23,161 +Whoops. +哇 + +1659 +01:05:23,163 --> 01:05:25,129 +Up to high speed. +最高速度 + +1660 +01:05:27,866 --> 01:05:30,266 +And the next hit gaining energy. +每一次撞击都获得能量 + +1661 +01:05:30,268 --> 01:05:31,568 +Oh, yeah. +好的 + +1662 +01:05:31,569 --> 01:05:32,869 +Gaining more and more speed with every bounce. +获得越来越快的速度 + +1663 +01:05:32,871 --> 01:05:34,203 +Okay? +好的 + +1664 +01:05:34,205 --> 01:05:36,605 +There we go. +接下来 + +1665 +01:05:36,607 --> 01:05:39,074 +I don't even need to look. +我甚至都不需要看 + +1666 +01:05:39,076 --> 01:05:41,326 +Okay. +好的 + +1667 +01:05:41,327 --> 01:05:43,577 +[LAUGH] And it just bounced off and just disappeared. +它一直反弹然后消失了 + +1668 +01:05:43,580 --> 01:05:45,513 +Went into some ether. +来看一些其他的 + +1669 +01:05:45,515 --> 01:05:47,748 +Okay. [SOUND] That is it. +好的,就是这个 + +1670 +01:05:47,750 --> 01:05:51,251 +I finished early for once today, so thank you all for +我今天提早结束了,非常感谢 + +1671 +01:05:51,253 --> 01:05:52,252 +coming. +你们的到来 + +1672 +01:05:52,254 --> 01:05:53,886 +And I'll be here if you have any questions. +我会在这如果你们有什么问题 + +1673 +01:05:55,256 --> 01:05:55,287 +>> For more, please visit us at stanford.edu + diff --git a/subtitles/2. More Xcode and Swift, MVC.srt b/subtitles/2. More Xcode and Swift, MVC.srt new file mode 100644 index 0000000..33df710 --- /dev/null +++ b/subtitles/2. More Xcode and Swift, MVC.srt @@ -0,0 +1,8425 @@ +1 +00:00:00,001 --> 00:00:04,636 +欢迎收看斯坦福大学公开课 + +2 +00:00:04,638 --> 00:00:08,373 +Stanford University. +本字幕由志愿者义务贡献 + +3 +00:00:08,375 --> 00:00:11,942 +>> All right, well,welcome to Stanford CS193P, +欢迎参加斯坦福大学 2015 年 + +4 +00:00:11,944 --> 00:00:13,377 +winter of 2015. +冬季学期的 CS193P 课程 + +5 +00:00:13,379 --> 00:00:14,744 +This is lecture number two. +这是我们的第二讲 + +6 +00:00:14,746 --> 00:00:18,581 +I apologize upfront for my terrible voice, we are going +由于我糟糕的嗓音,预先向大家致歉 + +7 +00:00:18,583 --> 00:00:20,549 +to try to get through this as best we can today. +我们要尽可能去克服这个困难 + +8 +00:00:22,153 --> 00:00:23,819 +Our topics are two fold. +我们的话题有两个方面 + +9 +00:00:23,821 --> 00:00:25,854 +We're going to continue the calculator +我们将继续在上一讲中已经开始的计算器 Demo, + +10 +00:00:25,856 --> 00:00:29,924 +demo that we started, in last lecture and then we're gonna +然后我们将会有 + +11 +00:00:29,926 --> 00:00:32,526 +have some slides about this model view controller, +一些关于 model view controller, + +12 +00:00:32,528 --> 00:00:35,462 +object-oriented design pattern that we're gonna use in +和面向对象设计模式的课件 + +13 +00:00:35,464 --> 00:00:36,797 +everything we do. +这些设计模式我们将要广泛的使用 + +14 +00:00:36,799 --> 00:00:40,066 +When we build applications in this class. +当我们在这节课中开发应用时 + +15 +00:00:40,068 --> 00:00:41,151 +All right? +有问题么? + +16 +00:00:41,152 --> 00:00:42,235 +So let's get started with that demo. +没问题就让我开始演示 Demo + +17 +00:00:42,237 --> 00:00:44,136 +Again, here's a slide with the summary of kind of +这里是一张总结 + +18 +00:00:44,138 --> 00:00:46,538 +the important things we're gonna talk about. +接下去我们即将要讲的重点的幻灯片 + +19 +00:00:46,540 --> 00:00:48,540 +You don't need to read those in advance here, +你们并不需要提前去阅读这些 + +20 +00:00:48,542 --> 00:00:49,708 +it's more for reference. +它更多地是为了提供参考的 + +21 +00:00:49,710 --> 00:00:52,410 +My slides in general, I post them, +我做的课件一般来讲, + +22 +00:00:52,412 --> 00:00:55,246 +it's mostly intended to almost be note taking for you. +主要是为了方便你们记笔记用 + +23 +00:00:55,248 --> 00:00:56,580 +To be able go back and try and +为了你们在复习的时候能够 + +24 +00:00:56,582 --> 00:00:58,515 +figure out, whoa, when did he talked about that day? +回忆出,我什么时候讲过这些? + +25 +00:00:58,517 --> 00:00:59,382 +Oh yeah. + +26 +00:00:59,384 --> 00:01:00,983 +What's important, et cetera. +什么是重要的,等等 + +27 +00:01:00,985 --> 00:01:03,419 +So my slides do tend to be a little bit dense. +所以,我的幻灯片也往往是有点多 + +28 +00:01:03,421 --> 00:01:05,187 +I tend to put a little more on them, than, +我更倾向于在上面多放一些内容, + +29 +00:01:05,189 --> 00:01:06,989 +than just bullet items. +而不是一项一项往上列 + +30 +00:01:06,990 --> 00:01:08,790 +But that's because I want you to be able to look back and +但是,那是因为我希望你们能够回过头来看的时候 + +31 +00:01:08,792 --> 00:01:11,726 +kind of get just a little bit more depth to +对于我所说的 + +32 +00:01:11,728 --> 00:01:14,162 +remind yourself what I talked about. +你们会有更深入的理解 + +33 +00:01:14,164 --> 00:01:15,363 +Okay? + +34 +00:01:15,365 --> 00:01:17,882 +All right, so +好了, + +35 +00:01:17,883 --> 00:01:20,400 +this demo, if you'll remember last time, where we left off, +关于这个 Demo,如果你们还记得上次我们快结束时, + +36 +00:01:20,403 --> 00:01:23,603 +we had gotten the keypad fully working. +我们已经完全实现了计算器的键盘的功能 + +37 +00:01:23,605 --> 00:01:26,606 +All right, and we were talking a little bit about properties +我们将要讲一些关于 properties 和 + +38 +00:01:26,608 --> 00:01:28,808 +and instant variables and how we had to initialize them. +实例变量相关的内容,以及如何去初始化它们 + +39 +00:01:28,810 --> 00:01:30,710 +And so I'm gonna ask a question right at +我将要回答上次课快要结束时 + +40 +00:01:30,712 --> 00:01:33,012 +the end of lecture, perfect timing. +提出的那个问题 + +41 +00:01:33,014 --> 00:01:37,248 +What about the little outlet that we dragged out +为什么我们拖出的 + +42 +00:01:37,250 --> 00:01:40,284 +that display UI label exclamation point, how come we +显示 UILabel 的 outlet 后面有个感叹号 + +43 +00:01:40,286 --> 00:01:43,888 +didn't have to make that equal to something, to start. +以及为什么我们从一开始不需要将它赋值 + +44 +00:01:43,890 --> 00:01:46,123 +And that's where this demo is gonna pick up. +我们将从这个地方继续上次的 Demo + +45 +00:01:46,125 --> 00:01:46,890 +Okay? + +46 +00:01:46,892 --> 00:01:49,759 +Okay. + +47 +00:01:49,760 --> 00:01:52,627 +Well, let's dive back into this demonstration, +好吧,让我们深入到演示中来, + +48 +00:01:52,630 --> 00:01:54,647 +where we left off. +接着我们上次讲的地方 + +49 +00:01:54,648 --> 00:01:56,665 +Which it was this line of code, here. +上次我们在这行代码结束的 + +50 +00:01:56,668 --> 00:01:59,868 +And, we had just talked about the fact that we have to +我们之前讲过我们必须 + +51 +00:01:59,870 --> 00:02:04,572 +initialize all of our variables in a class, +在类中初始化我们的变量 + +52 +00:02:04,574 --> 00:02:05,807 +in any class. +在任何类中都必须这样做 + +53 +00:02:05,809 --> 00:02:09,510 +And, so that's why we need this equals falls here. +所以我们需要在这加个等号 + +54 +00:02:09,512 --> 00:02:13,747 +They wanted the equal falls too but we needed it and yet +这里也需要等号赋值,但是 + +55 +00:02:13,749 --> 00:02:15,482 +it didn't seem like we needed one here. +这里看起来并不需要等号赋值 + +56 +00:02:15,484 --> 00:02:17,050 +And why was that? +为什么会是这样? + +57 +00:02:17,052 --> 00:02:19,085 +Well, it turns out that this right here, +其实,这里恰恰证明了 + +58 +00:02:19,087 --> 00:02:22,254 +even though it doesn't quite look like one, is an optional. +即使它看起来不完全像之前那个,这是一个 optional + +59 +00:02:23,490 --> 00:02:28,559 +And, optionals automatically get equaled nil, given to you. +而且 optional 在你使用之前就赋了 nil + +60 +00:02:29,595 --> 00:02:31,862 +So, you don't actually have to put the equals nil here. +所以,其实你们并不需要在这里给它赋 nil + +61 +00:02:31,864 --> 00:02:35,365 +So that's why, so this one here is getting initialized. +这就是为什么这里已经初始化了 + +62 +00:02:35,367 --> 00:02:37,600 +It's just being done automatically for you. +因为它都自动帮你做好了 + +63 +00:02:37,602 --> 00:02:39,635 +But, let's talk about the look of this thing. +但是,我们来谈论一下这个东西的语法 + +64 +00:02:40,905 --> 00:02:43,772 +It's got this exclamation point here. +在这里有个感叹号 + +65 +00:02:43,774 --> 00:02:45,040 +And, if it were an optional, +如果它是一个 optional 类型的值 + +66 +00:02:45,042 --> 00:02:47,208 +you'd be used to it having a question mark. +你们通常会在这里看到一个问号 + +67 +00:02:47,210 --> 00:02:49,310 +For example, we look at this optional right here, +例如,我们来看这里这个 optional 的值 + +68 +00:02:49,312 --> 00:02:51,028 +current title, +currentTitle, + +69 +00:02:51,029 --> 00:02:52,745 +you see it's String question mark not exclamation point, +你们将会看到这里 String 是问号而不是感叹号, + +70 +00:02:52,748 --> 00:02:54,665 +question mark. +这里是问号 + +71 +00:02:54,666 --> 00:02:56,583 +So what's the difference between a question mark and +那么,这里的问号和感叹号之间 + +72 +00:02:56,585 --> 00:02:58,551 +an exclamation point here? +有什么区别呢? + +73 +00:02:58,553 --> 00:03:00,570 +And the answer is, +答案是 + +74 +00:03:00,571 --> 00:03:02,588 +it makes no difference to the actual type, it's still +对于实际类型而言它们没有区别, + +75 +00:03:02,590 --> 00:03:05,958 +an optional whose value here could be a UI label. +它仍然是一个 optional 的值,其值在这里可能是一个 UILabel 类型 + +76 +00:03:07,161 --> 00:03:09,761 +But it matters on the usage of it. +但是它们在用法上是不一样的 + +77 +00:03:09,763 --> 00:03:12,597 +And this is purely just kind of +这完全是编译器 + +78 +00:03:12,599 --> 00:03:15,466 +a compiler helping you out thing, here. +帮你把这事做好了 + +79 +00:03:16,502 --> 00:03:18,602 +But if we look at when I change this to +但是如果我们将这个感叹号改成问号 + +80 +00:03:18,604 --> 00:03:21,538 +a question mark you see that some errors appear down here. +Xcode 将会在这里报出一些错误提示 + +81 +00:03:21,540 --> 00:03:23,940 +So then let's click on one of these errors, like this one, +那么,让我们点击这其中的一个错误提示,比如说这个 + +82 +00:03:23,942 --> 00:03:26,208 +and you can see the errors that UI label, +你们会看到这个错误提示说 UILabel? + +83 +00:03:26,210 --> 00:03:29,244 +question mark does not have a member named text. +没有一个叫 text 的成员变量 + +84 +00:03:29,246 --> 00:03:31,279 +In other words you can't send text. +就是说,你不能向它发送 text 消息 + +85 +00:03:31,281 --> 00:03:32,580 +UI label question mark, +UILabel? 顾名思义 + +86 +00:03:32,582 --> 00:03:35,350 +which is what this is and that makes sense because UI label +是一个不确定值的变量,所以也就明白了 UILabel? 是 + +87 +00:03:35,352 --> 00:03:36,784 +question mark is an optional and +optional 的类型 + +88 +00:03:36,786 --> 00:03:39,453 +obviously an optional doesn't respond to text. +并且显而易见的,一个 optional 类型的变量不会响应 text 消息 + +89 +00:03:39,455 --> 00:03:42,889 +UI labels do, but optionals don't. +UILabel 是这样的,但 optional 并不会这样 + +90 +00:03:42,891 --> 00:03:44,858 +So, why are we getting this error now when we +那么回到问题,为什么之前不会报错 + +91 +00:03:44,860 --> 00:03:46,726 +weren't getting it before. +而现在却出错了呢 + +92 +00:03:46,728 --> 00:03:47,993 +And how would we get rid of this error? +我们又如何去避免这个错误呢? + +93 +00:03:47,995 --> 00:03:49,461 +Well, you could certainly get rid of +嗯,我们当然可以通过 + +94 +00:03:49,463 --> 00:03:51,630 +this error by just putting an exclamation point here, +添加一个感叹号来避免这个错误 + +95 +00:03:51,632 --> 00:03:54,399 +that would unwrap this optional. +它会对这个 optional 的变量进行解包 + +96 +00:03:54,401 --> 00:03:56,734 +And now this would be an UI label right here and +那么现在这里刚好有一个 UILabel + +97 +00:03:56,736 --> 00:03:57,819 +we can send a text. +如果我们要想给它发送 text 消息 + +98 +00:03:57,820 --> 00:03:58,903 +And we do the same thing up here. +就可以在这里也做同样的事情 + +99 +00:03:58,905 --> 00:04:03,073 +We can unwrap it there and we can unwrap it there. +我们可以在这里对它进行解包,还有这里也要解包 + +100 +00:04:03,075 --> 00:04:05,742 +And that gets rid of all of our errors. +这样就解决了所有的错误 + +101 +00:04:05,744 --> 00:04:09,012 +But this kind of an interesting property in that +但是这里有个很有意思的属性 display + +102 +00:04:09,014 --> 00:04:11,213 +even though it's not initialized in +因为它并没有在 + +103 +00:04:11,215 --> 00:04:14,450 +the very beginning of a class creation starts out +类最开始创建时初始化成 nil + +104 +00:04:14,452 --> 00:04:16,451 +as nil not set. +而是没有设值 + +105 +00:04:16,453 --> 00:04:21,723 +As soon as as this user interface gets loaded up +一旦这个 UI 界面 + +106 +00:04:21,725 --> 00:04:23,891 +by this new controller. +被右边的视图控制器加载了 + +107 +00:04:23,893 --> 00:04:26,794 +Then this gets wired up, alright, so, that gets +那么它就会和代码连接起来,嗯对,只要连接起来 + +108 +00:04:26,796 --> 00:04:30,497 +wired up, and this is set, and then this it's set forever. +这个变量就会被设置并初始化,那么它在整个类中就是永远初始化过了 + +109 +00:04:30,499 --> 00:04:33,199 +So it's really, kinda would be sad if we actually, +但是,如果当我们每次解包时都要写感叹号 + +110 +00:04:33,201 --> 00:04:36,536 +every time we used it had to unwrap it all the time. +那真是一件难过的事儿 + +111 +00:04:36,538 --> 00:04:38,437 +So these kind of properties that. +所以这些很早前就被设置过属性变量 + +112 +00:04:38,439 --> 00:04:42,674 +Get set very early, maybe not right at creation like +不一定要和这个一样,在创建时初始化 + +113 +00:04:42,676 --> 00:04:44,976 +this one, but very, they get set very early, and +并且,它们设置的时间非常非常的早 + +114 +00:04:44,978 --> 00:04:46,511 +then they stay set all the time. +之后一直保持着已设置的状态 + +115 +00:04:47,447 --> 00:04:49,030 +You can, instead of +你也可以 + +116 +00:04:49,031 --> 00:04:50,614 +putting a question mark in their decoration. +在声明的地方用一个问号来代替 + +117 +00:04:50,616 --> 00:04:52,683 +We're talking about their decoration here. +我们将在这里谈论他们的声明 + +118 +00:04:52,685 --> 00:04:54,317 +You can put an exclamation point. +你可以在这里加一个感叹号 + +119 +00:04:54,319 --> 00:04:56,586 +And what that says is. +那么它要表达的意思是 + +120 +00:04:56,588 --> 00:04:58,521 +This is just an optional, but +这虽然只是一个 optional 类型 + +121 +00:04:58,523 --> 00:05:03,625 +always automatically unwrap it so that you don't have to +但它会自动对变量解包,从而就可以不用 + +122 +00:05:03,627 --> 00:05:06,261 +put this exclamation point in here. +在这里加感叹号 + +123 +00:05:06,263 --> 00:05:07,695 +So I take this exclamation point out. +所以,我把这里的感叹号删掉了 + +124 +00:05:07,697 --> 00:05:09,764 +You can see, it's not generating any errors. +你们可以看到,它将不再报错 + +125 +00:05:10,933 --> 00:05:15,735 +And it's still going to unwrap this display and +它将把 display 转化成 + +126 +00:05:15,737 --> 00:05:17,670 +turn into a UI label. +UILabel + +127 +00:05:17,672 --> 00:05:18,838 +And. +而且 + +128 +00:05:18,840 --> 00:05:21,006 +It's still gonna crash your program if for +它还是会由于 + +129 +00:05:21,008 --> 00:05:22,307 +some reason the display were nil. +某些原因比如 display 是 nil 崩溃 + +130 +00:05:22,309 --> 00:05:25,110 +If you tried to execute this code, that may +如果你执意要执行这段代码,那是 + +131 +00:05:25,112 --> 00:05:28,146 +be impossible because this is the button sending those. +不可能的,因为这里是由按钮来发送这些的 + +132 +00:05:28,148 --> 00:05:31,716 +So the button wouldn't be here if this hadn't gotten already +这个按钮不会在这里除非它被加载 + +133 +00:05:31,718 --> 00:05:33,818 +loaded up in the set. +被赋值的时候 + +134 +00:05:33,819 --> 00:05:35,919 +But if somehow you had some place in your controller or +但是如果在某种情况下你必须 + +135 +00:05:35,921 --> 00:05:39,589 +you were accessing display before this UI got loaded. +在 UI 加载之前你要获取 display + +136 +00:05:39,591 --> 00:05:42,158 +It would crash, because it is unwrapping this, +它将崩溃,因为它还没有 unwrap + +137 +00:05:42,160 --> 00:05:44,327 +it's just that you don't have to put the explanation point, +你不需要在这里写感叹号 + +138 +00:05:44,329 --> 00:05:46,629 +it's kinda like auto explanation point. +它会自动解析 + +139 +00:05:46,631 --> 00:05:51,066 +And, this is called a implicitly unwrapped optional. +这个就叫做 unwrapped optional + +140 +00:05:51,068 --> 00:05:53,968 +Okay? Implicitly unwrapped optional. +有问题嘛?隐式 unwrapped optional + +141 +00:05:53,970 --> 00:05:56,704 +And it's really only useful for this kind, of property, +在这种情况下它对这类 property 来说有用 + +142 +00:05:56,706 --> 00:06:00,274 +that's, set very early, and then stay set, forever. +在创建的时候就赋值,那么将一直被赋值 + +143 +00:06:00,276 --> 00:06:02,642 +It's kind of sugar, really. +这是一种语法糖 + +144 +00:06:04,379 --> 00:06:07,246 +Okay, so let's move on +好了,我们将继续 + +145 +00:06:07,248 --> 00:06:11,117 +to the next button in our here. +接着下一个按钮 + +146 +00:06:11,119 --> 00:06:13,285 +Which is going to be an enter button. +它就是 Enter 键 + +147 +00:06:13,287 --> 00:06:16,655 +Now our calculator does not have an equals sign. +现在我们的计算器还没有等号 + +148 +00:06:16,657 --> 00:06:18,223 +So you're probably used to calculators where you +你们也许通常会这样使用计算器 + +149 +00:06:18,225 --> 00:06:21,726 +say six plus three then when you hit equals it shows you +6 乘以 3,然后你们按等号计算器展示 + +150 +00:06:21,728 --> 00:06:23,027 +the result. +结果 + +151 +00:06:23,029 --> 00:06:24,912 +This calculator is +我们的计算器会 + +152 +00:06:24,913 --> 00:06:26,796 +a little more like a scientific calculator. +更像科学计算器 + +153 +00:06:26,799 --> 00:06:27,564 +Has an enter key. +将没有等号按钮 + +154 +00:06:27,566 --> 00:06:31,668 +And so, instead you put the numbers you want to add or +那么,你们按你们想相加的数字按钮或者 + +155 +00:06:31,670 --> 00:06:35,671 +divide or multiply or whatever onto a stack and then when you +除以或者乘以无论什么都将会入栈,然后当你 + +156 +00:06:35,673 --> 00:06:38,440 +press the operation keys it pulls them off the stack. +按下操作按钮的时候,数字将会出栈 + +157 +00:06:38,442 --> 00:06:43,011 +So that looks like this, 6 enter 3 times. +比如这样 6 3 乘 + +158 +00:06:43,013 --> 00:06:45,279 +Four, six, enter, three, enter, times. +4 6 enter 3 enter 乘 + +159 +00:06:45,281 --> 00:06:48,449 +So the times is going to pull the six and +这个乘法操作符将会把 6 和 + +160 +00:06:48,451 --> 00:06:50,735 +the three off the stack. +3 出栈 + +161 +00:06:50,736 --> 00:06:53,020 +You could even go six, enter, five, enter, four, enter, and +你也可以按 6,enter,5,enter,4, enter,然后 + +162 +00:06:53,022 --> 00:06:54,521 +then go times plus. +按乘以 加 + +163 +00:06:55,590 --> 00:06:58,624 +That would multiply the top two on the stack and +它将会把栈顶的两个元素出栈 + +164 +00:06:58,626 --> 00:07:00,893 +then add the last one on. +操作完再将加上栈顶的元素 + +165 +00:07:01,829 --> 00:07:04,629 +So we need an enter key here for our calculator. +所以我们的计算器还是需要一个 Enter 键 + +166 +00:07:04,631 --> 00:07:06,798 +Now, I'm gonna create that enter key in a way that's +现在,我将要通过这种方式创建一个 enter 键 + +167 +00:07:06,800 --> 00:07:09,367 +actually gonna cause a problem for me in a moment, but +它虽然会引起一些问题,但是 + +168 +00:07:09,369 --> 00:07:12,370 +I wanna show you how to resolve that very problem. +我将会展示给你们看如何解决这些问题 + +169 +00:07:12,372 --> 00:07:16,039 +So I'm gonna create this enter key by copying and pasting. +那么,我将通过复制粘贴 + +170 +00:07:16,041 --> 00:07:18,608 +This digit key right here. +这里的数字键来创建 Enter 键 + +171 +00:07:18,610 --> 00:07:19,475 +And I'm just gonna put it in here. +那么我将会把这放在这里 + +172 +00:07:19,477 --> 00:07:20,743 +Notice that I'm lining these, +我通过这些蓝色辅助线 + +173 +00:07:22,113 --> 00:07:23,745 +blue lines up absolutely perfectly. +把这些连接起来 + +174 +00:07:23,747 --> 00:07:27,315 +I don't want them to be, like it's lined up with that one, +我不想这按钮放这 + +175 +00:07:27,317 --> 00:07:28,750 +but not that one or vice versa. +或者放这里 + +176 +00:07:28,752 --> 00:07:30,685 +I want them perfectly lined up. +我希望它完全对齐 + +177 +00:07:30,687 --> 00:07:33,520 +Cuz later I'm gonna spread these out over the whole UI +因为我待会要在整个 UI 中放大这些按钮 + +178 +00:07:33,522 --> 00:07:37,057 +and if I haven't lined these up just absolutely perfectly +如果我没有将这些按钮对齐的话 + +179 +00:07:37,059 --> 00:07:39,693 +then Expo's not gonna quite know what I want here in Xcode +我将不会知道它们会被 + +180 +00:07:39,695 --> 00:07:41,828 +terms of the relationship between these. +Xcode 安排到哪里 + +181 +00:07:43,264 --> 00:07:46,999 +All right so we don't want a three on here, we want to have +好了,我们不希望这个按钮上还是 3,所以我们需要修改一下 + +182 +00:07:47,001 --> 00:07:52,237 +a,enter symbol so I'm gonna go up here to special characters. +一个 enter 的符号,我将输入一个特殊的符号 + +183 +00:07:52,239 --> 00:07:54,505 +This is on in most Mac applications. +这个符号在很多的 Mac 应用中都有 + +184 +00:07:54,507 --> 00:07:57,174 +You can go to the edit menu to get special characters. +你们可以从编辑菜单中获取这些特殊符号 + +185 +00:07:57,176 --> 00:07:58,342 +And I'm going to search for +我想要搜索 + +186 +00:07:58,344 --> 00:08:00,510 +this one actually, I think that's called a return. +这个特殊符号,我觉得它应该叫 return + +187 +00:08:00,512 --> 00:08:01,945 +Yeah. And these are just +是的,这些都是 + +188 +00:08:01,947 --> 00:08:04,614 +Unicode characters right here. +Unicode 字符 + +189 +00:08:04,616 --> 00:08:06,615 +And so I want this one that looks, +我想要这个 + +190 +00:08:06,617 --> 00:08:09,551 +kind of like a return or enter key. +看起来像返回或者 enter 按钮的 + +191 +00:08:10,487 --> 00:08:11,686 +So I have this. +好了,我找到了 + +192 +00:08:11,688 --> 00:08:13,721 +And I'm gonna use the same mechanism we used before, +我将使用之前使用过的机制 + +193 +00:08:13,723 --> 00:08:14,822 +which is CTRL+drag. +那就是 CTRL+drag + +194 +00:08:14,824 --> 00:08:18,958 +So I'm just gonna CTRL+drag out here. +那么我想 CTRL+drag 拖到这里 + +195 +00:08:18,960 --> 00:08:21,027 +And, we're creating an action, +然后,我们创建一个 action + +196 +00:08:21,029 --> 00:08:24,196 +of course, cuz we want this button to send us a message. +当然,我们希望这个按钮给我们发个消息 + +197 +00:08:24,198 --> 00:08:25,431 +I'm gonna call it"enter". +我将叫它 “enter” + +198 +00:08:26,700 --> 00:08:28,333 +That's what it is the enter key +那就是我们的返回键. + +199 +00:08:28,335 --> 00:08:30,134 +Now one thing is different about this one, +现在有一件事会有一点不同 + +200 +00:08:30,136 --> 00:08:32,470 +if you'll remember when we wired this action up, +如果你记得当我们连接这个 action 的时候 + +201 +00:08:32,472 --> 00:08:35,906 +we had the button that was sending it as an argument and +我们让这个按钮传递给我们一个参数 + +202 +00:08:35,908 --> 00:08:37,441 +we don't want that this time. +但是我们这次不需要这么做 + +203 +00:08:37,443 --> 00:08:38,808 +Because there's only one answer key we +因为这里只有一个返回键 + +204 +00:08:38,810 --> 00:08:40,977 +really don't need to talk back to the answer key, so +我们并不需要让返回键传参,所以 + +205 +00:08:40,979 --> 00:08:42,712 +we're going to say none right here. +我们在这里不需要参数 + +206 +00:08:42,714 --> 00:08:45,714 +It also doesn't really matter about this type because we're +这里我们更不用关心它的类型,因为 + +207 +00:08:45,716 --> 00:08:46,948 +not going to have an argument so +我们这里并不需要参数 + +208 +00:08:46,950 --> 00:08:48,750 +it doesn't matter what this type is. +不用管它这里是什么类型 + +209 +00:08:48,752 --> 00:08:49,717 +So connect that. +所以把它们连接 + +210 +00:08:49,719 --> 00:08:51,686 +As you can see right here. +你们可以看这里 + +211 +00:08:51,688 --> 00:08:54,154 +We have enter, and it has no arguments. +我们已经有一个 enter 键,没有参数的 + +212 +00:08:55,691 --> 00:08:57,690 +Now, what are we gonna do inside enter? +那么现在,我们将在这个 enter 里做什么操作? + +213 +00:08:57,692 --> 00:08:59,558 +Well, the main thing we need to do is, +好吧,我们主要要做的是 + +214 +00:08:59,560 --> 00:09:03,228 +put whatever number is in this display up here, +把 display 显示的数字 + +215 +00:09:03,230 --> 00:09:05,697 +okay, onto our internal stack. +放入我们的栈中 + +216 +00:09:05,699 --> 00:09:06,931 +So, we're gonna need +那么,我们需要 + +217 +00:09:06,933 --> 00:09:09,367 +an internal stack, in a moment, here. +一个栈 + +218 +00:09:09,369 --> 00:09:10,868 +Another thing we might wanna do, is. +另一件我们想做的事 + +219 +00:09:11,904 --> 00:09:14,604 +Set usersInTheMiddleOfTypeingANumber to false. +设置 usersInTheMiddleOfTypeingANumber 为 false + +220 +00:09:14,606 --> 00:09:17,507 +Because we might have been typing a number, but +因为我们可能已经输入了一个数字 + +221 +00:09:17,509 --> 00:09:20,343 +as soon as we hit enter, we're putting it on the stack. +但是,只要我们单击 enter 键,我们将把数字放入栈中 + +222 +00:09:20,345 --> 00:09:21,977 +Next time we type a digit, +接下来我们再输入一个数字 + +223 +00:09:21,979 --> 00:09:23,846 +we're going to be starting a new number. +我们将输入一个新的数字 + +224 +00:09:23,848 --> 00:09:27,182 +All right, so we'll call that user in +好了,那么我们 + +225 +00:09:27,184 --> 00:09:29,451 +the middle of typing falls there. +把它设置为 false 就好了 + +226 +00:09:29,453 --> 00:09:32,387 +Now, let's go ahead and, and actually run this and +现在,让我们继续,运行这个 + +227 +00:09:32,389 --> 00:09:33,788 +see how this is working. +看看它是怎么工作的 + +228 +00:09:33,790 --> 00:09:37,991 +Because there's going to be a little problem here. +因为这里有个小问题 + +229 +00:09:37,993 --> 00:09:44,197 +So, run this. +那么,先运行一下 + +230 +00:09:44,199 --> 00:09:47,499 +Alright, so let's try eight, enter. +好了,让我们试一下输入 8,然后回车 + +231 +00:09:47,501 --> 00:09:48,367 +Oh.Oh + +232 +00:09:48,369 --> 00:09:50,001 +What's that? Oh, my god. +那是什么? + +233 +00:09:50,003 --> 00:09:52,337 +Six, enter. +6,然后回车 + +234 +00:09:52,338 --> 00:09:54,672 +Well it's, it's kind of working because after we +好吧,它能运行,但是我们 + +235 +00:09:54,674 --> 00:09:57,241 +press enter the user is in the middle of typing numbers. +所按的回车也一起出现在数字里面了 + +236 +00:09:57,243 --> 00:09:59,160 +Starts over. +重新开始 + +237 +00:09:59,161 --> 00:10:01,078 +So that's good, but I had no intention for +所以这是好的,但是我并不想 + +238 +00:10:01,080 --> 00:10:03,380 +this to be showing up on the end of my display. +让这个在最后显示出来 + +239 +00:10:03,382 --> 00:10:05,115 +This little enter. +这个 enter + +240 +00:10:05,117 --> 00:10:06,749 +What the heck is that doing on there? +到底发生了什么? + +241 +00:10:06,751 --> 00:10:07,783 +Why is that happening? +为什么会发生这样的事 + +242 +00:10:09,086 --> 00:10:09,951 +Let's take a look here. +让我们看看这里 + +243 +00:10:11,988 --> 00:10:15,023 +The problem here, has to do with the messages being sent. +问题出在这里,在发消息之前 + +244 +00:10:15,025 --> 00:10:17,358 +So, when we wire this up, that's good. +那么,当我们连接好了 + +245 +00:10:17,360 --> 00:10:20,161 +We got enter. +我们已经有 enter 键了 + +246 +00:10:20,162 --> 00:10:22,963 +The problem is that button also sends a appendDigit. +问题是那个按钮还传递 appendDigit 消息 + +247 +00:10:22,965 --> 00:10:25,598 +That's because we copied and pasted this three, remember? +那是因为我们复制粘贴的 3 的按钮,记得么? + +248 +00:10:25,600 --> 00:10:28,735 +And the three sends appendDigit, until we copy and +而 3 按钮还传递了 appendDigit,直到我们复制 + +249 +00:10:28,737 --> 00:10:29,903 +paste it. +粘贴了它 + +250 +00:10:29,904 --> 00:10:31,070 +Now, this one sends, sends appendDigit. +现在 ,这个按钮发送了 appendDigit + +251 +00:10:31,072 --> 00:10:32,805 +So this is both. +而且这个也是 + +252 +00:10:32,807 --> 00:10:34,874 +Okay, sending two. +传递了两次 + +253 +00:10:34,875 --> 00:10:36,942 +Now, that's a common mistake to make. +这是一个很常见的错误 + +254 +00:10:36,944 --> 00:10:39,744 +You know, you only think about that when you copy and +你们知道么,你们不会去想这些当你们复制 + +255 +00:10:39,746 --> 00:10:41,145 +paste it. +粘贴它 + +256 +00:10:41,147 --> 00:10:42,947 +And how do we fix this? +那么我们如何来修复这个问题? + +257 +00:10:42,949 --> 00:10:44,348 +Well if you right click, so +好了,如果你们右击一下 + +258 +00:10:44,350 --> 00:10:46,717 +I'm going to right click on this button. +我将右键一下这个按钮 + +259 +00:10:46,719 --> 00:10:48,885 +You'll get this window that comes up. +你们将会看到这个窗口 + +260 +00:10:48,887 --> 00:10:51,687 +And it shows you all the connections from this +然后你们可以看到所有的连接 + +261 +00:10:52,723 --> 00:10:54,189 +UI element to your code. +UI 元素到你们的代码 + +262 +00:10:54,191 --> 00:10:57,025 +And you can see here both appendage and +你们可以看到这里都连接 + +263 +00:10:57,027 --> 00:10:58,826 +enter are connected. +enter 键 + +264 +00:10:58,828 --> 00:11:01,562 +The great thing is I can just click this little X right here +最棒的事我可以点击这里的 X 按钮 + +265 +00:11:01,564 --> 00:11:03,530 +and it'll take this connection away. +然后这个连接就被取消了 + +266 +00:11:04,666 --> 00:11:06,232 +So now I only have enter. +那么,现在我们只有 enter 键的连接了 + +267 +00:11:06,234 --> 00:11:08,101 +So now if I go back here. +那么现在我们再回到之前的地方 + +268 +00:11:08,103 --> 00:11:09,853 +See it's, +看这里 + +269 +00:11:09,854 --> 00:11:11,604 +it's not sending appendDigit, it is sending enter. +它将不再发送 appendDigit,它只发送 enter + +270 +00:11:11,606 --> 00:11:14,440 +And you can do this right clicking for anything. +你们可以右键操作任何你们想做的 + +271 +00:11:14,442 --> 00:11:16,608 +Like we need to do it for our label up here. +就像我们连接 label 一样 + +272 +00:11:16,610 --> 00:11:21,112 +See there's the display connection we have right here. +看到没,这里显示了我们的连接 + +273 +00:11:21,114 --> 00:11:24,448 +So don't forget right click to disconnect things. +不要忘记右键去除连接 + +274 +00:11:24,450 --> 00:11:27,918 +Now if you forget about this and you don't do it. +现在,如果你们忘记这个,你们不要去操作它 + +275 +00:11:27,920 --> 00:11:32,455 +Or maybe you have it wired to some thing that you change. +否则你们会连接一些你们修改的东西 + +276 +00:11:32,457 --> 00:11:35,391 +For example, if we have accidentally put an argument +比如,我们需要传递一个参数 + +277 +00:11:35,393 --> 00:11:40,062 +here to enter, if we had made it do descending button trick, +对于 enter 键来说,如果我们已经做过了 + +278 +00:11:40,064 --> 00:11:42,064 +kind of like this. +像这样的 + +279 +00:11:42,066 --> 00:11:44,432 +You can't just say, oh okay. +你们不能说好的 + +280 +00:11:44,434 --> 00:11:45,066 +I'll fix that. +我将会修复它 + +281 +00:11:45,068 --> 00:11:46,667 +I'll just delete that +我将会删除它的 + +282 +00:11:46,669 --> 00:11:49,136 +Because that would not work because, +因为它将会不工作 + +283 +00:11:49,138 --> 00:11:52,072 +enter with an argument is actually a different +因为带有参数的 enter 键 + +284 +00:11:52,074 --> 00:11:54,774 +message than enter with no argument. +对于没参数的 enter 键来说发送的是不同的消息 + +285 +00:11:54,776 --> 00:11:57,510 +And so, if you just deleted that when you were running +如果你们在运行的时候删除了这些 + +286 +00:11:57,512 --> 00:11:58,978 +your program it would crash and +你的应用将会崩溃 + +287 +00:11:58,980 --> 00:12:02,581 +it would say, couldn't send message enter colon. +它会说,不能发送消息 enter: + +288 +00:12:02,583 --> 00:12:05,150 +When you touch this button cause enter colon means enter +当你点击 enter 键的时候 + +289 +00:12:05,152 --> 00:12:08,853 +with an argument, only for the purpose of this tour It doe-, +enter: 代表有参数,但是代码中看不到 + +290 +00:12:08,855 --> 00:12:10,655 +we don't see enter colon in our code. +enter: 参数 + +291 +00:12:10,657 --> 00:12:12,656 +That's just something that's, this story board here. +这就是 Story board 中发生的一些事 + +292 +00:12:13,793 --> 00:12:17,661 +So if that happens, you need to right click on here and +那么如果这个发生了,你需要点击这里 + +293 +00:12:17,663 --> 00:12:21,431 +disconnect the enter colon, that happened in there and +去除连接,然后再重新 + +294 +00:12:21,433 --> 00:12:23,566 +then you just recontrol drag. +拖拽连接 + +295 +00:12:23,568 --> 00:12:25,834 +When you recontrol drag it's nice it will. +当你重新连接好,它会变正常了 + +296 +00:12:25,836 --> 00:12:28,103 +Kind of let you try to grab onto something, so +这里好像让你抓住什么东西一样 + +297 +00:12:28,105 --> 00:12:32,373 +its easy to reconnect. +它很容易重新连接 + +298 +00:12:32,375 --> 00:12:35,293 +OKay + +299 +00:12:35,294 --> 00:12:38,212 +All right, so now we want to actually implement enter here. +好了,那么现在我们在这里实现这个方法 + +300 +00:12:38,214 --> 00:12:41,248 +We want to enter the guts of it. +我们开始着手实现它的内部 + +301 +00:12:41,250 --> 00:12:44,150 +And so we are going to need another property here which is +我们需要在这定义另一个属性 + +302 +00:12:44,152 --> 00:12:45,702 +going to be that +它将是用 + +303 +00:12:45,703 --> 00:12:47,253 +internal stack that these numbers are going to go on. +一个内部的栈去存储这些数字 + +304 +00:12:47,255 --> 00:12:52,057 +And so that's gonna be a var just like +所以它会是一个变量,就像 + +305 +00:12:52,059 --> 00:12:54,393 +this var up here that we've created and +我们刚创建的这个变量 + +306 +00:12:54,395 --> 00:12:57,562 +I'm call it operand stack that's a good name for it. +我叫它 operandStack,不错的名字 + +307 +00:12:57,564 --> 00:12:58,730 +And it's gonna have a type, +它会有一个类型 + +308 +00:12:58,732 --> 00:13:02,233 +it's type is going to be an array and +它的类型是数组 + +309 +00:13:02,235 --> 00:13:05,869 +just like in other languages like Java when you specify, +就像在其他语言中,比如说 Java + +310 +00:13:05,871 --> 00:13:08,805 +when you create an array type you have to specify. +当你创建一个数组,你必须指明它的类型 + +311 +00:13:08,807 --> 00:13:10,840 +What kind of thing is in the array. +表明数组里面存储的是什么 + +312 +00:13:10,842 --> 00:13:15,211 +And so, I'm gonna put doubles in my array. +因此,我打算在里面存放 double 元素 + +313 +00:13:17,214 --> 00:13:20,782 +And that's, even though you might say, well we can't +嗯 也许你会说,好吧我们并不能 + +314 +00:13:20,784 --> 00:13:25,286 +enter doubles, because these are all integers, basically. +输入 double,因为这里大都是些整数 + +315 +00:13:25,288 --> 00:13:29,723 +But if I were to say, 3 enter 6 divide, I get .5. +但是假如我说,输入 3 除以 6,我会得到 0.5 + +316 +00:13:29,725 --> 00:13:31,925 +So than a double would appear. +这样就出现了一个 double 的结果 + +317 +00:13:31,927 --> 00:13:34,661 +So that's why I'm going to use double. +这就是我为什么要使用 double 的原因 + +318 +00:13:34,663 --> 00:13:38,964 +Now, you can see that we've got this error up here again. +现在,你们可以看到这里又弹出了这个错误 + +319 +00:13:38,966 --> 00:13:41,133 +It says stored property operandStack does not +上面说 “存储的 property operandStack 并没有 + +320 +00:13:41,135 --> 00:13:43,368 +have initial value. +一个初始值” + +321 +00:13:43,370 --> 00:13:45,036 +So we have to give this an initial value. +所以我们得赋给它初始值 + +322 +00:13:45,038 --> 00:13:47,071 +So I'm going to give this an initial value of +我准备把初始值赋为 + +323 +00:13:47,073 --> 00:13:48,472 +an empty array. +一个空的数组 + +324 +00:13:48,474 --> 00:13:51,608 +So now you're seeing for the first time how you actually. +现在你们第一次看到如何 + +325 +00:13:51,610 --> 00:13:57,480 +Create an instance of a class or of a data type. +创建一个类或者数据类型的实例 + +326 +00:13:57,482 --> 00:14:00,249 +And you do that just by specifying the type and +你只需要在这指明类型 + +327 +00:14:00,251 --> 00:14:01,984 +then use parenthesis. +然后加上圆括号 + +328 +00:14:01,986 --> 00:14:03,752 +Now, we're not, +现在,我们没有 + +329 +00:14:03,754 --> 00:14:05,554 +again we haven't talked about initializers. +我们还没有讨论过初始化方法(initializer) + +330 +00:14:05,556 --> 00:14:06,888 +A class or +一个类或者 + +331 +00:14:06,890 --> 00:14:09,390 +a data structure can have multiple initializers. +一种数据类型可以有许多初始化方法 + +332 +00:14:09,392 --> 00:14:11,158 +Some of them might have arguments in here. +其中的一些可能会需要参数 + +333 +00:14:12,128 --> 00:14:16,863 +But most, if it's possible they'll allow you to +但大多数情况,如果允许,你都可以 + +334 +00:14:16,865 --> 00:14:21,133 +create them with no arguments and in a case on +利用没有参数的初始化方法来创建对象 + +335 +00:14:21,135 --> 00:14:22,835 +array,it's very obvious what to do. +对于这里的数组,很明显 + +336 +00:14:22,837 --> 00:14:25,103 +No arguments just creates an empty array right, +不需要参数,只要创建一个空的数组 + +337 +00:14:25,105 --> 00:14:27,739 +with no elements in it. +数组内部不需要任何的元素 + +338 +00:14:27,741 --> 00:14:31,142 +Now, one thing I want to talk about is this right here. +现在,我想说一下这里的这个东西(第一个 Array) + +339 +00:14:31,144 --> 00:14:32,376 +This type, you know? +这个东西,你们知道吗 + +340 +00:14:32,378 --> 00:14:34,078 +It's kind of annoying that we have to type this and +你会觉得很烦,如果在前面定义了类型 + +341 +00:14:34,080 --> 00:14:36,147 +then we have to type it right again. +然后在后面又得定义一遍 + +342 +00:14:36,148 --> 00:14:38,215 +And the answer is, we don't have to do that, +而事实上,我们并不需要这么做 + +343 +00:14:38,217 --> 00:14:41,051 +because in swift, swift is very strongly typed. +因为 Swift 是强类型语言 + +344 +00:14:41,053 --> 00:14:43,252 +You know there's all the variables, but +所有的变量 + +345 +00:14:43,254 --> 00:14:45,221 +the properties are strongly typed. +属性都是强类型的 + +346 +00:14:45,223 --> 00:14:48,724 +But they, there's also a lot of type inference. +而且 Swift 可以做很多的类型推断 + +347 +00:14:48,726 --> 00:14:50,625 +So swift can infer. +类型推断 + +348 +00:14:50,627 --> 00:14:53,995 +This type in the exact same way that digit had no type and +比如说这里的 digit 并没有声明类型 + +349 +00:14:53,997 --> 00:14:55,596 +it inferred it from here. +但它可以从后面的语句中推断出来 + +350 +00:14:55,598 --> 00:14:58,366 +OperandStack, we don't have to specify they type, and +operandStack,我们并不需要指明它的类型,因为 + +351 +00:14:58,368 --> 00:14:59,633 +it can infer it from here. +可以从这里的初始化方法中推断出来 + +352 +00:14:59,635 --> 00:15:02,302 +And if we option click on operandStack you'll see that +如果我们按住 option 点击 operandStack,你会看到 + +353 +00:15:02,304 --> 00:15:05,271 +indeed, it's figured out that that's an array of double. +它确实可以辨识出这是一个 double 类型的数组 + +354 +00:15:05,273 --> 00:15:07,824 +And in fact, +事实上 + +355 +00:15:07,825 --> 00:15:10,376 +putting the type in here is considered bad form. +在这里指明类型被认为是不好的书写形式 + +356 +00:15:10,378 --> 00:15:14,080 +If it can be inferred, you should let it infer, so, +如果可以推断出类型,你就应该让它(编译器)自己去推断,所以 + +357 +00:15:14,082 --> 00:15:16,915 +if we didn't have this bool up here we shouldn't that either, +拿这里的 Bool 来说,我们其实不需要声明类型 + +358 +00:15:16,917 --> 00:15:21,419 +because, false, and true are, can only be bool values so, +因为 false 和 true 只可能是 Bool 类型的 + +359 +00:15:21,421 --> 00:15:22,887 +we're gonna take that off as well. +所以我们也可以把它去掉 + +360 +00:15:22,889 --> 00:15:28,025 +Okay, so, now, our operand +好了,那么现在,我们这里有操作符栈 + +361 +00:15:28,027 --> 00:15:30,994 +stack right here what do we wanna do with it? +我们打算把怎么处理它呢? + +362 +00:15:30,996 --> 00:15:34,597 +Well, when we press enter, we just want to append. +嗯,我们按下回车,然后我们想要 append + +363 +00:15:34,599 --> 00:15:35,798 +So, append. +所以,append + +364 +00:15:35,800 --> 00:15:39,034 +This is actually the first time we're sending an actual +事实上这是我们第一次发送一条 + +365 +00:15:39,036 --> 00:15:41,703 +message to an object looks just like when we +消息给一个对象,但是这种写法就像 + +366 +00:15:41,705 --> 00:15:43,738 +accessed a property. +获取了一个属性一样 + +367 +00:15:43,740 --> 00:15:47,375 +The dot and it's just the name of the method that we're +输入点号,然后就出现了我们想要在这个数组上 + +368 +00:15:47,377 --> 00:15:49,110 +trying to invoke in our arrays. +调用的方法名字 + +369 +00:15:49,112 --> 00:15:51,478 +Just an array, an array method right here called a append. +这是一个叫做 append 的数组方法 + +370 +00:15:51,480 --> 00:15:54,414 +I think you see the arguments as newElement: T. +我想你们看到了这个参数 —— newElement: T + +371 +00:15:54,416 --> 00:15:57,517 +This : T means it has to be of this type. +这个 : T 意味着它必须是这个类型 + +372 +00:15:57,519 --> 00:16:00,853 +Type of things in the array so this has to be a double. +这个数组里面东西的类型,所以它必须是一个 double + +373 +00:16:00,855 --> 00:16:04,223 +So that's kind of a problem, cuz really what I want to +这也是一个问题,因为事实上我想要在 + +374 +00:16:04,225 --> 00:16:08,060 +append onto my stack is what's up here in this display text. +我的栈上附加的是,这里 display.text 的内容 + +375 +00:16:08,062 --> 00:16:11,830 +And, you know, I'd like to say something along the lines +然后在这行输入 + +376 +00:16:11,832 --> 00:16:13,164 +of display.text. +display.text + +377 +00:16:13,166 --> 00:16:15,099 +Okay? But what type is this? +好吧,它的类型是什么呢? + +378 +00:16:15,101 --> 00:16:16,767 +I can type display.text.(type of display.text??) +display.text 的类型 + +379 +00:16:18,437 --> 00:16:19,936 +Now that's not String. +它不是 String + +380 +00:16:19,938 --> 00:16:22,205 +That is an optional. +它是一个 optional String + +381 +00:16:22,207 --> 00:16:24,874 +Remember that display.text is an optional. +记住这里的 display.text 是一个 optional String + +382 +00:16:24,876 --> 00:16:28,043 +So we can unwrap it even though +所以我们可以把它拆包,但 + +383 +00:16:28,045 --> 00:16:29,911 +that's not gonna solve the problem. +这并不能解决问题 + +384 +00:16:29,913 --> 00:16:31,212 +This is still a String and +这仍是一个 String + +385 +00:16:31,214 --> 00:16:33,381 +you're still seeing an error here. +你们还是可以看到这里有一个错误 + +386 +00:16:33,383 --> 00:16:36,217 +This saying 'String' is not convertible to double [COUGH]. +上面写着 “String 不可以转化为 Double” + +387 +00:16:36,219 --> 00:16:37,651 +Because we're supposed to be putting doubles in +因为我们本应把 Double 放入 + +388 +00:16:37,653 --> 00:16:39,086 +this array putting Strings. +这个数组而不是 String + +389 +00:16:39,088 --> 00:16:40,987 +So, we have a problem here. +所以,我们在这有个问题 + +390 +00:16:40,989 --> 00:16:44,323 +We have somehow to convert this String into a double so +我们得用某种方式把 String 转化成 Double 以便 + +391 +00:16:44,325 --> 00:16:45,358 +we can put it on this stack. +我们把它放入栈中 + +392 +00:16:46,394 --> 00:16:48,994 +I'm gonna use this opportunity. +我要借用这个机会, + +393 +00:16:48,996 --> 00:16:51,129 +Just show you another feature which we +向你们展示另一个特性,我们 + +394 +00:16:51,131 --> 00:16:52,930 +call Computed Properties. +称之为计算型属性(Computed Properties) + +395 +00:16:52,932 --> 00:16:56,000 +So I'm gonna create another property display value and +所以我要在这里创建另一个属性 displayValue, + +396 +00:16:56,002 --> 00:16:57,401 +it's gonna be a Double. +它是一个 Double + +397 +00:16:57,403 --> 00:17:00,671 +And what I want this to be equal to is, I always want it +然后我想让它等于,我想让它 + +398 +00:17:00,673 --> 00:17:03,773 +to be whatever's in this display converted to a double. +等于这里的显示转化成 Double 的值 + +399 +00:17:04,742 --> 00:17:05,786 +Okay? And I want to +好了,然后我想 + +400 +00:17:05,787 --> 00:17:06,831 +be able to set it or get it so +有办法对它进行设值以及取值,以便 + +401 +00:17:06,832 --> 00:17:07,876 +I'm gonna be able to get the value of this double. +我能够取到这个 Double 的值 + +402 +00:17:07,878 --> 00:17:10,112 +I just want to be able to set it as a double and +我想把它设值成一个 Double 然后 + +403 +00:17:10,114 --> 00:17:11,413 +have it turn into text. +把它转化成文本 + +404 +00:17:13,016 --> 00:17:15,616 +Well, that kind of +好吧,这种类型的 + +405 +00:17:15,618 --> 00:17:19,886 +property really is tied to some data somewhere else. +属性实际上是与其他地方的某些数据绑定的 + +406 +00:17:19,888 --> 00:17:22,756 +So, I don't ever want to set it equal to some initial value +所以,我不想把它设成某个初始值 + +407 +00:17:22,758 --> 00:17:25,125 +or something. +还是其他的什么 + +408 +00:17:25,126 --> 00:17:27,493 +Really, I want it to always be calculated and we can do that. +我想让它总是由计算得到的,而我们在 Swift 里可以做到 + +409 +00:17:27,495 --> 00:17:29,295 +Instead of saying equals something, +与其输入 “这个变量等于什么什么” + +410 +00:17:29,297 --> 00:17:32,364 +you just put curly braces after. +你只需要在后面输入,花括号 + +411 +00:17:32,366 --> 00:17:37,168 +And you say, get, and we say, set. +然后写下 get ,再写 set + +412 +00:17:37,170 --> 00:17:39,871 +Okay? +就好了 + +413 +00:17:39,872 --> 00:17:42,573 +And inside here we are gonna compute the value of this. +然后在这里面,我们要对它的值进行计算了 + +414 +00:17:42,575 --> 00:17:46,010 +Which is we are gonna convert this display text +这将会把这里的 display.text 转化成 + +415 +00:17:46,012 --> 00:17:49,479 +to a double and then inside here, we are, someone said, +Double,然后在这里,我们要,要让 + +416 +00:17:49,481 --> 00:17:52,449 +display value equal something and we are going to +displayValue 等于什么,我们要做的是 + +417 +00:17:52,451 --> 00:17:55,251 +somehow compute, not really compute it, but. +想办法能够计算它,并不是真正计算某一个特定的值,而是 + +418 +00:17:55,253 --> 00:17:58,854 +We're gonna de, decide, what code we need to put that +我们要决定我们需要什么样的代码能够 + +419 +00:17:58,856 --> 00:18:02,024 +number that they tried to set the display value to in here. +决定 displayValue 在这里被设成什么值 + +420 +00:18:03,126 --> 00:18:05,393 +'Kay, so let's do the set side first. +好吧,那么让我们先来写 set 方法 + +421 +00:18:05,395 --> 00:18:07,695 +It's actually a little simpler. +这其实会简单一些 + +422 +00:18:07,697 --> 00:18:08,929 +Inside this set, +在 set 方法里 + +423 +00:18:08,931 --> 00:18:11,231 +there's a magic variable called new value. +会有一个叫作 newValue 的变量 + +424 +00:18:12,300 --> 00:18:14,901 +It doesn't, it's not purple for some reason, but. +因为某些原因,它的高亮并不是显示为紫色的 + +425 +00:18:14,903 --> 00:18:16,235 +New value in this, this is the new value. +这里的 newValue 就是将要被设置的那个值 + +426 +00:18:16,237 --> 00:18:17,903 +So if someone says somewhere in our code, +如果说某些人在我们的代码里 + +427 +00:18:17,905 --> 00:18:19,338 +display value equals five, +让 displayValue 的值等于 5 + +428 +00:18:19,340 --> 00:18:21,306 +this new value will have the five. +那这个 newValue 就会是 5 + +429 +00:18:22,442 --> 00:18:23,541 +And so all I really wanna do +我所想做的 + +430 +00:18:23,543 --> 00:18:26,276 +here is say display text equals the new value. +就是在这,让 display.text 等于 newValue + +431 +00:18:26,278 --> 00:18:30,480 +But again, of course this is an optional String. +但同样的问题,这是个 optional String + +432 +00:18:30,482 --> 00:18:33,216 +You can't set it to a double because displayValue equals +你不能把它设成一个 Double,因为 displayValue 等于 + +433 +00:18:33,218 --> 00:18:36,419 +five, this new values going to be a double. +5,这个 newValue 将会是一个 Double + +434 +00:18:36,421 --> 00:18:41,557 +But we know how to convert something to a String by +但是我们知道如何把它转化成 String,只需要写上 + +435 +00:18:41,559 --> 00:18:45,260 +using backlash parenthesis. +反斜线,圆括号 + +436 +00:18:45,262 --> 00:18:48,129 +And this is the same thing we did when we +这其实和我们 + +437 +00:18:48,131 --> 00:18:51,399 +printed out [COUGH] our digit up here. +之前输出的 digit 的过程是一样的 + +438 +00:18:51,401 --> 00:18:53,501 +We just use the back slash parenthesis. +我们只需要写上反斜线和圆括号 + +439 +00:18:53,503 --> 00:18:55,336 +It tries to convert this thing inside here, +它会试着在这里转化这个东西 + +440 +00:18:55,338 --> 00:18:57,938 +which is a double into a String of doubles. +把一个 Double 转化成 String + +441 +00:18:57,940 --> 00:19:00,540 +You know how to do that themselves. +你知道该怎么做了 + +442 +00:19:00,542 --> 00:19:02,575 +And so bingo, we've got our display text and +没错 我们有了自己的 display.text + +443 +00:19:02,577 --> 00:19:04,477 +that's all that necessary. +这就够了 + +444 +00:19:04,479 --> 00:19:07,479 +also, every time someone sets this displayValue and then we're +而且,每次有人设 displayValue 的值时 + +445 +00:19:07,481 --> 00:19:10,282 +clearly not in the middle of typing a number anymore. +很明显,我们知道,此时我们不在是在输入数字的状态了 + +446 +00:19:10,284 --> 00:19:14,085 +[INAUDIBLE] Say that. +把这个状态设置成 false + +447 +00:19:14,087 --> 00:19:17,221 +[INAUDIBLE] All right, what about the getting? +好吧,那关于取值呢? + +448 +00:19:17,223 --> 00:19:19,290 +Now in the getting all we have to do is +在取值方法中,我们所要做的就是 + +449 +00:19:19,292 --> 00:19:21,258 +return this display value. +返回 displayValue + +450 +00:19:21,260 --> 00:19:24,161 +So it's do something to calculate what this +所以这里需要做的就是计算 + +451 +00:19:24,163 --> 00:19:26,363 +display value is here. +这里的 displayValue + +452 +00:19:27,399 --> 00:19:29,215 +And then return it. +然后返回它 + +453 +00:19:29,216 --> 00:19:31,032 +Now this one I'm not gonna take time to go +这次我不会花时间去 + +454 +00:19:31,035 --> 00:19:32,801 +through the details here. +详细说明细节 + +455 +00:19:32,803 --> 00:19:37,205 +And actually I've made it an extra credit item that you can +实际上我把它算作一个给你们去做的额外加分项 + +456 +00:19:37,207 --> 00:19:40,008 +do, which requires you to figure out +需要你们利用文档,去搞清楚我在这写的代码 + +457 +00:19:40,010 --> 00:19:44,345 +what I'm gonna type here using the documentation. +是什么意思 + +458 +00:19:44,347 --> 00:19:45,879 +But I'm not going to explain it here. +但现在我不想给出代码的解释 + +459 +00:19:45,881 --> 00:19:49,382 +I'm gonna use a class that's in this number formatter. +这里,我要在使用一个叫作 NumberFormatter 的类 + +460 +00:19:49,384 --> 00:19:52,051 +I'm actually gonna create one and +我先创建一个实例,然后 + +461 +00:19:52,053 --> 00:19:56,822 +I'm gonna use a method on it called number from String. +使用它的 numberFromString 方法 + +462 +00:19:57,858 --> 00:19:59,624 +And I'm gonna give it this String which is +然后我会把这个字符串传给它, + +463 +00:19:59,626 --> 00:20:02,593 +the display values text, unwrapped of course. +这个字符串也就是 display.text,当然得拆包 + +464 +00:20:03,596 --> 00:20:06,497 +The result is acting optional so I'm gonna unwrap that. +它的返回值是一个 optional String,所以我继续要把它拆包 + +465 +00:20:06,499 --> 00:20:09,499 +And then I'm gonna get the double value of the thing I +然后我再得到它返回的 Double 值 + +466 +00:20:09,501 --> 00:20:11,067 +get back [COUGH]. + +467 +00:20:11,068 --> 00:20:12,634 +Number gives me this kind of generic number so +Number 给了我这种泛型的数字,所以 + +468 +00:20:12,637 --> 00:20:14,637 +I am gonna take it and turn it into a double. +我把它转化成一个 Double + +469 +00:20:14,639 --> 00:20:15,738 +So there we go. +好了 + +470 +00:20:15,739 --> 00:20:16,838 +So you can go the next spread and +你们可以继续下一步了 + +471 +00:20:16,841 --> 00:20:18,374 +look at that later if you want. +如果你想的话,以后再考虑它 + +472 +00:20:19,410 --> 00:20:20,959 +But surprising to say we +高兴的是,我们 + +473 +00:20:20,960 --> 00:20:22,509 +now have a property display value that when we set it and +现在有了一个 displayValue 的属性,当我们设值和取值时 + +474 +00:20:22,512 --> 00:20:24,579 +get it, it's gonna be setting and getting. +我们调用了自定义的 set 和 get 方法 + +475 +00:20:24,581 --> 00:20:27,415 +It has a String here, so that is really convenient. +UILabel 这里是一个字符串,所以也挺方便的 + +476 +00:20:27,417 --> 00:20:29,400 +Especially for +尤其是这里 + +477 +00:20:29,401 --> 00:20:31,384 +right here, where we wanna say display value. +其实我们想传入的是 displayValue + +478 +00:20:31,387 --> 00:20:32,285 +'Kay? +明白了吗? + +479 +00:20:32,287 --> 00:20:33,953 +So let's see the double. +让我们回头检查一下,Double + +480 +00:20:33,955 --> 00:20:34,987 +No problem. +没错 + +481 +00:20:34,989 --> 00:20:37,256 +We're pinning that onto operandStack. +我们把它附到 operandStack 上了,而 operandStack 里的元素也是 Double 的 + +482 +00:20:37,258 --> 00:20:40,058 +So let's print in our operandStack here. +接下来,让我们把 operandStack 在这打印出来 + +483 +00:20:42,362 --> 00:20:45,162 +Just so, I mean we can do the same thing here, operandStack. +就像这样,一样的方式,\(operandStack) + +484 +00:20:46,632 --> 00:20:48,649 +Okay? +没问题吧? + +485 +00:20:48,650 --> 00:20:50,667 +And this worked because operandStack is an array, and +这种方式可行是因为 operandStack 是一个数组 + +486 +00:20:50,669 --> 00:20:53,636 +arrays know how to turn themselves into Strings. +数组知道如何把它们自身转化成字符串 + +487 +00:20:53,638 --> 00:20:55,938 +You'll see how they do that in the console in a moment here. +你一会儿就会在控制台输出里看到它们是怎么做到的了 + +488 +00:20:56,874 --> 00:20:58,040 +So let's go ahead and +所以,我们继续 + +489 +00:20:58,042 --> 00:21:00,842 +see if our application is actually putting things on +来看看我们的应用是否真的正确地能够把东西放到 + +490 +00:21:00,844 --> 00:21:02,343 +our stack properly here. +我们的栈里 + +491 +00:21:04,547 --> 00:21:14,054 +[NOISE] All right. +好的 + +492 +00:21:14,056 --> 00:21:14,854 +Let's try here. +我们尝试着在这里 + +493 +00:21:14,856 --> 00:21:18,591 +Let's try 56 enter. +在这里输入 56 + +494 +00:21:18,593 --> 00:21:21,761 +And look, operandStack equals 56 doing good. +看,operandStack 是等于 56,运行正常 + +495 +00:21:21,763 --> 00:21:23,128 +Seven enter. +输入 7 + +496 +00:21:23,130 --> 00:21:24,429 +All right, 56.0 and 7.0. +好的,56.0 和 7.0 + +497 +00:21:24,431 --> 00:21:27,699 +So, you can see that arrays turn themselves into Strings +所以你们看到了数组是如何把自身转化成字符串的 + +498 +00:21:27,701 --> 00:21:30,735 +by doing open square bracket and then they turn each of +在这个方括号里,它们把自身的每个 + +499 +00:21:30,737 --> 00:21:33,937 +their elements into Strings and separated by commas. +元素转化成字符串并以逗号分隔 + +500 +00:21:35,507 --> 00:21:37,207 +Now this is good. +这个就搞定了 + +501 +00:21:37,209 --> 00:21:39,642 +So we got our operand, operandStack building here. +我们这的 operandStack 就创建好了 + +502 +00:21:41,179 --> 00:21:44,713 +So all we need to do is have some times, and plus, and +接下来我们现在需要做的就是要有乘法,加法和 + +503 +00:21:44,715 --> 00:21:45,947 +minus buttons, etc. +减法之类的按钮 + +504 +00:21:45,949 --> 00:21:47,549 +I'm gonna put them right here. +我准备把它们放在这个位置 + +505 +00:21:47,551 --> 00:21:50,385 +That will operate on these items uh, on the stack. +它在在这些项上进行运算,准确的说是在栈上 + +506 +00:21:50,387 --> 00:21:52,119 +So, if I pressed plus right now, +所以,如果我现在按下加 + +507 +00:21:52,121 --> 00:21:55,122 +it would pull the seven and the eight off the stack. +它就会把 7 和 8 从栈中取出来(pop) + +508 +00:21:55,124 --> 00:21:57,057 +Add them together, it would be 15. +把他们相加,得到 15 + +509 +00:21:57,059 --> 00:21:58,758 +Show that 15 here, and +然后在这里显示 15 + +510 +00:21:58,760 --> 00:22:00,560 +it actually will put the 15 back on the stack. +实际上,15 会被放回到栈里(push) + +511 +00:22:00,562 --> 00:22:03,696 +So then, we'd have 56 and 15 on our stack. +然后,我们的栈里就有了 56 和 15 + +512 +00:22:03,698 --> 00:22:04,863 +Then we could, maybe. +接着我们就可以 + +513 +00:22:04,865 --> 00:22:08,400 +Plus those together and we wanted by it plus again. +再运行一次加法,把它们加到一起 + +514 +00:22:08,402 --> 00:22:08,933 +All right? +没错吧? + +515 +00:22:08,935 --> 00:22:12,036 +[COUGH] Okay. +好的 + +516 +00:22:12,038 --> 00:22:15,539 +So how are we gonna do that? +所以我们应该怎么做呢? + +517 +00:22:15,541 --> 00:22:17,040 +Well, we would make our buttons here. +嗯,我们将把这些运算符的按钮放在这个位置 + +518 +00:22:17,042 --> 00:22:22,245 +And I'm gonna make the buttons again by copying and +我通过复制粘贴数字按钮来 + +519 +00:22:22,247 --> 00:22:24,580 +pasting a digit button. +创建这些个运算符按钮 + +520 +00:22:24,582 --> 00:22:26,648 +But this time I know about that problem, +但是这次我已经知道会出现哪个问题了 + +521 +00:22:26,650 --> 00:22:29,584 +so right off the bat I'm gonna right click on it. +所以我马上就右键点击刚才粘贴的按钮 + +522 +00:22:29,586 --> 00:22:31,353 +And disconnect appendDigit: it. +然后取消和 appendDigit 方法的关联 + +523 +00:22:31,355 --> 00:22:34,472 +Okay? So +好的,那么 + +524 +00:22:34,473 --> 00:22:37,590 +now this button sends no messages, yet anyway. +现在,这个按钮就不会发送任何消息了 + +525 +00:22:37,593 --> 00:22:40,461 +And then we could put a type on here. +然后我们要在这上面设置一个运算符 + +526 +00:22:40,463 --> 00:22:44,331 +So here I'm gonna have my all my operations buttons use +这里我要让所有的运算符按钮都使用 + +527 +00:22:44,333 --> 00:22:47,000 +mathematical symbols so if we go down here to math symbols. +数学符号,而不是编程中的那些运算符号,所以我们看这里的 Math Symbols + +528 +00:22:47,002 --> 00:22:49,936 +See there's a bunch of math symbols here. +看这里有好多数学符号 + +529 +00:22:49,938 --> 00:22:51,737 +So let's do times, right here, +现在,我们来给乘法设置符号 + +530 +00:22:51,739 --> 00:22:56,775 +first, we'll put times right there, and we can wire it up. +首先,把乘法放到这,然后我们可以把它与代码链接在一起 + +531 +00:22:56,777 --> 00:22:59,511 +I'm just gonna hold that Ctrl and drag out here. +按住 Ctrl 然后拖动这里来 + +532 +00:23:00,580 --> 00:23:03,881 +We're gonna call this action method. +我们把这个 Action 称作 + +533 +00:23:03,883 --> 00:23:05,549 +Operate. +operate 方法 + +534 +00:23:05,551 --> 00:23:09,052 +And because I'm gonna have multiple operation buttons and +因为会有许多运算按钮,所以 + +535 +00:23:09,054 --> 00:23:11,588 +they're all going to send operate. +他们都会发送 operate 消息 + +536 +00:23:11,590 --> 00:23:13,289 +Just like I did with append digit, +就像数字按钮和 appendDigit 方法链接在一起一样 + +537 +00:23:13,291 --> 00:23:14,457 +I am going to use the sender. +我要使用这个 sender + +538 +00:23:14,459 --> 00:23:18,193 +So I'm gonna be very careful to change this any +所以我得仔细地 + +539 +00:23:18,195 --> 00:23:19,661 +object to be button. +把 Sender 的类型从 AnyObject 改成 UIButton + +540 +00:23:20,697 --> 00:23:22,129 +Do not forget that. +不要忘记这点 + +541 +00:23:22,131 --> 00:23:24,965 +'Kay, so action, we are gonna have it sender. +Sender 类型 + +542 +00:23:24,967 --> 00:23:25,932 +UIButton. +为 UIButton + +543 +00:23:25,934 --> 00:23:26,666 +Call it operate. +Action 名字为 operate + +544 +00:23:27,669 --> 00:23:28,868 +There it is. +就是这些设置了 + +545 +00:23:28,870 --> 00:23:30,269 +That's method doing operate. +这就是做操作符运算的方法 + +546 +00:23:31,338 --> 00:23:33,438 +We can copy and paste this button now, right? +我们现在可以复制粘贴这个按钮了 + +547 +00:23:33,440 --> 00:23:34,639 +We got this one, so +我们用乘法的这个 + +548 +00:23:34,641 --> 00:23:37,775 +let's copy and paste and make some more of these. +复制粘贴,然后重复,重复 + +549 +00:23:37,777 --> 00:23:41,778 +We'll start out with four of them, let's say. +我们先粘贴出 4 个运算符 + +550 +00:23:41,780 --> 00:23:43,680 +'Kay? + +551 +00:23:43,681 --> 00:23:45,581 +Let's get back our special characters here. +我们回到特殊符号这里 + +552 +00:23:45,584 --> 00:23:51,087 +[COUGH] All right, so let's make this one be divide. +我们来把第二个设置为除法 + +553 +00:23:51,089 --> 00:23:53,522 +Let's make this one plus. +第三个,加法 + +554 +00:23:53,524 --> 00:23:55,924 +And this one be minus. +最后一个,减法 + +555 +00:23:55,926 --> 00:23:58,660 +All right. +好了 + +556 +00:23:58,662 --> 00:24:00,461 +So we've got these buttons [COUGH]. +操作符按钮就完成了 + +557 +00:24:00,463 --> 00:24:02,930 +And they're all sending, if we look at this here, +它们都会发送,如果我们看这里 + +558 +00:24:02,932 --> 00:24:04,598 +they're all sending operate. +它们都会发送 operate 消息 + +559 +00:24:05,701 --> 00:24:08,535 +Luckily, they're not sending anything except operate, so +幸运的是它们并不会发送运算之外的东西 + +560 +00:24:08,537 --> 00:24:09,869 +that's good. +这样就好 + +561 +00:24:09,871 --> 00:24:12,905 +And when they send operate, we're gonna figure out +当它们发送同样的 operate 消息的时候,我们要搞清楚 + +562 +00:24:12,907 --> 00:24:15,808 +which one is sending it by the same exact way we did above. +发送消息的对象是哪一个 + +563 +00:24:15,810 --> 00:24:18,543 +We're gonna say what is the sender's current title? +也就是说,Sender 的 currentTitle 是什么? + +564 +00:24:18,545 --> 00:24:20,111 +We're gonna unwrap it. +我们要把它拆包 + +565 +00:24:20,113 --> 00:24:24,582 +So operation here is gonna be a String. +这里的 operation 是一个 String + +566 +00:24:24,584 --> 00:24:28,418 +And it's going to tell us the title of the buttons so +它会告诉我们按钮的 title,所以 + +567 +00:24:28,420 --> 00:24:31,721 +we know which one to use there. +我们就知道了该怎么处理 + +568 +00:24:31,723 --> 00:24:35,758 +Now I'm gonna show you a control flow operator here in +现在我要给你们展示 Swift 中的控制流符号 + +569 +00:24:35,760 --> 00:24:39,128 +Swift that's very powerful, much more powerful than +它非常强大,比其他语言中的强大多了 + +570 +00:24:39,130 --> 00:24:41,463 +this operator is in other languages. + +571 +00:24:41,465 --> 00:24:43,432 +And also very, very important to swift. +而且对 Swift 语言自身来说是很重要的 + +572 +00:24:43,434 --> 00:24:46,401 +I'm only gonna show you the simplest usage of it here, but +这里我只会向你们展示控制流符号最简单的用法 + +573 +00:24:46,403 --> 00:24:49,170 +you're gonna see on Monday's demonstration and +你们会在周一的展示和 + +574 +00:24:49,172 --> 00:24:51,906 +later in the quarter how important this operator is. +接下来的学习中感受到它的强大之处 + +575 +00:24:51,908 --> 00:24:54,541 +But, it's switch, okay, and +switch + +576 +00:24:54,543 --> 00:24:59,846 +switch looks like switch in other languages, like C. +它和其他语言中的 switch 看起来很像,比如说 C + +577 +00:24:59,848 --> 00:25:01,080 +You switch on something. +你在某个变量上使用 switch + +578 +00:25:01,082 --> 00:25:03,015 +In this case I'm gonna switch on this String. +在这里,我会在这个字符串上 switch + +579 +00:25:03,017 --> 00:25:04,483 +This is the String. +字符串 operation + +580 +00:25:04,485 --> 00:25:06,852 +Then you just specify the case of each thing. +然后你指明所有 case 情况 + +581 +00:25:06,854 --> 00:25:10,822 +So for example here I have a case. +举例来说,有一个 case + +582 +00:25:10,824 --> 00:25:17,561 +Let's do the multiply. +进行乘法 + +583 +00:25:17,563 --> 00:25:21,031 +Okay, so we've got multiply case right here. +那我们就在这里创建一个乘法 case + +584 +00:25:21,033 --> 00:25:24,234 +And then we just put the code that we want here +接着我们只需把做乘法的代码 + +585 +00:25:24,236 --> 00:25:26,203 +for multiply. +放到这里 + +586 +00:25:26,204 --> 00:25:28,171 +And we'd do that for all the other cases here. +接着对其他的操作符 case 也这么做 + +587 +00:25:28,173 --> 00:25:30,439 +So let's copy and paste. +复制粘贴一下 + +588 +00:25:30,441 --> 00:25:36,478 +And we'll do this be our divide case. +这个是除法 case + +589 +00:25:36,480 --> 00:25:39,347 +And we'll have this be our plus case and +这个是加法 case + +590 +00:25:39,349 --> 00:25:41,215 +we'll have this be our, +在这里是减法 case + +591 +00:25:41,217 --> 00:25:45,753 +make sure we're doing the same here, plus case. +我们在复制粘贴减法 case 的时候 + +592 +00:25:47,923 --> 00:25:49,689 +Again, you've got to be a little careful here. +你需要仔细一点 + +593 +00:25:49,691 --> 00:25:51,858 +You know, this minus is slightly different from this +因为左边的减号符号和 + +594 +00:25:51,860 --> 00:25:54,593 +minus which might be slightly different than the minus +右边的减号符号有轻微的不同 + +595 +00:25:54,595 --> 00:25:55,828 +you type with the keyboard. +右边的减号符号是你从键盘上输入的那种 + +596 +00:25:55,830 --> 00:25:59,164 +So, when you're putting the symbols here, +所以,当你们在这放置符号的时候 + +597 +00:25:59,166 --> 00:26:03,434 +you wanna use exactly the same symbols here in your case. +你们要确保代码中的和 Storyboard 中使用的是同一个 + +598 +00:26:03,436 --> 00:26:06,871 +Now, one thing about switch on Swift though is it +关于 Swift 中的 switch,要注意的一件事就是 + +599 +00:26:06,873 --> 00:26:11,274 +absolutely requires that you have every case covered. +你必须确保覆盖所有情况(case) + +600 +00:26:11,276 --> 00:26:13,877 +Now since this is a String, obviously can't have case of +由于这是一个字符串,你显然不可能 + +601 +00:26:13,879 --> 00:26:15,345 +every single String in the universe. +穷举每一种情况 + +602 +00:26:15,347 --> 00:26:18,280 +That is almost infinite, but luckily there, +通常是无限多的,但是很幸运的是 + +603 +00:26:18,282 --> 00:26:22,584 +you can take defaults and just break out of the switch. +可以在 default 后,使用 break 来跳出 switch + +604 +00:26:22,586 --> 00:26:26,187 +That means if it's not one of these cases by default just +也就意味着,如果不是 default 之前列举的那些情况 + +605 +00:26:26,189 --> 00:26:27,088 +break out of the switch. +就会跳出 switch + +606 +00:26:27,090 --> 00:26:28,355 +You could put code here as well, +这不是说代码不能放在 default 中 + +607 +00:26:28,357 --> 00:26:31,091 +but breaking out of it is what we wanna do in our case. +只是在这里,我们想要从 switch 中 break 而已 + +608 +00:26:33,028 --> 00:26:35,861 +now, in here, we're just going to put the code for multiply. +现在,在这里,我们输入与乘法相关的语句 + +609 +00:26:35,863 --> 00:26:37,896 +So, what do we need to do for multiply? +那么,乘法需要做些什么? + +610 +00:26:37,898 --> 00:26:40,432 +For the moment, I'm gonna comment this out. +我会暂时将这部分注释掉 + +611 +00:26:40,434 --> 00:26:42,667 +I'm gonna use command, slash, +使用 ⌘ + / 键来注释 + +612 +00:26:42,669 --> 00:26:44,502 +which is a really nice feature. +这个快捷键的确称得上是一个很不错的功能 + +613 +00:26:44,504 --> 00:26:46,103 +You do command slash. +按下 ⌘ + / 键之后 + +614 +00:26:46,105 --> 00:26:48,238 +And then command slash again, to uncomment. +再次按下 ⌘ + / 键来取消给代码注释 + +615 +00:26:48,240 --> 00:26:55,311 +[INAUDIBLE] real quick cuz I just wanna focus on times. +这里我想专注于乘法操作的代码 + +616 +00:26:55,313 --> 00:26:58,247 +Now any time I press any operator, +任何时候,点击任何操作符 + +617 +00:26:58,249 --> 00:27:02,317 +I probably wanna give the user an automatic enter. +我希望自动给用户按下 enter 按钮 + +618 +00:27:02,319 --> 00:27:05,087 +That's so that six enter, three enter, +也就是 6,enter,3,enter + +619 +00:27:05,089 --> 00:27:07,989 +times is the same as six enter three times. +乘法,等价于 6 乘以 3 + +620 +00:27:09,392 --> 00:27:12,393 +Okay, so six enter three times is gonna do an automatic enter +这里,6,enter,3,乘法会自动在 + +621 +00:27:12,395 --> 00:27:13,927 +on that three. +在 3 之后输入一个 enter + +622 +00:27:14,996 --> 00:27:16,596 +Cuz obviously, I intend to have six and +显然在这种情况下,我想让 6 和 + +623 +00:27:16,598 --> 00:27:18,998 +three be multiplied in that case. +3 相乘 + +624 +00:27:19,000 --> 00:27:26,705 +So for all of these operations, I going to say, +所以,对于所有的操作符的 Action + +625 +00:27:26,707 --> 00:27:29,708 +if the users in the middle of typing a number. +如果用户正在输入一个数字(userIsInTheMiddleOfTypingANumber 为 true) + +626 +00:27:29,710 --> 00:27:32,443 +Then hit enter for me, right here. +那么,我要自动帮用户输入一个 enter,即调用 enter() + +627 +00:27:32,445 --> 00:27:36,347 +Okay, so [COUGH] what do we need to do in +接下来,我们 + +628 +00:27:36,349 --> 00:27:39,516 +this specific case of times? +需要乘法在这里做什么? + +629 +00:27:39,518 --> 00:27:42,886 +Well, really we just want to set our display value. +我们需要在这里对 displayValue 设值 + +630 +00:27:42,888 --> 00:27:46,856 +Remember we have our nice display value down here. +还记得吗?我们自定义了 displayValue 的取值和设值方法 + +631 +00:27:46,858 --> 00:27:49,492 +And we can do setting as well as getting. +取值和设值方法 + +632 +00:27:49,494 --> 00:27:52,094 +So I set that display value. +因此,我在这里需要做的是 + +633 +00:27:52,096 --> 00:27:55,264 +Up here. +设值 + +634 +00:27:55,265 --> 00:27:58,433 +Equal to multiplying the top two things on this stack. +displayValue 等于将栈顶的两个数相乘 + +635 +00:27:58,435 --> 00:28:02,270 +So I can actually remove something off our stack. +因此,我可以从栈里移除一些元素 + +636 +00:28:02,272 --> 00:28:04,705 +We're representing our stack as an array. +我们可以使用一个数组代表栈结构 + +637 +00:28:05,941 --> 00:28:07,908 +Of course, they are stacked as an array. +而且,这里确实是使用了一个数组来表示栈结构 + +638 +00:28:07,910 --> 00:28:11,311 +And so a stack is something you push things on, +栈是一种数据结构,你可以压入元素到栈里 + +639 +00:28:11,313 --> 00:28:12,979 +you pop things off. +也可以从栈里弹出元素 + +640 +00:28:12,981 --> 00:28:15,614 +And with an array, we're just gonna add something there at +用数组实现的话,我们只需要 + +641 +00:28:15,616 --> 00:28:17,082 +the end to push something on, and +在数组的末尾添加一个元素,来模拟元素的入栈操作 + +642 +00:28:17,084 --> 00:28:19,317 +that will just remove it from the end to pop it off. +在数组的末尾移除一个元素,来模拟元素的出栈操作 + +643 +00:28:19,319 --> 00:28:21,653 +So there's a nice. +没问题吧? + +644 +00:28:21,655 --> 00:28:23,654 +All right. This is an array, right? +好的,这是一个数组 + +645 +00:28:23,656 --> 00:28:26,007 +Operand stacks. +数组名称是 operandStack + +646 +00:28:26,008 --> 00:28:28,359 +There's a nice method called remove last. +有个方法叫 removeLast() + +647 +00:28:28,361 --> 00:28:30,894 +And if we option click on remove last, you'll see here +如果在 removeLast 方法上按住 option 键并单击 + +648 +00:28:30,896 --> 00:28:33,430 +that it removes an element from the end of the array. +可以看到说明:从数组的末尾移除一个元素 + +649 +00:28:34,666 --> 00:28:37,567 +Now, it does require a count greater than zero. +这个方法需要数组的元素个数大于零 + +650 +00:28:37,569 --> 00:28:42,705 +So if our array were empty this would crash our program. +如果数组是空的话,移除元素会导致程序崩溃 + +651 +00:28:42,707 --> 00:28:44,840 +So let's put a little protective thing here. +所以,在这里做一些保护性的措施. + +652 +00:28:44,842 --> 00:28:47,742 +If the operand stacks. +如果 operandStack + +653 +00:28:47,744 --> 00:28:50,411 +There's a nice property here called Count on that. +operandStack 变量有一个属性叫做 count + +654 +00:28:50,413 --> 00:28:52,947 +It is greater or +如果它大于或者 + +655 +00:28:52,948 --> 00:28:55,482 +equal to two actually because multiply takes two operand so +等于 2,因为乘法需要 2 个操作数 + +656 +00:28:55,485 --> 00:28:57,484 +there better two things on this stack. +所以栈中至少需要有 2 个元素 + +657 +00:28:58,921 --> 00:29:01,121 +Then we can do this and so +那么我们可以把这取出来的栈顶元素 + +658 +00:29:01,123 --> 00:29:05,324 +we're gonna multiply that by and remove the next one. +相乘上第二次调用 removeLast() 所取出来的栈顶元素 + +659 +00:29:05,326 --> 00:29:06,125 +Okay? +明白了吗? + +660 +00:29:06,127 --> 00:29:07,259 +So here we got- +这样的话 + +661 +00:29:09,062 --> 00:29:12,463 +We're just taking the last two things off of this stack by +我们从栈中移除最顶上的两个元素 + +662 +00:29:12,465 --> 00:29:14,832 +removing them from the end of the array and +通过从数组中移除最后的元素(removeLast 方法) + +663 +00:29:14,834 --> 00:29:17,334 +just assigning it to display value. +将运算结果赋值给 displayValue 变量 + +664 +00:29:17,336 --> 00:29:19,469 +And we probably also want to do an enter here, +接着,我们希望在这里输入一个 enter() + +665 +00:29:19,471 --> 00:29:22,539 +because [COUGH] if I go six enter three times, +如果用户按下了 6,enter,3,乘 + +666 +00:29:22,541 --> 00:29:25,108 +well then I want to be able to say then nine plus and +然后接着,用户按下了 9,加 + +667 +00:29:25,110 --> 00:29:28,744 +have it add onto the six times three. +这代表着在原来运算的结果上加 9 + +668 +00:29:29,713 --> 00:29:32,213 +So we want an automatic enter here, as well. +所以,这里需要一个自动点击 enter 的操作 + +669 +00:29:32,215 --> 00:29:34,149 +Okay? +明白了吗? + +670 +00:29:34,150 --> 00:29:36,084 +So, that's pretty much all we need to do here. +这大概就是我们所有需要在这里做的了 + +671 +00:29:36,086 --> 00:29:41,021 +Let's go ahead and run this, see how this works. +让我们运行这个应用,看看它是否正常工作 + +672 +00:29:43,826 --> 00:29:47,527 +And so, six enter, or three enter, six enter. +我们尝试输入 3,enter,6,enter + +673 +00:29:47,529 --> 00:29:49,996 +Now we've got them both on the stack. +我们可以从控制台看到它们已经在栈上了 + +674 +00:29:49,998 --> 00:29:52,898 +Times and you can see we put our 18 here. +然后我让它们相乘,可以看到结果是 18 + +675 +00:29:52,900 --> 00:29:55,668 +It also put it back on the stack and +18 这个结果也被放入了栈中 + +676 +00:29:55,670 --> 00:29:57,536 +we can say five times. +我们再输入 5,乘 + +677 +00:29:57,538 --> 00:29:59,237 +That put a five on the stack and +这个操作将 5 放入栈中, + +678 +00:29:59,239 --> 00:30:01,372 +then multiplied them, took it off. +将它们两个从栈中移除并相乘,返回结果 + +679 +00:30:01,374 --> 00:30:03,107 +So that's working nicely. +程序正常运行 + +680 +00:30:03,109 --> 00:30:05,576 +[COUGH] Now what about our- +现在 + +681 +00:30:05,578 --> 00:30:06,743 +Other buttons, here. +我们的其他的运算符按钮 + +682 +00:30:06,745 --> 00:30:08,745 +We gonna make those work. +我们想要让它们正常工作 + +683 +00:30:08,747 --> 00:30:12,548 +Let's do that. +让我们继续完成 + +684 +00:30:12,550 --> 00:30:16,152 +Now, they do a very similar thing, here. +其他的运算符功能和乘法的功能是十分相似的 + +685 +00:30:16,154 --> 00:30:20,088 +So, one temptation would be to just copy here. +所以,我们复制乘法的这部分代码 + +686 +00:30:20,090 --> 00:30:22,657 +Let's uncomment these out. +先取消这部分的注释 + +687 +00:30:23,693 --> 00:30:25,459 +And then just paste it, repeatedly. +然后重复粘贴 + +688 +00:30:25,461 --> 00:30:26,827 +So, put it there. +放到这些位置 + +689 +00:30:27,996 --> 00:30:31,831 +There, there and then just changes times in here. +只需要修改这里的乘号 + +690 +00:30:31,833 --> 00:30:35,868 +D note to plus for example on this one. +把这个换成个加号 + +691 +00:30:35,870 --> 00:30:39,038 +But his is pretty messy code, look at all this +但是,这样的代码看起来很乱 + +692 +00:30:39,040 --> 00:30:42,841 +incredible amount of duplicating code, in here. +这里有大量的重复的代码 + +693 +00:30:42,843 --> 00:30:47,145 +We really probably wouldn't to write our code like this. +我们不希望代码写成这样子 + +694 +00:30:47,147 --> 00:30:49,780 +People would think we were terrible programmers I +如果写成这样,别人会认为我们是很糟糕的程序员 + +695 +00:30:49,782 --> 00:30:51,482 +think if we did that. + +696 +00:30:51,484 --> 00:30:54,251 +Really what would be nice is if we had some, +什么样的代码看起来会不错呢? + +697 +00:30:54,253 --> 00:30:56,453 +could write some kind of function. +那就是如果我们可以把这些重复的代码写成函数 + +698 +00:30:56,455 --> 00:31:00,990 +Maybe we could call it perform operation or +然后给函数起名为 perfomOperation + +699 +00:31:00,992 --> 00:31:02,458 +something like that. +或者类似意思的名字 + +700 +00:31:02,460 --> 00:31:05,927 +And if the argument to that function. +至于函数的参数 + +701 +00:31:05,929 --> 00:31:08,196 +Remember that arguments have names. +需要注意的是,函数参数也是有名字的 + +702 +00:31:08,198 --> 00:31:09,163 +Here's the name. +这就是参数的名字 + +703 +00:31:09,165 --> 00:31:10,364 +And then we have the type. +然后是参数的类型 + +704 +00:31:11,434 --> 00:31:16,269 +The argument were something which basically was this +这里的参数是 + +705 +00:31:16,271 --> 00:31:19,305 +little operation in here, or +这里的运算操作符 + +706 +00:31:19,307 --> 00:31:21,707 +some sort of function that would do this operation. +或者是能够完成运算操作符操作的函数 + +707 +00:31:21,709 --> 00:31:24,576 +So if this could be some sort of function that +如果可以把这些重复代码写成函数的话 + +708 +00:31:24,578 --> 00:31:25,277 +would be cool. +看起来就很棒了 + +709 +00:31:25,279 --> 00:31:27,078 +Then, maybe we could. +接下来 + +710 +00:31:27,080 --> 00:31:28,880 +I take this code out of here, put it in here. +将这段代码移动到这个位置 + +711 +00:31:30,149 --> 00:31:34,384 +Let's call it perform not pre-form, perform operation. +并起名为 performOperation + +712 +00:31:34,386 --> 00:31:36,353 +[LAUGH] Put it in here and +放到这里 + +713 +00:31:36,355 --> 00:31:38,921 +instead of doing, you know, multiply here. +这里注意,我们把乘号改掉 + +714 +00:31:38,923 --> 00:31:41,190 +Let's go ahead and we can do this operation some how. +用其他的方式来进行运算 + +715 +00:31:41,192 --> 00:31:42,891 +I guess, well maybe operation, +可能是某个叫 operation 函数 + +716 +00:31:42,893 --> 00:31:48,196 +call it like a function with two arguments here. +接受两个参数 + +717 +00:31:51,067 --> 00:31:52,500 +Okay. That would be +好了,这样看起来很不错了 + +718 +00:31:52,502 --> 00:31:55,202 +cool because we'd be sharing, you know, this check. +因为我们复用了这段代码,复用了这个判读 + +719 +00:31:55,204 --> 00:31:57,204 +We'd be sharing this enter. +复用了这 enter 方法 + +720 +00:31:57,206 --> 00:31:59,472 +[COUGH] We'd be sharing the removal of the operator. +复用了从栈中弹出两个元素的方法 + +721 +00:31:59,474 --> 00:32:01,441 +We'd be sharing the same display value. +复用了 displayValue 变量 + +722 +00:32:01,443 --> 00:32:04,209 +We'd be kind of sharing a lot of code here and +通过这样,复用了大段的代码 + +723 +00:32:05,746 --> 00:32:08,179 +then up here if we could just do something like, +至于在上面的 case 结构,我们只需要像这样 + +724 +00:32:08,181 --> 00:32:12,850 +perform operation, and, somehow, specify, +调用函数 performOperation,并且 + +725 +00:32:12,852 --> 00:32:16,186 +multiply, as the operation we wanted to do here. +指定函数参数 multiply + +726 +00:32:16,188 --> 00:32:23,593 +And then we wouldn't need all this stuff here, right? +原来的那一大段代码就都不需要了,明白了吗? + +727 +00:32:23,595 --> 00:32:24,527 +So this is gonna be cool. +看起来很不错 + +728 +00:32:24,529 --> 00:32:25,995 +Now, can we do this? +有人会质疑,我们可以这样做吗? + +729 +00:32:25,997 --> 00:32:28,564 +Well, yes, the answer is we can. +答案是当然可以 + +730 +00:32:28,566 --> 00:32:33,134 +And so, types, functions. +参数类型,函数 + +731 +00:32:33,136 --> 00:32:37,005 +Can be types in Swift, just like any other type. +函数在 Swift 里可以被当做一种类型,就像 Swfit 中其他的类型一样 + +732 +00:32:37,007 --> 00:32:40,040 +So, you know, we have a double here, oops, double. +你知道,这里需要一个 Double 类型的参数 + +733 +00:32:41,844 --> 00:32:42,809 +That's a type. +就是这个类型 + +734 +00:32:42,811 --> 00:32:43,943 +You can also have a function type. +当然也可以有一个函数类型的参数 + +735 +00:32:43,945 --> 00:32:45,611 +So how do you specify a function type? +那么,怎么指定一个函数类型呢? + +736 +00:32:45,613 --> 00:32:47,846 +Well multiple I or +无论是 multiple + +737 +00:32:47,848 --> 00:32:49,981 +whatever function I'm about to perform here. +或者是任何其他我想要在这里执行的函数 + +738 +00:32:49,983 --> 00:32:54,686 +This is a function that takes two doubles as arguments. +这样的函数需要两个 Double 类型的参数 + +739 +00:32:54,688 --> 00:32:56,354 +And it returns a double. +并且,它的返回值类型也是一个 Double 类型 + +740 +00:32:56,356 --> 00:33:00,190 +So, I can just say, I want operation to be +所以我在这里输入 + +741 +00:33:00,192 --> 00:33:04,661 +a function that takes two doubles and returns a double. +我想要 operation 是一个函数,带两个 Double 类型参数,返回 Double 类型 + +742 +00:33:04,663 --> 00:33:07,363 +I can express that right here. +这就是我要表达的 + +743 +00:33:07,365 --> 00:33:11,300 +This is a type, the type of this. +这就是函数类型的定义 + +744 +00:33:12,369 --> 00:33:15,870 +Argument right here that you can click on and say yeah +在函数的名称上按住 option 单击 + +745 +00:33:15,872 --> 00:33:18,639 +that type is double takes two doubles and returns a double. +你可以看到信息:2 个 Double 类型的参数,1 个 Double 类型的返回值 + +746 +00:33:20,276 --> 00:33:22,176 +So, just simple as that. +就是这么简单 + +747 +00:33:22,177 --> 00:33:24,077 +So all we need now is a function here +我们目前已知的就是,这里有一个函数 + +748 +00:33:24,079 --> 00:33:26,379 +called multiply that takes two doubles and +这个函数名称为 multiply,带 2 个 Double 类型的参数 + +749 +00:33:26,381 --> 00:33:28,514 +returns a double and does multiplication. +返回 1 个 Double 类型的返回值,函数功能是完成乘法操作 + +750 +00:33:28,516 --> 00:33:33,118 +So we could go down here and say okay multiply and +接下来我们在下面输入 multiply 函数的代码 + +751 +00:33:33,120 --> 00:33:35,587 +you'll have op1 which is double and op2. +第一个参数 op1,Double 类型,第二个参数 op2 + +752 +00:33:35,589 --> 00:33:39,157 +[COUGH] A double and it returned the double. +Double 类型,返回一个 Double 类型 + +753 +00:33:39,159 --> 00:33:41,926 +And it's just return one times out two. +返回值是 op1 乘以 op2 的结果 + +754 +00:33:42,962 --> 00:33:44,261 +Okay? +对吗? + +755 +00:33:44,263 --> 00:33:45,729 +And that worked great. +一切都很好 + +756 +00:33:45,731 --> 00:33:51,600 +Back out again so we can see if this actually works. +回到上面,看它是否真的可以正常运行 + +757 +00:33:51,602 --> 00:33:53,168 +But there's no errors here. +没有任何错误 + +758 +00:33:53,170 --> 00:33:55,387 +Right? It seems to work. +对么?看起来很正常 + +759 +00:33:55,388 --> 00:33:57,605 +Multiply seems to be a function to take the $2 and +multiply 就是一个接受两个参数,返回一个 Double 这样的函数 + +760 +00:33:57,608 --> 00:33:59,274 +turns it double. + +761 +00:33:59,275 --> 00:34:00,941 +And that's what this argument here is and +这就是 performOperation 的参数 + +762 +00:34:00,944 --> 00:34:02,661 +I'm passing it along. +我将 multiply 传入 + +763 +00:34:02,662 --> 00:34:04,379 +It should all work so let's give it a try. +这一切都没有问题,所以应该是可行的,那么我们来试一下吧 + +764 +00:34:08,818 --> 00:34:10,684 +So here we go as six enter. +输入 6,enter + +765 +00:34:10,686 --> 00:34:15,188 +54 times and sure enough it's working it. +54,乘以,输出结果是 324.0,没问题 + +766 +00:34:15,190 --> 00:34:17,757 +It's doing that multiplication. +完成了乘法操作,我们可以在控制台输出里看到 + +767 +00:34:18,826 --> 00:34:23,428 +Works great and so what about all of our other cases here? +乘法做的不错,其他的 case 情况呢? + +768 +00:34:23,430 --> 00:34:26,731 +Well we would just need to take this same. +只需要也像 multiply 这样做 + +769 +00:34:26,733 --> 00:34:29,400 +Piece of code right here and put it for all of them. +我们在所有的 case 情况下粘贴 performOperation(multiply) + +770 +00:34:29,402 --> 00:34:32,169 +And of course we need a divide method, so we have to +当然了,我们需要除法函数 + +771 +00:34:32,171 --> 00:34:35,805 +come down here, and copy and paste that, and make divide. +所以把这里 multiply 改名为 divide,同时,然后复制 multiply 的实现并在它的下面粘贴更名为 divide + +772 +00:34:35,807 --> 00:34:37,907 +Oh wait a second, +稍等 + +773 +00:34:37,909 --> 00:34:41,210 +this is starting to be just as bad as I had before. +这又像之前看起来的那样糟糕了 + +774 +00:34:41,212 --> 00:34:44,646 +Having to make all these extra functions, multiply and +需要这些额外的函数:乘法 + +775 +00:34:44,648 --> 00:34:46,081 +divide and all that. +除法,等等 + +776 +00:34:46,082 --> 00:34:47,515 +Well [COUGH] it turns out it's so +事情上 + +777 +00:34:47,518 --> 00:34:52,553 +common to pass functions as arguments in Swift, that it +在 Swift 中,将函数作为参数传递是很常见的 + +778 +00:34:52,555 --> 00:34:56,390 +allows you to put a function like multiply right in +允许你在这里传递一个,例如 multiply 的函数 + +779 +00:34:56,392 --> 00:35:00,327 +here without having to create a separate function like this. +而不需要单独创建一个函数 + +780 +00:35:00,329 --> 00:35:02,195 +And all you do is you just pick it up. +所有你需要做的是就是选中函数的这块部分 + +781 +00:35:02,197 --> 00:35:05,131 +So I'm just going to cut that from down here and +从这里剪切 + +782 +00:35:05,133 --> 00:35:06,599 +I'm going to paste it right in here. +粘贴到上面这里来 + +783 +00:35:07,702 --> 00:35:10,168 +The only thing you have to change syntactically when you +唯一需要在语法上做的改变的就是 + +784 +00:35:10,170 --> 00:35:13,738 +do that is this curly brace, okay. +这里左侧的花括号 + +785 +00:35:13,740 --> 00:35:16,541 +Instead of being after the declaration of +不是之前在声明函数的参数和返回值之后 + +786 +00:35:16,543 --> 00:35:21,779 +the arguments in the return value, it needs to be before. +而是在这两者之前 + +787 +00:35:21,781 --> 00:35:24,314 +So, you move the curly brace before. +所以,你把花括号放到前面去 + +788 +00:35:24,316 --> 00:35:25,648 +And then where the curly brace was, +之前这里是小括号的位置 + +789 +00:35:25,650 --> 00:35:27,417 +you gonna put in, the word in. +添加一个单词 in + +790 +00:35:28,586 --> 00:35:30,486 +And so that allows us to just. +这里我们稍微调整下 + +791 +00:35:30,488 --> 00:35:34,723 +Come and do that again to eliminate some of our errors. +现在把这些代码都注释掉,不要让程序有错误 + +792 +00:35:34,725 --> 00:35:37,291 +And we can get rid of function multiply down here. +然后,我们就可以移除这里的 func multiply 了 + +793 +00:35:39,328 --> 00:35:42,862 +So that allows me to just put that multiplier right in here. +以上这些步骤就允许我们把乘法的实现 + +794 +00:35:42,864 --> 00:35:44,030 +Right in line. +放在 case 情况的一行里面 + +795 +00:35:44,032 --> 00:35:46,032 +Right as the argument to this function. +直接给 performOperation 函数传递一个函数参数 + +796 +00:35:46,034 --> 00:35:48,167 +And this things kind of wacky. +对于一些不了解的人来说 + +797 +00:35:48,169 --> 00:35:49,701 +For those of you who don't know it, +这种方式看起来略古怪 + +798 +00:35:49,703 --> 00:35:51,469 +user programming languages that allow this kind +但在一些编程语言中,这种写法是允许的 + +799 +00:35:51,471 --> 00:35:53,604 +of thing to happen are called closures. +这样的情况称之为闭包(closure) + +800 +00:35:54,607 --> 00:35:56,540 +It basically allows you to put a function right in there. +它允许你在这里放置一个函数 + +801 +00:35:56,542 --> 00:36:02,812 +And this, okay here, looks okay, I mean we can certainly +好的,这样就看起来不错 + +802 +00:36:02,814 --> 00:36:05,481 +you know, now we can copy and paste this and put it here. +下面就可以复制,粘贴这段代码 + +803 +00:36:05,483 --> 00:36:06,615 +You know, here and +放在除法的 case 这里 + +804 +00:36:06,617 --> 00:36:09,118 +change this and put it here and change this. +然后将 divide 改成我们复制的代码,以此类推,加法、减法也是如此 + +805 +00:36:09,120 --> 00:36:12,287 +But it can even be better than this. +但是,我们可以进一步改进 + +806 +00:36:12,289 --> 00:36:15,223 +So we know that Swift is really good at +我们知道 Swift 引以为傲的 + +807 +00:36:15,225 --> 00:36:17,658 +something called type inference. +一个特性称就是类型推断 + +808 +00:36:17,660 --> 00:36:19,493 +Where I can kinda figure out the type, +也就是我可以通过上下文(context)来 + +809 +00:36:19,495 --> 00:36:22,863 +of something, from the context. +推断某个东西是什么类型的 + +810 +00:36:22,865 --> 00:36:25,165 +And you can do the same thing here. +这里你也可以这么做 + +811 +00:36:25,167 --> 00:36:27,267 +Because its looking at performOperation. +因为 Swift 的编译器看到这里的 performOperation + +812 +00:36:27,269 --> 00:36:29,435 +It knows you're calling perform operation. +它知道你在调用 performOperation + +813 +00:36:29,437 --> 00:36:33,039 +It knows this argument is a function that takes two +它知道这个函数的参数 + +814 +00:36:33,041 --> 00:36:34,940 +doubles and returns a double. +是 2 个 Double 类型,返回值是 1 个 Double 类型的 + +815 +00:36:34,942 --> 00:36:38,377 +So you really don't have to specify all the types in here. +所以在这里,我们不需要指定参数和返回值的类型 + +816 +00:36:38,379 --> 00:36:39,978 +Cuz it knows all of this. +因为编译器知道这些事情 + +817 +00:36:39,980 --> 00:36:43,381 +So you can actually get rid of all these type decorations, +所以,你可以删除这些参数类型声明 + +818 +00:36:43,383 --> 00:36:45,416 +right here, even the return. +甚至是返回值类型也一样可以省去 + +819 +00:36:45,418 --> 00:36:47,851 +And, again, seeing no warnings, no errors. +可以看到,删除后,没有任何警告和错误 + +820 +00:36:47,853 --> 00:36:49,553 +It knows that this has to be a double, and +它知道这个第一个参数必须是一个 Double 类型的 + +821 +00:36:49,555 --> 00:36:51,454 +this has to be a double. +第二个参数也必须是一个 Double 类型的 + +822 +00:36:51,456 --> 00:36:53,556 +Because it knows you're calling perform operation. +因为它知道你调用的是 performOperation + +823 +00:36:53,558 --> 00:36:56,959 +So it knows the argument to that is like that. +所以,它知道函数的参数是什么类型的 + +824 +00:36:58,529 --> 00:37:00,962 +Okay, and you can even make this look a little nicer. +好的,那么我们可以对我们的代码进行进一步的改进 + +825 +00:37:00,964 --> 00:37:03,631 +We can move this all up onto one line. +把这个闭包写在一行里面 + +826 +00:37:04,800 --> 00:37:08,168 +Really nice for readability here. +看来起更具有可读性、更优雅 + +827 +00:37:08,170 --> 00:37:11,037 +But, we can actually do even better than this, +事实上,还能有更好的写法 + +828 +00:37:11,039 --> 00:37:15,074 +because Swift knows that perform operations argument +因为 Swift 的编译器知道这个函数 + +829 +00:37:15,076 --> 00:37:18,844 +returns something, you don't need this return key if your +会返回一个 Double 的值,所以你甚至都不需要使用 return + +830 +00:37:18,846 --> 00:37:22,715 +whole is just an expression like this return key word. +如果所有的代码只有一个返回语句 + +831 +00:37:22,717 --> 00:37:25,717 +You don't need that key word because it knows this is +那就不需要 return 这个关键字 + +832 +00:37:25,719 --> 00:37:27,485 +going to return something so +因为程序知道这里,你要返回什么东西 + +833 +00:37:27,487 --> 00:37:32,056 +this is just an expression it's going to return it. +这样只需要输入一个表达式就可以了,编译器知道这个表达式的值就是你想返回的值 + +834 +00:37:33,325 --> 00:37:37,260 +But it's even better than that because a swift does +而 Swift 还有一个更棒的功能是 + +835 +00:37:37,262 --> 00:37:40,597 +not force you to name these two arguments. +Swift 不强制要求你给这两个参数命名 + +836 +00:37:40,599 --> 00:37:44,967 +If you don‘t name them it will use the names $0. +如果不命名的参数的话,程序自动给参数起名为 $0 + +837 +00:37:44,969 --> 00:37:46,952 +$1, and +和 $1 + +838 +00:37:46,953 --> 00:37:48,936 +if you have more arguments, dollar 2, dollar 3, dollar 4. +如果你有更多的参数,将会命名为 $2,$3,$4... + +839 +00:37:48,939 --> 00:37:50,706 +So you don't even need this. +所以,函数名字也不要了 + +840 +00:37:52,142 --> 00:37:53,441 +Okay? +明白了吗? + +841 +00:37:53,443 --> 00:37:55,710 +So this is a function right here. +所以这里的意思是,这是一个函数 + +842 +00:37:55,712 --> 00:37:58,112 +It takes two doubles, dollar 0 and dollar 1, and +这个函数有两个 Double 类型参数,名称是 $0 和 $1 + +843 +00:37:58,114 --> 00:37:59,546 +returns a double. +返回一个 Double 类型的值 + +844 +00:37:59,548 --> 00:38:02,916 +Now Swift knows that they're doubles because it knows that +Swift 编译器知道它们是 Double 类型 + +845 +00:38:02,918 --> 00:38:04,517 +you're passing them to perform an operation. +因为你将它们传递给 performOperation + +846 +00:38:04,519 --> 00:38:07,920 +If you were passing this to some other, a function that +如果把它们传递给其他的函数 + +847 +00:38:07,922 --> 00:38:10,789 +took different kind of function as an argument, then, +这些函数有不一样的参数类型,那么 + +848 +00:38:10,791 --> 00:38:14,126 +you know, these types might be different but in this case it +$0 和 $1 的类型可能和上面不同 + +849 +00:38:14,128 --> 00:38:16,961 +knows that's what it is and it knows that it returns once +但是在这里,Swift 知道它们是什么类型 + +850 +00:38:16,963 --> 00:38:20,731 +it knows it's going to return what this calculation is. +也知道它们的计算结果是什么类型的 + +851 +00:38:21,801 --> 00:38:22,366 +All right. +明白了吗? + +852 +00:38:23,568 --> 00:38:26,536 +Now one more cool syntactic thing you can do is if you +更酷的事情是 + +853 +00:38:26,538 --> 00:38:29,305 +have a function like performOperation, and +如果你有一个 performOperation 这样的函数 + +854 +00:38:29,307 --> 00:38:32,741 +it has an argument which is a function like operation here, +有个像 operation 这样的函数作为一个参数 + +855 +00:38:32,743 --> 00:38:36,445 +if this argument is the last argument, okay, so +如果这个参数是最后一个参数 + +856 +00:38:36,447 --> 00:38:38,446 +if I had other arguments before it, and +在它之前有别的参数 + +857 +00:38:38,448 --> 00:38:42,917 +this was the argument, then you can move the function. +这是传入的参数,那么你就可以把这个函数 + +858 +00:38:43,886 --> 00:38:47,888 +Outside the parentheses, so other arguments, +移动到括号外,至于其他的参数 + +859 +00:38:47,890 --> 00:38:50,123 +if there were other arguments before, they would go in here. +如果有的话,仍旧放在括号内 + +860 +00:38:51,726 --> 00:38:54,327 +But this last argument, +但是最后的参数除外,可以放在括号之后 + +861 +00:38:54,328 --> 00:38:56,929 +which is this operation, gets to go outside the parentheses. +也就是这个 operation,可以放在括号外 + +862 +00:38:56,931 --> 00:38:59,564 +And if there are no other arguments, if this is +如果除了最后一个参数以外,没有其他的参数 + +863 +00:38:59,566 --> 00:39:02,033 +the only argument, you can actually get rid of that. +简单的说,只有一个参数时,你可以把括号也去掉 + +864 +00:39:03,870 --> 00:39:05,269 +Okay. +明白了吗? + +865 +00:39:05,271 --> 00:39:08,705 +So, we're cutting down to incredibly concise +因此,我们把我们乘法的代码变得相当简洁 + +866 +00:39:08,707 --> 00:39:13,509 +language here and we can do this exact same deal, +我们再对其他的运算做同样的事情 + +867 +00:39:13,511 --> 00:39:18,047 +of course with these other form operations. +复制粘贴这个代码 + +868 +00:39:18,049 --> 00:39:19,848 +We just need to change the. +只需要改一下算数运算符 + +869 +00:39:20,817 --> 00:39:21,382 +Nothing here. +这里不需要改 + +870 +00:39:22,585 --> 00:39:24,184 +This one, we be a little careful with the order of +除法需要注意的是参数的顺序 + +871 +00:39:24,186 --> 00:39:27,421 +operations here, we wanna do this because we +我们想把这两个参数的位置颠倒一下 + +872 +00:39:27,423 --> 00:39:30,824 +click the thing that we're dividing by on the stack last. +是因为我们希望,除数是栈中的最后一个元素 + +873 +00:39:30,826 --> 00:39:34,660 +And that's the first thing that comes off the stack. +而除数是栈中最先弹出的元素 + +874 +00:39:34,662 --> 00:39:35,494 +And same thing here actually, +同样,这里也要注意减法的参数顺序 + +875 +00:39:35,496 --> 00:39:38,163 +the subtraction minus dollar here. +$1 - $0 + +876 +00:39:38,165 --> 00:39:41,900 +Okay, so, this is our entire operate, and +好了,这就是我们的全部的运算操作 + +877 +00:39:41,902 --> 00:39:44,469 +you can see that it's incredibly concise. +你可以看到,与之前相比,这相当的简洁 + +878 +00:39:44,471 --> 00:39:45,803 +Very readable. +同时也有很高的可读性 + +879 +00:39:45,805 --> 00:39:47,504 +Times is clearly doing this function. +一眼看上去就知道这里是在做乘法 + +880 +00:39:47,506 --> 00:39:48,905 +And very extensible. +同时,这样做保证了良好的可扩展性 + +881 +00:39:48,907 --> 00:39:50,206 +If you wanna add more functions, +如果你需要添加更多的操作 + +882 +00:39:50,208 --> 00:39:51,974 +we just one liners here, +只需要这里添加一行代码 + +883 +00:39:51,976 --> 00:39:55,745 +but more these [COUGH] binary functions that have two So, +但在这里我们就只有这么多二元运算 + +884 +00:39:55,747 --> 00:39:58,814 +let's go ahead and make sure these are all working. +让我们运行一下,以确保我们应用没有问题 + +885 +00:40:02,753 --> 00:40:04,686 +All right. +好的 + +886 +00:40:04,687 --> 00:40:06,620 +So, 6 enter 5 times, that's 30, that's good. +输入 6,enter,5,乘法,结果是 30 + +887 +00:40:06,623 --> 00:40:11,291 +How about 47 plus 77, excellent. +再来,输入 47,加法,结果是 77,不错 + +888 +00:40:11,293 --> 00:40:13,593 +How about 2 divide. +再输入 2,除法 + +889 +00:40:13,595 --> 00:40:14,928 +38.5. +结果是 38.5 + +890 +00:40:14,930 --> 00:40:17,397 +[INAUDIBLE] number there. +控制台也输出同样的结果 + +891 +00:40:17,399 --> 00:40:20,299 +Working, you can see the stack doing all the right things. +一切都很好,控制台的输出也没有问题 + +892 +00:40:21,368 --> 00:40:24,102 +Okay? Make sense? +没问题吧? + +893 +00:40:24,104 --> 00:40:26,771 +Now, I'm going to do one more thing, here. +现在,我还需要做一个事情 + +894 +00:40:27,840 --> 00:40:29,473 +Which is to add another operation, +就是添加另外的一个运算操作 + +895 +00:40:29,475 --> 00:40:31,174 +this is going to be a slightly different operation. +它完成一个稍有不同的操作 + +896 +00:40:31,176 --> 00:40:32,375 +So, I'm going to copy and +这里,我复制一个运算符的按钮 + +897 +00:40:32,377 --> 00:40:35,144 +paste these operation buttons here. +然后粘贴到这里 + +898 +00:40:35,146 --> 00:40:37,880 +Again, I'm going to make sure they are lined up really +确保对齐 + +899 +00:40:37,882 --> 00:40:41,350 +nice with as many of these blue lines as I can get. +我使用这些蓝色的线来确保对齐 + +900 +00:40:42,786 --> 00:40:44,919 +I'm actually going to leave these buttons here. +我打算把按钮放在这个位置 + +901 +00:40:46,255 --> 00:40:48,389 +Because you're going to need them for your homework. +因为你们等下做课后作业的时候会需要用到 + +902 +00:40:48,391 --> 00:40:50,323 +But we gonna change this button right down here to be +我们将会让这个按钮 + +903 +00:40:50,325 --> 00:40:51,825 +a different operator. +完成成为一个不同的运算 + +904 +00:40:52,894 --> 00:40:54,760 +Which is going to be, square root. +它将是一个平方根运算符 + +905 +00:40:54,762 --> 00:40:57,629 +Which is right here, square root operator. +就在这里,一个平方根 + +906 +00:40:58,732 --> 00:40:59,297 +All right? +有什么问题吗? + +907 +00:40:59,299 --> 00:41:05,803 +And, so, I'm going to go back her to do square root, and +然后我回到这里的代码,添加一个平方根运算 + +908 +00:41:05,805 --> 00:41:07,704 +it's just another case, right. +只需要再添加一个 case 就可以搞定了 + +909 +00:41:07,706 --> 00:41:08,805 +Case square root. +case "√" + +910 +00:41:09,841 --> 00:41:12,808 +And, maybe I should just be able to use the same +也许这里我应该直接拷贝同样的代码 + +911 +00:41:12,810 --> 00:41:13,709 +mechanism, right? +对吧? + +912 +00:41:13,711 --> 00:41:14,843 +Let's see if that works. +让我们看看,这样能不能行 + +913 +00:41:15,946 --> 00:41:18,897 +Place that in there. +把它们放在这 + +914 +00:41:18,898 --> 00:41:21,849 +And instead of this bracket here, let's use the built in +把花括号里的内容删掉,用一个 + +915 +00:41:21,851 --> 00:41:25,285 +function in Swift to do square root called sqrt. +Swift 里内置的平方根运算函数,叫做 sqrt + +916 +00:41:25,287 --> 00:41:26,219 +And a dollar there. +还有一个 $0 + +917 +00:41:26,221 --> 00:41:27,187 +Looks good. +看起来不错 + +918 +00:41:27,189 --> 00:41:29,322 +And then we're ready to go. +好的,我们准备运行我们的应用 + +919 +00:41:29,324 --> 00:41:32,591 +Let's just work, call it, what's going on here. +稍等,这里好像有什么问题 + +920 +00:41:32,593 --> 00:41:35,794 +They have some sort of error, what's the problem. +好像是某种错误,是什么问题呢? + +921 +00:41:35,796 --> 00:41:36,995 +I don't understand. +我也不清楚 + +922 +00:41:36,997 --> 00:41:38,163 +Let's take a look at this. +我们来看一看 + +923 +00:41:38,165 --> 00:41:42,867 +Now this error is a little hard to understand but +这里的错误有点难理解,不过 + +924 +00:41:42,869 --> 00:41:46,970 +basically what it's saying is that you're calling +大概意思是说,你使用的这个 + +925 +00:41:46,972 --> 00:41:51,207 +performOperation here with an argument which is a function, +performOperatin 是个函数,它接受一个函数作为一个参数 + +926 +00:41:51,209 --> 00:41:54,177 +it only takes on argument. +但是这个函数只有一个参数,正常的应该是有两个参数 + +927 +00:41:54,179 --> 00:41:55,378 +Goes Swift looks here and +Swift 编译器检查了一个闭包 + +928 +00:41:55,380 --> 00:41:57,579 +it's used that it's only using a dollar zero so +发现这个函数参数只使用了一个参数 $0 + +929 +00:41:57,581 --> 00:42:00,849 +this is a one argument function this whole +也就是说这个函数只有一个参数 + +930 +00:42:00,851 --> 00:42:03,785 +curly brace thing is a function that is one argument. +大括号里只有一个参数 + +931 +00:42:03,787 --> 00:42:07,121 +Well four operation takes a function that +上面的四个运算调用的这个 performOperation 函数 + +932 +00:42:07,123 --> 00:42:08,189 +has two arguments. +有两个参数 + +933 +00:42:09,692 --> 00:42:11,591 +So that's a mismatch that doesn't work. +所以参数个数不匹配,导致了这个错误 + +934 +00:42:12,594 --> 00:42:14,694 +So how can we fix this. +那么我们来修复这个错误 + +935 +00:42:14,695 --> 00:42:16,795 +Well actually believe it or not we can just make a copy of +不管你相不相信,我们直接复制这个函数体 + +936 +00:42:16,798 --> 00:42:19,398 +form operation of another method, same name. +相同的函数名字 + +937 +00:42:19,400 --> 00:42:22,067 +This one we are gonna have different arguments. +但是这个函数与原来的函数有不同的参数个数 + +938 +00:42:22,069 --> 00:42:24,736 +It's gonna have a, an argument which is +将只有一个参数 + +939 +00:42:24,738 --> 00:42:27,605 +a function that only takes one double and returns a double. +只有一个 Double 参数,返回一个 Double 的值 + +940 +00:42:28,574 --> 00:42:30,224 +And then inside here, +然后在函数体的内部 + +941 +00:42:30,225 --> 00:42:31,875 +obviously we don't need topull two things off the stack, +显然我们不需要弹出两个元素 + +942 +00:42:31,877 --> 00:42:32,609 +just one. +只弹出一个就行了 + +943 +00:42:32,611 --> 00:42:35,645 +And obviously we only need to +同样,我们只需要确保 + +944 +00:42:35,647 --> 00:42:37,413 +check to make sure there is one thing on the stack. +栈中至少存在一个元素 + +945 +00:42:37,415 --> 00:42:41,950 +And look, all error warnings gone, okay? +现在看一看,所有的错误都消失了,对吧? + +946 +00:42:41,952 --> 00:42:44,319 +So it automatically figured out that this +所以,它自动搞清楚 + +947 +00:42:44,321 --> 00:42:46,321 +performer operation must be this one, +他必须匹配哪个 performOperation 的函数 + +948 +00:42:46,323 --> 00:42:49,857 +because this is a function that only has one argument. +因为这里只有一个参数 $0 + +949 +00:42:49,859 --> 00:42:52,460 +And so it matched it up with this version of it. +所以它匹配了只有一个参数的函数的版本 + +950 +00:42:52,462 --> 00:42:55,996 +So in Swift, you can have functions with the same name. +所以在 Swift 中,我们让函数有相同名字 + +951 +00:42:55,998 --> 00:42:58,265 +As long as they have different arguments. +只要他们有不同的参数就可以了 + +952 +00:42:58,267 --> 00:42:59,399 +And that Swift will +Swift 的编译器将会 + +953 +00:42:59,401 --> 00:43:02,168 +automatically pick the right one, if it can. +自动选择正确的一个 + +954 +00:43:02,170 --> 00:43:03,936 +There are sometimes when it's just like, +某些时候这就好比 + +955 +00:43:03,938 --> 00:43:05,971 +I can't really tell which one you mean. +你不告诉它你到底想要的是哪个 + +956 +00:43:05,973 --> 00:43:08,673 +And it will certainly complain, in that case. +在这种情况下,它当然会发牢骚了(报错) + +957 +00:43:11,378 --> 00:43:14,311 +But most of the type it's gonna be on [INAUDIBLE] from +但是,大部分情况 + +958 +00:43:14,313 --> 00:43:16,647 +the types involved, what's going on. +它会通过参数类型判断到底使用哪个函数 + +959 +00:43:16,649 --> 00:43:18,582 +So, just gonna run this one again real quick. +让我们运行一次这个程序 + +960 +00:43:18,584 --> 00:43:22,852 +[INAUDIBLE] 36 square root. +输入 36,平方根 + +961 +00:43:22,854 --> 00:43:27,423 +Looks like it's working,9 times square root. +答案正确,再输入 9,乘法,平方根 + +962 +00:43:27,425 --> 00:43:27,989 +Excellent. +很好 + +963 +00:43:29,726 --> 00:43:30,291 +Okay. +明白了吗? + +964 +00:43:31,627 --> 00:43:33,894 +All right. So, +我们继续 + +965 +00:43:33,895 --> 00:43:36,162 +the last thing I'm going to do here is work on +我们要做的最后一件事 + +966 +00:43:36,165 --> 00:43:37,431 +the layout of these buttons. +就是设置这些按钮的布局 + +967 +00:43:37,433 --> 00:43:38,531 +So that's all I'm gonna do for the code. +我用代码写的就是这么多 + +968 +00:43:38,533 --> 00:43:40,333 +You can see that we really didn't have to +你可以看到,我们实际上 + +969 +00:43:40,335 --> 00:43:41,367 +write that much code. +并没有写太多代码 + +970 +00:43:42,436 --> 00:43:45,003 +To make this work and +来让这个应用运行起来 + +971 +00:43:45,005 --> 00:43:47,939 +we got to do a lot of stuff in our UI here. +我们而是在 UI 上做了很多事 + +972 +00:43:47,941 --> 00:43:50,708 +So, let's go ahead and make it so these buttons spread out. +让我们继续,把这些按钮位置重新摆放 + +973 +00:43:50,710 --> 00:43:54,778 +Cuz right now you see all this space is wasted right here. +因为你现在可以看到,我们浪费了很多空间 + +974 +00:43:54,780 --> 00:43:57,481 +And on an iPhone in portrait mode. +如果 iPhone 在竖屏的时候 + +975 +00:43:57,483 --> 00:43:59,549 +Whole bottom space is wasted. +我们下面的空间都浪费了 + +976 +00:43:59,551 --> 00:44:01,484 +And an iPhone on landscape mode, +如果 iPhone 在横屏状态 + +977 +00:44:01,486 --> 00:44:02,685 +this whole size can be wasted. +这块区域被浪费了 + +978 +00:44:02,687 --> 00:44:04,920 +So I really want these buttons much bigger, and +所以我很想把这些按钮弄得大一些 + +979 +00:44:04,922 --> 00:44:05,687 +stretching out. +拉伸开 + +980 +00:44:07,124 --> 00:44:09,791 +Now, when you do something like that, you have to think +现在,如果你想做类似这样的事情,你需要认真 + +981 +00:44:09,793 --> 00:44:12,226 +a little bit of kind of what your strategy is gonna be. +思考一下到底应该怎么做比较合适 + +982 +00:44:12,228 --> 00:44:15,696 +You can't just kinda root four start, you know, +而不是急匆匆就开始随便就开始 + +983 +00:44:15,698 --> 00:44:17,597 +control drag it between things. +用鼠标随便拖动这些按钮之类的 + +984 +00:44:17,599 --> 00:44:20,667 +And trying to set up the horizontal spacing, +或是试着设置水平间距 + +985 +00:44:20,669 --> 00:44:24,437 +and maybe line up the, make the equal width and height. +或是对齐这些线,设置相同的宽度和高度 + +986 +00:44:24,439 --> 00:44:27,106 +Oh my gosh, you'd be control dragging all day long, +要是这么做你肯定得用鼠标拖一整天 + +987 +00:44:27,108 --> 00:44:28,374 +by doing that. + +988 +00:44:28,376 --> 00:44:30,475 +So I'm not going to use control drag to do this. +所以我不会使用鼠标拖动来做这些事 + +989 +00:44:30,477 --> 00:44:33,945 +I'm going to use these buttons down here which will kind of +我们将使用下面的这些按钮来布局 + +990 +00:44:33,947 --> 00:44:36,414 +bulk out a layout buttons. +这些按钮称之为布局按钮 + +991 +00:44:36,416 --> 00:44:40,451 +Let's go ahead and use the whole screen here. +我们先把这个界面扩大到全屏 + +992 +00:44:40,453 --> 00:44:43,620 +Document outline. +把左边栏关掉 + +993 +00:44:43,622 --> 00:44:45,939 +So what is going to be my strategy? +那么,我的策略是什么呢? + +994 +00:44:45,940 --> 00:44:48,257 +Well, my strategy is I'm going to make a perfect grid here. +我的策略就是在这做一个完美的网格 + +995 +00:44:48,260 --> 00:44:52,195 +So, I almost have one, except for there's one missing here. +目前已经差不多了,不过左下角还缺一个按钮 + +996 +00:44:52,197 --> 00:44:54,897 +So I'm actually going to take a button, copy and paste it. +所以我要复制一个按钮,然后粘贴在左下角的这个位置 + +997 +00:44:54,899 --> 00:44:59,167 +Okay, just kind of be a dummy button here actually. +把这个当做一个占位按钮就行了 + +998 +00:44:59,169 --> 00:45:00,969 +With no title. +不用添加任何标题 + +999 +00:45:00,970 --> 00:45:02,770 +I'm going to right click on it also because I don't want it +然后右键单击这个按钮,因为我不想让它 + +1000 +00:45:02,773 --> 00:45:04,939 +sending appendage or anything else, So +和 controller 里的任何 Action 或者属性关联 + +1001 +00:45:04,941 --> 00:45:06,841 +its not going to send any messages. +现在,它就不会发送任何消息了 + +1002 +00:45:06,843 --> 00:45:09,309 +But it's just a dummy, so I'm kind of using. +现在我得费点 + +1003 +00:45:09,311 --> 00:45:12,245 +A little bit of brains over brawn here to do +脑筋来思考下这里的布局 + +1004 +00:45:12,247 --> 00:45:13,680 +this perfect grid. +这个完美的网格布局 + +1005 +00:45:13,682 --> 00:45:16,916 +Now if I have this perfect grid, then if I had a rule +现在我已经有了这个网格,接下来我需要一些规则 + +1006 +00:45:16,918 --> 00:45:20,720 +where all these buttons had to be the same size, and they all +例如,这些按钮需要相同的大小尺寸 + +1007 +00:45:20,722 --> 00:45:24,857 +had the same spacing between their neighbors, not just. +所有的按钮都要和他相邻的按钮 + +1008 +00:45:24,859 --> 00:45:28,160 +Between each other but the same spacing to this edge and +有相同的间距,还要和这个边界 + +1009 +00:45:28,162 --> 00:45:30,929 +the same spacing to this top edge. +或者顶部有相同的间距 + +1010 +00:45:30,931 --> 00:45:33,631 +Okay, if I had a rule like that then they would get +如果我有这么一个规则,那么 + +1011 +00:45:33,633 --> 00:45:36,434 +big and of course the spacing is facing from this edge +我们的按钮自然就会稀疏并且 + +1012 +00:45:36,436 --> 00:45:38,035 +to edge and this edge to this edge. +与四边有相同的间距 + +1013 +00:45:38,037 --> 00:45:41,304 +If it was all the exactly the same, which I'll make it be +如果这些按钮都有相同的规则 + +1014 +00:45:41,306 --> 00:45:44,708 +whatever this is, whatever the dash for the lines gave me. +那么无论这个按钮是什么 + +1015 +00:45:44,710 --> 00:45:47,443 +If that was the same then they would all have to spread out. +如果是规则一样的话,他们将都延伸开来 + +1016 +00:45:48,479 --> 00:45:50,179 +Okay, they'd get bigger but +好的,按钮之间会变的更稀疏,但是 + +1017 +00:45:50,180 --> 00:45:51,880 +they'd all stay the same size because I'm going to +我希望他们的尺寸都保持现在的大小,因为 + +1018 +00:45:51,882 --> 00:45:54,516 +make a rule that they have to be the same size. +我将制定一个规则来使他们保持大小 + +1019 +00:45:54,518 --> 00:45:56,317 +But they would move out to this edge so +但是这些按钮将移到这边 + +1020 +00:45:56,319 --> 00:46:00,121 +that this nearest neighbor would be the same, you know, +并且最近的元素保持相同的距离 + +1021 +00:46:00,123 --> 00:46:02,322 +this distance would be the same as this distance. +例如这个按钮到右边的间距将和它到它左侧按钮的间距是一样 + +1022 +00:46:02,324 --> 00:46:05,092 +So that's my strategy, I'm going to try to do that. +这就是我的想法,我们尝试一下 + +1023 +00:46:05,094 --> 00:46:06,760 +Now to make that work, +现在就开始 + +1024 +00:46:06,762 --> 00:46:09,128 +all these buttons need to know who their nearest neighbor is. +所有这些按钮需要知道他们的最近的元素是谁 + +1025 +00:46:09,130 --> 00:46:11,564 +Well, these all know their nearest neighbor here, +好,这些都知道他们的最近的元素 + +1026 +00:46:11,566 --> 00:46:13,999 +the other buttons, because I made sure I used dashed +也就是其他按钮的,因为当我拖拽它们时 + +1027 +00:46:14,001 --> 00:46:17,035 +blue lines when I dragged them in there. +我确保使用的蓝色虚线来对齐它们 + +1028 +00:46:17,037 --> 00:46:18,303 +So, that's what kind of +这也是某种 + +1029 +00:46:18,305 --> 00:46:19,904 +teaches them their nearest neighbor. +确定它们最近的元素的一种方式 + +1030 +00:46:19,906 --> 00:46:22,573 +And I'm also going to make sure that the entire grid +接下来,我要确保整个网格 + +1031 +00:46:22,575 --> 00:46:25,442 +knows that the left edge and +知道它的左边界 + +1032 +00:46:25,444 --> 00:46:29,046 +just under the label there, our nearest neighbor. +并且,知道它就位于这个标签的下面 + +1033 +00:46:29,048 --> 00:46:30,447 +So now it knows on the top, +现在,它知道 + +1034 +00:46:30,449 --> 00:46:32,348 +the nearest neighbor is the label, and +离它最近的顶部元素是这个标签,并且 + +1035 +00:46:32,350 --> 00:46:34,383 +on the left is this edge. +离它最近的左边元素是这个边界 + +1036 +00:46:34,385 --> 00:46:37,386 +And it's going to pick this edge as +我们要做的就是让这些按钮知道,右侧的边界是离他们最近的右侧元素 + +1037 +00:46:37,388 --> 00:46:39,888 +the nearest neighbor for these buttons and the bottom edge, +底部的边界是离他们最近的底部元素 + +1038 +00:46:39,890 --> 00:46:41,356 +cuz that's all there is and +因为这儿没有其他的东西 + +1039 +00:46:41,357 --> 00:46:42,823 +nothing else out here that's gonna become, +可以成为这些按钮的最近的元素 + +1040 +00:46:42,826 --> 00:46:45,326 +that's the only neighbor there is, it's gonna pick those. +它们只能选择这两个边界 + +1041 +00:46:47,263 --> 00:46:48,962 +So now that I've used my dash for +那么,现在我已经使用这些虚线 + +1042 +00:46:48,964 --> 00:46:51,898 +the lines it makes this all quite easy. +这将变的很容易 + +1043 +00:46:51,900 --> 00:46:53,866 +Now, if you don't use the dash for the lines, or +如果你不使用这些虚线 + +1044 +00:46:53,868 --> 00:46:56,602 +if you make some mistakes then it's not going to work. +或者你搞错了什么的话,它就不会有效的 + +1045 +00:46:56,604 --> 00:47:00,305 +This strategy won't work and I've made doing this part of +我做的这部分演示 + +1046 +00:47:00,307 --> 00:47:03,809 +this demonstration be extra credit. +是额外的 + +1047 +00:47:03,811 --> 00:47:06,044 +And so if you can't get it, don't worry about it too much, +因此,如果你不能做到或者不明白的话,也不必太担心 + +1048 +00:47:06,046 --> 00:47:09,247 +just keep all your buttons in the upper left corner here +只需保持你所有的按钮在左上角 + +1049 +00:47:09,249 --> 00:47:11,199 +and that's fine. +这就好了 + +1050 +00:47:11,200 --> 00:47:13,150 +But if you want to give this a try, the key is to +但是如果你想尝试一下我所做的 + +1051 +00:47:13,152 --> 00:47:15,753 +use the dash lines to make the perfect grid. +重点是使用虚线,来确保整个按钮网格是对齐的 + +1052 +00:47:15,755 --> 00:47:18,822 +Make sure that you set the nearest neighbors here by +同时通过拖拽整个网格确保你将左侧边界和这个标签 + +1053 +00:47:18,824 --> 00:47:23,793 +dragging the whole grid to make blue lines appear on the sides. +设置为离这些按钮最近的上部元素和左侧元素 + +1055 +00:47:23,795 --> 00:47:26,962 +And then, we are going to set these rules in bulk and +然后,我们来设置这些规则 + +1056 +00:47:26,964 --> 00:47:29,965 +we do that with these buttons down here. +我们可以用下面的这些按钮 + +1057 +00:47:29,966 --> 00:47:32,967 +So there's this button right here the left most button and +在最左边的这个按钮 + +1058 +00:47:32,969 --> 00:47:36,337 +it let's you set things like lining up leading edges or +它可以设置左边对齐 + +1059 +00:47:36,339 --> 00:47:37,872 +the tops or the centers. +上边对齐或者居中 + +1060 +00:47:37,874 --> 00:47:40,174 +And you could imagine there might be a way to do this by +也许你能想到,利用这些,可以实现我们想要的布局 + +1061 +00:47:40,176 --> 00:47:42,542 +doing that but I am not going to use that strategy. +但是我们在这里不会这么做 + +1062 +00:47:42,544 --> 00:47:45,045 +My strategy is just make them the same size and +我的方法就是让它们的大小一样 + +1063 +00:47:45,047 --> 00:47:48,447 +make the space in between them, be the same. +并且它们之间的间距也一样 + +1064 +00:47:49,617 --> 00:47:51,450 +But, I bet there's probably a way to do it by +但是,我相信,也许通过中点的方式 + +1065 +00:47:51,452 --> 00:47:54,919 +lining up their centers, or something like that, too. +或者类似的方式也可以做到一样的效果 + +1066 +00:47:54,921 --> 00:47:56,921 +So I'm not going to use this one. +因此,我这里不打算使用个按钮 + +1067 +00:47:56,923 --> 00:47:59,357 +The next one over, +下一个按钮 + +1068 +00:47:59,358 --> 00:48:01,792 +right here, is the one that has the things I want. +这里就有我想要的东西 + +1069 +00:48:01,794 --> 00:48:04,094 +And so you can see that it'll ask you to +正如你所看见的,它会让你选择 + +1070 +00:48:04,096 --> 00:48:06,196 +make all the buttons equal widths and heights. +是否让所有按钮的宽度相等、高度相等 + +1071 +00:48:06,198 --> 00:48:07,464 +Okay, not width and +没有勾选的这两个选项(Width,Height) + +1072 +00:48:07,466 --> 00:48:09,832 +height, that fixes them at a certain width and +是用来将它们修改成某个特定的宽度和高度的 + +1073 +00:48:09,834 --> 00:48:12,401 +height, this means that there,they can be any width and +但是这里的意思是,对于所有的这些按钮,宽度和高度可以是任意的值 + +1074 +00:48:12,403 --> 00:48:14,803 +height they want, but they all have to be the same width and +但是他们必须拥有相同的宽度和相同的高度 + +1075 +00:48:14,805 --> 00:48:16,938 +height all these buttons. + +1076 +00:48:16,940 --> 00:48:18,840 +Of course I had these all selected by the way, if you +当然,我把这些按钮都选中了 + +1077 +00:48:18,842 --> 00:48:20,842 +don't have them selected it doesn't make any sense. +如果你没选中那就不会应用这些规则 + +1078 +00:48:22,011 --> 00:48:23,711 +And then up here, you can see there is spacing to +然后在这里,你可以看到这是一个 Spacing to + +1079 +00:48:23,713 --> 00:48:25,679 +nearest neighbor, so this is where I am going to set +nearest neighbor 的面板,我们把这些 + +1080 +00:48:25,681 --> 00:48:29,716 +that spacing between all these, to be the same. +按钮之间的间距设为一样 + +1081 +00:48:29,718 --> 00:48:31,417 +And you can see that it's put eight here. +正如你所看到的,这里设置为 8 + +1082 +00:48:31,419 --> 00:48:33,585 +That's because when I did the dash lines +这是因为当我使用虚线对齐元素时 + +1083 +00:48:35,022 --> 00:48:39,323 +to the top eight seems to be kind of a standard number of +标准的间距就是 8 个像素点 + +1084 +00:48:39,325 --> 00:48:42,727 +points between elements. + +1085 +00:48:42,729 --> 00:48:45,429 +These are all multiple because some of these buttons, +这里显示所有的左间距为 Multiple,那是因为这些按钮中 + +1086 +00:48:45,431 --> 00:48:48,432 +their nearest neighbor is way over here and it's huge. +有些最近的元素是右边界,这是一个巨大的数值 + +1087 +00:48:48,434 --> 00:48:50,250 +All right. +明白了吗? + +1088 +00:48:50,251 --> 00:48:52,067 +The bottom or their right. +最近的下边元素和右边元素的数值不一样导致 Multiple + +1089 +00:48:52,070 --> 00:48:55,838 +But all these buttons,the thing on top, +所有这些按钮,最近的上部元素 + +1090 +00:48:55,840 --> 00:48:58,274 +whether it's another button or whether it's this label, +无论是另一个按钮或者是这个标签 + +1091 +00:48:58,276 --> 00:49:01,343 +all of them happen to be this eight points right here. +他们的间距都是 8 个像素点 + +1092 +00:49:01,345 --> 00:49:03,178 +So I want all of these to be eight. +我想让这些都设置为 8 个像素点 + +1093 +00:49:03,180 --> 00:49:07,482 +So I'm just going to turn this bar on right here, which says, +在这里我们打开这一栏 + +1094 +00:49:07,484 --> 00:49:11,018 +yes please enforce, and make the rule that all of +“ 请确保这些所有 + +1095 +00:49:11,020 --> 00:49:15,255 +these are 8 points from their nearest neighbor to the top. +按钮的到距离它顶部最近元素距离为 8 个像素点 ” + +1096 +00:49:15,257 --> 00:49:18,124 +And also, 8 to the left,8 to the right, and +同样,左边间距为 8 个像素点,右边间距为 8 个像素点 + +1097 +00:49:18,126 --> 00:49:19,459 +8 to the bottom. +底部间距也为 8 个像素点 + +1098 +00:49:19,461 --> 00:49:21,060 +Really wanna make sure these beams are on, +确保这里是打开的 + +1099 +00:49:21,062 --> 00:49:23,362 +if these beams are off,even if there's a number here, +如果他是关闭的,即使这里有数字 + +1100 +00:49:23,364 --> 00:49:24,963 +then it's not gonna add this rule. +也不会添加规则的 + +1101 +00:49:24,965 --> 00:49:26,998 +So we wanted to add this rule.· +我们想要添加这些规则 + +1102 +00:49:27,000 --> 00:49:30,101 +So this adds up to +87 different rules. +所以总共有 87 个不同的规则 + +1103 +00:49:30,103 --> 00:49:32,554 +All these equal widths and +所有相同宽度,相同高度 + +1104 +00:49:32,555 --> 00:49:35,006 +heights and all these So if you don't have 87 in here, +以及这些,如果你的规则的数目不是 87 + +1105 +00:49:35,008 --> 00:49:36,974 +if it says a hundred and something, +假如是 100 或者其它, + +1106 +00:49:36,976 --> 00:49:39,209 +probably you don't have everything lined up right. +那么很可能你没有将所有东西正确对齐起来 + +1107 +00:49:39,211 --> 00:49:43,279 +It only takes 87 constraints to express all these rules. +只需要 87 个规则就可以表示我们想要的网格布局 + +1108 +00:49:44,482 --> 00:49:45,547 +All right. +明白了吗? + +1109 +00:49:45,549 --> 00:49:48,316 +Now, when I click this Add 87 Constraints it's +现在,如果我按下 “Add 87 Constraints” + +1110 +00:49:48,318 --> 00:49:51,886 +going to add these rules to all these buttons, and +就会在这些按钮上添加这些规则 + +1111 +00:49:51,888 --> 00:49:52,787 +watch what happens. +看看会发生什么 + +1112 +00:49:54,790 --> 00:49:56,723 +So, I get all kinds of, +嗯,我得到了很多的线 + +1113 +00:49:56,725 --> 00:49:59,392 +first these blue lines are showing me the rules. +首先这些蓝色的线表示规则 + +1114 +00:49:59,394 --> 00:50:01,094 +'Kay? A lot them are saying here +许多蓝色的线代表这里 + +1115 +00:50:01,096 --> 00:50:03,062 +that things are equal widths and heights. +的按钮都是相同长度和宽度的 + +1116 +00:50:03,064 --> 00:50:05,531 +So these are what equals rules means. +这就是 equals 规则的意思 + +1117 +00:50:05,533 --> 00:50:08,700 +But there's also tiny little I beams right up here. +这里还有一些小的 I 形状的线 + +1118 +00:50:08,702 --> 00:50:13,671 +That are showing this basing to nearest neighbor, and +I 行的线表示以最近的物体为基准 + +1119 +00:50:13,673 --> 00:50:16,073 +also like there's a yellow, yellow here. +这里还有一些黄色的线 + +1120 +00:50:16,075 --> 00:50:18,409 +This yellow, remember, means yeah, +记住,这些黄色的线代表 + +1121 +00:50:18,411 --> 00:50:21,044 +there's constraints on these, but they're not actually where +这里虽然有一些规则,但是这些东西的位置本不应该 + +1122 +00:50:21,046 --> 00:50:23,113 +they're supposed to be based on those rules. +放置在这里,也就是说,目前的位置和预想的位置有偏差 + +1123 +00:50:24,049 --> 00:50:27,016 +So we really want to move them all to be in their +我们很需要将这些按钮,按照这些规则 + +1124 +00:50:27,018 --> 00:50:29,852 +proper spaces based on these rules. +移动到合适的地方 + +1125 +00:50:29,854 --> 00:50:31,753 +That's what these dashed yellow lines mean. +这就是这些黄色的线的意思 + +1126 +00:50:31,755 --> 00:50:33,221 +So we can do the same thing to do that, +我们可以像按刚开始 + +1127 +00:50:33,223 --> 00:50:36,224 +that we did at the beginning with the label on the top +处理顶部的标签那样 + +1128 +00:50:36,226 --> 00:50:38,225 +which is go to our document outline here, +点击左下角的 document outline 菜单 + +1129 +00:50:38,227 --> 00:50:39,393 +in the lower left corner. + +1130 +00:50:39,395 --> 00:50:42,929 +Okay these are document outline when we last saw it, +这些是 UI 文档的缩略图,上一次我们查看时 + +1131 +00:50:42,931 --> 00:50:45,331 +it only had this one label in there. +只有这一个标签在这里 + +1132 +00:50:46,401 --> 00:50:47,700 +Now we got all these buttons added. +现在把所有的按钮都添加上来了 + +1133 +00:50:47,702 --> 00:50:50,002 +And you can see they're all selected. +而且你看到这些按钮都处于选中状态 + +1134 +00:50:50,004 --> 00:50:52,304 +All selected here as well. +在 Storyboard 中也处于全部选中的状态 + +1135 +00:50:52,306 --> 00:50:54,673 +And, we've got this little yellow thing up here. +这上面有一个黄色的小箭头 + +1136 +00:50:54,675 --> 00:50:58,643 +Now, if this is red, okay, if you do all this and +如果这里是红色箭头,如果你做了之前的这些操作 + +1137 +00:50:58,645 --> 00:51:02,747 +this is red, well that means that you've got not just +并且是红色箭头,那就意味着你所添加的 + +1138 +00:51:02,749 --> 00:51:05,516 +warnings that your constraints aren't in the right place, but +规则不仅是警告,警告你目标的位置和预期的规则不同 + +1139 +00:51:05,518 --> 00:51:08,452 +you've got errors, usually conflicting constraints, +而且有错误,错误通常是由规则之间的冲突所引起 + +1140 +00:51:08,454 --> 00:51:11,721 +where you've asked auto layout to +当你让自动布局强制 + +1141 +00:51:11,723 --> 00:51:13,890 +enforce two rules that conflict with each other. +实施两种相互冲突的规则时 + +1142 +00:51:13,892 --> 00:51:17,626 +So if you get to that red, this is not going to work. +所以如果箭头是红色,这些规则就不会正常工作 + +1143 +00:51:17,628 --> 00:51:20,295 +So, you'll want to start over, and +这是,你可能想重新再设置一遍 + +1144 +00:51:20,297 --> 00:51:23,432 +I'll show you in a minute how you can start over if things, +我稍后为大家展示怎么再重新开始 + +1145 +00:51:23,434 --> 00:51:26,234 +or not going your way, but if it's yellow that just means +如果和你想的不同,黄色箭头 + +1146 +00:51:26,236 --> 00:51:27,201 +things were in the wrong place. +仅代表有些东西在错误的位置 + +1147 +00:51:27,203 --> 00:51:29,136 +So no problem, we click the yellow. +很简单,点击黄色箭头 + +1148 +00:51:29,138 --> 00:51:30,637 +Here's all the things that were in the wrong place. +这里是在错误位置的东西 + +1149 +00:51:30,639 --> 00:51:31,972 +This is all the buttons, +这是所有的按钮 + +1150 +00:51:31,974 --> 00:51:34,274 +you can see they highlight as I mouse over them. +你可以看到当鼠标移到按钮上时,对应的按钮高亮 + +1151 +00:51:34,276 --> 00:51:38,077 +And you can really pick on any one of them to fix this +你可以任意选一个来修改 + +1152 +00:51:38,079 --> 00:51:40,880 +because there's a nice little switch here called apply to +因为这里有一个很方便的复选框,它代表 + +1153 +00:51:40,882 --> 00:51:42,047 +all views and containers. +将修改应用到所有视图(views)和容器(containers) + +1154 +00:51:42,049 --> 00:51:44,116 +You don't have to click on each one and +你就不必每一个都点击 + +1155 +00:51:44,118 --> 00:51:46,985 +have it to frame update to the proper thing. +使它的 frame 更新到合适的大小 + +1156 +00:51:46,987 --> 00:51:50,588 +You can just click quite obvious in container and it's +你可以很容易的选中复选框 + +1157 +00:51:50,590 --> 00:51:55,125 +going to move the frame of all the buttons to fix the fact +这样就会移动所有按钮的 frame,修改 + +1158 +00:51:55,127 --> 00:51:57,494 +that they're in the wrong place based on their rules. +那些处于错误位置的 + +1159 +00:51:57,496 --> 00:51:59,096 +So let's try that. +让我们试试看 + +1160 +00:51:59,097 --> 00:52:00,697 +I'm gonna hit this button here, Fix Misplacement. +我要点击这个按钮,“Fix Misplacement” + +1161 +00:52:01,933 --> 00:52:03,032 +And it moved them all. +所有的按钮都移动了 + +1162 +00:52:03,034 --> 00:52:03,966 +There's no more yellow. +没有黄色的警告了 + +1163 +00:52:03,968 --> 00:52:06,101 +There's no auto layout issues. +没有自动布局的问题了 + +1164 +00:52:06,103 --> 00:52:07,435 +Okay. All looks good here. +看起来不错 + +1165 +00:52:07,437 --> 00:52:09,070 +We can close our document outline. +可以关闭 document outline 视图了 + +1166 +00:52:10,306 --> 00:52:13,440 +We zoom out, we can see, wow, it spread them all out. +将视图缩小,可以看到按钮充满了整个视图 + +1167 +00:52:13,442 --> 00:52:14,675 +Okay? Because, + +1168 +00:52:14,677 --> 00:52:18,444 +maybe it's obeying those rules I gave it. +因为他们都遵守我定下的规则 + +1169 +00:52:18,446 --> 00:52:20,079 +Okay? + +1170 +00:52:20,080 --> 00:52:21,713 +So let's now run this on some devices here and +现在,试试在不同的设备上运行 + +1171 +00:52:21,716 --> 00:52:23,182 +see what this looks like. +看看结果会怎样 + +1172 +00:52:26,220 --> 00:52:30,221 +So turn off on an iPhone 6, which is a pretty tall device. +在 特别长的 iPhone 6 上 + +1173 +00:52:30,223 --> 00:52:32,790 +It's made, you know, kind of tall and thin. +iPhone 6 做的既长又窄 + +1174 +00:52:32,792 --> 00:52:35,459 +So if this still works fine enter. +一切正常 + +1175 +00:52:35,461 --> 00:52:39,763 +69874 times 5 divide maybe square root something like +输入 5,enter,69874,乘法,5,除以,开平方根 + +1176 +00:52:39,765 --> 00:52:44,266 +that, it all seems to be working. +看起来运行正常 + +1177 +00:52:44,268 --> 00:52:48,804 +Now, not only is it working here in this portrait mode, +自动布局不但在 iPhone 竖屏时工作正常 + +1178 +00:52:48,806 --> 00:52:51,023 +tall and thin. +既长又窄的情况 + +1179 +00:52:51,024 --> 00:52:53,241 +But if we go over here to this we can rotate the device. +如果我们从这里旋转设备 + +1180 +00:52:54,277 --> 00:52:55,843 +Okay, so I'm going to rotate left and +我要通过 ⌘ + 左,右键来 + +1181 +00:52:55,845 --> 00:52:58,979 +right and use the command keys to do this. +旋转设备 + +1182 +00:52:58,981 --> 00:53:02,449 +And we rotate it right and you see it +设备向右转可以看到 + +1183 +00:53:02,451 --> 00:53:08,220 +may the buttons spread out to this new location and +按钮均匀分布到新的位置 + +1184 +00:53:09,190 --> 00:53:13,491 +we can rotate back using the command keys here. +可以用 ⌘ + 左,右键将设备转回来 + +1185 +00:53:14,627 --> 00:53:17,461 +And it looks good in either orientation. +可以看到,在两个方向上看起来都不错 + +1186 +00:53:17,463 --> 00:53:21,465 +And in fact, it can look good on other devices as well. +实际上,在其他设备上同样看起来很棒 + +1187 +00:53:21,467 --> 00:53:23,066 +So let's go over here and +点击这里 + +1188 +00:53:23,068 --> 00:53:26,235 +instead of doing iPhone 6, let's try it on an iPhone 4S. +这次不用 iPhone 6,试一下 iPhone 4S 上的效果 + +1189 +00:53:26,237 --> 00:53:27,937 +Okay so, + +1190 +00:53:27,939 --> 00:53:32,407 +gonna switch the simulation here, let's run that. +切换模拟器,运行 + +1191 +00:53:34,077 --> 00:53:37,345 +Now the iPhone 4s, you can see is a little shorter, +现在是 iPhone 4S,它看起来短一点 + +1192 +00:53:37,347 --> 00:53:39,280 +it's not quite as tall. +并没有那么长 + +1193 +00:53:39,282 --> 00:53:42,416 +A little lower resolution, obviously. +很明显,分辨率也有些低 + +1194 +00:53:42,418 --> 00:53:46,986 +But it relayed out the buttons to look good in that case too. +但是在这种情况下也将按钮的位置摆放的很棒 + +1195 +00:53:46,988 --> 00:53:52,558 +9 times 9, divided by 8, square root, et cetera. +输入 9,enter,9,乘法,8,除法,开平方等等 + +1196 +00:53:52,560 --> 00:53:56,995 +And same thing here we can rotate and +同样我们可以旋转 + +1197 +00:53:56,997 --> 00:54:00,131 +look at this one as well. +这样看起来也不错 + +1198 +00:54:00,133 --> 00:54:03,067 +Okay. +明白了吗? + +1199 +00:54:03,069 --> 00:54:05,019 +All righty. +好的 + +1200 +00:54:05,020 --> 00:54:06,970 +So the last thing I just want to talk about briefly is if +最后我想简单说下 + +1201 +00:54:06,973 --> 00:54:10,207 +you try this extra credit and it doesn't work for you. +你尝试得到额外加分,这是行不通的 + +1202 +00:54:10,209 --> 00:54:16,413 +Get all messed up, you can kind of start over by clicking +打乱所有限制,你可以通过点击 + +1203 +00:54:16,415 --> 00:54:21,450 +on this and using the third button over here on the right. +这个位置并使用右边第三个按钮重新开始 + +1204 +00:54:21,452 --> 00:54:23,852 +And this allows you to reset your constraints and +这里允许你重置你的约束, + +1205 +00:54:23,854 --> 00:54:26,688 +you can see the top section here is the selected views. +你能看到上面的部分是被选中的视图 + +1206 +00:54:26,690 --> 00:54:27,922 +I don't have any selected here so +我这里没有任何选中的视图,因此 + +1207 +00:54:27,924 --> 00:54:29,257 +this wouldn't do anything right now. +现在这里不能做任何操作 + +1208 +00:54:29,259 --> 00:54:31,659 +But the bottom is all views in container and +但是下面的部分是容器内的所有视图 + +1209 +00:54:31,661 --> 00:54:34,161 +I kinda recommend going down here to all views +我推荐到下面所有视图 + +1210 +00:54:34,163 --> 00:54:37,164 +container and clearing the constraints entirely. +容器内并清除所有约束 + +1211 +00:54:37,166 --> 00:54:40,000 +Reset to suggested constraints and try and +重置到建议的约束条件, + +1212 +00:54:40,002 --> 00:54:44,437 +make some sense of your dashed lines but if it's not working, +但如果不工作, + +1213 +00:54:44,439 --> 00:54:47,673 +you're probably, you're dashed lines are off anyway. +你很可能, + +1214 +00:54:47,675 --> 00:54:49,875 +So you can just go here and +因此你仅仅需要到这里 + +1215 +00:54:49,877 --> 00:54:51,343 +Clear Constraints, that'll clear them all. +清除所有约束条件,这将清除所有限制 + +1216 +00:54:51,345 --> 00:54:53,211 +Now that's gonna clear not just your buttons but +现在不仅仅需要清除你的按钮,而且 + +1217 +00:54:53,213 --> 00:54:55,880 +also it's gonna clear your labels. +需要清除你的标签 + +1218 +00:54:55,882 --> 00:54:59,450 +So you'll have to reposition your label with blue lines and +所以你必须使用蓝色线条重新放置你的标签并且 + +1219 +00:54:59,452 --> 00:55:02,953 +use control drag to say your top space, and, and +拖拽来确定你上部的空间 + +1220 +00:55:02,955 --> 00:55:05,388 +all that stuff, you know? +所有东西,了解? + +1221 +00:55:05,390 --> 00:55:08,458 +If your buttons are really huge, they got really huge, +如果你所有按钮确认很大,他们会变得很大, + +1222 +00:55:08,460 --> 00:55:10,726 +but they're not in the right place, you can actually change +但是他们不能在正确的位置,你可以根据实际情况在工具窗口中调整 + +1223 +00:55:10,728 --> 00:55:13,595 +the size of all your buttons in the utilities window. +你的按钮的大小 + +1224 +00:55:14,565 --> 00:55:16,164 +You can go to the size inspector right here, +有可以到尺寸查看器这里 + +1225 +00:55:16,166 --> 00:55:19,467 +that's this one, you can actually type in the width and +这个位置你可以输入所期望按钮的实际宽度和 + +1226 +00:55:19,469 --> 00:55:22,370 +the height you want the buttons to be, make them +高度,确保他们 + +1227 +00:55:22,372 --> 00:55:25,272 +smaller again, which, you know, maybe 64 by 64. +再次变小,就像你所知道的那样 可能是 64 x 64 + +1228 +00:55:25,274 --> 00:55:29,376 +That might make them easier to re-drag them into position so +这可以是他们变得容易再次拖拽到适当位置, + +1229 +00:55:29,378 --> 00:55:31,210 +the blue lines are working. +蓝色线条正常工作 + +1230 +00:55:32,313 --> 00:55:36,015 +And don't forget the very important blue line dragging, +不要忘记这个很重要的蓝色线条的拖拽, + +1231 +00:55:36,017 --> 00:55:38,283 +which is you want to take the whole grid and drag it, +你想要拖拽挣个格栏, + +1232 +00:55:38,285 --> 00:55:40,285 +so that it's sitting underneath your label. +以至于它在你标签下方 + +1233 +00:55:41,654 --> 00:55:44,021 +If you have problems dragging the whole grid underneath your +如果你拖拽你标签下面的整个格栏有问题, + +1234 +00:55:44,023 --> 00:55:46,490 +label, sometimes it's a good idea, clear all +通常清除所有约束限制是个好的做法 + +1235 +00:55:46,492 --> 00:55:48,892 +your constraints, kind of move your buttons out of the way, +移动你的按钮到远处, + +1236 +00:55:48,894 --> 00:55:51,761 +just kind of move them down to the bottom here and then +仅仅移动他们到底部,然后 + +1237 +00:55:51,763 --> 00:55:56,132 +just for your label, do reset to suggest your constraint. +对你的标签,做重置到建议的约束条件 + +1238 +00:55:56,134 --> 00:55:57,499 +This top one selected view +最上面那个被选中的视图, + +1239 +00:55:57,501 --> 00:56:01,036 +Rest Suggestion Constraints cuz that will work for +重置建议的约束条件英文这将对你的标签起作用 + +1240 +00:56:01,038 --> 00:56:03,204 +the label if you move it into position as long as +你可以移动他倒适当位置只要 + +1241 +00:56:03,206 --> 00:56:06,407 +the buttons aren't too close and it thinks that, you know. +按钮们不要靠的太近 + +1242 +00:56:06,409 --> 00:56:08,042 +Those buttons are near neighbors or something. +这些按钮是进邻或者其他什么 + +1243 +00:56:09,145 --> 00:56:11,945 +And sometimes resetting it to suggest the constraints will +一些情况,重置到推荐约束 + +1244 +00:56:11,947 --> 00:56:17,483 +make it so that, that bottom edge of your UI label will +能做到,UI 标签下边缘是 + +1245 +00:56:17,485 --> 00:56:21,253 +be attainable when you drag your buttons into position. +可以达到的,当你拖拽一个按钮到一个位置 + +1246 +00:56:22,289 --> 00:56:23,538 +But again, not to +但是,不要 + +1247 +00:56:23,539 --> 00:56:24,788 +worry too much about this auto layout stuff. +太担心界面自动布局的内容 + +1248 +00:56:25,825 --> 00:56:27,158 +It's extra credit in assignment one. +这是作业一的额外加分 + +1249 +00:56:27,160 --> 00:56:29,493 +It's not going to be extra credit in assignment two, +到了作业二就不是额外加分了 + +1250 +00:56:29,495 --> 00:56:31,728 +so you're eventually going to have to do it. +最终你都要做这件事 + +1251 +00:56:31,730 --> 00:56:34,197 +I'm going to be giving a big lecture on this in a couple of +我将花好几个星期给你们好好讲一下 + +1252 +00:56:34,199 --> 00:56:35,465 +weeks, on auto layout. +自动布局 + +1253 +00:56:35,467 --> 00:56:38,968 +I've really just shown you just kind of what it can do, +我仅仅向你们展示了它的小小一角 + +1254 +00:56:38,970 --> 00:56:41,770 +I haven't really taught you how to do +我以前没有教你们如何设置 + +1255 +00:56:41,772 --> 00:56:43,338 +auto layout in particular. +自动布局 + +1256 +00:56:44,374 --> 00:56:48,409 +Auto layout is very important because we work in this +自动布局十分重要因为我们 + +1257 +00:56:48,411 --> 00:56:50,745 +square area and +在这个方框被做工作 + +1258 +00:56:50,746 --> 00:56:53,080 +we want our UIs to work on all kinds of different devices. +我想要我们的界面能再各种不同设备上正常工作 + +1259 +00:56:53,082 --> 00:56:54,614 +That's why we're starting off in the very +这也是我们用它 + +1260 +00:56:55,584 --> 00:56:57,717 +start with some experience with it. +作为入门的原因 + +1261 +00:56:59,820 --> 00:57:00,686 +All right. +好了 + +1262 +00:57:00,688 --> 00:57:02,520 +So that is it. +就这样 + +1263 +00:57:02,522 --> 00:57:06,190 +Now, later today, I'm gonna, in this lecture, +稍后,这次课中 + +1264 +00:57:06,192 --> 00:57:10,828 +I'm gonna give you a talk about this design paradigm +我将要给你讲关于设计模式 + +1265 +00:57:10,830 --> 00:57:14,197 +called model-view-controller, and we actually designed our +叫做 模型 - 视图 - 控制器,事实上我们设计的 + +1266 +00:57:14,199 --> 00:57:17,300 +calculator kind of poorly, because all of +计算器很差,因为这里的所有 + +1267 +00:57:17,302 --> 00:57:20,436 +this code here is really nothing to do with UI. +代码和界面没有任何关系 + +1268 +00:57:20,438 --> 00:57:26,141 +This is all calculator brain, calculator engine code. +这是所有计算器的核心,计算器的引擎代码 + +1269 +00:57:26,143 --> 00:57:28,143 +And this really wants to meet a different object and +这里需要接触一个不同的对象, + +1270 +00:57:28,145 --> 00:57:30,211 +that's what MVC is all about. +这也就是 MVC + +1271 +00:57:30,213 --> 00:57:33,648 +And so I'll give a little talk about MVC later today. +今天稍后我将讲关于 MVC 的内容 + +1272 +00:57:33,650 --> 00:57:36,650 +And then on Monday, we're going to fix our calculator +然后再周一,我们将要解决我们计算器的问题, + +1273 +00:57:36,652 --> 00:57:41,855 +to obey MVC and be a proper citizen in the iOS world, +达到遵循 MVC 架构,并成为 iOS 世界里的一员, + +1274 +00:57:41,857 --> 00:57:45,258 +where all apps need to obey model V controller paradigm. +在这里所有的程序都需要遵循 MVC 模式 + +1275 +00:57:46,294 --> 00:57:49,261 +>> So let's try and +understand for, I mean half of +来让我们尝试并理解,据你们说过半的人 + +1276 +00:57:49,263 --> 00:57:52,764 +you said that you already know MVC or you've seen it +知道 MVC 或者在其他 + +1277 +00:57:52,766 --> 00:57:54,499 +somewhere else so, this is going to be mostly review. +地方听过它,因此这里将是复习 + +1278 +00:57:54,501 --> 00:57:57,769 +But the other half of you, this will hopefully give you +另外一半人,这里将给你 + +1279 +00:57:57,771 --> 00:58:00,705 +an idea of what MVC is all about. +一个 MVC 相关的概念 + +1280 +00:58:00,707 --> 00:58:04,975 +So MVC is basically a mechanism where we divide up +MVC 是一个基本机制,用于分类 + +1281 +00:58:04,977 --> 00:58:09,379 +all the objects in our application into one of +程序中的所有对象到 + +1282 +00:58:09,381 --> 00:58:11,180 +these three camps. +三个营地中的任意一个 + +1283 +00:58:11,182 --> 00:58:12,281 +Okay? +了解? + +1284 +00:58:12,283 --> 00:58:14,182 +So, the three camps. +三个营地 (或者叫三层) + +1285 +00:58:14,184 --> 00:58:15,884 +On the left there you see the model. +在左边你看到的是模型 + +1286 +00:58:15,886 --> 00:58:19,220 +So, the model camp is gonna be all the objects that are what +模型层是那些对象的集合,这些对象是 + +1287 +00:58:19,222 --> 00:58:21,355 +your application does. +是程序的行为 + +1288 +00:58:21,357 --> 00:58:24,858 +So, for our calculator its, it calculates. +在我们计算器中,计算是模型 + +1289 +00:58:24,860 --> 00:58:26,794 +Okay, that's what it does. +那是计算器要做的 + +1290 +00:58:26,795 --> 00:58:28,729 +So, all the parts what we're doing perform operation, and +我们用于做执行操作的部分,和 + +1291 +00:58:28,731 --> 00:58:32,098 +all that stuff, that's all kind of calculator stuff. +相关材料,也就是计算器相关的内容 + +1292 +00:58:32,100 --> 00:58:35,935 +That should be in a calculator object somewhere else, +那些应属于计算器对象 + +1293 +00:58:35,937 --> 00:58:37,569 +it shouldn't be in our controller. +不应该在我们的控制器中 + +1294 +00:58:38,639 --> 00:58:43,841 +And then the second camp is the controller, the controller +第二个阵营叫做 controller ,controller + +1295 +00:58:43,843 --> 00:58:48,178 +controls how the model is presented on screen. +控制模型是如何显示在屏幕上 + +1296 +00:58:48,180 --> 00:58:51,348 +And the view is the minions, the classes that +视图是 controller 要 + +1297 +00:58:51,350 --> 00:58:52,916 +the controller is going to use are kind of +用到的的附属类,有点类似于 + +1298 +00:58:52,918 --> 00:58:55,485 +like the the building blocks, the Lincoln Logs, +像积木,林肯积木, + +1299 +00:58:55,487 --> 00:58:57,520 +I know maybe that's before all of your time. +我知道这也许是在你所有的时间。 + +1300 +00:58:57,522 --> 00:59:00,289 +But, you know, these things we're gong to do to build our +但是,这些事情是我们构建我们界面 + +1301 +00:59:00,291 --> 00:59:02,524 +UI, we're going to use in the view. +要做的事,我们在 view 中要用到它 + +1302 +00:59:02,526 --> 00:59:06,127 +So the stuff that's in the view is pretty generic, okay, +在 view 中的内容是相当通用的 + +1303 +00:59:06,129 --> 00:59:07,795 +generic UI elements. +的界面元素 + +1304 +00:59:07,797 --> 00:59:10,030 +The stuff in the controller is very specific to +在控制器中的内容是明确的,指出 + +1305 +00:59:10,032 --> 00:59:11,498 +how your UI works. +你的界面元素是如何工作的 + +1306 +00:59:11,500 --> 00:59:13,600 +And the stuff in the model is completely independent of +模型中的内容完全独立于 + +1307 +00:59:13,602 --> 00:59:15,234 +how your UI works. +界面如何工作的 + +1308 +00:59:15,236 --> 00:59:15,801 +Okay? +懂吗? + +1309 +00:59:15,803 --> 00:59:22,007 +So doing MVC right is about knowing where things go but +因此正确的 MVC 不仅仅知道内容的存放位置而且 + +1310 +00:59:22,009 --> 00:59:25,543 +also about how to communicate between these three camps. +知道三层(camps)是如何通讯的 + +1311 +00:59:25,545 --> 00:59:27,412 +And so we can try and summarize how +我们来尝试总结, + +1312 +00:59:27,414 --> 00:59:29,113 +the communication works between these camps, and +三层之间是如何通讯的, + +1313 +00:59:29,115 --> 00:59:32,182 +I've used road markings, you see the double yellow line and +我使用路面标线做讲解,你看到的黄色双线和 + +1314 +00:59:32,184 --> 00:59:33,350 +then the dashed white line. +白色虚线 + +1315 +00:59:33,352 --> 00:59:34,884 +So that's like you're driving in your car. +就像你驾驶你的汽车 + +1316 +00:59:35,887 --> 00:59:40,356 +Try to use them as an image for how this communication +尝试用做以道路标线想象是如何通信的 + +1317 +00:59:40,358 --> 00:59:42,090 +happens, where it's allowed, where it's not allowed. +哪里是允许通信的,哪里是不被允许的 + +1318 +00:59:43,093 --> 00:59:45,693 +So let's talk about the Controller talking to +这样,我们描述控制器是如何与 + +1319 +00:59:45,695 --> 00:59:47,294 +the Model. +模型 + +1320 +00:59:47,296 --> 00:59:50,097 +Going from that side of the road over to the Model side is +从控制器这侧到模型 (Model) 这侧是 +1321 +00:59:50,099 --> 00:59:51,565 +a dashed white line, in other words, +白色虚线,换句话说, + +1322 +00:59:51,567 --> 00:59:52,799 +you can head right across there. +你可以轧过虚线到另一侧 + +1323 +00:59:52,801 --> 00:59:54,267 +You probably want to look before you go, but +你可能需要在你过对面之前观察一下,但是 + +1324 +00:59:54,269 --> 00:59:56,603 +you can go right across, okay? +你可以正常穿越,对吗? + +1325 +00:59:56,604 --> 00:59:58,938 +The controller has to know everything about the model, +控制器必须了解 Model 的一切行为, + +1326 +00:59:58,940 --> 01:00:01,740 +and it has to have complete ability to talk to +而且必须完全有能力和 + +1327 +01:00:01,742 --> 01:00:04,776 +the model, use its public API as much as it wants +模型(Model)通信,根据控制器需要,使用模型的开放 API + +1328 +01:00:04,778 --> 01:00:08,313 +because the controller's job is to present the model to +因为控制器的职责就是展示模型(Model)给 + +1329 +01:00:08,315 --> 01:00:10,848 +the user using its view as its minions. +用户,其视图作为它的对象 + +1330 +01:00:10,850 --> 01:00:12,650 +So it has to have this access. +因此你必须有该权限 + +1331 +01:00:12,652 --> 01:00:16,319 +That full, unrestricted access the controller has talking to +控制器拥有的完全访问权限可以与 + +1332 +01:00:16,321 --> 01:00:17,320 +the model. +模型通信 + +1333 +01:00:17,322 --> 01:00:18,354 +This is a one way arrow. +这是个单向箭头 + +1334 +01:00:18,356 --> 01:00:20,289 +Control, or +控制器 + +1335 +01:00:20,290 --> 01:00:22,223 +one way arrow, from the controller to the model. +对模型的控制也是单向的 + +1336 +01:00:22,226 --> 01:00:25,160 +And similarly, from the controller to the view, +类似的,也可以从控制器到视图, + +1337 +01:00:25,162 --> 01:00:27,095 +is also unlimited communication, +也是允许通信的 + +1338 +01:00:27,097 --> 01:00:28,830 +because the controller is responsible for +因为控制器负责通过自身对象 + +1339 +01:00:28,832 --> 01:00:30,798 +talking using it's own minions. +向视图发送指令 + +1340 +01:00:30,800 --> 01:00:32,667 +The view is, the controller's new meaning is +视图是控制器设计 + +1341 +01:00:32,669 --> 01:00:35,569 +to lay out the user interface and all that stuff. +用户界面的新方式 + +1342 +01:00:35,571 --> 01:00:37,671 +So, the controller can do anything it wants. +因此,控制器可以做任何它想做的事 + +1343 +01:00:37,673 --> 01:00:39,305 +I put that little green word, outlet, +我放置了一个绿色小字 Outlet 在上面, + +1344 +01:00:39,307 --> 01:00:42,809 +up there because when we have a property of a controller +因为当我们有一个控制器的属性, + +1345 +01:00:42,811 --> 01:00:46,278 +that points into the view, we call it an outlet, okay? +该属性指向视图,我们称它为 Outlet,懂吗? + +1346 +01:00:46,280 --> 01:00:48,213 +And you're gonna see that in the demo on Wednesday. +我们周三的演示中将要看到它 + +1347 +01:00:48,215 --> 01:00:51,249 +I'm gonna say, oh let's create an outlet from our controller +我想说的,让我们创建一个 outlet, 从我们的控制器 + +1348 +01:00:51,251 --> 01:00:52,634 +to our view so +到我们的视图 + +1349 +01:00:52,635 --> 01:00:54,018 +our controller can talk to it's view, all right? +这样,我们控制器可以发送指令到对应视图 对吧? + +1350 +01:00:55,055 --> 01:00:56,354 +What about this communication? +这是如何通信的呢? + +1351 +01:00:56,356 --> 01:00:57,554 +Model to view? +可以从 Model 到视图吗? + +1352 +01:00:57,556 --> 01:00:58,422 +Never. +不可能! + +1353 +01:00:58,424 --> 01:00:59,989 +And why is that? +为什么会这样呢? + +1354 +01:00:59,991 --> 01:01:03,292 +100% obvious, the model is completely UI independent. +很明显,Model 是完全独立于 UI 的 + +1355 +01:01:03,294 --> 01:01:05,494 +So, there's absolutely no way it could talk to +因此,Model 没有任何办法向 + +1356 +01:01:05,496 --> 01:01:07,863 +a viewer object or anyone in that camp. +视图对象发送指令,也不能和视图层的任何对象通讯 + +1357 +01:01:07,865 --> 01:01:10,399 +Because the view objects are fundamentally UI objects. +因为视图对象是基本的 UI 对象 + +1358 +01:01:10,401 --> 01:01:11,466 +They're kind of generic, but +他们是某种程度上是通用的,但是 + +1359 +01:01:11,468 --> 01:01:13,401 +they're still fundamentally UI objects. +他们也是基本的 UI 对象 + +1360 +01:01:13,403 --> 01:01:16,237 +Similarly, since the view objects are kind of generic, +同样地,既然视图对象是通用的对象, + +1361 +01:01:16,239 --> 01:01:18,272 +they can't be talking to any specific model. +他们就不能和任何特定的 Model 对象通讯 + +1362 +01:01:18,274 --> 01:01:20,674 +They need a controller to interpret a model +他们需要用一个控制器来传到信息 + +1363 +01:01:20,676 --> 01:01:22,375 +for them, okay? +懂吗? + +1364 +01:01:22,377 --> 01:01:24,377 +So there's never any communication this way. +因此这里没有任何通信 + +1365 +01:01:24,379 --> 01:01:25,911 +That's why it's a double yellow line. +这也是这里使用黄色双线的原因 + +1366 +01:01:25,913 --> 01:01:27,780 +That's why these lines are red. +这是这些线是红色的原因 + +1367 +01:01:27,782 --> 01:01:29,748 +That's why there's fire, okay? +这也是这里用火标注的原因 明白? + +1368 +01:01:29,750 --> 01:01:31,783 +Never go across that line, Never. +永远不要跨越这条线, 绝不! + +1369 +01:01:34,120 --> 01:01:36,520 +What about the view talking back to the controller? +那视图怎么样向控制器发送指令呢? + +1370 +01:01:36,522 --> 01:01:38,588 +You got these generic view objects, like buttons. +你得到这些通用的视图对象,例如按钮 + +1371 +01:01:38,590 --> 01:01:40,724 +Can they talk to the controller? +他们能与控制器通信吗? + +1372 +01:01:40,726 --> 01:01:43,593 +Well, yes, they can. +对,当然可以 + +1373 +01:01:43,595 --> 01:01:46,495 +But, they have to be careful because the view objects +但是你必须小心,因为视图对象 + +1374 +01:01:46,497 --> 01:01:48,397 +are generic. +是通用的 + +1375 +01:01:48,398 --> 01:01:50,298 +So they can't really know much about the controller. +这样,他们不能真正的了解控制器 + +1376 +01:01:50,301 --> 01:01:53,201 +So, they can only communicate back to the controller +因此他们只能用盲目的方式和控制器通信, + +1377 +01:01:53,203 --> 01:01:55,437 +in a blind way where they don't know the class of +视图并不知道他们所通信的类 + +1378 +01:01:55,439 --> 01:01:58,673 +the thing they're talking to, and in a structured way. +在什么位置,并用一种结构化的方式和控制器通信 + +1379 +01:01:58,675 --> 01:02:02,776 +A way where we all agree we're gonna communicate this way +这是一种大家都认同的,视图和控制器通信的 + +1380 +01:02:02,778 --> 01:02:03,844 +between the view and the controller. +方式 + +1381 +01:02:03,846 --> 01:02:05,512 +So, whats an example of a structured way? +那,有没有是结构化的方式例子? + +1382 +01:02:05,514 --> 01:02:07,480 +Well one is called target action. +其中一个方式叫做 Target 操作 + +1383 +01:02:07,482 --> 01:02:10,816 +So, the controller basically drops a target on itself, and +一般控制器本身写一个 target + +1384 +01:02:10,818 --> 01:02:15,087 +then it hands out an action, which is like an arrow, +然后分给出一个操作方法,想一个箭头 + +1385 +01:02:15,089 --> 01:02:17,389 +to the view and says to the view, +指向视图,并和视图通信 + +1386 +01:02:17,391 --> 01:02:20,058 +okay, when you do what you do, like you're a button and +当你想做了一个操作,比如你是一个按钮, + +1387 +01:02:20,060 --> 01:02:21,659 +someone touches you or your a slider and +别人点击了你,或者你是个拖动条 + +1388 +01:02:21,661 --> 01:02:24,828 +someone moves you, send me that action. +别人移动了你,给向我发送那个操作 + +1389 +01:02:24,830 --> 01:02:26,430 +Okay? +懂吗? + +1390 +01:02:26,431 --> 01:02:28,031 +So, in this way, the generic button or +这样,用这种方式,通用的按钮或者 + +1391 +01:02:28,033 --> 01:02:30,600 +slider is communicating back to the controller. +拖动条就可以反过来和控制器通信 + +1392 +01:02:30,602 --> 01:02:32,835 +It has no idea that it's a card game controller or +它不知道这是一个纸牌游戏控制器还是 + +1393 +01:02:32,837 --> 01:02:34,103 +a space game controller. +一个空间游戏控制器 + +1394 +01:02:34,105 --> 01:02:36,071 +It doesn't know what kind of controller it is. +它并不知道它是什么类型的控制器 + +1395 +01:02:36,073 --> 01:02:38,607 +All it knows is that when something happens in itself, +它所知道的只是某一个事件何时在它身上发生 + +1396 +01:02:38,609 --> 01:02:40,108 +boom, it sends a message to the target. +它发送一个消息给 target + +1397 +01:02:40,110 --> 01:02:43,678 +So that's a blind, simple, structured way for +这样就是一个盲目的,简单的,结构化的方式来做 + +1398 +01:02:43,680 --> 01:02:45,780 +the view to communicate with the controller. +到视图和控制器之间的通信 + +1399 +01:02:45,782 --> 01:02:47,465 +Okay? +明白吗? + +1400 +01:02:47,466 --> 01:02:49,149 +But what about more complicated ways? +那什么是更复杂的通信方式呢? + +1401 +01:02:49,151 --> 01:02:52,119 +Sometimes the view, things are happening in the view +有时,发生在视图上的事件 + +1402 +01:02:52,121 --> 01:02:53,987 +that are somewhat complicated, and +是比较复杂的, + +1403 +01:02:53,989 --> 01:02:56,456 +the controller needs to be informed of what's going on, +控制器需要知道正在发生的事是什么, + +1404 +01:02:56,458 --> 01:02:58,791 +synchronizing what's happening. +同步正在发生的事件 + +1405 +01:02:58,793 --> 01:03:01,694 +And one way to think about this is these words I +理解这个的一种方法是我放着 + +1406 +01:03:01,696 --> 01:03:04,096 +put up here, will, should and did. +will, should 和 did 这些单词, + +1407 +01:03:04,098 --> 01:03:06,598 +When the view is kind of like, +当某种视图 + +1408 +01:03:06,600 --> 01:03:08,132 +let's say I am in the scroll view and +就比如说是在一个 scroll 视图中, + +1409 +01:03:08,134 --> 01:03:11,669 +I am scrolling around, and I want to let the controller +我正在到处滚动,并且我想要让控制器 + +1410 +01:03:11,671 --> 01:03:15,806 +somebody know that the user just did scroll. +知道用户刚刚做了滚动操作 + +1411 +01:03:15,808 --> 01:03:17,691 +Okay? Or +懂吗?或者 + +1412 +01:03:17,692 --> 01:03:19,575 +the user puts down the touch and is about to scroll, I want +用户按住屏幕,将要滑动,我想让 + +1413 +01:03:19,578 --> 01:03:23,413 +to let the controller know the user will be scrolling, okay? +控制器知道用户将要执行滑动操作 懂吗? + +1414 +01:03:23,415 --> 01:03:25,114 +Or, the user puts the touch down and +或者用户按住屏幕 + +1415 +01:03:25,116 --> 01:03:26,448 +the scroll viewer wants to know, +scroll viewer 需要知道 + +1416 +01:03:26,450 --> 01:03:30,452 +should I allow the user to scroll here, is that allowed? +是否允许用户这里执行滚动操作? + +1417 +01:03:30,454 --> 01:03:33,221 +All those things, the scroll view itself might not +这里所有的事情,scroll 视图本身或许没有 + +1418 +01:03:33,223 --> 01:03:36,190 +have enough logic to know the answer to those questions. +足够的逻辑知道那些问题的答案 + +1419 +01:03:36,192 --> 01:03:39,727 +So what it does is, it delegates the authority to +那它做的事情是,它代理给 + +1420 +01:03:39,729 --> 01:03:42,730 +answer those questions to some other object. +其他对象来回答那些问题 + +1421 +01:03:42,732 --> 01:03:44,664 +Now, it doesn't know the class of that object. +现在,它并不知道那个对象的类是什么 + +1422 +01:03:44,666 --> 01:03:46,199 +All it knows is that other object can +他知道只是另一个对象可以 + +1423 +01:03:46,201 --> 01:03:49,135 +answer these questions, will, should, did, this, that, or +回答这些问题,will, should, did, this, that, 或者 + +1424 +01:03:49,137 --> 01:03:51,570 +the other thing like, should allow scrolling. +其他事情,像是否允许滑动 + +1425 +01:03:51,572 --> 01:03:53,939 +Did scroll to point. +滑动到一个点 + +1426 +01:03:53,941 --> 01:03:54,539 +Things like that. +就像那样 + +1427 +01:03:54,541 --> 01:03:56,591 +So those are the kind of +这些是这样一类 + +1428 +01:03:56,592 --> 01:03:58,642 +methods you are going to see in these delicate protocols. +方法,你将要在那些代理协议中看到他们 + +1429 +01:03:58,645 --> 01:04:00,878 +Now, I know this here is 1, 6 a and b, +现在,我知道这里是 1,6,a 和 b + +1430 +01:04:00,880 --> 01:04:02,847 +do not teach protocols. +没有教过协议, + +1431 +01:04:02,849 --> 01:04:04,582 +How many people know what +多少人知道 + +1432 +01:04:04,583 --> 01:04:06,316 +the word protocol means an +object during a programming? +协议在编程中代表什么对象? + +1433 +01:04:06,318 --> 01:04:07,117 +I can see very few of you. +很少能做到 + +1434 +01:04:07,119 --> 01:04:08,818 +So, I will be teaching that. +这里我将要讲它 + +1435 +01:04:08,820 --> 01:04:12,421 +A protocol is just a blind way to talk to another object. +协议仅仅是 blind 和其他对象通信的方式 + +1436 +01:04:12,423 --> 01:04:13,556 +When I teach it, +我讲了它以后, + +1437 +01:04:13,557 --> 01:04:14,690 +you're gonna be like oh, yeah, I know what that is. +你将会明白,这知道这就是它 + +1438 +01:04:14,692 --> 01:04:16,958 +So we can really call it protocol or whatever. +我们实际上叫它协议,或者不管什么了 + +1439 +01:04:16,960 --> 01:04:19,160 +But that's how we do delegation, okay, +但这是我们如何实现一个代理, + +1440 +01:04:19,162 --> 01:04:20,862 +this blind communication. +盲目通信 + +1441 +01:04:21,931 --> 01:04:24,932 +Also another important thing is +另一个重要事情是 + +1442 +01:04:24,934 --> 01:04:28,502 +that views should not own the data that they're displaying. +视图不应该持有他们展示的数据 + +1443 +01:04:28,504 --> 01:04:30,170 +They should not own it. +他们不应该持有数据 + +1444 +01:04:30,171 --> 01:04:31,837 +In other words, it shouldn't be a property inside of them, +换句话说,数据不应该作为视图内部的属性, + +1445 +01:04:31,840 --> 01:04:34,707 +where that's the truth of that data. +这就是数据。 + +1446 +01:04:34,709 --> 01:04:37,810 +And the easiest example for this is, all the songs in +最简单的例子就是,在 + +1447 +01:04:37,812 --> 01:04:40,679 +your iPod, on your iPhone or your iPad, right? +你 iPod,iPhone 或者 iPad 中的所有歌曲 对吗? + +1448 +01:04:40,681 --> 01:04:43,281 +You might have 10,000 songs in there. +你可能有 10000 首歌曲 + +1449 +01:04:43,283 --> 01:04:46,017 +So, if you have some kind of generic list view in +假如你有一些通用的视图列表在你视图中, + +1450 +01:04:46,019 --> 01:04:50,354 +your view, you can't transfer all 10,000 songs to its +你不能传递 10000 首歌到它的 + +1451 +01:04:50,356 --> 01:04:52,773 +instance variables, and +实例变量中,并 + +1452 +01:04:52,774 --> 01:04:55,191 +expect it to hold 10,000 songs so it can list through it. +期望它来持有 10000 首歌,来展示给你看 + +1453 +01:04:55,194 --> 01:04:56,860 +A, that would be inefficient, and +第一,这样做是很低效的, + +1454 +01:04:56,862 --> 01:05:01,064 +B that information, those 10,000 songs belongs where? +第二,这 10000 首歌属于哪一层? + +1455 +01:05:01,066 --> 01:05:02,131 +In the model. +在 Model 层 + +1456 +01:05:02,133 --> 01:05:04,900 +Okay, because your song database is a model. +OKay,因为你的音乐数据库是一个 Model + +1457 +01:05:04,902 --> 01:05:06,468 +It has nothing to do with UI. +它和 UI 没有任何关系 + +1458 +01:05:06,469 --> 01:05:08,035 +It's just a list of songs and artists and albums and +视图仅仅是歌曲,艺术家,专辑和其他信息的一个列表 + +1459 +01:05:08,038 --> 01:05:09,604 +all that, it's in the model. +它在 Model 层 + +1460 +01:05:09,606 --> 01:05:12,073 +Some controller has to look at that database and +一些控制器必须查询数据并 + +1461 +01:05:12,075 --> 01:05:16,243 +tell a view how to display all those songs. +告诉一个视图如何展示这些歌曲 + +1462 +01:05:16,245 --> 01:05:18,429 +Okay? +懂吗? + +1463 +01:05:18,430 --> 01:05:20,614 +So, we need that communication to happen here and the view is +这里,我们这里需要通信产生, 视图 + +1464 +01:05:20,616 --> 01:05:23,249 +displaying some sort of list, and you're touching down and +展示列表分类,并且当你按下屏幕, + +1465 +01:05:23,251 --> 01:05:26,619 +you're flicking on the list and trying to see more songs, +你轻轻滑动列表,试图查看更多歌曲, + +1466 +01:05:26,621 --> 01:05:28,087 +how does that communication happen? +这些通信如何发生的? + +1467 +01:05:28,089 --> 01:05:30,923 +And the answer is, we have another special kind of +答案是我们 有另一种特殊的 + +1468 +01:05:30,925 --> 01:05:33,992 +delegate, which we call a data source. +代理,我们叫它数据源 + +1469 +01:05:33,994 --> 01:05:36,928 +Now the data source doesn't do the will did should. +数据源并不做 will, did, should 的事 + +1470 +01:05:36,930 --> 01:05:39,230 +It's gonna be asking questions like count, +它将回答类似,数量 + +1471 +01:05:39,232 --> 01:05:41,098 +like how many songs are there? +像这里有多少首歌? + +1472 +01:05:41,100 --> 01:05:42,900 +And the controller looks in the model, +控制器查找 Model + +1473 +01:05:42,902 --> 01:05:45,435 +10,000 response to the view. +把 10000 返回给视图 + +1474 +01:05:45,437 --> 01:05:47,020 +There's 10,000. The view +这是 10000, 视图 + +1475 +01:05:47,021 --> 01:05:48,604 +makes space internally for 10,000 things. +为 10000 歌开辟内部空间 + +1476 +01:05:48,607 --> 01:05:50,340 +It doesn't know what they are. +视图并不知道这些歌曲是什么 + +1477 +01:05:50,342 --> 01:05:53,009 +Moves the scroll bar indicator a little bit so +稍微移动滚动条 + +1478 +01:05:53,011 --> 01:05:54,276 +that you know where it is. +你便能知道它在哪里 + +1479 +01:05:54,278 --> 01:05:57,779 +And then you start scrolling, flipping through it, and +当你开始滚动,轻滑动它, + +1480 +01:05:57,781 --> 01:06:00,849 +it starts sending the message to the controller, +它开始发送消息给控制器 + +1481 +01:06:00,851 --> 01:06:03,785 +give me the data at line 150 next 10 items. +返回 150 行后面的 10 条数据 + +1482 +01:06:03,787 --> 01:06:04,975 +You see what I mean? +你懂我意思吗? + +1483 +01:06:04,976 --> 01:06:06,164 +And then you flick down some more. +然后你再往下轻轻滑动 + +1484 +01:06:06,165 --> 01:06:07,353 +Now it's saying 250, 10 more items. +现在显示 250, 另外 10 条数据 + +1485 +01:06:07,357 --> 01:06:10,257 +And so the control is going back to the model and +控制器再次与 Model 通信,并 + +1486 +01:06:10,259 --> 01:06:11,725 +saying give me more, give me more data. +要求得到更多的数据 + +1487 +01:06:11,727 --> 01:06:14,361 +And it's providing it to the view in this blind way. +控制器用这种 blind 方式提供数据给视图 + +1488 +01:06:14,363 --> 01:06:17,230 +So to see how the view is getting data from the model +来看一下视图如何从 Model 得到数据, + +1489 +01:06:17,232 --> 01:06:20,232 +through the controller in this kind of blind structured way. +是通过控制器用这种 blind structured 方式实现的 + +1490 +01:06:20,234 --> 01:06:21,767 +Okay? +懂吗? + +1491 +01:06:21,768 --> 01:06:23,301 +That makes sense to everybody? +每个人都明白吗? + +1492 +01:06:23,304 --> 01:06:24,970 +So data source is just a kind of delegate, +数据源只是一种代理 + +1493 +01:06:24,972 --> 01:06:27,105 +it's a specific kind of delegate for getting data. +它是一种特殊类型的用于获取数据的代理 + +1494 +01:06:27,107 --> 01:06:30,408 +So you're gonna see that there are classes in iOS that have +因此你将在 iOS 中看到一些类, + +1495 +01:06:30,410 --> 01:06:33,477 +a data source, and they usually also have a delegate. +他们有一个数据源,并且通常有一个代理 + +1496 +01:06:33,479 --> 01:06:36,547 +Most sophisticated classes in iOS have a delegate, the will, +大部分 iOS 高级类有代理,包括 will, + +1497 +01:06:36,549 --> 01:06:38,415 +did, should, kind of things. +did, should, 等要做的事 + +1498 +01:06:38,417 --> 01:06:40,316 +Some of them have a data source, +其中一些有数据源, + +1499 +01:06:40,318 --> 01:06:43,219 +it depends on whether they are showing a lot of data or not. +这取决于他们是否要显示大量数据 + +1500 +01:06:43,221 --> 01:06:46,455 +Now simple data, like if I had a view, if I invented a view +一些简单的数据,比如我给纸牌游戏 + +1501 +01:06:46,457 --> 01:06:49,224 +for my card game called Playing Card View and +创建了一个叫 Playing Card View 的视图 + +1502 +01:06:49,226 --> 01:06:51,109 +it just has a suit and a rank. +它仅有花色和点数两点属性 + +1503 +01:06:51,110 --> 01:06:52,993 +Okay, we're not going to do count data app for +我们不会为了花色和点数 + +1504 +01:06:52,996 --> 01:06:54,262 +just suit and rank. +进行计算 + +1505 +01:06:54,264 --> 01:06:56,030 +We are going to set those properties. +我们会把它们设置成属性 + +1506 +01:06:56,032 --> 01:06:58,766 +And so the view then would have that data set in it but +所以 view 里会有设置好的数据,但是 + +1507 +01:06:58,768 --> 01:07:00,267 +it wouldn't be owning it. +它不会拥有这些数据 + +1508 +01:07:00,269 --> 01:07:02,536 +Right? The model would still be +model 仍然会是花色和点数的 + +1509 +01:07:02,538 --> 01:07:04,571 +owning the suit and +拥有者 + +1510 +01:07:04,572 --> 01:07:06,605 +rank, the view is just getting that data to present it. +view 仅仅是为了显示而获取那些数据 + +1511 +01:07:06,608 --> 01:07:07,840 +'Kay. So simple data, +所以对于简单的数据, + +1512 +01:07:07,842 --> 01:07:10,743 +we might transfer to the view but it's merely for +我们会把它传递到 view 里,但是 + +1513 +01:07:10,745 --> 01:07:12,878 +it to display it. +只是给 view 来显示 + +1514 +01:07:12,880 --> 01:07:14,312 +Okay. + +1515 +01:07:14,314 --> 01:07:17,615 +This all adds up to the controller's job being to +所以 controller 的工作就是 + +1516 +01:07:17,617 --> 01:07:22,520 +interpret and format the model's data for the view. +给 view 解释并格式化这些 model 提供的数据 + +1517 +01:07:22,522 --> 01:07:23,654 +That's the controller's job. +这就是 controller 的工作 + +1518 +01:07:23,656 --> 01:07:25,188 +And when we do our demo, +在我们做 demo 的时候, + +1519 +01:07:25,190 --> 01:07:28,758 +I'm going to be marking like, oh see I'm writing this code. +我会在写代码的时候提示大家, + +1520 +01:07:28,760 --> 01:07:31,494 +This is to make the controller perform its job, +这段代码是为了让 controller 执行它的工作, + +1521 +01:07:31,496 --> 01:07:34,430 +which is to take the model data and +也就是从 model 中取出数据然后 + +1522 +01:07:34,432 --> 01:07:36,265 +using its view minion to put it on screen. +送到 view 中去,然后显示到屏幕上 + +1523 +01:07:36,267 --> 01:07:37,132 +Okay? That's what +这就是 + +1524 +01:07:37,134 --> 01:07:38,667 +the controller does. +controller 做的事情 + +1525 +01:07:38,669 --> 01:07:40,468 +What about this communication? +那关于通信呢? + +1526 +01:07:40,470 --> 01:07:42,970 +Can the model talk to the controller? +model 可以和 controller 通信吗? + +1527 +01:07:42,972 --> 01:07:46,040 +Again, obviously that's verboten because model knows +同样的,显然是不可以 因为 model 对于 UI + +1528 +01:07:46,042 --> 01:07:47,708 +nothing about UI, so +一无所知,所以 + +1529 +01:07:47,710 --> 01:07:50,710 +it couldn't possibly talk to a UI object like the controller. +它不可能同像 controller 一样的 UI 对象进行通信 + +1530 +01:07:50,712 --> 01:07:53,046 +But sometimes things change in the model, and +但是有些时候,model 中的数据变了, + +1531 +01:07:53,048 --> 01:07:54,580 +the controller needs to know about it, okay? +controller 需要知道这个变化 + +1532 +01:07:54,582 --> 01:07:56,782 +Data changes, a database changes or +数据改变了,数据库改变了,或者 + +1533 +01:07:56,784 --> 01:07:59,017 +the model is some network database, and +model 是网络数据库, + +1534 +01:07:59,019 --> 01:08:01,186 +somebody changes something on the network and it changes. +某人在网络上修改了数据,数据改变了 + +1535 +01:08:01,188 --> 01:08:02,587 +And the controller needs to find out. +controller 需要了解这些 + +1536 +01:08:02,589 --> 01:08:04,555 +So, how do we do that communication? +所以,我们怎样进行这种通信呢? + +1537 +01:08:05,958 --> 01:08:09,592 +We do that using kind of a radio station model. +这可以通过一种电台的模型来理解 + +1538 +01:08:09,594 --> 01:08:11,928 +Okay? + +1539 +01:08:11,929 --> 01:08:14,263 +So, the model, a radio station concept, the model will use +所以,model 是一种电台的概念, + +1540 +01:08:14,265 --> 01:08:17,866 +this concept to essentially broadcast information to +model 将会利用这一概念,把信息广播给 + +1541 +01:08:17,868 --> 01:08:19,768 +anyone who's interested. +感兴趣的任何人 + +1542 +01:08:19,770 --> 01:08:21,937 +Okay? + +1543 +01:08:21,938 --> 01:08:24,105 +And the mechanisms for doing this in iOS are called +在 iOS 中为了解决这种问题而使用的技术我们叫做 + +1544 +01:08:24,107 --> 01:08:28,476 +Notification and Key Value Observing, KVO we call it. +Notification 和 KVO + +1545 +01:08:28,478 --> 01:08:31,211 +And so, the model can just say, oh, anytime +所以,model 可以这样, + +1546 +01:08:31,213 --> 01:08:33,547 +something changes in my model I'm just gonna broadcast on +我当中的任何东西发生了变化,我会通过我的电台 + +1547 +01:08:33,549 --> 01:08:37,484 +my radio station, and then the controller simply tunes into +广播一下,随后,controller + +1548 +01:08:37,486 --> 01:08:40,453 +that radio station, and he can find out things are changing. +会接收到来自电台的信息,它会发现数据在变化 + +1549 +01:08:40,455 --> 01:08:42,254 +And when he finds out something changes, +发现数据变化以后, + +1550 +01:08:42,256 --> 01:08:46,058 +it's gonna communicate via its green arrow to the model and +它就会通过它的绿剪头同 model 进行通信, + +1551 +01:08:46,060 --> 01:08:47,659 +say, okay, give me that data that changed. +给我那个改变过的数据 + +1552 +01:08:48,962 --> 01:08:49,560 +Right? + +1553 +01:08:49,562 --> 01:08:50,978 +That make sense? +能听懂吗? + +1554 +01:08:50,979 --> 01:08:52,395 +So, towards the end of the quarter we'll start seeing +所以在课程快要结束的时候,我们将会学习 + +1555 +01:08:52,398 --> 01:08:54,531 +a little how to do notification to find out, for +如何利用 notification 得知 + +1556 +01:08:54,533 --> 01:08:57,334 +example, if the data in a database changes. +例如数据库中的数据发生了改变 + +1557 +01:08:57,336 --> 01:09:00,070 +We'll get a notification, the UI can then, you know, +我们将会获取一个 notification,UI 的 controller + +1558 +01:09:00,072 --> 01:09:03,272 +controller can then go talk to the model to get the info. +随后可以同 model 通信来获取信息 + +1559 +01:09:05,309 --> 01:09:06,286 +Okay? + +1560 +01:09:06,287 --> 01:09:07,264 +Some people have asked, +有些人会问, + +1561 +01:09:07,265 --> 01:09:08,242 +can a view tune into the radio station? +view 可以接收广播吗? + +1562 +01:09:08,245 --> 01:09:09,878 +They probably could, but +它们也许可以,但是 + +1563 +01:09:09,880 --> 01:09:11,179 +you probably wouldn't want to do that. +你最好不要这样做 + +1564 +01:09:11,181 --> 01:09:12,980 +That would probably be a violation of MVC. +这可能违背了 MVC 的原则 + +1565 +01:09:12,982 --> 01:09:14,749 +All right. + +1566 +01:09:14,751 --> 01:09:16,750 +So we do this. +我们这样做, + +1567 +01:09:16,752 --> 01:09:18,785 +We have all this nice communication and +我们有这些很好的通信方式和 + +1568 +01:09:18,787 --> 01:09:21,288 +all these rules, +所有的这些规则 + +1569 +01:09:21,289 --> 01:09:23,790 +and we can imagine building something simple using this. +我们可以利用这些来制作一些小的应用 + +1570 +01:09:23,792 --> 01:09:26,259 +But what if we wanna build a big complicated app? +但是如果我们想要制作一个巨大复杂的应用呢? + +1571 +01:09:26,261 --> 01:09:28,861 +An app that has multiple screens on our iPhone, or +一个在 iPhone 或 iPad 上运行,有多个屏幕, + +1572 +01:09:28,863 --> 01:09:30,863 +an iPad, it's got three or +在屏幕上有三个或四个不同的区域, + +1573 +01:09:30,865 --> 01:09:34,166 +four different areas on screen where things are happening. +都发生着事情 + +1574 +01:09:34,168 --> 01:09:35,433 +How do we do that? +我们该怎么做? + +1575 +01:09:35,435 --> 01:09:36,834 +Well, we're essentially going to +我们会结合 + +1576 +01:09:36,836 --> 01:09:40,071 +combine multiple MVCs, okay? +多个 MVC + +1577 +01:09:40,073 --> 01:09:47,244 +Because an MVC can use as part of its view, another MVC. +因为一个 MVC 可以将另一个 MVC 当做视图的一部分 + +1578 +01:09:47,246 --> 01:09:48,311 +Okay? + +1579 +01:09:48,313 --> 01:09:52,114 +So an MVC, an entire MVC can be one of +所以一个完整的 MVC 可以被一个稍大些的 + +1580 +01:09:52,116 --> 01:09:56,051 +the minions of some bigger MVC. +MVC 当做仆从使用 + +1581 +01:09:56,053 --> 01:09:57,803 +'Kay? + +1582 +01:09:57,804 --> 01:09:59,554 +And by doing that and cascading it down, +我们可以一层一层地这样堆叠, + +1583 +01:09:59,556 --> 01:10:01,756 +we can build more and more complicated applications. +就可以制作出越来越复杂的应用 + +1584 +01:10:01,758 --> 01:10:07,561 +So, an example of this is, you might have your calendar app, +例如,你可能有一个日历应用, + +1585 +01:10:07,563 --> 01:10:09,930 +and it's showing you the entire year. +它展示给你一整年的信息 + +1586 +01:10:09,932 --> 01:10:12,599 +And you click on a month, and now it shows you a month view. +随后你点击了一个月份,于是它展示给你月视图 + +1587 +01:10:12,601 --> 01:10:14,567 +Well, a month view looks a lot different than a year view. +月视图看起来和年视图就不太一样了 + +1588 +01:10:14,569 --> 01:10:17,503 +A month view just has all the days and maybe some circle +一个月视图只含有日期,也许在日期上 + +1589 +01:10:17,505 --> 01:10:19,204 +that tells you where you have an appointment on a day. +会有一些通知你在某天会有任务的圈圈 + +1590 +01:10:19,206 --> 01:10:20,939 +And then when you click on a day, and +随后,你点击了一天,然后你 + +1591 +01:10:20,941 --> 01:10:23,074 +now you get a day view, okay? +获得了一个日视图 + +1592 +01:10:23,076 --> 01:10:25,043 +And the day is showing you the hours and what all +日视图会显示小时信息和这天你的所有任务, + +1593 +01:10:25,045 --> 01:10:27,611 +your appointments are, and you click on the Appointment now +随后你点击了任务, + +1594 +01:10:27,613 --> 01:10:29,947 +you get an appointment view and it showing the detail of +你会获得任务视图,它会显示任务的细节, + +1595 +01:10:29,949 --> 01:10:32,182 +where you're going and when it is et cetera, okay? +将要去哪,何时动身还有其它一些东西 + +1596 +01:10:32,184 --> 01:10:36,452 +Well, each of those views, year view, month view, the day +这些 view 中的每一个,年视图,月视图,日视图, + +1597 +01:10:36,454 --> 01:10:40,155 +view, and the appointment view are their own MVCs. +任务视图,都有他们自己的 MVC + +1598 +01:10:40,157 --> 01:10:41,857 +Okay? + +1599 +01:10:41,858 --> 01:10:43,558 +But you can see how the last three, okay, +但是你可以发现,最后三个 view, + +1600 +01:10:43,560 --> 01:10:47,628 +are used as essentially a minion of the top level view, +都被最顶层的年视图为了展示更多的细节 + +1601 +01:10:47,630 --> 01:10:51,032 +year view, to show more detail, okay? +而被当做仆从使用 + +1602 +01:10:51,034 --> 01:10:52,766 +So the year view,you click on a month, +所以在年视图里,你点击了一个月份, + +1603 +01:10:52,768 --> 01:10:57,404 +it's going to use the month view MVC to show more detail. +它会利用月份视图的 MVC 来展现更多细节 + +1604 +01:10:57,406 --> 01:11:00,406 +So it's part of its view,okay? +所以它是它视图的一部分, + +1605 +01:11:00,408 --> 01:11:03,476 +So, you see this also in iOS with tab bar +所以你也在带有 tab bar 的 iOS 应用 + +1606 +01:11:03,478 --> 01:11:05,228 +controllers, right? +中见过这些吧 + +1607 +01:11:05,229 --> 01:11:06,979 +You have the tab bar at the bottom, I have four or +在底部有一个 tab bar,有四个或五个 + +1608 +01:11:06,981 --> 01:11:09,615 +five things you can choose. +项可以供你选择 + +1609 +01:11:09,616 --> 01:11:12,250 +Well there's some MVC at the top whose has four pointers to +在上面有一个 MVC,它指向四个仆从, + +1610 +01:11:12,252 --> 01:11:15,120 +four minions, which are the four MVCs that are each going +也就是将要出现在 + +1611 +01:11:15,122 --> 01:11:17,488 +to appear in a tab bar, okay? +tab bar 的 MVC, + +1612 +01:11:17,490 --> 01:11:18,673 +We'll be doing that for +我们将会做一个这方面的 demo, + +1613 +01:11:18,674 --> 01:11:19,857 +example, in assignment number two or +在第二次或第三次作业,我们会 + +1614 +01:11:19,859 --> 01:11:21,792 +three where we'll be making a tab bar and +制作一个 tab bar, + +1615 +01:11:21,794 --> 01:11:25,328 +you're gonna have to do multiple MVCs, okay? +你们将会学习如何使用多个 MVC + +1616 +01:11:25,330 --> 01:11:28,531 +So, that basically results in a picture looks kinda +所以使用多个 MVC 的效果看起来就像 + +1617 +01:11:28,533 --> 01:11:29,899 +like this. +这张图片一样 + +1618 +01:11:29,901 --> 01:11:31,434 +All right? + +1619 +01:11:31,435 --> 01:11:32,968 +Where you got this MVC, and +在你看到的这个 MVC 里, + +1620 +01:11:32,969 --> 01:11:34,502 +you see the purple one that's like underneath the word +找到'together' 下面的那个 + +1621 +01:11:34,505 --> 01:11:37,239 +together there, and +紫色的, + +1622 +01:11:37,240 --> 01:11:39,974 +it points to three other MVCs outside of its view thing. +它从 view 指向了另外三个 MVC, + +1623 +01:11:39,977 --> 01:11:40,542 +Okay? + +1624 +01:11:41,478 --> 01:11:42,710 +That's how we're going to build it, so +这就是我们创建 tab bar 的方式, + +1625 +01:11:42,712 --> 01:11:43,944 +that might be a tab bar control and +这些可能就是它的 + +1626 +01:11:43,946 --> 01:11:45,812 +those might be the three tabs. +三个标签 + +1627 +01:11:45,814 --> 01:11:47,614 +Okay, and each one is its own little MVC +并且它们每一个都是 + +1628 +01:11:47,616 --> 01:11:50,249 +completely independent, operates on its own. +完全独立的,可以独自行动的小 MVC + +1629 +01:11:50,251 --> 01:11:52,418 +Doesn't even know, +这时它就是一个 + +1630 +01:11:52,419 --> 01:11:54,586 +it's a generic reusable view like thing at this point. +普通的可重用的 view 之类的东西, + +1631 +01:11:54,589 --> 01:11:56,689 +Doesn't even know that it's in a tab bar. +它甚至不知道它在 tab bar 中 + +1632 +01:11:56,691 --> 01:11:58,090 +Okay, it just knows that it's supposed to do +它只知道它应该做 + +1633 +01:11:58,092 --> 01:11:59,591 +whatever it does. +这些事情 + +1634 +01:11:59,593 --> 01:12:01,192 +And so it's modular in that way. +所以在这方面,它是模块化的 + +1635 +01:12:01,194 --> 01:12:04,328 +You can also see that there's no communication between any +可以看到这里不再有其他箭头, + +1636 +01:12:04,330 --> 01:12:06,397 +other, there's no other arrows, except for +除了 + +1637 +01:12:06,399 --> 01:12:08,249 +some of the models. +一些 model + +1638 +01:12:08,250 --> 01:12:10,100 +You see some of the models are communicating with each other. +某些 model 之间在互相通信 + +1639 +01:12:10,102 --> 01:12:11,852 +You know a big +要知道, + +1640 +01:12:11,853 --> 01:12:13,603 +application might have a single shared model. +一个大型的应用也许会有一个单独的共享 model + +1641 +01:12:13,605 --> 01:12:17,606 +Or the models might be split off into pieces to be used by +或者,model 会被分开来 + +1642 +01:12:18,876 --> 01:12:20,208 +sub MVCs. +供子 MVC 使用 + +1643 +01:12:20,210 --> 01:12:21,326 +Okay? But +但是, + +1644 +01:12:21,327 --> 01:12:22,443 +that's the only kind of communication you have there. +这里只能使用这种通信方式 + +1645 +01:12:22,446 --> 01:12:23,678 +All other communication is +其它所有的通信 + +1646 +01:12:23,680 --> 01:12:26,681 +either the structure view communication we saw on MVC, +要么是 MVC 中的结构化通信, + +1647 +01:12:26,683 --> 01:12:29,716 +or it's using MVCs as part of the view of another MVC. +要么是将 MVC 用作另一个 MVC 视图的一部分 + +1648 +01:12:31,386 --> 01:12:32,385 +Any question about that? +有问题吗? + +1649 +01:12:33,688 --> 01:12:36,689 +So we definitely don't want to be having designs that +所以我们当然不希望 + +1650 +01:12:36,691 --> 01:12:38,190 +look like this, okay? +设计成这样, + +1651 +01:12:38,192 --> 01:12:39,824 +Where everybody's talking to everybody. +所有都在互相通信, + +1652 +01:12:39,826 --> 01:12:41,459 +We can't tell who's talking to what. +我们不能分清谁在和什么通信 + +1653 +01:12:41,461 --> 01:12:43,994 +It's just impossible to debug a program like this, and +这会让调试程序变得异常艰难, + +1654 +01:12:43,996 --> 01:12:45,446 +it doesn't scale. +而且它无法规模化 + +1655 +01:12:45,447 --> 01:12:46,897 +You can't build really big programs this way. +你不能通过这种方式创建出大程序 + +1656 +01:12:46,899 --> 01:12:48,165 +It just becomes impossible to +这样的话, + +1657 +01:12:48,167 --> 01:12:51,634 +know how touching anything would break everything, right? +你无法弄清楚,什么地方会引发整个程序的崩溃 + +1658 +01:12:51,636 --> 01:12:53,469 +So we're definitely not going to be doing that. +所以我们绝对不会这样做的 + +1659 +01:12:54,639 --> 01:12:57,573 +All right so that's MVC and, +所以,这就是 MVC, + +1660 +01:12:57,575 --> 01:13:00,875 +like I say, on Monday we'll apply MVC to our calculator. +我们将会在周一的课里把 MVC 应用到我们的 calculator 中 + +1661 +01:13:01,845 --> 01:13:02,977 +So what's coming up? +所以,接下来是什么? + +1662 +01:13:02,979 --> 01:13:06,146 +I always try to get to this slide every lecture. +我每节课都尽量讲到这里, + +1663 +01:13:06,148 --> 01:13:09,716 +Sometimes I forget but it's posted in the slides. +有时我会忘记,但是它被放到了课件中 + +1664 +01:13:09,718 --> 01:13:12,018 +It says tomorrow is Friday. +周五也就是明天, + +1665 +01:13:12,020 --> 01:13:14,320 +No, day after tomorrow is Friday. +不对,后天的周五, + +1666 +01:13:14,322 --> 01:13:17,256 +And people who are watching on iTunes U, +在 iTunes U 上观看的同学们, + +1667 +01:13:17,258 --> 01:13:19,858 +these Friday sections will not be on iTunes U so +周五的部分不会被放到 iTunes U 上, + +1668 +01:13:19,860 --> 01:13:22,461 +don't go looking for them only the normal Monday, +只有周一和周三的才会被放上去, + +1669 +01:13:22,463 --> 01:13:24,596 +Wednesday lectures went on iTunes U. +所以不要到处找 + +1670 +01:13:25,999 --> 01:13:27,164 +But, for Stanford students, +但是对于在坐的同学, + +1671 +01:13:27,166 --> 01:13:30,300 +Friday we have this debugger section we talked about. +周五我们将讨论之前谈到的调试部分 + +1672 +01:13:30,302 --> 01:13:32,769 +And then next Monday, +下周一,你们的阅读作业 + +1673 +01:13:32,771 --> 01:13:35,638 +your reading assignment is gonna be due. +将会截至 + +1674 +01:13:35,640 --> 01:13:37,040 +In other words, you should be done with that +换句话说,你应当在周一上课之前 + +1675 +01:13:37,042 --> 01:13:40,176 +reading assignment before the start of Monday's lecture. +完成阅读作业 + +1676 +01:13:40,178 --> 01:13:43,045 +And I'm gonna assign you another reading assignment. +我会再布置给你们一个阅读作业 + +1677 +01:13:43,047 --> 01:13:45,180 +It might be your only other reading assignment. +它将会是你们最后一个阅读作业 + +1678 +01:13:45,182 --> 01:13:46,815 +Perhaps there'll be a reassignment three, +也许以后还会有阅读作业, + +1679 +01:13:46,817 --> 01:13:48,383 +but it won't be any more than that. +但是不会像那个一样多 + +1680 +01:13:49,318 --> 01:13:50,351 +And then on Wednesday I'm +下周三,我会深入介绍 + +1681 +01:13:50,353 --> 01:13:53,420 +really gonna dive into Swift and Foundation. +Swift 语言和 Foundation 框架 + +1682 +01:13:53,422 --> 01:13:56,556 +I'm gonna talk a little bit about the Objective C legacy, +我将会介绍一点遗留下来的 Objective-C + +1683 +01:13:57,625 --> 01:13:59,425 +and then your assignment one is gonna be +你们的作业一将会在 + +1684 +01:13:59,427 --> 01:14:00,792 +due a week from today. +一周后截止 + +1685 +01:14:00,794 --> 01:14:05,129 +It's been posted for you, and your assignment two is gonna +你们已经看到了,作业二将会在 + +1686 +01:14:05,131 --> 01:14:08,032 +go out next Wednesday and be due the Wednesday after that. +下周三布置下去,下下周三截止 + +1687 +01:14:08,034 --> 01:14:09,900 +Just for a little bit of advanced planning for +提前为你们所有人 + +1688 +01:14:09,902 --> 01:14:11,335 +all of you. +做一些计划 + +1689 +01:14:11,337 --> 01:14:12,235 +Okay? + +1690 +01:14:12,237 --> 01:14:13,202 +Any other questions? +还有问题吗? + +1691 +01:14:14,439 --> 01:14:15,904 +Okay, thank you. +好的,谢谢 + +1692 +01:14:15,906 --> 01:14:19,808 +>> For more, please visit us at stanford.edu. +>> 想了解更多,请登录 stanford.edu diff --git a/subtitles/3. Applying MVC.srt b/subtitles/3. Applying MVC.srt new file mode 100644 index 0000000..ed97cbc --- /dev/null +++ b/subtitles/3. Applying MVC.srt @@ -0,0 +1,8572 @@ +1 +00:00:00,001 --> 00:00:04,636 +[MUSIC] +音乐 + +2 +00:00:04,638 --> 00:00:07,171 +Stanford University. +斯坦福大学 + +3 +00:00:09,809 --> 00:00:13,343 +Okay, well welcome to CS193p, Winter 2015. +好的,热烈欢迎来到 CS193p 2015 冬季课程。 + +4 +00:00:13,345 --> 00:00:15,445 +This is Lecture NO.3. +这是第三堂课。 + +5 +00:00:15,447 --> 00:00:17,714 +This is gonna be all demo. +这节课将全部是演示。 + +6 +00:00:17,716 --> 00:00:21,283 +today, my voice is mostly recovered from last week, +跟上周比我今天的声音基本上恢复了, + +7 +00:00:21,285 --> 00:00:22,918 +not 100% as you can tell. +但如你们听到的,我并没有完全恢复。 + +8 +00:00:22,920 --> 00:00:23,985 +But it's getting there. +但是差不多了。 + +9 +00:00:25,455 --> 00:00:29,924 +So what we're gonna be doing today is a demo. +好的,我们今天将要进行一个演示。 + +10 +00:00:29,926 --> 00:00:31,825 +We're gonna extend our calculator a little bit, +我们会给计算器加点东西, + +11 +00:00:31,827 --> 00:00:33,460 +we're gonna make it more powerful. +让它功能更强大。 + +12 +00:00:33,462 --> 00:00:36,629 +But more importantly, we're gonna have it obey this MVC +更重要的是,我们将会让它遵从 MVC + +13 +00:00:36,631 --> 00:00:37,930 +design paradigm. +设计范例。 + +14 +00:00:37,932 --> 00:00:39,682 +'Kay? +好么? + +15 +00:00:39,683 --> 00:00:41,433 +So it's good, a pretty good example of showing how +因此,这是一个演示如何把(计算器里的)内容 + +16 +00:00:41,436 --> 00:00:44,670 +we're gonna separate the stuff into the camps here. +分成不同的部分(把 Model 从 View 中独立出来)的好例子。 + +17 +00:00:44,672 --> 00:00:46,138 +Now, we're gonna cover a bunch of other things, +现在我们要讲讲其他的,比如 + +18 +00:00:46,140 --> 00:00:48,473 +language features and stuff as I always do. +语言特性和用法这些惯例内容。 + +19 +00:00:48,475 --> 00:00:52,143 +That's really the primary goal of these first three lectures +这是前三节有演示的课的 + +20 +00:00:52,145 --> 00:00:54,078 +with the demo. +最主要的目标。 + +21 +00:00:54,079 --> 00:00:56,012 +So I just mean for you to see it in action because you can +我之所以将要向你们实时演示 + +22 +00:00:56,015 --> 00:00:59,750 +read all you want about Swift or, about iOS, but until you +是因为虽然你们能读到所有你们想读的关于 Swift 或者 iOS 的内容 + +23 +00:00:59,752 --> 00:01:02,619 +actually see it act, turning into an app, it's not real. +但直到你看到代码如何成为应用,才融会贯通。 + +24 +00:01:02,621 --> 00:01:04,420 +So I'm just trying to make it real for you. +因此我会试着将应用的编写的过程展示给你们。 + +25 +00:01:06,057 --> 00:01:08,590 +I'm going to go to my last slide, because, +我会讲完最后一张幻灯片, 因为, + +26 +00:01:08,592 --> 00:01:11,093 +once I go to the demo, I'll forget to come back. +我一旦开始做演示就停不下来了。 + +27 +00:01:11,095 --> 00:01:13,895 +Which is just the what's coming up in this class. +这张幻灯片仅仅是说明接下来这门课要讲什么。 + +28 +00:01:13,897 --> 00:01:17,031 +On Wednesday, it's gonna be no demo, it's gonna be all +本周三没有课上演示,全是幻灯片, + +29 +00:01:17,033 --> 00:01:19,967 +slides, it's going to be one of the few lectures where it's all slides +这种课不会多,但这节是其中之一。 + +30 +00:01:21,186 --> 00:01:22,402 +But what I'm gonna try to do, +我会尝试 + +31 +00:01:22,405 --> 00:01:25,205 +on Wednesday, is give you the highlights of this all +在周三的课上划出你们现阶段 + +32 +00:01:25,207 --> 00:01:27,307 +this reading that you're doing. +所学重点。 + +33 +00:01:27,309 --> 00:01:28,658 +Okay? Because you're +可以么?因为 + +34 +00:01:28,659 --> 00:01:30,008 +reading a lot of stuff and it's sometimes hard to +你们要读很多的东西,有时候区分 + +35 +00:01:30,011 --> 00:01:32,611 +tell what's really important in there and what's not. +哪些是重点哪些不是重点会比较困难。 + +36 +00:01:32,613 --> 00:01:34,279 +So I'm gonna kinda give you the highlights so +因此我会给你们划重点, + +37 +00:01:34,281 --> 00:01:36,448 +you can get an idea of what's important. +这样你们会对重点内容有些概念。 + +38 +00:01:36,450 --> 00:01:40,618 +And then I'm also gonna start talking about some of +接着我会开始讲一些 + +39 +00:01:40,620 --> 00:01:45,255 +the foundation layer API in iOS that's the non, +iOS 中基础层的 + +40 +00:01:45,257 --> 00:01:47,891 +user interface layer basically and +非用户界面 API,大体上讲, + +41 +00:01:47,893 --> 00:01:51,227 +kinda what some of the classes are in there. +和其中包含的一些类。 + +42 +00:01:51,229 --> 00:01:54,130 +And then also just a little bit of how we use the language +接着是一点点关于如何使用 iOS 中 Swift 语言特性 + +43 +00:01:54,132 --> 00:01:57,099 +features of Swift, and Foundation, in iOS so +和一些关于 Foundation 框架的东西。 + +44 +00:01:57,101 --> 00:02:00,169 +that you can kinda get this kind of your +这样在一定程度上, + +45 +00:02:00,171 --> 00:02:01,870 +next Wednesday's lecture, +本周三的课, + +46 +00:02:01,872 --> 00:02:03,772 +is gonna be your baseline lecture, +会成为你当做奠基的课程。 + +47 +00:02:03,774 --> 00:02:07,241 +can kinda get you grounded in how to do all this stuff. +你在一定程度会获得如何做这些东西的根基。 + +48 +00:02:07,243 --> 00:02:10,044 +And then next week we'll start diving in, +然后接下来一周我们开始深入, + +49 +00:02:10,046 --> 00:02:13,814 +to build a more sophisticated iOS application. +写一个更成熟高端的 iOS 应用。 + +50 +00:02:13,816 --> 00:02:15,682 +Okay, I know this is kind of a whirlwind in first two +好的,我知道头两周会有些吃力, + +51 +00:02:15,684 --> 00:02:18,752 +weeks, you're learning a new language, all new system. +你们将在其间学一门新的编程语言,一个全新的体系。 + +52 +00:02:18,754 --> 00:02:20,920 +But hopefully by the end of this week and the end of your +但是希望在这周以及 + +53 +00:02:20,922 --> 00:02:24,757 +second assignment which will go out on Wednesday you'll be +将在周三布置的第二个作业结束之后, + +54 +00:02:24,759 --> 00:02:26,225 +pretty confident that you'll at least, +你能够比较确信,至少自己, + +55 +00:02:26,227 --> 00:02:30,595 +you know, have a, solid ground foundation to build from, +额...有一个的坚实的基础。 + +56 +00:02:30,597 --> 00:02:31,662 +no pun intended there. +我不是在说笑。 + +57 +00:02:33,032 --> 00:02:36,767 +There's a holiday weekend this weekend no Friday section and +这周末有公众假期,所以这周五没课, + +58 +00:02:36,769 --> 00:02:39,603 +no class on Monday until we resume next Wednesday, and +下周一也没课,直到下周三重新开始上课, + +59 +00:02:39,605 --> 00:02:42,305 +the primary thing I'm gonna do next Wednesday, +下周三我的首要任务是 + +60 +00:02:42,307 --> 00:02:44,341 +not day after tomorrow but +不是后天的周三 + +61 +00:02:44,342 --> 00:02:46,376 +the next Wednesday, is talk a little more about AutoLayout. +是下周周三,是讲一些关于 AutoLayout 的内容。 + +62 +00:02:46,378 --> 00:02:49,445 +Cause you've only just seen kind of a glimpse of +因为到目前为止你们只是瞥见了一点关于 + +63 +00:02:49,447 --> 00:02:51,013 +AutoLayouts so far and +AutoLayout 的内容。 + +64 +00:02:51,015 --> 00:02:53,849 +I haven't even really told you how to do AutoLayout and so +我实际上并没有告诉你们如何做 AutoLayout + +65 +00:02:53,851 --> 00:02:55,383 +you're kinda just fumbling around and trying, +你们差不多只是在摸索和尝试 + +66 +00:02:55,385 --> 00:02:58,619 +trying to reproduce what I do so next Wednesday we'll +重现我做过的内容,所以下周三 + +67 +00:02:58,621 --> 00:03:01,588 +talk about how to really do AutoLayout hm, and all that. +我们会讲如何做真正的 AutoLayout 和相关内容。 + +68 +00:03:02,825 --> 00:03:05,225 +'Kay, any questions before I dive into this demo? +好的,在我开始演示之前还有没有问题? + +69 +00:03:06,194 --> 00:03:10,396 +Hopefully my voice will hold out I can already hear it +希望我的声音能坚持住,我已经感觉到 + +70 +00:03:10,398 --> 00:03:14,065 +starting to not hold out but we will see. +嗓子有些挺不住了,但是...看看吧。 + +71 +00:03:14,067 --> 00:03:15,266 +All right. +好的。 + +72 +00:03:15,268 --> 00:03:21,839 +So, I'm going to just go to Xcode here, launch Xcode. +嗯,我现在点这里的 Xcode,运行 Xcode。 + +73 +00:03:22,941 --> 00:03:25,942 +And we're gonna leave off right where we, were, +我们将继续上次课程, + +74 +00:03:25,944 --> 00:03:27,410 +last time, in the calculator. +计算器程序的编写。 + +75 +00:03:28,846 --> 00:03:32,681 +There it is right here, and so these are UI. +都在这里了,这是 UI。 + +76 +00:03:32,683 --> 00:03:34,783 +Hopefully you recognize that and you did, +希望你们都认出来了并且 + +77 +00:03:34,785 --> 00:03:36,051 +did your homework. +做了作业。 + +78 +00:03:36,053 --> 00:03:38,070 +I hope. +我希望。 + +79 +00:03:38,071 --> 00:03:40,088 +And here is this area that I selected at the end, +这是我在代码尾部选中的区域, + +80 +00:03:40,090 --> 00:03:43,290 +which is this area that's really has not, +这块区域并不是, + +81 +00:03:43,292 --> 00:03:47,928 +this is not about how, how the calculator gets presented on +并不是负责计算器如何在屏幕上呈现的(并不是 Controller 的工作), + +82 +00:03:47,930 --> 00:03:51,064 +screen, this blue area is about how the calculator is +这块蓝色的区域是关于这个计算器, + +83 +00:03:51,066 --> 00:03:52,165 +a calculator, Okay? +为什么是个计算器(应该是 Model 的工作),可以么? + +84 +00:03:52,167 --> 00:03:54,367 +This is where all our calculations are and +这里是存放运算的地方, + +85 +00:03:54,369 --> 00:03:57,302 +this blue area really shouldn't be in this class, +这个蓝色区域不应该出现在这个类里, + +86 +00:03:57,304 --> 00:04:00,839 +this ViewController class because this is the C +这个视图控制器类,因为这是我们 MVC 模型的中的 C + +87 +00:04:00,841 --> 00:04:01,973 +of our MVC, Okay. +控制器(Controller),好么? + +88 +00:04:01,975 --> 00:04:06,910 +And our MVC, this is the C, this is the V, the View, +我们的 MVC 模型,这是控制器(Controller),这是视图(View), + +89 +00:04:06,912 --> 00:04:09,546 +these are the minions that this Controller's using. +它们是控制器使用的小兵们。 + +90 +00:04:09,548 --> 00:04:11,948 +And today we're gonna create the M. +今天我们将构建计算器的模型(Model)。 + +91 +00:04:11,950 --> 00:04:13,349 +Okay? The Model. +好么?模型。 + +92 +00:04:13,351 --> 00:04:15,351 +The Model is gonna be what our calcu, +这个模型将会决定我们的计(口误), + +93 +00:04:15,353 --> 00:04:18,854 +what our application is, which is, it's a calculator. +我们的应用是什么,也就是一个计算器。 + +94 +00:04:18,856 --> 00:04:20,155 +'Kay? +好么? + +95 +00:04:20,157 --> 00:04:23,758 +We're also going to enhance our calculator the primary new +我们将会加强这个计算器, 我们将赋予 + +96 +00:04:23,760 --> 00:04:26,360 +feature we're gonna give our calculator is that +它的首要新特性是 + +97 +00:04:26,362 --> 00:04:30,030 +our calculators Model is gonna remember every operand and +我们的计算器模型将会记住所有我们要求的 + +98 +00:04:30,032 --> 00:04:32,833 +operation you ever asked it to do. +操作数和操作符。 + +99 +00:04:32,835 --> 00:04:38,271 +Okay, so right now as we do operations we consume all +好的,现在当我们做运算的是时候我们假设我们用完了所有 + +100 +00:04:38,273 --> 00:04:39,505 +the operands. +操作数。 + +103 +00:04:39,507 --> 00:04:41,040 +'Kay, they consume, kinda, they're gone. +他们都用完了,没有了。 + +104 +00:04:42,276 --> 00:04:43,792 +So in this case, +所以在这种情况下, + +105 +00:04:43,793 --> 00:04:45,309 +we're going to actually collect all the operations and +我们要收集所有在堆栈中的操作符和 + +106 +00:04:45,312 --> 00:04:48,346 +operands in our, in a stack and then we can +操作数,然后我们可以 + +107 +00:04:48,348 --> 00:04:53,350 +ask the Model to, evaluate that stack of operations and +要求我们模型,在任何时候求出我们 + +108 +00:04:53,352 --> 00:04:55,385 +operands at any time we want. +所有操作运算的值。 + +109 +00:04:55,387 --> 00:04:57,654 +And the reason we're adding that ability is because your homework, +我们增加这个功能的原因是因为你们的家庭作业, + +110 +00:04:57,656 --> 00:05:00,256 +assignment number two, you're gonna add two +第二份作业,你需要添加两个 + +111 +00:05:00,258 --> 00:05:03,726 +major features where having all the operands and the +主要功能,它包括所有的操作数和操作符, + +112 +00:05:03,728 --> 00:05:06,628 +operations in a stack is gonna be really valuable to you. +这将会对你很有用的。 + +113 +00:05:06,630 --> 00:05:09,264 +So you'll be starting your second homework with what I +所以你要开始做第二份作业, + +114 +00:05:09,266 --> 00:05:12,334 +do today cause you'll need this capability to do what I +用我今天讲的东西,因为在里面你将会用到 + +115 +00:05:12,336 --> 00:05:13,735 +ask you there. +这些知识。 + +116 +00:05:13,737 --> 00:05:14,902 +Okay, and I'll talk about that at the end. +我会在结束的时候说一下这个问题。 + +117 +00:05:14,904 --> 00:05:17,237 +If I forget to talk about that, remind me. +如果我忘记说的话,提醒我一下。 + +118 +00:05:17,239 --> 00:05:21,240 +Say, tell us about assignment two. Okay. +就说和我们说一下第二份作业。 + +120 +00:05:21,242 --> 00:05:22,908 +So, how do we create a new class. +那么,我们怎么去创建一个新的类呢? + +121 +00:05:22,910 --> 00:05:25,911 +Because we're gonna put our Model, 'kay, the calculator, +因为我们要把我们的模型,这个计算器, + +122 +00:05:25,913 --> 00:05:28,680 +kind of, it, it's the guts, in a different class. +它的内脏,放在另一个类里面(不放在 Controller 里面)。 + +123 +00:05:28,682 --> 00:05:31,983 +So how do we create a new class, in Xcode. +那么,我们应该怎么用 Xcode 创建一个新的类? + +124 +00:05:31,985 --> 00:05:33,651 +We do that up here from the File menu. +我们从这上面找到文件菜单。 + +125 +00:05:33,653 --> 00:05:35,619 +We go, New > File. +然后选择,New -> File。 + +126 +00:05:35,621 --> 00:05:38,489 +So, you're gonna do File menu > New > File for a lot of +所以你要使用 File -> New -> File + +127 +00:05:38,491 --> 00:05:41,291 +different things you're gonna add to your project. +来为你的项目来添加很多各种不同的东西。 + +128 +00:05:41,293 --> 00:05:43,693 +Not even just, new classes or +不仅如此,新的类 + +129 +00:05:43,695 --> 00:05:46,863 +whatever, but, when you click that you're gonna see +或者随便什么,当你点击那里的时候你将会看到, + +130 +00:05:46,865 --> 00:05:48,497 +there's a lot of different things you could add. +你可以添加很多不一样的东西。 + +131 +00:05:48,499 --> 00:05:49,865 +And, we're in iOS, so +我们现在做的是 iOS,所以 + +132 +00:05:49,867 --> 00:05:52,267 +you're gonna click on this iOS thing at the top. +你需要点击上面的 iOS + +133 +00:05:52,269 --> 00:05:53,635 +And we wanna add a source file. +我们想要添加一个资源文件。 + +134 +00:05:53,637 --> 00:05:56,671 +And over here we're gonna be doing this later in the quarter, +在之后的学习中,我们将会添加这种文件, + +135 +00:05:56,673 --> 00:06:04,378 +this is how we basically add subclasses of iOS classes, Co, Cocoa Touch classes. +我们主要用这种方式来添加 iOS 的类和 Cocoa Touch 的类的子类。 + +137 +00:06:04,380 --> 00:06:06,446 +But we're gonna do today this one Swift File, +但是今天我们添加一个 Swift 的文件, + +138 +00:06:06,448 --> 00:06:08,948 +you can see it's an empty Swift File. +你可以看到这是一个空的 Swift 文件。 + +139 +00:06:08,950 --> 00:06:11,517 +And since our Model is completely UI independent it doesn't inherit, +因为我们的模型是一个完全和 UI 独立的类,它不需要继承, + +140 +00:06:11,519 --> 00:06:15,287 +it doesn't subclass any iOS class or anything, +它不是 iOS 或者其他的类的子类, + +141 +00:06:15,289 --> 00:06:17,923 +it's just a basic, Swift File. +它只是一个基本的 Swift 文件。 + +142 +00:06:17,925 --> 00:06:19,824 +So I'm gonna pick on this Swift File, +所以我要选中这个 Swift 文件, + +143 +00:06:19,826 --> 00:06:23,394 +click Next, and now it wants to know the name of +点击下一步,现在它需要知道文件名 + +144 +00:06:23,396 --> 00:06:26,564 +it and where we wanna put it, and we're gonna put it in +和存放的位置,我们想把它放在 + +145 +00:06:26,566 --> 00:06:29,466 +the same place that all our other Swift files are. +和其他 Swift 文件相同的位置。 + +146 +00:06:29,468 --> 00:06:30,901 +Here's our Controller and +这是我们的 Contriller, + +147 +00:06:30,902 --> 00:06:32,335 +this AppDelegate, we moved it out of the way at the very +这个 AppDelegate,在第一节课最开始的时候我们把它移出去了, + +148 +00:06:32,338 --> 00:06:34,571 +beginning of the very first lecture but it's in there too. +但是它现在又在这里了。 + +149 +00:06:34,573 --> 00:06:36,439 +So we want to put it in this same directory. +所以我们想把它放在相同的路径下面。 + +150 +00:06:36,441 --> 00:06:41,910 +And we're gonna call this new class CalculatorBrain. +我们把这个新的类叫做 CalculatorBrain + +151 +00:06:41,912 --> 00:06:43,645 +Now, you don't have to have the name of +在这里,你不用非得把这个 Swift 文件的名字 + +152 +00:06:43,647 --> 00:06:47,048 +this Swift File here be the name of the primary class but +写成和这个主类一样, + +153 +00:06:47,050 --> 00:06:48,049 +we always do that. +但是我们一般都这么写。 + +154 +00:06:48,051 --> 00:06:49,617 +It would be kinda confusing to +如果 Swift 的文件名, + +155 +00:06:49,619 --> 00:06:52,019 +people a little bit if the name of the Swift File +不同于这里面的任何的主类, + +156 +00:06:52,021 --> 00:06:54,554 +was different than whatever the primary class is in there. +会让人有点困惑。 + +157 +00:06:54,556 --> 00:06:55,755 +But it's certainly legal. +但是它是完全合法的。 + +158 +00:06:55,757 --> 00:06:56,422 +All right. +好了。 + +159 +00:06:56,424 --> 00:06:58,857 +And Swift, the name of the file really doesn't mean anything. +而且在 Swift 中,文件名并不代表着什么。 + +161 +00:06:58,859 --> 00:07:00,359 +It's what's inside that matters. +它里面有什么才是主要的。 + +162 +00:07:00,361 --> 00:07:04,929 +But, CalculatorBrain is gonna be the name of our class, our Model. +但是,CalculatorBrain 将会是我们类和模型的名字, + +164 +00:07:04,930 --> 00:07:06,396 +I'm calling it that cause it's the brain of our calculator, +我这么叫它是因为它是我们计算器的大脑, + +165 +00:07:06,399 --> 00:07:07,898 +I'm trying to pick a descriptive name. +我尝试着取一个描述性的名字。 + +166 +00:07:09,201 --> 00:07:12,302 +Notice the capitalization here, +注意这里的大写, + +167 +00:07:12,304 --> 00:07:16,306 +types in Swift, we always capitalize them. +Swift 里面的类型,我们一般都用大写(名字的第一个字母)。 + +168 +00:07:16,308 --> 00:07:19,409 +And we do not put underbars and other stuff in there. +我们不把下划线之类的东西放在这里。 + +169 +00:07:19,411 --> 00:07:20,609 +Okay? We use what's called this +在这里我们使用一个叫做 + +170 +00:07:20,611 --> 00:07:25,380 +camel notation here, where every word gets capitalized, +驼峰命名法(camel notation),每一个单词(第一个字母)都要有大写, + +171 +00:07:25,382 --> 00:07:27,882 +including the first name, word for types. +包括名字和类型。 + +172 +00:07:27,884 --> 00:07:31,219 +Everything else, we don't capitalize. +其他的东西,我们都不用大写(第一个字母)。 + +173 +00:07:31,221 --> 00:07:34,755 +So property names and things like that, function names, +所有属性的名字和其他一些类似的,函数名, + +174 +00:07:34,757 --> 00:07:36,457 +those all start with lower case, +这些都要开头都用小写, + +175 +00:07:36,459 --> 00:07:38,992 +they still do the uppercase and the other words. +但是他们后面的单词的首字母要用大写。 + +176 +00:07:38,994 --> 00:07:40,427 +That way we, in our reading our code we +用这种方法,我们读代码的时候, + +177 +00:07:40,429 --> 00:07:43,196 +can really quickly pick out what to type and what to not. +我们可以很快的找到我们想要的。 + +178 +00:07:43,198 --> 00:07:45,164 +'Kay? So please adhere to that. +所有请坚持这么写, + +179 +00:07:45,166 --> 00:07:48,334 +If you don't, you're gonna look like a newb out there. +如果你不这么做的话,那你看起来就像一个新手了。 + +180 +00:07:48,336 --> 00:07:49,501 +'Kay. CalculatorBrain's what we're +好了,我们叫它 CalculatorBrain 的, + +181 +00:07:49,503 --> 00:07:50,835 +gonna call it, I'm gonna create it. +下面我要开始创建它。 + +182 +00:07:51,938 --> 00:07:53,121 +Here it is right here. +这里。 + +183 +00:07:53,122 --> 00:07:54,305 +I'm gonna make it my whole screen. +我把它设置为全屏。 + +184 +00:07:55,541 --> 00:07:58,975 +You can see that the import here is not import UIKit, +你可以看到这里导入的库,但是没有导入 UIKit, + +185 +00:07:58,977 --> 00:08:00,477 +it's import Foundation. +只导入了 Foundation。 + +186 +00:08:00,479 --> 00:08:03,379 +Foundation is that layer, that kinda core services layer I +Foundation 是一个核心的服务层, + +187 +00:08:03,381 --> 00:08:05,581 +talked about in the first lecture. +在第一节课里我已经讲过了。 + +188 +00:08:05,583 --> 00:08:07,883 +It don't have many UI stuff in it which is good because our +它没有太多 UI 的东西,这是很好的,因为 + +189 +00:08:07,885 --> 00:08:11,687 +Model is UI independent so there should be no UI in here. +我们的模型是独立于 UI 的,所以这里应该没有 UI 的东西。 + +190 +00:08:11,689 --> 00:08:17,392 +So we would never be importing UIKit into a Model class, 'kay? +所以我们永远不要在模型类里导入 UIKit。 + +192 +00:08:17,393 --> 00:08:18,826 +You can feel free to stop me, by the way, +顺便说一句,你们可以随时让我停下来, + +193 +00:08:18,828 --> 00:08:19,793 +if you have any questions. +如果你有任何的问题。 + +194 +00:08:19,795 --> 00:08:22,095 +All right, so we're gonna create a new class, +好,那么我们要创建一个新类, + +195 +00:08:22,097 --> 00:08:23,029 +you already know how to do that. +你已经知道该怎么去做了。 + +196 +00:08:23,031 --> 00:08:24,364 +We just type class and +我们创建这个类, + +197 +00:08:24,366 --> 00:08:27,500 +then the name of the class, it's gonna be CalculatorBrain. +然后给这个类取一个名字,我们就叫它 CalculatorBrain。 + +198 +00:08:27,502 --> 00:08:32,537 +Now, this class is not going to inherit from any other class, +现在,这个类不会继承其他的类, + +200 +00:08:32,539 --> 00:08:35,640 +Just gonna be a basic Swift, class. +只是一个基本的 Swift 类。 + +201 +00:08:35,642 --> 00:08:38,509 +Now sometimes your Model might inherit from a class called +有时候你的模型会继承一个叫做 + +202 +00:08:38,511 --> 00:08:40,861 +NSObject, and +NSObject 的类, + +203 +00:08:40,862 --> 00:08:43,212 +I'll talk about that a little later maybe on Wednesday even. +这个我后面会讲解,甚至可能在周三讲。 + +204 +00:08:43,215 --> 00:08:46,683 +You'll get a little bit if you inherit from NSObject, but +如果继承 NSObject,你将会得到一些(函数),但是 + +205 +00:08:46,685 --> 00:08:50,587 +we're just gonna have it be basic Swift base class, 'kay. +这里我们就用 Swift 基类。 + +206 +00:08:50,589 --> 00:08:55,224 +It doesn't, doesn't need to inherit any functionality. Okay. +它不需要继承任何功能函数。 + +208 +00:08:55,225 --> 00:08:56,758 +So what's gonna be our data structure of +所以,我们的 CalculatorBrain 的 + +209 +00:08:56,761 --> 00:08:57,859 +our CalculatorBrain. +数据结构是什么样的呢? + +210 +00:08:57,861 --> 00:08:59,961 +It, it has to be a little different than the data +它必须有点不同于我们的 + +211 +00:08:59,963 --> 00:09:01,662 +structure we used in our Controller to +Controller 中用于捕获操作数的数据结构, + +212 +00:09:01,664 --> 00:09:04,565 +capture the operand because we gotta capture operand, +因为我们得捕获操作数,操作符 + +213 +00:09:04,567 --> 00:09:07,368 +operations and operands both into this. +以及两者的运算。 + +214 +00:09:07,370 --> 00:09:12,305 +So we want it to be a stack, I'm gonna call it opStack and +所以,我们需要一个栈,我称之为 opStack, + +215 +00:09:12,307 --> 00:09:14,741 +but the type can't be array of Double. +但是这个类型不能是 Double 数组。 + +216 +00:09:15,743 --> 00:09:20,245 +Okay, because operands are Doubles but operations +因为操作数是 Doubles,但操作符则像 + +217 +00:09:20,247 --> 00:09:23,648 +are like a combination of a syn, a mathematical symbol +一种符号的结合,一个数学符号。 + +218 +00:09:23,650 --> 00:09:26,651 +like plus, times and then also a function. +比如相加,相乘,当然也包括函数。 + +219 +00:09:26,653 --> 00:09:29,186 +Function that actually does the thing, 'kay? +函数实际上也是同样的东西。 + +220 +00:09:29,188 --> 00:09:30,888 +So obviously we can't do that so +所以显然,我们不能这么做, + +221 +00:09:30,890 --> 00:09:32,022 +we're gonna have to need some, +我们需要一些, + +222 +00:09:32,024 --> 00:09:34,691 +some new data structure I'm gonna call that data +新的数据结构,我叫这种数据结构 + +223 +00:09:34,693 --> 00:09:37,760 +structure op and we're gonna define that in a second. +为 op,我们随后就定义这个结构。 + +224 +00:09:37,762 --> 00:09:41,663 +So op is gonna be something that could be an operand or +所以 op 可能是操作数, + +225 +00:09:41,665 --> 00:09:43,532 +maybe it could be an operation. +也可能是操作符。 + +226 +00:09:43,534 --> 00:09:47,519 +'Kay? It could be either or. 'Kay? +它可能是两者中的任一种 + +228 +00:09:47,520 --> 00:09:49,804 +Now a couple of things about this here is of course I +现在有几件事情要做,当然, + +229 +00:09:49,806 --> 00:09:51,572 +have to initialize this so I'm gonna do +我需要初始化, + +230 +00:09:51,574 --> 00:09:54,575 +the exact same thing that I did in the Controller which is +我将做在 Controller 中同样的事情, + +231 +00:09:54,577 --> 00:09:59,496 +I'm just gonna create an empty array of op. 'Kay? +那就是我要创建一个新的 op 数组, + +233 +00:09:59,497 --> 00:10:02,181 +And I'm even gonna use a little different syntax, 'kay? +我甚至要用一点不一样的语法, + +234 +00:10:02,183 --> 00:10:03,382 +We've been using this. +我们使用这个, + +235 +00:10:03,384 --> 00:10:05,851 +I like this syntax because especially for +我喜欢这个语法,特别是对于 + +236 +00:10:05,853 --> 00:10:08,553 +people who are first time to Swift it's very clear, +那些初次接触 Swift 的同学,它非常清晰, + +237 +00:10:08,555 --> 00:10:12,624 +this is an array and inside the array are these ops but +这是一个数组,在数组中,是这些 op, + +238 +00:10:12,626 --> 00:10:17,661 +this is evidently not the syntax that is preferred. +但这明显并不是推荐使用的语法, + +239 +00:10:17,663 --> 00:10:23,433 +The preferred syntax is actually to do [Op] 'kay? +推荐的语法实际上是使用 [Op]。 + +240 +00:10:23,435 --> 00:10:27,070 +So this is just an alternate syntax, putting square +这是另一种可选择的语法,把类型放在 + +241 +00:10:27,072 --> 00:10:29,739 +brackets with the type in the middle for declaring an array. +方括号中,这样就声明了一个数组。 + +242 +00:10:29,741 --> 00:10:32,008 +It's exactly the same thing just different way of +这是一样的东西,只是不一样的方式, + +243 +00:10:32,010 --> 00:10:34,276 +typing in, identical in every possible way, +写法不一样,但其他都一样。 + +244 +00:10:34,278 --> 00:10:37,062 +it's exactly the same. Okay. +真的是相同的东西。 + +246 +00:10:37,063 --> 00:10:38,346 +I think this is a little bit preferred because if +我认为这是更好的方式因为 + +247 +00:10:38,348 --> 00:10:41,449 +you ever initialize an array which will see later. +如果你曾初始化过数组,你就会明白的。 + +248 +00:10:41,451 --> 00:10:43,884 +You use this syntax to create the array and +你使用这种语法创建数组, + +249 +00:10:43,886 --> 00:10:45,686 +put things in it. +并将东西放在其中。 + +250 +00:10:45,687 --> 00:10:47,487 +So I, I can understand why they do that. +所以我很理解他们这样做的原因。 + +251 +00:10:47,490 --> 00:10:50,257 +Okay? So this is an array of op. +这是一个 op 数组。 + +252 +00:10:50,259 --> 00:10:50,924 +That make sense? +这很容易理解。 + +253 +00:10:51,860 --> 00:10:53,859 +Now, let's talk about op. +现在,让我们说说 op。 + +254 +00:10:53,861 --> 00:10:55,094 +What kinda thing should op be? +op 是什么东西呢? + +255 +00:10:55,096 --> 00:10:57,596 +Well, we could make op a class. +好吧,我们可以将 op 变成一个类。 + +256 +00:10:57,598 --> 00:10:59,731 +An op could have a property for op, +然后 op 应当有这些属性, + +257 +00:10:59,733 --> 00:11:02,033 +for an operand, which would be the value of the operand. +操作数,也就是操作数的值。 + +258 +00:11:02,035 --> 00:11:05,169 +It could have another property, which is the, +他还应该有另一个属性,那就是, + +259 +00:11:05,171 --> 00:11:07,371 +symbol, mathematical symbol for the operation and +符号,用于运算的数学符号, + +260 +00:11:07,373 --> 00:11:10,173 +another property, which was a function, which does it, +还有个属性,函数,用于实现计算, + +261 +00:11:10,175 --> 00:11:12,509 +and obviously, if the operand is set, +很明显,如果一个操作数被赋值了, + +262 +00:11:12,511 --> 00:11:15,144 +then the other two would be not set and vice versa. +那另两个(操作符和函数)就不会被赋值,反过来也一样。 + +263 +00:11:15,146 --> 00:11:18,481 +But that, that's a little bit weird to have a class that +但这样就有些奇怪,一个类拥有一些 + +264 +00:11:18,483 --> 00:11:21,250 +has properties that sometimes they're set and, +属性,有时他们被赋值了, + +265 +00:11:21,252 --> 00:11:23,218 +and if other things are set, they're not set. +但其他东西被赋值了,他们却没有值了。 + +266 +00:11:23,220 --> 00:11:24,285 +It's really not what we want. +这不是我们想要的。 + +267 +00:11:24,287 --> 00:11:27,621 +What we really want is an enum. +我们需要的是枚举类型。 + +268 +00:11:28,591 --> 00:11:31,658 +Okay, so you're probably used to enums in other languages so +你可能在其他编程语言中使用过枚举, + +269 +00:11:31,660 --> 00:11:32,959 +I'm gonna create an enum, +所以我将创建一个枚举, + +270 +00:11:32,961 --> 00:11:35,728 +[UNKNOWN] enum, it looks very similar creating a class. +和创建一个类类似。 + +271 +00:11:35,730 --> 00:11:38,397 +I just use the word enum instead of class, +我使用 enum,而不是 class。 + +272 +00:11:38,399 --> 00:11:41,633 +obviously no inheritance for enum, sorry. +显然,枚举没有继承特性。 + +273 +00:11:41,635 --> 00:11:45,537 +But enums can have functions, just like the class, +但枚举和类一样,有函数, + +274 +00:11:45,539 --> 00:11:49,474 +they can also have properties but only computed properties. +他们也有属性,但只能是计算类属性。 + +275 +00:11:49,476 --> 00:11:51,242 +'Kay, the Camry's stored properties. +Camry 存储属性。 + +276 +00:11:52,278 --> 00:11:55,779 +So you know enums are kinda for basic types and +你们知道枚举是基本类型, + +277 +00:11:55,781 --> 00:11:58,782 +enums are really great when you have something that can be +枚举非常棒,特别是你有一些东西,在某个 + +278 +00:11:58,784 --> 00:12:01,317 +one thing one time and a different thing another time. +时候有一个值,在别的一些时候有另外的值。 + +279 +00:12:01,319 --> 00:12:02,585 +And never both at the same time, +但不会同时拥有两个值。 + +280 +00:12:02,587 --> 00:12:03,952 +that's kinda what enums are right, +这样,使用枚举是对的, + +281 +00:12:03,954 --> 00:12:06,421 +they're enumerating different possibilities so +它们枚举不同的可能性,所以 + +282 +00:12:06,423 --> 00:12:09,257 +we could say you know case Operand and we could have +我们可以写"case Operand",同样我们也可以写 + +283 +00:12:09,259 --> 00:12:15,563 +a case Operation, to have the different things that we have. +"case Operation",去表达我们拥有的不同的东西。 + +284 +00:12:15,565 --> 00:12:19,133 +Now, in other languages, this would be as far as we can go. +在其他编程语言中,这就是我们所能做的最多的了。 + +285 +00:12:19,135 --> 00:12:21,101 +And this would be pretty useless. +然后这也是相当没用的, + +286 +00:12:21,103 --> 00:12:24,270 +Because if we had an array that just said whether it +因为如果我们有一个数组,他可能是一个 + +287 +00:12:24,272 --> 00:12:26,105 +was an operand or an operation, that doesn't help. +操作数,或者操作符,这没有任何帮助。 + +288 +00:12:26,107 --> 00:12:27,973 +I need the actual operand. +我需要一个实际的操作数。 + +289 +00:12:27,975 --> 00:12:30,242 +I need the operations mathematical symbol and +我需要的是数学符号,还有 + +290 +00:12:30,244 --> 00:12:31,977 +its function. +它的函数。 + +291 +00:12:31,978 --> 00:12:33,711 +I need them, they have to be in this enum. +我需要它们,它们要在这个枚举(enum)中。 + +292 +00:12:33,714 --> 00:12:36,448 +And Swift has a really cool feature where you can +Swift 有一个非常酷的特性,你们可以 + +293 +00:12:36,450 --> 00:12:41,085 +associate data with any of the cases in the enum. +将数据和任何 case 中的枚举关联起来。 + +294 +00:12:41,087 --> 00:12:44,021 +So for an operand I'm gonna associate the data Double. +所以对于一个操作数,我将关联 Double 数据。 + +295 +00:12:45,123 --> 00:12:48,157 +So if my enum is an operand it'll have this +所以如果我的枚举是一个操作数,它将有这个 + +296 +00:12:48,159 --> 00:12:49,558 +Double associated with it, +和它关联的 Double 数据, + +297 +00:12:49,560 --> 00:12:52,194 +that's gonna be the value of the operand. +这将是这个操作数的值。 + +298 +00:12:52,196 --> 00:12:54,013 +And similarly for +类似地, + +299 +00:12:54,014 --> 00:12:55,831 +operation I'm actually gonna do unary operation first, +对于操作符,我实际上首先使用一元操作(比如平方,开方等), + +300 +00:12:55,833 --> 00:12:57,866 +that's a single argument operation. +这是单个参数的运算。 + +301 +00:12:57,868 --> 00:13:00,768 +I'm gonna have a String which is gonna be the symbol, +首先我需要用一个字符串来表示符号, + +302 +00:13:00,770 --> 00:13:01,936 +the mathematical symbol for +数学运算符 + +303 +00:13:01,938 --> 00:13:04,238 +it and of course I'm gonna have a function. +我当然还需要一个函数来做这个运算 + +304 +00:13:05,341 --> 00:13:08,408 +Okay again functions are just types in Swift, +再重提一遍,函数在 Swift 里也是一种类型, + +305 +00:13:08,410 --> 00:13:11,344 +it's no different than String 'kay we're just saying this is +与字符串相比并没有任何的不同,我们只需要知道 + +306 +00:13:11,346 --> 00:13:13,612 +a function, put a function in there. +这是个函数,放在这就好了 + +307 +00:13:13,614 --> 00:13:15,147 +A lot of times we'll do the curly braces and +很多时候在这里我们会通过用花括号 + +308 +00:13:15,149 --> 00:13:17,883 +put a closure use closures to create our function but +写一个闭包来实现这个函数, + +309 +00:13:17,885 --> 00:13:19,584 +we could create actual functions and +但是我们也可以通过在其他地方写一个真正的函数 + +310 +00:13:19,586 --> 00:13:21,185 +pass them in there, that's fine. +然后传递进来,也是没有问题的 + +311 +00:13:21,187 --> 00:13:25,289 +So, and we'd also want a binary function here that takes two arguments. +继续,我们还需要一个有 2 个参数的二元运算函数, + +313 +00:13:26,959 --> 00:13:28,625 +Binary operation and +二元运算,然后 + +314 +00:13:28,627 --> 00:13:34,296 +just those two arguments here in it's function. Okay? +在里面加一个带 2 个参数的函数 + +316 +00:13:34,297 --> 00:13:37,499 +So now we have the stack. Okay. Which is an array of Ops. +我们这里还有一个栈,是由 Op 组成的数组 + +318 +00:13:37,501 --> 00:13:41,369 +And these ops are either each op in this, is array is either +这个数组的元素要么是一个操作数, + +319 +00:13:41,371 --> 00:13:44,638 +an operand or it's one of these two kinds of operations. +要么是刚才这个枚举里两种运算中的一种 + +320 +00:13:46,308 --> 00:13:49,142 +Okay so so this is great. +很好 + +321 +00:13:49,144 --> 00:13:53,979 +We got this op it's either an operation or an operand. +我们现在有了 Op,它是操作数或者是运算 + +322 +00:13:53,981 --> 00:13:59,251 +How are we going to, you know, put things into this opStack for example and something like that. +下边我们要做的是往 opStack 这个数组里放东西 + + +324 +00:13:59,253 --> 00:14:01,653 +So let, let's go talk about, the API. +这里简单说一下 API + +325 +00:14:01,655 --> 00:14:05,356 +A, API stands for application programing interface. +API 指的是应用程序接口 + +326 +00:14:05,358 --> 00:14:09,060 +API is kind of the methods, all the methods and properties +API 就是组成你的类里边所有属性 + + +327 +00:14:09,062 --> 00:14:13,230 +that make up your class, the description of them. +和方法的描述 + +328 +00:14:13,232 --> 00:14:16,066 +So I'll use that word a lot, API. +我之后会经常提到这个词 + +329 +00:14:16,068 --> 00:14:18,835 +And we really need to be able to put an operand on there and +现在我们需要想办法往 opStack 这个栈里压入 + +330 +00:14:18,837 --> 00:14:20,736 +stack, and we need to be able to put an operation on. +操作符和运算 + +331 +00:14:20,738 --> 00:14:24,573 +So I'm gonna have a function called pushOperand, and +所以我写一个叫 pushOperand 的函数, + +332 +00:14:24,575 --> 00:14:27,809 +it's gonna take an operand, which is a Double. +需要传入一个 Double 类型的参数作为操作数 + +333 +00:14:27,811 --> 00:14:30,578 +Okay it's not gonna return anything yet anyway. +不需要返回值 + +334 +00:14:30,580 --> 00:14:33,715 +And to push an operand on my stack, could not be easier, +要把一个操作数压进栈非常简单, + +335 +00:14:33,717 --> 00:14:36,217 +I'm just gonna say opStack.append, + 我只需要写 opStack.append, + +336 +00:14:36,219 --> 00:14:42,355 +you'll remember that append is a function in array and the thing that you put on, +要记住 append 是数组从尾部添加元素的函数, + + +338 +00:14:42,357 --> 00:14:45,858 +obviously has to be this little type T. +这有一个类型 T, + +339 +00:14:45,860 --> 00:14:48,627 +T is whatever you put in here, so op in this case. +T 代表你添加到数组里的类型,在这里是Op + +340 +00:14:48,629 --> 00:14:50,729 +So we have to have an op here. +我们要加一个 Op 进去 + +341 +00:14:50,731 --> 00:14:52,964 +How do you create an enum item? +我们怎么新建一个枚举项呢? + +342 +00:14:52,966 --> 00:15:01,539 +You just Op.Operand and you give it the associated value. Okay? +只需要写 Op.Operand 然后给它一个相关值 + +344 +00:15:01,541 --> 00:15:10,013 +So, very simple kind of way to create these enums and associate the value with them. +看,新建枚举项以及他们的相关值非常简单 + +346 +00:15:10,015 --> 00:15:11,114 +Any questions about that? +这里有问题吗? + +347 +00:15:12,450 --> 00:15:13,749 +Okay, and then how about operations? +好,那运算呢? + +348 +00:15:13,751 --> 00:15:15,384 +We'll have instead of push, +我们这次不写 push, + +349 +00:15:15,386 --> 00:15:18,720 +we're gonna call this performOperation. +而是写一个叫 performOperation(执行运算)的函数 + +350 +00:15:18,722 --> 00:15:20,922 +And I think when I do performOperation, what I'm +并且我希望当我执行 performOperation 的时候, + +351 +00:15:20,924 --> 00:15:23,024 +gonna have is, my CalculatorBrain is going to have +我的 CalculatorBrain 类已经有一些 + +352 +00:15:23,026 --> 00:15:26,493 +a bunch of known operations, things it knows how to do. +已知的运算以及他们具体的运算方法 + +353 +00:15:26,495 --> 00:15:27,861 +And when you perform an operation, +然后当你执行一个运算的时候, + +354 +00:15:27,863 --> 00:15:30,697 +you just specify the mathematical symbol of it. +你只需要写出它的数学符号就可以了 + +355 +00:15:30,699 --> 00:15:36,301 +So the argument here is going to be symbol, which is a String.Okay? +所以这个函数的参数是一个数学符号,也就是字符串 + +358 +00:15:36,303 --> 00:15:41,306 +So, to append an op on here that is, an operation, +我们要把运算,也就是一个 Op 压进栈, + +359 +00:15:41,308 --> 00:15:43,274 +I'm gonna need to have these known operations. +我需要用到已知的运算 + +360 +00:15:43,276 --> 00:15:44,775 +So, how am I gonna do that? +要怎么做呢? + +361 +00:15:44,777 --> 00:15:47,878 +Well, to have known operations, I'm gonna create +我们要新建另外一个实例变量 knownOps 作为 + +362 +00:15:47,880 --> 00:15:51,048 +another instance variable here called knownOps, so +存储已知运算的地方 + +363 +00:15:51,050 --> 00:15:55,251 +my known operations. And it's gonna be a dictionary. +这些已知的运算,是一个字典类型 + +365 +00:15:55,253 --> 00:15:58,987 +Okay, now, you read about dictionaries in last week's reading assignment. +上周的阅读材料里你们应该已经读到过字典类型了 + +367 +00:15:58,989 --> 00:16:00,489 +That's why I have the reading assignment due today. +这就是为什么今天是阅读材料的截止日期, + +368 +00:16:00,491 --> 00:16:02,257 +Cuz then I can know you've read about them. +这样我就能知道你们已经读过了 + +369 +00:16:02,259 --> 00:16:02,824 +I hope you have. +希望你们确实读了 + +370 +00:16:05,495 --> 00:16:07,428 +And so, how do I create a dictionary? +我们如何新建一个字典? + +371 +00:16:07,430 --> 00:16:08,995 +It looks like this, Dictionary. +像这样 + +372 +00:16:08,997 --> 00:16:11,531 +And it's the same kind of thing with these angled +同样是使用尖括号, + +373 +00:16:11,533 --> 00:16:14,434 +brackets, because you have to say for the dictionary, +你必须为字典 + +374 +00:16:14,436 --> 00:16:17,036 +what type are the keys, what type are the values. +建立相对应的键值关系 + +375 +00:16:17,038 --> 00:16:20,506 +And our dictionary is gonna have keys that are Strings and +在这里,键是字符串 + +376 +00:16:20,508 --> 00:16:22,874 +it's gonna have values that are ops. +值的类型是 Op + +377 +00:16:22,876 --> 00:16:26,478 +Oops, sorry, ops. +哦,对不起,Op + +378 +00:16:26,480 --> 00:16:29,947 +Okay, and I'm gonna create one. Okay? +好,新建了一个字典 + +380 +00:16:29,949 --> 00:16:32,316 +Everyone understand this? +大家都明白这个了吗? + +381 +00:16:32,317 --> 00:16:34,684 +Now, this knownOps, I'm just gonna put all of the ops that +现在在这个 knownOps 变量里,我要把所有 + +382 +00:16:34,687 --> 00:16:38,955 +I know in there, where the key is the symbol and the value is +我知道的运算放进去,键是符号 + +383 +00:16:38,957 --> 00:16:42,392 +the actual op, and then when someone says performOperation, +值是实际的 Op 也就是运算方法,每次我要执行 performOperation 时, + +384 +00:16:42,394 --> 00:16:44,527 +I'm gonna look it up in the knownOps. +我会去 knownOps 里去找那些已知的运算 + +385 +00:16:44,529 --> 00:16:47,329 +And when I find it, then that's the operation I'm +当我找到的时候,我就要把这个 + +386 +00:16:47,331 --> 00:16:49,531 +gonna push onto the stack, all right? +运算压到 opStack 这个栈里 + +387 +00:16:49,533 --> 00:16:51,183 +Make sense? +能明白吗? + +388 +00:16:51,184 --> 00:16:52,834 +But I have to load this knownOps up. +但是我需要预先载入 knownOps + +389 +00:16:52,836 --> 00:16:55,903 +Oh, but first of all, so let me talk about this syntax. +哦,首先,我要说一下这个语法 + +390 +00:16:55,905 --> 00:17:00,941 +Just like array has a special syntax with the square brackets, so does dictionary. +跟前边数组使用方括号的特殊语法一样,字典也可以这么写 + +392 +00:17:00,943 --> 00:17:03,510 +So to have a dictionary like this with this kind of +如果字典用这种写法, + +393 +00:17:03,512 --> 00:17:07,080 +special syntax, we're gonna do open square bracket. +我们需要用方括号, + +394 +00:17:07,082 --> 00:17:12,752 +And then a colon in between the key and +然后中间用冒号隔开键和值, + +395 +00:17:12,754 --> 00:17:15,254 +the value type, so it looks like that. +就像这样 + +396 +00:17:15,256 --> 00:17:17,789 +So it looks very similar to array, but +跟数组很像,但是 + +397 +00:17:17,791 --> 00:17:22,660 +you've got this thing where you've got the key and the value separated by a colon. Okay? +你需要用冒号把键和值分隔开 + +400 +00:17:23,796 --> 00:17:25,429 +Same thing, though, exact same thing. +其实是完全一样的 + +401 +00:17:25,431 --> 00:17:27,430 +Just a dictionary, Strings, +仅仅是字典,字符串, + +402 +00:17:27,432 --> 00:17:28,698 +looking up in Strings to find ops. +用字符串找 op + +403 +00:17:28,700 --> 00:17:32,701 +All right, so how am I gonna initialize this knownOps? +好,那我们怎么初始化这个已知的 op + +404 +00:17:32,703 --> 00:17:33,869 +Well, this is a great time for +这是我们 + +405 +00:17:33,871 --> 00:17:37,906 +the first time for you see an initializer, Okay? +第一次提到 initializer + +406 +00:17:37,908 --> 00:17:41,876 +So far we've been creating classes like right here, Okay, +到此,我们已经通过加括号 + +407 +00:17:41,878 --> 00:17:44,311 +just by putting these parentheses. +创建了一个像这样类。 + +408 +00:17:44,313 --> 00:17:46,680 +And I told you that was calling an initializer in +这就是在调用字典的 initializer , + +409 +00:17:46,682 --> 00:17:47,947 +Dictionary, Okay, and +好的, + +410 +00:17:47,949 --> 00:17:50,817 +this one was calling an initializer in Array. +这是在调用数组的 initializer + +411 +00:17:50,819 --> 00:17:52,585 +And so we're gonna have our own initializer in +然而,我们会为 CalculatorBrain 设置自己的 initializer + +412 +00:17:52,587 --> 00:17:55,421 +CalculatorBrain, and +并且 + +413 +00:17:55,422 --> 00:17:58,256 +we just do that by saying init, like this, Okay. +通过像 init 这样的形式 + +414 +00:17:58,258 --> 00:18:01,726 +Now any time someone says something like let brain equal +现在不论何时 使用 let brain = CalculatorBrain() + +415 +00:18:01,728 --> 00:18:05,296 +CalculatorBrain, with the parentheses, Okay? +得加上括号。 + +416 +00:18:05,298 --> 00:18:07,531 +It's going to call an init that +就会调用匹配对应 + +417 +00:18:07,533 --> 00:18:09,667 +matches the same arguments. +参数的 init 方法 + +418 +00:18:09,669 --> 00:18:11,668 +In this case, no arguments, so it's gonna call this init. +在这里,没有参数,所以将会调用这个 init 方法 + +419 +00:18:13,505 --> 00:18:14,070 +Okay. + +420 +00:18:15,439 --> 00:18:16,838 +Couldn't be simpler there. +就是这么简单 + +421 +00:18:16,840 --> 00:18:18,173 +So what are we gonna do in this init? +那我们要在这个初始化方法里做什么呢? + +422 +00:18:18,175 --> 00:18:20,375 +We're just gonna initialize this known op, so +我们将要初始化 op + +423 +00:18:20,377 --> 00:18:24,545 +I'm just gonna start putting some known ops into this +于是,加入一些已知的 op + +424 +00:18:24,547 --> 00:18:26,780 +knownOps dictionary. +到 op 的字典里 + +425 +00:18:26,782 --> 00:18:31,617 +We need our friend special characters here for that. +我们需要刚才用过的特殊字符 + +426 +00:18:31,619 --> 00:18:34,253 +So let's go ahead and +让我们继续 + +427 +00:18:34,254 --> 00:18:36,888 +put, well, let's put times here first, I guess. +先加入乘法 + +428 +00:18:36,891 --> 00:18:39,257 +Okay, and we need to create an operation. +再创建一个操作 + +429 +00:18:39,259 --> 00:18:40,392 +How do we create an operation? +怎么创建一个操作呢? + +430 +00:18:40,394 --> 00:18:43,461 +Very similar to how we created this enum. +跟我们创建这个枚举很像 + +431 +00:18:43,463 --> 00:18:47,431 +Op, dot, and times is a binary operation. +op,点,乘法是一个二元操作符 + +432 +00:18:47,433 --> 00:18:49,566 +And you can see that it's typing this for me. +自动为我补全了 + +433 +00:18:49,568 --> 00:18:51,735 +I'm just pressing Tab to get along. +按 Tab 继续 + +434 +00:18:51,737 --> 00:18:56,105 +This is the symbol, which is this thing here. +这是这里的符号 + +435 +00:18:56,107 --> 00:18:58,908 +Now, this is kinda bad code that I ended up +现在,我完成一个糟糕的代码 + +436 +00:18:58,910 --> 00:19:00,809 +typing this twice in the same line. +同一行输入了这段两次 + +437 +00:19:00,811 --> 00:19:03,378 +If I accidentally use the wrong x, +假如不小心输错 x + +438 +00:19:03,380 --> 00:19:06,881 +like some x from somewhere else or the x just from my +比如 x 来自别的地方或者 + +439 +00:19:06,883 --> 00:19:10,451 +keyboard might be different from this x, than this x, ugh, +我键盘的 x 不同于这个 x + +440 +00:19:10,453 --> 00:19:12,920 +we could get in trouble where these things don't match up. +万一它们不匹配,我们就会遇到问题 + +441 +00:19:12,922 --> 00:19:15,489 +So later, in the, right at the very end of the demo, +晚点在演示快结束的时候, + +442 +00:19:15,491 --> 00:19:16,857 +I'm gonna show you how we could do this in +我会向你展示 + +443 +00:19:16,859 --> 00:19:20,960 +a way where we don't have to type this x twice like that. +不需要像这样输入两次 x 的方法 + +444 +00:19:20,962 --> 00:19:22,161 +Okay. + +445 +00:19:22,162 --> 00:19:23,361 +But now we just need the function. +但是现在我们只需要这个方法 + +446 +00:19:23,364 --> 00:19:25,230 +We know how to do that with closures. +我们知道如何用闭包实现 + +447 +00:19:25,232 --> 00:19:27,866 +We say $0 times $1. +用 $0 * $1 + +448 +00:19:27,868 --> 00:19:29,000 +End the closure. +结束闭包 + +449 +00:19:29,002 --> 00:19:31,736 +And yes, I could put this closure outside, +当然,这是最后,于是我也可以把闭包放到外面 + +450 +00:19:31,738 --> 00:19:33,838 +since it's the last thing here. +因为这个闭包在代码结尾处 + +451 +00:19:33,840 --> 00:19:37,107 +That is also legal to do when you're creating +当你创建这样的操作时, + +452 +00:19:37,109 --> 00:19:39,109 +the operations like this. +也是合法的。 + +453 +00:19:39,111 --> 00:19:40,310 +'Kay? + +454 +00:19:40,312 --> 00:19:41,377 +So that's kinda nice. +这看上去很棒吧。 + +455 +00:19:41,379 --> 00:19:44,880 +Let's do our other three binary operations here. +让我们来加入另外三种二元操作 + +456 +00:19:44,882 --> 00:19:46,982 +We'll go divide. +除法 + +457 +00:19:46,984 --> 00:19:49,784 +And this is where it really gets annoying to have to +这就是非得输入两遍 + +458 +00:19:49,786 --> 00:19:51,736 +type it twice. +的烦人的地方 + +459 +00:19:51,737 --> 00:19:53,687 +But I have to show you something else before I can +但是在这之前, + +460 +00:19:53,690 --> 00:19:56,357 +show you how to do that right. +我得给你们演示一下别的。 + +461 +00:19:57,726 --> 00:19:58,591 +Let's go here. +从这里开始 + +462 +00:19:58,593 --> 00:20:02,362 +And there we have minus. +这里我们有减法 + +463 +00:20:02,364 --> 00:20:04,997 +You can see there's two different minuses there, so +你可以看到有两种减法 + +464 +00:20:04,999 --> 00:20:07,866 +hopefully I clicked the same minus in both those spots. +我在这两处都点了同一个减法符号 + +465 +00:20:07,868 --> 00:20:09,434 +And then we change these things. +改一下这里 + +466 +00:20:09,436 --> 00:20:13,671 +We know that divide is 1 divided by $0, and +除法是用 $1 除以 $0 + +467 +00:20:13,673 --> 00:20:15,106 +this is plus. +加法 + +468 +00:20:16,742 --> 00:20:21,678 +And this is 1 minus 0, $1 minus $0, Okay, so +减法 $1 - $0 + +469 +00:20:21,680 --> 00:20:23,813 +everyone cool here? +大家跟得上吧? + +470 +00:20:25,350 --> 00:20:27,483 +These enums are really easy to create. +枚举简单地就能创建 + +471 +00:20:27,485 --> 00:20:31,920 +The API of them is really, really nice, simple. +它们的接口非常简单、漂亮 + +472 +00:20:31,922 --> 00:20:34,055 +And then we have our other operation, +接下来我们来看看其它操作 + +473 +00:20:34,057 --> 00:20:37,058 +which is our unary operation, which is square root. +一个一元操作符——开方 + +474 +00:20:37,060 --> 00:20:40,861 +So let's put that in here, square root is right here. +那那个放这,开方放这 + +475 +00:20:40,863 --> 00:20:43,830 +And we'll put it right here. +把它放这里 + +476 +00:20:45,266 --> 00:20:48,267 +And square root is not a binary operation it's +开方不是一个二元操作符, + +477 +00:20:48,269 --> 00:20:49,601 +a unary operation. +而是一元操作符 + +478 +00:20:49,603 --> 00:20:53,738 +Oops, look at all this. +看这 + +479 +00:20:53,740 --> 00:20:56,591 +'Kay? + +480 +00:20:56,592 --> 00:20:59,443 +And of course, inside here, it's square root of $0. +当然,这里,它是 $0 的平方根 + +481 +00:20:59,445 --> 00:21:01,745 +Okay, you remember that from last time. +跟之前说的一样 + +482 +00:21:01,747 --> 00:21:02,879 +So this is good. +不错 + +483 +00:21:02,881 --> 00:21:04,864 +Now, while I'm here, +这里 + +484 +00:21:04,865 --> 00:21:06,848 +I wanna show you a couple things more about closures. +我再给大家介绍一些闭包相关的东西 + +485 +00:21:06,851 --> 00:21:07,950 +Okay. + +486 +00:21:07,952 --> 00:21:10,052 +This, what is this curly brace? +看这里,这个大括号是什么? + +487 +00:21:10,054 --> 00:21:12,721 +It's a function that takes one argument and +这是一个接受一个参数, + +488 +00:21:12,723 --> 00:21:14,356 +returns one argument. +返回一个参数的函数 + +489 +00:21:14,358 --> 00:21:16,308 +And we know that +我们知道 + +490 +00:21:16,309 --> 00:21:18,259 +it's Doubles because we're creating a unary operation. +我们创建一元操作,所以是 Double + +491 +00:21:18,261 --> 00:21:21,962 +And so, it's inferring the type here, right? +于是,它推出这里的类型,对吧? + +492 +00:21:21,964 --> 00:21:23,530 +Everyone understand that? +大家都能理解吗? + +493 +00:21:23,532 --> 00:21:27,133 +Well, there's another function that returns a function, or +这里有另外一个函数返回一个函数,或者 + +494 +00:21:27,135 --> 00:21:28,901 +there's another function that takes a Double and +一个函数接受一个 Double + +495 +00:21:28,903 --> 00:21:31,570 +returns a Double, that does square root, +返回一个开方后的 Double + +496 +00:21:31,572 --> 00:21:33,772 +it's called square root. +称作 sqrt + +497 +00:21:33,774 --> 00:21:36,941 +So inside here, we could just say square root. +所以这里,我们可以就说 sqrt + +498 +00:21:38,178 --> 00:21:40,811 +Okay, we don't even need this business. +甚至不需要这个 + +499 +00:21:42,881 --> 00:21:44,080 +Just wanna emphasize that +需要强调的是 + +500 +00:21:44,082 --> 00:21:45,515 +we're just passing a function here. +我们在这里传入了一个函数 + +501 +00:21:45,517 --> 00:21:47,450 +And it can be a named function, or +它可以是一个被命名的函数 + +502 +00:21:47,452 --> 00:21:49,518 +we could use these curly braces. +或者可以用花括号 + +503 +00:21:49,520 --> 00:21:52,754 +Now, this is really gonna freak you out, cuz watch this. +现在,让你惊讶的事来了,看好了 + +504 +00:21:52,756 --> 00:21:57,091 +For times, there's a function that does times called times. +对于乘法,有一个做乘法运算的函数就叫做“*” + +505 +00:21:58,728 --> 00:22:00,728 +Okay. + +506 +00:22:00,729 --> 00:22:02,729 +So in Swift, all these operators, times and +在 Swift 里,所有的操作符,乘号等等 + +507 +00:22:02,732 --> 00:22:04,664 +all these things, are just functions. +都是函数 + +508 +00:22:04,666 --> 00:22:06,966 +They just happen to be specified in a way that says +只不过它们刚好以某种方式规定了 + +509 +00:22:06,968 --> 00:22:09,068 +that they can be infix, right, between the two +可以插入到两个参数之间 + +510 +00:22:09,070 --> 00:22:11,370 +arguments instead of taking the arguments in parentheses. +而不需要从圆括号里获取参数 + +511 +00:22:11,372 --> 00:22:13,138 +And we do the same thing here with plus. +然后我们对加法做同样的事 + +512 +00:22:14,641 --> 00:22:16,074 +All right, plus. +好的,加号 + +513 +00:22:16,076 --> 00:22:17,508 +Now, we can't do it with divide and +现在要注意,这种方法不适用于除法和减法 + +514 +00:22:17,510 --> 00:22:20,378 +minus because the order is backwards. +因为运算方向是反的 + +515 +00:22:20,380 --> 00:22:22,146 +Right, we put the things on the stack, +对吧,我们把这些东西放到栈上 + +516 +00:22:22,148 --> 00:22:23,513 +we pull them out backwards, so +然后反方向取出来,所以 + +517 +00:22:23,515 --> 00:22:25,081 +we can't do it with those, but. +这种方法不适用于除法和减法 + +518 +00:22:27,919 --> 00:22:31,086 +I just wanna emphasize, that's what's going on there. +我只是想强调一下,这里是怎么运作的 + +519 +00:22:31,088 --> 00:22:33,455 +Okay, so now we have this nice knownOps. +好,现在我们做好了这些 knwonOps + +520 +00:22:33,457 --> 00:22:34,222 +So we have this thing. +做好了 + +521 +00:22:34,224 --> 00:22:36,724 +It's loaded up. +它已经装载好了 + +522 +00:22:36,725 --> 00:22:39,225 +It gets loaded up whenever the CalculatorBrain gets created. +每当 CalculatorBrain 被创建它就会被装载 + +523 +00:22:39,228 --> 00:22:41,612 +So that's all good. +万事俱备 + +524 +00:22:41,613 --> 00:22:43,997 +Now we can use that down here in performOperation. +现在我们可以将它用在 performOperation 上 + +525 +00:22:43,999 --> 00:22:47,134 +All right, so how are we gonna use this in performOperation? +好,那我们要怎么使用呢 + +526 +00:22:47,136 --> 00:22:50,870 +Well, we basically wanna let the operation equal +我们让 operation 等于 + +527 +00:22:50,872 --> 00:22:53,172 +knownOps sub symbol. +knownOps[symbol] + +528 +00:22:53,174 --> 00:22:55,240 +Okay? Someone passed us a symbol. +明白了吗?使用者传递给我们一个参数 symbol + +529 +00:22:55,242 --> 00:22:56,641 +They're trying to perform this operation. +当他们想用这个方法的时候 + +530 +00:22:56,643 --> 00:22:58,810 +So this is either a plus or a times. +参数可以是加号或者乘号 + +531 +00:22:58,812 --> 00:23:00,111 +Hopefully an operation we know. +是我们已知的操作符 + +532 +00:23:00,113 --> 00:23:02,747 +And we're gonna look it up in knownOps. +然后我们会来到 knownOps + +533 +00:23:02,749 --> 00:23:05,683 +And the way we do that is with the subscript notation with +我们要做的就是根据在方括号里的下标 + +534 +00:23:05,685 --> 00:23:06,650 +the square brackets. +在字典里找到需要的东西 + +535 +00:23:06,652 --> 00:23:07,951 +Okay? That's how you +明白了吗?这就是 + +536 +00:23:07,952 --> 00:23:09,251 +look something up in a dictionary. +在字典里查找东西的方法 + +537 +00:23:09,254 --> 00:23:11,454 +But what might be kind of surprising to you, +不过有一点可能会让你惊讶 + +538 +00:23:11,456 --> 00:23:13,622 +what type do you think this would be, operation? +得到的 operation,你觉得是什么类型的呢? + +539 +00:23:15,292 --> 00:23:17,959 +Any guesses, yeah, some people are saying the right thing. +猜猜?哈,有人说出了正确答案 + +540 +00:23:17,961 --> 00:23:20,128 +You'd think this might be an Op, +你可能会觉得这个是一个 Op + +541 +00:23:20,130 --> 00:23:24,498 +because I'm looking up in knownOps right here, a String. +因为我在 knownOps 这里看,String:Op + +542 +00:23:24,500 --> 00:23:27,134 +And so hopefully I'm getting an Op, but this is not an Op, +因此可以预见得到的会是一个 Op,事实上它并不是 Op + +543 +00:23:27,136 --> 00:23:30,971 +this actually is an Optional Op. +实际上它是一个 Optional Op + +544 +00:23:30,973 --> 00:23:33,173 +Okay, now why is that an Optional Op, because you +好了,为什么它会是一个 Optional Op,因为 + +545 +00:23:33,175 --> 00:23:35,541 +might be looking up something that's not in there. +因为它可能不存在于此 + +546 +00:23:35,543 --> 00:23:38,344 +And it has to return, oh, nil, sorry, couldn't find it, +而且它没有返回值“噢,nil,不好意思找不到该值” + +547 +00:23:38,346 --> 00:23:41,413 +so that's why it has to be an Optional, is returned. +所以这就是为什么它必须是 Optional + +548 +00:23:41,415 --> 00:23:43,015 +So a dictionary, +比方说字典 + +549 +00:23:43,016 --> 00:23:44,616 +whenever you look up something in a dictionary, +每当你要在字典里面寻找东西的时候 + +550 +00:23:44,618 --> 00:23:47,118 +it always returns an Optional, Okay, either nil or +它总是会返回一个 Optional 类型 nil 或者是 + +551 +00:23:47,120 --> 00:23:50,655 +the type of thing you said was supposed to be in there. +其他它原本的类型 + +552 +00:23:50,657 --> 00:23:53,457 +So I'm gonna if let here, I'm gonna say, +所以我在这里加上 if + +553 +00:23:53,459 --> 00:23:56,827 +if I'm able to look up my operation in my knownOps, +如果 我能在 knownOps 里取得我的 operation + +554 +00:23:56,829 --> 00:23:59,696 +then I'm going to push it on to my opStack. +那我就将它放进我的 opStack. + +555 +00:24:02,534 --> 00:24:03,232 +Okay. + +556 +00:24:03,234 --> 00:24:06,068 +Are you cool with that? +明白了吗? + +557 +00:24:06,070 --> 00:24:08,303 +Make sense? +理解? + + +558 +00:24:08,305 --> 00:24:10,171 +Okay. + +559 +00:24:10,173 --> 00:24:12,407 +Now, what's next? +好,下一步是什么呢 + +560 +00:24:12,409 --> 00:24:13,908 +Well. + +561 +00:24:13,910 --> 00:24:14,541 +Now we have. +现在我们有… + +562 +00:24:14,543 --> 00:24:15,509 +Oh, well. +噢,等等 + +563 +00:24:15,510 --> 00:24:16,476 +I'm gonna take a pause here to +在这我先暂停一下 + +564 +00:24:16,478 --> 00:24:18,845 +talk a little bit about access control. +谈一下 access control(访问控制) + +565 +00:24:18,847 --> 00:24:20,697 +Okay? + +566 +00:24:20,698 --> 00:24:22,548 +Access control is about public and private. +access control 是关于公有和私有 + +567 +00:24:22,550 --> 00:24:25,017 +Okay? What methods in this class +在这个类里面什么方法是共有的 + +568 +00:24:25,019 --> 00:24:27,353 +are public, in other words, other people can use them, +换言之,其他人能够使用它 + +569 +00:24:27,355 --> 00:24:30,022 +other classes in my code allowed to call them? +其他类能调用它 + +570 +00:24:30,024 --> 00:24:31,189 +And what things are private? +而什么方法是私有的呢 + +571 +00:24:31,191 --> 00:24:32,757 +My internal data structures that I +里面的一些内部数据 + +572 +00:24:32,759 --> 00:24:34,458 +don't want people messing with? +并不想给别人乱搞 + +573 +00:24:34,460 --> 00:24:38,428 +Okay, so the way public private works in +Swift 处理公有和私有的方法 + +574 +00:24:38,430 --> 00:24:41,064 +Swift is kind of interesting. +很有趣 + +575 +00:24:41,066 --> 00:24:42,999 +You basically specify the things you want to +基本上,你只在想要私有化的东西前 + +576 +00:24:43,001 --> 00:24:45,935 +be private by putting the word private on them. +加上 private + +577 +00:24:45,937 --> 00:24:47,569 +If you don't put any word on them, +如果你什么都不加 + +578 +00:24:47,571 --> 00:24:50,639 +then they're public inside your program. +那他们就是在你的程序里公有的 + +579 +00:24:50,641 --> 00:24:52,040 +'Kay? + +580 +00:24:52,042 --> 00:24:55,109 +And you only use the word public if you're shipping out, +当你想要打包 + +581 +00:24:55,111 --> 00:24:58,979 +like, a framework of objects to other people, and +比如说一个框架给别人, + +582 +00:24:58,981 --> 00:25:02,215 +you want stuff in there to be public outside the framework. +并且你希望里面框架里的东西对框架外是公开的,你才会使用 public + +583 +00:25:03,251 --> 00:25:04,684 +So I'm making some framework, +比如我做一些框架 + +584 +00:25:04,686 --> 00:25:07,153 +a bunch of objects that I'm trying to sell to people or +一些对象想要卖给别人用 + +585 +00:25:07,155 --> 00:25:09,555 +I get people to use to do something, and +别人可以用这些东西做点什么 + +586 +00:25:09,557 --> 00:25:12,624 +of course I'm gonna have things where my objects inside +我当然希望在框架内部的一些类 + +587 +00:25:12,626 --> 00:25:14,192 +my framework can talk to each other. +可以互相交流 + +588 +00:25:14,194 --> 00:25:16,361 +There's no keyword needed for that. +那就不需要什么关键字 + +589 +00:25:16,363 --> 00:25:18,229 +Then I'll have things inside certain objects +然后我可以对某些类里面的东西加上 private + +590 +00:25:18,231 --> 00:25:20,464 +that are private only to that object, I'll say private. +让它们私有化 + +591 +00:25:20,466 --> 00:25:24,267 +And then some of them might be public that the customer who's +而另外的东西就是公有的,那些 + +592 +00:25:24,269 --> 00:25:27,404 +buying my objects, my framework, can use. +买了我们的类、框架的顾客就可以使用它们 + +593 +00:25:27,406 --> 00:25:29,238 +Now, in this class we're not gonna be doing frameworks, +在这节课我们不会做框架 + +594 +00:25:29,240 --> 00:25:30,840 +we don't really have time to get to that, so +我们没有那个时间 + +595 +00:25:30,842 --> 00:25:32,508 +we're not gonna be using the keyword public, +所以我们不需要用到关键字 public + +596 +00:25:32,510 --> 00:25:34,076 +we won't ever use that, +我们之后都不会用它 + +597 +00:25:34,078 --> 00:25:35,510 +because we don't have any frameworks. +因为我们没有什么框架 + +598 +00:25:35,512 --> 00:25:37,578 +But we are gonna use private. +但我们会用 private + +599 +00:25:37,580 --> 00:25:39,180 +And, starting with assignment two, +然后,从第二次作业开始 + +600 +00:25:40,216 --> 00:25:42,516 +it's one of your evaluation criteria is gonna be, +它将是你们的评分标准之一 + +601 +00:25:42,518 --> 00:25:45,985 +make private things private. OK? +让应该是 private(私有化) 的东西 private + +603 +00:25:45,987 --> 00:25:47,453 +So that is important to do. +所以这点很重要 + +604 +00:25:47,455 --> 00:25:48,354 +And you could just say, +也许你会这么说, + +605 +00:25:48,356 --> 00:25:49,988 +well, I like everything to be public. +呃,我喜欢让所有对象和方法都是 public 的 + +606 +00:25:49,990 --> 00:25:51,156 +Well, that's bad. +可惜,这样做会很糟糕 + +607 +00:25:51,158 --> 00:25:53,391 +Okay? If you make your internal structure public, +假如你让内部的 structure(结构体)public 化, + +608 +00:25:53,392 --> 00:25:55,625 +and some other object in your program +然后其他在你程序中的对象可能会修改它的内容, + +609 +00:25:55,628 --> 00:25:58,796 +starts muck in with it and breaks your object, and +这将会导致你的对象错乱, + +610 +00:25:58,798 --> 00:26:00,931 +then you come to a new version of your program, and +随后,你又可能新建了一个程序版本号, + +611 +00:26:00,933 --> 00:26:03,467 +you change something, and now everybody's breaking. +改变了一些代码,好了,所有对象都错乱了 + +612 +00:26:03,469 --> 00:26:05,335 +That's bad, Okay, that's chaos. +所以这么做是不好的,这会导致混乱明白了吗? + +613 +00:26:05,337 --> 00:26:08,671 +So the only things that want to be not private are things +只有当你想用来给别的类或对象提供支持的时候, + +614 +00:26:08,673 --> 00:26:11,507 +that you're committing to sign up to support. +你才会想让它不是 private 的 + +615 +00:26:11,509 --> 00:26:14,677 +So in this class, the only public things so +因此在这个 class 里面,目前为止唯一是 public + +616 +00:26:14,679 --> 00:26:17,279 +far are the initializer. +的,只有 initializer + +617 +00:26:17,281 --> 00:26:18,513 +Obviously, we want to allow people to +很显然,我们希望让别人 + +618 +00:26:18,515 --> 00:26:19,847 +create a CalculatorBrain. +创建一个 CalcualtorBrain 的对象 + +619 +00:26:19,849 --> 00:26:21,349 +That's clearly public. +很明显,这应当是 public 的 + +620 +00:26:21,351 --> 00:26:25,385 +Also pushing and performing operands and operations. +同样的,将操作数和操作符压栈然后计算的这些操作 + +621 +00:26:25,387 --> 00:26:28,238 +That's public. Okay? +也都应当是 public 的 + +623 +00:26:28,239 --> 00:26:29,889 +Everything else, for now, I'm gonna make private. +而目前为止我们不需要对外提供的东西,我们都让它们成为 private 的 + +624 +00:26:29,891 --> 00:26:31,657 +So I'm gonna make this private. +现在,我将让 Op 变成 private 的 + +625 +00:26:31,659 --> 00:26:33,592 +Notice that if I make this private, +注意,当我把这个变成了 private 以后, + +626 +00:26:33,594 --> 00:26:35,427 +it's gonna start saying, whoa, +这边将提示, + +627 +00:26:35,429 --> 00:26:38,730 +wait a second, this can't be public, you know, it can't be +这(opStack)不能是 public 的,不能 + +628 +00:26:38,732 --> 00:26:42,100 +non-private because this is private and it uses it. +因为 Op 是 private 的,然后 opStack 使用了 Op,所以 opStack 也只能是 private 的 + +629 +00:26:42,102 --> 00:26:44,368 +That's what this warning's gonna say right here, see. +如果不这么做,这个位置将会出现一个警告,看 + +630 +00:26:44,370 --> 00:26:45,720 +Property must be +Property 必须 + +631 +00:26:45,721 --> 00:26:47,071 +declared private because its type is private. +声明为 private,因为它的类型是 private 的 + +632 +00:26:47,073 --> 00:26:48,205 +Okay, that's the type of this. +好的,这个就是它的类型 + + +633 +00:26:48,207 --> 00:26:49,906 +But I want this to be private anyway, +在这个情况下,我都希望它是 private 的, + +634 +00:26:49,908 --> 00:26:52,742 +this is my internal data structure, opStack. +opStack 就是我程序内部的数据结构了 + +635 +00:26:52,744 --> 00:26:56,278 +Now, knownOps is kind of an interesting one. +现在我们来看看 knownOps,它是个很有意思的对象 + +636 +00:26:56,280 --> 00:26:58,614 +Maybe I would want that to be public one day, +也许我在某种情况下想让它变成 public , + +637 +00:26:58,616 --> 00:27:01,650 +because maybe I want people to use my CalculatorBrain and +比如我希望人们使用我的 CalculatorBrain 的同时 + +638 +00:27:01,652 --> 00:27:03,685 +teach it new ops. +并为它增加新的运算功能 + +639 +00:27:03,687 --> 00:27:05,386 +That wouldn't be that unreasonable. +这种情况是真实存在的 + +640 +00:27:05,388 --> 00:27:08,356 +However, I'm not ready to support that functionality in +但是呢,我现在还没准备好让我的 CalculatorBrain 来 + +641 +00:27:08,358 --> 00:27:09,456 +my CalculatorBrain. +支持这些功能 + +642 +00:27:09,458 --> 00:27:12,059 +I'm just not sure I wanna do it this way. +或许我只是还不确定我想这么做 + +643 +00:27:12,061 --> 00:27:13,827 +Maybe I don't want this property to be public, +所以在某种情况下,我可能又不想让这个 property 变成 public 的, + +644 +00:27:13,829 --> 00:27:17,263 +I might want to just have some functions to learn an op or +我希望只是有些函数去增加一个运算操作或者 + +645 +00:27:17,265 --> 00:27:18,982 +something like that, so +类似的东西,所以 + +646 +00:27:18,983 --> 00:27:20,700 +I'm just not sure, so I'm gonna start out private. +我不确定我会怎么做,所以我默认设置它为 private 的 + +647 +00:27:20,702 --> 00:27:23,268 +And that's really, when you're designing APIs, +上面这些这就是当你在设计 APIs 的时候需要考虑的问题, + +648 +00:27:23,270 --> 00:27:24,536 +you wanna kinda start out, +你总得找个地方入手, + +649 +00:27:24,538 --> 00:27:27,405 +make it private first, and then open it up as you're +所以比较好的做法是,先让它是 private 的,然后等到你想要支持一些功能 + +650 +00:27:27,407 --> 00:27:30,308 +willing to support that functionality. +的时候,再让其变成 public 的 + +651 +00:27:30,310 --> 00:27:31,709 +-Question? -Is the common view in +- 有什么问题吗?- [学生提问] + + +652 +00:27:31,711 --> 00:27:34,278 +Swift to make most instance variables private and +- [学生提问] + +653 +00:27:34,280 --> 00:27:36,980 +use getters and setters, or is it to make them, if, +- [学生提问] + +654 +00:27:36,982 --> 00:27:38,882 +if they are supposed to be public, or +- [学生提问] + +655 +00:27:38,884 --> 00:27:40,683 +make them public and then let the? +- [学生提问] + +656 +00:27:40,685 --> 00:27:43,052 +All right. So the question is, is it, +好的那么这个学生的问题是, + +657 +00:27:43,054 --> 00:27:45,854 +is it kind of part of the Swift way to make +“是不是有 Swift 的标准做法让 + +658 +00:27:45,856 --> 00:27:47,889 +most instant variables private and +一个 private 的实例变量可以 + +659 +00:27:47,891 --> 00:27:50,75 +then have getters and setters that are public to get them. +用 public 的 getters 和 setters 方法去访问它们” + +660 +00:27:50,761 --> 00:27:52,226 +That doesn't really even make sense in Swift. +这在 Swift 中根本没有意义 + +661 +00:27:52,228 --> 00:27:53,961 +That's more of an Objective-C thing. +这更像是 Objective-C 的做法 + +662 +00:27:53,963 --> 00:27:56,263 +In Objective-C, you had instance variables, and +在 Objective-C 中,你有一个实例变量,然后 + +663 +00:27:56,265 --> 00:27:59,032 +then you had properties that would get and set them. +你有 properties ,会用 getter 和 setter 方法去获取和设置它们 + +664 +00:27:59,034 --> 00:28:00,967 +And Swift has kind of merged those a little bit +Swift 把这些东西进一步 + +665 +00:28:00,969 --> 00:28:05,638 +closer together so that properties are really kind of +融合在一起了,所以 properties 事实上是一种 + +666 +00:28:05,640 --> 00:28:08,907 +the public or private getters and setters. +public 或者 private 的 getters 和 setters 方法 + +667 +00:28:08,909 --> 00:28:11,043 +So, if you have a property, you just have to +因此,如果你有一个 property,你只需要 + +668 +00:28:11,045 --> 00:28:13,178 +decide whether you want people to access it or +决定你是否想要别人能够访问它, + +00:28:13,180 --> 00:28:15,246 +not, and if not, make it private. +如果不是,将它变成 private 的 + +670 +00:28:15,248 --> 00:28:16,681 +And if so, make it public. +如果是,将它变成 public 的 + +671 +00:28:16,683 --> 00:28:19,350 +And that, you know, don't make it non-private, basically. +一般来说不要让它是 public 的 + +672 +00:28:19,352 --> 00:28:21,685 +And that's, just that's all you need to think about. +所以,你需要考虑的是这些 + +673 +00:28:21,687 --> 00:28:24,854 +I wouldn't even think in Swift in terms of instance variable +我甚至不会在 Swift 中考虑实例变量 + +674 +00:28:24,856 --> 00:28:26,289 +versus the property. +和 property 的区别 + +675 +00:28:26,291 --> 00:28:28,557 +Now, it is still possible in Swift to do that, +但是目前,用 Swift 还是有可能做到的你说的这些的, + +676 +00:28:28,559 --> 00:28:30,526 +because you have computed properties. +因为有 computed properties(计算属性) + +677 +00:28:30,528 --> 00:28:32,328 +And those could be setters and +这些都可以成为设置 private properties + +678 +00:28:32,329 --> 00:28:34,129 +getters that are setting private properties. +的 setters 和 getters 方法 + +679 +00:28:34,131 --> 00:28:36,464 +But we're gonna see on Wednesday, even, +我们将会在周三的课程中了解到更多相关的东西, + +680 +00:28:36,466 --> 00:28:39,634 +I'm gonna talk to you a little bit about a way that when your +我甚至会和你们讨论一点点关于 + +681 +00:28:39,636 --> 00:28:41,902 +properties get set, you can intervene, +properties 的 get 和 set 方面的东西,你可以介入到它们其中, + +682 +00:28:41,904 --> 00:28:44,571 +you can check them to make sure the value is Okay. +检查一下,来保证它们的值是正确的 + +683 +00:28:44,573 --> 00:28:46,373 +So if you have a public property, +所以说,如果你有一个 public 的 property, + +684 +00:28:46,375 --> 00:28:49,142 +you can still protect it by intervening a little bit +当人们尝试获取或者设置它的值的时候, + +685 +00:28:49,144 --> 00:28:51,110 +when people set it or try and get it. +你仍然可以介入这个 property 来保护它 + +686 +00:28:51,112 --> 00:28:52,912 +So it is possible to still have some protection there, +这里面仍可以设置一些保护机制, + +687 +00:28:52,914 --> 00:28:53,545 +we'll see that. +在周三的课程中,我们都会有所了解 + +688 +00:28:56,016 --> 00:28:57,749 +All right, so these are our only public things. +好,回到主题,这些就是我们仅有的 public 的东西 + +689 +00:28:57,751 --> 00:29:00,651 +Now, there's only one other public thing we need to do in +那么现在,在我们的 CalculatorBrain 里, + +690 +00:29:00,653 --> 00:29:02,420 +our CalculatorBrain, which is, +还剩一个 public 的东西要做的是, + +691 +00:29:02,422 --> 00:29:04,688 +we need to let people evaluate this stack. +我们需要允许用户对这个 stack 求值 + +692 +00:29:06,058 --> 00:29:09,492 +So people are pushing operands and performing operations, +用户把操作符压栈然后进行计算, + +693 +00:29:09,494 --> 00:29:11,828 +now they wanna know what's the result. +随后,他们想知道结果是什么 + +694 +00:29:11,830 --> 00:29:14,129 +Okay? They pushed an operand of a five. +举例,我们往栈里压了一个数字5 + +696 +00:29:14,132 --> 00:29:15,898 +They pushed an operand of a four. +然后我们再压一个数字4 + +697 +00:29:15,900 --> 00:29:18,166 +They performed operation plus, +做加法操作, + +698 +00:29:18,168 --> 00:29:19,668 +they want to see four plus five. +我们想看到的是 4 + 5 + +699 +00:29:19,670 --> 00:29:21,202 +Where's that nine, Okay? +得到的答案应该是 9,对吧? + +700 +00:29:21,204 --> 00:29:22,403 +They need the result. +他们需要看到结果 + +701 +00:29:22,405 --> 00:29:25,606 +So we need another public method here, +所以,这里我们还需要一个公共方法, + +702 +00:29:25,608 --> 00:29:29,876 +which I'm gonna call evaluate. +将其命名为 evaluate + +703 +00:29:29,878 --> 00:29:31,344 +'Kay? And evaluate, + +704 +00:29:31,346 --> 00:29:34,880 +we could have it return a Double, for example. +像这样,我们可以设置其返回类型为 Double + +705 +00:29:34,882 --> 00:29:38,917 +And it would just evaluate this opStack and +这个方法会对 opStack 求值并 + +706 +00:29:38,919 --> 00:29:40,535 +return the value. +返回结果 + +707 +00:29:40,536 --> 00:29:42,152 +But I really can't make this a Double. +但现在我并不能设置这个返回类型为 Double + +708 +00:29:43,390 --> 00:29:46,524 +Really, this has to be an Optional. +事实上,它必须为 Optional (Double?) + +709 +00:29:46,526 --> 00:29:48,892 +'Kay, why does this have to be an Optional? +为什么它必须为 Optional? + +710 +00:29:48,894 --> 00:29:52,295 +Well, that's because someone might get my CalculatorBrain, +这是由于,当某人使用 CalculatorBrain 时, + +711 +00:29:52,297 --> 00:29:53,963 +and the first thing they do is, +他们做的第一件事 + +712 +00:29:53,965 --> 00:29:55,932 +they say, perform operation plus. +是——执行加法 + +713 +00:29:55,934 --> 00:29:57,600 +Okay, well I have no operands. +但我们此时并没有可以被加的数 + +714 +00:29:57,602 --> 00:29:59,051 +Okay? And + +715 +00:29:59,052 --> 00:30:00,501 +you're asking to evaluate plus. +可这个时候又被要求执行加法计算 + +716 +00:30:00,504 --> 00:30:02,287 +I can't do that. +这个操作是无法完成的 + +717 +00:30:02,288 --> 00:30:04,071 +So, I have to return something to you, that lets you know, +所以我必须返回一些东西,让用户知道 + +718 +00:30:04,074 --> 00:30:07,776 +I could not evaluate what you ask me to evaluate. +我无法计算你让我计算的东西 + +719 +00:30:07,778 --> 00:30:09,477 +So, I'm gonna return nil in that case, +这种情况下,我就会返回 nil, + +720 +00:30:09,479 --> 00:30:12,213 +so valuate here really needs to be an Optional. +所以这里需要返回一个 Optional + +721 +00:30:13,249 --> 00:30:14,848 +'Kay, so you can see some of the thinking, +你可以看到我们对于什么时候 + +722 +00:30:14,850 --> 00:30:17,283 +when do you make something an Optional when not. +应该使用 Optional 的思考 + +723 +00:30:17,285 --> 00:30:19,285 +'Kay, so this is a classic case of that, +这里就是 Optional 一个典型的使用场景, + +724 +00:30:19,287 --> 00:30:21,787 +where you got sometimes you wanna return it and +有时你想要返回一些东西, + +725 +00:30:21,789 --> 00:30:23,889 +you can't do it, so you have to return nil. +但又无法返回的时候,那么就返回 nil. + +726 +00:30:23,891 --> 00:30:28,793 +All right, so how we going to implement evaluate? +那么,接下来我们应该怎么实现 evaluate 呢? + +727 +00:30:28,795 --> 00:30:30,595 +Okay, how many people in the class, +对了,在这个班上有多少人 + +728 +00:30:30,597 --> 00:30:34,365 +raise your hands don't be shy, are you comfortable with +不要害羞,举起你们的手, + +729 +00:30:34,367 --> 00:30:37,067 +the computer science concept of recursion? +有多少人熟悉计算机科学中递归的概念? + +730 +00:30:39,271 --> 00:30:40,903 +Okay. Excellent, that's about 80 or +很好,大概有80~90%, + +731 +00:30:40,905 --> 00:30:43,939 +90%, so I'm gonna explain this really fast then. +那么我将只是快速地解释一下 + +732 +00:30:43,941 --> 00:30:45,974 +And if you don't understand recursion, +如果你不明白递归 + +733 +00:30:45,976 --> 00:30:47,309 +if you didn't raise your hand, +如果你刚才没有举手的话 + +734 +00:30:47,311 --> 00:30:48,843 +that's something you should go review. +那就意味着你需要回去复习 + +735 +00:30:48,845 --> 00:30:50,378 +Okay? [LAUGH] Recursion is +递归是 + +736 +00:30:50,379 --> 00:30:51,912 +something, you should know by the time you take this class, +当你在学习这门课程的时候,应该了解的东西 + +737 +00:30:51,915 --> 00:30:53,714 +so that's something you definitely wanna know. +而且是必须了解的东西 + +738 +00:30:53,716 --> 00:30:57,317 +So, how are we going to use recursion to +那么在这种情况下, + +739 +00:30:57,319 --> 00:30:59,252 +evaluate this stack? +我们应该怎样在 evaluate 中使用递归? + +740 +00:30:59,254 --> 00:31:00,653 +All right, looks like this. +看这里 + +741 +00:31:00,655 --> 00:31:02,988 +I'm gonna do a sample stack, right here. +我将会在这里写一个栈 + +742 +00:31:02,990 --> 00:31:08,393 +So, let's say I put a 6 on the stack, and then I put a 5, and +这样说吧,我放了一个 6 在这个栈上,然后我再放了一个5, + +743 +00:31:08,395 --> 00:31:14,065 +then I put a plus, and then I put a 4, and then I put times. +随后我再放了加号,再放4,最后放上乘号 + +744 +00:31:14,067 --> 00:31:15,166 +Okay? + +745 +00:31:15,168 --> 00:31:17,968 +So here's our stack, and I'm gonna evaluate this, +这就是我们的栈,我将要使用递归 + +746 +00:31:17,970 --> 00:31:18,702 +I'm gonna recursion. +计算这个栈 + +747 +00:31:18,704 --> 00:31:19,769 +How am I gonna do that? +我要怎么做? + +748 +00:31:19,771 --> 00:31:21,437 +Well, really, what I'm gonna do is I'm gonna +我要这样 + +749 +00:31:21,439 --> 00:31:24,740 +have a helper method here, a recursive helper method. +在这里我需要一个 helper 方法,一个帮助实现递归的方法 + +750 +00:31:24,742 --> 00:31:27,543 +I'm gonna call it evaluate also, actually. +事实上这个方法我也叫 evaluate + +751 +00:31:27,545 --> 00:31:29,644 +And it's gonna take a stack, as an argument, +它会将我们的栈当做一个参数, + +752 +00:31:29,646 --> 00:31:31,012 +a stack of things to evaluate. +一堆用来计算的东西 + +753 +00:31:31,014 --> 00:31:34,449 +And it's only gonna evaluate the top thing on the stack. +它计算处于这个栈顶的元素 + +754 +00:31:34,451 --> 00:31:36,717 +That's it just gonna value the top of the stack and +而且它只计算处于栈顶的元素,并且返回, + +755 +00:31:36,719 --> 00:31:38,819 +return it, but the top thing of the stack might +但是计算栈顶的这个元素时, + +756 +00:31:38,821 --> 00:31:41,421 +involve looking at every single of one of these, right? +可能也会涉及到栈中的每一个元素 + +757 +00:31:41,423 --> 00:31:44,157 +Cuz, this times needed to two operations. +因为,乘法需要两个数才能进行 + +758 +00:31:44,159 --> 00:31:47,026 +So, lets look at this, this recursive evaluates gonna come +所以,这个递归计算将 + +759 +00:31:47,028 --> 00:31:48,961 +in here, it's gonna try and +将尝试着计算处于栈顶的元素 + +760 +00:31:48,962 --> 00:31:50,895 +evaluate the top of the stack, which is a times. +也就是乘法 + +761 +00:31:50,898 --> 00:31:51,597 +Okay? So it's like, +这将是 + +762 +00:31:51,599 --> 00:31:53,265 +Okay, I'm doing times. +我在算乘法 + +763 +00:31:53,267 --> 00:31:56,101 +Now for times it needs two operate, +我需要要找到乘数和被乘数 + +764 +00:31:56,103 --> 00:31:58,302 +two operands here for times. +来做乘法, + +765 +00:31:58,304 --> 00:31:59,737 +So, it recursively calls, +evaluate 开始递归 + +766 +00:31:59,739 --> 00:32:03,807 +itself to say give me to first operand for time. +它说,给我第一个操作数来做乘法 + +767 +00:32:03,809 --> 00:32:07,010 +And so recursively, comes in here, it finds a 4 on +然后从这里递归地,在子栈的栈顶找到了一个 4, + +768 +00:32:07,012 --> 00:32:10,913 +the top it's like, I know how to evaluate 4, it's 4. +它找到了一个操作数 + +769 +00:32:10,915 --> 00:32:12,148 +So, it just returns. +所以直接返回 + +770 +00:32:12,150 --> 00:32:15,751 +Okay, so now I have my first operands. +好,现在我就有了第一个操作数 + +771 +00:32:15,753 --> 00:32:16,618 +'Kay? Now, +现在 + +772 +00:32:16,620 --> 00:32:18,386 +I take the rest of the stack and +我在剩下的栈上进行递归, + +773 +00:32:18,388 --> 00:32:21,255 +evaluate it, to get the second one. +以得到第二个操作数 + +774 +00:32:21,257 --> 00:32:24,291 +And when I do that, I get plus, 'kay? +当在剩下的栈上递归时,我得到一个加号 + +775 +00:32:24,293 --> 00:32:26,393 +So, plus says, oh, I have to evaluate plus. +然后加号说:"噢,我要计算加法" + +776 +00:32:26,395 --> 00:32:27,727 +It needs operands. +"那需要操作数才行" + +777 +00:32:27,729 --> 00:32:30,763 +So, I come over here, I'm getting a plus. +然后我在这里写上,我有了一个加号 + +778 +00:32:30,765 --> 00:32:34,700 +And I gotta go recursive again, to go get its operands. +我要再次递归,用于获取做加法的操作数 + +779 +00:32:34,702 --> 00:32:36,401 +I get the 5, that's good. +我得到 5,不错 + +780 +00:32:36,403 --> 00:32:41,072 +I'm gonna go recursive again, get the 6, over here. +我还要再次递归,得到一个 6,填写到这里 + +781 +00:32:41,074 --> 00:32:42,907 +And I've evaluated the whole stack. +这样,我计算完整个栈 + +782 +00:32:42,909 --> 00:32:45,876 +So, you see how I have to keep going backward recursively to +就这样,你看到我这样通过来回 + +783 +00:32:45,878 --> 00:32:46,576 +my evaluate +递归 + +784 +00:32:46,578 --> 00:32:47,911 +[COUGH] + +785 +00:32:47,912 --> 00:32:49,245 +To get the operands for my operations. +获取操作符所需要的操作数 + +786 +00:32:49,247 --> 00:32:51,848 +Once, I get to an operand I can stop, +一旦我取得的是操作数,本次递归就可以停止, + +787 +00:32:51,850 --> 00:32:54,483 +Okay number, I got it and I'm out of of there. +因为我得到我需要的数字,我可以停止递归 + +788 +00:32:54,485 --> 00:32:56,418 +But every time I encounter another operation, +但每一次我遇到另一个操作符时, + +789 +00:32:56,420 --> 00:32:58,153 +I have to keep going recursively to +我就必须继续递归来 + +790 +00:32:58,155 --> 00:33:00,822 +get all my arguments, any questions about that? +获取所需要的操作数,有人对这个过程有疑问吗? + +791 +00:33:00,824 --> 00:33:06,327 +'Kay, so it's actually gonna be pretty simple recursion. +这是一个非常简单的递归算法 + +792 +00:33:06,329 --> 00:33:08,862 +When you see the code, you're gonna be, that makes sense. +但你看到了代码,你就会觉得:"哦,还真是这样" + +793 +00:33:08,864 --> 00:33:12,832 +So, I'm gonna have this separate I'm gonna put this up +我将把这个分开,放在最上面 + +794 +00:33:12,834 --> 00:33:15,201 +on top for scrolling reasons. +为了更好地滚动 + +795 +00:33:15,203 --> 00:33:18,237 +Oops. Didn't mean that. +Opps,我不是故意的 + +796 +00:33:18,239 --> 00:33:19,672 +The separate evaluate. +这是分离的另一个 evaluate + +797 +00:33:20,808 --> 00:33:25,677 +And this evaluate is going to take a stack of ops, +这个 evaluate 将会取得栈上的操作数, + +798 +00:33:25,679 --> 00:33:27,078 +as its argument. +作为参数 + +799 +00:33:27,080 --> 00:33:28,645 +And why does it take a stack of ops? +为什么它会获取栈上的操作数呢? + +800 +00:33:28,647 --> 00:33:31,048 +Because as it's recursing, +因为当它递归时, + +801 +00:33:31,050 --> 00:33:32,882 +it's using the rest of the +ops. +它使用剩下的操作数 + +802 +00:33:32,884 --> 00:33:34,050 +So, you see what I mean? +所以,你们明白我的意思了吗? + +803 +00:33:34,052 --> 00:33:35,618 +It's not, +它不能 + +804 +00:33:35,619 --> 00:33:37,185 +it can't be looking at the big opStack in our brain. +访问我们的程序里巨大的 opStack + +805 +00:33:37,188 --> 00:33:38,320 +It can't look at this. +它无法这么做 + +806 +00:33:38,322 --> 00:33:40,756 +'Kay, cuz it's kind of consuming it. +因为这有点太消耗时间了 + +807 +00:33:40,758 --> 00:33:42,991 +Right? And every time I call it +我每次递归调用 + +808 +00:33:42,992 --> 00:33:45,225 +recursively, I'm gonna get fewer operands to work with. +都只需要处理很少的操作数 + +809 +00:33:45,228 --> 00:33:46,194 +So this is what I'm doing. +所以这就是我做的事情 + +810 +00:33:46,196 --> 00:33:47,962 +Now, the first time I call it, +在这里,我第一次调用, + +811 +00:33:47,964 --> 00:33:50,864 +right here, I'm gonna give it the full opStack. +这时需要给出完整的 opStack + +812 +00:33:50,866 --> 00:33:53,767 +So, I'll call my recursive one from here. +我从这里开始调用递归函数 + +813 +00:33:53,769 --> 00:33:56,036 +Now, what's this thing gonna return? +那么,这里将要返回什么? + +814 +00:33:56,038 --> 00:33:56,836 +'Kay. + +815 +00:33:56,838 --> 00:33:57,770 +That's interesting and +这将会很有趣 + +816 +00:33:57,772 --> 00:34:00,873 +here's a big new thing for you to see. +而且这里有其他的新鲜东西等待你们发现 + + +817 +00:34:00,875 --> 00:34:03,709 +You've read about it I, I can't remember I +你们看过了吧,我不记得 + +818 +00:34:03,711 --> 00:34:05,910 +even asked you to read about this but I think I. +有没有叫你们去看相关内容,不过 + +819 +00:34:05,912 --> 00:34:06,811 +No, I guess I didn't. +我猜我没有 + +820 +00:34:06,813 --> 00:34:08,846 +Which is Tuples, 'kay? +什么是 Tuple(元组)? + +821 +00:34:08,848 --> 00:34:14,484 +So in Swift, you can combine multiple things together +在 Swift 里,你可以把多个东西组合起来 + +822 +00:34:14,486 --> 00:34:16,853 +into one kind of really te, +成为一个相当 + +823 +00:34:16,855 --> 00:34:19,922 +mini data structure called a Tuple, 'kay? +迷你的数据结构叫做 Tuple + +824 +00:34:19,924 --> 00:34:22,124 +Don't let the tu [LAUGH] sound in there fool you. +不要被 tu 的发音愚弄了 + +825 +00:34:22,126 --> 00:34:24,560 +It's not just two, it's any number, Okay? +这不代表 two,它可以是任意数目 + +826 +00:34:24,562 --> 00:34:26,762 +And you just put them in a parentheses, Okay? +你只需要把它们放进一对圆括号里 + +827 +00:34:26,764 --> 00:34:28,664 +And, and that's it. +这就好了 + +828 +00:34:28,665 --> 00:34:30,565 +So you can use this for return values. +你可以用它来做返回值 + +829 +00:34:30,567 --> 00:34:32,033 +So I've gotta function right here, +我在这里使用了这一功能, + +830 +00:34:32,035 --> 00:34:34,735 +and I actually need to return two things from this evaluate. +实际上我需要在求值后返回两个东西 + +831 +00:34:35,771 --> 00:34:37,754 +'Kay? One thing I +一个是 + +832 +00:34:37,755 --> 00:34:39,738 +need to return is the result of a evaluating it. +求值运算的结果 + +833 +00:34:40,975 --> 00:34:43,042 +But the other thing I +另一个是 + +834 +00:34:43,043 --> 00:34:45,110 +need to return is the rest of the stack that I didn't use. +剩余的未使用的栈 + +835 +00:34:45,112 --> 00:34:48,647 +Cuz as I'm working my way down here and I take off that +因此就像我在这里演示的, + +836 +00:34:48,649 --> 00:34:52,884 +times, and the 4 and the 5, Okay, I'm consuming things but +我取走了乘号,然后是4跟5我拿走了栈里的一些东西, + +837 +00:34:52,886 --> 00:34:54,652 +then I'm leaving the rest of the stacks, so +同时栈有剩余部分, + +838 +00:34:54,654 --> 00:34:56,920 +I have to keep returning what's left of the stacks, +所以我需要在求值过程中 + +839 +00:34:56,922 --> 00:34:58,722 +while we keep consuming it. +返回栈的剩余部分 + +840 +00:34:58,724 --> 00:34:59,689 +Okay? + +841 +00:34:59,691 --> 00:35:01,958 +So, I'm gonna return this in a Tuple. +所以,我要在 Tuple 里返回这个 + +842 +00:35:01,960 --> 00:35:04,126 +Tuples could not be simpler syntax, +Tuple 的语法不能再简单了, + +843 +00:35:04,128 --> 00:35:08,097 +just open parentheses, not nine, open parentheses. +只要左括号,不是9,左括号 + +844 +00:35:08,099 --> 00:35:11,066 +Open parentheses, and just all the types that you, +然后是所有你要的类型数据 + +845 +00:35:11,068 --> 00:35:12,634 +of things that you want in here. +统统放在这里 + +846 +00:35:12,636 --> 00:35:14,569 +So, I'm gonna return a Double question mark, +所以我要在这里返回 Double? + +847 +00:35:14,571 --> 00:35:16,070 +that's my results. +这是我的结果 + +848 +00:35:16,072 --> 00:35:17,683 +'Kay? + +849 +00:35:17,684 --> 00:35:19,295 +That's what's eventually, gonna be +这是最终 + +850 +00:35:19,296 --> 00:35:20,907 +returned out here after all the recursion unwinds. +所有递归都被展开后返回的结果 + +851 +00:35:20,910 --> 00:35:23,643 +And then also I'm going to +同时我也需要 + +852 +00:35:23,645 --> 00:35:28,348 +have the ops that are left over. +剩下的 op + +853 +00:35:28,350 --> 00:35:32,851 +Now, a Tuple could look just like this, unnamed. +现在,一个未命名的 Tuple 看上去像这样 + +854 +00:35:32,853 --> 00:35:34,519 +Did you see how these things are not named, +你们看到这些未命名的格式, + +855 +00:35:34,521 --> 00:35:35,920 +each of these things in here. +里面每一个东西 + +856 +00:35:35,922 --> 00:35:38,956 +But you can also put names in here as, if you want, as well. +如果你想要,你也可以把名称放在这里 + +857 +00:35:38,958 --> 00:35:41,092 +So maybe I would call this one the result. +我会把这个(Tuple 的第一项)命名为 result + +858 +00:35:42,061 --> 00:35:44,728 +Okay? And + +859 +00:35:44,729 --> 00:35:47,396 +I would call this one remainingOps, 'kay? +把这个(Tuple 的第二项)命名为 remainingOps + +860 +00:35:47,399 --> 00:35:49,666 +And I kinda recommend putting those in there, and +我推荐给 Tuple 中的对象命名, + +861 +00:35:49,668 --> 00:35:52,601 +you'll see why in a second because there's two ways to +马上你们就会知道为什么因为有两种方法 + +862 +00:35:52,603 --> 00:35:56,138 +call a function that returns a Tuple and get the results. +的返回值是 Tuple + +863 +00:35:56,140 --> 00:36:00,208 +And one of the ways requires that you name these, 'kay? +其中一种强制要求命名 + +864 +00:36:00,210 --> 00:36:01,843 +So, it doesn't hurt to name the, you might, as well. +所以,加上名字没什么要紧的 + +865 +00:36:01,845 --> 00:36:03,111 +It's good documentation. +这是很好的代码习惯 + +866 +00:36:03,113 --> 00:36:05,379 +Someone looking at this now knows, oh, yeah, +有些人看到这个方法就会明白 + +867 +00:36:05,381 --> 00:36:07,147 +this is the result of the evaluation, and +这个(Tuple 的第一项)是求值的结果, + +868 +00:36:07,149 --> 00:36:09,783 +these the ops that were left over. +这个(Tuple 的第二项)是剩下的栈 + +869 +00:36:09,785 --> 00:36:10,784 +'Kay? + +870 +00:36:10,786 --> 00:36:13,419 +All right. + +871 +00:36:13,421 --> 00:36:15,121 +So let's dive in here. +好,我们从这里开始 + +872 +00:36:15,123 --> 00:36:16,956 +The first thing, +第一件事, + +873 +00:36:16,957 --> 00:36:18,790 +line of code I'm gonna put in this recursive function +编写这个递归函数 + +874 +00:36:18,793 --> 00:36:21,193 +is the failure line of code, +处理失败的情况的代码, + +875 +00:36:21,195 --> 00:36:25,930 +which is return nil, ops, Okay? +这里,我们直接返回 (nil, ops) + +876 +00:36:25,932 --> 00:36:28,566 +So if I fail, Okay, I'm gonna try and +如果失败了,我会尝试 + +877 +00:36:28,568 --> 00:36:33,303 +do my best in here to evaluate these ops you passed me, but +用这里传入的 ops 求值, + +878 +00:36:33,305 --> 00:36:36,272 +if I fail I'm just gonna return my result of nil. +如果失败了,就以 nil 为结果返回 + +879 +00:36:36,274 --> 00:36:37,974 +'Kay? + +880 +00:36:37,975 --> 00:36:39,675 +And that's gonna be my default is to return nil so +返回 nil 将是默认行为, + +881 +00:36:39,678 --> 00:36:40,643 +I know I failed. +如果返回 nil,我就知道我失败了 + +882 +00:36:40,645 --> 00:36:42,344 +So, if I run out of operands or +再者,比如当我处理完毕所有的操作数, + +883 +00:36:42,346 --> 00:36:44,613 +I run out of stack can't find it for +或者处理完毕整个栈时, + +884 +00:36:44,615 --> 00:36:47,915 +example, it's just gonna fall out here and return nil. +那么也会跳转到这里,返回 nil + +885 +00:36:49,152 --> 00:36:49,683 +Okay? + +886 +00:36:49,685 --> 00:36:50,784 +So that's good. +这样挺不错的 + +887 +00:36:50,786 --> 00:36:52,619 +So, what do I need to do here? +在这里需要我做什么呢? + +888 +00:36:52,621 --> 00:36:56,089 +Well, first thing is I need to make sure I have some ops. +首先我要确定栈中有元素 + +889 +00:36:56,091 --> 00:36:59,859 +So I'm gonna check to see if the ops is not empty. +我要检查栈是不是空的 + +890 +00:36:59,861 --> 00:37:04,529 +Okay, if you've handed me a stack of no ops to evaluates, +如果传入一个没有元素的栈 + +891 +00:37:04,531 --> 00:37:05,463 +I can't do that. +我将无法求值 + +892 +00:37:05,465 --> 00:37:06,698 +So I'm just gonna return nil. +我简单地返回 nil 即可 + +893 +00:37:06,700 --> 00:37:07,615 +'Kay? So + +894 +00:37:07,616 --> 00:37:08,531 +that's the very first thing, +这是最开始要做的事, + +895 +00:37:08,534 --> 00:37:11,035 +I gotta make sure I have some ops to work with. +我要确定我有待处理的栈元素 + +896 +00:37:11,037 --> 00:37:14,237 +Now, I'm gonna grab the first op of the stack, so +现在,我要获取栈里的第一个操作符或者操作数, + +897 +00:37:14,239 --> 00:37:16,639 +in this example, I'm gonna grab that x off of here. +在这个例子里,我要在这里获取 x + +898 +00:37:16,641 --> 00:37:17,206 +'Kay? + +899 +00:37:17,208 --> 00:37:18,574 +I'm gonna do that, +想要这么做, + +900 +00:37:18,576 --> 00:37:24,012 +I'm gonna try to do that by saying, let op equal ops. +这么实现: let op = ops + +901 +00:37:38,994 --> 00:37:40,594 +that's how we do it, Okay? +我们就会那样做 + +902 +00:37:40,595 --> 00:37:42,195 +We push things by putting these on the end of the array. +我们通过在数组的最后插入元素来压栈 + +903 +00:37:42,197 --> 00:37:44,196 +We pop things by, by pulling it out. +我们再把数组的最后一个元素取出来来出栈 + +904 +00:37:44,198 --> 00:37:45,431 +But you can see I got an error there. +但是,你们看到这里我有个 error + +905 +00:37:45,433 --> 00:37:48,166 +[BLANK_AUDIO] + +906 +00:37:48,168 --> 00:37:49,768 +And it's very important to understand why I +要理解为什么我在这里 + +907 +00:37:49,770 --> 00:37:50,835 +have an error here, Okay? +有个 error,这非常重要 + +908 +00:37:51,838 --> 00:37:53,704 +So I'm gonna click on it. +我点击这里 + +909 +00:37:53,706 --> 00:37:54,805 +We're gonna read what it says, +我们看看它说什么 + +910 +00:37:54,807 --> 00:38:00,009 +it says, immutable value of type array of op, +它说,数组中的 op 是不可变类型, + +911 +00:38:00,011 --> 00:38:04,113 +only has a mutating member named removeLast. +只有一个可变的成员函数,命名是 removeLast + +912 +00:38:04,115 --> 00:38:06,548 +Okay, well this is kind of a formal way of saying, +好吧这只是一种“正式”的说法 + +913 +00:38:06,550 --> 00:38:13,221 +you can't do removeLast on ops because ops is immutable. +你不能在 ops 数组中移除最后一个元素,因为 ops 是不可变的 + +914 +00:38:13,223 --> 00:38:14,455 +It's read-only. +它是只读的 + +915 +00:38:14,457 --> 00:38:15,556 +You cannot mutate it. +你不能改变它 + +916 +00:38:15,558 --> 00:38:16,990 +You cannot change it. +你不能更改它 + +917 +00:38:16,992 --> 00:38:20,160 +Okay, why is ops read-only? +ops 为什么是只读的? + +918 +00:38:20,162 --> 00:38:23,063 +Well, there's two things to think about here. +这里有两个问题需要大家思考 + +919 +00:38:23,065 --> 00:38:26,899 +One is, when you pass arguments into functions, +一个是,当你给方法传递参数时 + +920 +00:38:26,901 --> 00:38:29,702 +unless it's a class that you're passing, +只要你传入的不是一个类 + +921 +00:38:29,704 --> 00:38:32,137 +unless you're passing an instance of a class. +只要你传入的不是一个类的实例 + +922 +00:38:32,139 --> 00:38:34,172 +The thing you pass is copied. +那么你传入的参数就是拷贝过的 + +923 +00:38:34,174 --> 00:38:35,791 +Okay? +Okay? + +924 +00:38:35,792 --> 00:38:37,409 +It's very important to understand that, +弄明白这一点非常重要 + +925 +00:38:37,411 --> 00:38:38,876 +that's passed by value. +就是传入的是值 + +926 +00:38:38,878 --> 00:38:40,845 +You're used to it in other languages, +你在其他语言中习惯了这一点, + +927 +00:38:40,847 --> 00:38:43,313 +most languages do this, pass by value. +大多数的语言是传递值的 + +928 +00:38:43,315 --> 00:38:46,516 +Arrays and dictionaries are not classes. +数组和字典不是类, + +929 +00:38:47,652 --> 00:38:49,952 +They're not classes in Swift. +它们在 Swift 中不是类 + +930 +00:38:49,954 --> 00:38:50,886 +They're structs. +它们是结构体 + +931 +00:38:50,888 --> 00:38:52,754 +You know, like a C struct? +你知道的,就像 C 语言中的结构体 + +932 +00:38:52,756 --> 00:38:53,955 +Okay? +Okay? + +933 +00:38:53,957 --> 00:38:55,723 +Arrays and dictionaries are structs. +数组和字典是结构体 + +934 +00:38:55,725 --> 00:38:58,759 +Structs in Swift look a lot like classes. +结构体在 Swift 中看起来很像类 + +935 +00:38:58,761 --> 00:39:00,594 +They have functions, +它们有方法 + +936 +00:39:00,595 --> 00:39:02,428 +they can even have properties that have storage. +它们甚至拥有带有存取方法的属性 + +937 +00:39:02,431 --> 00:39:04,865 +They're almost identical to a class, really. +它们几乎等同于一个类,真的 + +938 +00:39:04,867 --> 00:39:09,102 +The only two huge differences between structs and classes. +这里的结构体和类仅有两大不同之处 + +939 +00:39:09,104 --> 00:39:12,638 +One is that classes can have inheritance. +一个是,类可以继承 + +940 +00:39:12,640 --> 00:39:15,274 +And structs cannot, Okay? +但结构体不可以 + +941 +00:39:15,276 --> 00:39:20,745 +But number two is that structs are passed by value and +第二个就是,结构体传递的是值, + +942 +00:39:20,747 --> 00:39:25,049 +classes are passed by reference, Okay? +而类传递的是引用,Okay? + +943 +00:39:25,051 --> 00:39:27,751 +Very important that you understand that distinction. +非常重要,你弄明白这里面的区别 + +944 +00:39:27,753 --> 00:39:30,687 +So structs are usually only used for basic. +因此结构体通常仅用于基础数据类型 + +945 +00:39:30,689 --> 00:39:33,289 +You know, components like arrays and dictionaries. +你知道的,像数组和字典这样的元素 + +946 +00:39:33,291 --> 00:39:37,159 +Even Doubles and Ints are structs in Swift, Okay? +甚至 Double 类型和 Int 类型在 Swift 中都是结构体 + +947 +00:39:37,161 --> 00:39:38,627 +>> [COUGH] + +948 +00:39:38,628 --> 00:39:40,094 +>> And that's great because that means Doubles and +这非常棒,因为这意味着 Double 和 + +949 +00:39:40,097 --> 00:39:42,564 +Ints can have functions on them and things like that, +Int 也拥有方法和其他类似的语法, + +950 +00:39:42,566 --> 00:39:44,599 +which we will see as the quarter goes by. +随着时间的推移我们可能会看到 + +951 +00:39:44,601 --> 00:39:46,501 +But those things are all passed by values. +但是这里传递的都是值 + +952 +00:39:46,503 --> 00:39:48,669 +So that's the first thing to understand is that this ops, +因此首先要做的事是 + +953 +00:39:48,671 --> 00:39:52,139 +when I call evaluate, whatever array of ops I pass to it, +理解当我调用 evaluate 方法,无论我传什么给 ops 数组 + +954 +00:39:52,141 --> 00:39:53,840 +it's gonna be copied. +它都会被拷贝 + +955 +00:39:53,842 --> 00:39:55,108 +Okay? +Okay? + +956 +00:39:55,110 --> 00:39:57,643 +The second thing to understand here is that they're kind of +第二件事是理解在这里 + +957 +00:39:57,645 --> 00:40:03,682 +an implicit let in front of all things you pass. +在你传递的参数前面,实际上隐含了一个 let + +958 +00:40:03,684 --> 00:40:05,484 +In other words, they're read-only. +换言之,它们是只读的 + +959 +00:40:05,486 --> 00:40:06,651 +Make sense? +明白了吗? + +960 +00:40:06,653 --> 00:40:12,390 +And a read-only array can't be mutated. +一个只读的数组不能被改变 + +961 +00:40:12,392 --> 00:40:14,475 +I can't append things to it. +我不能给它添加元素 + +962 +00:40:14,476 --> 00:40:16,559 +You can't remove things from it cuz it's read-only. +你不能从它身上移除元素,因为它是只读的 + +963 +00:40:16,562 --> 00:40:21,364 +Now, I can actually put the word var here, Okay? +现在,你实际上可以写一个 var 在这 ,Okay? + +964 +00:40:21,366 --> 00:40:22,999 +If I, sorry. +如果我...抱歉 + +965 +00:40:23,001 --> 00:40:25,267 +If I put the word var here, +如果我写一个词 var 在这里 + +966 +00:40:25,269 --> 00:40:29,204 +then ops inside here look no error. +那么 ops 在这个方法体里面看起来就没有错误了 + +967 +00:40:29,206 --> 00:40:32,674 +Ops is a mutable array. +Ops 是一个可变数组了 + +968 +00:40:32,676 --> 00:40:34,575 +It's still a copy though. +不过它仍然是一个拷贝 + +969 +00:40:34,577 --> 00:40:36,711 +So they copied it, made it mutable. +那么它们把 ops 拷贝成了一个可变的副本 + +970 +00:40:36,713 --> 00:40:41,381 +And now inside here, I have a mutable copy to work with. +于是在这里面,有一个可变的拷贝在工作了 + +971 +00:40:41,383 --> 00:40:45,084 +Now, I'm not a big fan of doing that, kay? +但现在我不想要这么做 + +972 +00:40:45,086 --> 00:40:46,118 +Putting var up here. +写一个 var 在这里 + +973 +00:40:46,120 --> 00:40:47,586 +I think it's a little confusing for readers of the code, +我认为这对于读代码的人会造成一些困惑, + +974 +00:40:49,222 --> 00:40:50,855 +to understand exactly what's going on there. +要确切地理解这里到底发生了什么 + +975 +00:40:50,858 --> 00:40:53,208 +So, I'm not gonna do that, +因此,我不会这样做 + +976 +00:40:53,209 --> 00:40:55,559 +instead, I'm gonna make a local variable here, which I'm +而是替换成一个局部变量在这里, + +977 +00:40:55,562 --> 00:41:00,865 +gonna call remainingOps and I'm gonna set it equal to ops. +命名为 remainingOps ,让 remainingOps 等于 ops + +978 +00:41:00,867 --> 00:41:03,000 +Now, when you set equals like this, +注意,当你像这样赋值时, + +979 +00:41:04,103 --> 00:41:07,103 +that copies it if it's not a class. +就将它拷贝了,只要用来赋值的对象不是一个类 + +980 +00:41:07,105 --> 00:41:08,571 +Classes are all by reference. +类赋值的都是引用 + +981 +00:41:08,573 --> 00:41:09,438 +It's exactly, what you would think. +就好像你们想的那样 + +982 +00:41:09,440 --> 00:41:10,539 +But anything else, +但是别的, + +983 +00:41:10,541 --> 00:41:12,808 +strucks or enums or anything else. +像结构体、枚举或者其他的什么 + +984 +00:41:12,810 --> 00:41:14,543 +When you do equals here, +当你像这样赋值时, + +985 +00:41:14,544 --> 00:41:16,277 +this is actually going to make a copy of this, and +实际上是做了,这个的拷贝, + +986 +00:41:16,279 --> 00:41:17,895 +put it in here. +然后把它赋给这里 + +987 +00:41:17,896 --> 00:41:19,512 +And since it's a var, it's going to be mutable. +因为它是一个变量,所以它是可变的 + +988 +00:41:21,584 --> 00:41:23,083 +Okay? +Okay? + +989 +00:41:23,084 --> 00:41:24,583 +So now I have a mutable array of ops and +因此现在我有了一个可变数组 ops + +990 +00:41:24,586 --> 00:41:26,519 +now I can say remainingOps. +现在我可以说 remainingOps + +991 +00:41:26,521 --> 00:41:27,854 +Remove the first one. +移除了栈顶元素 + +992 +00:41:27,856 --> 00:41:30,122 +And now I truly do have the remainingOps. +现在我真正有 remainingOps 了 + +993 +00:41:30,124 --> 00:41:32,358 +I've removed the last thing in there. +我在这里移除了最后一个元素 + +994 +00:41:32,360 --> 00:41:35,594 +[BLANK_AUDIO] + +995 +00:41:35,596 --> 00:41:38,463 +Did everyone understand that little tidbit there? +每个人都理解这个小技巧了嘛? + +996 +00:41:38,465 --> 00:41:39,464 +Yeah? >> So there's a,Yeah? +Yeah? -(学生提问) + +997 +00:41:39,466 --> 00:41:42,800 +like a, a unseen let in sort +of the opts? +-(学生提问) + +998 +00:41:42,802 --> 00:41:43,600 +>> Yeah.>> Why isn't that like in +- Yeah. -(学生提问) + +999 +00:41:43,602 --> 00:41:47,371 +front of Doubles and +-(学生提问) + +1000 +00:41:47,373 --> 00:41:48,672 +like ends or straightened >> It is. +是的 + +1008 +00:41:48,674 --> 00:41:50,873 +So, the question is why is there not a kind of unseen, +所以,问题是:为什么不是一种看不见的 + +1009 +00:41:50,875 --> 00:41:52,508 +let in front of all arguments? +let 在所有的参数前面? + +1010 +00:41:52,510 --> 00:41:54,376 +Pretty much all arguments to functions kind of +差不多所有的函数里的参数 + +1011 +00:41:54,378 --> 00:41:55,577 +have that unseen let in there. +都有个看不见的 let 在那 + +1012 +00:41:55,579 --> 00:41:57,545 +They're all read on, 'kay? +这些都是默认的 + +1013 +00:41:57,547 --> 00:41:59,681 +So and you could put var in front of any one and +所以你可以把 var 放在任何一个参数前面 + +1014 +00:41:59,683 --> 00:42:02,516 +turn it into a mutable copy of it, +把这个变成可以在本地用的 + +1015 +00:42:02,518 --> 00:42:03,484 +that you could use locally. +一个可变的复制 + +1016 +00:42:03,486 --> 00:42:04,885 +But if you only use it locally, +但如果你在本地用这个 + +1017 +00:42:04,887 --> 00:42:06,219 +it's not that great a thing. +这不是个好事 + +1018 +00:42:06,221 --> 00:42:08,371 +Okay? +Okay? + +1019 +00:42:08,372 --> 00:42:10,522 +Now, there is a way to have, to pass by value things back +现在,有一种通过值去获取、传递回来的方法 + +1020 +00:42:10,525 --> 00:42:13,959 +out, but I'm not even gonna talk about that. +但是我不打算讲 + +1021 +00:42:13,961 --> 00:42:14,726 +Okay. +Okay. + +1022 +00:42:14,728 --> 00:42:16,027 +You can read about it. +你可以读到关于这些的东西 + +1023 +00:42:16,029 --> 00:42:17,328 +It's this in out thing. +传入、传出的事情 + +1024 +00:42:18,698 --> 00:42:20,665 +I'm not even gonna talk about it. +我不打算讲 + +1025 +00:42:20,666 --> 00:42:22,633 +I really think it's better to stay within the value, +我真的觉得还是在值上更好 + +1026 +00:42:22,635 --> 00:42:25,035 +pass by value, pass by reference parameters. +通过值或者引用传递参数 + +1027 +00:42:25,037 --> 00:42:27,604 +I think you can get more readable code that way. +我想你可以通过那种方式来写出可读性更高的代码 + +1028 +00:42:27,606 --> 00:42:30,139 +But there is a way, there is a way I'm not going to talk +但是我不想讲 + +1029 +00:42:30,141 --> 00:42:33,075 +about to do in out basically, parameters that go in out. +那种传入传出的方式 + +1030 +00:42:33,077 --> 00:42:33,842 +Yeah. +Yeah + +1031 +00:42:33,844 --> 00:42:36,712 +>> Is there any way to +-(学生提问) + +1032 +00:42:36,714 --> 00:42:39,180 + + + +1033 +00:42:39,182 --> 00:42:40,949 +>> Yeah that's what I just said. +这就是我刚才提到的 + +1034 +00:42:40,950 --> 00:42:42,717 +There is a way to pass it kind of by reference in out. +有一种通过引用传递参数的方式 + +1035 +00:42:42,719 --> 00:42:44,618 +You know, you pass it in, you modify it, +如果传入后,改变它 + +1036 +00:42:44,620 --> 00:42:47,054 +and then it'll come back out when it's done at the end. +在完成后、结尾时更改就会生效 + +1037 +00:42:47,056 --> 00:42:48,255 +So, it's kind of like by reference. +所以这就是一种通过引用传递 + +1038 +00:42:49,224 --> 00:42:50,323 +But the other thing you said is, +但你可能又会说了 + +1039 +00:42:50,325 --> 00:42:52,558 +oh this is terrible I'm making three copies of +把这个值做了三次复制 + +1040 +00:42:52,560 --> 00:42:55,394 +that dang thing, this must be super slow. +真是一件很糟糕的事,会让程序变的非常慢 + +1041 +00:42:55,396 --> 00:42:57,029 +And the answer is no. +但答案是否定的 + +1042 +00:42:57,031 --> 00:43:01,599 +Swift is super smart about not actually copying it, +Swift 是不会真的复制它的 + +1043 +00:43:01,601 --> 00:43:04,135 +until you actually make a change to it. +直到你真的改变它 + +1044 +00:43:04,137 --> 00:43:07,271 +So here when it passes a copy in it didn't really +所以当传入一个拷贝的时候 + +1045 +00:43:07,273 --> 00:43:10,073 +copy it, it just kinda passed a pointer in but it knows that +并不是真的复制了,而是传入一种指针 + +1046 +00:43:10,075 --> 00:43:13,576 +pointer is by, you know, not by reference it's by value. +一种它知道从哪来的指针,不是通过引用而是值 + +1047 +00:43:13,578 --> 00:43:15,611 +And then when I copied it again here. +然后我们再次在这复制 + +1048 +00:43:15,613 --> 00:43:17,146 +It still didn't really copy it. +这还是不会真的复制 + +1049 +00:43:17,148 --> 00:43:19,081 +Even if this array had 10,000 things in it, +甚至这个数组里有一万条数据 + +1050 +00:43:19,083 --> 00:43:21,116 +it didn't make 10,000 copy of it. +它不会做一万次复制 + +1051 +00:43:21,118 --> 00:43:25,019 +It was only here where I actually mutated, +只有在这我真正改变的地方 + +1052 +00:43:25,021 --> 00:43:26,120 +now it had to make a copy. +它就必须得复制了 + +1053 +00:43:26,122 --> 00:43:28,989 +And it may not even have made an entire copy. +并且这可能甚至不会做一个完整的复制 + +1054 +00:43:28,991 --> 00:43:32,025 +It might have just kept track of the changes, for example. +它可能只会追踪改变的地方 + +1055 +00:43:32,027 --> 00:43:33,860 +So, it's super smart behind the scenes. +所以这真的非常智能 + +1056 +00:43:33,862 --> 00:43:34,861 +Sweet to very smart. +真的很智能 + +1057 +00:43:34,863 --> 00:43:36,862 +So, don't worry too, about much about oh, +所以不必总是担心 + +1058 +00:43:36,864 --> 00:43:38,630 +I'm copying these things over and over. +我一遍一遍的复制这些 + +1059 +00:43:38,632 --> 00:43:40,332 +Swift is making the minimum out of +Swift 在做复制之前 + +1060 +00:43:40,334 --> 00:43:41,433 +actual copying going on. +只做了少量的工作 + +1061 +00:43:41,435 --> 00:43:42,600 +Okay? +Okay? + +1062 +00:43:42,602 --> 00:43:47,171 +All right, so now I have remainingOpts here, +好的,现在这就有了 remainingOps + +1063 +00:43:47,173 --> 00:43:49,840 +which truly are my remaining ops +是真的余下的那个 ops + +1064 +00:43:49,842 --> 00:43:51,842 +'Kay. Because I've +因为我已经 + +1065 +00:43:51,843 --> 00:43:53,843 +removed the top one, the x, off the top. +把最上面的那个 x 从栈顶移除了 + +1066 +00:43:53,845 --> 00:43:56,279 +So now I've got all the remainingOps, +所以我得到了所有的 remainingOps + +1067 +00:43:56,281 --> 00:43:59,181 +in this local variable here called remainingOps. + 在这个叫 remainingOps 的局部变量 + +1068 +00:43:59,183 --> 00:44:00,566 +Okay. +Okay + +1069 +00:44:00,567 --> 00:44:01,950 +Now, what am I gonna do with this op that I pulled off, +现在,我现在要对这个已经取出来的 op 做什么呢? + +1070 +00:44:01,952 --> 00:44:03,218 +this one on the top, x? +这个在栈顶的 x + +1071 +00:44:03,220 --> 00:44:06,621 +Well I'm gonna get the associated value from +我想从枚举中 + +1072 +00:44:06,623 --> 00:44:07,888 +the enum. +得到这个关联变量 + +1073 +00:44:07,890 --> 00:44:11,792 +'Kay. Either this or these or this. +可能是这个,这个或这个 + +1074 +00:44:11,794 --> 00:44:13,226 +And how do I do that? +那么我该怎么做呢? + +1075 +00:44:13,228 --> 00:44:15,094 +I use switch. +我用 switch + +1076 +00:44:15,096 --> 00:44:17,496 +'Kay, I told you that switch is really important. +我告诉过你们 switch 很重要 + +1077 +00:44:17,498 --> 00:44:20,032 +And now you're seeing that switch is really important. +现在你们看到了它真的很重要 + +1078 +00:44:20,034 --> 00:44:21,867 +switch is how you pull things out, +switch 用来把 + +1079 +00:44:21,869 --> 00:44:23,668 +associated values out of enums. +关联变量取出枚举 + +1080 +00:44:23,670 --> 00:44:25,036 +So I'm just gonna switch on the op. +所以我想在 op 上用 switch + +1081 +00:44:25,038 --> 00:44:27,772 +'Kay, this is the op that I pulled off the top, +这就是我从上面取得的 op + +1082 +00:44:27,774 --> 00:44:30,708 +that x from the thing we did on the board. +那个 x 就是我们之前取得的 + +1083 +00:44:30,710 --> 00:44:32,109 +And I'm just gonna look at the cases, so +我现在只会关注这些 case + +1084 +00:44:32,111 --> 00:44:35,412 +I have the case operand, Okay. +case .Operand + +1085 +00:44:35,414 --> 00:44:38,581 +Notice that it puts a little dot here because it's +注意这里放了个小点 + +1086 +00:44:38,583 --> 00:44:41,450 +really Op.Operand and it's using type inference to +因为这应该是 Op.Operand,并且用了类型推断 + +1087 +00:44:41,452 --> 00:44:43,652 +know that it's Op.Operand, right. +为了清楚这是 Op.Operand + +1088 +00:44:43,654 --> 00:44:47,289 +Op.op, Op.Operand but it doesn't need the Op there. +Op.op, Op.Operand 但这里不需要 Op + +1089 +00:44:47,291 --> 00:44:50,892 +And here it's asking in this space, what do you wanna do +在这里 + +1090 +00:44:50,894 --> 00:44:54,628 +with the associated value if you're handling this case. +你想在这个 case 里对相关变量做什么 + +1091 +00:44:54,630 --> 00:44:56,864 +Where the enum is operand. +对于相关的枚举 operand + +1092 +00:44:56,866 --> 00:44:58,432 +'Kay? +Okay? + +1093 +00:44:58,434 --> 00:45:04,037 +Well I want to let that associated value +我想在那个关联变量前面放个 let + +1094 +00:45:04,039 --> 00:45:10,175 +be assigned to a constant called operand. +用来关联一个叫做 operand 的常量 + +1095 +00:45:10,177 --> 00:45:11,510 +'Kay? +Okay? + +1096 +00:45:11,512 --> 00:45:14,746 +And yes I could put var here, which would do the same thing, +我当然也可以放个 var 在这,也一样有用 + +1097 +00:45:14,748 --> 00:45:17,715 +except for I could then change the thing in here. +除非我之后把这里的东西改变了 + +1098 +00:45:17,717 --> 00:45:20,685 +But I almost never wanna do this, almost always let. +但我几乎从来都不会这样做,几乎都用 let + +1099 +00:45:20,687 --> 00:45:23,887 +So let operand means that inside the handling of +所以 let operand 表示在这个 case 中 + +1100 +00:45:23,889 --> 00:45:27,157 +this case, 'kay, this case of the switch. +这个 switch 中的这个 case + +1101 +00:45:27,159 --> 00:45:30,693 +Inside here, operand is gonna have the associated value of +在这里面,operand 就会获得 + +1102 +00:45:30,695 --> 00:45:31,427 +the operand. +operand 的关联变量 + +1103 +00:45:32,430 --> 00:45:34,196 +'Kay? +'Kay? + +1104 +00:45:34,198 --> 00:45:35,897 +Oh, that's exactly what I want. +这就是我想要的 + +1105 +00:45:35,899 --> 00:45:38,599 +I'm just gonna return right now I have to return this +我现在就要返回一个值 + +1106 +00:45:38,601 --> 00:45:40,301 +Tuple right here. +我要返回一个 Tuple + +1107 +00:45:40,303 --> 00:45:42,569 +So I'm gonna returned the operand. +所以我要返回 operand + +1108 +00:45:42,571 --> 00:45:45,005 +That's the result, 'kay. +这就是结果 + +1109 +00:45:45,007 --> 00:45:47,191 +When I go here and +当我到这 + +1110 +00:45:47,192 --> 00:45:49,376 +I encounter that next one down which was a four, I got a four +我碰到下一个是 4,我得到一个 4 + +1111 +00:45:49,378 --> 00:45:52,845 +I can just return that result to evaluate this one. +我可以直接返回这个结果来计算它 + +1112 +00:45:52,847 --> 00:45:55,881 +And I also though have to return the remainingOps. +当然我也需要返回 remainingOps + +1113 +00:45:57,018 --> 00:46:00,085 +'Kay, so I'm just returning the two values of this Tuple, +所以我返回了 Tuple 里的两个值 + +1114 +00:46:00,087 --> 00:46:02,754 +notice I don't have to put result: and +注意我没有在这放 result: + +1115 +00:46:02,756 --> 00:46:06,390 +remainingOps: colon in here it knows that those match and +remainingOps: ,因为这里知道这些是对应的 + +1116 +00:46:06,392 --> 00:46:07,224 +so it's still doing it. +所以这还是会正常执行 + +1117 +00:46:07,226 --> 00:46:09,159 +All right, makes sense. +好的,懂了吧 + +1118 +00:46:09,161 --> 00:46:13,763 +That's it for operand that's all I have to do. +这就是我对 operand 做的一切 + +1119 +00:46:13,765 --> 00:46:15,064 +It's kind of a, in the recursion, +这在递归中 + +1120 +00:46:15,066 --> 00:46:20,102 +it's kind of an end case. +是一种结束的情况 + +1121 +00:46:20,104 --> 00:46:21,069 +Yeah? >> Is remainingOps part of +-(学生提问) + +1122 +00:46:21,071 --> 00:46:22,520 +the stack or heap? +-(学生提问) + +1123 +00:46:22,521 --> 00:46:23,970 +>> This one here, or this one here? +-(学生提问) + +1124 +00:46:23,973 --> 00:46:24,989 +>> What in general [INAUDIBLE]. +-(学生提问) + +1125 +00:46:24,990 --> 00:46:26,006 +>> Okay so, so the question is, +问题是: + +1126 +00:46:26,009 --> 00:46:29,276 +when I do something like this, where is remainingOps? +当我像这样做的时候,remainingOps 在哪? + +1127 +00:46:29,278 --> 00:46:30,377 +Is it in the heap? +在堆中吗? + +1128 +00:46:30,379 --> 00:46:31,812 +Is it on the stack? +还是在栈中? + +1129 +00:46:31,813 --> 00:46:33,246 +And the thing is, that's implementation detail. +事实上这些是实现时的细节 + +1130 +00:46:34,282 --> 00:46:36,148 +So, you, you don't know, but you don't care. +所以你不知道,也不用关心 + +1131 +00:46:38,018 --> 00:46:40,185 +All right, so that's operand. +这就是 operand + +1132 +00:46:40,187 --> 00:46:42,020 +Operand was really, really easy. +operand真的非常非常简单 + +1133 +00:46:42,022 --> 00:46:44,321 +How about our operation, that's you, you, +那么关于这里 UnaryOperation + +1134 +00:46:44,323 --> 00:46:46,090 +UnaryOperation right here. +的操作是怎么样的呢 + +1135 +00:46:46,092 --> 00:46:49,659 +Now when we handle the case of the unary operation, +当我们要处理 UnaryOperation + +1136 +00:46:49,661 --> 00:46:52,195 + we don't need that first associated value, +我们不需要第一个变量 + +1137 +00:46:52,197 --> 00:46:54,330 +that's the symbol, like plus. +这是符号,像是加号 + +1138 +00:46:54,332 --> 00:46:56,332 +Okay well I'm evaluating here I don't care what this +当我在这计算的时候我不在乎它是什么 + +1139 +00:46:56,334 --> 00:46:58,500 +symbol is, I only care what the function is cause I'm +我只在乎那个函数是什么 + +1140 +00:46:58,502 --> 00:47:00,002 +gonna evaluate the function. +因为我要去计算那个函数 + +1141 +00:47:00,004 --> 00:47:05,807 +So we can actually ignore this by putting in underbar, 'kay? +所以我们实际上可以在这放一个下划线来忽略它 + +1142 +00:47:05,809 --> 00:47:08,642 +Underbar in Swift is kind of +下划线在 Swift 里 + +1143 +00:47:08,644 --> 00:47:12,212 +the universal I don't care about this thing. +就是一种“我不关心这个”的通用表达 + +1144 +00:47:12,214 --> 00:47:14,681 +Okay and we're gonna see it other places we use it +我们还会在其它地方 + +1145 +00:47:14,683 --> 00:47:16,549 +where it's kinda like, I don't really care about that. +使用下划线来表达“我不关心这个” + +1146 +00:47:16,551 --> 00:47:18,251 +So you just put an underbarthere. +所以你只需要放一个下划线在这 + +1147 +00:47:18,253 --> 00:47:19,819 +That way you don't have to declare a variable with +这样你就不需要声明一个奇怪的变量 + +1148 +00:47:19,821 --> 00:47:22,221 +some dumb name or something like that. +或者跟他相似的东西 + +1149 +00:47:22,223 --> 00:47:24,389 +Just put an underbar it ignores it. +只是放一个下划线在这 + +1150 +00:47:24,391 --> 00:47:25,323 +'Kay? +'Kay? + +1151 +00:47:25,324 --> 00:47:26,256 +But I do care about this. +但我真的关心这个 + +1152 +00:47:26,259 --> 00:47:29,794 +I'm gonna let that equal the operation that I'm doing. +我会放 let operation 在这 + +1153 +00:47:29,796 --> 00:47:30,361 +'Kay? +'Kay? + +1154 +00:47:31,397 --> 00:47:32,929 +Everyone, make sense there? +所有人都懂了吗? + +1155 +00:47:32,931 --> 00:47:34,897 +So I'm ignoring the String, but +所以我忽略了 String + +1156 +00:47:34,899 --> 00:47:36,699 +I'm grabbing the operation. +我在获取 operation + +1157 +00:47:36,701 --> 00:47:40,402 +So here, what I wanna do is return and I'll try to do it, +所以这里我试着返回 + +1158 +00:47:40,404 --> 00:47:41,370 +but I'm not gonna be able to. +我还没法做 + +1159 +00:47:41,372 --> 00:47:45,540 +I'm gonna say, return this operation with +我会返回我还没有的 operation + +1160 +00:47:45,542 --> 00:47:48,342 +its operand which I don't have. +还有 operand + +1161 +00:47:48,344 --> 00:47:51,512 +And there's some remaining ops that are leftover after I +还有一些我获取 operand 后 + +1162 +00:47:51,514 --> 00:47:52,579 +get the operand. +余下的 ops + +1163 +00:47:52,581 --> 00:47:55,515 +So I'm kinda, I need to do some stuff here to +所以我要在这做一些 + +1164 +00:47:55,517 --> 00:47:58,251 +be able to return what I want. +能让我返回我想要的东西的操作 + +1165 +00:47:58,253 --> 00:48:01,053 +The first thing I need to do is get the operand. +第一件事就是获取 operand + +1166 +00:48:01,055 --> 00:48:03,689 +'Kay? +'Kay? + +1167 +00:48:03,690 --> 00:48:06,324 +So, I did a unary operation let's say it was square root. +例如我要处理平方根 + +1168 +00:48:06,326 --> 00:48:07,625 +I need to go back to the staff and +我需要返回到那个地方 + +1169 +00:48:07,627 --> 00:48:10,862 +pick off the next thing but I can't just +来获得下一个东西,但我不能 + +1170 +00:48:10,864 --> 00:48:13,931 +assume that it's a number, it might be more operations so +假定这是一个数字,接下来可能是更多的操作符 + +1171 +00:48:13,933 --> 00:48:17,001 +I have to recurse, so here's where the recursion comes in. +所以我需要递归,这里就是用到递归的地方 + +1172 +00:48:17,003 --> 00:48:20,103 +And I'm gonna show you how to call a function that +我会展示如何调用一个函数 + +1173 +00:48:20,105 --> 00:48:22,172 +returns a Tuple. +返回一个 Tuple + +1174 +00:48:22,174 --> 00:48:25,274 +And get it's value up so this is important little example +获得这个值,所以这是这里一个重要的例子 + +1175 +00:48:25,276 --> 00:48:27,677 +here, so there's two ways to do it. +所以有两种方法来实现 + +1176 +00:48:27,679 --> 00:48:30,279 +I'm gonna do it one way here, which is, +我会在这里做其中一种 + +1177 +00:48:30,281 --> 00:48:32,881 +I'm gonna let operandEvaluation, +let operandEvaluation + +1178 +00:48:32,883 --> 00:48:37,919 +which is just a local variable that I'm inventing, equal call +一个我声明的局部变量 + +1179 +00:48:37,921 --> 00:48:43,057 +evaluate with the remainingOps that I have. +等于 evaluate(remainingOps) + +1180 +00:48:43,059 --> 00:48:45,025 +'Kay, so here I've recursed. +这样我就递归了 + +1181 +00:48:45,027 --> 00:48:46,459 +Okay, I'm recursing. +我正在做一个递归 + +1182 +00:48:46,461 --> 00:48:48,661 +And I just set it to operandEvaluation. +我把他赋给 operandEvaluation + +1183 +00:48:48,663 --> 00:48:51,564 +Now, let's look at the type of this thing. +来看看它的类型 + +1184 +00:48:51,566 --> 00:48:55,300 +If I look at its type, you can see that it's a Tuple. +如果你看它的类型,就会发现它是一个 Tuple + +1185 +00:48:55,302 --> 00:48:56,468 +That's its type. +这就是他的类型 + +1186 +00:48:56,470 --> 00:48:58,770 +It's a Tuple result remainingOps. +这是一个 Tuple 类型,里面有 result 和 remainingOps + +1187 +00:48:58,772 --> 00:49:00,671 +It's this Tuple right here. +就是这边的这个 Tuple + +1188 +00:49:00,673 --> 00:49:03,140 +That is the type of this operandEvaluation. +就是这个 operandEvaluation 的类型 + +1189 +00:49:04,309 --> 00:49:06,242 +So now that I have that Tuple, +所以现在我有了这个 Tuple + +1190 +00:49:06,244 --> 00:49:09,245 +it's the result of evaluation how do I get the result and +这就是计算的结果,我是怎么获得的这个结果 + +1191 +00:49:09,247 --> 00:49:13,716 +the remaining op out of it well I can get the operand by +获得这些余下的 op + +1192 +00:49:13,718 --> 00:49:19,621 +saying operand eval, operandEvaluation.result. +只要 let operand = operandEvaluation.result + +1193 +00:49:19,623 --> 00:49:21,423 +'Kay? +'Kay? + +1194 +00:49:21,424 --> 00:49:23,224 +So that just pull this is the Tuple here I'm +所以只是把 Tuple 放这 + +1195 +00:49:23,226 --> 00:49:26,227 +getting this value of the Tuple out of there. +就获得了这里 Tuple 的值 + +1196 +00:49:26,229 --> 00:49:27,461 +Now what type is this? +这个的类型是什么 + +1197 +00:49:29,298 --> 00:49:29,863 +Anybody? +有人知道吗 + +1198 +00:49:30,865 --> 00:49:31,931 +It's an Optional. +这是个 Optional + +1199 +00:49:31,932 --> 00:49:32,998 +You're pretty safe saying Optional when I +当我问你这是什么类型时 + +1200 +00:49:33,001 --> 00:49:34,099 +ask what type it is, aren't you? +说 Optional 是很安全的 + +1201 +00:49:34,101 --> 00:49:35,801 +It's almost always an Optional. +答案总可以是 Optional + +1202 +00:49:35,803 --> 00:49:37,168 +Cuz I usually don't ask if it's not. +如果它不是我才不会问呢 + +1203 +00:49:37,170 --> 00:49:40,672 +But it is indeed an Optional, an Optional Double. +但是在这它确实是个 Optional,一个 Optional Double 型 + +1204 +00:49:40,674 --> 00:49:42,707 +It's this type right here, Okay? +这就是它的类型 + +1205 +00:49:42,709 --> 00:49:46,043 +So we need to turn it into a Double if we're gonna pass it +如果我们想把它传入这里, + +1206 +00:49:46,045 --> 00:49:48,078 +to this operation right here. +就得把它变成一个 Double 类型的 + +1207 +00:49:48,080 --> 00:49:52,648 +So I'm gonna use if let to turn that into a Double. +所以在这里我是用 if let 来把它变成 Double + +1208 +00:49:52,650 --> 00:49:55,084 +'Kay? + +1209 +00:49:55,085 --> 00:49:57,519 +Now, I can actually do this because I have the operand. +我确实可以这么做,因为我已经有了操作数 + +1210 +00:49:57,521 --> 00:49:58,587 +Just got it right here. +从这里获取到的 + +1211 +00:49:58,589 --> 00:50:00,755 +'Kay? This is now a Double, see? +它现在变成 Double 了 + +1212 +00:50:00,757 --> 00:50:04,125 +And I can call this operation right here. +我可以在这里调用这个运算 + +1213 +00:50:04,127 --> 00:50:06,327 +And this is the remaining ops, but this has got to +这里是余下的 ops, + +1214 +00:50:06,329 --> 00:50:09,229 +be the remaining ops after we recursed. +但这里得放递归之后余下的 ops + +1215 +00:50:09,231 --> 00:50:13,233 +So it's gotta be the remaining ops in this operandEvaluation. +它得是这个 operandEvalution 余下的 ops + +1216 +00:50:13,235 --> 00:50:15,368 +So that operandEvaluation.remainingOps. +所以这里放 operandEvaluation.remainingOps + +1217 +00:50:15,370 --> 00:50:19,471 +Everybody cool with that? +都懂了吗? + +1218 +00:50:19,473 --> 00:50:21,206 +So that's it. +就这么简单 + +1219 +00:50:21,208 --> 00:50:25,343 +It's just recurse, we just recursed to evaluate that. +我们为了计算而进行递归 + +1220 +00:50:25,345 --> 00:50:29,180 +If this fails if, if this recursion returned nil, +如果这步失败了,这次递归返回 nil + +1221 +00:50:29,182 --> 00:50:31,849 +then this is, this, if let's not gonna happen this +这里都不会进行 + +1222 +00:50:31,851 --> 00:50:34,584 +return's not gonna happen, gonna fall all the way out and +不会 return,然后一路向下运行, + +1223 +00:50:34,586 --> 00:50:37,454 +return nill which is what we want, 'kay. +最后返回我们需要的 nil + +1224 +00:50:37,456 --> 00:50:39,522 +We failed in any of our recursive attempts to +如果为了得到操作数 + +1225 +00:50:39,524 --> 00:50:40,756 +get the operands we need, +递归失败了 + +1226 +00:50:40,758 --> 00:50:42,825 +we gotta fail all the way up to the top level. +就是一路失败到最顶层的递归 + +1227 +00:50:42,827 --> 00:50:46,028 + + +1228 +00:50:46,030 --> 00:50:48,063 +Okay now binary operation. +现在谈谈双目操作符 + +1229 +00:50:49,299 --> 00:50:52,466 +Also Okay, let's do yeah, binary here case. +在这个 case 里处理双目操作符 + +1230 +00:50:53,535 --> 00:50:54,267 +Binary. +输入Binary + +1231 +00:50:55,470 --> 00:50:57,570 +Obviously same exact thing here. +显然,跟上面一样 + +1232 +00:50:57,572 --> 00:50:59,438 +We don't care about that. +我们不需要关心这个 + +1233 +00:50:59,440 --> 00:51:00,906 +And here we're gonna let operation. +在这里,let operation + +1234 +00:51:00,908 --> 00:51:03,708 +And we're gonna do the exactly the same thing we did +跟之前做相同的事情 + +1235 +00:51:03,710 --> 00:51:06,577 +here but we just have to do it twice because we have two +但在这里得做两次 + +1236 +00:51:06,579 --> 00:51:08,646 +operands to do here, through here. +因为我们得获取到两个操作数 + +1237 +00:51:08,648 --> 00:51:15,052 +So let's let opp1Evaluation = evaluate(remainingOps). +所以,let opp1Evaluation = evaluate(remainingOps) + +1238 +00:51:16,088 --> 00:51:17,487 +'Kay. + +1239 +00:51:17,488 --> 00:51:18,887 +And then if we can let operand1 = +如果我们 let operand1 = + +1240 +00:51:18,890 --> 00:51:20,756 +op1Evaluation.result. +op1Evaluation.result + +1241 +00:51:20,758 --> 00:51:23,625 +'Kay, then we got op1, that's good. +我们就得到了 op1,还不错 + +1242 +00:51:23,627 --> 00:51:27,262 +So now let's let op2Evaluation = +现在我们再 let op2Evaluation = + +1243 +00:51:27,264 --> 00:51:32,600 +evaluation(op1Evaluation.remainingOps). +evaluation(op1Evaluation.remainingOps) + +1244 +00:51:32,602 --> 00:51:36,370 +'Kay? + +1245 +00:51:36,371 --> 00:51:40,139 +And if we can let operand, oops, if we can let operand2 +如果在这里 let operand2 + +1246 +00:51:40,142 --> 00:51:44,844 += op2Evaluation.result, += op2Evaluation.result, + +1247 +00:51:44,846 --> 00:51:50,716 +then we can return (operation(operand1, operand2). +然后 return (operation(operand1, operand2) + +1248 +00:51:50,718 --> 00:51:53,185 +'Kay? + + +1249 +00:51:53,186 --> 00:51:55,653 +And we'll have op2Evaluation.remainingOps +接着把 op2Evaluation.remainingOps + +1250 +00:51:55,656 --> 00:51:57,355 +as our remaining ops. +作为余下的 ops + +1251 +00:51:57,357 --> 00:52:00,825 +Okay? + + +1252 +00:52:00,827 --> 00:52:01,692 +Make sense? +明白了吗 + +1253 +00:52:01,694 --> 00:52:02,426 +All right. +好的 + +1254 +00:52:02,428 --> 00:52:03,159 +We have an error here. +哦,出现了个 error + +1255 +00:52:03,161 --> 00:52:04,560 +What is it? +看看它错哪了 + +1256 +00:52:04,562 --> 00:52:05,695 +Okay. +我明白了 + +1257 +00:52:05,696 --> 00:52:06,829 +Yeah, this is a good error to cover here. +这个 error 值得一讲 + +1258 +00:52:06,831 --> 00:52:09,665 +See this it says method must be declared private +看这,它说函数必须被声明为 private + +1259 +00:52:09,667 --> 00:52:12,501 +because this parameter uses a private type. +因为它的参数使用了 private 类型 + +1260 +00:52:12,503 --> 00:52:16,137 +And sure enough op is private so this has to be private. +显然由于 op 是 private 的,这个函数也得是 private 的 + +1261 +00:52:17,740 --> 00:52:19,273 +'Kay? + +1262 +00:52:20,476 --> 00:52:21,875 +Now notice by the way, +注意 + +1263 +00:52:21,877 --> 00:52:28,080 +I don't have default: break here in this switch. +这个 switch 我没有写 default: break + +1264 +00:52:28,082 --> 00:52:30,215 +And why do I not have that? +我之所以没写 + +1265 +00:52:30,217 --> 00:52:33,418 +Because I've handled every possible value of op. +是因为我已经处理了 op 的每一个可能的情形 + +1266 +00:52:35,088 --> 00:52:35,986 +'Kay? + + +1267 +00:52:35,988 --> 00:52:37,254 +There are only three kinds of op. +这里只有三种 op + +1268 +00:52:37,256 --> 00:52:38,522 +I've handled them all. +每一种我都处理过了 + +1269 +00:52:38,524 --> 00:52:40,374 +So I don't need any default. +所以就不需要 default 了 + +1270 +00:52:40,375 --> 00:52:42,225 +It wasn't like in the other one where we had a String and +这不像上一个处理 String 的 switch + +1271 +00:52:42,227 --> 00:52:44,761 +we only handle a few Strings, we had a default break. +我们只处理了几个 String,所以需要写 default: break + +1272 +00:52:44,763 --> 00:52:47,863 +You don't put default break in when you handle every thing. +如果能处理完所有情况,就不需要 default: break 了 + +1273 +00:52:47,865 --> 00:52:49,598 +And it's really bad programing style to +而且在每一个 switch 后面都放一个 default: break + +1274 +00:52:49,600 --> 00:52:51,633 +put a default break in every single switch. +是一种很不好的编程风格 + +1275 +00:52:51,635 --> 00:52:54,903 +'Kay, you should only put them in the ones where you +除非你真的没法处理所有的情况 + +1276 +00:52:54,905 --> 00:52:58,373 +truly are breaking because you can't handle every case. +必须得要一个 break 才行 + +1277 +00:52:58,375 --> 00:53:00,574 +'Kay? All right. +好的我们继续。 + +1278 +00:53:00,576 --> 00:53:03,844 +Now, the last thing we have to do is just call this recursive +那么最后要做的 + +1279 +00:53:03,846 --> 00:53:06,113 +version from here. +就是调用这个递归 + +1280 +00:53:06,115 --> 00:53:08,782 +And I'm gonna call this one and +这次调用它来获取 Tuple 值的方式 + +1281 +00:53:08,784 --> 00:53:11,117 +get these Tuple values a little differently. +略有不同 + +1282 +00:53:11,119 --> 00:53:12,718 +I'm not gonna call it in the same way here. +我不会像上次那么调用 + +1283 +00:53:12,720 --> 00:53:14,920 +I'm not gonna say, let something equal. +我不会写 let XX = XX 这种 + +1284 +00:53:14,922 --> 00:53:20,091 +Instead I'm gonna say let a Tuple which has let's call it +我会 let 一个 Tuple , + +1285 +00:53:20,093 --> 00:53:24,062 +say (result, remainder) = evaluate +比如 (result, remainder) = evaluate + +1286 +00:53:24,064 --> 00:53:28,666 +and I'm gonna pass my whole (opStack) here, Okay. +我要把整个 opStack 传进去 + +1287 +00:53:28,668 --> 00:53:31,668 +So this is a different way to call a function that returns +这里就是调用能返回 Tuple 的函数的不同方法 + +1288 +00:53:31,670 --> 00:53:35,305 +a Tuple here you actually let a Tuple equal the result. +其实是令一个 Tuple 等于函数的返回值 + +1289 +00:53:35,307 --> 00:53:37,974 +Instead of letting a single thing equal result and +而不是让一个单独的东西等于返回值再 + +1290 +00:53:37,976 --> 00:53:42,111 +then using the dots to get it, you let the Tuple equal it and +使用 . 来获取元素,你是令 Tuple 等于后面这些 + +1291 +00:53:42,113 --> 00:53:45,547 +notice that these names don't have to be the same as these +顺便注意这些名字并不必须和上面这些相同 + +1292 +00:53:45,549 --> 00:53:48,283 +names so result is the same, but here I +两个 result 是一样的,但是这里 + +1293 +00:53:48,285 --> 00:53:52,286 +use the word remainder instead of the word remainingOps. +我用了 remainder 而没有用 remainingOps + +1294 +00:53:52,288 --> 00:53:53,754 +Okay they do not have to be the same. +它们不必相同 + +1295 +00:53:55,024 --> 00:54:00,694 +And then here we just return our result. +在这里,返回我们的结果 + +1296 +00:54:00,696 --> 00:54:02,261 +Okay? + +1297 +00:54:02,263 --> 00:54:04,163 +So we learned a lot right there, Okay. +在这我们讲了很多 + +1298 +00:54:04,165 --> 00:54:05,297 +We learned about Tuple, +我们讲了 Tuple + +1299 +00:54:05,299 --> 00:54:08,033 +passing, you know, things back Tuples in +讲了通过不同的方法获取 Tuple + +1300 +00:54:08,035 --> 00:54:13,237 +different ways, you know, how to ignore things in enums, and, +以及要得到所需的值或者其他的东西的时候 + +1301 +00:54:13,239 --> 00:54:15,106 +when we're getting associate values, all that stuff. +如何在 enum 里忽略一些东西 + +1302 +00:54:15,108 --> 00:54:16,974 +So hopefully, you got all that. +希望你们都掌握了 + +1303 +00:54:16,976 --> 00:54:19,676 +I see a few people still kinda catching up on their typing. +我看到有些同学仍然在忙着敲代码 + +1304 +00:54:19,678 --> 00:54:21,444 +So I'll break for second here. +那我就暂时等你们一下 + +1305 +00:54:21,446 --> 00:54:24,480 + + +1306 +00:54:24,482 --> 00:54:27,283 +So that's it that's the entire implementation of +这就是我们计算器的 calculator brain + +1307 +00:54:27,285 --> 00:54:28,384 +our calculator brain. +全部的实现过程 + +1308 +00:54:28,386 --> 00:54:30,919 +It wasn't really that bad actually, right? +其实它并没有那么难理解,对吗? + +1309 +00:54:30,921 --> 00:54:33,722 +Pretty simple little data structure here. +很简单的数据结构 + +1310 +00:54:33,724 --> 00:54:36,858 +Just have to say what our known ops are. +只需要说清我们要用哪些 ops + +1311 +00:54:36,860 --> 00:54:38,726 +And have this recursion which you know, +再加上这个递归 + +1312 +00:54:38,728 --> 00:54:42,196 +actually is quite simple, powerful code. +这其实就是一段简单而功能强大的代码 + +1313 +00:54:42,198 --> 00:54:44,031 +If you're not comfortable with your recursion +如果你不明白这个递归 + +1314 +00:54:44,033 --> 00:54:46,533 +I can see how it might be a little bit disturbing. +我也知道它确实有些地方有点烦人 + +1315 +00:54:46,535 --> 00:54:48,301 +But go stare at it for a while +但如果你多看看这段代码 + +1316 +00:54:48,302 --> 00:54:50,068 +and you'll, you'll get it, how it works. +你就会明白它的原理了 + +1317 +00:54:50,071 --> 00:54:51,921 +Okay. + +1318 +00:54:51,922 --> 00:54:53,772 +So, now that we've got this new calculator brain, +既然我们已经有了这个新的 calculator brain + +1319 +00:54:53,775 --> 00:54:57,509 +we have to use it in our old Controller. +我们得把它用在之前的 Controller 上 + +1320 +00:54:57,511 --> 00:54:59,678 +Okay, yeah question? +说你的问题 + +1321 +00:54:59,679 --> 00:55:01,846 +- Do we have to let the opStack equal the remainder? +- 我们必须得让 opStack 等于 remainder 吗? + +1322 +00:55:01,848 --> 00:55:04,549 +Do we have to let the opStack equal the remainder? +我们是不是得让 opStack 等于 remainder + +1323 +00:55:04,551 --> 00:55:05,349 +Here, you mean? +你是说这段代码吗? + +1324 +00:55:05,351 --> 00:55:05,916 +- Yeah. +- 是的! + +1325 +00:55:07,119 --> 00:55:08,418 +well, we're not gonna use remainder, so +嗯,我们不必让它等于 remainder + +1326 +00:55:08,420 --> 00:55:10,620 +actually, even I could put I don't care here. +实际上,这个 remainder 甚至可以写成 ‘I don't care’ + +1327 +00:55:10,622 --> 00:55:13,255 +I only put that remainder there to show you could have +我在这用 remainder 只是想让你们知道 + +1328 +00:55:13,257 --> 00:55:15,257 +a different name, but I'm not using the remainder. +你可以起一个不同的名称,我实际没有使用 remainder 这个变量 + +1329 +00:55:15,259 --> 00:55:16,892 +I only want the result. You see. +我只需要一个结果。你看这(被学生打断) + +1330 +00:55:16,894 --> 00:55:19,861 +- Won't the opStack contain +- 在你计算 opStack 之前, + +1331 +00:55:19,862 --> 00:55:22,829 +- what was previously in it before you evaluate it? +- 它不包含原先在它里面的东西吗? + +1332 +00:55:22,832 --> 00:55:25,016 +Yes, the opStack will be +是的,但是这不会影响到 opStack + +1333 +00:55:25,017 --> 00:55:27,201 +unaffected by this because opStack is an array. +因为它是一个数组 + +1334 +00:55:27,203 --> 00:55:28,702 +Arrays are passed by value so +数组是通过值传递的, + +1335 +00:55:28,704 --> 00:55:30,837 +a copy of it gets passed into here. +它的一个 copy 被传递到这里 + +1336 +00:55:30,839 --> 00:55:33,506 +So this would be untouched and which is what I want. +所以它不会改变,这正是我想要的 + +1337 +00:55:33,508 --> 00:55:36,242 +I don't want evaluate to consume my opStack. +我不想 evaluate 方法耗尽我的运算栈 + +1338 +00:55:36,244 --> 00:55:38,010 +I wanna be able to call evaluate over and +我希望它一遍又一遍的 + +1339 +00:55:38,012 --> 00:55:38,744 +over and over. +调用 evaluate + +1340 +00:55:38,746 --> 00:55:39,945 +'Kay? Especially if, +明白了吗?尤其是假如 + +1341 +00:55:39,947 --> 00:55:43,581 +I, let's say, introduced variable operands and, +我引入变量操作数, + +1342 +00:55:43,583 --> 00:55:45,550 +hint that's what you're homeworks gonna be, then I wouldn't +提示你们下这个会留给你们当作业, + +1343 +00:55:45,552 --> 00:55:47,685 +want to change the variables to different things and +而且我不想改变这些变量 + +1344 +00:55:47,687 --> 00:55:49,520 +be calling it over and +然后通过不同的值,比如变量 + +1345 +00:55:49,521 --> 00:55:51,354 +over with different values for the variable for example and +一直调用它 + +1346 +00:55:51,357 --> 00:55:53,690 +then maybe next week I can have an assignment where I'm +也许下周我会布置这么一个任务, + +1347 +00:55:53,692 --> 00:55:57,894 +gonna make you graph such a thing, which I'm going to do. +让你们就画这样的东西,我会布置给你们的 + +1348 +00:55:57,896 --> 00:55:59,012 +Okay? + +1349 +00:55:59,013 --> 00:56:00,129 +So that's why I wanna do that. +这就是我为什么想这么做 + +1350 +00:56:00,131 --> 00:56:02,131 +So anyway, yeah, remainder here can just be anything. +总而言之,这个 remainder 你想怎么写都行 + +1351 +00:56:02,133 --> 00:56:03,532 +I'm actually gonna put this here because we're +实际上,我这么写 + +1352 +00:56:03,534 --> 00:56:05,300 +gonna println this in a second just so +是想一会 println 它 + +1353 +00:56:05,302 --> 00:56:06,567 +we can get a better look at what's going on. +这样我们就可以明白它内部是如何运行的 + +1354 +00:56:06,569 --> 00:56:10,904 +But first, let's go back to our Controller and use this +接着,回到我们的 Controller + +1355 +00:56:10,906 --> 00:56:14,007 +CalculatorBrain, this nice Model we just invented. +用 CalculatorBrain 这个刚刚建立的不错的 Model + +1356 +00:56:14,009 --> 00:56:15,842 +Let's use it. Now, +我们现在就把它用上 + +1357 +00:56:15,843 --> 00:56:17,676 +I'm gonna show you how to get two things on screen at +我先教你们怎样让这两个页面同时 + +1358 +00:56:17,679 --> 00:56:18,644 +the same time. +显示在你的屏幕上 + +1359 +00:56:18,646 --> 00:56:20,880 +That aren't necessarily directly related. +它们之间不一定要直接相关 + +1360 +00:56:20,882 --> 00:56:23,549 +Before we have the Storyboard and then I went up and +之前我们用 Storyboard 的时候,移动鼠标 + +1361 +00:56:23,551 --> 00:56:25,784 +clicked this Assistant Editor right here and +点击右上角的 Assistant Editor 按钮 + +1362 +00:56:25,786 --> 00:56:27,319 +it showed me the Controller. +它显示的是一个对应的 Controller + +1363 +00:56:27,320 --> 00:56:28,853 +Because the Assistant Editor figured out that, oh, +那是因为 Assistant Editor 这个编辑模块认为 + +1364 +00:56:28,855 --> 00:56:30,388 +if you have the Storyboard up you probably want +如果打开了 Storyboard,那么你可能想要打开 + +1365 +00:56:30,390 --> 00:56:33,257 +the Controller for the scene you have selected. +你选择的那个事件的 Controller + +1366 +00:56:33,259 --> 00:56:34,992 +But here it's like, I don't know what to show you. +但是现在,这里没啥能显示的 + +1367 +00:56:34,994 --> 00:56:36,827 +So I'm gonna show you a different way to +现在我教教你们别的方法 + +1368 +00:56:36,829 --> 00:56:39,229 +get something in here, two ways actually. +来显示控制器界面,实际上是两种方法 + +1369 +00:56:39,231 --> 00:56:41,931 +One is if you go to this top bar where +看没看见 top bar 上 + +1370 +00:56:41,933 --> 00:56:44,667 +it says counterparts, you can mouse down and +counterparts 这个选项, + +1371 +00:56:44,669 --> 00:56:47,603 +you can find all kinds of things about this +点击它你会发现更多选项 + +1372 +00:56:47,605 --> 00:56:50,272 +like subclasses of this class on the left. +比如左边代码这个类的子类 + +1373 +00:56:51,341 --> 00:56:54,642 +Superclasses of this class on the left. +这个类的父类 + +1374 +00:56:54,644 --> 00:56:57,111 +Of course it has no superclasses or subclasses. +当然了,它没有任何子类或者父类 + +1375 +00:56:57,113 --> 00:57:00,547 +But other things, things it includes are included by it. +还有其他的选项,比如它包含或包含它的一些文件 + +1376 +00:57:00,549 --> 00:57:02,115 +You can also just manually go in. +你也可以手动去找 + +1377 +00:57:02,117 --> 00:57:03,283 +We can go over here for example and +比如我们可以在里面浏览 + +1378 +00:57:03,285 --> 00:57:06,152 +find our ViewController and load it up that way, but +找到我们想要的 ViewController,并且打开它 + +1379 +00:57:06,154 --> 00:57:09,088 +I'm gonna show you a different way than doing that +先不要点,我给你们展示下第二种方法 + +1380 +00:57:09,090 --> 00:57:11,423 +which is to go over here to your navigator. +首先打开左侧的导航条, + +1381 +00:57:11,425 --> 00:57:14,893 +If you hold down Option and press on +按住 Option 键,同时点击 + +1382 +00:57:14,895 --> 00:57:18,663 +a file like ViewController it will appear on the right. +一个文件,比如这个 ViewController,它就会显示在右边 + +1383 +00:57:18,665 --> 00:57:20,464 +'Kay? + + +1384 +00:57:20,466 --> 00:57:22,866 +So Option clicking in here is another good way to +按Option + 左键也能非常方便地把 + +1385 +00:57:22,868 --> 00:57:23,767 +put things on the right. +东西在右边打开 + +1386 +00:57:25,437 --> 00:57:27,320 +Okay? + +1387 +00:57:27,321 --> 00:57:29,204 +So now here we have our CalculatorBrain on the left +现在 CalculatorBrain 显示在左边, + +1388 +00:57:29,207 --> 00:57:31,040 +and we have our Controller on the right, +同时 Controller 显示在我们的右边 + +1389 +00:57:31,042 --> 00:57:34,943 +we are going to rip out all of the stuff in our +我们将删掉 Controller 里 + +1390 +00:57:34,945 --> 00:57:39,180 +Controller that had to do with being calculator. +那些以前写的计算用的代码 + +1391 +00:57:39,182 --> 00:57:41,716 +Okay, so that's all this stuff right in here. +那么要删的就是这些 + +1392 +00:57:41,718 --> 00:57:43,484 +'Kay. + +1393 +00:57:43,485 --> 00:57:45,251 +All this calculating stuff, we don't need any of this +这些计算用的代码我们再也不需要了, + +1394 +00:57:45,254 --> 00:57:47,254 +because those were only called from there. +因为那些代码只在刚删掉那调用 + +1395 +00:57:47,256 --> 00:57:49,022 +'Kay, so our Controller's getting quite simple, +我们的 Controller 变得更简洁了, + +1396 +00:57:49,024 --> 00:57:50,757 +our Controller hardly has anything left in it. +几乎没剩下什么了 + +1397 +00:57:50,759 --> 00:57:54,727 +And that's because the UI only needs this to be controlled. +因为要想控制 UI 有这些就够了 + +1398 +00:57:54,729 --> 00:57:56,579 +'Kay? + +1399 +00:57:56,580 --> 00:57:58,430 +We also don't need our operandStack because the brain is +我们也不需要我们 operandStack,因为 brain + +1400 +00:57:58,432 --> 00:58:00,766 +gonna do that. +会处理这些东西 + +1401 +00:58:00,767 --> 00:58:03,101 +However, we do need a new instance variable here +但是这里得有一个新的实例变量 + +1402 +00:58:03,103 --> 00:58:04,903 +which is the CalculatorBrain. +就是 CalculatorBrain + +1403 +00:58:05,905 --> 00:58:07,838 +Okay I'm just gonna create one like that, +我将会定义一个像那样的实例变量 + +1404 +00:58:07,840 --> 00:58:12,676 +this is extremely common, Okay? this is +这是非常常见的, + +1405 +00:58:12,678 --> 00:58:16,680 +the green arrow that goes from the Controller to the Model. +这是之前讲 MVC 时候说到的从 Controller + +1406 +00:58:16,682 --> 00:58:18,948 +Remember that in our MVC talk that I did last time I +指向 Model 那个绿色箭头 + +1407 +00:58:18,950 --> 00:58:21,584 +said that the Controller has a green arrow to the Model, +还记得 Controller 有个绿色的箭头指向 Model 吗 + +1408 +00:58:21,586 --> 00:58:24,386 +it can talk to it all it wants, say anything it wants. +Controller 可以给 Model 传递任何它想传递的信息 + +1409 +00:58:24,388 --> 00:58:26,922 +This is essentially that green arrow. +这段代码本质上来说就是那个绿色箭头 + +1410 +00:58:26,924 --> 00:58:29,591 +This is our Model right here. +这是我们的 Model + +1411 +00:58:29,593 --> 00:58:31,592 +And this is the Controller this is how the Controller +这是 Controller,这就是 Controller 怎样 + +1412 +00:58:31,594 --> 00:58:33,661 +talks to it, through this thing we call the brain. +跟 Model 对话,通过我们称之为 brain 的这个东西 + +1413 +00:58:33,663 --> 00:58:35,562 +Thing you can call it anything you want and +这个 brain 你想怎么给他命名都行 + +1414 +00:58:35,564 --> 00:58:38,298 +of course this might be much more complicated green arrow, +当然了,这个绿色箭头可以表示相当复杂的东西 + +1415 +00:58:38,300 --> 00:58:40,767 +it might be a network database that is connecting to you to +它可能代表一个网络数据库, + +1416 +00:58:40,769 --> 00:58:41,934 +get the data. +你可以和它进行链接并获取数据 + +1417 +00:58:41,936 --> 00:58:43,102 +Okay? + +1418 +00:58:43,104 --> 00:58:45,671 +But in our case it's this very simple little brain. +但是在我们的例子中这是一个十分简单的小 brain + +1419 +00:58:45,673 --> 00:58:47,206 +Okay. + +1420 +00:58:47,207 --> 00:58:48,740 +So now we don't need this either down here. +我们也不需要下面这些代码了 + +1421 +00:58:48,742 --> 00:58:51,343 +This is where we're appending onto the opStack and +这是我们往 opStack 添加东西以及 + +1422 +00:58:51,345 --> 00:58:52,044 +printing it out. +把 opStack 打印出来的地方 + +1423 +00:58:52,045 --> 00:58:52,744 +So we don't need that. +我们也不需要这些 + +1424 +00:58:52,746 --> 00:58:57,548 +But we do need an enter() to push the operand onto +但是我们确实需一个 enter() + +1425 +00:58:57,550 --> 00:58:58,615 +the stack. +来把 operand 压到栈里 + +1426 +00:58:59,718 --> 00:59:00,516 +Okay. + +1427 +00:59:00,518 --> 00:59:03,519 +So here I'm just gonna say, +在这 + +1428 +00:59:03,521 --> 00:59:08,657 +that I'm gonna say I'm just gonna +我准备写 + +1429 +00:59:08,659 --> 00:59:13,561 +say brain.pushOperand(displayValue). +brain.pushOperand(displayValue) + +1430 +00:59:13,563 --> 00:59:15,413 +'Kay? + +1431 +00:59:15,414 --> 00:59:17,264 +That's the main thing I need to do, it's just do that. +这是我主要要做的,就这么做就好 + +1432 +00:59:17,266 --> 00:59:21,902 +One thing though is, I also need to update my display. +接下来我就需要更新 display 了 + +1433 +00:59:21,904 --> 00:59:23,870 +Because when I push this operand, +因为当我往栈里压这个 operand 时 + +1434 +00:59:23,872 --> 00:59:25,672 +that's gonna change the brain. +它会改变 brain + +1435 +00:59:25,674 --> 00:59:28,341 +I need to call that evaluate, right? +我需要调用那个 evaluate ,对吧? + +1436 +00:59:28,343 --> 00:59:29,442 +And get the value. +再得到它的值 + +1437 +00:59:29,443 --> 00:59:30,542 +So I could call evaluate here, but +我确实可以在这里调用 evaluate 但是 + + +1438 +00:59:30,544 --> 00:59:34,613 +actually, I'm gonna go back to my brain, and I'm gonna change +实际上我们再看下 brain ,我将会改变 + +1439 +00:59:34,615 --> 00:59:39,484 +pushOperand to return the result of evaluating. +pushOperand 让它返回 evaluating 的结果 + +1440 +00:59:39,486 --> 00:59:42,486 +Typing today. +今天这字打的 + +1441 +00:59:43,789 --> 00:59:46,623 +From it, from its, from internally, so +从它的内部 + +1442 +00:59:46,625 --> 00:59:48,991 +I'm gonna return evaluate here. +evaluate 在这里返回 + +1443 +00:59:48,993 --> 00:59:50,593 +So that every time you push an operand, +所以每次你往栈里压一个 operand + +1444 +00:59:50,595 --> 00:59:52,127 +it'll just return the evaluation. +它就会返回一个计算结果 + +1445 +00:59:52,129 --> 00:59:55,163 +Now one could argue whether this is the best thing to do. +现在有人或许会质疑这种方法是不是最好的 + +1446 +00:59:55,165 --> 00:59:57,932 +Because, you know, you might not be interested in +因为,你现在可能不会对 + +1447 +00:59:57,934 --> 01:00:00,568 +the result of evaluating that right now. +计算的结果感兴趣 + +1448 +01:00:00,570 --> 01:00:03,671 +But it kind of feels to me kind of good. +但我感觉蛮好的 + +1449 +01:00:03,673 --> 01:00:05,339 +And it's not gonna be, +而且 + +1450 +01:00:05,341 --> 01:00:07,341 +there's not gonna be that many things on the stack. +也不会有很多东西在栈上 + +1451 +01:00:07,343 --> 01:00:10,143 +You're not gonna usually have calculator brain +因为通常你的 calculator brain 不会有 + +1452 +01:00:10,145 --> 01:00:12,712 +have 1,000 operations and operands, although you could. +上千个操作符和操作数,虽然理论上可以这样 + +1453 +01:00:12,714 --> 01:00:14,013 +But you're not usually going to, so +但是你通常不会那样做 + +1454 +01:00:14,015 --> 01:00:16,548 +it's probably not a performance issue. +所以只返回这个应该不会是一个性能问题 + +1455 +01:00:16,550 --> 01:00:19,751 +To have it just return this and it'll make caller's code, +而且可以使调用部分的代码 + +1456 +01:00:19,753 --> 01:00:22,320 +you know, look a little simpler. +看起来简单些 + +1457 +01:00:22,322 --> 01:00:24,522 +And if they don't want this return value, +如果它们不想要这个返回值 + +1458 +01:00:25,858 --> 01:00:27,808 +then they can just ignore it. +它们可以直接忽略它 + +1459 +01:00:27,809 --> 01:00:29,759 +They don't have to use it but I am gonna use it. +它们没有必要用它,但我要用到 + +1460 +01:00:29,762 --> 01:00:31,495 +So, when I push this operand right here, +那么当我在这里将 operand 压栈 + +1461 +01:00:31,497 --> 01:00:35,798 +I'm gonna say, I'm gonna if let the results equal that. +我打算这样写 if let result = 后面这些代码 + +1462 +01:00:36,734 --> 01:00:38,000 +Okay, because it's an Optional. +它是 Optional 的 + +1463 +01:00:39,036 --> 01:00:41,836 +And if it's not nil then I'm gonna +如果它不是 nil,我就可以 + +1464 +01:00:41,838 --> 01:00:43,671 +set the displayValue to the result. +把 result 的值赋给 displayValue + +1465 +01:00:43,673 --> 01:00:46,140 +So in other words, every time I push an operand, +因此换句话说每次我往栈里压一个 operand + +1466 +01:00:46,142 --> 01:00:49,343 +I'm gonna up my displayValue with the evaluation. +我将会把计算结果赋给我的 displayValue + +1467 +01:00:49,345 --> 01:00:50,811 +Make sense? +能理解吗? + +1468 +01:00:50,813 --> 01:00:53,446 +Okay, what if this comes back nil? +如果它是 nil 的话该怎么办? + +1469 +01:00:54,982 --> 01:00:56,615 +So, I push something on, +我会往栈里压一些东西 + +1470 +01:00:56,617 --> 01:00:59,151 +this is not gonna happen probably with pushOperand(), +但这里应该不是调用 pushOperand() + +1471 +01:00:59,153 --> 01:01:02,587 +but it might, and after your homework it might. +但也有可能是 nil, 在你们做过作业之后,可能会是 + +1472 +01:01:02,589 --> 01:01:04,022 +So, what if I push and it comes back nil? +所以,当我往栈里压并且返回是 nil 的时候怎么办? + +1473 +01:01:04,024 --> 01:01:07,258 +Well, now I'm kinda stuck, Okay? +呵呵,现在我被难倒了 + +1474 +01:01:07,260 --> 01:01:10,728 +This is why, in your homework assignment, I suggested, wow +所以在你们的家庭作业中,我建议, + +1475 +01:01:10,730 --> 01:01:13,730 +wouldn't it be cool if displayValue took an Optional. +如果 displayValue 是 Optional 该多好 + +1476 +01:01:15,100 --> 01:01:17,600 +Right, if displayValue took and returned an Optional. +对吧,如果 displayValue 是 Optional 并返回一个 Optional + +1477 +01:01:17,602 --> 01:01:20,769 +You could put something sensible in the display when +当你有一些你无法计算的东西, + +1478 +01:01:20,771 --> 01:01:23,605 +you had something that couldn't be evaluated. +你可以放一些合理的东西在你的 display 中 + +1479 +01:01:23,607 --> 01:01:25,874 +So in assignment two making displayValue into +所以在作业二中让 displayValue 是 Optional + +1480 +01:01:25,876 --> 01:01:27,809 +an Optional is gonna be required task. +将会是要求之一 + +1481 +01:01:27,811 --> 01:01:29,977 +So you might as well do it for homework one, +你也可以在作业一中这样做 + +1482 +01:01:29,979 --> 01:01:33,447 +cuz you're gonna have to do it for homework two anyway. +因为你反正都要在作业二中这么做 + +1483 +01:01:33,449 --> 01:01:35,182 +Okay. + +1484 +01:01:35,183 --> 01:01:36,916 +Just wanted to give you more time because I didn't +我只是想多给你们点时间 + +1485 +01:01:36,917 --> 01:01:38,650 +really teach you the things about NumberFormatter and +因为我没有在布置作业一之前 + +1486 +01:01:38,653 --> 01:01:41,320 +stuff in time for assignment one. +完整地教你们关于有关 NumberFormatter 的知识 + +1487 +01:01:41,322 --> 01:01:44,623 +But it's going to be required and that's because the best I +但是这将会是硬性要求,因为我最多只能告诉你们 + +1488 +01:01:44,625 --> 01:01:48,093 +can do here is maybe say displayValue equals zero. +令 displayValue 的值为 0 + +1489 +01:01:48,095 --> 01:01:50,962 +That's really lame but that's the best I can do. +那真的没什么道理,但是那是我也只能这样了 + +1490 +01:01:50,964 --> 01:01:54,432 +I really wanna say, displayValue was nil, Okay. +我也蛮想令 displayValue 为 nil 的 + +1491 +01:01:54,434 --> 01:01:56,634 +I really just wanna set displayValue equal to +我真的只想把 displayValue 等于 + +1492 +01:01:56,636 --> 01:01:58,953 +the result of this. +这段代码的结果 + +1493 +01:01:58,954 --> 01:02:01,271 +And I wanna have nil, you know, clear out my display or +我想设为 nil, 清除我的 display 或者 + +1494 +01:02:01,274 --> 01:02:02,606 +in assignment two, +在作业二中作为一个加分项 + +1495 +01:02:02,608 --> 01:02:06,743 +extra credit, maybe it puts an error message in my display. +让它在我的 display 上显示一段错误提示信息也好 + +1496 +01:02:07,912 --> 01:02:09,545 +Now that's extra credit, but +现在那是加分项,但是 + +1497 +01:02:09,547 --> 01:02:11,246 +that would be an even better thing to put there. +显示这么一段错误提示信息应该会更好 + +1498 +01:02:12,216 --> 01:02:14,216 +Okay? + +1499 +01:02:14,217 --> 01:02:16,217 +But same thing for, for forming the operation. +但是形成运算也是一样的 + +1500 +01:02:16,219 --> 01:02:17,652 +Here's our operation right here. +这就是我们所做的操作 + +1501 +01:02:17,654 --> 01:02:21,005 +And I'm just gonna say, +我要说的是, + +1502 +01:02:21,006 --> 01:02:24,357 +if I can let the result equals brains.performOperation of +如果把 result 置为 brain.performOperation() + +1503 +01:02:24,360 --> 01:02:27,361 +the operation that I got off the button, then I'm going to +当松开按钮时, 那么 + +1504 +01:02:27,363 --> 01:02:29,963 +let my displayValue equal that result. +displayValue 应该等于之前所得的 result 值 + +1505 +01:02:31,366 --> 01:02:34,667 +Otherwise I'm going to do the very lame thing of +否则, 我们就要做一件很差劲的事 + +1506 +01:02:34,669 --> 01:02:38,904 +saying display value equals, whoops, value equals zero. +也就是将 displayValue 的值置为0. + +1507 +01:02:38,906 --> 01:02:40,389 +Okay? Unders, +明白了么?明…… + +1508 +01:02:40,390 --> 01:02:41,873 +people understand why that's kind of lame? +大家都明白为什么这么做很差劲了么? + +1509 +01:02:41,875 --> 01:02:43,240 +All right. +好的 + +1510 +01:02:45,644 --> 01:02:47,077 +Okay. + +1511 +01:02:47,079 --> 01:02:48,144 +So that's it. +至此, + +1512 +01:02:48,146 --> 01:02:49,812 +Look at how simple our Controller is here. +我们的 Controller 的实现非常简单 + +1513 +01:02:49,814 --> 01:02:52,481 +It has almost no code in it,Okay. +里面几乎没有代码 + +1514 +01:02:52,483 --> 01:02:54,550 +And that's really iOS is great about that. +这就是 iOS 开发的一个神奇之处 + +1515 +01:02:54,552 --> 01:02:56,885 +It really is pretty good about making it so +这是一个非常棒的体验, + +1516 +01:02:56,887 --> 01:02:58,920 +that you can build your UI mostly graphically so +你可以图形化的创建大部分 UI + +1517 +01:02:58,922 --> 01:03:01,923 +that there's very little code to control what's going on. +并且用非常少的代码来控制流程 + +1518 +01:03:01,925 --> 01:03:03,491 +And then even our Model, +对我们的模型来说, + +1519 +01:03:03,493 --> 01:03:05,759 +which is a pretty powerful calculator right now, +目前是一个功能非常强大的计算器, + +1520 +01:03:05,761 --> 01:03:07,961 +we could add as many functions as we wanted to. +我们可以随意添加各种方法 + +1521 +01:03:07,963 --> 01:03:09,963 +It's just one liners here. +只需要若干行代码 + +1522 +01:03:09,965 --> 01:03:13,766 +And it would be capable of,you know, evaluating any se, +它就可以计算任何 + +1523 +01:03:13,768 --> 01:03:15,334 +series of them that's evaluatable. +可计算的序列 + +1524 +01:03:15,336 --> 01:03:18,003 +And it's also set up to do your homework, Okay, +这也是你们的作业, + +1525 +01:03:18,005 --> 01:03:19,738 +which is to add those variables, +添加这些变量, + +1526 +01:03:19,740 --> 01:03:22,140 +to be able to push operand that are variables. +把操作符作为变量压栈 + +1527 +01:03:22,142 --> 01:03:25,309 +The other thing your homework is gonna ask you to do is to +另外一项作业需要你们做的是, + +1528 +01:03:25,311 --> 01:03:28,112 +eval, to draw this, Okay, +把这些公式的内容 + +1529 +01:03:28,114 --> 01:03:30,848 +the contents of it in a human readable form. +转换成可读的形式 + +1530 +01:03:30,850 --> 01:03:33,850 +Using infix notation like this with parentheses when +像这样用中缀法 + +1531 +01:03:33,852 --> 01:03:36,019 +necessary, things like that and +必要时配合括号使用等类似的方法 + +1532 +01:03:36,021 --> 01:03:37,820 +that's gonna be a lot easier here too. +有了之前的铺垫,这个作业相当容易完成 + +1533 +01:03:37,822 --> 01:03:39,055 +Cuz you can recur, +因为你可以 + +1534 +01:03:39,056 --> 01:03:40,289 +use recursion, use recursion to build this as well. +使用递归来解决这个问题 + +1535 +01:03:41,559 --> 01:03:43,725 +Okay, so that's the main two things of +这就是我们的作业里 + +1536 +01:03:43,727 --> 01:03:44,693 +your homework that's what they are. +所要解决的两个主要问题 + +1537 +01:03:44,695 --> 01:03:48,496 +All right, so let's see if we broke anything here, all right, +现在来看看我们有没有出错的地方 + +1538 +01:03:48,498 --> 01:03:50,064 +so we're gonna go up here and run. +单击此处运行, + +1539 +01:03:52,168 --> 01:03:53,834 +See if this all still works. +看是否仍然可以正常运行 + +1540 +01:03:53,836 --> 01:03:55,101 +Our UI has not changed. +我们的UI是没有变化的, + +1541 +01:03:55,103 --> 01:03:57,804 +You notice I never even opened the Storyboard here. +你们可能注意到我在这里从来没有打开过 Storyboard + +1542 +01:03:57,806 --> 01:03:59,005 +Didn't even open the Storyboard. +甚至没有打开过 Storyboard + +1543 +01:03:59,007 --> 01:04:01,607 +Okay all these changes were pushing things out of +所有这些变动 + +1544 +01:04:01,609 --> 01:04:03,175 +the Controller into the Model. +Controller 改变了, Model 随之改变 + +1545 +01:04:03,177 --> 01:04:04,510 +Okay?The co, +好的 + +1546 +01:04:04,511 --> 01:04:05,844 +communication between the Controller and +所以, Controller 和 View + +1547 +01:04:05,846 --> 01:04:08,012 +the View has not changed here. +之间的交互没有发生改变 + +1548 +01:04:08,014 --> 01:04:10,915 +So hopefully this is gonna work let's try 85, and +我们输入 85, 希望可以成功运行 + +1549 +01:04:10,917 --> 01:04:13,083 +our number entering is still working in +输入数字后,Controller 如期工作 + +1550 +01:04:13,085 --> 01:04:15,252 +our Controller that's good,Enter. +这是对的, + +1551 +01:04:15,254 --> 01:04:17,921 +Okay it still says 85 that's good, +好的,程序说明 85 是可以的 + +1552 +01:04:17,923 --> 01:04:22,224 +how about 41 plus seems to actually be working. +那么试一试 41 + , 没有问题 + +1553 +01:04:22,226 --> 01:04:23,325 +Square root, +开平方根, + +1554 +01:04:23,327 --> 01:04:26,861 +that's also working, nine times, excellent. +也没有问题, 再乘以 9, 非常好 + +1555 +01:04:26,863 --> 01:04:28,813 +That's working. +都可以得出正确结果 + +1556 +01:04:28,814 --> 01:04:30,764 +Now what if we do something that's not evaluatable? +现在,如果我们做一些不可计算的操作会怎样? + +1557 +01:04:30,767 --> 01:04:33,034 +I'm going to press times a whole bunch of times. +我输入很多个乘号, + +1558 +01:04:33,036 --> 01:04:33,901 +Right? Times, times. +乘,乘 + +1559 +01:04:33,903 --> 01:04:35,736 +Oh, times no, zero. +得出了 0 + +1560 +01:04:35,738 --> 01:04:37,404 +See that's not really great feedback. +可以看出这不是一个好的反馈 + +1561 +01:04:37,406 --> 01:04:41,207 +Okay? But, it's not really zero but +虽然结果不是 0,但是 + +1562 +01:04:41,209 --> 01:04:43,642 +it's, it's not good either. +也不是一个好的结果 + +1563 +01:04:43,644 --> 01:04:46,912 +So your homework is going to be printing out what's on +所以你们的作业是要 + +1564 +01:04:46,914 --> 01:04:48,747 +the stack in a nice form so +将栈中的内容,以一个合适的形式打印出来 + +1565 +01:04:48,749 --> 01:04:50,548 +you'll be able to see that you have times, times, +你们可以看到有很多乘号 + +1566 +01:04:50,550 --> 01:04:53,918 +times, and it's gonna equal a blank display. +将会得到一个空白输出 + +1567 +01:04:53,920 --> 01:04:56,353 +And that's gonna make sense that it's blank. +空白的输出是比较合理的 + +1568 +01:04:56,355 --> 01:04:57,020 +'Kay? +明白了么? + +1569 +01:04:57,022 --> 01:04:59,422 +All right. +好了 + +1570 +01:04:59,424 --> 01:05:01,724 +Now, I wanna do one other thing here, though, just so +现在,我要做另外一件事, + +1571 +01:05:01,726 --> 01:05:03,659 +you can really visualize what's going on, +让你们可以真正将整个过程视觉化 + +1572 +01:05:03,661 --> 01:05:05,561 +which is, I wanna print out, +那就是, + +1573 +01:05:05,563 --> 01:05:08,630 +when we evaluate, I wanna print out this stack. +在计算时,我会打印出这些栈 + +1574 +01:05:08,632 --> 01:05:10,265 +I wanna print out the thing we're evaluating, +我希望打印出我们在计算的东西 + +1575 +01:05:10,267 --> 01:05:12,934 +I wanna print out the result,and I even wanna print out +打印结果,甚至 + +1576 +01:05:12,936 --> 01:05:14,702 +the remainder here so we can see what's going on. +希望打印出栈里剩下的, 这样我们就可以看到整个流程 + +1577 +01:05:14,704 --> 01:05:17,471 +So, I wanna say println. +所以,使用 println 函数 + +1578 +01:05:17,473 --> 01:05:21,841 +And I'm gonna say I'm gonna use my backslash thing here. +在这里用一个反斜杠 + +1579 +01:05:21,843 --> 01:05:30,916 +opStack equals result with how did I say this? +opStack 等于 result 加上... 应该怎么说, + +1580 +01:05:30,918 --> 01:05:32,685 +With [NOISE], oh, yeah. +呃,对 + +1581 +01:05:32,687 --> 01:05:36,688 +With our remainder left over. +加上栈里剩下的元素 + +1582 +01:05:37,857 --> 01:05:39,507 +Okay. +好的 + +1583 +01:05:39,508 --> 01:05:41,158 +So wouldn't it be cool if I could just do this. +如果这样做,是不是很酷? + +1584 +01:05:41,160 --> 01:05:44,361 +Just say, Okay, the opStack evaluated equals this +opStack 等于 + +1585 +01:05:44,363 --> 01:05:47,064 +result with the remainder left over. +结果加上剩下的 remainder + +1586 +01:05:47,066 --> 01:05:47,897 +Okay? +好了吗? + +1587 +01:05:47,899 --> 01:05:48,765 +Let's run that. +我们运行程序, + +1588 +01:05:48,766 --> 01:05:49,632 +Do you think that's going to work? +你们认为程序会正常允许吗? + +1589 +01:05:51,302 --> 01:05:52,468 +Maybe.Let's see. +可能会,让我们来看看 + +1590 +01:05:52,470 --> 01:05:54,336 +[BLANK_AUDIO] + +1591 +01:05:54,338 --> 01:05:56,204 +Okay. +好的 + +1592 +01:05:56,205 --> 01:05:58,071 +So let's try putting eight on the stack. +我们试试把 8 放入栈中, + +1593 +01:05:59,709 --> 01:06:01,375 +Okay? + +1594 +01:06:01,376 --> 01:06:03,042 +Let's make so we can see this over here, where is it, +把窗口居中,这样看的更清楚 + +1595 +01:06:03,045 --> 01:06:06,213 +it's this probably right there, there it is. +大概在这个位置 + +1596 +01:06:06,215 --> 01:06:08,114 +We don't need that one Okay,so +我们不需要这个, 好 + +1597 +01:06:08,116 --> 01:06:11,117 +here is our Okay it's gonna be that, it's this. +这就是我们想要的结果 + +1598 +01:06:11,119 --> 01:06:16,288 +Okay, so it said here hm, enum value in, in an array, equals +这里写着,枚举值,在一个队列中, 等于 + +1599 +01:06:16,290 --> 01:06:21,860 +result of Optional(8), that's good, Optional(8) is good. +Optional(8),很好,Optional(8) 是一个正确的结果 + +1600 +01:06:21,862 --> 01:06:23,161 +With nothing left over. +同时栈里没有其他东西 + +1601 +01:06:23,163 --> 01:06:24,962 +Okay, that's good. +Okay,没有问题 + +1602 +01:06:24,964 --> 01:06:26,397 +Let's go 6, Enter. +点击 6,然后点击 Enter + +1603 +01:06:26,399 --> 01:06:30,734 +Oh, now we have enum enum on the stack equals Optional 6, +哦,现在我们的栈里有两个 enum 一个赋值为 Optional(6.0) + +1604 +01:06:30,736 --> 01:06:32,602 +with enum left over. +另一个为 enum + +1605 +01:06:32,604 --> 01:06:33,936 +Well that's not so good. +好吧,出问题了 + +1606 +01:06:33,938 --> 01:06:38,807 +Times enum, enum, enum equals it with, this is terrible. +点击 ×(乘号), enum, enum, enum 等于这个以及… 糟糕 + +1607 +01:06:38,809 --> 01:06:40,342 +This is, I can't understand what the heck is +这是怎么回事? + +1608 +01:06:40,344 --> 01:06:41,342 +going on here. +到底为什么会是这样? + +1609 +01:06:41,344 --> 01:06:42,943 +Why is this happening? +为什么会出现这些东西? + +1610 +01:06:42,945 --> 01:06:47,014 +Okay, when you put something in parentheses like this, +Okay, 在圆括号中使用类似这样的东西 + +1611 +01:06:47,016 --> 01:06:49,315 +it tries to convert it to a String. +编译器会试图将它转化为 String + +1612 +01:06:49,317 --> 01:06:51,718 +Okay, well the thing that's in here is an array. +但是括号里的代码却是一个 Array + +1613 +01:06:51,720 --> 01:06:54,520 +Arrays know how to convert themselves to Strings. +Array 知道怎么将自己转化为 String + +1614 +01:06:54,522 --> 01:06:57,623 +What they do is, they put open square bracket. +Array 所做的是,在最外层加上方括号 + +1615 +01:06:57,625 --> 01:07:00,759 +Then they ask every single thing in the array, +然后将 Array 里的所有元素 + +1616 +01:07:00,761 --> 01:07:04,462 +convert yourself to a String O'kay, and it puts them here. +转化为 String, 然后 Array 将转换后的元素放在方括号中 + +1617 +01:07:04,464 --> 01:07:07,298 +Well our op is converting itself to this String. +所以,op 将自己转化成了这个 String + +1618 +01:07:07,300 --> 01:07:10,334 +Enum Value 'kay? +Enum Value,看到没? + +1619 +01:07:10,336 --> 01:07:12,670 +That's because the system doesn't really know how to +这是因为编译器并不知道 + +1620 +01:07:12,672 --> 01:07:14,171 +convert it any other way so +怎么将它(op)转换为其他的类型 + +1621 +01:07:14,173 --> 01:07:15,872 +it's just saying that's an enum value. +编译器仅仅把它当作一个枚举类型来处理 + +1622 +01:07:15,874 --> 01:07:18,241 +It doesn't know how to convert itself to a String. +它(op)不知道怎么将自己转化为 String + +1623 +01:07:18,243 --> 01:07:20,376 +So, you see, see what's going on here? +现在,你们知道这是怎么回事了吗? + +1624 +01:07:20,378 --> 01:07:24,146 +So, I'm going to show you how to teach a type to +接下来,我将给你们示范怎么让一种类型 + +1625 +01:07:24,148 --> 01:07:26,381 +turn itself into a String. +将自己转换为 String 类型 + +1626 +01:07:26,383 --> 01:07:28,716 +Okay, cuz that's really valuable for debugging and +Okay,因为这对程序的调试来说,是非常有用的,而且 + +1627 +01:07:28,718 --> 01:07:30,651 +also might be valuable for your homework. +可能对你们的作业有很大的参考价值 + +1628 +01:07:33,756 --> 01:07:35,356 +So, how we gonna do that? +那么,该怎么做呢? + +1629 +01:07:35,357 --> 01:07:36,957 +All right, the way you do that is, +方法就是, + +1630 +01:07:36,959 --> 01:07:42,595 +you have to add a computed property to your type. +你需要为你的类型添加一个 computed property (计算属性) + +1631 +01:07:42,597 --> 01:07:44,730 +And enums, just like structs and +枚举、结构体和类一样 + +1632 +01:07:44,732 --> 01:07:47,599 +classes, can have properties,Okay? +也可以拥有属性,对么? + +1633 +01:07:47,601 --> 01:07:50,435 +Only computed properties in enums, structs and +只有在枚举、结构体和类 + +1634 +01:07:50,437 --> 01:07:53,104 +classes can have properties that are values. +中的 computed properties (计算属性)可以有带值的属性 + +1635 +01:07:53,106 --> 01:07:56,240 +Like these, like this over here, all right. +比如这个, + +1636 +01:07:56,242 --> 01:07:57,408 +But they can only be computed. +但是它们只能被计算 + +1637 +01:07:57,410 --> 01:08:00,344 +You remember a computed property looks like this, var. +一个 computed property (计算属性)应该是这样,var + +1638 +01:08:00,346 --> 01:08:01,929 +The name of it. +它的名字 + +1639 +01:08:01,930 --> 01:08:03,513 +It has to be called description because +它必须被称为 description,因为 + +1640 +01:08:03,515 --> 01:08:05,081 +it's gonna be a String description of it. +这将是计算属性(computed property)的文字描述 + +1641 +01:08:05,083 --> 01:08:07,517 +The type has to be String. +它的类型必须是 String 类型 + +1642 +01:08:07,519 --> 01:08:09,418 +It's a String description of it. +这个字符串是计算属性的一个文字描述 + +1643 +01:08:09,420 --> 01:08:12,588 +And then of course you want your get here. +然后,可以使用 get 方法 + +1644 +01:08:12,590 --> 01:08:18,360 +And, whoops, your get and your set set. +你们自己写的 get 方法和 set 方法 + +1645 +01:08:18,362 --> 01:08:21,896 +But it has to not only be a computed property. +但是它不可能仅仅只是一个 computed property + +1646 +01:08:21,898 --> 01:08:24,165 +This description thing to make this work. +为了让这个 description 起作用 + +1647 +01:08:24,167 --> 01:08:26,900 +It wants to be a read only one. +它需要是一个只读的属性 + +1648 +01:08:26,902 --> 01:08:28,068 +So we're not going to put the set, +所以,我们不要 set 方法, + +1649 +01:08:28,070 --> 01:08:29,769 +so there will be no set, just a get. +没有 set 方法,仅仅是一个 get 方法 + +1650 +01:08:30,805 --> 01:08:36,108 +So this get just has to return this op as a String, so +因此,这个 get 方法仅需将 op 作为 String 返回, + +1651 +01:08:36,110 --> 01:08:38,176 +I say someone turned it into a String. +所以说得有人将它转化为 String + +1652 +01:08:38,178 --> 01:08:40,045 +Well how would we turn our op into a String. +我们到底怎么将 op 转化为 String呢? + +1653 +01:08:40,047 --> 01:08:44,749 +Well for the operations we're just gonna return the symbol. +对于操作符,返回符号 + +1654 +01:08:44,751 --> 01:08:47,484 +Okay if this is a plus operation turning into +如果这是一个加法运算,将它转化 + +1655 +01:08:47,486 --> 01:08:49,052 +String is I'm just gonna return a plus, +为 String 的操作是返回 +(加号), + +1656 +01:08:49,054 --> 01:08:53,389 +cuz that pretty well describes a plus operation, a plus. +因为一个加号很好的描述了一个加法操作 + +1657 +01:08:53,391 --> 01:08:55,224 +For the operand, +对于操作数, + +1658 +01:08:55,225 --> 01:08:57,058 +I'm gonna have to turn this Double into a String. +我要将 Double 类型 转化为 String类型 + +1659 +01:08:57,061 --> 01:08:58,627 +And return that. +并返回这个 String + +1660 +01:08:58,629 --> 01:08:59,528 +Okay so how am I gonna do that? +怎么去实现这个转换呢? + +1661 +01:08:59,530 --> 01:09:03,131 +I'm gonna do that using switch, +可以使用 switch 来实现它 + +1662 +01:09:03,133 --> 01:09:05,867 +I need to switch on myself. +我需要把自己作为 switch 的参数 + +1663 +01:09:07,070 --> 01:09:09,837 +Okay cuz I'm gonna do this switch so that I can get these +因为我要用 switch ,所以, + +1664 +01:09:09,839 --> 01:09:12,939 +same things out here, and you do the same thing I did here, +相同的代码部分提取出来,你们跟着我做, + +1665 +01:09:12,941 --> 01:09:14,307 +see how I did this switch. +注意我怎么实现这个 switch + +1666 +01:09:14,309 --> 01:09:16,309 +So I could get these associated values out. +以便我可以获取这些相关的值 + +1667 +01:09:16,311 --> 01:09:18,177 +I'm gonna do the same thing here. +我将要在这里做相同的事情 + +1668 +01:09:18,179 --> 01:09:20,512 +So how do I switch on my self? +怎么把自己作为 switch 的参数呢? + +1669 +01:09:20,514 --> 01:09:23,415 +I say switch self. +那就是 switch self + +1670 +01:09:23,417 --> 01:09:24,716 +'Kay? +看到了没? + +1671 +01:09:24,718 --> 01:09:28,019 +And then I just have to say the case for Operand. +然后,我仅需要写下 Operand 的 case + +1672 +01:09:28,021 --> 01:09:29,987 +And I'll let that be the operand. +再写一句 let operand + +1673 +01:09:29,989 --> 01:09:33,657 +And I have to do the case for UnaryOperation. +然后,UnaryOperation 的 case + +1674 +01:09:33,659 --> 01:09:34,624 +Now when I do the case for +现在,当我处理 UnaryOperation 的 case 时, + +1675 +01:09:34,626 --> 01:09:37,493 +UnaryOperation, I want the symbol. +我需要符号 + +1676 +01:09:37,495 --> 01:09:40,529 +But I don't care about the function. +但是我并不关心实际的运算 + +1677 +01:09:40,531 --> 01:09:42,831 +Cuz I'm not actually gonna compute anything. +因为在这里我不会进行任何计算 + +1678 +01:09:42,833 --> 01:09:45,500 +I'm just going to return the symbol. +我只是返回符号 + +1679 +01:09:45,502 --> 01:09:47,469 +And then for BinaryOption same, same, Operation +BinaryOperation 也一样 + +1680 +01:09:47,471 --> 01:09:51,972 +same thing I want the symbol but I don't want this. +我仅需要符号,不需要这些 + +1681 +01:09:51,974 --> 01:09:53,307 +So that's the, the don't care. +所以,忽略这些东西 + +1682 +01:09:53,309 --> 01:09:55,609 +And what am I gonna do in each of these cases? +在每个 case 中我要做什么? + +1683 +01:09:55,611 --> 01:10:01,080 +Well in the operand case I'm gonna return a String that +在 operand 的 case 中,我将 + +1684 +01:10:01,082 --> 01:10:02,848 +is that operand. +返回这个操作数的 String + +1685 +01:10:02,850 --> 01:10:06,251 +Oops, don't like the way it puts that extra thing +Oops, 不喜欢编辑器在这里添加额外代码的方法 + +1686 +01:10:06,253 --> 01:10:06,985 +on there. +还有这里 + +1687 +01:10:06,987 --> 01:10:08,286 +Okay. + +1688 +01:10:08,287 --> 01:10:09,586 +And then in the UnaryOperation case I'm +在 UnaryOperation 的 case 中,我将 + +1689 +01:10:09,589 --> 01:10:11,522 +just gonna return the symbol. +返回符号 + +1690 +01:10:11,524 --> 01:10:13,390 +And in the BinaryOperation case I'm also just +在 BinaryOperation 的 case 中,因为我也只是 + +1691 +01:10:13,392 --> 01:10:14,224 +gonna return the symbol. +返回符号 + +1692 +01:10:14,226 --> 01:10:19,329 +And we have, oops, don't want the parentheses there. +那么…噢, 不需要这个括号 + +1693 +01:10:19,331 --> 01:10:22,965 +Kay and we've covered every case of this switch. +我们覆盖了 switch 的每一个 case + +1694 +01:10:22,967 --> 01:10:25,735 +So not only does it know that this switch is covered but +现在它(description)不仅知道这个 switch 覆盖了所有情况 + +1695 +01:10:25,737 --> 01:10:28,604 +it knows that we for sure have returned something out of +而且它知道我们肯定会从这里返回一些东西, + +1696 +01:10:28,606 --> 01:10:31,506 +here, because we only have one expression here which is +因为我们这里只有一个表达式,即 Swift(口误), 不, + +1697 +01:10:31,508 --> 01:10:34,909 +this Swift and switch and we know that covers every case. +switch,并且我们知道 switch 覆盖了所有 case + +1698 +01:10:34,911 --> 01:10:36,377 +So there goes so we have this nice description. +现在,我们有了一个很好的 description. + +1699 +01:10:36,379 --> 01:10:40,814 +Now this is not quite enough O'kay? +但是,这还不够, + +1700 +01:10:40,816 --> 01:10:42,916 +You have to implement this property, +比必须实现这个 property(属性), + +1701 +01:10:42,918 --> 01:10:44,784 +this computed property read-only. +这个 computed property 是只读的 + +1702 +01:10:44,786 --> 01:10:46,652 +But if you do one other thing, +但如果我们在这里 + +1703 +01:10:46,654 --> 01:10:50,456 +which is up here, you have to put, colon Printable. +放一个 : Printable + +1704 +01:10:51,859 --> 01:10:56,961 +Now, I told you enums and structs have no inheritance. +enum 和 struct 没有继承 + +1705 +01:10:56,963 --> 01:10:58,696 +So you're like what, wait a second, there. +等一下,看这里 + +1706 +01:10:58,698 --> 01:11:01,098 +You're telling me op inherits from Printable? +你竟然告诉我让 op 继承于 Printable? + +1707 +01:11:01,100 --> 01:11:04,234 +And the answer is no, does not inherit, Okay, it's an enum. +不是这样的,这里不是继承 + +1708 +01:11:04,236 --> 01:11:07,070 +Enums don't have any inheritance, only classes do. +enum 没有继承关系,只有 class 有 + +1709 +01:11:07,072 --> 01:11:10,540 +What this colon Printable means is, and +这个 : Printable 代表 + +1710 +01:11:10,542 --> 01:11:12,842 +this can be true for classes or structs or whatever. +这个也可以对 class 或者 struct 有效 + +1711 +01:11:12,844 --> 01:11:14,643 +You can put after the colon here. +在这里的冒号后面写 + +1712 +01:11:15,713 --> 01:11:17,979 +This is called a protocol. +这个叫做 protocol + +1713 +01:11:17,981 --> 01:11:21,215 +And all this means is you're telling Swift that this +这就代表,你告诉 Swift, + +1714 +01:11:21,217 --> 01:11:24,852 +enum implements whatever is in this protocol. +这个 enum 需要自己实现这个 protocol 的内容 + +1715 +01:11:24,854 --> 01:11:28,389 +And this protocol happens to just be one computed +这个 protocol 恰好有一个叫做 description 的 computed property + +1716 +01:11:28,391 --> 01:11:30,590 +property called Description that returns the String. +用来返回一个 String + +1717 +01:11:31,826 --> 01:11:33,326 +Okay? + +1718 +01:11:33,327 --> 01:11:34,827 +Now we're going to talk about protocols in depth. +我们会深入了解 protocol + +1719 +01:11:34,829 --> 01:11:37,062 +Because protocols are very important for +因为 protocol 能够帮助我们了解, + +1720 +01:11:37,064 --> 01:11:40,065 +explaining how things work 'kay? +这到底是怎么一回事儿 + +1721 +01:11:40,067 --> 01:11:43,501 +But we're not gonna cover it today, though. +但是我们今天不会讲 + +1722 +01:11:43,503 --> 01:11:46,204 +Okay, so if you do those two things, put description in +如果我这么做,加上 Printable + +1723 +01:11:46,206 --> 01:11:52,209 +Printable, now when we run, you'll see, I'll go 5 enter. +再运行程序,5 enter,6, + +1724 +01:11:52,211 --> 01:11:54,511 +Six, and you see it's put a five in there. +你就会看到这里有个 5 + +1725 +01:11:54,513 --> 01:11:55,512 +There's a 6. +这是 6 + +1726 +01:11:55,514 --> 01:11:57,447 +Times, it's even putting the times. +乘,它把乘号也放进去了 + +1727 +01:11:57,449 --> 01:11:59,915 +If I hit times again, now I get nil and +如果我再点乘,这里得到了 nil + +1728 +01:11:59,917 --> 01:12:03,652 +it shows me the whole thing is left over, Okay. +剩下所有的东西都显示了 + +1729 +01:12:03,654 --> 01:12:06,454 +Let's go another thing here, +再来一个测试 + +1730 +01:12:06,456 --> 01:12:10,358 +what if I go 6 Enter 5 Enter 4 Enter. +输入 6 enter 5 enter 4 enter + +1731 +01:12:10,360 --> 01:12:13,661 +Now if I do times it says times of 4 and +再做一次乘法,它出现 4 * 5 = 20 + +1732 +01:12:13,663 --> 01:12:18,098 +5 is 20 with the 6 left over, exactly right. +6 被剩下了,这都是正确的 + +1733 +01:12:19,134 --> 01:12:22,368 +Kay now notice I had to rerun there to do that, +为了这么做我得重新运行一次, + +1734 +01:12:22,370 --> 01:12:24,303 +you're gonna have a clear button right, +你得在这里放置一个清除按钮 + +1735 +01:12:24,305 --> 01:12:25,571 +that you do in assignment one, you're gonna have to +这是你们在作业一里完成的,你们需要 + +1736 +01:12:25,573 --> 01:12:27,239 +make that work in assignment two as well. +作业二里令这个按钮工作起来 + +1737 +01:12:28,308 --> 01:12:31,309 +Okay the last thing really out of time but I'm gonna show you +最后一件事,快没时间了 + +1738 +01:12:31,311 --> 01:12:34,311 +the last thing really quickly that I was gonna do is use +我快速给你们展示一下 + +1739 +01:12:34,313 --> 01:12:38,182 +this description to fix this problem I said right here. +利用 description 来回答我留在这里的问题 + +1740 +01:12:38,184 --> 01:12:41,385 +Which is what if I had a function called learn +定义一个叫 learn 的函数 + +1741 +01:12:41,387 --> 01:12:45,388 +op 'kay and it took an op as an argument here. +它把 op 作为参数 + +1742 +01:12:45,390 --> 01:12:53,029 +And it just said known ops ops description equals that op. +knownOps[op.description] = op + +1743 +01:12:53,031 --> 01:12:59,368 +You see, now these could all just be learn op this. +这些都可以变成 learnOp() + +1744 +01:13:00,404 --> 01:13:03,438 +Okay which is a lot nicer, I only have to type this thing +这看起来就好多了,我只需要把它敲一次 + +1745 +01:13:03,440 --> 01:13:05,306 +once, and I just use the description here. +我在这里用到了 description + +1746 +01:13:05,308 --> 01:13:08,875 +he other thing about this, notice where this function is. +另一点,注意这个函数的位置 + +1747 +01:13:08,877 --> 01:13:10,143 +Inside the init. +它在 init 内部 + +1748 +01:13:11,246 --> 01:13:12,545 +Okay you are allowed to +你可以在 + +1749 +01:13:12,547 --> 01:13:14,513 +put functions inside other functions. +一个函数的内部放另一个函数 + +1750 +01:13:14,515 --> 01:13:17,549 +If this is only called inside here, you can put it in here. +如果只在内部被调用,你可以这么做 + +1751 +01:13:17,551 --> 01:13:20,518 +If if I put it outside in fact I'd have a little a problem, +如果我把它放到外部,就会有点小问题 + +1752 +01:13:20,520 --> 01:13:22,387 +because it would have to be private. +它得是 private 的 + +1753 +01:13:22,389 --> 01:13:26,390 +Because it uses op, and that's what this error right here is. +因为它用到了 op,就好像这里的 error 提示的那样 + +1754 +01:13:26,392 --> 01:13:29,460 +All right I'd have say private func, but I don't want to do +我得把它变成 private 的,但是我不想这么做 + +1755 +01:13:29,462 --> 01:13:32,462 +private func, instead I'm just gonna put this right down +所以我把它放到这里 + +1756 +01:13:32,464 --> 01:13:35,131 +here, Okay and obviously I would do that one last. +显然,我最后还是把它放在这里 + +1757 +01:13:35,133 --> 01:13:37,333 +Okay that's it, hope you learned a lot and +这就是今天所要讲的,希望你们能学到很多知识 + +1758 +01:13:37,335 --> 01:13:40,236 +stuff elsewhere for that and I will see you on Wednesday, +周三再见 + +1759 +01:13:40,238 --> 01:13:42,037 +I'm here if you have questions. +如果有问题,来找我,我都在的 + +1760 +01:13:44,074 --> 01:13:47,976 +For more, please visit us at stanford.edu. +想了解更多,请登录 stanford.edu diff --git a/subtitles/4. More Swift and Foundation Frameworks.srt b/subtitles/4. More Swift and Foundation Frameworks.srt new file mode 100644 index 0000000..8f8de42 --- /dev/null +++ b/subtitles/4. More Swift and Foundation Frameworks.srt @@ -0,0 +1,8654 @@ +1 +00:00:00,001 --> 00:00:04,836 +欢迎收看斯坦福大学公开课 + +2 +00:00:04,838 --> 00:00:07,405 +本字幕由志愿者义务贡献 + +3 +00:00:11,277 --> 00:00:15,946 +>> Okay, well, welcome to lecture four of CS193P, +欢迎参加斯坦福大学2015年冬季学期的 CS193P 课程 + +4 +00:00:15,948 --> 00:00:18,748 +Stanford Winter of 2015. +CS193P 课程 + +5 +00:00:18,750 --> 00:00:21,284 +So, I've been doing all demo up until now, +在今天以前,我们一直都在写 demo, + +6 +00:00:21,286 --> 00:00:24,553 +and now we're going to be doing all slides today. +而今天,我们将会全部通过幻灯片学习 + +7 +00:00:24,555 --> 00:00:28,724 +So, I have a lot of stuff to talk about +我将会讲到很多东西 + +8 +00:00:28,726 --> 00:00:31,143 +most of this, although not all of it, +大部分,但不是全部, + +9 +00:00:31,144 --> 00:00:33,561 +is covered in your reading assignments, okay? +都在你的阅读任务中 + +10 +00:00:33,563 --> 00:00:35,496 +But here I'm going to +在这里我会尽量把 + +11 +00:00:35,497 --> 00:00:37,430 +try to highlight the things that are pretty important, and +重点强调一些重要的部分 + +12 +00:00:37,433 --> 00:00:39,066 +also just show you some stuff that are not in +并且也会给你看一些 + +13 +00:00:39,068 --> 00:00:41,802 +that reading assignment that you kinda need to know. +并不包含在阅读任务中,但你仍然需要知道的东西 + +14 +00:00:41,804 --> 00:00:43,336 +So this is definitely not a substitute for +但这绝对不能代替阅读 + +15 +00:00:43,338 --> 00:00:46,472 +the reading you'll still need to do the reading in order to +你仍然需要通过阅读 + +16 +00:00:46,474 --> 00:00:49,875 +kinda get the, the details of a lot of this stuff. +来掌握这些的细节部分 + +17 +00:00:49,877 --> 00:00:54,613 +So but this hopefully will kinda get you focused in on, +希望这节课可以让你注意在 + +18 +00:00:54,615 --> 00:00:58,066 +on the key stuff. +关键的东西上 + +19 +00:00:58,067 --> 00:01:01,518 +All right, so first, I wanna talk about +好的,那么我将讲讲 + +20 +00:01:01,521 --> 00:01:05,589 +Optionals and enums, so now that you know what an enum is. +Optional 和 enum,你已经知道 enum 是什么了 + +21 +00:01:05,591 --> 00:01:08,425 +I can tell you what an Optional really is okay? +那么我可以告诉你 Optional 到底是什么了 + +22 +00:01:08,427 --> 00:01:10,994 +An Optional is just an enum, okay? +Optional 就是 enum, + +23 +00:01:10,996 --> 00:01:15,098 +It's a very simple enum it's a generic kind of like Array. +就是一个非常简单的 enum,它是泛型的,类似于 Array + +24 +00:01:15,100 --> 00:01:15,998 +You know, have an Array, +比如一个 Array , + +25 +00:01:16,000 --> 00:01:17,666 +you specify the type of thing in it, +你指定了其中的类型, + +26 +00:01:17,668 --> 00:01:19,301 +Optionals exactly the same, okay? +Optional 跟它完全一样 + +27 +00:01:19,303 --> 00:01:20,335 +It's a generic. +就是泛型 + +28 +00:01:20,337 --> 00:01:22,637 +You specify the type of Optional it is. +你指定了 Optional 的类型是什么 + +29 +00:01:22,639 --> 00:01:26,173 +And that type, which is T here in this little enum, +而此类型,在这个 enum 中的 T + +30 +00:01:26,175 --> 00:01:29,376 +is just the type of the associated value, you know, +就是关联值的类型 + +31 +00:01:29,378 --> 00:01:31,578 +that enums can have associated values. +enums 可以关联各种值 + +32 +00:01:31,580 --> 00:01:35,882 +So that's just the type that, if the Optional is not nil. +如果 Optional 不是 nil,这就是它的类型 + +33 +00:01:35,884 --> 00:01:38,751 +That's what you get so that's all an enum is and +你就可以获取到它。这就是 enum + +34 +00:01:38,753 --> 00:01:42,054 +so for example, this is what it would look like if we +举个例子 + +35 +00:01:42,056 --> 00:01:45,724 +used the enum notation to do an Optional. +使用一个 enum 实现一个 Optional 看起来会像是这样 + +36 +00:01:45,726 --> 00:01:49,561 +Saying you know, x which is an enum or is an Optional String, +你可以看到,x 可以是一个 enum 或者是一个 Optional String, + +37 +00:01:49,563 --> 00:01:52,130 +which nil would just be saying x equals Optional +如果是 nil 可以这样表示: + +38 +00:01:52,132 --> 00:01:53,497 +angle bracket String dot none. +x = Optional.None + +39 +00:01:54,800 --> 00:01:56,200 +Okay? + +40 +00:01:56,201 --> 00:01:57,601 +Or, if you're sending it to not be know you +或者你可以将其赋值 + +41 +00:01:57,603 --> 00:02:00,403 +would say Optional angle bracket String dot Some, +x = Optional.Some() + +42 +00:02:00,405 --> 00:02:02,705 +parentheses, the associated value, which would be hello. +关联值,也就是 "Hello". + +43 +00:02:04,408 --> 00:02:05,607 +That make sense? +很合理吧? + +44 +00:02:05,609 --> 00:02:07,709 +So Optional really actually super simple. +Optional 其实就是这么简单 + +45 +00:02:07,711 --> 00:02:10,478 +With a question mark and exclamation point, +由问号及感叹号组成, + +46 +00:02:10,480 --> 00:02:13,180 +I know that makes it seem like, it's just so +我知道这看起来 + +47 +00:02:13,182 --> 00:02:17,451 +really complicated, but it's pretty simple really it's just +非常复杂,但实际上非常简单 + +48 +00:02:17,453 --> 00:02:20,787 +syntax sugar, syntactic sugar to do this Optional. +这只是语法糖,为了实现 Optional + +49 +00:02:20,789 --> 00:02:25,124 +Now the unwrapping, really just looks like this It's just +现在到解包,真的这看起来 + +50 +00:02:25,126 --> 00:02:28,894 +a switch and the case of some, you give the value back. +就只是 switch 与 case,在 "Some" 的情况下你可以得到其值 + +51 +00:02:28,896 --> 00:02:32,230 +In the case of none, you raise an exception, okay? +在 "None" 的情况下,就会抛出异常 + +52 +00:02:32,232 --> 00:02:36,034 +And simple as that. +就这么简单 + +53 +00:02:36,036 --> 00:02:38,836 +That's why it crashes when you unwrap something that's +这也是为什么当你解包一个 nil 的时候会崩溃 + +54 +00:02:38,838 --> 00:02:41,405 +nil, okay? + +55 +00:02:41,407 --> 00:02:45,242 +So that's Optional all right, so Array, I just wanna. +这就是一个 Optional 。对于 Array + +56 +00:02:45,244 --> 00:02:47,744 +We covered this so I'm gonna really fast through this but +我们已经概括了一次,所以我会快点进行这部分 + +57 +00:02:47,746 --> 00:02:50,480 +Arrays, the syntax there is the same, right? +Array ,这里的语法是相同的,对吧? + +58 +00:02:50,482 --> 00:02:51,781 +That square bracket thing, +这里的方括号 + +59 +00:02:51,783 --> 00:02:54,050 +that means exactly the same thing. +这就意味着他们是相同的 + +60 +00:02:54,052 --> 00:02:59,054 +Also you can't append or modify in any way +并且你不能通过任何方式增加或修改 + +61 +00:02:59,056 --> 00:03:02,257 +an Array that is a let, right, that's a constant Array. +一个声明为 let 的 Array ,因为这是常量 Array + +62 +00:03:02,259 --> 00:03:04,992 +I just wanna make it clear that defining an Array to +我在这里重申一下,通过 let 将一个 + +63 +00:03:04,994 --> 00:03:07,328 +be a constant by saying let something equal +Array 声明为常量 + +64 +00:03:07,330 --> 00:03:09,229 +an Array versus var something equal an Array, +与声明一个 Array 为 var + +65 +00:03:09,231 --> 00:03:12,833 +means that it's immutable, so you can't do append or insert, +声明为 let 意味着它是不可变的,所以你不能增加或插入, + +66 +00:03:12,835 --> 00:03:15,468 +or anything else that you could do on a mutable Array. +或任何你想要改变这个 Array 的操作 + +67 +00:03:15,470 --> 00:03:17,337 +Also, of course, +当然 + +68 +00:03:17,338 --> 00:03:19,205 +if you access an Array with the square brackets and +如果你通过方括号访问一个 Array + +69 +00:03:19,207 --> 00:03:21,540 +try to pull out something that's outside the bounds of +然后尝试着获取一个超出了 Array 范围东西 + +70 +00:03:21,542 --> 00:03:23,809 +the Array, this Array only has four animals in it and +一个 Array 只有四种动物在里面, + +71 +00:03:23,811 --> 00:03:27,145 +I'm trying to get animal five that's gonna crash. +我想要获取第五种,那么就会崩溃 + +72 +00:03:27,147 --> 00:03:28,279 +Array index out of bounds, +Array 访问越界 + +73 +00:03:28,281 --> 00:03:30,981 +just like pretty much any language you've used. +你以前使用过的语言也会是这样 + +74 +00:03:32,551 --> 00:03:33,850 +How to enumerate an Array. +如何枚举一个 Array 呢 + +75 +00:03:33,852 --> 00:03:35,885 +If you wanted to go through every single item +如果你想要获取在 Array 中的每一个对象 + +76 +00:03:35,887 --> 00:03:39,655 +in an Array and look at it, you can use for in, okay? +你可以使用 for in, + +77 +00:03:39,657 --> 00:03:43,526 +So you just say for, some variable you want, +就比如 for,一个你需要的变量, + +78 +00:03:43,528 --> 00:03:46,061 +in your Array, and then inside there, +in Array,然后在这里面 + +79 +00:03:46,063 --> 00:03:49,131 +that'll be your value, okay pretty obvious. +就是你想要的值了 + +80 +00:03:49,133 --> 00:03:51,433 +I put this here mostly to compare it to the next slide, +我放在这里主要是为了与 + +81 +00:03:51,435 --> 00:03:54,902 +which is Dictionary so Dictionary again, +接下来的 Dictionary 进行对比 + +82 +00:03:54,904 --> 00:03:56,470 +that's where a bracket thing is an alternate for +这里的括号也是起着同样的作用 + +83 +00:03:56,472 --> 00:03:59,406 +the exact same thing so if I had a nice +有一个 Dictionary + +84 +00:03:59,408 --> 00:04:02,576 +Dictionary here I can create a Dictionary. +我创建了一个 Dictionay + +85 +00:04:02,578 --> 00:04:04,177 +Using this square bracket notation, +使用了方括号标记 + +86 +00:04:04,179 --> 00:04:07,146 +which is just square bracket, key colon value, comma +[key:value, key:value] + +87 +00:04:07,148 --> 00:04:08,914 +key colon value okay, you know that. +你懂的 + +88 +00:04:08,916 --> 00:04:12,084 +And you also know that if I access a Dictionary with +如果我通过方括号访问一个 Dictionay, + +89 +00:04:12,086 --> 00:04:14,519 +the square bracket, it returns an Optional and +它会返回一个 Optional + +90 +00:04:14,521 --> 00:04:17,722 +that's because, for example here, I'm looking up PAC ten +举个例子,我要在 pac10teamRankings 中寻找 Ohio State + +91 +00:04:17,724 --> 00:04:21,192 +team Ohio State obviously that is not. +明显就没有 + +92 +00:04:21,194 --> 00:04:23,961 +It packed ten team so it's not in the Dictionary. +这里只包含了十个队伍,而它不在这个 Dictionay 里 + +93 +00:04:23,963 --> 00:04:25,929 +So it's going to return nil, okay? +那么就应该返回 nil 对吧? + +94 +00:04:25,931 --> 00:04:27,931 +So, that's why when you access a Dictionary, +这就是为什么你访问一个 Dictionay, + +95 +00:04:27,933 --> 00:04:29,299 +it comes back it's an Optional. +它会返回一个 Optional + +96 +00:04:30,769 --> 00:04:32,868 +To enumerate Dictionary you use a tuple. +枚举 Dictionay 你需要使用 tuple + +97 +00:04:33,871 --> 00:04:36,171 +Okay, so you say for, the tuple, +for tuple + +98 +00:04:36,173 --> 00:04:39,207 +key com of value in the Dictionary. +(key, value) in Dictionay + +99 +00:04:39,209 --> 00:04:41,376 +And inside there, key and value will both be set. +然后在里面,key 与 value 都会被设置好 + +100 +00:04:41,378 --> 00:04:46,947 +Okay, that's really easy way to enumerate Dictionaries. +这是非常简单的枚举 Dictionay 的方法 + +101 +00:04:48,083 --> 00:04:53,686 +Sence? All right I'm gonna teaching about new struct that +那接下来我会教你们一个之前没见过的 + +102 +00:04:53,688 --> 00:04:59,358 +you haven't seen called Range. A Range is just two points +新的结构体 Range,Range 是一个包含一种合理类型的两个点 + +103 +00:04:59,360 --> 00:05:01,893 +of a sensible type, so a starting point and an ending +一个是起始点,另一个是终止点 + +104 +00:05:01,895 --> 00:05:03,528 +point is exactly what you think a range would be. +正如你们所想的范围那样 + +105 +00:05:03,530 --> 00:05:07,098 +Now I say a sensible type here because, you know, +之所以称为合理类型 + +106 +00:05:07,100 --> 00:05:10,568 +the sensible type depends on what you're talking about for +取决于你怎么看 + +107 +00:05:10,570 --> 00:05:12,403 +an Array, the sensible type is an Int, +对于 Array 来说,这个合理的类型可以是 Int + +108 +00:05:12,405 --> 00:05:14,805 +but for other things like a String, it's not, and +但是对于别的比如 String 来说,它就不是了 + +109 +00:05:14,807 --> 00:05:16,106 +we're gonna talk about that in a minute. +我们稍后将会讲解这些知识 + +110 +00:05:17,409 --> 00:05:21,844 +Range is also a generic, just like Array or +Range 跟 Array 或者 Optional enum 一样 + +111 +00:05:21,846 --> 00:05:24,413 +like that Optional enum. +是泛型的 + +112 +00:05:24,415 --> 00:05:28,783 +And so it takes the type of thing so the Range again that. +所以它包含了一个类型 + +113 +00:05:28,785 --> 00:05:32,520 +To specify a range in an Array would be Range, angle bracket, +在 Array 中指定一个范围的方法是 Range + +114 +00:05:32,522 --> 00:05:35,389 +Int because Ints are how you index an Array. +因为 Array 是通过 Int 索引的 + +115 +00:05:35,391 --> 00:05:36,857 +So, if you were gonna specify a Range in +所以,如果你想要在数组中声明 Range + +116 +00:05:36,859 --> 00:05:38,758 +an Array they would be Ints, okay? +它就需要是 Int 类型的 + +117 +00:05:38,760 --> 00:05:40,693 +And it's approximately what I put here it's +我在这里讲的大概差不多了 + +118 +00:05:40,695 --> 00:05:44,663 +not exactly this, but as far as given what, you know, +但不完全是,但是就目前你们了解的知识来看 + +119 +00:05:44,665 --> 00:05:47,966 +so far this is the best I can describe it to you. +这是我能想到的最好的描述方式 + +120 +00:05:47,968 --> 00:05:51,069 +It's just a struct that has a startIndex and endIndex and +它仅仅是一个包含了 startIndex 和 endIndex 的结构体 + +121 +00:05:51,071 --> 00:05:53,271 +it is a struct you can go and get those values and +它也是一种能让你获取 + +122 +00:05:53,273 --> 00:05:55,940 +set those values out of there so +和设置值的结构体 + +123 +00:05:55,942 --> 00:06:01,145 +Array's Range would be a range of Int. String, it's, +所以 Array 的 Range 是 Int 的一个取值区间 至于 String + +124 +00:06:01,147 --> 00:06:04,047 +you would think that String would also be. +你们可能会想,对于 String 也是这样的 + +125 +00:06:04,049 --> 00:06:07,017 +You see sub ranges of Strings would also be specified by +可以看到 String 的子串可以通过 Int 去指定 + +126 +00:06:07,019 --> 00:06:08,451 +an Int, but in not, it not. +但也不一定 + +127 +00:06:08,453 --> 00:06:11,420 +There's a special type called String.index, +这里有一种特殊的类型叫做 String.index + +128 +00:06:11,422 --> 00:06:12,654 +which is an index into a String, +它是一种对 String 的索引 + +129 +00:06:12,656 --> 00:06:16,224 +I'm gonna talk all about that in a later slide, okay? +我将会在后面的幻灯片中讲到 + +130 +00:06:16,226 --> 00:06:18,960 +So Ranges, just like Arrays and +所以 Range 就像 Array 和 + +131 +00:06:18,962 --> 00:06:22,530 +Dictionaries, we don't usually say Range, angle bracket, +Dictionay 一样,但我们一般不会用 Range = XXX, + +132 +00:06:22,532 --> 00:06:26,867 +Int equals something we use this special syntax. +我们使用这种特殊的语法 + +133 +00:06:26,869 --> 00:06:29,569 +And the special syntax is this three dots, or +这个特殊的语法是 ... ,或者 + +134 +00:06:29,571 --> 00:06:32,739 +two dots and a less than sign. +..< + +135 +00:06:32,741 --> 00:06:37,009 +Okay, so the three dots means a range from the first thing, +... 意味着 + +136 +00:06:37,011 --> 00:06:39,778 +oh, no, on the left of the dots, to the other thing on +从点的左边到点的右边 + +137 +00:06:39,780 --> 00:06:41,480 +the right of the dots. That's the startIndex and +也就是 startIndex 和 + +138 +00:06:41,482 --> 00:06:44,015 +the endIndex, and it includes them both. +endIndex,它包含这两个值 + +139 +00:06:44,017 --> 00:06:47,218 +Includes both the start and end, whereas the other one, +包含开头和结尾 + +140 +00:06:47,220 --> 00:06:49,920 +two dot dot less than means it includes the first one, but +..< 意味着它只包含了开头,但是 + +141 +00:06:49,922 --> 00:06:51,355 +it does not include the second one. +没有包含结尾 + +142 +00:06:51,357 --> 00:06:54,591 +So it's an open-ended Range, okay cuz those, +所以它是一个有左闭右开的区间 + +143 +00:06:54,593 --> 00:06:56,092 +both of those kind of Ranges are common. +这些都是常用的 Range 的种类 + +144 +00:06:57,028 --> 00:07:00,463 +So that's how we specify a Range 99% of the time, +也是你们在 99% 的时候定义一个 Range 的方法 + +145 +00:07:00,465 --> 00:07:03,298 +we don't use the Range struct to do it +我们不使用 Range 的结构来定义 + +146 +00:07:03,300 --> 00:07:05,834 +although you can you could create a Range struct. +尽管可以创建一个 Range 的结构体 + +147 +00:07:05,836 --> 00:07:08,903 +And you could pass it as an argument to anything that +而且你们可以将它作为参数传递给任何接受 Range 的地方 + +148 +00:07:08,905 --> 00:07:12,040 +takes these dot, dot, dots. You could put an actual Range in +你们可以使用真正的 Range 结构 + +149 +00:07:12,042 --> 00:07:13,941 +there as well, okay they're the same thing. +他们是同样的 + +150 +00:07:13,943 --> 00:07:16,127 +It's just the dot, dot, +... 对你们而言只是一种 + +151 +00:07:16,128 --> 00:07:18,312 +dots are syntaxed to create that Range for you, okay and +创建 Range 的语法 + +152 +00:07:18,314 --> 00:07:20,781 +the things on either side of the dot, dot, dot. +在 ... 的两侧 + +153 +00:07:20,783 --> 00:07:21,799 +You know, it depends on +它取决于 + +154 +00:07:21,800 --> 00:07:22,816 +what kind of Range you're trying to create. +你要创建哪种类型的 Range + +155 +00:07:22,818 --> 00:07:24,150 +If you're creating an Int Range. +如果你要创建一个 Int 类型的 Range + +156 +00:07:24,152 --> 00:07:27,486 +A Range of angle bracket Int, then they'd be Ints, okay? +那么 Range,然后 Range 就是 Int 类型的了 + +157 +00:07:27,488 --> 00:07:28,854 +But if you're doing a String, +但是如果你们正在处理 String + +158 +00:07:28,856 --> 00:07:30,188 +they have to be String.indexes. +那就必须使用 String.index 类型了 + +159 +00:07:30,190 --> 00:07:33,591 +And that's a little harder to create, because a String.index +而且创建这种类型的 Range 有一点点难度,因为 String.index 类型 + +160 +00:07:33,593 --> 00:07:36,294 +can't be created from a numeric literal. +不能通过数字去创建 + +161 +00:07:36,296 --> 00:07:38,362 +You have to create it programmatically, so +你必须需要一点编程技巧去创建,所以 + +162 +00:07:38,364 --> 00:07:39,963 +we'll talk about that. +我们将会在大概十张幻灯片后 + +163 +00:07:39,965 --> 00:07:45,602 +In about ten slides or so. Okay and +来讨论这个 + +164 +00:07:45,604 --> 00:07:48,438 +you can enumerate a Range using for-in just like we +你们可以 通过 for-in 来遍历一个 Range,就像我们 + +165 +00:07:48,440 --> 00:07:50,906 +can with our raising Dictionaries there okay? +使用 Dictionay 一样 + +166 +00:07:50,908 --> 00:07:54,610 +All right, +好了 + +167 +00:07:54,611 --> 00:07:58,313 +other classes, besides Arrays, Dictionaries, Range. NSObject. +除了 Array, Dictionay, Range,接下来讨论其他的类,比如 NSObject + +168 +00:07:58,315 --> 00:08:00,982 +So NSObject was the the base class for +NSObject 在 Objective-C 中 + +169 +00:08:00,984 --> 00:08:02,817 +all of Objective-C classes. +是所有类的基类 + +170 +00:08:02,819 --> 00:08:05,119 +In Swift we don't really have a base class for +在 Swift 中,我们并没有 + +171 +00:08:05,121 --> 00:08:07,154 +all Swift classes. +这样一个基类 + +172 +00:08:07,156 --> 00:08:10,757 +however, there are some kind of advanced features in +然而,它有一些在 iOS 中的 + +173 +00:08:10,759 --> 00:08:13,726 +iOS that require, +高级特性 + +174 +00:08:13,728 --> 00:08:18,163 +even your Swift class to inherit from NSObject. +你的 Swift 类也可以继承自 NSObject + +175 +00:08:18,165 --> 00:08:19,598 +I can't really talk about them, +我现在还不能跟你们讨论这些 + +176 +00:08:19,599 --> 00:08:21,032 +because there's other things you need to know for +因为还有些别的你们必须得知道的东西 + +177 +00:08:21,035 --> 00:08:23,401 +me to even explain them to you but +我得去解释 + +178 +00:08:23,403 --> 00:08:25,536 +down the road that will happen. +学下去你们就知道了 + +179 +00:08:25,538 --> 00:08:27,805 +It really doesn't hurt to make your Swift class be +让你们的 Swift 类继承自 NSObject 没什么麻烦的 + +180 +00:08:27,807 --> 00:08:29,406 +a subclass of NSObject, so we could have +所以我们可以让 + +181 +00:08:29,408 --> 00:08:31,808 +made CalculatorBrain be a subclass of NSObject. +CalculatorBrain 类继承自 NSObject + +182 +00:08:31,810 --> 00:08:33,109 +Wouldn't hurt, and +没有任何影响,而且 + +183 +00:08:33,111 --> 00:08:35,845 +in the future, once we learn these advance things, +在将来,一旦我们学到这些进阶的东西 + +184 +00:08:35,847 --> 00:08:38,948 +it'd be nice to be able to do those advanced features with +我们将可以使用一些高级的特性来编写 + +185 +00:08:38,950 --> 00:08:41,617 +CalculatorBrain so it's kinda one. +CalculatorBrain + +186 +00:08:41,619 --> 00:08:42,851 +Can feel free I'm not sure what to +唔,我也不知道该怎么说 + +187 +00:08:42,853 --> 00:08:45,220 +say the best practice here is to always have your Swift +就是,在 iOS 中,最好让你们所有的 Swift 类 + +188 +00:08:45,222 --> 00:08:49,090 +classes inherit from NSObject. All the classes in iOS, +都继承自 NSObject. 在 iOS 中,所有的类, + +189 +00:08:49,092 --> 00:08:50,975 +like UIViewController, and +比如 UIViewController,还有其他 + +190 +00:08:50,976 --> 00:08:52,859 +all those, they all inherit from NSObject eventually. +其实最后都是继承自 NSObject + +191 +00:08:52,862 --> 00:08:55,462 +It's the super class of all of them there's not +它是所有类的基类 + +192 +00:08:55,464 --> 00:08:59,599 +really much in NSObject anymore that matters. +关于 NSObject,没有其他需要讲的了 + +193 +00:08:59,601 --> 00:09:03,002 +But like I say, there's these advanced features but. +但是,就像我说的,有一些高级特性 + +194 +00:09:03,004 --> 00:09:04,637 +Then there's NSNumber, +接下来是 NSNumber + +195 +00:09:04,638 --> 00:09:06,271 +you've actually briefly seen NSNumber. +你们之前其实已经见过 NSNumber + +196 +00:09:06,273 --> 00:09:09,908 +NSNumber is just a generic number-holding class, it just holds a number. +它只是一个装数字的类 + +197 +00:09:09,910 --> 00:09:12,677 +That's all it does on it has a ton of methods on and I'm not +它里面有很多方法 + +198 +00:09:12,679 --> 00:09:15,013 +gonna go through and here you can look in the documentation. +但是我不打算去讲,你们可以自己去看文档 + +199 +00:09:15,015 --> 00:09:17,114 +But, the methods are things like doubleValue. +但是,这些方法,比如 doubleValue + +200 +00:09:17,116 --> 00:09:20,317 +intValue which is give me your value of yourself as +intValue ,会将他们自身的值 + +201 +00:09:20,319 --> 00:09:21,818 +an Int, as a Double etc. +以 Int, Double 等类型返回给我们 + +202 +00:09:23,121 --> 00:09:26,322 +In Swift, we don't really use this very much, +在 Swift 中,我们不会用太多这些东西 + +203 +00:09:26,324 --> 00:09:28,324 +because it's strongly typed and, +因为 Swift 是强类型 + +204 +00:09:28,326 --> 00:09:31,527 +so we're using types like Int and Double. +我们直接用像 Int 、 Double 这样的类型 + +205 +00:09:31,529 --> 00:09:35,997 +But in Objective-C APIs, there's no NSNumbers lying +但在 Objective-C 的 API 中,没有遍地的 NSNumbers 类型 + +206 +00:09:35,999 --> 00:09:39,701 +around and so you kinda need to know about it. +这一点是你们要了解的 + +207 +00:09:39,703 --> 00:09:42,069 +I'm gonna talk a little bit later about the fact that +接下来我会多讲一点强类型的内容 + +208 +00:09:42,071 --> 00:09:44,772 +all those Swift types are kinda magically bridged +所有这些 Swift 类型都通过巧妙桥接到 NSNumber 类型 + +209 +00:09:44,774 --> 00:09:48,075 +to NSNumber, okay those ints and Doubles. +比如 Int, Double 等 + +210 +00:09:48,077 --> 00:09:50,076 +So, you really don't even have to worry about NSNumber. +所以你甚至不必担心 NSNumber + +211 +00:09:50,078 --> 00:09:53,880 +Unless you use NSNumberFormatter that we used in +除非你要用作业中提到的 NSNumberFormatter + +212 +00:09:53,882 --> 00:09:58,117 +the assignment, because that thing returns an NSNumber. +因为它会返回一个 NSNumber 类型的值 + +213 +00:09:58,119 --> 00:10:00,652 +>> So it there's no like NSObject parallel in Swift, +>>(学生提问) + +214 +00:10:00,654 --> 00:10:02,721 +is there a way to make like an Array that holds +(学生提问) + +215 +00:10:02,723 --> 00:10:04,773 +any kind of [CROSSTALK] ? +(学生提问) + +216 +00:10:04,774 --> 00:10:06,824 +>> Yep, so the question is, if there's no NSObject, well, +嗯,他的问题是,如果没有 NSObject (那么该怎么处理 NSObject 相关的东西呢) + +217 +00:10:06,826 --> 00:10:09,060 +it wouldn't really matter about NSObject. +其实没有 NSObject 并不是造成困扰的所在 + +218 +00:10:09,062 --> 00:10:11,062 +But the question is can I +真正的问题在于没了 NSObject 之后 + +219 +00:10:11,063 --> 00:10:13,063 +create an Array where there are random Objects in there? +我能不能创建一个包含任意对象的数组呢 + +220 +00:10:13,065 --> 00:10:15,932 +And we're gonna talk about that later. +我们下面会讲这个东西 + +221 +00:10:15,934 --> 00:10:18,468 +Another class, NSDate, exactly what is sounds like, +另一个类, NSDate,顾名思义 + +222 +00:10:18,470 --> 00:10:21,270 +stores a date, let's you get the current date and time too. +可以存储日期,也可以让你获取当前日期和时间 + +223 +00:10:22,306 --> 00:10:24,139 +Pretty self-explanatory has lots and +显然,NSDate 有非常非常多的方法 + +224 +00:10:24,141 --> 00:10:25,874 +lots of methods in it. +会涉及到这些东西 + +225 +00:10:25,876 --> 00:10:28,143 +And it has even more and more methods because there's those +它还因为下面即将提到的另外三个类 + +226 +00:10:28,145 --> 00:10:29,577 +three other classes mentioned here, +还会有更多相关的方法 + +227 +00:10:29,579 --> 00:10:32,480 +Calendar, DateFormatter, and DateComponents. +Calendar, DateFormatter, 和 DateComponents. + +228 +00:10:32,482 --> 00:10:34,281 +And if you're ever doing a date where you're gonna +如果你正要做日期相关的事情 + +229 +00:10:34,283 --> 00:10:37,784 +put a date on screen as part of your application, +在你的应用的某个地方放置一个日期 + +230 +00:10:37,786 --> 00:10:39,753 +you really wanna look at all these classes and +你就需要查看所有 + +231 +00:10:39,755 --> 00:10:41,954 +read the documentation that talks about dates. +提到日期的类和文档 + +232 +00:10:41,956 --> 00:10:43,422 +Because, dates are displayed very +因为全世界的日期 + +233 +00:10:43,424 --> 00:10:45,224 +differently around the world. +显示方式各不相同 + +234 +00:10:45,226 --> 00:10:48,160 +Different calendars different you know even +不同的日历,就我们所熟知的差异 + +235 +00:10:48,162 --> 00:10:50,895 +different languages, the order of the month, day, year even +在语言方面,年月日的顺序方面都不同 + +236 +00:10:50,897 --> 00:10:53,031 +if you're using the Gregirian calendar is different. +甚至你正在用的 Gregirian 类型的标准日历也有不同的地方 + +237 +00:10:53,033 --> 00:10:56,600 +So, you really, really dates are tricky to get right if +所以如果你要做在全世界都能正确显示的日历 + +238 +00:10:56,602 --> 00:10:59,136 +you wanna build an app that can work around the world. +是需要一些技巧的 + +239 +00:10:59,138 --> 00:11:00,871 +Okay, so I'm just kind of warning you if +所以我只是提醒你 + +240 +00:11:00,873 --> 00:11:03,506 +you're gonna build an app like that some day you wonna really +如果你要做一个应用需要用到日期时间 + +241 +00:11:03,508 --> 00:11:06,542 +understand date and all it's friends here. +你需要理解和 NSDate 相关的东西 + +242 +00:11:06,544 --> 00:11:07,977 +There's NSData, +还有 NSData + +243 +00:11:07,979 --> 00:11:11,280 +super easy class it's just a bag of bits, okay? +非常简单的类,它就是一个比特包 + +244 +00:11:11,282 --> 00:11:13,849 +Could be gigantic bag of bits, small bag of bits, whatever. +可以是巨大的比特包,也可以是一个小小的比特包 + +245 +00:11:13,851 --> 00:11:18,586 +But it's just untyped data that's just in there it's just +不管怎样,它里面只是无类型的数据 + +246 +00:11:18,588 --> 00:11:21,055 +you can think of it almost like a pointer to memory and +你可以把它看成是一个指向内存的指针 + +247 +00:11:21,057 --> 00:11:22,256 +you just don't know what's in there. +并且你不知道它那里有什么东西 + +248 +00:11:23,292 --> 00:11:26,693 +This is how iOS will pass around untyped data, raw data. +这就是 iOS 可以四处传递无类型数据、原始数据的原因 + +249 +00:11:26,695 --> 00:11:31,263 +It passes around using this class. +它就是通过这个类来传递的 + +250 +00:11:31,265 --> 00:11:33,632 +It will be obvious when we start using this what it's for. +所以我们用这个类的目的是显而易见的 + +251 +00:11:33,634 --> 00:11:36,134 +You're not gonna be using NSData much in this class, +你不会用太多 NSData 的东西 + +252 +00:11:36,136 --> 00:11:38,970 +cuz we're not dealing with raw data that much,okay. +因为我们不会去处理那么多原始数据 + +253 +00:11:38,972 --> 00:11:41,439 +All right, so, let, +好的,其实 + +254 +00:11:41,441 --> 00:11:43,974 +I just wanted to mention some of those classes just so, +我只是想稍微提一下这其中的一些类 + +255 +00:11:43,976 --> 00:11:47,144 +you know, they exist you can check out the documentation +它们都在文档中,你可以通过文档 + +256 +00:11:47,146 --> 00:11:48,945 +on all of them to find out more about it and +找到它们并查看更详细的内容 + +257 +00:11:48,947 --> 00:11:50,914 +I'm gonna revisit a few of them like Array and +下面我会再稍微提到其中的一些类,比如 Array + +258 +00:11:50,916 --> 00:11:54,283 +Dictionary and String because they, they're so important I'm +Dictionary 还有 String,因为它们实在太重要了 + +259 +00:11:54,285 --> 00:11:56,552 +actually gonna talk about some of their methods. +所以我会着重介绍它们的一部分方法 + +260 +00:11:56,554 --> 00:11:58,554 +But, I wanna talk a little bit about data structures in +通常,我会先谈谈 Swift 中的一些数据结构 + +261 +00:11:58,556 --> 00:12:00,589 +Swift in general, okay? +没问题吧 + +262 +00:12:01,491 --> 00:12:03,124 +There's really three fundamental building +在这些数据结构中 + +263 +00:12:03,126 --> 00:12:04,692 +blocks for your data structure that you +有三个基础块 + +264 +00:12:04,694 --> 00:12:06,927 +might build and you've seen them +而且你之前已经见过了 + +265 +00:12:06,929 --> 00:12:08,795 +two of the three of them in detail, but +其中的两个的具体内容 + +266 +00:12:08,797 --> 00:12:10,597 +they are class, struct, and +它们就是类、结构体 + +267 +00:12:10,599 --> 00:12:13,333 +enum, okay they're the three basic building blocks. +和枚举,它们就是那三个基础的块 + +268 +00:12:14,469 --> 00:12:17,936 +And they look very similar their declaration syntax looks +它们在声明的语法上看起来很像 + +269 +00:12:17,938 --> 00:12:19,137 +very, very similar, right? +非常非常像,对吧 + +270 +00:12:19,139 --> 00:12:21,106 +Just, the only difference is whether it's class, +唯一的差别就在声明的关键字是 class + +271 +00:12:21,108 --> 00:12:23,341 +struct, or enum, but otherwise looks the same. +struct 还是 enum,除此之外看起来就是一模一样 + +272 +00:12:23,343 --> 00:12:25,009 +They're also very similar in that they can all +它们还有个非常相像的地方,它们都能拥有 + +273 +00:12:25,011 --> 00:12:27,878 +have properties and functions, okay, all three of them. +属性和方法 + +274 +00:12:27,880 --> 00:12:31,448 +Now enums they can't store any values +Enum 本身是不能存储任何值 + +275 +00:12:31,450 --> 00:12:34,050 +you store the values of your enum in that associated +你可以将值存储在枚举的关联信息中 + +276 +00:12:34,052 --> 00:12:38,454 +information but they can have computed properties, okay? +枚举是可以有计算型属性 + +277 +00:12:38,456 --> 00:12:42,458 +And all three of them can have functions, all right? okay? +这三种数据结构都可以有函数,明白吗 + +278 +00:12:42,460 --> 00:12:44,292 +So, that's very important to understand so, +理解这点非常的重要 + +279 +00:12:44,294 --> 00:12:45,927 +they are very, very similar in that way. +它们在那方面看起来非常的相似 + +280 +00:12:47,197 --> 00:12:49,397 +They're also similar at least structs, and +结构体和类更甚 + +281 +00:12:49,399 --> 00:12:51,098 +classes in that they can have intializers. +它们甚至都可以有初始化的构造器 + +282 +00:12:51,100 --> 00:12:53,800 +And we're gonna talk about initializers in detail in +我们后面的幻灯片中会详细地 + +283 +00:12:53,802 --> 00:12:55,468 +a few slides, okay? +谈到这个构造器 + +284 +00:12:55,470 --> 00:12:56,703 +So, they're similar in a lot of ways but +它们在许多方面都非常相似 + +285 +00:12:56,705 --> 00:12:58,938 +there's a couple ways in which they're very different, +但仍然有几个不同的地方 + +286 +00:12:58,940 --> 00:13:00,039 +all right? + +287 +00:13:00,040 --> 00:13:01,139 +Classes are the only ones where you +类是三者中唯一拥有 + +288 +00:13:01,142 --> 00:13:04,009 +have inheritance, okay? +继承的性质 + +289 +00:13:04,011 --> 00:13:05,243 +And it's pretty obvious, +显而易见 + +290 +00:13:05,245 --> 00:13:07,478 +that's kind of the main definer of what a class is, +这是一种确定类是什么东西的主要定义 + +291 +00:13:07,480 --> 00:13:08,045 +it has inheritance. +就是它有继承性质 + +292 +00:13:09,715 --> 00:13:12,082 +And then, introspection and +我也会讲 + +293 +00:13:12,084 --> 00:13:13,750 +casting, which I'm also gonna talk about a little +内省和转型 + +294 +00:13:13,752 --> 00:13:16,652 +later those are only for classes, so none of this +都是属于类的性质 + +295 +00:13:16,654 --> 00:13:19,555 +casting thing I'm gonna talk about can you do for structs. +所以我所说所有关于转换的内容,你不能应用到结构体上 + +296 +00:13:21,158 --> 00:13:23,224 +And the most important difference to understand, and +而我们要明白的三种结构最重要的区别 + +297 +00:13:23,226 --> 00:13:24,625 +we really went over this in the demo, +在我们接下来的 demo 中会遇见的 + +298 +00:13:24,627 --> 00:13:27,561 +is this value type versus reference type. +就是 value type (值类型)与 reference type (引用类型) + +299 +00:13:27,563 --> 00:13:29,663 +Structs and enums are passed around and +结构体和枚举的传递和 + +300 +00:13:29,665 --> 00:13:32,499 +stored in variables copied, okay? +存储是通过拷贝过的变量 + +301 +00:13:32,501 --> 00:13:34,117 +Right? +对吗? + +302 +00:13:34,118 --> 00:13:35,734 +And referenced and classes are reference types. +类属于引用类型 + +303 +00:13:35,737 --> 00:13:37,637 +In other words, we pass round pointers to them, +换句话说,我们传递的是这些对象的指针, + +304 +00:13:37,639 --> 00:13:39,171 +they live in the heap. +而这些对象本身存储在堆内存中 + +305 +00:13:39,173 --> 00:13:41,407 +And remember that class is their memory and +需要记住的是,堆内存中的对象 + +306 +00:13:41,409 --> 00:13:43,809 +the heap is managed for us. +系统会自动为我们管理(ARC) + +307 +00:13:43,811 --> 00:13:45,444 +Okay, so there's nothing, +这样一来, + +308 +00:13:45,445 --> 00:13:47,078 +we don't have to do anything alloc and free them. +我们就没有必要去开辟和释放内存了 + +309 +00:13:47,080 --> 00:13:48,212 +We create them when we want, and +我们创建想要的对象后, + +310 +00:13:48,214 --> 00:13:49,714 +when nobody else, no one's using it, +一旦没有任何指针指向这些对象, + +311 +00:13:49,716 --> 00:13:52,316 +it gets cleaned up and it's not garbage collection, okay? +这些对象就会被马上清理掉,注意,这不是垃圾回收机制,明白吗? + +312 +00:13:52,318 --> 00:13:53,850 +Reference counting, automatic reference counting. +这是引用计数,自动引用计数 (ARC) + +313 +00:13:53,852 --> 00:13:56,252 +But, I wanna just have a slide on this +我还想多讲一下 + +314 +00:13:56,254 --> 00:13:58,221 +value type versus reference type again, because it's +值类型和引用类型的区别,因为分清它们 + +315 +00:13:58,223 --> 00:13:59,789 +a really important thing to understand it. +真的很重要 + +316 +00:13:59,791 --> 00:14:01,890 +Cuz people get confused writing the code and +因为人们在写代码的时候并不是很清楚 + +317 +00:14:01,892 --> 00:14:04,726 +they don't understand what's going on, +他们背后的区别和原理, + +318 +00:14:04,728 --> 00:14:08,329 +but a value type struct means, you know, it's +对于值类型,比如结构体,它表示 + +319 +00:14:08,331 --> 00:14:11,599 +mean that it's copied when you pass it into a function. +当你将它传递给方法的时候,方法使用的是它的拷贝 + +320 +00:14:11,601 --> 00:14:14,235 +It's copied when you assign it to a different variable, +当你将它赋值给另外一个变量的时候也是如此, + +321 +00:14:14,237 --> 00:14:15,436 +this one especially gets people. +理解这个是很重要的 + +322 +00:14:15,438 --> 00:14:16,636 +I don't understand as I have, +比如, + +323 +00:14:16,638 --> 00:14:20,540 +you know let x equals Array, and I say let y equal x. +let x = Array<>,然后 let y = x + +324 +00:14:20,542 --> 00:14:22,508 +That makes, essentially a copy of x, +这实际上是将 x 的值拷贝一份给了 y , + +325 +00:14:22,510 --> 00:14:25,611 +now that copy might be lazy behind the scenes, but +或许这背后是以惰性的方式拷贝的,总之 + +326 +00:14:25,613 --> 00:14:28,279 +as far as you're concerned it's a copy, okay? +你只需要知道这是一份拷贝,明白吗? + +327 +00:14:29,449 --> 00:14:31,015 +And if you wanna to be mutable, +如果你希望赋值后可以修改它, + +328 +00:14:31,017 --> 00:14:33,183 +you could copy it into a VAR instead of a LET, +你只需要将这个常量赋值给一个变量(var y = x), + +329 +00:14:33,185 --> 00:14:34,718 +and now you could mutate it. +之后,你就可以修改它了 + +330 +00:14:34,720 --> 00:14:36,486 +And if you mutate it you get, +当你修改你得到的值的时候, + +331 +00:14:36,488 --> 00:14:38,988 +you're mutating your own copy, you're not mutating. +你修改的是你拷贝来的值,而不是修改 + +332 +00:14:38,990 --> 00:14:42,491 +What the other one pointed to, okay? +之前被拷贝的那个值(修改 y 不会影响 x ),明白吗? + +333 +00:14:42,493 --> 00:14:47,729 +you, because of this, when you make a struct or an enum, +因为上述原理,当你定义一个 struct 或者一个 enum, + +334 +00:14:47,731 --> 00:14:51,866 +and you add a function to it that modifies it, +并且为它添加方法来修改它的状态时, + +335 +00:14:51,868 --> 00:14:56,236 +you have to mark it with this keyword mutating. +你必须在方法前面加上 mutating 关键字。 + +336 +00:14:56,238 --> 00:14:59,306 +And that's so that Swift knows when someone else. +这样当其他人 + +337 +00:14:59,308 --> 00:15:02,042 +Gets you know, tries to use your enum or struct, if +需要使用你的 enum 或 struct 的时候, + +338 +00:15:02,044 --> 00:15:05,178 +they use one of these mutating functions it obviously has to +他们就必须在一个变量上来调用这些 mutating 函数, + +339 +00:15:05,180 --> 00:15:07,613 +be in a var but not in a let type variable. +而不是在一个常量上 + +340 +00:15:07,615 --> 00:15:13,552 +[NOISE] Okay so reference stored in the heap, reference +引用类型存储在堆中, + +341 +00:15:13,554 --> 00:15:19,524 +counted even if you have a constant pointer to a class. +即使是一个常量指针,也会导致引用计数增加 + +342 +00:15:19,526 --> 00:15:21,525 +Let something equals the class. +对于指向一个对象的常量指针, + +343 +00:15:21,527 --> 00:15:24,261 +You can still send messages to that thing that can mutate it, +你同样可以向这个常量指针发送消息,来修改所指对象里面的属性, + +344 +00:15:24,263 --> 00:15:26,196 +because it didn't the heap. +因为这个对象存储在堆里面, + +345 +00:15:26,197 --> 00:15:28,130 +All right, so it being, you have a pointer to it. +而你可以用一个指针来引用它 + +346 +00:15:28,133 --> 00:15:29,933 +So, and when you pass it to a function, +当你把这个这个对象传递个一个方法的时候, + +347 +00:15:29,935 --> 00:15:31,267 +you're passing a pointer to that thing, so +你传递的是指向这个对象的指针,所以 + +348 +00:15:31,269 --> 00:15:32,968 +if the function modifies it, +如果这个方法修改了这个对象, + +349 +00:15:32,970 --> 00:15:35,571 +it's modifying the thing back where it was called. +那它修改的就是存储在堆内存中的那个对象了 + +350 +00:15:35,573 --> 00:15:37,406 +Okay? +明白吗? + +351 +00:15:37,408 --> 00:15:41,809 +So which do you use between these two? +那么如何正确选择这两种数据类型呢? + +352 +00:15:41,811 --> 00:15:42,894 +Well you know, +事实上, + +353 +00:15:42,895 --> 00:15:43,978 +90% of the time, you're gonna use a class. +百分之九十的情况下我们都会使用类 + +354 +00:15:43,980 --> 00:15:45,746 +This is object-oriented programming language. +因为这是面向对象的编程语言 + +355 +00:15:45,748 --> 00:15:48,348 +You're gonna wanna have the ability to do inheritance, and +当你使用类时,你就可以使用诸如继承, + +356 +00:15:48,350 --> 00:15:49,916 +overriding, and things like that. +重写之类的特性了 + +357 +00:15:49,918 --> 00:15:53,786 +Structs are really more for the basic fundamental types, +而结构体更适合基础数据类型, + +358 +00:15:53,788 --> 00:15:57,456 +like Double, Int, Array, Dictionaries, String. +比如 Double, Int, Array, Dictionaries, String。 + +359 +00:15:57,458 --> 00:16:00,826 +These are all you know, really fundamental things and +你知道,这些东西都非常基础,而且 + +360 +00:16:00,828 --> 00:16:03,128 +when we get into the graphics, you're gonna see the points, +当我们涉及到绘图的时候,我们会更多地使用 points , + +361 +00:16:03,130 --> 00:16:07,131 +sizes, rectangles, those are structs, okay? +sizes,rectangles,它们都是都是结构体 + +362 +00:16:07,133 --> 00:16:09,166 +But, most of everything else we build, +但是,我们的大多数操作都是 + +363 +00:16:09,168 --> 00:16:12,036 +we build the classes, okay. +与类打交道 + +364 +00:16:12,038 --> 00:16:13,804 +And since it manages all the memory for you and +而且系统会为你管理内存, + +365 +00:16:13,806 --> 00:16:18,775 +all that, it's really no big pain to do, to use classes. +所以现在使用类是一件非常轻松的事情了 + +366 +00:16:19,944 --> 00:16:22,228 +All right, so methods. +好的,接下来, + +367 +00:16:22,229 --> 00:16:24,513 +So, I wanna talk a little bit about methods, all right. +我想讨论一下方法 + +368 +00:16:24,515 --> 00:16:26,181 +You obviously- +很明显, + +369 +00:16:26,183 --> 00:16:27,449 +>> [COUGH] + +370 +00:16:27,451 --> 00:16:29,417 +>> If you override a method in a class, +当你重写父类的方法的时候, + +371 +00:16:29,419 --> 00:16:33,287 +you have to put the keyword, override in front of it, 'kay? +你必须在该方法前面加上 override 关键字,记住了吗? + +372 +00:16:34,490 --> 00:16:37,057 +You can also mark a method final, +你也可以把一个方法标记为 final , + +373 +00:16:37,059 --> 00:16:39,559 +that means no one can override it. +final 表示这个方法不能被重写 + +374 +00:16:39,561 --> 00:16:41,694 +So, if someone subclasses a class you wrote, +如果有人继承了你的类, + +375 +00:16:41,696 --> 00:16:43,328 +they can't override you if you marked it final. +他们不能重写那些被标记为 final 的方法 + +376 +00:16:43,330 --> 00:16:46,131 +You can also mark an entire class final, which means hm, +你还可以把整个类都标记为 final ,这表示, + +377 +00:16:46,133 --> 00:16:47,565 +it's a, you know, this is the end of the line. +谁都不能更改这个类, + +378 +00:16:47,567 --> 00:16:49,634 +You can't do any subclasses of it basically. +甚至不能继承这个类。 + +379 +00:16:49,636 --> 00:16:51,402 +Okay? +明白了吗? + + +380 +00:16:51,404 --> 00:16:58,508 +Both types and instances have methods and properties. +类和实例都有自己的方法和属性 + +381 +00:16:58,510 --> 00:17:00,577 +So, types, a type is like Array, +比如, Array 就是一个类, + +382 +00:17:00,579 --> 00:17:04,047 +that's the type and instance of an Array is an actual Array +而具体的一个 Array 就是一个实例, + +383 +00:17:04,049 --> 00:17:04,947 +with things in it. +实例封装有自己数据 + +384 +00:17:04,949 --> 00:17:07,249 +Okay? +明白吗? + +385 +00:17:07,250 --> 00:17:09,550 +So let's look at this pili, piece of code, right here. +我们来看看下面这段代码 + +386 +00:17:09,553 --> 00:17:11,620 +I've defined a Double, 'kay? +我定义里一个 Double 类型的变量 d , + +387 +00:17:11,622 --> 00:17:13,922 +This var which is a Double, and I say, +这个是一个 Double 变量, + +388 +00:17:13,924 --> 00:17:17,625 +if the Double isSignMinus, that means if it's minus sign, +然后向 d 发送 isSignMinus 消息,来判断它 + +389 +00:17:17,627 --> 00:17:19,727 +has, it's negative. +是否是负数, + +390 +00:17:19,729 --> 00:17:21,962 +Then I'm going to set the Double to be it, +然后我把 d 设置为, + +391 +00:17:21,964 --> 00:17:23,863 +the absolute value of the Double. +它自己的绝对值 + +392 +00:17:23,865 --> 00:17:28,501 +So, isSignMinus is an instance variable, +所以, isSignMius 是实例 d 的变量, + +393 +00:17:28,503 --> 00:17:30,035 +an instance property. +或者说是实例 d 的一个属性 + +394 +00:17:30,037 --> 00:17:32,804 +You send it to a particular Double to ask it, +你通过对一个具体的 Double 类型的实例 d 发送 isSignMius 消息, + +395 +00:17:32,806 --> 00:17:34,673 +is your SignMinus? +来判实例 d 是否是负数 + +396 +00:17:34,675 --> 00:17:39,210 +Whereas Double.abs is a type function on Double. +然而, abs 是 Double 这个类型的方法(不依赖类型的实例) + +397 +00:17:39,212 --> 00:17:42,379 +You pass the Double you wanna operate on to it, and +你向这个方法中传入你需要操作的 Double 类型的实例, + +398 +00:17:42,381 --> 00:17:44,381 +it works on it. +它返回你想要的结果 + +399 +00:17:44,382 --> 00:17:46,382 +But your, and you're not sending abs to a particular +这里,你并没有向一个特定的 Double 实例发送消息, + +400 +00:17:46,385 --> 00:17:48,385 +Double, you're sending it to the class, or +而是向 Double 的类型在发送消息, + +401 +00:17:48,387 --> 00:17:49,952 +the struct in this case, the type. +在这个例子中是向着 struct 类型(Double 是 struct) + +402 +00:17:49,954 --> 00:17:51,721 +You see what I mean? +明白我的意思吗? + +403 +00:17:51,723 --> 00:17:54,723 +So, some method you send to instances, particular +你把一些方法发送给实例 + +404 +00:17:54,725 --> 00:17:57,592 +instances of some things, something you can send to the type. +一些特殊的方法,你可以发送给类型 + +405 +00:17:57,594 --> 00:18:00,628 +All right, so two different kinds of, of method but +所以是两种不一样的方法 + +406 +00:18:00,630 --> 00:18:02,597 +otherwise, the rules for them are about the same. +但他们的规则是一样的 + +407 +00:18:02,599 --> 00:18:04,732 +It's just that, who you asked to do the work. +区别就是你叫谁去完成任务 + +408 +00:18:05,668 --> 00:18:08,101 +You declare a type method or +你声明一个类方法或者 + +409 +00:18:08,103 --> 00:18:11,037 +a property by using static in front of it. +前面使用关键字 static 修饰的一个 property + +410 +00:18:11,039 --> 00:18:14,474 +So, like abs, there would static func abs, +就像 abs 方法,原型是 + +411 +00:18:14,476 --> 00:18:16,842 +takes a Double returns a Double. +static func abs(d: Double) -> Double + +412 +00:18:16,844 --> 00:18:19,345 +And that makes it so you send it that to, the Double type +这就规定了你要向 Double 类型发消息 + +413 +00:18:19,347 --> 00:18:21,880 +instead of sending it to a particular Double. +而不是某个特定的 Double 实例 + +414 +00:18:21,882 --> 00:18:24,749 +In a class you use the word class not static. +在一个 class 中你使用关键字 class 而不是 static(static 用于 struct 和 enum) + +415 +00:18:24,751 --> 00:18:26,617 +Okay, cuz it's called a class function. +因为它被称为类方法 + +416 +00:18:27,787 --> 00:18:28,819 +Okay? +明白吗? + +417 +00:18:28,821 --> 00:18:31,055 +So, I just don't want you to be confused, +我不想让你们感到困惑 + +418 +00:18:31,056 --> 00:18:33,290 +when you start seeing methods like abs that are sent to +当你看见一个类似于 abs 的方法 + +419 +00:18:33,292 --> 00:18:35,108 +the Double type. +被发送给 Double 类型时 + +420 +00:18:35,109 --> 00:18:36,925 +That looks kinda weird but it's perfectly normal. +那看起来有一点奇怪,但是很正常 + +421 +00:18:36,928 --> 00:18:38,228 +Okay? +明白吗? + +422 +00:18:38,229 --> 00:18:39,529 +And what would you do with a ty, wh, when do +那么…… + +423 +00:18:39,531 --> 00:18:42,231 +you have a type function versus an instant function? +类方法和实例方法该如何选择呢? + +424 +00:18:42,233 --> 00:18:44,800 +Well, if you're doing any kind of utility work, right? +如果你正在进行通用性工作 + +425 +00:18:44,802 --> 00:18:46,218 +You're not doing anything in +你不需要针对 + +426 +00:18:46,219 --> 00:18:47,635 +particular to a certain kind of Double, but +特定的 Double 实例做修改, + +427 +00:18:47,638 --> 00:18:50,705 +just in utilities, you would have those in there. +只是通用的一些步骤,那么你可以使用两种方式 + +428 +00:18:50,707 --> 00:18:53,908 +Sometimes you would have type methods that create objects of +有时候你会用类方法 + +429 +00:18:53,910 --> 00:18:56,310 +certain kinds and hand them out. +来创建对象并供外部使用 + +430 +00:18:56,312 --> 00:18:59,013 +Maybe a shared object like if you had one, +比如共享对象,如果你有一个 + +431 +00:18:59,015 --> 00:19:00,547 +only one instance of an object for +只有一个实例的对象 + +432 +00:19:00,549 --> 00:19:03,383 +your entire app of a certain type, maybe you would ask that +也许你会要求那个类型 + +433 +00:19:03,385 --> 00:19:07,120 +type, give me that shared instance, okay? +给我那个共享的实例,明白了吗? + +434 +00:19:07,122 --> 00:19:08,587 +So it's kinda before utilities and +这是通用步骤和 + +435 +00:19:08,589 --> 00:19:10,889 +creation, that kinda thing. +创建对象之前的东西 + +436 +00:19:10,891 --> 00:19:12,991 +And they're, now I wouldn't, I don't wanna say, they're rare, +我不想说类方法很少见 + +437 +00:19:12,993 --> 00:19:15,960 +they're not super common, you'll see them in, in iOS and +说类方法不是非常常见,你们在 iOS 里面会看到 + +438 +00:19:15,962 --> 00:19:18,496 +you'll probably use them occasionally. +偶尔还会使用 + +439 +00:19:18,498 --> 00:19:21,565 +you, you would use them really instead of global functions. +你可能会使用类方法而非全局函数 + +440 +00:19:21,567 --> 00:19:23,801 +You can't have global functions. +你不允许使用全局函数 + +441 +00:19:23,803 --> 00:19:25,936 +In Swift, of course. +当然是在 Swift 中 + +442 +00:19:25,938 --> 00:19:28,271 +But you'd really probably prefer to make it a type +但是你可能真的喜欢创建类方法 + +443 +00:19:28,273 --> 00:19:31,674 +method so that function is associated with you know, +以便那个方法关联到 + +444 +00:19:31,676 --> 00:19:33,542 +the type and kind of, unless it's +类型和其他东西,除非它真的是 + +445 +00:19:33,544 --> 00:19:35,844 +truly a global function that applies to the world. +一个世界通用的全局函数 + +446 +00:19:35,846 --> 00:19:39,348 +It doesn't, it's not about a particular class, +它跟一个特殊的类无关 + +447 +00:19:39,350 --> 00:19:41,716 +usually you would make them be a type, +通常情况下你将会把它们当做一个类使用 + +448 +00:19:41,718 --> 00:19:44,485 +a type function [SOUND] very well [SOUND]. +一个类方法 + +449 +00:19:44,487 --> 00:19:46,454 +All right? +对吧? + +450 +00:19:46,456 --> 00:19:49,390 +So method, now lets talk about the parameter names +现在让我们来谈谈 + +451 +00:19:49,392 --> 00:19:50,908 +of methods. +方法的参数名 + +452 +00:19:50,909 --> 00:19:52,425 +This is, this is a, this is gonna be the crash course, +这会是速成课, + +453 +00:19:52,428 --> 00:19:54,361 +you read all about this I hope in the documentation. +你们已经阅读了我希望你们知道的,在文档中所有的相关内容 + +454 +00:19:54,363 --> 00:19:57,697 +But, all parameters to functions have an internal +但是,方法中的所有参数都有 + +455 +00:19:57,699 --> 00:19:58,731 +name and an external name. +一个内部的名字和一个外部的名字 + +456 +00:19:58,733 --> 00:20:00,432 +So, we're talking about the parameters. +所以,让我们来讨论一下这些参数 + +457 +00:20:00,434 --> 00:20:00,999 +Okay? +明白了么? + +458 +00:20:01,001 --> 00:20:03,068 +So, down there, +所以,在下面 + +459 +00:20:03,069 --> 00:20:05,136 +foo, the parameters the parameter to foo there. +foo , 参数 foo 在这里 + +460 +00:20:05,138 --> 00:20:07,071 +'Kay, it has internal name and external name. +明白了么,它有一个内部命名和一个外部命名 + +461 +00:20:07,073 --> 00:20:09,874 +So, the internal name, which goes kinda near +所以,内部的名字,和冒号有一点接近 + +462 +00:20:09,876 --> 00:20:12,643 +the colon, is the name that that thing is gonna have as +是在方法中拥有一个本地变量的名字 + +463 +00:20:12,645 --> 00:20:15,479 +a local variable inside the method, at this internal name. +在这个内部名称中 + +464 +00:20:15,481 --> 00:20:18,615 +And then the external name is the name that +外部命名是一个名字 + +465 +00:20:18,617 --> 00:20:22,251 +callers are going to use when the, to put before the colon. +调用者准备使用的,放在冒号之前 + +466 +00:20:22,253 --> 00:20:23,285 +'Kay? +明白了么? + +467 +00:20:23,286 --> 00:20:24,318 +When they call the thing. +当他们调用东西的时候 + +468 +00:20:24,321 --> 00:20:26,822 +So in bar there, I'm calling things, and +所以在这里,我要调用一个东西 + +469 +00:20:26,824 --> 00:20:30,008 +in foo I'm defining them. +在 foo 方法中我定义了他们 + +470 +00:20:30,009 --> 00:20:33,193 +So, you see that here, I call foo with external colon 123. +所以,在这里你可以看到,我通过 foo(external:123) 来调用 foo + +471 +00:20:33,196 --> 00:20:37,598 +Even though, internal to foo, that thing is called internal. +尽管,foo 的内部,那东西叫做 internal + +472 +00:20:38,801 --> 00:20:39,933 +'Kay? +明白了吗? + +473 +00:20:39,935 --> 00:20:41,401 +So, you can have both external, +所以,你可以同时拥有外部的 + +474 +00:20:41,403 --> 00:20:42,368 +internal names, they can be different. +以及内部的名字,他们可以不一样 + +475 +00:20:43,604 --> 00:20:45,037 +You can put an under bar, +你可以添加一个下划线 + +476 +00:20:45,039 --> 00:20:48,473 +remember under bar is kinda the don't care thing in Swift. +记住,在 Swift 中下划线是会被忽略的 + +477 +00:20:48,475 --> 00:20:50,808 +Even under bar if you don't want callers to +如果你不想有调用者 + +478 +00:20:50,810 --> 00:20:52,009 +use an external name. +使用一个外部命名 + +479 +00:20:52,011 --> 00:20:53,410 +So now look at bar. +现在来看 bar 方法 + +480 +00:20:53,412 --> 00:20:55,345 +It calls foo, +它调用了 foo 方法 + +481 +00:20:55,346 --> 00:20:57,279 +it doesn't even put internal colon or external colo, colon. +可是却没有写 internal: 或者 external: + +482 +00:20:57,282 --> 00:20:59,282 +It just puts the argument there. +它只是把参数留在了那儿 + +483 +00:20:59,284 --> 00:21:00,550 +'Kay? So, the under bar says, +所以,下划线说: + +484 +00:21:00,552 --> 00:21:03,285 +I don't wanna have an external name for this. +“我不想拥有一个外部命名” + +485 +00:21:03,287 --> 00:21:07,422 +'Kay, now that is the default for +其实,函数的第一个参数的 + +486 +00:21:07,424 --> 00:21:09,958 +the first argument to a function. +默认外部命名就是下划线 + +487 +00:21:10,994 --> 00:21:12,393 +So, foo only has one argument, so +所以,foo 方法只有一个参数 + +488 +00:21:12,395 --> 00:21:14,695 +it's first argument, it's only argument. +所以,它是第一个参数也是唯一的一个参数 + +489 +00:21:14,697 --> 00:21:17,731 +You can see that when you call it from bar, +你可以看到它当你从 bar 处调用它 + +490 +00:21:17,733 --> 00:21:19,332 +you don't say internal colon, +你不会写 “internal:” + +491 +00:21:19,334 --> 00:21:22,435 +as because that under bar thing is the default. +因为下划线是默认的 + +492 +00:21:23,371 --> 00:21:25,337 +Now, if you don't want that to be the default, +现在,如果你不想让它作为默认的值 + +493 +00:21:25,339 --> 00:21:28,506 +you can force the first one to be required by +你可以强制第一个参数是必要的 + +494 +00:21:28,508 --> 00:21:31,609 +putting a pound sign there, a little hashtag, okay? +通过添加一个 “#” 井号标志,一个小标签,明白? + +495 +00:21:31,611 --> 00:21:34,345 +And that makes it so you have to say internal colon- +这使得你不得不通过 internal: 来调用函数 + +496 +00:21:34,347 --> 00:21:36,814 +>> [COUGH] >> 'Kay? +明白吗? + +497 +00:21:37,950 --> 00:21:42,318 +For other parameters, not the first parameter but +对于另外的参数,不是第一个参数 + +498 +00:21:42,320 --> 00:21:43,886 +other parameters. +是其他的参数 + +499 +00:21:43,888 --> 00:21:46,555 +The name, the internal or external name, +他们的名称,内部命名或外部命名 + +500 +00:21:46,557 --> 00:21:49,391 +is mandatory, 'kay? +是必须要写的,明白? + +501 +00:21:49,393 --> 00:21:52,460 +Unless, you put the and you can change the name, +除非,你设置或者改变了它的名称 + +502 +00:21:52,462 --> 00:21:55,430 +you can be you can, you can have the external name be +这个因人而异,你可以将外部命名区别于其他的参数 + +503 +00:21:55,432 --> 00:21:58,165 +different for any parameter not just the first one. +这个不仅限于第一个参数 + +504 +00:21:58,167 --> 00:22:01,001 +And you can put the under bar in there and make it so +还有,你可以在这里添加一个下划线 + +505 +00:22:01,003 --> 00:22:03,070 +even the second one has no parameter name. +来让第二个变量没有参数名 + +506 +00:22:03,072 --> 00:22:06,940 +This would be incredibly un-Swift like to do this. +我不建议这样做,因为这不是标准的做法 + +507 +00:22:06,942 --> 00:22:10,610 +To have a function like this that takes two arguments, and +要想让这样一个接受两个参数的方法的第二个参数 + +508 +00:22:10,612 --> 00:22:13,946 +the second one doesn't really have, a name. +不需要名称 + +509 +00:22:13,948 --> 00:22:16,382 +Because in Swift you can kind of think of the name of +因为在 Swift 中,你一般会认为方法的名字 + +510 +00:22:16,384 --> 00:22:20,018 +the method, as describing what the first argument is. +即描述了它的第一个参数是什么 + +511 +00:22:20,020 --> 00:22:22,487 +The first argument's your method, it should always be, +你的方法的第一个参数,始终需要 + +512 +00:22:22,489 --> 00:22:24,422 +kind of obvious based on the name of the method. +基于此方法的名字 + +513 +00:22:24,424 --> 00:22:25,623 +Because the method does something, +因为方法完成了某些功能 + +514 +00:22:25,625 --> 00:22:27,424 +it operates on something or whatever. +它在某个事物之上进行操作 + +515 +00:22:27,426 --> 00:22:29,309 +That should be the first argument. +那个事物就应该是第一个参数 + +516 +00:22:29,310 --> 00:22:31,193 +That's why it usually doesn't need a first parameter name. +这就是我们不需要第一个参数名的原因 + +517 +00:22:31,196 --> 00:22:32,462 +And then all the other arguments, +至于其余的参数 + +518 +00:22:32,464 --> 00:22:33,663 +you wanna give them names, so +如果你理解了它们在干什么之后 + +519 +00:22:33,665 --> 00:22:35,398 +if you understand what they are, 'kay? +你想要给它们命名 + +520 +00:22:35,400 --> 00:22:37,132 +What they're about? +说明这个参数是用来干什么的 + +521 +00:22:37,134 --> 00:22:40,035 +And in other languages a lot of times you'll have a real, +在其他的语言中,你经常会遇到 + +522 +00:22:40,037 --> 00:22:42,937 +really long method that says you know, do this, and +非常非常长的方法命名告诉你某个方法 + +523 +00:22:42,939 --> 00:22:44,405 +that, with this other thing, and +做了 A 和 B ,使用了 C 跟 D + +524 +00:22:44,407 --> 00:22:47,408 +that, and then in parenthesis you have four arguments and +然后你需要在括号中将这四个参数 + +525 +00:22:47,410 --> 00:22:49,810 +people have to kinda match up what's what. +一一对应起来 + +526 +00:22:49,812 --> 00:22:51,945 +Here, the name of the method really is kind of +而在 Swift 中,方法名是根据 + +527 +00:22:51,947 --> 00:22:53,580 +distributed out amongst it's arguments. +它的参数来命名的 + +528 +00:22:53,582 --> 00:22:55,014 +So, it's really a lot easier to read and +比较方便去阅读 + +529 +00:22:55,016 --> 00:22:57,516 +a lot easier to understand, what the heck is going on? +也比较方便去理解,方法这里到底是在干什么? + +530 +00:22:57,518 --> 00:22:59,718 +so, I don't recommend it, +显然,我并不推荐这么做 + +531 +00:22:59,720 --> 00:23:03,655 +I don't recommend putting the under bar in, in parameters. +我不推荐在参数之前加上下划线 + +532 +00:23:03,657 --> 00:23:05,089 +There, there are some exceptions, but +虽然有一些特例,但是 + +533 +00:23:05,091 --> 00:23:08,692 +I generally don't recommend that. +一般来说我不推荐这么做 + +534 +00:23:08,694 --> 00:23:09,860 +'Kay? +明白了吗? + +535 +00:23:09,862 --> 00:23:10,994 +All right properties, +接来下是 properties + +536 +00:23:10,996 --> 00:23:13,062 +let's talk a little bit about properties. +让我们一起来看看什么是 properties + +537 +00:23:13,064 --> 00:23:15,331 +So, property observers are very important and +显然, property observers 是非常关键的 + +538 +00:23:15,333 --> 00:23:17,333 +we're gonna use them a lot. +而且我们会大量使用它 + +539 +00:23:17,335 --> 00:23:19,452 +They are very simple, +它们使用起来很简单 + +540 +00:23:19,453 --> 00:23:21,570 +you have a property like here I have some stored property. +在这里你有一个 someStoredProperty + +541 +00:23:21,572 --> 00:23:23,238 +It's an Int equals 42, and +它是 Int 类型的,值为42 + +542 +00:23:23,240 --> 00:23:26,941 +yes I didn't need to type there, I'm just putting there. +其实我并不需要在这里写这些,我只是把它放在这里 + +543 +00:23:26,943 --> 00:23:29,210 +okay, and throughout my slides by the way. +这些一直贯穿在我的 Slides 中 + +544 +00:23:29,212 --> 00:23:32,880 +Green, I put things in green because I'm just trying to +绿色,我将这部分标注为绿色,因为 + +545 +00:23:32,882 --> 00:23:35,782 +make you draw attention to the fact that this is code. +我想让你们注意到的是,这部分是代码 + +546 +00:23:35,784 --> 00:23:37,684 +Okay? That's all green means, but +明白了吗?这是被标注为绿色的部分的意义 + +547 +00:23:37,686 --> 00:23:40,353 +yellow usually will mean this is +黄色部分通常表示 + +548 +00:23:40,355 --> 00:23:42,221 +the thing I'm talking about, right now. +这是我正在跟你们讲的东西 + +549 +00:23:42,223 --> 00:23:43,422 +This is the thing to pay attention to. +这是你们需要关心的部分 + +550 +00:23:43,424 --> 00:23:44,590 +So, you can al, +所以,你可以把黄色部分 + +551 +00:23:44,591 --> 00:23:45,757 +almost think of yellow, as like highlighted. +认为是一种高亮 + +552 +00:23:45,759 --> 00:23:47,309 +Okay? +明白了吗? + +553 +00:23:47,310 --> 00:23:48,860 +So, here I have some stored property. +回到我们之前讲的,这里我拥有一个 someStoredProperty + +554 +00:23:48,862 --> 00:23:51,195 +It stores in Int 42. +它存储了 Int 类型的42 + +555 +00:23:51,197 --> 00:23:54,398 +And notice though, even though it's a stores property, +需要注意的是,这是一个 + +556 +00:23:54,400 --> 00:23:56,100 +not computed, it's stored. +直接存储、不需要计算过程的 property + +557 +00:23:56,102 --> 00:23:58,435 +I still put a curly brace after it. +我仍旧在它之后放置了一对花括号 + +558 +00:23:58,437 --> 00:24:00,103 +But in that curly brace instead of +花括号的意思并不是说, + +559 +00:24:00,105 --> 00:24:02,472 +saying get instead like a computer property. +这个 property 是通过计算得到的 + +560 +00:24:02,474 --> 00:24:05,675 +I say, will set and did set, 'kay? +而是有 willSet 和 didSet,明白了吗? + +561 +00:24:05,677 --> 00:24:09,277 +So these are little pieces of code inside the willSet and +所以在 willSet 和 didSet 之后的 + +562 +00:24:09,279 --> 00:24:11,396 +dill, didSet. +小段的代码 + +563 +00:24:11,397 --> 00:24:13,514 +They get called when that property gets set by anybody, +会在设置 property 的值的过程中被调用 + +564 +00:24:13,517 --> 00:24:16,884 +so it's called an a property observer cause I'm observing +这就是它为什么叫 property observer 的原因 + +565 +00:24:16,886 --> 00:24:20,021 +with this code I'm observing this thing is being set. +因为这段代码 observe 这个 property 的设置方法 + +566 +00:24:20,023 --> 00:24:21,989 +And the willSet is called right before +willSet 这个方法会在设置 property 值之前被调用 + +567 +00:24:21,991 --> 00:24:25,592 +the properties value gets set, and the didSet, right after. +同理,didSet 这个方法会在设置 property 值之后被调用 + +568 +00:24:25,594 --> 00:24:27,244 +And inside the willSet, +在 willSet 方法中 + +569 +00:24:27,245 --> 00:24:28,895 +you've got this special variable called new value, +你会有一个特殊的 newValue 变量 + +570 +00:24:28,897 --> 00:24:31,230 +which is gonna be the new value that's going to be set. +这是 property 将要被设置的新的值 + +571 +00:24:31,232 --> 00:24:34,233 +And then inside didSet, you've got this special thing +同样,在 didSet 方法中,你会有一个特殊的 oldValue 变量 + +572 +00:24:34,235 --> 00:24:36,535 +called old value, which is the old value. +这是 property 要被设置之前的值 + +573 +00:24:36,537 --> 00:24:39,371 +Okay? +明白了吗? + +574 +00:24:39,372 --> 00:24:42,206 +Now, you use this in really kind of these two cases. +现在,你可以在这两种情况下使用它们 + +575 +00:24:42,208 --> 00:24:44,608 +One is you have the stored property in yourself, +一种情况是你在自己的类中拥有 + +576 +00:24:44,610 --> 00:24:46,660 +in your class. +stored property + +577 +00:24:46,661 --> 00:24:48,711 +And whenever someone sets it, you want to kinda notice and +当其他方法的设置它的值时,你想要获得一个 notice + +578 +00:24:48,714 --> 00:24:50,013 +do something, okay? +然后你可以根据这个 notice 做一些事情 + +579 +00:24:50,015 --> 00:24:54,384 +And the other one is you inherit some property, and you +另一种情况是你继承了某些类 + +580 +00:24:54,386 --> 00:24:57,319 +don't necessarily do anything with that property directly. +你并不需要对这些类中的 property 做什么修改 + +581 +00:24:57,321 --> 00:24:59,722 +But you wanna know, when that gets changed by anybody. +但它们被改变时你想知道 + +582 +00:24:59,724 --> 00:25:00,756 +'Kay? +明白了吗? + +583 +00:25:00,758 --> 00:25:01,956 +So, you can even do willSet and +所以,你可以在某些 + +584 +00:25:01,958 --> 00:25:04,726 +didSet on properties you inherit from somebody, +继承的类之上 + +585 +00:25:04,728 --> 00:25:05,526 +from your super class. +重写继承自父类的 willSet 和 didSet + +586 +00:25:06,529 --> 00:25:07,861 +Okay? +明白了吗? + +587 +00:25:07,863 --> 00:25:10,697 +Now, what kinda things would we do in here? +在这里,我们能够做些什么? + +588 +00:25:10,699 --> 00:25:13,533 +Well, one extremely common thing to do in iOS is to +在 iOS 开发中非常常见的做法是 + +589 +00:25:13,636 --> 00:25:15,019 +update the user-interface. +更新用户界面(UI) + +590 +00:25:16,020 --> 00:25:18,403 +So, you have some view controller let's say, or +举例,你有一个 view controller + +591 +00:25:18,406 --> 00:25:21,440 +you have a view, and you change some property in it and +或者你有一个 view ,你改变了其中的某些 property + +592 +00:25:21,442 --> 00:25:25,043 +it, that changing that property means would change. +改变其中某些 property 意味着 + +593 +00:25:25,045 --> 00:25:28,146 +So, in the didSet, you'll go update the user-interface. +在 didSet 中,你将对用户界面进行更新 + +594 +00:25:28,148 --> 00:25:30,281 +That make sense? +这样说能理解一点了吗? + +595 +00:25:30,283 --> 00:25:32,083 +'Kay. +好 + +596 +00:25:32,084 --> 00:25:33,884 +So, the observers are really cool, they're a really good +所以, property observers 是非常酷的 + +597 +00:25:33,886 --> 00:25:35,852 +way to kinda keep track of what's going on and +他们是跟踪发生了什么事情以及 + +598 +00:25:35,854 --> 00:25:36,853 +keep things in sync. +保持事务同步的一种好方法 + +599 +00:25:38,323 --> 00:25:42,624 +All right, lazy initialization so a lazy property, +接下来,我们谈谈惰性实例化 + +600 +00:25:42,626 --> 00:25:45,494 +if you put lazy in front of a property declaration, it means +如果你在 property 声明前加了 lazy ,这意味着 + +601 +00:25:45,496 --> 00:25:49,230 +it does not get initialized until someone accesses it. +它只会在被用到的时候才会初始化 + +602 +00:25:50,333 --> 00:25:53,467 +And that's true whether it's initialized with +比如它以被赋值的操作执行初始化 + +603 +00:25:53,469 --> 00:25:55,769 +equal something, so that equal something will not +那么这个赋值的动作会在这个 property 实际被用到的时候 + +604 +00:25:55,771 --> 00:25:59,305 +happen until someone actually accesses that property. +才会执行 + +605 +00:25:59,307 --> 00:26:03,876 +Or you can actually initialize it by putting a closure there, +你也可以在初始化的时候使用闭包 + +606 +00:26:03,878 --> 00:26:06,712 +put parenthesis after it, and we'll execute that closure. +后面放一对圆括号,也就是通过执行这个闭包 + +607 +00:26:06,714 --> 00:26:10,048 +And that will initialize the property. +来初始化这个属性 + +608 +00:26:10,050 --> 00:26:15,186 +But that closure won't get executed until someone tries to get it, 'kay? +但是这个闭包只有在 property 被用到的时候才会执行 + +610 +00:26:15,188 --> 00:26:19,023 +And then you can even in a lazy property, you could call +在 lazy property 中 + +611 +00:26:19,025 --> 00:26:23,593 +a method to, to initialize it because it, normally you +你甚至可以调用一个方法来初始化 + +612 +00:26:23,595 --> 00:26:27,296 +wouldn't be able to do this if you didn't say lazy. +如果你不把 property 标记为 lazy,这样做是不允许的 + +613 +00:26:27,298 --> 00:26:29,415 +Because you can't call any +因为在类初始化之前 + +614 +00:26:29,416 --> 00:26:31,533 +methods in your class until you're fully initialized, so +类里的方法都是不可以调用的 + +615 +00:26:31,535 --> 00:26:33,535 +there's kinda a catch 22 there. +有点像第22条军规 + +616 +00:26:33,537 --> 00:26:34,736 +But in this case since, +但是在这种情况 + +617 +00:26:34,738 --> 00:26:37,238 +you can't call any methods until you're initialized, +在属性全部初始化以前确实不可以调用方法, + +618 +00:26:37,240 --> 00:26:39,974 +by the time somebody tries to get this property, +直到有人试图 get 这个 property + +619 +00:26:39,976 --> 00:26:41,408 +you'd be fully initialized. +它就会被初始化了 + +620 +00:26:41,410 --> 00:26:43,343 +So, you can call methods. +所以方法就可以调用了 + +621 +00:26:43,345 --> 00:26:45,779 +So, you see the advantage of lazy there? +到这你能看出用 lazy 的优势了吗? + +622 +00:26:45,781 --> 00:26:47,798 +'Kay. + +623 +00:26:47,799 --> 00:26:49,816 +This lazy thing still satisfies the rule that you +这个 lazy 特性依然满足“所有属性必须 + +624 +00:26:49,818 --> 00:26:53,285 +must initialize all of your properties. +初始化”的规则 + +625 +00:26:53,287 --> 00:26:56,688 +'Kay, even though it doesn't actually initialize it until someone accesses it. +即使它在被用到以前并没有被初始化, + +627 +00:26:56,690 --> 00:26:58,490 +It still satisfies that rule. +它依然遵循这个规则 + +628 +00:27:00,293 --> 00:27:04,528 +unfortunately, only vars can be lazily initialized. +但是,只有 var 才可以用 lazy 初始化这个特性 + +629 +00:27:04,530 --> 00:27:06,347 +Things that are let, +因为 let,也就是类里的常量 + +630 +00:27:06,348 --> 00:27:11,134 +if you had constants in your class, those would have to be initializing in your initializer. +都必须在类的初始化方法里初始化 + +632 +00:27:11,135 --> 00:27:14,102 +You can't initialize them lazily, only vars, not lets. +只有 var 可以用 lazy,let 不可以 + +633 +00:27:14,105 --> 00:27:19,108 +This can be used to get around some kind of tricky initialization dependencies. +这个特性一般会用来处理一些错综复杂的初始化依赖 + +635 +00:27:19,110 --> 00:27:20,909 +Because of that rule that everything has to be +正是因为在类的内部的规则:在做任何事之前, + +636 +00:27:20,911 --> 00:27:22,577 +initialized before you can do anything. +所有的 property 都必须被初始化 + +637 +00:27:22,579 --> 00:27:24,479 +Sometimes you can get into fights with your +有时类会和它的父类有一些交集, + +638 +00:27:24,481 --> 00:27:27,114 +superclass for example, about when something's gonna be +举个例子 + +639 +00:27:27,116 --> 00:27:29,883 +initialized, and you need your superclass to do something or +当有些 property 将要被初始化时,需要你或者你的父类做一些事情 + +640 +00:27:29,885 --> 00:27:32,252 +you can do something, but it needs you to do something +但是你在做这些事情之前还需要先解决一些事情 + +641 +00:27:32,254 --> 00:27:35,288 +before they can do something, so you're kinda we're stuck. +这时候你就会有点卡住 + +642 +00:27:35,290 --> 00:27:37,290 +And what you can do is one of the other of you, +这时候你就可以让 + +643 +00:27:37,292 --> 00:27:40,259 +make one of the things that depends on their lazy. +某些 property 依赖于它们的 lazy 初始化 + +644 +00:27:40,261 --> 00:27:45,196 +Okay. And then, as soon as somebody wants it, it'll get initialized and off we go. +这样的话,当有东西需要这个 property 的时候,它才会被初始化 + + +646 +00:27:47,000 --> 00:27:48,599 +Okay? Any questions about Lazy? +明白了吗?关于 lazy 大家有问题吗? + +647 +00:27:48,601 --> 00:27:53,337 +Pretty cool feature. All right? +非常好的特性 + +649 +00:27:53,338 --> 00:27:55,338 +And it's exactly, what it sounds like, just lazily waits +准确的来说,就跟这个特性的名字一样,就是懒懒地等着别人 + +650 +00:27:55,341 --> 00:27:58,342 +to initialize until someone wants this property. +需要这个属性的时候,这个属性才开始初始化 + +651 +00:27:58,344 --> 00:27:59,743 +Okay? + +652 +00:27:59,745 --> 00:28:02,545 +So, now let's talk about initialization, so +下边咱们来聊聊初始化, + +653 +00:28:02,547 --> 00:28:06,148 +I need to get, I need a drink before the initialization, cuz it's complicated. +在说这个话题之前我得喝点水,因为初始化很复杂 + +655 +00:28:08,719 --> 00:28:10,652 +Hopefully my, I'm just, I'm not, this is not, +希望我没事儿 + +656 +00:28:10,654 --> 00:28:11,819 +just taking care of my voice here. +就是怕我嗓子坏了 + +657 +00:28:11,821 --> 00:28:15,689 +Okay, init, all right. +好了,init + +658 +00:28:15,691 --> 00:28:18,392 +So, when do you need an init method? +什么时候需要一个 init 方法? + +659 +00:28:18,394 --> 00:28:20,344 +Well, you know what? +事实上你知道吗? + +660 +00:28:20,345 --> 00:28:22,295 +You actually don't need an init method that often. +大多数时候并不需要 init 方法 + +661 +00:28:22,297 --> 00:28:26,332 +'Kay? We showed,had the init method in the CalculatorBrain. +我们之前演示过 CalculatorBrain 类的 init 方法, + +663 +00:28:26,334 --> 00:28:27,766 +Made sense there. We needed it there. +在那 init 确实是有用而且必要的 + +665 +00:28:28,902 --> 00:28:29,868 +But you don't need it that often, +但是实际上大多数时候不太需要 init, + +666 +00:28:29,870 --> 00:28:34,005 +because a lot of your variables and constants in your class or +因为类或者结构体里边大部分的常量和变量都会 + +668 +00:28:34,007 --> 00:28:37,808 +struct are set with equals, so you don't need them. +通过赋值被初始化 + +669 +00:28:37,810 --> 00:28:40,110 +Or maybe the properties are Optionals. +或者有些属性是 Optional 的, + +670 +00:28:40,112 --> 00:28:41,511 +And so they can just start out nil and +这样即使他们是 nil 也没问题, + +671 +00:28:41,513 --> 00:28:46,115 +you can set them later like the outlets in a storyboard. +也可以在之后在给他们赋值,就像 StoryBoard 里的 outlet 一样 + +672 +00:28:46,117 --> 00:28:50,752 +Or you can actually initialize by using a closure. +又或者可以用闭包来初始化 + +673 +00:28:50,754 --> 00:28:52,287 +Okay? As I showed in the previous +理解这个吗?就像我之前演示的 + +674 +00:28:52,289 --> 00:28:54,756 +thing, that lazy thing, that you, you can do that for +lazy 那个特性一样,你一样可以用闭包来初始化一个 + +675 +00:28:54,758 --> 00:28:57,558 +non-lazies, put the closure thing there and execute it. +非 lazy 的属性 + +676 +00:28:57,560 --> 00:28:59,226 +It'll get executed right away and +不同的是这个闭包会立即执行并且 + +677 +00:28:59,228 --> 00:29:01,328 +nothing inside that closure could refer to +闭包里没有任何与其他实例变量有关系的东西 + +678 +00:29:01,330 --> 00:29:03,830 +other instance variables of, of course because it +因为这个闭包会在初始化全部完成 + +679 +00:29:03,832 --> 00:29:06,666 +would be executing before the initialization was done. +以前就执行了 + +680 +00:29:06,668 --> 00:29:09,869 +But still, you can calculate some things to assign things +但是你仍然可以通过闭包 + +681 +00:29:09,871 --> 00:29:11,937 +in a closure, by executing a closure. +做一些计算来赋值 + +682 +00:29:13,173 --> 00:29:16,841 +and, or you could use the lazy mechanism and then to avoid needing an init. +你也可以使用 lazy 机制,从而避免使用 init 方法 + +684 +00:29:16,843 --> 00:29:18,776 +So, there's a lot of ways to avoid init. +所以有很多方法来避免使用 init + +685 +00:29:19,979 --> 00:29:24,014 +But if you do need an init then what, +但如果你确实需要一个 init 方法的时候, + +686 +00:29:24,016 --> 00:29:26,516 +what, how do we do init? +该怎么做呢? + +687 +00:29:26,518 --> 00:29:28,384 +Because init has some kind of +因为 init 方法会有一些很有趣 + +688 +00:29:28,386 --> 00:29:31,220 +interesting inter-dependencies, +的互相依赖关系, + +689 +00:29:31,222 --> 00:29:34,956 +it's not as straightforward as you might think. +它并不像你可能想象的那么简单 + +690 +00:29:34,958 --> 00:29:37,658 +Now you get some free inits- +在一些情况下,init 方法会自动生成, + +691 +00:29:37,660 --> 00:29:39,593 +'Kay? Inits that get done for +也就是说 init 已经给你准备好了 + +692 +00:29:39,595 -->00:29:45,231 +you, one is that if all the properties in a class,in a base class. +其中一种情况就是如果一个基类, + +694 +00:29:45,233 --> 00:29:47,600 +Not a co, this is something that has no superclass, +基类就是指没有父类的类, + +695 +00:29:47,602 --> 00:29:48,668 +like CalculatorBrain. +比如 CalculatorBrain + +696 +00:29:48,670 --> 00:29:50,469 +If they all have defaults, +如果它的所有的 property 都有默认值 + +697 +00:29:50,471 --> 00:29:53,939 +then you'll get an inits with no arguments for free. +那么你就会自动得到一个没有参数的 init 方法 + +698 +00:29:53,941 --> 00:29:56,508 +So, if we haven't implemented CalculatorBrains, init, +所以尽管我们没有为 CalculatorBrains 类写 init 方法, + +699 +00:29:56,510 --> 00:29:58,109 +of course, we still could have said. +我们依然可以写 + +700 +00:29:58,111 --> 00:30:00,378 +>> You know, brain = CalculatorBrain(). +brain = CalculatorBrain() + +701 +00:30:00,380 --> 00:30:03,280 +That's because we get a free init in calculator brain, +这是因为我们有一个默认的 init + +702 +00:30:03,282 --> 00:30:06,283 +cuz we initialized our default using equals something. +我们默认使用等于某值初始化 + +703 +00:30:06,285 --> 00:30:07,467 +Okay. So you, +所以 + +704 +00:30:07,468 --> 00:30:08,650 +that's one way to get an init. +这是一种得到 init 的方法 + +705 +00:30:08,653 --> 00:30:11,421 +A struct, not a class, but a struct, +结构体,不是类,但是结构体 + +706 +00:30:11,423 --> 00:30:15,324 +it will get a default one that has all the properties as +它将默认得到一个将所有 property 作为参数的初始化方法 + +707 +00:30:15,326 --> 00:30:18,627 +arguments only if you have no initializers. +仅当没有初始化函数时 + +708 +00:30:18,629 --> 00:30:21,897 +So if you had a struct and you gave it no initializers, +因此,如果你有一个结构体并且没有初始化方法 + +709 +00:30:21,899 --> 00:30:24,899 +you would get one for free, which would be init or +你会得到一个默认的初始化方法 + +710 +00:30:24,901 --> 00:30:27,935 +all the arguments match all of the vars you have. +并且所有的参数和变量匹配,如果有的话 + +711 +00:30:27,937 --> 00:30:29,970 +All the vars and lets, okay? +所有的 var 和 let,明白吧? + +712 +00:30:29,972 --> 00:30:35,108 +So here I got a struct, it has two properties there, x and y. +一个结构体,它有两个 property ,x 和 y + +713 +00:30:35,110 --> 00:30:38,945 +And you can see that I got this init, x takes an Int and +你可以看到我这里有一个 init 方法,x 是 Int类型 + +714 +00:30:38,947 --> 00:30:41,514 +a y String for free, for free. +y 是 String 类型 + +715 +00:30:41,516 --> 00:30:44,183 +I didn't have to implement that at all, it just came for +我不要实现它 + +716 +00:30:44,185 --> 00:30:45,684 +free and so people can call that. +它就可以被调用 + +717 +00:30:45,686 --> 00:30:48,186 +They can initialize MyStruct, by saying, +可以通过圆括号,提供 x 和 y 的值来 + +718 +00:30:48,188 --> 00:30:51,322 +MyStruct open parentheses and provide the x and the y. +初始化 MyStruct + +719 +00:30:51,324 --> 00:30:52,857 +Okay? + +720 +00:30:52,859 --> 00:30:54,058 +All right. + +721 +00:30:54,060 --> 00:30:56,727 +So, what can you do inside of init? +你可以在 init 里面做什么? + +722 +00:30:56,729 --> 00:30:57,895 +Okay. We saw, +好,我们看到 + +723 +00:30:57,896 --> 00:30:59,062 +what we did in calculator brain, +我们在 CalculatorBrain 里做了什么 + +724 +00:30:59,064 --> 00:31:00,763 +we initialized some stuff. +我们初始化了些 property + +725 +00:31:00,765 --> 00:31:02,498 +But what can you do? +你可以做什么? + +726 +00:31:02,499 --> 00:31:04,232 +Well, you can set any properties value in there. +你可以在里面设置任何 property 的值 + +727 +00:31:04,235 --> 00:31:05,300 +You can even set +你甚至可以 + +728 +00:31:05,302 --> 00:31:07,235 +properties that have default values. +给 property 设置默认值 + +729 +00:31:07,237 --> 00:31:09,771 +So even if you have properties set equals 12. +即使你把它设置为等于12 + +730 +00:31:09,773 --> 00:31:12,540 +In your init, you can reset that thing to something else +在你的 init 里,你可以把一些东西重置为别的什么 + +731 +00:31:12,542 --> 00:31:15,109 +if you wanted to, if you changed your mind in init. +如果你想的话 + +732 +00:31:15,111 --> 00:31:16,010 +Okay? + +733 +00:31:16,012 --> 00:31:16,910 +You can do that. +你可以这样做 + +734 +00:31:16,912 --> 00:31:20,913 +You can also set constant properties. +你也可以给常量 property 赋值 + +735 +00:31:20,915 --> 00:31:24,817 +So if you have a struct or a class and +如果你有一个结构体或者类 + +736 +00:31:24,819 --> 00:31:31,189 +it has let x colon String, you can set that in your init. +它有一个 property: let x: String + +737 +00:31:31,191 --> 00:31:34,192 +Even though to let, it's gotta get set some time in your init +即使是 let,它也可以在 init 里 + +738 +00:31:34,194 --> 00:31:35,326 +is when you can set it. +被你赋值 + +739 +00:31:35,328 --> 00:31:37,094 +You can also say, equal something, but +也可以是等于其他什么 + +740 +00:31:37,096 --> 00:31:38,495 +you can also set it in your init. +你可以在 init 里这么做 + +741 +00:31:38,497 --> 00:31:40,230 +Okay? + +742 +00:31:40,231 --> 00:31:41,964 +So people sometimes don't understand, realize, +人们有时不理解 + +743 +00:31:41,967 --> 00:31:44,567 +they're like, oh, I can have lets in my class? +他们肯定在想,哦,在我的 class 里可以有 let? + +744 +00:31:44,569 --> 00:31:46,602 +Can have like, you know, constants for +可有一样,你知道的 + +745 +00:31:46,604 --> 00:31:49,038 +my class that are created at initialization and +类里的常量在初始化和创建实例 + +746 +00:31:49,040 --> 00:31:51,306 +stay the same for the lifetime of instance and +的生命周期里是保持不变的 + +747 +00:31:51,308 --> 00:31:54,242 +absolutely you can and you initialize them in your init. +你绝对可以在 init 里初始化它们 + +748 +00:31:54,244 --> 00:31:55,443 +Okay. + +749 +00:31:55,444 --> 00:31:56,643 +That's actually a good practice if +这实际上是很好的做法 + +750 +00:31:56,646 --> 00:32:00,214 +you have something that's, you know, constant like that. +如果你需要定义常量属性 + +751 +00:32:00,216 --> 00:32:04,385 +You can call other init methods in your own class or +在你的类或者结构体里你可以调用其他的 init 方法 + +752 +00:32:04,387 --> 00:32:06,687 +struct using self.init. +使用 self.init + +753 +00:32:06,689 --> 00:32:08,422 +Okay? + +754 +00:32:08,423 --> 00:32:10,156 +Self.init, you can call the other ones with the ones that +self.init,你可以调用有不同参数的 + +755 +00:32:10,158 --> 00:32:11,524 +have different arguments. +其他 init 方法 + +756 +00:32:11,526 --> 00:32:13,026 +Okay? + +757 +00:32:13,027 --> 00:32:14,527 +So that sounds good. +所以听起来很不错 + +758 +00:32:14,529 --> 00:32:18,297 +And of course in a class, you can call super.init. +当然,在类里你也可以调用 super.init + +759 +00:32:18,299 --> 00:32:20,132 +Call your superclass's initializers, +调用你父类的初始化方法 + +760 +00:32:20,134 --> 00:32:22,267 +what their arguments whatever, they might be. +参数无论是什么,如果有的话 + +761 +00:32:22,269 --> 00:32:26,237 +However, big old humongous, however on this one. +然而很重要的是 + +762 +00:32:26,239 --> 00:32:28,205 +There are a lot of rules for +调用其他的 init 时有很多规则 + +763 +00:32:28,207 --> 00:32:31,842 +calling other inits, especially in classes. +尤其是在类里 + +764 +00:32:31,844 --> 00:32:34,077 +They instruct, it's not a big deal. +在结构体里,这并不是一个大问题 + +765 +00:32:34,078 --> 00:32:36,311 +But in classes, there's a lot of rules and were gonna take +但在类里,有很多规则,我们将拿两个幻灯片 + +766 +00:32:36,314 --> 00:32:39,182 +two slides here to go through these rules briefly. +对这些规则做简单介绍 + +767 +00:32:39,184 --> 00:32:39,849 +All right. + +768 +00:32:39,851 --> 00:32:41,116 +So as part of these rules, +所以作为这些规则的一部分 + +769 +00:32:41,118 --> 00:32:43,118 +what do you required to do inside of init? +你需要在 init 里做些什么? + +770 +00:32:43,120 --> 00:32:45,186 +What is mandatory for you to do? +什么是你必须要做的? + +771 +00:32:45,188 --> 00:32:48,156 +Well, as you know, you have to have initialized all +好,正如你所知道的,在你的类里 + +772 +00:32:48,158 --> 00:32:50,324 +the properties in your entire class. +所有的 property 都必须初始化 + +773 +00:32:50,326 --> 00:32:52,659 +You can not start a class off with no value. +他们都必须有值 + +774 +00:32:52,661 --> 00:32:56,163 +And remember, Optionals, nil is a value for an Optional. +记住,对于 Optionals,nil 也是值 + +775 +00:32:56,165 --> 00:32:58,498 +So if an Optional is nil, it is set. +所以,如果你有一个 Optional 是 nil,这也算它有值 + +776 +00:32:58,500 --> 00:32:59,766 +So, everything's fine there. +一切都好了 + +777 +00:32:59,768 --> 00:33:03,202 +There are two times, type, +在类里,Swift 提供两种类型 + +778 +00:33:03,204 --> 00:33:05,504 +types of inits in a class. +的构造器来初始化 + +779 +00:33:05,506 --> 00:33:06,805 +Not in a struct, but in a class. +不是在结构体里,在类里 + +780 +00:33:06,807 --> 00:33:09,007 +One is called a convenience init and +一种是 Convenience Init + +781 +00:33:09,009 --> 00:33:11,242 +then there's all the other kinds. +其它的都是另一种类型 + +782 +00:33:11,244 --> 00:33:13,377 +Those are called designated initializers. +叫 Designated Initializers + +783 +00:33:13,379 --> 00:33:15,012 +So by default, an initializer is +默认的 initializer + +784 +00:33:15,014 --> 00:33:17,647 +called a designated initializer, but there's also +是 designated initializer,但是另外还有些 + +785 +00:33:17,649 --> 00:33:20,116 +these things called convenience initializers. +叫 convenience initializers + +786 +00:33:20,118 --> 00:33:21,384 +And we make this distinction, +我们得做出区分 + +787 +00:33:21,386 --> 00:33:23,886 +because there's a little bit different rules about them. +因为它们的规则有一点点的不同 + +788 +00:33:23,888 --> 00:33:25,220 +So lets talk about that. +我们来看看吧 + +789 +00:33:25,222 --> 00:33:28,056 +A designated initializer, one that doesn't take +Designated initializer,不能有 + +790 +00:33:28,058 --> 00:33:29,858 +convenience in the front of it. +convenience 在它的前面 + +791 +00:33:29,860 --> 00:33:31,325 +It has to, and +它只能 + +792 +00:33:31,327 --> 00:33:37,564 +can only call a designated initializer in its superclass. +调用其父类的 designated initializer + +793 +00:33:37,566 --> 00:33:38,899 +It's a very important rule. +这是一个非常重要的规则 + +794 +00:33:38,901 --> 00:33:40,601 +Okay. If you + +795 +00:33:40,602 --> 00:33:42,302 +have a designated initializer, initializer doesn't have +如果有一个 designated initializer + +796 +00:33:42,304 --> 00:33:43,936 +the word convenience in front of it, +它前面没有 convenience 这个单词在 + +797 +00:33:43,938 --> 00:33:45,838 +it can't call another init in your class. +在你的类里不能调用其他的 init 方法 + +798 +00:33:45,840 --> 00:33:47,706 +It has to call a superclass in init and +必须在 init 里调用父类的 init + +799 +00:33:47,708 --> 00:33:49,808 +it has to be a designated initializer not +而且它必须是一个 designated initializer + +800 +00:33:49,810 --> 00:33:52,243 +a convenience initializer in the superclass. +而不是 convenience initializer + +801 +00:33:52,245 --> 00:33:53,878 +Okay? + +802 +00:33:53,880 --> 00:33:56,280 +Understand that rule number one? +理解第一条规则了吗? + +803 +00:33:56,282 --> 00:33:57,314 +That's your designated initial. +这就是你们的预设初始化(designated initial) + +804 +00:33:57,316 --> 00:33:59,183 +This is all, by +这就是全部了 + +805 +00:33:59,184 --> 00:34:01,051 +the way in the documentation It's very elaborately. +顺便说一下,在文档中有详细的描述 + +806 +00:34:01,053 --> 00:34:02,485 +Drawn out with pictures and all that. +有图表之类的说明 + +807 +00:34:02,487 --> 00:34:04,020 +I'm just trying to summarize it here. +我这里只是大概提一下 + +808 +00:34:04,022 --> 00:34:05,488 +Okay. Hopefully, +希望 + +809 +00:34:05,489 --> 00:34:06,955 +you've read that already and this is review. +你们已经读了文档,这是复习 + +810 +00:34:06,958 --> 00:34:09,458 +But if not, hopefully you're understanding a little bit of +如果没有,希望你们能理解一点 + +811 +00:34:09,460 --> 00:34:11,093 +what I'm saying. +我所说的 + +812 +00:34:11,094 --> 00:34:12,727 +Tonight when you read it, you'll be, oh yeah, I get it. +今晚,当你们阅读文档时,就会明白了 + +813 +00:34:12,730 --> 00:34:14,262 +Okay. So that's the rule for +这就是 + +814 +00:34:14,264 --> 00:34:15,897 +designating initializer. +designating initializer 的规则 + +815 +00:34:15,899 --> 00:34:19,233 +You have to initialize all of your own +你必须在调用父类的初始化函数前 + +816 +00:34:19,235 --> 00:34:24,838 +properties before you call your superclass's initializer. +先初始化你自己的所有的 property + +817 +00:34:24,840 --> 00:34:25,572 +Okay? This is for +只有 designated initializers + +818 +00:34:25,574 --> 00:34:26,939 +designated initializers only, +需要这样 + +819 +00:34:26,941 --> 00:34:29,342 +cuz they are the ones who call supervisors initializers. +因为他们调用 supervisors initializers + +820 +00:34:29,344 --> 00:34:32,478 +So you have to be done with your own properties before you +所以你必须在调用父类的 property 前 + +821 +00:34:32,480 --> 00:34:34,046 +call your superclass's. +先处理你自己(类)的 property + +822 +00:34:34,048 --> 00:34:36,348 +This one will trip you up, often. +这经常让你有些麻烦 + +823 +00:34:36,350 --> 00:34:39,350 +Okay? You also have to call your +你要先调用 + +824 +00:34:39,352 --> 00:34:43,420 +superclass's init before you assign a value to +父类的初始化函数,然后才能给继承自父类的 + +825 +00:34:43,422 --> 00:34:47,557 +any property you inherit from your superclass. +property 赋值 + +826 +00:34:47,559 --> 00:34:49,125 +In other words, +也就是说, + +827 +00:34:49,126 --> 00:34:50,692 +you have to let your superclass's initialize, +你必须先让你的父类初始化它的 property, + +828 +00:34:50,695 --> 00:34:53,262 +it's properties before you can start setting them. +然后你才能给它们赋值 + +829 +00:34:53,264 --> 00:34:54,963 +So you get those three rules? +你们现在明白这三条规则了吗? + +830 +00:34:54,965 --> 00:34:56,832 +Okay. + +831 +00:34:56,833 --> 00:34:58,700 +That has to do with, so you're superclass, cuz it has to do +这和你们的父类有关,因为它必须处理 + +832 +00:34:58,702 --> 00:35:01,302 +with designated intitializers and calling super. +designated intitializers 并调用它的父类(的初始化函数) + +833 +00:35:01,304 --> 00:35:02,921 +All right. Now + +834 +00:35:02,922 --> 00:35:04,539 +a convenience initializer has different rules. +convenience initializer 有不同的规则 + +835 +00:35:04,541 --> 00:35:06,073 +Okay? First of all, +首先, + +836 +00:35:06,075 --> 00:35:09,243 +a convenience initializer must and +convenience initializer 必须 + +837 +00:35:09,245 --> 00:35:14,581 +can only call a designated initializer in it's own class. +而且只能调用本类的 designated initializer + +838 +00:35:14,583 --> 00:35:16,249 +Convenience initializer, +Convenience initializer, + +839 +00:35:16,251 --> 00:35:19,118 +initializer cannot call super init of any kind. +这类初始化函数不能调用任何父类的初始化函数 + +840 +00:35:19,120 --> 00:35:21,653 +And it can't call and it must call a, +它必须调用 + +841 +00:35:21,655 --> 00:35:23,388 +a designated initializer. +designated initializer + +842 +00:35:23,390 --> 00:35:26,358 +Now it can call that designated initializer +它能通过调用其他的 convenience initializer + +843 +00:35:26,360 --> 00:35:29,860 +indirectly through another convenience initializer. +间接调用 designated initializer + +844 +00:35:29,862 --> 00:35:31,312 +Okay. + +845 +00:35:31,313 --> 00:35:32,763 +So one convenience initializer can call self another +因此 convenience initializer 能调用本类其他 + +846 +00:35:32,765 --> 00:35:35,866 +convenience initializer, which called designated initializer. +调用 designated initializer 的 convenience initializer + +847 +00:35:35,868 --> 00:35:39,268 +But eventually, a designated initializer must be called. +但最后,有个 designated initializer 必须被调用 + +848 +00:35:39,270 --> 00:35:40,870 +Okay? + +849 +00:35:40,872 --> 00:35:43,906 +A convenience initializer must call that +一个 convenience initializer 必须先直接或 + +850 +00:35:43,908 --> 00:35:46,775 +designated initializer, directly or +间接调用 designated initializer, + +851 +00:35:46,777 --> 00:35:50,945 +indirectly before it can touch any values, obviously. +然后才能访问其他的值 + +852 +00:35:50,947 --> 00:35:52,263 +Okay? + +853 +00:35:52,264 --> 00:35:53,580 +You have to kinda get the main, your +你必须让主要的, + +854 +00:35:53,583 --> 00:35:56,483 +object primarily initialized before you can have +你的对象首先被初始化,然后你才能 + +855 +00:35:56,485 --> 00:36:00,253 +the convenience initializer start hacking at properties. +让 convenience initializer 开始访问 property + +856 +00:36:00,255 --> 00:36:03,356 +The calling of other inits, whether your a convenience guy +其他初始化函数的调用,不管是你的 convenience initializer + +857 +00:36:03,358 --> 00:36:06,125 +calling your designator or whether your a designator +调用你的 designator initializer,还是你的 designator initializer + +858 +00:36:06,127 --> 00:36:08,961 +calling up to your supers designator has to be complete +调用你父类的 designator initializer, + +859 +00:36:08,963 --> 00:36:12,197 +before you can start accessing your properties and methods. +所有这些都必须在你开始访问 property 和方法之前完成 + +860 +00:36:12,199 --> 00:36:15,400 +In other words, the class has to be initialized before you +也就是说,这个类必须被初始化,然后 + +861 +00:36:15,402 --> 00:36:17,869 +can start calling methods and properties. +你才能开始调用方法和 property + +862 +00:36:17,871 --> 00:36:19,838 +Okay? + +863 +00:36:19,839 --> 00:36:21,806 +That's why we have to use lazy if we want a property to +这就是为什么我们必须使用 lazy 的方式, + +864 +00:36:21,808 --> 00:36:24,275 +set its value to be calling a method. +如果想让 property 在被调用方法的时候被赋值 + +865 +00:36:24,277 --> 00:36:25,943 +Because we can't do it non-lazily, +因为我们不能使用 non-lazily 的方式 + +866 +00:36:25,945 --> 00:36:28,245 +because we wouldn't be initialized at that time. +因为那时我们还没被初始化 + +867 +00:36:28,247 --> 00:36:30,113 +We'd still be in the process of initializing. +我们还在初始化过程中 + +868 +00:36:30,115 --> 00:36:31,981 +It's kind of a two phase initialization. +这如同初始化的两个阶段 + +869 +00:36:31,983 --> 00:36:36,652 +You get fully initialized, now you can go do that. +完全初始化之后,你就能那样做了 + +870 +00:36:36,654 --> 00:36:38,120 +Okay? So these are the rules. +这就是(初始化的)规则了 + +871 +00:36:38,122 --> 00:36:40,139 +Question? +有问题吗? + +872 +00:36:40,140 --> 00:36:42,157 +Is there a way to set the constant then by +(学生提问) + +873 +00:36:42,159 --> 00:36:43,691 +by calling a method? +(学生提问) + +874 +00:36:43,693 --> 00:36:44,942 +So the question is, +问题是, + +875 +00:36:44,943 --> 00:36:46,192 +is there a way to set constant by calling a method or +有没有一种方式,可以调用方法或者类似的途径 + +876 +00:36:46,195 --> 00:36:47,027 +something like that? +给常量赋值 + +877 +00:36:47,029 --> 00:36:47,828 +And the answer is no. +答案是不能 + +878 +00:36:47,830 --> 00:36:49,029 +Okay. + +879 +00:36:49,031 --> 00:36:52,098 +You can only set constants either setting them equals +你只能给常量赋予等于的某个值, + +880 +00:36:52,100 --> 00:36:54,033 +something or in your initializers. +或者在你的初始化函数中 + +881 +00:36:54,035 --> 00:36:57,969 +Unfortunately, later we can't do it. +不幸的是,之后我们不能做这些了 + +882 +00:36:57,971 --> 00:36:59,104 +Okay. + +883 +00:36:59,106 --> 00:37:01,239 +Let's talk about inheriting init. +让我们聊聊继承式初始化 + +884 +00:37:01,241 --> 00:37:02,507 +Okay? + +885 +00:37:02,508 --> 00:37:03,774 +Cuz this is complicated, as well. +这也很复杂 + +886 +00:37:03,776 --> 00:37:05,876 +So here are the rules for inheriting init. +这就是继承式初始化的规则了 + +887 +00:37:05,878 --> 00:37:10,413 +If you do not implement any designated initializers in +如果你没有在你的类中实现任何 designated initializers , + +888 +00:37:10,415 --> 00:37:14,250 +your class, any, then you'll inherit all of +那么,你将继承你父类中的 + +889 +00:37:14,252 --> 00:37:18,320 +your superclass's designated initializers. +所有 designated initializers + +890 +00:37:18,322 --> 00:37:20,889 +Otherwise, you'll inherit none of your de, +否则,你将不继承任何你的父类中的 + +891 +00:37:20,891 --> 00:37:23,358 +superclass's designated initializers. +designated initializers + +892 +00:37:23,360 --> 00:37:25,059 +Okay? + +893 +00:37:25,061 --> 00:37:28,396 +It's all or nothing on designated initializers. +要么就是继承全部的 designated initializers,要么就是一个都不继承 + +894 +00:37:28,398 --> 00:37:33,934 +If you override all of your superclass's designated inits. +如果你覆盖了你父类中的所有 designated initializers, + +895 +00:37:33,936 --> 00:37:34,668 +Okay? + +896 +00:37:34,670 --> 00:37:36,536 +All, so your superclass has +比如,你的父类中有 + +897 +00:37:36,537 --> 00:37:38,403 +three designated initializers with different arguments. +三种不同参数的 designated initializers, + +898 +00:37:38,406 --> 00:37:41,607 +If you override all of them, then you'll inherit all of +如果你重写了所有这些方法,那么你就继承了父类中所有的 + +899 +00:37:41,609 --> 00:37:44,443 +your superclass's convenient initializers. +convenient initializers + +900 +00:37:44,445 --> 00:37:46,778 +Also, if you implement none of them. +同样,如果你没有实现它们中的任一个方法, + +901 +00:37:46,780 --> 00:37:48,947 +Because you'll essentially inherit all +在这种情况下,你将继承 + +902 +00:37:48,949 --> 00:37:51,816 +the designateds and all the convenience in that case. +所有 designated 和 convenience initializer + +903 +00:37:51,818 --> 00:37:53,884 +Okay? + +904 +00:37:53,886 --> 00:37:55,419 +So that's the inheritance rule. +这就是继承的规则 + +905 +00:37:55,421 --> 00:37:56,520 +This trips people up, too. +这让人有点搞不懂 + +906 +00:37:56,522 --> 00:37:57,587 +They're like, oh yeah, +他们说,哦耶, + +907 +00:37:57,589 --> 00:37:59,255 +I implemented that one initializer, but +我实现了一个初始化 + +908 +00:37:59,257 --> 00:38:01,190 +how come the other initializer doesn't work? +但是其他的初始化为什么没用? + +909 +00:38:01,192 --> 00:38:02,624 +Well, because once you initiali... +好吧,因为一旦你初始化 + +910 +00:38:02,626 --> 00:38:04,326 +implement one designated initializer, +执行一个 designated initializer + +911 +00:38:04,328 --> 00:38:05,827 +you don't inherit the rest of them. +你就不必继承其他的 + +912 +00:38:05,829 --> 00:38:08,129 +Okay? + +913 +00:38:08,130 --> 00:38:10,430 +So it's all or nothing on designateds. +所以对于 designated initializers 不是全有就是全无 + +914 +00:38:10,433 --> 00:38:13,067 +And on convenience, it's kind of all or nothing too. +而对于 convenience 也一样如此 + +915 +00:38:13,069 --> 00:38:15,936 +Cuz you have to implement or not implement all of +因为为了执行 convenience,你必须全实现或者 + +916 +00:38:15,938 --> 00:38:18,939 +the designateds to get the conveniences. +全不实现 designated initializers + +917 +00:38:18,941 --> 00:38:23,876 +Any init that you inherit by these rules that I just said, +任何 init,如果是按照我刚才说的规则继承而来的话 + +918 +00:38:23,878 --> 00:38:27,880 +count for all the rules on the previous slide. +包括之前幻灯片提到的所有规则 + +919 +00:38:27,882 --> 00:38:30,849 +I'm not gonna go back to the previous slide and go through +在这里,我就不回顾之前幻灯片的内容了 + +920 +00:38:30,851 --> 00:38:33,852 +them all, but you can satisfy a lot of the requirements in +不过,其实就这样继承 initializer 就可以满足 + +921 +00:38:33,854 --> 00:38:36,988 +the previous slide by just inheriting your initializers. +很多之前的幻灯片里讲的规则了 + +922 +00:38:36,990 --> 00:38:38,289 +Okay? + +923 +00:38:38,291 --> 00:38:39,757 +But you have, +但是你 + +924 +00:38:39,758 --> 00:38:41,224 +you can only inherit them in these kind of restricted ways. +只能通过这种受限制的方法去继承它们 + +925 +00:38:41,227 --> 00:38:42,426 +But once you do, +不过只要你这么做了 + +926 +00:38:42,428 --> 00:38:46,063 +you can satisfy a lot of those previous rules. +之前的所有规则就都可以满足了 + +927 +00:38:46,065 --> 00:38:48,999 +It is possible to have what's called a required init. +可能有人问什么是 required init + +928 +00:38:49,001 --> 00:38:51,034 +You just put required on it. +就是在前面写上 required + +929 +00:38:51,036 --> 00:38:52,268 +And if you put required, +如果你写上 required, + +930 +00:38:52,270 --> 00:38:54,536 +it means that subclasses must implement it. +那么它的子类就必须实现这个方法 + +931 +00:38:54,538 --> 00:38:56,722 +It is required. +这就是 required + +932 +00:38:56,723 --> 00:38:58,907 +Now they can inherit it by the rules above. +现在通过遵守上面的规则,你可以继承它了 + +933 +00:38:58,909 --> 00:39:00,241 +In other words, if they don't, +换句话说,如果没有实现 + +934 +00:39:00,243 --> 00:39:02,043 +implement any designated negative initializers, +任何 designated initializers + +935 +00:39:02,045 --> 00:39:04,578 +they'll inherit the required initializer, that's good. +它们将会继承 required 的初始化,这非常棒 + +936 +00:39:04,580 --> 00:39:07,948 +But if you implement any of the designated initializers, +但是如果你实现了任何一个 designated initializers, + +937 +00:39:07,950 --> 00:39:10,217 +you must implement the required ones. +你就必须实现 required 的那些 + +938 +00:39:10,219 --> 00:39:11,885 +Okay? + +939 +00:39:11,887 --> 00:39:15,554 +Finally, there's failable initializers. +最后,再说说 failable initializers + +940 +00:39:15,556 --> 00:39:18,357 +Okay? + +941 +00:39:18,358 --> 00:39:21,159 +So some initializers are allowed to fail and return nil. +有一些 initializer 允许失败并且返回 nil + +942 +00:39:21,161 --> 00:39:22,878 +Okay? + +943 +00:39:22,879 --> 00:39:24,596 +You, you designate them by putting question mark +你在初始化完成后,可以加个注释 + +944 +00:39:24,598 --> 00:39:26,931 +after the init, like this right here. +就像我这里一样 + +945 +00:39:26,933 --> 00:39:28,316 +Okay? + +946 +00:39:28,317 --> 00:39:29,700 +Now, this is pretty uncommon. +现在,这是很少见的 + +947 +00:39:29,702 --> 00:39:31,702 +Okay? You don't see +明白吗?你们不经常见这些 + +948 +00:39:31,703 --> 00:39:33,703 +these very often and the documentation last I checked, +我上次查文档的时候, + +949 +00:39:33,706 --> 00:39:35,739 +doesn't really show this very well. +它也没描述的特别仔细 + +950 +00:39:35,741 --> 00:39:37,574 +It doesn't put the question mark in there. +它没有把问号写在那儿 + +951 +00:39:37,576 --> 00:39:38,541 +I think it's just +我觉得是 + +952 +00:39:38,543 --> 00:39:41,010 +a documentation generation problem. +生成文档的时候出现的问题 + +953 +00:39:41,012 --> 00:39:43,712 +It will say in, in the comment for +它会在初始化的时候提示 + +954 +00:39:43,714 --> 00:39:46,915 +the init, this can return nil, if it fails. +这个可能会返回 nil ,如果失败的话 + +955 +00:39:46,917 --> 00:39:48,083 +But it doesn't put, +但是它没有写, + +956 +00:39:48,084 --> 00:39:49,250 +the question mark on there. +应该是把问号写在那儿 + +957 +00:39:49,252 --> 00:39:51,419 +But that's okay, because when you start using it, +但是没关系,因为当你用它的时候 + +958 +00:39:51,421 --> 00:39:53,087 +you're gonna call this initializer. +你就会调用它 + +959 +00:39:53,089 --> 00:39:54,988 +And the thing's gonna come back and you're gonna try and +回调了之后你尝试 + +960 +00:39:54,990 --> 00:39:55,722 +send messages to it. +给它发送一个消息 + +961 +00:39:55,724 --> 00:39:57,524 +And it's gonna say, +它会提示 + +962 +00:39:57,525 --> 00:39:59,325 +this isn't Optional, does not respond to the method. +这个方法不是 Optional 的,没有对应的方法 + +963 +00:39:59,327 --> 00:40:00,159 +And you're like, what? +你会惊讶,我擦! + +964 +00:40:00,161 --> 00:40:01,294 +Isn't Optional? +它不是 Optional? + +965 +00:40:01,295 --> 00:40:02,428 +And then you're gonna know. +然后你就会瞬间反应过来 + +966 +00:40:02,429 --> 00:40:03,562 +Oh, the initializer was failable. +哦,这是个 failable initializer + +967 +00:40:03,564 --> 00:40:05,698 +So let's look at an example of this. +来,我们来看这个例子 + +968 +00:40:05,700 --> 00:40:07,065 +So UIImage. +关于 UIImage + +969 +00:40:07,067 --> 00:40:09,751 +Okay? + +970 +00:40:09,752 --> 00:40:12,436 +That's a class in UIKit. +它是 UIKit 中的一个类 + +971 +00:40:12,439 --> 00:40:14,772 +And it returns an image. +然后,它返回一个图片 + +972 +00:40:14,774 --> 00:40:17,107 +And you can ask for an image by its name. +你可以通过它的名称来获取图片 + +973 +00:40:17,109 --> 00:40:19,976 +But of course, that image named that might not be +当然,如果你的项目中如果不存在图片的话 + +974 +00:40:19,978 --> 00:40:23,346 +anywhere in your project, so this thing can return nil. +它就会返回 nil + +975 +00:40:23,348 --> 00:40:24,814 +So in this case right here, +那么在这里, + +976 +00:40:24,816 --> 00:40:27,316 +image equals UIImage named: "foo". +名为 "foo" 的图片赋值给 image + +977 +00:40:27,318 --> 00:40:29,284 +image is an Optional UIImage, +image 是一个 Optional UIImage + +978 +00:40:29,286 --> 00:40:32,320 +even I'm calling initializer there, right? +即使我调用了 initializer + +979 +00:40:32,322 --> 00:40:34,222 +UIImages initializer. +UIImages 的 initializer + +980 +00:40:34,224 --> 00:40:35,923 +It could be. So, +image 可以是 Optional + +981 +00:40:35,925 --> 00:40:38,092 +Usually, what we do in this case is we use if let. +这种情况下我们会用 if let + +982 +00:40:38,094 --> 00:40:41,061 +If we can let the image equal the image name foo, +如果 image = UIImage(name: "foo") 成立 + +983 +00:40:41,063 --> 00:40:42,863 +then we'll do what we want. +那么我们就处理相关的事件 + +984 +00:40:42,865 --> 00:40:44,464 +Otherwise, we couldn't find it. +不成立,不能创建图片 + +985 +00:40:44,466 --> 00:40:46,232 +So, we'll do whatever we do in that case. +这种情况下我们做点什么 + +986 +00:40:46,234 --> 00:40:47,500 +Okay? +是吗? + +987 +00:40:47,502 --> 00:40:48,734 +So watch out for those. +所以,多注意这些细节 + +988 +00:40:48,736 --> 00:40:51,670 +There's a few of them, a few dozen at the most. +这种情况非常少,最多不过十几种 + +989 +00:40:51,672 --> 00:40:52,937 +Yeah. +说你的问题 + +990 +00:40:52,939 --> 00:40:55,206 +So this is a replace like try-catch? +-(学生提问) + +991 +00:40:55,208 --> 00:40:58,642 +So the question is does this replace try-catch? +-问题是:这是 try-catch 的一个取代吗? + +992 +00:40:58,644 --> 00:41:00,611 +And we're not even going to talk about try-catch in +我们不打算谈论 try-catch + +993 +00:41:00,613 --> 00:41:01,979 +this class. +在这门课 + +994 +00:41:01,980 --> 00:41:03,346 +Okay? That's how rare it is. +好吗? try-catch 非常少见 + +995 +00:41:03,349 --> 00:41:06,816 +You don't even really use try-catch in Swift. +甚至在 Swift 中也很少用到它 + +996 +00:41:06,818 --> 00:41:10,353 +You know, things are Optionals make a lot of try-catch stuff +Optional 让 + +997 +00:41:10,355 --> 00:41:11,654 +just not necessary. +try-catch 变得不是必须的 + +998 +00:41:11,656 --> 00:41:13,422 +try-catch, for +对于那些不知道什么是 try-catch 的同学, + +999 +00:41:13,423 --> 00:41:15,189 +those of you who don't know, is you can raise exceptions in +try-catch 是你的程序引发异常时 + +1000 +00:41:15,192 --> 00:41:17,926 +your program and they can percolate up the callstack and +它们会遍历调用堆栈并且 + +1001 +00:41:17,928 --> 00:41:20,161 +someone tries to catch them and handle them. +查找处理此类异常的 catch 语句 + +1002 +00:41:20,163 --> 00:41:22,013 +Okay? +明白了吗? + +1003 +00:41:22,014 --> 00:41:23,864 +And that programming methodology is not one +这种编程方法并不是 + +1004 +00:41:23,867 --> 00:41:27,501 +that's really something that we use much in iOS. +iOS 开发中常用的一种方法 + +1005 +00:41:27,503 --> 00:41:28,635 +Okay? In Objective-C, +明白了吗?在 Objective-C 中 + +1006 +00:41:28,637 --> 00:41:30,537 +maybe it was used even a little more. +这种方法可能只会用了一点点 + +1007 +00:41:30,539 --> 00:41:32,171 +I'm not even sure about that but +对此我不是很确定但是 + +1008 +00:41:32,173 --> 00:41:34,674 +certainly in Swift we're not gonna be using that. +在 Swift 中,我们肯定不会使用它 + +1009 +00:41:34,676 --> 00:41:36,442 +I'm not, I'm not even gonna show it to your in this class. +在本课程的范围内,我甚至不会演示给你们怎么使用它 + +1010 +00:41:36,444 --> 00:41:40,679 +That's how unneed, unnecessary it is to know that. +不需要了解 + +1011 +00:41:40,681 --> 00:41:41,979 +Okay. +好的 + +1012 +00:41:41,981 --> 00:41:44,782 +So let's talk about creating objects, +让我们来讲一下如何创建对象 + +1013 +00:41:44,784 --> 00:41:47,718 +then you know to do it by putting the type and +创建一个对象的语法是,你在想要创建的类型之后 + +1014 +00:41:47,720 --> 00:41:52,022 +then parentheses and then the arguments to the initializer. +加上一对括号,括号内是初始化方法的参数 + +1015 +00:41:52,024 --> 00:41:53,457 +Okay. + +1016 +00:41:53,458 --> 00:41:54,891 +It's completely obvious there. +这里写的很清楚 + +1017 +00:41:54,893 --> 00:41:58,561 +You notice you don't always create objects by doing that. +你可能会发现你并不总是通过这种方式来创建对象 + +1018 +00:41:58,563 --> 00:42:01,196 +Sometimes, you will ask a class method or +有时候你会使用一个类方法或者 + +1019 +00:42:01,198 --> 00:42:02,931 +a type method to do it. +类型方法去创建一个对象 + +1020 +00:42:02,933 --> 00:42:04,632 +So here's one, buttonWithType. +这里就是一个例子,.buttonWithType + +1021 +00:42:04,634 --> 00:42:07,802 +You see that's being sent UIButton, the type. +你看到这个消息被发送给了 UIButton,一种类型 + +1022 +00:42:07,804 --> 00:42:09,236 +All right. It's not being sent to +消息并没有发送给一个 + +1023 +00:42:09,238 --> 00:42:11,238 +a UIButton, it's being sent to the type, +UIButton 的对象,而是一个类型 + +1024 +00:42:11,240 --> 00:42:12,639 +like we talked about before. +我记得我们之前讲过 + +1025 +00:42:12,641 --> 00:42:14,040 +And so sometimes, +还有一种情况 + +1026 +00:42:14,042 --> 00:42:16,976 +you'll be creating things that way very rarely. +这种情况比较少见,需要你用另外一种方式创建对象 + +1027 +00:42:16,978 --> 00:42:20,546 +They really, Apple's been moving away from that model +甚至连 Apple 都已经将它们从 Model 中移除 + +1028 +00:42:20,548 --> 00:42:24,049 +and more towards just using initializers and creating +而转向于使用初始化方法 + +1029 +00:42:24,051 --> 00:42:28,219 +things but there, there's some that, that do that. +但是仍有部分的情况会使用到这种创建对象的方法 + +1030 +00:42:28,221 --> 00:42:31,322 +Like remember UIImage on the previous page, +还记得上一页中的 UIImage 吗? + +1031 +00:42:31,324 --> 00:42:34,025 +that wasn't UIImage dot image named. +那个不是像 UIImage.imageNamed: 这样的 + +1032 +00:42:34,027 --> 00:42:37,094 +That's kind of how it used to be in Apple, now it's UIImage +以前 Apple 就用那种创建对象的方法,但是现在用 + +1033 +00:42:37,096 --> 00:42:39,996 +parentheses whatever, called a constructor. +UIImage().xxx,这个叫做 constructor + +1034 +00:42:39,998 --> 00:42:43,733 +Sometimes other objects will obviously create +有些时候其他对象会为你 + +1035 +00:42:43,735 --> 00:42:45,034 +objects for you. +创建一些对象 + +1036 +00:42:45,036 --> 00:42:49,137 +So like here's a really cool method in String called join. +例如在 String 中有一个非常酷的方法叫 join + +1037 +00:42:49,139 --> 00:42:51,856 +Okay? + +1038 +00:42:51,857 --> 00:42:54,574 +Join takes an Array of Strings and it will separate them by +Join 接受一个由字符串组成的数组并 + +1039 +00:42:54,577 --> 00:42:57,545 +whatever String you send join to. +用接收 join 消息的字符串把这个数组分离开 + +1040 +00:42:57,547 --> 00:43:00,447 +So comma.join up in Array will give you a comma +所以,",".join(myArray) 会返回给你一个 + +1041 +00:43:00,449 --> 00:43:03,316 +separated String, a String with the things, +由逗号分隔的字符串,就是说这个字符串 + +1042 +00:43:03,318 --> 00:43:05,685 +in the Array comma separated. +中间有一个逗号把前后分为两段 + +1043 +00:43:05,687 --> 00:43:08,388 +And that's obviously creating a new Array (shoule be String). +这明显是创建了一个新数组 + +1044 +00:43:08,390 --> 00:43:10,489 +So this, this is kind of completely obvious. +这确实很明显 + +1045 +00:43:10,491 --> 00:43:13,325 +But yes, some methods return objects to you that +是的,一些方法会返回 + +1046 +00:43:13,327 --> 00:43:14,593 +are created. +创建出来的对象给你 + +1047 +00:43:14,595 --> 00:43:16,478 +okay. + + +1048 +00:43:16,479 --> 00:43:18,362 +So let's talk now about AnyObject, +让我们讲一下 AnyObject + +1049 +00:43:18,365 --> 00:43:20,832 +this was brought up earlier. +这个在之前涉及过 + +1050 +00:43:20,834 --> 00:43:24,201 +AnyObject is kind of okay. +AnyObject 是某种 + +1051 +00:43:24,203 --> 00:43:26,103 +For the purposes of what you know so +为了方便理解 + +1052 +00:43:26,105 --> 00:43:28,005 +far, you can think of it as a type. +你可以认为它是一种类型 + +1053 +00:43:28,007 --> 00:43:30,273 +Okay? It's not really a type, but +明白了吗?但是事实上,这并不是一种类型 + +1054 +00:43:30,275 --> 00:43:33,476 +you can think of it as type, like Double or +但是你可以认为它是一种类型,就像 Double + +1055 +00:43:33,478 --> 00:43:35,277 +Array or whatever. +或者 Array 等等 + +1056 +00:43:35,279 --> 00:43:37,079 +And it's used primarily for +AnyObject 主要用于 + +1057 +00:43:37,081 --> 00:43:40,749 +compatibility with existing Objective-C APIs and iOS. +兼容现有 Objective-C API 和 iOS 代码 + +1058 +00:43:40,751 --> 00:43:42,584 +Okay. You're really not gonna use +你并不会经常使用 + +1059 +00:43:42,586 --> 00:43:45,820 +AnyObject to build your own data structures very much. +AnyObject 来构建你自己的数据结构 + +1060 +00:43:45,822 --> 00:43:47,689 +I suppose you could, but +你可以这样做 + +1061 +00:43:47,690 --> 00:43:49,557 +it'd be kind of, it'd be, again, kind of anti-Swift. +但是,这有一点点,不像 Swift 风格的做法 + +1062 +00:43:49,559 --> 00:43:54,161 +Swift is very much into strong typing and type inference and +Swift 是强类型语言,并有类型推断的特性 + +1063 +00:43:54,163 --> 00:43:55,929 +all that. +的那种语言 + +1064 +00:43:55,930 --> 00:43:57,696 +So you could, but I'm only gonna talk about it in the +当然你可以这么做,但是我只会在兼容性的问题上 + +1065 +00:43:57,699 --> 00:44:00,566 +context here of using it here as this compatibility thing. +讲到 AnyObject 的问题 + +1066 +00:44:00,568 --> 00:44:01,167 +All right? +明白了吗? + +1067 +00:44:01,169 --> 00:44:04,837 +So what is AnyObject? +什么是 AnyObject? + +1068 +00:44:04,839 --> 00:44:06,672 +Okay? And where will you see it? +还有,我们会在哪里用到它? + +1069 +00:44:06,674 --> 00:44:10,742 +So AnyObject, means a pointer to an object. +AnyObject 的意思是,指向一个对象的指针 + +1070 +00:44:10,744 --> 00:44:12,476 +Meaning, an instance of a class. +也就是说,一个类的实例 + +1071 +00:44:12,478 --> 00:44:13,310 +Okay? That you +明白吗? + +1072 +00:44:13,312 --> 00:44:14,978 +don't know what the class is. +只是你不知道它的类是什么 + +1073 +00:44:14,980 --> 00:44:18,848 +So it's just kind of pointer to unknown class. +所以它是指向一个未知类的指针 + +1074 +00:44:18,850 --> 00:44:20,016 +Okay? Which it seems kind of +有问题吗?这可能听上去 + +1075 +00:44:20,018 --> 00:44:21,617 +weird and it is kind of weird. +有些奇怪,确实它有些奇怪 + +1076 +00:44:21,619 --> 00:44:24,786 +And you, so we gonna have to play around to be able to +你们会考虑,我们到底会在什么情况下使用到它 + +1077 +00:44:24,788 --> 00:44:26,921 +use it but that's what it is. +但这里我想告诉你们的是,它是什么 + +1078 +00:44:26,923 --> 00:44:29,524 +And where will you see this in iOS? +在 iOS 开发中,哪里能看到它呢? + +1079 +00:44:29,526 --> 00:44:32,360 +Sometimes, you'll see properties that are in +有些时候你会看到某些属性的类型是 AnyObject 的 + +1080 +00:44:32,362 --> 00:44:36,430 +AnyObject, like there's a property on storyboard segues +例如我们下周会讲到的 + +1081 +00:44:36,432 --> 00:44:38,932 +which we're gonna talk about next week. +在 Storyboard Segues 的一个属性 + +1082 +00:44:38,934 --> 00:44:41,401 +Called destinationViewController, +这个属性叫 destinationViewController + +1083 +00:44:41,403 --> 00:44:44,403 +instead of being a UIViewController (which) is a type, +它不是以 UIViewController 作为它的类型 + +1084 +00:44:44,405 --> 00:44:45,604 +it's AnyObject. +而是 AnyObject + +1085 +00:44:45,606 --> 00:44:47,572 +Okay, for historical reasons really. +这是某些历史遗留问题造成的 + +1086 +00:44:47,574 --> 00:44:50,842 +And similarly, in UIViewController, +类似的,在 UIViewController 中 + +1087 +00:44:50,844 --> 00:44:53,978 +there is a property called toolbarItems and +有一个叫 toolbarItems 的属性 + +1088 +00:44:53,980 --> 00:44:57,148 +it would return to an Array of the AnyObject. +它会返回一个由 AnyObject 组成的数组 + +1089 +00:44:57,150 --> 00:44:59,083 +Okay? + + +1090 +00:44:59,084 --> 00:45:01,017 +So basically, these properties are giving you back things you +基本上,这些属性返回给你一些 + +1091 +00:45:01,020 --> 00:45:02,552 +don't even know what they are. +你都不知道是什么类型的东西 + +1092 +00:45:03,989 --> 00:45:05,421 +Kay? + + +1093 +00:45:05,423 --> 00:45:07,623 +You'll also see them as arguments to functions. +还有,你会在函数的参数中见到 AnyObject + +1094 +00:45:07,625 --> 00:45:09,625 +Like here is +类似在这里一样 + +1095 +00:45:09,626 --> 00:45:11,626 +a UIViewController method prepare for segue. +一个 UIViewController 的方法 prepareForSegue + +1096 +00:45:11,629 --> 00:45:13,462 +It takes a normal argument there, segue, but +它接受一个普通的参数,segue,但是它还接受一个 + +1097 +00:45:13,464 --> 00:45:16,364 +then it also takes a sender, which can be AnyObject. +sender 参数,这个参数的类型是 AnyObject 的 + +1098 +00:45:17,834 --> 00:45:19,366 +Now in that case, it kinda makes sense because it +在这个情况下,AnyObject 的说法更有道理 + +1099 +00:45:19,368 --> 00:45:21,068 +really could be AnyObject in that case, +因为 Sender 确实可以是任意对象 + +1100 +00:45:21,070 --> 00:45:23,703 +cuz whatever's causing the segue to happen in a user +因为无论什么导致 UI 中 Segue 发生的东西 + +1101 +00:45:23,705 --> 00:45:27,006 +interface, could be AnyObject, so it makes some sense. +都可以是任意对象,所以这么就说通了 + +1102 +00:45:27,008 --> 00:45:30,276 +But there's addConstraints, kay? +但这里是 addConstraints + +1103 +00:45:30,278 --> 00:45:32,311 +Which is another UIViewController thing. +也是一种跟 UIViewController 类似的东西 + +1104 +00:45:32,313 --> 00:45:34,746 +And you add the constraints, you think that would be +如果你加了 constraints,你可以认为 + +1105 +00:45:34,748 --> 00:45:36,715 +Array of whatever class constraints are, +那是一个 constraints 的 Array,不管 constraints 是什么类型 + +1106 +00:45:36,717 --> 00:45:38,483 +I haven't taught you about this, but +我还没有教你们这些 + +1107 +00:45:38,485 --> 00:45:41,285 +these are the constraints that do all our UI shifting. +这些 constraints 都是用来控制 UI 的移位 + +1108 +00:45:41,287 --> 00:45:44,455 +But again, for historical reasons, it's an Array of +但是,由于历史遗留问题 + +1109 +00:45:44,457 --> 00:45:47,290 +AnyObject and even in a appendDigit in calculator. +这是一个任意对象的 Array ,甚至是计算器里的 appendDigit + +1110 +00:45:47,292 --> 00:45:51,294 +Okay, remember, when we drag, control, dragged the button to +记住,当我按住 control + +1111 +00:45:51,296 --> 00:45:54,430 +make a appendDigit, and I made a big deal of of saying, +拖动按钮去生成一个 appendDigit 的,我们其实是在说 + +1112 +00:45:54,432 --> 00:45:57,433 +change that from AnyObject to UI button, okay? +把那个任意对象变成一个 UI Button + +1113 +00:45:57,435 --> 00:46:01,070 +Well, if you hadn't changed it, then you could've ended up +如果你还没改变这个,你最后可能会得到 + +1114 +00:46:01,072 --> 00:46:03,305 +with a appendDigit, sender AnyObject. +一个 appendDigit(sender: AnyObject) + +1115 +00:46:03,307 --> 00:46:03,872 +Kay? + + +1116 +00:46:05,442 --> 00:46:08,142 +It also can even be the return type for fun, for functions, +这甚至可以作为函数返回对象 + +1117 +00:46:08,144 --> 00:46:10,577 +like that buttonWithType I talked about a few slides ago? +就像是前几张幻灯片中我说过的那个 buttonWithType 函数 + +1118 +00:46:10,579 --> 00:46:12,112 +It actually returns AnyObject, +它其实返回 AnyObject + +1119 +00:46:12,114 --> 00:46:14,948 +it doesn't return a UI button, you would think it would, but +这不会返回一个 UI Button,你可能想这会返回这样一个类型 + +1120 +00:46:14,950 --> 00:46:16,916 +it doesn't, it returns AnyObject. +但其实不会,他会返回 AnyObject + +1121 +00:46:16,918 --> 00:46:18,684 +Okay, so, this, +就是这样 + +1122 +00:46:18,686 --> 00:46:20,519 +you're probably like what the heck is going on. +你可能会想这是怎么了 + +1123 +00:46:20,521 --> 00:46:22,688 +Why would you be passing around these pointers if +为什么你要传递这些 + +1124 +00:46:22,690 --> 00:46:24,989 +you don't even know what these things are, okay? +甚至你不知道这些是什么的指针呢? + +1125 +00:46:24,991 --> 00:46:28,426 +Well we'll talk a little bit why we do it but +我们稍后会讨论一下为什么这么做 + +1126 +00:46:28,428 --> 00:46:32,163 +let's talk first about how we use it, because it's this +但先来说说我们怎么用这个,因为这是一个指向未知对象的指针 + +1127 +00:46:32,165 --> 00:46:35,766 +pointer to unknown object, so I can't really send any +所有我不能发送任何信息给它 + +1128 +00:46:35,768 --> 00:46:40,136 +messages to it because I don't even know what it is, okay? +因为我甚至不知道这是什么 + +1129 +00:46:40,138 --> 00:46:45,474 +And so to use it, we convert it to a type we do know, kay? +为了使用它,我们把它转换成一种我们知道的类型 + +1130 +00:46:45,476 --> 00:46:49,044 +That's the only way we're really gonna use AnyObject, +我们唯一的使用 AnyObject 的方式 + +1131 +00:46:49,046 --> 00:46:52,547 +is to invert it to some class that we do know, all right? +就是把它转换成我们知道的类 + +1132 +00:46:52,549 --> 00:46:55,283 +And we do that with. +我们通过 + +1133 +00:46:56,319 --> 00:46:59,787 +By creating a new variable, so we, we've got some AnyObject, +建立一个新的变量来做这件事。比如,我们有一些 AnyObject + +1134 +00:46:59,789 --> 00:47:01,989 +it's a, it was an argument to a method, or +是一个方法的参数 + +1135 +00:47:01,991 --> 00:47:03,557 +it's a local variable or +或者是一个本地变量 + +1136 +00:47:03,559 --> 00:47:05,959 +something like that, and we wanna convert it. +诸如此类,我们想把它转换掉 + +1137 +00:47:05,961 --> 00:47:08,661 +So, we're gonna create a new variable of the, +所以我们可以建立一个新的变量 + +1138 +00:47:08,663 --> 00:47:11,163 +of the type we wanna convert it to, okay? +新变量的类型就是我们想要转换到的类型 + +1139 +00:47:11,165 --> 00:47:13,832 +And we're gonna assign this new variable to be +然后我们要把这个变量声明成 + +1140 +00:47:13,834 --> 00:47:17,269 +equal to that AnyObject thing converted. +“变量 = AnyObject 转换后的东西” + +1141 +00:47:17,271 --> 00:47:18,704 +Now, of course, +接着 + +1142 +00:47:18,705 --> 00:47:20,138 +we have to convert it to a compatible type. +我们需要转换成一个合适的类型 + +1143 +00:47:20,140 --> 00:47:21,539 +It actually has, +实际上,它也 + +1144 +00:47:21,540 --> 00:47:22,939 +has to actually be one of those things. +必须是那种类型 + +1145 +00:47:22,942 --> 00:47:26,344 +So, if we got a UIButton back from buttonWithType and +所以如果我们从 buttonWithType 中取回了 UIButton + +1146 +00:47:26,346 --> 00:47:27,711 +it comes back as AnyObject, +其实返回了 AnyObject + +1147 +00:47:27,713 --> 00:47:30,881 +we can convert it to UIButton, cuz it is a UIButton. +你可以把它转换成 UIButton,因为他真的是个 UIButton + +1148 +00:47:30,883 --> 00:47:32,666 +Kay? + + +1149 +00:47:32,667 --> 00:47:34,450 +But we can't convert it to a UILabel, it's not a UILabel, so +但是不能转换成 UILabel,因为他不是个 UILabel + +1150 +00:47:34,453 --> 00:47:36,953 +that would crash our program actually. +这会让你的程序崩溃 + +1151 +00:47:36,955 --> 00:47:39,055 +So, how do we do that conversion? +那我们怎么去做这个转换呢? + +1152 +00:47:40,524 --> 00:47:42,758 +yeah, see, it will crash our program if we do that. +看到没,这会让我们的程序崩溃 + +1153 +00:47:42,760 --> 00:47:44,392 +How do we do that conversion safely so +如何安全地去做这个转型 + +1154 +00:47:44,394 --> 00:47:46,394 +we're not crashing our program all the time? +才不会让我们的程序一直崩溃呢? + +1155 +00:47:46,396 --> 00:47:50,531 +So, there's two ways, and we call this casting, kay? +这里有两种方式,我们叫它转换 + +1156 +00:47:50,533 --> 00:47:53,067 +You know what typecasting is, we're essentially casting +你知道类型转换是什么,我们 + +1157 +00:47:53,069 --> 00:47:55,068 +the type from AnyObject to something else. +本质上是把一个类型从任意类型转换成其他的 + +1158 +00:47:56,004 --> 00:48:00,439 +And we can typecast forcibly using the as keyword. +我们还可以用 as 关键词强行转换 + +1159 +00:48:00,441 --> 00:48:01,840 +A S, as. +用 as + +1160 +00:48:01,842 --> 00:48:04,343 +Okay Swift as usual, very succinct. +通常 Swift 是非常简洁的 + +1161 +00:48:04,345 --> 00:48:06,811 +And so I'm gonna use that destination view +下面我要用 destinationViewController + +1162 +00:48:06,813 --> 00:48:08,813 +controller thing as an example so +来做个例子 + +1163 +00:48:08,815 --> 00:48:12,283 +I've got this property destinationViewController. +我得到了这个 destinationViewController 作为属性 + +1164 +00:48:12,285 --> 00:48:14,051 +It's in AnyObject. +这是个 AnyObject + +1165 +00:48:14,053 --> 00:48:16,620 +And, I know it's a ViewController. +我知道这是个 ViewController + +1166 +00:48:16,622 --> 00:48:20,223 +And I think it should be a CalculatorViewController. +我想这应该是个 CalculatorViewController + +1167 +00:48:20,225 --> 00:48:21,491 +So, I'm gonna be using in my +我要在我的 + +1168 +00:48:21,493 --> 00:48:23,559 +examples CalculatorViewController. +CalculatorViewController 里面用 + +1169 +00:48:23,561 --> 00:48:25,761 +Imagine we had called our CalculatorViewController, +先想象一下我们调用 CalculatorViewController + +1170 +00:48:25,763 --> 00:48:28,864 +CalculatorViewController instead of ViewController. +是 CalculatorViewController 而不是 ViewController + +1171 +00:48:28,866 --> 00:48:30,432 +I'm doing that in examples because it, +我因为这个才用在我的例子里 + +1172 +00:48:30,434 --> 00:48:32,000 +it's just going to make more sense, okay? +这样能让你们更好理解 + +1173 +00:48:32,002 --> 00:48:35,269 +So, I want to talk to this destinationViewController, +所以我想说说这个 destinationViewController + +1174 +00:48:35,271 --> 00:48:37,037 +which is AnyObject. +这是个 AnyObject + +1175 +00:48:37,039 --> 00:48:39,473 +And I know that it's a CalculatorViewController. +同时我又知道这是个 CalculatorViewController + +1176 +00:48:39,475 --> 00:48:41,474 +And if it's not a CalculatorViewController, +如果这个不是个 CalculatorViewController + +1177 +00:48:41,476 --> 00:48:43,209 +my program should probably crash. +这个程序就应该会崩溃 + +1178 +00:48:43,211 --> 00:48:45,177 +Because, in the context I'm using it, +因为在使用它的情景下 + +1179 +00:48:45,179 --> 00:48:46,679 +I want it to be that. +我需要它是 CalculatorViewController + +1180 +00:48:46,681 --> 00:48:48,397 +Okay? + + +1181 +00:48:48,398 --> 00:48:50,114 +So, I can just say, let calcVC equals +所以可以写 let calcVC = + +1182 +00:48:50,117 --> 00:48:52,484 +DestinationViewController as CalculatorViewController. +destinationViewController as CalculatorViewController + +1183 +00:48:52,486 --> 00:48:56,821 +And now, calcVC, this new constant, its type is +现在,calcVC 这个常量的类型 + +1184 +00:48:56,823 --> 00:48:59,990 +not AnyObject, its type is CalculatorViewController. +不是 AnyObject,而是 CalculatorViewController + +1185 +00:48:59,992 --> 00:49:02,159 +And so now, I've gotten hold of that AnyObject in +所以现在我可以这种方法处理好了 AnyObject + +1186 +00:49:02,161 --> 00:49:03,626 +a way that I can actually do things with it, +之后就可以针对它做事情了 + +1187 +00:49:03,628 --> 00:49:04,761 +and I can send messages, +也可以发送消息 + +1188 +00:49:04,763 --> 00:49:07,696 +CalculatorViewControl messages, to calcVC. +CalculatorViewControl 消息给 calcVC. + +1189 +00:49:08,999 --> 00:49:10,899 +Now, you can protect against crashing if +现在如果你想防止崩溃 + +1190 +00:49:10,901 --> 00:49:13,801 +you're not sure whether that destinationViewController is +但你不确定 destinationViewController 是不是 + +1191 +00:49:13,803 --> 00:49:16,771 +a CalculatorViewController, but you're hoping it is. +一个 CalculatorViewController,但你希望是 + +1192 +00:49:16,773 --> 00:49:18,272 +Okay? + + +1193 +00:49:18,273 --> 00:49:19,772 +You can use as question mark. +你可以用 as 加问号 + +1194 +00:49:19,775 --> 00:49:22,909 +And as question mark returns an Optional. +as? 会返回一个可选的 + +1195 +00:49:22,911 --> 00:49:26,879 +Same as as, right, as returns that AnyObject thing cast to +跟 as 一样,as 返回 AnyObject 转换成 + +1196 +00:49:26,881 --> 00:49:28,414 +be a different class. +其他类之后的对象 + +1197 +00:49:28,416 --> 00:49:30,983 +As question mark does the same thing, but it's Optional +问号做了同样的事,但是返回的是 Optional 版本 + +1198 +00:49:30,985 --> 00:49:33,585 +version of that, so we can return nil if that AnyObject, +如果类型为 AnyObject 的 destinationViewController + +1199 +00:49:33,587 --> 00:49:35,387 +destinationViewController cannot be +不能转换成 CalculatorViewController + +1200 +00:49:35,389 --> 00:49:37,388 +turned into a CalculatorViewController, +那就返回 nil + +1201 +00:49:37,390 --> 00:49:39,757 +because it's not a CalculatorViewController some +因为它不是 CalculatorViewController,而是其他的 + +1202 +00:49:39,759 --> 00:49:41,992 +other kinda ViewController or something else. +ViewController 或者其他的(类) + +1203 +00:49:41,994 --> 00:49:42,726 +All right? + +1204 +00:49:42,728 --> 00:49:44,745 +And so you can say, +所以,你可以说, + +1205 +00:49:44,746 --> 00:49:46,763 +if let calcVC equals destinationViewController as +if let calcVC = destinationViewController as + +1206 +00:49:46,765 --> 00:49:48,131 +CalculatorViewController, and +CalculatorViewController, 然后 + +1207 +00:49:48,133 --> 00:49:51,067 +then inside there, you've got calcVC set. +在那里面,你就给 calcVC 赋值了 + +1208 +00:49:51,069 --> 00:49:53,502 +And it's, you know that it's a CalculatorViewController. +你知道它是一个 CalculatorViewController + +1209 +00:49:53,504 --> 00:49:57,205 +And AnyObject is now in your past, okay? +AnyObject 也就成了过去式了 + +1210 +00:49:58,975 --> 00:50:00,174 +Make sense? So, we have as and +理解吗?好了,我们学了 as 和 + +1211 +00:50:00,176 --> 00:50:01,675 +as question mark. +as? + +1212 +00:50:01,677 --> 00:50:05,512 +You can also check beforehand if you just wanna see, is this +如果你愿意,你也可以事先检查下,这是不是一个 + +1213 +00:50:05,514 --> 00:50:08,748 +a CalculatorViewController, you can say is. +CalculatorViewController + +1214 +00:50:08,750 --> 00:50:10,750 +So, you can say if destinationViewController is +你可以写 + +1215 +00:50:10,752 --> 00:50:13,252 +a calculation view... CalculatorViewController, +if destinationViewController is CalculatorViewController, + +1216 +00:50:13,254 --> 00:50:16,422 +then I'll go ahead and, then I can do the as, for example. +那么我就继续,然后我就可以进行 as(转换) + +1217 +00:50:16,424 --> 00:50:20,358 +But usually we use the as question mark, you know, +但通常地,我们使用 as? + +1218 +00:50:20,360 --> 00:50:23,194 +check it and convert it all in one go. +做检查并且转换,一次搞定 + +1219 +00:50:23,196 --> 00:50:25,013 +Okay? + +1220 +00:50:25,014 --> 00:50:26,831 +So that's how we're gonna use an AnyObject. +这就是我们怎么使用 AnyObject + +1221 +00:50:26,833 --> 00:50:30,434 +We're gonna have to cast it with as into something else. +我们必须将它转化成其他东西 + +1222 +00:50:30,436 --> 00:50:32,936 +Question? +有问题吗? + +1223 +00:50:32,937 --> 00:50:35,437 +Is there a way to check if it's not it +(学生提问) + +1224 +00:50:35,440 --> 00:50:37,473 +doesn't ? +(学生提问) + +1225 +00:50:37,475 --> 00:50:39,041 +Yeah. So the question is, +所以,问题是, + +1226 +00:50:39,043 --> 00:50:41,977 +is there a way to kind of ask it what the type is and +有没有这样一种方式,可以先检察这个类是什么类型, + +1227 +00:50:41,979 --> 00:50:44,079 +get the answer back in some way? +然后通过某种方式得到结果 + +1228 +00:50:44,081 --> 00:50:47,448 +And, the answer is, for the purposes of where you are, no. +答案是,就你所提的这个问题,不能 + +1229 +00:50:47,450 --> 00:50:48,883 +Okay? You don't do that. +你不能那样做 + +1230 +00:50:48,885 --> 00:50:50,317 +You, you, you ask it for +你想要知道 + +1231 +00:50:50,319 --> 00:50:52,919 +certain, whether it can be a certain thing. +它是否是一个确定的东西 + +1232 +00:50:52,921 --> 00:50:54,587 +You don't ask it, what are you? +你不能问,你是什么? + +1233 +00:50:54,589 --> 00:50:55,988 +And then try and figure it out from there. +然后试图知道它是什么 + +1234 +00:50:55,990 --> 00:50:57,589 +Just, that's, we're not gonna use that paradigm. +因此,我们不能使用那样的模式 + +1235 +00:50:59,827 --> 00:51:00,792 +Okay? + +1236 +00:51:00,794 --> 00:51:03,728 +Let's talk about Arrays of AnyObject. +让我们说说包含 AnyObject 的 Array + +1237 +00:51:03,730 --> 00:51:05,996 +Cuz sometimes you're gonna get an Array of AnyObject back, +有时你会得到一个 AnyObject 的 Array + +1238 +00:51:05,998 --> 00:51:08,766 +like that constraints one I was talking about. +就像我刚刚提到的 constraints + +1239 +00:51:08,768 --> 00:51:10,967 +Where it's going to be an Array of constraints that +它可能是一个 AnyObject 类型 constraints 的 Array (译注:[AnyObject]) + +1240 +00:51:10,969 --> 00:51:13,536 +are going to be AnyObject, but I know they're going to be in +但我知道它们在这个 + +1241 +00:51:13,538 --> 00:51:16,539 +this layout constraint, but they're going to be an Array. +布局约束中,但它们是一个 Array + +1242 +00:51:16,541 --> 00:51:18,491 +So, you can do +所以,你可以在转换它们 + +1243 +00:51:18,492 --> 00:51:20,442 +some interesting things with casting there. +时做些有趣的事情 + +1244 +00:51:20,445 --> 00:51:23,045 +So, let's use the toolbarItems one, +让我们以 toolbarItems 为例, + +1245 +00:51:23,047 --> 00:51:26,048 +so that toolbarItems it's a, that's a property on +toolbarItems 是 UIViewController 的 + +1246 +00:51:26,050 --> 00:51:29,184 +UIViewController and it returns an Array that's gonna +一个属性,它返回一个 UIBarButtonItem 的 + +1247 +00:51:29,186 --> 00:51:31,519 +have UIBarButtonItem in it. + Array + +1248 +00:51:31,521 --> 00:51:35,122 +But, for historical reasons it returns the square bracket +但,由于历史原因,它返回 + +1249 +00:51:35,124 --> 00:51:36,556 +of AnyObject. +[AnyObject] + +1250 +00:51:36,558 --> 00:51:37,957 +So, I can say for +所以,我可以说, + +1251 +00:51:37,959 --> 00:51:41,994 +item in toolbarItems, then item is gonna be in AnyObject. +在 toolbarItems 中,item 会是 AnyObject + +1252 +00:51:41,996 --> 00:51:44,697 +So, I'm enumerating those AnyObject. +所以,我遍历这些 AnyObject + +1253 +00:51:44,699 --> 00:51:47,499 +And I'm actually having my variable item be AnyObject, +这些变量也确实是 AnyObject, + +1254 +00:51:47,501 --> 00:51:48,967 +but then inside I'm saying, +但在里面,我判断, + +1255 +00:51:48,969 --> 00:51:51,736 +if I can let the toolbarItem equal, you know, +如果我能 let toolbarItem = + +1256 +00:51:51,738 --> 00:51:55,172 +be a UIBarButtonItem, then I'm good to go. +UIBarButtonItem,我就可以继续了 + +1257 +00:51:55,174 --> 00:51:57,908 +So, you see how I'm enumerating this Array of +我是这样遍历这个 + +1258 +00:51:57,910 --> 00:51:58,842 +AnyObject. +AnyObject 的 Array + +1259 +00:51:58,844 --> 00:52:00,611 +Then the objects, and +然后这些 object, + +1260 +00:52:00,612 --> 00:52:02,379 +then inside I'm doing the as question mark. +在里面我使用 as? + +1261 +00:52:02,381 --> 00:52:04,113 +But I can do it another way to. +但我也可以使用其他方式, + +1262 +00:52:04,115 --> 00:52:05,815 +Kay? Which is I can say, for +我可以使用 for + +1263 +00:52:05,817 --> 00:52:09,885 +toolbarItem in toolbarItems as an Array of UIBarButtonItem. +toolbarItem in toolbarItems as [UIBarButtonItem] + +1264 +00:52:09,887 --> 00:52:12,454 +Another words, I can cast the entire Array. +换句话说,我可以转换整个 Array , + +1265 +00:52:12,456 --> 00:52:14,288 +If I know that that Array of AnyObjects is +如果我确认这整个的 AnyObject 的 Array 是个 + +1266 +00:52:14,290 --> 00:52:17,825 +really an Array of UIBarButtonItem, I can just cast it. +UIBarButtonItem 的 Array 我就能转化它 + +1267 +00:52:17,827 --> 00:52:20,561 +Now this one, you can't do question mark, because it +现在这个,你不能使用问号,因为 + +1268 +00:52:20,563 --> 00:52:24,197 +wouldn't make sense to say for toolbarItem in nil, okay? +for toolbarItem in nil 是没有意义的 + +1269 +00:52:24,199 --> 00:52:25,732 +So, that makes no sense. +没有意义 + +1270 +00:52:25,734 --> 00:52:28,017 +So, you can't here, +你不能在这里, + +1271 +00:52:28,018 --> 00:52:30,301 +you better be darn sure that that Array has what you want. +你最好确认那个 Array 是你想要的 + +1272 +00:52:30,304 --> 00:52:32,838 +But then inside, now toolbarItem is a tool, +但这里面,toolbarItem 是一个 + +1273 +00:52:32,840 --> 00:52:36,008 +UIBarButtonItem, cuz I've casted the whole Array from +UIBarButtonItem,因为我已经转换了整个 Array ,从 [AnyObject] + +1274 +00:52:36,010 --> 00:52:38,810 +Array of AnyObject to Array of UIBarButtonItem. +转换到 [UIBarButtonItem] + +1275 +00:52:38,812 --> 00:52:42,380 +You understand the difference there between those two? +你们明白这两个的不同吗? + +1276 +00:52:42,382 --> 00:52:46,350 +Okay another example of AnyObject and +另一个出现 + +1277 +00:52:46,352 --> 00:52:48,085 +where it appears. +AnyObject 的例子 + +1278 +00:52:48,087 --> 00:52:51,054 +So, if we hadn't changed, when we control drag to +当我们 control 拖建一个 + +1279 +00:52:51,056 --> 00:52:54,123 +make a appendDigit, what if we had left at AnyObject? +appendDigit,如果我们保留 AnyObject 会怎样? + +1280 +00:52:55,259 --> 00:52:56,775 +Kay? So we had +所以我们有一个 + +1281 +00:52:56,776 --> 00:52:58,292 +a appendDigit sender colon AnyObject. +appendDigit(sender: AnyObject) + +1282 +00:52:58,295 --> 00:52:59,794 +How could we have dealt with that? +我们怎么处理这个呢? + +1283 +00:52:59,796 --> 00:53:01,996 +Well, we just would've said, +好吧,我们刚才说的, + +1284 +00:53:01,998 --> 00:53:05,166 +if we can let the sendingButton equal sender as +如果我们能够 let sendingButton = sender as UIButton + +1285 +00:53:05,168 --> 00:53:08,502 +a UIButton, then do what we do, let digit equals +那么,做我们该做的,let digit = + +1286 +00:53:08,504 --> 00:53:12,072 +sendingButton.currenTitle exclamation point, +sendingButton.currenTitle! + +1287 +00:53:12,074 --> 00:53:14,507 +et cetera, et cetera, et cetera. +等等 + +1288 +00:53:14,509 --> 00:53:15,775 +Make sense? +有道理吧? + +1289 +00:53:15,776 --> 00:53:17,042 +But we didn't want to put that extra if let and +但是我们不想使用这个额外的 if let, + +1290 +00:53:17,045 --> 00:53:18,844 +I hadn't talked to you about as, so +我还没有跟你们讲 as, + +1291 +00:53:18,846 --> 00:53:22,014 +that's why I said be sure to put that thing UIButton. +这是为什么我说要确保这个东西是 UIButton + +1292 +00:53:22,016 --> 00:53:22,581 +All right? + +1293 +00:53:24,451 --> 00:53:27,485 +Now you might ask, why is that even in AnyObject? +现在你们可能会问,为什么会有 AnyObject? + +1294 +00:53:27,487 --> 00:53:30,454 +When I control dragged, why did he just put UIButton? +当我们 control 拖拽时, 为什么不只提供给我们 UIButton? + +1295 +00:53:30,456 --> 00:53:32,456 +Why did it even offer AnyObject? +为什么它甚至提供了 AnyObject? + +1296 +00:53:32,458 --> 00:53:35,525 +Well, because you could have an action that is sent +因为你们可能有一个 action,这个 action 是 + +1297 +00:53:35,527 --> 00:53:38,695 +by two different kinds of UI elements. +两个不同的 UI 元素发起的 + +1298 +00:53:38,697 --> 00:53:41,464 +Maybe it's set by a Button and also by a Slider. +它可能是由 Button 和 Slider 发起的 + +1299 +00:53:41,466 --> 00:53:43,099 +I don't know what that would be, +我不知道它会是什么 + +1300 +00:53:43,101 --> 00:53:44,900 +I couldn't even think of an example of that. +我甚至举不出例子 + +1301 +00:53:44,902 --> 00:53:47,803 +But you possibly could, It's theoretically possible. +但是你可以这么做,理论上是可以的 + +1302 +00:53:47,805 --> 00:53:49,671 +And in that case the sender would be AnyObject. +在这种情况下 sender 就应该是 AnyObject + +1303 +00:53:49,673 --> 00:53:51,573 +And you would have, +这样你就可以这么写, + +1304 +00:53:51,574 --> 00:53:53,474 +say if the sender is a Slider then do one thing, else, +if sender 是一个 Slider 的时候,做某些事情,else if + +1305 +00:53:53,476 --> 00:53:56,110 +if the sender is a Button, then do something else. +sender 是一个 Button 的时候,做别的事 + +1306 +00:53:56,112 --> 00:53:57,544 +And you would do that with as. +可以用 as 来实现 + +1307 +00:53:58,547 --> 00:53:59,112 +Okay? + +1308 +00:54:00,181 --> 00:54:01,581 +So, the rea, + +1309 +00:54:01,582 --> 00:54:02,982 +that's why I'm saying I think that default should not be +这就是为什么我觉得默认不应该是 AnyObject + +1310 +00:54:02,984 --> 00:54:05,551 +AnyObject cuz that's a pretty rare case, where two +的原因,毕竟两个不同的 UI 元素发送同样 action 是 + +1311 +00:54:05,553 --> 00:54:07,986 +different kinds of UI elements are sending the same thing. +比较罕见的例子 + +1312 +00:54:07,988 --> 00:54:11,222 +So, why do the rare case, even though that's the more +所以我不太明白为什么要适应罕见的情况,如果是为了适用 + +1313 +00:54:11,224 --> 00:54:13,925 +generic or more general case, I agree. +于一些非常常见的例子的话,我会同意的 + +1314 +00:54:13,927 --> 00:54:17,595 +It still just seems kinda error prone to me, but anyway. +对我来说,这个非常容易犯错,但是无所谓了 + +1315 +00:54:17,597 --> 00:54:20,597 +So there's another a, AnyObject example. +上面就是 AnyObject 的另一个例子 + +1316 +00:54:20,599 --> 00:54:22,766 +So here's one more AnyObject thing. +这还有一个例子 + +1317 +00:54:22,768 --> 00:54:24,668 +Let's go back to that button thing. +再来看看这个 button + +1318 +00:54:24,670 --> 00:54:29,505 +So I told you the buttonWithType returns AnyObject, kay? +我说过 buttonWithType 返回一个 AnyObject + +1320 +00:54:29,507 --> 00:54:33,109 +And so if I got a button and I wanted to find out +那么如果我有一个按钮,我需要知道它 + +1321 +00:54:33,111 --> 00:54:36,011 +it's title or something like that, I have to cast it. +的标题或者其他东西,我就需要做类型转换 + +1322 +00:54:36,013 --> 00:54:40,315 +So, I would call UIBut, I would call that buttonWithType +这里我会调用 buttonWithType + +1323 +00:54:40,317 --> 00:54:43,685 +and I can cast on the fly, right in line. +然后做一个直接的类型转换,就在调用这行 + +1324 +00:54:43,687 --> 00:54:46,354 +So, if I called that line green at the top, +如果我调用上边那行绿色代码, + +1325 +00:54:46,356 --> 00:54:49,289 +then down here I could say the title of the button +在下边我就可以写 + +1326 +00:54:49,291 --> 00:54:52,125 +equals button as UIButton.currentTitle. +title = (button as UIButton).currentTitle + +1327 +00:54:52,127 --> 00:54:54,361 +So, I'm just casting that AnyObject, +这样我就把上边那个按钮的 AnyObject + +1328 +00:54:54,363 --> 00:54:57,363 +that button AnyObject up there, to be a UIButton, and +转换成一个 UIButton + +1329 +00:54:57,365 --> 00:54:58,864 +then sending it a message. +并且发送一个消息 + +1330 +00:54:58,866 --> 00:55:00,132 +So, you can cast on the fly. +所以你是可以做这样一个直接的类型转换 + +1331 +00:55:00,134 --> 00:55:03,101 +Again, crasheroo if that button is not a button, +再说一次,如果这个按钮不是 UIButton,程序就崩溃了 + +1332 +00:55:03,103 --> 00:55:04,102 +but that's okay. +不过也可以 + +1333 +00:55:04,104 --> 00:55:06,020 +In this case, +在这个例子里, + +1334 +00:55:06,021 --> 00:55:07,937 +button with type better darn well return a UIButton. +buttonWithType 我觉得最好还是直接返回 UIButton 比较好 + +1335 +00:55:10,876 --> 00:55:15,279 +Okay, now this casting business is not just for AnyObject. +继续,类型转换并不仅仅针对 AnyObject + +1337 +00:55:15,280 --> 00:55:17,180 +You can actually cast any two objects. +你可以对任意两种不同的对象进行类型转换 + +1338 +00:55:17,182 --> 00:55:20,416 +For all non AnyObject case though, obviously those two +对于所有的非 AnyObject 对象,需要类型转换的两个对象 + +1339 +00:55:20,418 --> 00:55:23,886 +objects will have to be in the same inheritance hierarchy. +必须在一条继承链上 + +1340 +00:55:23,888 --> 00:55:24,920 +Right? + +1341 +00:55:24,922 --> 00:55:26,221 +Can only cast down you know, +并且只能向下转换, + +1342 +00:55:26,223 --> 00:55:29,290 +down cast into your own inherit this hierarchy. +沿着继承链向下转换 + +1343 +00:55:29,292 --> 00:55:34,061 +So, for example, if I had a local variable called vc +举个例子,如果我有一个 UIViewController + +1344 +00:55:34,063 --> 00:55:36,897 +which was of type UIViewController, but I set it +类型的局部变量 vc, 但是我需要把它 + +1345 +00:55:36,899 --> 00:55:40,600 +to CalculatorViewController, okay? +设置成 CalculatorViewController + +1346 +00:55:40,602 --> 00:55:43,169 +I couldn't say vc.enter(), right? +我不可以直接写 vc.enter(), + +1347 +00:55:43,171 --> 00:55:45,338 +Enter is a method in our CalculatorViewController. +因为 enter() 是 CalculatorViewController 类的方法 + +1348 +00:55:45,340 --> 00:55:49,474 +I couldn't say vc.enter because vc is a UIViewController. +所以我不能写 vc.enter(),因为vc是一个 UIViewController + +1350 +00:55:49,476 --> 00:55:52,477 +So as far as Swift knows, it doesn't respond to enter. +至少 Swift 是这么认为的,所以 vc 不会响应 enter 方法 + +1351 +00:55:52,479 --> 00:55:55,079 +Even though it is in fact, a CalculatorViewController, +尽管它事实上是一个 CalculatorViewController + +1352 +00:55:55,081 --> 00:55:57,715 +from Swift's point of view, that local variable is not. +但是从 Swift 的角度看,它明显不是 + +1353 +00:55:57,717 --> 00:55:59,350 +It's a type UIViewController. +它是一个 UIViewController 对象 + +1354 +00:55:59,352 --> 00:56:04,154 +But I could cast it and say if I can let the calcVC equal vc +但是我可以做一个类型转换,新建一个常量 calcVC = vc + +1355 +00:56:04,156 --> 00:56:09,525 +as a CalculatorViewController, now I can say vc.,.calcVC.enter. +as CalculatorViewController,现在就可以写 calcVC.enter() + +1357 +00:56:09,527 --> 00:56:10,826 +Okay. + +1358 +00:56:10,828 --> 00:56:15,229 +So you can cast, downcast through your inherit hierarchy as well. +所以说,向下转换是可以的 + +1360 +00:56:17,333 --> 00:56:19,967 +We rarely do that but, you might occasionally. +我们很少这么做,但是你也许以后偶尔会做 + +1361 +00:56:19,969 --> 00:56:21,969 +All right. + +1362 +00:56:21,970 --> 00:56:23,970 +So let's zoom on here to every, +你们需要深入的 + +1363 +00:56:23,973 --> 00:56:26,139 +any questions about that whole AnyObject thing? +研究一下 AnyObject 的所有细节 + +1364 +00:56:26,141 --> 00:56:27,540 +When you see it in action, +当你在实际的项目中见到的时候, + +1365 +00:56:27,542 --> 00:56:29,475 +it'll make a lot more sense, okay? +你就会更加透彻的理解了 + +1366 +00:56:31,212 --> 00:56:33,296 +okay. So now let's just +下面咱们看一些在 + +1367 +00:56:33,297 --> 00:56:35,381 +talk about some fun functions throughout all our classes. +所有我们见过的类里很有趣的函数 + +1368 +00:56:35,383 --> 00:56:36,682 +And we're gonna start with Array. +从 Array 开始 + +1369 +00:56:37,751 --> 00:56:41,385 +First of all that you know, you know that Array does plus equals. +你们应该知道 Array 可以用 += . + +1371 +00:56:41,387 --> 00:56:42,853 +Can do, say Array plus equals. +Array += + +1372 +00:56:42,855 --> 00:56:45,489 +But the argument plus equals is another Array. +但是 += 的另外一个参数是另一个 Array + +1373 +00:56:46,591 --> 00:56:49,559 +Okay, so if you just wanna add one thing to an Array using +所以,如果你想用 += 把一个东西加到 Array 里, + +1374 +00:56:49,561 --> 00:56:51,627 +plus equals, you would have to put it in another Array. +你需要把它放到另一个 Array 里 + +1375 +00:56:51,629 --> 00:56:54,329 +Just square brackets, put the thing inside, okay? +就是把它放到方括号里 + +1376 +00:56:54,331 --> 00:56:56,415 +Some people get tripped up by this. +有一些人在这里犯错误 + +1377 +00:56:56,416 --> 00:56:58,500 +They do plus equals, you know, they have an Array of Ints, +比如他们有一个 Int 的 Array ,他们想用 += , + +1378 +00:56:58,502 --> 00:57:01,269 +and they say my Array of Ints plus equals an Int, and +他们会写我的 Array += 一个 Int + +1379 +00:57:01,271 --> 00:57:02,637 +they're like, oh, why doesn't it work? +然后他们就会纳闷为什么不行 + +1380 +00:57:02,639 --> 00:57:07,141 +It's because plus equal only adds whole Arrays to other Arrays. +这是因为 += 只能是一个 Array 加上另外一个 Array + +1382 +00:57:07,142 --> 00:57:08,575 +It's an Array concatenater, okay? +这是一个 Array 的连接器 + +1383 +00:57:11,246 --> 00:57:15,381 +There's a couple of interesting variables, +Array 还有一些有趣的变量, + +1384 +00:57:15,383 --> 00:57:18,283 +properties in Array first and last that will +first 和 last 会分别返回 + +1385 +00:57:18,285 --> 00:57:20,719 +return the first or last item in the Array. +Array 的第一个和最后一个元素 + +1386 +00:57:20,721 --> 00:57:22,053 +What's interesting about them is +它们有趣的地方是 + +1387 +00:57:22,055 --> 00:57:23,721 +that they return an Optional. +他们返回一个 Optional + +1388 +00:57:23,723 --> 00:57:25,990 +So, they don't do Array index out of bounds. +所以他们不会访问到越界的 Array 下标 + +1389 +00:57:25,992 --> 00:57:28,359 +So, thay'll return nil if your Array is empty. +当然如果 Array 是空的,它们会返回nil + +1390 +00:57:29,428 --> 00:57:31,345 +Okay? So, + +1391 +00:57:31,346 --> 00:57:33,263 +you should know, you should know about these because they +你们应该了解这些,这会让你们的代码 + +1392 +00:57:33,265 --> 00:57:36,132 +can make your code read really nicely sometimes. +有些时候看起来非常好看 + +1393 +00:57:37,335 --> 00:57:38,700 +so, for these next ones I'm +下边我还有一个关于 + +1394 +00:57:38,702 --> 00:57:40,802 +gonna have a little example Array here, +Array 的小例子, + +1395 +00:57:40,804 --> 00:57:42,937 +this can be an Array that's got three things in it. +这是一个有3个元素的 Array + +1396 +00:57:42,939 --> 00:57:44,372 +I'm not even gonna say what the types of +我们不需要知道它们的类型, + +1397 +00:57:44,374 --> 00:57:46,874 +those three things in there, they could be anything, okay? +任何类型都可以 + +1398 +00:57:46,876 --> 00:57:48,108 +Cuz Array is generic, right? +因为 Array 是泛型的 + +1399 +00:57:48,110 --> 00:57:49,743 +Array angle bracket T. +Array + +1400 +00:57:49,745 --> 00:57:50,743 +You can assume for +你可以假设 + +1401 +00:57:50,745 --> 00:57:52,878 +the purposes of this, they're of type T. +它们都是 T 类型 + +1402 +00:57:52,880 --> 00:57:56,248 +Whatever the T is that I created the Array with, right? +无论 T 是什么类型,我创建了一个 T 类型的 Array + +1403 +00:57:56,250 --> 00:57:58,617 +So, let's talk about, you know about append. +让我们继续,你应该知道 append(追加,即在 Array 的末尾增加元素)方法 + +1404 +00:57:58,619 --> 00:57:59,984 +That's how you add something to Array, +这就是我们在计算器的 App 中 + +1405 +00:57:59,986 --> 00:58:02,020 +we did that in the calculator all the time. +对 Array 操作一直在使用的方法 + +1406 +00:58:02,022 --> 00:58:03,521 +There's also insert, so +当然, Array 也有 insert(插入)操作 + +1407 +00:58:03,522 --> 00:58:05,021 +you can inset something in the middle of your Array. +你可以在 Array 中间的某个位置插入元素 + +1408 +00:58:05,024 --> 00:58:06,924 +You just specify what index. +通过指定一个 index(位置) + +1409 +00:58:06,926 --> 00:58:09,159 +There is also splice. +同样也有 splice 操作 + +1410 +00:58:09,161 --> 00:58:10,593 +Kay? Splice will take +Splice 操作会 + +1411 +00:58:10,595 --> 00:58:15,064 +another Array and splice it into the middle of your Array. +将另外的一个 Array 加入到你的 Array 的中间位置 + +1412 +00:58:15,066 --> 00:58:15,964 +Kay? So that can +明白了吗?有时候 + +1413 +00:58:15,966 --> 00:58:17,699 +sometimes be invaluable. +这个操作是十分重要的 + +1414 +00:58:17,701 --> 00:58:19,467 +It's otherwise just like insert, it's just like +它不像 insert 操作插入一个元素,它是 + +1415 +00:58:19,469 --> 00:58:22,270 +inserting another Array inside the Array. +在 Array 中插入 Array 而不是元素的一种方法 + +1416 +00:58:22,272 --> 00:58:25,673 +Okay there's also removeAtIndex of course of +当然还有 removeAtIndex 这样一个方法 + +1417 +00:58:25,675 --> 00:58:29,243 +course its a var, if you've got your Array in +如果你确定 Array 是变量,你可以利用这个方法来 + +1418 +00:58:29,245 --> 00:58:31,445 +a var you can do removeAtIndex and +从一个 Array 中移除一个元素 + +1419 +00:58:31,447 --> 00:58:33,913 +there's also removeRange, okay? +有了这个方法,也有 removeRange 方法 + +1420 +00:58:33,915 --> 00:58:36,683 +So you can specify a range with the dot dot dot thing or +removeRange 的方法接受一个范围,并移除这个范围内的所有元素 + +1421 +00:58:36,685 --> 00:58:38,451 +the dot dot dot less than thing and +你可以通过 ... 或者 ..< 来创建一个范围 + +1422 +00:58:38,453 --> 00:58:41,253 +remove a range of your Array elements. +并在 removeRange 方法中使用这个范围 + +1423 +00:58:41,255 --> 00:58:43,522 +And there's also replaceRange, and +另外,还有 replaceRange 这样的方法 + +1424 +00:58:43,524 --> 00:58:46,191 +when you replace a range, the thing you replace it with +当你替换一个范围内的元素时,替换的元素个数 + +1425 +00:58:46,193 --> 00:58:47,425 +doesn't have to be the same length. +不需要等于被替换的元素个数 + +1426 +00:58:48,428 --> 00:58:51,228 +So, I can have an Array and replace a range that +假如我有一个包含3个元素的 Array ,我将这个 Array 的全范围 + +1427 +00:58:51,230 --> 00:58:55,132 +spans three things with something that is six long, +替换成包含6个元素的 Array + +1428 +00:58:55,134 --> 00:58:56,700 +and make my Array it'll make my Array longer, okay? +这样就可以使原 Array 变长了 + +1429 +00:58:56,702 --> 00:58:59,102 +So you can replace range. +这就是 replaceRange + +1430 +00:58:59,104 --> 00:59:01,370 +There's also sorting. +同样,Array 泛型提供排序方法 + +1431 +00:59:02,306 --> 00:59:04,006 +You can sort an Array. +你可以对一个 Array 进行排序 + +1432 +00:59:04,008 --> 00:59:08,676 +The sorting method in Array takes one argument and +排序方法接受一个函数作为参数, + +1433 +00:59:08,678 --> 00:59:13,313 +that's just a function to determine whether two +一个决定两个元素 + +1434 +00:59:13,315 --> 00:59:16,516 +things are ordered before each other or not. +谁放在前面的函数 + +1435 +00:59:16,518 --> 00:59:17,868 +Kay? So, it's +明白了吗?这个函数 + +1436 +00:59:17,869 --> 00:59:19,219 +going through the Array and putting everything in order. +将遍历整个 Array 并排序整个 Array + +1437 +00:59:19,221 --> 00:59:20,987 +It needs to know, it pick, picks out, +排序方法需要知道元素谁放在前面,它接受一个 Array ,并传出一个 Array + +1438 +00:59:20,989 --> 00:59:23,055 +however whatever sort, if it's Quicksort or +无论是怎么样的排序算法,例如快排 + +1439 +00:59:23,057 --> 00:59:25,691 +I don't know what sort it's using in there. +我不知道里面用的什么排序算法 + +1440 +00:59:25,693 --> 00:59:27,092 +But it needs to be able to compare things so +它只需要能够比较两个元素即可 + +1441 +00:59:27,094 --> 00:59:30,795 +you just provide a function desk comparison and +你只需要提供一个比较函数 + +1442 +00:59:30,797 --> 00:59:32,997 +usually you're going to do it with a closure just like this. +通常一般会把比较函数写成一个闭包 + +1443 +00:59:32,999 --> 00:59:36,133 +You can see this is kind of the default sorting assuming +这里你可以看到这样的排序函数默认 + +1444 +00:59:36,135 --> 00:59:39,336 +that this type can just be compared with less than. +两者之间通过小于来比较 + +1445 +00:59:39,338 --> 00:59:44,174 +I would just say a dot sort, closure, $0 < $1. +例如:a.sort { $0 < $1 } + +1446 +00:59:44,176 --> 00:59:45,992 +Make sense? +明白了吗 + +1447 +00:59:45,993 --> 00:59:47,809 +And that's gonna return yes, if $0 < $1, and +如果 $0 < $1 的话,这个函数会返回 yes + +1448 +00:59:47,812 --> 00:59:49,745 +that's what sort wants to know and +这个返回结果是我们想了解的 + +1449 +00:59:49,747 --> 00:59:52,548 +it's gonna call that closure repeatedly okay? +sort 方法会不断的调用这个闭包 + +1450 +00:59:52,550 --> 00:59:55,684 +As it's going through doing it's quick sort or whatever. +当它采用的是快速排序或者其他任何的排序算法 + +1451 +00:59:55,686 --> 00:59:58,286 +There's also another one call sorted. +这里还有另外一个方法叫 sorted + +1452 +00:59:58,288 --> 01:00:00,555 +So we're ta, this is an in place sort. +在适当的地方 + +1453 +01:00:00,557 --> 01:00:01,889 +Right? Sorts the Array in place. +将整个 Array 进行排序 + +1454 +01:00:01,891 --> 01:00:05,959 +They're sorted, will return a new Array that is sorted. +如果一个 Array 是已排序,它将会返回一个已排序的新 Array + +1455 +01:00:05,961 --> 01:00:07,593 +Okay? A copy of your Array sorted. +这个意思是,一个已排序的 Array 的拷贝 + +1456 +01:00:10,298 --> 01:00:11,497 +More Array methods. +接下来让我们看看更多的 Array 方法 + +1457 +01:00:11,499 --> 01:00:14,466 +Okay, so these three are pretty cool. +这里有3个非常酷的方法 + +1458 +01:00:14,468 --> 01:00:16,034 +This one's called filter. +这一个叫 filter + +1459 +01:00:16,036 --> 01:00:19,103 +So filter will give you a new Array with all +filter 方法将你所有不想要的元素 + +1460 +01:00:19,105 --> 01:00:22,807 +the undesirable elements filtered out of there. +过滤掉然后返回给你那个过滤后的 Array + +1461 +01:00:22,809 --> 01:00:25,576 +And the way you specify which ones are all undesirable is +你指定元素是不是你想要的方式,就是提供一个 + +1462 +01:00:25,578 --> 01:00:27,511 +with the argument which is a function, +函数作为参数 + +1463 +01:00:27,513 --> 01:00:28,812 +that just returns a Bool, +函数返回一个 Bool 的结果 + +1464 +01:00:28,814 --> 01:00:31,080 +whether something's undesirable or not. +来表明这个元素是不是想要的 + +1465 +01:00:32,283 --> 01:00:32,848 +Make sense? +明白了吗? + +1466 +01:00:33,850 --> 01:00:36,351 +And there's another one you can do by mapping. +另外一个很酷的方法就是 mapping(映射) + +1467 +01:00:36,353 --> 01:00:39,387 +So this will give you a new Array where every single +这将会将你原来的 Array 中每一个元素 + +1468 +01:00:39,389 --> 01:00:43,023 +element in your Array is mapped to something else. +映射到一个新的 Array + +1469 +01:00:43,025 --> 01:00:44,458 +And the thing you map it to doesn't even have to +原来的元素通过映射后的类型甚至都 + +1470 +01:00:44,460 --> 01:00:46,693 +be the same type, so I can have an Array of Ints, and +不需要与原来的一样,好比我有一个 Int 型的 Array + +1471 +01:00:46,695 --> 01:00:49,095 +I could map it to an Array of Strings. +我可以将这些元素映射为 String 类型 + +1472 +01:00:49,097 --> 01:00:50,763 +And that's what I've done here. +这就是我在这里所做的 + +1473 +01:00:50,765 --> 01:00:52,231 +So I have this Array of Ints, 1, 2, 3, and +这里,我有一个包含1,2,3的 Int 型 Array + +1474 +01:00:52,233 --> 01:00:54,399 +I've mapped it using a closure that +我利用一个闭包将它们映射 + +1475 +01:00:54,401 --> 01:00:59,804 +returns the Stringification of it to an Arrayed Strings. +到它们的字符串形式 + +1476 +01:00:59,806 --> 01:01:02,940 +Now, you can see, incredibly concise language Swift. +从这些方法中你可以看到,Swift 语言是多么简洁 + +1477 +01:01:02,942 --> 01:01:05,976 +I mean, to take an Array of Ints and turn it into an Array +我的意思是,拿来一个 Int 型的 Array ,将 + +1478 +01:01:05,978 --> 01:01:08,578 +of Strings, no for loops, no nothing. +它转变成一个 String 型的 Array ,不需要循环 + +1479 +01:01:08,580 --> 01:01:11,147 +Just, you know, running a dozen characters here. +你只需要知道的是,你可以充分享受 + +1480 +01:01:11,149 --> 01:01:13,116 +So you really want to take advantage of some of +Swift 语言带给你的闭包特性 + +1481 +01:01:13,118 --> 01:01:15,918 +the things Swift can do with closures, syntax and +不需要撰写 + +1482 +01:01:15,920 --> 01:01:16,485 +things like that. +一大堆的代码 + +1483 +01:01:16,487 --> 01:01:20,856 +You can also reduce an entire Array to, to a single value. +还有,你可以将整个 Array reduce(减少)为一个值 + +1484 +01:01:20,858 --> 01:01:23,925 +So this one takes an argument which is the initial value you +这个方法接受一个参数 + +1485 +01:01:23,927 --> 01:01:25,059 +want to start with. +这个参数是你自定的初始值 + +1486 +01:01:25,061 --> 01:01:26,794 +And then it just takes a function that +还有一个函数作为参数 + +1487 +01:01:26,796 --> 01:01:30,364 +takes the value so far and the next element in the Array and +这个函数传入当前的值和下一个 Array 中的元素 + +1488 +01:01:30,366 --> 01:01:31,832 +you return what the combination is. +你只需要返回他们两者的组合是什么 + +1489 +01:01:31,834 --> 01:01:33,533 +So you're just combining, combining, combining. +就这样你一直组合、组合、组合,直到得到最终的结果 + +1490 +01:01:33,535 --> 01:01:36,069 +So for example if you wanted to add up an Array, +举例来说,你想要累加整个 Array 中的值 + +1491 +01:01:36,071 --> 01:01:38,571 +you could say [1, 2, 3.]reduce. +你只需要输入 [1, 2, 3].reduce + +1492 +01:01:38,573 --> 01:01:41,473 +Start with a 0, and then my closure just gonna add +然后我们以0为初始值,即第一个参数,我的闭包作为第二个参数 + +1493 +01:01:41,475 --> 01:01:48,113 +the next element, which is the $1 to, so far which is $0. +将下一个元素($1)累加起来 + +1494 +01:01:48,115 --> 01:01:52,516 +Okay all right, String. +以上就是所有 Array 中的方法,String + +1495 +01:01:52,518 --> 01:01:54,618 +So String is a little bit complicated. +String 有一点点复杂 + +1496 +01:01:57,690 --> 01:01:59,055 +I can tell all the, by the way, +今天的课程我无法将所有 String 的内容讲完 + +1497 +01:01:59,057 --> 01:02:00,790 +already I'm not gonna get to the end of this so +String 的内容可能一直要持续到 + +1498 +01:02:00,792 --> 01:02:02,658 +we'll finish this next Wednesday. +下周三的课程 + +1499 +01:02:02,660 --> 01:02:05,327 +This whole slide package here but. +这个 Slide 包在这里 + +1500 +01:02:05,329 --> 01:02:06,945 +So String. +String + +1501 +01:02:06,946 --> 01:02:08,562 +String is complicated when it comes to indexing. +字符串处理的一个难点是处理索引 + +1502 +01:02:08,565 --> 01:02:10,765 +You know, creating sub Strings and stuff like that. +和创建字符串等其他的问题 + +1503 +01:02:10,767 --> 01:02:13,368 +A lot of people are like, oh, I can't even figure out how to +一堆人会说:“我根本弄不明白怎么 + +1504 +01:02:13,370 --> 01:02:16,103 +make a subString of a String in Swift. +在 Swift 中创建一个字符串的子串 + +1505 +01:02:16,105 --> 01:02:18,155 +It's so complicated. +太复杂了” + +1506 +01:02:18,156 --> 01:02:20,206 +But once you understand that Strings are made of unicode +但是一旦你了解到字符串只不过是由一堆 Unicode 字符组成 + +1507 +01:02:20,209 --> 01:02:23,844 +characters and when you get a subString, you actually don't +的时候,你就不会希望你处理的子串的是 + +1508 +01:02:23,846 --> 01:02:26,179 +want a subString of unicode characters. +一堆由 Unicode 字符组成的了 + +1509 +01:02:26,181 --> 01:02:27,213 +You want a subString of +你想要处理的是 + +1510 +01:02:27,215 --> 01:02:29,615 +unicode characters that are on glyph boundaries. +单个的 Unicode 字素 +[字素概念引用自:https://msdn.microsoft.com/zh-cn/library/vstudio/7h9tk6x8(v=vs.100).aspx] + +1511 +01:02:29,617 --> 01:02:33,752 +A glyph is something you perceive to be a character. +字素是显示为单字符的文本单元 + +1512 +01:02:33,754 --> 01:02:34,986 +But in unicode, it could be +在 Unicode 编码中 + +1513 +01:02:34,988 --> 01:02:36,821 +multiple characters making up one glyph. +一个字素有可能由多个字符组成 + +1514 +01:02:36,823 --> 01:02:38,522 +For example, an accent. +举例说,一个重音符号 + +1515 +01:02:38,524 --> 01:02:41,291 +So you know, a lot of European languages, there's accents, +在一些欧洲语系中有重音符号 + +1516 +01:02:41,293 --> 01:02:44,561 +okay, maybe you know, in French, you have accent aigu, +你们中有些人应该知道,在法语中有 ´ 重音符号 + +1517 +01:02:44,563 --> 01:02:46,396 +right, which is the forward going top slash. +对,就是这个斜向上的横线 + +1518 +01:02:46,398 --> 01:02:48,464 +Well, that could be two unicode characters, E and +带有这个重音符号的 é 就是由两个 Unicode 字符组成,e 和 + +1519 +01:02:48,466 --> 01:02:50,433 +the accent character. +重音符号 ´ + +1520 +01:02:50,435 --> 01:02:53,302 +So two characters makes what you perceive to be one glyph. +两个 Unicode 字符组成一个字素 + +1521 +01:02:53,304 --> 01:02:57,172 +So you can't index into this String which is +所以你不能在一个字符串像数组一样 + +1522 +01:02:57,174 --> 01:02:58,206 +an Array of characters. +使用索引 + +1523 +01:02:58,208 --> 01:02:59,674 +That's what a String is, +字符串是 + +1524 +01:02:59,675 --> 01:03:01,141 +a String is Array of in essentially, +简单的说,内部是 + +1525 +01:03:01,144 --> 01:03:03,010 +internally a collection or +由一系列 Unicode 字符 + +1526 +01:03:03,012 --> 01:03:04,778 +collection of unicode characters. +组成的一个集合 + +1527 +01:03:04,780 --> 01:03:06,312 +You can't really index by Int or +你不能用整数来索引 + +1528 +01:03:06,314 --> 01:03:08,981 +you might be halfway through the e accent aigu, and +因为你有可能碰巧遇到类似的重音符号 + +1529 +01:03:08,983 --> 01:03:12,284 +you're getting you know, either the ac, accent aigu or +像数组一样用整数索引做有可能会把重音符号和 + +1530 +01:03:12,286 --> 01:03:14,319 +the e but not the character. +e 分开,而无法取得整个字符 é + +1531 +01:03:14,321 --> 01:03:17,055 +So instead Strings are indexed by this other type called +所以字符串是由另外的一个类型来索引的 + +1532 +01:03:17,057 --> 01:03:18,890 +String.index. +这种类型叫 String.Index + +1533 +01:03:18,892 --> 01:03:20,024 +Okay? Now how do +接下来,你如何 + +1534 +01:03:20,026 --> 01:03:22,193 +you get a String.index? +获得一个 String.Index 呢? + +1535 +01:03:22,195 --> 01:03:22,826 +Okay, well, yes. +好 + +1536 +01:03:22,828 --> 01:03:23,660 +It's saying here. +用 Slide 上这里说的函数 + +1537 +01:03:23,662 --> 01:03:25,862 +Okay? +明白了吗? + +1538 +01:03:25,863 --> 01:03:28,063 +So you get a sting.index by getting the startIndex of +你可以通过 startIndex 来获取这个字符串的开始位置 + +1539 +01:03:28,066 --> 01:03:29,299 +the String. +来得到一个 String.Index 类型的变量 + +1540 +01:03:29,300 --> 01:03:30,533 +That gives you String.index that point to +刚才的那个方法,它会返回给你一个指向字符串开头的 + +1541 +01:03:30,535 --> 01:03:31,967 +the first character of the String. +String.Index 的变量 + +1542 +01:03:31,969 --> 01:03:34,903 +And then you advance it forward, +然后你可以讲这个索引向后推进 + +1543 +01:03:34,905 --> 01:03:36,505 +however many times you wanna go. +随便你想推进多少次都行 + +1544 +01:03:36,507 --> 01:03:38,306 +So in other words, you have to look through the characters so +换言之,你在遍历整个字符的过程中 + +1545 +01:03:38,308 --> 01:03:40,141 +that it will jump over e accent aigu, +这种方法它会跳过整个 é 而不是只跳过一个 e 而停在重音符号上 + +1546 +01:03:40,143 --> 01:03:42,443 +both characters to the next one, you see? +明白了吗? + +1547 +01:03:43,646 --> 01:03:45,278 +So you do that with this function, +而你可以你使用下面的这个函数来推进你的 String.Index + +1548 +01:03:45,280 --> 01:03:47,914 +it's not a method in String, it's actually just a function, +这不是 String 类中的一个方法,这只是一个函数 + +1549 +01:03:47,916 --> 01:03:50,183 +a global function called advance. +一个叫 advance 的全局函数 + +1550 +01:03:50,185 --> 01:03:52,618 +And you give it the index, okay, and +你传入索引 + +1551 +01:03:52,620 --> 01:03:55,187 +you tell it how many times you want it to move forward. +同时,你告诉这个函数你想向后推进多少次 + +1552 +01:03:55,189 --> 01:03:58,123 +And it will give you back a new index. +然后它就会返回给你一个新的索引位置 + +1553 +01:03:58,125 --> 01:03:59,491 +So here's an example. +这里举一个例子 + +1554 +01:03:59,493 --> 01:04:01,859 +I have a String that says hello, okay? +我有一个内容为 hello 的字符串 + +1555 +01:04:01,861 --> 01:04:05,462 +I wanna get the index of the L, the first L. +我想要知道第一个 l 的位置 + +1556 +01:04:05,464 --> 01:04:06,596 +Okay? So I say, +我只需要输入 + +1557 +01:04:06,598 --> 01:04:08,765 +let the index equal advance, +let index = advance ... + +1558 +01:04:08,767 --> 01:04:11,767 +the startIndex of that String, go forward two. +advance(s.startIndex, 2) + +1559 +01:04:12,903 --> 01:04:13,769 +Okay? +明白了吗? + +1560 +01:04:13,771 --> 01:04:15,487 +So now it's pointing at the l. +然后它就会指向第一个 l 了 + +1561 +01:04:15,488 --> 01:04:17,204 +It went forward one to the e, now forward one to the l. +向前1个会指向 e,向后一个会指向 l + +1562 +01:04:17,207 --> 01:04:18,806 +And again, if that, it was e accent aigu, +这里我再重申,假如这里不是 e 而是一个 é + +1563 +01:04:18,808 --> 01:04:21,642 +it would have gone forward four Unicode characters, but +刚才的操作他会向前推进4个 Unicode 字符 + +1564 +01:04:21,644 --> 01:04:25,446 +only three to the third glyph, as you perceive it, okay? +但只有第3个字符是 e + +1565 +01:04:25,448 --> 01:04:28,715 +So now that I have a pointer to that L, I could use, for +接下来,既然我已经有一个指向 l 的指针 + +1566 +01:04:28,717 --> 01:04:31,484 +example, a nice String function called splice. +我就可以用一个 String 类中的方法,叫 splice + +1567 +01:04:31,486 --> 01:04:33,953 +So splice is just like the splice in Array. +字符串中的 splice 和数组中的 splice 方法很像 + +1568 +01:04:33,955 --> 01:04:38,157 +It will splice a String into the middle of another String. +它会将一个字符串拼合到另外的一个字符串之中 + +1569 +01:04:38,159 --> 01:04:40,459 +Okay? And I'm gonna have a splice at +明白吗?如果我在这个位置使用了 splice 方法 + +1570 +01:04:40,461 --> 01:04:44,229 +that index, and that's gonna make it be heabcllo. +(另外一个字符串是 abc 的话)那么原先的字符串就会变成 heabcllo + +1571 +01:04:44,231 --> 01:04:47,265 +Splice the abc right into the middle there. +将 abc 加入到这个中间的位置 + +1572 +01:04:47,267 --> 01:04:49,233 +Okay? +明白了吗? + +1573 +01:04:49,235 --> 01:04:53,303 +So, this startIndex is the magic behind making that work. +所以 startIndex 是在幕后起关键作用的 + +1574 +01:04:53,305 --> 01:04:56,840 +Also if I said, if I got two local variables star deck, +另外假如我说,我有两个局部变量 startIndex + +1575 +01:04:56,842 --> 01:05:00,477 +Index, and endIndex, which I made by taking advance of +和 endIndex + +1576 +01:05:00,479 --> 01:05:02,478 +the startIndex by one and six. +startIndex 是由最初的 startIndex 向后推进1个字符得到的,endIndex 是向后推进6个得到的 + +1577 +01:05:02,480 --> 01:05:05,448 +So this is going to be, I want it to be from index one to +这也就意味着,我想这两个变量一个指向索引1的位置 + +1578 +01:05:05,450 --> 01:05:08,150 +index six, then I could get a subString and +另一个指向索引6的位置,然后我可以在这两个范围内创建一个子串 + +1579 +01:05:08,152 --> 01:05:11,253 +I get a subString and in the String exactly the same like +就像数组创建子数组一样 + +1580 +01:05:11,255 --> 01:05:13,221 +an Array, square brackets. +使用方括号得到一个字符串的子串 + +1581 +01:05:13,223 --> 01:05:14,689 +String, square brackets. +也就是说,字符串也可以使用方括号来创建子串 + +1582 +01:05:14,691 --> 01:05:17,792 +But inside that square brackets goes a range. +方括号里面是一个范围 + +1583 +01:05:17,794 --> 01:05:19,326 +And the range, the dot, dot, +范围由两个 String.Index 类型的 + +1584 +01:05:19,328 --> 01:05:22,529 +dot thing has to have a String.index on the left and +变量组成,一个在左侧 + +1585 +01:05:22,531 --> 01:05:26,265 +a String.index on the right, not Ints. +一个在右侧,中间是 .. + +1586 +01:05:26,267 --> 01:05:27,633 +Okay? +String.Index 类型而不是 Int 型,明白了吗? + +1587 +01:05:27,634 --> 01:05:29,000 +So here I got String.index. +这里我 + +1588 +01:05:29,003 --> 01:05:31,937 +By doing this advance for the left and a String.Index on +通过向前推进到左侧的位置和右侧的位置,得到 + +1589 +01:05:31,939 --> 01:05:34,673 +the right, until the subString will be eabcl. +截断的子串为 eabcl 的两个 String.Index 类型的变量 + +1590 +01:05:34,675 --> 01:05:36,574 +Cuz I went from index one, +因为我从索引1的位置 + +1591 +01:05:36,576 --> 01:05:41,112 +which is the second character, index zero is the first, or, +也就是是第二个字符,索引0是第一个字符,这跟数组索引情况相似 + +1592 +01:05:41,114 --> 01:05:44,581 +to index six, not including index six, okay? +到索引6,但是不包括索引6 + +1593 +01:05:44,583 --> 01:05:46,049 +Everyone understand String.Index now? +每个人都理解了 String.Index 了吗? + +1594 +01:05:46,051 --> 01:05:49,552 +It's all about advance, 'kay? +以上这些是关于 advance 函数的 + +1595 +01:05:49,554 --> 01:05:52,588 +The advance function is the key to understanding how to +advance 函数是理解如何创建子串的关键 + +1596 +01:05:52,590 --> 01:05:54,957 +subString Strings. + +1597 +01:05:54,959 --> 01:05:57,126 +And, there's lots of other, once you understand this, +还有其他的东西,一旦你弄懂了这个 + +1598 +01:05:57,128 --> 01:05:58,527 +there's things like range of String. +类似 rangeOfString 这样的东西你也会明白了 + +1599 +01:05:58,529 --> 01:06:01,629 +Remember we used range of String in calculator, and it, +还记得我们在我们的计算器应用中用到了 rangeOfString + +1600 +01:06:01,631 --> 01:06:04,365 +I told you it returned nil if it couldn't find it? +我告诉过你们,如果 rangeOfString 不能找到的想要的范围的话,会返回 nil + +1601 +01:06:04,367 --> 01:06:06,834 +Well, what does it return if it could find it? +那么如果 rangeOfString 能找到范围的话,它会返回什么? + +1602 +01:06:06,836 --> 01:06:09,536 +Well, it returns a Range of String.Index. +它会返回 Range + +1603 +01:06:09,538 --> 01:06:11,388 +Actually, it +实际上 + +1604 +01:06:11,389 --> 01:06:13,239 +returns an Optional Range of String.Index. +它会返回一个 Optional 的 Range + +1605 +01:06:13,242 --> 01:06:14,607 +Okay? That's how, if you used it for +明白了吗?这就是如何使用这个方法 + +1606 +01:06:14,609 --> 01:06:15,908 +your assignment, that's how you used it. +你们的作业中可能会用到它 + +1607 +01:06:15,910 --> 01:06:17,543 +You used the Optional nature of it, +你可以用到它 Optional 的性质 + +1608 +01:06:17,545 --> 01:06:20,212 +but now you can even use the Range nature of it. +你更可以用到它 Range 的性质 + +1609 +01:06:20,214 --> 01:06:22,498 +So for example, if we wanted to +比如我们想要在一个含有数字的字符串中 + +1610 +01:06:22,499 --> 01:06:24,783 +get the whole number portion of a String that had a number. +获取其中的数字部分 + +1611 +01:06:24,785 --> 01:06:27,252 +So I have, let's say, 56.25 as a String, +这里我有一个“56.25”的字符串 + +1612 +01:06:27,254 --> 01:06:29,020 +I wanna get the whole number part. +我想要获取整个数字部分 + +1613 +01:06:29,022 --> 01:06:33,457 +I could just say find me that decimal point. +我可以这么做——首先找到小数点 + +1614 +01:06:33,459 --> 01:06:34,942 +Kay? And that's gonna +然后 + +1615 +01:06:34,943 --> 01:06:36,426 +return a range if, if it can find it. +它会返回一个范围,如果它能够找到小数点 + +1616 +01:06:36,428 --> 01:06:37,844 +If there's a decimal point in +如果在我刚才的字符串中有小数点的话 + +1617 +01:06:37,845 --> 01:06:39,261 +there it's gonna return that range. +这个方法会返回那个范围 + +1618 +01:06:39,264 --> 01:06:43,232 +And I'm gonna grab the part from the num.startIndex, +接着我就可以用 num.startIndex 来获取那部分了 + +1619 +01:06:43,234 --> 01:06:46,102 +you see the num is the number, it's startIndex all the way +这里你可以看到 num 是一个数字,他的 startIndex 是 + +1620 +01:06:46,104 --> 01:06:49,805 +to where the decimal is, not including the decimal, okay? +小数点之后的那个位置,而不是小数点,明白了吗? + +1621 +01:06:49,807 --> 01:06:51,406 +Now I've got sub String which is the whole part. +现在我已经从字符串中提取了我想要的那部分 + +1622 +01:06:53,476 --> 01:06:54,108 +Are we cool with that? +理解了吗? + +1623 +01:06:55,544 --> 01:06:57,644 +So sub Stringing and Strings actually, +所以,字符串和子字符串 + +1624 +01:06:57,646 --> 01:07:01,247 +once you understand this whole index thing pretty powerful. +一旦你了解了这些方法, + +1625 +01:07:01,249 --> 01:07:03,416 +We could even remove the whole number part. +我们就可以利用它们在字符串中移除整个数字部分 + +1626 +01:07:03,418 --> 01:07:06,185 +'Kay, just by using removeRange of that same +只需要对相同的范围使用 removeRange + +1627 +01:07:06,187 --> 01:07:09,421 +range, num.startIndex, the decimal range. +num.startIndex,小数的范围 + +1628 +01:07:09,423 --> 01:07:12,357 +Or we can replace the range with other things, etc. +或者我们可以将这个范围替换成其他的东西,等等 + +1629 +01:07:12,359 --> 01:07:15,060 +Okay, so there's a lot of String methods there for +好的,对字符串进行修改的方法大多数 + +1630 +01:07:15,062 --> 01:07:17,895 +doing that and they're all based on that String index. +都基于字符串的索引 + +1631 +01:07:17,897 --> 01:07:19,363 +Okay, other String methods, +还有另外一些字符串的方法 + +1632 +01:07:19,365 --> 01:07:21,265 +I'm gonna start blasting through a lot of this. +我会快速讲解其中的一些 + +1633 +01:07:21,267 --> 01:07:22,933 +You could look these all up in the documentation. +你可以在文档里找到所有的这些方法 + +1634 +01:07:22,935 --> 01:07:24,567 +Some of these it actually gets from NSString, +其中一些实际上从 NSString 中来的 + +1635 +01:07:24,569 --> 01:07:26,402 +which I'm gonna talk about in a moment. +稍后我会讲一下 NSString + +1636 +01:07:26,404 --> 01:07:28,771 +You can see that you can find the endIndex, +你看你从 Slide 上可以找到 endIndex + +1637 +01:07:28,773 --> 01:07:31,740 +there is the join takura talked about before +还有我们之前讨论过的 join 方法 + +1638 +01:07:31,742 --> 01:07:36,544 +notice that there's toInt but not toDouble. +注意,还有一个方法是 toInt 而不是 toDouble + +1639 +01:07:36,546 --> 01:07:38,880 +Why is there toInt in String and not toDouble? +为什么在字符串操作中只有 toInt 而没有 toDouble? + +1640 +01:07:38,882 --> 01:07:40,614 +Anybody having any idea why it is? +有人知道原因吗? + +1641 +01:07:43,118 --> 01:07:45,485 +It's because when you convert to a Double, +这是因为如果你转换到一个 Double 时 + +1642 +01:07:45,487 --> 01:07:46,986 +you have to specify things. +你需要指定一些东西 + +1643 +01:07:46,988 --> 01:07:48,721 +How many significant digits do you want? +你需要多少的有效位数? + +1644 +01:07:48,723 --> 01:07:50,723 +How many digits after the fraction do you want, +你需要小数点后几位? + +1645 +01:07:50,725 --> 01:07:52,258 +things like that? +如此之类的问题 + +1646 +01:07:52,259 --> 01:07:53,792 +And so there's really nowhere to specify that. +事实上没有地方去指定这些东西 + +1647 +01:07:53,794 --> 01:07:55,560 +It would have to be toDouble with a whole bunch of +如果有一个 toDouble 方法,那么会有一大堆的 + +1648 +01:07:55,562 --> 01:07:57,795 +arguments to specify how you wanna do that conversion. +参数来指定转换中的一些细节 + +1649 +01:07:57,797 --> 01:08:00,498 +When you convert to an Int, there's nothing inside, +但当你将字符串转换为 Int 时,这些细节都不存在了 + +1650 +01:08:00,500 --> 01:08:01,899 +you just convert it to the Int, right? +你仅仅需要将它转换为 Int,对吗? + +1651 +01:08:01,901 --> 01:08:05,602 +So the whole number so but notice that toInt does return +注意,toInt 方法返回的是一个 Optional Int, + +1652 +01:08:05,604 --> 01:08:08,672 +an Optional Int, that's because if you say toInt, +那是因为,当你调用 toInt 方法时 + +1653 +01:08:08,674 --> 01:08:13,509 +if you send out to hello, it's going to be nil, okay? +但是你的字符串是“hello”,此时会返回 nil,明白了吗? + +1654 +01:08:13,511 --> 01:08:15,844 +So, String methods, all right? +String 中的方法,没问题了吧? + +1655 +01:08:16,880 --> 01:08:20,248 +Okay, there's kind of a hidden bunch of methods which you +好的,其实有一些隐藏的方法 + +1656 +01:08:20,250 --> 01:08:24,018 +don't even know about, which is conversions using init. +这些方法你根本不知道,这就是使用初始化方法实现转换 + +1657 +01:08:24,020 --> 01:08:26,220 +So for example, if I had a Double and +比如,我有一个 Double 的值 + +1658 +01:08:26,222 --> 01:08:31,224 +a Float, I could say, let x equal Int of that Double, and +浮点数,我可以利用 let x = Int(d), + +1659 +01:08:31,226 --> 01:08:35,461 +I just basically create a floor and turned it to an int. +我就可以对这个值取下整并将它转化为一个 Int + +1660 +01:08:35,463 --> 01:08:37,029 +So I converted it. +这就是我如何转换的 + +1661 +01:08:37,030 --> 01:08:38,596 +So I know you convert things and +我知道你们把这个东西转换成那个东西 + +1662 +01:08:38,599 --> 01:08:39,865 +convert them from one thing to another. +或者从那个东西转换成这个东西 + +1663 +01:08:39,867 --> 01:08:42,834 +It makes total sense with the number values like Ints and +像 Int 和 Float 或者类似的 + +1664 +01:08:42,836 --> 01:08:44,152 +Floats and things like that. +都可以这么做来相互转换 + +1665 +01:08:44,153 --> 01:08:45,469 +And you're gonna see CGFloat next week. +下周你们会使用到 CGFloat + +1666 +01:08:45,472 --> 01:08:47,905 +That's another kind of floating point number. +这是另外一种浮点数 + +1667 +01:08:47,907 --> 01:08:49,340 +And you can convert using. +同样你可以通过转换使用它 + +1668 +01:08:49,342 --> 01:08:50,741 +There's no toInt or anything. +但是 CGFloat 没有 toInt 或者其他的方法 + +1669 +01:08:50,743 --> 01:08:53,410 +You just create a new one with the initializer. +你只能通过初始化方法(initializer)创建一个 CGFloat 对象 + +1670 +01:08:53,412 --> 01:08:54,411 +'Kay, so the numbers. +接下来,Numbers + +1671 +01:08:54,413 --> 01:08:56,212 +But you almost might be surprised. +你会感到惊讶的是 + +1672 +01:08:56,214 --> 01:08:57,747 +Actually, if you read the homework carefully or +如果你之前认真地读过了课后作业的要求 + +1673 +01:08:57,749 --> 01:08:59,715 +the reading assignment, you saw this. +你会看到 + +1674 +01:08:59,717 --> 01:09:02,217 +Is that you can convert Arrays and +你可以在 Array 和字符串之间 + +1675 +01:09:02,219 --> 01:09:06,521 +Strings using these initializer. +通过初始化方法完成相互转化 + +1676 +01:09:06,523 --> 01:09:11,158 +For example, you can say Array of a String, so create a new +举例,你通过调用 Array("abc") 来 + +1677 +01:09:11,160 --> 01:09:13,927 +Array and the initializers argument is a String. +创建一个数组 + +1678 +01:09:13,929 --> 01:09:15,095 +And it will return you an Array of +这个方法会返回一个数组 + +1679 +01:09:15,097 --> 01:09:18,231 +all the characters in that String, right? +而数组中的元素是字符串中的字符 + +1680 +01:09:18,233 --> 01:09:20,800 +Unicode characters. +Unicode 字符 + +1681 +01:09:20,801 --> 01:09:23,368 +Or vice versa, you can have an Array of unicode characters. +相反的,你有一个包含一堆 Unicode 字符的数组 + +1682 +01:09:23,371 --> 01:09:25,404 +Right? +是吧? + +1683 +01:09:25,405 --> 01:09:27,438 +And it will, and you pass that to Strings constructor and +你可以使用 String 的构建器(constructor)来创建一个字符串 + +1684 +01:09:27,441 --> 01:09:29,974 +it will return the String with those things zipped up. +字符串中字符由数组中元素拼接而成 + +1685 +01:09:31,377 --> 01:09:32,660 +Okay? +明白了吗? + +1686 +01:09:32,661 --> 01:09:33,944 +So there's kind of a hidden thing there. +所以还有一些隐藏的方法 + +1687 +01:09:35,647 --> 01:09:38,214 +Notice that you can't do String of 52.5, +但是,注意你不能调用 let s = String(52.5) + +1688 +01:09:38,216 --> 01:09:40,950 +but that's okay because you have that back slash, +但是你可以通过 let s = "\(37.5)" 来实现 + +1689 +01:09:40,952 --> 01:09:43,319 +open-parenthesis thing to convert. +浮点数到字符串之间的 + +1690 +01:09:43,321 --> 01:09:45,087 +Of Floats to Strings. +转换 + +1691 +01:09:46,857 --> 01:09:47,722 +Okay? You can do +明白了吗?你可以 + +1692 +01:09:47,724 --> 01:09:49,190 +String of 52 though. +let s = String(52) 这么做 + +1693 +01:09:49,192 --> 01:09:51,359 +Cuz it has toInt, it kinda knows how to do that. +因为 String 有 toInt 这个方法,它知道如何将 Int 转换成字符串 + +1694 +01:09:52,728 --> 01:09:54,294 +All right, assertions. +接下来,Assertions + +1695 +01:09:54,296 --> 01:09:57,364 +So assertions, really valuable debugging aid. +Assertions 是一个很有用的 debug 方法 + +1696 +01:09:57,366 --> 01:10:01,200 +They basically take a closure as the first argument. +它们接受一个闭包作为其第一个参数 + +1697 +01:10:01,202 --> 01:10:02,434 +It's an auto closure, +闭包是 autoclosure 的 + +1698 +01:10:02,436 --> 01:10:03,635 +which means you don't need the curly braces. +这意味着你不需要花括号 + +1699 +01:10:03,637 --> 01:10:05,937 +Is this just kind of funky think, okay. +这是一个很有意思的事情 + +1700 +01:10:06,940 --> 01:10:10,041 +So the first argument is what would be inside the, +总而言之,第一个参数应该是 + +1701 +01:10:10,043 --> 01:10:11,275 +the curly braces of a closure. +在闭包括号内的那些东西 + +1702 +01:10:11,277 --> 01:10:14,244 +And the second argument is some String that's gonna be +assert() 的第二个参数是一个字符串 + +1703 +01:10:14,246 --> 01:10:18,181 +printed out on your console because assert, if whatever +假如 assert 方法的第一个参数返回的是 false + +1704 +01:10:18,183 --> 01:10:21,184 +that thing that was in the auto-closure evaluates to, +这个字符串将会在你的控制台中输出 + +1705 +01:10:21,186 --> 01:10:22,818 +if that's not true. + +1706 +01:10:22,820 --> 01:10:24,720 +'Kay, cuz you're asserting that that's true, +这是因为你 assert 的条件应该是成立的 + +1707 +01:10:24,722 --> 01:10:26,154 +then it's gonna crash your program. +如果不成立,那么它会导致你的程序崩溃 + +1708 +01:10:27,257 --> 01:10:28,356 +Okay, and print that message out. +这时在控制台中输出一个信息 + +1709 +01:10:28,358 --> 01:10:30,241 +So it's a great way to make +对程序的 debug 是很有帮助的 + +1710 +01:10:30,242 --> 01:10:32,125 +your program crash when things that should be true aren't. +因为你的程序因为某些条件的不满足而导致崩溃 + +1711 +01:10:32,128 --> 01:10:35,796 +Now, asserts don't work when you build your program for +assert 方法会在你生成程序的 Release 版本的时候 + +1712 +01:10:35,798 --> 01:10:37,497 +release, like to the App Store. +失效,比如提交到 App Store 的版本 + +1713 +01:10:37,499 --> 01:10:40,600 +When you're shipping to the App Store, asserts don't work. +当你在把程序提交到 App Store 的时候,assert 不会工作 + +1714 +01:10:40,602 --> 01:10:42,635 +It doesn't even evaluate the closure, okay, +这时,它甚至不会对闭包求值 + +1715 +01:10:42,637 --> 01:10:43,302 +they're just ignored. +它们被忽略了 + +1716 +01:10:44,405 --> 01:10:46,138 +But for debugging, it's pretty good. +这个在 debug 中很有用 + +1717 +01:10:46,140 --> 01:10:50,108 +So I might have a function called validation that should, +我可能会有一个叫 validation 的函数 + +1718 +01:10:50,110 --> 01:10:52,944 +at this point that I'm executing this assert +当我在执行 assert 的时候 + +1719 +01:10:52,946 --> 01:10:54,945 +not be returning nil. +不应该返回 nil + +1720 +01:10:54,947 --> 01:10:59,249 +And if it does return nil then I'm going to crash here. +而且,它如果返回 nil 了,这会把程序搞崩溃 + +1721 +01:10:59,251 --> 01:11:01,685 +So I say the assertion is that validation should not be +这里我写 assert(validation() != nil, "the validation fucniton return nil") + +1722 +01:11:01,687 --> 01:11:04,087 +nil right now. + +1723 +01:11:04,089 --> 01:11:04,653 +'Kay? + +1724 +01:11:05,890 --> 01:11:10,291 +So a lot of languages have assert so Swift does too. +assert 在很多语言中都有实现,Swift 也有一样 + +1725 +01:11:10,293 --> 01:11:12,827 +okay, other function, so there's a lot of function and +好的,还有一些其他的函数 + +1726 +01:11:12,829 --> 01:11:15,830 +these do not appear to be documented anywhere yet. +这些函数并没有出现在文档中 + +1727 +01:11:15,832 --> 01:11:18,332 +So the slide might be your only documentation. +所以我的 Slide 可能是唯一你们可以参考的文档 + +1728 +01:11:18,334 --> 01:11:20,033 +I'm sure you can find about them on the internet instead +我相信你们在网上也可以找到这些 + +1729 +01:11:20,035 --> 01:11:22,002 +of too but there's a lot of functions. +可能网上的资料还要更详细一点 + +1730 +01:11:22,004 --> 01:11:24,303 +These are global functions, not methods. +这些是全局函数,并不是 String, Array 或者其他的 struct 的方法 + +1731 +01:11:24,305 --> 01:11:26,872 +They take arguments which are hard for +它们接受一些参数,这些参数 + +1732 +01:11:26,874 --> 01:11:28,907 +me to explain to you right now. +目前我很难跟你们解释 + +1733 +01:11:28,909 --> 01:11:32,044 +But basically they take Arrays and Strings, and Dictionaries, +但是你们只需要知道这些函数可以接受 Array, Dictionary, String 的参数 + +1734 +01:11:32,046 --> 01:11:34,245 +because they take other things that Arrays and +因为它们还接受 Array, Dictionary, String 的参数 + +1735 +01:11:34,247 --> 01:11:37,448 +Strings, and Dictionaries are, those things. +和其他的一些东西 + +1736 +01:11:37,450 --> 01:11:40,985 +But you can look through this list kinda interesting things. +你可以看一遍这个列表 + +1737 +01:11:40,987 --> 01:11:42,853 +I can combine it with the thing I +我会将它和 String 中的方法 + +1738 +01:11:42,855 --> 01:11:45,956 +was talking about at the end there with the String. +混合在一起 + +1739 +01:11:45,958 --> 01:11:47,624 +Passing in an Array of characters. +传入一个由字符组成的数组 + +1740 +01:11:47,626 --> 01:11:51,694 +I can actually take a String, call a reverse, which returns +我可以拿一个字符串,在它之上调用 reverse 方法 + +1741 +01:11:51,696 --> 01:11:55,731 +an Array of the characters reversed and then call String +返回这些字符的反转,然后再调用 + +1742 +01:11:55,733 --> 01:11:59,201 +to push it back and call it, create a String again. +String 的方法创建一个新的字符串 + +1743 +01:11:59,203 --> 01:12:00,502 +All right? +明白了吗? + +1744 +01:12:00,504 --> 01:12:02,070 +Objective-C Compatibility. +Objective-C 兼容性 + +1745 +01:12:02,072 --> 01:12:04,322 +You know what? +这个话题 + +1746 +01:12:04,323 --> 01:12:06,573 +We are going to wait and talk about this next time. +我们下一次再讲 + +1747 +01:12:06,576 --> 01:12:08,009 +Very important topic. +这是一个很重要的话题 + +1748 +01:12:08,010 --> 01:12:09,443 +But I don't want to give it short shrift. +我想好好探讨一下 + +1749 +01:12:09,445 --> 01:12:11,178 +So, that is it for today. +这就是今天课程的所有内容 + +1750 +01:12:11,180 --> 01:12:15,882 +Let me, quickly, show you, this slide. +最后让我快速给你们看一下这页 Slide + +1751 +01:12:17,719 --> 01:12:20,052 +Okay coming up, no Friday section this week. +周五没有课程 + +1752 +01:12:20,054 --> 01:12:21,820 +Next Monday is holiday, no lecture. +下周一是节假日,也没有课程 + +1753 +01:12:21,822 --> 01:12:23,138 +Next Wednesday, +下周三 + +1754 +01:12:23,139 --> 01:12:24,455 +I might not be talking about auto layout next week, +我可能会讲一些 Auto Layout 的话题 + +1755 +01:12:24,458 --> 01:12:26,425 +I'm not sure. +但不一定 + +1756 +01:12:26,426 --> 01:12:28,393 +Your homework one was due today, your homework two was +课后作业一今天截止,课后作业二 + +1757 +01:12:28,395 --> 01:12:31,529 +already posted, your reading assignment two was posted on +我也贴出来了,你们的阅读作业二会在 + +1758 +01:12:31,531 --> 01:12:35,165 +Monday, all that stuff is due next Wednesday. +(下)周一贴上来,然后所有的东西下周三截止 + +1759 +01:12:35,167 --> 01:12:36,933 +If you have any questions, I'm here. +如果你们有其他的疑问,欢迎来询问 + +1760 +01:12:36,935 --> 01:12:42,405 +[SOUND] For more, please visit us at stanford.edu. +更多课程,请访问 stanford.edu diff --git a/subtitles/5. Objective-C Compatibility, Property List, Views.srt b/subtitles/5. Objective-C Compatibility, Property List, Views.srt new file mode 100644 index 0000000..818e40a --- /dev/null +++ b/subtitles/5. Objective-C Compatibility, Property List, Views.srt @@ -0,0 +1,9069 @@ +1 +00:00:00,001 --> 00:00:04,636 +[MUSIC] +[音乐] + +2 +00:00:04,638 --> 00:00:07,672 +Stanford University. +斯坦福大学 + +3 +00:00:13,579 --> 00:00:18,248 +Okay, well welcome to Stanford CS193p, Winter of 2015. +欢迎来到2015冬季学期,斯坦福大学CS193P课程。 + +4 +00:00:18,250 --> 00:00:20,983 +This is lecture number five. +这次是第五讲。 + +5 +00:00:20,985 --> 00:00:22,318 +And, today we're gonna finish up +这次我们要继续上次没讲完 + +6 +00:00:22,320 --> 00:00:24,486 +what were talking about last time. +的内容。 + +7 +00:00:24,488 --> 00:00:27,289 +And talk a little bit about Objective-C compatibility, +然后再说一点关于Objective-C兼容性的问题。 + +8 +00:00:27,291 --> 00:00:29,991 +because, of course iOS was originally written in +因为iOS起初是用Objective-C 这种 + +9 +00:00:29,993 --> 00:00:31,426 +an entirely different language. +完全不同于Swift的语言写的。 + +10 +00:00:31,428 --> 00:00:33,078 +And so there's a little bit of +所以在旧世界和Swift的世界中间 + +11 +00:00:33,079 --> 00:00:34,729 +bridging between the Swift world and the old world. +需要有一个桥接。 + +12 +00:00:34,731 --> 00:00:37,931 +And we're gonna talk about an example of +然后我们会讲 Property List,这是适用 + +13 +00:00:37,933 --> 00:00:41,168 +using AnyObject which is Property Lists. +AnyObject的又一个例子。 + +14 +00:00:41,170 --> 00:00:43,703 +And I'm gonna do a kind of a brief demo even, +这里我会用一个简单的 + +15 +00:00:43,705 --> 00:00:45,104 +showing you that. +demo来演示这个。 + +16 +00:00:45,106 --> 00:00:50,793 +Then we're gonna move onto a completely new topic, which is views. +然后我们就要开始一个全新的课题,view + +18 +00:00:50,794 --> 00:00:53,645 +So, views on how we draw, and how we handle touch input. +是关于在我们的UI里,如何绘制view, + +19 +00:00:53,647 --> 00:00:56,381 +In our UI and so we're gonna go over that, and +如何响应触屏事件,先讲一些内容,然后 + +20 +00:00:56,383 --> 00:00:58,116 +I'll be having a demo for that as well. +依然会有一个demo。 + +21 +00:00:58,118 --> 00:01:00,818 +So, I'm gonna blast through these slides pretty quick. +幻灯片我可能会讲的比较快。 + +22 +00:01:00,820 --> 00:01:04,188 +As usual, the demonstration is probably +总体来说,示例会比幻灯片更 + +23 +00:01:04,190 --> 00:01:06,823 +a little more elucidating then some of the slides, cuz when +容易让你们理解,因为当你们真正看见如何做的 + +24 +00:01:06,825 --> 00:01:08,925 +you see it in action, it's a lot easier to understand. +时候,知识会容易理解的多。 + +25 +00:01:08,927 --> 00:01:11,995 +Okay. + +26 +00:01:11,996 --> 00:01:15,064 +So, Objective-C compatibility, so, virtually all the iOS API, +下面开始讲 Objective-C 兼容的问题, 基本上iOS全部的API都是 + +27 +00:01:15,066 --> 00:01:20,002 +this API that was written over the last, however many years, +在之前许多年内用 Objective-C 写的。 + +28 +00:01:20,004 --> 00:01:23,905 +in Objective-C, is available from Swift. +现在在Swift里也可以用。 + +29 +00:01:23,907 --> 00:01:25,773 +And you can't even tell the difference, okay? +甚至你都看不出区别来。 + +30 +00:01:25,775 --> 00:01:29,176 +It's just kind of, automatically made available. +就好像非常自然的就可以用一样。 + +31 +00:01:29,178 --> 00:01:30,711 +And, when they designed Swift, +但是当他们设计Swift的时候, + +32 +00:01:30,713 --> 00:01:33,513 +they went to a lot of trouble to make sure that it would, +为了达到非常好的兼容性,他们遇到了 + +33 +00:01:33,515 --> 00:01:35,515 +could be done in a very compatible way. +很多麻烦。 + +34 +00:01:35,517 --> 00:01:38,785 +So, that all of the iOS API, would work, +所以现在的这些 API,在Swift里 + +35 +00:01:38,787 --> 00:01:40,553 +just fine in Swift. +还算能用。 + +36 +00:01:40,555 --> 00:01:44,523 +There's few special data types though, that they've gone +但是有一些特殊的数据类型,在交接两种语言的 + +37 +00:01:44,525 --> 00:01:49,294 +to special care to bridge between the two languages, +时候需要特殊的注意。 + +38 +00:01:49,296 --> 00:01:54,532 +and this makes using iOS API from Objective-C, much easier +这使得使用 Objective-C 调用 iOS API的时候,会比Swift + +39 +00:01:54,534 --> 00:01:58,235 +in Swift, and so, I'm gonna talk briefly about those. +容易很多,我下边会简要的说一下这个问题。 + +40 +00:01:58,237 --> 00:02:00,203 +One is NSString. +其中一个就是 NSString 。 + + +41 +00:02:00,205 --> 00:02:02,939 +That is the old way that String were represented, +这是String以前的形式, + +42 +00:02:02,941 --> 00:02:06,775 +in iOS, and that is bridged interchangeably to +在iOS里, 它与Swift的String + +43 +00:02:06,777 --> 00:02:07,909 +Swift's String. +是可以互换使用的。 + +44 +00:02:07,911 --> 00:02:09,310 +You can't really even tell the difference. +甚至可以当它们没有区别。 + +45 +00:02:09,312 --> 00:02:11,546 +If you have a method that takes an NSString, +如果有一个方法接受 NSString 的参数, + +46 +00:02:11,548 --> 00:02:14,415 +you can pass a Swift String in there, and vice-versa. +你可以传一个Swift的String进去,反之亦然。 + +47 +00:02:14,417 --> 00:02:16,283 +Okay, they're just automatically treated if +尽管他们两个是非常不同的东西, + +48 +00:02:16,285 --> 00:02:17,317 +they were the same thing, +它们还是被当成 + +49 +00:02:17,319 --> 00:02:19,119 +even though they are quite different things. +完全一样的。 + +50 +00:02:19,121 --> 00:02:22,088 +String in Swift is not even a class. +Swift里的String甚至都不是一个类, + +51 +00:02:22,090 --> 00:02:23,189 +Okay, its just a struct. +而仅仅是一个 struct 。 + +52 +00:02:23,191 --> 00:02:26,258 +So, they've done some miraculous work to +苹果的人做了非常神奇的工作把 + +53 +00:02:26,260 --> 00:02:27,592 +bridge these things. +它们桥接了起来。 + +54 +00:02:27,594 --> 00:02:30,528 +NSArray, which is the old Array, +数组的老版本, NSArray, + +55 +00:02:30,530 --> 00:02:33,865 +is bridged to Array of AnyObject. +桥接到Swift 里就是 AnyObject 元素组成的数组。 + +56 +00:02:33,867 --> 00:02:37,468 +Okay, so any time you see, an Array of AnyObject in +所以以后只要你们在iOS的API里看到 + +57 +00:02:37,470 --> 00:02:42,439 +an iOS API, it's because it was an NSArray before, okay? +AnyObject 的数组,说明他们以前都是 NSArray 。 + +58 +00:02:42,441 --> 00:02:44,374 +Then NSDictionary is an interesting one, +NSDictionary 是比较有趣的一个, + +59 +00:02:44,376 --> 00:02:47,343 +it's bridged to Dictionary where the keys have to be +在Swift里,它被桥接成键是 NSObject 的子类对象 + +60 +00:02:47,345 --> 00:02:52,848 +subclasses of NSObject, and the values are AnyObject, okay? +而值是 AnyObject + +62 +00:02:52,850 --> 00:02:55,350 +Now, you might think, that's gonna be a problem, and +你们可能觉得这样会有问题, + +63 +00:02:55,352 --> 00:02:58,153 +I'll explain why that's not in a moment. +我一会儿会解释为什么目前这样做没问题。 + +64 +00:02:58,155 --> 00:02:59,554 +And then of course, Int and +然后,Int, Float + +65 +00:02:59,556 --> 00:03:03,357 +Float, Double, Bool, they are all bridged to NSNumber. +Double, Bool,他们都是从 NSNumber 桥接过来的。 + +66 +00:03:03,359 --> 00:03:04,858 +We talked briefly about NSNumber, +我们之前简单的讲过 NSNumber , + +67 +00:03:04,860 --> 00:03:06,960 +we talked about the NSNumberFormatter and all that. +我们讲了 NSNumberFormatter 还有其他东西。 + +68 +00:03:06,962 --> 00:03:10,430 +So, NSNumber was the old Objective-C object that +所以, NSNumber 是 Objective-C 里所有关于 + +69 +00:03:10,432 --> 00:03:12,965 +just meant, any kind of numeric value. +数值的对象。 + +70 +00:03:12,967 --> 00:03:15,801 +And, so anything that used to take an NSNumber, you can +所以在所有用到 NSNumber的地方,你传入一个 + +71 +00:03:15,803 --> 00:03:19,204 +pass a Double, or Float or Int in there, and it'll just work. +Double,Float 或者 Int 都是没问题的。 + +72 +00:03:19,206 --> 00:03:21,573 +Of course, coming back the other way isn't automatic, +当然反过来是不行的, + +73 +00:03:21,575 --> 00:03:23,775 +because it doesn't really know necessarily what you want. +因为那样系统就不知道你到底需要那种数字类型了。 + +74 +00:03:24,811 --> 00:03:27,278 +But you can use the methods like doubleValue or +当然你可以用类似 doubleValue 或者 + +75 +00:03:27,280 --> 00:03:31,382 +IntValue, like we use doubleValue, in the Calculator. +IntValue 的这样的方法, 比如我们在计算器里就用了 doubleValue。 + +76 +00:03:31,384 --> 00:03:34,484 +And of course, Int and Float and Double are also bridged to +当然 Int Float 和 Double 都是和 C 语言 + +77 +00:03:34,486 --> 00:03:37,287 +the C types int, float, and double. +里的int,float 和 double 桥接好的。 + +78 +00:03:37,289 --> 00:03:41,390 +So, you have an API that takes an int, and hold a C int. +所以如果一个API里结构一个C语言的int参数, + +79 +00:03:41,392 --> 00:03:45,194 +It'll be bridged to take capital I Swift Int. +它也可以接受一个 Swift 里的 Int (I是大写的)。 + +80 +00:03:45,196 --> 00:03:48,296 +So, this stuff, all just works completely automatically. +这个特性是完全自动生效的, + +81 +00:03:48,298 --> 00:03:51,232 +And you don't ever have to do anything.And it just works. +我们什么都不需要做。 + + +83 +00:03:51,234 --> 00:03:55,803 +However, if you wanna be explicit, about the type, +然后,如果你需要非常明确的类型, + +84 +00:03:55,805 --> 00:03:57,270 +you can cast, okay? +你可以做类型转换。 + +85 +00:03:57,272 --> 00:04:01,240 +So, it is perfectly legal to cast a Swift String to +把 Swift 的String转换成 NSString 是完全合法的, + +86 +00:04:01,242 --> 00:04:04,543 +an NSString, and it will always work, so +不会有任何问题, + +87 +00:04:04,545 --> 00:04:06,145 +you don't need as? +并且不需要 as?。 + +88 +00:04:06,147 --> 00:04:09,114 +Okay, it's all a hundred percent guaranteed cast. +这是完全安全的转换。 + +89 +00:04:09,116 --> 00:04:10,916 +And then once you do that, +如果你这么做, + +90 +00:04:10,917 --> 00:04:12,717 +you have an NSString instead of a String, and so +你就把之前的String转换成了 NSString , + +91 +00:04:12,719 --> 00:04:15,620 +you can send it messages that are in NSString. +你就可以给它发送 NSString 的消息了。 + +92 +00:04:15,622 --> 00:04:17,421 +Although you wanna be careful with some of them, +你们也需要注意一些问题, + +93 +00:04:17,423 --> 00:04:19,990 +like length, is an NSString method, +比如length 是一个 NSString, + +94 +00:04:19,992 --> 00:04:22,325 +that doesn't exist on String. +在 String 里并不存在。 + +95 +00:04:22,327 --> 00:04:24,661 +It doesn't exist on String for a reason. +它在 String 里不存在是有原因的, + +96 +00:04:24,663 --> 00:04:27,830 +Because, we talked about this before, you know, +我们曾经讲过, + +97 +00:04:27,832 --> 00:04:31,066 +the length of a Unicode String, can vary, +Unicode 字符串的长度是可变的, + +98 +00:04:32,269 --> 00:04:35,403 +compared to the number of glyphs you'll see on screen, +根据你在屏幕上看到符号的不同而不同, + +99 +00:04:35,405 --> 00:04:37,739 +and the new Swift String deals with that, and the old +新的 Swift 的 String 会处理此类字符串,但是 NSString 确实 + +100 +00:04:37,741 --> 00:04:40,307 +NSString doesn't really deal with that properly. +没有很好的处理。 + +101 +00:04:40,309 --> 00:04:43,577 +So, you gotta be careful, when you start calling NSString +所以当你要调用 NSString 方法的时候要特别小心, + +102 +00:04:43,579 --> 00:04:45,012 +methods that, you know, + +103 +00:04:45,014 --> 00:04:47,614 +there's not, you wanna look for a String equivalent, and +尽量用 String 代替,因为 + +104 +00:04:47,616 --> 00:04:49,349 +use that if you can, because it's newer, and +String 是最新的, + +105 +00:04:49,351 --> 00:04:52,284 +it does thinks a little more accurately. +而且可以更精确。 + +106 +00:04:52,286 --> 00:04:57,189 +But NSArray is the same thing, you can cast from an Array, +NSArray 也是一样的, 你可以从 Swift 的 Array + +107 +00:04:57,191 --> 00:04:59,457 +that you have in Swift, to an NSArray, and +转换到它, + +108 +00:04:59,459 --> 00:05:01,025 +then you can call them methods in NSArray. +然后你就可以调用 NSArray 的方法了。 + +109 +00:05:01,027 --> 00:05:03,594 +Like componentsJoinedByString, which is kinda cool, +比如 componentsJoinedByString 就是一个很酷的方法, + +110 +00:05:03,596 --> 00:05:05,429 +it takes all the components in the Array, +它收集数组中的所有元素, + +111 +00:05:05,431 --> 00:05:07,964 +sends them description, takes those descriptions and +给它们一个描述,然后用传进来的字符串把 + +112 +00:05:07,966 --> 00:05:10,400 +joins them by the String you pass as an argument. +它们连接起来。 + +113 +00:05:10,402 --> 00:05:14,704 +This is the same as the join method in Swift's String. +这个跟Swift里String的join方法是一样的。 + +114 +00:05:14,706 --> 00:05:17,172 +Okay, so, you can look at the documentation for +你们可以去查阅 String,NSString 和 NSArray + +115 +00:05:17,174 --> 00:05:18,907 +String and, NSString and NSArray, but +的官方文档, + +116 +00:05:18,909 --> 00:05:21,710 +pretty much all the things you can do there, or most +基本上所有的东西,或者说大多数的东西, + +117 +00:05:21,712 --> 00:05:25,846 +of them anyway, are available in the Swift versions. +都可以在Swift里用。 + +118 +00:05:25,848 --> 00:05:27,281 +But again, if you're passing them back and +如果你在两个版本里转换, + +119 +00:05:27,283 --> 00:05:30,951 +forth, it's all automatic, so you'd say. +可以说都是自动的过程。 + +120 +00:05:30,953 --> 00:05:33,753 +Now, you might get a little concerned about Dictionary, +好的,你们对 Dictionary 可能还有点疑问, + +121 +00:05:34,989 --> 00:05:40,225 +because Dictionary, the key has to be an NSObject. +因为字典的键必须是 NSObject。 + +122 +00:05:40,227 --> 00:05:42,594 +And of course, we know that String, and Array, and +当然我们知道,String,Array 和 Dictionary 在 Swift + +123 +00:05:42,596 --> 00:05:45,663 +Dictionary in Swift, are not even objects, okay? +里都不是对象。 + +124 +00:05:45,665 --> 00:05:47,198 +They're not AnyObject, or +它们既不是 AnyObject , + +125 +00:05:47,200 --> 00:05:50,401 +they're, and they're not an NSObject for sure. +当然更不是 NSObject 。 + +126 +00:05:50,403 --> 00:05:53,570 +But you can still pass them anywhere you wanna pass in +但是我们依然可以在需要传 AnyObject 类型 或者 NSObject 的子类 + +127 +00:05:53,572 --> 00:05:56,907 +AnyObject, or a subclass of NSObject, because they +的参数里传入它们, 因为他们 + +128 +00:05:56,909 --> 00:06:00,343 +are bridged to classes that inherit from NSObject, +都被桥接到了 NSObject的子类里。 + +129 +00:06:00,345 --> 00:06:01,744 +because NSString, NSArray, and +因为 NSString ,NSArray 和 + +130 +00:06:01,746 --> 00:06:03,412 +NSDictionary all inherit from NSObject. +NSDictionary 全都继承自 NSObject 。 + +131 +00:06:03,414 --> 00:06:05,814 +So, that means Strings, Swift Strings, +所以 String, 也就是Swift的字符串, + +132 +00:06:05,816 --> 00:06:09,718 +can be the keys in a Dictionary, an NSDictionary, +可以作为 NSDictionary 的键, + +133 +00:06:09,720 --> 00:06:11,919 +even though it requires NSObject, okay? +尽管要求键是 NSObject 类型的。 + +134 +00:06:11,921 --> 00:06:14,889 +And of course, all three of them can be values, +当然,它们3个也可以作为字典的值, + +135 +00:06:14,891 --> 00:06:17,324 +because, even though they're not really objects, +因为,尽管他们不是对象,是 struct , 但是他们桥接 + +136 +00:06:17,326 --> 00:06:21,994 +they are structs, they are bridged to things that can be. Okay? +到 Objective-C 的东西可以作为值。 + + +138 +00:06:21,996 --> 00:06:23,529 +So, it is okay to pass a String or +所以,在需要传入 AnyObject 传入 + +139 +00:06:23,531 --> 00:06:24,530 +an Array to AnyObject. +String 或者 Array 都没问题。 + +140 +00:06:27,034 --> 00:06:30,285 +You won't even notice this bridge isn't bridging 99% of the time. +你在99%的时候都见不到这种桥接, + + +142 +00:06:30,286 --> 00:06:31,435 +It just happens automatically. +它们都是自动的。 + +143 +00:06:31,438 --> 00:06:33,637 +But I just wanted you to know that's going on, so +我只是想让你们知道背后发生了什么, + +144 +00:06:33,639 --> 00:06:34,938 +you don't get kinda confused when you start +这样在你们见到 NSString 或者 NSArray 的时候就 + +145 +00:06:34,940 --> 00:06:37,874 +seeing NSString, NSArray, what's going on, okay? +不会感到疑惑了。 + +146 +00:06:37,876 --> 00:06:40,109 +They're just being automatically bridged for you. +它们都是自动桥接过来的。 + +147 +00:06:41,579 --> 00:06:43,396 +All right. + +148 +00:06:43,397 --> 00:06:45,214 +So, we talked about AnyObject last time, +上次我们讲过了AnyObject。 + +149 +00:06:45,216 --> 00:06:47,182 +and now I'm gonna talk about a use of AnyObject, +现在我们要讲 AnyObject 的一个用处。 + +150 +00:06:47,184 --> 00:06:48,783 +which is called Property List. +这就是 Property List 。 + +151 +00:06:48,785 --> 00:06:51,052 +So, Property List is not a type or +Property List 并不是任何一种类型, + +152 +00:06:51,054 --> 00:06:54,689 +anything like that, it's just a term that we use. +它属于一种工具类的东西。 + +153 +00:06:54,691 --> 00:06:58,792 +And the definition of that term is, it's in AnyObject, +它的定义是, + +154 +00:06:58,794 --> 00:07:03,129 +a Property List is AnyObject, that is known to be, +Property List 表面上是 AnyObject , 但是在 + +155 +00:07:03,131 --> 00:07:05,865 +behind the scenes, one of those six classes. +后台,它是 NSString + +156 +00:07:05,867 --> 00:07:07,650 +NSString, NSArray, +NSArray, + +157 +00:07:07,651 --> 00:07:09,434 +NSDictionary, NSNumber, NSData and NSDate. +NSDictionary, NSNumber, NSData and NSDate. + +158 +00:07:09,437 --> 00:07:12,404 +Or bridged to with Swift, okay? +这六种类型中的一种,或者是它们桥接到Swift里的版本。 + +159 +00:07:12,406 --> 00:07:17,609 +So, why do we define this Property List thing? +我们为什么要用 Property List 呢? + +160 +00:07:17,611 --> 00:07:19,544 +It's in AnyObject. +它属于 AnyObject + +161 +00:07:19,545 --> 00:07:21,478 +It's kind of unwieldy, because you have to do a lot, +它看起来非常笨重,因为我们需要用 is 或者 as 做 + +162 +00:07:21,481 --> 00:07:24,115 +a fair amount of casting, ising and asing, cuz +大量的类型转换,因为要使用 AnyObject, + +163 +00:07:24,117 --> 00:07:27,284 +AnyObject, of course, to use it, we have to kinda cast it. +我们就要进行类型转换。 + +164 +00:07:27,286 --> 00:07:30,053 +And so, why do we have this thing? +所以说,我们为什么要用它? + +165 +00:07:30,055 --> 00:07:32,722 +Two reasons really. +实际上有两个原因。 + +166 +00:07:32,723 --> 00:07:35,390 +One, Property List is used to pass data around blind. +第一, Property List 要用来隐式的传递数据。 + +167 +00:07:35,393 --> 00:07:37,993 +It's like a cookie, right? In a browser. +就好像浏览器里的cookie一样。 + +169 +00:07:37,995 --> 00:07:40,295 +It's kind of this just bundle of data, +它们是只有创建者才知道如何 + +170 +00:07:40,297 --> 00:07:43,098 +that only the creator of it knows how to interpret it, +解释它们的一组数据。 + +171 +00:07:43,100 --> 00:07:45,166 +because only they know what Strings, Arrays, +因为只有创建人才知道里边到底是 String, Array + +172 +00:07:45,168 --> 00:07:46,734 +Dictionaries, and stuff are in there. +Dictionary 还是别的什么。 + +173 +00:07:46,736 --> 00:07:48,252 +But to everyone else it, +但是对于其他人来说 + +174 +00:07:48,253 --> 00:07:49,769 +just looks like AnyObject, so they don't know what it is. +它们就是 AnyObject ,但不知道具体是什么。 + +175 +00:07:49,772 --> 00:07:53,273 +So, all they can do, is pass it around to other things. +所以他们能做的就是把它传给其他人。 + +176 +00:07:53,275 --> 00:07:57,010 +So, it's good for blind data passing, the other thing is, +这是隐式数据传送的好处。另一个原因是 + +177 +00:07:57,012 --> 00:08:00,580 +a Property List can be used as generic data structures, okay? +Property List 可以用于泛型的数据结构。 + +178 +00:08:00,582 --> 00:08:02,014 +Since it's got Arrays, and +因为它可以是Array, + +179 +00:08:02,016 --> 00:08:05,584 +Dictionaries, and Numbers, and Dates, and all that in there. +Dictionary, Number, Date,都有可能。 + +180 +00:08:05,586 --> 00:08:10,021 +You can turn a data structure, like your r-ops stack, +你可以把一个数据结构变成一个泛型的数据结构,就像你的 + +181 +00:08:10,023 --> 00:08:12,523 +in the CalculatorBrain, it has op enums in there, +CalculatorBrain类里面的opStack, + +182 +00:08:12,525 --> 00:08:14,392 +that's not a generic data structure, but +它有一个叫做op的枚举,它不是泛型的 + +183 +00:08:14,394 --> 00:08:17,461 +we can turn it into a generic data structure, for example, +但是我们可以把它改成泛型的。 + +184 +00:08:17,463 --> 00:08:20,831 +and then do things with it like write it out to disk, or +泛型的数据结构可以用来写入磁盘, + +185 +00:08:20,833 --> 00:08:23,700 +send it over the network, or things like that. +或者通过网络传送。 + +186 +00:08:23,702 --> 00:08:26,569 +So, those are the two main reasons we use Property List. +以上就是使用Property List的两个主要原因。 + +187 +00:08:26,571 --> 00:08:31,073 +And, a really good use of Property List in +Property List 在 iOS里另外一个很好的用处 + +188 +00:08:31,075 --> 00:08:33,575 +iOS is NSUserDefaults. +就是 NSUserDefaults。 + +189 +00:08:33,577 --> 00:08:37,012 +So, NSUserDefaults is like a really tiny little database, +NSUserDefaults 就像一个微型的数据库。 + +190 +00:08:37,014 --> 00:08:39,347 +and it only knows how to store Property Lists. +它只会存储Property List + +191 +00:08:39,349 --> 00:08:40,999 +Okay? + +192 +00:08:41,000 --> 00:08:42,650 +And it's really for things like settings, and +存储那些诸如设置, + +193 +00:08:42,652 --> 00:08:44,051 +preferences, stuff like that. +参数等等的东西。 + +194 +00:08:44,053 --> 00:08:45,852 +You would never, it's not high performance, +由于它的性能不高, + +195 +00:08:45,854 --> 00:08:48,054 +you would never use it for big things like images or +所以千万不要用它存一些图片什么的比较大的数据, + +196 +00:08:48,056 --> 00:08:50,089 +anything like that, just Property Lists, you know, +只用来存 Property List,你懂的 + +197 +00:08:50,091 --> 00:08:54,060 +Dates and Strings and Doubles, and things like that. +日期,字符串,数字什么的。 + +198 +00:08:54,062 --> 00:08:57,796 +It can store and retrieve any Property List, and +它可以像字典一样存储和 + +199 +00:08:57,798 --> 00:08:59,831 +it just stores it like a Dictionary, +导出Property List, + +200 +00:08:59,833 --> 00:09:03,034 +as if the NSUserDefaults thing itself is a Dictionary. +NSUserDefaults本身就是一个字典。 + +201 +00:09:03,036 --> 00:09:05,103 +And, it can store the whole Property List, +它可以存储所有的Property List。 + +202 +00:09:05,105 --> 00:09:08,005 +like setObject forkey: , that first method you see there. +比如 setObject forkey:, 就是你们在那看到的第一个方法。 + +203 +00:09:08,007 --> 00:09:10,007 +And, repeat, retrieve all Property List, +然后,重复,取回所有的Property List。 + +204 +00:09:10,009 --> 00:09:12,642 +or, it can just do little tiny pieces of Property List, +或者,它可以只处理Property List中的一小部分。 + +205 +00:09:12,644 --> 00:09:14,377 +like it has a method set Double, +比如,它有个方法 set Double, + +206 +00:09:14,379 --> 00:09:16,813 +that will just set a Double for a certain key. +这将为某一 key 设置一个 Double 值。 + +207 +00:09:16,815 --> 00:09:18,348 +Okay? So, +所以, + +208 +00:09:18,349 --> 00:09:19,882 +it's like a Dictionary in it's key value, but +它像一个有 key value 的字典,但 + +209 +00:09:19,884 --> 00:09:21,350 +it only stores Property List. +它只存储Property List。 + +210 +00:09:21,352 --> 00:09:23,919 +And, the big thing about the way it stores them, +最大的不同是,它存储这些属性, + +211 +00:09:23,921 --> 00:09:28,056 +is that it persists when your app is gone, okay? +当你的app关闭时,它永久保存这些数据。 + +212 +00:09:28,058 --> 00:09:29,390 +So, you know, +你们知道的, + +213 +00:09:29,392 --> 00:09:30,958 +normally, a Dictionary is stored in the heap. +一般的,一个字典存储在堆中。 + +214 +00:09:30,960 --> 00:09:32,759 +As soon as your app quits, it's gone. +只要你的 app 退出了,它就没了。 + +215 +00:09:32,761 --> 00:09:34,327 +But this, stays around, so +但这个,保留着,所以 + +216 +00:09:34,329 --> 00:09:35,995 +that when your app launches the next time, +当你的 app 在下次启动时, + +217 +00:09:35,997 --> 00:09:37,697 +all the data's still there. +所有的数据都在。 + +218 +00:09:37,699 --> 00:09:39,465 +So, that's why it's kind of like a database, but +因此,这就是为什么它像个数据库,但 + +219 +00:09:39,467 --> 00:09:40,932 +it's very small, okay? +它非常小。 + +220 +00:09:40,934 --> 00:09:43,034 +For preference and settings. +一般使用 NSUserDefaults 来 + +221 +00:09:43,036 --> 00:09:45,503 +Here's how you use NSUserDefaults. +保存偏好设置和相关设定 + +222 +00:09:45,505 --> 00:09:49,006 +You use this type method in NSUserDefaults called +你在 NSUserDefaults 中使用这类方法 + +223 +00:09:49,008 --> 00:09:50,974 +standardUserDefaults. +standardUserDefaults。 + +224 +00:09:50,976 --> 00:09:53,243 +This gives you an instance of an NSUserDefaults. +这给你一个 NSUserDefaults 的实例。 + +225 +00:09:53,245 --> 00:09:54,310 +You're always gonna use +你总是使用同一个实例, + +226 +00:09:54,312 --> 00:09:56,579 +the same instances like a shared instance. +类似于一个共享实例。 + +227 +00:09:56,581 --> 00:09:58,114 +You'll always to use the same one. +你总是使用同一个(实例)。 + +228 +00:09:58,116 --> 00:10:02,117 +And then you just send it messages like, you know, +然后,你就发消息给它,比如,正如你知道的, + +229 +00:10:02,119 --> 00:10:05,587 +setObject forkey:, store this Property List, and +setObject forkey:,保存这个Property List。 + +230 +00:10:05,589 --> 00:10:07,989 +getObject forkey: to get it back. +然后使用 getObject forkey:,获取它。 + +231 +00:10:07,991 --> 00:10:09,257 +Now, the changes you make in there, +现在,你在那里做的改变, + +232 +00:10:09,259 --> 00:10:12,193 +are automatically saved, but, there is a method called +会自动保存。有一个方法叫 + +233 +00:10:12,195 --> 00:10:15,929 +synchronize, which is kinda like save, which can force it, +synchronize,类似于 save,这个方法可以强制 + +234 +00:10:15,931 --> 00:10:17,931 +to save out to disc. +保存数据到磁盘。 + +235 +00:10:17,933 --> 00:10:19,666 +Why do you ever need synchronize when it +既然有自动保存,为什么你还需要 + +236 +00:10:19,668 --> 00:10:21,868 +auto saves? +synchronize? + +237 +00:10:21,869 --> 00:10:24,069 +Well, in auto save, when things happen like you app +好吧,在自动保存中,当有些事情发生时,比如你的 app + +238 +00:10:24,072 --> 00:10:28,073 +stops being the front most app, +不再作为最前端的 app, + +239 +00:10:28,075 --> 00:10:29,708 +the user switched to another app. +用户转向使用其他 app。 + +240 +00:10:29,710 --> 00:10:31,709 +So, your app is still there, but +因此,你的 app 还在那里运行,但是 + +241 +00:10:31,711 --> 00:10:33,077 +it switched to the background. +变成后台运行了。 + +242 +00:10:33,079 --> 00:10:35,145 +It'll save then. +那时它将保存数据。 + +243 +00:10:35,147 --> 00:10:36,580 +So, it won't always save when you want, and +因此,它不会总是在你需要的时候保存数据, + +244 +00:10:36,582 --> 00:10:39,315 +especially when you're debugging, okay? +特别是当你调试的时候。 + +245 +00:10:39,317 --> 00:10:42,118 +When you hit stop in the debugger, +当你在调试器中停止时, + +246 +00:10:42,120 --> 00:10:43,986 +it doesn't save, okay? +它并不保存数据。 + +247 +00:10:43,988 --> 00:10:47,289 +And so, you probably wanna throw some synchronizes in +因此,你可能要放一些 synchronize, + +248 +00:10:47,291 --> 00:10:49,157 +there, to save this thing out, +以便把数据保存下来。 + +249 +00:10:49,159 --> 00:10:50,792 +especially when you're debugging. +特别是当你调试的时候。 + +250 +00:10:50,794 --> 00:10:52,960 +It's not really that expensive to synchronize, +synchronize 操作,代价并不高, + +251 +00:10:52,962 --> 00:10:54,562 +especially if there's not much data in there, +特别是它没有很多数据的时候。 + +252 +00:10:54,564 --> 00:10:56,697 +which there shouldn't be, because it's small. +它也不应该有很多数据,因为它很小。 + +253 +00:10:56,699 --> 00:10:59,266 +So, it can't hurt too much to throw them in there. +因此,使用 synchronize 方法并没有太大伤害。 + +254 +00:10:59,268 --> 00:11:01,334 +Okay? + +255 +00:11:01,336 --> 00:11:03,403 +And yeah, synchronize return to Bool, +当然,synchronize 返回 Bool 值, + +256 +00:11:03,405 --> 00:11:05,021 +whether it failed or not. +表示它失败与否。 + +257 +00:11:05,022 --> 00:11:06,638 +But if it failed, there's really not much you can do. +但如果它失败了,你也不能做太多事情, + +258 +00:11:07,775 --> 00:11:10,075 +So, a lot of times people don't even look at the return +因此,大多数时候人们甚至不检查 synchronize 的 + +259 +00:11:10,077 --> 00:11:13,044 +values synchronize, they just synchronize, and they pray. +返回值,他们只是使用 synchronize,然后他们祈祷。 + +260 +00:11:13,046 --> 00:11:16,014 +But, it's only not gonna save if like the disk is full or +但是,它只是在磁盘满了或者其他时候无法保存数据, + +261 +00:11:16,016 --> 00:11:17,715 +something, that virtually never happens. +但这些情况很少发生。 + +262 +00:11:19,285 --> 00:11:20,851 +All right, so, I'm gonna do a little demo here. +我要做些 demo。 + +263 +00:11:20,853 --> 00:11:23,086 +And show you a little more about Property List. +给你展示更多的 Property List。 + +264 +00:11:23,088 --> 00:11:24,821 +And also AnyObject, +还有 AnyObject。 + +265 +00:11:24,822 --> 00:11:26,555 +cuz you've never seen AnyObject in action. +因为你们在之前的演示中还没见过 AnyObject + +266 +00:11:26,558 --> 00:11:31,260 +And what we're gonna do, is add a property to our +我们将做的,是在我们的 CalculatorBrain + +267 +00:11:31,262 --> 00:11:34,796 +CalculatorBrain, which gets its program. +添加一个属性,这个属性获取它的 program。 + +268 +00:11:35,732 --> 00:11:37,448 +Okay? + +269 +00:11:37,449 --> 00:11:39,165 +So, our CalculatorBrain has a program, especially your +所以我们的 CalculatorBrain 有一个 program,特别是你们的 + +270 +00:11:39,168 --> 00:11:41,468 +versions, where you added variables to it. +版本,当你们在其中添加变量。 + +271 +00:11:41,470 --> 00:11:42,936 +It's got this kind of program, +它会有这样的 program, + +272 +00:11:42,938 --> 00:11:44,337 +it's almost like a little computer program. +它几乎像一个小的计算机程序。 + +273 +00:11:44,339 --> 00:11:48,007 +You can execute that program, set its variables, it's great. +你可以执行这个程序,设置变量,这很好。 + +274 +00:11:48,009 --> 00:11:49,709 +So, it would be nice if we could get that program. +如果我们能得到这个 program 那就好了。 + +275 +00:11:49,711 --> 00:11:52,678 +But we don't wanna reveal our internal data structure, and +但我们并不想暴露我们内部的数据结构, + +276 +00:11:52,680 --> 00:11:55,113 +there's nothing anyone can do with that program. +这样任何人就不能在这个 program 上做任何事。 + +277 +00:11:55,115 --> 00:11:56,848 +So, we're really just getting it as a cookie. +实际上我们的做法是像一个 cookie 一样来获取它。 + +278 +00:11:56,850 --> 00:11:59,717 +And the only thing you can do with it, is give it back +你能做的唯一事情,把它返回给 + +279 +00:11:59,719 --> 00:12:02,520 +to the CalculatorBrain, or another CalculatorBrain in +CalculatorBrain,或者将来的其他 CalculatorBrain, + +280 +00:12:02,522 --> 00:12:05,389 +the future, and then say, evaluate. +然后,调用 evaluate() + +281 +00:12:05,391 --> 00:12:07,724 +Okay, so you see the value of having this? +你们看到这样做的价值没? + +282 +00:12:07,726 --> 00:12:09,359 +So, basically getting the program out of +基本上就是,从 CalculatorBrain 中获取 program, + +283 +00:12:09,361 --> 00:12:10,793 +the CalculatorBrain and send it back. +然后把它送回去。 + +284 +00:12:10,795 --> 00:12:13,162 +But we're gonna return it as a Property List. +但我们将以 Property List 的形式返回。 + +285 +00:12:13,164 --> 00:12:14,196 +It's gonna be AnyObject. +它会是 AnyObject。 + +286 +00:12:14,198 --> 00:12:16,031 +People are gonna look at this var, and +人们将查看这个变量, + +287 +00:12:16,033 --> 00:12:17,632 +it's gonna be of type AnyObject, and +它会是 AnyObject 类型, + +288 +00:12:17,634 --> 00:12:20,068 +all they can do is get it, and then set it back. +他们能做的是 get 它,然后 set 回去。 + +289 +00:12:20,070 --> 00:12:21,503 +Okay? + +290 +00:12:21,504 --> 00:12:22,937 +So, what would that look like? +这会是什么样的? + +291 +00:12:22,939 --> 00:12:24,538 +Let's go over here to our Calculator. +让我们到我们的 Calculator 里来。 + +292 +00:12:24,540 --> 00:12:26,840 +So, I've gone much bigger font here. +我已经在这里调了更大的字体。 + +293 +00:12:26,842 --> 00:12:28,308 +Hopefully everybody, is this big enough? +希望每个人(能看到),这个够大吗? + +294 +00:12:28,310 --> 00:12:30,143 +Yeah? + +295 +00:12:30,145 --> 00:12:31,510 +Okay. + +296 +00:12:31,512 --> 00:12:32,745 +All right. + +297 +00:12:32,747 --> 00:12:35,514 +So, this is Calculator as I last left it. +这个是我上次留下的 Calculator。 + +298 +00:12:35,516 --> 00:12:37,716 +It doesn't have your enhancements to it for +它没有你们为变量的改进。 + +299 +00:12:37,718 --> 00:12:39,951 +the variables. + +300 +00:12:39,953 --> 00:12:42,319 +And I'm just gonna add a var here. +我就要再这里加一个 var。 + +301 +00:12:42,321 --> 00:12:43,887 +A public var. +一个 public 的 var。 + +302 +00:12:43,889 --> 00:12:44,554 +Okay? + +303 +00:12:44,556 --> 00:12:45,922 +Called program, and +叫做 program, + +304 +00:12:45,924 --> 00:12:49,225 +it's gonna be type AnyObject, but I'm gonna put comment here +这个会是 AnyObject 类型,但我要在这注释下, + +305 +00:12:49,227 --> 00:12:53,595 +that says guaranteed to be a Property List. +要保证是个 Property List。 + +306 +00:12:53,597 --> 00:12:56,965 +So, the callers know that this is a Property List. +这样调用者知道这是个 Property List。 + +307 +00:12:56,967 --> 00:13:01,002 +So, for example, they could put it into NSUserDefaults. +例如,他们可以把它放入 NSUserDefaults。 + +308 +00:13:01,004 --> 00:13:02,737 +Or they could write it out to disc. +或者他们可以将这个写入磁盘。 + +309 +00:13:02,739 --> 00:13:04,571 +I haven't taught you how to write it out to disc, but +我还没教你们怎么把这个写入磁盘。 + +310 +00:13:04,573 --> 00:13:05,706 +you can do it. +你们能够做的。 + +311 +00:13:05,708 --> 00:13:06,673 +So, they could do that with it, +他们可以那样做。 + +312 +00:13:06,675 --> 00:13:09,375 +cuz they know it's a Property List, okay? +他们知道它是个 Property List。 + +313 +00:13:09,377 --> 00:13:13,346 +So, this is going to be a computed property. +这是个 computed property。 + +314 +00:13:13,348 --> 00:13:15,948 +Okay, so we're gonna have a get and a set. +我们将有一个 get 和一个 set。 + +315 +00:13:15,950 --> 00:13:17,183 +And when the get, +当 get 时, + +316 +00:13:17,184 --> 00:13:18,417 +we're just gonna get some sort of Property +我们将获取代表我们内部数据结构的某个 + +317 +00:13:18,419 --> 00:13:21,186 +List representation of our internal data structure. +Property List。 + +318 +00:13:21,188 --> 00:13:23,521 +And when you set, we're gonna take that Property List and +当你 set 时,我们将得到 Property List 并且 + +319 +00:13:23,523 --> 00:13:27,057 +turn it back into our private representation. +把它放回我们的私有代表。 + +320 +00:13:28,060 --> 00:13:29,259 +So, the get, +这个 get, + +321 +00:13:30,362 --> 00:13:34,063 +how are we gonna represent ourselves as a Property List +这是我们怎么将我们自己表现为一个 Property List, + +322 +00:13:34,065 --> 00:13:36,732 +because this is really our internal data structure here, +因为这实际上是我们内部数据结构, + +323 +00:13:36,734 --> 00:13:39,801 +it's Array of op, op is an enum, +是个 op 数组,op 是枚举类型, + +324 +00:13:39,803 --> 00:13:43,871 +clearly enums are not NSDates, or NSStrings, or NSArrays. +显然,枚举不是 NSDates,也不是 NSStrings 或 NSArrays。 + +325 +00:13:43,873 --> 00:13:46,407 +So, we can't just return this thing, okay? +我们不能只是返回这个东西, + +326 +00:13:46,409 --> 00:13:48,208 +Cuz that's not a Property List. +因为它不是一个 Property List。 + +327 +00:13:48,210 --> 00:13:51,244 +So, we need to return some sort of Property List. +我们必须返回某种 Property List。 + +328 +00:13:51,246 --> 00:13:53,980 +And I'm gonna return an Array of Strings. +我将返回一个 String 数组。 + +329 +00:13:53,982 --> 00:13:58,084 +And the String is either gonna be the symbol of an op, +这个 String 是某个 op 的符号, + +330 +00:13:58,086 --> 00:14:01,587 +in which case I will look it up in knownOps, or +这个 op 我可以在 knownOps 中找到,或者 + +331 +00:14:01,589 --> 00:14:04,956 +the String will be an numeric representation of +这个 String 会是个数字字符串,代表 + +332 +00:14:04,958 --> 00:14:06,958 +the String of the operand rather. +操作数。 + +333 +00:14:06,960 --> 00:14:08,026 +Right? The Double will +对吧,Double 将转换成 + +334 +00:14:08,028 --> 00:14:09,326 +turn into a String. +一个 String。 + +335 +00:14:09,328 --> 00:14:13,163 +Which I happened to have a var that does exactly that. +刚好我有一个变量正好可以处理这个。 + +336 +00:14:13,165 --> 00:14:15,565 +Okay? This turns an enum op, +这将一个 op 枚举变成 + +337 +00:14:15,567 --> 00:14:17,800 +into a String. +一个 String。 + +338 +00:14:17,802 --> 00:14:19,635 +And I know how to turn it back. +我知道怎么把它变回来。 + +339 +00:14:19,637 --> 00:14:22,771 +Because I know how to use a number formatter to turn +因为我知道怎么使用一个 number formatter 来把一个 + +340 +00:14:22,773 --> 00:14:25,273 +the String of a operand back into a Double and +操作数字符串变成一个 Double。 + +341 +00:14:25,275 --> 00:14:27,709 +obviously I know how to look up binary and +显然我也知道怎么在 knownOps 中 + +342 +00:14:27,711 --> 00:14:30,645 +uniary operations in our knownOps. +查找二元和一元操作符。 + +343 +00:14:30,647 --> 00:14:32,764 +Okay? + +344 +00:14:32,765 --> 00:14:34,882 +So, we could say something along these lines. +我们可以在这几行里写一些东西 + +345 +00:14:34,884 --> 00:14:39,586 +Our get, I'm gonna show you a much better get in a second, +我们的 get,我马上给你演示一个更好的 get, + +346 +00:14:39,588 --> 00:14:43,590 +but one way we could do our get is we could just say, +实现 get 的一种方式是: + +347 +00:14:43,592 --> 00:14:47,226 +we could make a returnValue that is going to be +定义一个 returnValue,它的类型是 + +348 +00:14:47,228 --> 00:14:48,861 +an Array of String. +Array + +349 +00:14:48,863 --> 00:14:52,764 +Okay, in fact let's just create an empty Array of +实际上,我们只是创建一个空的字符串数组, + +350 +00:14:52,766 --> 00:14:56,768 +String here, and then we can just go through our ops, +然后我们可以在我们的 opStack 中遍历我们的操作符, + +351 +00:14:56,770 --> 00:14:59,737 +in our opStack here, and for each op, +对于每一个操作符, + +352 +00:14:59,739 --> 00:15:04,307 +we can just say returnValue.append, an op's description. +我们可以使用 returnValue.append,将一个操作符的描述 + +353 +00:15:04,309 --> 00:15:07,877 +On to the end of it, and then we could return, returnValue. +附加在它(returnValue)的后面,然后我们可以返回 returnValue。 + +354 +00:15:10,748 --> 00:15:13,882 +Right, makes sense, I just my internal data structure into +懂了吗?我刚刚把我的内部数据结构转变成一个 + +355 +00:15:13,884 --> 00:15:16,918 +a Property List, because this is a Property List. +Property List,因为这是一个 Property List。 + +356 +00:15:16,920 --> 00:15:20,588 +Notice I can return, this through AnyObject, +注意我可以通过 AnyObject 返回。 + +357 +00:15:20,590 --> 00:15:22,557 +because Arrays are bridged, and +因为 Arrays 是桥接好的, + +358 +00:15:22,559 --> 00:15:24,392 +NSArray which happens to be an object. +NSArray 恰好是一个 object, + +359 +00:15:24,394 --> 00:15:25,392 +Okay. + +360 +00:15:25,394 --> 00:15:27,961 +But this is an awful lot of code for this. +但这里这么多行代码,太可怕了。 + +361 +00:15:27,963 --> 00:15:31,731 +We can actually do this in one line of code, okay? +实际上,我们可以仅使用一行代码 + +362 +00:15:31,733 --> 00:15:34,834 +So if you paid attention in my last lecture, you'll remember +如果你们注意我上次讲的课,你们就会记得 + +363 +00:15:34,836 --> 00:15:36,969 +that I told you about this function called map. +我跟你们说过,这个叫做 map 的函数。 + +364 +00:15:36,971 --> 00:15:43,041 +And I can actually just return my opStack mapped, +实际上我可以直接返回 opStack.map + +365 +00:15:43,043 --> 00:15:49,047 +so that each element description is returned. +这样每个元素的描述都返回了。 + +366 +00:15:49,049 --> 00:15:51,349 +So I don't need any of this, okay? +因此我不需要这里的任何一行代码。 + +367 +00:15:52,485 --> 00:15:54,785 +So everyone understand this line of code right here? +每个人都理解了这行代码了吧。 + +368 +00:15:54,787 --> 00:15:57,921 +This is just a little closure that gets the opportunity to +这仅仅是一个闭包,它转化 opStack 内的 + +369 +00:15:57,923 --> 00:16:00,723 +convert every single thing inside opStack, +每个单一的东西, + +370 +00:16:00,725 --> 00:16:03,893 +which is an op, these are ops, into a String and it takes +也就是将操作符,这些都是操作符,转换成字符串, + +371 +00:16:03,895 --> 00:16:07,396 +this String and maps them all and returns a new Array. +然后得到这个字符串,然后将它们所有都映射,最后返回一个新的数组。 + +372 +00:16:09,132 --> 00:16:09,697 +Okay? + +373 +00:16:10,733 --> 00:16:13,434 +So when you start getting familiar with Swift and +当你们开始熟悉 Swift, + +374 +00:16:13,436 --> 00:16:14,785 +what it can do, +和 Swift 能做的事情。 + +375 +00:16:14,786 --> 00:16:16,135 +you'll start realizing a lot of things that take five or +你就开始意识到很多需要五六行代码处理的东西, + +376 +00:16:16,138 --> 00:16:17,570 +six line of code, you can just do them in one. +现在你只需要一行。 + +377 +00:16:18,640 --> 00:16:20,873 +Okay, but it does take some experience. +但这需要一定的经验。 + +378 +00:16:20,875 --> 00:16:22,775 +So now let's talk about going the other way. +现在让我们谈谈其他方式, + +379 +00:16:22,777 --> 00:16:25,177 +So now we have, someone gives us back our program. +现在有人给我们返回 program, + +380 +00:16:25,179 --> 00:16:27,245 +We wanna load our opStack back up. +我们想加载上我们的 opStack, + +381 +00:16:27,247 --> 00:16:33,117 +Well the first thing we wanna make sure is that the thing +第一件我们需要确认的事情是 + +382 +00:16:33,119 --> 00:16:37,387 +they're giving us back is an Array of these symbols. +他们给我们的是这些符号的数组。 + +383 +00:16:37,389 --> 00:16:38,988 +Because they could just give me junk, +因为他们可能给我们没用的东西。 + +384 +00:16:38,990 --> 00:16:40,923 +because it's AnyObject they could set it to anything. +这是个 AnyObject,他们可以给它设置任何值。 + +385 +00:16:40,925 --> 00:16:42,291 +So, I, I want to make sure that's what it is. +我需要确认这是什么。 + +386 +00:16:42,293 --> 00:16:43,826 +So what I'm going to do, +我将要做的是, + +387 +00:16:43,828 --> 00:16:47,529 +I'm going to let opSymbols equal newValue, right? +输入 opSymobls = newValue, + +388 +00:16:47,531 --> 00:16:49,731 +newValue remember we are in the setter here. +newValue 记得我们在 setter 里。 + +389 +00:16:49,733 --> 00:16:52,633 +So, newValue is the newValue which is in AnyObject. +这个 newValue 是 AnyObject 的。 + +390 +00:16:54,070 --> 00:16:57,571 +As an Array of String, because that's what it has to be. +as Array,因为它必须是一个 Array 才行。 + +391 +00:16:57,573 --> 00:17:00,573 +If this thing that they passed in is not an Array of String, +如果他们传递的不是字符串数组, + +392 +00:17:00,575 --> 00:17:02,308 +I don't know what to do with it. +我就不知道怎么处理。 + +393 +00:17:02,310 --> 00:17:07,479 +So really here what I wanna do is, if let as question mark, +所以这里我想做的是, if let as? + +394 +00:17:07,481 --> 00:17:09,981 +because they could pass me anything. +因为他们可能传给我任何东西, + +395 +00:17:09,983 --> 00:17:13,485 +And so, here I'm using the as to make sure this AnyObject +所以这里我使用 as 以确保他们传递过来的 AnyObject + +396 +00:17:13,487 --> 00:17:17,488 +they pass me is actually and Array of Strings, okay? +确实是个字符串数组。 + +397 +00:17:17,490 --> 00:17:19,390 +If it is, now I can convert back, so +如果是,我就可以转化回来, + +398 +00:17:19,392 --> 00:17:22,893 +I'm gonna create something called my newOpStack which +我将创建一个 newOpStack, + +399 +00:17:22,895 --> 00:17:27,497 +is just gonna be an Array of ops and I'm just gonna go for +它是一个操作符数组。我将遍历这个 + +400 +00:17:27,499 --> 00:17:31,834 +each opSymbol in this opSymbols. +opSymbols 里的每个 opSymbol。 + +401 +00:17:32,836 --> 00:17:35,603 +opSymbols is this thing right here, that's the Array, +opSymbols 是这个东西,这是 Array + +402 +00:17:35,605 --> 00:17:38,373 +that's the newValue, the AnyObject converted +这是 newValue,AnyObject 转换成了 + +403 +00:17:38,375 --> 00:17:42,776 +into an Array of Strings, okay? +Array 类型,明白了吗? + +404 +00:17:42,778 --> 00:17:48,448 +So for each one if I can find a known op, +所以对于每一个 opSymbol + +405 +00:17:48,450 --> 00:17:53,586 +that matches that symbol then this must be an op, +在 knownOps 中找到对应的 op + +406 +00:17:53,588 --> 00:17:56,255 +and so I will just add that op +那么我就可以将 + +407 +00:17:56,257 --> 00:18:01,326 +to, to my stack, otherwise I'm gonna see +那个 op 加至我的 newOpStack 中 + +408 +00:18:01,328 --> 00:18:04,162 +if I could turn that String into an operand, and I'm gonna +否则我将尝试把字符串转换成一个操作数 + +409 +00:18:04,164 --> 00:18:09,166 +do that with if let operand equal NSNumberFormatter. +这里我可以输入 if let operand = NSNumberFormatter() + +410 +00:18:09,168 --> 00:18:12,736 +Okay, numberFromString, I'm gonna pass it +NSNumberFormatter().numberFromString(...) + +411 +00:18:12,738 --> 00:18:16,773 +this opSymbol that I got out of that Array it gave me. +括号里的参数我将把 opSymbol 传进去 + +412 +00:18:16,775 --> 00:18:20,042 +I'm going to use Optional Chaining here and +这里我将使用 Optional Chaining 并且 + +413 +00:18:20,044 --> 00:18:24,113 +put a question mark, then doubleValue, okay. +放一个问号在这里,然后 .doubleValue + +414 +00:18:24,115 --> 00:18:27,616 +Remember Optional Chaining, if you have an expression like +记住,Optional Chaining 就是,如果你有一个像这样的表达式 + +415 +00:18:27,618 --> 00:18:31,653 +this, this whole expression, and if anything along the way +那么整个表达式中任意一个 + +416 +00:18:31,655 --> 00:18:36,157 +returns nil then this whole expression will return nil. +返回了 nil 的话,那么整个表达式将返回 nil + +417 +00:18:36,159 --> 00:18:38,659 +If you put a question mark after that term. +我在这里放置了一个问号 + +418 +00:18:38,661 --> 00:18:40,927 +So, numberFromString can return nil if this is +那么如果给 numberFromString 传一个不能被解释成一个数字的 String + +419 +00:18:40,929 --> 00:18:44,364 +not a String, that can be interpreted as a number. +它就会返回 nil + +420 +00:18:44,366 --> 00:18:47,000 +So by putting a question mark here it says, okay? +所以这里我放置一个问号的意思是 + +421 +00:18:47,002 --> 00:18:50,169 +If that's nil than just return nil back to here. +如果这个表达式返回 nil,则 operand 也将是 nil + +422 +00:18:50,171 --> 00:18:52,604 +Otherwise keep going and send it doubleValue. +如果不返回 nil,那么 operand 设置成表达式返回值的 doubleValue + +423 +00:18:53,574 --> 00:18:57,709 +So this operand is either going to not get set, +这个 operand 要么不被设值 + +424 +00:18:57,711 --> 00:19:01,879 +because of the if let, or it's going to be a Double, +因为有 if let 的存在,要么它将成为一个 Double + +425 +00:19:01,881 --> 00:19:03,580 +which is what this doubleValue comes out of here. +也就是这里出现 doubleValue 的原因 + +426 +00:19:04,883 --> 00:19:07,384 +Okay, so that's kind of explaining from last week how +好的,这就是上周我们讲的 + +427 +00:19:07,386 --> 00:19:09,252 +we did this number formatter thing. +使用 number formatter 的知识 + +428 +00:19:09,254 --> 00:19:12,005 +So in this case, +在这里 + +429 +00:19:12,006 --> 00:19:14,757 +I can just append onto the end of it that a new op. +我只需要追加一个新的 op + +430 +00:19:14,759 --> 00:19:19,361 +So, we'll say dot operand with that operand. +我们输入 .Operand(operand) + +431 +00:19:19,363 --> 00:19:20,795 +So we're just putting a new op on there. +这样我们就追加了一个新的 op + +432 +00:19:20,797 --> 00:19:24,565 +So now I've built a new opStack using all those Strings, +现在我使用了所有的那些字符串创建了一个 newOpStack + +433 +00:19:24,567 --> 00:19:27,901 +and I can just return that new opStack. +这里我将返回这个 newOpStack + +434 +00:19:27,903 --> 00:19:30,170 +Not return it, sorry. +喔,这里不是返回 + +435 +00:19:30,171 --> 00:19:32,438 +I'm gonna set my opStack equal to that new op +而是将 opStack = newOpStack + +436 +00:19:32,441 --> 00:19:33,740 +Stack, okay? +明白了吗? + +437 +00:19:33,742 --> 00:19:35,174 +That's it. +就这些 + +438 +00:19:37,111 --> 00:19:38,276 +Any questions about that? +对此有什么疑问吗? + +439 +00:19:38,278 --> 00:19:41,513 +>>Property List? +- [学生提问] + +440 +00:19:41,515 --> 00:19:42,780 +Like that's just because. +- [学生提问] + +441 +00:19:42,782 --> 00:19:44,932 +>> This is documentation, +这是文档 + +442 +00:19:44,933 --> 00:19:47,083 +this is a public thing, it's not private, and I'm just +这是一个 public 的东西,不是 private 的 + +443 +00:19:47,086 --> 00:19:49,520 +documenting to anyone who's using it that this is true. +这是提供给任何使用我代码的人的文档 + +444 +00:19:49,522 --> 00:19:52,389 +I can document this even better using a typealias. +我能够用 typealias 更好地整理我的代码文档 + +445 +00:19:52,391 --> 00:19:54,290 +So you can basically have a typealias, +你仅仅需要输入 typealias + +446 +00:19:54,292 --> 00:19:55,892 +which is an alias for a type. +typealias 是一个类型的替身 + +447 +00:19:55,894 --> 00:19:58,094 +It's just a way of another type, and +是其他类型的一个替身 + +448 +00:19:58,096 --> 00:20:00,429 +I could have a typealias called PropertyList, +输入 typealias PropertyList = AnyObject + +449 +00:20:00,431 --> 00:20:02,831 +which is equals AnyObject. + +450 +00:20:03,934 --> 00:20:08,302 +Then I could have this type be PropertyList, okay? +接下来我就可以让 program: AnyObject 中的 AnyObject 成为 PropertyList 类型,明白了吗? + +451 +00:20:08,304 --> 00:20:11,772 +So I just created PropertyList as an alias for AnyObject, so +这里我创建了 PropertyList 类型,它是 AnyObject 的一个替身 + +452 +00:20:11,774 --> 00:20:13,106 +someone looking at this is gonna go, +当别人看到这里的时候 + +453 +00:20:13,108 --> 00:20:14,974 +whoa, what the heck is PropertyList? +他会有一个疑问,究竟什么是 PropertyList + +454 +00:20:14,976 --> 00:20:16,309 +Now they're going to look at this typealias, and +然后他们会回头看到这个 typealias + +455 +00:20:16,311 --> 00:20:18,844 +say, oh, that's AnyObject, but they're really going to +然后知道,那是 AnyObject,但是他们会明确知道 + +456 +00:20:18,846 --> 00:20:21,480 +understand that I'm returning the Property List to them, and +我将返回一个 Property List 给他们 + +457 +00:20:21,482 --> 00:20:22,848 +the reason is Property List, again, so +原因还是 Property List + +458 +00:20:22,850 --> 00:20:26,584 +I can throw it again as user defaults or whatever, okay? +我可以把它用作 NSUserDefaults 或者其他东西, 明白了吗? + +459 +00:20:28,354 --> 00:20:30,621 +But otherwise, it's only good, the only thing it's good for +但是它只有在 + +460 +00:20:30,623 --> 00:20:33,056 +is giving it back to me to reset my program in +将来返回给我以重置 program 的时候才有用 + +461 +00:20:33,058 --> 00:20:34,724 +the future; that's all this thing is good for. +这个东西就是这一点有用 + +462 +00:20:36,394 --> 00:20:39,762 +Now, you're gonna wanna add this to your assignment for +现在,你们大概希望把这个加到你们的 + +463 +00:20:39,764 --> 00:20:41,497 +assignment three, okay? +作业三中 + +464 +00:20:44,802 --> 00:20:47,502 +So, all right, back to slides. +好的,回到我们的幻灯片中 + +465 +00:20:48,571 --> 00:20:50,871 +I'm not gonna, I don't have time to really run this +我并没有足够的课堂时间运行这个 + +466 +00:20:50,873 --> 00:20:53,940 +unfortunately due to in test code because we are +因为这个代码可能还需要调试, + +467 +00:20:56,178 --> 00:20:57,577 +schedule constraint here. +可是我们的时间表有限制 + +468 +00:20:57,579 --> 00:20:59,979 +So let's go back to here, continue. +让我们继续 + +469 +00:21:01,182 --> 00:21:03,415 +All right, so now let's talk about, new thing here, +继续讨论一些新东西 + +470 +00:21:03,417 --> 00:21:06,584 +which is views, okay, totally new topic. +Views,全新的话题 + +471 +00:21:06,586 --> 00:21:09,087 +A view, that is to say, +一个 view + +472 +00:21:09,089 --> 00:21:12,156 +a subclass of the class UIView in iOS +iOS 中 UIView 类的一个子类 + +473 +00:21:12,158 --> 00:21:15,259 +represents a rectangular area on the screen. +表示了屏幕上的一个长方形的区域 + +474 +00:21:15,261 --> 00:21:17,861 +That defines a coordinate space to draw in, and +定义了一个坐标系空间来绘图 + +475 +00:21:17,863 --> 00:21:20,463 +also to handle touch events, okay? +和处理触摸的操作,明白了吗? + +476 +00:21:20,465 --> 00:21:24,100 +That's what a view is, and you are going to learn today, +这就是 view,你们今天要学的 + +477 +00:21:24,102 --> 00:21:25,301 +how to make your own views. +如何制作你们自己的 views + +478 +00:21:26,771 --> 00:21:29,638 +The views are hierarchical, so, +views 是有层次的 + +479 +00:21:29,640 --> 00:21:32,407 +views are within views are within views. +这就意味着 views 可以在 views 中 + +480 +00:21:32,409 --> 00:21:34,742 +Any view only has one superview. +但是任何一个 view 都只能有一个 superview + +481 +00:21:34,744 --> 00:21:37,478 +Right, it's only contained directly in one view. +这也就意味,一个 view 是直接包含在另一个 view 中的 + +482 +00:21:37,480 --> 00:21:39,480 +But, it can have any number of subviews. +但是一个 view 可以有多个 subview + +483 +00:21:39,482 --> 00:21:41,948 +So in our Calculator, we had a top level view, +在我们的计算器程序中,我们有一个最高层的 view + +484 +00:21:41,950 --> 00:21:43,316 +which I'm gonna talk about in a moment, +这个一会儿我会讲到 + +485 +00:21:43,318 --> 00:21:45,752 +and then we had a lot of subviews, all the buttons, +接下来我们有一大堆的 subviews,都是按钮 + +486 +00:21:45,754 --> 00:21:49,221 +the labels, those are all UIView subclasses. +和标签,它们是 UIView 的子类 + +487 +00:21:49,223 --> 00:21:50,989 +Okay, so we made a whole bunch. +所以我们将会用到一大堆 + +488 +00:21:50,991 --> 00:21:53,091 +A bunch of subviews in that view. +一大堆的 subviews,在最高层的 view 中 + +489 +00:21:53,093 --> 00:21:54,225 +But you can go even deeper. +但是你可以更深入地研究它 + +490 +00:21:54,227 --> 00:21:55,593 +It's hierarchical multi-layer. +这是个有层次的 multi-layer + +491 +00:21:55,595 --> 00:21:58,295 +We can go as deep as we want. +我们想研究多深入都可以 + +492 +00:21:58,297 --> 00:22:01,231 +The two, you can see the two properties there for +在这里,你看到这两个 properties + +493 +00:22:01,233 --> 00:22:03,317 +getting your superview. +用来获取你的 superview + +494 +00:22:03,318 --> 00:22:05,402 +Notice it returns a Optional, because you +注意,它返回一个 Optional,这是因为 + +495 +00:22:05,404 --> 00:22:07,804 +can have a view that's not currently on screen. +你可以拥有一个当前不在屏幕中的 view + +496 +00:22:07,806 --> 00:22:10,406 +It's not currently in the view hierarchy so that can be nil. +不在当前 view 层次结构中的 view 都会是 nil + +497 +00:22:11,509 --> 00:22:15,577 +Your subviews, I show Array of UIView there. +还有一个属性是 subviews,这里我写的是一个 UIView 数组 + +498 +00:22:15,579 --> 00:22:18,847 +Actually the subview's property is an Array of AnyObject, +实际上这个 subview property 是一个 AnyObject 数组 + +499 +00:22:18,849 --> 00:22:20,482 +again for historical reasons, but +因为一些历史性的原因,不过 + +500 +00:22:20,484 --> 00:22:21,849 +there will always be UIViews in there. +元素始终都是 UIView 对象 + +501 +00:22:21,851 --> 00:22:26,086 +So don't even worry about that, okay? +所以不用担心,okay? + +502 +00:22:26,088 --> 00:22:28,588 +And usually in this class on the the slides, +在这门课的幻灯片中, + +503 +00:22:28,590 --> 00:22:30,290 +if something's an Array of AnyObject, +如果看到一个 AnyObject 数组 + +504 +00:22:30,292 --> 00:22:32,258 +if there's gonna be a certain kind of thing in there, +那就是里面肯定有某种特定的东西 + +505 +00:22:32,260 --> 00:22:34,460 +I'll say, Array of the certain kind of thing. +换言之,由某种特定的对象组成的数组 + +506 +00:22:34,462 --> 00:22:36,628 +But when you write your code, then, +但是当你编写自己的代码时 + +507 +00:22:36,630 --> 00:22:40,565 +obviously, you might see, oh, that's Array of AnyObject, and +很明显,你将会知道这是个 AnyObject 数组 + +508 +00:22:40,567 --> 00:22:43,301 +that's again, the bridging will work here, +再一次,桥接起作用了 + +509 +00:22:43,303 --> 00:22:46,404 +automatically, so, no worries there. UIWindow. +这一切都是自动完成的,不需要你操心。UIWindow + +510 +00:22:46,406 --> 00:22:48,372 +There is a certain thing called a UIWindow. +有这么一个东西叫 UIWindow + +511 +00:22:48,374 --> 00:22:51,809 +It's a subclass UIView but it has no meaning in iOS. +它是 UIView 的子类,但是在 iOS 开发中你不需要关心 + +512 +00:22:51,811 --> 00:22:53,510 +There is a UIWindow it's at the very, +在每一个设备屏幕上都会有一个 UIWindow + +513 +00:22:53,512 --> 00:22:56,913 +very, very top of each device screen but +它在最高层上面 + +514 +00:22:56,915 --> 00:22:59,515 +you never send it any messages really. +但是你不会向它发送任何消息 + +515 +00:22:59,517 --> 00:23:00,583 +You don't interact with it. +你不跟它交互 + +516 +00:23:00,585 --> 00:23:02,151 +It's all about views. +在 iOS 中你只要关心 views + +517 +00:23:02,153 --> 00:23:04,152 +On a desktop windows matter. +但是在桌面环境中,UIWindow 就很关键 + +518 +00:23:04,154 --> 00:23:07,589 +But on iOS, it's all about views, okay? +再次强调,在 iOS 中你只要关心 views,明白了吗? + +519 +00:23:07,591 --> 00:23:08,690 +So don't worry about UIWindow. +不要操心 UIWindow + +520 +00:23:10,927 --> 00:23:13,127 +This hierarchy of views, subviews and +views 的层次结构,subviews 和 + +521 +00:23:13,129 --> 00:23:15,629 +superviews, is created usually, graphically. +superviews 通常不需要通过代码来创建 + +522 +00:23:15,631 --> 00:23:17,664 +You can drag things out in the StoryBoard. +你可以直接从 StoryBoard 中拖出来这些组件 + +523 +00:23:17,666 --> 00:23:20,800 +You can drag views inside other views to +你可以在其他 views 中拖入 views + +524 +00:23:20,802 --> 00:23:23,102 +create your hierarchy. +来创建你自己的层次结构 + +525 +00:23:23,104 --> 00:23:25,104 +But you can do it in code as well. +但是这并不是说不能用代码来创建这些东西 + +526 +00:23:25,106 --> 00:23:28,674 +It's pretty rare to do it in code, but you can. +很少人用代码创建图形部分,但是你可以这么做 + +527 +00:23:28,676 --> 00:23:30,809 +There's two methods here addSubview and +这里有两个方法:addSubview 和 + +528 +00:23:30,811 --> 00:23:33,611 +removeFromSuperview, addSubview is sent to +removeFromSuperview,addSubview 是 + +529 +00:23:33,613 --> 00:23:35,446 +the prospective superview. +向预期的 superview 发送的消息 + +530 +00:23:35,448 --> 00:23:37,314 +In other words to the place you wanna add your, +换言之,superview 是你想添加你的 view 的地方 + +531 +00:23:37,316 --> 00:23:38,749 +this view into. + +532 +00:23:38,751 --> 00:23:40,984 +And removeFromSuperview is sent to the view that you +同样的,removeFromSuperview 是 + +533 +00:23:40,986 --> 00:23:42,285 +want to remove. +向你想要移除的 view 发送的消息 + +534 +00:23:42,287 --> 00:23:44,571 +So these are sent to different people, +这两个消息发送给不同的对象 + +535 +00:23:44,572 --> 00:23:46,856 +okay, removeFromSuperview means remove yourself from +removeFromSuperview 意味着把“你”自己从 superview 中 + +536 +00:23:46,858 --> 00:23:47,556 +your superview. +移除 + +537 +00:23:49,493 --> 00:23:51,593 +So, where does the view hierarchy start? +那么 view 的层次结构从那里开始呢? + +538 +00:23:51,595 --> 00:23:52,927 +Where is the kind of the root, +它肯定有一个根节点 + +539 +00:23:52,929 --> 00:23:55,596 +the top level of this hierarchy, and +在层次结构的最顶上 + +540 +00:23:55,598 --> 00:23:58,132 +the answer is very simple, but, for some reason, +答案很简单,但是因为某些原因 + +541 +00:23:58,134 --> 00:24:00,667 +students have a very difficult time understanding this one. +学生们会很难理解这个概念 + +542 +00:24:00,669 --> 00:24:04,737 +There is a property in your UIView Controller +在你们的 UIView Controller 中有一个 property + +543 +00:24:04,739 --> 00:24:06,505 +called view, and +名字叫 view + +544 +00:24:06,507 --> 00:24:11,209 +it is the top level view in the scene in the StoryBoard. +这就是你们在 StoryBoard 场景中的最高层次的 view + +545 +00:24:11,211 --> 00:24:12,544 +All right. So you have this StoryBoard. +这里你有这个 StoryBoard + +546 +00:24:12,546 --> 00:24:15,346 +You've got your scene that we've seen like your +你有一个场景跟 Calculator 差不多的场景 + +547 +00:24:15,348 --> 00:24:17,331 +Calculator one. + +548 +00:24:17,332 --> 00:24:19,315 +The top level one, the place where you're going to add +在视图层次中最高层(你将要添加 + +549 +00:24:19,318 --> 00:24:22,720 +your top level views, is called view in your View Controller. +你顶层 views 的地方)在 View Controller 中叫做 view + +550 +00:24:22,722 --> 00:24:24,688 +It's just a property in UIView Controller. +它就是一个在 UIViewController 中的 property + +551 +00:24:24,690 --> 00:24:27,390 +So it really couldn't be simpler, okay? +不能够更简单了吧 + +552 +00:24:27,392 --> 00:24:29,859 +Sometimes students they just forget that's there and +有时学生们忘记了 UIViewController 中还有这么一个 view + +553 +00:24:29,861 --> 00:24:32,495 +ask how do I add something to my StoryBoard? +然后问:我怎么在我的 StordBoard 中添加东西呢? + +554 +00:24:32,497 --> 00:24:34,229 +You know in code or something like that. +你想要从代码中实现 + +555 +00:24:34,231 --> 00:24:37,065 +Well you just you add it to the view of +你只需要把它加入 UIViewController + +556 +00:24:37,067 --> 00:24:40,502 +your UIViewController, okay? +的 view 中,明白了吗? + +557 +00:24:40,504 --> 00:24:46,741 +So, let's talk about initializing a view. +接下来让我们讨论一下初始化一个 view + +558 +00:24:46,743 --> 00:24:50,444 +As usual, as I've kind of recommended, you probably want +通常我建议,不要做初始化 + +559 +00:24:50,446 --> 00:24:52,946 +to avoid doing an initializer, if you can. +尽可能不要 + +560 +00:24:52,948 --> 00:24:55,782 +So, to initialize any properties in +这里,在你的 view 中初始化 + +561 +00:24:55,784 --> 00:24:58,584 +your view hopefully using equals or +一些 properties 可以使用 = 来赋值 + +562 +00:24:58,586 --> 00:25:00,953 +some of the other ways we've talked about doing it. +或者我们说过的其他方法实现 + +563 +00:25:00,955 --> 00:25:03,856 +But, in UIView it's slightly more likely that you +但是,在 UIView 中有一点点相似的地方是 + +564 +00:25:03,858 --> 00:25:05,724 +might want to have an initializer. +你可能需要一个 initializer + +565 +00:25:05,726 --> 00:25:07,826 +So it's a slightly complicated thing. +通常这个有一点点复杂 + +566 +00:25:07,828 --> 00:25:08,926 +Only slightly. +不过只有一点点 + +567 +00:25:08,928 --> 00:25:11,262 +In that UIView has two initializers you +UIView 中有两个 initializers 是 + +568 +00:25:11,264 --> 00:25:12,730 +have to deal with. +你需要处理的 + +569 +00:25:12,731 --> 00:25:14,197 +And that's because UIViews can be created in +那是因为 UIView 可以由两种不同的方法 + +570 +00:25:14,200 --> 00:25:15,499 +two different ways. +来创建 + +571 +00:25:15,501 --> 00:25:18,468 +In code by just saying UIView and +在代码中你会写 UIView(frame: CGRect) + +572 +00:25:18,470 --> 00:25:22,438 +this frame initializer, which is just the frame in the superview, +这个 frame 就是 superview 的 frame + +573 +00:25:22,440 --> 00:25:26,042 +coordinate system where this view is gonna live. +它是一个坐标系,这个 view 将在这个坐标系里面 + +574 +00:25:26,044 --> 00:25:27,643 +But then there's also this init with coder. +还有一个是 init(coder: NSCoder) + +575 +00:25:27,645 --> 00:25:29,311 +And I'm not gonna talk about coders and +这里不打算讲 coders + +576 +00:25:29,313 --> 00:25:30,679 +archiving and all that. +和归档的那些东西 + +577 +00:25:30,681 --> 00:25:33,614 +But that is the initializer that is called when the view +但是在 Storyboard 中初始化的时候会 + +578 +00:25:33,616 --> 00:25:35,649 +comes out of a StoryBoard. +调用 init(coder: NSCoder) 方法 + +579 +00:25:35,651 --> 00:25:38,318 +So, if you create a view by dragging on a StoryBoard, +所以,你在 StoryBoard 中拖入一个 view + +580 +00:25:38,320 --> 00:25:41,455 +its initializer is this coder thing, okay? +它的初始化方法就会是 init(coder: NSCoder),明白了吗? + +581 +00:25:41,457 --> 00:25:44,858 +So, if you want, if you absolutely have to use +如果你想要,如果你不得不 + +582 +00:25:44,860 --> 00:25:47,694 +an initializer to initialize something in your UIView, +在你的 UIView 中使用一个 initializer 时 + +583 +00:25:47,696 --> 00:25:50,329 +you're gonna want to implement both of these things. +你就要实现这两个方法 + +584 +00:25:50,331 --> 00:25:53,432 +And I recommend this kind of format here. +这里我推荐的格式是 + +585 +00:25:53,434 --> 00:25:57,669 +Where you override init with frame there. +当你在这里 override init(frame: CGRect) + +586 +00:25:57,671 --> 00:26:00,271 +That is a designated initializer in UIView. +这是一个UIView 的 designated initializer + +587 +00:26:00,273 --> 00:26:03,641 +And then, there's actually a required initializer, +接下来,还有一个 requried 的 initializer + +588 +00:26:03,643 --> 00:26:05,042 +which is the decoder one. +也就是 decoder 方法 + +589 +00:26:05,044 --> 00:26:08,245 +So if you implement the init with frame you have to +如果你实现了 init(frame: CGRect) 方法 + +590 +00:26:08,247 --> 00:26:09,746 +implement the coder one, it's required, +你必须同时实现 init(coder: NSCoder), + +591 +00:26:09,748 --> 00:26:11,848 +cuz as soon as you implement the init with frame, +因为只要是你实现了 init(frame: CGRect) + +592 +00:26:11,850 --> 00:26:14,216 +you'll no longer inherit all of your designated +你就不再继承所有的 designated initializers + +593 +00:26:14,218 --> 00:26:17,052 +initializers you won't inherit the init with the coder. +同样你不再继承 init(coder: NSCoder) + +594 +00:26:17,054 --> 00:26:18,787 +So, basically implement them both, and +所以,简单来说就是实现这两者 + +595 +00:26:18,789 --> 00:26:21,189 +then just factor your initialization code into some +然后将这两个 initializer 分解成 + +596 +00:26:21,191 --> 00:26:24,659 +setup method or something, and call that, okay? +setup 方法或者其他的方法,然后调用分解出来的方法,明白了吗? + +597 +00:26:24,661 --> 00:26:26,827 +So, that's only if you absolutely have to +当且仅当你不得不 + +598 +00:26:28,064 --> 00:26:28,895 +have an initializer. +自己实现一个 initializer 才这么做 + +599 +00:26:30,365 --> 00:26:33,566 +All right, there's another alternative to initializing. +好了,还有一个初始化的办法 + +600 +00:26:33,568 --> 00:26:37,336 +Which is if you can wait until the initialization is finished +那就是,如果你可以等初始化完成 + +601 +00:26:37,338 --> 00:26:40,005 +but you want something really early in the view's life, +但你真的需要在这个视图构造好之前做一些东西的话 + +602 +00:26:40,007 --> 00:26:42,007 +you can implement this method awakeFromNib. +你可以实现 awakeFromNib 方法 + +603 +00:26:42,009 --> 00:26:43,508 +But that only works for +但是只有 Storyboard 中的视图 + +604 +00:26:43,510 --> 00:26:46,411 +views that come out of a StoryBoard, okay? +才会调用这个方法,记住了吗? + +605 +00:26:46,413 --> 00:26:49,347 +awakeFromNib means I just awoke from coming out of +awakeFromNib 表示,我刚刚从 Storyboard 中 + +606 +00:26:49,349 --> 00:26:50,848 +a StoryBoard. +被加载出来了 + +607 +00:26:50,850 --> 00:26:53,617 +So now you can initialize me. +你可以做一些初始化操作 + +608 +00:26:53,619 --> 00:26:56,019 +So it's a little bit limited, because it only is good for +不过这个方法使用很有局限性 + +609 +00:26:56,021 --> 00:26:57,353 +views that come out of a Storyboard. +因为它只是针对 Storyboard 中的视图 + +610 +00:26:58,322 --> 00:26:59,488 +But it is an alternative. +但是这确实是另外一种方法 + +611 +00:27:00,557 --> 00:27:02,157 +Now okay, so +好的 + +612 +00:27:02,159 --> 00:27:04,726 +that's all I'm going to say about that actually. +以上是关于视图初始化方面的内容 + +613 +00:27:04,728 --> 00:27:06,827 +Now let's go on to how do we. +现在我们来看看怎样在视图中 + +614 +00:27:06,829 --> 00:27:09,663 +Draw and handle events in this rectangular area. +绘制和处理触摸事件 + +615 +00:27:09,665 --> 00:27:11,765 +Well we need a coordinate system to work in. +我们需要一个坐标系来完成这些功能 + +616 +00:27:11,767 --> 00:27:13,233 +So there's some data structures I'm going to +所以我先会大致介绍一些 + +617 +00:27:13,235 --> 00:27:16,736 +show you real quick to get us started here, that we're +我们在绘制和处理触摸事件中 + +618 +00:27:16,738 --> 00:27:19,939 +gonna use when we're drawing and handling events. +需要用到的数据结构 + +619 +00:27:19,941 --> 00:27:24,843 +First of all, all coordinates are gonna be CGFloat. +首先,所有的坐标系的单位都是 CGFloat + +620 +00:27:24,845 --> 00:27:27,879 +Okay, CGFloat is a type in Swift struct. +是的,CGFloat 在 Swift 中是结构体 + +621 +00:27:27,881 --> 00:27:31,315 +And always use CGFloat when you're drawing or +记住,在绘制和处理触摸事件的时候 + +622 +00:27:31,317 --> 00:27:32,416 +handling events in a view. +我们都用 CGFloat 类型 + +623 +00:27:32,418 --> 00:27:33,684 +Do not use Double. +不要用 Double 类型 + +624 +00:27:33,686 --> 00:27:34,951 +Do not use Float. +也不要用 Float 类型 + +625 +00:27:34,953 --> 00:27:35,952 +If you use those in your homework, +如果你在课后作业中使用 Double 和 Float 这些类型 + +626 +00:27:35,954 --> 00:27:37,186 +you're gonna get dying, okay? +这在程序里是行不通的 + +627 +00:27:37,188 --> 00:27:38,020 +CGFloat. +只能用 CGFloat + +628 +00:27:39,056 --> 00:27:40,322 +Now Doubles and +你可以通过初始化方法 + +629 +00:27:40,324 --> 00:27:44,059 +Floats can be converted to a CGFloat using the initializer. +将 Double 和 Float 类型转换成 CGFloat 类型 + +630 +00:27:44,061 --> 00:27:47,462 +CGFloat has initializer for Float and Double. +你也可以通过 CGFloat 的初始化方法 + +631 +00:27:47,464 --> 00:27:48,929 +that you can pass and turn into a Float. +把 CGFloat 类型转换为 Double 或 Float 类型 + +632 +00:27:48,931 --> 00:27:52,966 +But, you always want things to be into CGFloat when you're +但是你在坐标系中操作的时候 + +633 +00:27:52,968 --> 00:27:55,568 +working in the coordinate system, okay? +你希望所有的东西都是 CGFloat 类型,对吧? + +634 +00:27:56,671 --> 00:27:58,571 +Now, there's a couple other structures that +这里还有一些比较重要的 + +635 +00:27:58,573 --> 00:27:59,538 +are important here. +结构体 + +636 +00:27:59,540 --> 00:28:00,472 +One is CGPoint. +一个是 CGPoint + +637 +00:28:00,474 --> 00:28:03,274 +It's just two Floats, X and Y. +它是由 x 和 y 两个 Float 类型组成的 + +638 +00:28:03,276 --> 00:28:05,209 +Just defines a point in the coordinate system. +它用来定义坐标系中的一个点 + +639 +00:28:05,211 --> 00:28:06,210 +Couldn't be simpler. +不能更简单了 + +640 +00:28:06,212 --> 00:28:08,712 +Okay? And there's also CGSize, +然后,另外一个是 CGSize + +641 +00:28:08,714 --> 00:28:09,846 +just defines a width and +它在坐标系中定义 + +642 +00:28:09,848 --> 00:28:11,815 +a height in the coordinate system. +一个长和一个宽 + +643 +00:28:11,817 --> 00:28:13,483 +Okay, so these are just simple structs. +是的,就是一些简单的结构体而已 + +644 +00:28:13,485 --> 00:28:14,517 +That's all they are, structs. +他们都是结构体 + +645 +00:28:14,519 --> 00:28:16,785 +I don't know, certainly Point, +我不太确定,但貌似 + +646 +00:28:16,787 --> 00:28:19,221 +I don't think has any other methods on it or anything. +CGPoint 并没有其他的方法 + +647 +00:28:19,223 --> 00:28:22,223 +Size, maybe, I don't think so, though. +CGSize 可能有,不过我也不太确定 + +648 +00:28:22,225 --> 00:28:24,726 +But these two are combined, the points and +当 CGSize 和 CGPoint 组合在一起的时候 + +649 +00:28:24,728 --> 00:28:27,928 +the size, to CGRect. +就变成了 CGRect + +650 +00:28:27,930 --> 00:28:31,031 +So CGRect is struct that has a point and a size. +CGRect 是由一个 CGPoint 类型的 point 和一个 CGSize 类型的 size 组成的结构体 + +651 +00:28:31,033 --> 00:28:33,100 +The point is the origin of the rect. +point 是这个矩形的原点 + +652 +00:28:33,102 --> 00:28:34,734 +Upper left, which I'm going to talk about in a second. +也就是矩形左上角的点,我稍后会详细解释的 + +653 +00:28:34,736 --> 00:28:37,270 +And then the size is the width and height. +然后 size 是矩形的宽和高 + +654 +00:28:37,272 --> 00:28:40,740 +Now rect has a lot of methods on it, okay? +CGRect 有很多方法 + +655 +00:28:40,742 --> 00:28:42,708 +Rect has things like minX, +比如说 minX + +656 +00:28:42,710 --> 00:28:44,242 +which is the left edge of the rect. +它表示矩形的左边界 + +657 +00:28:44,244 --> 00:28:48,112 +Or midY, which is the midpoint of the rectangle vertically. +又比如说 midY,表示矩形垂直方向上的中点 + +658 +00:28:48,114 --> 00:28:49,880 +Or intersects. +还有 intersects 方法 + +659 +00:28:49,882 --> 00:28:51,382 +And you pass another Rect, and it'll tell you, +你传递另外一个矩形进去,它会返回一个布尔值 + +660 +00:28:51,384 --> 00:28:53,650 +Boolean, whether it intersects that Rect, right? +来判断这两个矩形是否相交 + +661 +00:28:53,652 --> 00:28:55,251 +The two Rects overlap. +也就是它们是否重叠 + +662 +00:28:55,253 --> 00:28:57,887 +Or, intercept, which says, take this other Rect and +或者,intercept 方法可以创建一个 + +663 +00:28:57,889 --> 00:28:59,321 +create a smaller rectangle, +更小的矩形 + +664 +00:28:59,323 --> 00:29:01,457 +which is the intersection of those two Rects. +这个小矩形是由两个矩形交叉的部分 + +665 +00:29:02,459 --> 00:29:04,159 +Or contains point. +还有一个 CGRect 的方法叫 contains + +666 +00:29:04,161 --> 00:29:05,560 +Okay, we passed a point and +就是我们传递一个 CGPoint 类型的值进去 + +667 +00:29:05,562 --> 00:29:07,461 +it'll tell you whether it contains that point. +它告诉你这个点是否在矩形中 + +668 +00:29:07,463 --> 00:29:09,563 +So rect is this struct, but +所以,CGRect 这个结构体 + +669 +00:29:09,565 --> 00:29:11,264 +it has a lot of cool methods in there. +有很多很有意思的方法 + +670 +00:29:11,266 --> 00:29:12,732 +A whole bunch more. +一大堆的方法 + +671 +00:29:12,734 --> 00:29:16,035 +You can just type a rect, type and +你只需要键入 CGRect + +672 +00:29:16,037 --> 00:29:21,006 +then a dot Xcode show you all the cool methods it has, okay? +然后输入一个点(表示方法调用),Xcode 会显示所有这些方法 + +673 +00:29:21,008 --> 00:29:23,875 +All right, so those are the types of data types we're +好的,以上所有这些结构体 + +674 +00:29:23,877 --> 00:29:26,044 +gonna use to talk about our coordinate system and +都是关于坐标系和在坐标系中操作 + +675 +00:29:26,046 --> 00:29:27,979 +to write our code in coordinate system. +时所需要用的数据结构 + +676 +00:29:27,981 --> 00:29:30,915 +So let's talk about the Views coordinate system itself. +接下来我们看看视图中的坐标系统 + +677 +00:29:30,917 --> 00:29:33,283 +First of all, origin upper left. +首先,原点在左上角 + +678 +00:29:33,285 --> 00:29:35,652 +Some of you might be used to origin lower left, +你或许遇到过原点在左下角的坐标系 + +679 +00:29:35,654 --> 00:29:36,786 +like Cartesian coordinates, +比如笛卡尔坐标系 + +680 +00:29:36,788 --> 00:29:38,621 +the origin is in the lower left. +它的原点就在左下角 + +681 +00:29:38,623 --> 00:29:42,491 +But all this origin that you're using a view is in +但是你在使用一个视图的时候,它的坐标原点 + +682 +00:29:42,493 --> 00:29:44,543 +the upper left. +都处于左上角 + +683 +00:29:44,544 --> 00:29:46,594 +So, that means increasing Y is down the screen, +也就是说,Y 轴向下延伸 + +684 +00:29:46,597 --> 00:29:48,714 +increasing X is across. +X 轴向右延伸 + +685 +00:29:48,715 --> 00:29:50,832 +So, I put an example, 500 dot 35, 500 comma 35, over there. +比如这里有一个点(500,35) + +686 +00:29:50,834 --> 00:29:53,801 +It's 500 across, and only 35 down, okay? +它相对于左上角 + +687 +00:29:53,803 --> 00:29:58,238 +From the upper left. +向右500单位距离,向下35单位距离,明白吗? + +688 +00:29:58,240 --> 00:30:01,508 +The units that we're talking about here are points +在这里我们用的单位是点 + +689 +00:30:01,510 --> 00:30:02,342 +not pixels. +不是像素 + +690 +00:30:02,344 --> 00:30:03,476 +Okay. +是的 + +691 +00:30:03,478 --> 00:30:07,980 +Pick high, very high resolution displays have more +高分辨率的屏幕中,每一个点可能表示 + +692 +00:30:07,982 --> 00:30:10,282 +than one pixel per point. +多个像素 + +693 +00:30:10,284 --> 00:30:13,551 +Okay, 'cuz they are able to draw very find curves, +因为这么做可以用来绘制非常平滑的曲线 + +694 +00:30:13,553 --> 00:30:16,154 +very fine text, et cetera. +和文本等(抗锯齿) + +695 +00:30:16,156 --> 00:30:17,956 +You don't usually care +你通常不需要留心 + +696 +00:30:17,957 --> 00:30:19,757 +about the difference between points and pixels. +点和像素之间的区别 + +697 +00:30:19,759 --> 00:30:20,991 +It's automatically handled for +因为在你绘制文本或者曲线的时候 + +698 +00:30:20,993 --> 00:30:23,126 +you because you're doing things like drawing text or +这些东西会被自动处理,iOS 系统尽可能考虑 + +699 +00:30:23,128 --> 00:30:26,162 +drawing an arc and the system automatically uses as much +一个点到底应该占多少个像素 + +700 +00:30:26,164 --> 00:30:28,464 +pixels as it can to make things nice. +才能使绘制看上去更加完美 + +701 +00:30:28,466 --> 00:30:30,132 +But occasionally you do care, +但有些特殊的时候,你需要注意这些区别 + +702 +00:30:30,134 --> 00:30:33,836 +because maybe you're drawing something very finely detailed +特别是你需要处理和控制 + +703 +00:30:33,838 --> 00:30:37,372 +and you want to control pixel boundaries. +非常精细的细节和像素边界的时候 + +704 +00:30:37,374 --> 00:30:39,708 +And if you want to do that you can call this, +你可以访问你的视图中的一个属性 + +705 +00:30:39,710 --> 00:30:42,610 +get this property in view called contentScaleFactor +这个属性的名字是 contentScaleFactor + +706 +00:30:42,612 --> 00:30:46,180 +and it will return the number of pixels per point. +它会返回给你每点占多少个像素的值 + +707 +00:30:46,182 --> 00:30:48,182 +So on a retina display, that's gonna be 2. +在视网膜屏(Retina)中,一个点表示2个像素 + +708 +00:30:48,184 --> 00:30:51,184 +On a non-retina display, that will be 1. +非视网膜屏中表示1个像素 + +709 +00:30:51,186 --> 00:30:52,986 +It could be anything, though. +当然在其他屏幕中或许是任意的值 + +710 +00:30:52,988 --> 00:30:54,471 +Okay? +明白吗? + +711 +00:30:54,472 --> 00:30:55,955 +So you shouldn't write your code assuming it's 2 or 1. +所以你在代码里,不能直接写死2或1 + +712 +00:30:55,957 --> 00:30:58,758 +You should just write your code, get the contentScaleFactor +你在写代码的时候 + +713 +00:30:58,760 --> 00:31:00,993 +and you'll know how many pixels per point. +应该通过获取 contentScaleFactor 属性来知道这个值 + +714 +00:31:00,995 --> 00:31:02,528 +Okay? +记住了吗? + +715 +00:31:02,529 --> 00:31:04,062 +99% of the time, you don't have to worry about this, but +百分之九十九的情况下,你不需要担心这个问题,但是 + +716 +00:31:04,064 --> 00:31:07,065 +in your assignment three, hint, hint, you might have to. +在课后作业3中,你可能需要处理这个问题 + +717 +00:31:07,067 --> 00:31:07,632 +Okay. +好的 + +718 +00:31:09,502 --> 00:31:12,469 +So what about the boundaries of where drawing happens. +那么,我们绘制区域的边界在哪里? + +719 +00:31:12,471 --> 00:31:13,870 +You've got this rectangular area. +你已经有一个矩形区域 + +720 +00:31:13,872 --> 00:31:17,107 +Well, there's a very important property called bounds, +另外,有一个非常重要的属性,叫做 bounds + +721 +00:31:17,109 --> 00:31:20,910 +which is a CGRect, which describes the area you're +它是 CGRect 类型,它定义了坐标系中 + +722 +00:31:20,912 --> 00:31:25,047 +drawing in in your own coordinate system. +的绘制区域 + +723 +00:31:25,049 --> 00:31:26,081 +Okay? It's important that it's in +明白吗?需要特别注意的是 + +724 +00:31:26,083 --> 00:31:28,149 +your own coordinate system. +绘制是相对于自身的坐标系 + +725 +00:31:28,151 --> 00:31:32,553 +Because these views can be scaled and even rotated and +因为视图可以被拉伸,旋转 + +726 +00:31:32,555 --> 00:31:35,556 +translated to other you know, coordinates systems. +或者变换等(父视图坐标系中) + +727 +00:31:35,558 --> 00:31:37,257 +But when you're using the bounds and +但是你用 bounds 属性的时候 + +728 +00:31:37,259 --> 00:31:39,926 +you're drawing it yourself, you have this rectangle and +你是在自身坐标系绘制,你知道这个矩形 + +729 +00:31:39,928 --> 00:31:42,495 +you know where it is. +的确切位置 + +730 +00:31:42,496 --> 00:31:45,063 +Now the origin of your bounds usually is 0,0. +bounds 的原点通常是(0,0) + +731 +00:31:45,066 --> 00:31:46,865 +But you could define it to mean something else, for +但是你可以更改它 + +732 +00:31:46,867 --> 00:31:49,935 +example, scroll views they define their origin to +比如,Scroll View 在滚动的时候会 + +733 +00:31:49,937 --> 00:31:53,338 +be where they are in the thing they're scrolling, +更改它的原点为目前滚动到的位置 + +734 +00:31:53,340 --> 00:31:55,707 +that's just what they define origin to be, but +这是 Scroll View 定义 bounds 原点的方式 + +735 +00:31:55,709 --> 00:31:58,442 +90% of the time, your origin is just going to be 0,0. +但是百分之九十的情况下,你的 bounds 的原点是(0,0) + +736 +00:31:58,444 --> 00:31:59,410 +So, the width and +宽和高 + +737 +00:31:59,411 --> 00:32:00,377 +height is what you're going to care about, +才是你需要关心的 + +738 +00:32:00,379 --> 00:32:02,212 +how big a space am I drawing into. +我可以在多大的区域内绘制? + +739 +00:32:03,215 --> 00:32:06,082 +There are two other properties that often get confused with +这里还有两个容易和 bounds 混淆的属性 + +740 +00:32:06,084 --> 00:32:08,551 +bounds, but don't let this happen to you. +我希望你不会混淆它们 + +741 +00:32:08,553 --> 00:32:10,252 +One is center. +一个是 center + +742 +00:32:10,254 --> 00:32:14,589 +Center is the center of your view rectangle in your +center 是你自身视图矩形的中点 + +743 +00:32:14,591 --> 00:32:17,158 +superview's coordinate system, not in yours. +不过它是相对于父视图的坐标系,而不是自身坐标系的 + +744 +00:32:18,127 --> 00:32:20,194 +So if you write code that say, oh, I'm gonna start to +如果你这样写代码,我将在矩形中心 + +745 +00:32:20,196 --> 00:32:23,063 +draw something in middle of my rectangle. +绘制一些东西 + +746 +00:32:23,065 --> 00:32:24,297 +I'll get center. +我使用 center + +747 +00:32:24,299 --> 00:32:25,098 +Aah! + +748 +00:32:25,100 --> 00:32:26,516 +That's wrong. +这样就会出问题了 + +749 +00:32:26,517 --> 00:32:27,933 +Okay? Center is in your super view. +明白了吗?center 是相对于父视图的坐标系 + +750 +00:32:27,935 --> 00:32:29,368 +Center positions you. +center 定义你在父视图的位置 + +751 +00:32:29,370 --> 00:32:31,470 +It has nothing to do with how you draw. +它和绘制操作没有关系 + +752 +00:32:31,472 --> 00:32:33,805 +It just says where you are in your super view. +它仅仅用来在你父视图中定位 + +753 +00:32:33,807 --> 00:32:36,674 +Same thing, frame, frame is a rectangle in your +同样,frame 是父视图坐标系中 + +754 +00:32:36,676 --> 00:32:40,277 +super view's coordinate system that contains you. +用来包含子视图的一个矩形 + +755 +00:32:40,279 --> 00:32:43,847 +Okay, it contains all of you, of your drawing. +是的,它包含子视图的所有区域,包括绘制部分 + +756 +00:32:43,849 --> 00:32:45,615 +But it's in your super user coordinates systems so +但是它是相对于父视图的坐标系 + +757 +00:32:45,617 --> 00:32:48,385 +it's only good to position you, not for drawing. +所以它只是用来定位子视图,与绘制无关 + +758 +00:32:48,387 --> 00:32:50,186 +When you're drawing, you use bounds. +绘制的时候,你使用 bounds + +759 +00:32:50,188 --> 00:32:52,421 +To kind of give you a picture of this, +为了更形象地说明这个 + +760 +00:32:52,423 --> 00:32:55,057 +as better like you might think that +你可以这样认为 + +761 +00:32:55,059 --> 00:32:59,361 +the frame size is exactly the same as the bound size. +frame 的 size 和 bounds 的 size 总是相同的 + +762 +00:32:59,363 --> 00:33:02,563 +Right, if it's a rectangle that contains my rectangle, +如果一个矩形要完全包含我 + +763 +00:33:02,565 --> 00:33:04,932 +it must be exactly the same size. +它必须和我的尺寸一样大 + +764 +00:33:04,934 --> 00:33:07,734 +But no, because view can be rotated. +但也有例外,因为视图可以被旋转 + +765 +00:33:08,704 --> 00:33:10,487 +Okay? And +明白了吗? + +766 +00:33:10,488 --> 00:33:12,271 +if you rotate your view like this green view, +如果你像这个绿色视图这样,旋转你的视图 + +767 +00:33:12,273 --> 00:33:14,707 +look how much bigger the frame is. +你可以看到,frame 要大的多 + +768 +00:33:14,709 --> 00:33:18,410 +The rectangle that contains you is much bigger than you. +包含你的矩形,要比你自己大得多 + +769 +00:33:18,412 --> 00:33:19,878 +Because you're tilted. +因为你是倾斜的 + +770 +00:33:19,880 --> 00:33:20,578 +All right? +没问题吧? + +771 +00:33:21,814 --> 00:33:24,014 +Make sense? +清楚了吗? + +772 +00:33:24,015 --> 00:33:26,215 +So don't confuse frame and center, which are about +所以不要混淆了,frame 和 center 是用来定位视图的 + +773 +00:33:26,218 --> 00:33:30,420 +positioning, with bounce which is your size and +而 bounds 是用来在视图自身的坐标系中 + +774 +00:33:30,422 --> 00:33:33,623 +area that you're drawing into in your own coordinate system. +确定大小和区域的 + +775 +00:33:36,127 --> 00:33:37,059 +Okay? +明白吗? + +776 +00:33:37,060 --> 00:33:37,992 +Okay, so creating views. +接下来,视图的创建 + +777 +00:33:37,995 --> 00:33:38,527 +How do we create views? +我们怎样创建一个视图? + +778 +00:33:42,533 --> 00:33:45,333 +Most often views are created by dragging them out to +大部分的视图是直接 + +779 +00:33:45,335 --> 00:33:46,801 +the Storyboard. +通过 Storyboard 生成的 + +780 +00:33:46,803 --> 00:33:50,104 +That's 95% of the time. +大概百分之九十五都是这样 + +781 +00:33:50,106 --> 00:33:52,123 +And af, but +但是 + +782 +00:33:52,124 --> 00:33:54,141 +of course, your views aren't sitting in the Object Pallet, +官方视图可能不能满足你的需要 + +783 +00:33:54,143 --> 00:33:57,577 +there's buttons and sliders, but there's no your view. +这里有按钮,滑条等,但是可能没有你需要的视图 + +784 +00:33:57,579 --> 00:34:00,113 +So you have to drag it out of generic view. +这时候,你就需要先拖一个通用的视图(UIView) + +785 +00:34:00,115 --> 00:34:01,681 +It's kind of at the bottom of the pallet and +就在控件区的底部 + +786 +00:34:01,683 --> 00:34:02,782 +you just drag it out. +拖出来就可以了 + +787 +00:34:02,784 --> 00:34:05,051 +Once you drag it out though, +一旦你拖出来这个视图后 + +788 +00:34:05,052 --> 00:34:07,319 +you have to go to the Identity Inspector and change the class +你需要在它的 Identity Inspector 里 + +789 +00:34:07,321 --> 00:34:10,989 +of that view that you dragged out, so that it's your class. +把对应的类修改你自己的实现类 + +790 +00:34:10,991 --> 00:34:12,457 +Okay? So it's a two step process. +明白吗?需要两步来完成这个操作 + +791 +00:34:12,459 --> 00:34:15,093 +You drag a view, your custom view out and then you change +先拖一个通用的视图出来 + +792 +00:34:15,095 --> 00:34:19,930 +this class to view whatever your custom class is on rare +然后把对应的类改为你自己的类 + +793 +00:34:19,932 --> 00:34:24,034 +occasion, you might create an instance of your view in code. +只有在很少情况下,你才需要用纯代码创建视图 + +794 +00:34:25,036 --> 00:34:26,569 +Probably never in this class, +至少本课程范围内,你不需要这样做 + +795 +00:34:26,571 --> 00:34:29,938 +maybe in your final project, although I doubt it. +大作业上可能会用到 + +796 +00:34:29,940 --> 00:34:34,442 +You just do that using UIView's frame initializer. +你可以通过一个特殊的构造器 + +797 +00:34:34,444 --> 00:34:35,376 +Right? So you just say +来通过代码创建一个视图 + +798 +00:34:35,378 --> 00:34:36,644 +view equals UIView frame. +这里你输入 view = UIView(frame: ...) + +799 +00:34:38,214 --> 00:34:40,414 +You can even do UIView with no arguments and +甚至你也可以不传参数给这个构造器 + +800 +00:34:40,416 --> 00:34:43,283 +it'll give you a CGRect to zero which is a frame zero +这样的话,它返回给你一个空视图(CGRectZero),也就是说这个视图的 + +801 +00:34:43,285 --> 00:34:45,485 +size and width and +size 和 frame 都是0 + +802 +00:34:45,486 --> 00:34:47,686 +then you could later set its frame to position the view. +稍后,你可以再设置这个视图的 frame 来确定位置 + +803 +00:34:47,689 --> 00:34:50,189 +So here's an example of creating a view in code. +这里有一个使用代码创建视图的例子 + +804 +00:34:50,191 --> 00:34:51,590 +I'm going to use UILabel. +我接下来要使用 UILabel 控件 + +805 +00:34:51,592 --> 00:34:55,093 +UILabel is a subclass of UIView so I can send it. +UILabel 是 UIView 的一个子类,所以我可以使用带 frame 参数的构造器 + +806 +00:34:55,095 --> 00:34:57,495 +UILabels parentheses frame. +UILabel(frame: ...) + +807 +00:34:57,497 --> 00:34:59,263 +So I just give it this frame which is kind of in +我传入一个 frame + +808 +00:34:59,265 --> 00:35:00,698 +the upper left. +这个 frame 会让视图设置在左上方的位置 + +809 +00:35:00,700 --> 00:35:04,334 +Notice I've created this view but it's not on screen yet. +注意,我已经创建了这个视图,但是它并没有显示在屏幕上 + +810 +00:35:04,336 --> 00:35:06,003 +Okay. + +811 +00:35:06,004 --> 00:35:07,671 +Assuming this code here is in a View Controller, +假设这里的代码是在一个 View Controller 里 + +812 +00:35:07,673 --> 00:35:10,640 +I could then say view.addSubview. +我接下来可以输入 view.addSubview + +813 +00:35:10,642 --> 00:35:12,475 +Cuz remember view is a property in +还记得 view 是一个在我的 View Controller 中的一个属性吗? + +814 +00:35:12,477 --> 00:35:15,144 +my View Controller which is that top level view. +它指向了 View Controller 中最顶层的那个视图 + +815 +00:35:15,146 --> 00:35:17,279 +And I could say add subview of the label and +这里我输入,view.addSubview(label) + +816 +00:35:17,281 --> 00:35:18,613 +boom, it'll appear on screen. +这样,这个视图就出现在屏幕上了 + +817 +00:35:19,616 --> 00:35:20,514 +Okay? At 20,20 , +在(20,20)的位置上 + +818 +00:35:20,516 --> 00:35:22,716 +width 100, height 50. +宽度是100,高度是50 + +819 +00:35:22,718 --> 00:35:23,283 +Okay? +明白了么? + +820 +00:35:25,120 --> 00:35:26,619 +So it is possible to create views in code. +所以可以完全通过代码来创建一个视图 + +821 +00:35:26,621 --> 00:35:28,821 +We almost never do that in iOS. +不过 iOS 开发中几乎不这么做 + +822 +00:35:28,823 --> 00:35:29,855 +We use Storyboard. +我们使用 Storyboard + +823 +00:35:31,458 --> 00:35:35,727 +Okay, so when do I wanna create my own UIView? +那么,什么时候我们会想创建一个自己的 UIView 呢? + +824 +00:35:35,729 --> 00:35:36,660 +Right? +嗯? + +825 +00:35:36,662 --> 00:35:38,162 +Well, when don't you want to? +换一个思路,什么时候我么你不想创建一个自己的 UIView + +826 +00:35:38,164 --> 00:35:40,597 +Well you don't want to if you want a button or a slider or +当你只是需要一个按钮或者 Slider 或者任何东西 + +827 +00:35:40,599 --> 00:35:43,099 +anything where there's already an iOS view. +这些已经存在于 iOS 系统的控件库中的时候,你不需要自己创建一个 UIView + +828 +00:35:43,101 --> 00:35:44,400 +But if you want to do something that +但是如果你想要做一些 + +829 +00:35:44,402 --> 00:35:47,303 +those things can't do, draw something special or +特别的事情,比如绘制一些其他图形 + +830 +00:35:47,305 --> 00:35:49,538 +handle touch events like swipes and +或者想让触摸事件,例如 Swipes 和 + +831 +00:35:49,540 --> 00:35:54,509 +taps and pinches, differently or for a different purpose. +Taps 以及 Pinches 手势,有着不同的处理方式 + +832 +00:35:54,511 --> 00:35:58,212 +Then those things then you create your own custom view. +那么你这时候,你想要创建自己的 UIView + +833 +00:35:58,214 --> 00:36:00,581 +So, we're going to focus on drawing today, and +所以,我们今天将会专注于绘制 + +834 +00:36:00,583 --> 00:36:03,984 +I'll do gestures in the next lec, in the next lecture. +然后在下节课我将会讲触摸手势识别相关的内容 + +835 +00:36:03,986 --> 00:36:05,585 +To draw in your UIView, +在你的 UIView 中绘制时 + +836 +00:36:05,587 --> 00:36:09,155 +all you need to do is override this method drawRect. +你需要重写 drawRect 方法 + +837 +00:36:10,591 --> 00:36:13,425 +Okay, very simple method only takes one argument. +一个非常简单的方法,它只接受一个参数 + +838 +00:36:13,427 --> 00:36:15,594 +In the code, it's actually called Rect, but +在代码中,这个参数实际上叫做 rect + +839 +00:36:15,596 --> 00:36:18,697 +I've renamed it to be regionThatNeedsToBeDrawn, so +但是我已经将它重新命名为 regionThatNeedsToBeDrawn + +840 +00:36:18,699 --> 00:36:20,798 +that people understand what that argument is. +这样人们就可以更好理解 rect 参数是什么意思 + +841 +00:36:20,800 --> 00:36:23,734 +That argument is purely an optimization. +那个参数纯粹是起一个优化效果 + +842 +00:36:23,736 --> 00:36:27,338 +It's just the system saying, hey, draw yourself and really, +这个参数告诉系统,当你绘图的时候 + +843 +00:36:27,340 --> 00:36:29,339 +I only care about this rectangle of you. +我只是关心参数的这个区域 + +844 +00:36:29,341 --> 00:36:31,641 +But you can draw your, the whole self if you want. +当然你可以绘制整个,整个你想要的视图区域 + +845 +00:36:31,643 --> 00:36:33,609 +But this is the only rectangle I really care about. +但是只有这个矩形范围,才是我真正关注的 + +846 +00:36:33,611 --> 00:36:37,279 +So if you had a View that knew how to draw parts of itself, +所以如果你有一个视图,而且视图知道如何去绘制它的部分区域 + +847 +00:36:37,281 --> 00:36:40,182 +okay, then it could only draw the part that's in +那么这个方法只会绘制 + +848 +00:36:40,184 --> 00:36:41,650 +this rectangle, but +参数这个矩形区域内的部分 + +849 +00:36:41,651 --> 00:36:43,117 +you can completely ignore this rectangle if you want. +当然你可以完全忽略你想要的这个矩形范围 + +850 +00:36:43,120 --> 00:36:45,387 +It's purely an optimization. +它纯粹的起一个优化效果 + +851 +00:36:45,389 --> 00:36:45,953 +Okay? +明白了吗? + +852 +00:36:48,124 --> 00:36:49,990 +This is very important to understand, +下面这个概念是相当重要的 + +853 +00:36:49,992 --> 00:36:53,260 +you never call drawRect, ever, never. +“永远不要调用 drawRect 方法” + +854 +00:36:53,262 --> 00:36:54,160 +Never. +永远不要 + +855 +00:36:54,162 --> 00:36:55,345 +Okay? + +856 +00:36:55,346 --> 00:36:56,529 +If you call drawRect in your homework, +如果你在你的课后作业中调用了 drawRect 方法 + +857 +00:36:56,531 --> 00:36:58,330 +you're going to be a major ding. +你会得到一个很糟糕的分数 + +858 +00:36:58,332 --> 00:36:59,999 +Because I'm standing here in front of +因为我站在这里,站在 + +859 +00:37:00,001 --> 00:37:01,600 +you with red text on my slide. +我 Slide 上的红色文字之前 + +860 +00:37:01,602 --> 00:37:03,034 +Saying, never. +告诉你,永远不要这么做 + +861 +00:37:03,036 --> 00:37:05,153 +Okay. + +862 +00:37:05,154 --> 00:37:07,271 +Do not call drawRect, drawRect is called by the system. +不要调用 drawRect 方法,drawRect 方式是被系统调用的 + +863 +00:37:07,273 --> 00:37:09,190 +Okay? +明白了吗? + +864 +00:37:09,191 --> 00:37:11,108 +It's called by the system when your view needs to be redrawn. +当你的视图需要重新绘制时,它会自动被系统调用 + +865 +00:37:11,110 --> 00:37:13,010 +How does the system know your needs, +那么你们会问,系统是怎样知道你需要重绘这个视图呢? + +866 +00:37:13,012 --> 00:37:14,578 +view needs to be redrawn? +重绘这个视图呢? + +867 +00:37:14,580 --> 00:37:18,314 +Because somebody called setNeedsDisplay on your view. +在你的视图里,有一个叫做 setNeedDisplay 的方法 + +868 +00:37:18,316 --> 00:37:19,982 +And you can call it on yourself if you want. +如果你需要重绘视图的话,你可以调用它 + +869 +00:37:19,984 --> 00:37:22,985 +If something has changed about your view, some property or +如果在你的视图中有内容发生变化时 + +870 +00:37:22,987 --> 00:37:24,887 +something that would change the way it's drawn, +比如一些属性或者一些东西的改变 + +871 +00:37:24,889 --> 00:37:26,888 +you call setNeedsDisplay on yourself, +你可以对自身调用 setNeedsDisplay 方法 + +872 +00:37:26,890 --> 00:37:29,691 +eventually the system will call your drawRect. +最终,系统会在合适的时机调用你的 drawRect 方法 + +873 +00:37:29,693 --> 00:37:31,993 +But it's got to set some things up first, okay. +但是首先,它会设置某些东西 + +874 +00:37:31,995 --> 00:37:33,928 +There's other views around you. +在你周围有其他的视图 + +875 +00:37:33,930 --> 00:37:36,330 +That it has to get organized. +它们必须先被组织起来 + +876 +00:37:36,332 --> 00:37:38,965 +Okay, so never call drawRect, drawRect it's called for you. +所以,永远不要调用 drawRect,drawRect 会自动被系统调用的 + +877 +00:37:38,967 --> 00:37:42,002 +When you call setNeedsDisplay, you can specify I +当你调用 setNeedsDisplay 的时候 + +878 +00:37:42,004 --> 00:37:44,303 +really only need this rectangle redisplayed and +你可以指定,你只需要某个特定的范围来重绘 + +879 +00:37:44,305 --> 00:37:45,905 +then obviously, +接下来 + +880 +00:37:45,906 --> 00:37:47,506 +that rectangle's gonna show up in the argument to drawRect. +那块区域将会以参数形式传递给 drawRect 方法 + +881 +00:37:48,609 --> 00:37:51,143 +Okay, but if multiple people call set in use display with +好的,如果当很多人在用不同的矩形范围上 + +882 +00:37:51,145 --> 00:37:53,345 +different rectangles, probably the union of those +调用 setNeedsDisplay 的时候,可能这些区域的并集 + +883 +00:37:53,347 --> 00:37:56,280 +rectangles might get called here one time for drawRect. +会作为参数被 drawRect 方法一次调用完成 + +884 +00:37:56,282 --> 00:37:57,581 +Okay? +明白了么? + +885 +00:37:57,583 --> 00:38:00,517 +Make sense? +听懂了么? + +886 +00:38:00,519 --> 00:38:01,418 +All right. + +887 +00:38:01,420 --> 00:38:03,186 +So, how do you implement this, pow, +所以,你要怎样实现这个 + +888 +00:38:03,188 --> 00:38:05,922 +all-powerful drawRect method? +无所不能的 drawRect 方法呢? + +889 +00:38:05,924 --> 00:38:09,625 +You can use, kind of a C-like, function-based API, +你可以使用,类似于 C 语言,基于函数的 API + +890 +00:38:09,627 --> 00:38:11,259 +called Core Graphics. +叫做 Core Graphics + +891 +00:38:11,261 --> 00:38:13,094 +That's what it's all based on. +它是所有图像绘制的基础 + +892 +00:38:13,096 --> 00:38:15,596 +Or you can use a nice object-oriented, thing, +或者你可使用一种更高层次、面向对象的做法 + +893 +00:38:15,598 --> 00:38:18,432 +called UIBezierPath, which is what we're gonna use, +叫做 UIBezierPath,这就是我们接下来要使用的 + +894 +00:38:18,434 --> 00:38:20,367 +because we like object-oriented. +因为我们偏向于用一些高层次的 API + +895 +00:38:20,369 --> 00:38:23,603 +But since the underlying stuff core graphics is what +但是,因为涉及到图形绘制底层的东西 + +896 +00:38:23,605 --> 00:38:26,973 +UIBezierPath is built on, I'm gonna kinda explain a little +我会介绍一些 Core Graphics 的概念 + +897 +00:38:26,975 --> 00:38:29,442 +bit about the concepts of Core Graphics. +它是构建 UIBezierPath 的核心和基础 + +898 +00:38:29,444 --> 00:38:31,944 +How one draws in Core Graphics. +一个东西是怎么样在 Core Graphics 中绘制的? + +899 +00:38:31,946 --> 00:38:34,380 +The first thing in Core Graphics that's important is, +在 Core Graphics 中第一件很重要的事是 + +900 +00:38:34,382 --> 00:38:37,416 +you have to get a context to draw in. +你得拥有一个用来绘制的上下文(context) + +901 +00:38:37,418 --> 00:38:38,700 +Okay? +明白了吗? + +902 +00:38:38,701 --> 00:38:39,983 +So if you're printing you'll have a printing context. +如果你要 printing 那你得有一个 printing 的 context + +903 +00:38:39,986 --> 00:38:41,519 +If you're drawing on screen you'll have a draw on +如果你要在屏幕上绘制你得有一个 + +904 +00:38:41,521 --> 00:38:44,305 +screen context, et cetera. +可以绘制的屏幕 context,等等 + +905 +00:38:44,306 --> 00:38:47,090 +And inside drawRect, when you're drawRect is called by +在 drawRect 中,当你准备绘制时 + +906 +00:38:47,093 --> 00:38:50,227 +the system, it sets up the drawing context for you. +系统会调用 drawRect 方法并且为你建立一个绘制的 context + +907 +00:38:50,229 --> 00:38:51,895 +So it's automatically set up, +所以它是自动建立的 + +908 +00:38:51,897 --> 00:38:54,097 +and it's called the current context, +并且它被称为当前的 context + +909 +00:38:54,099 --> 00:38:55,431 +the current drawing context. +当前的绘制 context + +910 +00:38:55,433 --> 00:38:58,233 +And you can get it if you were using the C-API. +同时如果你使用 C-API 你也可以得到它 + +911 +00:38:58,235 --> 00:39:01,837 +Or C-like APIs it's still Swift but it's functional. +或者C-like APIs 它仍然是 Swift 但是它是实用的 + +912 +00:39:01,839 --> 00:39:03,405 +Function API, you can get it +API 函数,你可以得到他们 + +913 +00:39:03,407 --> 00:39:06,207 +with this function UIGraphicsGetCurrentContext. +通过 UIGraphicsGetCurrentContext 方法 + +914 +00:39:06,209 --> 00:39:07,541 +And it will return this cookie, +它将会返回到这个 cookie + +915 +00:39:07,543 --> 00:39:08,876 +it's just this magic cookie. +它只个令人惊奇的 cookie + +916 +00:39:08,878 --> 00:39:11,411 +You don't know what it is, but it is the context of drawing. +你不知道它是什么,但是它是绘制时的 context + +917 +00:39:11,413 --> 00:39:15,615 +Because all of the C-like functional API take +因为所有的 C-like 函数的 API + +918 +00:39:15,617 --> 00:39:17,483 +a context as an argument. +使用 context 作为参数 + +919 +00:39:17,485 --> 00:39:20,786 +Okay, BezierPath doesn't do that no worries, +Okay,BezierPath 不会这样做,不用担心 + +920 +00:39:20,788 --> 00:39:22,521 +but that one does. +但是那个会这么做 + +921 +00:39:22,522 --> 00:39:24,255 +So the first thing you need is a context automatically set up +所以你需要做的第一件事是自动创建一个 context + +922 +00:39:24,258 --> 00:39:25,824 +for your when drawRect is called. +当你的 drawRect 被调用时 + +923 +00:39:25,826 --> 00:39:29,927 +Then you create paths, you create paths with lines and +然后你创建路径,通过线条和 + +924 +00:39:29,929 --> 00:39:31,395 +arcs and things like that. +弧线以及诸如此类的东西创建路径 + +925 +00:39:32,297 --> 00:39:33,930 +Then you set the drawing attributes, +然后你设置绘制的属性 + +926 +00:39:33,932 --> 00:39:36,499 +like the colors you want to draw in, the linewidths, and +比如你希望绘制的颜色,线条宽度 + +927 +00:39:36,501 --> 00:39:37,800 +things like that, and +和类似于这些的东西 + +928 +00:39:37,802 --> 00:39:41,370 +finally, you stroke and fill those paths. +最后你描边并且填充这些路径 + +929 +00:39:42,305 --> 00:39:44,122 +Okay? +明白了么? + +930 +00:39:44,123 --> 00:39:45,940 +And you can do either, or, or both stroking and filling. +你可以做任意一个,或者同时做两个 + +931 +00:39:45,942 --> 00:39:48,509 +So that is how, that is fundamentally how you draw. +因此这就是你绘制的基础 + +932 +00:39:48,511 --> 00:39:52,979 +Things like drawing text is just the fonts know how to +类似于绘制文字之类的事情只是需要知道字体 + +933 +00:39:52,981 --> 00:39:56,049 +have the perfect path to draw beautiful letters. +并且如何获得一个完美的路径来绘制漂亮的字母 + +934 +00:39:56,051 --> 00:39:58,918 +And so, your stroking would outline the letters, and +所以,你的描边将描绘出字母的轮廓 + +935 +00:39:58,920 --> 00:40:01,620 +filling fills in the letters, okay? +然后填充到字母的内部,明白? + +936 +00:40:01,622 --> 00:40:05,023 +So even drawing text, is just stroking and filling paths. +所以即使是绘制文字,也只需要描边和填充的路径 + +937 +00:40:06,093 --> 00:40:10,061 +Okay? Now, UIBzierPath, this object-oriented +明白了么?现在,UIBzierPath,这个面向对象的 + +938 +00:40:10,063 --> 00:40:12,830 +thing on top, it always draws in the current context, +东西在最上面,它通常在当前的 context 上绘制 + +939 +00:40:12,832 --> 00:40:14,431 +you don't have to worry about context. +你不用担心这个 context + +940 +00:40:14,433 --> 00:40:17,934 +It has methods, to do things like line two, arch two, +它有很多方法,去做一些类似于两个线条,两个弧线的东西 + +941 +00:40:17,936 --> 00:40:19,069 +to build the path. +用来建立路径 + +942 +00:40:19,071 --> 00:40:20,821 +It also has methods for +它同样拥有很多方法 + +943 +00:40:20,822 --> 00:40:22,572 +setting a lot of these attributes like linewidth and +用来设置很多属性例如线宽 + +944 +00:40:22,574 --> 00:40:25,174 +things like that and it has methods to stroke and fill. +和一些类似的属性同时它还有很多方法去描边和填充 + +945 +00:40:25,176 --> 00:40:28,243 +So combine all those Core Graphics things into one class. +所以将所有的 Core Graphics 放到一个类里 + +946 +00:40:28,245 --> 00:40:30,012 +So let's look at UIBezierPath, and +让我们来看一下 UIBezierPath + +947 +00:40:30,014 --> 00:40:32,747 +how we would use it to draw a triangle, let's say. +和我们怎样使用它绘制一个三角形,比如说 + +948 +00:40:34,183 --> 00:40:37,418 +First we create a path, so we just say, UIBezierPath. +首先,我们创建一个路径,比方说,UIBezierPath + +949 +00:40:37,420 --> 00:40:40,320 +There are other initializers for UIBezierPath but +有其他的 UIBezierPath 初始化方法 + +950 +00:40:40,322 --> 00:40:42,889 +you could also just create an empty path, and +但是你也可以只建立一个空的路径 + +951 +00:40:42,891 --> 00:40:45,625 +then you can start moving around. +然后你就可以开始在周围移动了 + +952 +00:40:45,627 --> 00:40:50,195 +So, here I'm going to assume this screen is 160 points wide +所以,在这里我们假设这个屏幕是 160 * 250 + +953 +00:40:50,197 --> 00:40:53,965 +by 250 wide, and I'm gonna draw, this triangle here. +然后我准备在这里绘制一个三角形 + +954 +00:40:53,967 --> 00:40:57,102 +So I'm gonna move to 80 which is halfway across and +所以我准备移动 80 个点,大概在屏幕中间 + +955 +00:40:57,104 --> 00:40:58,369 +50 which is a little bit down, +和 50 个点一点点下降 + +956 +00:40:58,371 --> 00:41:03,607 +and then I'm going to add a line down to 140, 150. +然后我将要添加一条线向下到 140,150 + +957 +00:41:03,609 --> 00:41:06,743 +Then I wanna another line over to 10, 150. +接下来我想再添加另一条线到 10,150 + +958 +00:41:06,745 --> 00:41:10,446 +Then I'm going to close this path. +然后我将会关闭这个路径 + +959 +00:41:10,448 --> 00:41:11,681 +Okay? +看明白了么? + +960 +00:41:11,682 --> 00:41:12,915 +So that's it, that's how you can make a triangle. +所以,这是这样,这就是如何绘制一个三角形 + +961 +00:41:12,917 --> 00:41:16,285 +Now, I'm kind of lying to you a little bit, because as you +现在,我有点儿欺骗了你们一下,因为当你们 + +962 +00:41:16,287 --> 00:41:18,687 +execute these, nothing is appearing on screen. +这么做的时候,屏幕上什么也不会出现 + +963 +00:41:18,689 --> 00:41:21,389 +The screen will be blank. +屏幕将会一片空白 + +964 +00:41:21,391 --> 00:41:23,891 +Okay, I was only showing them so you could understand what I +Okay,我只是向你们展示它们,这样你就可以理解 + +965 +00:41:23,893 --> 00:41:25,726 +was doing there with the lines. +我在这儿通过这些线做了什么 + +966 +00:41:25,728 --> 00:41:27,278 +So it'd be blank. +所以它将会一篇空白 + +967 +00:41:27,279 --> 00:41:28,829 +To make it appear, you have to stroke or fill. +要让它出现,你必须描边或者填充 + +968 +00:41:28,831 --> 00:41:31,331 +So, let's set the attributes we want. +所以,让我们设置我们需要的属性 + +969 +00:41:31,333 --> 00:41:34,300 +So, I'm gonna set the color for filling to be green, and +所以,我将填充的颜色设置为绿色 + +970 +00:41:34,302 --> 00:41:37,403 +the color for stroking to be red. +描边的颜色设置为红色 + +971 +00:41:37,405 --> 00:41:41,007 +Okay, now notice that I set those with methods on UIColor, +Okay,现在注意我是通过 UIColor 的方法设置这些属性 + +972 +00:41:41,009 --> 00:41:43,409 +not with methods on the BezierPath. +不是通过 BezierPath 的方法 + +973 +00:41:43,411 --> 00:41:46,144 +Okay, that's a little interesting but +Okay,那是有一点有趣但是 + +974 +00:41:46,146 --> 00:41:47,679 +that's the way that works. +它就是那样工作的 + +975 +00:41:47,681 --> 00:41:51,015 +But linewidth, I do step by talking to the paths, so +但是线宽,我得通过和路径进行沟通来做 + +976 +00:41:51,017 --> 00:41:52,316 +I sent a message to the BezierPath, +所以我发送一个消息到 BezierPath + +977 +00:41:52,318 --> 00:41:53,650 +set linewidth the three. +设置线条的宽度为 3 + +978 +00:41:53,652 --> 00:41:57,254 +So once I set up all my attributes, now I can fill, +所以当我设置我所需要的全部属性后,现在我可以填充 + +979 +00:41:57,256 --> 00:41:58,988 +for example by saying, path fill and +比方说,填充路径 + +980 +00:41:58,990 --> 00:42:01,791 +see, I get the rectangle filled in green. +看,我得到了一个填充为绿色的三角形 + +981 +00:42:01,793 --> 00:42:05,127 +Or, I can say stroke and it'll stroke the red line. +或者说,我可以给它描边,它将会变成红边 + +982 +00:42:05,129 --> 00:42:07,696 +Okay? +明白了么? + +983 +00:42:07,698 --> 00:42:10,098 +Pretty straightforward? +很简单吧? + +984 +00:42:10,100 --> 00:42:12,100 +Most of learning to draw is all about +大多数的学习绘制全都关于 + +985 +00:42:12,102 --> 00:42:14,568 +understanding UIBezierPath and all the methods on it. +理解 UIBezierPath 和它全部的方法 + +986 +00:42:14,570 --> 00:42:15,269 +Question back there? +这里有什么问题么? + +987 +00:42:16,438 --> 00:42:18,038 +>> if I have two shapes onscreen, +-(学生提问)如果我在屏幕上有两个图形 + +988 +00:42:18,040 --> 00:42:20,707 +>> how would I set the colors be different for each one? +- 我怎么样给每个图形不同的颜色呢? + +989 +00:42:20,709 --> 00:42:21,875 +If you have two what? +如果你有两个什么? + +990 +00:42:21,876 --> 00:42:23,042 +>> If you have two different shapes onscreen? +- 如果你在屏幕上有两个图形 + +991 +00:42:23,044 --> 00:42:23,976 +Oh, yes. So, the question, +哦,是的,这就是问题 + +992 +00:42:23,978 --> 00:42:25,210 +if I have two shapes onscreen, +如果我在屏幕上有两个图形 + +993 +00:42:25,212 --> 00:42:27,912 +how would I set the colors be different for each one? +我怎么样给每个图形不同的颜色呢? + +994 +00:42:27,914 --> 00:42:30,748 +I would set the colors, stroke or fill one. +我可以给一个设置颜色,描边或者填充 + +995 +00:42:30,750 --> 00:42:32,149 +Set the colors on something else, stroke or +给另一个设置其他的颜色,描边或者 + +996 +00:42:32,151 --> 00:42:32,783 +fill the other. +填充 + +997 +00:42:33,719 --> 00:42:34,918 +Okay? +明白了么? + +998 +00:42:34,920 --> 00:42:36,503 +Question. +问题 + +999 +00:42:36,504 --> 00:42:38,087 +>> If the path isn't closed, what does fill do? +- 如果路径不是闭合的,那怎么去填充呢 + +1000 +00:42:38,089 --> 00:42:39,605 +So the question is, +这就是问题 + +1001 +00:42:39,606 --> 00:42:41,122 +if the path is not closed, what does fill do? +如果 path 不是闭合的,填充的结果是什么? + +1002 +00:42:41,125 --> 00:42:43,926 +Well, it depends on, I think the winding rule, and, +我想它取决于绕圈规则,以及 + +1003 +00:42:43,928 --> 00:42:45,694 +other things about how it draws. +其他如何绘制的一些东西 + +1004 +00:42:45,696 --> 00:42:48,196 +But, it will try to fill it in. +但是,它会努力去填充 + +1005 +00:42:48,198 --> 00:42:49,097 +Okay. I mean a path could +我的意思是 path 可以 + +1006 +00:42:49,099 --> 00:42:50,931 +cross back over itself. +回头和自己相交 + +1007 +00:42:50,933 --> 00:42:52,132 +Right? And so filling it +对吗?对这种情况进行填充 + +1008 +00:42:52,134 --> 00:42:54,234 +might be hard to understand. +可能很难理解 + +1009 +00:42:54,236 --> 00:42:55,502 +And so there are rules for that. +所以有相应的一些规则去处理 + +1010 +00:42:56,604 --> 00:42:58,637 +I'll talk about that just briefly in just a second, but +我简要地介绍一下 + +1011 +00:42:58,639 --> 00:43:00,139 +it will fill. +它会去填充的 + +1012 +00:43:00,140 --> 00:43:01,640 +But there are other things, if you don't close a path then +但是对于别的操作,如果你没有闭合 path + +1013 +00:43:01,642 --> 00:43:04,042 +you can't do things like hit detection, right? +那么你没法做类似碰撞检测等操作,对吗? + +1014 +00:43:04,044 --> 00:43:05,410 +Detecting whether a point is inside it +检测一个点是不是在它里面 + +1015 +00:43:05,412 --> 00:43:07,345 +because it's not closed, so there's no inside. +因为没有闭合,所以它没有内部 + +1016 +00:43:10,049 --> 00:43:13,083 +So you can, UIBezierPath also has kind of +所以你能,UIBezierPath 有各种 + +1017 +00:43:13,085 --> 00:43:17,653 +pre-canned cool shapes like roundedRect, okay, +预制的漂亮图形,比如 roundedRect + +1018 +00:43:17,655 --> 00:43:20,489 +which is a rectangle that the corners are rounded off of, or +它是四个角被磨圆了的矩形 + +1019 +00:43:20,491 --> 00:43:24,960 +obviously ovals and circles, it has ways of doing that. +或者干脆是椭圆跟圆形,它有处理这些的方法 + +1020 +00:43:24,962 --> 00:43:28,830 +You can also clip to any arbitrary path. +你也可以剪切任意的 path + +1021 +00:43:28,832 --> 00:43:30,543 +So clipping, +所以对于剪切 + +1022 +00:43:30,544 --> 00:43:32,255 +hopefully everyone knows what that means. +希望每个人都明白它的意义 + +1023 +00:43:32,256 --> 00:43:33,967 +That means, if I set it up, if I have a path, and I say clip. +它意味着如果我设置好了,我有一个 path,我要剪切 + +1024 +00:43:33,970 --> 00:43:37,404 +If I say, addClip, then all drawing I do after that +如果我说,addClip,那么在这之后所有的绘图操作 + +1025 +00:43:37,406 --> 00:43:41,941 +will only show up if it's inside that path, okay? +只会影响到 path 里面的部分,okay? + +1026 +00:43:43,178 --> 00:43:44,677 +So, for example, +举个例子 + +1027 +00:43:44,678 --> 00:43:46,177 +if you were drawing playing card on screen, +如果你正在屏幕上绘制纸牌 + +1028 +00:43:46,180 --> 00:43:49,114 +playing cards have little rounded rects, so you might +纸牌有小小的圆角效果,所以你可以 + +1029 +00:43:49,116 --> 00:43:52,484 +draw your playing card in a big rectangle, and then clip +把纸牌画在一个大的矩形里面,然后剪切到 + +1030 +00:43:52,486 --> 00:43:56,988 +to a rounded rect, so that the corners get cut off, okay. +一个圆角矩阵里,这样四角就修圆了 + +1031 +00:43:56,990 --> 00:43:59,990 +That's a cheap simple way to get a rounded rect playing card. +这是一个获得圆角纸牌便宜而又简单的方法 + +1032 +00:44:01,260 --> 00:44:04,127 +You can also do hit detection as I mentioned, the hit +你也可以做我提到的碰撞检测,碰撞检测 + +1033 +00:44:04,129 --> 00:44:07,430 +detection and the filling depends on the winding rules, +和填充取决于绕圈规则 + +1034 +00:44:07,432 --> 00:44:10,866 +and there's this usesEvenOddFillRule, property, +这里有 usesEvenOddFillRule 属性 + +1035 +00:44:10,868 --> 00:44:14,837 +which is only yes or no to say which winding rule it uses. +bool 类型,指定了它使用的绕圈规则 + +1036 +00:44:14,839 --> 00:44:16,605 +And so people who don't know what that means, +所以不了解它含义的同学们 + +1037 +00:44:16,607 --> 00:44:17,605 +don't worry about it. +不用担心 + +1038 +00:44:17,607 --> 00:44:19,207 +In fact, don't worry about hit detection or +实际上,不用担心碰撞检测 + +1039 +00:44:19,209 --> 00:44:20,764 +any of this stuff, +或者类似的 API + +1040 +00:44:20,765 --> 00:44:22,320 +cuz you're not going to have to do this for your homework. +因为你们的课外作业里不用做这些 + +1041 +00:44:22,321 --> 00:44:23,876 +But I just want you to know that BezierPath has a lot of +不过我希望你们能了解 BezierPath 拥有许多 + +1042 +00:44:23,880 --> 00:44:25,946 +other stuff besides just line to, line to, +其他东西,不仅仅是画线条 + +1043 +00:44:25,948 --> 00:44:26,680 +fill and stroke. +填充和描边 + +1044 +00:44:26,682 --> 00:44:28,615 +Okay, it has other stuff. +Okay,它有别的东西 + +1045 +00:44:28,616 --> 00:44:30,549 +And when you want to look at UIBezierPath, +当你想要查看 UIBezierPath + +1046 +00:44:30,552 --> 00:44:32,618 +check out its documentation and +可以打开相关文档 + +1047 +00:44:32,620 --> 00:44:34,553 +kind of experience it in its full glory. +经历它的各种荣耀 + +1048 +00:44:36,057 --> 00:44:39,491 +Okay, let's talk a little bit more about colors because I +Okay,我们再聊一聊颜色 + +1049 +00:44:39,493 --> 00:44:41,626 +used a color there, that green color. +因为我在那里用了一种绿色 + +1050 +00:44:41,628 --> 00:44:43,227 +UIColor is just an object. +UIColor 是一个对象 + +1051 +00:44:43,229 --> 00:44:45,262 +It's really powerful. +它非常强大 + +1052 +00:44:45,264 --> 00:44:46,497 +Colors not only can be +它不仅仅是 + +1053 +00:44:46,499 --> 00:44:49,433 +standard colors like UIColor.greenColor, but +类似 UIColor.greenColor 的标准颜色 + +1054 +00:44:49,435 --> 00:44:52,736 +you can create a color from RGB, red, green, blue, or +你也可以用 RGB,红绿蓝,或者 + +1055 +00:44:52,738 --> 00:44:55,838 +HSB, that's hue, saturation, and brightness. +HSB,色调,饱和度,亮度来创建颜色 + +1056 +00:44:55,840 --> 00:44:59,208 +You can even set your color to be a pattern, so that when you +你甚至可以把你的颜色设置为一个模式,这样当你 + +1057 +00:44:59,210 --> 00:45:02,311 +draw with that color, it actually draws some image. +用那种颜色绘制时,它实际上画出的是图像 + +1058 +00:45:02,313 --> 00:45:02,911 +Okay? + +1059 +00:45:02,913 --> 00:45:05,347 +So that's kinda cool. +这个相当酷 + +1060 +00:45:05,349 --> 00:45:10,017 +Views have a backgroundColor, which you can set on them. +你可以给 view 设置 backgroundColor + +1061 +00:45:10,019 --> 00:45:13,353 +Also colors can be transparent. +颜色也可以是透明的 + +1062 +00:45:13,355 --> 00:45:14,988 +Okay? + +1063 +00:45:14,989 --> 00:45:16,622 +They can be see-through, partially see-through. +他们可以是透明的,半透明的 + +1064 +00:45:16,625 --> 00:45:18,191 +This is called alpha. +这叫做 alpha(透明度) + +1065 +00:45:18,193 --> 00:45:21,027 +So alpha is a value between zero and one. +alpha 是一个介于 0 和 1 之间的值 + +1066 +00:45:21,029 --> 00:45:22,461 +Zero means fully transparent, so +0 代表完全透明 + +1067 +00:45:22,463 --> 00:45:24,096 +you can see completely through it, and +你的视线可以完全穿过去 + +1068 +00:45:24,098 --> 00:45:25,663 +it won't even show up on the screen. +它甚至不会出现在屏幕上 + +1069 +00:45:25,665 --> 00:45:27,598 +To one, which is fully opaque. +1 代表完全不透明 + +1070 +00:45:27,600 --> 00:45:29,400 +It obscures anything behind it. +它遮挡了背后的所有东西 + +1071 +00:45:29,402 --> 00:45:30,868 +Anything drawn with this color. +用这种颜色绘制的任何东西 + +1072 +00:45:30,870 --> 00:45:32,903 +And you can create a transparent color from +并且你可以通过 colorWithAlphaComponent() 方法来 + +1073 +00:45:32,905 --> 00:45:35,472 +another color with this color with alpha component. +生成某种颜色的透明色 + +1074 +00:45:35,474 --> 00:45:37,840 +This would create kind of half transparent yellow. +这里创建了一种半透明的黄色 + +1075 +00:45:37,842 --> 00:45:40,943 +Color to draw with, and you can draw in your view with +用于绘制,你可以用这些透明颜色 + +1076 +00:45:40,945 --> 00:45:43,045 +these transparent colors, okay? +来绘制你的 view,okay? + +1077 +00:45:43,047 --> 00:45:45,247 +Using these BezierPaths. +使用 BezierPaths + +1078 +00:45:45,249 --> 00:45:48,750 +However, if you draw in your view with transparency, +然而,如果你要用透明度来绘制 + +1079 +00:45:48,752 --> 00:45:51,519 +you must tell the system that you are going to do that. +你必须告诉系统你要这么做 + +1080 +00:45:51,521 --> 00:45:54,221 +And you do that by setting this property on +实现这个,你需要设置 + +1081 +00:45:54,223 --> 00:45:56,623 +your UIView called opaque to false. +UIView 的 opaque 属性为 false + +1082 +00:45:56,625 --> 00:45:58,091 +And why is this required? +为什么需要这么做? + +1083 +00:45:58,093 --> 00:46:00,727 +Well, because drawing with transparency is expensive. +因为带透明度的绘制是非常昂贵的 + +1084 +00:46:00,729 --> 00:46:01,961 +Because the views behind you +因为你后面的 view + +1085 +00:46:01,963 --> 00:46:03,829 +are gonna start showing through. +会被展示出来 + +1086 +00:46:03,831 --> 00:46:05,197 +Okay? So the system has to +Okay?所以系统必须 + +1087 +00:46:05,199 --> 00:46:08,734 +blend basically the different views that are overlapping. +把重叠的 view 混合起来绘制 + +1088 +00:46:08,736 --> 00:46:12,237 +That's expensive in terms of graphics power. +这在图像处理能力上非常昂贵 + +1089 +00:46:12,239 --> 00:46:14,772 +And so it doesn't wanna do that if it doesn't have to. +所以如无必要别这么干 + +1090 +00:46:14,774 --> 00:46:16,374 +If it can just draw the bit. +假设它在绘制某个点 + +1091 +00:46:16,376 --> 00:46:17,875 +If you don't set this to false and +如果你没有把这个设置为 false + +1092 +00:46:17,877 --> 00:46:20,410 +you try drawing transparently, it's not gonna work. +并且你还要画成透明的,那不会成功的 + +1093 +00:46:20,412 --> 00:46:22,479 +Okay? + +1094 +00:46:22,480 --> 00:46:24,547 +Cuz it's not gonna blend with the things behind. +因为它不会把后面的东西混合进来 + +1095 +00:46:24,549 --> 00:46:28,918 +You can make your entire view transparent. +你可以把整个 view 设置成透明的 + +1096 +00:46:28,920 --> 00:46:29,985 +Okay? + +1097 +00:46:29,987 --> 00:46:31,386 +It has its own property alpha, +它有自己的 alpha 属性 + +1098 +00:46:31,388 --> 00:46:33,722 +which you can set to anywhere between zero and one. +你可以设置 0 到 1 之间的任意值 + +1099 +00:46:33,724 --> 00:46:34,906 +It'll make your view, +它会使你的 view + +1100 +00:46:34,907 --> 00:46:36,089 +everything you draw in the view will be +你在 view 上绘制的所有东西 + +1101 +00:46:37,193 --> 00:46:39,460 +however much transparent you want it to be. +带上你想要的任意透明度 + +1102 +00:46:39,462 --> 00:46:41,194 +Okay? + +1103 +00:46:41,196 --> 00:46:45,331 +What happens when views overlap and have transparency? +当带有透明度的 view 互相重叠时会发生什么? + +1104 +00:46:45,333 --> 00:46:46,832 +They're blended as I said, +它们会像我说的那样混合 + +1105 +00:46:46,834 --> 00:46:49,268 +remember that the subview's order matters. +记住 subview 的顺序有影响 + +1106 +00:46:49,270 --> 00:46:51,636 +Okay? The thing that is first in +Okay?subview array 里的第一个 + +1107 +00:46:51,638 --> 00:46:54,439 +the subviews array is in the back. +出现在最后面 + +1108 +00:46:54,441 --> 00:46:56,808 +And everything down the array is in front. +array 里剩下的 view 按照顺序出现在前面 + +1109 +00:46:56,810 --> 00:46:59,276 +So, when the transparency happens, +所以,当透明度产生时 + +1110 +00:46:59,278 --> 00:47:01,979 +that's the order it's gonna happen in. +这就是将要发生的顺序 + +1111 +00:47:01,981 --> 00:47:05,315 +You can completely hide a view by sending it hidden equal to +你可以完全隐藏一个 view,只要把它的 hidden 设置为 + +1112 +00:47:05,317 --> 00:47:08,718 +true, and this is surprisingly common to just hide a view, +true,这种隐藏一个 view 的做法非常普遍 + +1113 +00:47:08,720 --> 00:47:11,854 +and maybe it appears when a certain condition is true on +当某个条件成立它可以出现在屏幕上 + +1114 +00:47:11,856 --> 00:47:14,490 +screen, or whatever you can set up this view in +或者在你的 StoryBoard 里创建这个 view + +1115 +00:47:14,492 --> 00:47:17,526 +your StoryBoard and then set it to hidden, to true. +然后把 hidden 设置为 true + +1116 +00:47:17,528 --> 00:47:19,161 +And so it comes up, it's not there. +所以它出来的时候,你看不到 + +1117 +00:47:19,163 --> 00:47:22,230 +And then in code you say hidden equals false, boom, +然后你在代码中设置 hidden 为 false,轰隆 + +1118 +00:47:22,232 --> 00:47:23,431 +it appears, okay? +出现了,okay? + +1119 +00:47:23,433 --> 00:47:25,466 +So that's a way to, completely hide the view. +所以这是个彻底隐藏 view 的方法 + +1120 +00:47:25,468 --> 00:47:26,900 +A hidden view not only doesn't draw, +隐藏的 view 不仅不会被绘制 + +1121 +00:47:26,902 --> 00:47:28,635 +it doesn't receive any touch events either. +也不会接受任何触控事件 + +1122 +00:47:28,637 --> 00:47:30,103 +But it's still in the view hierarchy. +不过它依旧存在于 view 的层级关系中 + +1123 +00:47:30,105 --> 00:47:31,304 +It's kinda there waiting. +有点像在那等待 + +1124 +00:47:31,306 --> 00:47:33,139 +Okay? + +1125 +00:47:33,141 --> 00:47:34,807 +All right, drawing text. +好的,绘制文本 + +1126 +00:47:34,809 --> 00:47:37,476 +So, usually you draw text on screen with a UILabel. +通常你们用 UILabel 在屏幕上绘制文本 + +1127 +00:47:37,478 --> 00:47:40,211 +That's what you did with your display, et cetera. +这就是你用你的显示做的事,等等 + +1128 +00:47:40,213 --> 00:47:43,548 +But you might wanna draw in your drawRect and +不过你可能想要在 drawRect 上绘制 + +1129 +00:47:43,550 --> 00:47:45,916 +you do that with this class called NSAttributedString, +你用 NSAttributedString 来干这个 + +1130 +00:47:45,918 --> 00:47:47,685 +which I'm really not gonna cover. +这部分我不准备讲解 + +1131 +00:47:47,687 --> 00:47:49,503 +You wanna look at +你可以查看 + +1132 +00:47:49,504 --> 00:47:51,320 +its documentation if you wanna draw a text. +它的文档,如果你想要绘制文本 + +1133 +00:47:51,323 --> 00:47:53,890 +I'm not gonna do a demo of NSAttributedString, but +我不会给出 NSAttributedString 的演示,不过 + +1134 +00:47:53,892 --> 00:47:55,058 +I'm gonna give you some code for +我会给你们一些代码作为 + +1135 +00:47:55,060 --> 00:47:56,325 +your assignment next week, and I'm +下周的作业 + +1136 +00:47:56,327 --> 00:47:59,361 +gonna use NSAttributedString in the code I'm giving you, +我会在给你们的代码里使用 NSAttributedString + +1137 +00:47:59,363 --> 00:48:01,630 +so you'll be able to see an example of how it's used. +所以你们能看到如何使用它的例子 + +1138 +00:48:01,632 --> 00:48:03,865 +But basically NSAttributedString is +但是基本上 NSAttributedString + +1139 +00:48:03,867 --> 00:48:05,333 +a bunch of characters and +就是一串字符和 + +1140 +00:48:05,335 --> 00:48:07,668 +some attributes on those characters. +设置在这些字符上的一些 attributes(属性) + +1141 +00:48:07,670 --> 00:48:11,805 +Now attributed String has a couple of interesting things +现在 AttributedString 有一些有趣的 + +1142 +00:48:11,807 --> 00:48:12,572 +about it. +特点 + +1143 +00:48:12,574 --> 00:48:13,740 +It's easy to use. +它易于使用 + +1144 +00:48:13,742 --> 00:48:16,075 +You can just create it, pass it a String, and +你可以创建它,传入一个 String + +1145 +00:48:16,077 --> 00:48:19,044 +then say drawAtPoint, and that will draw the String with +然后调用 drawAtPoint,然后 String 就画出来了 + +1146 +00:48:19,046 --> 00:48:21,580 +its point, its upper left corner at that point. +参数指定了它的左上角位置 + +1147 +00:48:21,582 --> 00:48:24,215 +And you can even find out how big it's gonna be by asking it +你可以查看它将要占用的大小 + +1148 +00:48:24,217 --> 00:48:25,850 +the size of this attribute String. +调用 size 就行 + +1149 +00:48:25,852 --> 00:48:28,285 +So it's pretty easy to use in that way. +这么做非常容易 + +1150 +00:48:28,287 --> 00:48:30,688 +Mutability is not done with var and +var 跟 let 无法为 NSAttributedString + +1151 +00:48:30,690 --> 00:48:32,756 +let for NSAttributedString. +带来可变性 + +1152 +00:48:32,758 --> 00:48:33,656 +There's a different class +有另一种 class + +1153 +00:48:33,658 --> 00:48:36,325 +called NSMutableAttributedString. +叫做 NSMutableAttributedString + +1154 +00:48:36,327 --> 00:48:37,827 +Okay? And why would you +Okay?为什么你们 + +1155 +00:48:37,829 --> 00:48:40,262 +want a MutableAttributedString? +想要一个 MutableAttributedString 呢? + +1156 +00:48:40,264 --> 00:48:41,830 +Well because these Strings, +因为这些 String + +1157 +00:48:41,832 --> 00:48:44,265 +what makes an AttributedString attributed, +AttributedString 之所以是 AttributedString + +1158 +00:48:44,267 --> 00:48:47,502 +is you can put attributes on the characters in this String. +是因为你可以在 String 的字符上面设置 attributes + +1159 +00:48:47,504 --> 00:48:49,770 +And so a MutableAttributedString, +所以对于 MutableAttributedString + +1160 +00:48:49,772 --> 00:48:51,538 +you can set the attributes. +你可以设置 attributes + +1161 +00:48:51,540 --> 00:48:54,007 +You can get the String out as an NSString, +你可以把里面的文本导出为 NSString + +1162 +00:48:54,009 --> 00:48:57,210 +using the string property on NSAttributedString but +用 NSAttributedString 的 string 属性 + +1163 +00:48:57,212 --> 00:48:59,946 +NSAttributedString itself is not a String. +但是 NSAttributedString 本身不是 String + +1164 +00:48:59,948 --> 00:49:02,048 +It's not like a subclass of NSString or anything. +它不是 NSString 的子类或者别的 + +1165 +00:49:02,050 --> 00:49:03,349 +It's its own thing. +它属于它自己 + +1166 +00:49:03,351 --> 00:49:05,434 +So you set +所以你们 + +1167 +00:49:05,435 --> 00:49:07,518 +these attributes with functions like setAttributes. +用 setAttributes 等函数设置 attributes + +1168 +00:49:07,521 --> 00:49:09,387 +It takes a Dictionary of attributes. +它使用一个 Dictionary 类型的 attributes + +1169 +00:49:09,389 --> 00:49:11,189 +I'll talk to you about what the keys and +我稍后介绍它的各种 keys + +1170 +00:49:11,191 --> 00:49:12,590 +values are in a second. +跟 values + +1171 +00:49:12,592 --> 00:49:15,143 +And then a range. +还有 range(范围) + +1172 +00:49:15,144 --> 00:49:17,695 +That's an NSRange right there by the way, not a Swift Range. +注意是 NSRange,不是 Swift Range + +1173 +00:49:17,697 --> 00:49:20,497 +And the indexing into these Strings is +这些 Strings 的索引 + +1174 +00:49:20,499 --> 00:49:22,966 +the old style NSString version. +是 NSString 版的古老风格 + +1175 +00:49:22,968 --> 00:49:24,967 +It's not the string.index stuff we +它不是 string.index 这样 + +1176 +00:49:24,969 --> 00:49:26,335 +talked about last time. +上次我们讲过了 + +1177 +00:49:26,337 --> 00:49:29,471 +It's literally which Unicode character are you +字面上的意思是在哪个你关注的 + +1178 +00:49:29,473 --> 00:49:32,107 +talking about setting an attribute at? +的 Unicode 文字上面设置一个 attribute? + +1179 +00:49:32,109 --> 00:49:33,792 +Okay? + +1180 +00:49:33,793 --> 00:49:35,476 +So, this Dictionary has a bunch of attributes. +所以这个 Dictionary 有一串 attributes + +1181 +00:49:35,479 --> 00:49:37,178 +The attributes can be things like, +attributes 可以是类似 + +1182 +00:49:37,180 --> 00:49:39,280 +set the foreground color of this text. +设置文本的前景色 + +1183 +00:49:39,282 --> 00:49:39,947 +Okay? + +1184 +00:49:39,949 --> 00:49:41,648 +Set the stroke width. +可以是设置描边的宽度 + +1185 +00:49:41,650 --> 00:49:43,283 +Okay? Because remember, +Okay?记住 + +1186 +00:49:43,285 --> 00:49:44,484 +text is just paths. +文本就是一些 paths + +1187 +00:49:44,486 --> 00:49:47,153 +You can stroke them and set the width or the font, +你可以对它们描边,而且可以指定宽度或者字体 + +1188 +00:49:47,155 --> 00:49:49,421 +is a really important one to be able to say. +这是值得一提的重要能力 + +1189 +00:49:49,423 --> 00:49:52,991 +Set this text to have this particular font, okay? +(attributes 可以是)对文本使用特定字体,okay? + +1190 +00:49:52,993 --> 00:49:55,827 +And so you just set a Dictionary that has +这样你只要设置一个 + +1191 +00:49:55,829 --> 00:49:59,964 +the key NSFontAttribute and the value would be a UIFont. +key 为 NSFontAttribute,value 为 UIFont 的一个 Dictionary + +1192 +00:49:59,966 --> 00:50:01,799 +Okay? + +1193 +00:50:01,800 --> 00:50:03,633 +Now let's talk about UIFonts, briefly. +现在我们简要讨论一下 UIFonts + +1194 +00:50:03,636 --> 00:50:07,270 +Fonts in iOS 7 and later, including iOS 8, +Fonts 从 iOS 7 开始,包括 iOS 8 + +1195 +00:50:07,272 --> 00:50:09,439 +are very important to get right, okay? +正确使用非常重要,okay? + +1196 +00:50:09,441 --> 00:50:10,640 +Look at these screenshots. +请看这些截图 + +1197 +00:50:10,642 --> 00:50:12,908 +Look how important the fonts are. +看下这些字体有多么重要 + +1198 +00:50:12,910 --> 00:50:14,743 +Okay? They're critical, +Okay?它们是 + +1199 +00:50:14,745 --> 00:50:16,745 +to making the UI look good. +创建漂亮 UI 的关键 + +1200 +00:50:16,747 --> 00:50:18,497 +Okay? + +1201 +00:50:18,498 --> 00:50:20,248 +So, you've got to get the right fonts in your app. +所以你需要让你的 app 拥有一个合适的字体 + +1202 +00:50:20,250 --> 00:50:22,350 +And where do you get the right fonts? +那么怎么能够使字体合适呢? + +1203 +00:50:22,352 --> 00:50:24,752 +Well, the number one place to get a font, +使这个字体合适的, + +1204 +00:50:24,754 --> 00:50:28,489 +the right place 99% of the time, is this class function +百分之九十九都能使你的字体好看的,是这个在 UIFont 这个类 + +1205 +00:50:28,491 --> 00:50:32,826 +in UIFont called preferredFontForTextStyle, okay? +里面的一个类函数,叫 preferredFontForTextStyle + +1206 +00:50:32,828 --> 00:50:36,696 +The text style is something like headline, or +字体样式是类似标题,或者 + +1207 +00:50:36,698 --> 00:50:38,548 +a body, okay? +正文这些东西 + +1208 +00:50:38,549 --> 00:50:40,399 +The body would be like the main content that your user is +正文就是你展现给用户看的主要的 + +1209 +00:50:40,401 --> 00:50:42,051 +looking at. +内容 + +1210 +00:50:42,052 --> 00:50:43,702 +Headline might be like a title at the top. +标题一般就是顶部的这个标题 + +1211 +00:50:43,704 --> 00:50:46,171 +Footnote might be a small little thing mentioned at +注脚是在底部的一行小小的字, + +1212 +00:50:46,173 --> 00:50:47,923 +the bottom, okay? +好吧? + +1213 +00:50:47,924 --> 00:50:49,674 +And there's a whole bunch more of these text styles. +这里还有很多很多这种字体样式 + +1214 +00:50:49,676 --> 00:50:51,559 +And so, you're gonna ask +那么你可能会问, + +1215 +00:50:51,560 --> 00:50:53,443 +the assistant give me the preferred font for that style. +这个字体助手给我了一个对应这种样式的推荐的字体 + +1216 +00:50:53,446 --> 00:50:57,664 +The font includes a size. Okay? +这个字体包含了字体大小 + +1218 +00:50:57,665 --> 00:50:59,815 +UIFont include the size, as well as the face. +UIFont 包括了其大小以及它的样子 + +1219 +00:50:59,818 --> 00:51:02,852 +And users can go into their settings on their phone and +用户可能会去设置里面改变了一些字体相关的设置, + +1220 +00:51:02,854 --> 00:51:05,321 +change and say I can't see it anymore. +比如老花眼了看不清楚那些字 + +1221 +00:51:05,323 --> 00:51:06,706 +Kinda like me. +像我一样 + +1222 +00:51:06,707 --> 00:51:08,657 +And they make their fonts bigger. Okay? +那么他们设置大一点的字体 + +1224 +00:51:08,659 --> 00:51:09,491 +And so this would +那这个推荐字体将会 + +1225 +00:51:09,493 --> 00:51:12,027 +automatically get that new size. +自动地获取到新的字体大小 + +1226 +00:51:12,029 --> 00:51:13,261 +Okay? So that's why you +所以你 + +1227 +00:51:13,263 --> 00:51:15,162 +always wanna use preferred font any +用这个推荐的字体总是好的, + +1228 +00:51:15,164 --> 00:51:17,931 +time you're displaying any user content, okay? +在任何时候都是,尤其是你要展示给用户看的时候 + +1229 +00:51:17,933 --> 00:51:20,767 +Now, it is possible to create fonts where you say, +你当然可以自己创建一个字体, + +1230 +00:51:20,769 --> 00:51:22,702 +give me Arial 15 narrow or what. +比如说,给我一个 15 号大小的窄体 Arial 字体 + +1231 +00:51:22,704 --> 00:51:25,071 +It is possible, but you really shouldn't be doing that. +你可以这么做,但是你不该这么做 + +1232 +00:51:25,073 --> 00:51:27,006 +You should be using this preferred font for style. +你还是乖乖地用推荐的字体 + +1233 +00:51:27,008 --> 00:51:28,941 +There's also a system font. +这里也有系统默认字体 + +1234 +00:51:28,943 --> 00:51:31,376 +This is something that appears on buttons and +比如出现在按钮上的,或者 + +1235 +00:51:31,378 --> 00:51:35,113 +in things like Segmented Controls, things like that. +出现在 Segmented Control (UI控件的一种)上的 + +1236 +00:51:35,115 --> 00:51:39,316 +You never wanna use only the system fonts for user content. +你永远不会只想用系统设置的是吧? + +1237 +00:51:39,318 --> 00:51:42,719 +User content you wanna use the preferred fonts. Okay? +你更希望用推荐的字体来显示你的内容给用户看 + +1239 +00:51:44,155 --> 00:51:45,821 +So yeah, other ways to get fonts, ignore them. +啊这里是些其他获得字体的方法,忽略它们 + +1240 +00:51:45,823 --> 00:51:48,090 +I'm not gonna talk about it, okay? +在这里我不会讲它 + +1241 +00:51:48,092 --> 00:51:50,425 +All right, how about drawing images? +好的,那么怎么显示图像呢? + +1242 +00:51:50,427 --> 00:51:52,227 +How do you do that? +你会怎么做? + +1243 +00:51:52,228 --> 00:51:54,028 +Well there is a UILabel for +我们有个专门负责图像的 "UILabel" + +1244 +00:51:54,031 --> 00:51:56,264 +images, it's called UIImageView. +叫 UIImageView + +1245 +00:51:56,266 --> 00:51:58,065 +And you can use that to put an image on screen, but +你可以用这个类把图像显示到屏幕上,但是呢, + +1246 +00:51:58,067 --> 00:52:01,368 +you might wanna draw an image, in your drawRect as well. +你可能希望把这个图像丢到你的 drawRect 里面 + +1247 +00:52:01,370 --> 00:52:04,338 +And usually you create an image by name, from that +一般来说你会以名字来创建这个图像, + +1248 +00:52:04,340 --> 00:52:07,674 +Images.xcassets thing that we moved out of the way real +从 Images.xcassets 里面拿出来, + +1249 +00:52:07,676 --> 00:52:10,076 +quick right at the beginning of our very first demo. +一会第一个演示一开始就会给大家瞅瞅 + +1250 +00:52:10,078 --> 00:52:12,345 +And if you click on that, it's pretty self-explanatory. +如果你点击它,故名思议 + +1251 +00:52:12,347 --> 00:52:13,679 +You can drag images. +你可以拖动图像 + +1252 +00:52:13,681 --> 00:52:16,081 +You can have different images of different resolutions for +你可以根据不同的分辨率,不同的设备, + +1253 +00:52:16,083 --> 00:52:17,149 +different devices. +设置不同尺寸的图像 + +1254 +00:52:17,150 --> 00:52:18,216 +It's really pretty powerful. +总之就是很强大 + +1255 +00:52:18,218 --> 00:52:20,200 +That's usually how you create an image. +这就是一般创建图像的步骤 + +1256 +00:52:20,201 --> 00:52:23,120 +By name and dragging into the Images.xcassets. +通过图像的名字,拖进 Images.xcassets 里面 + +1257 +00:52:23,122 --> 00:52:25,389 +You can create it in other ways from the file system, +你也可以用其他方法从系统文件中创建出来, + +1258 +00:52:25,391 --> 00:52:27,991 +which we haven't talked about, or even with drawing, but +我们还没讲到这些,包括怎么画图像, + +1259 +00:52:27,993 --> 00:52:29,826 +we're not gonna talk about that either. +我们也不会讲这些 + +1260 +00:52:29,828 --> 00:52:33,429 +Once you have the UIImage, you can draw it by just sending it +当你有了这个 UIImage,你可以发送一个消息去显示它, + +1261 +00:52:33,431 --> 00:52:35,231 +the message, drawAtPoint. +这个函数是 drawAtPoint + +1262 +00:52:35,233 --> 00:52:38,133 +And it will draw in its normal size with that point as +然后这个函数就会把正常尺寸的的图像在左上角的那个点上 + +1263 +00:52:38,135 --> 00:52:39,634 +it's upper left. +显示出来 + +1264 +00:52:39,636 --> 00:52:41,403 +You can also say drawInRect, and +你也可以用 drawInRect 这个函数, + +1265 +00:52:41,405 --> 00:52:44,605 +it'll scale to fit that rect, either bigger or smaller, or +它会缩放图像让其适应这个长方形区域,可以放大或者缩小,或者 + +1266 +00:52:44,607 --> 00:52:47,608 +you can draw a pattern in rect it'll tile it repeatedly to +你可以在这个长方形区域里面画一个图案,它会不断地重复平铺, + +1267 +00:52:47,610 --> 00:52:50,044 +fill the rect. Okay? +铺满整个长方形区域 + +1269 +00:52:50,045 --> 00:52:51,645 +So really easy to draw images inside your drawRect. +在你的 drawRect 里面显示图像真的是很简单 + +1270 +00:52:51,647 --> 00:52:54,547 +And the last thing I wanna talk about is, +那么关于这个我想补充的是, + +1271 +00:52:54,549 --> 00:52:58,484 +what happens when your bounds changes in your UIView? +如果你的 UIView 的边框变了咋办? + +1272 +00:52:58,486 --> 00:53:00,719 +Like the, the user rotates the phone. +比如说用户旋转了他的手机 + +1273 +00:53:00,721 --> 00:53:02,721 +Now your bounds are wide and +现在你的边框变得胖矮胖矮的, + +1274 +00:53:02,723 --> 00:53:06,257 +not very tall, instead of tall and not so wide. +不是以前那样高瘦高瘦的 + +1275 +00:53:07,427 --> 00:53:09,210 +You might think, +你也许会想, + +1276 +00:53:09,211 --> 00:53:10,994 +oh my drawRect's gonna get called, and I'm gonna redraw. +噢我需要再调用一次 drawRect,然后就会重新适应 + +1277 +00:53:10,996 --> 00:53:12,529 +But no, that does not happen. +但这是不可能的 + +1278 +00:53:12,531 --> 00:53:16,666 +Instead, the bits that were on screen get stretched. +相反,在屏幕中的图像会被拉扁 + +1280 +00:53:16,668 --> 00:53:20,035 +Okay? So, usually that's not what you want. +所以一般来说得不到你想要的效果 + +1281 +00:53:20,038 --> 00:53:22,772 +You can and +你将会 + +1282 +00:53:22,773 --> 00:53:25,507 +result in a very grainy, kind of bit stretching of your UI. +使其变成马赛克那样,有点强行拉大了图像 + +1283 +00:53:25,509 --> 00:53:27,426 +But that is the default, +但这是默认设置 + +1284 +00:53:27,427 --> 00:53:29,344 +is the bit stretching because it's higher performance. +默认就会将图像拉伸,因为其有更好的性能 + +1285 +00:53:29,346 --> 00:53:32,914 +Now, you control though, you can control what happens to +其实呢,当边界改变了,你可以控制 + +1286 +00:53:32,916 --> 00:53:35,049 +your view when the bounds change, +你的 view 的变化, + +1287 +00:53:35,051 --> 00:53:38,052 +with this property in view called contentMode. +用 view 中的一个叫 contentMode 的属性就能做到 + +1288 +00:53:38,054 --> 00:53:40,821 +And here are some of the contentModes you can set. +这里有些你可以修改的 contentMode, + +1289 +00:53:40,823 --> 00:53:43,323 +There's left, right, top, bottom, et cetera. +这里有上下左右等等 + +1290 +00:53:43,325 --> 00:53:46,592 +All these ones basically don't change the bits. +这里的这些修改基本上不会像刚才那样的改变 + +1291 +00:53:46,594 --> 00:53:48,461 +They don't re-draw, but +它们不会重新显示图片,但是 + +1292 +00:53:48,462 --> 00:53:50,329 +they just move your entire view to the left edge, +它们只是让你的 view 整体移动到新的边界的左边,右边, + +1293 +00:53:50,331 --> 00:53:53,432 +right edge, top, or bottom of the new bounds. +上边或者下边 + +1294 +00:53:53,434 --> 00:53:54,933 +These are kinda strange ones. +这是些奇怪的属性, + +1295 +00:53:54,935 --> 00:53:56,801 +You probably don't need that very often. +一般来说你应该不会用到 + +1296 +00:53:56,803 --> 00:53:58,169 +Then there's the scaling of the bits. +这里是些缩放, + +1297 +00:53:58,171 --> 00:54:00,604 +So here's the default, ScaleToFill. +默认的是 ScaleToFill + +1298 +00:54:00,606 --> 00:54:02,840 +'Kay, we'll scale the bits to fill the new bounds, but +我们会缩放图像去填满新的边界,但是 + +1299 +00:54:02,842 --> 00:54:05,842 +you can also fill or fit the bounds and +你仍可以填满或者适应边界, + +1300 +00:54:05,844 --> 00:54:07,210 +keep it aspect ratio. +而且保存图像原来的长宽比例 + +1301 +00:54:07,212 --> 00:54:09,012 +So that won't stretch your bits. +这些就不会再拉伸你的图像了 + +1302 +00:54:09,014 --> 00:54:10,413 +It'll still scale them, but +它们可以缩放,但是 + +1303 +00:54:10,415 --> 00:54:13,582 +it'll scale them with your aspect ratio maintained, or +是以原来的长宽比例来缩放的,或者 + +1304 +00:54:13,584 --> 00:54:17,219 +you can have the wonderest Redraw, 'kay? +你也可以用你最想用的 redraw + +1305 +00:54:17,221 --> 00:54:19,421 +This is the one you wanna set that says, +你心想:我设成这样, + +1306 +00:54:19,423 --> 00:54:22,690 +when my bounds change, call my drawRect again. +当我的边界发生了变化,再次调用我的 drawRect 函数 + +1308 +00:54:22,692 --> 00:54:25,392 +Okay? With the new bounds. +有了新的边界 + +1309 +00:54:25,394 --> 00:54:26,793 +So you're gonna want that quite often. +你将会常常需要用到它 + +1310 +00:54:26,795 --> 00:54:29,129 +I'll show you that in the demo today. +我会在今天的展示中做给你们看 + +1311 +00:54:29,131 --> 00:54:30,630 +All right, so let's get right to this demo. +好的,那我们开始展示吧 + +1312 +00:54:31,699 --> 00:54:34,767 +Today, it's gonna be a little tight to do this in 20 minutes +今天这个展示的时间有点紧,因为还剩20分钟了, + +1313 +00:54:34,769 --> 00:54:37,002 +but, cuz we're gonna cover a lot of stuff but +因为我们今天讲了好多东西,但是 + +1314 +00:54:37,004 --> 00:54:38,036 +I think we can do it. +我觉得我们应该够时间的 + +1315 +00:54:38,038 --> 00:54:42,273 +We're going to start by creating a new project. +我们开始创建一个新的项目 + +1316 +00:54:42,275 --> 00:54:43,841 +So I'm just going to file a new project, +点击 file -> new -> project, + +1317 +00:54:43,843 --> 00:54:44,775 +this is brand new. +全新的一个项目 + +1318 +00:54:44,776 --> 00:54:45,708 +Okay? We're going away from +我们将暂时把我们之前的 + +1319 +00:54:45,711 --> 00:54:46,676 +the Calculator here. +计算器放一边 + +1320 +00:54:46,678 --> 00:54:47,944 +And as always we're gonna be +就像之前一样我们将 + +1321 +00:54:47,946 --> 00:54:50,346 +using the single view application thing right here. +用这里的 Single View Application + +1322 +00:54:50,348 --> 00:54:52,781 +I'm gonna call this project Happiness, +我将这个项目命名为 Happiness, + +1323 +00:54:52,783 --> 00:54:55,684 +because we're gonna draw a face, a smiley face. +因为我们将会展示一个笑脸, + +1324 +00:54:55,686 --> 00:54:56,851 +Okay? And it's gonna be +它将能够 + +1325 +00:54:56,853 --> 00:54:59,654 +able to smile or frown, depending on how happy it is. +微笑或者皱眉,这取决于它有多开心 + +1327 +00:54:59,656 --> 00:55:02,489 +Okay? So that's why we're gonna call this Happiness. +所以我们命名为 Happiness + +1328 +00:55:02,492 --> 00:55:04,992 +I'm gonna put it in the same place I put my Calculator, +我把它放在我的 Calculator 项目的位置, + +1329 +00:55:04,994 --> 00:55:07,094 +which is my home directory developer there. +也就是我的 home 目录下的 developer 里面 + +1330 +00:55:07,096 --> 00:55:08,428 +Here it is. +就是这里 + +1331 +00:55:08,430 --> 00:55:12,031 +As before I'm gonna move this AppDelegate out of the way. +像之前一样我将会把这个 AppDelegate 放开一边 + +1332 +00:55:12,033 --> 00:55:14,433 +I'm gonna move, actually let's take a look at image.xcassets. +我将会移...等等我们先看看这个 image.xcassets + +1333 +00:55:14,435 --> 00:55:16,669 +So here's the appicon slots. +这里是 Appicon(应用图标)的空槽 + +1334 +00:55:16,671 --> 00:55:18,403 +You can see that for any given image, +你可以看到,对于不同的图像, + +1335 +00:55:18,405 --> 00:55:21,306 +like the appicon, there's lots of different resolutions, +像这个 Appicon,它有很多不同的分辨率 + +1336 +00:55:21,308 --> 00:55:24,876 +depending on the devices that you can provide. Okay? +取决于你提供的设备 + +1338 +00:55:24,877 --> 00:55:26,210 +You don't have to provide all the different resolutions, +你不必提供所有的分辨率, + +1339 +00:55:26,212 --> 00:55:27,945 +it will interpolate but you can do it. +它会自己添加,但你也可以都提供 + +1340 +00:55:27,947 --> 00:55:31,848 +So you just drag an image into here, and now you can get it +那么先把这个图像拖进来,然后你就能通过图片名来指定了, + +1341 +00:55:31,850 --> 00:55:34,951 +by name with that UIImage named function. +用 UIImage 那个函数 + +1342 +00:55:34,953 --> 00:55:36,169 +So we'll get that out of there. +我们还是先把它放出去 + +1343 +00:55:36,170 --> 00:55:37,386 +We don't want the launch screen either. +我们也不想要 LaunchScreen + +1344 +00:55:37,389 --> 00:55:38,955 +So here we are. +就先这样 + +1345 +00:55:38,956 --> 00:55:40,522 +I'm gonna show you something fun here too. +我将给你们展示一些有趣的东西 + +1346 +00:55:40,525 --> 00:55:43,158 +Here is my StoryBoard. +这是我的 StoryBoard + +1347 +00:55:43,160 --> 00:55:46,028 +I'm gonna show you how to add a new View Controller to +我将给你们展示一下怎么把一个新的 View Controller 添加到 + +1348 +00:55:46,030 --> 00:55:47,062 +your StoryBoard. +你的 StoryBoard 中 + +1349 +00:55:47,064 --> 00:55:48,696 +And in fact, I'm gonna delete this one. +事实上我将删除这一个 + +1350 +00:55:48,698 --> 00:55:50,064 +So, you see this one right here I've selected? +看到我选择的这个了吗? + +1351 +00:55:50,066 --> 00:55:50,964 +I'm just deleting it. +然后我删除它 + +1352 +00:55:50,966 --> 00:55:52,866 +It's gone. I'm gonna delete its +删掉了同时我也将删除它的 + +1353 +00:55:52,868 --> 00:55:54,735 +code as well. +代码 + +1354 +00:55:54,736 --> 00:55:56,603 +I'm gonna go here, and just delete, move it to the trash. +我点击这里,然后删除,将其移除到垃圾箱 + +1355 +00:55:56,605 --> 00:55:59,339 +Now I have a StoryBoard with nothing in it, and +现在我有一个啥都没有的空 StoryBoard, + +1356 +00:55:59,341 --> 00:56:01,040 +I've no View Controllers. +里面也没有 View Controllers + +1357 +00:56:01,042 --> 00:56:02,542 +Okay? + +1358 +00:56:02,543 --> 00:56:04,043 +So, how do I add a View Controller? +我怎么添加一个 View Controller? + +1359 +00:56:04,045 --> 00:56:06,144 +You go over here to your Object Pallet. +你点这个 Object Pallet(Xcode 最右下角) + +1360 +00:56:06,146 --> 00:56:08,313 +The very first thing is a View Controller. +这里的第一个就是 View Controller + +1361 +00:56:08,315 --> 00:56:09,981 +And you just drag it out, and boom. +然后你拖出来,哗的一下, + +1362 +00:56:09,983 --> 00:56:10,781 +You've got one. +你得到了一个 View Controller + +1363 +00:56:11,917 --> 00:56:13,550 +Now, the class. +现在,它的类, + +1364 +00:56:13,552 --> 00:56:15,318 +What class is this going to be though? +它的类是什么呢? + +1365 +00:56:15,320 --> 00:56:17,720 +This is gonna be Generic UIViewController, so +它是一个普通的的 UIViewController + +1366 +00:56:17,722 --> 00:56:19,121 +it's pretty useless. +所以这并没什么用 + +1367 +00:56:19,123 --> 00:56:20,823 +Okay? You can't add any outlets, or +你不能用它来添加 outlet (IBOutlet) + +1368 +00:56:20,825 --> 00:56:23,525 +have any actions because it's not a subclass of UIViewController, +也不能添加任何 action,因为它不是 UIViewController 的子类, + +1369 +00:56:23,527 --> 00:56:26,628 +so you can't put any of that implementation in. +所以你不能在里面放任何实现功能的代码 + +1370 +00:56:26,630 --> 00:56:30,564 +So, we're gonna create a new subclass of UIViewController. +因此我们需要创建一个 UIViewController 的子类 + +1371 +00:56:30,566 --> 00:56:31,665 +So let me show you how to do that. +让我来给你们展示一下 + +1372 +00:56:31,667 --> 00:56:33,834 +You say New > File. +新建一个文件, New -> File + +1373 +00:56:33,836 --> 00:56:35,869 +And last time we went to New > File, +上回我们这么做, + +1374 +00:56:35,871 --> 00:56:38,671 +we said Swift file to make the CalculatorBrain. +是新建 Swift 文件来创建 CalculatorBrain + +1375 +00:56:38,673 --> 00:56:41,574 +But now we're gonna go over here to Cocoa Touch Class, +但是现在我们选择这个 Cocoa Touch Class, + +1376 +00:56:41,576 --> 00:56:45,661 +which we do anytime we wanna create a subclass of an iOS class. +每当我们想要新建 iOS 的子类的时候,我们都会选择它 + +1378 +00:56:45,662 --> 00:56:47,212 +And here I'm creating a subclass of UIViewController. +这里我要创建一个 UIViewController 的子类, + +1379 +00:56:47,214 --> 00:56:48,346 +I need this. +那么我就需要它 + +1380 +00:56:48,348 --> 00:56:50,381 +So I'm gonna click on that. +点击一下 + +1381 +00:56:50,383 --> 00:56:52,583 +Here's where I pick what I want it to be a subclass of. +在这里我选择我想要继承的类 + +1382 +00:56:52,585 --> 00:56:53,884 +You can see there's a lot of things in here. +你可以看到这里有很多东西 + +1383 +00:56:53,886 --> 00:56:56,119 +I'm gonna say I want a View Controller. +我想要一个 View Controller + +1384 +00:56:56,121 --> 00:56:58,021 +It wants to call it ViewController by default. +它默认名字就是 ViewController + +1385 +00:56:58,023 --> 00:56:59,889 +We don't even like that for +我们甚至在我们的 Calculator 中 + +1386 +00:56:59,891 --> 00:57:02,291 +the Calculator, let alone this. +都不这样叫,更别说这个了 + +1387 +00:57:02,293 --> 00:57:06,128 +So I'm gonna call this my HappinessViewController. +我想叫它 HappinessViewController + +1389 +00:57:06,130 --> 00:57:08,997 +Okay? So it creates that. +这样就创建好了 + +1390 +00:57:08,999 --> 00:57:11,599 +Put it in the same place all my other Swift files are. +把它放在我其他的 Swift 文件那里 + +1391 +00:57:11,601 --> 00:57:12,800 +Here it is. +搞定了 + +1392 +00:57:12,802 --> 00:57:14,118 +HappinessViewController. + +1393 +00:57:14,119 --> 00:57:16,470 +Again, I'm gonna get rid of this code.Okay? +再一次,我将把这些代码删掉 + +1395 +00:57:16,472 --> 00:57:18,972 +Just to make things a little clearer. +让它看起来更简洁 + +1396 +00:57:18,974 --> 00:57:20,039 +So here's my HappinessViewController. +这个就是我的 HappinessViewController + +1397 +00:57:20,041 --> 00:57:22,675 +It's just like the View Controller you had, +就像是之前的 View Controller 一样, + +1398 +00:57:22,677 --> 00:57:26,278 +that was called ViewController in your Calculator. +我们在 Calculator 叫 ViewController + +1399 +00:57:26,280 --> 00:57:28,013 +It was called HappinessViewController. +这里呢我们叫它 HappinessViewController + +1400 +00:57:28,015 --> 00:57:29,481 +But this guy right here, +但是这里的这个家伙, + +1401 +00:57:29,483 --> 00:57:31,783 +is still playing old View Controller. +还是以前的 View Controller + +1402 +00:57:31,785 --> 00:57:32,917 +How do I know that? +我怎么能知道呢? + +1403 +00:57:32,919 --> 00:57:34,752 +Well, it's this magic right here. +神奇的东西在这里, + +1404 +00:57:34,754 --> 00:57:36,787 +You see this Identity Inspector? +你看到这个 Identity Inspector 了吗? + +1405 +00:57:36,789 --> 00:57:38,521 +Okay. You can see the class of +你可以看到被选择的东西的类, + +1406 +00:57:38,523 --> 00:57:41,791 +this selected thing here, in this UIView Controller. +在这里是 UIViewController + +1407 +00:57:41,793 --> 00:57:43,793 +And I don't want it to be UIViewController. +我不想让其是 UIViewController + +1408 +00:57:43,795 --> 00:57:46,462 +I want it to be HappinessViewController. +我想让它是 HappinessViewController + +1409 +00:57:46,464 --> 00:57:49,264 +So, very important to understand that in +明白这里很重要,在 StoryBoard 里, + +1410 +00:57:49,266 --> 00:57:52,033 +StoryBoards, everything is linked up to +所有东西都用名字和你的代码 + +1411 +00:57:52,035 --> 00:57:53,334 +your code by name. +相连接 + +1412 +00:57:53,336 --> 00:57:54,902 +Only by the name. +只用名字 + +1413 +00:57:54,904 --> 00:57:56,603 +That is the only thing that links what's in +这个是唯一连接 + +1414 +00:57:56,605 --> 00:57:57,971 +your StoryBoard with your code. +你代码和 StoryBoard 的东西 + +1415 +00:57:57,973 --> 00:58:00,674 +The names of outlets, the names of methods, +outlet 的名字,method 的名字, + +1416 +00:58:00,676 --> 00:58:01,974 +the action methods. +action 的名字 + +1417 +00:58:01,976 --> 00:58:04,610 +The name of your UIViewControllers. +你的 UIViewController 的名字, + +1418 +00:58:04,612 --> 00:58:06,412 +The name of your UIViews. +你的 UIView 的名字 + +1419 +00:58:06,414 --> 00:58:07,612 +Okay? It's all by name. +好吧?所有的都是和名字有关 + +1420 +00:58:07,614 --> 00:58:09,881 +So you have to go to the Identity Inspector here and +所以你需要到 Identity Inspector 这里,然后 + +1421 +00:58:09,883 --> 00:58:12,050 +make sure that name matches up. +保证你的名字对得上号 + +1422 +00:58:12,052 --> 00:58:13,835 +So now, you can see +现在你可以看到, + +1423 +00:58:13,836 --> 00:58:15,619 +this says that it's a HappinessViewController. +这里说它是一个 HappinessViewController + +1424 +00:58:15,621 --> 00:58:20,240 +So that's making me happy. Okay. +这让我很快乐 + +1426 +00:58:20,241 --> 00:58:22,758 +Now, we want to put our custom view in here, okay? +现在我们想把我们自定义的 View 放进去, + +1427 +00:58:22,761 --> 00:58:26,329 +So how do I add a custom view to my UI? +那我怎么把这个自定义的 View 放进去呢? + +1428 +00:58:26,331 --> 00:58:29,231 +And the answer is, I go into the Object Pallet. +答案就是,我又一次选择 Object Pallet + +1429 +00:58:29,233 --> 00:58:30,766 +It's all the way at the bottom, +一直滚下去, + +1430 +00:58:30,768 --> 00:58:32,134 +near the bottom somewhere. +知道就快到底部的时候 + +1431 +00:58:32,136 --> 00:58:32,901 +Where is that thing? +在哪里呢? + +1432 +00:58:32,903 --> 00:58:33,801 +There it is. +在这里 + +1433 +00:58:33,803 --> 00:58:35,870 +You can drag out a generic view. +你可以拖出一个普通的 View + +1434 +00:58:35,872 --> 00:58:37,705 +So this is just a UIView. +这其实是一个 UIView + +1435 +00:58:37,707 --> 00:58:39,339 +Now when I drag it out, +现在当我拖出来 + +1436 +00:58:39,341 --> 00:58:43,343 +I'm gonna put it right here with the dashed blue lines. +我将把它放在这些虚蓝线这里 + +1437 +00:58:43,345 --> 00:58:46,279 +'Kay, because we know that that's a good thing to do. +因为我们知道这么做总是好的 + +1438 +00:58:46,281 --> 00:58:50,416 +And I want to set up the AutoLayout so +我想要设置 AutoLayout,因此 + +1439 +00:58:50,418 --> 00:58:56,054 +that this view always fully fills my scene here. +这个 View 将填满我的整个画面 + +1440 +00:58:56,056 --> 00:58:58,489 +Okay? Now I could Control drag to +现在,我可以按住 Control 拖动到边缘, + +1441 +00:58:58,491 --> 00:59:02,560 +the edges like I did before, but since this is already +就像我之前做的那样,但是现在这已经 + +1442 +00:59:02,562 --> 00:59:06,630 +perfectly where I want it, and I use the blue lines, I +很完美了,所以我用这些蓝线 + +1443 +00:59:06,632 --> 00:59:12,302 +can go down here and use Reset to Suggested Constraints. 'Kay? +我可以在下面用这个 Reset to Suggested Constraints + +1445 +00:59:12,303 --> 00:59:13,602 +Now, I'm only showing you dribs and drabs of AutoLayout. +现在我只是一点点地向你们展示 AutoLayout + +1446 +00:59:13,605 --> 00:59:16,105 +I wasn't gonna talk all about Auto Layout today, but +我不会在今天讲 AutoLayout 的,但是 + +1447 +00:59:16,107 --> 00:59:17,439 +we need to move on to this. +在这里我们需要这么做 + +1448 +00:59:17,441 --> 00:59:19,941 +But I will be having the lecture on AutoLayout, +我会专门有节课讲 AutoLayout, + +1449 +00:59:19,943 --> 00:59:21,409 +probably week after next. +也许是下下周 + +1450 +00:59:21,411 --> 00:59:23,745 +In the meantime I'm just gonna show you little bits of it and +同时我会展示一点点, + +1451 +00:59:23,747 --> 00:59:25,730 +you can explore. +让你们摸索一下 + +1452 +00:59:25,731 --> 00:59:27,714 +I'm never gonna ask you to do a ton of it in your homework. +我不会让你们在作业中做很多这个, + +1453 +00:59:27,717 --> 00:59:30,084 +So this one I'm gonna Reset to Suggested Constraints, and +所以对于这个我将选 Reset to Suggested Constraints, + +1454 +00:59:30,086 --> 00:59:31,284 +it added those Constraints. +然后它就添加了这些 Constraints(约束) + +1455 +00:59:31,286 --> 00:59:32,585 +And I could go over here. +我可以点击这里 + +1456 +00:59:32,587 --> 00:59:34,187 +Let me make some more space here. +让我在这里腾出多一点空间 + +1457 +00:59:34,189 --> 00:59:35,654 +I could go look at them over here. +我可以在这里浏览到它们 + +1458 +00:59:35,656 --> 00:59:37,523 +You've all determined that. +你已经确定了这些 + +1459 +00:59:37,525 --> 00:59:40,559 +Another place you can see the Constraints of a view is +另一个能看到 View 的这些 Constraints 的地方是 + +1460 +00:59:40,561 --> 00:59:42,193 +here in the Size Inspector. +在这个 Size Inspector 这里 + +1461 +00:59:42,195 --> 00:59:44,662 +If you look towards the bottom of the Size Inspector- +如果你看 Size Inspector 的最底部, + +1462 +00:59:44,664 --> 00:59:46,163 +Look, here's all the Constraints, see? +看,这里就是全部的 Constraints,看到么 + +1463 +00:59:46,165 --> 00:59:48,165 +Trailing, leading, top, bottom. +Trailing, leading, top, bottom. + +1464 +00:59:48,167 --> 00:59:50,634 +It added all these because these are the Suggested +这里添加的全部都是刚刚添加的 + +1465 +00:59:50,636 --> 00:59:55,822 +constraints based on the dash blue lines that I used. Okay? +Suggested Constraints,基于刚刚我用的那些蓝色虚线 + +1467 +00:59:55,823 --> 00:59:57,673 +So, oftentimes if you put something in place perfectly +一般来说你把东西都放到刚刚好的位置, + +1468 +00:59:57,675 --> 00:59:58,874 +with the blue lines, +放到有蓝线的位置, + +1469 +00:59:58,876 --> 01:00:01,443 +you can use Reset to Suggested Constraints. +你就可以用 Reset to Suggested Constraints + +1470 +01:00:01,445 --> 01:00:04,979 +We coulda done that with our display in our Calculator. +我们也可以在在我们的 Calculator 中的显示结果的那个地方使用 + +1471 +01:00:04,981 --> 01:00:06,748 +We couldn't do it with the buttons. +但是我们不能用在按钮上 + +1472 +01:00:06,750 --> 01:00:09,116 +Cuz it just wasn't lined up enough with other things, but +因为它并没有和其他的物体排列起来,但是 + +1473 +01:00:09,118 --> 01:00:11,618 +we could have done it with the display. +我们可以用于显示结果的那里 + +1474 +01:00:11,620 --> 01:00:12,853 +All right? So now we have this. +好的,现在我们有了这个 + +1475 +01:00:12,855 --> 01:00:17,623 +Now, this UIView, let's look at its Identity Inspector. +这个 UIView,我们看看它的 Identity Inspector + +1476 +01:00:17,625 --> 01:00:19,258 +It's just a generic UIView. +它是个普通的 UIView + +1477 +01:00:19,260 --> 01:00:20,726 +That's no good. +这并不好 + +1478 +01:00:20,727 --> 01:00:22,193 +We need a custom UIView sub-class. +我们需要一个自定义的 UIView 子类 + +1479 +01:00:22,196 --> 01:00:23,161 +So let's go do that. +我们来实现这个 + +1480 +01:00:23,163 --> 01:00:24,996 +File > New File. +选择 File > New File + +1481 +01:00:24,998 --> 01:00:26,665 +Same thing, +一样的, + +1482 +01:00:26,666 --> 01:00:28,333 +I'm gonna create a subclass of a Cocoa Touch Class. +我将创建 Cocoa Touch Class 的子类 + +1483 +01:00:28,335 --> 01:00:30,801 +This one's not gonna be a View Controller, +这次不是一个 View Controller, + +1484 +01:00:30,803 --> 01:00:32,202 +it's gonna be a UIView. +而是一个 UIView + +1485 +01:00:32,204 --> 01:00:33,837 +Okay? I'm gonna call it FaceView, +好的,我将叫它 FaceView, + +1486 +01:00:33,839 --> 01:00:35,238 +cuz that's what it's gonna do. +因为它要做的就是, + +1487 +01:00:35,240 --> 01:00:38,041 +It's gonna draw a face, okay? +显示出一张脸 + +1488 +01:00:38,043 --> 01:00:40,776 +Put it in the same place, put everything. +将它放在同一个地方,放所有文件的地方 + +1489 +01:00:40,778 --> 01:00:42,845 +Here's our, my FaceView right here. +这里是我们的 FaceView + +1490 +01:00:42,847 --> 01:00:44,413 +We'll get back to that in a second. +我们一会再回来这里 + +1491 +01:00:44,415 --> 01:00:45,780 +In our StoryBoard, +在我们的 StoryBoard 中 + +1492 +01:00:45,782 --> 01:00:49,517 +we wanna make sure that we inspect our FaceView. +我们想确保我们能观察我们的 FaceView + +1494 +01:00:49,519 --> 01:00:51,718 +Okay? And change its class to FaceView. +然后把它的类改成 FaceView + +1495 +01:00:51,721 --> 01:00:54,087 +By the way, it can kinda get tricky sometimes, +顺带说一句,选择到一个你想要的东西, + +1496 +01:00:54,089 --> 01:00:55,655 +picking the right thing. +有时候会比较困难 + +1497 +01:00:55,657 --> 01:00:57,490 +Like, sometimes you're picking the UIViewController, +比如说有时候你想选择 UIViewController, + +1498 +01:00:57,492 --> 01:00:58,691 +sometimes you're picking the view. +但有时你会不小心选到 View + +1499 +01:00:58,693 --> 01:01:02,628 +One kinda cool trick, Control + Shift. +有个酷炫的小技巧,就是按 Control + Shift + +1500 +01:01:02,630 --> 01:01:05,397 +If you hold Control + Shift and click, then it +如果你按住 Control + Shift 然后点击,它会 + +1501 +01:01:05,399 --> 01:01:09,367 +lets you pick which thing you want, that's under the mouse. +在这个鼠标位置后面,有许多东西,它会让你选择其中一个 + +1502 +01:01:09,369 --> 01:01:11,636 +A very important little trick, Control + Shift. +所以,这个是一个很重要的小技巧,Control + Shift + +1503 +01:01:11,638 --> 01:01:13,804 +So here I could pick the View Controller. +这里我可以选择 View Controller + +1504 +01:01:13,806 --> 01:01:15,539 +Now I'm seeing the Identity Inspector of +现在我看到,Identity Inspector + +1505 +01:01:15,541 --> 01:01:16,473 +the View Controller. +是我选择的那个 View Controller + +1506 +01:01:16,475 --> 01:01:18,041 +Or I could go here and pick, +同样,我可以在这里选择 + +1507 +01:01:18,043 --> 01:01:20,843 +this is the view property in my View Controller. +这是我的 View Controller 中的 view 属性 + +1508 +01:01:20,845 --> 01:01:21,977 +The top level view. +最顶层的 view + +1509 +01:01:21,979 --> 01:01:24,380 +This is my FaceView that I'm trying to create. +这是我想要创建的 FaceView + +1510 +01:01:24,382 --> 01:01:26,615 +So I select this here, then I'm gonna go to +所以我选择这个,然后我来到 + +1511 +01:01:26,617 --> 01:01:28,750 +the Identity Inspector again, up here. +上面的 Identity Inspector + +1512 +01:01:28,752 --> 01:01:32,887 +I'm gonna change this to be a FaceView. Okay? +并将其改成 FaceView + +1514 +01:01:32,889 --> 01:01:35,189 +So now this thing is a FaceView, and so +那么现在这个 view 就是 FaceView 了 + +1515 +01:01:35,191 --> 01:01:37,524 +when it's time for this thing to draw, +当有需要绘制的时候 + +1516 +01:01:37,526 --> 01:01:40,727 +it's gonna call the drawRect of the FaceView class. +这将会调用 FaceView 类里的 drawRect 方法 + +1517 +01:01:40,729 --> 01:01:43,096 +So let's go take a look at the FaceView class. +所以现在我们来看看这个 FaceView + +1518 +01:01:43,098 --> 01:01:44,630 +Here it is. +这里就是 FaceView 的代码 + +1519 +01:01:44,632 --> 01:01:48,100 +And here is drawRect. +这里是 drawRect 方法 + +1520 +01:01:48,102 --> 01:01:50,602 +Now, it's commented out by default. +现在,它默认是被注释的 + +1521 +01:01:50,604 --> 01:01:52,303 +Why is it commented out by default? +为什么默认被注释掉呢? + +1522 +01:01:52,305 --> 01:01:57,308 +Well because having a drawRect costs system resources. +因为调用 drawRect 会消耗系统资源 + +1523 +01:01:57,310 --> 01:01:59,677 +It thinks it has to draw this thing. +系统认为需要重绘这个东西 + +1524 +01:01:59,678 --> 01:02:02,045 +So you only wanna have a drawRect if you actually draw, +所以当你确实需要手动绘制的时候,你才需要实现 drawRect 方法 + +1525 +01:02:02,047 --> 01:02:03,279 +in your drawRect. + +1526 +01:02:03,281 --> 01:02:06,149 +Don't have it just sitting there uncommented out, +当你并不需要手动绘制的时候 + +1527 +01:02:06,151 --> 01:02:08,050 +if you're not actually using it. +别让 drawRect 方法取消注释但不做任何操作 + +1528 +01:02:08,052 --> 01:02:10,386 +All right, so, how am I gonna draw this face? +好的,我怎么画这个脸出来呢? + +1529 +01:02:10,388 --> 01:02:13,622 +Let's start by drawing the outline of the head. +我们从画头的轮廓开始吧 + +1530 +01:02:13,624 --> 01:02:16,074 +Just a round circle. Okay? +一个圆圈 + +1532 +01:02:16,075 --> 01:02:17,158 +Cuz that's pretty simple to draw. +因为这很简单 + +1533 +01:02:17,160 --> 01:02:20,695 +And how am I gonna do that? +我该怎么做? + +1534 +01:02:20,697 --> 01:02:24,164 +Let's start by creating a BezierPath. +我们开始创建一个 UIBezierPath 吧 + +1535 +01:02:24,166 --> 01:02:29,636 +I'll call it facePath which is, BezierPath. +我叫这个为 facePath,是一个 UIBezierPath 对象 + +1536 +01:02:29,638 --> 01:02:31,188 +And let's look at +让我们看看 + +1537 +01:02:31,189 --> 01:02:32,739 +all the different kinds of BezierPaths we can make. +我们能用 UIBezierPath 绘制的所有东西吧 + +1538 +01:02:32,741 --> 01:02:34,257 +Ovals. +椭圆形 + +1539 +01:02:34,258 --> 01:02:35,774 +We could use this one, ovalInRect, okay? +我们可以用 ovalInRect 这个方法 + +1540 +01:02:35,777 --> 01:02:36,809 +That's a pretty good one. +这是个不错的选择 + +1541 +01:02:36,811 --> 01:02:38,977 +I'm actually gonna use this one, +事实上,我要用这个 + +1542 +01:02:38,979 --> 01:02:42,447 +arcCenter cuz I wanna show you a really bad error message +arcCenter,因为我想向你们展示一些你将会在 Swift 中遇到的错误信息 + +1543 +01:02:42,449 --> 01:02:45,650 +you're gonna get in Swift that I want you to avoid. +我希望你们能够避免这些地方 + +1544 +01:02:45,652 --> 01:02:48,019 +So I'm gonna use this one which lets you create an arc, +所以我需要这个,让你创建一个弧 + +1545 +01:02:48,021 --> 01:02:50,254 +and I'm just gonna have my arc go all the way around. +然后我想让这个弧绕成一个圆 + +1546 +01:02:50,256 --> 01:02:52,089 +Okay? From zero all the way around. +从 0 度到 360 度 + +1547 +01:02:52,091 --> 01:02:54,190 +So, it wants to know the center. +它需要知道中心点在哪里 + +1548 +01:02:54,192 --> 01:02:56,626 +So I'm gonna have to have my faces center somehow. +我假设这里有一个 faceCenter 是这个圆的中心点 + +1549 +01:02:56,628 --> 01:02:58,094 +We'll define that in a second. +我们稍后会定义它 + +1550 +01:02:58,096 --> 01:03:00,229 +It also wants to know the radius, so +同样,这个方法需要知道半径是多少 + +1551 +01:03:00,231 --> 01:03:02,731 +I have to have my faces radius in a second. +所以我同样假设这里有一个 faceRadius 是这个圆的半径 + +1552 +01:03:02,733 --> 01:03:04,332 +We'll do that. +同样我们稍后定义它 + +1553 +01:03:04,334 --> 01:03:07,602 +It wants to know the start angle, to draw this arc. +另外,它还需要知道画这个弧度的起始角度 + +1554 +01:03:07,604 --> 01:03:09,003 +Okay? So +这里 + +1555 +01:03:09,004 --> 01:03:10,403 +I'm gonna start at angle zero. +我将从 0 度开始 + +1556 +01:03:10,406 --> 01:03:12,339 +The angle's in radians. +半径是用弧度来计算的 + +1557 +01:03:12,341 --> 01:03:15,542 +So I wanna go around to 2pi. +所以我希望它能从 0 度画到 2pi + +1558 +01:03:15,544 --> 01:03:17,444 +Going, I'm gonna draw an arc from zero, +继续,我将从 0 度开始画这个弧 + +1559 +01:03:17,446 --> 01:03:19,045 +all the way around to 2pi radians. +绕一圈直到 2pi 的弧度 + +1560 +01:03:19,047 --> 01:03:22,965 +Hopefully everyone knows what radians are. Okay? +希望所有人都知道弧度是什么 + +1562 +01:03:22,966 --> 01:03:24,482 +So zero to 2pi that's good, and then clockwise or +所以,0 到 2pi,没问题了吧?,顺时针还是 + +1563 +01:03:24,485 --> 01:03:25,935 +counter clockwise, +逆时针 + +1564 +01:03:25,936 --> 01:03:27,386 +I don't care cuz I'm going all the way around. +我不在乎是顺还是逆,因为我画的是一个整圆 + +1565 +01:03:27,388 --> 01:03:28,953 +So I'll just say clockwise true. +所以我选择顺时针,clockwise: true + +1566 +01:03:28,955 --> 01:03:31,823 +Now, when I do this, well first let's do +现在,当我这么做,我们先定义 + +1567 +01:03:31,825 --> 01:03:34,458 +our faceCenter and faceRadius here. +我们的 faceCenter 和 faceRadius 吧 + +1568 +01:03:34,460 --> 01:03:40,630 +So I'm gonna make actually computed properties for those. +事实上我将会让这俩变成 computed properties + +1569 +01:03:40,632 --> 01:03:43,600 +So the faceCenter is a CGPoint. +faceCenter 是一个 CGPoint + +1570 +01:03:43,602 --> 01:03:47,970 +And really, it would be cool, yeah, I could do get and set. +作为一个 computed properties,我可以编写 get 和 set 方法 + +1571 +01:03:47,972 --> 01:03:51,240 +It's gonna be Get Only. Okay? +但在这里我只需要 get + +1573 +01:03:51,241 --> 01:03:52,574 +I'm not gonna allow me to set my faceCenter, +我不允许用户来设置 faceCenter 的值 + +1574 +01:03:52,576 --> 01:03:54,209 +I'm almost going to calculate it. +get 方法大部分工作就是计算 + +1575 +01:03:54,211 --> 01:03:56,644 +I could make it settable, actually too, but +事实上我也可以让 faceCenter 能够被赋值,但 + +1576 +01:03:56,646 --> 01:03:59,080 +I'm gonna make it so it's calculated only. +这里,我只让它能够计算 + +1577 +01:03:59,082 --> 01:04:00,681 +When you do calculated only, +当你只用做计算时 + +1578 +01:04:00,683 --> 01:04:03,050 +you actually don't need this part. +你就不需要编写 get {...} 这部分 + +1579 +01:04:03,052 --> 01:04:03,683 +This get. +这里的 get + +1580 +01:04:03,685 --> 01:04:04,851 +You can take that out. +你可以把它删去 + +1581 +01:04:04,853 --> 01:04:06,352 +And if it's returned Only. +而且,如果它只是返回一个数值 + +1582 +01:04:06,354 --> 01:04:08,253 +So I'll say return. +我会写 return + +1583 +01:04:08,255 --> 01:04:11,023 +Now I, you might be saying oh I'm gonna return center, +现在你也许会写 return center + +1584 +01:04:11,025 --> 01:04:12,257 +let's put the face in the center. +把我们的 FaveView 放在 center 上吧 + +1585 +01:04:12,259 --> 01:04:15,660 +Did everyone understand why this is very bad? +大家都明白这里为什么错了吗? + +1586 +01:04:15,662 --> 01:04:17,528 +All right, cuz center is not in my coordinate system. +因为这个 center 并不在我的坐标系中 + +1587 +01:04:17,530 --> 01:04:19,029 +It's in my superview's coordinate system. +它在我的 superview 的坐标系中 + +1588 +01:04:19,031 --> 01:04:23,967 +Luckily, I can convert a point from my superview's coordinate +不过幸运地,我可以把这个点从 superview 的坐标系转换到 + +1589 +01:04:23,969 --> 01:04:29,138 +system using this nice method, convertPoint(fromView:). +我的坐标系中,用一个很好用的方法叫 convertPoint(fromView:) + +1590 +01:04:29,140 --> 01:04:34,876 +So I'm gonna convert center from my superview. Okay? +所以我从 superview 转换 center + +1592 +01:04:34,877 --> 01:04:36,376 +That's gonna put my face right in the center, +这将会让我的笑脸放在正中心 + +1593 +01:04:36,379 --> 01:04:39,680 +cuz I've converted that center from my superview's coordinate +因为我从 superview 的坐标系转换过来 + +1594 +01:04:39,682 --> 01:04:41,381 +system to mine. Okay? +成为我的坐标系的 center + +1596 +01:04:41,383 --> 01:04:43,083 +So that's faceCenter. +那么这个就是 faceCenter 了 + +1597 +01:04:43,085 --> 01:04:45,151 +Let's also do faceRadius. +接着来定义 faceRadius + +1598 +01:04:45,153 --> 01:04:46,786 +So for the faceRadius, +那么对于这个 faceRadius + +1599 +01:04:46,788 --> 01:04:50,990 +I'm gonna have it be as big as it can be. Okay? +我将希望它尽可能的大 + +1601 +01:04:50,991 --> 01:04:52,491 +So faceRadius is gonna be a CGFloat to all of +faceRadius 会是 CGFloat 类型的 + +1602 +01:04:52,493 --> 01:04:55,493 +our drawing stuff is Float, and I'm gonna return as big as +所有的绘画元素都是 Float 类型的,在它不会被截断的情况下 + +1603 +01:04:55,495 --> 01:04:57,261 +it can be without getting cut off. +我会让它尽可能大 + +1604 +01:04:57,263 --> 01:04:59,563 +So it's gonna be the minimum of my width or height. +所以,让它成为宽和高中较小的那一个 + +1605 +01:04:59,565 --> 01:05:03,934 +So I'm gonna say, min of my bounds. +这里我输入 min(bounds + +1606 +01:05:03,936 --> 01:05:06,203 +Sorry. +抱歉 + +1607 +01:05:06,204 --> 01:05:08,471 +bounds.size.width, or my bounds.size.height. +min(bounds.size.width, bounds.size.height) + +1608 +01:05:08,473 --> 01:05:10,306 +Whichever is less than that. +哪个短用哪个 + +1609 +01:05:10,307 --> 01:05:12,140 +Min is just a nice little function in Swift. +Swift 中的 min 是一个不错的小函数 + +1610 +01:05:12,143 --> 01:05:15,077 +And I'm gonna divide by two because this is a radius, +这里把它除以 2,因为这是半径 + +1611 +01:05:15,079 --> 01:05:16,612 +not diameter of my face. +不是直径 + +1612 +01:05:16,614 --> 01:05:17,946 +This is the radius. +这就是 faceRadius + +1613 +01:05:17,948 --> 01:05:20,982 +So now I have my center facing radius, but +现在我有了半径和中心 + +1614 +01:05:20,984 --> 01:05:22,984 +I still have an error here. +但是这里还是有个错误 + +1615 +01:05:22,986 --> 01:05:24,669 +Look at this error. +来看看这个错误 + +1616 +01:05:24,670 --> 01:05:26,353 +Even though I did my center, I did my radius. +即使我算好了中心位置,算好了半径 + +1617 +01:05:26,356 --> 01:05:27,554 +I still have an error. +这里还是有错误 + +1618 +01:05:27,556 --> 01:05:28,955 +What is the problem? +到底是什么问题? + +1619 +01:05:28,957 --> 01:05:31,891 +Oh, "Extra argument 'radius' in call". +噢,"Extra argument 'radius' in call" + +1620 +01:05:31,893 --> 01:05:33,760 +Huh. + +1621 +01:05:33,762 --> 01:05:34,944 +That's weird. +这很奇怪 + +1622 +01:05:34,945 --> 01:05:36,127 +I didn't see any extra argument. +我没看到额外的参数 + +1623 +01:05:36,130 --> 01:05:37,329 +What the heck is that about? +到底出什么错了? + +1624 +01:05:37,331 --> 01:05:39,131 +Okay. + +1625 +01:05:39,132 --> 01:05:40,932 +You could waste a half an hour looking for this, okay? +你可能会花半个小时找错误 + +1626 +01:05:40,934 --> 01:05:42,250 +I was thinking, oh, +你可能会想 + +1627 +01:05:42,251 --> 01:05:43,567 +radius, there's nothing wrong with the radius. +radius,radius 这里也没什么问题啊 + +1628 +01:05:43,570 --> 01:05:45,687 +It's right. +是的 + +1629 +01:05:45,688 --> 01:05:47,805 +The problem for this has nothing to do with the radius. +radius 跟这个问题一点关系都没有 + +1630 +01:05:47,807 --> 01:05:50,708 +The problem is this. +问题在这,2*M_PI + +1631 +01:05:50,710 --> 01:05:52,410 +Okay? +明白了吗? + +1632 +01:05:52,411 --> 01:05:54,111 +So this is an error you get from switching occasionally, +这个错误你们可能会偶尔遇到 + +1633 +01:05:54,113 --> 01:05:56,813 +I'm sure they'll fix all these errors, but occasionally, +我确定 Apple 会修复好这些错误 + +1634 +01:05:56,815 --> 01:05:59,416 +you get this very misleading error, and this is one. +但是偶尔还是会获得这些误导你的错误,这就是一个 + +1635 +01:05:59,418 --> 01:06:00,817 +The problem is that this- +问题在于 + +1636 +01:06:00,819 --> 01:06:01,784 +What type is this? +它的类型是什么? + +1637 +01:06:05,022 --> 01:06:06,021 +It's a Double. +它是一个 Double + +1638 +01:06:06,023 --> 01:06:07,489 +Yeah. +是的 + +1639 +01:06:07,490 --> 01:06:08,956 +And what type do we draw with? +但是我们绘画用什么类型的? + +1640 +01:06:08,959 --> 01:06:10,224 +CGFloat. +CGFloat + +1641 +01:06:10,226 --> 01:06:14,194 +So this problem is just that I need to cast this to +所以把它转型成 CGfloat,这个问题就可以 + +1642 +01:06:14,196 --> 01:06:15,195 +a CGFloat. +解决了 + +1643 +01:06:15,197 --> 01:06:16,908 +Okay? +明白了吗? + +1644 +01:06:16,909 --> 01:06:18,620 +That's gonna make this error go away. +这个错误就会消失了 + +1645 +01:06:18,621 --> 01:06:20,332 +It had nothing to do with radius whatsoever there. +跟 radius 一点关系都没有 + +1646 +01:06:20,335 --> 01:06:22,168 +Okay? + +1647 +01:06:22,169 --> 01:06:24,002 +So, best warning, watch out for that. +这就是我给你们的提醒,以后要注意点 + +1648 +01:06:24,005 --> 01:06:26,605 +All right, so I have my nice facePath here. +我已经得到了 facePath + +1649 +01:06:26,607 --> 01:06:30,476 +Maybe I wanna set my facePath's lineWidth. +在这里设置一下 facePath 的 lineWidth(线宽) + +1650 +01:06:30,478 --> 01:06:34,246 +Something like three, something like that. +设置成 3 吧 + +1651 +01:06:34,248 --> 01:06:36,181 +In fact, maybe I even want lineWidth to +我想把 lineWidth 变成 FaceView 中 + +1652 +01:06:36,183 --> 01:06:42,019 +be something that's configurable in my FaceView. +可以设置的一个属性 + +1653 +01:06:42,021 --> 01:06:43,253 +So it's a CGFloat. +类型是 CGFloat + +1654 +01:06:43,255 --> 01:06:45,222 +And we'll set it to default of three. +我们把它的默认设置为 3 + +1655 +01:06:45,224 --> 01:06:46,790 +One thing that's interesting and +一个很有趣的事是 + +1656 +01:06:46,792 --> 01:06:48,891 +then we'll set this down here to lineWidth. +我先把这里设置成 lineWidth + +1657 +01:06:48,893 --> 01:06:51,794 +One thing that's interesting about this is any time +一个有趣的事情是,无论何时 lineWidth 被改变了 + +1658 +01:06:51,796 --> 01:06:54,997 +someone changes my lineWidth, I need to redraw myself. +我都需要把这个 view 重新绘制一遍 + +1659 +01:06:54,999 --> 01:06:56,565 +All right? +明白了吗? + +1660 +01:06:56,567 --> 01:06:58,133 +So how can I make that happen? +我怎么做才能实现呢? + +1661 +01:06:58,135 --> 01:07:01,502 +Well, I can use Property Observer. +我可以使用 Property Observer + +1662 +01:07:01,504 --> 01:07:02,937 +Okay? + +1663 +01:07:02,938 --> 01:07:04,371 +Anytime someone sets this, +无论什么时候,有人改变了它 + +1664 +01:07:04,373 --> 01:07:08,108 +I'm gonna call setNeedsDisplay on myself. +我就会在向自身调用 setNeedsDisplay + +1665 +01:07:08,110 --> 01:07:09,709 +Okay? +明白了吗? + +1666 +01:07:09,711 --> 01:07:11,127 +Bam. + +1667 +01:07:11,128 --> 01:07:12,544 +I'm in it redrawn by the system. +系统就会帮你重新绘制视图 + +1668 +01:07:12,547 --> 01:07:13,879 +Okay? So anytime you have +如果在你的 view 中有一个 + +1669 +01:07:13,881 --> 01:07:16,815 +a property in your, in a view that changes how you would be +property 在改变的时候需要被重新绘制 + +1670 +01:07:16,817 --> 01:07:19,284 +drawn, just put a little Property Observer into +只要在 Property Observer 里调用 + +1671 +01:07:19,286 --> 01:07:20,952 +the setNeedsDisplay after it. +setNeedsDisplay 就可以了 + +1672 +01:07:20,954 --> 01:07:23,354 +And it'll get you automatically redrawn. +它就会帮你重新绘制 + +1673 +01:07:23,356 --> 01:07:25,189 +Maybe I'll have another property here, +在这里我还想添加一个 + +1674 +01:07:25,191 --> 01:07:26,490 +which is the color I wanna be. +颜色的 property + +1675 +01:07:26,492 --> 01:07:29,626 +UIColor, we'll set the default here to be +类型是 UIColor,默认设置成 + +1676 +01:07:29,628 --> 01:07:31,461 +blueColor for example. +蓝色 + +1677 +01:07:31,463 --> 01:07:33,329 +But I want the exact same thing here. +但我也想跟这里一样 + +1678 +01:07:33,331 --> 01:07:34,029 +Okay? + +1679 +01:07:34,031 --> 01:07:35,330 +Someone sets it. +有人改变了它 + +1680 +01:07:35,332 --> 01:07:36,631 +I want it redrawn. +视图就会被重新绘制 + +1681 +01:07:36,633 --> 01:07:39,167 +And so let's go ahead and set our color. +现在设置一下颜色 + +1682 +01:07:39,169 --> 01:07:42,003 +Now I'm gonna do both my set, I could do setFill and +我既可以做 setFill 又可以做 setStroke + +1683 +01:07:42,005 --> 01:07:44,638 +setStroke colors, but I'm just gonna do set, +我两者都想做,但这里,只要 set 就可以了 + +1684 +01:07:44,640 --> 01:07:46,773 +which sets both my fill and my stroke. +这样填充和笔画的颜色都会被设置 + +1685 +01:07:46,775 --> 01:07:49,976 +I'm not gonna be filling so it doesn't matter, but set to +因为这里不会被填充,所以调用 set 也没问题 + +1686 +01:07:49,978 --> 01:07:53,146 +both, and then how do I draw this BezierPath right here? +然后呢?我怎么绘制 BezierPath? + +1687 +01:07:53,148 --> 01:07:56,716 +I just say, facePath.stroke. +facePath.stroke 就可以了 + +1688 +01:07:56,718 --> 01:08:01,319 +And that's gonna draw, okay? +这样就可以绘制了 + +1689 +01:08:01,321 --> 01:08:04,456 +So let's go take a look at this. +我们运行一下程序 + +1690 +01:08:04,458 --> 01:08:11,395 +Okay. + +1691 +01:08:11,397 --> 01:08:13,397 +So, it comes up, it's blank. +运行起来了,它是空的 + +1692 +01:08:13,399 --> 01:08:15,866 +And not only is it blank, it's got some error down here. +不仅仅是空白的,这里还有一些错误信息 + +1693 +01:08:15,868 --> 01:08:17,918 +What does it say? It says, +它说 + +1694 +01:08:17,919 --> 01:08:19,969 +failed to instantiate the default View Controller. +failed to instantiate the default View Controller(初始化默认 View Controller 失败) + +1695 +01:08:19,971 --> 01:08:21,738 +Okay? Well that means that in my +这表明 + +1696 +01:08:21,740 --> 01:08:27,009 +StoryBoard, there is no scene that's specified, +在 StoryBoard 中,没有指定 + +1697 +01:08:27,011 --> 01:08:29,444 +as the scene to start in. +开始场景 + +1698 +01:08:29,446 --> 01:08:31,079 +Okay? It has no starting scene. +没有开始场景 + +1699 +01:08:31,081 --> 01:08:33,848 +The starting scene always has a little arrow pointing to it. +开始场景总是有一个指向它的小箭头 + +1700 +01:08:33,850 --> 01:08:34,983 +Right here, +在这里 + +1701 +01:08:34,984 --> 01:08:36,117 +you've probably seen in in your Calculator right? +你们可能在 Calculator 中已经见过了 + +1702 +01:08:36,119 --> 01:08:38,419 +A little arrow that says this is the place to come in +当你运行程序时 + +1703 +01:08:38,421 --> 01:08:39,720 +when you start this app. +一个代表程序入口点的小箭头 + +1704 +01:08:39,722 --> 01:08:42,322 +You can set that arrow with the Inspector the regular +你可以在选中的 View Controller 的 + +1705 +01:08:42,324 --> 01:08:44,524 +Attributes Inspector by selecting your +Attributes Inspector 里 + +1706 +01:08:44,526 --> 01:08:47,693 +View Controller that you wanna be the one that comes in. +设置它为入口场景 + +1707 +01:08:47,695 --> 01:08:48,894 +And click. This little button here is +点击这里的小按钮 + +1708 +01:08:48,896 --> 01:08:49,828 +Initial View Controller. +Is Initial View Controller + +1709 +01:08:49,830 --> 01:08:51,129 +You see that arrow appear? +看到剪头出现了吗? + +1710 +01:08:51,131 --> 01:08:52,997 +You can also pick this arrow up and +你也可以把这个剪头选中 + +1711 +01:08:52,999 --> 01:08:55,032 +move it to another View Controller. +把它移动到另一个 View Controller 里 + +1712 +01:08:55,034 --> 01:08:56,767 +Okay? + +1713 +01:08:56,769 --> 01:08:59,269 +So now we have a thing, oh all right. +好了 + +1714 +01:08:59,271 --> 01:09:01,154 +So we've got our face. +脸已经出现了 + +1715 +01:09:01,155 --> 01:09:03,038 +Now, one thing I don't like about this face is it goes all +现在我对这个脸不满意的地方就是 + +1716 +01:09:03,041 --> 01:09:04,407 +the way to the edges. +它太靠近边缘了 + +1717 +01:09:04,409 --> 01:09:06,675 +I want it to actually be 90% of the edges. +我想让它占据整个长度的 90% + +1718 +01:09:08,178 --> 01:09:09,544 +Okay? Another thing I +另一件 + +1719 +01:09:09,546 --> 01:09:10,712 +don't like is this. +我不满意的事情是 + +1720 +01:09:10,714 --> 01:09:12,113 +Ugh, okay? +额 + +1721 +01:09:12,115 --> 01:09:15,982 +So my face is gonna be distorted every time I rotate. +每一次我旋转屏幕,脸都会被破坏 + +1722 +01:09:15,984 --> 01:09:17,601 +Why is that? +这是怎么回事儿? + +1723 +01:09:17,602 --> 01:09:19,219 +That's this stretching thing I was telling you about. +这就是我之前告诉你们的拉伸的情况 + +1724 +01:09:19,221 --> 01:09:22,155 +We want our drawRect to be called again when we +我们希望每一个获得新的边界时(就像旋转屏幕) + +1725 +01:09:22,157 --> 01:09:24,523 +have a new bounds like that. +drawRect 都会被再一次调用 + +1726 +01:09:24,525 --> 01:09:26,492 +So let's fix both of those things. +现在我们一起把它们处理好 + +1727 +01:09:26,494 --> 01:09:29,795 +We can fix that content mode redraw by selecting our view, +修改 Mode (重绘模式)的方法是:选中 view + +1728 +01:09:29,797 --> 01:09:31,596 +going to the inspector up here, +去到 Inspector + +1729 +01:09:31,598 --> 01:09:33,431 +the Attributes Inspector, and +Attributes Inspector + +1730 +01:09:33,433 --> 01:09:35,199 +the very first one is the mode. +第一个就是 Mode + +1731 +01:09:35,201 --> 01:09:37,835 +And you can see the default was scale to fill. +默认的是 Scale To Fill (拉伸以填充) + +1732 +01:09:37,837 --> 01:09:38,835 +We want Redraw. +我们想要 Redraw (重绘) + +1733 +01:09:39,905 --> 01:09:41,170 +Okay? So I'm gonna pick Redraw. +所以我选择 Redraw + +1734 +01:09:41,172 --> 01:09:42,738 +So that'll fix that. +这样就修改好了 + +1735 +01:09:42,740 --> 01:09:49,711 +And as far as the 90%, I'm going to fix that in here, +至于 90%,我在这里修改 + +1736 +01:09:49,713 --> 01:09:55,683 +by having the, my face radius be times 90%. +把 faceRadius 再乘以 90% + +1737 +01:09:55,685 --> 01:09:58,319 +But really, I'd like this to be settable too. +但是我也想让它成为一个可以被设置的 + +1738 +01:09:58,321 --> 01:10:02,456 +So I'm gonna have var scale, CGFloat. +添加一个变量 scale,类型是 CGFloat + +1739 +01:10:03,425 --> 01:10:05,358 +Okay. And we'll start this out at +默认设置为 + +1740 +01:10:05,360 --> 01:10:05,958 +90%. + +1741 +01:10:05,960 --> 01:10:07,393 +So I want that, and +我想让它 + +1742 +01:10:07,395 --> 01:10:11,963 +this one also, if I change, I want it to change. +在更改以后也重绘视图 + +1743 +01:10:11,965 --> 01:10:13,231 +Okay? + +1744 +01:10:13,232 --> 01:10:14,498 +So now let's go try that. +运行一下程序 + +1745 +01:10:14,501 --> 01:10:15,132 +See what happens. +看看发生了什么 + +1746 +01:10:15,134 --> 01:10:16,567 +Okay? We got our 90%. +90% 已经实现了 + +1747 +01:10:16,569 --> 01:10:18,135 +That's good. +还不错 + +1748 +01:10:18,136 --> 01:10:19,702 +And when I rotate, it doesn't stretch it. +当我旋转屏幕时,也没有拉伸 + +1749 +01:10:20,672 --> 01:10:22,138 +Okay? And it's using the minimum of +它使用了宽度和高度中 + +1750 +01:10:22,140 --> 01:10:23,072 +the width or height. +较小的那个 + +1751 +01:10:23,074 --> 01:10:24,006 +Okay? + +1752 +01:10:24,008 --> 01:10:24,906 +So that's good. +还不错 + +1753 +01:10:24,908 --> 01:10:26,074 +That's going good. +越来越好了哈 + +1754 +01:10:26,076 --> 01:10:29,444 +Now we wanna draw the eyes and the mouth, and +现在开始绘制眼睛和嘴巴 + +1755 +01:10:29,446 --> 01:10:31,712 +cuz time is running out here, +时间已经不多了 + +1756 +01:10:31,714 --> 01:10:35,249 +I'm actually gonna type those in super fast. +我将会用超快的速度输入 + +1757 +01:10:35,251 --> 01:10:38,752 +I posted for those of you who are trying to keep along here, +我会贴给你们这些源代码,所以 + +1758 +01:10:38,754 --> 01:10:40,687 +which is probably impossible. +就不要尝试手动输入了 + +1759 +01:10:40,689 --> 01:10:44,390 +To do that though, I need some constants. +为了实现这些,我需要一些常量 + +1760 +01:10:44,392 --> 01:10:47,560 +And this how we do constants in Swift. +在 Swift 中我们这样定义常量 + +1761 +01:10:47,562 --> 01:10:49,461 +We create structs. +创建 struct + +1762 +01:10:49,463 --> 01:10:52,330 +Okay? And then use class, or +使用 class 或者 + +1763 +01:10:52,332 --> 01:10:55,500 +in this case, static lets. +在这里使用 static let 修饰 + +1764 +01:10:55,502 --> 01:10:56,868 +Okay? So this is gonna be +所以这个常量就是 + +1765 +01:10:56,870 --> 01:11:00,071 +a constant called Scaling.FaceRadiustoEyeRadius. +Scaling.FaceRadiustoEyeRadius + +1766 +01:11:00,073 --> 01:11:01,956 +Okay. And + +1767 +01:11:01,957 --> 01:11:03,840 +then I'm going to have a function here, that I'm +这里有个函数叫做 bezierPathForEye + +1768 +01:11:03,843 --> 01:11:07,911 +gonna type in really, really fast, called bezierPathForEye. +同样我这里用了 Code Snippet + +1769 +01:11:07,913 --> 01:11:11,548 +And it's just gonna return a BezierPath that draws an eye. +它会返回一个绘制一只眼睛的 BezierPath 对象 + +1770 +01:11:11,550 --> 01:11:13,149 +Either the left eye or the right eye. +左眼或者右眼 + +1771 +01:11:13,151 --> 01:11:14,283 +This says which one. +参数用来确定是哪一只眼睛 + +1772 +01:11:14,285 --> 01:11:16,051 +Okay? So it returns a BezierPath. +它返回了一个 BezierPath + +1773 +01:11:16,053 --> 01:11:18,804 +Okay? + +1774 +01:11:18,805 --> 01:11:21,556 +Then I'm gonna have another one, which is BezierSmile. +这里还会有一个函数,BezierSmile + +1775 +01:11:21,558 --> 01:11:23,124 +We're gonna type that in real fast. +再一次使用 Code Snippet + +1776 +01:11:23,126 --> 01:11:24,158 +Okay? +没问题吧? + +1777 +01:11:24,160 --> 01:11:26,060 +So here is BeizerPath for smile. +这就是笑容的 BeizerPath + +1778 +01:11:26,062 --> 01:11:27,794 +And what this is gonna do, +这个函数会 + +1779 +01:11:27,796 --> 01:11:31,331 +it's gonna take a fractionOfMaximumSmile. +把 fractionOfMaximumSmile 作为参数 + +1780 +01:11:31,333 --> 01:11:33,800 +So one is full smile. +1 是最开心的笑容 + +1781 +01:11:33,802 --> 01:11:35,835 +Minus one is full frown. +-1 是最难过的 + +1782 +01:11:35,837 --> 01:11:37,069 +And everywhere in between. +其余的值都在 1 和 -1 之间 + +1783 +01:11:37,071 --> 01:11:38,570 +'Kay? So that's what this does. +这就是它做的事情 + +1784 +01:11:38,572 --> 01:11:39,738 +And it returns a BeizerPath. +返回一个 BeizerPath + +1785 +01:11:39,740 --> 01:11:42,440 +So now here in my drawRect, +在 drawRect 函数中 + +1786 +01:11:42,442 --> 01:11:46,477 +I can say bezierPathForEye, left eye. +调用 bezierPathForEye,left 作为参数 + +1787 +01:11:46,479 --> 01:11:47,611 +I got the BezierPath. +我获得了 BezierPath + +1788 +01:11:47,613 --> 01:11:51,047 +I'm just gonna immediately send it stroke. +我立即用它调用 stroke + +1789 +01:11:51,049 --> 01:11:52,949 +Okay? + +1790 +01:11:52,950 --> 01:11:54,850 +And then BezierPath for the right eye. +接着是右眼的 BezierPath + +1791 +01:11:54,852 --> 01:11:56,985 +I'm gonna send it stroke. +给它发送 stroke 消息 + +1792 +01:11:56,987 --> 01:11:59,087 +So I'm just gonna stroke the left eye and the right eye. +现在绘制了左眼和右眼 + +1793 +01:11:59,089 --> 01:12:00,338 +Okay? + +1794 +01:12:00,339 --> 01:12:01,588 +Then I'm gonna do the smiliness. +接着处理笑容 + +1795 +01:12:01,591 --> 01:12:06,127 +So, I'm going to let smiliness equal some value. +我在这里写 let smiliness = + +1796 +01:12:06,129 --> 01:12:08,429 +Let's start it at 0.75. +从 0.75 开始吧 + +1797 +01:12:08,431 --> 01:12:11,064 +We're pretty, pretty happy to start. +这是一个很开心很开心的数值了 + +1798 +01:12:11,066 --> 01:12:13,767 +And then I'm going to create a bez, +接着,我用上面的这些给笑容 + +1799 +01:12:13,769 --> 01:12:16,269 +this BezierPath using this thing up here for +创建一个 BezierPath + +1800 +01:12:16,271 --> 01:12:19,005 +a smile, which is bezierPathForSmile. +用这个函数 bezierPathForSmile + +1801 +01:12:19,007 --> 01:12:22,775 +And we're gonna pass it the smiliness. +把 smiliness 传进去 + +1802 +01:12:22,777 --> 01:12:25,810 +And then I'm just going to stroke this smile path. +然后绘制这个笑容的线条 + +1803 +01:12:27,881 --> 01:12:29,147 +Okay? + +1804 +01:12:29,148 --> 01:12:30,414 +And I hoped to have a little more time so +我很希望能有时间 + +1805 +01:12:30,416 --> 01:12:32,449 +I could have gone through this code, but +跟大家一起分析代码 + +1806 +01:12:32,451 --> 01:12:34,985 +it's a pretty straightforward code, really. +但是这些代码都很易懂 + +1807 +01:12:34,987 --> 01:12:37,654 +Here we're just using addCurveToPoint in +这里,我们在 BezierPath 里 + +1808 +01:12:37,656 --> 01:12:38,788 +our BezierPath. +调用 addCurveToPoint + +1809 +01:12:38,790 --> 01:12:41,724 +To draw a curve, which is the curve of the mouth. +接着,我们绘制嘴部的曲线 + +1810 +01:12:41,726 --> 01:12:43,793 +And then here, +接着,这儿 + +1811 +01:12:43,794 --> 01:12:45,861 +we're just using BezierPath arcCenter again. +我们又调用了一次 BezierPath(arcCenter: ...) + +1812 +01:12:45,863 --> 01:12:46,495 +Okay? + +1813 +01:12:46,497 --> 01:12:48,063 +To create the circle. +为了绘制圆 + +1814 +01:12:48,064 --> 01:12:49,630 +The eyes are just circles, okay? +眼睛都是圆的 + +1815 +01:12:49,633 --> 01:12:50,965 +That's really all those two methods do. +这就是这两个方法做的事情 + +1816 +01:12:50,967 --> 01:12:53,100 +There's nothing really special about them. +没什么特别的 + +1817 +01:12:53,102 --> 01:12:57,004 +And what do I have error here, which is, oops. +这里有个错误 + +1818 +01:12:57,006 --> 01:12:58,971 +Dot. +点 + +1819 +01:12:58,973 --> 01:13:00,172 +Okay? + +1820 +01:13:00,174 --> 01:13:01,607 +That's not it either. +不是点 + +1821 +01:13:01,609 --> 01:13:04,176 +SmilePath oh, equals, not that. +SmilePath 等于, + +1822 +01:13:04,178 --> 01:13:05,143 +Equals. +等号 + +1823 +01:13:05,145 --> 01:13:06,044 +There we go. +这就对了 + +1824 +01:13:06,046 --> 01:13:06,744 +Okay? + +1825 +01:13:06,746 --> 01:13:08,078 +Yes? +有问题吗? + +1826 +01:13:08,080 --> 01:13:09,479 +So let's run this. +运行一下程序 + +1827 +01:13:09,481 --> 01:13:11,414 +Hopefully, we'll have a smiley face. +希望我们能有一张笑脸 + +1828 +01:13:13,284 --> 01:13:14,049 +There it is. +来了 + +1829 +01:13:14,051 --> 01:13:15,017 +He looks pretty happy. +他看起来很快乐 + +1830 +01:13:15,019 --> 01:13:16,051 +We can rotate him. +我们可以旋转屏幕 + +1831 +01:13:16,053 --> 01:13:17,335 +He's very happy. +他真的很快乐 + +1832 +01:13:17,336 --> 01:13:18,618 +Okay, let's make him a little sad. +来,我们让他难过一点 + +1833 +01:13:18,621 --> 01:13:21,422 +How about minus 0.5? +-0.5 怎么样? + +1834 +01:13:21,424 --> 01:13:22,389 +Minus 0.5. +-0.5 + +1835 +01:13:22,391 --> 01:13:24,424 +Pretty, pretty sad. +非常非常难过 + +1836 +01:13:27,929 --> 01:13:29,495 +Aw. + +1837 +01:13:29,497 --> 01:13:31,764 +Okay? +明白了吗? + +1838 +01:13:31,766 --> 01:13:33,466 +Okay. +好的 + +1839 +01:13:33,467 --> 01:13:35,167 +So now we have this nice FaceView. +FaceView 已经完成了 + +1840 +01:13:35,169 --> 01:13:38,603 +What we're gonna do in our next lecture, is we're going +下一次课要讲的是 + +1841 +01:13:38,605 --> 01:13:41,439 +to add a gesture so we can make him happy or sad. +给这个程序添加手势,我们就可以让他一会儿开心一会儿难过 + +1842 +01:13:41,441 --> 01:13:42,306 +Happy or sad. +开心或者难过 + +1843 +01:13:42,308 --> 01:13:43,908 +Okay? + +1844 +01:13:43,909 --> 01:13:45,509 +We're also gonna put a gesture in there, a pinch gesture so +我们也会加入 Pinch Gesture (缩放手势) + +1845 +01:13:45,511 --> 01:13:46,977 +we can make them bigger or smaller. +我们就能把他变大或者变小 + +1846 +01:13:46,979 --> 01:13:49,396 +Okay? + +1847 +01:13:49,397 --> 01:13:51,814 +Then we're going to actually add a whole another MVC and +接着我们会添加另一个完整的 MVC + +1848 +01:13:51,817 --> 01:13:55,718 +make a much more powerful application that just uses +使用 FaceView 制作一个 + +1849 +01:13:55,720 --> 01:13:58,421 +the FaceView. +更强大的应用 + +1850 +01:13:58,422 --> 01:14:01,123 +The HappinessViewController as a view in another MVC. +把 HappinessViewController 用作另一个 MVC 的 view + +1851 +01:14:01,125 --> 01:14:02,413 +Okay? + +1852 +01:14:02,414 --> 01:14:03,702 +So now we're going to do multiple MVCs. +我们接下来就会处理多个 MVC 了 + +1853 +01:14:03,703 --> 01:14:04,991 +So that's what we're gonna be doing on Monday. +这就是下周一要完成的事情了 diff --git a/subtitles/6. Protocols and Delegation, Gestures.srt b/subtitles/6. Protocols and Delegation, Gestures.srt new file mode 100644 index 0000000..a8d0f91 --- /dev/null +++ b/subtitles/6. Protocols and Delegation, Gestures.srt @@ -0,0 +1,8789 @@ +1 +00:00:00,001 --> 00:00:04,669 +[MUSIC] +[音乐] + +2 +00:00:04,671 --> 00:00:08,272 +Stanford University. +斯坦福大学 + +3 +00:00:08,274 --> 00:00:11,742 +>> Okay well, welcome to lecture six of +欢迎来到第六课 + +4 +00:00:11,744 --> 00:00:15,646 +Stanford CS193p winter of 2015. +2015 冬季学期,斯坦福大学 CS193p 课程 + +5 +00:00:15,648 --> 00:00:18,882 +So today I am gonna do a little bit of +今天我们将要在最开始的时候 + +6 +00:00:18,884 --> 00:00:21,451 +demo action right at the beginning. +做一点点演示 + +7 +00:00:21,453 --> 00:00:24,754 +I wanna show you a kind of a cool trick that you can do +我将会向你展示一种很酷的技巧 + +8 +00:00:24,756 --> 00:00:28,124 +inside your Storyboard, and we also, last time, +你可以在你的 Storyboard 里使用,同样的,我们在上次 + +9 +00:00:28,126 --> 00:00:31,794 +didn't get to the point where we had actually a Model for +没有为我们的 MVC 创建一个实际的 Model + +10 +00:00:31,796 --> 00:00:33,795 +our MVC, our happiness MVC. +我们的 Happiness MVC + +11 +00:00:33,797 --> 00:00:36,398 +We had worked on the FaceView and got that working but +我们处理过 FaceView 并且使它能正常工作了 + +12 +00:00:36,400 --> 00:00:37,632 +we didn't have a Model, +但是我们没有一个 Model + +13 +00:00:37,634 --> 00:00:40,368 +so I'm gonna just put that Model in there, but then I am +所以我准备在那里放置一个 Model,但是随后 + +14 +00:00:40,370 --> 00:00:43,103 +going to jump right back into the slides and I am going to +我将回到幻灯片上,然后我将 + +15 +00:00:43,105 --> 00:00:45,906 +cover a very important concept, which is delegation. +介绍一个重要的概念,就是 delegation + +16 +00:00:45,908 --> 00:00:51,511 +And I'll have to kinda go over Swift's protocol syntax, and +我将会重新讲述一下 Swift 语言的协议语法 + +17 +00:00:51,513 --> 00:00:56,348 +then I will do a demo to show you how delegation works, +随后我将会进行一个演示向你们展示 delegation 是怎么工作的 + +18 +00:00:56,350 --> 00:01:00,018 +then I'm gonna cover gestures, okay? +随后我准备介绍一些手势,明白? + +19 +00:01:00,020 --> 00:01:02,954 +We know how to draw in our view now from last time. +在上节课中我们知道了怎么在 view 中进行绘制 + +20 +00:01:02,956 --> 00:01:06,190 +So, now we're gonna then talk about how we handle gestures. +所以,现在我们准备去探讨怎么样去处理手势 + +21 +00:01:06,192 --> 00:01:08,859 +Pinches and pans and swipes and things like that. +类似于捏合、滑动之类的动作 + +22 +00:01:10,129 --> 00:01:12,295 +And I think that'll probably use all of my time up. +我想这会花掉我所有的时间 + +23 +00:01:12,297 --> 00:01:13,630 +But if I have a little bit of time at the end, +但是如果我在结束前有一点时间的话 + +24 +00:01:13,632 --> 00:01:15,732 +I'm gonna get started on the next major topic. +我准备开始下一个主要的话题 + +25 +00:01:15,734 --> 00:01:19,035 +Which we're gonna spend most of Wednesday on. +我们准备在周三进行探讨的 + +26 +00:01:19,037 --> 00:01:21,303 +Which is Multiple MVCs, right? +就是 Multiple MVCs,明白? + +27 +00:01:21,305 --> 00:01:22,704 +We know how to build an MVC. +我们知道如何去创建一个 MVC + +28 +00:01:22,706 --> 00:01:25,573 +It's got a controller, it's got a Model, it's got a view. +它有一个 controller,Model,view + +29 +00:01:25,575 --> 00:01:27,675 +And now we're gonna build a bigger application by +然后我们将要创建一个大一点的应用 + +30 +00:01:27,677 --> 00:01:29,810 +combining MVCs, okay? +通过结合多个 MVC,明白? + +31 +00:01:29,812 --> 00:01:31,478 +And that's critical, obviously, +并且那是很关键的,很明显 + +32 +00:01:31,480 --> 00:01:34,815 +to growing the capability of size of app you can build. +增加功能会使你创建的 App 的尺寸增加 + +33 +00:01:34,817 --> 00:01:38,785 +So I'll try and fit in five or ten minutes of slides for +所以我将会尽量控制在 5 到 10 分钟把幻灯片讲完 + +34 +00:01:38,787 --> 00:01:41,921 +that just to make sure we have more time on Wednesday. +以确保我们再周三的时候会有更多的时间 + +35 +00:01:42,990 --> 00:01:45,690 +Anybody have any questions about any of this? +有人对这部分内容有问题么? + +36 +00:01:47,227 --> 00:01:47,792 +All right. +好吧 + +37 +00:01:47,794 --> 00:01:54,531 +So, let's dive into this demo first, before I talk about +所以,让我们进行这个 demo,在我谈论其他那些内容之前 + +38 +00:01:54,533 --> 00:01:59,202 +that, okay I am just going to bring up +我准备 + +39 +00:01:59,204 --> 00:02:03,272 +Happiness from where we left off last time. +从我们上次离开 Happiness 的地方开始 + +40 +00:02:03,274 --> 00:02:07,476 +And really all we had done here was the FaceView, +这是我们已经完成的 FaceView + +41 +00:02:07,478 --> 00:02:09,511 +we had not done our Happiness View. +我们没有完成 Happiness View + +42 +00:02:09,513 --> 00:02:12,280 +In fact, if I switch over to our HappinessViewController, +事实上,如果我切换到 HappinessViewController + +43 +00:02:12,282 --> 00:02:14,382 +you can see it is completely empty. +你可以看到它是完全空的 + +44 +00:02:14,384 --> 00:02:17,051 +So one thing we're gonna do is +我们将要做的一件事是 + +45 +00:02:17,053 --> 00:02:19,786 +fix our Model here but before we do that I'm gonna show you +修复我们的 Model,但是在我向你们演示之前 + +46 +00:02:19,788 --> 00:02:22,455 +something really cool that you can do in Storyboards. +我要跟你们讲一些可以在 Storyboards 里完成的很酷的事 + +47 +00:02:22,457 --> 00:02:26,359 +So here we have our story board and it's pretty blank. +这里是我们的 Storyboard,它是空白的 + +48 +00:02:26,361 --> 00:02:29,762 +It looks blank there's this big blank square here. +它看起来是空的因为那里有很大一块空白的地方 + +49 +00:02:29,764 --> 00:02:32,865 +This is our FaceView in here that I have selected. +在这里我选中的是我们的 FaceView + +50 +00:02:32,867 --> 00:02:36,168 +You can see the little resize handles are selected but +你可以看到小的调节手柄被选中了 + +51 +00:02:36,170 --> 00:02:38,403 +I can't even really tell that's a FaceView +但是我甚至不能告诉你那就是 FaceView + +52 +00:02:38,405 --> 00:02:40,638 +It's hard to tell where it is. +很难去描述出来他在哪儿 + +53 +00:02:40,640 --> 00:02:42,640 +It's just kinda hard to tell what's going on. +也很难描述这到底是怎么一回事 + +54 +00:02:42,642 --> 00:02:46,276 +And it's actually possible believe it or not to have your +不管你信不信,它实际上可以 + +55 +00:02:46,278 --> 00:02:51,381 +custom UIView subclasses draw in your Storyboard. +把你的自定义的 UIView 子类绘制在了你的 Storyboard 里 + +56 +00:02:51,383 --> 00:02:52,715 +Okay? So they can actually be +明白?所以他们实际上 + +57 +00:02:52,717 --> 00:02:54,784 +live drawing in your Storyboard. +已经在你的 Stroyboard 中被绘制了 + +58 +00:02:54,786 --> 00:02:56,985 +And it's really incredibly easy to do. +这真是令人难以置信的简单 + +59 +00:02:56,987 --> 00:02:59,121 +I'm just gonna go back to my FaceView. +我准备返回 FaceView + +60 +00:02:59,123 --> 00:03:01,173 +Here it is. +它在这里 + +61 +00:03:01,174 --> 00:03:03,224 +And right before the class here I'm gonna say +在这个类之前我输入 + +62 +00:03:03,226 --> 00:03:06,160 +at sign IBDesignable. +@IBDesignable + +63 +00:03:07,663 --> 00:03:11,264 +And if I put at sign IBDesignable in there, +如果我在这里放置 IBDesignable 标记 + +64 +00:03:11,266 --> 00:03:12,899 +then when I go back to my Storyboard, +然后当我返回 Storyboard 的时候 + +65 +00:03:12,901 --> 00:03:18,838 +Xcode automatically notices that's an IBDesignable +Xcode 会自动识别出来那是一个 IBDesignable 类 + +66 +00:03:18,840 --> 00:03:22,941 +class and it will draw it right here in the Storyboard, +然后它会在 Storyboard 中绘制它 + +67 +00:03:22,943 --> 00:03:26,511 +so now I can see much more easily what's going on with my +所以现在我可以更加容易地看到 FaceView 发生了什么变化 + +68 +00:03:26,513 --> 00:03:27,979 +FaceView, where it is here. +因为它在这里(被绘制出来了) + +69 +00:03:29,349 --> 00:03:31,582 +And if I change something in my FaceView, +然后如果我在 FaceView 中改变了什么的话 + +70 +00:03:31,584 --> 00:03:34,585 +like let's go change that smile so it's not a frown. +比如我们将笑脸换成不是皱眉的那个 + +71 +00:03:34,587 --> 00:03:37,821 +Whoops where is that, it's right here, minus 0.5. +Whoops 哪里去了,它在这里,-0.5 + +72 +00:03:37,823 --> 00:03:41,358 +Let's change that to plus 0.5. +让我们把它改成 0.5 + +73 +00:03:41,360 --> 00:03:45,028 +Then you'll notice that this file has changed and +然后你会发现这个文件被修改了 + +74 +00:03:45,030 --> 00:03:49,098 +it will recompile it and redraw it. +随后它将会重新编译并且绘制它 + +75 +00:03:49,100 --> 00:03:51,467 +Okay so you're always seeing the latest version. +所以你总是看到最新的版本 + +76 +00:03:51,469 --> 00:03:54,587 +Now another thing that would be really +这里还有另外一件很酷的事 + +77 +00:03:54,588 --> 00:03:57,706 +cool here is just like if we have a button or a label. +比如我们拥有一个 button 或一个 label + +78 +00:03:57,708 --> 00:04:00,708 +When we bring up the attributes inspector here +当我们在这里设置属性窗口中的内容 + +79 +00:04:00,710 --> 00:04:03,411 +we can edit attributes of a button or a label. +我们可以编辑 button或者 label的属性 + +80 +00:04:03,413 --> 00:04:04,812 +Right? Like its alignment or its font. +明白?类似于它的对齐方式或者字体 + +81 +00:04:04,814 --> 00:04:07,180 +Well wouldn't it be cool if we could edit the attributes of +想象一下如果我们在这里可以编辑 FaceView 的属性 + +82 +00:04:07,182 --> 00:04:09,115 +this FaceView here as well? +会不会变得很酷 + +83 +00:04:09,117 --> 00:04:11,101 +And we can do that too. +我们可以做到这一点 + +84 +00:04:11,102 --> 00:04:13,086 +If we go back here to the FaceView here's some of +如果我们返回到 FaceView 的这里 + +85 +00:04:13,088 --> 00:04:15,287 +the things that are setable about a FaceView. +这里是有一些地方是可以设置 FaceView 的 + +86 +00:04:15,289 --> 00:04:18,991 +The line width, the color, and the scale. +线宽、颜色和比例 + +87 +00:04:18,993 --> 00:04:24,329 +And you can make any of these things editable inside of your +你可以令这些属性在 Storyboard 中变成可设置的 + +88 +00:04:25,732 --> 00:04:30,234 +Storyboard by just putting in here IBInspectable. +方法很简单,就是在这里放置 @IBInspectable 标记 + +89 +00:04:31,437 --> 00:04:33,136 +Put IBInspectable before them. +在这些属性之前放置 @IBInspectable + +90 +00:04:34,105 --> 00:04:36,272 +Then Interface Builder, +然后 Interface Builder, + +91 +00:04:36,274 --> 00:04:39,041 +which is the part of Xcode that is doing part of your +这个 Xcode 的组件,这个完成 Storyboard 那部分工作的组件 + +92 +00:04:39,043 --> 00:04:46,414 +Storyboard will create a new UI to make all those editable. +会创建一个新的 UI 使所有的这些变成可设置的 + +93 +00:04:46,416 --> 00:04:48,400 +Here is our Storyboard. +这是我们的 Storyboard + +94 +00:04:48,401 --> 00:04:50,385 +Now if you look over here you can see FaceView. +现在你看这里,你可以看见 FaceView + +95 +00:04:50,387 --> 00:04:52,153 +It's added things to be able to set these. +这是新添加的选项,这些选项可以用来设置这些属性 + +96 +00:04:52,155 --> 00:04:54,588 +I can set things like my line width. +我可设置很多东西,比如我的线宽 + +97 +00:04:54,590 --> 00:04:57,190 +Maybe I want thicker lines. +也许我想要更粗的线条 + +98 +00:04:57,192 --> 00:04:58,892 +Maybe I want a different color. +也许我想要不同的颜色 + +99 +00:04:58,894 --> 00:05:00,626 +So we can go to the color chooser here. +所以我们可以打开颜色选择器 + +100 +00:05:00,628 --> 00:05:05,531 +We could pick green color or orange or something like that. +我们可以选择绿色或者橙色或者其他颜色 + +101 +00:05:05,533 --> 00:05:06,231 +Tangerine. +橘黄色 + +102 +00:05:06,233 --> 00:05:07,699 +It looks good. +看起来不错 + +103 +00:05:07,701 --> 00:05:09,734 +And we can change the scale as well, too. +我们同样也可以改变比例 + +104 +00:05:09,736 --> 00:05:14,071 +We can go down to 0.5, maybe we want to go 0.95, all right? +我们可以向下调整 0.5,或者我们想要调整 0.95,看到没? + +105 +00:05:14,073 --> 00:05:15,573 +We can change that. +我们可以改变这个参数 + +106 +00:05:15,574 --> 00:05:17,074 +Now, these are not only changing here in +现在,这些不仅仅是在你的 Storyboard 中改变了 + +107 +00:05:17,076 --> 00:05:19,776 +your Storyboard, but they're actually setting the default +实际上他们被当做了默认值 + +108 +00:05:19,778 --> 00:05:21,978 +value so that when you run your application, so +这样当你运行你的应用的时候 + +109 +00:05:21,980 --> 00:05:23,846 +let's go and run our application here. +现在让我们来运行一下我们的应用 + +110 +00:05:23,848 --> 00:05:25,814 +It's going to use these values that are set in +它将会使用这些你在 + +111 +00:05:25,816 --> 00:05:27,833 +the Storyboard. +Storyboard 中设置的参数 + +112 +00:05:27,834 --> 00:05:29,851 +Just like if those were buttons or labels and you had +如果这些是 button 或者 label 然后 + +113 +00:05:29,853 --> 00:05:33,321 +changed something about them in the inspector, it's going +你在 inspector 中改变了他们的一些参数 + +114 +00:05:33,323 --> 00:05:35,456 +to change the way it works in your program as well. +你的程序中这些参数的所代表的东西也会改变 + +115 +00:05:36,859 --> 00:05:38,809 +Yes, questions. +有问题么? + +116 +00:05:38,810 --> 00:05:40,760 +>> So that overwrites what's in your code? +>> 所以重写了在你的代码中写的那些参数? + +117 +00:05:40,763 --> 00:05:43,530 +>> Yes, so the question is does that overwrite what's in +>> 好的,问题是这是不是重写了在我们的代码中写的那些参数 + +118 +00:05:43,532 --> 00:05:44,430 +our code? +在我们的代码中写的那些参数? + +119 +00:05:44,432 --> 00:05:46,232 +So for example, back here. +举个例子,回到这里 + +120 +00:05:46,234 --> 00:05:49,535 +We had equals three, we had equals blue color and +我们写了 = 3,我们写了 = UIColor.blueColor() + +121 +00:05:49,537 --> 00:05:50,869 +the answer is yes, it overrides it. +答案是:是的,这重写了这些参数 + +122 +00:05:50,871 --> 00:05:54,272 +Basically, when interface loads it up it respects those. +基本上,当 interface 加载它的时候,interface 会参考这些参数 + +123 +00:05:54,274 --> 00:05:57,175 +It will use those but as soon as you start editing them, +它将会使用代码中设定的这些参数,但是当你设置这些参数的时候 + +124 +00:05:57,177 --> 00:05:59,110 +then it's going to override them and +它将会重写他们 + +125 +00:05:59,112 --> 00:06:00,344 +reset them to the editor value. +并将这些参数重置为编辑器的值 + +126 +00:06:01,613 --> 00:06:03,213 +Any other questions about that? +关于这里还有其他问题么? + +127 +00:06:03,215 --> 00:06:04,113 +Question? +你的问题是? + +128 +00:06:08,052 --> 00:06:09,651 +>> Yes, so the question is are there some, +>> 好的,问题是:这是不是 + +129 +00:06:09,653 --> 00:06:11,686 +there's got to be some gotchas, or something. +这里看上去像是个“陷阱”(需要注意的地方)什么的 + +130 +00:06:11,688 --> 00:06:15,323 +Why wouldn't it just be the ideal design be the default? +为什么不直接设置一个理想的默认值呢? + +131 +00:06:15,325 --> 00:06:17,992 +And, yes, there are some gotchas. +是的,这有一些“陷阱” + +132 +00:06:17,994 --> 00:06:22,796 +There's certain things that, really, it can't do. +有些事情,真的是,它做不了 + +133 +00:06:22,798 --> 00:06:26,466 +It can't load your code up, you might have dependencies on +因为它不能加载你的代码,比如,你也许依赖于 + +134 +00:06:26,468 --> 00:06:30,003 +other frameworks that it can't see, things like that. +另外一些看不见的 frameworks + +135 +00:06:30,005 --> 00:06:31,537 +So yeah, there are some gotchas, +所以,是有一些“陷阱” + +136 +00:06:31,539 --> 00:06:33,405 +I don't have time to go through them all but +我没有时间去把这些都讲一遍 + +137 +00:06:33,407 --> 00:06:35,340 +I just wanted to show you that this is here for +我把这些放在这里说是因为 + +138 +00:06:35,342 --> 00:06:37,175 +most straight forward subclass UIView, +这是跟 UIView 直接相关的 + +139 +00:06:37,177 --> 00:06:38,643 +it works great without gotchas. +它在没有“陷阱”的时候可以正常地运行 + +140 +00:06:38,645 --> 00:06:42,880 +But yeah, there are obviously some times when it's not going +但是,很明显地,也有一些时候它会出问题 + +141 +00:06:42,882 --> 00:06:46,683 +to work, because you could have a complicated view, so +因为你也许有一个复杂的 view + +142 +00:06:46,685 --> 00:06:49,152 +any other questions about it? +还有其他的问题么? + +143 +00:06:49,154 --> 00:06:50,519 +That's all there is to know about that. +这就是所有关于这部分的内容 + +144 +00:06:52,456 --> 00:06:55,957 +So let's go back to our Model here, or +所以让我们回到我们的 Model + +145 +00:06:55,959 --> 00:07:00,028 +to our controller, and I want to put the Model in here for +或者我们的 controller,然后我想在这里放一个 Model + +146 +00:07:00,030 --> 00:07:01,295 +the HappinessViewController. +提供给 HappinessViewController + +147 +00:07:01,297 --> 00:07:04,331 +So it's Model, because this is demoed and +这里是 Model,因为这是一个 demo + +148 +00:07:04,333 --> 00:07:06,199 +I want it all to be really quick and +并且我想要快点讲 + +149 +00:07:06,201 --> 00:07:08,868 +you can even follow along with me, some of you. +你们甚至可以跟着我,你们中的部分同学 + +150 +00:07:08,870 --> 00:07:10,370 +This Model's gonna be really simple. +这个 Model 将会变得非常简单 + +151 +00:07:10,372 --> 00:07:12,738 +I'm gonna have the Model of and +我将会创建一个 Model + +152 +00:07:12,740 --> 00:07:14,006 +a Model you know the Model is right? +一个 Model,你们知道什么是 Model 吧 + +153 +00:07:14,008 --> 00:07:16,141 +Your calculator's Model was a CalculatorBrain so +你的计算器的 Model 是一个 CalculatorBrain + +154 +00:07:16,143 --> 00:07:19,277 +it was a whole object that you created to be the Model. +所以你创建的 Model 是一整个对象 + +155 +00:07:19,279 --> 00:07:22,547 +Here I'm gonna have my Model be the happiness and +在这里我将使用 happiness 作为 Model + +156 +00:07:22,549 --> 00:07:25,082 +it's going to be the very complicated data structure of +这将是一个非常复杂的数据结构 + +157 +00:07:25,084 --> 00:07:26,216 +an Int. +一个 Int 型 + +158 +00:07:26,218 --> 00:07:28,135 +Okay. So +好的,所以 + +159 +00:07:28,136 --> 00:07:30,053 +we're gonna represent our happiness as an Int. +我们用一个 Int 型来代表我们的 happiness + +160 +00:07:30,055 --> 00:07:32,422 +And I'm gonna start it out at 50. +所以我把它的初始值设定为 50 + +161 +00:07:32,424 --> 00:07:36,559 +And I'm gonna have my happiness mean 0 is very sad, +然后我在这里注释:happiness 为 0 的时候代表非常伤心 + +162 +00:07:36,561 --> 00:07:39,094 +and 100 is ecstatic. +100 的时候代表欣喜若狂 + +163 +00:07:39,096 --> 00:07:40,462 +Okay? +明白? + +164 +00:07:40,464 --> 00:07:41,930 +So that's my Model. +所以那是我的 Model + +165 +00:07:41,932 --> 00:07:44,966 +Super duper simple Model, and don't get this Model confused +超级简单的一个 Model,然后不要将这个 Model 跟 + +166 +00:07:44,968 --> 00:07:46,801 +with the smiliness in the FaceView, +FaceView 中的 smiliness 混淆起来 + +167 +00:07:46,803 --> 00:07:49,903 +that's a different thing, that's just the angle of +那是一件不同的东西,这仅仅是 + +168 +00:07:49,905 --> 00:07:52,572 +that arc in the FaceView, totally separate thing. +FaceView 中圆弧的角度,完全独立的东西 + +169 +00:07:52,574 --> 00:07:54,808 +And you notice they're kind of on different scales anyways. +而且他们的取值也不同 + +170 +00:07:54,810 --> 00:07:55,842 +This is 0 to 100, +这是 0 到 100 + +171 +00:07:55,844 --> 00:08:00,379 +the smiliness is minus 1 to positive 1, etc. +smiliness 是 -1 到 +1,等等 + +172 +00:08:00,381 --> 00:08:01,680 +And that's okay because one of +那是没关系的,因为 + +173 +00:08:01,682 --> 00:08:05,883 +the things that controllers do, one of their jobs really, +controller 做的其中一件事,他们的其中一项工作 + +174 +00:08:05,885 --> 00:08:09,487 +is to interpret the Model for the view. +就是为 View 解释 Model + +175 +00:08:09,489 --> 00:08:11,755 +Okay, or vice versa in what happens in the view. +反之亦然 + +176 +00:08:11,757 --> 00:08:12,723 +And they have to figure out what to +他们必须弄清楚 + +177 +00:08:12,725 --> 00:08:13,941 +communicate to the Model. +用什么去和 Model 沟通 + +178 +00:08:13,942 --> 00:08:15,158 +That's a lot of what a controller does. +这就是 controller 做的大部分工作 + +179 +00:08:15,160 --> 00:08:17,026 +And so, we're going to have some coding here, +所以,我们准备在这里添加一些代码 + +180 +00:08:17,028 --> 00:08:19,712 +that does exactly that. +完成我刚才说的那些工作 + +181 +00:08:19,713 --> 00:08:22,397 +Interprets our 0 to 100 happiness into a smile or not. +将 0 到 100 的 happiness 转换成一个笑脸或哭脸 + +182 +00:08:22,400 --> 00:08:23,665 +Now there's other things that +除了微笑,还有其他的东西 + +183 +00:08:23,667 --> 00:08:25,567 +represent happiness besides smiling. +可以代表 happiness + +184 +00:08:25,569 --> 00:08:27,001 +You know, little crinkly eyes. +比如,有点弯曲的眼睛 + +185 +00:08:27,003 --> 00:08:29,870 +And other things that make you appear that you're happy. +和其他让你看起来快乐的东西 + +186 +00:08:29,872 --> 00:08:32,139 +But we're just gonna use our FaceView which only knows how +但我们只会使用我们的 FaceView,它只知道怎样 + +187 +00:08:32,141 --> 00:08:34,975 +to smile or not. +去微笑或者不微笑 + +188 +00:08:34,977 --> 00:08:39,846 +Now one thing that we can do inside this Model. +现在在这个 Model 中有一件事我们可以做 + +189 +00:08:41,282 --> 00:08:43,115 +I put the curly braces here and +我在这里添加一个大括号 + +190 +00:08:43,117 --> 00:08:44,750 +you might say why did I put that there? +你可能会问我为什么我把它放在这里? + +191 +00:08:44,752 --> 00:08:48,353 +That is because I want to use the property observer for +那是因为我想要对我的 Model 使用属性观察器来 + +192 +00:08:48,355 --> 00:08:52,790 +my Model to, essentially, validate my Model. +验证我的 Model + +193 +00:08:52,792 --> 00:08:55,359 +So you can use property observers to do evaluation, +所以你可以使用属性观察器去进行评估 + +194 +00:08:55,361 --> 00:08:57,527 +really, of any property that you want. +对任何你想查看的属性进行评估 + +195 +00:08:57,529 --> 00:08:59,829 +So my happiness can only be 0 to a 100. +所以我的 happiness 只能是 0 到 100 + +196 +00:08:59,831 --> 00:09:02,865 +If someone passes me happiness minus 1 or +如果有人给我的 happiness 传递了 -1 或者 + +197 +00:09:02,867 --> 00:09:07,236 +5,000 I need to kind of keep it in range to 0 to 100. +5000,我需要将它保持在 0 到 100 的范围内 + +198 +00:09:07,238 --> 00:09:09,871 +So I'm just going to say, in my setter here, +所以,我要写,在我的 setter 中 + +199 +00:09:09,873 --> 00:09:11,606 +my property observer here, +我的属性观察器中 + +200 +00:09:11,608 --> 00:09:18,279 +I'm going to say min max of my happiness to 0 or 100, +我要写 happiness 的最小和最大值是 0 和 100 + +201 +00:09:18,281 --> 00:09:21,048 +so I'm just keeping it between zero and a hundred, right? +因此我将把它保持在 0 到 100 之间, 对么? + +202 +00:09:21,050 --> 00:09:22,649 +So no matter what someone passes me -1 or 5000, +无论输入了 -1 还是 5000 + +203 +00:09:22,651 --> 00:09:24,718 +my happiness won't ever be outside of that. +我的 happiness 永远不会超出范围 + +204 +00:09:24,720 --> 00:09:26,986 +Again, this is kind of a trivial example. +再说一遍, 这是一个很简易的例子 + +205 +00:09:26,988 --> 00:09:28,854 +You might have a much powerful Model that +你可以有个更强大的 Model + +206 +00:09:28,856 --> 00:09:31,457 +needs much more powerful validation than this, +需要比这更严谨的评估 + +207 +00:09:31,459 --> 00:09:34,526 +but you can see this as a place to put it. +你可以把这些评估操作写在这里 + +208 +00:09:34,528 --> 00:09:36,461 +Another thing you might want to have here is if someone +你可能想做的另一件事情是 + +209 +00:09:36,463 --> 00:09:39,630 +updates your Model, you might want to update your UI. +如果有人改变了你的 Model, 你可能想要更新你的 UI + +210 +00:09:39,632 --> 00:09:42,333 +Okay, so I'm going to have updateUI, +好的, 因此我在这里进行 updateUI 操作 + +211 +00:09:42,335 --> 00:09:45,135 +and I'm just going to have a function down here, updateUI, +我将在下面这里加一个函数, 叫 updateUI + +212 +00:09:45,137 --> 00:09:49,205 +and it's going to do something to update the user interface, +它将会负责更新用户界面 + +213 +00:09:49,207 --> 00:09:50,073 +and that's a common thing. +更新 UI 是一件很寻常的事情 + +214 +00:09:50,075 --> 00:09:51,440 +When your Model changes, +当你的 Model 改变时 + +215 +00:09:51,442 --> 00:09:55,177 +you want your controller to cause the UI to be updated. +你想让你的 Controller 将 UI 更新 + +216 +00:09:55,179 --> 00:09:59,381 +I think I'm going to put in here also is a little println +我还会在这里写一句 + +217 +00:09:59,383 --> 00:10:07,855 +happiness equals back slash happiness. +println("happiness = \(happiness)") + +218 +00:10:07,857 --> 00:10:12,125 +Just so we can see our happiness changing in our +这样我们就能在接下来的演示中 + +219 +00:10:12,127 --> 00:10:15,962 +console all the time as we work the rest of the demos. +在 console(控制台)中看到 happiness 的变化情况 + +220 +00:10:15,964 --> 00:10:18,297 +So we'll work on this updateUI piece when we +好的,在我们之后重新进行演示的时候会完成 + +221 +00:10:18,299 --> 00:10:20,299 +get back to the demos. +updateUI() 这部分 + +222 +00:10:20,300 --> 00:10:22,300 +I just wanted to show you the Model of happiness. +我就是想向你们展示 Happiness 的 Model + +223 +00:10:22,303 --> 00:10:24,503 +Right now it's not hooked up to a it's UI. +现在, Model 并没有和 UI 关联 + +224 +00:10:24,505 --> 00:10:26,138 +So if I run my application, +因此, 如果我现在运行应用 + +225 +00:10:26,140 --> 00:10:31,109 +you'll see that this is not happiness of 50. +你们将会看到这并不是 happiness 为 50 的情况 + +226 +00:10:31,111 --> 00:10:34,979 +This is not even looking at the happiness. +这甚至跟这里鼠标所指的 happiness 没有任何关系 + +227 +00:10:34,981 --> 00:10:37,815 +I could change this to anything that I want and +我可以把这个变成任何我想要的值 + +228 +00:10:37,817 --> 00:10:40,350 +it's not going to change this. +但是这并不会改变运行结果 + +229 +00:10:40,352 --> 00:10:43,353 +And so later we'll show you how we hook up our UI +所以, 稍后我会向你们展示如何通过 Controller 连接 UI + +230 +00:10:43,355 --> 00:10:44,687 +to our Model through our controller, +与 Model 关联 + +231 +00:10:44,689 --> 00:10:46,555 +that's one of the main things a controller does. +这个是 Controller 的主要工作之一 + +232 +00:10:47,792 --> 00:10:51,026 +Okay, so let's go back to our slides though. +好的, 现在我们回到幻灯片 + +233 +00:10:51,028 --> 00:10:55,430 +All right here, I'm going to start with this miscellaneous +好的, 我将以这个混杂的 + +234 +00:10:55,432 --> 00:10:59,633 +topic here, kind of a bonus topic, which is extensions. +主题开始, 类似于额外的主题, 它就是 extensions(扩展) + +235 +00:10:59,635 --> 00:11:01,835 +You read about in your reading assignments, so +你已经在阅读作业里读到过了 + +236 +00:11:01,837 --> 00:11:03,770 +you know what this is, +你知道它是什么 + +237 +00:11:03,771 --> 00:11:05,704 +hopefully you've been reading those reading assignments. +希望你们一直以来都完成了阅读作业 + +238 +00:11:05,707 --> 00:11:07,373 +But I'm discovering here in class, +但是我在课中发现并没有很多人 + +239 +00:11:07,375 --> 00:11:09,975 +not as much because it's an important feature per se but +完成了阅读作业,因为这本身是个重要的特性但是 + +240 +00:11:09,977 --> 00:11:12,011 +it can be a little bit of a dangerous feature so +它(extensions)有时会变得有点危险 + +241 +00:11:12,013 --> 00:11:14,212 +I wanted to cover it a little bit. +因此我想讲一点这个 + +242 +00:11:14,214 --> 00:11:16,481 +So an extension is really simple. +extensions 真得很简单 + +243 +00:11:16,483 --> 00:11:20,685 +It's just a way, a little syntax, to add methods and properties to +它就是一个给一个现存类、结构和枚举 + +244 +00:11:20,687 --> 00:11:23,620 +existing classes, structures, and enums. +添加新方法或属性的小语法 + +245 +00:11:23,622 --> 00:11:25,355 +Okay? You do not have to +好么? 你无须修改 + +246 +00:11:25,356 --> 00:11:27,089 +have the source code to those things you're adding it to. +目标的源代码 + +247 +00:11:27,092 --> 00:11:29,893 +You could just add these methods and +你可以就把这些方法和属性 + +248 +00:11:29,895 --> 00:11:32,428 +properties pretty much at will. +想加就加 + +249 +00:11:32,430 --> 00:11:37,032 +There are some restrictions, one is that you can't add, via +这里有些限制, 其中之一是 + +250 +00:11:37,034 --> 00:11:41,136 +an extension, a method or property that already exists. +你不能通过 extensions 添加一个已存在的方法或特性 + +251 +00:11:42,105 --> 00:11:45,306 +So it's not a way to replace it, this is not sub classing, +因此这不是一个替换的手段, 这也不是创建子类 + +252 +00:11:45,308 --> 00:11:47,941 +you're not replacing or overwriting methods, so +你不能替换或者覆盖一个方法, 因此 + +253 +00:11:47,943 --> 00:11:49,810 +this has to be something where the property or +这些你想添加进类的 + +254 +00:11:49,812 --> 00:11:51,544 +method you wanna add to a class. +属性或方法 + +255 +00:11:52,514 --> 00:11:53,612 +Does not exist. +必须是之前不存在的 + +256 +00:11:53,614 --> 00:11:55,614 +The second thing is that any +第二个是 + +257 +00:11:55,615 --> 00:11:57,615 +properties you add cannot have any storage. +你添加的属性不能有存储 + +258 +00:11:57,618 --> 00:11:59,818 +Okay so they can only be computed properties, +Okay? 因此这些属性只能是运算属性 + +259 +00:11:59,820 --> 00:12:01,252 +right the get, set, kind. +有 get 和 set 方法的那些 + +260 +00:12:01,254 --> 00:12:03,454 +That's the only kind of property you can have. +那是你唯一能添加的一种属性 + +261 +00:12:04,424 --> 00:12:06,924 +Okay, but inside an extension otherwise it kind of +好的, 但是在一个 extension 中, 相反地, 它 + +262 +00:12:06,926 --> 00:12:09,026 +looks like you're in the definition of class. +看起来有点像你在定义类 + +263 +00:12:09,028 --> 00:12:10,694 +You can refer to self if you want and +你可以把它指向 self + +264 +00:12:10,696 --> 00:12:13,396 +that will be the thing that you are extending. +这样它就是你扩展的对象 + +265 +00:12:13,398 --> 00:12:15,698 +It's a pretty powerful feature actually. +这实际上是一个很强大的特性 + +266 +00:12:17,034 --> 00:12:21,169 +This feature is easily abused however people putting all +但是这个特性容易被误用, 人们把 + +267 +00:12:21,171 --> 00:12:24,139 +kinds of adding methods to classes making it so it's +一些方法加进类里把它变得 + +268 +00:12:24,141 --> 00:12:28,542 +completely not understandable of what that does anymore. +完全不能理解它是做什么的 + +269 +00:12:28,544 --> 00:12:32,713 +It's also whoever designed the class thinks a lot about it,it's +另外, 设计这个类的人考虑了很多关于 + +270 +00:12:32,715 --> 00:12:34,781 +API and what should be in it and what shouldn't and +它的 API 和它应包含的和不包含的内容 + +271 +00:12:34,783 --> 00:12:36,382 +now all of the sudden things are being added. +但是现在突然加了这么多东西 + +272 +00:12:36,384 --> 00:12:37,216 +That's kind of weird. +这有些奇怪 + +273 +00:12:38,252 --> 00:12:40,686 +This is really best used for beginners like you +它对你们这些初学 Swift 的人 + +274 +00:12:40,688 --> 00:12:44,556 +who are just starting with Swift to add little +最有用的地方是加入一些 + +275 +00:12:44,558 --> 00:12:47,859 +helper functions to enhance the readability of your code. +小的 helper function(帮助函数)以增强代码的可读性 + +276 +00:12:47,861 --> 00:12:49,193 +Okay, so if there's something that it would be +好的, 如果 CGRect 能做这件事 + +277 +00:12:49,195 --> 00:12:53,563 +really great if a CGRect could do this little thing, you +那么真的会很棒 + +278 +00:12:53,565 --> 00:12:55,665 +could add a little extension to a CGRect to do that. +你可以给 CGRect 加个 extension 来做到这点 + +279 +00:12:55,667 --> 00:12:58,067 +Or maybe a UIViewController just once. +或者给 UIViewController 加一次 + +280 +00:12:58,069 --> 00:13:01,137 +This extra little property that it can calculate about itself. +这个小小的能计算它本身的额外属性 + +281 +00:13:02,640 --> 00:13:05,307 +That's the kind of thing that you could use it for. +这就是你能用 extensions 做到的事情 + +282 +00:13:05,309 --> 00:13:09,010 +Now extensions actually can be used by advanced Swift users +现在 extensions 实际上能被进阶 Swift 用户 + +283 +00:13:10,179 --> 00:13:13,047 +to architects or, for architects, to really organize all your code. +用来整理或设计全部代码 + +284 +00:13:13,049 --> 00:13:14,682 +Because you can +因为你可以 + +285 +00:13:14,683 --> 00:13:16,316 +put almost everything into extensions, and +把几乎所有的东西放在 extensions 中 + +286 +00:13:16,318 --> 00:13:19,552 +use extensions as basically groupings of functionality. +并且将 extensions 主要用于功能的分组 + +287 +00:13:19,554 --> 00:13:21,988 +And so, it's really a powerful feature and +因此它真的是非常强大的特性 + +288 +00:13:21,990 --> 00:13:24,657 +I don't want to make it sound like it's only for +我不想让它听起来好像 + +289 +00:13:24,659 --> 00:13:28,060 +little kinda dribs and drabs add tiny little helper things. +只能零碎地加些 helper 函数 + +290 +00:13:28,062 --> 00:13:30,862 +It can actually be used as a core foundation of how you +其实它用作你的软件架构的核心基础 + +291 +00:13:30,864 --> 00:13:32,664 +architect. + +292 +00:13:32,665 --> 00:13:34,465 +But that does require some one to sit down and +但是完成它需要某人坐下来 + +293 +00:13:34,468 --> 00:13:36,634 +have an architectural plan to do that and +并且按照软件架构书来做 + +294 +00:13:36,636 --> 00:13:39,870 +you obviously a little early in the game to be doing that. +现在你们这样做很显然有点早了 + +295 +00:13:39,872 --> 00:13:42,206 +So I would say, when in doubt, if you're not sure whether or +因此, 我会说, 如果你有点迷惘 + +296 +00:13:42,208 --> 00:13:43,707 +not you should make something an extension, +不知道这里是否要加 extensions + +297 +00:13:43,709 --> 00:13:45,041 +don't do it for now. +现在这个阶段就不用加了 + +298 +00:13:45,043 --> 00:13:46,743 +And over time, you'll get more comfortable with it, +随着时间推移, 你会越来越适应使用它 + +299 +00:13:46,745 --> 00:13:49,345 +you'll understand what to do. +你会明白怎么做 + +300 +00:13:49,347 --> 00:13:51,246 +And again, the syntax for +再说一遍,它的语法 + +301 +00:13:51,248 --> 00:13:53,648 +it is all explained in the documentation. +在文档里都写得清清楚楚 + +302 +00:13:53,650 --> 00:13:57,085 +Maybe in the demo here, I'll try and throw one in, so +可能在今天的演示里, 我会加一个 + +303 +00:13:57,087 --> 00:13:59,087 +you can see what it looks like. +这样你们就能明白它是什么样的 + +304 +00:13:59,089 --> 00:14:00,588 +That was just an aside, +这些只是顺带提一提 + +305 +00:14:00,590 --> 00:14:03,390 +now let's get back to the main guts, okay? +现在我们回到真正的干货,好么? + +306 +00:14:03,392 --> 00:14:05,559 +This very important feature called delegation, +有个非常重要的特性叫做代理(delegation) + +307 +00:14:05,561 --> 00:14:07,427 +I have to teach you about protocols first, +我先要教你们协议(protocols) + +308 +00:14:07,429 --> 00:14:10,063 +again you probably read about this in reading assignments, +你们应该已经在阅读作业里读到过这些了 + +309 +00:14:10,065 --> 00:14:12,064 +but I want to go over it anyway. +不过我还是重头说一遍 + +310 +00:14:12,066 --> 00:14:15,534 +A protocol is basically a way to express your +一个协议基本上是 + +311 +00:14:15,536 --> 00:14:18,503 +API a little more minimally. +一种相对简便的表示 API 的方法 + +312 +00:14:18,505 --> 00:14:22,073 +Not to drag in so much API by, for example, +不是通过添加非常多的 API,比如 + +313 +00:14:22,075 --> 00:14:25,376 +having an argument to a function be a class where now +传递一个代表类的参数给函数 + +314 +00:14:25,378 --> 00:14:27,545 +you're passing an entire class into that function, +你把整个类传递给了那个函数 + +315 +00:14:27,547 --> 00:14:30,047 +who knows what that function might do with that class. +谁知道那个函数会对那个类做什么 + +316 +00:14:30,049 --> 00:14:34,017 +It could access the entire non private API of that thing. +它可能会访问类的所有非私有 API + +317 +00:14:34,019 --> 00:14:36,586 +So really, the function just wants to use the one method of +所以,说真的,这个函数只是想用类中 + +318 +00:14:36,588 --> 00:14:37,520 +a class. +的一个方法而已 + +319 +00:14:37,522 --> 00:14:39,689 +Protocols are a way for +协议是函数的一种表达方式 + +320 +00:14:39,690 --> 00:14:41,857 +the function to express or really, I just want you to +或者,我只是想让你给我 + +321 +00:14:41,859 --> 00:14:43,926 +pass me something that can do this one function. +传递一些能让这个函数运作的东西 + +322 +00:14:43,928 --> 00:14:45,894 +Because that's what I'm going to call in here. +因为我要在这里调用这些东西 + +323 +00:14:45,896 --> 00:14:49,197 +So, it's a way to kind of minimize your API. +所以,这是一个简化 API 的方法 + +324 +00:14:49,199 --> 00:14:51,432 +A protocol is a type. +一个协议是一个数据类型 + +325 +00:14:51,434 --> 00:14:54,535 +Okay, it's just like a class, or an enum, or a struct. +就像一个类(class),或者枚举(enum),或者结构(struct) + +326 +00:14:54,537 --> 00:14:55,620 +Okay. It's a type. +它是一个数据类型 + +327 +00:14:55,621 --> 00:14:56,704 +It can be used everywhere a type is. +它可以被用在任何数据类型能用的地方 + +328 +00:14:56,706 --> 00:14:58,372 +A type of an argument to a function. +一个函数的参数 + +329 +00:14:58,374 --> 00:15:02,342 +A var or a let can be a protocol +一个变量或者一个常量也能是一个协议类型 + +330 +00:15:02,344 --> 00:15:04,844 +Type. So it is absolutely a type. +因此它绝对是一个数据类型 + +331 +00:15:04,846 --> 00:15:07,112 +The only thing that is interesting about it is it +唯一有趣的地方是 + +332 +00:15:07,114 --> 00:15:08,380 +has no implementation. +协议本身是没有实现的 + +333 +00:15:09,349 --> 00:15:10,999 +Okay? + +334 +00:15:11,000 --> 00:15:12,650 +In fact, it's kind of the definition of a protocol, +事实上,这类似于协议的定义 + +335 +00:15:12,652 --> 00:15:15,052 +it's a type with no implementation. +这是一个没有实现的数据类型 + +336 +00:15:15,054 --> 00:15:16,553 +It only has declaration. +它只有声明 + +337 +00:15:17,623 --> 00:15:20,623 +Use a protocol to declare various properties and +协议用来声明各种各样的属性 + +338 +00:15:20,625 --> 00:15:22,191 +methods but it has no implementation. +和方法,但是没有相应的实现 + +339 +00:15:22,193 --> 00:15:25,628 +The implementation is provided by other objects that conform +这个实现是由其它遵从协议的对象 + +340 +00:15:25,630 --> 00:15:27,162 +to the protocol. +提供的 + +341 +00:15:27,164 --> 00:15:29,214 +Okay, and there might be +可能会有成百个 + +342 +00:15:29,215 --> 00:15:31,265 +hundreds of objects that will conform to a certain protocol. +遵从某一个协议的对象 + +343 +00:15:31,268 --> 00:15:33,635 +Okay? + +344 +00:15:33,636 --> 00:15:36,003 +But the protocol when you use it looks just like a type, +但是,协议在使用的时候就像数据类型 + +345 +00:15:36,006 --> 00:15:37,605 +exactly like a type as you're gonna see here. +你们将会看到,跟数据类型一模一样 + +346 +00:15:37,607 --> 00:15:41,409 +Now there's three aspects to a protocol, to using one. +这有三个使用协议的条件 + +347 +00:15:41,411 --> 00:15:43,277 +One is the declaration of the protocol. +一个是协议的声明 + +348 +00:15:43,279 --> 00:15:45,112 +This looks a lot like declaring your class or +这看起来很像声明你的类 + +349 +00:15:45,114 --> 00:15:46,346 +an enum or struct. +或者枚举或者结构 + +350 +00:15:46,348 --> 00:15:47,847 +It's just that there is no implementations for +它仅仅是没有任何属性或方法 + +351 +00:15:47,849 --> 00:15:49,782 +any of the properties or methods. +的实现 + +352 +00:15:49,784 --> 00:15:52,484 +Then there's the declaration part where a class or +接下来是声明的部分 + +353 +00:15:52,486 --> 00:15:56,455 +a struct or an enum says, I will implement this protocol. +如果一个类、结构或者枚举说我会实现这个协议 + +354 +00:15:56,457 --> 00:15:59,724 +So it declares that it will conform to, or implement, +因此它声明它会遵从或者实现 + +355 +00:15:59,726 --> 00:16:00,958 +this protocol. +这个协议 + +356 +00:16:00,960 --> 00:16:03,294 +And then there's the part where that class, struct or +接着,在类、结构或者枚举中 + +357 +00:16:03,296 --> 00:16:05,095 +enum actually implements the protocol. +会有负责实现协议的部分 + +358 +00:16:05,097 --> 00:16:07,064 +So, it implements that, all the properties and +所以,它会实现所有在协议中需要的 + +359 +00:16:07,066 --> 00:16:09,833 +methods in the protocol that's required, all of them. +属性和方法 + +360 +00:16:09,835 --> 00:16:11,351 +Okay? + +361 +00:16:11,352 --> 00:16:12,868 +So we'll see what that looks like in some code. +我们会在几行代码里看到(协议)到底是怎样 + +362 +00:16:12,871 --> 00:16:15,871 +So here's a declaration of a protocol itself, okay? +这里是一个协议自身的声明 + +363 +00:16:15,873 --> 00:16:19,107 +The protocol's called SomeProtocol, all right? +这个协议叫做 SomeProtocol + +364 +00:16:20,877 --> 00:16:25,179 +This protocol has really what some might call +这个协议有些叫做 + +365 +00:16:25,181 --> 00:16:27,981 +inherited protocols, or a protocol that inherits. +继承协议,或者,一个协议它能够继承 + +366 +00:16:27,983 --> 00:16:31,218 +Which are other protocols that if you want to implement some +如果你想要实现某些协议 + +367 +00:16:31,220 --> 00:16:33,586 +protocol you have to implement those too. +你必须也将这些继承协议实现 + +368 +00:16:33,588 --> 00:16:35,188 +Okay that's what this colon thing, so +这就是代码里冒号所代表的 + +369 +00:16:35,190 --> 00:16:37,390 +it kind of looks like this superclass kind of thing but +这感觉上有点像父类(superclass) + +370 +00:16:37,392 --> 00:16:39,491 +there can be multiple of them, but it's not really +但是能够有多个继承协议 + +371 +00:16:39,493 --> 00:16:42,060 +inherent in this, per se, like you think of in classes, it's +继承协议并不是跟你想象中的类那样 + +372 +00:16:42,062 --> 00:16:44,429 +more just saying if you want to implement SomeProtocol you +我想说的是,如果你想要实现 SomeProtocol 这个协议 + +373 +00:16:44,431 --> 00:16:46,497 +also have to implement inherited protocol one and +你必须还要实现继承协议 1 + +374 +00:16:46,499 --> 00:16:47,665 +inherited protocol two. +以及继承协议 2 + +375 +00:16:47,667 --> 00:16:48,766 +If you don't implement those then you +如果你没有实现这些 + +376 +00:16:48,768 --> 00:16:51,268 +haven't implemented all of SomeProtocol. +那你就没有实现这个 SomeProtocol 协议 + +377 +00:16:51,270 --> 00:16:51,835 +Okay? + +378 +00:16:52,871 --> 00:16:57,406 +Now you have to specify, when you do a property, +现在你必须明确,当你设计一个属性 + +379 +00:16:57,408 --> 00:16:58,740 +you don't put the implementation there but +你并不加入实现部分 + +380 +00:16:58,742 --> 00:17:01,976 +you have to classify whether this is a get only property or +但是你必须区分这是一个只有 get 的属性 + +381 +00:17:01,978 --> 00:17:04,012 +it's a get and set, okay? +还是既有 get 也有 set + +382 +00:17:04,014 --> 00:17:05,279 +The system needs to know whether it's +系统需要知道它是否是一个 set 方法 + +383 +00:17:05,281 --> 00:17:08,182 +a set because structs and enums are value types and +因为结构和枚举都是数值类型并且 + +384 +00:17:08,184 --> 00:17:09,950 +it needs to know when it's being mutated so +它需要知道什么时候被改变 + +385 +00:17:09,952 --> 00:17:12,852 +it can copy them and etcetera, okay? +这样的话它才能复制和其他之类的 + +386 +00:17:12,854 --> 00:17:17,223 +Any functions that are expected to mutate also need +任何可能会被更改的函数还需要 + +387 +00:17:17,225 --> 00:17:20,492 +to be noted with this mutating keyword, okay? +用这个 mutating 关键字标注 + +388 +00:17:20,494 --> 00:17:22,060 +You probably read that in the description, +你可能在描述文件里读到了 + +389 +00:17:22,062 --> 00:17:24,095 +you know that structs and enums, +你知道结构和枚举 + +390 +00:17:24,097 --> 00:17:27,398 +these are value types, the system needs to know when a function +是数值类型,系统需要知道函数 + +391 +00:17:27,400 --> 00:17:31,869 +is actually changing them, so they can copy it on demand. +具体什么时候会改变它们,这样它们能根据需求复制 + +392 +00:17:33,272 --> 00:17:36,039 +It is possible to limit your protocol to only work +限制你的协议只用类实现 + +393 +00:17:36,041 --> 00:17:38,141 +with classes. +是可行的 + +394 +00:17:38,142 --> 00:17:40,242 +You put the word class right after that colon. +你把 class 这个词放在那个冒号后面 + +395 +00:17:40,245 --> 00:17:42,878 +So SomeProtocol colon class means this protocol can +这样 SomeProtocol : class 意味着 + +396 +00:17:42,880 --> 00:17:44,279 +only be implemented by a class. +它只能被类实现 + +397 +00:17:44,281 --> 00:17:46,782 +It cannot be implemented by a struct or an enum. +它不能被结构或者枚举实现 + +398 +00:17:46,784 --> 00:17:47,549 +Okay? Then you wouldn't need +这样你不需要 + +399 +00:17:47,551 --> 00:17:49,584 +any mutatings because a class, +mutating 关键字,因为这是一个类 + +400 +00:17:49,586 --> 00:17:52,620 +since it's a reference passed by reference all the time, +这是个引用,并且一直以引用被传递 + +403 +00:17:52,622 --> 00:17:56,190 +you can obviously mutate with any method or property. +因此你可以通过任何方法或者属性进行改变 + +404 +00:17:56,192 --> 00:17:59,226 +Okay, you can even specify that +你甚至可以设计 + +405 +00:17:59,228 --> 00:18:02,095 +a protocol requires the class or +一个协议,要求这个类或者 + +406 +00:18:02,097 --> 00:18:05,531 +structure enum to implement a certain initializer. +结构枚举去实现特定的初始化函数 + +407 +00:18:05,533 --> 00:18:06,833 +Okay, that way you +通过这种方式,你知道你可以创建 + +408 +00:18:06,834 --> 00:18:08,134 +know that you can create one of these things. +这些东西中的一个 + +409 +00:18:08,136 --> 00:18:11,136 +All right. So, that's kinda cool too. +这非常酷 + +410 +00:18:11,138 --> 00:18:15,106 +All right, so that's how you declare a protocol. +这就是你要怎样声明一个协议 + +411 +00:18:15,108 --> 00:18:16,741 +See? It's pretty straightforward. +看到了吗?非常直观 + +412 +00:18:16,743 --> 00:18:18,242 +No implementations in here, right? +这里没有实现 + +413 +00:18:19,445 --> 00:18:22,279 +All right, so now let's talk about the part of it where it +现在我们要讲的是 + +414 +00:18:22,281 --> 00:18:23,680 +says I'm an implementer. +如果我是一个实现人员 + +415 +00:18:23,682 --> 00:18:24,881 +I want to implement this protocol. +我想实现这个协议 + +416 +00:18:24,883 --> 00:18:28,250 +How do I tell the world I'm going to implement this? +我怎么告诉这个世界我要实现它? + +417 +00:18:28,252 --> 00:18:31,353 +You do that by putting at +要实现它,你要将它放在 + +418 +00:18:31,355 --> 00:18:34,389 +the end of the declaration of the thing, so here's class, +声明的末尾,这是个类 + +419 +00:18:34,391 --> 00:18:37,625 +SomeClass then it inherits from SuperclassOfSomeClass. +SomeClass 继承自 SuperclassOfSomeClass + +420 +00:18:37,627 --> 00:18:40,361 +You just put a comma and all the protocols that +你可以放个逗号,还有这个类将要实现的 + +421 +00:18:40,363 --> 00:18:43,998 +this class is claiming to implement, okay? +所有协议 + +422 +00:18:44,000 --> 00:18:46,800 +Now, obviously if this was a struct or +显然,如果这是个结构或者枚举 + +423 +00:18:46,802 --> 00:18:49,302 +enum it wouldn't have that superclass name. +那么它没有父类 + +424 +00:18:49,304 --> 00:18:51,004 +So it would just be colon and then the list of +因此,它就只有一个冒号 + +425 +00:18:51,006 --> 00:18:53,873 +all the protocols that it is claiming to implement. +还有它将实现的所有协议 + +426 +00:18:53,875 --> 00:18:56,175 +So this enum says it's going to implement SomeProtocol, +这个枚举将实现 SomeProtocol 协议 + +427 +00:18:56,177 --> 00:18:58,077 +and it's also going to implement AnotherProtocol. +同时它也将实现 AnotherProtocol 协议 + +428 +00:18:58,079 --> 00:19:00,012 +And once it says that, it has to do it or +一旦它声明了,它就必须实现(协议) + +429 +00:19:00,014 --> 00:19:03,148 +the compiler will not allow you to compile, okay? +否则编译器不让你通过编译 + +430 +00:19:03,150 --> 00:19:05,583 +Same thing with the struct, all right? +结构也是一样的 + +431 +00:19:05,585 --> 00:19:09,486 +So pretty straightforward syntax there. +这是非常直观的语法 + +432 +00:19:09,488 --> 00:19:11,722 +The number of protocols is unlimited, +协议的数量是无限的 + +433 +00:19:11,724 --> 00:19:13,590 +you can just keep putting more and +你可以一直把越来越多你将实现的 + +434 +00:19:13,592 --> 00:19:16,359 +more protocols that you say you'll implement. +协议放进去 + +435 +00:19:16,361 --> 00:19:19,428 +In a class, if you implement an init in a class, +在一个类中,如果你实现了一个类的初始化函数 + +436 +00:19:19,430 --> 00:19:22,464 +you have to say it's required. +你必须使用 required 关键字 + +437 +00:19:22,466 --> 00:19:24,516 +Okay? + +438 +00:19:24,517 --> 00:19:26,567 +So that's because you wouldn't want a subclasser +这是因为你不希望一个子类 + +439 +00:19:26,570 --> 00:19:29,170 +using the rules of inheritance of initializers which we +使用初始化函数的继承规则,这个我们 + +440 +00:19:29,172 --> 00:19:32,507 +talked about in depth last lecture or the one before. +在上次课或上上次课有深入讲解过 + +441 +00:19:32,509 --> 00:19:35,176 +It can get to a situation where that init is +这有可能导致这样一种情况:子类 + +442 +00:19:35,178 --> 00:19:37,644 +not even implemented, okay, in subclass. +没有实现初始化函数 + +443 +00:19:37,646 --> 00:19:39,546 +And that would be no good because you're saying +这样不好,因为你既然遵循了 + +444 +00:19:39,548 --> 00:19:42,115 +you conform to this protocol and then that init is part of +这个协议,那初始化函数就是协议的一部分 + +445 +00:19:42,117 --> 00:19:44,117 +this protocol so you have to make them required. +所以你必须将它们标为 required + +446 +00:19:45,086 --> 00:19:45,651 +Okay? + +447 +00:19:46,653 --> 00:19:51,055 +You are allowed to add protocol compliance or +你可以使用扩展(extension)来补充 + +448 +00:19:51,057 --> 00:19:53,324 +conformance with an extension. +协议的一致性 + +449 +00:19:54,393 --> 00:19:56,643 +And this is very common to do, +这很常用 + +450 +00:19:56,644 --> 00:19:58,894 +again, in a bigger architected system, is you will implement +在一个大一点的架构系统中,你在类或结构枚举上 + +451 +00:19:58,897 --> 00:20:02,432 +the entire implementation of a protocol on some class or +实现整个协议的内容是 + +452 +00:20:02,434 --> 00:20:06,035 +structure enum by implementing it as an extension. +通过扩展来实现的 + +453 +00:20:06,037 --> 00:20:07,636 +Now the only thing about that implementation is, +现在关于这个实现的唯一事情是 + +454 +00:20:07,638 --> 00:20:09,338 +of course, no stored properties in there. +当然,这里没有存储属性 + +455 +00:20:09,340 --> 00:20:10,238 +Only computed properties. +只有计算属性 + +456 +00:20:10,240 --> 00:20:12,340 +So you would have to be able to +所以你不需要任何存储就能够实现 + +457 +00:20:12,341 --> 00:20:14,441 +implement that entire protocol without any storage. +整个协议 + +458 +00:20:14,444 --> 00:20:16,978 +But a lot of protocols can be implemented without storage. +但很多协议可以不需要任何存储就实现了 + +459 +00:20:16,980 --> 00:20:20,314 +Cuz they're fairly simple protocols, okay. +因为它们是些相当简单的协议 + +460 +00:20:22,451 --> 00:20:26,286 +Here's what it looks like to use a protocol as a type. +将协议当作一个类型来用是这样子的 + +461 +00:20:26,288 --> 00:20:30,389 +So I've created a protocol called Moveable. +我已创建了一个协议,叫做 Moveable + +462 +00:20:30,391 --> 00:20:31,657 +It has one function in it, +它有一个函数 + +463 +00:20:31,659 --> 00:20:35,994 +moveTo, which presumably moves the thing. +moveTo,这个函数大概是移动这个东西的 + +464 +00:20:35,996 --> 00:20:37,929 +I've created two things, +我创建了两个东西 + +465 +00:20:37,931 --> 00:20:40,664 +a class called Car which is a Moveable. +一个叫做 Car 的类,这是一个 Moveable + +466 +00:20:40,666 --> 00:20:43,534 +So the Car can be moved, and a class called, +因此这个 Car 可以被移动,还有一个类 + +467 +00:20:43,536 --> 00:20:46,303 +or struct rather called Shape which can be moveable, so this +更确切地说是结构,叫做 Shape,这个可以被移动 + +468 +00:20:46,305 --> 00:20:48,571 +might be a graphical shape that can be moved on screen. +这可能是一个可以在屏幕上被移动的图形形状 + +469 +00:20:48,573 --> 00:20:49,872 +Now you see that Car and +现在你看到 Car 和 + +470 +00:20:49,874 --> 00:20:52,608 +Shape are completely different kinds of things, but +Shape 是两个完全不同的东西 + +471 +00:20:52,610 --> 00:20:55,711 +they both could be moved, so they both could be Movables. +但它们都能被移动,所以它们都是 Movable + +472 +00:20:55,713 --> 00:20:59,081 +And you can see that they both properly implement the movable +你们看,它们都正确地实现了 Movable 协议 + +473 +00:20:59,083 --> 00:21:02,150 +protocol and they both claimed implement movable. +并且声明实现了 Movable + +474 +00:21:02,152 --> 00:21:06,287 +Then I've created a couple of little variables here prius +然后我创建了几个变量,prius 和 + +475 +00:21:06,289 --> 00:21:10,090 +and square which are just instances of Car and Shape. +square,分别是 Car 和 Shape 的实例 + +476 +00:21:11,260 --> 00:21:14,094 +Okay, so now let's look at some code. +现在我们来看一些代码 + +477 +00:21:14,096 --> 00:21:17,563 +I can create a variable called thingToMove. +我可以创建一个变量,叫做 thingToMove + +478 +00:21:17,565 --> 00:21:19,899 +It is of type Moveable. +这是 Moveable 类型 + +479 +00:21:19,901 --> 00:21:22,001 +That's protocol, but protocols are types. +那是协议,但协议都是类型 + +480 +00:21:22,003 --> 00:21:23,301 +And I can set it equal to prius. +我可以让它等于 prius + +481 +00:21:23,303 --> 00:21:26,504 +This is completely legal because a prius +这是完全合法的,因为一个 prius + +482 +00:21:26,506 --> 00:21:28,172 +is a Moveable, right? +就是一个 Moveable + +483 +00:21:28,174 --> 00:21:29,507 +It implements the Moveable protocol. +它实现了 Moveable 协议 + +484 +00:21:29,509 --> 00:21:32,409 +So I can set a variable that is Moveable to a prius, +因此我可以将一个 Moveable 的变量赋值 prius + +485 +00:21:32,411 --> 00:21:32,976 +works great. +非常棒 + +486 +00:21:33,912 --> 00:21:36,713 +I can then say thingToMove, move to. +然后我可以使用 thingToMove.moveTo() + +487 +00:21:36,715 --> 00:21:40,216 +Because thingToMove is anything that implements +因为 thingToMove 是一个实现了 Moveable + +488 +00:21:40,218 --> 00:21:41,250 +the Moveable protocol. +协议的任何东西 + +489 +00:21:41,252 --> 00:21:46,955 +However, I cannot say thingMoveTo.changeOil(), okay? +然而,我不能使用 thingMoveTo.changeOil() + +490 +00:21:46,957 --> 00:21:49,190 +ChangeOil is a Car thing, +changOil 是 Car 的方法 + +491 +00:21:49,192 --> 00:21:51,359 +it's not a Moveable thing, okay? +不是 Moveable 的方法 + +492 +00:21:51,361 --> 00:21:52,893 +So I can't send it to a Moveable. +所以我不能在 Moveable 中调用它 + +493 +00:21:54,463 --> 00:21:56,396 +Even though, yes, +尽管 + +494 +00:21:56,397 --> 00:21:58,330 +that thingToMove happens to currently contain a Car +这个 thingToMove 恰好包含了一个 Car + +495 +00:21:58,333 --> 00:22:01,034 +it's still a compiler won't even let you put this in. +但是编译器依然不会让你这样使用 + +496 +00:22:01,036 --> 00:22:02,001 +It'll complain. +它会报错 + +497 +00:22:02,003 --> 00:22:04,436 +It'll say, thingToMove is a Moveable. +它会说,thingToMove 是一个 Moveable + +498 +00:22:04,438 --> 00:22:05,904 +Moveables don't understand changeOil. +Moveable 不懂 changeOil + +499 +00:22:05,906 --> 00:22:07,639 +You understand? +明白了吗? + +500 +00:22:08,842 --> 00:22:12,176 +I could then say thingToMove equal square. +我可以让 thingToMove 等于 square + +501 +00:22:12,178 --> 00:22:15,279 +That's perfectly legal as well cuz a square is a Moveable. +这是相当合法的,因为 square 是一个 Moveable + +502 +00:22:15,281 --> 00:22:17,147 +It implements that protocol so it can do it as well. +它实现了这个协议,所以这也是可以的 + +503 +00:22:18,550 --> 00:22:23,619 +More interestingly I could let thingsToMove be an array of +更有趣的是,我可以让 thingsToMove 为一个 + +504 +00:22:23,621 --> 00:22:26,855 +Moveable, and I could set it equal to an array that +包含 prius 和 square 的 + +505 +00:22:26,857 --> 00:22:28,690 +has a prius and a square in it. +Moveable 数组 + +506 +00:22:28,692 --> 00:22:34,862 +So it's got a Car and a Shape, a class and a struct, +所以它有一个 Car 和一个 Shape,一个类和一个结构 + +507 +00:22:34,864 --> 00:22:37,031 +all in this array and it's perfectly legal because +都在这个数组中,这是完全合法的 + +508 +00:22:37,033 --> 00:22:39,566 +they're both Moveable so I can create an array of them +因为它们都是 Moveable,因此我可以创建关于它们的数组 + +509 +00:22:39,568 --> 00:22:42,035 +because Moveable is a protocol It's just like a type. +因为 Moveable 是一个协议,就如同一种类型 + +510 +00:22:42,037 --> 00:22:42,602 +It is a type. +它就是一种类型 + +511 +00:22:44,472 --> 00:22:45,771 +Okay, make sense? +有道理吧? + +512 +00:22:45,773 --> 00:22:47,973 +Why can I do that? +为什么我能这样做? + +513 +00:22:47,975 --> 00:22:50,742 +All right I can also have a function like slide, +当然我也可以有一个函数 slide + +514 +00:22:50,744 --> 00:22:53,712 +let's say that slide something along the ground or +就是在地上或其他地方滑动某物 + +515 +00:22:53,714 --> 00:22:57,315 +something, and you can take an argument which is a Moveable. +你可以使用 Moveable 的参数 + +516 +00:22:57,317 --> 00:22:59,483 +And then inside of it I can say moveTo and +然后在函数里面,我可以使用 moveTo + +517 +00:22:59,485 --> 00:23:01,719 +that works fine, and I say slide prius, +这能正常工作,我可以使用 slide(prius) + +518 +00:23:01,721 --> 00:23:04,254 +slide square, all works fine because. +slide(square),都能正常工作 + +519 +00:23:04,256 --> 00:23:04,921 +They're all Moveable. +因为它们都是 Moveable + +520 +00:23:04,923 --> 00:23:08,458 +It's actually possible to declare an argument like slipAndSlide +事实上,声明一个 slipAndSlide 是可以的 + +521 +00:23:08,460 --> 00:23:12,294 +that implements two, that takes an argument +这个实现了两个,带一个参数,这个参数 + +522 +00:23:12,296 --> 00:23:14,730 +that has to implement two separate protocols. +必须实现两个不同的协议 + +523 +00:23:14,732 --> 00:23:17,265 +Moveable, but also something called Slippery, let's say, +Moveable,还有 Slippery,Slippery 这个 + +524 +00:23:17,267 --> 00:23:18,566 +which I haven't defined. +我还没定义 + +525 +00:23:18,568 --> 00:23:20,051 +Okay, so + +526 +00:23:20,052 --> 00:23:21,535 +this little thing where you say protocol angle bracket and +这个东西,你使用 protocol <,然后很多你想 + +527 +00:23:21,538 --> 00:23:24,305 +then as many protocols as you want closed angle bracket, +实现的协议,最后以 > 结束 + +528 +00:23:24,307 --> 00:23:27,241 +that says this argument to this function has to implement +这表明这个参数必须同时实现 + +529 +00:23:27,243 --> 00:23:29,076 +both of those protocols. +这两个协议 + +530 +00:23:29,078 --> 00:23:31,211 +Or all of those protocols. +或者所有这些协议 + +531 +00:23:31,213 --> 00:23:32,445 +And then if I tried to say slipAndSlide(prius) +如果我试图使用 slipAndSlide(prius) + +532 +00:23:32,447 --> 00:23:35,014 +not even compile. +是不能通过编译的 + +533 +00:23:35,016 --> 00:23:36,749 +Because while Prius is a Moveable, +因为 prius 是一个 Moveable + +534 +00:23:36,751 --> 00:23:38,216 +it's not as Slippery. +不是 Slippery + +535 +00:23:38,218 --> 00:23:39,918 +And so it can't do that. +所以不能这么做 + +536 +00:23:39,920 --> 00:23:43,821 +Can't be passed through that argument, okay? +不能传递这个参数 + +537 +00:23:43,823 --> 00:23:44,888 +Everyone cool with protocols? +每个人都理解协议了吗? + +538 +00:23:44,890 --> 00:23:46,590 +Any question about that before I +在我开始讲解使用协议的代理(delegation)前,还有人 + +539 +00:23:46,591 --> 00:23:48,291 +start talking about delegation which uses protocols? +有问题吗? + +540 +00:23:49,894 --> 00:23:51,744 +Okay. So + +541 +00:23:51,745 --> 00:23:53,595 +delegation is a very important use of protocols. +代理是协议的一个非常重要用途 + +542 +00:23:53,598 --> 00:23:56,832 +Delegation, if you remember back to our MVC talk right at +代理,如果你记得我们这学期刚开始讲的 MVC + +543 +00:23:56,834 --> 00:23:59,901 +the beginning of the quarter, we had this big graph. +我们有这个大图 + +544 +00:23:59,903 --> 00:24:02,704 +And one of the things we showed was how Views need to +我们讲的其中一点是,View 如何与它们的 + +545 +00:24:02,706 --> 00:24:05,306 +be able to talk back to their Controller, okay? +Controller 通讯 + +546 +00:24:05,308 --> 00:24:07,174 +But Views are generic. +但 View 是普通的 + +547 +00:24:07,176 --> 00:24:09,276 +So, they can't know anything about the class or +因此它们不知道使用它们的 + +548 +00:24:09,278 --> 00:24:10,744 +the Controller that's using them. +类或者 Controller + +549 +00:24:10,746 --> 00:24:12,579 +They're generic building blocks. +它们是普通的积木 + +550 +00:24:12,581 --> 00:24:14,180 +Okay? So how do they talk back? +那它们是怎么通讯的? + +551 +00:24:14,182 --> 00:24:16,649 +Well, it turns out they talk back using protocols, okay, +实际上它们使用协议进行通讯 + +552 +00:24:16,651 --> 00:24:18,817 +and this is called delegation. +这个叫做代理 + +553 +00:24:18,819 --> 00:24:19,384 +Okay? + +554 +00:24:20,554 --> 00:24:22,887 +So, let's talk a little bit about how that works, +让我们讲讲这是如何工作的 + +555 +00:24:22,889 --> 00:24:24,989 +how it plays out to do delegation. +代理是如何进行的 + +556 +00:24:24,991 --> 00:24:27,291 +First, you're gonna create the delegate protocol. +首先,你要创建一个代理协议 + +557 +00:24:27,293 --> 00:24:29,626 +So, the delegate protocol is just gonna be protocol, +这个代理协议是一个 + +558 +00:24:29,628 --> 00:24:31,661 +something with a bunch of methods and +包含了许多方法的协议,也 + +559 +00:24:31,663 --> 00:24:33,529 +perhaps even properties. +可能包含属性 + +560 +00:24:33,531 --> 00:24:37,800 +And it's going to describe what the View is looking for +它描述了这个 View 要别人帮 + +561 +00:24:37,802 --> 00:24:39,768 +someone else to do for it. +它做的事情 + +562 +00:24:39,770 --> 00:24:41,136 +Okay? + +563 +00:24:41,137 --> 00:24:42,503 +It's gonna describe the responsibilities the View is +它描述了 View 要代理给其他人的 + +564 +00:24:42,506 --> 00:24:44,038 +going to delegate to someone else. +职责 + +565 +00:24:45,208 --> 00:24:46,807 +Okay? So if this is a scroll View, +所以如果这是一个 scroll View + +566 +00:24:46,809 --> 00:24:50,644 +something the protocol might be, should scroll to point. +这个协议可能是,应该滚动到一个点 + +567 +00:24:50,646 --> 00:24:52,946 +The View wants to know should I scroll to this point? +这个 View 想知道我是否要滚动到这个点? + +568 +00:24:52,948 --> 00:24:54,147 +The user's trying to scroll to this point. +用户试图滚动到这个点 + +569 +00:24:54,149 --> 00:24:55,147 +Should I do it? +我应该处理这个吗? + +570 +00:24:55,149 --> 00:24:57,049 +And the View doesn't know because it +View 并不知道,因为它并不没有 + +571 +00:24:57,051 --> 00:24:58,634 +doesn't own its own data. +自己的数据 + +572 +00:24:58,635 --> 00:25:00,218 +It doesn't really even know what it's scrolling on. +它甚至不知道它在什么东西上滚动 + +573 +00:25:00,220 --> 00:25:01,386 +It needs to ask someone else. +它需要询问别人 + +574 +00:25:01,388 --> 00:25:02,787 +So it's going to create this protocol. +所以它要创建这个协议 + +575 +00:25:02,789 --> 00:25:05,389 +Any time it either needs to notify someone else to +任何时候,它需要告知他人 + +576 +00:25:05,391 --> 00:25:06,724 +something interesting that is happening or +正在发生的有趣的事情,或者 + +577 +00:25:06,726 --> 00:25:09,226 +ask someone else for permission to do something or +向他人请求权限去做一些事情又或者 + +578 +00:25:09,228 --> 00:25:12,095 +to try to get its data, which is a common thing. +去尝试获取自己的数据,这是非常常见的 + +579 +00:25:12,097 --> 00:25:13,863 +It wants its data that it's trying to draw but +它需要它尝试绘图的数据,但 + +580 +00:25:13,865 --> 00:25:14,930 +it can't own its own data. +它没有自己的数据 + +581 +00:25:14,932 --> 00:25:16,598 +Remember Views can't own their data, +记住 View 不能有自己的数据 + +582 +00:25:16,600 --> 00:25:18,567 +the data is owned by the Controller. +数据是被 Controller 拥有的 + +583 +00:25:18,569 --> 00:25:19,868 +Really, it's probably in the Model, but +实际上,数据可能在 Model 中 + +584 +00:25:19,870 --> 00:25:23,004 +the Controller is responsible for dishing the data out. +但 Controller 负责取出数据 + +585 +00:25:23,006 --> 00:25:25,306 +So at first you're gonna create that protocol. +因此首先你要创建协议 + +586 +00:25:25,308 --> 00:25:28,242 +Then you're gonna create a property in your View, +然后你要在 View 中创建一个属性 + +587 +00:25:28,244 --> 00:25:31,244 +okay, called delegate or sometimes it's called data +称作代理或者有时叫做数据源 + +588 +00:25:31,246 --> 00:25:34,047 +source if it's delegating the data. +如果它代理数据的话 + +589 +00:25:34,049 --> 00:25:37,417 +And the type of that property is +然后这个属性的类型是 + +590 +00:25:37,419 --> 00:25:39,318 +this delegation protocol that you're gonna create. +这个你将创建的代理协议 + +591 +00:25:40,521 --> 00:25:41,687 +Protocols are just types so +协议就是类型 + +592 +00:25:41,689 --> 00:25:44,122 +that's what the property type is gonna be. +就是属性将被声明的类型 + +593 +00:25:44,124 --> 00:25:47,525 +Okay, then it's gonna use that property to go do all +然后它将使用这个属性去处理 + +594 +00:25:47,527 --> 00:25:48,526 +the delegation. +所有的代理 + +595 +00:25:48,528 --> 00:25:50,327 +It's going to send a message to +它将发送一个消息给代理属性 + +596 +00:25:50,329 --> 00:25:53,764 +the delegate property saying, should I scroll to this point, +我是否要滚动到这个点 + +597 +00:25:53,766 --> 00:25:55,832 +it's going to send a message to this delegate property. +它将发送一条消息给代理属性 + +598 +00:25:55,834 --> 00:25:58,034 +Maybe it will be called data source in this case, but +这个例子中它大概叫做数据源,但 + +599 +00:25:58,036 --> 00:25:59,735 +it's saying hey, where's my data? +它会询问,我的数据在哪里? + +600 +00:25:59,737 --> 00:26:01,503 +Give me more of my data. +给我更多我的数据 + +601 +00:26:01,505 --> 00:26:02,838 +Okay? That's what it's going to +明白了吗?这就是它将要 + +602 +00:26:02,840 --> 00:26:04,806 +send and it's going to send it to this object right here, +发送的消息,而且,它将会把这个消息发送给这里的对象 + +603 +00:26:04,808 --> 00:26:06,858 +this delegate property. +也就是这个 delegate 属性 + +604 +00:26:06,859 --> 00:26:08,909 +And this delegate property, all it is is a protocol. +然后,这个 delegate 属性,完全就是一种协议 + +605 +00:26:08,912 --> 00:26:12,013 +So all that, anybody who implements that +所以,只要是任何遵循这个协议的对象 + +606 +00:26:12,015 --> 00:26:14,548 +protocol can be set as the value for that. +都可以对这个属性设值 + +607 +00:26:14,550 --> 00:26:15,115 +Delegate. + +608 +00:26:15,117 --> 00:26:18,084 +All right then the controller is going to come along and +好的,接下来的是控制器 + +609 +00:26:18,086 --> 00:26:21,354 +it's going to first say that it implements that protocol. +控制器首先会说,它自身实现了这个协议 + +610 +00:26:21,356 --> 00:26:25,624 +Okay, so it's a class thing, it's going to say, yeah, +由于它是一个类,那么它会说 + +611 +00:26:25,626 --> 00:26:28,226 +I implement this view this delegate protocol. +我实现了这个视图的代理协议的方法 + +612 +00:26:28,228 --> 00:26:29,260 +Then the controller is going to +接着,控制器将 + +613 +00:26:29,262 --> 00:26:32,163 +set it's self as the delegate. +会将它自身作为代理对象 + +614 +00:26:32,165 --> 00:26:35,766 +So it's going to set that delegate property inside +它会设置这个视图的代理属性为其自身 + +615 +00:26:35,768 --> 00:26:39,703 +the view to itself, which is fine because it just said it +这里没有任何问题,因为它刚才 + +616 +00:26:39,705 --> 00:26:43,006 +implements that protocol, so that's good. +声明自己已经实现了这个协议所需的方法 + +617 +00:26:43,008 --> 00:26:45,042 +Then, of course, +接下来,当然 + +618 +00:26:45,043 --> 00:26:47,077 +the controllers going to have to implement the protocol, and +这个控制器将实现这个协议 + +619 +00:26:47,079 --> 00:26:49,779 +implement all the methods and properties required by +实现协议规定的必须(required)实现的所有方法 + +620 +00:26:49,781 --> 00:26:52,381 +the protocol so that it conforms to that protocol. +这样它就遵循了这个协议 + +621 +00:26:52,383 --> 00:26:53,782 +Otherwise compiler is going to complain. +否则编译器会报错 + +622 +00:26:55,085 --> 00:26:56,217 +And you're good to go. +这就可以了 + +623 +00:26:56,219 --> 00:26:58,886 +Now the view is hooked up to the controller, okay? +现在,这个视图已经和控制器建立关系了,明白了吗? + +624 +00:26:58,888 --> 00:27:00,688 +But the view still knows nothing about the controller. +但是视图仍旧不知道控制器是什么东西 + +625 +00:27:00,690 --> 00:27:01,855 +It doesn't know what class it is. +不知道控制器的类是什么 + +626 +00:27:01,857 --> 00:27:03,423 +It doesn't know what its purpose in life is. +不知道控制器的目的是什么 + +627 +00:27:03,425 --> 00:27:05,142 +It knows nothing. +什么都不知道 + +628 +00:27:05,143 --> 00:27:06,860 +All it knows is it implements the methods in its protocol, +唯一知道的是,这个控制器实现了视图中的协议的方法 + +629 +00:27:06,862 --> 00:27:08,094 +in the views protocol. + +630 +00:27:08,096 --> 00:27:09,662 +That's all it knows and that's all it needs to know. +这就是所有它所知道的,这也是所有它需要知道的 + +631 +00:27:10,598 --> 00:27:12,998 +Okay? So that keeps +明白了吗? + +632 +00:27:12,999 --> 00:27:15,399 +the view completely generic and allows the controller to +这种模式,就让这个视图完全变得通用起来,同时也让控制器 + +633 +00:27:15,402 --> 00:27:19,771 +have complete control of this generic minion in its view. +对这个视图有完全的控制 + +634 +00:27:19,773 --> 00:27:21,472 +Remember the view is the controller's minions, +还记得吗?形象地说,视图就是控制器的傀儡 + +635 +00:27:21,474 --> 00:27:23,640 +it's how it's communicating with the user. +这就是它如何跟用户打交道 + +636 +00:27:24,576 --> 00:27:27,243 +So that's how we do it. +以上就是我们如何做的 + +637 +00:27:27,245 --> 00:27:30,580 +So let's take a look at a demo of doing that in happiness. +让我们看看在 Happiness 这个 Demo 中如何做这些操作 + +638 +00:27:30,582 --> 00:27:32,348 +We're going to have +首先,我们需要 + +639 +00:27:32,349 --> 00:27:34,115 +the face view delegate getting its data. +让 faceView 的代理获取它的数据 + +640 +00:27:34,118 --> 00:27:36,518 +Its data is basically its smiliness, +这个数据基本上就是它的 smiliness + +641 +00:27:36,520 --> 00:27:38,320 +how much smileyness is going on. +smiliness 会是多少 + +642 +00:27:38,322 --> 00:27:40,889 +It's going to get that from the delegate. +faceView 将从这个代理对象中获取数据 + +643 +00:27:40,891 --> 00:27:43,091 +And, of course, the happiness view controller is going to +当然,happiness view controller 将会 + +644 +00:27:43,093 --> 00:27:44,358 +be the delegate it gets it from. +成为它的代理,它从那里获取数据 + +645 +00:27:45,895 --> 00:27:48,879 +>> Okay. +好的 + +646 +00:27:48,880 --> 00:27:51,864 +Well, let's now use delegation to hook up our +让我们来使用代理模式来连接 + +647 +00:27:51,867 --> 00:27:55,701 +face view to our happiness view controller. +我们的 faceView 和我们的 happiness view controller + +648 +00:27:56,737 --> 00:27:58,036 +And we're gonna do that by +我们将会 + +649 +00:27:58,038 --> 00:27:59,904 +starting here in the face view. +从 faceView 开始 + +650 +00:27:59,906 --> 00:28:01,606 +We're gonna go through the same steps we +我们要按照我们刚才在幻灯片中说的步骤 + +651 +00:28:01,608 --> 00:28:05,609 +just talked about in the slides to do delegation. +来创建代理关系 + +652 +00:28:05,611 --> 00:28:09,146 +So remember the first step is that we need a protocol, +还记得第一步吗?首先我们需要一个协议 + +653 +00:28:09,148 --> 00:28:13,116 +some particular way that the face view is going to talk to +某些具体的方式,让 faceView 与 + +654 +00:28:13,118 --> 00:28:16,285 +whoever's going to provide its data, and +任何一个可以提供它的数据的对象进行沟通 + +655 +00:28:16,287 --> 00:28:19,555 +the face view's data is really it's smiliness. +faceView 的数据就是它的 smiliness + +656 +00:28:19,557 --> 00:28:20,989 +So the face view has this data. +现在 faceView 已经有这个数据了 + +657 +00:28:20,991 --> 00:28:23,258 +Now this is a very, very simple data. +这个非常简单的数据 + +658 +00:28:23,260 --> 00:28:25,360 +Probably in real life if this weren't, +或许在实际中这个不是 + +659 +00:28:25,362 --> 00:28:28,796 +you know a demo where I'm trying to show you delegation, +但是,这里毕竟只是一个演示代理模式的 Demo + +660 +00:28:28,798 --> 00:28:31,565 +you would probably just set this, you +你可以就简单设置这个 + +661 +00:28:31,567 --> 00:28:34,935 +can't own it's own data, it's such a simple piece of data. +你不能拥有这个数据,它是这样一个简单的数据块 + +662 +00:28:34,937 --> 00:28:36,203 +But we're going to use delegation to +但我们将会使用代理来 + +663 +00:28:36,205 --> 00:28:39,072 +get this piece of data here. +获得这里的数据块 + +664 +00:28:39,074 --> 00:28:41,974 +Rather than have it be set right here. +而不是直接在这里设值 + +665 +00:28:41,976 --> 00:28:44,360 +All right, so +好的 + +666 +00:28:44,361 --> 00:28:46,745 +we need some sort of protocol that gets this smiliness from +所以,我们需要某种协议,来从某些对象中获取这个 smiliness + +667 +00:28:46,748 --> 00:28:51,083 +someone and, so we're gonna type in here protocol and +这里我们输入 protocol + +668 +00:28:51,085 --> 00:28:53,351 +I'm gonna call this protocol. +这里我打算叫这个协议为 + +669 +00:28:53,353 --> 00:28:58,522 +That I'm developing my face view data source protocol. +因为这里我正在做的是我的 faceView 的数据来源协议,所以叫 FaceViewDataSource + +670 +00:28:59,692 --> 00:29:04,027 +And sometimes we call these delegation protocols delegate. +通常我们将代理类型的协议命名为 Delegate + +671 +00:29:04,029 --> 00:29:05,795 +Like face view delegate. +类似于 FaceViewDelegate + +672 +00:29:05,797 --> 00:29:08,864 +But when the only purpose of the protocol is to +但当这个协议唯一的作用是 + +673 +00:29:08,866 --> 00:29:11,633 +get the data that the view is going to draw. +获得这个视图用来绘制的一些数据 + +674 +00:29:11,635 --> 00:29:14,269 +Because the view can't own its own data, +因为这个视图不能拥有自己的数据 + +675 +00:29:14,271 --> 00:29:17,972 +then we often will call the protocol datasource. +通常我们称这种协议为 DataSource + +676 +00:29:19,142 --> 00:29:21,375 +So this just needs to have whatever functions and +所以这里需要的就是 + +677 +00:29:21,377 --> 00:29:24,511 +properties are required to get this used data. +用来获取数据的一些必需的函数和属性 + +678 +00:29:24,513 --> 00:29:27,447 +Well such a simple view that it +这里,这么一个简单的视图 + +679 +00:29:27,449 --> 00:29:32,218 +just needs something to get the smile in some function so +只需要一个用来获取笑容灿烂度的函数 + +680 +00:29:32,220 --> 00:29:36,021 +I'm going to say smiliness for face view. +这里我输入 smilinessForFaceView + +681 +00:29:36,023 --> 00:29:38,523 +I have an argument here which is the sender. +这里有一个参数,也就是 sender + +682 +00:29:38,525 --> 00:29:39,891 +Face view. +FaceView + +683 +00:29:39,892 --> 00:29:41,258 +And this is gonna be myself. +这里会是这个控制器自身 + +684 +00:29:41,261 --> 00:29:44,362 +So when I ask somebody else to provide my data by +当我要求其他的对象来提供我的数据的时候 + +685 +00:29:44,364 --> 00:29:45,463 +sending them this message. +我发送这个消息 + +686 +00:29:45,465 --> 00:29:48,032 +I'm gonna pass myself, this face view, +我将传入 self,这个 FaceView + +687 +00:29:48,034 --> 00:29:49,433 +along as an argument. +作为其参数 + +688 +00:29:49,435 --> 00:29:53,336 +And you'll see all throughout iOS when they have +你在 iOS 开发中会看到 + +689 +00:29:53,338 --> 00:29:55,604 +a delegate or a data source. +当某个对象拥有一个 Delegate 或者 DataSouce 的时候 + +690 +00:29:55,606 --> 00:29:58,173 +They are always going to pass themselves along. +他们都会传入他们自身 + +691 +00:29:58,175 --> 00:30:00,709 +If you are trying to provide the smiliness for +如果你尝试给这个 FaceView 提供 smiliness 的时候 + +692 +00:30:00,711 --> 00:30:03,678 +this FaceView, you have a point or two to FaceView. +你将这个参数指向 FaceView + +693 +00:30:03,680 --> 00:30:05,913 +You know, which FaceView is asking you that, and +你知道的,这个 FaceView 要求你这个 + +694 +00:30:05,915 --> 00:30:08,115 +maybe if you need to ask the FaceView some other +当然也许你也可以要求 FaceView 其他的问题 + +695 +00:30:08,117 --> 00:30:11,318 +questions to answer this, you can do that. +来回答这个,当然你可以这么做 + +696 +00:30:11,320 --> 00:30:13,987 +Now, this smiliness what is it going to return? +现在,这个 smiliness,它会返回什么呢? + +697 +00:30:13,989 --> 00:30:15,822 +Now I'm going to have it return a double, +我想让它返回一个 Double + +698 +00:30:15,824 --> 00:30:17,457 +which is going to be that smiliness, +也就是那个 smiliness + +699 +00:30:17,459 --> 00:30:22,861 +remember that smiliness goes from a plus 1 down to minus 1, +还记得 smiliness 从-1到+1吗? + +700 +00:30:22,863 --> 00:30:24,129 +plus 1 that's very smiley and ++1代表很开心 + +701 +00:30:24,131 --> 00:30:29,400 +minus 1 that's very frowny and so we made that double. +-1代表很不开心,我们设置它为 Double + +702 +00:30:29,402 --> 00:30:33,404 +I'm also going to make this double be an optional. +同时,我将设置它为一个可选的 Double + +703 +00:30:33,406 --> 00:30:36,607 +And that's because if the data source, if I ask it for +那是因为这个 DataSource,如果我问 + +704 +00:30:36,609 --> 00:30:39,360 +the smiliness, and for +它要 smiliness 时 + +705 +00:30:39,361 --> 00:30:42,112 +some reason it can't provide that smiliness, then I'm gonna +因为某些原因,它无法提供这个 smiliness + +706 +00:30:42,114 --> 00:30:47,083 +allow them to return nil, and just have no smile or +那么我允许它们返回 nil,也就是说 + +707 +00:30:47,085 --> 00:30:52,020 +no frown, just flatlined mouth there. +既不是开心也不是不开心,一条线的嘴巴 + +708 +00:30:52,022 --> 00:30:55,056 +Now we only by the way pass one argument here. +这里我们只传入了一个参数 + +709 +00:30:55,058 --> 00:30:57,859 +But we could definitely, if we were asking our data source, +但是我们完全可以,如果我们在请求我们的 DataSource 的时候 + +710 +00:30:57,861 --> 00:31:00,828 +we could have some more arguments in here. +可以使用多个参数 + +711 +00:31:00,830 --> 00:31:03,297 +And so that's perfectly reasonable. +而且这么做也是完全合理的 + +712 +00:31:03,299 --> 00:31:04,598 +You can have as many arguments as you +你为了从 DataSource 中获取这个 smiliness + +713 +00:31:04,600 --> 00:31:08,134 +need to get this smiliness out of the data source. +需要多少个参数都可以 + +714 +00:31:08,136 --> 00:31:11,637 +Okay, so that's step one, we have this data source here. +好的,这就是步骤一,我们这里已经有了 DataSource + +715 +00:31:11,639 --> 00:31:17,676 +Step two is we need to have a public var in our face view, +第二步是,在我们的 FaceView 中我们需要有一个公开的变量 + +716 +00:31:17,678 --> 00:31:19,878 +which I'm going to call dataSource, and +这里我将称之为 dataSource + +717 +00:31:19,880 --> 00:31:23,348 +it's going to be of type FaceViewDataSource. +它的类型是 FaceViewDataSource + +718 +00:31:23,350 --> 00:31:25,450 +Okay? +明白了吗? + +719 +00:31:25,451 --> 00:31:27,551 +I'm going to make that an optional as well. +同样我这里会把它的类型变成可选的 + +720 +00:31:27,553 --> 00:31:30,421 +So you can see here that I'm using FaceViewDataSource, +这里你可以看到,我将 FaceViewDataSource + +721 +00:31:30,423 --> 00:31:33,590 +which is this protocol, just as a type. +这个协议,作为一个类型 + +722 +00:31:33,592 --> 00:31:34,691 +And what this means is, +这代表的是 + +723 +00:31:34,693 --> 00:31:37,093 +somebody who wants to provide my data, +某个想要提供给我数据的对象 + +724 +00:31:37,095 --> 00:31:39,128 +who wants to be my dataSource, +也就是想成为我的 dataSource + +725 +00:31:39,130 --> 00:31:43,265 +all they need to do is set themselves as this variable. +那么,它们所需要的是将它们自身设置为这个变量的值 + +726 +00:31:43,267 --> 00:31:46,702 +And then I'm going to talk to them through this variable to +接着,我可以通过这个变量来向它们发送消息 + +727 +00:31:46,704 --> 00:31:47,769 +call this function on them. +来调用它们的某些函数 + +728 +00:31:48,805 --> 00:31:50,405 +Okay? +明白了吗? + +729 +00:31:50,406 --> 00:31:52,006 +Now, why did I make this an optional here? +为什么这里我让它变成一个可选类型呢? + +730 +00:31:52,008 --> 00:31:54,575 +Because it's possible that +因为有可能 + +731 +00:31:54,577 --> 00:31:56,243 +I can just live without a data source. +我们的 FaceView 并没有一个 dataSource + +732 +00:31:56,245 --> 00:31:58,578 +I will just always have a flat line, a flat mouth. +那么在这种的情况下,FaceView 的嘴巴始终是一条直线 + +733 +00:31:58,580 --> 00:32:01,814 +I won't be smiling or frowning. +既不微笑也不伤心 + +734 +00:32:01,816 --> 00:32:04,450 +And so this can be allowed to be nil. +所以 dataSource 可以允许是 nil + +735 +00:32:04,452 --> 00:32:07,686 +Okay, now normally, this is not going to want to be nil, +通常,我们不想让它是 nil + +736 +00:32:07,688 --> 00:32:11,489 +because we don't want a face with no frown and no smile. +因为我们不希望看到一个既不微笑也不伤心的脸 + +737 +00:32:11,491 --> 00:32:14,425 +But, we'll certainly allow it. +但我们一定会允许(不提供 dataSource) + +738 +00:32:14,427 --> 00:32:15,760 +So, allow that there. +允许这么做 + +739 +00:32:16,896 --> 00:32:19,896 +Now one other thing we have to do about this data source here +现在,我们还要继续对 dataSource 做的一件事情是 + +740 +00:32:19,898 --> 00:32:23,867 +is we really want to describe it as weak. +声明它是一个 weak 类型的 + +741 +00:32:23,869 --> 00:32:26,703 +Now this is gonna be the first time we talk about +这是我们在这次课中 + +742 +00:32:26,705 --> 00:32:28,637 +memory management in this class. +第一次讨论内存管理 + +743 +00:32:28,639 --> 00:32:29,972 +And really the memory's just been +事实上,内存是被操作系统 + +744 +00:32:29,974 --> 00:32:32,140 +managed automatically for you. +自动管理的,所以你不用担心 + +745 +00:32:32,142 --> 00:32:33,375 +But here we have to be a little bit +但是我们需要注意的是 + +746 +00:32:33,377 --> 00:32:36,811 +careful with the memory management of this pointer. +对这个指针的内存管理 + +747 +00:32:36,813 --> 00:32:38,930 +Because, for example, +因为,例如 + +748 +00:32:38,931 --> 00:32:41,048 +our controller is going to set itself as the data source. +我们的控制器将会设置它自身为 dataSource + +749 +00:32:41,050 --> 00:32:44,418 +So it's going to set this pointer back to itself because +然后它将把这个指针指向自身 + +750 +00:32:44,420 --> 00:32:47,721 +our controller's going to be a FaceViewDataSource. +因为我们的控制器将会成为一个 FaceViewDataSource + +751 +00:32:47,723 --> 00:32:50,657 +And, unfortunately, the controller also has +不幸的是,我们的控制器 + +752 +00:32:50,659 --> 00:32:54,127 +a pointer to this FaceView through the view hierarchy. +在视图的层次上已经有一个指向 FaceView 的指针了 + +753 +00:32:54,129 --> 00:32:57,296 +Because it's gonna have some outlet to the face view, and +因为它有一个链接到 FaceView 的 outlet + +754 +00:32:57,298 --> 00:32:59,465 +so they'll be pointing to each other. +这样,这两个对象就互相指向了对方 + +755 +00:32:59,467 --> 00:33:02,668 +And since they're pointing to each other they're keeping +那么在这个时候,它们 + +756 +00:33:02,670 --> 00:33:04,669 +each other in memory at all times, so +就会一直在内存中相互引用对方 + +757 +00:33:04,671 --> 00:33:07,605 +that kinda memory cycle is really bad. +在内存中出现这样的循环是很可怕的 + +758 +00:33:07,607 --> 00:33:09,607 +Because then the FaceView and +因为 FaceView + +759 +00:33:09,609 --> 00:33:11,508 +the controller can never leave memory. +和控制器都无法释放其内存 + +760 +00:33:11,510 --> 00:33:14,011 +They'll be stuck in memory forever. +它们就会永远呆在了内存中 + +761 +00:33:14,013 --> 00:33:17,681 +So, by making this weak, if we put weak in front of a var +但是,通过在变量之前声明这个为 weak + +762 +00:33:17,683 --> 00:33:24,320 +pointer it means that this pointer, this thing, whatever +这个的意思是,这个对象,无论它 + +763 +00:33:24,322 --> 00:33:30,225 +this points to, should not be used to keep it in memory. +指向的是什么东西,这个东西都不应该保留在内存中 + +764 +00:33:30,227 --> 00:33:32,794 +So the controller is gonna set itself as this data source. +也就是说,控制器将会设置它自身为 dataSource + +765 +00:33:32,796 --> 00:33:35,229 +This pointer, since it is going to be a weak pointer, +这个指针,既然它声明了自己是一个 weak 指针 + +766 +00:33:35,231 --> 00:33:36,864 +is not going to keep the controller in memory. +将不会在内存中保存这个控制器 + +767 +00:33:36,866 --> 00:33:38,932 +So the controller will be allowed to go out of memory. +所以,这个控制器被允许从内存中释放 + +768 +00:33:38,934 --> 00:33:40,033 +And when it goes out of memory, +当它被释放的时候 + +769 +00:33:40,035 --> 00:33:41,601 +of course the FaceView loss will go out of +当然 FaceView 也会同样从内存中释放 + +770 +00:33:41,603 --> 00:33:43,803 +memory with it because its entire view hierarchy, +因为 FaceView 在控制器的视图层次中 + +771 +00:33:43,805 --> 00:33:48,340 +the controller's view hierarchy will go out as well. +而控制器的视图层次会随控制器一起被释放掉 + +772 +00:33:48,342 --> 00:33:51,643 +And now you can see that we have an error here, okay? +现在你看到这里有一个错误 + +773 +00:33:51,645 --> 00:33:55,079 +And this error says weak cannot be applied to non-class +这个错误说,weak 类型不能应用在非类的类型上 + +774 +00:33:55,081 --> 00:33:56,280 +types, okay? +明白了吗? + +775 +00:33:56,282 --> 00:34:00,250 +So FaceViewDataSource is a protocol, not a class. +FaceViewDataSource 是一个协议,而不是一个类 + +776 +00:34:00,252 --> 00:34:02,185 +So FaceViewDataSource could be an enum or +所以我们需要把 FaceViewDataSource 改成枚举类型 + +777 +00:34:02,187 --> 00:34:05,922 +a struct and that's a problem because we really need this to +或者结构体,因为我们希望这个变量是 weak 类型的 + +778 +00:34:05,924 --> 00:34:07,957 +be weak because we +我们不希望 + +779 +00:34:07,958 --> 00:34:09,991 +don't want that cycle things pointing back to each other. +在内存中出现两个对象互相指向对方的环 + +780 +00:34:09,994 --> 00:34:12,828 +So, we can actually make FaceViewDataSource, even +所以我们要将 FaceViewDataSource + +781 +00:34:12,830 --> 00:34:15,430 +though it's a protocol, we can make it be a class type. +变成一个类,尽管它只是一个协议 + +782 +00:34:15,432 --> 00:34:17,766 +If you remember from the slides in our +如果你还记得幻灯片中的 + +783 +00:34:17,768 --> 00:34:21,502 +protocol declaration, we can say colon class. +协议声明的话,我们可以通过在协议后面加上 : class + +784 +00:34:21,504 --> 00:34:24,372 +And that says that FaceViewDataSource can only be +这代表的是,FaceViewDataSource 只能被一个类所实现 + +785 +00:34:24,374 --> 00:34:27,307 +implemented by a class, it cannot be implemented by +它不能被一个枚举类型或者一个结构体所实现 + +786 +00:34:27,309 --> 00:34:30,477 +a struct or an enum, and that's perfectly fine and +这是完全没有问题的 + +787 +00:34:30,479 --> 00:34:33,046 +usually that's what we're going to want anyway, but +同样也是我们所希望的 + +788 +00:34:33,048 --> 00:34:35,815 +we definitely need that so we can have this weak behavior. +我们绝对需要这个,所以我们能够让这个变量为 weak + +789 +00:34:35,817 --> 00:34:38,751 +So this data source, the pointer it has to whatever its +那么, 这个 dataSource,任何它指向的对象 + +790 +00:34:38,753 --> 00:34:41,053 +data source will not keep it's data source in memory. +它的 dataSource 都不会在内存中保留它的数据源 + +791 +00:34:42,523 --> 00:34:45,090 +As long as the dataSource is in memory, +只要是 dataSource 在内存中 + +792 +00:34:45,092 --> 00:34:47,209 +this pointer will be good. +那么这个指针就不会有问题 + +793 +00:34:47,210 --> 00:34:49,327 +As soon as the dataSource goes out of memory then this +一旦 dataSource 从内存中释放了 + +794 +00:34:49,329 --> 00:34:52,697 +pointer will be set to nill automatically by the system. +那么这个指针将会被系统自动设成 nil + +795 +00:34:52,699 --> 00:34:54,965 +So it's pretty cool, these banners are pretty cool. +这非常酷,这些横幅很酷 + +796 +00:34:54,967 --> 00:34:57,734 +We don't use them a lot you saw that we used them for IB +平时我们不会经常使用到 weak,但是在 IBOutlet + +797 +00:34:57,736 --> 00:35:00,303 +outlets and this is the second place that we have used them, +里 weak 被大量使用到,这里 + +798 +00:35:00,305 --> 00:35:02,038 +which is for delegation. +代理,是第二个被大量使用到的地方 + +799 +00:35:02,040 --> 00:35:04,707 +We're always gonna use a weak var when we have delegation. +如果我们有一个代理的时候,我们始终需要一个 weak 类型的变量 + +800 +00:35:04,709 --> 00:35:05,274 +Okay? +明白了吗? + +801 +00:35:06,243 --> 00:35:08,943 +That just requires that we make our protocol, +那仅仅要求我们使得 protocol, + +802 +00:35:08,945 --> 00:35:10,378 +you only work for classes. +只对 class 类型起作用 + +803 +00:35:11,547 --> 00:35:12,446 +All right? +明白了? + +804 +00:35:12,448 --> 00:35:13,964 +Okay? So now we +现在我们 + +805 +00:35:13,965 --> 00:35:15,481 +have this nice data source right here. +有了个不错的 dataSource + +806 +00:35:15,484 --> 00:35:18,018 +Let's go ahead and go to the next step, +我们继续到下一步, + +807 +00:35:18,019 --> 00:35:20,553 +which to use the data source to get our smiliness, right? +谁来使用这个 dataSource 以得到 smiliness,对吗? + +808 +00:35:20,555 --> 00:35:22,355 +So we have our smiliness right here, +于是我们在这里得到了 smiliness, + +809 +00:35:22,357 --> 00:35:26,058 +it's currently at constant minus 0.5, so we're going to +现在是常量-0.5,所以我们要 + +810 +00:35:26,060 --> 00:35:28,093 +get it from the data source by just saying to the data +从 dataSource 里获取,简单告诉 dataSource, + +811 +00:35:28,095 --> 00:35:32,664 +source, please give us our smiliness for FaceView Self. +请把 FaceView self 的 smiliness 给我们 + +812 +00:35:33,967 --> 00:35:34,865 +Okay? + +813 +00:35:34,867 --> 00:35:36,100 +Now when I type that in, +现在当我输入的时候, + +814 +00:35:36,102 --> 00:35:38,035 +Swift automatically put this question mark here. +Swift 自动把"?"放在这里 + +815 +00:35:38,037 --> 00:35:39,035 +I didn't type that. +我没有输入它 + +816 +00:35:39,037 --> 00:35:40,503 +It put it in here. +它把它放在这里 + +817 +00:35:40,505 --> 00:35:42,872 +Why did it put here? +为什么它要在这里? + +818 +00:35:42,873 --> 00:35:45,240 +Well it put it here because data source is an optional. +因为 dataSource 是 optional + +819 +00:35:45,243 --> 00:35:47,543 +And it could be nil, okay? +它可能值为 nil,okay? + +820 +00:35:47,545 --> 00:35:49,678 +This is an optional, it could be nil. +这是个 optional,可以是 nil + +821 +00:35:49,680 --> 00:35:52,681 +And so Swift is assuming that we wanna use optional +所以 Swift 认为我们想要在这里使用 + +822 +00:35:52,683 --> 00:35:54,015 +chaining here. +optional 链 + +823 +00:35:54,017 --> 00:35:57,618 +And just, if this is nil, then this whole rest of +如果这是 nil,那么剩下所有的 + +824 +00:35:57,620 --> 00:35:59,153 +this expression is gonna be ignored. +表达式都将被忽略 + +825 +00:35:59,155 --> 00:36:00,854 +This whole thing would be nil. +整体的值将是 nil + +826 +00:36:00,856 --> 00:36:03,923 +And smiliness here would be set to nil, okay? +这里 smiliness 将会被设置为 nil,okay? + +827 +00:36:03,925 --> 00:36:06,225 +But smiliness, you can see this error here is +不过 smiliness,你会在这里看到这个 error + +828 +00:36:06,227 --> 00:36:08,327 +because smiliness, it can't be nil. +是因为 smiliness,它不能为 nil + +829 +00:36:08,329 --> 00:36:09,995 +It has to be a double. +它必须是 double + +830 +00:36:09,997 --> 00:36:12,431 +So we're going to use another cool little feature switch. +所以我们要使用另一个酷酷的小特性转换 + +831 +00:36:12,433 --> 00:36:15,600 +Swift which is the question mark question mark operator. +Swift 中的 ?? 操作符 + +832 +00:36:15,602 --> 00:36:17,735 +Now what this operator says is, +这个操作符的意思是 + +833 +00:36:17,737 --> 00:36:21,238 +if the thing on the left-hand side of the question mark +如果操作符左侧的表达式 + +834 +00:36:21,240 --> 00:36:25,275 +question mark is not nill, then use that. +不是 nil,那么使用它作为值 + +835 +00:36:25,277 --> 00:36:28,779 +But if it is nil, then use what's on the righthand side, +如果左侧表达式为 nil,那么使用右侧的表达式, + +836 +00:36:28,781 --> 00:36:32,048 +and to the right hand side I'm gonna put 0.0. +在右侧我放上0.0 + +837 +00:36:32,050 --> 00:36:37,687 +So what that says is that if the data source is nil, +它的意思是如果 dataSource 是 nil, + +838 +00:36:37,689 --> 00:36:39,955 +then we're going to use smiliness of 0, +那么我们将使用0为 smiliness 的值, + +839 +00:36:39,957 --> 00:36:42,090 +which is not a frown or a smile, it's in the middle. +它不是皱眉也不是微笑,它正好处在中间 + +840 +00:36:43,226 --> 00:36:45,426 +Now this is also gonna be working if +这也会在 + +841 +00:36:45,428 --> 00:36:48,796 +smilinessForFaceView happens to return nil because you +smilinessForFaceView 正好返回 nil 时起作用 + +842 +00:36:48,798 --> 00:36:52,599 +remember it is also an optional double right here. +因为你记得,它也是个 optinal double + +843 +00:36:52,601 --> 00:36:54,968 +So that'll work perfectly fine there as well. +所以这里处理得非常好 + +844 +00:36:54,970 --> 00:36:56,703 +So whether this returns nil or +所以无论是这里返回 nil + +845 +00:36:56,705 --> 00:37:00,406 +whether this is nil, invalidating the rest of this, +还是这里是 nil,使得这里剩下的都无效, + +846 +00:37:00,408 --> 00:37:01,741 +we're gonna get no smile or frown. +我们将得不到笑脸或者皱眉 + +847 +00:37:01,743 --> 00:37:06,912 +So this is a cool little operator [INAUDIBLE]. +所以这是个酷酷的小操作符 + +848 +00:37:06,914 --> 00:37:09,681 +Okay, so we've got our face view doing its part. +Okay,所以我们让 FaceView 干好了它的活 + +849 +00:37:09,683 --> 00:37:11,749 +It's declaring this nice property, +它在这里声明了这个漂亮的 property, + +850 +00:37:11,751 --> 00:37:13,417 +this protocol right here. +这个 protocol + +851 +00:37:13,419 --> 00:37:16,854 +It's got a property which let people set themselves as +它有个让别人把他们设置为 + +852 +00:37:16,856 --> 00:37:18,055 +the data source and +dataSource 然后 + +853 +00:37:18,057 --> 00:37:21,224 +then it uses that data source to get its smiliness. +使用 dataSource 获得 smiliness + +854 +00:37:21,226 --> 00:37:23,226 +All right, so +好了,所以 + +855 +00:37:23,227 --> 00:37:25,227 +now let's go back to our happiness view controller. +现在让我们回到 HappinessViewController + +856 +00:37:25,230 --> 00:37:26,228 +Okay? The controller has to +这个 controller 必须 + +857 +00:37:26,230 --> 00:37:28,664 +implement the other side of delegation. +实现 delegation 的另一面 + +858 +00:37:28,666 --> 00:37:30,932 +Now you remember one of the steps it has is it has to +你们记住有一个步骤是,它必须 + +859 +00:37:30,934 --> 00:37:34,302 +say to the world, I am HappinessViewController and +对外宣布,我是 HappinessViewController + +860 +00:37:34,304 --> 00:37:38,072 +I implement the FaceViewDataSource protocol. +我会实现 FaceViewDataSource protocol + +861 +00:37:38,074 --> 00:37:41,709 +And it does that by just saying FaceViewDataSource. +声明 FaceViewDataSource 就完成了这些 + +862 +00:37:41,711 --> 00:37:43,344 +Now as soon as I put this on here, +一旦我把它放在这里, + +863 +00:37:43,346 --> 00:37:44,811 +I'm going to get a warning right here, +我会得到一个 warning, + +864 +00:37:44,813 --> 00:37:46,863 +an error that says, +一个 error 说, + +865 +00:37:46,864 --> 00:37:48,914 +HappinessViewController does not conform to that protocol. +HappinessViewController 没有遵从那个 protocol. + +866 +00:37:48,917 --> 00:37:51,918 +And indeed it doesn't because we do not implement +实际上也没有,因为我们还没有 + +867 +00:37:51,920 --> 00:37:54,787 +that smiliness by anywhere in our class. +在我们的 class 里实现 smiliness + +868 +00:37:54,789 --> 00:37:56,355 +So, easily fixed though. +所以,简单地搞定它 + +869 +00:37:56,357 --> 00:37:59,458 +We go down here, now, since, we've already told it, +我们往下到这里,我们已经说过了, + +870 +00:37:59,460 --> 00:38:01,376 +it implements this. +它会实现这个 + +871 +00:38:01,377 --> 00:38:03,293 +If I just start typing smiliness it's going to +如果我开始输入 smiliness, 它会 + +872 +00:38:03,296 --> 00:38:05,530 +automatically know to escape complete. +自动提示完成 + +873 +00:38:05,532 --> 00:38:07,064 +So I'll hit Tab. +所以我点击 Tab 键, + +874 +00:38:07,066 --> 00:38:09,166 +I've got my nice method here. +我就在这里得到了我的 method + +875 +00:38:09,168 --> 00:38:13,570 +So how am I going to implement this protocol? +所以我如何实现这个 protocal? + +876 +00:38:13,572 --> 00:38:15,571 +Okay, this method in this protocol, +Okay,这个 protocol 的 method, + +877 +00:38:15,573 --> 00:38:17,273 +how am I going to implement that? +我怎么实现呢? + +878 +00:38:17,275 --> 00:38:21,476 +Well the happiness view controller is going to +好吧,HappinessViewController 要 + +879 +00:38:21,478 --> 00:38:23,812 +interpret the happiness here. +在这里解析 happiness + +880 +00:38:23,814 --> 00:38:25,213 +Which is the Model. +这里是 Model 层 + +881 +00:38:25,214 --> 00:38:26,613 +This is the happiness view controller's Model. +这是 HappinessViewController 的 Model + +882 +00:38:26,616 --> 00:38:30,718 +It's gonna interpret this for the view, because the view +它要为 view 解析这些,因为 view + +883 +00:38:30,720 --> 00:38:33,487 +doesn't know about happiness, it only knows about smiliness. +不知道 happiness,它只知道 smiliness + +884 +00:38:33,489 --> 00:38:35,956 +Smiliness goes from 1 to minus 1. +smiliness 的值介于-1到1之间 + +885 +00:38:35,958 --> 00:38:38,792 +Here, we're taking about the Model which is happiness that +这里,我们讨论 Model 层也就是 happiness, + +886 +00:38:38,794 --> 00:38:40,226 +goes from 0 to 100. +值介于0到100. + +887 +00:38:40,228 --> 00:38:43,162 +So it's a typical job of the controller to +所以这是个 controller 的典型任务 + +888 +00:38:43,164 --> 00:38:46,965 +interpret the Model for the view. +为 view 解析 Model + +889 +00:38:46,967 --> 00:38:48,734 +You also interpret the view for the Model and we'll see +你也会为了 Model 解析 view,我们 + +890 +00:38:48,736 --> 00:38:51,536 +that a little bit later when we talk about gestures. +待会儿讨论手势的时候再作说明 + +891 +00:38:51,538 --> 00:38:55,006 +But, here we're going to interpret the Model for +但是,这里我们要解析 Model 来 + +892 +00:38:55,008 --> 00:38:56,841 +the view. +绘制 view + +893 +00:38:56,842 --> 00:38:58,675 +So, I'm just going to return. +所以,我要返回 + +894 +00:38:59,712 --> 00:39:04,047 +Now, happiness is an int, and smiliness is a double, so +现在,happiness 是 int,smiliness 是 double, + +895 +00:39:04,049 --> 00:39:06,916 +I am going to have to convert the happiness. +所以我必须转化 happiness + +896 +00:39:07,952 --> 00:39:11,653 +Also, the happiness is on a scale of 0 to 100, so +同样,happiness 是0到100之间的一个标量, + +897 +00:39:11,655 --> 00:39:14,088 +I am going to do minus 50. +所以我要减去50. + +898 +00:39:15,158 --> 00:39:18,192 +Divide by 50 to convert it into that plus 1 to +再除以50把它转化到 + +899 +00:39:18,194 --> 00:39:19,626 +minus 1 scale. +1到-1之间 + +900 +00:39:19,628 --> 00:39:22,762 +So here I'm just interpreting the Model for the view. +所以这里我做的是,将模型中的变量转换成视图所需要的数值 + +901 +00:39:23,998 --> 00:39:25,197 +Make sense? +听懂了吗? + +902 +00:39:25,199 --> 00:39:27,399 +Now the last thing that needs to happen here is +现在这里最后一件事 + +903 +00:39:27,401 --> 00:39:30,669 +that the controller needs to set itself +是控制器需要把自己 + +904 +00:39:30,671 --> 00:39:35,773 +as the data source of the FaceView. +设置为 FaceView 的 dataSource + +905 +00:39:35,775 --> 00:39:36,807 +Let's all go back to FaceView, +让我们回到 FaceView + +906 +00:39:36,809 --> 00:39:38,575 +I'm going to show you a nice trick here. +这里,我要给你们展示一个小技巧 + +907 +00:39:38,577 --> 00:39:43,946 +Cmd+Shift+O will let you type in like, start typing +按下 ⌘ + Shift + O 键,然后输入 + +908 +00:39:43,948 --> 00:39:46,215 +FaceView and you can see it appear right there, and +FaceView,然后你会看到 FaceView 的实现文件出现在这里 + +909 +00:39:46,217 --> 00:39:50,285 +you can switch really quick so Cmd+Shift+O is a great way to +你通过这两种方式能快速地在文件之间切换,所以 ⌘ + Shift + O 快捷键是非常棒的 + +910 +00:39:50,287 --> 00:39:54,923 +switch really quickly between files in your project. +在工程中快速切换文件的方式 + +911 +00:39:56,026 --> 00:39:59,093 +All right, so we need to set this data source right here +好了,我们需要在 FaceView 的代码中 + +912 +00:39:59,095 --> 00:40:01,895 +inside of our face view to be the controller. +设置我们的 FaceView 的 dataSource + +913 +00:40:02,964 --> 00:40:04,497 +So for the controller to do that, +所以,为了让控制器成为它的 dataSource + +914 +00:40:04,499 --> 00:40:08,200 +though, it needs to have a pointer to the FaceView. +它需要一个指向 FaceView 的指针 + +915 +00:40:08,202 --> 00:40:09,702 +And we do pointers to things in +我们在视图里用 outlets + +916 +00:40:09,704 --> 00:40:13,071 +our view using outlets, right? +来保存指向对象的指针,还记得吗? + +917 +00:40:13,073 --> 00:40:18,209 +So let's go over here to our Storyboard and wire up +所以我们进入 Storyboard 的这里 + +918 +00:40:18,211 --> 00:40:20,111 +an outlet from this. +从这里拖出一个 outlet + +919 +00:40:20,113 --> 00:40:21,679 +We'll go to automatic mode up here. +在 Assistant View 里选择 Automatic 模式 + +920 +00:40:21,681 --> 00:40:23,413 +Remember, when you go to automatic mode you're +注意,当你进入 Automatic 模式时,你会 + +921 +00:40:23,415 --> 00:40:26,249 +gonna see the controller that matches what you +看到,跟你在 Storyboard 里选择的控件相对应的 + +922 +00:40:26,251 --> 00:40:27,650 +have selected in your Storyboard. +控制器实现的代码 + +923 +00:40:29,387 --> 00:40:31,186 +So here we can have that. +所以这里,我们有 FaceView 的实现代码 + +924 +00:40:31,188 --> 00:40:34,589 +So I'm just going to take my controller right here and +所以我要在这里选择我的控制器 + +925 +00:40:34,591 --> 00:40:37,058 +I'm going to Ctrl+drag to create an outlet. +同时 Control 并拖拽来创建一个 outlet + +926 +00:40:37,060 --> 00:40:41,028 +This is the same way that I create an outlet to buttons or +这种方式和创建 button 或者 + +927 +00:40:41,030 --> 00:40:42,529 +to the labels or whatever we've done. +label 的 outlet 的方式是一模一样的 + +928 +00:40:42,531 --> 00:40:43,296 +It's exactly the same. +完全一样 + +929 +00:40:43,298 --> 00:40:44,931 +It's just a normal outlet. +好的,这就是个普通的 outlet + +930 +00:40:44,933 --> 00:40:48,067 +I'm going to call it Face View. +我把它命名为 faceView + +931 +00:40:49,103 --> 00:40:52,037 +So here's really nice FaceView right there. +于是这里有一个 faceView 了 + +932 +00:40:52,039 --> 00:40:55,473 +Now where in my code should I go and +现在,在代码中,哪里去 + +933 +00:40:55,475 --> 00:40:58,843 +set this var right here? +设置这个变量呢? + +934 +00:40:58,845 --> 00:41:00,277 +Okay, this data source var. +这个 dataSource 变量 + +935 +00:41:00,279 --> 00:41:03,914 +Well a great place to do it since this is +好吧,既然我们想把 dataSource 变量 + +936 +00:41:03,916 --> 00:41:05,716 +the faceView we want to set that in, +设置到 faceView 中,所以 faceView 是一个不错的地方 + +937 +00:41:05,718 --> 00:41:11,554 +is right here in the property observer for the FaceView. +就是在这里,FaceView 的 property observer + +938 + 00:41:11,556 --> 00:41:15,124 +This property observer is called when the iOS starts up +这样,这个 property observer 会在 iOS 启动这个应用 + +939 +00:41:15,126 --> 00:41:16,725 +and loads the story board. +并加载这个 Storyboard 时被调用 + +940 +00:41:16,727 --> 00:41:18,360 +It connects this outlet. +它连接这个 outlet + +941 +00:41:18,362 --> 00:41:21,029 +It's going to set this variable. +然后设置这个变量 + +942 +00:41:21,031 --> 00:41:23,998 +And so it's a perfect time when this is +所以这是个完美的时刻 + +943 +00:41:24,000 --> 00:41:25,399 +being set to go ahead and +去设置变量,然后继续程序的执行 + +944 +00:41:25,401 --> 00:41:30,103 +say FaceView.dataSource equals self, okay? +我们输入 faceView.dataSource = self + +945 +00:41:30,105 --> 00:41:31,504 +This is the controller. +self 在这里是控制器自身 + +946 +00:41:31,506 --> 00:41:33,990 +It's perfectly legal for +所以这么写完全没问题 + +947 +00:41:33,991 --> 00:41:36,475 +it to say this because it is a FaceView data source, right? +因为它是 FaceView 的 dataSource,没问题吧? + +948 +00:41:36,478 --> 00:41:38,911 +The happiness view controller is a face view data source so +HappinessViewController 是 FaceView 的 dataSource + +949 +00:41:38,913 --> 00:41:41,547 +we can say that it is the new source. +所以我们说它是新的 dataSource + +950 +00:41:41,549 --> 00:41:42,714 +It's perfectly fine equals. +赋值完全没有问题 + +951 +00:41:42,716 --> 00:41:45,016 +All right? +明白了吗? + +952 +00:41:45,018 --> 00:41:46,784 +That make sense that we're doing that? +明白我们这么做的意义了吗? + +953 +00:41:48,087 --> 00:41:50,087 +Okay, so now everything is hooked, +好的,现在一切都关联好了 + +954 +00:41:50,089 --> 00:41:52,422 +and how is this gonna work. +你们会问,这是怎么工作的 + +955 +00:41:52,424 --> 00:41:55,391 +It's going to be very straight forward. +答案是非常直接的 + +956 +00:41:56,561 --> 00:41:59,828 +Every time that the face redraws itself, +每次 faceView 重绘自身的时候 + +957 +00:41:59,830 --> 00:42:03,265 +it's going to look for its data source. +它会去查找自己的 dataSource + +958 +00:42:03,267 --> 00:42:06,634 +Which we have set right here in our controller to +也就是我们在控制器的这里设置的 + +959 +00:42:06,636 --> 00:42:07,869 +be the controller itself. +控制器自身 + +960 +00:42:09,038 --> 00:42:11,438 +It's going to get its smiliness from the data +它会从 dataSource + +961 +00:42:11,440 --> 00:42:15,975 +source by calling the method in the protocol up here, okay? +通过调用上面协议里的方法, 来获得 smiliness 的值,明白了吗? + +962 +00:42:15,977 --> 00:42:18,478 +We implement that method in our controller. +我们在控制器里实现了对应的方法 + +963 +00:42:18,480 --> 00:42:20,813 +We interpret the Model for the view. +我们为视图解析模型中的变量 + +964 +00:42:20,815 --> 00:42:22,815 +And the FaceView's gonna be able to draw the proper value. +然后 FaceView 就会用合适的值绘制出它自身 + +965 +00:42:22,817 --> 00:42:26,885 +Now there's only one other thing that I wanna do here. +现在这里只剩下一件我另外要做的事了 + +966 +00:42:26,887 --> 00:42:29,120 +Which is every time something changes our Model, +也就是每次我们的模型有变动时 + +967 +00:42:29,122 --> 00:42:30,922 +I wanna make sure the face redraws itself. +我要让 faceView 重新绘制自身 + +968 +00:42:30,924 --> 00:42:35,993 +Of course, because we're representing that in the face. +这是当然的,因为我们要在 faceView 中表现出来 + +969 +00:42:35,995 --> 00:42:39,363 +So the best space to do that is in this update UI, so +所以做这个的最佳的位置是 UpdateUI + +970 +00:42:39,365 --> 00:42:42,899 +every single time the happiness changes I'm going to +每一次 happiness 的值发生变动了 + +971 +00:42:42,901 --> 00:42:48,304 +ask my faceView to set needs display of itself. +我都会让 faceView 在自身上调用 setNeedsDisplay + +972 +00:42:48,306 --> 00:42:50,272 +In other words, to redraw. +换句话说,重绘 + +973 +00:42:50,274 --> 00:42:53,141 +Remember setNeedsDisplay is the thing you do that says +还记得吗,setNeedsDisplay 就是那种 + +974 +00:42:53,143 --> 00:42:55,744 +hey, call my draw rect, redraw me. +“嘿,调用我的 drawRect 函数,重绘我”的意思 + +975 +00:42:55,746 --> 00:42:57,111 +Now if I didn't do this then every time I +现在如果我没有做这个,那么每次 + +976 +00:42:57,113 --> 00:42:59,680 +set my happiness the FaceView would not draw, okay? +我设置 happiness,faceView 都不会重新绘制,明白了吗? + +977 +00:42:59,682 --> 00:43:02,716 +Now maybe if I rotated my device and +当然有可能因为我旋转了我的设备之后 + +978 +00:43:02,718 --> 00:43:06,519 +it redrew then it would show it but. +faceView 进行了重绘并显示出来 + +979 +00:43:07,622 --> 00:43:12,024 +Otherwise it wasn't gonna show it. +否则它并不会重绘并显示 + +980 +00:43:12,026 --> 00:43:14,426 +We've got this hooked up, it really should be the happiness +我们把这个关联上了,它应该是真正的 + +981 +00:43:14,428 --> 00:43:17,495 +that's showing in here rather than the smiliness. +显示在这里的 happiness 而不是 smiliness + +982 +00:43:17,497 --> 00:43:19,731 +So it shouldn't be a flat line right here, +所以它不该是这样的一条水平直线 + +983 +00:43:19,733 --> 00:43:21,432 +it should actually show the happiness. +它应该实际展示 happiness + +984 +00:43:21,434 --> 00:43:24,435 +Let's go ahead run, see what we got here. +我们运行一下,看看效果如何 + +985 +00:43:29,107 --> 00:43:31,207 +I knew we should get a happiness of 75, +我们应该得到一个值为75的 happiness + +986 +00:43:31,209 --> 00:43:34,243 +which is a little bit happy. +看上去有点的高兴的样子 + +987 +00:43:34,245 --> 00:43:36,078 +Yeah. That looks good right there. +好的,看上去挺不错 + +988 +00:43:36,080 --> 00:43:40,048 +Let's go change our happiness here to be sad, like maybe 10. +我们把 happiness 改成悲伤的数值,比如说10 + +989 +00:43:40,050 --> 00:43:41,716 +Go ahead and re-run. +重新运行 + +990 +00:43:44,053 --> 00:43:48,588 +Okay, we're sad, all right and +好的,现在我们看上去是悲伤的 + +991 +00:43:48,590 --> 00:43:55,995 +let's go to the ecstatic and we're ecstatic, okay? +我们展示一下狂喜,现在,我们看上去非常开心,没问题吧? + +992 +00:43:55,997 --> 00:43:57,863 +Or we should be ecstatic because we +我们应该非常开心,因为 + +993 +00:43:57,865 --> 00:44:00,198 +successfully implemented delegation. +我们成功地实现了这个代理(dataSource) + +994 +00:44:04,404 --> 00:44:06,437 +>> All right. +好的 + +995 +00:44:06,438 --> 00:44:08,471 +Let's go back to our slides and +我们回到 Slide 上 + +996 +00:44:08,474 --> 00:44:12,109 +cover the next thing here, which is gestures. +讨论下一个东西,也就是手势 + +997 +00:44:13,311 --> 00:44:14,544 +All right. +好的 + +998 +00:44:14,545 --> 00:44:15,778 +So we know how to draw inner view, +我们已经知道怎么去绘制一个视图的内部 + +999 +00:44:15,780 --> 00:44:17,313 +now we wanna handle these gestures. +现在我们要处理这些手势 + +1000 +00:44:17,315 --> 00:44:19,599 +Okay? + +1001 +00:44:19,600 --> 00:44:21,884 +You know, pinches and maybe rotations, swipes, taps, +比如,缩放、旋转、滑动、点击 + +1002 +00:44:21,886 --> 00:44:24,170 +things like that. +等手势 + +1003 +00:44:24,171 --> 00:44:26,455 +Now we could get the raw data about every finger that +我们可以获取到每个手指按下 + +1004 +00:44:26,457 --> 00:44:29,691 +goes down, and where it is, that data is available, but +位置的原始信息,比如其坐标系、是否可用等信息 + +1005 +00:44:29,693 --> 00:44:31,325 +we never look at that. +但是我们很少直接使用这些它们 + +1006 +00:44:31,327 --> 00:44:34,061 +First of all it's very difficult to +因为我们很难自己来处理这些原始信息 + +1007 +00:44:34,063 --> 00:44:35,562 +look at that raw data, and + +1008 +00:44:35,564 --> 00:44:39,199 +see, is this a swipe, or is it just moving over to the right. +去判断,这是一个滑动手势,还是单纯地向右滑动 + +1009 +00:44:40,168 --> 00:44:41,534 +So iOS does all that for +所以,iOS 为我们做了底层封装 + +1010 +00:44:41,536 --> 00:44:44,203 +you, and that's the only way I'm going to teach you +而本课上,我只会教你 + +1011 +00:44:44,205 --> 00:44:48,006 +to react to user touches is via gestures, okay? +通过手势来处理用户的触摸事件,明白吗? + +1012 +00:44:48,008 --> 00:44:49,540 +So how do gestures work? +那么手势是如何工作的呢? + +1013 +00:44:49,542 --> 00:44:52,677 +Gestures are recognized by UI views when +当手指在视图边界内滑动时 + +1014 +00:44:52,679 --> 00:44:56,013 +the gesture happens inside their bounds. +视图会识别特定的手势 + +1015 +00:44:56,015 --> 00:44:58,782 +Okay, I told you the views are rectangular areas where you +是的,我说过,视图是用来绘制和 + +1016 +00:44:58,784 --> 00:45:00,450 +draw and you recognize gestures so +识别手势的矩形区域 + +1017 +00:45:00,452 --> 00:45:02,085 +this is how it happens. +手势识别就是这样工作的 + +1018 +00:45:02,087 --> 00:45:04,620 +There's a class called UIGestureRecognizer. +有一个叫 UIGestureRecognizer 的类 + +1019 +00:45:04,622 --> 00:45:06,255 +It's an abstract base class. +它是一个抽象的基类 + +1020 +00:45:06,257 --> 00:45:09,424 +You never actually create a UIGestureRecognizer base +通常,你不会直接创建 UIGestureRecognizer 基类, + +1021 +00:45:09,426 --> 00:45:13,128 +class, you create a sub class of UIGestureRecognizer. +而是创建它的子类 + +1022 +00:45:13,130 --> 00:45:15,263 +And those subclasses are concrete in +因为这些具体的子类 + +1023 +00:45:15,265 --> 00:45:17,932 +that they know about certain gestures, swipes and pans and +能够识别特定的手势,比如滑动、拖动 + +1024 +00:45:17,934 --> 00:45:19,233 +touches, et cetera. +触摸等 + +1025 +00:45:19,235 --> 00:45:24,137 +So there are two sides to using a gesture recognizer. +使用手势识别器有两个步骤 + +1026 +00:45:24,139 --> 00:45:27,674 +One is you have to add a gesture recognizer to a view. +首先是为视图添加手势识别器 + +1027 +00:45:27,676 --> 00:45:30,643 +That says to the view, start recognizing this gesture. +这表示,该视图现在能识别手势 + +1028 +00:45:30,645 --> 00:45:33,679 +If you recognize this gesture, you let somebody know. +如果你识别了这个手势,就报告给某个对象 + +1029 +00:45:33,681 --> 00:45:34,279 +Okay? +明白吗? + +1030 +00:45:34,281 --> 00:45:35,914 +And you do that with +完成这个步骤 + +1031 +00:45:35,915 --> 00:45:37,548 +a function on UIView called add gesture recognizer. +你只需要调用视图的 addGestureRecognized 方法 + +1032 +00:45:37,551 --> 00:45:38,950 +Couldn't be simpler. +非常简单 + +1033 +00:45:38,952 --> 00:45:42,687 +Then the second piece, though, is when you create the gesture +第二步是,当你创建手势识别器的时候 + +1034 +00:45:42,689 --> 00:45:46,323 +recognizer, you have to say, if you recognize the gesture, +你必须指定一个对象,如果视图识别了这个手势 + +1035 +00:45:46,325 --> 00:45:48,225 +who are you gonna tell about it? +就报告给这个对象 + +1036 +00:45:48,227 --> 00:45:49,893 +Okay, you have to notify somebody and +是的,你需要让某个对象知道 + +1037 +00:45:49,895 --> 00:45:51,361 +say oh, I recognize that swipe. +嘿,这是一个滑动手势 + +1038 +00:45:51,363 --> 00:45:51,961 +Okay? +明白吗? + +1039 +00:45:51,963 --> 00:45:53,395 +So there's the handler. +也就是说,你需要提供一个处理事件的对象 + +1040 +00:45:53,397 --> 00:45:56,365 +So you've got the recognizer, that's the view. +一个是识别手势的对象,就是视图 + +1041 +00:45:56,367 --> 00:45:58,800 +Okay, the gesture recognizer in association with the view. +是的,添加了手势识别器的视图 + +1042 +00:45:58,802 --> 00:46:00,935 +And then you've got the handler that's who handles it, +然后是处理事件的对象, + +1043 +00:46:00,937 --> 00:46:02,870 +and those are not always the same person. +这两个并不一定是同一个对象 + +1044 +00:46:02,872 --> 00:46:05,506 +Sometimes they're the same object, sometimes not. +有些时候是的,有些时候不是 + +1045 +00:46:05,508 --> 00:46:08,775 +Usually the first one, adding a gesture recognizer to +通常,为视图添加识别器 + +1046 +00:46:08,777 --> 00:46:11,211 +a view is done by a controller. +是通过控制器来完成的 + +1047 +00:46:11,213 --> 00:46:13,646 +Although a view will sometimes add it to itself, for +不过有些时候,视图自己也可以添加识别器 + +1048 +00:46:13,648 --> 00:46:14,914 +example scroll view. +比如 Scroll View + +1049 +00:46:14,916 --> 00:46:17,449 +Scroll view doesn't even exist without the pan and +Scroll View 可以自动识别 + +1050 +00:46:17,451 --> 00:46:19,451 +pinch gestures, that's what it does. +拖动和缩放手势 + +1051 +00:46:19,453 --> 00:46:22,020 +So it adds the gesture recognizers to itself. +它为自身添加了这些识别器 + +1052 +00:46:22,022 --> 00:46:25,189 +But a lot of times other times you have a gesture that +但是大多数时候 + +1053 +00:46:25,191 --> 00:46:28,992 +you're going to recognize only if the controller wants you to +只有在控制器需要视图识别手势的时候 + +1054 +00:46:28,994 --> 00:46:31,411 +recognize it, so +你才添加识别器到视图上 + +1055 +00:46:31,412 --> 00:46:33,829 +you make some public handler possibly in your view. +你可能在视图中实现公开的触摸事件响应方法 + +1056 +00:46:33,832 --> 00:46:37,233 +And then your controller can add this gesture recognizer to +然后控制器可以添加这个识别器到 + +1057 +00:46:37,235 --> 00:46:39,035 +one of its views, one of its minions and say, +它其中的一个视图 + +1058 +00:46:39,037 --> 00:46:41,804 +start recognizing this gesture and you can even handle it +这个视图就开始识别手势,甚至在手势被识别后 + +1059 +00:46:41,806 --> 00:46:44,106 +yourself if you want, the controller might say. +可以自己处理相关事件 + +1060 +00:46:44,108 --> 00:46:47,009 +Or the controller might say oh, and I'll handle it. +又或者控制器说“由我来处理” + +1061 +00:46:47,011 --> 00:46:49,778 +So the second thing, the handling is either done by +所以,第二步中,如果是显示相关的事件 + +1062 +00:46:49,780 --> 00:46:53,281 +the view if it's a display-oriented handling +如果这是一个显示主导型的时间处理,一般由视图自己来处理 + +1063 +00:46:53,283 --> 00:46:56,217 +thing, or it's done by the controller if it's handling +而如果涉及到修改模型的时候 + +1064 +00:46:56,219 --> 00:46:58,719 +something that's going to modify the Model. +事件一般由控制器来处理 + +1065 +00:46:58,721 --> 00:47:00,320 +Okay? Or be something that's +明白吗? 如果 + +1066 +00:47:00,322 --> 00:47:03,623 +complicated that's going to cause multiple views to +涉及很多视图这种复杂情况的时候 + +1067 +00:47:03,625 --> 00:47:05,525 +be involved and so the controller has to do it. +就必须由控制器来处理了 + +1068 +00:47:05,527 --> 00:47:08,260 +And it's perfectly fine to have either the controller or +所以,事件的处理通常都是由控制器 + +1069 +00:47:08,262 --> 00:47:10,295 +the view handle something although you would +或者视图两个中的一个来完成的, + +1070 +00:47:10,297 --> 00:47:13,665 +never have the view handle a gesture that is directly +你绝不会在视图中直接 + +1071 +00:47:13,667 --> 00:47:15,633 +modifying the Model cuz a view can't see the Model. +修改模型,因为模型对视图应该是不可见的 + +1072 +00:47:15,635 --> 00:47:17,635 +Only a controller can do that. +只有控制器可以直接和模型交互 + +1073 +00:47:18,838 --> 00:47:20,871 +Okay? +明白吗? + +1074 +00:47:20,872 --> 00:47:22,905 +So how do you add a gesture recognizer to a UI view? +那么,怎样为视图添加识别器呢? + +1075 +00:47:22,908 --> 00:47:24,274 +It's very simple. +非常简单 + +1076 +00:47:24,276 --> 00:47:27,310 +I'm going to do it in a way that is very common, which is +我会用一种很通用的方式, + +1077 +00:47:27,312 --> 00:47:31,147 +to do it in the property observer of an outlet setter, +就是在属性监听(property observer)的 set 方法中来完成, + +1078 +00:47:31,149 --> 00:47:34,784 +just exactly like we did when we set the face views delegate +就和我们在设置 faceView 代理一样 + +1079 +00:47:34,786 --> 00:47:38,420 +in the property observer, when the face view got set. +当 faceView 调用 set 方法时,我们为它设置代理 + +1080 +00:47:38,422 --> 00:47:40,789 +We could do the same thing adding adjuster recognizer. +我们可以通过同样的方法来添加手势识别器 + +1081 +00:47:40,791 --> 00:47:42,924 +In fact, we're going to do that in the demo. +事实上,我们会在 Demo 中演示这个过程 + +1082 +00:47:42,926 --> 00:47:44,926 +So here I have an IV outlet. +这里我有一个 IBOutlet 属性 + +1083 +00:47:44,928 --> 00:47:47,361 +It's just a UI view. +就是一个 UIView + +1084 +00:47:47,363 --> 00:47:49,363 +In my story board. +在 Storyboard 中的一个视图 + +1085 +00:47:49,365 --> 00:47:50,864 +It's called pannableView and +它叫 pannableView + +1086 +00:47:50,866 --> 00:47:54,000 +I'm going to make it so it can pan around in there. +我希望可以拖动这个视图 + +1087 +00:47:54,002 --> 00:47:58,170 +All right, and in his property observer there the did stat. +好的,在这个属性监听器的 didSet 方法中 + +1088 +00:47:59,206 --> 00:48:02,274 +I'm going to add this gesture recognizer. +我将添加这个识别器 + +1089 +00:48:02,276 --> 00:48:04,242 +I'm going to create a pan gesture recognizer and +我需要创建拖动手势识别器 + +1090 +00:48:04,244 --> 00:48:05,376 +then add it to the view. +然后添加到视图中 + +1091 +00:48:05,378 --> 00:48:06,577 +So here I'm creating it. +这里我创建它 + +1092 +00:48:06,579 --> 00:48:08,813 +This is just +我只需要 + +1093 +00:48:08,814 --> 00:48:11,048 +calling UIPanGestureRecognizer initializer here. +调用 UIPanGestureRecognizer 的初始化方法即可 + +1094 +00:48:11,050 --> 00:48:13,750 +The arguments to the initializer are who to +第一个参数表示,当手势被识别的时候 + +1095 +00:48:13,752 --> 00:48:18,421 +send a message to when the gesture is recognized. +向谁发送消息 + +1096 +00:48:18,423 --> 00:48:20,122 +When we start seeing a pan. +当视图识别到拖动手势 + +1097 +00:48:20,124 --> 00:48:22,224 +And as the pan is happening we're gonna be +我们会向这个对象 + +1098 +00:48:22,226 --> 00:48:24,159 +sending a message to this object. +发送一个消息 + +1099 +00:48:24,161 --> 00:48:25,560 +In this case it's self. +这里,它是 self + +1100 +00:48:25,562 --> 00:48:28,496 +So this method would obviously be in a controller, right? +所以这个方法肯定在一个控制器中,对吗? + +1101 +00:48:28,498 --> 00:48:29,597 +Because controllers are the only +因为只有 + +1102 +00:48:29,599 --> 00:48:31,031 +things that have the outlets. +控制器才会有 outlets + +1103 +00:48:31,033 --> 00:48:32,332 +So this thing's going to be +所以这里 + +1104 +00:48:32,334 --> 00:48:34,367 +handled by the controller itself. +会由控制器来处理 + +1105 +00:48:34,369 --> 00:48:37,437 +And then action is the name of the method. +action 参数表示事件处理的方法名称 + +1106 +00:48:37,439 --> 00:48:38,971 +It's just a string that is the name of +就是方法名称字符串 + +1107 +00:48:38,973 --> 00:48:41,874 +the method that's gonna be +当手势被识别的时候 + +1108 +00:48:41,875 --> 00:48:44,776 +called in the controller when this gesture is recognized. +会调用控制器中的这个方法 + +1109 +00:48:44,778 --> 00:48:47,278 +Now notice there's a little colon on the end there? +看见后面的冒号了吗? + +1110 +00:48:47,280 --> 00:48:50,581 +That means that it's called a, it's gonna +这表示 + +1111 +00:48:50,583 --> 00:48:52,683 +call a method called pan that has an argument. +这个 pan: 方法会有一个参数 + +1112 +00:48:52,685 --> 00:48:54,251 +That's what the colon means. +这就是冒号的意思 + +1113 +00:48:54,253 --> 00:48:55,786 +There's an argument there. +表示方法需要一个参数 + +1114 +00:48:55,788 --> 00:48:58,221 +Okay, now you don't have to have the colon there if +你也可以不添加冒号 + +1115 +00:48:58,223 --> 00:49:00,690 +you want, but if you don't have it there, then you +如果没有冒号,那么 pan: 被调用的时候 + +1116 +00:49:00,692 --> 00:49:02,958 +won't get the argument when pan gets called and +你就得不到这个参数 + +1117 +00:49:02,960 --> 00:49:05,327 +the argument you get is the gesture recognizer. +而这个参数就是手势识别器 + +1118 +00:49:05,329 --> 00:49:07,829 +And for something like pan where you're gonna try and +有时候你需要 + +1119 +00:49:07,831 --> 00:49:09,330 +figure out where the finger is, +判断手指的点击位置 + +1120 +00:49:09,332 --> 00:49:10,965 +you need the gesture recognizer so +这样你就必须得到这个参数 + +1121 +00:49:10,967 --> 00:49:13,501 +it can tell you where the finger is basically, okay? +来判断手指的触点在哪里 + +1122 +00:49:13,503 --> 00:49:15,235 +So we almost always have a colon. +因此,我们通常都有冒号 + +1123 +00:49:15,237 --> 00:49:16,837 +The only place you +只有在 + +1124 +00:49:16,838 --> 00:49:18,438 +wouldn't have a colon might be like a swipe. +使用滑动手势的时候你不需要冒号 + +1125 +00:49:18,440 --> 00:49:20,507 +Because the swipe just got recognized, +因为这就是一个滑动手势 + +1126 +00:49:20,509 --> 00:49:21,741 +you don't really need any information, +你不需要额外的信息 + +1127 +00:49:21,743 --> 00:49:25,762 +you just need to know what happened. +你只需要知道识别到了一个滑动手势 + +1128 +00:49:25,763 --> 00:49:29,782 +So you might have action, quote, handle swipe, no colon. +所以你只需要在双引号中加上方法名称即可,不需要冒号 + +1129 +00:49:29,784 --> 00:49:31,016 +Then we just ask the view, +然后,我们告诉视图 + +1130 +00:49:31,018 --> 00:49:33,785 +this panable view, please recognize this gesture when it +当一个拖动手势发生它的边界之内的时候 + +1131 +00:49:33,787 --> 00:49:35,286 +happens inside your bounds. +请识别这个手势 + +1132 +00:49:38,190 --> 00:49:40,257 +Okay that's simple, that's like turning on, +就是这么简单,就像打开了开关 + +1133 +00:49:40,259 --> 00:49:41,358 +this is the on switch, for +这句话就是“开”开关 + +1134 +00:49:41,360 --> 00:49:43,159 +turning on that pan gesture I recognized, +打开了之后,通过向某个对象发送“识别它”的这么一个消息 + +1135 +00:49:43,161 --> 00:49:45,161 +by asking some of you to recognize it. +我启动这个手势识别器并开始识别拖动手势 + +1136 +00:49:45,163 --> 00:49:48,864 +So now every time this view recognizes a pan going on +这样每次视图在边界内识别了拖动手势的时候 + +1137 +00:49:48,866 --> 00:49:51,933 +inside its bounce it's going to send the message pan +它就会向控制器发送带一个参数的 + +1138 +00:49:51,935 --> 00:49:54,268 +with an argument to the controller. +pan 消息 + +1139 +00:49:56,105 --> 00:49:56,970 +Everybody okay with this? +都明白了吗? + +1140 +00:49:57,940 --> 00:50:01,141 +This is how you set up a gesture recognizer. +这是配置手势识别器的方法 + +1141 +00:50:01,143 --> 00:50:03,076 +How about the handler? +那么如何处理事件呢? + +1142 +00:50:03,078 --> 00:50:06,379 +So that pan thing with that argument, how do we do that? +有了这个参数后,我们可以做哪些事情呢? + +1143 +00:50:06,381 --> 00:50:09,448 +For us to handle the pan we need information about +在处理拖动手势的时候,我们需要 + +1144 +00:50:09,450 --> 00:50:11,216 +what's going on in that pan. +知道它的一些信息 + +1145 +00:50:11,218 --> 00:50:12,650 +Where are the fingers moving? +比如手指移动到哪里了? + +1146 +00:50:12,652 --> 00:50:14,118 +We need to know about that. +我们需要知道这些 + +1147 +00:50:14,120 --> 00:50:17,788 +So the concrete subclasses of UI gesture recognizer like UI +UIGestureRecognizer 的子类,比如 + +1148 +00:50:17,790 --> 00:50:21,258 +pangesture recognizer, they add methods that +PanGestureRecognizer,他们针对特定的手势 + +1149 +00:50:21,260 --> 00:50:23,727 +are specific to whatever kind of gesture they are. +添加了自己特定的方法 + +1150 +00:50:23,729 --> 00:50:26,930 +So the panGesture one has a translation in +比如 PanGesture 就有 translationInView 方法 + +1151 +00:50:26,932 --> 00:50:30,900 +view which tells you how far the finger has moved since, +用来告诉你,从手势被识别或重置开始 + +1152 +00:50:30,902 --> 00:50:34,737 +either since the panGesture was first recognized, or +手指移动了多远的 + +1153 +00:50:34,739 --> 00:50:36,705 +since that last got reset. +距离 + +1154 +00:50:38,141 --> 00:50:41,709 +And you can reset with this set translation which will +你可以通过 setTranslation 方法 + +1155 +00:50:41,711 --> 00:50:43,778 +reset this translation to a different spot so +重置这个起点 + +1156 +00:50:43,780 --> 00:50:45,813 +that the next time that you get notified, +这样下一次计算拖动距离的时候 + +1157 +00:50:45,815 --> 00:50:47,948 +it will be the distance between this. +会以你重置的起点开始计算 + +1158 +00:50:47,950 --> 00:50:50,383 +So that's a good way to get incremental panning instead of +这是一个得到增加距离的好方法 + +1159 +00:50:50,385 --> 00:50:52,251 +just the total distance that you've panned. +而不是得到移动的总距离 + +1160 +00:50:52,253 --> 00:50:54,353 +And then also I can tell you velocity, +还可以得到速度(velocity) + +1161 +00:50:54,355 --> 00:50:56,188 +how fast are you panning around? +拖动的速度有多快? + +1162 +00:50:56,190 --> 00:50:58,123 +Is the person kinda moving real slow, or +用户可能拖动得很慢,或者是想 + +1163 +00:50:58,125 --> 00:50:59,457 +trying to put something in a perfect spot, +拖动到某个特定的点 + +1164 +00:50:59,459 --> 00:51:01,559 +or are they kind of zooming it around, okay, +又或者是在放大缩小等 + +1165 +00:51:01,561 --> 00:51:03,327 +you might react differently depending on the velocity. +你可能对不同的速度做出不同的反应 + +1166 +00:51:03,329 --> 00:51:05,963 +So those are the things that are very specific to Pan, so +这是拖动手势的一些特有的东西,也是为什么 + +1167 +00:51:05,965 --> 00:51:08,598 +that's why these methods are in panGesture Recognizer. +这些方法属于 PanGestureRecognizer + +1168 +00:51:08,600 --> 00:51:11,434 +Now that last one is interesting because of +最后一个很有意思 + +1169 +00:51:11,436 --> 00:51:12,669 +this incremental translation. +因为它是改变的增量 + +1170 +00:51:12,671 --> 00:51:15,071 +A lot of people really don't quite understand this. +因为大多数人不是很理解这个 + +1171 +00:51:15,073 --> 00:51:16,538 +But you'll see when we do the demo, we'll +但是我在做 Demo 的时候你会明白的, + +1172 +00:51:16,540 --> 00:51:19,341 +do incremental translation with our pinch gesture. +我们会在缩放手势中演示增量改变的特性 + +1173 +00:51:19,343 --> 00:51:22,711 +And it'll make a little more sense what's going on there. +那时候你就更容易理解它了 + +1174 +00:51:22,713 --> 00:51:24,912 +The abstract superclass UIGestureRecognizer. +抽象类 UIGestureRecognizer + +1175 +00:51:24,914 --> 00:51:27,581 +It also has a very important property called State. +有个很重要的属性叫 state + +1176 +00:51:27,583 --> 00:51:31,685 +Okay when you have a pan it actually goes through states. +拖动手势会经历许多个状态 + +1177 +00:51:31,687 --> 00:51:34,421 +It starts out in the state Possible. +首先是 Possible 状态 + +1178 +00:51:34,423 --> 00:51:36,656 +It's possible a pan can happen. +表示它或许可能是一个拖动手势 + +1179 +00:51:36,658 --> 00:51:38,290 +Then if it were a swipe or +如果它是扫动或者 + +1180 +00:51:38,292 --> 00:51:40,959 +a discrete gesture, you would just get one state. +一个非连续的手势,那你就得到另一个的状态 + +1181 +00:51:40,961 --> 00:51:42,160 +Which is I recognize this. +也就是 Recognized 状态 + +1182 +00:51:42,162 --> 00:51:44,629 +So that's Recognized. +表示手势被识别了 + +1183 +00:51:44,631 --> 00:51:45,730 +But if it's pan and +但是如果是拖动手势 + +1184 +00:51:45,732 --> 00:51:48,599 +continuous, then you're gonna get began. +即手势是连续的,state 就会变为 Began 状态 + +1185 +00:51:48,601 --> 00:51:50,534 +Okay, recognize that the pan has started. +明白吗,表示拖动手势开始识别了 + +1186 +00:51:50,536 --> 00:51:51,602 +You'll get that. +就是这样 + +1187 +00:51:51,603 --> 00:51:52,669 +And then every time the finger moves, +随着手指的移动, + +1188 +00:51:52,671 --> 00:51:55,638 +you're gonna get another call to your handler saying, +会不断通知事件处理对象 + +1189 +00:51:55,640 --> 00:51:57,106 +changed, changed, changed. +状态改变为 Changed 了 + +1190 +00:51:57,108 --> 00:51:58,374 +And then when the finger goes up, +当手指离开屏幕的时候, + +1191 +00:51:58,376 --> 00:52:01,443 +you'll get another one that says the state is now ended. +状态就变为 Ended + +1192 +00:52:01,445 --> 00:52:03,245 +So this is basically a little state machine. +这是一个简单的状态机 + +1193 +00:52:03,247 --> 00:52:06,014 +Obviously a pan goes through the state machine of possible, +拖动手势在状态机中的状态就是 Possible + +1194 +00:52:06,016 --> 00:52:08,416 +began, changed, ended. +Began,Changed,Ended + +1195 +00:52:09,518 --> 00:52:10,951 +All right? +明白吗? + +1196 +00:52:10,953 --> 00:52:12,085 +There's also failed and +也有 Failed 和 Canceled 状态 + +1197 +00:52:12,087 --> 00:52:13,720 +canceled, like you're in the middle of a pan and +Canceled 状态,比如在拖动手势的中途 + +1198 +00:52:13,722 --> 00:52:15,721 +a phone call comes in, okay? +一个电话打进来了 + +1199 +00:52:15,723 --> 00:52:18,390 +That's going to cancel that pan, alright? +这样这个拖动手势就会被取消掉 + +1200 +00:52:18,392 --> 00:52:20,859 +So sometimes you have to pay attention to cancellation like +所以有时你需要注意手势的取消状态 + +1201 +00:52:20,861 --> 00:52:23,395 +that and sometimes not, it all depends on what you're doing +就像刚才这种情况,而有时候不必, + +1202 +00:52:23,397 --> 00:52:25,430 +with your pan, sometimes your pan is updating. +这全由拖动手势要实现的事情决定,有时候,拖动手势正在收集信息 + +1203 +00:52:25,432 --> 00:52:27,264 +Whatever's there is in real time and +无论状态机当前处于什么状态 + +1204 +00:52:27,266 --> 00:52:29,900 +if the phone call comes in it just stops doing that and +如果有电话打入,状态机将暂停原有操作 + +1205 +00:52:29,902 --> 00:52:32,569 +it's fine, everything is in perfectly fine state. +没问题,一切都处于正常的状态 + +1206 +00:52:32,571 --> 00:52:35,305 +Other times it might be putting something in +有时候,拖动手势会使一些东西 + +1207 +00:52:35,307 --> 00:52:36,873 +some temporary state and +处于临时状态中 + +1208 +00:52:36,875 --> 00:52:40,643 +now it's interrupted it's gotta clean up, or something. +当手势被中断,临时状态中的数据将被清空,或导致其他问题 + +1209 +00:52:40,645 --> 00:52:42,111 +All right. So given this information, +好,有了这些信息 + +1210 +00:52:42,113 --> 00:52:44,046 +what would the pan handler look like? +那拖动手势控制器到底是如何实现呢? + +1211 +00:52:44,048 --> 00:52:45,714 +Okay? The pan +拖动手势控制器 + +1212 +00:52:45,715 --> 00:52:47,381 +handler would be a method called pan. +是一个名叫 pan 的方法 + +1213 +00:52:47,384 --> 00:52:48,683 +It would take one argument which is +该方法带有一个参数 + +1214 +00:52:48,685 --> 00:52:50,484 +the UIPanGestureRecognizer itself. +即 UIPanGestureRecognizer 本身 + +1215 +00:52:50,486 --> 00:52:52,453 +You can see right there. +在这里你可以看到 + +1216 +00:52:52,455 --> 00:52:53,721 +Okay? + +1217 +00:52:53,722 --> 00:52:54,988 +We're going to look at the state machine and +我们来看一下状态机 + +1218 +00:52:54,990 --> 00:52:55,822 +say what state it's in. +状态机处于什么样的状态 + +1219 +00:52:55,824 --> 00:52:58,108 +So in my pan, +在我的拖动中 + +1220 +00:52:58,109 --> 00:53:00,393 +I'm only going to do something when the gesture moves or +只有当手势移动或者手指上划 + +1221 +00:53:00,395 --> 00:53:01,727 +the finger goes up. +我才做处理 + +1222 +00:53:01,729 --> 00:53:04,096 +I'm not even gonna do anything when it first goes down. +当它第一次滑下的时候,我不做任何处理 + +1223 +00:53:04,098 --> 00:53:05,364 +I can choose which things I wanna do. +我可以选择,我想要的操作 + +1224 +00:53:05,366 --> 00:53:08,099 +But that's what I wanna do. +这些就是我想做的 + +1225 +00:53:08,101 --> 00:53:09,600 +Hopefully you know about fall through. +愿你们对 fall through 有所了解 + +1226 +00:53:09,602 --> 00:53:10,801 +You read that in the documentation. +你在文档中查阅过相关内容 + +1227 +00:53:10,803 --> 00:53:13,070 +Fall through is just a thing in switch that says +Fall through 是在 switch 中用于 + +1228 +00:53:13,072 --> 00:53:15,772 +the implementation of this case is to go to the next one. +说明当前 case 的函数实现,即为下一个 case 的函数实现 + +1229 +00:53:15,774 --> 00:53:17,807 +And do whatever the next one is, okay? +无论下一个 case 的实现是什么 + +1230 +00:53:17,809 --> 00:53:19,175 +So it just falls through to the next case. +所以,它就落到了下一个 case + +1231 +00:53:19,177 --> 00:53:20,660 +So in changed and ended, +在 changed 和 ended 中 + +1232 +00:53:20,661 --> 00:53:22,144 +I'm gonna do exactly the same thing. +我想执行相同的函数 + +1233 +00:53:22,146 --> 00:53:25,114 +What I'm gonna do is I'm gonna find out where +我要做的就是 + +1234 +00:53:25,116 --> 00:53:30,585 +the pan is in the coordinates of the panable view, so +在可拖动 view 的坐标系中,找出拖动手势的位置 + +1235 +00:53:30,587 --> 00:53:32,020 +its coordinate system. +拖动手势所在的坐标系 + +1236 +00:53:32,022 --> 00:53:33,721 +'Kay, that's translation in view. +好,那就是拖动手势在 view 中的坐标 + +1237 +00:53:33,723 --> 00:53:35,534 +I give it the view. +我在 view 中得到这个坐标值 + +1238 +00:53:35,535 --> 00:53:37,346 +I want the coordinate system. +我需要坐标系 + +1239 +00:53:37,347 --> 00:53:39,158 +It's gonna give me the point in that view where the pan is. +它将告诉我,在 view 中拖动手势所在的点的位置 + +1240 +00:53:39,161 --> 00:53:42,429 +Then I'm gonna update anything I want inside of my controller +然后,我将更新控制器中我所需的东西 + +1241 +00:53:42,431 --> 00:53:44,798 +cuz this is being handled by the controller. +因为这就是由控制器来控制的 + +1242 +00:53:44,800 --> 00:53:47,567 +So I'm gonna update anything I want based on that +所以,我要,基于 x,y 坐标轴,来更新任何我所需要的东西 + +1243 +00:53:47,569 --> 00:53:51,103 +translation, x and y, then I'm gonna reset the translation +然后,再重置坐标 + +1244 +00:53:51,105 --> 00:53:54,340 +and I don't have to do this but I'm going to in this case, +我并非每次都必须执行这一步,但在这要做一次 + +1245 +00:53:54,342 --> 00:53:56,441 +reset the translation back to 0, so +将坐标重置为0, + +1246 +00:53:56,443 --> 00:53:59,544 +that the next time I get this called, in the next time it +这样,当下一次调用这个方法的时候,即下一次手势状态 + +1247 +00:53:59,546 --> 00:54:02,980 +changes it's gonna be just the difference. +改变的时候,将得到当前位置与上一次位置之间的偏差 + +1248 +00:54:02,982 --> 00:54:05,616 +Otherwise it's going to tell me from the time the gesture +在其他情况下,将得到第一次识别到手势 + +1249 +00:54:05,618 --> 00:54:07,351 +was first recognized to where I am now. +到这次手势位置的偏差 + +1250 +00:54:07,353 --> 00:54:08,719 +So that'd be a big distance when I +这将会是一大段距离 + +1251 +00:54:08,721 --> 00:54:11,988 +just want the incremental distance as I move around. +而我只想要这次移动的距离增量 + +1252 +00:54:11,990 --> 00:54:13,756 +So that set translation to 0 is optional, +所以将坐标设置为0是可选的 + +1253 +00:54:13,758 --> 00:54:14,490 +you can do it if you want. +如果你想做的话,可以做 + +1254 +00:54:16,060 --> 00:54:17,793 +Okay? So that's it. +就这些 + +1255 +00:54:17,795 --> 00:54:20,428 +That's how we handle a gesture. +这就是如何控制一个手势 + +1256 +00:54:20,430 --> 00:54:21,496 +Very straight forward. +非常直白 + +1257 +00:54:22,865 --> 00:54:23,931 +So let's talk about some of +我们来讨论一下,当前存在的几个 + +1258 +00:54:23,933 --> 00:54:26,133 +the concrete gestures that exist. +具体的手势 + +1259 +00:54:26,135 --> 00:54:27,300 +There's pinch. +有缩放 (pinch) 手势 + +1260 +00:54:27,302 --> 00:54:28,434 +Okay? Pinch, + + +1261 +00:54:28,436 --> 00:54:29,735 +instead of giving you translation, +pinch 手势给你传递的不是坐标 + +1262 +00:54:29,737 --> 00:54:31,103 +it gives you scale. +而是比例 + +1263 +00:54:31,105 --> 00:54:33,605 +So when the pinch starts, the scale is 1. +当 pinch 手势开始的时候,比例为1 + +1264 +00:54:33,607 --> 00:54:35,840 +If you spread your fingers out twice as wide, +如果你把你的手指拉宽两倍 + +1265 +00:54:35,842 --> 00:54:37,108 +the scale would be 2. +比例将变成2 + +1266 +00:54:37,110 --> 00:54:40,744 +If you go down to half as wide, the scale would be 0.5. +如果你将手指靠拢到一半的位置,比例将变成0.5 + +1267 +00:54:40,746 --> 00:54:42,379 +Okay? + +1268 +00:54:42,381 --> 00:54:44,280 +So that's how pinches work. +这就是 pinch 手势的工作原理 + +1269 +00:54:44,282 --> 00:54:45,548 +And it'll tell you the velocity. +它也会告诉你速度 + +1270 +00:54:45,550 --> 00:54:47,283 +How fast the person is pinching. +用户缩放的速度有多快 + +1271 +00:54:47,285 --> 00:54:48,350 +There's also rotation. +还有旋转 (rotation) 手势 + +1272 +00:54:48,352 --> 00:54:50,218 +So that's a two finger thing as well. +这也是一个两个手指的手势 + +1273 +00:54:50,220 --> 00:54:52,020 +You turn in a circle. +你在一个圆周上转动 + +1274 +00:54:52,022 --> 00:54:54,305 +So it's like you're turning a knob. +就像在转动一个旋钮 + +1275 +00:54:54,306 --> 00:54:56,589 +It tells you how many radians the thing has been rotated. +它会告诉你旋转了多少弧度 + +1276 +00:54:56,592 --> 00:54:58,158 +Okay? + +1277 +00:54:58,160 --> 00:54:59,826 +And it'll also tell you how fast in +它也会告诉你,旋转的过程中 + +1278 +00:54:59,828 --> 00:55:01,961 +radians per second the rotations happen. +每秒转动的弧度 + +1279 +00:55:01,963 --> 00:55:03,529 +So that's the way you can rotate. +这也旋转的可能情况 + +1280 +00:55:03,531 --> 00:55:04,997 +There's also swipes. +接下来是滑动 (swipes) 手势 + +1281 +00:55:04,999 --> 00:55:06,165 +Now, swipes are a little different. +swipes 手势有一些不同 + +1282 +00:55:06,167 --> 00:55:08,834 +When you create the swipe gesture, okay, +当你创建一个 swipes 手势的时候, + +1283 +00:55:08,836 --> 00:55:11,670 +back in the property observer of the outlet, +返回到 outlet 的 property observer 中 + +1284 +00:55:11,672 --> 00:55:13,237 +I created a pan gesture. +我创建了一个拖动手势 + +1285 +00:55:13,239 --> 00:55:15,239 +But if I created a swipe gesture there, +但如果我创建了一个 swipe 手势 + +1286 +00:55:15,241 --> 00:55:16,440 +I would send a message, +我将发送一条消息 + +1287 +00:55:16,442 --> 00:55:18,475 +set the property of the swipe gesture, +来设置 swipe 手势的属性, + +1288 +00:55:18,477 --> 00:55:21,544 +number of touches required, or swipe direction there, and +点击所需的次数,或者滑动的方向 + +1289 +00:55:21,546 --> 00:55:24,580 +that determines whether it's a two finger swipe to the left +这也决定了是两个手指向左滑动, + +1290 +00:55:24,582 --> 00:55:27,016 +or a one finger swipe down, or whatever. +还是一个手指向下滑动,或者其他什么 + +1291 +00:55:27,018 --> 00:55:29,351 +You just kinda say what kind of swipe you're looking for, +你只需要说明你在查找的滑动类型 + +1292 +00:55:29,353 --> 00:55:32,487 +and then your handler would only be called once, +在状态为 .Recognized 的情况下, + +1293 +00:55:32,489 --> 00:55:35,924 +with the state .Recognized when that combination +一旦手指合并,且向指定方向滑动, + +1294 +00:55:35,926 --> 00:55:37,625 +of fingers and direction happens. +控制器将会被调用 + +1295 +00:55:37,627 --> 00:55:40,661 +So that's a little different than these other ones. +所以,这里与其他的有些不同 + +1296 +00:55:40,663 --> 00:55:41,995 +And there's also tap, a question. +接下来是点击 (Tap) 手势,说你的问题 + +1297 +00:55:41,997 --> 00:55:46,366 +>> Also for these gestures I said you can now test in +(学生提问) + +1298 +00:55:46,368 --> 00:55:48,668 +the simulator, right? +(学生提问) + +1299 +00:55:48,670 --> 00:55:50,036 +>> Can you test these in the simulator? +>> 我们可以在模拟器中,测试这些手势吗? + +1300 +00:55:50,038 --> 00:55:50,869 +Absolutely you can test these in +你当然可以在模拟器中测试这些手势 + +1301 +00:55:50,871 --> 00:55:52,454 +the simulator, I'll show you. +我将会展示给你们看 + +1302 +00:55:52,455 --> 00:55:54,038 +>> How do you test more than one finger? +(学生提问) + +1303 +00:55:54,041 --> 00:55:56,675 +>> Yes, how do you test more than one finger in +>> 要如何在模拟器中测试多于一个手指的手势 + +1304 +00:55:56,677 --> 00:55:59,577 +the simulator, I'll show you how to do that. +我将会给你们展示,这个手势的操作方法 + +1305 +00:55:59,579 --> 00:56:01,078 +Tap gesture is an interesting one. +点击 (Tap) 手势是比较有趣的手势之一 + +1306 +00:56:01,080 --> 00:56:02,196 +It seems like it would be +这个手势看起来似乎是 + +1307 +00:56:02,197 --> 00:56:03,313 +discrete because it's kind of like swipe. +间断的,因为这类似于滑动 (swipe) 手势 + +1308 +00:56:03,315 --> 00:56:05,582 +You set up the number of taps and the number of touches. +你可以设置点击 (tap) 和触摸 (touch) 的次数 + +1309 +00:56:05,584 --> 00:56:08,018 +Except for that if you have a double tap it'll actually tell +除此之外,如果你双击,事实上它会告诉 + +1310 +00:56:08,020 --> 00:56:10,887 +you about the first tap and the second tap. +你第一次的点击和第二次的点击 + +1311 +00:56:10,889 --> 00:56:12,988 +So if you're only interested in the actual double tap you +所以,如果你需要知道双击 + +1312 +00:56:12,990 --> 00:56:14,323 +can just look at the state ending because +你可以只关注结束的状态 + +1313 +00:56:14,325 --> 00:56:15,957 +that's the end of that gesture. +因为那是该手势的结尾 + +1314 +00:56:15,959 --> 00:56:18,793 +But if you want to look at the intermediate states you +但如果你想要关注中间状态 + +1315 +00:56:18,795 --> 00:56:22,163 +can actually look at the dot changed stated as well, so +实际上,你也可以查看点改变的状态 + +1316 +00:56:22,165 --> 00:56:23,998 +it's not purely a discrete gesture tap. +所以这并不是一个真正的分离手势 + +1317 +00:56:25,701 --> 00:56:28,535 +Okay, so let's go look at how we do gestures by putting some +好,一起来看一下,我们应该如何为 + +1318 +00:56:28,537 --> 00:56:29,436 +gestures in the FaceView. +FaceView 添加手势 + +1319 +00:56:29,438 --> 00:56:31,137 +So I'm gonna put two gestures in. +我要添加两个手势 + +1320 +00:56:31,139 --> 00:56:35,141 +I'm gonna put in pinch to change the size of the face, +添加 pinch 手势来改变脸的大小 + +1321 +00:56:35,143 --> 00:56:40,612 +and then I'm gonna put in pan to control the happiness, +然后,添加 pan 手势来控制表情 + +1322 +00:56:40,614 --> 00:56:41,980 +in other words, control my Model. +换句话说,控制我的模型 + +1323 +00:56:43,650 --> 00:56:44,515 +All right? + + +1324 +00:56:44,517 --> 00:56:45,382 +With pan. +用 pan 手势 + +1325 +00:56:45,384 --> 00:56:46,900 +When I move up and +当我上下拖动, + +1326 +00:56:46,901 --> 00:56:48,417 +down it's gonna be happy is up, sad is down. +向上拖动时,是开心的表情;向下拖动时,是悲伤的表情 + +1327 +00:56:48,420 --> 00:56:50,020 +Not a swipe but actual pan so +不是滑动,而是拖动 + +1328 +00:56:50,022 --> 00:56:52,855 +I can move my happiness up in small increments if I want. +所以,如果我想的话,我也可以将这个表情向上移动一点 + +1329 +00:56:54,191 --> 00:56:57,693 +All right, so let's go back to here to do that. +好,让我们继续 + +1330 +00:56:57,695 --> 00:57:03,765 +So let's go get some more space here. +让我们腾出更多的空间 + +1331 +00:57:03,767 --> 00:57:06,100 +So we'll go here. +从这里开始 + +1332 +00:57:06,102 --> 00:57:10,170 +So we'll do the pinch first. +我们先来完成这个 pinch 手势 + +1333 +00:57:10,172 --> 00:57:12,105 +Let's do the pinch first. +先做 pinch 手势 + +1334 +00:57:12,107 --> 00:57:14,707 +So the first thing I'm gonna do when I +当我添加 pinch 手势的时候,我要做的第一件事 + +1335 +00:57:14,709 --> 00:57:18,444 +make my pinch happen is to add a gesture recognizer. +添加一个手势识别器 + +1336 +00:57:18,446 --> 00:57:22,181 +A pinch gesture recognizer to my FaceView. +针对 FaceView 的 pinch 手势识别器 + +1337 +00:57:22,183 --> 00:57:24,483 +And so a great place to do that, +添加这个方法的位置 + +1338 +00:57:24,484 --> 00:57:26,784 +as I said, is in the property observer of the FaceView. +正如我所说,就是在 FaceView 的 Property Observer 中 + +1339 +00:57:26,787 --> 00:57:29,554 +So here I can just say, add gesture. +所以,这里我只需要写 addGesture + +1340 +00:57:29,556 --> 00:57:31,155 +Whoops, sorry, FaceView. +抱歉,FaceView + +1341 +00:57:31,157 --> 00:57:32,490 +FaceView. + +1342 +00:57:32,492 --> 00:57:34,458 +Add gesture recognizer. +AddGestureRecognizer + +1343 +00:57:34,460 --> 00:57:36,460 +And this is just any kind of gesture recognizer. +这是任意类型的手势识别器 + +1344 +00:57:36,462 --> 00:57:37,627 +I'm going to do a pan Gesture. +而我要做的是 pan 手势 + +1345 +00:57:37,629 --> 00:57:40,329 +So I'm going to say UI Pan gesture recognizer. +所以,我要写 UIPanGestureRecognizer + +1346 +00:57:40,331 --> 00:57:41,497 +And then you can see that it +你可以看到 + +1347 +00:57:41,499 --> 00:57:44,199 +has target in action are the arguments. +action 中的 target 是参数 + +1348 +00:57:44,201 --> 00:57:48,103 +So the target I'm gonna have the pinch be handled +我要使 pinch 完全由 view 来控制 + +1349 +00:57:48,105 --> 00:57:50,171 +entirely by the view. + + +1350 +00:57:50,173 --> 00:57:52,440 +Because all it's doing is changing the view scale. +因为手势的所有操作,都是在改变 view 的比例 + +1351 +00:57:52,442 --> 00:57:53,991 +Its own scale. +view 本身的比例 + +1352 +00:57:53,992 --> 00:57:55,541 +So there's no reason I'm the controller I don't need to +毫无疑问,我是 controller,我没有必要 + +1353 +00:57:55,544 --> 00:57:56,843 +get involved with that. +处理那些事情 + +1354 +00:57:56,845 --> 00:58:00,347 +So I'm just going to have the target be the FaceView. +所以,我只需要将 FaceView 传给 target + +1355 +00:58:00,349 --> 00:58:04,183 +So the FaceView is going to handle this pan. +由 FaceView 处理拖动手势 + +1356 +00:58:04,185 --> 00:58:06,085 +Or, sorry, we're doing pan, no, we'll do pinch. +抱歉,我们要做 pinch,不是 pan + +1357 +00:58:06,087 --> 00:58:06,985 +So I'm doing pinch. +我要做 pinch + +1358 +00:58:09,289 --> 00:58:10,522 +Do pinch first. +先做 pinch + +1359 +00:58:10,524 --> 00:58:11,940 +So we're doing pinch. +好的,我们先做 pinch + +1360 +00:58:11,941 --> 00:58:13,357 +So we're doing the pinch of scale, not pan, sorry. +我们正在做比例的缩放,并不是 pan,抱歉 + +1361 +00:58:13,360 --> 00:58:15,426 +We're doing the pinch and I'm gonna have the FaceView +我们先做 pinch,我将要用FaceView + +1362 +00:58:15,428 --> 00:58:18,128 +handle this because it's just gonna modify its scale. +来控制 pinch 手势,因为它仅仅改变了 FaceView 的比例 + +1363 +00:58:19,064 --> 00:58:25,201 +And this action needs to be some nonprivate method +对于 action,在 FaceView 中,需要一个非私有的方法 + +1364 +00:58:25,203 --> 00:58:28,904 +in my FaceView that I can call to handle it. +用来调用这个函数 + +1365 +00:58:28,906 --> 00:58:33,308 +So, let's go ahead and go over to our faceview and +继续,到 faceview + +1366 +00:58:33,310 --> 00:58:34,509 +add such a thing. +添加这样的一个东西 + +1367 +00:58:34,511 --> 00:58:38,412 +So I'm going to call this method, what to call it? +我要调用这个方法,那么,谁来调用它? + +1368 +00:58:38,414 --> 00:58:39,813 +Scale. +比例 + +1369 +00:58:39,815 --> 00:58:42,299 +Okay? + +1370 +00:58:42,300 --> 00:58:44,784 +And it's going to take a UI pinch gesture recognizer +它将把 UIPinchGestureRecognizer + +1371 +00:58:44,787 --> 00:58:47,687 +as an argument, and we'll call that the gesture. +作为参数,我们将使用这个手势 + +1372 +00:58:48,956 --> 00:58:52,157 +And all this is gonna do is modify our scale. +所有的这些,都是用来调整比例大小的 + +1373 +00:58:53,894 --> 00:58:54,459 +Okay? + +1374 +00:58:55,661 --> 00:58:56,960 +Understand? You got this method here? +明白吗?都理解这个方法了吗? + +1375 +00:58:56,962 --> 00:58:58,562 +So how is this method gonna do this? +那么,这个方法将要做些什么呢? + +1376 +00:58:58,564 --> 00:59:03,833 +Well, I'm only going to adjust my scale when the pinch moves. +好,pinch 的时候,我只是在调整比例 + +1377 +00:59:04,769 --> 00:59:06,869 +I'm not gonna do it when it first goes down because it's +当手指第一次点击到屏幕的时候,我无需执行这个方法 + +1378 +00:59:06,871 --> 00:59:09,037 +gonna be scale of 1 anyway, and +因为此时无论如何它的比例都将是1 + +1379 +00:59:09,039 --> 00:59:11,873 +I probably should do it when the fingers go up, but just to +当手指移开的时候,我应该要执行这个方法,但是 + +1380 +00:59:11,875 --> 00:59:14,842 +make less code here I'm just gonna do it when it changes. +这里尽可能少写一点代码,因为我只想在手势改变的时候执行 + +1381 +00:59:14,844 --> 00:59:23,450 +So I'm gonna say if the gesture state equals .changed. +所以,我会写如果手势的状态等于 .changed + +1382 +00:59:23,452 --> 00:59:24,751 +Okay. + +1383 +00:59:24,753 --> 00:59:28,955 +Then I'm going to take my own scale and +然后,我将用原来的比例 (scale) + +1384 +00:59:28,957 --> 00:59:32,891 +multiply it by the gestures scale. +乘以手势的比例 (gesture.scale) + +1385 +00:59:32,893 --> 00:59:33,992 +Okay. + +1386 +00:59:33,994 --> 00:59:35,994 +So if the gesture pinch scales out. +如果手势向外拉伸 + +1387 +00:59:35,996 --> 00:59:37,261 +I'm going to make my scale bigger. +将使得比例增大 + +1388 +00:59:37,263 --> 00:59:39,630 +If it scales in I'm going to make my scale smaller. +如果手势向内靠拢,将使得比例缩小 + +1389 +00:59:39,632 --> 00:59:41,716 +Okay. + +1390 +00:59:41,717 --> 00:59:43,801 +And I'm going to reset the gesture scale back to 1 +我要把手势的比例 (gesture.scale) 重置为1 + +1391 +00:59:43,803 --> 00:59:45,403 +all the time. +任何情况下 + +1392 +00:59:45,404 --> 00:59:47,004 +By resetting it back to 1 then I'm only getting the +通过将比例重置为1,我才能只获取到 + +1393 +00:59:47,006 --> 00:59:49,439 +difference between the last time it told me to update. +用于更新的最后一次变化的比例大小 + +1394 +00:59:49,441 --> 00:59:52,975 +So that way I can update my scale every time it moves. +每当手势移动的时候,我将会更新比例 + +1395 +00:59:52,977 --> 00:59:54,643 +And since I keep resetting back to one, +再将比例重置为1 + +1396 +00:59:54,645 --> 00:59:56,178 +I keep getting incremental scale. +我一直获取增加的比例 + +1397 +00:59:56,180 --> 00:59:57,979 +It's gonna keep making my scale bigger or +根据最后一次 + +1398 +00:59:57,981 --> 01:00:00,148 +smaller depending on whether the last movement of +缩放的情况 + +1399 +01:00:00,150 --> 01:00:02,283 +the pinch was bigger or smaller. +使得比例变大或者变小 + +1400 +01:00:02,285 --> 01:00:04,552 +This makes my code a lot simpler. +这使得代码简洁很多 + +1401 +01:00:04,554 --> 01:00:06,887 +So that's it. That's all that's necessary. +就这么简单,这就是所有必需的代码 + +1402 +01:00:07,923 --> 01:00:11,257 +And it's typical for gesture recognizers to be this simple, +一般的手势识别器的代码就是如此简单 + +1403 +01:00:11,259 --> 01:00:14,827 +to not require a lot of code. +不需要编写一大堆的代码 + +1404 +01:00:14,829 --> 01:00:16,862 +So, this is the name of the handler. +scale 就是这个 handler 的名称 + +1405 +01:00:16,864 --> 01:00:18,731 +So, let's go back to our controller and +让我们回到 controller + +1406 +01:00:18,733 --> 01:00:20,932 +put that in here, the action is scale. +把手势识别器的 action 设置为 scale + +1407 +01:00:20,934 --> 01:00:22,500 +And it did take that argument. +由于这是其中的一个参数 + +1408 +01:00:22,502 --> 01:00:23,835 +So, I do need to put the colon there. +我需要在 scale 后面加上一个冒号 + +1409 +01:00:23,837 --> 01:00:25,970 +Okay, and that's it. +完成了 + +1410 +01:00:27,206 --> 01:00:28,071 +That's all that's required. +所有所需的代码我们都完成了 + +1411 +01:00:28,073 --> 01:00:28,972 +So, let's go ahead and try it. +让我们运行一下来看看 + +1412 +01:00:30,075 --> 01:00:33,942 +Now as was being asked here, how do I do two fingers, +这里我经常被问到的一个问题就是,如何我模拟两个手指的操作 + +1413 +01:00:33,944 --> 01:00:35,477 +I only got one mouse here. +我只有一个鼠标 + +1414 +01:00:35,479 --> 01:00:38,279 +And the answer is you hold down the option key. +回答是,你按住 option 键 + +1415 +01:00:38,281 --> 01:00:41,582 +You see when you hold down option, you get two fingers. +当你按住 option 键时,你模拟了两个手指的操作 + +1416 +01:00:41,584 --> 01:00:46,353 +Okay, and they're evenly spaced from the middle, and +没有问题吧?这两个手指与中心相对称 + +1417 +01:00:46,355 --> 01:00:49,255 +I can use them to pinch in and out. +我能使用这两个手指来模拟缩放的操作 + +1418 +01:00:52,193 --> 01:00:55,311 +Okay, there we go. +让我们继续 + +1419 +01:00:55,312 --> 01:00:58,430 +So you can see adding gestures really, really simple, okay. +你可以通过上面的演示看到,添加一个手势识别器是非常简单的 + +1420 +01:00:58,432 --> 01:00:59,698 +You can do other things too. +当然你也可以做其他的事情 + +1421 +01:00:59,700 --> 01:01:04,702 +If I can remember here I think Cmd, what is it. +可能是 ⌘(Command) 键吧,我记得 + +1422 +01:01:04,704 --> 01:01:06,287 +There's other things too, +用鼠标模拟其他的手指操作 + +1423 +01:01:06,288 --> 01:01:07,871 +I can't remember offhand what they are but +我现在记不起来了,但是 + +1424 +01:01:07,874 --> 01:01:11,408 +you can take the two things and move them. +你可以模拟两指移动 + +1425 +01:01:11,410 --> 01:01:12,843 +There we go. I'm using Shift. +噢,就是这个,按住 Control 键的同时,按住 Shift 键 + +1426 +01:01:12,845 --> 01:01:14,444 +Now you can move them up here. +现在你可以用鼠标模拟两个手指同时上移 + +1427 +01:01:14,446 --> 01:01:18,814 +So that you can expand them out from here or whatever. +你可以模拟把这个图形扩展开或者其他的什么操作 + +1428 +01:01:18,816 --> 01:01:20,282 +So you can control them a little bit. +但是你只能用鼠标模拟一点点的手指动作 + +1429 +01:01:20,284 --> 01:01:22,384 +Only two, you can't do three fingers or whatever. +因为你只能模拟两个手指的动作,不能模拟两个手指以上的动作 + +1430 +01:01:22,386 --> 01:01:25,020 +So there's some limitations but +尽管有些局限性 + +1431 +01:01:25,022 --> 01:01:28,089 +you can do some stuff there, all right. +但是至少你能在模拟器里模拟一些手指动作,明白了吗? + +1432 +01:01:28,091 --> 01:01:29,274 +So that's good. So +很好 + +1433 +01:01:29,275 --> 01:01:30,458 +now let's talk about another gesture. +让我们继续讲一下其他的手势 + +1434 +01:01:30,460 --> 01:01:32,826 +Let's do a pan gesture, where +让我们来做一个拖动手势(Pan Gesture) + +1435 +01:01:36,165 --> 01:01:41,000 +if I pan up it's gonna make my guy happier and +当我向上拖动的时候,我希望让我们的小人看上去比较开心 + +1436 +01:01:41,002 --> 01:01:42,535 +if I pan down it's gonna make him sadder. +当我向下拖动的时候,我希望让我们的小人看上去比较难过 + +1437 +01:01:43,637 --> 01:01:44,736 +Okay. +没问题吧? + +1438 +01:01:44,737 --> 01:01:45,836 +So I can use a pan gesture for that. +我可以使用一个拖动手势识别器来实现 + +1439 +01:01:45,839 --> 01:01:48,139 +Now, I could just go right here and +我在这个 faceView 里添加与之前 Pinch Gesture 类似的代码 + +1440 +01:01:48,141 --> 01:01:54,445 +do the same thing, I could say faceView.addGestureRecognizer- +这里我输入 faceView.addGestureRecognizer + +1441 +01:01:54,447 --> 01:01:59,316 +(UIPanGestureRecognizer{target . +UIPanGestureRecognizer(target: + +1442 +01:01:59,318 --> 01:02:00,884 +The target would be myself. +target 将会用 self + +1443 +01:02:00,886 --> 01:02:05,154 +Because if I'm modifying the Model with that pan gesture, +因为我通过这个拖动手势识别器改变了我的 Model + +1444 +01:02:05,156 --> 01:02:06,555 +my view can't do that. +我的 View 不能够完成这些 + +1445 +01:02:06,557 --> 01:02:08,590 +The controller has to handle it itself. +必须由 Controller 来处理 + +1446 +01:02:08,592 --> 01:02:10,125 +And we can have the action of +然后我们可以把这样的一个 Action + +1447 +01:02:10,127 --> 01:02:12,960 +this thing be something like changeHappiness. +称之为 changeHappiness + +1448 +01:02:12,962 --> 01:02:14,362 +Take that argument or something. +接受一个参数或者是其他什么的东西 + +1449 +01:02:14,364 --> 01:02:15,813 +So I could do this. +我可以按照之前我所说的这么做 + +1450 +01:02:15,814 --> 01:02:17,263 +But I'm not gonna do it this way, okay. +但我不想这么做,好吗? + +1451 +01:02:17,266 --> 01:02:18,231 +This would be perfectly fine. +我这么写,一点问题都没有 + +1452 +01:02:18,233 --> 01:02:19,332 +But I'm gonna show you how +但是我想演示给你们 + +1453 +01:02:19,334 --> 01:02:22,235 +you can set up gestures in the Storyboard. +如何在 Storyboard 中添加手势识别器 + +1454 +01:02:22,237 --> 01:02:25,071 +So you don't even need this line of code, okay. +所以你甚至都不需要这段代码 + +1455 +01:02:25,073 --> 01:02:26,972 +So here's how that works. +接下来看好 + +1456 +01:02:26,974 --> 01:02:27,773 +We're gonna go over here. +我们点击这里 + +1457 +01:02:27,775 --> 01:02:29,207 +Let's get our Storyboard. +点击我们的 Main.storyboard + +1458 +01:02:30,944 --> 01:02:35,779 +And I wanna add a gesture recognizer to this view. +我想在这个视图之上添加一个手势识别器 + +1459 +01:02:35,781 --> 01:02:37,748 +I do it by going over here, +我先点击这里 + +1460 +01:02:37,750 --> 01:02:41,117 +same place where I add things to my view here. +在我向我的视图添加控件的这个地方 + +1461 +01:02:41,119 --> 01:02:43,519 +If you go down towards the bottom, +如果你向下滚动 + +1462 +01:02:43,521 --> 01:02:46,722 +you'll see that there's tap gesture, pinch gesture, +你会看到里面有单击 (Tap)、缩放 (Pinch) + +1463 +01:02:46,724 --> 01:02:49,525 +rotation gesture, swipe gesture, pan gesture. +旋转 (Rotation)、滑动 (Swipe)、拖动 (Pan) 的手势识别器 + +1464 +01:02:49,527 --> 01:02:50,092 +Okay. + +1465 +01:02:50,094 --> 01:02:54,763 +So I'm gonna grab this pan gesture and drop it on this +我这里拖动这个拖动手势识别器并将其放在 + +1466 +01:02:54,765 --> 01:02:59,266 +view, which says I want this view to recognize a pan. +这个 view 之上,这也就表示我希望这个 view 识别一个拖动手势 + +1467 +01:02:59,268 --> 01:03:01,268 +Now you might say, whoa, where'd that go? +现在你可能会问,这个识别器去哪里了? + +1468 +01:03:01,270 --> 01:03:03,503 +I didn't see anything there what's going on? +我没发现任何东西有变化 + +1469 +01:03:03,505 --> 01:03:05,572 +Where is that thing, it's hard to tell. +哪去了?看不出来呀 + +1470 +01:03:05,574 --> 01:03:06,839 +Well, there's two places you +好的,有两个地方你可以 + +1471 +01:03:06,841 --> 01:03:08,474 +can find that thing you just dropped. +找到你刚才放置的手势识别器 + +1472 +01:03:08,476 --> 01:03:10,009 +One is in the document outline. +一个是在 Document Outline 中 + +1473 +01:03:10,011 --> 01:03:11,443 +You see it right here? +你在这里看到了吗? + +1474 +01:03:11,445 --> 01:03:13,345 +Pan Gesture Recognizer. +Pan Gesture Recognizer + +1475 +01:03:13,347 --> 01:03:15,380 +Another one is, right at the top. +另外一个地方是,就在这个视图的顶部 + +1476 +01:03:15,382 --> 01:03:17,348 +If you look at the view controller right here, you'll +如果你在 Storyboard 中查看你的 View Controller,你会 + +1477 +01:03:17,350 --> 01:03:19,550 +see there's a Pan Gesture Recognizer right there. +看到这里有一个叫 Pan Gesture Recognizer 的东西 + +1478 +01:03:20,853 --> 01:03:22,852 +Okay. Now all you need to do +好的,现在你所要做的就是 + +1479 +01:03:22,854 --> 01:03:26,422 +to make this pan gesture recognizer be handled by your +让这个拖动手势识别器被你的 Controller 所处理 + +1480 +01:03:26,424 --> 01:03:28,257 +controller is Ctrl + drag. +利用 Control 键加拖动 + +1481 +01:03:28,259 --> 01:03:32,994 +So I'm holding down Ctrl and dragging in here, okay. +我这里按住我的 Control 键,并拖动到这里 + +1482 +01:03:32,996 --> 01:03:34,930 +Let go. +释放拖动 + +1483 +01:03:34,931 --> 01:03:36,865 +It's an action kind of like target action for +这是一个 Action,类似于按钮中的 Target Action + +1484 +01:03:36,867 --> 01:03:38,800 +a button, but not quite exactly the same. +但不是完全相同 + +1485 +01:03:38,802 --> 01:03:42,803 +And I'm gonna call this change happiness cuz that's what +我把这个 Action 称之为 changeHappiness 因为 + +1486 +01:03:42,805 --> 01:03:44,137 +this pan gesture does. +这是这个拖动手势识别器所做的事情 + +1487 +01:03:44,139 --> 01:03:46,339 +Again, type I don't want to be any object. +再一次注意,这里的类型我不希望是 AnyObject + +1488 +01:03:46,341 --> 01:03:47,640 +This is gonna be the type of the argument. +这里设置的是参数的类型 + +1489 +01:03:47,642 --> 01:03:49,775 +I want it to be Pan Gesture Recognizer. +我想要让我参数的类型是 UIPanGestureRecognizer + +1490 +01:03:49,777 --> 01:03:51,477 +If you leave any object in there you'll have to be +如果你这里保留的是 AnyObject,那么 + +1491 +01:03:51,479 --> 01:03:55,247 +using as to turn it into a pan gesture recognizer so we can +你将要使用 as 将其类型转换为一个 UIPanGestureRecognizer 再使用它 + +1492 +01:03:55,249 --> 01:03:57,916 +use it, but obviously a lot easier to just click it here. +显然我这里设置好比较简单 + +1493 +01:03:57,918 --> 01:04:00,785 +The same as we had when we did button action. +这和我们处理按钮的时候是一样的 + +1494 +01:04:00,787 --> 01:04:03,988 +So it can connect, okay, here it is right here. +单击 Connect,好的,一个 Action 方法就建立好了 + +1495 +01:04:03,990 --> 01:04:06,656 +Let's go look at it. +让我们看看 + +1496 +01:04:07,626 --> 01:04:09,625 +Okay, change happiness. +changeHappiness + +1497 +01:04:09,627 --> 01:04:11,360 +And now we just need to implement this one. +现在我们只需要实现这个方法即可 + +1498 +01:04:11,362 --> 01:04:15,464 +So, what do we need to do to change our happiness? +我们需要在 changeHappiness 中做什么呢? + +1499 +01:04:15,466 --> 01:04:17,832 +Well the pan is moving up and down, +我们知道,这个拖动手势识别的是拖上拖下的操作 + +1500 +01:04:17,834 --> 01:04:20,668 +so I can get the coordinates of the pan in the face views +我可以获取到,在 faceView 中拖动时手指的坐标位置 + +1501 +01:04:20,670 --> 01:04:22,587 +coordinate system, but +在 faceView 的坐标系中 + +1502 +01:04:22,588 --> 01:04:24,505 +I really need to turn that into a happiness change in +但是,我真正需要的是将坐标的变换 + +1503 +01:04:24,507 --> 01:04:27,341 +some interpretations. +解释成一些其他的东西,其他可以导致我的小人脸部表情变化的东西 + +1504 +01:04:27,343 --> 01:04:29,676 +So again the controller is now interpreting what's +再一次,控制器现在承担了解释的操作 + +1505 +01:04:29,678 --> 01:04:32,212 +happening in the view for the Model, so it's going in +为 Model 解释 View 目前正在发生什么 + +1506 +01:04:32,214 --> 01:04:34,280 +the opposite direction of where we went before. +与之前的方向相反 + +1507 +01:04:34,282 --> 01:04:36,615 +And again, that's the controller's main job, +再次重申,这个才是控制器的主要任务 + +1508 +01:04:36,617 --> 01:04:38,650 +interpreting the Model for the view and +为 View 去解释 Model,同时 + +1509 +01:04:38,652 --> 01:04:41,286 +the view input to modify the Model. +接受 View 的输入来改变 Model + +1510 +01:04:41,288 --> 01:04:42,654 +So how's this going to work? +这里怎么让我们的方法工作? + +1511 +01:04:42,656 --> 01:04:48,159 +So again, I'm going to do sender.state = .Changed. +我输入 if sender.state == .Changed + +1512 +01:04:48,161 --> 01:04:50,561 +I'm not going to do this because if I do this, +噢,我不打算这么做,因为如果我这么做的话 + +1513 +01:04:50,563 --> 01:04:52,229 +everyone out there is going to start doing the same thing. +你们每一个人也将会做同样的事情 + +1514 +01:04:52,231 --> 01:04:54,898 +So let's do a switch of this. +让我们使用一个 switch + +1515 +01:04:54,900 --> 01:04:58,067 +I'm going to switch on the gestures, state. +输入 switch gesture.state + +1516 +01:04:58,069 --> 01:05:02,004 +I'm going to handle the case where it ended and +在里面,我会处理 .Ended 这样的情况 + +1517 +01:05:02,006 --> 01:05:06,675 +I'm going to handle the case where it changed, okay. +同样我会处理 .Changed 这样的情况 + +1518 +01:05:06,677 --> 01:05:08,443 +And I'm just going to do them the same, so +这两个情况之下,我将使用同样的处理方法 + +1519 +01:05:08,445 --> 01:05:11,179 +I'll do this fall through like we did in the slides. +所以我将 .Ended 情况设置为 fallthrough,就在我们之前所做的那样 + +1520 +01:05:11,181 --> 01:05:16,150 +So, when this pan is changing or when the finger lifts up, +所以,当用户正在拖动,或者当他们的手指离开屏幕的时候 + +1521 +01:05:16,152 --> 01:05:19,052 +I'm going to try and change my happiness, okay. +我将尝试改变我的小人的 happiness,明白了吗? + +1522 +01:05:20,722 --> 01:05:24,123 +So, first let's get the translation of the pan in +首先我们先在 faceView 的坐标系空间里 + +1523 +01:05:24,125 --> 01:05:26,392 +the face views coordinate system. +将这个 translation 获取 + +1524 +01:05:26,394 --> 01:05:28,960 +And to do that I'm going to send a message to the sender, +这里我要做的就是,给 sender 发送一个消息 + +1525 +01:05:28,962 --> 01:05:30,795 +you see sender right here? +你看到这里的 sender 了吗? + +1526 +01:05:30,797 --> 01:05:32,997 +That's the pan gesture recognizer that +这就是我们在这里 + +1527 +01:05:32,999 --> 01:05:34,465 +is being handled here. +处理的 UIPanGestureRecognizer + +1528 +01:05:34,467 --> 01:05:36,567 +We call this gesture in the other one and +我们称之为 sender + +1529 +01:05:36,569 --> 01:05:39,302 +a lot of people like to change this to gesture, +另外有些人习惯称之为 gesture + +1530 +01:05:39,304 --> 01:05:42,172 +which I think is perfectly fine to want to do. +这里我认为没有任何问题 + +1531 +01:05:42,174 --> 01:05:43,873 +So I'm going to ask the gesture, +接下来,我将要让 gesture + +1532 +01:05:43,875 --> 01:05:47,476 +tell me the translation in the face views coordinate system. +告诉我在 faceView 坐标系中的转换结果 + +1533 +01:05:47,478 --> 01:05:48,944 +So now I know how much it's moved in +那么现在我就知道拖动操作在 + +1534 +01:05:48,946 --> 01:05:50,812 +the face view coordinate system. +faceView 的坐标系系统中到底移动了多少位置 + +1535 +01:05:50,814 --> 01:05:53,448 +And so I'm going to let the happinessChange, this is +接下来,我定义 happinessChange + +1536 +01:05:53,450 --> 01:05:56,217 +the amount of change that's happening in my happiness. +这是我希望在 happiness 中变化的量 + +1537 +01:05:56,219 --> 01:06:00,888 +I could just have it be equal to translation.y, probably +我可以这里让它等于 translation.y + +1538 +01:06:00,890 --> 01:06:04,291 +would wanna be -translation.y because up means happy and +但是我更希望让它等于 -translation.y,因为向上拖动表示开心 + +1539 +01:06:04,293 --> 01:06:06,310 +down means not happy. +向下拖动表示不开心 + +1540 +01:06:06,311 --> 01:06:08,328 +But that's going to change the happiness a lot with very +但是这里的问题时,一个很小的拖动就会极大地改变 + +1541 +01:06:08,330 --> 01:06:09,228 +small movements. +happiness 的值 + +1542 +01:06:09,230 --> 01:06:11,230 +So I don't really want that. +我不希望是这样的 + +1543 +01:06:11,232 --> 01:06:15,934 +So I really want to have, also it needs to be an Int by +我真正希望的是,当然我希望它是一个 Int + +1544 +01:06:15,936 --> 01:06:21,272 +the way, so do that, because happiness is an Int. +因为 happiness 本身是一个 Int + +1545 +01:06:21,274 --> 01:06:22,907 +I really want this changed last so +我真正希望的是,它的变化量不那么大 + +1546 +01:06:22,909 --> 01:06:25,542 +I'm going to actually divide this by a constant. +所以我会将 -translation.y 除以一个常量 + +1547 +01:06:25,544 --> 01:06:27,344 +So I'm going to create a constant here, +这里我将创建一个常量 + +1548 +01:06:27,346 --> 01:06:31,514 +Constants.HappinessGestureS- cale I'll call it. +称之为 Constants.HappinessGestureScale + +1549 +01:06:31,516 --> 01:06:34,917 +And we'll go back up here and I'll do the private struct +我们回到上面,定义一个叫 Constants 的 private struct + +1550 +01:06:34,919 --> 01:06:39,888 +constants, and this is a static let, +里面输入 static let + +1551 +01:06:39,890 --> 01:06:45,594 +this thing which is a CG float. +这个常量应该是一个 CGFloat + +1552 +01:06:48,965 --> 01:06:50,231 +Let's do four. +让我们设置为4 + +1553 +01:06:50,233 --> 01:06:52,199 +So for every four points we move, +那么,我们每拖动或移动4个点 + +1554 +01:06:52,201 --> 01:06:54,001 +we'll move our happiness by one. +我们会让我们 happiness 改变1 + +1555 +01:06:54,003 --> 01:06:55,586 +Then we could play with this constant. +我们可以尝试不同的值 + +1556 +01:06:55,587 --> 01:06:57,170 +That's part of the reason I'm putting it out in a constant. +这就是为什么我把它单独拿出来的一个原因 + +1557 +01:06:57,172 --> 01:06:59,639 +We could play with this number until we got the feel that we +我们可以不断尝试其他的值 + +1558 +01:06:59,641 --> 01:07:03,576 +thought felt right for changing our happiness, okay. +直到我们觉得合适了 + +1559 +01:07:03,578 --> 01:07:04,610 +So we got our happinessChanged. +现在,我们有了 happinessChange + +1560 +01:07:04,612 --> 01:07:08,280 +So if the happiness change is not zero. +然后,如果 happinessChange 不是0的话 + +1561 +01:07:08,282 --> 01:07:11,416 +So if the happiness actually changed then I'm going to +那么我将改变我的 happiness + +1562 +01:07:11,418 --> 01:07:17,822 +change my happiness, happiness += happinessChange. +happiness += happinessChange + +1563 +01:07:17,824 --> 01:07:19,490 +I'm also going to do that reset thing. +接着我将做一些重置工作 + +1564 +01:07:19,492 --> 01:07:23,927 +So gesture.setTranslation(CGPoin- +在 faceView 中 gesture.setTranslation(CGPointZero, + +1565 +01:07:23,929 --> 01:07:26,629 +tZero in my faceView. +inView: faceView) + +1566 +01:07:28,766 --> 01:07:32,167 +I'm resetting it because I'm changing my happiness every +我重置它的原因是,每一次改变它的时候,都会改变 happiness + +1567 +01:07:32,169 --> 01:07:34,836 +time it changes, so I'm going to constantly be resetting it +所以我将持续重置它 + +1568 +01:07:34,838 --> 01:07:37,338 +so that it's incremental, okay. +以保证它是增量变化 + +1569 +01:07:38,474 --> 01:07:41,775 +And then of course we need to have the default case, +当然,我们需要 default 情况 + +1570 +01:07:41,777 --> 01:07:44,478 +which is going to be cancelled or failed or +比如说取消或者失败 + +1571 +01:07:44,480 --> 01:07:46,880 +began, and I'm just going to do nothing in that case. +或者是刚开始的情况,那么我将在 default 情况下不做任何操作 + +1572 +01:07:47,949 --> 01:07:50,949 +So any other state that gets thrown to me, I'll do nothing. +那么另外的状态触发了 changeHappiness 后,我将不做任何操作 + +1573 +01:07:52,619 --> 01:07:53,952 +So let's see if that works, let's run. +让我们看看是不是能够正常工作,让我们运行 + +1574 +01:07:53,954 --> 01:07:59,457 +Here we go, so now up is happier. +向上拖动,我们的小人看上去更开心了 + +1575 +01:07:59,459 --> 01:08:00,758 +Down is sad. +向下拖动,我们的小人看上去比较伤心 + +1576 +01:08:00,760 --> 01:08:02,292 +Up, good. +再向上,很好 + +1577 +01:08:02,294 --> 01:08:05,762 +And we can still do this. +当然我们还可以做缩放的操作 + +1578 +01:08:07,498 --> 01:08:12,901 +Okay, so these gestures, they don't look the same. +好的,所以这些手势,它们是不一样的 + +1579 +01:08:12,903 --> 01:08:14,302 +Okay, they don't start the same. +从根本上就不一样 + +1580 +01:08:14,304 --> 01:08:16,021 +This one's a two-finger one, +这一个是双指手势 + +1581 +01:08:16,022 --> 01:08:17,739 +okay, and this is a one-finger one. +这一个是单指手势 + +1582 +01:08:17,741 --> 01:08:19,640 +So the system can easily tell the difference between +系统可以轻易分辨出 + +1583 +01:08:19,642 --> 01:08:21,775 +which one is going on and iOS is very good at +到底是哪一种手势 + +1584 +01:08:21,777 --> 01:08:24,678 +telling the difference between different gestures starting. +iOS 尤其擅长这部分的东西 + +1585 +01:08:26,281 --> 01:08:28,614 +Okay? So everybody got that? +每个人都弄明白了吗? + +1586 +01:08:28,616 --> 01:08:29,982 +So we did a lot of different kind of +我们在这里处理了 + +1587 +01:08:29,984 --> 01:08:30,916 +gesture handling there. +不同种类的手势 + +1588 +01:08:30,918 --> 01:08:32,283 +We added one in a Storyboard. +我们学习了如何通过 Storyboard 添加一个手势 + +1589 +01:08:32,285 --> 01:08:33,251 +We added one in code. +也学习了如何通过代码来添加 + +1590 +01:08:33,253 --> 01:08:34,485 +We handled one in our controller. +我们在我们的 controller 中处理了一个 + +1591 +01:08:34,487 --> 01:08:36,320 +We handled one in our faceView. +另外一个在 faceView 里处理了 + +1592 +01:08:36,322 --> 01:08:39,256 +One is scaling and pinching, the other one was translation. +前者的的操作是处理尺寸缩放,后者是处理坐标系的变换 + +1593 +01:08:39,258 --> 01:08:41,175 +So hopefully between those two, +所以我希望你们通过这两种方法 + +1594 +01:08:41,176 --> 01:08:43,093 +you can look through that code and kinda get a good feel for +了解手势识别 + +1595 +01:08:43,095 --> 01:08:44,060 +how the gestures go. +大致的一个处理流程 + +1596 +01:08:47,165 --> 01:08:48,797 +Okay, good, so we do have some time left. +好的,我们还剩下一些时间 + +1597 +01:08:48,799 --> 01:08:51,600 +I'm going to get started on the next topic here. +我将开始讲下一个话题 + +1598 +01:08:52,669 --> 01:08:56,004 +Before I do that, because I'm going to get interrupted in +在这之前 + +1599 +01:08:56,006 --> 01:08:59,206 +the middle, let's talk quickly about what's coming up. +我要讲一下接下来的打算 + +1600 +01:08:59,208 --> 01:09:02,443 +So on Wednesday I'm going to continue the slides that I'm +周三我们会继续进行 Slide + +1601 +01:09:02,445 --> 01:09:04,111 +going to start in a minute here. +我马上要讲的这个 Slide + +1602 +01:09:04,113 --> 01:09:05,612 +About multiple MVCs and +是关于多个 MVC 的 + +1603 +01:09:05,614 --> 01:09:08,915 +then I'm gonna do a big demo creating multiple MVCs in +我将要演示一个大的 Demo, + +1604 +01:09:08,917 --> 01:09:11,717 +our happiness controller, okay. +在 happiness controller 中创建多个 MVC + +1605 +01:09:11,719 --> 01:09:13,719 +And again, time permitting, at the end of Wednesday I'll do +如果时间允许,在周三课程最后我会讲 + +1606 +01:09:13,721 --> 01:09:16,788 +another topic view controller lifecycle. +另一个主题,即 view controller 生命周期 + +1607 +01:09:16,790 --> 01:09:20,558 +Friday, hopefully, it will have this Instruments thing. +在周五,希望可以能够给大家讲一讲 Instruments + +1608 +01:09:20,560 --> 01:09:22,860 +And then next Monday I put Auto Layout question mark. +在下周一,我在 Auto Layout 后放了一个问号 + +1609 +01:09:22,862 --> 01:09:24,128 +Because I was telling you I was going to +因为我曾经告诉你们我会讲 Auto Layout 的内容 + +1610 +01:09:24,130 --> 01:09:25,796 +do Auto Layout sooner but I keep putting it off. +但是总是推迟 + +1611 +01:09:25,798 --> 01:09:27,597 +And I might put it off again, we'll see. +或许我会继续推迟,到时候就知道了 + +1612 +01:09:27,599 --> 01:09:29,182 +But I won't be asking you in +但是我不会要求你们 + +1613 +01:09:29,183 --> 01:09:30,766 +your homework to do much sophisticated Auto Layout. +在课后花太多时间熟悉 Auto Layout 的内容 + +1614 +01:09:30,769 --> 01:09:32,568 +So even it assignment three, there's very little. +所以尽管在它(Auto Layout)是第三次作业,但是也只是很少一部分内容 + +1615 +01:09:32,570 --> 01:09:37,573 +Okay, so next topic, multiple MVCs. +好的,下一个主题,多重 MVC + +1616 +01:09:37,575 --> 01:09:39,574 +So you remember this picture, I hope. +我希望你还记得这张图 + +1617 +01:09:42,713 --> 01:09:45,847 +Which was at the of the MVC talk where I talked about how +在讲到 MVC 的最后,我讲了如果我们想 + +1618 +01:09:45,849 --> 01:09:47,214 +if we wanna build a big app, +构建一个大的应用, + +1619 +01:09:47,216 --> 01:09:51,084 +we're gonna do it by putting multiple MVCs together, okay. +我们将要把多个 MVC 放在一起来实现它 + +1620 +01:09:51,086 --> 01:09:52,719 +So we're gonna zoom in here and +先关注这里 + +1621 +01:09:52,721 --> 01:09:55,254 +take a look at exactly how that's done. +看一看这到底是怎么实现的 + +1622 +01:09:55,256 --> 01:09:57,340 +Okay, how we're +我们怎么 + +1623 +01:09:57,341 --> 01:09:59,425 +gonna make multiple combine multiple MVC's. +将多个 MVC 联系到一起 + +1624 +01:09:59,427 --> 01:10:00,977 +Okay. + +1625 +01:10:00,978 --> 01:10:02,528 +So you see that MVC right there the purple one +看最上边紫色的这个 MVC + +1626 +01:10:02,530 --> 01:10:05,030 +at the top, that's an MVC and you can +这是一个 MVC ,而且它的 view + +1627 +01:10:05,032 --> 01:10:08,499 +see that this view is actually made up of other MVC's. +实际上是由其它 MVC 组成的 + +1628 +01:10:10,003 --> 01:10:13,237 +So iOS provides some controllers for +iOS 为 MVC 提供了一些 controller + +1629 +01:10:13,239 --> 01:10:17,474 +MVCs that have other MVCs as their view. +可以把其它 MVC 当做它们的 view + +1630 +01:10:17,476 --> 01:10:19,375 +And the three we're gonna talk about today, +今天我们要讲到三个 controller, + +1631 +01:10:19,377 --> 01:10:20,776 +by the way you can build your own. +BTW, 你可以创建自己的 controller + +1632 +01:10:20,778 --> 01:10:22,645 +I'm not gonna talk about that today. +今天我不会讲怎么自定义 controller + +1633 +01:10:22,646 --> 01:10:24,513 +You can build your own controllers that have MVCs as +你可以自定义 controller ,并将其它 MVC 作为 view + +1634 +01:10:24,515 --> 01:10:26,615 +the view, but I'm gonna talk about the three that are +但是我今天要讲的三种 controller 是 iOS 内置的 + +1635 +01:10:26,617 --> 01:10:29,884 +provided in iOS which you're gonna be using in this class. +也是你们在这门课将要用到的 + +1636 +01:10:29,886 --> 01:10:32,153 +Which is TabBarController SplitViewControllers and +这三个 controller 分别是 TabBarController SplitViewController + +1637 +01:10:32,155 --> 01:10:34,689 +NavigationControllers, 'kay. +和 NavigationController + +1638 +01:10:34,691 --> 01:10:35,856 +So these are just controllers, +它们都是 controller + +1639 +01:10:35,858 --> 01:10:39,893 +they're subclasses of UIViewController. +是 UIViewController 的子类 + +1640 +01:10:39,895 --> 01:10:42,261 +And they draw a little bit in their view but +而且它们会在它们的 view 中绘制很少的东西 + +1641 +01:10:42,263 --> 01:10:45,564 +then most of their view is what other MVC's draw, so +但是多数情况下,它们的 view 是其它 MVC 绘制的内容, + +1642 +01:10:45,566 --> 01:10:50,235 +the MVCs are part of their views. +所以其它 MVC 只是这些 controller view 的一部分 + +1643 +01:10:50,237 --> 01:10:51,670 +So let's look at TabBarController, +看看 TabBarController + +1644 +01:10:51,672 --> 01:10:53,471 +it's probably the simplest one of all these. +它可能是三个中最简单的 + +1645 +01:10:53,473 --> 01:10:55,006 +You've seen TabBarControllers, +你们已经见过 TabBarController, + +1646 +01:10:55,008 --> 01:10:58,442 +you see it's got the four tabs along the bottom on this one. +这个 TabBarController 底部罗列了四个 tab + +1647 +01:10:58,444 --> 01:11:00,343 +This is the health app, I think. +我觉得这个一个健康类的应用 + +1648 +01:11:02,814 --> 01:11:05,748 +And all that happens here is when you click one of those +当你点击底部四个 tab button 中的一个 + +1649 +01:11:05,750 --> 01:11:10,318 +tab buttons at the bottom, the top gets replaced with an MVC. +上面就会被一个新的 MVC 替换 + +1650 +01:11:10,320 --> 01:11:12,987 +An entire MVC is controlling that top. +整个 MVC 控制上面的内容 + +1651 +01:11:12,989 --> 01:11:16,457 +In this case, it's some sort of Dashboard MVC or health +在本例中,这上面要展现的是某种 "Dashboard" MVC + +1652 +01:11:16,459 --> 01:11:20,494 +Dashboard is being presented at the top, right here. +或是一个 health "Dashboard" + +1653 +01:11:20,496 --> 01:11:22,195 +And the icon and +"Dashboard" 下面的 + +1654 +01:11:22,197 --> 01:11:25,699 +the title that goes along with the Dashboard down there, +图标以及标题 + +1655 +01:11:25,701 --> 01:11:29,468 +is actually gotten from the Dashboard MVC. +实际上来自这个 "Dashboard" MVC + +1656 +01:11:29,470 --> 01:11:31,804 +In other words, +换句话说,图标和标题 + +1657 +01:11:31,805 --> 01:11:34,139 +not a property you set on the UITabBarController MVC. +不是你在 UITabBarController MVC 中设置的 property(属性) + +1658 +01:11:34,141 --> 01:11:37,109 +You actually just have a property on +实际上在你的 "Dashboard" MVC 中, + +1659 +01:11:37,111 --> 01:11:39,844 +your Dashboard MVC, it's called tabBarItem. +你仅有一个叫做 tabBarItem 的属性 + +1660 +01:11:39,846 --> 01:11:42,847 +And inside tabBarItem, if you go look it up in the doc, +在 tabBarItem 中, 如果你查找文档, + +1661 +01:11:42,849 --> 01:11:47,751 +it's got things like title, icon, things that the tab bar +tabBarItem 中有 title,icon,等,这些东西 + +1662 +01:11:47,753 --> 01:11:50,754 +controller needs to put a nice tab on the bottom for +都是 TabBarController 需要的,用来为你的 "Dashboard" 底部 + +1663 +01:11:50,756 --> 01:11:52,589 +your Dashboard MVC. +呈现一个适当的 tab + +1664 +01:11:52,590 --> 01:11:54,423 +So, as you can see, it's very object oriented, okay. +可以看到,这非常符合面向对象的思想 + +1665 +01:11:54,426 --> 01:11:57,427 +Everything is contained in just this MVC. +所有的东西都在这个 MVC 中 + +1666 +01:11:57,429 --> 01:11:59,395 +And so, if you press on a different tab, +如果你按下另一个 tab, + +1667 +01:12:00,331 --> 01:12:02,064 +maybe the second tab, then this is a totally +比如第二个 tab,然后 + +1668 +01:12:02,066 --> 01:12:04,899 +different MVC that takes over the top of this screen. +一个完全不同的 MVC 占据了屏幕的顶部 + +1669 +01:12:04,901 --> 01:12:08,269 +This would be Health Data MVC, and you can see that it's got +这是 Health Data MVC, 可以看到 + +1670 +01:12:08,271 --> 01:12:11,305 +a different icon and text down there, right? +它有一个不同的 icon 和 title 在它下面,对吧? + +1671 +01:12:11,307 --> 01:12:13,374 +By the way, if there's too +顺便说下,如果底部罗列了 + +1672 +01:12:13,375 --> 01:12:15,442 +many tabs along the bottom there, I think you get five, +太多 tab,比如有5个 tab, + +1673 +01:12:15,444 --> 01:12:19,479 +if you go to six tabs then iOS will automatically let +如果你要六个 tab,那么 iOS 将会自动让 + +1674 +01:12:19,481 --> 01:12:22,248 +the user manage which ones he wants down there. +用户来管理这些 tab + +1675 +01:12:22,250 --> 01:12:23,950 +It's pretty cool, okay. +相当 cool,对吧 + +1676 +01:12:23,952 --> 01:12:25,168 +So you don't even have to and +你可以在下面放 + +1677 +01:12:25,169 --> 01:12:26,385 +you can put as many tabs you want. +任意多的 tab + +1678 +01:12:26,387 --> 01:12:27,720 +I don't really recommend more than five +但是,我建议不超过五个 + +1679 +01:12:27,722 --> 01:12:28,720 +tabs here, by the way. +顺便一说 + +1680 +01:12:30,257 --> 01:12:31,940 +For users it's like, what, +对于用户来说情况可能是:“什么? + +1681 +01:12:31,941 --> 01:12:33,624 +I have to manage my tabs down there, I don't wanna do that. +我还得自己管理 tab,我可不想这么麻烦 ” + +1682 +01:12:33,626 --> 01:12:35,259 +It's just that you're asking yours to do more stuff. +这是自己给自己找麻烦 + +1683 +01:12:35,261 --> 01:12:36,827 +So hopefully you can fit it in five. +所以希望5个 tab 可以满足你的要求 + +1684 +01:12:38,097 --> 01:12:40,330 +And so we have other MVCs as well. +我们也有其它 MVC + +1685 +01:12:40,332 --> 01:12:43,266 +So there's the sources of health data, +这个是 health data(健康数据)的来源, + +1686 +01:12:43,268 --> 01:12:45,701 +I guess, in your Medical ID tab. +Medical ID tab. + +1687 +01:12:45,703 --> 01:12:48,871 +And so this is a very simple thing you can understand. +这些东西都很容易理解 + +1688 +01:12:48,873 --> 01:12:50,706 +You've got this UITabBarController, +你得到了这个 UITabBarController + +1689 +01:12:50,708 --> 01:12:53,108 +it's a controller of an MVC. +它是一个 MVC 的 controller. + +1690 +01:12:53,109 --> 01:12:55,509 +The view is the little tabs along the bottom that it's +它的(UITabBarController)的 view 是底部的它绘制的这些 tab + +1691 +01:12:55,512 --> 01:12:57,645 +drawing and the MVC's on the top. +以及顶部的 MVC + +1692 +01:12:58,915 --> 01:13:00,915 +Everyone understand what I +大家都明白我说的吗? + +1693 +01:13:00,916 --> 01:13:02,916 +mean now about an MVC whose view contains other MVC's? +关于一个 MVC 的 view 包含其它 MVC + +1694 +01:13:02,918 --> 01:13:06,686 +So let's look at another one that does that. +好的,一起看一下另一个 的 controller + +1695 +01:13:06,688 --> 01:13:08,121 +SplitViewController. + +1696 +01:13:08,123 --> 01:13:11,157 +So, SplitViewController takes two MVCs, and +SplitViewController 包括两个 MVC, + +1697 +01:13:11,159 --> 01:13:13,892 +it puts them side-by-side, okay. +并将它们并排放在一起 + +1698 +01:13:13,894 --> 01:13:15,460 +It puts the one on the left, +它将一个放在左边 + +1699 +01:13:15,462 --> 01:13:19,630 +kind of a well known width there. +似乎是一个熟知的宽度 + +1700 +01:13:19,632 --> 01:13:21,198 +But, you don't care what that width is because, +但是,你不必关心宽度是多少, + +1701 +01:13:21,200 --> 01:13:23,033 +hopefully, you've got Auto Layout, and so +你可以使用 Auto Layout, + +1702 +01:13:23,035 --> 01:13:24,334 +it could be any width you want, or +想让它多宽, + +1703 +01:13:24,336 --> 01:13:26,102 +any height you want, like this. +想让它都高都可以,就像这样 + +1704 +01:13:26,104 --> 01:13:27,503 +And then it puts another one on the right. +然后,它(UISplitViewController)将另一个 MVC 放在右边 + +1705 +01:13:27,505 --> 01:13:31,774 +Now, we call the MVC on the left, the Master in +接下来,我们将左边的 MVC 叫做 split view 的 Master + +1706 +01:13:31,776 --> 01:13:34,576 +the split view and we call the MVC on the right the Detail. +将右边的 MVC 叫做 Detail + +1707 +01:13:38,615 --> 01:13:41,349 +Now here I've got a calculator and a calculator graph. +目前我有一个计算器和一个计算器图表 + +1708 +01:13:41,351 --> 01:13:44,218 +You assignment three is going to be to build this basically. +你们第三次作业基本上将要实现这个计算器 + +1709 +01:13:44,220 --> 01:13:46,353 +It doesn't have to look exactly like this, okay. +你们的计算器不必和我的完全一样 + +1710 +01:13:46,355 --> 01:13:49,022 +I've made a simple looking one here. +我只做了一个简单的外观 + +1711 +01:13:49,024 --> 01:13:51,791 +But it could look very much like this. +但是你们的作业可能和我展示的样子差不了多少 + +1712 +01:13:51,793 --> 01:13:53,292 +But you do have to use a SplitViewController. +但是你必须使用一个 SplitViewController + +1713 +01:13:53,294 --> 01:13:54,260 +So this is what it looks like. +现在它就是这个样子 + +1714 +01:13:54,262 --> 01:13:58,897 +Now, this is only happening on an iPad. +当然,只有在 iPad 上才会这样 + +1715 +01:13:58,899 --> 01:14:00,732 +Now, when we talk about Auto Layout, +当我们说到 Auto Layout, + +1716 +01:14:00,734 --> 01:14:04,335 +we're going to start talking about Size Classes. +我们就要从 Size Classes 开始说起 + +1717 +01:14:04,337 --> 01:14:07,304 +So, different devices have been grouped into +各种不同尺寸的 iOS 设备 + +1718 +01:14:07,306 --> 01:14:08,839 +size classes. +都被集成到了 size classes 中 + +1719 +01:14:08,841 --> 01:14:13,410 +And the sizes basically are regular, so regular width and +size 通常为 regular,regular width 和 regular height + +1720 +01:14:13,412 --> 01:14:16,512 +regular height or compact width and height. +或者 compact width, compact height + +1721 +01:14:16,514 --> 01:14:18,614 +So an iPhone, all the iPhones except for +对于 iPhone 来说,除了在 + +1722 +01:14:18,616 --> 01:14:21,083 +the iPhone 6 plus in landscape, +landscape(横向模式)的 iPhone 6 plus, + +1723 +01:14:21,085 --> 01:14:25,220 +are compact both vertically and horizontally, okay. +在水平方向和竖直方向都是 compact + +1724 +01:14:25,222 --> 01:14:28,656 +The iPad is regular width, okay. +iPad 是 regular width + +1725 +01:14:28,658 --> 01:14:30,458 +Now, that's of the whole device. +这就是整个设备 + +1726 +01:14:30,460 --> 01:14:35,829 +But the MVC's inside also will have a certain size class. +但是设备里的 MVC 同样有特定的 size class + +1727 +01:14:35,831 --> 01:14:39,265 +So this side by side business can only happen in +所以这样并排排列的 MVC 只能出现在 + +1728 +01:14:39,267 --> 01:14:42,168 +a device whose size class is regular width. +拥有 regular width 的 size class + +1729 +01:14:42,170 --> 01:14:46,238 +So that's the iPad in both landscape and portrait could +所有只有 iPad 在 landscape(横向模式)和 portrait(纵向模式)是 regular width, + +1730 +01:14:46,240 --> 01:14:49,941 +be that, and the iPhone 6 plus in landscape, okay. +iPhone 6 plus 在 landscape(横向模式)下也是 regular width + +1731 +01:14:49,943 --> 01:14:52,977 +So SplitView is only gonna do the side by +所以 SplitView 只能在 + +1732 +01:14:52,979 --> 01:14:55,013 +side business there. +这几种情况下并排放置 + +1733 +01:14:55,015 --> 01:15:01,352 +And if you rotate the iPad, then the Master disappears. +如果你旋转 iPad,Master 消失了 + +1734 +01:15:02,521 --> 01:15:04,688 +But it can be swiped out. +但是可以将 Master 滑动唤出 + +1735 +01:15:04,690 --> 01:15:10,126 +If you just swipe from the left, when you rotate the only +如果你从屏幕左边滑动,当 iPad 旋转时只有 Detail 视图, + +1736 +01:15:10,128 --> 01:15:12,361 +ones there is the Detail, you don't see the Master. +看不到 Master + +1737 +01:15:12,363 --> 01:15:14,129 +But if you swipe out from the left, +但是如果你从左向右滑动, + +1738 +01:15:14,131 --> 01:15:15,830 +then you get to see the Master as well. +你也可以看到 Master + +1739 +01:15:15,832 --> 01:15:16,798 +Again, side by side. +Master 和 Detail 又并排放在一起了 + +1740 +01:15:18,334 --> 01:15:19,633 +Okay. + +1741 +01:15:19,635 --> 01:15:22,302 +And if you touch the Detail, it'll make the Master go +如果你点击 Detail,会使 Master 返回消失 + +1742 +01:15:22,304 --> 01:15:23,703 +back away and then you can swipe it. +然后可以再次滑动唤出 + +1743 +01:15:23,705 --> 01:15:26,005 +So you can bring the Master out or not, okay. +所以你可以决定是否唤出 Maser + +1744 +01:15:26,007 --> 01:15:28,607 +That make sense? +懂了吗? + +1745 +01:15:28,609 --> 01:15:30,609 +So that's the SplitViewController, +以上是 SplitViewController + +1746 +01:15:30,611 --> 01:15:32,444 +kind of how it's arranged. +以及它怎么排列 + +1747 +01:15:35,115 --> 01:15:37,915 +But most importantly, I want you to understand that again, +最重要的是,我想让你们再次理解 + +1748 +01:15:37,917 --> 01:15:40,217 +it's two MVCs that are the view. +这两个 MVC 是 view + +1749 +01:15:40,219 --> 01:15:43,653 +Now the SplitView draws nothing in its view, +SplitView 并没有在它的 view 中绘制任何内容, + +1750 +01:15:44,656 --> 01:15:47,189 +except for maybe that vertical separator line. +可能除了竖直的分界线 + +1751 +01:15:47,191 --> 01:15:48,590 +Okay, there's a vertical separator line. +这条竖直的分界线 + +1752 +01:15:48,592 --> 01:15:52,327 +That's probably drawn by the SplitViewController, but +可能是 SplitViewController 绘制的, + +1753 +01:15:52,329 --> 01:15:55,430 +otherwise it's only drawing whatever the MVCs draw. +但是,他只展示了 MVC 绘制的内容 + +1754 +01:15:55,432 --> 01:15:57,131 +So it doesn't even have any drawing on +所以,它甚至不像 TabBarViewController 那样 + +1755 +01:15:57,133 --> 01:15:58,632 +the bottom like the TabBar has. +绘制底部的 tabBar + +1756 +01:15:59,735 --> 01:16:00,884 +Okay? + +1757 +01:16:00,885 --> 01:16:02,034 +So the next thing I'm going to talk about, and +下面我要讲到的, + +1758 +01:16:02,037 --> 01:16:03,903 +we're going to start this next time, +以及我们要再下一节课继续讲的是 + +1759 +01:16:03,905 --> 01:16:07,407 +is NavigationController, which is a very powerful one. +NavigationController, 这是一个功能强大的 controller + +1760 +01:16:07,409 --> 01:16:10,242 +It draws at the top a little title and +它在顶部绘制小的 title 和其他东西, + +1761 +01:16:10,244 --> 01:16:12,277 +some things, it can draw even around the bottom. +它甚至可以在底部周围绘制内容 + +1762 +01:16:12,279 --> 01:16:15,380 +And then it can display any number of MVCs. +还有,它可以展示任意多的 MVC + +1763 +01:16:15,382 --> 01:16:19,917 +Okay, so we'll pick up the NavigationController next time +好的,下节课我们将要学习 NavigationController + +1764 +01:16:19,919 --> 01:16:22,219 +and in the meantime if you have any questions, +如果你有任何问题要问, + +1765 +01:16:22,221 --> 01:16:23,053 +I'll be here as usual. +我会像往常一样在这里解答 + +1766 +01:16:24,623 --> 01:16:25,654 +>> For more, please visit us at www.stanford.edu +>> 登录 www.stanford.edu 获取更多内容 diff --git a/subtitles/7. Multiple MVCs.srt b/subtitles/7. Multiple MVCs.srt new file mode 100644 index 0000000..133129e --- /dev/null +++ b/subtitles/7. Multiple MVCs.srt @@ -0,0 +1,12391 @@ +1 +00:00:01,000 --> 00:00:04,630 +[MUSIC] +[音乐] + +2 +00:00:04,630 --> 00:00:07,930 +Stanford University. +斯坦福大学 + +3 +00:00:07,940 --> 00:00:11,970 +Okay, well, welcome to lecture 7 of CS193P. +欢迎来到 CS193P 课程的第七课 + +4 +00:00:11,970 --> 00:00:14,240 +This is the winter of 2015. +这是 2015 年冬季课程 + +5 +00:00:14,240 --> 00:00:16,070 +And today, +今天 + +6 +00:00:16,080 --> 00:00:19,180 +we are going to talk about multiple MVCs, all right? +我们想讲一下多重 MVC(Multiple MVCs)的内容 + +7 +00:00:19,180 --> 00:00:21,110 +That includes Split View Controller, +这将涉及到 Split View Controller 和 + +8 +00:00:21,110 --> 00:00:22,150 +Navigation Controller. +Navigation Controller + +9 +00:00:22,150 --> 00:00:24,150 +We talked about Tab Bar Controller a little bit +我们在上一讲中已经讲过一点 Tab Bar Controller 的内容 + +10 +00:00:24,150 --> 00:00:25,380 +last time. + +11 +00:00:25,380 --> 00:00:27,920 +We're also gonna talk about segues which is how we make +我们同样会在本节课中讲到 Segues + +12 +00:00:27,920 --> 00:00:32,820 +all those multiple MVCs kind of transition to each other. +Segues 是多重 MVC 之间转换的一个东西 + +13 +00:00:32,820 --> 00:00:35,590 +And I have a big demo that shows it all off. +这里我会有一个比较大的 Demo 来演示这部分 + +14 +00:00:35,590 --> 00:00:37,990 +And that after that demo I'll come back. +在 Demo 之后,我们回到主题 + +15 +00:00:37,990 --> 00:00:42,130 +We'll talk about popovers which are similar thing for +然后,我们会谈到 Popovers,Popovers 和多重 MVC 有一些相似的地方 + +16 +00:00:42,130 --> 00:00:44,830 +having multiple MVCs but are not quite the same. +但不是完全一样的 + +17 +00:00:44,830 --> 00:00:46,170 +So that's why I've kind of +所以这是为什么我把 Popovers 这块 + +18 +00:00:46,170 --> 00:00:47,500 +segregated them off to the end. +放到最后的原因 + +19 +00:00:47,500 --> 00:00:49,440 +And we'll have a demo about that. +同样我们也会有一个关于 Popovers 的 Demo + +20 +00:00:50,640 --> 00:00:52,600 +All right. So MVCs working together. +好了,介绍完毕。多重 MVC 一起协同工作 + +21 +00:00:52,610 --> 00:00:55,910 +These are the slide we saw at the end of last time. +这些是我们上次课最后看到的 Slide + +22 +00:00:55,910 --> 00:00:58,980 +We're trying to build apps by taking our MVCs and combining +我们尝试通过让我们的 MVC 和 + +23 +00:00:58,980 --> 00:01:02,580 +them with tab bar, Split View, and Navigation Controller. +Tab Bar, Split View, Navigation Controller 混合在一起来构建我们的应用 + +24 +00:01:02,580 --> 00:01:04,420 +We talked about Tab Bar Controller which is +我们讲过 Tab Bar Controller 就是 + +25 +00:01:04,420 --> 00:01:06,980 +just simply four or five or however many +用一个小的 Tab Bar 来将四、五个或者任何数目的 + +26 +00:01:06,990 --> 00:01:10,790 +MVCs all connected by just having this little tab bar so +MVC 连接在一起,然后让你选择你想要展示那一个 + +27 +00:01:10,790 --> 00:01:13,460 +the bottom just picks which MVC you want to see. +MVC 的一个东西 + +28 +00:01:13,460 --> 00:01:16,260 +Each MVC by the way in the tab bar's completely independent. +在 Tab Bar 中的任意一个 MVC 都是独立的 + +29 +00:01:16,260 --> 00:01:17,230 +It runs on its own. +独立运行 + +30 +00:01:17,230 --> 00:01:19,090 +It doesn't depend on the other ones. +不依赖 Tab Bar 中的其他 MVC 而运行 + +31 +00:01:19,100 --> 00:01:21,030 +It actually might be kind of bad object on your +所以,假如你应用中,Tab Bar 中的 MVC + +32 +00:01:21,030 --> 00:01:23,430 +programming really for them to depend on the other one. +是依赖于其他的 MVC 的话,这是一种不好的编程方式 + +33 +00:01:23,430 --> 00:01:27,340 +So, tab bars for peers that aren't really talking to each +所以 Tab Bar 是为了那些层次上互相有关系的 MVC 而设计的 + +34 +00:01:27,340 --> 00:01:30,870 +other they're just working together, they're related. +并不是为了那些在逻辑上协同工作的 MVC 而设计的 + +35 +00:01:30,870 --> 00:01:32,440 +Maybe they share a model and +可能它们共用同样一个 Model + +36 +00:01:32,440 --> 00:01:35,410 +they're each having a different part of the model +也有可能它们用同一个 Model 中的不同部分 + +37 +00:01:35,410 --> 00:01:36,580 +or whatever. +或者其他情况 + +38 +00:01:36,580 --> 00:01:37,740 +And then we talked about Split View Controller, +接下来我们讲到 Split View Controller + +39 +00:01:37,750 --> 00:01:41,350 +which only has two MVCs in it, a master, and a detail. +它其中只有两个 MVC,一个 Master,一个 Detail + +40 +00:01:41,350 --> 00:01:42,950 +We call them master and detail, by the way, +我们称之这两者为 Master 和 Detail 是因为 + +41 +00:01:42,950 --> 00:01:46,120 +because the master is usually the one determining what's in +Master 决定了 Detail 的内容是什么 + +42 +00:01:46,120 --> 00:01:47,570 +the detail. + +43 +00:01:47,570 --> 00:01:49,020 +So the master is letting you view something, +举例来说,Master 让你浏览一些东西 + +44 +00:01:49,020 --> 00:01:52,060 +and then you're going to use the detail to see more detail +然后 Detail 让你浏览你在 Master 中做的东西更加详细的信息 + +45 +00:01:52,060 --> 00:01:54,090 +about what you're doing in the master, okay? +明白了吗? + +46 +00:01:54,090 --> 00:01:57,330 +So that's why we call it master and detail. +这就是我们为什么叫它们 Master 和 Detail + +47 +00:01:57,330 --> 00:02:00,400 +So we're going to pick up now with Navigation Controller. +接下来,我们讲一下 Navigation Controller + +48 +00:02:00,400 --> 00:02:03,900 +So Navigation Controller is just yet another MVC whose +Navigation Controller 就是一个 MVC + +49 +00:02:03,900 --> 00:02:07,800 +View is multiple of other MVCs and Navigation Controller can +它的 View 由其他的 MVC 组成 + +50 +00:02:07,810 --> 00:02:09,970 +handle any number of other MVCs. +Navigation Controller 可以包含任意数量的 MVC + +51 +00:02:09,970 --> 00:02:11,270 +Okay. + +52 +00:02:11,280 --> 00:02:14,810 +And it puts them on screen, it shares the screen instead of +它把其他的 MVC 放在屏幕上,与其他类型的 Controller 不同的是,它共享这个屏幕 + +53 +00:02:14,810 --> 00:02:17,550 +just putting them side by side or putting them with the tabs, +而不是将其他的 MVC 一一放置,或者放在 Tab Bar 上 + +54 +00:02:17,550 --> 00:02:20,010 +it puts them like a stack of cards. +它像一堆卡片一样放置这些 MVC,这里我们把 MVC 类比成卡片 + +55 +00:02:20,020 --> 00:02:21,150 +Okay? +明白了吗? + +56 +00:02:21,150 --> 00:02:22,280 +So Navigation Controller's basically stacking them +所以,Navigation Controller 基本上就是像一堆卡片一样放置 MVC + +57 +00:02:22,280 --> 00:02:24,080 +like cards and you can only see the one on top. +所以,你只能看到最上面的那个 MVC + +58 +00:02:25,290 --> 00:02:26,920 +That's how Navigation Controller +这就是 Navigation Controller 如何 + +59 +00:02:26,920 --> 00:02:29,460 +shares the small screen space between multiple MVCs. +在多重 MVC 之间共享一个小的屏幕空间的 + +60 +00:02:29,460 --> 00:02:31,560 +So it's gonna stack these MVCs up. +它会将这些 MVC 堆起来 + +61 +00:02:31,560 --> 00:02:33,890 +So here's a Navigation Controller. +这里有一个 Navigation Controller + +62 +00:02:33,890 --> 00:02:35,530 +And it's got an MVC in it. +它的里面有一个 MVC + +63 +00:02:35,530 --> 00:02:39,200 +This is the "All Settings" MVC from your device. +这里它显示的 MVC 是你设备的 "All Settings" MVC + +64 +00:02:39,200 --> 00:02:40,870 +If you go look in your iPhone or +当你打开你的 iPhone + +65 +00:02:40,870 --> 00:02:42,530 +whatever, you'll see the settings app looks like this. +或者其他 iOS 设备时,你会看到设置 App 的样子就是这样 + +66 +00:02:42,540 --> 00:02:45,200 +So this is just an MVC that's kind of the top level. +这就是在最顶层的 MVC + +67 +00:02:45,200 --> 00:02:49,040 +Has all the settings accessible from here. +它包含了所有设置的一个入口 + +68 +00:02:49,040 --> 00:02:53,780 +Now the Navigation Controller is drawing only a little part +需要注意的是,由 Navigation Controller 只会绘制它的 View 的一小部分 + +69 +00:02:53,780 --> 00:02:57,410 +of its View here, which is that title bar. +就是 Title Bar(顶部的一块区域) + +70 +00:02:57,420 --> 00:02:59,950 +And the Navigation Controller will put the title +Navigation Controller 会在 Title Bar 这里显示标题(Title) + +71 +00:02:59,950 --> 00:03:02,550 +there, and also you can have a couple of buttons up at +当然你还可以在这里放置一些按钮 + +72 +00:03:02,550 --> 00:03:05,490 +the top and the Navigation Controller draws that part. +Navigation Controller 也会帮你绘制 + +73 +00:03:05,490 --> 00:03:06,820 +The rest of it is totally drawn, +而在它之外的部分 + +74 +00:03:06,820 --> 00:03:10,390 +and even underneath that title bar, totally drawn by +甚至是在 Title Bar 底下(而不是下方)的那部分 + +75 +00:03:10,390 --> 00:03:13,660 +whatever MVC is on top of this stack of cards. +由 MVC 堆栈顶部的那个 MVC 来负责绘图 + +76 +00:03:13,660 --> 00:03:14,930 +Okay, and right now the only thing on +在这个图片中 + +77 +00:03:14,930 --> 00:03:18,700 +our stack of cards is this "All Settings" MVC. +我们 MVC 堆栈顶部的那个 MVC 是 "All Settings" MVC + +78 +00:03:18,700 --> 00:03:19,870 +Now even though the contents of +尽管顶部的部分由 Navigation Controller 来绘制 + +79 +00:03:19,870 --> 00:03:22,700 +the top are drawn by the Navigation Controller, what +但是,顶部部分的内容 + +80 +00:03:22,700 --> 00:03:27,340 +the contents are is determined by the MVC that's showing. +仍是由当前 MVC 堆栈顶部的 MVC 所决定的 + +81 +00:03:27,340 --> 00:03:28,710 +Okay? And that's done with this + +82 +00:03:28,710 --> 00:03:31,580 +UIViewController property called navigationItem. +UIViewController 里有一个叫 navigationItem 的属性 + +83 +00:03:31,580 --> 00:03:33,040 +So if you go look in the documentation for +如果你查看 UIViewController 的文档时 + +84 +00:03:33,050 --> 00:03:35,510 +UIViewController you'll see this property navigationItem. +你会看到有 navigationItem 这么一个属性 + +85 +00:03:35,510 --> 00:03:39,720 +If you click through to the type UINavigation item you'll +如果你查看 UINavigation 类型的东西的文档时 + +86 +00:03:39,720 --> 00:03:41,780 +see that it's got a lot of properties and +你看到它有许多的属性 + +87 +00:03:41,790 --> 00:03:45,690 +they're like left button, right button, title. +例如左按钮、右按钮、标题 + +88 +00:03:45,690 --> 00:03:47,540 +Things like that. So, +等等类似的东西 + +89 +00:03:47,540 --> 00:03:49,390 +the way the Navigation Controllers figures out +Navigation Controller 通过查询当前 MVC 堆栈顶部的 MVC + +90 +00:03:49,390 --> 00:03:52,590 +what to put in the top bar is it asks whatever MVC is on +来决定它在 Title Bar 上显示的内容 + +91 +00:03:52,600 --> 00:03:54,100 +top of the stack. + +92 +00:03:54,100 --> 00:03:56,900 +So as you go to different MVCs being on this stack of +所以栈顶 MVC 在不断变化的同时 + +93 +00:03:56,900 --> 00:03:59,200 +cards that thing at the top will change. +Navigation Controller 顶部区域也会随之变化 + +94 +00:04:00,300 --> 00:04:01,200 +Okay? +有问题吗? + +95 +00:04:01,200 --> 00:04:04,470 +So, let's say I click on General here, +假如我点击 General + +96 +00:04:04,470 --> 00:04:06,070 +because I want to see general settings. +因为我想看看通用设置 + +97 +00:04:06,070 --> 00:04:09,770 +Okay, so I click on it, and a new MVC gets put on top of +好的,当我点击 General 的时候,一个新的 MVC 就放在 MVC 堆栈的顶部了 + +98 +00:04:09,780 --> 00:04:12,910 +the stack of cards, so now I can't see the other one, okay? +现在,我就看不到其他的 MVC 了 + +99 +00:04:12,910 --> 00:04:14,180 +This new one is overlaying it, +新出现的 MVC 覆盖在其他 MVC 之上了 + +100 +00:04:14,180 --> 00:04:17,050 +and this is just a "General Settings" MVC. +这里是一个 "General Settings" MVC + +101 +00:04:17,050 --> 00:04:19,680 +Completely different MVC, +一个完全不同的 MVC + +102 +00:04:19,680 --> 00:04:22,320 +completely independent of the other one working on its own. +完全独立于其他 MVC 而工作的一个 MVC + +103 +00:04:22,320 --> 00:04:23,650 +By the way, +这里顺便提一句 + +104 +00:04:23,650 --> 00:04:24,990 +I don't have a good screenshot of this unfortunately, but +这里我不巧,没有一个很棒的截图来给你们展示其他的功能 + +105 +00:04:24,990 --> 00:04:27,720 +it's also possible for the Navigation Controller to +但是 Navigation Controller 可以 + +106 +00:04:27,730 --> 00:04:31,730 +draw some buttons along the bottom there. +在底部绘制几个新的按钮 + +107 +00:04:31,730 --> 00:04:33,190 +A little small sliver on the bottom. +可以在底部有一个小的灰色栏 + +108 +00:04:33,200 --> 00:04:36,400 +And it get those button items to put there, +然后将按钮置于那里 + +109 +00:04:36,400 --> 00:04:40,000 +by asking the MVC that's on top of the stack of cards for +而这个灰色栏的按钮布局是可以通过堆栈顶部的 MVC 的 + +110 +00:04:40,000 --> 00:04:42,670 +the toolbar items property. +toolbarItems 属性来设置的 + +111 +00:04:42,670 --> 00:04:43,870 +So if you look at toolbar items, +当你查看 toolbarItems 的文档时 + +112 +00:04:43,870 --> 00:04:47,240 +it's just an Array of these Bar Buttons, so +你会发现它就是一系列 Bar Button 组成的数组 + +113 +00:04:47,240 --> 00:04:50,080 +any MVC that returns anything in that Array, +当任意一个在 Navigation Controller 堆栈中的 MVC + +114 +00:04:50,080 --> 00:04:52,140 +when it's in a Navigation Controller like this, +在 toolbarItems 数组中返回什么东西的时候 + +115 +00:04:52,150 --> 00:04:54,280 +those buttons will appear at the bottom. +那些按钮会出现在屏幕的底部 + +116 +00:04:54,280 --> 00:04:55,710 +So those would change each time you go +同样,每次当你在堆栈上添加新的 MVC 的时候 + +117 +00:04:55,720 --> 00:04:58,320 +to the next thing on the stack as well. +这些按钮也会随之变化 + +118 +00:04:58,320 --> 00:05:00,920 +So let's go ahead and click on something here. +现在让我们继续点击什么东西 + +119 +00:05:01,920 --> 00:05:04,720 +Let's click on, oh sorry, the back button. +让我们点击,噢,返回按钮 + +120 +00:05:04,720 --> 00:05:07,290 +Yeah, you see there's a back button in the upper left. +你可以在屏幕的左上方看到一个返回按钮 + +121 +00:05:07,290 --> 00:05:11,090 +The back button says, Throw the top card off. +这个返回按钮的意思是,移走最顶部的那张卡片 + +122 +00:05:11,100 --> 00:05:12,260 +That's basically what back means. +这是返回最基本的意思 + +123 +00:05:12,260 --> 00:05:14,250 +Throw the top card on +移走 MVC 堆栈中 + +124 +00:05:14,250 --> 00:05:16,230 +this stack of MVCs that we're building, throw it off, and +最顶部的那张卡片 + +125 +00:05:16,230 --> 00:05:18,000 +then I'm going to go back to where I was before. +然后将我返回到我之前的那个位置 + +126 +00:05:18,000 --> 00:05:19,670 +So that's how back works, it just throws it off. +这就是返回如何工作的,扔掉卡片 + +127 +00:05:19,670 --> 00:05:21,570 +And when it throws it off, it completely throws it off, +当从 MVC 堆栈中移除最顶部的那张卡片时,它是完全被移除的 + +128 +00:05:21,570 --> 00:05:22,800 +it disappears. +它消失了 + +129 +00:05:22,810 --> 00:05:23,500 +Completely gone. +完全消失 + +130 +00:05:23,510 --> 00:05:24,400 +All right? +明白了吗? + +131 +00:05:24,410 --> 00:05:27,170 +Out of the heep, okay? +从堆栈中完全移除了 + +132 +00:05:27,180 --> 00:05:30,010 +All right, so let's put another card on the stacks, +好的,接下来让我们在堆栈中增加一个卡片 + +133 +00:05:30,010 --> 00:05:32,140 +I'm going to click on Accessibility here, +我点击这里的 Accessibility + +134 +00:05:32,150 --> 00:05:34,350 +another card's going to slide in, +另外一个卡片将会移入 + +135 +00:05:34,350 --> 00:05:39,380 +I'm trying to simulate the animation of it but in keynote +我尝试在 Keynote 里模仿这个动画 + +136 +00:05:39,390 --> 00:05:42,290 +I can't exactly do it, but it slides in from the side. +我不能很精确地模仿它,但是他从侧边移进去 + +137 +00:05:42,290 --> 00:05:44,710 +And this is yet +现在,这是 + +138 +00:05:44,710 --> 00:05:47,120 +another completely different MVC, the "Accessibility" MVC. +另外的一个完全不同的 MVC,"Accessibility" MVC + +139 +00:05:47,130 --> 00:05:48,460 +And we can pick something out of here, +这里我可以选择一些东西 + +140 +00:05:48,460 --> 00:05:51,060 +like I'm going to pick Larger Text right there, and +比如,我点击 Larger Text + +141 +00:05:51,060 --> 00:05:52,900 +another MVC is going to slide in. +这时,会有另外的一个 MVC 移入 + +142 +00:05:52,900 --> 00:05:55,530 +So we have four MVCs, totally different MVCs, +现在,我们有 4 个完全不同的 MVC 了 + +143 +00:05:55,530 --> 00:05:57,530 +on our stack of cards right here. +都在卡片堆栈上 + +144 +00:05:57,540 --> 00:06:00,400 +And the one on top, which is the last one that I chose, +最顶上的那个,也就是我最后选择的那个 + +145 +00:06:00,400 --> 00:06:02,600 +this "Larger Text" MVC, is showing. +"Larger Text" MVC,就是正在显示的这个 MVC + +146 +00:06:02,610 --> 00:06:03,840 +Okay? The rest of them are there, +明白了吗?在它的底下有其他的 MVC + +147 +00:06:03,840 --> 00:06:05,670 +you just can't see +但你看不见 + +148 +00:06:05,670 --> 00:06:07,510 +them because they're underneath this top card. +因为被顶部的卡片覆盖住了 + +149 +00:06:07,510 --> 00:06:08,940 +Okay, so now let's do the back button. +好的,现在让我们做返回操作 + +150 +00:06:08,950 --> 00:06:12,350 +So I'm going to click this back button in the upper left +我将点击左上角的返回按钮 + +151 +00:06:12,350 --> 00:06:15,420 +and when I do, it takes that "Larger Text" one off, throws it +当我点击的时候,它会将 "Larger Text" MVC 移走 + +152 +00:06:15,420 --> 00:06:18,750 +out, and now we've got the Accessibility card, which is +从堆栈里扔掉,现在我们有 Accessibility 的卡片了 + +153 +00:06:18,750 --> 00:06:22,320 +now the top of our stack which only has three things on it. +Accessibility 的卡片变成了堆栈上三个卡片中最顶端的那个 + +154 +00:06:22,320 --> 00:06:23,690 +And we can do back again. +我们继续返回 + +155 +00:06:23,690 --> 00:06:25,690 +It goes back to the general one. +现在返回到了 General 卡片 + +156 +00:06:25,690 --> 00:06:26,560 +We do back again. +再返回 + +157 +00:06:26,560 --> 00:06:28,490 +It goes back to the very top. +回到了最最上层 + +158 +00:06:28,490 --> 00:06:30,430 +Of course, once we get back to the very top there's no +当然,当我们回到了最最上层的时候 + +159 +00:06:30,430 --> 00:06:33,700 +more back button because this is the only card on the stack. +不会再有返回按钮了,因为那是堆栈上唯一的卡片了 + +160 +00:06:33,700 --> 00:06:34,870 +Okay, so everyone understand what +现在,每个人对 Navigation Controller + +161 +00:06:34,870 --> 00:06:35,800 +a Navigation Controller is? +都理解了吗? + +162 +00:06:35,800 --> 00:06:37,230 +It's just a stack of MVCs. +简单的说,就是 MVC 堆栈 + +163 +00:06:37,240 --> 00:06:38,370 +All right? +没问题吧? + +164 +00:06:38,370 --> 00:06:40,600 +But it's just like Split View Controller and +但是它和 Split View Controller 和 + +165 +00:06:40,610 --> 00:06:44,370 +UITabBarController in that it is showing multiple MVCs. +UITabBarController 一样,它们的功能都是展示多重 MVC + +166 +00:06:44,380 --> 00:06:45,970 +So I'm going talk a little bit about how navigation +所以我将更详细地讨论一下 Navigation Controller + +167 +00:06:45,980 --> 00:06:49,080 +controller works internally, so you can get a feel for it. +内部的工作方式,让你们有一个更直观的感受 + +168 +00:06:49,080 --> 00:06:52,950 +And I'm going to try to mix it with our MVC image that we +同时,我会尝试将它和我们的其他 MVC 混合在一起 + +169 +00:06:52,950 --> 00:06:56,220 +had so you can kind of combine the two concepts in your mind. +这样你就能在你的大脑里混合这两种概念了 + +170 +00:06:56,220 --> 00:06:58,690 +So, let's say I had an MVC. +这里,假设我有一个 MVC + +171 +00:06:58,690 --> 00:07:01,490 +This one up here, the purple MVC thing. +顶上的那个紫色的 MVC + +172 +00:07:01,490 --> 00:07:04,420 +And I had more features I wanted to put on there, but +我本想在这个 MVC 之上添加一些其他的功能,但是 + +173 +00:07:04,430 --> 00:07:06,430 +there's just not enough room on the screen anymore, +屏幕的空间不够 + +174 +00:07:06,430 --> 00:07:07,830 +I've kind of maxed out. +我已经尽量使用了所有可用的屏幕空间 + +175 +00:07:07,830 --> 00:07:10,400 +Or it's just those features don't logically make sense to +或者从逻辑上,我要添加的功能不应当 + +176 +00:07:10,400 --> 00:07:12,100 +be in the same place. +显示在这个 MVC 之上时 + +177 +00:07:12,100 --> 00:07:15,300 +Well, what I would do is create another MVC to manage +我应该怎么做呢?我应该创建另外一个 MVC + +178 +00:07:15,300 --> 00:07:18,300 +those other features that won't fit, okay? +去管理那些不属于这个 MVC 的那些功能,对吗? + +179 +00:07:18,310 --> 00:07:22,710 +And, so now though I need a way to have those two MVCs +所以,我应该找到某种方法,让这两个 MVC + +180 +00:07:22,710 --> 00:07:25,140 +share the screen and I can use a Split View Controller or +能够共享一个屏幕空间。这里,我能使用一个 Split View Controller + +181 +00:07:25,140 --> 00:07:27,140 +Tab Bar Controller if they were peers or +或者如果这两个 MVC 之间是平等关系的话,我可以使用 Tab Bar Controller + +182 +00:07:27,150 --> 00:07:28,910 +I could use Navigation Controller. +当然我也可以使用 Navigation Controller + +183 +00:07:28,910 --> 00:07:30,280 +So, let's see what it would look like to +让我们来看看 + +184 +00:07:30,280 --> 00:07:33,950 +use a Navigation Controller to have these two MVCs which +当我们使用一个 Navigation Controller 来结合这两个 MVC + +185 +00:07:33,950 --> 00:07:36,990 +they're related share the screen. +使得它们共享同一屏幕空间的情况 + +186 +00:07:36,990 --> 00:07:40,220 +So a Navigation Controller is just an MVC, okay? +还记得 Navigation Controller 也是一个 MVC 吗? + +187 +00:07:40,220 --> 00:07:42,810 +It's a controller of an MVC. +一个 MVC 的控制器(Controller) + +188 +00:07:42,810 --> 00:07:45,390 +And it's view is a little rectangular area that usually +它的视图是一个小的矩形区域 + +189 +00:07:45,400 --> 00:07:47,930 +fills the entire screen or a portion of the screen. +通常布满整个屏幕空间,或是占屏幕空间的一部分 + +190 +00:07:47,930 --> 00:07:48,860 +It's got the title. +它有一个标题 + +191 +00:07:48,870 --> 00:07:53,000 +But it's a special MVC and they've just got an outlet +但它是一个特殊的 MVC,它有一个叫做 rootViewController 的 outlet + +192 +00:07:53,000 --> 00:07:56,070 +called rootViewController that points to an MVC. +这个 outlet 指向某个 MVC + +193 +00:07:56,070 --> 00:07:59,440 +Okay, points to the controller of an MVC. +确切的说,是指向某个 MVC 的控制器 + +194 +00:07:59,440 --> 00:08:03,240 +And when it is pointing to that, then the navigation +当这个 outlet 指向某个 MVC 的控制器时 + +195 +00:08:03,240 --> 00:08:08,080 +controller puts that MVC's view, okay, its view property. +Navigation Controller 便会将那个 MVC 的视图绘制出来,也就是 view 属性 + +196 +00:08:08,080 --> 00:08:09,680 +All right, we know that UIViewController has +我们已经知道 UIViewController 有一个 + +197 +00:08:09,680 --> 00:08:11,320 +this very important property called view, +非常重要的属性,叫做 view + +198 +00:08:11,320 --> 00:08:12,980 +which is its top level of its view. +它是所有视图中最顶层的那个 + +199 +00:08:12,990 --> 00:08:16,520 +It puts that on the screen underneath this title thing. +Navigation Controller 把它放置在屏幕上,标题栏之下 + +200 +00:08:16,520 --> 00:08:18,860 +So it fills the entire rectangular area and +因为它会布满整个矩形空间 + +201 +00:08:18,860 --> 00:08:21,190 +then the title kind of overlaps it transparently, +所以标题栏会变成半透明,以显示标题栏之下的那部分 + +202 +00:08:21,190 --> 00:08:25,060 +semi-lucent transparency. +毛玻璃透明效果 + +203 +00:08:25,060 --> 00:08:25,730 +Okay? +明白了吗? + +204 +00:08:25,730 --> 00:08:26,860 +So that's great. +很好 + +205 +00:08:26,860 --> 00:08:28,480 +So we got it in there. +我们现在成功把一个 MVC 和 Navigation Controller 结合在一起了 + +206 +00:08:28,480 --> 00:08:30,100 +Now how do we get the other MVC on? +我们如何让其他的 MVC 和 Navigation Controller 继续结合在一起? + +207 +00:08:30,100 --> 00:08:33,170 +Well, when a ui element inside the view of +好的,当某个在这个视图中的 UI 元素 + +208 +00:08:33,170 --> 00:08:35,970 +this MVC like a button or something like that +例如一个按钮或者其他的东西 + +209 +00:08:35,970 --> 00:08:40,110 +is pressed then it can cause another MVC to get created. +被按下的时候,这能导致其他的 MVC 被创建 + +210 +00:08:40,110 --> 00:08:42,010 +You notice that MVC just appeared? +你注意到这个 MVC 刚刚出现了吗? + +211 +00:08:42,010 --> 00:08:43,310 +It wasn't there before. +之前这个新的 MVC 没有出现过 + +212 +00:08:43,310 --> 00:08:46,080 +But as soon as the button gets pressed in this guy's view, +但是,在用户的视图中,只要有按钮一按下 + +213 +00:08:46,080 --> 00:08:48,250 +this MVC's view, that thing gets created. +那么一个新的 MVC 就会被创建 + +214 +00:08:48,250 --> 00:08:50,880 +And that's something important to notice that we're always +在这个过程中,需要注意到的是 + +215 +00:08:50,890 --> 00:08:54,350 +going to be creating a new MVC when we do these transitions. +当我们做这些转换时,我们始终会创建一个新的 MVC + +216 +00:08:54,360 --> 00:08:56,520 +Okay? Transitioning to a new card. +明白了吗?转换到一个新的卡片 + +217 +00:08:56,520 --> 00:08:58,060 +In a Split View, +在一个 Split View 中 + +218 +00:08:58,060 --> 00:08:59,590 +we do something in the master that changes the detail. +我们在 Master 中做的操作会改变 Detail + +219 +00:08:59,590 --> 00:09:00,890 +That's always creating a new, +这也就是说,它始终创建了一个新的 Detail + +220 +00:09:00,890 --> 00:09:03,160 +even the first time we press a tab bar, but +这种情况甚至存在于,当我们按下了 Tab Bar + +221 +00:09:03,160 --> 00:09:06,230 +only the first time for the tab bar, it creates a new MVC. +并且是第一次按下 Tab Bar 的时候 + +222 +00:09:06,230 --> 00:09:07,730 +Okay? So it creates this new MVC. +明白了吗?所以这样的操作会创建一个新的 MVC + +223 +00:09:07,730 --> 00:09:10,470 +And then the Navigation Controller just +接着,Navigation Controller 就会移动到 + +224 +00:09:10,470 --> 00:09:13,270 +moves over to put that MVC's view on top. +新创建的 MVC 之上 + +225 +00:09:13,270 --> 00:09:15,000 +All right? + +226 +00:09:15,010 --> 00:09:16,840 +And then of course you've got the back button. +当然,之后你就会在左上角有一个返回按钮 + +227 +00:09:16,840 --> 00:09:18,310 +When you click the back button, +当你按下返回按钮的时候 + +228 +00:09:18,310 --> 00:09:20,640 +it goes back to the first MVC. +Navigation Controller 回到了第一个 MVC + +229 +00:09:20,640 --> 00:09:22,580 +And look what happens to that MVC. +让我们来看看新创建的 MVC,它会发生什么 + +230 +00:09:22,580 --> 00:09:23,780 +Gone. +消失了 + +231 +00:09:23,780 --> 00:09:25,010 +Okay. + +232 +00:09:25,010 --> 00:09:26,350 +That is not hidden or something. +它不是被隐藏起来了 + +233 +00:09:26,350 --> 00:09:28,220 +It's just gone. +它消失了 + +234 +00:09:28,220 --> 00:09:30,080 +It got deallocated probably from the heap. +它所占用的内存空间中被释放了 + +235 +00:09:30,090 --> 00:09:31,380 +Okay? And then we're back to here. +我们回到了第一个 MVC + +236 +00:09:32,590 --> 00:09:34,350 +Okay, so that's how Navigation Controller works. +好的,这就是 Navigation Controller 工作的方式 + +237 +00:09:34,360 --> 00:09:35,300 +Very simple. +非常的简单 + +238 +00:09:35,310 --> 00:09:36,250 +And, you know, Split View and +你要知道,Split View 和 + +239 +00:09:36,260 --> 00:09:38,420 +tab bar are similar kind of mechanism. +Tab Bar 的工作方式也是类似 + +240 +00:09:39,690 --> 00:09:41,780 +Okay. So +好的 + +241 +00:09:41,780 --> 00:09:43,860 +how do we get at these sub-MVCs? +另外一个问题,我们如何能够取得这些子 MVC 呢? + +242 +00:09:43,860 --> 00:09:45,960 +So let's say I had a Split View Controller or +假设说,我有一个 Split View Controller + +243 +00:09:45,960 --> 00:09:47,530 +a Navigation Controller or a Tab Bar Controller. +或者一个 Navigation Controller 或者一个 Tab Bar Controller + +244 +00:09:47,530 --> 00:09:50,170 +How do I get at the things on the stack of cards, +我如何去获取这些卡片堆栈上的东西呢? + +245 +00:09:50,170 --> 00:09:52,970 +or the two things the master and detail? +或者说,我如何去获取 Master 和 Detail 中的东西呢? + +246 +00:09:52,970 --> 00:09:54,840 +And the answer is +答案是 + +247 +00:09:54,840 --> 00:09:56,710 +they all have a property called viewControllers. +它们都会有一个叫 viewControllers 的属性 + +248 +00:09:56,710 --> 00:09:58,870 +And it's an Array of View Controller. +它是由 UIViewController 组成的一个数组 + +249 +00:09:58,880 --> 00:10:00,490 +Okay? +明白了吗? + +250 +00:10:00,490 --> 00:10:02,110 +And that it's all the View Controllers in a system. +它里面存储的是一个系统中所有的 View Controller + +251 +00:10:02,110 --> 00:10:05,110 +So in a Split View, there will be only two in there, +在 Split View 中,这里面只会有两个元素 + +252 +00:10:05,110 --> 00:10:07,550 +the master and the detail, in the tab bar there will be how +Master 和 Detail,在 Tab Bar 中 + +253 +00:10:07,550 --> 00:10:09,650 +ever many tabs there are, in a Navigation Controller there +有多少个 Tab,这里面就有多少个元素,而在 Navigation Controller 中 + +254 +00:10:09,650 --> 00:10:11,720 +will be however many cards are on the stack. +堆栈上有多少卡片,这里面就有多少个元素 + +255 +00:10:11,720 --> 00:10:13,050 +That's how many things will be in that Array. +这就是知道这个数组有多少个元素的方式 + +256 +00:10:13,050 --> 00:10:15,420 +And it's settable too which is a little weird, +当然它是可以被设值的,但是这么做有点奇怪 + +257 +00:10:15,420 --> 00:10:19,090 +we don't usually set things but you can do it. +通常我们不会对它直接设值,但是不代表不可以这么做 + +258 +00:10:19,090 --> 00:10:23,800 +And the way we usually set it is we're going to +我们通常对它设值的方式是 + +259 +00:10:23,800 --> 00:10:26,600 +do it in the Storyboards or Navigation Controller for +比如我们在 Storyboard 的 Navigation Controller 中 + +260 +00:10:26,600 --> 00:10:29,300 +example has methods like push and pop View Controller that +有 push 和 pop View Controller 的方法 + +261 +00:10:29,300 --> 00:10:31,400 +will push View Controller onto the stack. +这样的操作会把 View Controller push 到堆栈中 + +262 +00:10:31,400 --> 00:10:32,640 +But that is doing that in code and +但这是在代码中设值的方式 + +263 +00:10:32,640 --> 00:10:35,210 +we are usually doing all of this stuff in Storyboards. +通常我们在 Storyboard 中做这一系列的操作 + +264 +00:10:35,210 --> 00:10:38,910 +So that's how you get at the sub things of +以上就是你如何获得这些子 MVC + +265 +00:10:38,910 --> 00:10:41,740 +these three kinds of View Controllers. +这些 View Controller 的方法 + +266 +00:10:41,750 --> 00:10:44,550 +What about, how do I get a hold of the View Controller? +那么,我如何获得一个 View Controller 呢? + +267 +00:10:44,550 --> 00:10:45,480 +Okay? How do I get that +我如何获得一个 + +268 +00:10:45,480 --> 00:10:46,550 +Navigation Controller? +Navigation Controller? + +269 +00:10:46,550 --> 00:10:48,620 +How do I get a pointer to it, or whatever? +我怎么获得它的一个指针呢? + +270 +00:10:48,620 --> 00:10:52,420 +Well it turns out every View Controller knows if it's +答案是,每个 View Controller 都知道 + +271 +00:10:52,420 --> 00:10:55,660 +inside a Navigation Controller or if it's inside a split-view +它自己是不是身处在一个 Navigation Controller 或者 + +272 +00:10:55,660 --> 00:10:57,590 +controller, or if it's inside a Tab Bar Controller. +Split View Controller 或者 Tab Bar Controller 中 + +273 +00:10:57,590 --> 00:10:59,310 +It knows. +它自己知道 + +274 +00:10:59,310 --> 00:11:01,030 +And so UIView controller has these three properties: +因为,UIViewController 有三个属性: + +275 +00:11:01,030 --> 00:11:02,360 +tabBarController, splitViewController, +tabBarController,splitViewController + +276 +00:11:02,360 --> 00:11:03,560 +navigationController. +和 navigationController + +277 +00:11:03,560 --> 00:11:05,530 +And they will return to you the splitViewController +splitViewController 属性会返回给你 + +278 +00:11:05,530 --> 00:11:07,470 +that the View Controller is in. +它处在哪个 Split View Controller 中,其他的属性类推 + +279 +00:11:07,470 --> 00:11:09,030 +Okay? +明白了吗? + +280 +00:11:09,040 --> 00:11:11,070 +If it's in one, if it's not then it returns nil. +如果它不在某个 Controller 中,这个属性返回的是 nil + +281 +00:11:11,070 --> 00:11:12,940 +And notice some View Controllers might be inside a +注意到某些 View Controller 会在一个 Navigation Controller 中 + +282 +00:11:12,940 --> 00:11:15,510 +Navigation Controller, inside a Split View Controller. +而这个 Navigation Controller 又嵌套在一个 Split View Controller 中 + +283 +00:11:16,440 --> 00:11:17,770 +So more than one of these things can be +所以这些属性可以有多个 + +284 +00:11:17,780 --> 00:11:19,790 +non-nil at a time. +同时不为 nil + +285 +00:11:19,790 --> 00:11:21,810 +Because we can nest these things to build more powerful +我们可以利用这些嵌套来构建一个 + +286 +00:11:21,810 --> 00:11:23,960 +user interfaces. +强大的用户界面 + +287 +00:11:23,960 --> 00:11:26,110 +So let's just use the example, if I'm the master in +让我们举个例子,如果我是一个 Split View 中的 Master + +288 +00:11:26,120 --> 00:11:28,720 +a Split View, and I want to get the detail. +我想获取 Detail + +289 +00:11:28,720 --> 00:11:30,920 +Well I can get the splitViewController I'm in by +这里我可以通过访问 splitViewController + +290 +00:11:30,920 --> 00:11:32,390 +saying Split View Controller. +来获得我在哪个 Split View Controller 的指针 + +291 +00:11:32,390 --> 00:11:33,720 +I'll put the little question mark there, +这里我会输入一个问号 + +292 +00:11:33,720 --> 00:11:34,860 +that's optional chaining. +这是 Optional Chaining + +293 +00:11:34,860 --> 00:11:36,010 +If it's nil, +如果它返回的是 nil 的话 + +294 +00:11:36,010 --> 00:11:37,160 +then I'm obviously not going to get my detail. +那么显然我不应该获得 Detail(因为我根本不在一个 Split View Controller 中) + +295 +00:11:37,160 --> 00:11:39,260 +And then I'm going to say viewController sub 1, +然后我输入 viewControllers[1] + +296 +00:11:39,260 --> 00:11:40,960 +because we know that viewController sub 1 in +因为我们知道,viewControllers[1] 在 + +297 +00:11:40,960 --> 00:11:43,100 +split controller is the detail. +Split View Controller 中代表的是 Detail + +298 +00:11:43,100 --> 00:11:44,830 +So now I've got the detail and +现在,我就获得了 Detail + +299 +00:11:44,830 --> 00:11:46,570 +I can talk to it I could, you know, get to my detail. +我就能向 Detail 发送消息了 + +300 +00:11:46,570 --> 00:11:47,830 +So presumably I might want to tell it to +假设这里,我希望告诉 Detail 去 + +301 +00:11:47,840 --> 00:11:50,800 +do things display things or whatever, okay? +显示某些东西或者做其他的事情 + +302 +00:11:52,010 --> 00:11:55,170 +So that's how we get at these things in code if we need to, +所以,如果我们需要的话,我们可以通过这样的代码来获取我们想要的指针 + +303 +00:11:55,180 --> 00:11:58,240 +but we often don't need to because we can manage most of +但我们通常并不需要,因为我们能够 + +304 +00:11:58,240 --> 00:11:59,640 +this in the Storyboard. +在 Storyboard 完成大部分的操作 + +305 +00:11:59,650 --> 00:12:02,550 +And so how do we wire this up, how do we create this +所以,我们如何在 Storyboard 里链接起来这些 MVC + +306 +00:12:02,550 --> 00:12:05,720 +relationship between these split through tab bar and +如何在子 MVC 和 Split View Controller,Tab Bar Controller 以及 + +307 +00:12:05,720 --> 00:12:08,920 +Navigation Controller and these all the sub-MVCs. +Navigation Controller 之间建立关系呢? + +308 +00:12:08,920 --> 00:12:11,750 +And it can be done in code, okay? +这些都可以通过代码来完成 + +309 +00:12:11,760 --> 00:12:12,890 +But we're gonna do it +但是我们在这节课上 + +310 +00:12:12,890 --> 00:12:15,390 +in Storyboards in this class all the time. +将通过 Storyboard 来完成 + +311 +00:12:15,390 --> 00:12:17,190 +Okay. And we're just +我们要做的就是 + +312 +00:12:17,190 --> 00:12:18,990 +gonna use Ctrl + drag to do it. +按住Control键并拖动来链接多个 MVC + +313 +00:12:19,000 --> 00:12:20,500 +So let's see what that looks like. +让我们来看看这是什么样子的 + +314 +00:12:20,500 --> 00:12:22,630 +I'll do it for Split View Controller, +以 Split View Controller 举例 + +315 +00:12:22,630 --> 00:12:24,330 +we're just going to go the utilities area, +我们找到 Utilities 区域 + +316 +00:12:24,330 --> 00:12:26,970 +the same place we drag out a button or something like that. +和我们之前拖出来按钮和其他的 UI 元素同样的地方 + +317 +00:12:26,970 --> 00:12:29,300 +We're going to drag out a Split View Controller. +我们拖出来一个 Split View Controller + +318 +00:12:29,300 --> 00:12:30,600 +Now, when it comes out, +当它被拖动出来的时候 + +319 +00:12:30,610 --> 00:12:33,410 +it's going to come out with a whole bunch of other MVCs +它会带出来一整连串的 MVC + +320 +00:12:33,410 --> 00:12:35,910 +pre-attached to it in attempt to help you, but +这些 MVC 预先链接在一起以方便你的使用 + +321 +00:12:35,910 --> 00:12:38,280 +usually you're just going to delete those so +但通常你会删除它们以链接你自己的 MVC + +322 +00:12:38,280 --> 00:12:41,410 +that all you have left is the Split View Controller itself. +这样你就只保留了 Split View Controller 本身 + +323 +00:12:41,420 --> 00:12:43,280 +Okay? +明白了吗? + +324 +00:12:43,280 --> 00:12:45,150 +And then you're going to Ctrl+Drag from the Split View +然后,你从 Split View Controller 开始 + +325 +00:12:45,150 --> 00:12:46,720 +Controller to the Master and +按住 Control 键拖动,链接 Split View Controller 和 Master + +326 +00:12:46,720 --> 00:12:50,120 +Ctrl+Drag from the Split View Controller to the Detail. +同样方法,链接 Split View Controller 和 Detail + +327 +00:12:50,120 --> 00:12:51,150 +And that's how you are going to do the wire. +这样你就链接起来了 Master 和 Detail + +328 +00:12:51,160 --> 00:12:52,360 +So this is what it looks like. +这就是链接过程看上去的样子 + +329 +00:12:52,360 --> 00:12:53,620 +Here I have a Storyboard. +这里我有一个 Storyboard + +330 +00:12:53,630 --> 00:12:55,120 +I've dragged out of Split View Controller. +我从 Split View Controller 开始拖动 + +331 +00:12:55,130 --> 00:12:56,990 +That's that gray thing on the left. +Split View Controller 就是左边灰色的那个 + +332 +00:12:56,990 --> 00:12:58,190 +Okay? +没问题吧? + +333 +00:12:58,190 --> 00:12:59,390 +I deleted all the things it was attached to so +我删除了之前附加在 Split View Controller 的东西 + +334 +00:12:59,400 --> 00:13:00,360 +I just had that. +所以我只保留了 Split View Controller 本身 + +335 +00:13:00,360 --> 00:13:02,730 +Then I Ctrl+Drag to, +然后我按住 Control 键并拖动 + +336 +00:13:02,730 --> 00:13:05,500 +in this case my Master, which is my calculator. +在这个例子中,我的 Master 是我的计算器 + +337 +00:13:05,500 --> 00:13:08,400 +When I do that, it's going to put up this little thing says +当我做这个操作的时候,这里会提示说 + +338 +00:13:08,400 --> 00:13:10,140 +okay, what kind of connection do you want to make? +“你想要创建什么样类型的链接?” + +339 +00:13:10,140 --> 00:13:13,270 +And you're going to pick Master View Controller there. +选择 Master View Controller + +340 +00:13:13,280 --> 00:13:15,540 +And that's going to make like a little connection to it. +这样就建立了一个链接 + +341 +00:13:15,540 --> 00:13:18,280 +And then I'm going to Ctrl+Drag down to my Detail, +然后,我按住 Control 键并拖动到 Detail 上 + +342 +00:13:18,280 --> 00:13:20,980 +which is going to be the right side of my Split View. +这样 Detail 就会成为我 Split View 中右侧的部分了 + +343 +00:13:20,980 --> 00:13:23,320 +And here I'm going to choose I want Detail View Controller. +这里同样会弹出一个提示,选择 Detail View Controller + +344 +00:13:23,320 --> 00:13:25,180 +Okay? +明白了吗? + +345 +00:13:25,190 --> 00:13:26,720 +And then I'm going to have this, +然后我就拥有了一个 + +346 +00:13:26,720 --> 00:13:28,050 +fully hooked up Split View. +完整的 Split View + +347 +00:13:28,050 --> 00:13:29,090 +And that's it. +这就是如何通过 Storyboard 链接 Split View Controller 的方式 + +348 +00:13:29,090 --> 00:13:31,290 +So it's very easy to hook these things up. +非常简单就可以链接起来 + +349 +00:13:31,290 --> 00:13:32,570 +All right, and tab bar, +好的,Tab Bar Controller + +350 +00:13:32,570 --> 00:13:33,860 +you can hook up exactly the same way. +你可以通过几乎相同的方法把子 MVC 链接起来 + +351 +00:13:33,860 --> 00:13:36,130 +Connect as many of them as you want, okay? +想链接多少 MVC 都可以 + +352 +00:13:36,130 --> 00:13:38,290 +Navigation Controllers can be done a little bit differently, +Navigation Controller 有一点点的不同 + +353 +00:13:38,300 --> 00:13:39,730 +which we'll see in a second, okay? +稍后我们可以看到 + +354 +00:13:41,030 --> 00:13:45,130 +But there's a problem here which is that a Split View +但是这里有一个问题,那就是 + +355 +00:13:45,140 --> 00:13:48,970 +can't display side by side on an iPhone. +Split View 不能在 iPhone 上并排显示 + +356 +00:13:48,970 --> 00:13:50,900 +Or at least not anything but an iPhone 6 plus. +更确切的说,不能在 iPhone 6 Plus 以外的 iPhone 型号上显示 + +357 +00:13:50,910 --> 00:13:54,070 +That's the only one big enough to really display side +因为 iPhone 6 Plus 是唯一一个拥有足够大小 + +358 +00:13:54,080 --> 00:13:55,530 +by side. +来并排显示 Master 和 Detail 的型号 + +359 +00:13:55,530 --> 00:13:56,980 +So a Split View really can't work on an iPhone. +所以 Split View 不算是真正能够在 iPhone 上使用的 + +360 +00:13:56,980 --> 00:13:59,500 +Okay? +明白了吗? + +361 +00:13:59,500 --> 00:14:02,020 +The way we handle this is that iOS adapts its +我们处理这个的方式是 + +362 +00:14:02,020 --> 00:14:07,220 +user interface to whatever device it happens to be on, +因为 iOS 会在不同屏幕大小的设备上改变其用户界面 + +363 +00:14:07,220 --> 00:14:10,590 +depending on how its Size Class is. +这取决于它的 Size Class 是什么 + +364 +00:14:10,590 --> 00:14:13,930 +We'll talk about Size Class later, but if it's Compact, +我们稍后会讲到 Size Class,但如果它是 Compact 尺寸 + +365 +00:14:13,930 --> 00:14:17,730 +like a phone, then it can't show it in a Split View. +比如 iPhone,那么它没办法在 Split View 中显示 + +366 +00:14:17,730 --> 00:14:19,300 +So how can I show it then? +那我如何显示它呢? + +367 +00:14:19,300 --> 00:14:21,030 +If I have it Master in a Detail and +如果我有 Master 和 Detail + +368 +00:14:21,030 --> 00:14:24,030 +I wanna show it on an iPhone the way I show it is with +而且我想在 iPhone 上显示它的话 + +369 +00:14:24,040 --> 00:14:25,800 +a Navigation Controller. +那么请使用 Navigation Controller + +370 +00:14:25,800 --> 00:14:26,940 +So instead of having Master and +来替代同时在屏幕上显示 Master 和 Detail + +371 +00:14:26,940 --> 00:14:28,900 +Detail on the screen at the same time on an iPad, +只有 iPad 可以同时显示 + +372 +00:14:28,910 --> 00:14:32,810 +on the phone when I click in the Master, same button that I +在 iPhone 上,我点击 Master 中同样的按钮 + +373 +00:14:32,810 --> 00:14:35,610 +clicked to make the Detail show it in Split View, +用以在 Split View 中显示 Detail 的按钮 + +374 +00:14:35,610 --> 00:14:38,410 +but when I click in the Master on the iPhone is going to +但是在 iPhone 上同样的操作会导致 + +375 +00:14:38,420 --> 00:14:41,150 +slide the Detail on as a card. +Detail 卡片滑入 + +376 +00:14:41,150 --> 00:14:41,980 +On the deck. +在层面上 + +377 +00:14:41,980 --> 00:14:42,880 +All right. + +378 +00:14:42,890 --> 00:14:44,850 +On the navigation charts stack. +在 Navigation Controller 的栈上 + +379 +00:14:44,850 --> 00:14:46,450 +Now the thing is though we want to +现在我们想要做的是 + +380 +00:14:46,450 --> 00:14:48,650 +build one Storyboard that will work for +建立同一个 Storyboard 在不同的 + +381 +00:14:48,660 --> 00:14:51,820 +both platforms and automatically adapts. +平台上都工作并自动适应其屏幕大小 + +382 +00:14:51,830 --> 00:14:52,960 +So how do we do that? +我们应该如何实现呢? + +383 +00:14:52,960 --> 00:14:56,330 +We're just going to wrap our Master in +我们要做的就是,将我们的 Master 嵌入 + +384 +00:14:56,330 --> 00:14:58,730 +a Navigation Controller. +进一个 Navigation Controller 中 + +385 +00:14:58,730 --> 00:15:00,870 +So here is a Navigation Controller, +这样,这里有一个 Navigation Controller + +386 +00:15:00,870 --> 00:15:04,130 +which is my Master, it's the calculator, right? +它就是我的 Split View Controller 中的 Master,也就是我的计算器,对吗? + +387 +00:15:04,140 --> 00:15:06,140 +And you can see it's hooked up to the Split View already, and +你能看到,它已经链接到 Split View 了 + +388 +00:15:06,140 --> 00:15:08,710 +I'm just gonna select it, and then I'm gonna go to +这里我选择它,找到 + +389 +00:15:08,710 --> 00:15:13,810 +the Editor menu and pick Embed in Navigation Controller. +Xcode 菜单中的 Editor,然后选择 Embed in Navigation Controller + +390 +00:15:13,810 --> 00:15:14,740 +See that embed? +看到那个 Embed in 了吗? + +391 +00:15:14,750 --> 00:15:15,680 +And this is what's gonna happen. +这就是我们要做的 + +392 +00:15:17,880 --> 00:15:19,280 +Okay, the Navigation Controller, +好的,Navigation Controller + +393 +00:15:19,280 --> 00:15:23,850 +is going to the interposed between the Split View and +将会在 Split View 和 Master 之间充当一个中间者 + +394 +00:15:23,850 --> 00:15:25,420 +the Master. + +395 +00:15:25,420 --> 00:15:26,990 +So now the Master, is in a Navigation Controller. +现在 Master 已经嵌入进一个 Navigation Controller 中了 + +396 +00:15:27,990 --> 00:15:31,190 +Now if I am on an iPhone, and I click in something +当我在 iPhone 上运行并且点击某些东西 + +397 +00:15:31,190 --> 00:15:34,260 +that would change the Detail, then it's going to push it +即将改变 Detail 的内容的时候,它会 push 这个 + +398 +00:15:34,260 --> 00:15:37,600 +on that Navigation Controller, on top of the stack. +到 Navigation Controller 的栈顶上 + +399 +00:15:37,600 --> 00:15:39,330 +But if I am on an iPad it's going to +当我在 iPad 上运行的时候 + +400 +00:15:39,330 --> 00:15:40,930 +show them side by side. +它就会在右侧并排展示这个 Detail + +401 +00:15:40,930 --> 00:15:42,470 +So this structure that you see right here, +你这里看到的就是这个结构 + +402 +00:15:42,470 --> 00:15:44,070 +Split View, Navigation Controller for +用 Split View,Navigation Controller + +403 +00:15:44,070 --> 00:15:47,740 +the Master and then Detail is very common. +这种结构来链接 Master 和 Detail 是十分普遍的 + +404 +00:15:47,740 --> 00:15:50,470 +A universal way of specifying your UI so +这就是定义用户界面的一种通用方法 + +405 +00:15:50,480 --> 00:15:52,380 +it works on both, okay? +而且对 iPhone 和 iPad 都适用 + +406 +00:15:54,450 --> 00:15:57,350 +Now we can also put the Detail inside of +我们同样可以将 Detail 嵌入一个 Navigation Controller 中 + +407 +00:15:57,350 --> 00:16:00,050 +a Navigational Controller too, why would we want to do that? +不过我们会问,为什么我们会想要这么做? + +408 +00:16:00,050 --> 00:16:01,480 +Well the only reason we would wanna do that, +这么做的唯一理由是 + +409 +00:16:01,490 --> 00:16:03,650 +is cuz maybe we want +我们可能需要 + +410 +00:16:03,650 --> 00:16:05,820 +the Navigation Controller's feature of a title, right? +Navigation Controller 的标题栏的功能,对吗? + +411 +00:16:05,820 --> 00:16:08,060 +Or little buttons we wanna put at the top. +或者是我们想在标题栏上放置一些按钮的功能 + +412 +00:16:08,060 --> 00:16:09,560 +It's really nice for that. +这么做是个好方法 + +413 +00:16:09,560 --> 00:16:10,880 +But, we don't need +但是,我们并不需要 + +414 +00:16:10,880 --> 00:16:12,190 +a Navigation Controller down there for navigation, +用一个 Navigation Controller 来做导航 + +415 +00:16:12,190 --> 00:16:14,530 +because we are never navigating from the Detail. +因为我们从来不需要在 Detail 里导航 + +416 +00:16:14,530 --> 00:16:17,160 +We only navigate to the Detail. +我们只会导航至 Detail + +417 +00:16:17,170 --> 00:16:20,330 +So, it doesn't, itself, need to be in its own +因此它自身不需要一个 Navigation Controller + +418 +00:16:20,340 --> 00:16:22,900 +Navigation Controller, and we'll see that in the demo. +稍后我们会在 Demo 中看到 + +419 +00:16:22,900 --> 00:16:25,540 +All right, so that's how we wire these things up. +好的,这就是我们如何链接这些东西的 + +420 +00:16:25,540 --> 00:16:27,340 +Okay, and they end up looking like that. +它们最后应该会是这个样子的 + +421 +00:16:28,340 --> 00:16:31,980 +Now how do we make these things appear? +接下来,我们如何将它们显示出来? + +422 +00:16:31,980 --> 00:16:34,750 +How do we make changes in our master, +我们在 Master 中做了一些改变 + +423 +00:16:34,750 --> 00:16:37,010 +that cause something to appear in the Detail. +如何使 Detail 显示 Master 中的这些改变 + +424 +00:16:37,020 --> 00:16:39,250 +Or if we have a Navigational Controller that has multiple +或者说,我们有一个 Navigation Controller + +425 +00:16:39,250 --> 00:16:41,920 +cards, when we clicked all those buttons and another card +它拥有许多卡片(MVC),当我们点击这些按钮的时候 + +426 +00:16:41,920 --> 00:16:45,820 +kept coming on in the stack, how did we do that, okay? +另外的卡片会 push 进栈,我们如何做到呢? + +427 +00:16:45,820 --> 00:16:48,790 +And the answer is we use segues, okay? +答案是,我们利用 Segues,明白吗? + +428 +00:16:48,790 --> 00:16:53,230 +So segues is, how these things transition from +Segues 是如何从一个 View Controller 转换到 + +429 +00:16:53,230 --> 00:16:54,560 +View Controller to View Controller. +另一个 View Controller 的方式 + +430 +00:16:55,970 --> 00:16:57,500 +There's really four kinds of segues. +iOS 里已经定义了四种不同的 Segues + +431 +00:16:57,500 --> 00:16:58,730 +There are custom segues, too, but +当然你还可以自定义 Segues + +432 +00:16:58,730 --> 00:17:00,200 +we're not gonna talk about that in this class, +但是本节课我们不会讨论到 + +433 +00:17:00,200 --> 00:17:02,070 +kind of advanced, you almost never need those. +这些高级的 Segue,而且基本上你也不会用到 + +434 +00:17:03,140 --> 00:17:04,870 +So there's four basic segues. +所以,有四种基本的 Segues + +435 +00:17:04,870 --> 00:17:07,210 +There's show segue, okay? +Show Segue + +436 +00:17:07,210 --> 00:17:11,640 +Which basically shows the MVC that you're talking about, and +简而言之,就是展示你正在交互的那个 MVC + +437 +00:17:11,650 --> 00:17:14,210 +if you're a Navigation Controller, it will show it +假如你是一个 Navigation Controller,它会将那个 MVC + +438 +00:17:14,210 --> 00:17:16,880 +on the, it'll put it on top of the stack of cards. +放置于栈顶并显示它 + +439 +00:17:16,880 --> 00:17:18,980 +If you're not in a Navigation Controller, +假如你不是一个 Navigation Controller + +440 +00:17:18,980 --> 00:17:20,780 +then it will show it modally. +那么它会 Modally 展示这个 MVC + +441 +00:17:20,790 --> 00:17:24,220 +Okay, so now, modal presentation of an MVC, +下一个是 Modal 展示一个 MVC + +442 +00:17:24,220 --> 00:17:26,060 +we haven't talked about that with all these other things, +我们目前还没有在其他的地方讲到过 + +443 +00:17:26,060 --> 00:17:28,620 +but basically it just takes over the entire screen. +但是,基本上它就是会布满整个屏幕空间 + +444 +00:17:28,630 --> 00:17:30,030 +Okay? Just completely takes over the +只是将你想要展示的 MVC + +445 +00:17:30,030 --> 00:17:34,500 +entire screen, puts the MVC that you wanna show on screen. +完全布满整个屏幕空间 + +446 +00:17:34,500 --> 00:17:37,230 +So it's very kind of disruptive to +可能对于用户,这会有一点点混乱 + +447 +00:17:37,230 --> 00:17:40,300 +the user a little bit, because their app is stuck, +因为他们的 App 卡住了 + +448 +00:17:40,300 --> 00:17:43,300 +it can only do what this MVC is asking them to do. +App 只能做 MVC 要求做的操作 + +449 +00:17:43,310 --> 00:17:45,940 +So I kind of recommend against using modal, and +因此我不太推荐使用 Modal + +450 +00:17:45,940 --> 00:17:48,910 +trying to keep your apps from doing that. +尽量不要在你的 App 中用到它 + +451 +00:17:48,910 --> 00:17:50,110 +So if you're using a Show Segue, +所以当你使用一个 Show Segue 的时候 + +452 +00:17:50,110 --> 00:17:52,510 +you probably wanna be in a Navigation Controller, so +你大概想在 Navigation Controller 中使用到 + +453 +00:17:52,510 --> 00:17:53,950 +that it will slide it on deck. +因为这样的话会有一个滑入的效果 + +454 +00:17:53,950 --> 00:17:55,980 +Because, then the user can always go back, +而且,用户总是可以返回 + +455 +00:17:55,980 --> 00:17:58,380 +if they didn't mean that, they can go back. +假如用户误操作返回的话,还可以再回去 + +456 +00:17:58,390 --> 00:18:02,190 +Then there is Show Detail Segue, very similar to Show, +接下来的是 Show Detail Segue,和 Show Segue 非常相似 + +457 +00:18:02,190 --> 00:18:05,360 +the only difference with Show Detail is that if +唯一的区别就是,Show Detail Segue + +458 +00:18:05,360 --> 00:18:08,360 +you happen to be in a Split View Controller it +在 Split View Controller 中的效果就是 + +459 +00:18:08,360 --> 00:18:11,160 +will show this MVC as the Detail, okay? +在 Detail 中显示这个 MVC,明白了吗? + +460 +00:18:11,160 --> 00:18:13,160 +Otherwise if you are in Navigation Controller, but +否则,如果你在一个 Navigation Controller 中 + +461 +00:18:13,170 --> 00:18:14,960 +not in a Split View Controller it just pushes it +而不是在 Split View Controller 中,这个效果就是 + +462 +00:18:14,970 --> 00:18:16,670 +on the stack just like Show would, okay? +在栈上 push 这个 MVC,和 Show Segue 一样的滑入效果,明白了吗? + +463 +00:18:18,540 --> 00:18:20,470 +So, Show Detail tiny difference there. +所以,和 Show Segue 只有一点点的区别 + +464 +00:18:20,470 --> 00:18:22,370 +It's just about Split View. +只和 Split View 相关 + +465 +00:18:22,370 --> 00:18:24,410 +So, it really helps you when you're in a Split View +所以,如果你在使用 Split View 的时候,这个 Segues 确实很有帮助 + +466 +00:18:24,410 --> 00:18:26,810 +decide whether what you want is the Master to, +帮助你决定,你想要 Master 是什么 + +467 +00:18:26,810 --> 00:18:28,710 +if the Master is in a Navigation Controller, +如果 Master 嵌入 Navigation Controller 的话 + +468 +00:18:28,710 --> 00:18:30,880 +if you want that to slide on the Master? +如果你想要在 Master 上滑入? + +469 +00:18:30,880 --> 00:18:32,410 +The thing you're segueing to or +你 Segue 的目标 View Controller + +470 +00:18:32,410 --> 00:18:33,680 +do you want it to appear in the Detail, okay? +你是否想要它在 Detail 中显示 + +471 +00:18:34,950 --> 00:18:38,180 +Then there's modal which forces this full +接下来是 Modal Segue,它强制 + +472 +00:18:38,190 --> 00:18:40,190 +screen take over type of thing. +整个屏幕被 MVC 接管 + +473 +00:18:40,190 --> 00:18:42,090 +I'm not even gonna talk about that, I'll talk about it +我不打算讨论它 + +474 +00:18:42,090 --> 00:18:43,520 +later in the quarter, but I don't wanna talk about it +我会在这学期晚些时候讲一下,但是我不想过早涉及到 + +475 +00:18:43,520 --> 00:18:47,160 +early because it can be used as a crutch to build UIs. +因为它可以作为构建 UI 的一个支撑 + +476 +00:18:47,160 --> 00:18:49,490 +You really wanna be using Navigation Controllers, and +你肯定会用 Navigation Controller 和 + +477 +00:18:49,500 --> 00:18:50,790 +Split View Controllers to do that. +Split View Controller 来这么做的 + +478 +00:18:51,730 --> 00:18:53,030 +And then a Popover Segue. +接着,Popover Segue + +479 +00:18:53,030 --> 00:18:56,400 +Now a Popover Segue pops the View Controller that you're +Popover Segue 弹出 Segue 的目标 View Controller + +480 +00:18:56,400 --> 00:18:59,700 +segueing to, up into a little window that's on top of +并让这个 View Controller 显示在所有其他东西之上 + +481 +00:18:59,700 --> 00:19:01,400 +everything else, but just a little window instead of +但是并不布满整个屏幕 + +482 +00:19:01,410 --> 00:19:02,640 +taking over the whole screen. +它是一个小的窗口 + +483 +00:19:02,640 --> 00:19:04,240 +But it, really is taking over the whole screen, +但是,实质上它是布满整个屏幕的 + +484 +00:19:04,240 --> 00:19:06,540 +because the user can only interact with what's in +因为用户只能与这个小的 Popover 窗口进行交互 + +485 +00:19:06,540 --> 00:19:09,210 +the little Popover window, if they click anywhere else, +如果用户点击了除窗口以外的其他区域 + +486 +00:19:09,210 --> 00:19:11,350 +it dismisses the Popover window. +就会取消这个 Popover 窗口 + +487 +00:19:11,350 --> 00:19:14,250 +But what makes Popover nicer than just modal is that, +但是 Popover Segue 比 Modal 好的地方在于 + +488 +00:19:14,250 --> 00:19:16,550 +since it doesn't take over the whole screen, you can still +它并不布满整个屏幕 + +489 +00:19:16,550 --> 00:19:19,620 +kind of see grayed out where you came from, and if you +所以你可以让窗口背后你之前的界面显示为灰色 + +490 +00:19:19,620 --> 00:19:22,190 +click where you came from, it puts the Popover away. +当你点击这些灰色的区域,窗口会被弹走 + +491 +00:19:22,190 --> 00:19:25,690 +So the Popover has very easy to cancel, it's very easy for +所以 Popover 很容易取消 + +492 +00:19:25,690 --> 00:19:27,880 +you just to get back to +很容易让用户回到 + +493 +00:19:27,880 --> 00:19:30,060 +where they were if they didn't really mean to click that. +他们之前的界面,如果他们无意中点击到了的话 + +494 +00:19:30,060 --> 00:19:31,500 +Okay, so that's Popovers. +这就是 Popover Segues + +495 +00:19:31,500 --> 00:19:32,930 +So we'll talk over Popovers at the end. +我们会在最后再讲到 Popover + +496 +00:19:32,930 --> 00:19:36,500 +Again I wanna emphasize what it was talking about on +再一次,我想强调的是 + +497 +00:19:36,500 --> 00:19:39,240 +the previous slide Segues of all kinds, +我们在上一页幻灯片中讲到的各种 Segues + +498 +00:19:39,240 --> 00:19:43,810 +no matter what you're doing, Show Detail, Modal or Popover. +无论你在干什么,Show Detail,Modal 或者 Popover + +499 +00:19:43,810 --> 00:19:45,640 +They always create a new MVC. +它们都会创建一个新的 MVC + +500 +00:19:45,640 --> 00:19:49,550 +You're never segueing to an existing MVC anywhere. +你从来不会 Segue 到一个已经存在的 MVC + +501 +00:19:49,550 --> 00:19:51,310 +You're always creating a new one always, +我们总是创建一个新的 + +502 +00:19:51,320 --> 00:19:52,880 +that's what Segues do. +这就是 Segue 所做的事 + +503 +00:19:52,880 --> 00:19:54,550 +Okay, that takes a little bit of +这需要你慢慢去 + +504 +00:19:54,550 --> 00:19:55,780 +getting used to in your mind. +习惯这个概念 + +505 +00:19:55,790 --> 00:19:57,550 +Because of course you see this stack of cards. +因为当你看到卡片堆栈的时候 + +506 +00:19:57,550 --> 00:19:59,890 +Navigation one, and you press back. +跳转到一个,然后你点击返回 + +507 +00:19:59,890 --> 00:20:01,760 +And then you click to go back to where you were. +然后你再点击回到刚才的界面 + +508 +00:20:01,760 --> 00:20:03,420 +And you think you're going back to the same one. +你会认为你回到了原来的那个界面 + +509 +00:20:03,430 --> 00:20:04,690 +But you're not. Because as soon as +但事实并不是这样的。因为当 + +510 +00:20:04,690 --> 00:20:06,960 +that thing comes off the stack, [SOUND] it's gone. +这个 View 从栈中退出时,呼,它就消失了 + +511 +00:20:06,960 --> 00:20:08,360 +Even in Split View. +即便在 Split View 中也是这样的 + +512 +00:20:08,360 --> 00:20:11,500 +You click in the Master it updates your Detail. +点击 Master 界面上的东西,你的 Detail 界面就会更新 + +513 +00:20:11,500 --> 00:20:13,430 +You click again in the Master to update the Detail, +你再次点击 Master 界面的东西来更新 Detail + +514 +00:20:13,430 --> 00:20:15,300 +and the Detail changes and you think oh, +然后 Detail 改变了,然后你会想,噢 + +515 +00:20:15,300 --> 00:20:17,200 +that was the same thing it just got changed. +这和刚刚是一样的东西,只是改变了一点东西 + +516 +00:20:17,200 --> 00:20:19,040 +No the previous one got thrown away and +不是这样的,先前的那个被丢掉了 + +517 +00:20:19,040 --> 00:20:21,140 +new Detail got created, okay? +你看到的是新创建的 Detail 界面 + +518 +00:20:22,070 --> 00:20:23,870 +So Segues always create a new MVC. +因此 Segues 总是创建新的 MVC + +519 +00:20:25,140 --> 00:20:28,180 +All right, so how do we make these Segues happen, okay? +好的,我们怎么实现这些 Segue 呢 + +520 +00:20:28,180 --> 00:20:29,640 +You can do this in code as well, and +你可以用代码来实现 + +521 +00:20:29,650 --> 00:20:32,350 +I'm gonna show briefly how you do this in code. +我也会简单给你们展示一下怎么用代码实现 + +522 +00:20:32,350 --> 00:20:34,580 +But in 90% of the time you're gonna do it +但是百分之九十的情况你都将会 + +523 +00:20:34,580 --> 00:20:36,450 +in a Storyboard with Control drag, +在 Storyboard 中使用 Control 键加拖动来实现 + +524 +00:20:36,450 --> 00:20:39,820 +which is how we create most of the things we do in iOS. +这也是我们在 iOS 中创建东西最常用的方法 + +525 +00:20:39,820 --> 00:20:42,620 +So here's an example of doing it with the Control drag, +下面是一个用 Control 键加拖动来实现 Segue 的例子 + +526 +00:20:43,990 --> 00:20:47,230 +I'm Control dragging from a button in my calculator, so +我按住 Control 然后从按钮拖动到我的计算器 + +527 +00:20:47,230 --> 00:20:48,260 +I added a button. +那么我添加了一个按钮 + +528 +00:20:48,260 --> 00:20:49,600 +The icon is very, very small but +它的图标很小很小 + +529 +00:20:51,870 --> 00:20:53,450 +it actually looks like a little graph. +但是事实上它看起来像一个小图表 + +530 +00:20:53,450 --> 00:20:55,030 +So I'm Control dragging from that in the upper right corner +那么我 Control 拖动,从右上角 + +531 +00:20:55,040 --> 00:20:58,070 +there down to the Detail, because I +拖到 Detail 这个界面 + +532 +00:20:58,070 --> 00:21:01,340 +want when that buttons pressed I want the detail to be +因为我希望当我点击这个按钮时,Detail 界面就能够 + +533 +00:21:01,340 --> 00:21:06,440 +replaced with a new graphing MVC, okay? +被替换为一个新的绘图 MVC + +534 +00:21:06,450 --> 00:21:07,680 +When I let go it that, +当我放开鼠标 + +535 +00:21:07,680 --> 00:21:11,310 +it's gonna say, what kind of Segue do you want? +Xcode 就会问你想要哪一种 Segue + +536 +00:21:11,320 --> 00:21:13,980 +This little black box is gonna appear. +将会弹出这个小小的黑色框框 + +537 +00:21:13,990 --> 00:21:15,420 +And here I'm gonna pick Show Detail, +这里我会选择 Show Detail + +538 +00:21:15,420 --> 00:21:16,650 +because if I'm in a Split View, +因为这是个 Split View + +539 +00:21:16,650 --> 00:21:18,450 +I wanted to replace the Detail. +我想要替代 Detail + +540 +00:21:18,460 --> 00:21:21,160 +If I was in a Navigation Controller only, +如果这是个 Navigation Controller + +541 +00:21:21,160 --> 00:21:23,190 +I probably still would choose Show Detail because that +我也许仍然会选择 Show Detail + +542 +00:21:23,190 --> 00:21:25,030 +also pushes on the stack. +因为这也会把 View 压入栈内 + +543 +00:21:25,030 --> 00:21:27,130 +But if I were the Master in a Split View and +但是如果是 Split View 中的 Master + +544 +00:21:27,130 --> 00:21:28,500 +I didn't want it to do the Detail, +我不希望它是 Detail + +545 +00:21:28,500 --> 00:21:31,260 +I wanted it to actually slide on the stack of the Master, +我希望它存在 Master 的栈中 + +546 +00:21:31,270 --> 00:21:34,070 +cuz the Master could be a stack then I would use Show. +因为 Master 可以是一个栈,这种情况我就会用 Show Segue + +547 +00:21:34,070 --> 00:21:35,700 +All right? + +548 +00:21:35,700 --> 00:21:39,570 +I could also make it a Popover or a Modal here. +我也可以让它以 Popover 或者 Modal 的形式展示 + +549 +00:21:39,570 --> 00:21:42,710 +So I'm gonna pick Show Detail, that's what I want. +这里我选择 Show Detail,这正是我想要的 + +550 +00:21:42,710 --> 00:21:46,840 +And it's gonna make a line appear in the Storyboard. +这将会在 Storyboard 中生成一条连线 + +551 +00:21:46,850 --> 00:21:49,210 +And the middle of the line is a little round circle. +线的中间有个小小的圆圈 + +552 +00:21:49,220 --> 00:21:51,520 +If you click on that and bring up the attribute +如果你点击它,attribute inspector 中就会显示它的属性 + +553 +00:21:51,520 --> 00:21:54,920 +inspector, on the right you'll see that there's a little pop +你将会在右边看到这个下拉框 + +554 +00:21:54,920 --> 00:21:56,750 +up that says what kind of Segue you want. +上面显示你用的是哪种 Segue + +555 +00:21:56,760 --> 00:21:59,660 +We already, we already chose this one to be Show Detail. +我们已经选择了 Show Detail 作为 Segue 的类型 + +556 +00:21:59,660 --> 00:22:02,430 +And there's also a critical field there called Identifier. +这里还有一个重要的区域,叫做 Identifier(标识符) + +557 +00:22:02,430 --> 00:22:04,630 +That's a unique Identifier for +这是你的 Segue 唯一的 Identifier + +558 +00:22:04,630 --> 00:22:07,700 +this segue, and you need this Identifier. +你将会在后面用到这个 Identifier + +559 +00:22:07,700 --> 00:22:10,900 +Let's talk about, why we need this Identifier? +我们来说说为什么需要这个 Identifier + +560 +00:22:10,900 --> 00:22:12,500 +So I'm gonna call this Identifier for +我把这个 Identifier + +561 +00:22:12,500 --> 00:22:14,820 +this one Show Graph. +叫做 Show Graph + +562 +00:22:14,820 --> 00:22:17,140 +And you should usually, call the Segue something that +一般来说你应该把 Segue 命名为 + +563 +00:22:17,140 --> 00:22:20,370 +is probably a verb phrase that says what this segue does. +一个动词短语,这个名字能够告诉别人这个 Segue 是用来做什么的 + +564 +00:22:20,380 --> 00:22:21,980 +So this Segue when you're pressing the button it +这里的这个 Segue 是当你按下那个按钮时 + +565 +00:22:21,980 --> 00:22:25,850 +shows a graph so I'm gonna call it Show Graph, okay? +它显示出一个图标,所以我就叫它为 Show Graph + +566 +00:22:25,850 --> 00:22:27,210 +So just type that in there. +把名字输入进去就好了 + +567 +00:22:27,220 --> 00:22:29,680 +So, I told you before that everything in the Storyboard +我曾经说过,Storyboard 里的所有东西 + +568 +00:22:29,680 --> 00:22:32,320 +is linked up with what's in your code by name. +都是通过名字来和你的代码连接在一起的 + +569 +00:22:32,320 --> 00:22:33,720 +Whether it's the class of View Controller. +不管是 ViewController 的 class + +570 +00:22:33,720 --> 00:22:35,090 +Class of of UI view. +或者是 UIView 的 class + +571 +00:22:35,090 --> 00:22:36,150 +Name of an outlet. +outlet 的名字 + +572 +00:22:36,160 --> 00:22:37,250 +Name of an action. +action 的名字 + +573 +00:22:37,260 --> 00:22:38,870 +Name of a Segue which is +Segue 的名字 + +574 +00:22:38,870 --> 00:22:40,490 +basically what the Identifier of a segue is. +这里说的就是 Segue 的 Identifier + +575 +00:22:40,490 --> 00:22:41,930 +They're all just names, and +它们通通都只是名字而已 + +576 +00:22:41,930 --> 00:22:44,060 +we have to make the names the same in our code. +我们需要让代码中的名字和 Storyboard 中的名字一致 + +577 +00:22:44,060 --> 00:22:46,700 +So it's a loose coupling to make those two +这是一种松散耦合,能让两个 + +578 +00:22:46,700 --> 00:22:48,630 +things work together. +东西连接在一起 + +579 +00:22:48,630 --> 00:22:50,570 +So, we'll have to reference this name in our code. +因此我们需要让我们的代码和这个名字关联起来 + +580 +00:22:51,870 --> 00:22:54,040 +Okay, so where, where are we gonna use that Identifier? +好的,那我们在哪里用到这个 Identifier 呢 + +581 +00:22:54,040 --> 00:22:57,740 +Well, one way we can do it, only the 10% case I said, +其中一种方法,很少用到,可能只有 10% 的情况 + +582 +00:22:57,740 --> 00:23:00,640 +is to cause a Segue to happen from code. +就是在代码中触发这个 Segue + +583 +00:23:00,640 --> 00:23:02,690 +And you do that with +你会用 + +584 +00:23:02,690 --> 00:23:04,740 +UIViewController method performSequeWithIdentifier. +UIViewController 的一个方法,叫 performSequeWithIdentifier + +585 +00:23:04,750 --> 00:23:06,480 +And you just specify that Identifier, and +你只要在里面用了这个 Identifier, + +586 +00:23:06,480 --> 00:23:08,010 +it's gonna make that Segue happen, okay? +就能触发这个 Segue + +587 +00:23:09,620 --> 00:23:10,880 +Simple as that, +很简单 + +588 +00:23:10,890 --> 00:23:12,180 +so I am not gonna talk about this, +所以我不会讲这个的, + +589 +00:23:12,190 --> 00:23:14,120 +because you're not gonna be doing this one, +因为你们不会用这个, + +590 +00:23:14,120 --> 00:23:15,990 +probably in this class, maybe in your final project, +也许在这节课不会用,也许你们的最后的项目会用到 + +591 +00:23:15,990 --> 00:23:17,560 +you might find a reason to do it. +你也许能找到一个用它的理由 + +592 +00:23:18,890 --> 00:23:21,730 +But the number one reason to have the Identifier in there +但是使用 Identifier 最主要的理由 + +593 +00:23:21,730 --> 00:23:23,460 +and the main thing that it's used for +也是最主要用到的地方 + +594 +00:23:23,460 --> 00:23:27,730 +is to prepare a Segue, because when that segue happens, +是准备一个 Segue,因为当这些 Segue 被触发 + +595 +00:23:27,730 --> 00:23:32,000 +it creates a new MVC, that new MVC was just born. +它会创建一个新的 MVC,这个 MVC 刚来到这个世界 + +596 +00:23:32,000 --> 00:23:34,570 +It needs to be prepared to do what it wants to do. +它需要一些准备才能做你想让它做的事情 + +597 +00:23:34,570 --> 00:23:36,760 +So for example, +举例说明 + +598 +00:23:36,760 --> 00:23:38,940 +in the calculator case, when I Segue to a graphing MVC, +在计算器的例子中,当我 Segue 到一个绘图 MVC + +599 +00:23:39,880 --> 00:23:41,680 +it's just a blank graphing MVC. +它只是一个空白的绘图 MVC + +600 +00:23:41,680 --> 00:23:43,340 +I have to tell it what to graph. +我需要告诉它画什么 + +601 +00:23:43,350 --> 00:23:46,150 +I have to prepare it basically, okay? +我需要为它准备最基本的东西 + +602 +00:23:46,150 --> 00:23:48,150 +So, that's the number one thing, preparing. +所以这是最重要的,准备 + +603 +00:23:48,150 --> 00:23:50,120 +So how does preparing work? +怎么做这个准备工作呢 + +604 +00:23:50,120 --> 00:23:52,080 +Preparing very simple. +准备很简单的 + +605 +00:23:52,090 --> 00:23:55,690 +The MVC that contains the instigator of this segue. +MVC 包含着一个 segue 的发起者 + +606 +00:23:55,690 --> 00:23:58,820 +Like the button, or whatever's causing it to segue. +比如按钮,或者任何能够触发 segue 的东西 + +607 +00:23:58,830 --> 00:24:01,990 +That MVC implements a method called, prepareForSegue. +MVC 实现了一个方法,叫做 prepareForeSegue + +608 +00:24:02,000 --> 00:24:05,200 +And inside, it gets the MVC that was just created, and +在里面,它存着刚刚创建出来的 MVC, + +609 +00:24:05,200 --> 00:24:06,960 +it has to prepare it. +它需要为这个 MVC 做准备 + +610 +00:24:06,970 --> 00:24:09,430 +So let's talk about what that code looks like, +接着我们来说说这个 prepareForSegue + +611 +00:24:09,440 --> 00:24:11,200 +prepareForSegue. +里面的代码长什么样子 + +612 +00:24:11,200 --> 00:24:12,740 +It takes two arguments, okay? +它有两个参数 + +613 +00:24:12,740 --> 00:24:14,940 +The first one is the segue. +第一个就是 segue + +614 +00:24:14,940 --> 00:24:16,840 +That's UIStoryboardSegue instance and +UIStoryboardSegue 的实例 + +615 +00:24:16,840 --> 00:24:18,910 +it really has two important things in there. +这个实例里有两个相当重要的东西 + +616 +00:24:18,910 --> 00:24:20,480 +One is the Identifier, so +一个是 Identifier + +617 +00:24:20,480 --> 00:24:22,310 +you know which segue you're preparing. +这能让你知道你在准备哪一个 segue + +618 +00:24:22,310 --> 00:24:24,200 +And two is, +第二个是 + +619 +00:24:24,200 --> 00:24:26,080 +the MVC that it just created that you're going to segue to, +这个 segue 发生时新建的那个 MVC + +620 +00:24:26,080 --> 00:24:28,780 +which is called the destinationViewController. +名字叫 destinationViewController + +621 +00:24:28,780 --> 00:24:30,150 +It has a second argument there, +第二个参数是 + +622 +00:24:30,150 --> 00:24:33,220 +which is sender, that's just the UIButton or +叫做 sender 的,这就是比如说我们这里的 UIButton + +623 +00:24:33,220 --> 00:24:36,120 +whatever that caused the segue to happen. +或者触发这个 segue 的东西 + +624 +00:24:36,120 --> 00:24:38,220 +You don't usually need to look at that but sometimes. +一般来说你不需要经常用到这个参数 + +625 +00:24:38,230 --> 00:24:40,560 +We'll see later in the quarter when we wanna look at that. +这学期后面一点我们将会用到它的,到那时我们再看看它 + +626 +00:24:40,560 --> 00:24:42,590 +But that's all it is, +这就是它的全部了 + +627 +00:24:42,600 --> 00:24:44,630 +it's just what object caused the segue to happen. +它就是一个触发 segue 的对象 + +628 +00:24:45,730 --> 00:24:48,000 +So we're gonna look at that segue identifier. +我们来看一看这个 segue 的 Identifier + +629 +00:24:48,000 --> 00:24:49,770 +It's just a property, segue.identifier. +它只是一个 segue 的属性,通过 segue.identifier 来访问 + +630 +00:24:49,770 --> 00:24:52,240 +It could be nil, because you might not have set it. +它可能是 nil 值,因为你可能没有给它赋值 + +631 +00:24:52,240 --> 00:24:54,670 +And so you wanna check if it's nil here, so +所以你需要去检查一下它是不是 nil + +632 +00:24:54,670 --> 00:24:57,710 +here I am doing "if let" to check if that thing is nil. +所以这里我做解包,用 if let 来检查一下它是不是 nil + +633 +00:24:57,710 --> 00:25:00,410 +Then I'm just gonna switch on it, okay? +接着我只需要用 switch 来区分 + +634 +00:25:00,410 --> 00:25:03,080 +And I'm gonna look for Show Graph, and +我需要的是 Show Graph + +635 +00:25:03,080 --> 00:25:06,750 +once I know that, I'm preparing to show a graph, +一旦我知道了是哪一个,我就需要准备显示图表了 + +636 +00:25:06,750 --> 00:25:08,920 +then I can say, give me the MVC, +我可以告诉它,把 MVC 给我 + +637 +00:25:08,920 --> 00:25:12,450 +that graphing calculator MVC that you just made. +这个 MVC 是你刚刚新建的用来画图表的 MVC + +638 +00:25:12,460 --> 00:25:15,220 +Now, the thing is segue.destinationViewController, +现在,这个 MVC 就是 segue.destinationViewController + +639 +00:25:15,220 --> 00:25:16,960 +that property is anyObject. +这个属性是一个 anyObject + +640 +00:25:18,230 --> 00:25:21,590 +Okay, so you have to use as to turn it into +你需要把这个 anyObject 变成 + +641 +00:25:21,600 --> 00:25:24,460 +the right class of the MVC you just create. +你刚刚创建的 MVC 的类 + +642 +00:25:24,470 --> 00:25:26,070 +Now in the case here, +在这个例子中 + +643 +00:25:26,070 --> 00:25:28,630 +I created a calculator graph View Controller, +我创建了一个计算器画图的 View Controller + +644 +00:25:28,640 --> 00:25:30,940 +I've abbreviated here calcGraphViewController, +我缩写成 calcGraphViewController + +645 +00:25:30,940 --> 00:25:33,200 +although you shouldn't do that in your homework, okay? +尽管如此,你不该在你的作业中这么写 + +646 +00:25:33,210 --> 00:25:34,970 +It's just that it wouldn't fit on the slide here, +我这么写是因为如果不缩写就太长了,ppt单行容纳不下 + +647 +00:25:34,970 --> 00:25:37,440 +so CalculatorGraphViewControllers are on, +所以 CalculatorGraphViewControllers 是 + +648 +00:25:37,440 --> 00:25:38,640 +turning that destinationViewController +把 destinationView 变成 + +649 +00:25:38,640 --> 00:25:40,610 +into a CalculatorGraphViewController, and +一个 CalculatorGraphViewController + +650 +00:25:40,610 --> 00:25:42,410 +if I can't do it, well then I can't prepare it. +如果我不能把它变成 CalculatorGraphViewController,那我就不能准备它了 + +651 +00:25:42,410 --> 00:25:44,310 +So, I'm just gonna do if let there. +所以我这里用 if let 来解包 + +652 +00:25:45,450 --> 00:25:50,390 +So if I can, then I'm just going to call methods and set +如果我能够解包,也就是不是 nil 值,那我就可以在 + +653 +00:25:50,390 --> 00:25:54,620 +properties in that CalculatorGraphViewController, that +CalculatorGraphViewController 中调用方法和设定属性的值 + +654 +00:25:54,620 --> 00:25:58,830 +are needed to prepare that thing to come onscreen, okay? +这样就可以准备展现在屏幕上的东西了 + +655 +00:25:58,830 --> 00:26:01,060 +So again in this case I +再一次在这个例子中 + +656 +00:26:01,060 --> 00:26:03,300 +would probably tell it what I wanted it to graph here. +我很可能会告诉它我想要画什么 + +657 +00:26:03,300 --> 00:26:06,270 +Okay, maybe I would set it to color, or something else. +也许我会设定它的颜色之类的 + +658 +00:26:06,270 --> 00:26:09,670 +The scale, or I don't know whatever we wanted to set here +或者缩放大小,或者一些其他的东西 + +659 +00:26:09,670 --> 00:26:12,240 +we can do, okay? +我们都能这么做 + +660 +00:26:12,240 --> 00:26:15,540 +Now, I don't put a lot of red on my slides. +一般来说,我不会在我的幻灯片中放红色的东西 + +661 +00:26:15,540 --> 00:26:18,040 +And when I do, you really should pay attention, okay? +如果我放了,那你就真的要认真看一看了 + +662 +00:26:18,050 --> 00:26:20,080 +Very important thing to understand, +需要理解的很重要很重要的东西 + +663 +00:26:20,080 --> 00:26:23,150 +is when you are preparing that newly created MVC, +就是当你在准备新创建的 MVC 的时候 + +664 +00:26:24,220 --> 00:26:26,620 +it's outlets have not been set. +它的 outlet 还没被设定 + +665 +00:26:28,290 --> 00:26:30,170 +Remember outlets are these +记得这些 outlet 是 + +666 +00:26:30,170 --> 00:26:32,050 +implicitly unwrapped optionals, we are always kind +隐性解包的 optional,一般来说 + +667 +00:26:32,060 --> 00:26:33,890 +of expecting them to have been set. +它们都是被设定值的 + +668 +00:26:33,890 --> 00:26:36,320 +Well, this is one case where that's not true. +但是这个情况例外 + +669 +00:26:36,330 --> 00:26:39,060 +When you're preparing your MVC, it's outlets are not yet +当你正在准备你的 MVC 的时候,它的 outlet 还没 + +670 +00:26:39,060 --> 00:26:40,860 +set, okay? +被设定 + +671 +00:26:40,860 --> 00:26:44,800 +That can cause crashers, that can cause you to unexpected +这会让你的程序崩了,也可能会产生一些意想不到的 + +672 +00:26:44,800 --> 00:26:48,400 +behavior, because you set something in preparing it and +行为,因为你在准备的时候设定了一些东西 + +673 +00:26:48,400 --> 00:26:51,570 +you're expecting something in the view to have been set, but +你希望设定的东西是已经设定过的了,但是 + +674 +00:26:51,570 --> 00:26:54,470 +it didn't happen because the outlet is just not set yet. +它没发生,因为这些 outlet 还么被赋值 + +675 +00:26:54,480 --> 00:26:57,640 +So you have to take whatever the preparation is and hold +所以你需要把你的关于这些 oulet 的准备工作暂时存到一个地方 + +676 +00:26:57,650 --> 00:27:01,250 +onto it, and then later on when the outlet does get set, +当这些 outlet 被赋值了以后 + +677 +00:27:01,250 --> 00:27:04,780 +maybe in the property observer of that outlet, you can load +也许在 outlet 中的 property observer,你可以把 + +678 +00:27:04,790 --> 00:27:08,390 +up the information that you're prepared with here, okay? +刚刚准备的那些信息读取然后再设定 + +679 +00:27:08,390 --> 00:27:09,290 +I'll see that in the demo. +一会展示给你们看 + +680 +00:27:09,290 --> 00:27:10,890 +I've made my demo +我已经故意让我的展示 + +681 +00:27:10,890 --> 00:27:12,490 +intentionally crash because of this. +因为这个而崩溃了 + +682 +00:27:12,490 --> 00:27:14,890 +And we'll go back and look at why that happens, okay? +我们会看看为什么会这样 + +683 +00:27:14,890 --> 00:27:18,960 +But this is red, pay attention, you know, +这个是红色的,请注意,你知道 + +684 +00:27:18,960 --> 00:27:20,630 +if your segue doesn't work the first time, +如果你的 segue 一开始没正常工作 + +685 +00:27:20,630 --> 00:27:23,200 +it might well be because you're expecting outlets to +有可能是因为你以为 outlet 在 + +686 +00:27:23,200 --> 00:27:29,340 +be set when your MVC is being prepared, okay? +准备的时候已经赋值了 + +687 +00:27:29,340 --> 00:27:30,740 +So that's preparing for a segue. +这就是准备 segue + +688 +00:27:30,740 --> 00:27:33,140 +You can also prevent a segue from happening. +你也可以防止一个 segue 的触发 + +689 +00:27:33,140 --> 00:27:34,540 +If there's some reason it doesn't make sense for +如果有些原因让 segue 的发生不合理 + +690 +00:27:34,540 --> 00:27:36,710 +that segue to happen, you could just disable the button, +你直接可以禁用那个按钮 + +691 +00:27:36,710 --> 00:27:39,950 +but if you didn't wanna disable the button you could +不过如果你不想禁用按钮的话,你希望能够 + +692 +00:27:39,950 --> 00:27:41,920 +click the button. +点击那个按钮 + +693 +00:27:41,920 --> 00:27:43,880 +And what'll happen here is your UIViewController will be +这时候你的 UIViewController 会被问到 + +694 +00:27:43,890 --> 00:27:47,220 +asked, should I perform this segue with Identifier? +我应该执行这个 Identifier 的 segue 吗 + +695 +00:27:47,220 --> 00:27:49,290 +It'll pass you the Identifier and the sender. +它会把 Identifier 和 sender 传给你 + +696 +00:27:49,290 --> 00:27:51,060 +And you can just return, false. +然后你可以返回 false + +697 +00:27:51,060 --> 00:27:53,960 +And then it won't do that segue. +那么它就不会执行 segue 了 + +698 +00:27:53,960 --> 00:27:56,150 +It won't crash or anything. +这样做所有东西都不会崩 + +699 +00:27:56,150 --> 00:27:58,330 +It just, you know, touch the button, it does nothing. +它只是,当你按这个按钮,它什么都不会触发 + +700 +00:27:58,330 --> 00:28:01,430 +'Kay, so you can control your segues kind of +所以你可以某种意义上 + +701 +00:28:01,440 --> 00:28:05,440 +programmatically as well like that.Okay? +用代码来控制你的 segue 了 + +703 +00:28:05,440 --> 00:28:07,200 +So, demo time here. +那么,演示时间开始 + +704 +00:28:07,210 --> 00:28:09,770 +We're gonna demonstrate all of this. +我们将要演示刚刚说的那些 + +705 +00:28:09,780 --> 00:28:13,680 +And I'm gonna do this demonstration by creating +为了演示这些,我将会创建一个 + +706 +00:28:13,680 --> 00:28:18,450 +completely new application called Psychologist. +完全新的应用,叫 Psychologist + +707 +00:28:18,450 --> 00:28:21,420 +Okay, so, let's go over here. +那么我们开始吧 + +708 +00:28:22,750 --> 00:28:24,420 +So I'm going to Xcode. +我将要打开 Xcode + +709 +00:28:24,420 --> 00:28:25,690 +And here's Happiness and Calculator. +这里是 Happiness 和 Calculator 项目 + +710 +00:28:25,690 --> 00:28:27,890 +But I'm gonna create a new project here. +但是我将要创建一个新的项目 + +711 +00:28:27,890 --> 00:28:33,190 +I'm gonna call it psychologist, Psychologist. +我将其命名为 Psychologist + +712 +00:28:33,190 --> 00:28:37,400 +Okay this gonna put it in the same place that +我把它放在和我们前两个项目 + +713 +00:28:37,400 --> 00:28:40,030 +my Calculator and Happiness apps were. +Calculator 和 Happiness 相同的目录下 + +714 +00:28:41,230 --> 00:28:42,750 +Here it is. +创建好了 + +715 +00:28:42,750 --> 00:28:44,270 +I'm gonna move these things out of the way, +我将把这些东西放到 Supporting Files, + +716 +00:28:44,270 --> 00:28:46,470 +like we always do. +就像我们之前做的那样 + +717 +00:28:46,470 --> 00:28:48,670 +The images, the assets, the launch screen so that I +这些 images 啊, assets 啊, LaunchScreen 啊都放进去 + +718 +00:28:48,670 --> 00:28:53,140 +just have my main Storyboard here and this View Controller. +那么外面只剩下 MainStoryboard 和这个 ViewController 了 + +719 +00:28:53,150 --> 00:28:55,810 +And I'm actually gonna rename this View Controller. +事实上我会改一下这个 ViewController 的名字 + +720 +00:28:55,810 --> 00:28:59,080 +I don't like the name generic ViewController. +我不喜欢用这个普通的 ViewController 这个名字 + +721 +00:28:59,080 --> 00:29:00,280 +I even had you change it +我甚至会要求你们也要改 + +722 +00:29:01,220 --> 00:29:02,850 +in the latest homework assignment, because I +在这一次作业中要你们改,因为我 + +723 +00:29:02,850 --> 00:29:04,720 +just don't think that's a very descriptive name. +觉得这不是一个带有描述性的名字 + +724 +00:29:04,720 --> 00:29:07,190 +So, I'm gonna change the name of +于是我把我的 ViewController + +725 +00:29:07,190 --> 00:29:09,660 +my ViewController here to be PsychologistViewController. +的名字改成 PsychologistViewController + +726 +00:29:09,660 --> 00:29:12,090 +So I have to do that in three different places again, +所以我需要改三个地方 + +727 +00:29:12,090 --> 00:29:17,330 +so here I'm gonna say Psychologist. Okay? +这里加上 Psychologist + +729 +00:29:17,330 --> 00:29:19,100 +Here I'm gonna change the name of the file, +这里我更改文件的名字 + +730 +00:29:19,100 --> 00:29:20,900 +to be Psychologist. +加上 Psychologist + +731 +00:29:20,900 --> 00:29:23,640 +That's surprisingly hard to type by the way. +抱怨一下,这挺难打的 + +732 +00:29:23,640 --> 00:29:25,100 +And then in the Storyboard, +接着在 Storyboard 中 + +733 +00:29:25,110 --> 00:29:28,040 +of course, I need to go to the identity inspector here and +当然,我需要在 identity inspector 这里 + +734 +00:29:28,040 --> 00:29:30,640 +change it to be a PsychologistViewController. +修改成 PsychologistViewController + +735 +00:29:31,810 --> 00:29:33,840 +So that's those three steps. +就是这三个地方了 + +736 +00:29:33,850 --> 00:29:35,880 +So now I have this PsychologistViewController. +那么现在我有了这个 PsychologistViewController + +737 +00:29:35,880 --> 00:29:37,280 +What's this Psychologist gonna do? +它需要做什么呢 + +738 +00:29:37,280 --> 00:29:40,650 +Well, he can ask you a question like Psychologists +他可以像一个心理学家一样问你一个 + +739 +00:29:40,650 --> 00:29:41,890 +want to do. +问题 + +740 +00:29:41,890 --> 00:29:43,120 +And you're gonna give an answer. +然后你需要提供一个答案 + +741 +00:29:43,120 --> 00:29:45,450 +And then he's gonna make a diagnosis. +紧接着他将会对此做出判断 + +742 +00:29:45,460 --> 00:29:47,090 +Okay. Based on your answer as to +好了,基于你的回答然后 + +743 +00:29:47,090 --> 00:29:48,690 +how happy you are or not. +判断出你快不快乐 + +744 +00:29:48,690 --> 00:29:51,790 +And then it's gonna use the HappinessViewController, +然后它就会用 HappinessViewController + +745 +00:29:51,800 --> 00:29:55,000 +to show how happy you are, show the diagnosis basically. +来告诉你快不快乐,显示出判断结果 + +746 +00:29:55,000 --> 00:29:56,630 +Okay, so we are gonna use both the +所以我们将会同时 + +747 +00:29:56,630 --> 00:29:58,430 +PsychologistViewController, and +用到 PsychologistViewController + +748 +00:29:58,430 --> 00:30:00,870 +the HappinessViewController from our last app. +和 HappinessViewController,后者是我们上一个 app 中写的 + +749 +00:30:00,870 --> 00:30:03,200 +But let's start with this PsychologistViewController +那么,让我们开始实现这个 PsychologistViewController + +750 +00:30:03,210 --> 00:30:05,270 +here, let's build its UI. +先设计它的 UI + +751 +00:30:05,270 --> 00:30:06,870 +He's going to ask a question, so +他会提问题,所以 + +752 +00:30:06,870 --> 00:30:09,240 +I'm going to bring out a label for the question. +我拖出一个 label 用来显示问题 + +753 +00:30:09,240 --> 00:30:12,010 +He's going to ask the question, +他将会问 + +754 +00:30:12,010 --> 00:30:15,810 +what do you see in your dreams? +你在梦中看到了什么 + +755 +00:30:15,820 --> 00:30:17,700 +That sounds like +这听起来像 + +756 +00:30:17,700 --> 00:30:19,580 +a very psychologisty kind of question. +一个很心理学的问题 + +757 +00:30:19,590 --> 00:30:21,820 +And let's make it bigger font. +让字体变大一点 + +758 +00:30:22,890 --> 00:30:25,690 +Maybe like, 36 point or something like that. +大概 36 point 上下 + +759 +00:30:27,430 --> 00:30:31,190 +We can make it larger here. +让文本框也大一点 + +760 +00:30:32,900 --> 00:30:36,060 +Let's center it, make this text centered. +让文本居中 + +761 +00:30:36,070 --> 00:30:38,070 +Let's try to put it in a nice place, okay? +我们试着把它放到一个好的位置 + +762 +00:30:38,070 --> 00:30:40,370 +Let's use our blue lines to put it somewhere here. +用这些蓝线条来对齐 + +763 +00:30:40,370 --> 00:30:43,440 +Let's put it like that, so it's nice. +这么放就挺好的 + +764 +00:30:43,440 --> 00:30:46,970 +And put it in a good place. +让它呆在一个好的位置 + +765 +00:30:46,980 --> 00:30:48,170 +Let's try. +尝试一下 + +766 +00:30:48,180 --> 00:30:49,740 +I'm going to show you a little bit of +我每节课都尝试给你们传授一点 + +767 +00:30:49,740 --> 00:30:51,040 +Auto Layout every lecture. +关于 Auto Layout 的秘籍 + +768 +00:30:51,050 --> 00:30:53,110 +Just show you kind of things you can do. +展示一下你们可以怎么做 + +769 +00:30:53,110 --> 00:30:55,110 +So let's try and see if we can. +那我们一起试试看能不能这么做 + +770 +00:30:55,120 --> 00:30:57,180 +We put this all on blue lines up here. +我们把它全按照蓝线来放 + +771 +00:30:57,180 --> 00:30:58,780 +Right. +好的 + +772 +00:30:58,780 --> 00:31:00,380 +So let's see if we can request, or have it +接着来看看我们能否让它用这个 + +773 +00:31:00,390 --> 00:31:03,390 +Reset to Suggested Constraints and see if it'll work, okay? +Reset to Suggested Constraints,然后看看行不行 + +774 +00:31:03,390 --> 00:31:05,620 +So here I'm, this is for the Selected View. +这里是给选中的 View 的 + +775 +00:31:05,620 --> 00:31:07,260 +To select this view. +选中这个view + +776 +00:31:07,260 --> 00:31:10,830 +I'm gonna go reset to Suggested Constraints. +我将要设置 reset to Suggested Constraints + +777 +00:31:10,830 --> 00:31:11,730 +Now, let's see what happened. +现在看看发生了什么 + +778 +00:31:11,730 --> 00:31:12,560 +Now, this doesn't look good. +这并不好 + +779 +00:31:12,560 --> 00:31:14,430 +I don't like this, +我不喜欢这个 + +780 +00:31:14,430 --> 00:31:16,300 +cuz I really don't want this thing attached to the bottom. +因为我真的不想这个东西和 view 的底部有关系 + +781 +00:31:16,300 --> 00:31:19,000 +But the real place, a good place to look for +但是一个能看到我们约束的地方是 + +782 +00:31:19,000 --> 00:31:22,570 +the constraints is over here again in Size Inspector. +这里的 Size Inspector + +783 +00:31:22,570 --> 00:31:24,000 +If you look down at the bottom, +如果你看下去 + +784 +00:31:24,010 --> 00:31:26,970 +you can see all the constraints that that reset to +你能看到所有的约束 + +785 +00:31:26,980 --> 00:31:28,810 +Suggested Constraints did. +这些都是 reset to Suggested Constraints 生成的 + +786 +00:31:28,810 --> 00:31:32,680 +And I'd like this one, and I like that one. +我喜欢这个,也喜欢那个 + +787 +00:31:32,680 --> 00:31:33,810 +And I like that one. +还有这个也是 + +788 +00:31:33,810 --> 00:31:35,010 +But I don't like that one. +但是我不喜欢那个 + +789 +00:31:35,020 --> 00:31:36,350 +So I can just click on it and +所以我可以点击它 + +790 +00:31:36,350 --> 00:31:37,880 +hit delete, and get rid of that. +然后按 delete 键,就把它删了 + +791 +00:31:37,880 --> 00:31:39,350 +Now as soon as I did that, +当我删掉它以后 + +792 +00:31:39,350 --> 00:31:42,120 +of course I got the yellow cuz it's misplaced. +我就会得到了这些黄色的线因为它没有足够的约束了 + +793 +00:31:42,120 --> 00:31:43,390 +So I'm gonna go back and +所以我需要回到这里 + +794 +00:31:43,390 --> 00:31:46,290 +do what we did all the way, way back in lecture one, +然后做我们在第一课里面做过的动作 + +795 +00:31:46,290 --> 00:31:49,460 +which I'm gonna update this frame, fix the misplacement. +更新这个 frame,修正这个位置的问题 + +796 +00:31:49,460 --> 00:31:50,660 +No issues. +没问题了 + +797 +00:31:50,660 --> 00:31:52,360 +Boom. I've got this where I want it. +咔的一下,我得到了我向要得结果 + +798 +00:31:52,360 --> 00:31:55,800 +Okay, so that's another way to use auto layout there. +所以这是另一个用 autolayout 的方法 + +799 +00:31:56,970 --> 00:31:58,230 +Alright, so let's get the answers out. +好的,接着把答案给拖出来 + +800 +00:31:58,230 --> 00:31:59,500 +Here's our question. +这里是我们的问题 + +801 +00:31:59,500 --> 00:32:00,770 +Let's grab our answers out here. +现在把答案抓出来 + +802 +00:32:00,770 --> 00:32:05,670 +So let's, maybe I see a dancing tree, okay? +所以,也许我在这里输入“我看到一棵会跳舞的树” + +803 +00:32:05,670 --> 00:32:07,710 +If I see a dancing tree in my dream, +如果我想象看到一棵会跳舞的树 + +804 +00:32:07,710 --> 00:32:09,840 +let's make this font bigger again on this one too. +先让我把字体调大一点点 + +805 +00:32:11,550 --> 00:32:14,550 +If I see a dancing tree in my dreams I'm probably gonna be +如果我想象看到一棵会跳舞的树,我想我应该会 + +806 +00:32:14,550 --> 00:32:16,280 +pretty happy I think. +挺开心的 + +807 +00:32:16,280 --> 00:32:18,580 +So let's try and put this one where it should be. +尝试把它放在它该在的地方 + +808 +00:32:18,590 --> 00:32:20,350 +So I'm gonna try and +所以我尝试把它放在 + +809 +00:32:20,350 --> 00:32:22,120 +put this one right in the center of my view. +我的 view 的正中间 + +810 +00:32:22,120 --> 00:32:25,090 +So again, let's try and reset the suggested constraints and +再一次,试一下用 Reset to the Suggest Constraint + +811 +00:32:25,090 --> 00:32:26,320 +see if that works. +看这行不行 + +812 +00:32:26,330 --> 00:32:28,220 +Okay well that looks bad too. +好吧这个也不太行 + +813 +00:32:28,230 --> 00:32:29,690 +So let's go look over and see what it did. +所以我们看看它做了些什么 + +814 +00:32:31,600 --> 00:32:34,100 +Alright, well, it aligns center to the super view. +啊好的它在父类 view 中居中了 + +815 +00:32:34,100 --> 00:32:35,260 +That looks good. +这看起来不错 + +816 +00:32:35,270 --> 00:32:39,170 +But it aligned the X up with this thing up here and +但是它和 X 轴的上面对齐 + +817 +00:32:39,170 --> 00:32:40,940 +I don't really want that, so I'm gonna delete that. +我并不想要这样,所以我删掉它 + +818 +00:32:40,940 --> 00:32:43,470 +The bottom space, I definitely don't want that. +离底部的距离,我肯定也不想要这个 + +819 +00:32:43,470 --> 00:32:45,270 +And it fixed the width. +还有固定了它的宽度 + +820 +00:32:45,270 --> 00:32:46,870 +I definitely don't want the width fixed. +我肯定不想要宽度是固定的 + +821 +00:32:46,880 --> 00:32:50,140 +I want the width to match whatever the size of +我希望宽度随着里面的内容变化 + +822 +00:32:50,150 --> 00:32:51,480 +this thing is. +而变化 + +823 +00:32:51,480 --> 00:32:52,810 +So, kinda got most things here. +看起来做了很多东西 + +824 +00:32:52,810 --> 00:32:55,780 +But I really don't have a vertical position or +但是我并不想设定这个东西的 + +825 +00:32:55,780 --> 00:32:58,150 +horizontal position of this thing set. +垂直位置和水平位置 + +826 +00:32:58,150 --> 00:33:00,690 +So I'm gonna use another one down here. +所以我需要用这下面的另一个按钮 + +827 +00:33:00,690 --> 00:33:02,150 +This is the alignment one. +这就是 alignment 的这个按钮 + +828 +00:33:02,160 --> 00:33:05,260 +And I'm gonna go down here and say, I want the alignment, +然后我在最下面,我希望这个对齐 + +829 +00:33:05,260 --> 00:33:10,590 +the horizontal and vertical centers to be lined up. +到水平中心和垂直中心 + +830 +00:33:10,600 --> 00:33:15,030 +So I really already got the vertical center right there. +所以我已经在有垂直中心的这个约束了 + +831 +00:33:15,030 --> 00:33:16,400 +So I just do horizontal center, so +我只需要再加一个水平中心的就可以了 + +832 +00:33:16,400 --> 00:33:17,770 +I'll add that constraint. +那么我就添加了这个约束 + +833 +00:33:17,770 --> 00:33:20,370 +So now I've got these two things lined up, +所以现在我有这两个约束来对齐 + +834 +00:33:20,370 --> 00:33:21,870 +that looks like what I want. +这看起来就是我想要的 + +835 +00:33:21,870 --> 00:33:25,910 +Again, it's a little off this placement probably size is +再一次,这有一点点和放置的位置或者大小不一样 + +836 +00:33:25,910 --> 00:33:28,710 +not quite right, we'll put that right. +我们把它放到正确地位置 + +837 +00:33:28,710 --> 00:33:32,850 +And boom, now we've got this tree in the middle.Okay. +然后我们就让这个树居中了 + +839 +00:33:32,850 --> 00:33:34,450 +So let's add some more answers. I'm just going +接下来我们再添加多几个答案,我只要 + +840 +00:33:34,450 --> 00:33:36,050 +to copy and paste because I like this fun combination. +复制和粘贴就行了,因为我喜欢这个有趣的组合 + +841 +00:33:36,050 --> 00:33:40,790 +Let's say you dream of a dirty Golden, no not dirty, +比如说你想象一个肮脏的黄金,不不是肮脏 + +842 +00:33:40,790 --> 00:33:43,790 +we'll just say, a Golden Bear. +我们说,一个金色的熊 + +843 +00:33:43,790 --> 00:33:45,960 +[NOISE] Okay so let's say the Golden Bear somehow shows up +好吧这头金色的熊无意中出现 + +844 +00:33:45,960 --> 00:33:46,590 +in your dreams. +在你的想象里 + +845 +00:33:46,590 --> 00:33:50,030 +Doesn't sound very good. +听起来不太好 + +846 +00:33:50,030 --> 00:33:51,100 +So there's that. +就这样啦 + +847 +00:33:51,100 --> 00:33:54,100 +And this one, let's see if we +这个呢,我们看一下我们 + +848 +00:33:54,100 --> 00:33:56,870 +can do suggested constraints with this one. +能不能用推荐的约束 + +849 +00:33:58,270 --> 00:34:00,700 +Okay, we do that. Now this one looks good. +好的我们点击。哦!这看起来不错 + +850 +00:34:00,710 --> 00:34:04,240 +It's got the bottom space and the center. +它有底部距离,还有居中 + +851 +00:34:04,240 --> 00:34:05,110 +Looks good, okay? +看起来不错 + +852 +00:34:05,110 --> 00:34:06,470 +So we're rocking with that one. +所以我们就搞掂了这个了 + +853 +00:34:06,480 --> 00:34:07,610 +No need to do anything. +这个啥都不用做了 + +854 +00:34:07,610 --> 00:34:08,540 +Let's do another one. +来加另一个 + +855 +00:34:09,680 --> 00:34:12,550 +Buckeye, I'm not even sure what that is, but +加一个“七叶树”,我不太确定这是什么,但是 + +856 +00:34:12,550 --> 00:34:14,080 +we'll put that in there. +我们就把它放这里 + +857 +00:34:14,080 --> 00:34:17,420 +We'll reset suggested constraints for this one too. +我们也对它做 Reset Suggest Constraints + +858 +00:34:17,420 --> 00:34:19,690 +Make sure that looks good, yes it does, okay, +保证它看起来不错,啊,是的看起来不错 + +859 +00:34:19,690 --> 00:34:22,050 +this is just the size inspector right here, alright. +这个是 Size Inspector + +860 +00:34:22,060 --> 00:34:23,640 +Alright, so that's good. +好了,这不错 + +861 +00:34:23,640 --> 00:34:25,220 +So let's run our app and see how it looks. +先跑跑我们的程序看看怎么样 + +862 +00:34:30,230 --> 00:34:31,360 +Okay, here we go. +好的跑了 + +863 +00:34:31,360 --> 00:34:32,500 +Oh, that's doesn't look good. +噢这看起来不太好 + +864 +00:34:32,500 --> 00:34:34,060 +What do you see is getting cut off? +你看到这些字被切掉了 + +865 +00:34:34,070 --> 00:34:35,530 +Let's see, if we rotate. +我们旋转着看一看 + +866 +00:34:35,530 --> 00:34:36,930 +So it's good in landscape. +横屏模式看起来很好 + +867 +00:34:36,940 --> 00:34:39,170 +It doesn't look very good in portrait. +但是竖屏就不太好了 + +868 +00:34:39,170 --> 00:34:40,900 +So why is that happening right there? +为什么会这样呢 + +869 +00:34:40,910 --> 00:34:43,670 +Some of you found this out in your homework. +你们也能自己在作业中找到答案 + +870 +00:34:43,670 --> 00:34:44,910 +It's because right now, +因为在这里 + +871 +00:34:44,910 --> 00:34:48,440 +we have this thing set to be of a fixed size. +我们把这个的大小定死了 + +872 +00:34:48,450 --> 00:34:52,550 +The font size are here, see auto shrink, fixed font size. +字体大小,看这个 Autoshrink, Fixed Font Size(固定字体大小) + +873 +00:34:52,550 --> 00:34:54,010 +And that doesn't need to be fixed, +但这个并不需要固定大小 + +874 +00:34:54,020 --> 00:34:55,820 +I'm happy if that's any size. +我会希望 + +875 +00:34:55,820 --> 00:34:57,520 +I really don't want it to +我不希望它的字体大小 + +876 +00:34:57,520 --> 00:34:59,220 +be any smaller than like 12 point. +比 12 点小 + +877 +00:34:59,220 --> 00:35:01,190 +That's getting pretty small in the UI so, +如果比这小整个 UI 就会很小 + +878 +00:35:01,190 --> 00:35:04,090 +I'm gonna set the minimum size to 12. +我把最小尺寸设为 12 + +879 +00:35:04,090 --> 00:35:05,720 +And now when we run, +现在当我们运行 + +880 +00:35:05,730 --> 00:35:08,160 +it'll make the font smaller to fit the size. +会让字体缩小来适应屏幕的尺寸 + +881 +00:35:08,160 --> 00:35:10,300 +But if we go to a larger, it will make the font bigger. +但是如果我们屏幕变宽,字体就会跟着变大 + +882 +00:35:11,460 --> 00:35:12,980 +Okay. Question back there. +好的后面有问题 + +883 +00:35:12,980 --> 00:35:14,500 +>> Is there any way to make it wrap around to the next line? +有没有办法让这段文字自动换行呢 + +884 +00:35:14,500 --> 00:35:16,170 +>> So the question is, +所以问题是 + +885 +00:35:16,170 --> 00:35:18,770 +is there any way to make this text wrap to the next line? +有没有办法让这些文字自动换行到下一行 + +886 +00:35:18,770 --> 00:35:21,040 +And there is.There's a couple of ways to do it. +有的,有几个方法来实现 + +887 +00:35:21,040 --> 00:35:22,440 +There's UI text view, +有一个是 UI TextView + +888 +00:35:22,440 --> 00:35:26,580 +which is a very powerful text wrapping one. +这是个非常强大的可以让文字换行的东西 + +889 +00:35:26,580 --> 00:35:29,310 +But even Label, you can go here to the Label and +不过即使使用 Label,你可以点击你的 Label + +890 +00:35:29,310 --> 00:35:32,410 +when you inspect it, you can say, +然后去到 inspector,你可以选择 + +891 +00:35:32,420 --> 00:35:34,120 +how you want the line breaks to happen. +你想怎么断句 + +892 +00:35:34,120 --> 00:35:36,820 +You see here it says truncate tail. +你看这里说的是删减尾部 + +893 +00:35:36,820 --> 00:35:40,850 +And you can also control how many lines long you're gonna +你也可以控制你想要这个 label + +894 +00:35:40,860 --> 00:35:42,420 +allow the label to be. +能显示多少行 + +895 +00:35:43,730 --> 00:35:48,860 +Okay, so now we have this good UI, and we want to +好的,所以我们有这个做好的 UI,然后我们打算 + +896 +00:35:48,860 --> 00:35:52,460 +make it so that it works with the Happiness View Controller. +让它和我们的 Happiness View Controller 一起工作 + +897 +00:35:52,470 --> 00:35:54,170 +So we need our Happiness View Controller. +所以我们需要我们的 Happiness View Controller + +898 +00:35:54,170 --> 00:35:56,400 +So how are we going to get our Happiness View Controller? +那我们怎么获得这个 Happiness View Controller 呢 + +899 +00:35:56,400 --> 00:35:58,170 +And the answer is, +答案是 + +900 +00:35:58,170 --> 00:35:59,940 +we're just going to copy and paste it from our other app. +我们只需要从另一个 app 中复制粘贴过来 + +901 +00:35:59,940 --> 00:36:02,240 +So let's go open our other app. +让我们打开另一个 app + +902 +00:36:02,240 --> 00:36:03,810 +Okay, where is it? +唔,在哪儿呢 + +903 +00:36:03,810 --> 00:36:05,370 +It's here, Developer Happiness. +啊,在这儿,Developer文件夹,Happiness + +904 +00:36:05,380 --> 00:36:07,110 +I'm just gonna open Happiness in Xcode. +我用 Xcode 打开 Happiness + +905 +00:36:07,110 --> 00:36:08,760 +Here it is. +这就是了 + +906 +00:36:08,760 --> 00:36:10,410 +And I'm just gonna first of all copy the code over. +接着我只需要复制所有代码过来 + +907 +00:36:10,420 --> 00:36:13,680 +So I have my FaceView and my HappinessViewController. +这里我有 FaceView 和 HappinessViewController + +908 +00:36:13,690 --> 00:36:17,220 +I'm just gonna drag them from one into the other. +我只需要把它们从这里拖到那里 + +909 +00:36:18,160 --> 00:36:20,460 +Okay, just drag them from one project into the other. +只用把它们从一个项目拖到另一个项目 + +910 +00:36:20,460 --> 00:36:23,460 +When you do, it'll allow you to copy them if you want, or +当你这么做时,它会询问你是复制它们,还是 + +911 +00:36:23,460 --> 00:36:25,060 +you could have a reference. +只是做一个引用 + +912 +00:36:25,060 --> 00:36:27,830 +If you're going to have a reference, make sure that that +如果你选择了引用,请确认 + +913 +00:36:27,830 --> 00:36:30,330 +place you're referencing to stays around, +你放这个引用的位置在哪里 + +914 +00:36:30,330 --> 00:36:32,330 +that you're not deleting it and things like that. +你不会删除它或做其他操作 + +915 +00:36:32,330 --> 00:36:34,420 +Or you could have a copy. +或者你可以选择复制 + +916 +00:36:34,420 --> 00:36:36,500 +I'm going to add a copy, the items right here. +我选复制,选择这里 + +917 +00:36:36,500 --> 00:36:37,970 +Okay, so, copy those two things in. +好的,把这俩复制进来 + +918 +00:36:37,970 --> 00:36:40,070 +And then what about my Storyboard here? +那么我们的 Storyboard 怎么办 + +919 +00:36:40,070 --> 00:36:42,870 +I need to kind of get this HappinessViewController +我需要有这个 HappinessView + +920 +00:36:42,880 --> 00:36:44,540 +over here. +这里的 + +921 +00:36:44,540 --> 00:36:46,810 +Okay. Over, into this guy. +复制到这里 + +922 +00:36:46,810 --> 00:36:48,680 +Okay, well I can copy and paste that too. +我也可以复制粘贴这个 + +923 +00:36:48,680 --> 00:36:50,810 +Just select this thing, copy. +只需要选中它,复制 + +924 +00:36:50,820 --> 00:36:52,250 +Go over to here and paste. +来到这里,然后粘贴 + +925 +00:36:52,250 --> 00:36:53,480 +Okay. +就好了 + +926 +00:36:53,490 --> 00:36:59,860 +So, now I have somewhere my two View Controllers. +那么现在我有两个我的 ViewController 了 + +927 +00:36:59,860 --> 00:37:02,260 +Okay. +好的 + +928 +00:37:02,260 --> 00:37:04,490 +Now one thing I notice when you do copy and +现在我注意到一件事情 + +929 +00:37:04,490 --> 00:37:07,900 +paste, it doesn't draw the face. +当我复制粘贴以后,脸没有了 + +930 +00:37:07,900 --> 00:37:11,100 +It seems like it needs kind of a little bit of a kick, +看起来这需要一些触发, + +931 +00:37:11,100 --> 00:37:13,700 +a little boost before I do that. +一些小的触发动作 + +932 +00:37:13,700 --> 00:37:15,640 +So like if you go to FaceView and +比如我去到 FaceView 的文件 + +933 +00:37:15,640 --> 00:37:17,800 +just edit this file and hit save. +然后稍稍编辑一下然后保存 + +934 +00:37:17,810 --> 00:37:20,840 +It seems like that gives it the kick in the head, +这似乎就可以看到笑脸了 + +935 +00:37:20,840 --> 00:37:23,810 +literally, that it needs to draw the head, okay? +确实,它需要把脸画出来 + +936 +00:37:23,810 --> 00:37:25,900 +So, now we have it. +那么现在我们是有脸的人了 + +937 +00:37:25,900 --> 00:37:27,980 +So, we got our two View Controllers here and +所以我们有两个 ViewController 了 + +938 +00:37:27,980 --> 00:37:29,950 +we want to put them in a Split View. +我想把它们放进 SplitView 里面 + +939 +00:37:29,950 --> 00:37:33,280 +So that this is the master, and this is the detail. +这样做让这个是 master,而这个是 detail + +940 +00:37:33,290 --> 00:37:34,290 +So let's do that. +我们来做这个吧 + +941 +00:37:34,290 --> 00:37:36,050 +Super simple, we're gonna go down here. +超级简单,我们只需要滚到这里 + +942 +00:37:36,990 --> 00:37:39,060 +Go grab a Split View Controller, okay? +拖一个 SplitViewController 出来 + +943 +00:37:39,060 --> 00:37:40,690 +The Split View Controller's right here. +SplitViewController 在这里 + +944 +00:37:40,690 --> 00:37:42,930 +See, here's Tab Bar Controller. +看,这个是 TabBarController + +945 +00:37:42,930 --> 00:37:45,860 +Here's Navigation Controller, somewhere. +这个是 Navigation Controller + +946 +00:37:45,860 --> 00:37:46,900 +PageViewController, even. +这个是 PageViewController + +947 +00:37:46,900 --> 00:37:48,060 +We're not gonna talk about that, but +我们不会说这个,但是 + +948 +00:37:48,070 --> 00:37:50,500 +that's another way to combine MVCs. +这是另一种组合 MVC 的方法 + +949 +00:37:50,500 --> 00:37:53,200 +But let's drag this Split View Controller out. +我们把 SplitViewController 拖出来 + +950 +00:37:53,200 --> 00:37:54,770 +Now see how it +现在我们看看怎么把 + +951 +00:37:54,770 --> 00:37:56,340 +comes with other stuff that you don't want? +你不想要的它的一切其他东西删掉 + +952 +00:37:56,340 --> 00:37:58,640 +So when you drop it in there, literally just +那么当你把它放在这里,简单地选择 + +953 +00:37:58,640 --> 00:38:01,070 +select the stuff you don't want and delete it. +你不想要的东西,然后删除 + +954 +00:38:02,080 --> 00:38:04,210 +Okay. Don't want any of that stuff. +好吧。不想要 + +955 +00:38:04,210 --> 00:38:05,780 +Trying to be helpful. +那些可能有用而我们不想要的东西 + +956 +00:38:05,780 --> 00:38:08,810 +And so here's my Split View Controller, okay and +那么这就是我的 Split View Controller 了, + +957 +00:38:08,820 --> 00:38:10,550 +here's my master and detail. +然后这个是 master 和 detail + +958 +00:38:10,550 --> 00:38:12,750 +I'm just gonna control drag. +我只需要 control 加拖动 + +959 +00:38:12,750 --> 00:38:14,320 +To set my master. +去设置它为 master + +960 +00:38:14,320 --> 00:38:16,200 +So here's the master. +这就是 master 了 + +961 +00:38:16,200 --> 00:38:18,090 +And I'm gonna control drag, to set the detail. +接着我 control 加拖动去设置 detail + +962 +00:38:20,190 --> 00:38:21,360 +Okay. That's it. +好了就这样 + +963 +00:38:21,360 --> 00:38:22,360 +So let's run. +让我们运行一下 + +964 +00:38:22,360 --> 00:38:24,330 +Let's actually run on an iPad. +让我们在 iPad 上运行一下 + +965 +00:38:24,330 --> 00:38:27,460 +See what this looks like. +看看效果怎样 + +966 +00:38:27,470 --> 00:38:33,370 +[BLANK AUDIO] Alright, so here's an iPad. +好咧,这是 iPad + +967 +00:38:33,370 --> 00:38:36,970 +Oh, I thought I was gonna get a Split View, with this thing. +噢我想我会在这里得到一个 Split View + +968 +00:38:36,970 --> 00:38:38,110 +How come I don't get a Split View? +但是为什么我没有 Split View 呢 + +969 +00:38:38,110 --> 00:38:42,040 +>> [INAUDIBLE] >> What? +什么 + +970 +00:38:42,040 --> 00:38:45,980 +>> [INAUDIBLE] >> Yes, exactly. +对哒 + +971 +00:38:45,980 --> 00:38:47,850 +Very good job. +机智如你 + +972 +00:38:47,850 --> 00:38:50,450 +You should get extra credit or something up there. +我应该给你一些棒棒糖奖励 + +973 +00:38:50,450 --> 00:38:53,950 +Yeah, the problem is this UI comes in through this arrow, +是的,问题在于 UI 启动会从这个箭头开始 + +974 +00:38:53,950 --> 00:38:54,850 +so it comes to here. +现在它从这里启动 + +975 +00:38:54,860 --> 00:38:56,420 +So it's bypassing the Split View. +所以它跳过了这个 Split View + +976 +00:38:56,420 --> 00:38:57,790 +It's not even going. +它甚至没有经过 + +977 +00:38:57,790 --> 00:38:59,360 +So it's just a common mistake you'll do, +这是个常见的错误 + +978 +00:38:59,360 --> 00:39:00,770 +you'll forget to move this. +你可能会忘记移动这个箭头 + +979 +00:39:00,780 --> 00:39:02,190 +And you can just pick this arrow up and +那么你只需要把箭头拖动 + +980 +00:39:02,190 --> 00:39:02,790 +move it over here. +移动到这里 + +981 +00:39:04,330 --> 00:39:06,380 +Okay. +好的 + +982 +00:39:06,380 --> 00:39:08,430 +Now when we run, it's going to come in, via the Split View. +现在当我们运行,UI 将从 Split View 开始 + +983 +00:39:08,430 --> 00:39:09,400 +And it is a Split View. +这里确实有 Split View + +984 +00:39:09,400 --> 00:39:11,000 +If I slide out from the left, +如果我从左边划开 + +985 +00:39:11,000 --> 00:39:14,600 +there's my master and here's my detail. +这是我的 master,而这是我的 detail + +986 +00:39:14,600 --> 00:39:17,070 +Okay. And if I rotate. +好的,如果我旋转屏幕 + +987 +00:39:17,070 --> 00:39:18,210 +Okay. I get the master and detail on +那么我就有 master 和 detail 同时在 + +988 +00:39:18,210 --> 00:39:19,140 +the screen at the same time. +同一个屏幕上了 + +989 +00:39:20,940 --> 00:39:23,240 +Sound good? Now clicking this doesn't seem +听起来很棒不是么?现在,点击似乎没有 + +990 +00:39:23,250 --> 00:39:24,910 +to do anything, okay. +触发什么 + +991 +00:39:24,910 --> 00:39:26,150 +So we're gonna have to fix that. +接下来我们需要实现它们 + +992 +00:39:26,150 --> 00:39:28,210 +And let's go look at it on an iPhone see what it +让我们看看程序在 iPhone 上跑 + +993 +00:39:28,220 --> 00:39:29,180 +looks like there? +是什么样子的 + +994 +00:39:33,320 --> 00:39:38,960 +I didn't hit the button sorry Alright, here's my iPhone. +我忘记点运行按钮了抱歉同学们,好的,这是我的 iPhone + +995 +00:39:38,960 --> 00:39:40,620 +Okay? +好吧 + +996 +00:39:40,630 --> 00:39:41,120 +Oh. +噢 + +997 +00:39:41,130 --> 00:39:41,660 +Wait. +等等 + +998 +00:39:41,660 --> 00:39:43,060 +How do I? +怎么办? + +999 +00:39:43,060 --> 00:39:44,290 +I can't see the face. +我看不到笑脸了 + +1000 +00:39:44,300 --> 00:39:45,860 +Okay? Let's try landscape. +好吧?试试横着屏幕 + +1001 +00:39:45,860 --> 00:39:47,000 +That doesn't work either. +还是不行。 + +1002 +00:39:47,000 --> 00:39:49,400 +So there's no way to get at the face, right now. +看来是怎么都看不到笑脸了。 + +1003 +00:39:49,400 --> 00:39:51,470 +Absolutely no way to get the face. +貌似完全没办法了, + +1004 +00:39:51,470 --> 00:39:52,470 +And why is that? +这是为什么呢? + +1005 +00:39:52,470 --> 00:39:54,230 +Well that's because again on phone which is +刚才说过了,当设备处于 + +1006 +00:39:54,240 --> 00:39:56,670 +a compact size trait device. +横向compact尺寸的时候。 + +1007 +00:39:56,670 --> 00:40:02,310 +SplitView doesn't put things side by side, it just doesn't do that, okay. +SplitView 是不会左右平铺开的, + +1009 +00:40:02,310 --> 00:40:06,150 +Now if we do iPhone6 Plus. +如果我们在iPhone6 Plus上 + +1010 +00:40:06,150 --> 00:40:06,910 +Try that one. +尝试一下 + +1011 +00:40:11,380 --> 00:40:13,620 +It's kind of a hybrid. +iPhone6 plus是一种混合的产品, + +1012 +00:40:13,620 --> 00:40:15,850 +First of all it's such high resolution that even the small +首先来说,它虽然小,但是确有高分辨率的屏幕, + +1013 +00:40:15,860 --> 00:40:17,620 +versions, the smallest I can get it. +是高分辨率设备里最小的。 + +1014 +00:40:17,620 --> 00:40:18,590 +But see, in portrait, +看,在竖屏的时候, + +1015 +00:40:18,590 --> 00:40:20,320 +I have the same problem as another iPhone. +遇到了和其它iPhone一样的问题, + +1016 +00:40:20,330 --> 00:40:22,790 +There's just no way for me to get to the face. +看不到笑脸 + +1017 +00:40:22,790 --> 00:40:24,880 +Cuz it's no way to, +没办法, + +1018 +00:40:24,880 --> 00:40:26,960 +if I try sliding out from the side, nothing happens. +即使我从左边滑动,也没用。 + +1019 +00:40:26,960 --> 00:40:28,600 +Okay? Because in portrait mode, +因为在竖屏模式下, + +1020 +00:40:28,600 --> 00:40:31,270 +the iPhone 6 Plus works like an iPhone. +iPhone6 Plus和其它iPhine没区别。 + +1021 +00:40:31,270 --> 00:40:33,770 +But in landscape, on iPhone 6 Plus, +但是在iPhone6 plus的横屏下, + +1022 +00:40:33,770 --> 00:40:37,940 +it's big enough, that it can actually show them both. Okay? +因为足够大,所以两部分就可以完全显示。 + +1024 +00:40:37,940 --> 00:40:39,370 +So that's kinda cool. +这个非常酷。 + +1025 +00:40:39,370 --> 00:40:42,680 +Alright but it still doesn't work. Okay. +但是这个按钮依然不能用。 + +1027 +00:40:42,680 --> 00:40:44,440 +So why does this not work? +为什么没用? + +1028 +00:40:44,450 --> 00:40:47,710 +Well, it doesn't work because we have no segues. +因为我们还没有加入segue。 + +1029 +00:40:47,720 --> 00:40:51,550 +We don't describe how to get from one of +还没有告诉程序如何从这个地方跳转到 + +1030 +00:40:51,550 --> 00:40:53,620 +these things to another. +另一个地方。 + +1031 +00:40:53,620 --> 00:40:54,950 +So let's put some segues in. +现在我们来加入segue。 + +1032 +00:40:54,950 --> 00:40:56,320 +What we're gonna do, +在segue之前, + +1033 +00:40:56,320 --> 00:40:58,620 +well, actually before we do the segues, +我们要做的是, + +1034 +00:40:58,620 --> 00:41:02,590 +let's fix this problem with the iPhone not working. +如何修复在iPhone上的这个问题, + +1035 +00:41:02,590 --> 00:41:05,500 +Okay, let's fix the problem where we can't see the iPhone. +修复在iPhone上看不到两个视图的问题, + +1036 +00:41:05,500 --> 00:41:08,360 +In order to fix that, what we talked about in the slides, +我们需要把主视图放到一个 + +1037 +00:41:08,370 --> 00:41:11,730 +by putting this guy in a Navigation Controller.Okay. +Navigation Controller里来解决这个问题。 + +1039 +00:41:11,740 --> 00:41:13,030 +So let's go do that. +下面开始做, + +1040 +00:41:13,040 --> 00:41:15,440 +We're gonna do that with embed. +进到embed in里边, + +1041 +00:41:15,440 --> 00:41:17,270 +In Navigation Controller. +选Navigation Controller。 + +1042 +00:41:17,270 --> 00:41:19,740 +It puts it in a Navigation Controller, okay. +现在主视图在Navigation Controller里, + +1043 +00:41:19,740 --> 00:41:22,710 +Now when we run on the iPhone, we'll just run it in normal +现在我们在普通的iPhone上运行一下, + +1044 +00:41:22,710 --> 00:41:29,250 +iPhone, you'll see that we get the face. +可以正常看到笑脸了。 + +1045 +00:41:29,250 --> 00:41:30,350 +Okay? Awesome. +厉害吧。 + +1046 +00:41:30,350 --> 00:41:33,050 +And we can go back to the master and +可以正常的回到主视图, + +1047 +00:41:33,050 --> 00:41:35,990 +there's no way to get back to the detail.Okay. +但是没办法回到笑脸了。 + +1049 +00:41:35,990 --> 00:41:37,720 +So now we definitely need those segues. +所以现在我们必须要用到segue了。 + +1050 +00:41:37,720 --> 00:41:41,660 +We need these buttons to cause a segue to happen to the detail. +所以我们现在需要通过点击这些按钮跳转到笑脸。 + +1052 +00:41:41,660 --> 00:41:45,200 +Okay. So that's what we're gonna do next. +我们接下来做这个, + +1054 +00:41:45,200 --> 00:41:47,430 +And actually, let's take a second here and +在这之前,我们先看一下 + +1055 +00:41:47,430 --> 00:41:49,070 +show what this looks like on the iPad. +加了Navigation Controller之后, + +1056 +00:41:50,540 --> 00:41:53,000 +We added the Navigation Controller here. +在iPad上看起来是什么样的。 + +1057 +00:41:53,000 --> 00:41:55,170 +Let's see what effect it had on the iPad. +看一下在iPad上会有什么影响。 + +1058 +00:41:55,170 --> 00:41:58,940 +And the answer is, that the master now has a title. +看,主视图上现在有了一个标题, + +1059 +00:42:00,380 --> 00:42:02,940 +See? Has a title there. +看到没?这有个标题。 + +1061 +00:42:02,950 --> 00:42:04,610 +And this kind of would be nice, +在这放一个标题我 + +1062 +00:42:04,610 --> 00:42:06,700 +even to put a title in here. +感觉挺好的。 + +1063 +00:42:06,700 --> 00:42:08,780 +So we can go over here, and actually double click on here, +现在我们可以双击这, + +1064 +00:42:08,780 --> 00:42:14,250 +and put in psychologist. +然后输入 psychologist 。 + +1065 +00:42:14,260 --> 00:42:16,150 +Put a title in there. +设置一个标题。 + +1066 +00:42:16,160 --> 00:42:18,460 +Notice, look what happened to our question. +注意看我们刚才设置的问题。 + +1067 +00:42:18,460 --> 00:42:19,720 +It kind of got obscured. +被挡住了。 + +1068 +00:42:19,730 --> 00:42:21,690 +Do you see that? +看到了吗? + +1069 +00:42:21,690 --> 00:42:23,130 +By this title. +被标题挡住了。 + +1070 +00:42:23,130 --> 00:42:24,530 +And actually we have a warning up here. +上边有一个警告, + +1071 +00:42:24,530 --> 00:42:25,830 +Do you see that warning? +看见那个警告了么? + +1072 +00:42:25,830 --> 00:42:27,130 +That warning is about that. +那个警告说的是。。 + +1073 +00:42:27,130 --> 00:42:27,830 +Let's click on it. +点一下看看。 + +1074 +00:42:27,830 --> 00:42:31,300 +It says, the frame for what you see in your dreams will be different at run time. +它说,这个问题的label的frame在运行时看上去会不一样。 + +1076 +00:42:31,300 --> 00:42:36,470 +That's because it's going to automatically move it down underneath this. +因为在运行时它会自动往下挪到标题下边。 + +1078 +00:42:36,470 --> 00:42:39,240 +And we can make that happen in our Storyboard by going over +在 Storyboard 上也可以修改好, + +1079 +00:42:39,240 --> 00:42:42,580 +here, clicking here, doing what we always do when we +就像我们平时修复 auto layout的问题一样, + +1080 +00:42:42,580 --> 00:42:44,580 +have a problem with our auto layout, +点这里。 + +1081 +00:42:44,580 --> 00:42:47,310 +fix our misplacement and it will move it back down. Okay. +修复一下,它就往下移了。 + +1083 +00:42:49,080 --> 00:42:52,050 +Alright so this is looking good. +现在看上去没问题了。 + +1084 +00:42:52,050 --> 00:42:54,590 +So let's get this segue business happening. +好了,现在开始加segue了。 + +1085 +00:42:54,590 --> 00:42:57,790 +So I told you the segues are done just with control drag. Okay. +前面说过了,segue 也是通过control + 拖拽实现的。 + +1087 +00:42:59,130 --> 00:43:02,590 +When we click one of these things I wanna segue to +当点击这些按钮的时候,我希望看到一个脸 + +1088 +00:43:02,600 --> 00:43:05,400 +a face that shows the diagnosis based on +作为在梦里见到的东西 + +1089 +00:43:05,400 --> 00:43:06,930 +what you saw in your dreams. +的诊断结果。 + +1090 +00:43:06,930 --> 00:43:09,030 +So we do this just with Ctrl+drag. +开始 control + 拖拽, + +1091 +00:43:09,030 --> 00:43:11,900 +So let's Ctrl+drag from Golden Bear. +咱们从 Golden Bear 拽到 + +1092 +00:43:11,900 --> 00:43:13,920 +Down here. +这里。 + +1093 +00:43:13,920 --> 00:43:15,940 +See how it's grabbing on to this MVC down here? +看到下边这个MVC的变化了吗? + +1094 +00:43:15,940 --> 00:43:17,940 +So we'll let go and +松手 + +1095 +00:43:17,940 --> 00:43:19,940 +it says what kind of segue do you want. +然后Xcode问我们需要什么类型的segue。 + +1096 +00:43:19,940 --> 00:43:22,610 +And we're going to do show detail because we want it to +我们选 show detail,因为我们希望诊断结果显示在 + +1097 +00:43:22,610 --> 00:43:25,380 +show it in the detail side of the Split View, and +SplitView的细节视图部分,在Navination Controller里 + +1098 +00:43:25,380 --> 00:43:27,650 +in the Navigation Controller it will just push it. +把它推进来。 + +1099 +00:43:27,650 --> 00:43:30,220 +But the show detail will do the Split View thing. +虽然实际上它在做SplitView的事情。 + +1100 +00:43:30,220 --> 00:43:31,890 +So, there we go and +下边我们 + +1101 +00:43:31,890 --> 00:43:33,550 +look what happened there we got this little segue. +看看有了这个segue,会发生什么。 + +1102 +00:43:33,560 --> 00:43:35,290 +If we inspect it, over here, +如果我们点击它,在右边 + +1103 +00:43:35,290 --> 00:43:36,690 +you can see there is its identifier. +你会看到一个它的 identifier 。 + +1104 +00:43:36,690 --> 00:43:37,760 +You can even change what kind of +如果之后有需要, + +1105 +00:43:37,760 --> 00:43:39,860 +segue it is in the future if you wanted. +你还能在这修改segue的类型。 + +1106 +00:43:39,860 --> 00:43:42,560 +But this identifier is the Golden Bear one. +这个 identifier 指的是 Golden Bear。 + +1107 +00:43:42,560 --> 00:43:47,430 +I'm going to call this the sad identifier, okay. +所以我想让这个 identifier 叫 sad。 + +1108 +00:43:47,430 --> 00:43:49,330 +So whenever this goes through, +之后无论何时用到这个segue, + +1109 +00:43:49,340 --> 00:43:51,970 +this identifier for this segue, is called sad. +它的 identifier 就叫 sad。 + +1110 +00:43:51,970 --> 00:43:53,100 +And we'll do the same thing here for +下面是 Dancing Tree,是一样的, + +1111 +00:43:53,110 --> 00:43:57,010 +Dancing Tree, okay, show detail again. +还是选 show detail。 + +1112 +00:43:57,010 --> 00:44:00,910 +And dancing trees segue, which is right here. +Dancing Tree 的segue在这, + +1113 +00:44:00,910 --> 00:44:02,780 +We're gonna call this one, happy. +我们叫它 happy。 + +1114 +00:44:02,780 --> 00:44:04,000 +That's the happy one. +这个就叫happy了。 + +1115 +00:44:04,000 --> 00:44:05,210 +Now, I told you these should be verbs so +我之前说过这个名字最好用 + +1116 +00:44:05,220 --> 00:44:07,250 +maybe this should be, +动词。 + +1117 +00:44:07,250 --> 00:44:09,280 +show happy diagnosis, show sad diagnosis. +比如 ”显示 happy 的诊断“,”显示 sad 的诊断“ + +1118 +00:44:09,290 --> 00:44:11,920 +But for demo it's less typing later, +因为这是演示,我们就少打点字儿。 + +1119 +00:44:11,920 --> 00:44:13,150 +I'm just putting happy in that. +所以就叫 happy 吧。 + +1120 +00:44:13,160 --> 00:44:14,860 +How about buckeye. +Buckeye 呢? + +1121 +00:44:14,860 --> 00:44:16,490 +Okay, we'll say show detail. +还是 show detail。 + +1122 +00:44:16,490 --> 00:44:19,560 +And for the buckeye one. Where is that one? +Buckeye的segue 是哪个? + +1124 +00:44:19,560 --> 00:44:20,730 +That's this one I guess. +应该是这个。 + +1125 +00:44:20,730 --> 00:44:24,800 +We'll say meh. Okay, not happy or sad. +我们叫它 meh, 既不开心也不难过。 + +1127 +00:44:25,830 --> 00:44:28,300 +Okay, and you can move these things around. +你可以随意的拖拽。 + +1128 +00:44:28,300 --> 00:44:30,200 +Right, if you're having trouble selecting them or +当你不好选上这些的时候, + +1129 +00:44:30,200 --> 00:44:33,970 +whatever, you can move them around to get at them better. +你能拖拽调整一下 + +1130 +00:44:33,970 --> 00:44:35,420 +Okay. + +1131 +00:44:35,420 --> 00:44:36,870 +So this is what our Storyboard looks like now. +现在我们的 Storyboard 看上去是这样的。 + +1132 +00:44:36,880 --> 00:44:40,840 +Let's make some more space so you can see it, right here. +腾出点空间看的更清楚。 + +1133 +00:44:40,850 --> 00:44:42,140 +And we've got our detail. +这是我们的细节视图。 + +1134 +00:44:42,150 --> 00:44:44,810 +Let me whip this up here. +调整一下。 + +1135 +00:44:44,820 --> 00:44:48,050 +And we got our master and we've got the segues now. +这是主视图,这是segue。 + +1136 +00:44:48,050 --> 00:44:50,890 +So let's go ahead and run, and see if this works. +运行一下看看效果 + +1137 +00:44:50,890 --> 00:44:53,340 +Let's go. +走你。 + +1138 +00:44:53,340 --> 00:44:55,790 +On iPad, okay, huh, does not appear to work on the i-Pad, +在iPad上运行,啊,貌似在iPad上不行, + +1139 +00:44:55,790 --> 00:44:57,660 +huh, that's interesting. +奇怪。 + +1140 +00:44:57,660 --> 00:44:59,290 +Alright, let's try it on the iPhone. +到iPhone上试试。 + +1141 +00:45:10,970 --> 00:45:12,100 +All right, so there's iPhone. +iPhone来了。 + +1142 +00:45:12,110 --> 00:45:14,070 +So we're at the face, let's go back to the master. +我们先看到笑脸,点回到主视图。 + +1143 +00:45:14,080 --> 00:45:15,690 +Here's the master, +主视图。 + +1144 +00:45:15,690 --> 00:45:17,310 +notice we have this nice title up here now, Psychologist. +看到我们这有一个标题, Psychologist 。 + +1145 +00:45:17,310 --> 00:45:18,680 +Let's do this. +点一下, + +1146 +00:45:18,680 --> 00:45:20,040 +Oh, it's doing something, but, +啊,有变化了, + +1147 +00:45:20,050 --> 00:45:21,850 +it's not actually showing the diagnosis. +但是并没有显示出诊断结果。 + +1148 +00:45:21,850 --> 00:45:25,680 +But at least it's segueing to the other one. +但是至少跳转了。 + +1149 +00:45:25,690 --> 00:45:27,400 +Okay? + +1150 +00:45:27,400 --> 00:45:29,120 +So the iPad was working too, it's just there was nothing to +所以说在iPad上也是没问题的,因为细节视图已经在 + +1151 +00:45:29,120 --> 00:45:32,090 +see, because there was already a detail there and +右边了,所以看不到变化。它只是生成了一个 + +1152 +00:45:32,090 --> 00:45:33,990 +it replaced that detail with a new one. +新的细节视图。 + +1153 +00:45:33,990 --> 00:45:37,560 +But we didn't prepare that thing, so it doesn't know how +我们没有准备segue,所以它们还不知道笑脸要变化成 + +1154 +00:45:37,560 --> 00:45:39,800 +much to smile, it doesn't know how to show the diagnosis, +什么样,不知道如何显示诊断结果, + +1155 +00:45:39,800 --> 00:45:41,500 +cuz we have to prepare it. +我们要准备了它才能知道。 + +1156 +00:45:41,500 --> 00:45:43,570 +Okay, so preparing is the next step. +所以,下一步是准备。 + +1157 +00:45:43,570 --> 00:45:47,740 +We do the preparation for these segues in this ViewController. +我们需要在这个 View controller里准备这几个segue。 + +1159 +00:45:47,740 --> 00:45:50,470 +This is the ViewController that's instigating the segue, +因为跳转是从这开始的, + +1160 +00:45:50,470 --> 00:45:53,140 +so here's where we have to put our preparation. +所以我们要在这做准备。 + +1161 +00:45:53,140 --> 00:45:55,810 +This is the PsychologistViewController. +就是这个 PsychologistViewController 。 + +1162 +00:45:55,810 --> 00:45:57,910 +Okay, so we're gonna go over here to +所以我们现在到 + +1163 +00:45:57,910 --> 00:46:02,150 +our PsychologistViewController code, delete that stuff. +PsychologistViewController 的代码部分,删掉这些东西。 + +1164 +00:46:03,720 --> 00:46:05,150 +Okay, here's PsychologistViewController. +好了。 + +1165 +00:46:05,150 --> 00:46:09,990 +And all we have to do here is implement that one prepare method, okay. +我们要做的就是在这实现一个准备的方法, + +1167 +00:46:09,990 --> 00:46:15,090 +So it's called prepareForSegue. +这个方法叫 prepareForSegue 。 + +1168 +00:46:15,090 --> 00:46:18,760 +'Kay, I'll let it type it out for me by hitting tab. +我可以先打这个字儿然后摁 tab 。 + +1169 +00:46:18,760 --> 00:46:22,260 +And you can see there's the two arguments, the segue and the sender. +可以看到这个方法有两个参数,segue 和 sender 。 + +1171 +00:46:22,270 --> 00:46:26,140 +Now I'm gonna just say here, if the segue's +这我就可以写,if segue 的 + +1172 +00:46:26,140 --> 00:46:31,040 +destinationViewController, sorry, if I can let HVC, +destinationViewController,啊,对不起, if let HVC , + +1173 +00:46:31,040 --> 00:46:36,980 +HappinessViewController, equal the DestinationViewController +HappinessViewController 等于 segue的 destinationViewController + +1174 +00:46:36,980 --> 00:46:41,350 +as a HappinessViewController, then I'm gonna do +as HappinessViewController , 然后我们就可以判断 + +1175 +00:46:41,350 --> 00:46:45,290 +something based on what the identifier is. +identifier 然后写代码了 + +1176 +00:46:45,290 --> 00:46:47,650 +Now, if this segue, if we have a prepareForSegue and we're +在这个方法里,如果我们要跳转的 + +1177 +00:46:47,660 --> 00:46:50,220 +segueing to something that's not a HappinessViewController, +目的地不是 HappinessViewController。 + +1178 +00:46:50,220 --> 00:46:51,660 +then this if let is not gonna happen. +那么这个if let 就不会发生。 + +1179 +00:46:51,660 --> 00:46:53,960 +So none of what I'm gonna type right here is gonna happen, +所以下边我即将要完成的代码就不会运行, + +1180 +00:46:53,960 --> 00:46:55,390 +and that's perfectly fine. +完全没有问题。 + +1181 +00:46:55,400 --> 00:46:58,830 +You can kinda do the if let on what kind of +你可以先if let要跳转到什么 + +1182 +00:46:58,830 --> 00:47:00,560 +thing you're segueing to, or +对象上,或者 segue 的identifier, + +1183 +00:47:00,570 --> 00:47:02,500 +on the identifier, one on the outside, +一个在外边,一个在里边, + +1184 +00:47:02,500 --> 00:47:05,800 +one on the inside, kind of depends on what's going on. +根据实际情况来。 + +1185 +00:47:05,800 --> 00:47:08,100 +But in this case, I'm going to do the if let for +在这里,我要在外边先 if let 我的 + +1186 +00:47:08,110 --> 00:47:10,740 +my destinationViewController on the outside, and then I'm +destinationViewController, 然后在里面if let segue的 + +1187 +00:47:10,740 --> 00:47:16,110 +going to do the if let on the identifier on the inside. +identifier。 + +1188 +00:47:16,110 --> 00:47:18,250 +Okay? So if I had a segue to +如果我有一个跳转到 + +1189 +00:47:18,250 --> 00:47:21,950 +a happiness controller that had no identifier set, +HappinessViewController。而且没设置 identifier, + + +1190 +00:47:21,950 --> 00:47:24,120 +then we would do nothing. +那就不用做什么了。 + +1191 +00:47:24,120 --> 00:47:25,820 +But if it's set, we're going to go in here, +如果设置了,我们就需要一个 + +1192 +00:47:25,820 --> 00:47:27,190 +we'll switch on it. +switch + +1193 +00:47:27,190 --> 00:47:28,720 +So let's switch on identifier. +对 identifier 做一个 switch + +1194 +00:47:30,130 --> 00:47:34,430 +If it is the sad identifier, okay, +如果它是 sad + +1195 +00:47:34,430 --> 00:47:39,400 +the sad segue, then let's set our hvc's happiness to 0. +那 HVC 的开心值我们设置成0 + +1196 +00:47:41,770 --> 00:47:46,300 +Okay, so here's where I'm preparing, this newly created +所以我在这里准备马上要显示在屏幕上的新 + +1197 +00:47:46,310 --> 00:47:49,040 +HappinessViewController to be displayed on screen. +生成的 HappinessViewController + +1198 +00:47:50,280 --> 00:47:53,010 +Okay, and if it's the happy segue, +继续,如果segue是happy + +1199 +00:47:53,010 --> 00:47:56,710 +then we'll set the happiness to 100. +就把开心值设为100. + +1200 +00:47:56,710 --> 00:48:01,180 +And then, actually for anything else, I'm just gonna set the happiness to 50. +其他的情况,开心值是50就好了 + +1202 +00:48:01,180 --> 00:48:03,080 +Okay, something in the middle. +中间值 + +1203 +00:48:04,550 --> 00:48:06,950 +Okay, so that's it, that's all I have to do here, +好了,这是全部需要做的 + +1204 +00:48:06,960 --> 00:48:09,990 +that's all my ViewController needs to be prepared. +这是我的 ViewController 需要准备的所有东西 + +1205 +00:48:09,990 --> 00:48:12,830 +You know, if I had other things in here, I could +当然,如果这里有别的东西 + +1206 +00:48:12,830 --> 00:48:16,030 +set other properties, but this is all this one needs. +我可以在这里设置其他的属性,但是在这,现在就已经够了 + +1207 +00:48:16,030 --> 00:48:16,930 +Okay? +OK? + +1208 +00:48:16,930 --> 00:48:18,100 +So it's prepared. +已经准备好了 + +1209 +00:48:18,100 --> 00:48:19,260 +So let's go ahead and run this. +我们来运行一下 + +1210 +00:48:19,270 --> 00:48:20,770 +This should all work, right? +应该有效 + +1211 +00:48:20,770 --> 00:48:21,870 +It should be no problems. +应该没什么问题了 + +1212 +00:48:22,800 --> 00:48:24,270 +Okay. Here's our psychologist. +好,这是 Psychologist + +1213 +00:48:24,270 --> 00:48:25,570 +Let's try dancing tree. +试试 Dancing Tree + +1214 +00:48:25,570 --> 00:48:26,870 +Oh, crashed our program. +崩溃了 + +1215 +00:48:26,870 --> 00:48:30,070 +All right, kind of told you I was going to do this. +之前应该说过我会这么做 + +1216 +00:48:30,080 --> 00:48:31,770 +Why did our program crash? +为什么崩溃了呢? + +1217 +00:48:31,780 --> 00:48:33,280 +Well it says unexpected, +它说有未知的 + +1218 +00:48:33,280 --> 00:48:35,410 +I'm looking in the console down here. +我正在看下边的控制台。 + +1219 +00:48:35,410 --> 00:48:37,450 +You should always look in the console when it crashes. +程序崩溃的时候一般都要看这 + +1220 +00:48:37,450 --> 00:48:38,380 +Okay? It's the first place you want to look. +这是你最先要看的地方 + +1222 +00:48:40,530 --> 00:48:42,680 +This says unexpected found nil while unwrapping an optional. +它说在解包一个可选值的时候意外的发现空值 + +1223 +00:48:42,690 --> 00:48:46,490 +Okay, so I accessed some optional that was nil. +说明我使用了一个为空的可选值 + +1224 +00:48:46,490 --> 00:48:47,750 +So that's bad. +很糟 + +1225 +00:48:47,760 --> 00:48:49,940 +Where did I do that? +在哪发生的呢? + +1226 +00:48:49,940 --> 00:48:52,130 +Right here in updateUI, in HappinessViewController, +就在这,HappinessViewController + +1227 +00:48:52,130 --> 00:48:53,260 +HappinessViewController updateUI. +内部的 updateUI + +1228 +00:48:53,260 --> 00:48:57,930 +Well, let's see, what in this line might be nil? +让我们看一下,这行里什么东西是空值 + +1229 +00:48:57,930 --> 00:48:59,800 +Well, of course, it's the only thing that could be nil, +当然,这是唯一有可能为空的 + +1230 +00:48:59,800 --> 00:49:02,170 +which is the faceView is nil. +是 faceView + +1231 +00:49:03,100 --> 00:49:04,500 +What is the faceView? +faceView 是什么? + +1232 +00:49:04,500 --> 00:49:06,040 +It's this outlet right here. +它是在这的一个 outlet + +1233 +00:49:06,040 --> 00:49:09,410 +Okay, we can also, by the way, go over here and +另外,我们还能在这边 + +1234 +00:49:09,410 --> 00:49:11,010 +find out how we got here. +看看可以发现什么。 + +1235 +00:49:11,010 --> 00:49:12,780 +So we got here because someone was setting our +发现了updateUI 在属性观察器里 + +1236 +00:49:12,780 --> 00:49:14,640 +model into the property observer, +设置我们的 model + +1237 +00:49:14,650 --> 00:49:18,850 +we wanted to update UI, and we got there from preparation. +我们希望更新 UI,而且我们在这已经准备了 + +1238 +00:49:18,850 --> 00:49:19,910 +So here we are preparing, +在这准备好了 + +1239 +00:49:19,920 --> 00:49:22,120 +we're trying to prepare this new MVC, and +我们在这准备了新的 MVC + +1240 +00:49:22,120 --> 00:49:25,650 +it sets the model to be something, +设置了我们的 model + +1241 +00:49:25,660 --> 00:49:29,760 +that updates the UI, and we get here and we crash. +然后更新 UI, 然后我们在这就崩溃了 + +1242 +00:49:29,760 --> 00:49:31,690 +And why is faceView nil right there? +那么为什么 faceView 在这是空? + +1243 +00:49:31,690 --> 00:49:34,160 +Because as I said in red, +因为前面的 slide 我用红字提醒了 + +1244 +00:49:34,160 --> 00:49:37,200 +when you're preparing the outlets have not been set. +当你准备 segue 的时候,outlet 还没有设置 + +1245 +00:49:37,200 --> 00:49:40,330 +So this faceView outlet, down here, has not been set. +所以这个 faceView 的 outlet,还没有被设置 + +1246 +00:49:40,330 --> 00:49:43,240 +So, you know, it's an implicit unwrapped optional, but +这是一个强制解包的可选值,但是 + +1247 +00:49:43,240 --> 00:49:46,770 +it's still an optional, and it has not been set yet. +它依然是一个可选值,只是还没被设置 + +1248 +00:49:46,770 --> 00:49:48,540 +Okay, so how are we going to get around this? +那么我们怎么解决这个问题呢? + +1249 +00:49:48,540 --> 00:49:52,340 +Well, luckily in our case, whenever we set, if we set our +幸运的是,每当我们设置 model 的值时 + +1250 +00:49:52,350 --> 00:49:55,150 +model and we try to update the UI and the faceView's not +我们就会尝试更新 UI,如果这个时候 faceView 的 outlet 没有 + +1251 +00:49:55,150 --> 00:49:57,810 +even connected yet, well, we can just ignore it then, +连接,我们只需要忽略就好了 + + +1252 +00:49:57,820 --> 00:50:00,980 +because obviously the faceView is up to date because it's +因为很明显 faceView 是实时更新的,即使它在一开始 + +1253 +00:50:00,990 --> 00:50:02,620 +not even hooked up. +没有连接 + +1254 +00:50:02,620 --> 00:50:05,350 +So we can just use optional chaining here and +所以我们可以使用可选值链条 + +1255 +00:50:05,360 --> 00:50:06,590 +just put a question mark there. +在这加一个问号 + +1256 +00:50:07,560 --> 00:50:10,430 +Right, and what that says, if this thing is nil, +这个意思就是,如果它是空值 + +1257 +00:50:10,430 --> 00:50:12,290 +than just ignore the rest of this statement. +就忽略后边的部分 + +1258 +00:50:12,300 --> 00:50:14,030 +Okay. +好的 + +1259 +00:50:14,030 --> 00:50:18,470 +So, one thing you'll probably end up doing a lot of times +所以你之后应该经常做的一件事就是 + +1260 +00:50:18,470 --> 00:50:21,600 +is, in the things that could be called from a prepare, +如果某个属性在准备的时候被调用 + +1261 +00:50:21,600 --> 00:50:23,770 +you might be putting this optional chaining in. +你就需要把它们放到可选链里 + +1262 +00:50:23,770 --> 00:50:26,070 +Or checking, if base view does not equal nil, +或者先检查它是否为空 + +1263 +00:50:26,070 --> 00:50:30,010 +then do something. Okay? +然后在做其他的 + +1265 +00:50:30,010 --> 00:50:30,840 +So that should fix that. +这样应该就解决问题了 + +1266 +00:50:30,840 --> 00:50:33,310 +Let's go ahead and run this. +运行一下试试 + +1267 +00:50:33,310 --> 00:50:34,150 +Here it is. +出来了 + +1268 +00:50:34,150 --> 00:50:35,050 +Let's go back. +先回去 + +1269 +00:50:35,050 --> 00:50:37,450 +Dancing tree, very happy. +Dancing Tree,非常开心的笑脸 + +1270 +00:50:37,450 --> 00:50:39,780 +Golden bear, very unhappy. +Golden Bear,非常不爽 + +1271 +00:50:39,790 --> 00:50:41,380 +Buckeye? +Buckeye? + +1272 +00:50:41,390 --> 00:50:42,650 +Okay. +没问题 + +1273 +00:50:42,650 --> 00:50:43,920 +Working fine, let's go take a look, and +都没问题,然我们试试 + +1274 +00:50:43,920 --> 00:50:46,860 +let's go look in landscape here. +横屏 + +1275 +00:50:46,860 --> 00:50:48,160 +Golden Bear, working fine. +Golden Bear,没问题 + +1276 +00:50:48,160 --> 00:50:53,230 +Notice that this MVC underlaps this title bar up here. +注意这个 MVC 在标题栏的下层 + +1277 +00:50:53,230 --> 00:50:57,000 +You can actually control that in Storyboard if you inspect +你可以在 Storyboard 里点击这个 MVC + +1278 +00:50:57,000 --> 00:50:58,630 +the MVC, you can click on there, +设置它不要让 + +1279 +00:50:58,630 --> 00:51:02,970 +say do not go under thing above me. +任何东西覆盖在它的上面 + +1280 +00:51:02,970 --> 00:51:04,140 +Also notice that in landscape, +另外要注意在横屏下 + +1281 +00:51:04,140 --> 00:51:06,340 +you get a little smaller title bar up here, +标题栏变的更小了 + +1282 +00:51:06,340 --> 00:51:08,410 +which is kind of nice. +这样挺好看的 + +1283 +00:51:08,410 --> 00:51:09,810 +Okay +好的 + +1284 +00:51:09,810 --> 00:51:11,340 +But back in here, you get the bigger one, +回到横屏,就大了一些 + +1285 +00:51:11,340 --> 00:51:14,650 +because you're getting the carrier and the time up here. +因为上面有运营商和时间等等的东西 + +1286 +00:51:14,650 --> 00:51:17,680 +Okay, let's go look at it on the iPad. +我们在 iPad 上运行一下看看 + +1287 +00:51:25,420 --> 00:51:28,490 +Okay, here's this, I can slide this thing out from the right, +我能把主视图从左边滑出来 + +1288 +00:51:28,490 --> 00:51:31,590 +Golden Bear, Dancing Tree, Buckeye, working great. +Golden Bear, Dancing Tree, Buckeye,没问题 + +1289 +00:51:31,600 --> 00:51:33,900 +We can go over here. +再看看横屏 + +1290 +00:51:33,900 --> 00:51:37,530 +Golden Bear, Dancing Tree, Buckeye. +Golden Bear, Dancing Tree, Buckeye. + +1291 +00:51:37,530 --> 00:51:40,020 +Okay? +有问题吗? + +1292 +00:51:40,020 --> 00:51:42,500 +So pretty straightforward, the stuff is all pretty easy to +非常直观,所有东西在你的 + +1293 +00:51:42,510 --> 00:51:44,340 +envisualize in your Storyboard, +Storyboard 是可视的 + +1294 +00:51:44,340 --> 00:51:47,510 +when you're looking at the Storyboard it's pretty clear, +当你明白了这些连接的原理以后 + +1295 +00:51:47,510 --> 00:51:51,640 +once you understand how these connections happen, to see +看一下 Storyboard 你就会知道 + +1296 +00:51:51,650 --> 00:51:52,680 +what's going on over here. +运行的时候大致会发生什么 + +1297 +00:51:53,920 --> 00:51:59,120 +Okay, so one other thing I want to do here is make, +好了,下边我要做的是 + +1298 +00:51:59,120 --> 00:52:04,690 +let me go back to my simulator. +回到模拟器 + +1299 +00:52:04,690 --> 00:52:06,620 +Look at this guy over here. +看这 + +1300 +00:52:06,630 --> 00:52:07,960 +This guy doesn't get a title. +这边没有标题 + +1301 +00:52:08,960 --> 00:52:12,400 +That's kind of a bummer, that he doesn't get a title right +这有点讨厌,它在那里没有标题 + +1302 +00:52:12,400 --> 00:52:14,260 +there and he does on the iPhone. +iPhone 那边有(标题) + +1303 +00:52:14,270 --> 00:52:16,170 +Right, if you remember on the iPhone, he had a title, +如果你记得 iPhone,它有标题 + +1304 +00:52:16,170 --> 00:52:17,370 +it was blank, but he had a title. +这里是空,但它有标题 + +1305 +00:52:17,370 --> 00:52:21,200 +So I wanna give this guy a title on the iPad as well. +所以我想给这个家伙在 iPad 也有一个标题 + +1306 +00:52:21,210 --> 00:52:24,640 +So I'm gonna do that by just selecting it here and +我只要这样做,选择这里 + +1307 +00:52:24,640 --> 00:52:28,310 +saying Embed In > Navigation Controller. +选择 Embed In > Navigation Controller + +1308 +00:52:28,310 --> 00:52:29,380 +So I put this guy in +然后我就把这个家伙 + +1309 +00:52:29,380 --> 00:52:30,440 +a Navigation Controller too, down here. +放在 Navigation Controller 上了,在这下面 + +1310 +00:52:32,010 --> 00:52:32,880 +Okay? +OK? + +1311 +00:52:32,880 --> 00:52:35,280 +So then, I can have a title. +然后,我就有标题 + +1312 +00:52:35,280 --> 00:52:38,020 +Now, I could click here to set the title, right here I +现在,我可以点击这里设置标题,就在这里 + +1313 +00:52:38,020 --> 00:52:40,320 +could say diagnosis or something like that, +我可以使用 diagnosis 或类似的题目 + +1314 +00:52:40,320 --> 00:52:42,720 +but actually I am going to have the title be set in code. +但实际上我要在代码中设置标题 + +1315 +00:52:42,720 --> 00:52:45,990 +What I'm going to do is, every time someone says for my model +我将要做的是,每次有人在我的 HappinessViewController + +1316 +00:52:45,990 --> 00:52:48,890 +in my HappinessViewController, when I update the UI, +中访问我的 model,当我更新 UI 时 + +1317 +00:52:48,900 --> 00:52:56,070 +I'm going to say my title equals my happiness. +我将设置我的标题等于我的 happiness + +1318 +00:52:56,070 --> 00:52:57,970 +So I'm just gonna put that integer, +所以我只要设置这个数字 + +1319 +00:52:57,970 --> 00:52:59,640 +which is my happiness, as my title. +我的 happiness,为我的标题 + +1320 +00:52:59,640 --> 00:53:02,200 +So I'm gonna put that in here let's see if that works. +我要把这个放在这里,让我们看看这样是否可行 + +1321 +00:53:04,380 --> 00:53:06,440 +So we run, I've got a title. +我们运行下,我有了标题。 + +1322 +00:53:06,440 --> 00:53:07,840 +Doesn't look I've got there, but +看起来我没有设置成功 + +1323 +00:53:07,840 --> 00:53:13,780 +no one has set my happiness yet, so that makes sense. +但是还没人设置我的 happiness,所以这说的通 + +1324 +00:53:13,780 --> 00:53:14,580 +Oh, but it looks like I've +但看起来,这样做我似乎 + +1325 +00:53:14,580 --> 00:53:16,520 +broken something by doing that. +破坏了一些东西 + +1326 +00:53:16,520 --> 00:53:17,650 +This doesn't work. +这行不通 + +1327 +00:53:17,650 --> 00:53:18,850 +Huh. +哈 + +1328 +00:53:18,850 --> 00:53:20,690 +Why doesn't this work? +为什么这行不通? + +1329 +00:53:20,690 --> 00:53:24,920 +Well, the reason this doesn't work is because these segues +原因是,这些 segues + +1330 +00:53:24,930 --> 00:53:28,760 +are seguing now to a Navigation Controller. +现在导向 Navigation Controller + +1331 +00:53:28,760 --> 00:53:31,560 +They're not seguing directly to a HappinessViewController. +它们并没有直接导向 HappinessViewController + +1332 +00:53:31,560 --> 00:53:34,430 +So this prepare that we have right here, +所以我们在这里的 prepare + +1333 +00:53:34,430 --> 00:53:37,170 +this very first line is going to not work. +这里的第一行行不通 + +1334 +00:53:37,170 --> 00:53:38,940 +Because the destinationViewController is +因为 destinationViewController 不再是 + +1335 +00:53:38,940 --> 00:53:40,340 +no longer a HappinessController, +一个 HappinessController + +1336 +00:53:40,340 --> 00:53:41,670 +it's a Navigation Controller. +它是一个 Navigation Controller + +1337 +00:53:41,670 --> 00:53:44,770 +Everyone understand that? +每个人都明白这点吗? + +1338 +00:53:44,780 --> 00:53:46,080 +So how can we deal with that? +所以我们要怎样处理这个? + +1339 +00:53:46,080 --> 00:53:48,480 +Well, that's actually quite easy to deal with. +实际上这很容易处理 + +1340 +00:53:48,480 --> 00:53:52,280 +I'm gonna create a variable here called destination, which +我将创建一个叫做 destination 的变量 + +1341 +00:53:52,280 --> 00:53:57,850 +I'm gonna set equal to the destinationViewController as +我将这个变量等于 destinationViewController as? + +1342 +00:53:57,850 --> 00:53:59,790 +a UIViewController, +UIViewController + +1343 +00:53:59,790 --> 00:54:02,720 +cuz I know it's a UIViewController of some sort. +我知道它是某类 UIViewController + +1344 +00:54:02,730 --> 00:54:07,390 +And then I'm gonna say, if I can let navCon equal +我将说,if let navCon = destination + +1345 +00:54:07,400 --> 00:54:12,260 +the destination as a UINavigationController, +as? UINavigationController + +1346 +00:54:12,270 --> 00:54:15,500 +okay, then I'm going to set the destination to be the nav +我要让 destination = navCon + +1347 +00:54:15,500 --> 00:54:18,540 +cons, and what I want is the visible ViewController, +我要的是 visibleViewController + +1348 +00:54:18,540 --> 00:54:20,740 +the one on top of the stack. +在 stack 最上面的(Controller)。 + +1349 +00:54:20,740 --> 00:54:23,210 +Right? +对吧 + +1350 +00:54:23,210 --> 00:54:25,680 +So I'm going to say, .visibleViewController. +所以,我说的是 .visibleViewController + +1351 +00:54:25,680 --> 00:54:28,010 +So visibleViewController is just a property in +因此 visibleViewController 只是 + +1352 +00:54:28,010 --> 00:54:30,250 +UINavigationController that returns to the one +UINavigationController 的一个属性,它返回 + +1353 +00:54:30,250 --> 00:54:31,470 +that's on top of the stack, +stack 中最上面的(controller) + +1354 +00:54:31,470 --> 00:54:32,680 +which is going to be HappinessViewController, +即 HappinessViewController + +1355 +00:54:32,680 --> 00:54:34,780 +because it's the only one on the stack. +因为它是 stack 中唯一的(controller) + +1356 +00:54:34,790 --> 00:54:36,300 +Okay. And +OK + +1357 +00:54:36,300 --> 00:54:37,820 +then here, instead of saying destinationViewController +这里,不是 destinationViewController + +1358 +00:54:37,820 --> 00:54:39,490 +here, I'll just say destination. +而是 destination + +1359 +00:54:40,660 --> 00:54:42,760 +So now, if we come in here and +现在,如果我们来到这里 + +1360 +00:54:42,760 --> 00:54:44,160 +this is the HappinessViewController, +这是 HappinessViewController + +1361 +00:54:44,160 --> 00:54:46,060 +in other words, I don't have the Navigation Controller, +换句话说,我没有 Navigation Controller + +1362 +00:54:46,060 --> 00:54:47,360 +then this is not even going to happen. +那这就不会发生 + +1363 +00:54:47,360 --> 00:54:48,560 +And so it's fine. +所以这是可以的 + +1364 +00:54:48,560 --> 00:54:49,600 +This will work. +这可行 + +1365 +00:54:49,600 --> 00:54:51,060 +Otherwise, if it's a Navigation Controller, +否则,如果它是 Navigation Controller + +1366 +00:54:51,070 --> 00:54:53,530 +I'm going to pull the HappinessViewController out of +我将从中拉出 HappinessViewController + +1367 +00:54:53,530 --> 00:54:55,670 +it, and then this'll work again. +然后这就又可行了 + +1368 +00:54:55,670 --> 00:54:56,700 +So it would have worked in either case. +这在其它情况也可行 + +1369 +00:54:56,700 --> 00:54:59,400 +So this is nice, in your prepares, +所以这很好,在你的 prepares + +1370 +00:54:59,410 --> 00:55:02,210 +to make it so that if you ever think that the thing you're +这样做,以便你认为你将导向的控制器 + +1371 +00:55:02,210 --> 00:55:04,680 +segueing to might be wrapped in a Navigation Controller, +可能包裹在 Navigation Controller 中 + +1372 +00:55:04,680 --> 00:55:06,940 +this will make it so it'll work either way. +这会处理之,因此它在任何方式中都可行 + +1373 +00:55:06,950 --> 00:55:08,410 +So later, if you decide to unwrap it or +一会,如果你决定解包它或者 + +1374 +00:55:08,410 --> 00:55:09,850 +whatever, this'll work. +做其它任何操作,这依然可行 + +1375 +00:55:09,850 --> 00:55:10,750 +So let's try this. +让我们试试这个 + +1376 +00:55:13,080 --> 00:55:14,700 +All right, so +完全正确 + +1377 +00:55:14,700 --> 00:55:16,320 +we've got this Golden Bear, there's the title and +所以我选择这个 Golden Bear,这是标题 + +1378 +00:55:16,320 --> 00:55:20,460 +it's working, 100, Buckeye, that's working too. +它可以了,100,Buckeye,这也可以。 + +1379 +00:55:20,460 --> 00:55:21,020 +Okay? +OK? + +1380 +00:55:22,390 --> 00:55:23,020 +Make sense there? +有道理吧? + +1381 +00:55:24,990 --> 00:55:27,890 +All right, the last thing I want to show here is +我在这里要讲的最后一件事是 + +1382 +00:55:28,860 --> 00:55:31,860 +briefly how to do a segue in code. +在代码中如何处理 segue + +1383 +00:55:31,870 --> 00:55:34,830 +Because this segue we did with control dragging in +因为这个 segue,我们都在 Storyboard + +1384 +00:55:34,840 --> 00:55:36,800 +the Storyboard entirely. +中使用 control 拖拽实现的 + +1385 +00:55:36,800 --> 00:55:39,300 +So how would we do a segue in code? +那么我们要怎样在代码处理 segue + +1386 +00:55:39,310 --> 00:55:41,110 +So let's do a different segue here, +让我们弄个不一样的 segue + +1387 +00:55:41,110 --> 00:55:45,340 +I'm gonna add another thing to this. +我要做另一件事 + +1388 +00:55:46,750 --> 00:55:52,350 +Let's go down here and add a new button right here. +让我们到下面,在这里添加一个新的 button + +1389 +00:55:52,350 --> 00:55:54,550 +Put it in here, I'm going to call this Nothing. +把它放在这里,我把这个叫做 Nothing + +1390 +00:55:54,550 --> 00:55:56,180 +So what do I see in my dreams? +因此在我的梦中我看到了什么? + +1391 +00:55:56,190 --> 00:55:56,970 +Nothing. +Nothing + +1392 +00:55:56,970 --> 00:55:57,750 +I don't see anything. +我什么也没看到 + +1393 +00:55:57,750 --> 00:55:59,650 +Okay and I am going to put that here. +我要把它放在这里 + +1394 +00:55:59,660 --> 00:56:03,220 +I'm going to try Reset to Suggested Constraints. +我选择 Reset to Suggested Constraints + +1395 +00:56:03,230 --> 00:56:04,590 +I'm going to check to see what it did. +我要检查看看它做了什么 + +1396 +00:56:04,590 --> 00:56:06,830 +That looks perfectly fine to me. +对我来说,它看起来非常好 + +1397 +00:56:06,830 --> 00:56:08,760 +I'm rocking! +我很6! + +1398 +00:56:08,760 --> 00:56:10,700 +But instead of control dragging from here to make +但不是在这里用 control 拖拽以创建 + +1399 +00:56:10,700 --> 00:56:13,730 +this segue, I'm just going to create a normal target +segue,我将创建一个普通的目标 + +1400 +00:56:13,740 --> 00:56:14,330 +action method. +action 方法 + +1401 +00:56:15,270 --> 00:56:17,000 +Okay. +好的 + +1402 +00:56:17,000 --> 00:56:18,740 +So this is I'm just gonna make this be a completely normal +所以这就是我完全将这个当作普通的 + +1403 +00:56:18,740 --> 00:56:22,410 +button that's going to do target action from here. +button,它将从这里做一个目标 action + +1404 +00:56:22,410 --> 00:56:24,140 +Okay, so let's make some space over here in our +让我们在我们的 PsychologistViewController + +1405 +00:56:24,140 --> 00:56:25,240 +PsychologistViewController. +腾出些空间 + +1406 +00:56:25,240 --> 00:56:28,380 +I'm gonna Ctrl+drag over to here. +要将 Ctrl+drag 到这里 + +1407 +00:56:28,380 --> 00:56:29,650 +Okay, it's gonna be an action. +这将是个 action + +1408 +00:56:29,650 --> 00:56:33,950 +I'm gonna call it the nothing action. +我把这个命名为 nothing action + +1409 +00:56:33,950 --> 00:56:37,350 +I'm gonna have the center be a UI button, and Connect. +我将让中间是一个 UI button,然后连接 + +1410 +00:56:37,360 --> 00:56:39,150 +So now every time I click on Nothing, +现在每次我点击 Nothing + +1411 +00:56:39,160 --> 00:56:42,860 +it's going to do this target action right here. +它将执行这里的目标 action + +1412 +00:56:42,860 --> 00:56:45,890 +And what I wanna do inside here is cause a segue +在这个里面我想做的是,产生一个 + +1413 +00:56:45,900 --> 00:56:47,130 +to happen. +segue + +1414 +00:56:47,130 --> 00:56:49,300 +Okay? +OK? + +1415 +00:56:49,300 --> 00:56:51,470 +So base this segue in code, so how am I gonna do that? +所以在代码中有这个 segue,这样我要怎么做呢? + +1416 +00:56:51,470 --> 00:56:56,570 +Well, I still have to create the segue in the Storyboard. +我依然要在 Storyboard 中创建 segue + +1417 +00:56:56,570 --> 00:56:59,210 +Okay, so I'm still going to go back here and +所以我还得回到这里 + +1418 +00:56:59,210 --> 00:57:00,870 +create the segue, but +然后创建这个 segue + +1419 +00:57:00,880 --> 00:57:02,540 +the question is where do I create the segue from? +但问题是,我从哪里创建这个 segue? + +1420 +00:57:02,540 --> 00:57:03,710 +Where do I drag from? +我从哪里拖拽? + +1421 +00:57:03,710 --> 00:57:06,550 +Since I don't want this to directly cause it, +因为我不想这个直接创建它 + +1422 +00:57:06,550 --> 00:57:08,580 +and the answer is, I drag from this little thing up here. +答案是,我从这上面的这个小图标开始拖拽 + +1423 +00:57:08,580 --> 00:57:10,220 +Do you see this little yellow guy? +你们看到这个小小的黄色图标吗? + +1424 +00:57:10,220 --> 00:57:13,250 +This yellow thing represents the ViewController. +这个黄色的东西代表这个 ViewController + +1425 +00:57:13,250 --> 00:57:14,850 +So, when you're setting up a segue that's gonna be +当你创建一个 segue 时, + +1426 +00:57:14,850 --> 00:57:16,150 +fired off in code, +它会在代码中生成 + +1427 +00:57:16,160 --> 00:57:19,060 +you do the control drag from this little yellow thing. +我从这个黄色的东西开始拖拽 + +1428 +00:57:19,060 --> 00:57:20,890 +So, let's go down here. +让我们来到下面这里 + +1429 +00:57:20,890 --> 00:57:23,840 +Okay? +OK? + +1430 +00:57:23,840 --> 00:57:26,800 +I'm gonna take this guy and I'm gonna control drag over to +我将带着这个,我要拖拽到 + +1431 +00:57:26,800 --> 00:57:29,060 +here, to this Navigation Controller. +这里,到这个 Navigation Controller + +1432 +00:57:29,070 --> 00:57:31,370 +Sorry for the screen resolution there. +我为这个屏幕分辨率感到抱歉 + +1433 +00:57:31,370 --> 00:57:34,070 +It's still gonna be a show detail segue. +它依然是个 show detail segue + +1434 +00:57:34,070 --> 00:57:35,940 +I'm going to now zoom out. +现在我要缩小 + +1435 +00:57:38,310 --> 00:57:40,140 +Okay, let's find this thing. +让我们找到这个 + +1436 +00:57:40,140 --> 00:57:46,450 +It's not that one, it's not that one, it's this one. +它不是那个,不是那个,是这个 + +1437 +00:57:46,450 --> 00:57:48,250 +And so notice that when I select this one, +注意了,当我选择这个时 + +1438 +00:57:48,250 --> 00:57:51,150 +it's showing the whole View Controller sending this, and +可以看到,整个 View Controller 发送这个 + +1439 +00:57:51,150 --> 00:57:56,050 +so we will call this the nothing segue. +我们把这个叫做 nothing segue + +1440 +00:57:57,060 --> 00:57:59,120 +Okay, so now we have this segue named nothing, +现在我们有了这个叫做 nothing 的 segue + +1441 +00:57:59,130 --> 00:58:02,160 +it's not hooked up to any button or anything like that. +它没有和任何 button 关联,或和其他按钮关联 + +1442 +00:58:02,160 --> 00:58:06,330 +Okay, but if I go over to my PsychologistViewController, +但如果我来到我的 PsychologistViewController + +1443 +00:58:06,330 --> 00:58:09,870 +now in nothing I can say, let's make this nice and wide, +现在在 nothing 里,让我们把这个变好变宽 + +1444 +00:58:09,870 --> 00:58:15,400 +performSegueWithIdentifier the nothing segue. +performSegueWithIdentifier ("nothing", + +1445 +00:58:15,410 --> 00:58:18,940 +And the sender, we could make it be the button or +sender : sender),我们可以让它为 button 或 + +1446 +00:58:18,940 --> 00:58:21,340 +we could make this actually be self, so +实际上我们可以用 self + +1447 +00:58:21,350 --> 00:58:23,550 +that the view control itself could be the sender. +因此 View Controller 本身可以作为 sender + +1448 +00:58:23,550 --> 00:58:25,280 +Or we could make it be nil. +或者我们可以让它为 nil + +1449 +00:58:25,280 --> 00:58:26,550 +Okay? + +1450 +00:58:26,550 --> 00:58:28,780 +But this sender, whatever we put here is just going to get +但这个 sender,当我们有机会 prepare 时, + +1451 +00:58:28,780 --> 00:58:31,690 +passed along when we get a chance to prepare. +我们放在这里的任何东西都将被传递 + +1452 +00:58:31,690 --> 00:58:34,890 +Because this segue, even though we are executing it +因为这个 segue,即使我们在代码中 + +1453 +00:58:34,890 --> 00:58:37,420 +from code, is still going to get a chance to prepare. +执行它,它依然有机会 prepare + +1454 +00:58:37,430 --> 00:58:41,190 +So if we went down here and said case nothing, +如果我们来到下面这里,case nothing + +1455 +00:58:41,200 --> 00:58:44,560 +maybe the happiness there is not very happy, +那里的 happiness 可能并不高兴 + +1456 +00:58:44,570 --> 00:58:47,830 +okay, then you can still prepare down here. +然后你依然可以从下面这里 prepare + +1457 +00:58:47,840 --> 00:58:49,570 +So even though we are doing it in code, +即使我们在代码中做这个 + +1458 +00:58:49,570 --> 00:58:50,640 +it's still going to prepare. +它依然会 prepare + +1459 +00:58:52,140 --> 00:58:53,900 +All right, so let's go take a look at that. +让我们看看那个 + +1460 +00:58:55,340 --> 00:58:57,890 +Back to our iPad here. +回到我们的 iPad + +1461 +00:58:57,890 --> 00:59:00,440 +So there's happy, sad, and here's nothing. +这里有 happy,sad,这里是 nothing + +1462 +00:59:00,450 --> 00:59:01,110 +'Kay? +OK? + +1463 +00:59:03,180 --> 00:59:04,480 +Make sense? +说的通吧? + +1464 +00:59:04,480 --> 00:59:05,780 +So you can do things from code. +所以你可以在代码中做些事情 + +1465 +00:59:05,780 --> 00:59:07,080 +Now why would you ever wanna do it in code? +但为什么你想在代码中处理这个? + +1466 +00:59:07,080 --> 00:59:10,150 +Well, maybe you want to have a button clicked, and then, +你可能想让一个 button 被点击,然后 + +1467 +00:59:10,150 --> 00:59:11,720 +depending on the state of something, +根据一些东西的状态 + +1468 +00:59:11,720 --> 00:59:14,590 +it'll do one segue versus doing another segue. +它会处理一个 segue 相对另一个 segue + +1469 +00:59:14,590 --> 00:59:17,320 +So you can have a little if then there that performs one +你可以用少些代码,如果要执行两个 + +1470 +00:59:17,330 --> 00:59:18,830 +of two different segues. +不同 segue 中的一个 + +1471 +00:59:18,830 --> 00:59:20,160 +That's a classic reason you might want to +这是个经典理由,为什么你可能想在 + +1472 +00:59:20,160 --> 00:59:23,360 +do segues in code +代码中使用 segue + +1473 +00:59:23,360 --> 00:59:26,570 +versus just control dragging directly from the button. +而不是直接从 button control 拖拽生成 + +1474 +00:59:26,570 --> 00:59:28,720 +All right? +有问题吗? + +1475 +00:59:28,720 --> 00:59:30,870 +I believe that's all I wanted to cover today on that, yes. +我相信这是我今天要讲解的有关 (Navigation Controller)所有内容了 + +1476 +00:59:30,870 --> 00:59:35,140 +So now we'll go talk about popovers, so +现在让我们谈谈 popovers + +1477 +00:59:35,140 --> 00:59:38,840 +let's go back to our slides here. +让我们回到我们的幻灯片 + +1478 +00:59:42,720 --> 00:59:43,880 +All right, popovers. +popovers + +1479 +00:59:45,150 --> 00:59:50,050 +So I don't talk about popovers with the other three, because +我们没有和其他三个一起讲 popovers,因为 + +1480 +00:59:50,050 --> 00:59:51,920 +it's a little bit different, a popover's a little different. +它有点不一样,popover 是不一样的 + +1481 +00:59:51,920 --> 00:59:54,860 +So here is a UI that has a popover in it. +这是有一个 popover 的 UI + +1482 +00:59:54,860 --> 00:59:56,690 +This is the calendar app. +这是日历 app + +1483 +00:59:56,690 --> 00:59:59,290 +And you can see the popover is that whole area there where +你可以看到 popover,就是我在 + +1484 +00:59:59,300 --> 01:00:01,960 +I'm searching in my calendar trying to find something. +在我的日历中搜索一些东西的整个区域 + +1485 +01:00:01,960 --> 01:00:04,580 +Okay. +OK + +1486 +01:00:04,580 --> 01:00:07,200 +So that whole popover, that little lighter colored area in +因此整个 popover,在右上角的 + +1487 +01:00:07,200 --> 01:00:10,740 +the upper righthand corner, that is all one MVC. +有点颜色的区域,这是个 MVC + +1488 +01:00:10,740 --> 01:00:15,040 +It's the search for appointment MVC, okay? +这个搜索是为了 appointment MVC + +1489 +01:00:15,040 --> 01:00:18,640 +So and it completely fills that popover space. +所以它完全占据了 popover 的空间 + +1490 +01:00:18,650 --> 01:00:21,410 +Now, notice that the popover also has kind of +现在,注意 popover 也有类似的 + +1491 +01:00:21,420 --> 01:00:22,380 +a little arrow. +小箭头 + +1492 +01:00:22,380 --> 01:00:23,350 +You see that tiny little arrow? +你们看到这个小小的箭头了吗? + +1493 +01:00:23,350 --> 01:00:25,020 +It's just like a little white triangle. +它像一个小的白色三角形 + +1494 +01:00:25,020 --> 01:00:27,990 +That's pointing to whatever caused this to come up. +它指向让它出现的任何(view) + +1495 +01:00:27,990 --> 01:00:29,500 +So in this case, +所以在这个例子中 + +1496 +01:00:29,510 --> 01:00:31,020 +that little thing that looks like a magnifying glass, +这个小东西像个放大镜 + +1497 +01:00:31,020 --> 01:00:33,690 +that's what the user must have pressed on in order to +用户必须点击这个 + +1498 +01:00:33,690 --> 01:00:37,290 +have this pop-over for searching come up. +然后这个搜索用的 popover 才会出现 + +1499 +01:00:37,300 --> 01:00:39,050 +Right? +对吧 + +1500 +01:00:39,050 --> 01:00:40,800 +Now notice the rest of the screen here is gray, +注意现在屏幕上的其他地方是灰色的 + +1501 +01:00:40,800 --> 01:00:42,260 +except for the keyboard, is gray. +除了键盘,都是灰色的 + +1502 +01:00:42,270 --> 01:00:43,730 +See it's kind of grayed out? +像是灰色的在外面? + +1503 +01:00:43,730 --> 01:00:46,070 +And it's also if you tried to click in there, +如果你试图在灰色区域点击 + +1504 +01:00:46,070 --> 01:00:47,640 +it wouldn't work. +是行不通的 + +1505 +01:00:47,640 --> 01:00:49,200 +Like if you tried to click on the Week button at the top, +如果你试图点击顶部的 Week button + +1506 +01:00:49,210 --> 01:00:51,670 +or the Month button or the Year button it wouldn't work. +或者 Month button,或者 Year button,都不行 + +1507 +01:00:51,680 --> 01:00:56,240 +But what it would do is dismiss the popover, okay? +它能做的是让 popover 消失 + +1508 +01:00:56,250 --> 01:00:58,910 +So that grey area, so you can see that it's not as +所以灰色区域,你可以看到,没有和 + +1509 +01:00:58,910 --> 01:01:02,580 +bad as take over the screen, but it's still the case that I +占据整个屏幕一样糟糕,但依然是这种情况 + +1510 +01:01:02,580 --> 01:01:04,920 +can only do what the popover is asking me to do. +我只能做 popover 要我做的事情 + +1511 +01:01:04,920 --> 01:01:07,020 +I can't do anything else until I dismiss the popover but +直到我关闭 popover 我才能做其他事情 + +1512 +01:01:07,020 --> 01:01:09,490 +it's just really, really easy to see what the rest of +在你把 popover 放在最上面前,很容易看 + +1513 +01:01:09,490 --> 01:01:11,860 +what was going on before you brought the popover up, +其他都在做什么 + +1514 +01:01:11,860 --> 01:01:14,860 +and it's usually easy to get rid of the popover. +通常地,很容易就可以关闭 popover + +1515 +01:01:14,860 --> 01:01:16,390 +Now, the interesting thing about popover, and +关于 popover 有趣的事情是 + +1516 +01:01:16,400 --> 01:01:17,900 +the reason I talk about it differently, +我说它不同的原因是 + +1517 +01:01:17,900 --> 01:01:20,000 +is that it's not a UIViewController. +它不是一个 UIViewController + +1518 +01:01:21,070 --> 01:01:22,800 +Okay. Popover is itself, +Popover 就是 popover + +1519 +01:01:22,800 --> 01:01:24,670 +not a UIViewController. +不是一个 UIViewController + +1520 +01:01:24,670 --> 01:01:26,650 +It's brought on +它是通过一个叫做 + +1521 +01:01:26,650 --> 01:01:28,640 +screen using what's called a PresentationController. +PresentationController 来出现在屏幕上的 + +1522 +01:01:28,640 --> 01:01:30,810 +And I'm not really going to talk about presentation +我不是真的要讲 PresentationController + +1523 +01:01:30,810 --> 01:01:33,440 +controller, just a little bit about the PopoverPresentationController +只是一点有关 PopoverPresentationController 的内容 + +1524 +01:01:33,440 --> 01:01:36,610 +but it's the underlying mechanism that all +但是这是所有这些东西基于的 + +1525 +01:01:36,610 --> 01:01:40,050 +of this stuff is based on, so popover doesn't really need to +底层机制,因此 popover 并不真的需要 + +1526 +01:01:40,050 --> 01:01:43,320 +have a ViewController whose view is this MVC. +一个 ViewController,它的 view 是这个 MVC + +1527 +01:01:44,290 --> 01:01:46,370 +It can do it +它能由 + +1528 +01:01:46,370 --> 01:01:48,460 +purely with the presentation controller mechanism. +PresentationController 机制纯粹做到这一点 + +1529 +01:01:48,460 --> 01:01:50,720 +So let's talk about the popover then, +让我们谈谈 popover + +1530 +01:01:50,730 --> 01:01:53,230 +and how we make it work, because the interesting of +还有我们是怎样让它工作的,由于强大的 popover 很有趣 + +1531 +01:01:53,230 --> 01:01:56,860 +Power Popover that even though it's not its own MVC, +即使它不是自己的 MVC + +1532 +01:01:56,860 --> 01:02:00,030 +it still segues and all that stuff exactly the same. +它依然可以 segue,还有所有和此相关的 + +1533 +01:02:00,030 --> 01:02:02,900 +You still Ctrl+drag to some View Controller. +你依然可以 Ctrl+拖拽到一些 View Controller + +1534 +01:02:02,900 --> 01:02:04,570 +You still get to do prepareForSegue. +你依然可以处理 prepareForSegue. + +1535 +01:02:04,570 --> 01:02:06,770 +It all looks exactly the same because it's still doing +它看起来完全一样,因为它依然可以 segue + +1536 +01:02:06,770 --> 01:02:08,840 +segues even though it's not its own View Controller. +即使它不是自己的 View Controller + +1537 +01:02:08,840 --> 01:02:11,540 +It's still using segues to cause it to appear. +它依然使用 segue,让它出现 + +1538 +01:02:13,280 --> 01:02:17,310 +So, things to note when you're preparing for a segue here. +需要注意的是,当你在这为一个 segue 做 prepare 时, + +1539 +01:02:17,310 --> 01:02:22,950 +One is that inside your preparer you +一个是在你的 preparer 中, + +1540 +01:02:22,950 --> 01:02:26,250 +can get ahold of what's called the presentation controller. +你可以获取到 PresentationController. + +1541 +01:02:26,260 --> 01:02:28,390 +And the presentation controller for +这个创建 popover 的 PresentationController + +1542 +01:02:28,390 --> 01:02:31,960 +a popover will tell you things like what's the button that +将告诉你一些事情,比如是哪个 button + +1543 +01:02:31,960 --> 01:02:34,060 +brought this popover up. +带出了这个 popover + +1544 +01:02:34,060 --> 01:02:37,200 +And you can even configure the presentation like I don't want +你甚至可以配置这个 presentation,比如我不想 + +1545 +01:02:37,200 --> 01:02:40,430 +this popover to pop up to the left of anything. +让这个 popover 出现在左边 + +1546 +01:02:40,440 --> 01:02:43,000 +I always want it on the right side of something. +我想让它总在右边 + +1547 +01:02:43,000 --> 01:02:44,740 +So you can even control that. +你甚至可以控制这个 + +1548 +01:02:44,740 --> 01:02:48,310 +And very interestingly using the presentation controller's +PresentationController 的 delegate 非常有趣 + +1549 +01:02:48,310 --> 01:02:49,740 +delegate, this is the first time we +这是我们在这个课程上第一次 + +1550 +01:02:49,740 --> 01:02:51,940 +have talked about a delegate in iOS in this class, +谈论 iOS 中的 delegate + +1551 +01:02:51,950 --> 01:02:54,450 +although we'll gonna talk about it in slides next week. +虽然我们会在下周的 slides 中讲这个 + +1552 +01:02:56,780 --> 01:02:59,280 +Using the presentation controller's delegate, +使用 PresentationController 的 delegate + +1553 +01:02:59,280 --> 01:03:04,050 +you can affect how the popover adapts to being on an iPhone. +你可以调整 popover 以在 iPhone 上适配 + +1554 +01:03:04,060 --> 01:03:08,960 +So a popover on an iPad pops up like you saw in +popover 在 iPad 上出现,如你们在刚才 + +1555 +01:03:08,960 --> 01:03:10,660 +the previous screen there. +的屏幕上看到的 + +1556 +01:03:10,660 --> 01:03:12,260 +A little window that pops up. +一个小的窗口出现了 + +1557 +01:03:12,260 --> 01:03:14,500 +Well on the iPhone it adapts and +在 iPhone 上它被调整了 + +1558 +01:03:14,500 --> 01:03:17,930 +instead does modal, full-screen, okay? +成为了 modal 的全屏模式 + +1559 +01:03:17,930 --> 01:03:22,200 +So it doesn't pop up as a little thing on an iPhone. +所以在 iPhone 上它不是以一个小的窗口出现 + +1560 +01:03:22,200 --> 01:03:23,370 +And why is that? +为什么这样 + +1561 +01:03:23,370 --> 01:03:24,540 +Well, the iPhone's smaller and +好吧,iPhone 比较小 + +1562 +01:03:24,540 --> 01:03:27,670 +so if the thing you're popping up is really big, +所以如果你要弹出的 popover 很大 + +1563 +01:03:27,680 --> 01:03:30,110 +there might be no way to cram it in there and make it fit. +可能没有办法把它塞进去,让它适合 + +1564 +01:03:31,180 --> 01:03:33,240 +But if you present full screen modal, +但如果你展示为全屏的 modal 模式 + +1565 +01:03:33,250 --> 01:03:34,810 +it's definitely going to fit. +它肯定适合 + +1566 +01:03:34,810 --> 01:03:37,620 +Okay, so it automatically does this. +它自动为你处理了这个 + +1567 +01:03:37,620 --> 01:03:39,680 +iOS automatically does this adaptation for you, +iOS 自动为你进行了适配 + +1568 +01:03:39,690 --> 01:03:42,450 +just like it automatically adapts to Split View and +就像他自动适配 SplitView 和 + +1569 +01:03:42,450 --> 01:03:45,260 +Navigation Controller if you build your Storyboard right +Navigation Controller,如果你在 iPhone + +1570 +01:03:45,260 --> 01:03:48,730 +on iPhone, but using the delegate or the presentation +创建 Storyboard,使用 delegate 或 PresentationController + +1571 +01:03:48,730 --> 01:03:51,530 +control, you can actually affect that adaptation. +你可以调整这个适配 + +1572 +01:03:51,530 --> 01:03:54,130 +Okay. So, here is a brief slide. +接下来有几张幻灯片 + +1573 +01:03:54,130 --> 01:03:57,100 +We'll have a brief slide that talks about that in a second. +一会我们再来讲这个 + +1574 +01:03:57,100 --> 01:03:59,900 +But, first I want to show you how in prepareForSegue you +但首先我想向你们展示如何在 prepareForSegue + +1575 +01:03:59,900 --> 01:04:02,800 +get a hold of that popover presentation controller and +取得 PopoverPresentationController + +1576 +01:04:02,810 --> 01:04:04,270 +you can do something like set this delegate. +并且设置它的 delegate + +1577 +01:04:04,270 --> 01:04:07,470 +So this prepareForSegue all of the green is basically +这个 prepareForSegue,绿色部分和你在 + +1578 +01:04:07,480 --> 01:04:10,480 +the same as you would have in any other prepare for segue. +其他任何 prepareForSegue 中做的基本上一样 + +1579 +01:04:10,480 --> 01:04:13,950 +But the yellow line there is where I am, +黄色这行,代表我正在 + +1580 +01:04:13,950 --> 01:04:17,220 +from the View Controller that I'm segue-ing to, +从 ViewController 中我将 segue 到它那里去 + +1581 +01:04:17,220 --> 01:04:20,520 +I'm asking for it's popover presentation controller. +我请求它的 PopoverPresentationController. + +1582 +01:04:20,520 --> 01:04:22,240 +'Kay? +OK? + +1583 +01:04:22,240 --> 01:04:23,960 +So this is an object, the presentation controller, +这是个对象,PresentationController. + +1584 +01:04:23,960 --> 01:04:26,090 +that will only come back non-nil, here, +如果我是通过 popover segue 来的 + +1585 +01:04:26,090 --> 01:04:28,660 +if I'm being segued via popover. +它将只能返回非 nil + +1586 +01:04:28,660 --> 01:04:30,190 +If I'm being segued some other way, +如果我是通过其他方式 segue + +1587 +01:04:30,200 --> 01:04:33,460 +like just pushing in a Navigation Controller, or +比如在 Navigation Controller 被 push + +1588 +01:04:33,470 --> 01:04:35,600 +something like that, then this'll come back nil, and +或类似这的其他方式,那么这将返回 nil + +1589 +01:04:35,600 --> 01:04:37,670 +I'm just gonna ignore it, cuz I do if let right there. +我将忽略这个,因为我在那里做 if let 判断 + +1590 +01:04:38,840 --> 01:04:40,840 +But if it is popover, then I make it this popover +但如果它是 popover,那么我将让它等于这个 + +1591 +01:04:40,840 --> 01:04:42,200 +presentation controller and if you go look in +popoverPresentationController,如果你查看 + +1592 +01:04:42,210 --> 01:04:44,910 +the documentation for popover presentation controller, +PopoverPresentationController 的文档 + +1593 +01:04:44,910 --> 01:04:46,810 +you'll see it has some things you can configure about +你可以看到,有些东西你可以配置 + +1594 +01:04:46,810 --> 01:04:49,580 +the presentation like the permitted arrow directions, +比如允许剪头方向 + +1595 +01:04:49,580 --> 01:04:50,580 +that little white triangle. +那个小的白色三角形 + +1596 +01:04:50,580 --> 01:04:52,180 +Where is that allowed to point? +允许它指向哪里? + +1597 +01:04:52,180 --> 01:04:53,350 +In what direction? +在哪个方向上? + +1598 +01:04:53,350 --> 01:04:55,380 +And you can also set yourself, +你也可以设置你自己 + +1599 +01:04:55,380 --> 01:04:58,180 +the controller, you know you add the controller as +这个 controller,你把 controller 作为 + +1600 +01:04:58,190 --> 01:05:00,120 +the delegate of the presentation controller. +PresentationController 的 delegate + +1601 +01:05:00,120 --> 01:05:02,420 +Okay, so +好的
 + +1602 +01:05:02,420 --> 01:05:06,860 +when you set yourself as the delegate, what can you do? +当设置自身为 delegate 时,你可以做些什么呢?
 + +1603 +01:05:06,860 --> 01:05:08,560 +What is it going to offer to let you do? +你可以做些什么呢?
 + +1604 +01:05:08,560 --> 01:05:09,860 +Well, there's number of things, but +事实上,有很多事可做 + +1605 +01:05:09,860 --> 01:05:12,760 +I'm gonna talk about this adaptation behavior. +我会讲适配特性 + +1606 +01:05:12,770 --> 01:05:15,270 +So here's two methods that are in the protocol for +对于 delegete 可以实现协议中 + +1607 +01:05:15,270 --> 01:05:17,070 +the delegate there. +的两个
方法
 + +1608 +01:05:17,070 --> 01:05:19,340 +One is called adapter presentation, +一个是 + +1609 +01:05:19,340 --> 01:05:22,210 +presentation style for presentation controller. +adaptivePresentationStyleForPresentationController + +1610 +01:05:22,210 --> 01:05:26,540 +Okay, so when the popover is trying to present, it's going +没错,当 popover 将要弹出来的时候 + +1611 +01:05:26,540 --> 01:05:30,810 +to ask you, how do you want me to adapt if I'm on an iPhone? +这个方法会问你,我在 iPhone 上要怎样适配呢?
 + +1612 +01:05:31,980 --> 01:05:35,980 +Now by default, this is going to say full screen modal, but +默认会以 modal 方式全屏显示 + +1613 +01:05:35,990 --> 01:05:39,320 +you can say you want modal presentation style none +但你可以将展示风格设置为 none
 + +1614 +01:05:39,320 --> 01:05:42,060 +which means don't adapt. +表示不需要适配
 + +1615 +01:05:42,060 --> 01:05:44,490 +So presented on the iPhone exactly like you do +这样就和 iPad 上的展示方式 + +1616 +01:05:44,490 --> 01:05:46,090 +on the iPad. +一样
了
 + +1617 +01:05:46,090 --> 01:05:48,460 +Okay, so for +是的 + +1618 +01:05:48,460 --> 01:05:50,830 +a small popover, this makes a lot of sense, okay. +对于小的 popover 这并没问题
。 + +1619 +01:05:50,830 --> 01:05:52,460 +So this is how you can basically turn off +这是你怎样关闭适配特性
 + +1620 +01:05:52,470 --> 01:05:53,970 +that adaptation behavior. +的方法
 + +1621 +01:05:53,970 --> 01:05:55,970 +You can even go way more powerful than that, +还有更强大的方法 + +1622 +01:05:55,970 --> 01:05:57,900 +the other one here presentationController view, +这里还有一个 + +1623 +01:05:57,900 --> 01:06:00,270 +viewControllerForAdaptedPresentationStyle, +presentationController(viewControllerForAdaptedPresentationStyle:) 方法 + +1624 +01:06:00,270 --> 01:06:04,210 +you can return a whole other MVC on the iPhone. +用来在 iPhone 上展示一个完整的 MVC + +1625 +01:06:04,210 --> 01:06:06,580 +That displays your MVC in a totally different way +那会以另一种完全不同显示方式 + +1626 +01:06:06,580 --> 01:06:09,110 +maybe it's wrapped in a Navigation Controller or +可能被包含在 Navigation Controller 中或
 + +1627 +01:06:09,110 --> 01:06:10,410 +it can be completely different. +其他不同的形式
 + +1628 +01:06:10,420 --> 01:06:13,980 +So you can really customize it but I just wanted to +你完全可以各种自定义 + +1629 +01:06:13,990 --> 01:06:16,590 +show the this first one because it's common to say oh +但我只想展示第一种 + +1630 +01:06:16,590 --> 01:06:18,590 +I just have this small little pop over thing. +因为这种展示方式是很常见的 + +1631 +01:06:18,590 --> 01:06:20,460 +I want it to look like a pop over on an iPhone and +我想要在 iPhone 上显示像 popover
 的 popover + +1632 +01:06:20,460 --> 01:06:21,320 +this is how you do that. +你需要这么做 + +1633 +01:06:22,560 --> 01:06:23,990 +Okay. +好的
 + +1634 +01:06:23,990 --> 01:06:28,290 +The last thing about popover that's important is the size. +poover 最后一个重要的部分是尺寸 + +1635 +01:06:28,300 --> 01:06:31,000 +So you'd really like the popover to come up and +你想要 popover 显示的尺寸
 + +1636 +01:06:31,000 --> 01:06:33,870 +be exactly the right size to fit the MVC +正确地适配到 MVC 中
 + +1637 +01:06:33,870 --> 01:06:37,200 +because your MVC might be different sizes, okay? +因为你 MVC 可能不同,明白吗?
 + +1638 +01:06:37,200 --> 01:06:39,940 +Even as a given MVC might be different sizes and so +甚至当特定的 MVC 有不同尺寸
 + +1639 +01:06:39,940 --> 01:06:41,940 +you really wanna be able to control the size. +而且你希望能控制这个尺寸
 + +1640 +01:06:41,940 --> 01:06:44,410 +And in a really object oriented way, +用一种面向对象的方式
 + +1641 +01:06:44,410 --> 01:06:48,110 +the way the system does that, is it asks the MVC that is in +也就是系统所用的方式,会询问 MVC + +1642 +01:06:48,110 --> 01:06:50,880 +the popover what is your preferred size? +合适的尺寸是多少? + +1643 +01:06:50,880 --> 01:06:54,620 +What would you like to be if I could grant your wish, +如果我满足你的愿望,让你来指定尺寸 + +1644 +01:06:54,620 --> 01:06:57,320 +what would you like to be, okay? +你希望是多少,明白吗?
 + +1645 +01:06:57,320 --> 01:07:00,320 +So it's cuz only that MVC really knows what +所以只有 MVC 才知道
 + +1646 +01:07:00,330 --> 01:07:03,190 +its preferred or ideal size might be. +最理想的尺寸
 + +1647 +01:07:03,190 --> 01:07:04,990 +Now that's only a recommendation because +不过这只被作为参考建议,因为 + +1648 +01:07:05,000 --> 01:07:07,130 +the popover has some constraints as well, right? +popover 自身也有一些约束,明白吗?
 + +1649 +01:07:07,130 --> 01:07:10,570 +Because it can only appear in certain places on screen, and +因为它只能出现在屏幕的特定区域 + +1650 +01:07:10,570 --> 01:07:13,940 +the screen is only so big, and those arrows might have to go +而屏幕只有这么大,箭头要指向
 + +1651 +01:07:13,940 --> 01:07:16,970 +a certain direction, they might be restricted, so +特定方向,它们或许被
限制了,所以 + +1652 +01:07:16,970 --> 01:07:20,070 +the popover has got its own things to deal with. +popover 也要考虑自身的约束 + +1653 +01:07:20,080 --> 01:07:25,080 +But it's going to ask the MVC it's putting inside of +但是它会询问其中的 MVC + +1654 +01:07:25,080 --> 01:07:27,080 +itself what would you like to be? +应该怎样展示呢? + +1655 +01:07:27,080 --> 01:07:30,620 +And so this is just a property in your UIViewController. +这只是 UIViewController 的一个属性
 + +1656 +01:07:30,620 --> 01:07:33,650 +You can, for example, override this. +你可以重写它
 + +1657 +01:07:33,650 --> 01:07:34,920 +Okay. Override the property and +好的,重写这个属性
 + +1658 +01:07:34,920 --> 01:07:36,820 +return your preferred size. +并返回合适的尺寸
 + +1659 +01:07:36,820 --> 01:07:38,190 +Or you can set. +或者你可以直接设置
 + +1660 +01:07:38,190 --> 01:07:39,220 +It's a settable property so +这个属性是可以 set 的 + +1661 +01:07:39,230 --> 01:07:41,230 +you can set your preferred size. +所以你可以设置你希望的尺寸
 + +1662 +01:07:41,230 --> 01:07:44,930 +If your preferred size is always an exact size just set +如果你的尺寸是固定的
 + +1663 +01:07:44,930 --> 01:07:46,400 +your preferred size to that. +直接 set 它就可以了
 + +1664 +01:07:46,400 --> 01:07:48,530 +Or, if you have to calculate your preferred size based on +或者,你必须根据 MVC 的内容 + +1665 +01:07:48,530 --> 01:07:50,470 +what your content is, which you're going to +计算合适的尺寸 + +1666 +01:07:50,470 --> 01:07:54,100 +see in the demo that I'm going to show about popovers +你一会儿将会看到 + +1667 +01:07:54,100 --> 01:07:58,370 +in a moment here, than you can override it, +我如何在案例中
 + +1668 +01:07:58,380 --> 01:08:00,370 +which is what I did in that demo. +重写属性 + +1669 +01:08:00,380 --> 01:08:03,340 +'Kay, so, we're gonna have +好的,我们会
 + +1670 +01:08:03,350 --> 01:08:08,010 +a demo here which is adding a popover to psychologists. +在案例的时候为 Psychologists 添加 popover
 + +1671 +01:08:08,020 --> 01:08:09,750 +Popovers I +Popover 会 + +1672 +01:08:09,750 --> 01:08:11,480 +made them extra credit on your homework assignment. +给你额外的分数 + +1673 +01:08:12,620 --> 01:08:15,350 +So you don't have to do them but I recommend doing it cuz +虽然你不需要做这个,但是我还是推荐你做
 + +1674 +01:08:15,360 --> 01:08:17,620 +it's a good experience to make a popover. +因为做 popover 的体验很有趣
。 + +1675 +01:08:17,620 --> 01:08:18,920 +Okay, it is something. +好的
 + +1676 +01:08:20,190 --> 01:08:22,890 +If I had enough kind of room in your assignment to +如果我觉得你的作业还有提升的空间
 + +1677 +01:08:22,900 --> 01:08:25,100 +fit popovers, I wouldn't have made it extra credit, but +我不会给你额外的学分,但是
 + +1678 +01:08:25,100 --> 01:08:28,130 +I just feel I have only given you one week's worth of work, +由于这只是一周的作业
 + +1679 +01:08:28,130 --> 01:08:29,930 +I don't want to over burden you, +我不想你们有太多负担
 + +1680 +01:08:29,930 --> 01:08:31,730 +but this is an extra credit you really want to try to do, +但这个额外的分数很值得你尝试,
 + +1681 +01:08:31,740 --> 01:08:33,720 +I think, if you can. +如果你可以的话
 + +1682 +01:08:33,720 --> 01:08:35,700 +Because in your final project, you're almost certainly going +因为在期末项目上,你很可能会
 + +1683 +01:08:35,710 --> 01:08:39,140 +to have some reason, hopefully to put a popover in there. +使用到 popover
 + +1684 +01:08:39,140 --> 01:08:42,140 +Okay now before I do the demo let me talk about +在我做 demo 之前我想讲一下
 + +1685 +01:08:42,150 --> 01:08:45,110 +what's coming up because I never go back to the slides. +接下来的内容,因为我不会再展示这个 slide + +1686 +01:08:45,120 --> 01:08:48,150 +Friday we are gonna have that Friday section again for +星期五的部分
 + +1687 +01:08:48,150 --> 01:08:51,650 +IT & T people sorry it's not gonna be on video. +不会录制课程
 + +1688 +01:08:51,650 --> 01:08:54,060 +It's not in a room that we can do the video in really. +因为是在另外一个教室,我们无法录制课程 + +1689 +01:08:54,060 --> 01:08:57,360 +So that should be a good one. +那应该是不错的内容 + +1690 +01:08:57,360 --> 01:08:59,490 +And that's also an extra credit item in +这也是一个额外的分数 + +1691 +01:08:59,500 --> 01:09:02,300 +your homework is to analyze your performance of your +如果你在课后作业中
 + +1692 +01:09:02,300 --> 01:09:05,630 +calculator that you're doing, your graphing calculator. +分析你的计算器的性能 + +1693 +01:09:05,630 --> 01:09:07,830 +And find out where it's slow and +然后找出是哪里导致程序变慢
 + +1694 +01:09:07,840 --> 01:09:09,170 +then maybe you can fix it if you want, +并修复它
 + +1695 +01:09:09,170 --> 01:09:12,300 +that's another extra credit to try and go fix it. +这是另外一个你可以尝试的额外的分数 + +1696 +01:09:12,310 --> 01:09:13,810 +Next Monday I'm +下周一我会
 + +1697 +01:09:13,810 --> 01:09:15,310 +going to dive into the View Controller Lifecycle. +开始讲 ViewController 的生命周期
 + +1698 +01:09:15,310 --> 01:09:18,310 +I hate to have had put the View Controller Lifecycle onff +我真的很不想把这个内容推后
 + +1699 +01:09:18,310 --> 01:09:19,710 +for so long. +这么晚
 + +1700 +01:09:19,710 --> 01:09:22,950 +But in some ways it's kind of nice because it forces you to +不过也有好处,它迫使你 + +1701 +01:09:22,950 --> 01:09:24,850 +use other parts of your View Controller, +使用 View Controller 的其他部分
来实现 + +1702 +01:09:24,850 --> 01:09:28,050 +like the property observers in your outlets, and +比如 outlet 的 property observer + +1703 +01:09:28,050 --> 01:09:31,750 +in your model setting, and things like that. +就像你设置 model 那样
 + +1704 +01:09:31,760 --> 01:09:33,360 +But you're going to find out on Monday, you're +但是在星期一你会发现 + +1705 +01:09:33,360 --> 01:09:35,190 +probably going to be mad at me on Monday when I show you +你可能会气愤,当我展示一些
 MVC 的 + +1706 +01:09:35,190 --> 01:09:37,490 +all these nice methods in the View Controller Lifecycle and +生命周期相关的方法
 + +1707 +01:09:37,490 --> 01:09:39,890 +you're, like oh if you'd just told me that last week it +你可能会觉得,如果你上星期告诉我这些方法
 + +1708 +01:09:39,900 --> 01:09:41,730 +could have made something so much easier. +可以减轻多少工作量啊
 + +1709 +01:09:41,730 --> 01:09:44,570 +But the homeworks are designed to not need any of the view +但是课后作业就是这样设计的
 + +1710 +01:09:44,570 --> 01:09:46,530 +controller life cycle methods, you shouldn't need them for +不使用生命周期中的方法,你并不需要他们
 + +1711 +01:09:46,540 --> 01:09:48,300 +anything, even for the extra credits, you shouldn't. +即使额外分数中,你也可以不使用他们
 + +1712 +01:09:49,440 --> 01:09:51,870 +And then again, I have Auto Layout question mark, +又一次,我为 Autolayout 添加了问号 + +1713 +01:09:51,870 --> 01:09:53,670 +kind of a running joke, +只是开个玩笑 + +1714 +01:09:53,670 --> 01:09:55,470 +we'll see, hopefully we'll get to Auto Layout eventually in +我们会最终详细讲到 Autolayout 的
 + +1715 +01:09:55,480 --> 01:09:59,110 +this quarter, but like I say, see I'm kind of sprinkling it +就像我说的,我在每个 demo 中都会灌输一点点
 + +1716 +01:09:59,110 --> 01:10:01,710 +in in every demo, a little bit of Auto Layout, so +Autolayout 的知识,
 + +1717 +01:10:01,720 --> 01:10:04,150 +hopefully you're learning a little bit along the way. +希望这一路走来你已经学到了一些 + +1718 +01:10:04,150 --> 01:10:07,190 +And then, after Monday, we'll start diving into +然后,星期一之后,我们开始
 + +1719 +01:10:07,190 --> 01:10:10,320 +multithreading, because you're talking about a device, +学习多线程,因为你在和设备交互
 + +1720 +01:10:10,320 --> 01:10:13,790 +a phone, that needs to be highly responsive to the user. +就是 iPhone,它需要有很高的响应速度
 + +1721 +01:10:13,790 --> 01:10:14,730 +Okay? It needs to +明白吗?它需要
 + +1722 +01:10:14,730 --> 01:10:16,460 +always be responding to touches. +响应用户的每次点击
 + +1723 +01:10:16,460 --> 01:10:19,900 +It cannot, you press a touch and then it freezes for +不能点一下屏幕的时候就卡在那里
 + +1724 +01:10:19,900 --> 01:10:22,630 +two seconds or even a second, while it goes off and +几秒钟都 + +1725 +01:10:22,630 --> 01:10:23,920 +does something. +没有
反应
 + +1726 +01:10:23,920 --> 01:10:25,200 +It needs to immediately animating a response to +它必须立即以动画的方式响应
 + +1727 +01:10:25,200 --> 01:10:26,890 +what you're doing. +用户的操作
 + +1728 +01:10:26,890 --> 01:10:28,570 +So the only way to make that work if you're doing things +完成耗时操作的唯一方式
 + +1729 +01:10:28,570 --> 01:10:31,740 +like accessing the network, which is really slow, +比如网络请求,这非常慢
 + +1730 +01:10:31,740 --> 01:10:34,180 +compared to the things you're doing on-screen, +相对于屏幕上的操作来说, + +1731 +01:10:34,180 --> 01:10:36,840 +you need to be able to do those things offline of +你需要将这些耗时操作移到
 + +1732 +01:10:36,850 --> 01:10:40,350 +the main thread of execution, so we'll talk about that. +主线程之外执行,我们会讲到的
 + +1733 +01:10:40,350 --> 01:10:42,180 +Then we'll start talking about scrolling. +然后我们会讲到 scrolling
 + +1734 +01:10:42,180 --> 01:10:43,720 +Because you've got this small screen. +因为屏幕很小
 + +1735 +01:10:43,720 --> 01:10:45,890 +It's nice because it fits in your pocket but +虽然这样可以很方便的放在口袋中
 + +1736 +01:10:45,890 --> 01:10:47,390 +if you want to show something big, +但是如果你需要展示很大的东西
, + +1737 +01:10:47,390 --> 01:10:49,020 +you need to be able to scroll around in it. +你需要可以到处拖动它
 + +1738 +01:10:49,020 --> 01:10:50,690 +If you want to see a nice image and +如果你想查看高清图片
 + +1739 +01:10:50,690 --> 01:10:52,360 +you want to zoom in and see a really detailed part of it, +而且想放大然后查看细节部分 + +1740 +01:10:52,360 --> 01:10:55,130 +you have to be able to zoom in and scroll around. +你就必须可以放大并拖动它
 + +1741 +01:10:55,130 --> 01:10:57,700 +And then we're going to talk about the next big thing and +然后我们会讲
另一个大板块的知识 + +1742 +01:10:57,700 --> 01:11:00,400 +the topic of your next homework after the calculator. +你会在计算器后的下一个作业中用到。 + +1743 +01:11:00,400 --> 01:11:02,770 +Which is, I know you love the calculator, but +
我知道你喜欢计算器,但是 + +1744 +01:11:02,770 --> 01:11:05,070 +this is your last assignment for the calculator. +
这是你计算器部分的最后一次作业了 + +1745 +01:11:05,070 --> 01:11:07,900 +We're going to move on to a whole thing called table view. +然后我们会开始讲 tableview
 + +1746 +01:11:07,910 --> 01:11:12,340 +Which is really highly delicate based user interface +它是一个非常精致的用户界面
 + +1747 +01:11:12,340 --> 01:11:15,710 +mechanism in iOS that really helps you understand +
它可以帮助你更好地理解 + +1748 +01:11:15,710 --> 01:11:20,150 +how iOS works when it comes to sophisticated user interface. +iOS 是如何工作的,当遇到更复杂的界面的时候 + +1749 +01:11:20,150 --> 01:11:22,150 +Okay? So that's what we're going to +明白吗?这是我们 + +1750 +01:11:22,150 --> 01:11:22,950 +be doing next week. +下周的
内容
 + +1751 +01:11:24,450 --> 01:11:25,050 +All right? +没问题吧?
 + +1752 +01:11:25,050 --> 01:11:25,620 +Thank you. +好的
 + +1753 +01:11:27,020 --> 01:11:28,390 +Okay. So, +好的
 + +1754 +01:11:28,390 --> 01:11:31,390 +let's continue with our psychologist demo, here. +我们继续 Psychologist demo + +1755 +01:11:31,390 --> 01:11:33,090 +We're going to add a popover. +我们会增加一个 popover
 + +1756 +01:11:33,090 --> 01:11:37,400 +And the place I'm gonna add a popover is down here, okay? +我会加在这里
 + +1757 +01:11:37,400 --> 01:11:39,330 +In this HappinessViewController, here, +在 HappinessViewController 这里
 + +1758 +01:11:39,330 --> 01:11:41,270 +I'm gonna put a little button, here. +我会加一个小按钮在这里
 + +1759 +01:11:41,270 --> 01:11:44,270 +And this popover is going to show the history of +然后会用 popover 展示 + +1760 +01:11:44,270 --> 01:11:47,240 +all the diagnoses made by the psychologist. +Psychologist 
所有的 diagnoses 历史
。 + +1761 +01:11:47,240 --> 01:11:50,070 +So the psychologist is going to be diagnosing things as we +所以 Psychologist 会记录
 + +1762 +01:11:50,080 --> 01:11:51,970 +click on what we see in our dreams, and +
我们的点击历史 + +1763 +01:11:51,980 --> 01:11:54,680 +we're going to want a little button here that brings up +我们会用一个小按钮来弹出
 + +1764 +01:11:54,680 --> 01:11:56,010 +a popover right here, and +popover,然后
 + +1765 +01:11:56,010 --> 01:11:58,980 +this popover is going to show the history of the diagnoses. +这个 popover 会显示 diagnoses 历史
。 + +1766 +01:11:58,980 --> 01:12:02,320 +Now since this is a demo, I wanna keep the code simple. +因为只是 demo,我想让代码简单一点
 + +1767 +01:12:02,320 --> 01:12:04,820 +It's gonna show the history of the diagnosis just as +我只会显示
 + +1768 +01:12:04,820 --> 01:12:07,450 +an Array of ints, because we know that our happiness is +一个整数数组,因为 Happiness 程度用
 + +1769 +01:12:07,460 --> 01:12:08,490 +represented in int. +整数来表示
 + +1770 +01:12:08,490 --> 01:12:09,720 +So it's gonna be shown in an Array of ints. +所以会以一个整数数组来显示 + +1771 +01:12:09,730 --> 01:12:12,330 +It might be nicer to show it in a different way, but +或许有更好的方式,但是
 + +1772 +01:12:12,330 --> 01:12:14,460 +we're gonna show it as an Array of ints. +我只显示一个整数数组
 + +1773 +01:12:15,500 --> 01:12:19,730 +So let's build this popover segue first and +我们先创建 popover
 segue + +1774 +01:12:19,730 --> 01:12:23,000 +then we'll have to go on to build a brand new MVC, +然后建一个全新的 MVC + +1775 +01:12:23,000 --> 01:12:24,970 +actually, to show the information. +来显示信息
 + +1776 +01:12:24,970 --> 01:12:28,570 +It's just gonna be a simple MVC that shows text only, so +只是一个显示文本的 + +1777 +01:12:28,570 --> 01:12:29,810 +we'll have to do that. +简单 MVC + +1778 +01:12:29,810 --> 01:12:31,740 +And then we're obviously gonna prepare this segue. +然后很显然,我们需要实现 prepareForSegue 方法 + +1779 +01:12:31,740 --> 01:12:36,880 +But first let's build the UI portion of this and to do that +我们需要先完成界面部分
 + +1780 +01:12:36,880 --> 01:12:40,550 +I need to add a little bar but here is so I'm going to +先添加一个小按钮
 + +1781 +01:12:40,550 --> 01:12:45,990 +bring up my object palette here and zoom in on this guy. +打开控件区域然后放大 + +1782 +01:12:47,520 --> 01:12:54,230 +And when you put a button here you don't use this UI button. +然后拖一个按钮,但不要用 UIButton + +1783 +01:12:54,230 --> 01:12:57,960 +Okay so UI buttons, even if you drag the UI Button here it +虽然你使用 UIButton
 + +1784 +01:12:57,970 --> 01:12:59,830 +will look like it is going to work but +看起来没问题
 + +1785 +01:12:59,830 --> 01:13:03,070 +actually don't do that, it will mess you up. +但不要用 UIButton,这会有很多问题 + +1786 +01:13:04,170 --> 01:13:07,440 +Instead you want to go down here quite a ways +你需要选择最下面的
 + +1787 +01:13:07,440 --> 01:13:11,980 +towards the very bottom and there is this Bar Button Item. +BarButtonItem
 + +1788 +01:13:11,980 --> 01:13:15,480 +Bar Button Items is a little lighter weight button that +BarButtonItem 是轻量化的按钮
 + +1789 +01:13:15,480 --> 01:13:19,750 +goes in bars like this, navigation bars and tool bars. +在导航栏或工具栏中使用它们 + +1790 +01:13:19,750 --> 01:13:21,920 +So I should put that one right there. +我把它放在这里 + +1791 +01:13:21,920 --> 01:13:25,190 +We'll call this one history since it's the diagnostic +我会叫它 history
 + +1792 +01:13:25,190 --> 01:13:29,190 +history of what's going on with this patient right here. +因为是 diagnostic 的历史 + +1793 +01:13:29,190 --> 01:13:31,530 +And of course if we're gonna have a popover, +当然,如果我们使用 popover
 + +1794 +01:13:31,530 --> 01:13:32,990 +the popover shows a MVC. +popover 里面包含一个 MVC + +1795 +01:13:33,000 --> 01:13:34,660 +So we need to create a new MVC. +所以我们还需要创建一个新的 MVC + +1796 +01:13:34,660 --> 01:13:38,300 +So let's go back to the top here and get ourselves +所以我们回去创建
 + +1797 +01:13:38,300 --> 01:13:41,070 +brand new View Controllers, this is just the regular old +一个新的 View Controller,就是我们
 + +1798 +01:13:41,070 --> 01:13:43,000 +View Controller like we've dragged out before, so +通常拖的普通 View Controller + +1799 +01:13:43,010 --> 01:13:48,270 +I'm just gonna drag that right in here, and make some room. +我拖到这里,腾一些空间出来
 + +1800 +01:13:48,280 --> 01:13:50,840 +So here we have this, zoom out a little so +缩小一点
 + +1801 +01:13:50,850 --> 01:13:52,480 +you can see it a little better, and +这样看起来更好 + +1802 +01:13:52,480 --> 01:13:56,210 +what we want is for this little button to segue to this +我们想这个小按钮可以 segue 到这个
 + +1803 +01:13:56,220 --> 01:14:00,350 +MVC, and show it in a little popover right here. +控制器,并通过一个小的 Popover 显示在这里
 + +1804 +01:14:00,350 --> 01:14:01,620 +Okay? So that's all we +明白吗?这是
 + +1805 +01:14:01,620 --> 01:14:02,690 +wanna do there. +所有我们想要的 + +1806 +01:14:02,690 --> 01:14:04,890 +So let's just Ctrl+Drag, just like we +我们只要 Control + Drag,就像我们
 + +1807 +01:14:04,890 --> 01:14:06,790 +created in the other segue, we're gonna Ctrl+Drag from +创建其他的 segue 一样,直接从
 + +1808 +01:14:06,790 --> 01:14:10,290 +the history button over to this MVC, and when we let go +History 按钮链接到这个控制器,然后释放鼠标 + +1809 +01:14:10,300 --> 01:14:13,130 +it's gonna say well, what kind of segue do you want? +接下来 Xcode 会询问你,你想要什么类型的 segue?
 + +1810 +01:14:13,130 --> 01:14:16,170 +And we want the propover presentation segue right here. +我们这里需要 popover presentation + +1811 +01:14:16,170 --> 01:14:18,170 +So I'm gonna click that. +所以点这个
 + +1812 +01:14:18,170 --> 01:14:20,450 +This is a popover. +这是一个 popover segue。
 + +1813 +01:14:20,450 --> 01:14:22,740 +If I click here, on the segue, and go to the attributes +如果我选中这个 segue + +1814 +01:14:22,740 --> 01:14:25,470 +inspector here, you can see that it is a popover segue. +然后查看 Attributes Inspector,你可以看到它是一个 popover 类型的 segue + +1815 +01:14:25,480 --> 01:14:28,940 +I can control where the little arrow, if you remember +如果你回忆起来了之前我们讲 popover 的 Slide + +1816 +01:14:28,950 --> 01:14:32,010 +the slide about the popover, there was a little kind of +这里,我可以控制 popover 箭头的方向 + +1817 +01:14:32,010 --> 01:14:35,280 +triangle that was pointing at the thing that brought it up. +也就是那个小三角形,指向触发 popover 的控件
 + +1818 +01:14:35,280 --> 01:14:36,450 +Like this History button, or +就像这里的 History 按钮,或者
 + +1819 +01:14:36,450 --> 01:14:39,090 +in that slide it was a little search button. +课件里面的搜索按钮 + +1820 +01:14:39,090 --> 01:14:41,290 +So I can control which direction that arrow pointed. +这样我可以控制箭头的指向 + +1821 +01:14:41,290 --> 01:14:43,060 +And I can even see here the anchor. +我甚至可以看到锚点
(Anchor) + +1822 +01:14:43,060 --> 01:14:44,990 +See it highlighting there. +看这个高亮的地方
 + +1823 +01:14:44,990 --> 01:14:47,690 +That is going to bring up this popover. +它代表,这里会弹出一个 popover
 + +1824 +01:14:47,690 --> 01:14:48,560 +So that's great. +非常好
 + +1825 +01:14:48,560 --> 01:14:49,830 +And of course I need an identifier, +当然,我还需要一个标识符(identifier
) + +1826 +01:14:49,830 --> 01:14:51,760 +just like any other segue, I need an identifier. +就像其他任何 segue 一样 + +1827 +01:14:51,760 --> 01:14:54,930 +So, this shows the diagnostic history, so +这个 segue 用来显示诊断的历史
, + +1828 +01:14:54,930 --> 01:14:58,370 +I'm gonna call this Show Diagnostic History. +我就叫它 Show Diagnostic History
 + +1829 +01:14:58,370 --> 01:15:00,140 +Oh, my caps lock. +噢,这里不小心大写锁定了 + +1830 +01:15:00,140 --> 01:15:01,500 +There she is, there. +好的 + +1831 +01:15:01,510 --> 01:15:02,770 +History, there we go. +History,让我们继续 + +1832 +01:15:02,770 --> 01:15:04,770 +Show Diagnostic History. +Show Diagnostic History
 + +1833 +01:15:04,780 --> 01:15:06,570 +Okay? +明白吗?
 + +1834 +01:15:06,580 --> 01:15:09,080 +So now we've got this set up to this segue and +现在我们已经设置好了 segue 和
 + +1835 +01:15:09,080 --> 01:15:10,640 +show this MVC. +被显示的控制器
 + +1836 +01:15:10,650 --> 01:15:13,250 +Now, this MVC is just a blank MVC right now, +虽然现在控制器是空白的
 + +1837 +01:15:13,250 --> 01:15:15,820 +but let's go ahead and run and see what this looks like. +但我们先运行看下效果
,看看这个 popover 是怎么样子的 + +1838 +01:15:15,820 --> 01:15:18,920 +So this is going to show a blank MVC at this point. +它应该会在这个点弹出一个空白控制器
 + +1839 +01:15:21,090 --> 01:15:24,020 +So here's our iPad right here and we'll. +这是我们的 iPad
模拟器 + +1840 +01:15:24,030 --> 01:15:25,660 +Go to Landscape Mode. +切换到横屏模式
 + +1841 +01:15:25,660 --> 01:15:27,790 +And so if I click on this, +如果我点击这里
 + +1842 +01:15:27,790 --> 01:15:29,930 +you see I get this nice blank MVC appearing right here. +你可以看到,会弹出一个空白的控制器
 + +1843 +01:15:29,930 --> 01:15:34,500 +So our next step in this is we need to create this MVC. +所以,下一步,我们需要做的就是创建这个控制器
 + +1844 +01:15:34,500 --> 01:15:35,930 +All right, we're going to. +好的,让我们继续 + +1845 +01:15:36,940 --> 01:15:39,470 +Create the MVC that is going to go in here. +继续创建一个在这里的控制器
 + +1846 +01:15:39,470 --> 01:15:42,170 +It's going to be a very, very simple little MVC. +这会是一个非常简单的控制器
 + +1847 +01:15:42,170 --> 01:15:46,010 +It's just going to have a text view in it here to show text. +它只包含一个显示文本的 textView
 + +1848 +01:15:46,010 --> 01:15:48,080 +And that's all it's gonna do is show text. +它需要做的只是显示文本
 + +1849 +01:15:48,080 --> 01:15:50,180 +It doesn't do anything else. +不需要做其他事情
 + +1850 +01:15:50,180 --> 01:15:51,800 +Okay? +明白吗?
 + +1851 +01:15:51,800 --> 01:15:53,420 +So, let's start by creating a new +我们先创建
 + +1852 +01:15:54,520 --> 01:15:56,180 +UIViewController subclass. +UIViewController 子类
。 + +1853 +01:15:56,190 --> 01:15:59,850 +So again I'm gonna go to iOS source cocoa touch class here +所以我们选择 iOS -> Source -> Cocoa Touch Class + +1854 +01:15:59,860 --> 01:16:01,620 +because I'm gonna create a cocoa touch class, and +因为我需要创建一个 Cocoa Touch Class + +1855 +01:16:01,620 --> 01:16:03,760 +it is gonna be a UIViewController. +它将一个 UIViewController
 + +1856 +01:16:03,760 --> 01:16:06,830 +I'm gonna call it TextViewController because that's what +我叫它 TextViewController
 + +1857 +01:16:06,830 --> 01:16:08,260 +it does, it shows some text. +因为它负责显示文本
 + +1858 +01:16:08,260 --> 01:16:09,960 +That's all this View Controller knows how to do. +这是这个控制器需要做的
 + +1859 +01:16:11,130 --> 01:16:13,900 +I'm gonna put it in the same place all the rest of +我把它和剩下所有的 Swift 文件 + +1860 +01:16:13,900 --> 01:16:15,030 +my SWF files are. +放
在一起
 + +1861 +01:16:16,140 --> 01:16:17,330 +Okay, here it is. +好的,就是这里 + +1862 +01:16:17,340 --> 01:16:18,800 +Here's the code for it. +这是它的代码
 + +1863 +01:16:18,800 --> 01:16:21,270 +We're gonna delete all of this stuff in here. +我们先删除里面的所有东西
 + +1864 +01:16:22,210 --> 01:16:24,060 +Start. +这样 + +1865 +01:16:24,060 --> 01:16:25,910 +Right, so we've got a nice subclass of UIViewController. +我们有了一个干净的 UIViewController 子类 + +1866 +01:16:25,910 --> 01:16:28,180 +We'll have to put our implementation in here. +我们需要在这里面放置实现的代码 + +1867 +01:16:28,180 --> 01:16:30,010 +Meanwhile, let's go back to our Storyboard and +除此之外,我们需要在 Storyboard 中
 + +1868 +01:16:30,010 --> 01:16:33,380 +make sure that we set this thing's class in +确保我们设置这个类
为 popover 的类 + +1869 +01:16:33,380 --> 01:16:36,080 +the Identity Inspector up here. +在 Identity Inspector 中 + +1870 +01:16:36,090 --> 01:16:38,320 +To be the TextViewController, so +设置 Custom Class 为 TextViewController + +1871 +01:16:38,320 --> 01:16:41,390 +that we know this is a TextViewController. +那么这样,Xcode 就知道了这是一个 TextViewController + +1872 +01:16:41,390 --> 01:16:42,690 +Okay? +明白吗?
 + +1873 +01:16:42,690 --> 01:16:43,990 +Now, let's talk about this thing's UI. +我们说说它的用户界面 + +1874 +01:16:43,990 --> 01:16:45,430 +It has a very simple UI. +界面会很简单
 + +1875 +01:16:45,430 --> 01:16:50,300 +I'm actually gonna drag out a text displaying object here. +我将会拖一个文本控件到这里
 + +1876 +01:16:50,300 --> 01:16:51,700 +And I'm not going to use label. +这里我不打算使用 Label + +1877 +01:16:52,630 --> 01:16:54,400 +Label is nice for one and two and +Label 适合于那些一到两
 + +1878 +01:16:54,400 --> 01:16:58,040 +maybe three lines of static text. +或者是三行的静态文本 + +1879 +01:16:58,040 --> 01:17:00,100 +But I really want something that kind of can show as +但是这里,我需要尽可能多的显示
 + +1880 +01:17:00,110 --> 01:17:01,870 +much diagnostic history as I want it. +诊断的历史 + +1881 +01:17:01,870 --> 01:17:04,140 +So I want something that shows a lot more text. +所以我需要一个可以显示很多文本的控件 + +1882 +01:17:04,140 --> 01:17:05,740 +A text field is +输入框
 + +1883 +01:17:05,740 --> 01:17:07,340 +not really appropriate because that's editable. +也不合适,因为它是可编辑的 + +1884 +01:17:07,350 --> 01:17:08,610 +One, two, three liner. +而且同样适用于一到三行 + +1885 +01:17:08,610 --> 01:17:10,910 +So label and text field are very similar. +所以标签和输入框很相似 + +1886 +01:17:10,920 --> 01:17:12,050 +It's just editable or not. +两者区别在于能否编辑
 + +1887 +01:17:12,050 --> 01:17:14,530 +But there's yet +但在这两个下面还有一个 + +1888 +01:17:14,530 --> 01:17:17,020 +another one down here, called text view, right here. +叫 text view 的控件 + +1889 +01:17:17,020 --> 01:17:19,290 +And this displays multiple lines of editable text. +它用来显示多行可编辑的文本 + +1890 +01:17:19,290 --> 01:17:23,860 +It lets you set the font, and the text can be selectable. +你可以设置字体,还可以让用户选中其中的文本 + +1891 +01:17:23,860 --> 01:17:25,560 +You can copy and paste from it, things like that. +从这些文本中复制粘贴等等操作 + +1892 +01:17:25,560 --> 01:17:27,330 +So it's a much more powerful text styler, but +所以它是一个功能非常强大的文本显示空间
 + +1893 +01:17:27,330 --> 01:17:29,100 +we'll talk about this later in the quarter. +后期我们会详细讲到 + +1894 +01:17:29,100 --> 01:17:32,330 +But for now I'm just going to drag this in right here. +现在,我只需要拖动这个控件到这里 + +1895 +01:17:32,330 --> 01:17:34,730 +You noticed I used the blue lines. +这里注意我是使用到了蓝色的辅助线 + +1896 +01:17:34,740 --> 01:17:35,770 +I'm going to go up here and +接着我点击这里 + +1897 +01:17:35,770 --> 01:17:37,800 +reset to suggested constraints. +选择 Reset to Suggested Constraints
 + +1898 +01:17:37,800 --> 01:17:41,140 +I'm going to go over here to the size inspector up here. +然后到 Size Inspector + +1899 +01:17:41,140 --> 01:17:44,880 +And verify that my constraints are the way I want, and +确认所有约束正确
 + +1900 +01:17:44,880 --> 01:17:45,610 +they look fine. +它们看上去都没问题 + +1901 +01:17:45,610 --> 01:17:47,410 +Okay, so that's good. +还不错 + +1902 +01:17:47,410 --> 01:17:50,450 +I could also set some attributes maybe, about this +我也可以设置一下这个 text view 的某些属性 + +1903 +01:17:50,450 --> 01:17:54,180 +text view, like I probably don't want it to be editable. +比如,我不想让它可以被编辑 + +1904 +01:17:54,190 --> 01:17:57,050 +I don't want the diagnostic history to be actually, +我不希望诊断历史可以被编辑 + +1905 +01:17:57,050 --> 01:17:59,050 +you know, touched on and edited. +因为这样的话,用户一点击就开始编辑 + +1906 +01:17:59,060 --> 01:18:00,760 +But it's not bad to have it selectable, +不过让它可以被选中是没什么问题的 + +1907 +01:18:00,760 --> 01:18:03,930 +someone might wanna select the diagnostic history and +有人可能会想要选中诊断历史 + +1908 +01:18:03,930 --> 01:18:05,630 +then copy it and +然后拷贝 + +1909 +01:18:05,630 --> 01:18:07,330 +paste it somewhere, or something like that. +把它粘贴到别处 + +1910 +01:18:07,330 --> 01:18:09,530 +Or you could set the font to be larger too, +你也可以把字体设置得大些 + +1911 +01:18:09,530 --> 01:18:12,430 +maybe something 24 point or something like that. +比如可以设置成24 pt 的字体之类的 + +1912 +01:18:13,370 --> 01:18:15,570 +And of course we've got this kind of +在这里还有一些 + +1913 +01:18:17,170 --> 01:18:19,710 +pseudo latin placeholder text right here. +占位(placeholder)用的文字 + +1914 +01:18:19,710 --> 01:18:21,270 +But that's not gonna matter cuz that's not +不用管它,因为没什么关系 + +1915 +01:18:21,280 --> 01:18:23,040 +gonna show because we're going to +因为我们会在准备 segue 的时候 + +1916 +01:18:23,040 --> 01:18:27,880 +set the text we want when we prepare for this segue, okay? +设定这些文字,所以这些默认的文字不会显示出来,明白了吗? + +1917 +01:18:27,880 --> 01:18:30,350 +So now let's go ahead and wire up this UI. +现在,我们来把 UI 元素和代码联系起来 + +1918 +01:18:30,350 --> 01:18:32,480 +We've got this text view right here. +选中 text view + +1919 +01:18:32,480 --> 01:18:35,150 +Let's Ctrl + Drag to create an outlet to it, okay? +按住 Ctrl 并拖动,创建一个 outlet 的链接 + +1920 +01:18:35,150 --> 01:18:37,750 +I'm gonna call that outlet textview. +把这个 outlet 起名为 textView + +1921 +01:18:37,760 --> 01:18:39,190 +So, we've got a nice outlet here. +这样,我们创建好了一个 outlet + +1922 +01:18:39,190 --> 01:18:41,790 +And let's add a model to our TextViewController. +在 TextViewController 中添加一个 model + +1923 +01:18:41,790 --> 01:18:43,460 +My model, I'm going to call it text. +称之为 text + +1924 +01:18:43,460 --> 01:18:44,860 +It's going to be a String. +是一个 String 类型的 + +1925 +01:18:44,860 --> 01:18:46,560 +We'll start out as an empty String. +先设置成一个空的 String + +1926 +01:18:47,560 --> 01:18:48,700 +Okay. + +1927 +01:18:48,700 --> 01:18:51,130 +Now every time my model gets set, +每一次我的 model 被设值的时候 + +1928 +01:18:52,170 --> 01:18:56,870 +I want to make sure that I update my text views text. +我都要确保 text view 上的文字被更新了 + +1929 +01:18:56,870 --> 01:19:00,410 +So text view is this thing that manages text. +所以,text view 就是一个显示 text 内容的东西 + +1930 +01:19:00,410 --> 01:19:03,080 +And you can see has an enormous number of things you +你可以看到,text view 能够做很多事情 + +1931 +01:19:03,080 --> 01:19:05,810 +can do on it it's a very powerful text object, but +它是一个非常强大的显示文本的控件 + +1932 +01:19:05,810 --> 01:19:07,910 +it also has just a simple method called text. +不过它也有一个很简单的属性叫做 text + +1933 +01:19:07,910 --> 01:19:11,520 +Just like UILabel does, and we're gonna set that equal to +就像 UILabel,我们把它 + +1934 +01:19:11,520 --> 01:19:14,020 +our text the model's text right. +设置成 model 的 text + +1935 +01:19:14,020 --> 01:19:16,720 +And just to be safe in case this is being called while +为了安全起见 + +1936 +01:19:16,720 --> 01:19:17,990 +we're preparing. +防止我们正在准备 segue 的时候,此方法被调用 + +1937 +01:19:17,990 --> 01:19:20,490 +Okay, we'll do the same thing with optional chaining in +在这里也使用可选链(optional chaining) + +1938 +01:19:20,490 --> 01:19:22,760 +case our outlet here has not been set. +防止 outlet 在没被设置好的时候,设置了其中的属性而导致程序崩溃 + +1939 +01:19:22,760 --> 01:19:25,790 +And similarly when our outlet finally does get +类似的,当 outlet 被设置好以后 + +1940 +01:19:25,800 --> 01:19:31,530 +set by the system, we're going to have it, property observer, +我们在它的 property observer 里 + +1941 +01:19:31,540 --> 01:19:35,000 +say text view dot text equals text. +设置 textView.text = text + +1942 +01:19:36,110 --> 01:19:37,600 +Okay. And here we don't have to do +这里我们不需要加问号 + +1943 +01:19:37,610 --> 01:19:40,340 +the question mark because where actually the text view +因为这里 textview + +1944 +01:19:40,340 --> 01:19:41,840 +is being set by the system, so +在 didSet 被调用的时候 + +1945 +01:19:41,840 --> 01:19:44,340 +we know it's set by the time this didSet happens. +已经被系统设置完毕了,它不可能是 nil 了 + +1946 +01:19:44,350 --> 01:19:46,080 +Okay, so this is a very, +这就是一个我们将要使用的 + +1947 +01:19:46,080 --> 01:19:49,350 +very simple MVC that we're using right here. +非常简单的 MVC + +1948 +01:19:50,580 --> 01:19:55,920 +And it should have no +它用于显示诊断历史 + +1949 +01:19:55,920 --> 01:20:02,330 +problem displaying our little diagnostic history, there. +应该没什么问题了吧? + +1950 +01:20:02,330 --> 01:20:04,540 +Okay? + +1951 +01:20:04,550 --> 01:20:06,760 +So now it's time to prepare this segue. +现在是时候准备这个 segue 了 + +1952 +01:20:06,770 --> 01:20:08,460 +All right? We want to +我们想要 + +1953 +01:20:08,470 --> 01:20:11,230 +prepare this segue so that you click on history, +为这个 segue 做些准备,当我们点击 History 的时候 + +1954 +01:20:11,240 --> 01:20:13,740 +it shows the diagnostic history here now. +这个 MVC 就会展示出诊断的记录 + +1955 +01:20:13,740 --> 01:20:16,810 +We might, we know that this instigator right here is +我们知道这里的 + +1956 +01:20:16,810 --> 01:20:19,070 +inside this HappinessViewController. +HappinessViewController 是 segue 的发起者 + +1957 +01:20:19,080 --> 01:20:22,310 +So we might think that we should go to our +所以我们也许会想 + +1958 +01:20:22,310 --> 01:20:25,480 +HappinessViewController right here and add the prepare in here. +把 segue 准备的代码放到这里 + +1959 +01:20:26,450 --> 01:20:28,350 +Okay. And we could do that but +我们完全可以这样做 + +1960 +01:20:28,350 --> 01:20:29,920 +remember that HappinessViewController is +但是,还记得吗? HappinessViewController 是我们从 + +1961 +01:20:29,920 --> 01:20:32,180 +something we dragged in from another app. +另一个 App 拽进来的 + +1962 +01:20:32,190 --> 01:20:35,220 +And maybe that's another app that's being worked on at +也许是我们公司正在开发的另一个 App + +1963 +01:20:35,220 --> 01:20:37,990 +our company or that there's another programer who +或是其他程序员 + +1964 +01:20:37,990 --> 01:20:39,620 +owns this particular class. +管理这个 HappinessViewController 的类 + +1965 +01:20:39,630 --> 01:20:41,110 +And he said no, no, +他不想让其他人添加代码 + +1966 +01:20:41,110 --> 01:20:42,590 +you can't add prepareForSegue to this class. +他说:“你不能在这个类里添加 prepareForSegue” + +1967 +01:20:42,600 --> 01:20:45,230 +It's a generic happiness showing thing. +它只是一个通用的展示笑脸的东西 + +1968 +01:20:45,230 --> 01:20:46,960 +It doesn't know anything about diagnostic history. +它(应该)对于诊断历史一无所知 + +1969 +01:20:46,970 --> 01:20:51,770 +And they'd probably be right because if we started +他这么说是对的,因为,如果我们想把诊断历史相关的东西 + +1970 +01:20:51,770 --> 01:20:54,400 +adding things about diagnostic history to a happiness view +放进 HappinessViewController 里 + +1971 +01:20:54,410 --> 01:20:57,340 +controller, it would be kind of a diagnostic or +它就会更像一个 + +1972 +01:20:57,340 --> 01:21:00,340 +DiagnosedHappinessViewController not +DiagnosedHappinessViewController + +1973 +01:21:00,340 --> 01:21:02,610 +a HappinessViewController anymore. +而不是一个 HappinessViewController + +1974 +01:21:02,610 --> 01:21:04,750 +So where are we going to put our prepareForSegue then? +所以,我们应该把 prepareForSegue 放在哪里呢? + +1975 +01:21:04,750 --> 01:21:06,850 +The answer is that we are going to +答案是 + +1976 +01:21:06,850 --> 01:21:08,450 +actually create a subclass of +我们会创建一个 HappinessViewController 的子类 + +1977 +01:21:08,450 --> 01:21:11,450 +HappinessViewController that we can use that's going to get +然后我们就会继承所有 + +1978 +01:21:11,450 --> 01:21:14,420 +all the behavior of HappinessViewController. +HappinessViewController 中的属性和方法 + +1979 +01:21:14,420 --> 01:21:17,060 +Plus, we're going to add the ability to do +除此之外,我们还会往这个子类中 + +1980 +01:21:17,060 --> 01:21:18,160 +the diagnostic history. +添加显示诊断历史的功能 + +1981 +01:21:18,160 --> 01:21:19,430 +Okay. So we're going to +我们开始 + +1982 +01:21:19,430 --> 01:21:20,560 +create a subclass. +首先,我们创建一个子类 + +1983 +01:21:20,560 --> 01:21:22,660 +We're just going to go up here. +先点击这里 + +1984 +01:21:22,660 --> 01:21:24,600 +New file. +New File + +1985 +01:21:24,600 --> 01:21:26,530 +Again, I'm just going to create a Swift file this time. +这次我们创建一个 Swift 文件 + +1986 +01:21:26,530 --> 01:21:32,700 +I'm going to call it DiagnosedHappinessViewController. +把它起名为 DiagnosedHappinessViewController + +1987 +01:21:32,710 --> 01:21:35,770 +Okay, because it's just like a happiness controller, but +它和 happiness controller 类似 + +1988 +01:21:35,770 --> 01:21:39,080 +it's diagnosed happiness. +但是它是 diagnosed happiness + +1989 +01:21:39,080 --> 01:21:41,090 +Here it is right here. +创建完毕 + +1990 +01:21:41,100 --> 01:21:43,110 +I'm gonna import UIKit because it's a UI class. +我要在文件开头导入 UIKit,因为它是一个 UI 相关的类 + +1991 +01:21:43,110 --> 01:21:47,250 +And I'm just gonna say that my class +接着,我让 DiagnosedHappinessViewController + +1992 +01:21:47,250 --> 01:21:52,220 +DiagnosedHappinessViewController inherits from +继承自 + +1993 +01:21:52,220 --> 01:21:53,920 +HappinessViewController, okay? +HappinessViewController + +1994 +01:21:54,920 --> 01:21:56,820 +So I am going to be +那么现在 + +1995 +01:21:56,830 --> 01:21:58,730 +a sub class that DiagnosedHappinessViewController. +我有一个叫 DiagnosedHappinessViewController 的子类了 + +1996 +01:21:58,730 --> 01:22:01,360 +Make sense? +我这么说,明白吗? + +1997 +01:22:01,360 --> 01:22:04,230 +Now, over here in my Storyboard, +回到 Storyboard 中 + +1998 +01:22:04,230 --> 01:22:07,770 +I am going to select this scene right here. +选择这个的场景 + +1999 +01:22:07,770 --> 01:22:10,400 +And I'm going to go to the Identity Inspector, and +打开 Identity Inspector + +2000 +01:22:10,410 --> 01:22:12,240 +I am going to say that this scene is no +这个场景的类,不再是 + +2001 +01:22:12,240 --> 01:22:14,210 +longer a HappinessViewController. +HappinessViewController + +2002 +01:22:14,210 --> 01:22:18,510 +It is a DiagnosedHappinessViewController. +而是 DiagnosedHappinessViewController + +2003 +01:22:18,510 --> 01:22:20,010 +So now I'm this guy here. +现在笑脸的类已经改变了 + +2004 +01:22:20,010 --> 01:22:23,550 +Now, all my outlets that were set up will +我之前设置好的那些 outlet + +2005 +01:22:23,550 --> 01:22:24,820 +work absolutely just fine. +不会出现任何的问题 + +2006 +01:22:25,750 --> 01:22:27,320 +Okay? Because I'm gonna inherit all +因为它是子类 + +2007 +01:22:27,320 --> 01:22:30,490 +the capability of HappinessViewController in my +继承了父类的 + +2008 +01:22:30,490 --> 01:22:32,690 +DiagnosedHappinessViewController subclass. +所有东西 + +2009 +01:22:32,690 --> 01:22:35,220 +In fact, what's really cool is I have a scene right here. +更酷的事情是 + +2010 +01:22:35,230 --> 01:22:39,530 +And this scene is a DiagnosedHappinessViewController. +这个 DiagnosedHappinessViewController 的场景 + +2011 +01:22:39,530 --> 01:22:45,330 +But if I go up here to pick a different class. +我在 Assistant View 里选择一个不同的类 + +2012 +01:22:45,330 --> 01:22:46,820 +If I go back and +如果我选择 + +2013 +01:22:46,820 --> 01:22:48,300 +pick my HappinessViewController, and I see it here. +选择 HappinessViewController,这里我看到它显示出来了 + +2014 +01:22:48,300 --> 01:22:51,500 +You can see that it'll show me that that's hooked up. +你可以看到,outlet 依旧是链接起来的 + +2015 +01:22:51,510 --> 01:22:53,510 +Okay, cuz it knows that this is inherited, +因为它知道其中的继承关系 + +2016 +01:22:53,510 --> 01:22:54,670 +this outlet is inherited. +outlet 也被继承了 + +2017 +01:22:54,680 --> 01:22:56,540 +And so it's hooked up. +所以一切都链接好了 + +2018 +01:22:56,540 --> 01:22:59,880 +So I can still go back and show my +所以当你继承了某个类的时候,如果你担心 outlet 的链接的话 + +2019 +01:22:59,880 --> 01:23:03,150 +superclasses for my DiagnosedHappinessViewController to +你可以返回这个子类的父类 + +2020 +01:23:03,150 --> 01:23:05,580 +HappinessViewController, and see the outlets. +来检查这些 outlet 的链接 + +2021 +01:23:07,390 --> 01:23:09,120 +Okay? So this is an important thing. +所以这是一个很重要的事情 + +2022 +01:23:09,120 --> 01:23:11,250 +Polymorphism of controllers, here. +这里你看到的是,控制器的多态性 + +2023 +01:23:11,260 --> 01:23:13,760 +You often might have a reusable controller. +你通常会有一个可重用的控制器 + +2024 +01:23:13,760 --> 01:23:15,160 +And you wanna add something to it for +也许你想要在某个 Stroryboard 中 + +2025 +01:23:15,160 --> 01:23:16,960 +a particular Storyboard or +为其添加特定的功能 + +2026 +01:23:16,960 --> 01:23:18,590 +a particular use in the Storyboard. +或作为一个特殊的用途 + +2027 +01:23:18,600 --> 01:23:21,730 +Then you can just create a little subclass of it and +这样,你就可以创建一个它的子类 + +2028 +01:23:21,730 --> 01:23:23,930 +put your prepare. +在子类中实现 prepareForSegue + +2029 +01:23:23,930 --> 01:23:26,130 +So what we're gonna do is put our prepare right in here. +所以我们要在这里实现 prepareForSegue + +2030 +01:23:27,270 --> 01:23:28,140 +Okay? + +2031 +01:23:28,140 --> 01:23:30,090 +So this +首先,这个 + +2032 +01:23:30,090 --> 01:23:32,040 +DiagnosedHappinessViewController, first of all it's +DiagnosedHappinessViewController + +2033 +01:23:32,040 --> 01:23:35,310 +going to have to keep track of the diagnosed happinesses. +负责追踪诊断记录 + +2034 +01:23:35,310 --> 01:23:38,510 +Okay. So we're gonna add a new var +所以我们要给子类添加一个新的变量 + +2035 +01:23:38,510 --> 01:23:43,080 +to this subclass called diagnosed happiness. +叫做 diagnosedHappiness + +2036 +01:23:43,080 --> 01:23:46,990 +Or diagnosticHistory, let's call it. +或者叫做 diagnosticHistory + +2037 +01:23:46,990 --> 01:23:49,450 +Okay it's the diagnostic history of this thing, +它就是这个东西的诊断历史 + +2038 +01:23:49,460 --> 01:23:52,690 +and we're just gonna keep it as an Array of Ints. +用它来存储一个 Int 数组 + +2039 +01:23:52,690 --> 01:23:54,660 +So we've got our nice diagnostic history right +现在我们有了一个 diagnosticHistory 变量 + +2040 +01:23:54,660 --> 01:24:00,400 +there, and now let's go ahead and let's do this. +接着,让我们 + +2041 +01:24:00,400 --> 01:24:04,530 +Let's go here and here and +让我们关闭侧边栏 + +2042 +01:24:05,500 --> 01:24:07,800 +here to give ourselves some room. +留出一些空间 + +2043 +01:24:07,810 --> 01:24:09,970 +And let's override. +让我们开始重写 + +2044 +01:24:09,970 --> 01:24:14,080 +Actually, we don't even have to type the override here +其实我们不必在这里输入 override + +2045 +01:24:14,080 --> 01:24:17,310 +because we start typing prepareForSegue end tab. +因为在输入 prepareForSegue 的时候,按一下 Tab 键 + +2046 +01:24:17,310 --> 01:24:18,450 +It's going to automatically put +它就会自动 + +2047 +01:24:18,450 --> 01:24:20,850 +the override func in there for us, which is nice. +出现 override func + +2048 +01:24:20,850 --> 01:24:23,780 +We don't have to be typing this unnecessarily. +我们就不需要键入这些不必要的东西了 + +2049 +01:24:23,790 --> 01:24:25,250 +So here's our prepareForSegue. +这就是我们的 prepareForSegue + +2050 +01:24:25,250 --> 01:24:28,490 +And so all we're going to be doing in this prepareForSegue +我们在这个函数里需要做的就是 + +2051 +01:24:28,490 --> 01:24:31,960 +is prepare our TextViewController, all right? +为 TextViewController 做好准备 + +2052 +01:24:31,960 --> 01:24:34,360 +Because our TextViewController, here, +因为 TextViewController + +2053 +01:24:34,360 --> 01:24:37,100 +is what we're seguing to. +是我们将要跳转的 + +2054 +01:24:37,100 --> 01:24:38,900 +So we're preparing this segue right here. +所以我们在这里做好准备 + +2055 +01:24:38,900 --> 01:24:40,530 +So we wanna prepare this MVC, +我们想要准备这个 MVC + +2056 +01:24:40,530 --> 01:24:43,000 +which is a TextViewController, okay? +也就是一个 TextViewController + +2057 +01:24:43,000 --> 01:24:44,630 +So let's prepare that. +所以我们开始实现准备的代码 + +2058 +01:24:44,640 --> 01:24:49,510 +And let's, first of all, make sure that this is +首先,我们要确保 + +2059 +01:24:49,510 --> 01:24:51,940 +the segue we're talking about, here. +这是我们的想要的那个 segue + +2060 +01:24:51,940 --> 01:24:55,340 +So let's go right here, check our identifiers, +到这里检查一下 identifier + +2061 +01:24:55,350 --> 01:24:57,710 +get our identifier out of there. +获取一下 identifier + +2062 +01:24:57,720 --> 01:24:59,310 +Let's switch on our identifier. +在这里 switch identifier + +2063 +01:24:59,320 --> 01:25:04,590 +Currently, we only support this one case. +目前我们只有这一种 case + +2064 +01:25:04,590 --> 01:25:06,620 +I'm also going to put this case, +所以我会把它放在这里 + +2065 +01:25:06,620 --> 01:25:08,650 +this is something you should probably always do, +在这里有一个需要你们注意的地方,通常你们应该也会这么做的 + +2066 +01:25:08,660 --> 01:25:11,990 +which is to put the segue identifier here into some +就是,把 segue 的 identifier + +2067 +01:25:11,990 --> 01:25:15,200 +sort of constants struct. +放进某个结构体中,作为一个常亮 + +2068 +01:25:15,200 --> 01:25:17,260 +I'm gonna call this my history struct. +我把这个结构体命名为 History + +2069 +01:25:17,270 --> 01:25:21,630 +I'm going to have, and let me make sure this is private. +我要把它设置为 private + +2070 +01:25:21,640 --> 01:25:25,770 +Oops. Let's type +打错了 + +2071 +01:25:25,770 --> 01:25:27,240 +this correctly here, private. +更正一下,private + +2072 +01:25:27,240 --> 01:25:29,540 +All right. +好的 + +2073 +01:25:29,540 --> 01:25:32,280 +Yes. + +2074 +01:25:32,280 --> 01:25:35,010 +I'm going to have this be static let +接着我会创建一个静态常量 + +2075 +01:25:35,010 --> 01:25:39,450 +Segue equal that Show Diagnostic History. +static let Segue = "Show Diagnostic History" + +2076 +01:25:39,450 --> 01:25:42,150 +So this would be a segue identifier. +它现在就是一个 segue identifier 了 + +2077 +01:25:42,150 --> 01:25:46,320 +Maybe we'd even want to call this identifier, +也许,我更想称之为 + +2078 +01:25:46,320 --> 01:25:48,120 +segue identifier. +SegueIdentifier + +2079 +01:25:48,130 --> 01:25:52,190 +All right. + +2080 +01:25:52,200 --> 01:25:55,230 +All right, so putting this in here it just, you know, +这个结构体的作用 + +2081 +01:25:55,230 --> 01:25:57,900 +collects all your constant Strings together. +就是存放所有的常量 String + +2082 +01:25:57,900 --> 01:25:59,970 +And if you ever change something in your Storyboard. +如果你想改变 Storyboard 里的东西,你也得对这个进行一个修改 + +2083 +01:25:59,970 --> 01:26:02,670 +Some people might even call this struct Storyboard, so +有人可能希望给这个结构体起名为 Storyboard + +2084 +01:26:02,670 --> 01:26:06,110 +that every String that's in your Storyboard that has to +也就是,在 Storyboard 里出现的每一个字符串 + +2085 +01:26:06,110 --> 01:26:08,540 +match up here in their code, is in one struct. +都要和代码中的这个结构体连接起来 + +2086 +01:26:08,540 --> 01:26:11,540 +We'll call this one History right here. +对这个结构体起名是有争议的 + +2087 +01:26:11,550 --> 01:26:13,210 +It's kind of debatable which way to go there. +但这里,我们久称之为 History + +2088 +01:26:14,410 --> 01:26:16,500 +So what do +所以 + +2089 +01:26:16,500 --> 01:26:18,580 +we want to do when that history identifier happens? +在 History.SegueIdentifier 的这种情况下,我们需要做什么 + +2090 +01:26:18,590 --> 01:26:23,450 +Well, if we can get our segue's destinationViewController +们能够获取到 segue 的 destinationViewController + +2091 +01:26:23,460 --> 01:26:26,590 +as a TextViewController, +并将其类型转换成 TextViewController + +2092 +01:26:26,590 --> 01:26:30,760 +that's the only thing we need to segue to with this segue. +这是这个 segue 跳转到的唯一的那个控制器 + +2093 +01:26:30,760 --> 01:26:33,730 +Then we're just going to set the tvc's text equal to +然后我们输入 tvc.text = diagnosticHistory + +2094 +01:26:33,730 --> 01:26:35,100 +our diagnosticHistory, + +2095 +01:26:35,100 --> 01:26:37,630 +which I'm going to do by diagnosticHistory. +这就是我希望对 diagnosticHistory 做的事情 + +2096 +01:26:37,630 --> 01:26:39,830 +So, it's just going to show this Array, +所以,这里它就显示出这个数组的内容了 + +2097 +01:26:39,840 --> 01:26:42,300 +this diagnostic history Array, as a String. +把 diagnosticHistory 这个数组作为一个字符串显示出来 + +2098 +01:26:42,310 --> 01:26:42,940 +All right. + +2099 +01:26:45,640 --> 01:26:48,680 +And of course we'll need the default. +当然,我们需要考虑 default 情况 + +2100 +01:26:48,680 --> 01:26:50,240 +Break out of here. +这里输入简单的 break 就可以了 + +2101 +01:26:51,310 --> 01:26:52,480 +Okay? So there we +现在 + +2102 +01:26:52,480 --> 01:26:54,310 +have this nice diagnostic history. +我们已经有了诊断历史 + +2103 +01:26:54,320 --> 01:26:57,220 +So let's go ahead and run this and see if this is working. +运行一下程序,看看起没起作用 + +2104 +01:27:01,390 --> 01:27:03,190 +All right, so again we click here. +点击这里 + +2105 +01:27:03,190 --> 01:27:04,690 +And, well, it seems to be working, +看来是起作用了 + +2106 +01:27:04,690 --> 01:27:06,560 +cuz it's showing no diagnostic history. +它没有显示诊断记录 + +2107 +01:27:06,560 --> 01:27:08,960 +I haven't clicked any of these. +我还没有点击这些按钮 + +2108 +01:27:08,960 --> 01:27:10,390 +So, since we added this code, +我们已经添加了这部分代码 + +2109 +01:27:10,400 --> 01:27:13,630 +anyway, I haven't gotten any diagnosis, so that's good. +我也还没有做任何诊断,还不错 + +2110 +01:27:13,630 --> 01:27:14,660 +So let's dismiss that. +先把它隐藏起来 + +2111 +01:27:14,670 --> 01:27:17,730 +And here, I'm gonna go there, go there. +到处点一点 + +2112 +01:27:17,740 --> 01:27:19,100 +Oh, it's not working. +它不起作用了 + +2113 +01:27:19,100 --> 01:27:19,870 +So why is it not working? +为什么它不工作了呢 + +2114 +01:27:20,940 --> 01:27:23,640 +Okay, well, we have this nice diagnostic history, but +我们是有这个 diagnosticHistory + +2115 +01:27:23,640 --> 01:27:25,440 +we never actually set it. +但我们从来没有 set 过它 + +2116 +01:27:25,440 --> 01:27:27,270 +Okay, it's always just empty. +它就一直是空的了 + +2117 +01:27:27,280 --> 01:27:28,540 +And so how are we gonna set it, though? +我们通过什么方法 set 它呢 + +2118 +01:27:28,540 --> 01:27:30,980 +We are sub class of HappinessViewController. +这个类是 HappinessViewController 的子类 + +2119 +01:27:30,980 --> 01:27:36,110 +Well, we can just override our var happiness from +我们直接重写 happiness 变量 + +2120 +01:27:36,120 --> 01:27:40,080 +our super class, and do a didSet of our own in here. +在这里写一个自己的 didSet + +2121 +01:27:40,090 --> 01:27:43,420 +So that happiness has its own didSet. +happiness 有它自己的 didSet + +2122 +01:27:43,420 --> 01:27:45,120 +And we're gonna add our own didSet here, +添加自己的 didSet + +2123 +01:27:45,120 --> 01:27:48,960 +which is we're gonna say the diagnosticHistory plus equals +输入代码 diagnosticHistory += happiness + +2124 +01:27:48,960 --> 01:27:51,360 +the happiness, okay? +OK? + +2125 +01:27:51,360 --> 01:27:53,300 +You can use plus equals with an Array but +你可以对 Array 进行 += 操作 + +2126 +01:27:53,300 --> 01:27:55,260 +you have to remember that the argument has to be an Array, +但是你得记住,参数需要是另外一个 Array + +2127 +01:27:55,270 --> 01:27:57,900 +so if you just want to add one thing, +如果你想给它添加一个元素 + +2128 +01:27:57,900 --> 01:28:00,540 +you can just wrap a little Array around it here, okay? +就需要给参数加一个方括号 + +2129 +01:28:00,540 --> 01:28:04,010 +So here, it's perfectly fine to override a var from your +在这里,重写父类的变量 + +2130 +01:28:04,010 --> 01:28:05,320 +super class. +是完全没有问题的 + +2131 +01:28:05,320 --> 01:28:06,640 +If you go look at our super class, +如果你查看一下父类 + +2132 +01:28:06,640 --> 01:28:10,910 +happiness It has a var and even does it's own didSets. +happiness 变量有它自己的 didSet + +2133 +01:28:10,910 --> 01:28:14,910 +So I'm overriding this var, and I do my own didSet, +所以我重写了这个变量,执行我自己的 didSet + +2134 +01:28:14,920 --> 01:28:18,520 +it does not override or replace this didSet. +它没有覆盖父类的 didSet + +2135 +01:28:18,520 --> 01:28:21,390 +So it's gonna do this didSet, and +它只是先执行了父类的 didSet + +2136 +01:28:21,390 --> 01:28:23,320 +then it's gonna do this didSet. +然后再执行子类的 + +2137 +01:28:23,320 --> 01:28:25,260 +So, it'll do both of them. +两个都会执行 + +2138 +01:28:25,260 --> 01:28:27,190 +So it's a really nice feature, the property observers, +所以这是个很不错的特性,property observer + +2139 +01:28:27,190 --> 01:28:29,830 +when you override they don't replace the super class as +当你重写的时候,并没有取代父类的 + +2140 +01:28:29,830 --> 01:28:31,800 +one, they add on to it. +而是添加了一个 + +2141 +01:28:32,770 --> 01:28:34,380 +Okay. +OKay. + +2142 +01:28:34,380 --> 01:28:36,000 +So now our diagnostic history is being added. +所以诊断历史已经添加好了 + +2143 +01:28:36,000 --> 01:28:37,630 +So hopefully now when we go and +希望现在运行程序 + +2144 +01:28:37,640 --> 01:28:39,440 +look in our diagnostic history, it will work. +能够看到诊断的历史 + +2145 +01:28:39,440 --> 01:28:41,200 +So here we'll go dancing tree. +现在点击 Dancing Tree + +2146 +01:28:41,210 --> 01:28:42,770 +Look up here. +查看一下这里 + +2147 +01:28:42,770 --> 01:28:43,870 +And look at that! +看! + +2148 +01:28:43,870 --> 01:28:45,640 +We've got our diagnostic history. +我们已经拥有了诊断的历史 + +2149 +01:28:45,640 --> 01:28:47,680 +Let's go over and do golden bear. +再试试 Golden Bear + +2150 +01:28:47,680 --> 01:28:48,490 +Oh. +哦 + +2151 +01:28:48,490 --> 01:28:49,310 +That's kind of Interesting. +有点意思 + +2152 +01:28:49,310 --> 01:28:50,480 +This is not a very good history. +这个诊断历史并不完整 + +2153 +01:28:50,480 --> 01:28:52,910 +It's only remembering the last thing I redo. +它只记录了我上次点击的记录 + +2154 +01:28:52,920 --> 01:28:56,650 +I wonder why it only remembers the last thing I redo. +我想知道它为什么只记录了上一次的记录 + +2155 +01:28:56,650 --> 01:28:57,250 +That's bad. +不对 + +2156 +01:28:57,250 --> 01:28:58,420 +That's a bug. +这是一个 bug + +2157 +01:28:58,420 --> 01:29:01,090 +So, why has that happened? +什么使得这种情况发生了呢 + +2158 +01:29:01,090 --> 01:29:05,990 +Well, I did it this way to show you, and to remind you, +我之所以这样做,是想要提醒你 + +2159 +01:29:05,990 --> 01:29:08,760 +that these segues, all of these segues that +这些所有的 segue + +2160 +01:29:08,760 --> 01:29:13,130 +are happening here, they are always creating a new MVC. +每次跳转的时候,都会创建一个新的 MVC + +2161 +01:29:13,130 --> 01:29:17,430 +So this segue, when we click on golden bear, dancing tree, +所以当我们每一次点击这些按钮 + +2162 +01:29:17,440 --> 01:29:20,400 +and it segues to this, it creates a brand new MVC. +程序跳转到这里,创建了一个新的 MVC + +2163 +01:29:20,410 --> 01:29:23,770 +And since this is a brand new DiagnosedHappinessViewController +这个新的 DiagnosedHappinessViewController + +2164 +01:29:23,770 --> 01:29:28,140 +it's going to get a brand new +也会有一个新的 + +2165 +01:29:28,150 --> 01:29:31,210 +diagnostic history, which is going to be empty. +空的诊断历史 + +2166 +01:29:31,210 --> 01:29:32,480 +So it is constantly going to +所以每次跳转的时候 + +2167 +01:29:32,480 --> 01:29:34,480 +be reentering it every time we segue. +都会擦除之前的记录 + +2168 +01:29:34,480 --> 01:29:36,200 +We really need to +我们需要把这些诊断记录 + +2169 +01:29:36,200 --> 01:29:37,920 +store this diagnostic history somewhere else. +放在其他的地方 + +2170 +01:29:37,920 --> 01:29:39,850 +We can't just have it be in a far here. +我们不能单单把它放到这里 + +2171 +01:29:39,860 --> 01:29:43,620 +And a great place to have permanent storage, of course, +适合存放这些记录的地方是程序的 + +2172 +01:29:43,620 --> 01:29:46,490 +is in its future defaults. +NSUserDefaultss + +2173 +01:29:46,490 --> 01:29:47,880 +Okay. +Okay. + +2174 +01:29:47,880 --> 01:29:49,260 +So let's change this diagnosticHistory. +我们把 diagnosticHistory 改变一下 + +2175 +01:29:49,260 --> 01:29:52,230 +Instead of being a stored property here, +用计算属性替代 + +2176 +01:29:52,230 --> 01:29:55,370 +let's change it to be a computed property. +之前的存储属性 + +2177 +01:29:55,370 --> 01:29:57,100 +So I'm gonna have it be an Int. +它是 Int 类型的 + +2178 +01:29:57,100 --> 01:29:59,140 +And it's gonna become computed, so +因为它是计算属性 + +2179 +01:29:59,140 --> 01:30:00,470 +it's gonna have a get. +所以它需要一个 get + +2180 +01:30:00,470 --> 01:30:01,540 +And the set. +和 set + +2181 +01:30:01,540 --> 01:30:03,510 +And in the get and the set here, and +在 get 和 set 中 + +2182 +01:30:03,510 --> 01:30:05,570 +I'm gonna go Into UserDefaults. +需要 UserDefaults + +2183 +01:30:07,110 --> 01:30:09,380 +Put this diagnostic history Into UserDefaults, and +把诊断历史放入 UserDefaults 中 + +2184 +01:30:09,380 --> 01:30:10,880 +out of UserDefaults. +或者从 UserDefaults 中获取 + +2185 +01:30:10,880 --> 01:30:13,110 +Since I'm going to be using UserDefaults, +既然我要使用 UserDefaults + +2186 +01:30:13,120 --> 01:30:16,950 +I'm just gonna create a little private let called defaults. +我创建一个 private 常量 defaults + +2187 +01:30:16,950 --> 01:30:17,920 +Which is just gonna be the +它等于 + +2188 +01:30:17,920 --> 01:30:20,450 +NSUserDefaults.standardUserDefaults. +NSUserDefaults.standardUserDefaults. + +2189 +01:30:20,460 --> 01:30:23,160 +You remember this is like a shared version of any of +你们还记得 + +2190 +01:30:23,160 --> 01:30:24,460 +those UserDefaults that we get. +这个获取到的 UserDefaults 吗 + +2191 +01:30:24,460 --> 01:30:27,060 +The whole app is gonna be sharing this, and +整个 App 都共享这一个对象 + +2192 +01:30:27,060 --> 01:30:31,030 +using it to read and write from NSUserDefaults. +靠它读取或写入 NSUserDefaults + +2193 +01:30:31,030 --> 01:30:32,110 +Okay. This is nice, +还不错 + +2194 +01:30:32,110 --> 01:30:33,200 +it's convenient to have this. +有它还是很方便的 + +2195 +01:30:33,200 --> 01:30:35,000 +Makes the code a little more readable to +有了这个变量,代码更具有可读性 + +2196 +01:30:35,000 --> 01:30:36,300 +have this be repeated everywhere, +我们没必要每次都重复这些 + +2197 +01:30:36,300 --> 01:30:39,800 +versus just this little short thing right here. +只需要简单地变量名就可以了 + +2198 +01:30:39,810 --> 01:30:42,240 +All right. So how am I going to get the +怎么写 defaults 的 + +2199 +01:30:42,240 --> 01:30:45,580 +defaults and set the defaults, well let's do set first. +get 和 set 呢?我们先处理 set + +2200 +01:30:45,580 --> 01:30:48,410 +Once we set maybe it will be easier to imagine our get. +一旦完成了 set,get 也比较容易想了 + +2201 +01:30:48,410 --> 01:30:49,780 +So I am just going to go to defaults, +所以,我只是要去使用 defaults + +2202 +01:30:49,780 --> 01:30:53,680 +I am going to set an object and remember that this is +我准备创建一个对象并且记住它是一个 AnyObject + +2203 +01:30:53,680 --> 01:30:56,480 +any object, but it has to be a property list, okay? +但它必须是一个属性列表,明白? + +2204 +01:30:56,490 --> 01:30:59,220 +But luckily an Array of Ints, +但是幸运的是它是一个 Int 型的数组 + +2205 +01:30:59,220 --> 01:31:02,320 +which is what our diagnostic history is. +这就是我们的诊断历史 + +2206 +01:31:02,330 --> 01:31:04,630 +Sorry, this isn't an Array of Ints, +抱歉,这不是一个 Int 型数组 + +2207 +01:31:04,630 --> 01:31:09,160 +this diagnose is an Array of Ints, +这个诊断是一个 Int 型的数组 + +2208 +01:31:09,160 --> 01:31:12,130 +that is a property so luckily, we can do that. +很幸运的是这只是一个属性,我们可以操作它 + +2209 +01:31:12,130 --> 01:31:14,500 +And here we're in the setting, okay, so +在这里我们在 set 中 + +2210 +01:31:14,500 --> 01:31:16,840 +we're just gonna put our new value here. +所以我们只需要把我们的新的值放到这里 + +2211 +01:31:16,840 --> 01:31:19,770 +So that's gonna be an Array of Ints, the new value. +所以 newValue 将会是一个 Int 型的数组 + +2212 +01:31:19,770 --> 01:31:22,910 +For key we need a key, so let's go back down to +我们需要一个 Key,所以让我们回到 + +2213 +01:31:22,910 --> 01:31:25,940 +our constants here and add another one, and +常量这里再添加一个 + +2214 +01:31:25,950 --> 01:31:30,250 +this is going to be our called defaults key, for the history. +起名为 DefaultsKey + +2215 +01:31:30,250 --> 01:31:34,320 +And we can really put anything we want in here, any name for +并且我们可以起任何名字 + +2216 +01:31:34,320 --> 01:31:38,220 +the key, but remember that default is a database that is +但是记住这是默认的数据库 + +2217 +01:31:38,220 --> 01:31:41,790 +shared in our entire application, so we might want +在我们的整个应用程序中共享,所以我们也许想要 + +2218 +01:31:41,790 --> 01:31:44,860 +to kind of name space it a little bit by saying +起一个带有命名空间的名字 + +2219 +01:31:44,860 --> 01:31:48,430 +diagnosedHappinessViewController.History or +diagnosedHappinessViewController.History 或者 + +2220 +01:31:48,430 --> 01:31:50,130 +something like that. +一些类似于这样的名字 + +2221 +01:31:50,130 --> 01:31:54,300 +So this is just a naming convention to throw the name +所以,这只是一个命名约定将 + +2222 +01:31:54,300 --> 01:31:57,300 +of the ViewContoller or the name of the class in general. +ViewContoller 的名字 或者类的名字放到 + +2223 +01:31:57,310 --> 01:31:59,340 +That is writing to the default in front. +名字的前面 + +2224 +01:32:00,510 --> 01:32:01,880 +You don't have to do this. +你不必做成这样 + +2225 +01:32:01,880 --> 01:32:05,280 +This is purely something you just want to be consistent +这只是使你的程序 + +2226 +01:32:05,280 --> 01:32:06,750 +with in your whole application and +保持一致并且 + +2227 +01:32:06,750 --> 01:32:09,150 +how you divide up this name space for the defaults, +对于 defaults,把它分成不同的命名空间 + +2228 +01:32:09,150 --> 01:32:12,920 +because this is a global name space inside your application. +因为在你的应用里这是一个全局的命名空间 + +2229 +01:32:14,020 --> 01:32:18,060 +So this will be our History.DefaultsKey. +这里写 History.DefaultsKey + +2230 +01:32:18,060 --> 01:32:21,630 +All right, so that's the new write our any time we set this +每一次 set 以后 + +2231 +01:32:21,630 --> 01:32:25,800 +diagnostic history it's gonna write it out to user defaults. +我们创建的这个诊断历史,它将会写在用户的 defaults 中 + +2232 +01:32:25,800 --> 01:32:27,100 +Then similarly we can get it +那么同样的,我们处理一下 get 方法 + +2233 +01:32:27,100 --> 01:32:30,970 +out by just returning defaults.objectForKey. +直接通过返回 defaults.objectForKey + +2234 +01:32:30,970 --> 01:32:32,130 +Same thing. +这都是类似的 + +2235 +01:32:32,140 --> 01:32:33,300 +This History.DefaultsKey. +这个 History.DefaultsKey + +2236 +01:32:33,300 --> 01:32:37,440 +But one thing I wanna make sure of is that it's +但是有一件我想要确定的关于这个的事情是 + +2237 +01:32:37,440 --> 01:32:39,240 +always an Array of Int. +它始终是一个 Int 型的数组 + +2238 +01:32:39,240 --> 01:32:41,710 +So I'm gonna do as Array of Int. +所以我把它转型成 Int 数组 + +2239 +01:32:41,710 --> 01:32:45,150 +And if that returns nil then I'm gonna turn empty Array. +并且如果那个返回一个空值的话我将要把它转为一个空的数组 + +2240 +01:32:45,150 --> 01:32:47,530 +Okay. So if I have +Okay,如果我 + +2241 +01:32:47,530 --> 01:32:49,920 +never saved the diagnostic history to the defaults for +从没有存储诊断记录到 defaults 中 + +2242 +01:32:49,920 --> 01:32:52,020 +example, then this is going to come back nil, +那么这个将会返回一个空值回来 + +2243 +01:32:52,020 --> 01:32:54,620 +okay, but I never have saved it before. +okay,但是我从来没有存储过它 + +2244 +01:32:54,620 --> 01:32:55,690 +So we'll start out with a nice, +所以我们将会在开始时拥有一个漂亮的 + +2245 +01:32:55,690 --> 01:32:56,920 +empty Array in that case. +空的数组 + +2246 +01:32:58,330 --> 01:33:00,430 +Okay. +Okay. + +2247 +01:33:00,430 --> 01:33:02,530 +And also, if somehow some junk had got written here that +同样的,如果一些杂乱的数据被写到了这里 + +2248 +01:33:02,530 --> 01:33:03,690 +wasn't in an Array of Int for +由于一些原因不是 Int 型的数组 + +2249 +01:33:03,700 --> 01:33:05,600 +some reason, then this would also be nil and +那么这也将会是空值并且 + +2250 +01:33:05,600 --> 01:33:06,900 +we would start out with a fresh Array. +我们将以一个新的数组开始 + +2251 +01:33:06,900 --> 01:33:09,670 +It would be kind of a weird case, but anyway so you +它也许会是一种奇怪的情况,但是无论如何你可以 + +2252 +01:33:09,670 --> 01:33:14,100 +can see a simple way here to read and write from default. +在这里看到一种使用 default 进行读写的简单的方式 + +2253 +01:33:14,110 --> 01:33:19,270 +Okay make sense, all right so now let's go run around and +好的体会一下,所以现在让我们运行起来看一下 + +2254 +01:33:19,280 --> 01:33:22,310 +see if this fixed our problem, of our defaults not +如果这个修复我们的问题,我们的 defaults 有没有起作用 + +2255 +01:33:22,310 --> 01:33:24,650 +lying around, so let's see golden bear, dancing tree, +所以让我们看 Golden Bear,Dancing Tree + +2256 +01:33:24,650 --> 01:33:26,350 +buckeye, put a whole bunch in there, +Buckeye,放了几个数据 + +2257 +01:33:26,350 --> 01:33:28,720 +history it's remembering them all. +历史记录它把他们全记下来了 + +2258 +01:33:28,720 --> 01:33:31,800 +Okay. +Okay. + +2259 +01:33:31,800 --> 01:33:34,890 +Golden Bear, 0, Dancing Tree, 100. +Golden Bear, 0, Dancing Tree, 100. + +2260 +01:33:34,890 --> 01:33:36,160 +Okay? +明白? + +2261 +01:33:36,160 --> 01:33:38,460 +That looks quite awesome. +这看起来很不错 + +2262 +01:33:38,460 --> 01:33:39,660 +All right. +好的 + +2263 +01:33:39,660 --> 01:33:40,860 +Let's try one other thing here. +让我们在这里尝试另外一件事 + +2264 +01:33:40,860 --> 01:33:42,060 +Let's go try running this on an iPhone. +让我们在 iPhone 上运行这个程序 + +2265 +01:33:42,060 --> 01:33:45,600 +Let's see how this works on an iPhone, with our great new +让我们看看在 iPhone 上它是怎么工作的 + +2266 +01:33:45,600 --> 01:33:48,730 +feature here, and we'll see what it looks like. +使用我们这些新的特性,我们看看它到底什么样 + +2267 +01:33:52,710 --> 01:33:54,870 +All right so we got there a gold bear. +好吧,按一下 Golden Bear + +2268 +01:33:54,870 --> 01:33:56,370 +We got a dancing tree. +点一下 Dancing Tree + +2269 +01:33:56,380 --> 01:33:58,510 +We got the buckeye. +点一些 Buckeye + +2270 +01:33:58,510 --> 01:34:01,010 +Okay, let's see that history. +好的,让我们看看那个 history + +2271 +01:34:01,010 --> 01:34:05,980 +Whoa, that looks really, really bad, okay? +这看起来非常糟 + +2272 +01:34:05,980 --> 01:34:07,020 +Well, hm. +好的 + +2273 +01:34:07,020 --> 01:34:08,520 +So it didn't put up the history in +它没把历史记录放到类似 iPad + +2274 +01:34:08,520 --> 01:34:10,550 +the little popover like that. +一样的,小的 popover 里 + +2275 +01:34:10,550 --> 01:34:12,620 +It took over the whole screen. +它占据了整个屏幕 + +2276 +01:34:12,620 --> 01:34:16,120 +Modal, it's what a modal segue looks like. +这看起来就是一个 modal 的 segue + +2277 +01:34:16,130 --> 01:34:17,390 +And I put it up here, and +它占据了这里 + +2278 +01:34:17,390 --> 01:34:19,660 +smashed Into my carrier thing up here, and +把我运营商的地方都占据了 + +2279 +01:34:19,660 --> 01:34:22,800 +there's no way to get out of here there's no done button or +也没有办法退出,这里没有完成按钮 + +2280 +01:34:22,800 --> 01:34:26,030 +dismiss or something, because in a popover we don't need to +dismiss 之类的,因为在 popover 里我们不需要 + +2281 +01:34:26,030 --> 01:34:28,770 +dismiss because you just click on the background. +dismiss 因为你只需要点击一下背景 + +2282 +01:34:28,770 --> 01:34:32,870 +So you know, this is really a small amount of information I +所以你知道,我们可以把它放到 popover 中 + +2283 +01:34:32,870 --> 01:34:36,810 +could have put it in a popover there why did iOS adapt that +因为信息量很少,这里为什么 iOS + +2284 +01:34:36,810 --> 01:34:40,240 +popover for the iPhone and put it to your screen? +把 popover 适配为 占据 iPhone 的整个屏幕呢? + +2285 +01:34:40,250 --> 01:34:42,580 +Well, because it doesn't really know how big this is +好的,应为它的确不知道它将会变得多大 + +2286 +01:34:42,580 --> 01:34:45,050 +going to be and how much data is going to be drawn or +有多少数据将要被绘制或者怎么样绘制 + +2287 +01:34:45,050 --> 01:34:48,690 +whatever until it's being displayed. +直到它被显示出来 + +2288 +01:34:48,690 --> 01:34:51,890 +And so on an iPhone to be safe it always adapts +所以在 iPhone 上为了确保稳定,它通常会适应 + +2289 +01:34:51,890 --> 01:34:54,820 +popovers to make them full screen presentation like +popovers 使他们作为全屏展示像是 + +2290 +01:34:54,830 --> 01:34:55,990 +this to take over the screen. +这个接管了整个屏幕一样 + +2291 +01:34:56,990 --> 01:34:59,060 +Okay, but in this case, we don't actually want that. +好的,但是在这个例子中,我们实际上不想那样 + +2292 +01:34:59,060 --> 01:35:00,700 +We don‘t want that adaptation behavior. +我们不想要那个适配行为 + +2293 +01:35:00,700 --> 01:35:02,900 +We want to prevent this adaptation behavior so +我们想防止这个适配行为 + +2294 +01:35:02,900 --> 01:35:06,200 +they just keep putting it in its nice little popover. +只需要把这些数据放入 popover 里就可以了 + +2295 +01:35:06,200 --> 01:35:07,770 +It'll be perfectly fine in iPad and +它在 iPad 上看起来很不错 + +2296 +01:35:07,770 --> 01:35:09,440 +it will be perfectly fine for iPhone. +并且它在 iPhone 也会这样 + +2297 +01:35:09,440 --> 01:35:13,140 +So, how do we prevent this adaptation behavior +所以,我们如何阻止这个适配行为 + +2298 +01:35:13,140 --> 01:35:14,610 +from happening? +发生呢? + +2299 +01:35:15,610 --> 01:35:19,540 +To do that, we need to get at that popover presentation +要想实现,我们需要得到那个 popoverPresentationController + +2300 +01:35:19,550 --> 01:35:24,180 +controller I was talking to you about in the slides. +slide 中讨论过的那个 + +2301 +01:35:24,180 --> 01:35:26,120 +And it's pretty easy to get a hold of it. +并且得到它是非常容易的 + +2302 +01:35:26,120 --> 01:35:27,550 +Inside our prepare- +在 prepareForSegue 中 + +2303 +01:35:27,550 --> 01:35:29,420 +So here's our prepare in our diagnosed, +这个 DiagnosedHappinessViewController + +2304 +01:35:29,420 --> 01:35:32,720 +DiagnosedHappinessViewController right here. +里面的 + +2305 +01:35:32,720 --> 01:35:36,290 +The same place down here where we're doing the preparation +在这里的同一个地方我们准备那些将要发生的事情 + +2306 +01:35:36,290 --> 01:35:40,500 +happening, we can also say if we can let, +我们也可以说 + +2307 +01:35:40,500 --> 01:35:43,330 +ppc I'll call it, equal the text view +if let ppc = + +2308 +01:35:43,330 --> 01:35:46,830 +controller's PopoverPresentationController. +tvc.popoverPresentationController + +2309 +01:35:46,840 --> 01:35:49,450 +Okay. +好的 + +2310 +01:35:49,460 --> 01:35:52,070 +So, this is a method in UI viewcontroller and +所以,这里是一个在 UIViewcontroller 中的方法并且 + +2311 +01:35:52,080 --> 01:35:54,740 +it'll return nil if you're not currently in the process of +它将会返回一个 nil + +2312 +01:35:54,740 --> 01:35:57,310 +being presented in a popover. +如果你当前没有显示 popover + +2313 +01:35:57,310 --> 01:36:00,280 +So if this segue if we changed this segue to +如果我们改变这个 segue + +2314 +01:36:00,280 --> 01:36:03,020 +segue somehow else other than a popover, +跳转到不是 popover 的地方 + +2315 +01:36:03,020 --> 01:36:06,990 +maybe we wanted to go full modal for some reason or +也许我们因为某些原因想要完整的 modal 模式 + +2316 +01:36:06,990 --> 01:36:09,690 +we decided to push it on a navigation stack or +我们决定把它放入一个导航栈中或者 + +2317 +01:36:09,690 --> 01:36:11,820 +whatever then this would return nill and +其他怎么样,这将返回一个空值 + +2318 +01:36:11,830 --> 01:36:14,060 +so nothing that I'm gonna do right here would even happen. +这样的话我在这里做的任何事都将不会发生 + +2319 +01:36:15,530 --> 01:36:18,050 +So what am I going to do? +所以接下来我要做什么? + +2320 +01:36:18,050 --> 01:36:20,560 +I'm just going to set the popoverPresentationControll- +我只是要设置 popoverPresentationController的 + +2321 +01:36:20,570 --> 01:36:24,670 +er's delegate to myself, and that's because the popover +delegate 给 self,那是因为 PopoverController 的 + +2322 +01:36:24,670 --> 01:36:27,340 +controller's delegate allows you to +delegate 允许你 + +2323 +01:36:27,340 --> 01:36:31,510 +have someone else control the way the presentation works. +让其他人控制 popover 工作的方式 + +2324 +01:36:31,510 --> 01:36:35,340 +And this is the first time you're seeing the +并且这是第一次你看到 + +2325 +01:36:35,350 --> 01:36:39,380 +idea of a delegate in an action in an iOS. +在 iOS 系统中的 delegate + +2326 +01:36:39,380 --> 01:36:41,280 +Now you remember when we set ourselves as +现在你记住当我们设置我们自己作为 + +2327 +01:36:41,280 --> 01:36:43,980 +a delegate you can see there's an error right here it says +一个 delegate 的时候 你可以看到这里有一个错误 + +2328 +01:36:43,990 --> 01:36:46,690 +DiagnosedHappinessViewContro- ller does not conform to +它的意思是 DiagnosedHappinessViewController 没有符合 + +2329 +01:36:46,690 --> 01:36:48,520 +this protocol +这个 protocol + +2330 +01:36:48,520 --> 01:36:50,360 +UIPopoverPrsentationControlle- rDelegate. +UIPopoverPrsentationControllerDelegate 的协议 + +2331 +01:36:50,360 --> 01:36:54,630 +And that's true, because up here we have to say we are a +这是真的,因为在这里我们必须说明我们是一个 + +2332 +01:36:54,630 --> 01:36:56,760 +UIPopoverPresentationControll- erDelegate. +UIPopoverPresentationControllerDelegate + +2333 +01:36:57,730 --> 01:36:59,060 +Okay? And now, +明白?现在 + +2334 +01:36:59,070 --> 01:37:03,770 +once we put this on here, we have to go down here and +一旦我们把这个放在这里,我们必须去实现方法 + +2335 +01:37:03,770 --> 01:37:08,440 +actually implement that method, the method we want. +我们想要的那个方法 + +2336 +01:37:08,440 --> 01:37:10,540 +And this method that we want is called +并且那个我们想要的方法被称作 + +2337 +01:37:10,540 --> 01:37:13,980 +adaptivePresentationStyleForPresentationController. +adaptivePresentationStyleForPresentationController + +2338 +01:37:15,050 --> 01:37:18,000 +Okay? +明白? + +2339 +01:37:18,000 --> 01:37:20,950 +And this is basically saying, here's a popover controller. +这里的意思是,这里是一个 popoverController + +2340 +01:37:20,950 --> 01:37:23,180 +You know how, in a delegate method, we +在一个 delegate 方法中 + +2341 +01:37:23,190 --> 01:37:25,850 +usually pass along the thing that's doing the delegation. +我们通常传递的东西在 delegation 中传递一样 + +2342 +01:37:25,860 --> 01:37:29,120 +So this is that same PopoverPresentationController being +所以这就是这个 popoverPresentationController + +2343 +01:37:29,130 --> 01:37:30,790 +passed back to us. +被传递回来了 + +2344 +01:37:30,790 --> 01:37:35,400 +And it's saying, please return a presentation style which you +并且它说,请返回一种你想要的呈现方式 + +2345 +01:37:35,400 --> 01:37:38,760 +want and when you're adapting on the iPhone. +当你运行在 iPhone 上时 + +2346 +01:37:38,770 --> 01:37:43,170 +So I'm gonna return the UIModalPresentationStyle.None, +所以我返回 UIModalPresentationStyle.None + +2347 +01:37:43,170 --> 01:37:46,440 +which means don't adapt, Okay do not when you're on +它的意思是不进行适配,不要在 iPhone 上进行适配 + +2348 +01:37:46,440 --> 01:37:49,370 +iPhone do no adaptations do what you normally do, +不做任何你通常做的修改 + +2349 +01:37:50,310 --> 01:37:51,840 +which is put the pop over in a little window. +把 popover 放到一个小的窗口里 + +2350 +01:37:53,310 --> 01:37:54,480 +And that's it. That's all I +就是这样 + +2351 +01:37:54,480 --> 01:37:56,310 +need to do to suppress that. +这就是我需要做的 + +2352 +01:37:56,310 --> 01:37:58,680 +Now, by the way, +现在,顺便说一下 + +2353 +01:37:58,680 --> 01:38:01,050 +in addition to PPC delegating inside here, I could, there +对于 ppc 的 delegate + +2354 +01:38:01,050 --> 01:38:04,690 +are other methods in PopoverPresentationController. +还有其他 PopoverPresentationController 的方法 + +2355 +01:38:04,690 --> 01:38:10,190 +You can go take a look at, and they will show you things that +你可以查看一下文档 + +2356 +01:38:10,190 --> 01:38:12,860 +you can find out about what's going on with the popover. +你可以发现关于 popover 相关的东西 + +2357 +01:38:12,860 --> 01:38:16,360 +But setting its delegates so that you can control that +但是设置成它的 delegate 这样的话你可以控制 + +2358 +01:38:16,370 --> 01:38:19,230 +adaptation is a popular thing to want to do. +你想做的任何适配操作 + +2359 +01:38:19,240 --> 01:38:20,300 +All right. +好的 + +2360 +01:38:20,300 --> 01:38:21,840 +So let's go try it now on the iPhone again. +所以让我们在 iPhone 上再次尝试一次 + +2361 +01:38:21,840 --> 01:38:25,770 +Here we go let's hit history and +这里让我们敲击 history + +2362 +01:38:25,770 --> 01:38:28,670 +now it's working okay coming up in the pop over here. +现在它在这里弹出的 popover 中工作的很好 + +2363 +01:38:28,680 --> 01:38:31,980 +Let's go add history let's go another dancing tree over here +让我们添加 history,让我们在这里点击 Dancing Tree + +2364 +01:38:31,980 --> 01:38:34,780 +now we've dancing tree added there. +现在我们已经在这里添加了 Dancing Tree + +2365 +01:38:34,780 --> 01:38:37,150 +Okay? +明白? + +2366 +01:38:37,150 --> 01:38:39,520 +And it'll work fine landscape or portrait. +并且它在垂直和水平模式下工作的很好 + +2367 +01:38:42,590 --> 01:38:42,990 +Okay? +明白? + +2368 +01:38:42,990 --> 01:38:43,390 +Questions about that? +有关于这些的问题么? + +2369 +01:38:44,560 --> 01:38:46,440 +All right. +好的 + +2370 +01:38:46,440 --> 01:38:48,320 +The last thing I want to do with the pop over is +最后一件我想对 popover 做的事情是 + +2371 +01:38:48,330 --> 01:38:50,160 +when we ran this pop over, +当我运行这个 popover 的时候 + +2372 +01:38:50,160 --> 01:38:51,990 +over here, you notice that it's kind of big. +在这里,你注意到它是很大的 + +2373 +01:38:52,000 --> 01:38:54,600 +It's covering the whole smiley face for no reason, +它无缘无故地遮盖了住了整个笑脸 + +2374 +01:38:54,600 --> 01:38:58,530 +because it really only needs to be big enough to hold that. +因为它的确是需要变得足够大 + +2375 +01:38:58,540 --> 01:39:02,300 +Well, that's because really again the popover presentation +好吧,那是因为 PopoverPresentationController + +2376 +01:39:02,310 --> 01:39:05,710 +controller really has no idea how big this information is +不知道在这里的信息是有 + +2377 +01:39:05,710 --> 01:39:06,340 +in here. +多大 + +2378 +01:39:07,380 --> 01:39:09,240 +And, but there is a way to tell it. +但是,这里有一种方式可以告诉它 + +2379 +01:39:09,240 --> 01:39:11,910 +And if you think about who knows what the size of +如果你考虑谁知道什么样的尺寸是最好的 + +2380 +01:39:11,910 --> 01:39:15,250 +this is best, well it's the TextViewController. +那就是 TextViewController + +2381 +01:39:15,250 --> 01:39:16,400 +Cuz the text view +因为 TextViewController + +2382 +01:39:16,400 --> 01:39:17,550 +controller's the one that's gonna display this. +是将会在这里显示的控件之一 + +2383 +01:39:17,550 --> 01:39:20,950 +It knows what it's preferred size would be. +它知道它的首选的大小将会是多少 + +2384 +01:39:20,950 --> 01:39:23,050 +So as we're talking about in the slides. +所以当我们在 slide 中讨论的时候 + +2385 +01:39:23,060 --> 01:39:25,090 +Let's go ahead and make it so +让我们继续实现它 + +2386 +01:39:25,090 --> 01:39:27,790 +the TextViewController reports its preferred size. +这样的话 TextViewController 会报告它的首选的尺寸 + +2387 +01:39:27,790 --> 01:39:33,430 +So I'm gonna go over here to the TextViewController. +所以我将到这个 TextViewController 中 + +2388 +01:39:33,430 --> 01:39:35,320 +Okay. +好的 + +2389 +01:39:35,320 --> 01:39:37,200 +Now the prefered size is just a var in +现在首选的尺寸在 UIViewController 是一个 var + +2390 +01:39:37,200 --> 01:39:41,300 +UIV controller so the TextViewController could set that +所以 TextViewController 可以对它进行设置 + +2391 +01:39:41,310 --> 01:39:45,640 +somewhere, it could just say preferredContentSize equals +可以进行 preferredContentSize = _ 之类的操作 + +2392 +01:39:45,640 --> 01:39:49,910 +something, but since this is a subclass UIV controller and +但是因为这是一个 UIViewController 的子类并且 + +2393 +01:39:49,910 --> 01:39:55,150 +the content size would change every time this is changing. +内容的大小可能随时发生变化 + +2394 +01:39:55,150 --> 01:39:57,050 +And also might change depending on +也可能根据一些内容进行改变例如 + +2395 +01:39:57,050 --> 01:39:59,720 +how big a space the popover is being popped Into. +当 popover 进入的时候它占了多大 + +2396 +01:40:01,060 --> 01:40:06,560 +We can actually do better here by overriding the var +实际上我们可以在这里做的更好,通过重写这个 var + +2397 +01:40:06,560 --> 01:40:12,400 +preferredContentSize, which is a CGSsize. +preferredContentSize,类型是 CGSsize + +2398 +01:40:12,400 --> 01:40:16,730 +I'm going to override it and do the get set. +我准备重写它并且做好 get 和 set. + +2399 +01:40:16,740 --> 01:40:19,200 +Okay, so it's going to be a computed property, +好的,所以这将会是一个计算属性 + +2400 +01:40:19,210 --> 01:40:20,940 +get and set. +get 和 set. + +2401 +01:40:20,940 --> 01:40:23,440 +And on the setting side of this, +在 set 中 + +2402 +01:40:23,440 --> 01:40:25,440 +if someone set the preferredContentSize, +如果某人设置好了 preferredContentSize + +2403 +01:40:25,440 --> 01:40:27,140 +I'm just gonna let my super class. +我只需要让我的父类的 + +2404 +01:40:27,150 --> 01:40:32,480 +preferredContentSize do its thing, okay? +preferredContentSize + +2405 +01:40:32,480 --> 01:40:33,920 +We'll just let the new value do that. +等于 newValue + +2406 +01:40:33,920 --> 01:40:36,180 +So I'm going to let my super class handle it or +所以当有人 set 的时候 + +2407 +01:40:36,190 --> 01:40:36,880 +someone sets it. +我让父类来处理 + +2408 +01:40:37,920 --> 01:40:40,920 +All right? +明白? + +2409 +01:40:40,920 --> 01:40:43,920 +But if someone tries to get it, then if my text view has +但是如果有人想要 get 它,接下来如果我的 textView + +2410 +01:40:43,930 --> 01:40:46,890 +been set, so if this outlet has been set, and if I'm in +已经 set 了,所以如果这个 outlet 已经被设置了,并且如果 + +2411 +01:40:46,900 --> 01:40:52,100 +the middle of being presented on screen, okay, then I can +我在中途把它呈现到了屏幕上,好的,接下来我可以 + +2412 +01:40:52,100 --> 01:40:55,100 +ask the text view what its preferred size would be. +向 textView 询问它的首选的尺寸将会是多少 + +2413 +01:40:56,100 --> 01:40:58,540 +Okay, so we're going to let the textView do the work here. +好的,所以我们准备让 textView 处理这里 + +2414 +01:40:58,540 --> 01:40:59,870 +So what does that look like? +所以它看起来的怎么样? + +2415 +01:41:01,510 --> 01:41:03,910 +So, we might say, +我们也许会说 + +2416 +01:41:03,910 --> 01:41:09,110 +for example here, if textView does not equal nil. +if textView != nil + +2417 +01:41:09,110 --> 01:41:13,180 +Oops, I've got sticky keys on here, so +哦,我启用了粘滞键 + +2418 +01:41:13,180 --> 01:41:15,480 +you see that in the lower corner there. +你可以在右下角看得到 + +2419 +01:41:15,490 --> 01:41:18,650 +If textView doesn't equal nil, and if we're +如果 textView 不等于空,并且它正呈现在屏幕中 + +2420 +01:41:18,660 --> 01:41:22,120 +being presented right now so how can we find that out? +怎么能知道正在屏幕当中显示? + +2421 +01:41:22,130 --> 01:41:25,530 +UIViewController has another great var +UIViewController 拥有另一个 var + +2422 +01:41:25,530 --> 01:41:28,760 +called presentingViewController. +叫做 presentingViewController + +2423 +01:41:29,900 --> 01:41:31,900 +The presentingViewController is the View Controller that +presentingViewController 是一个 ViewController + +2424 +01:41:31,900 --> 01:41:35,940 +is currently presenting you via some sort of segue. +通过某种 segue 正在屏幕中显示的 ViewController + +2425 +01:41:35,940 --> 01:41:39,610 +So, in the popover case, it's going to be that +所以,在 popover 情形中 + +2426 +01:41:39,610 --> 01:41:41,840 +DiagnosedViewController's gonna be presenting me. +这个 ViewController 是 DiagnosedViewController + +2427 +01:41:41,840 --> 01:41:44,610 +But whoever it is, I can check to make sure that's not nil. +但是无论是谁在呈现,我可以检查它以确保它不是 nil + +2428 +01:41:45,550 --> 01:41:48,450 +So, this is only gonna happen right here, +所以这里只会在 + +2429 +01:41:48,450 --> 01:41:51,180 +in the case where I'm in the middle of a presentation. +presentingViewController 不是 nil 的时候才会运行 + +2430 +01:41:51,180 --> 01:41:53,550 +Okay, also my text here not to be no it's not clear that I +textView 在这里没必要检查一下 + +2431 +01:41:53,550 --> 01:41:56,720 +really need to set this because, probably my +也许在这之前 + +2432 +01:41:56,720 --> 01:41:59,690 +outlets are all gonna be set before this gets there. +outlets 已经都被设置好了 + +2433 +01:41:59,690 --> 01:42:03,790 +But just to be safe I'll set both of these things and +这样做只是为了保险起见 + +2434 +01:42:03,800 --> 01:42:06,600 +in this case I'm gonna let the text view tell me a size that +在这里返回 textView.sizeThatFits + +2435 +01:42:06,600 --> 01:42:10,500 +fits inside my PresentingViewControllers. +PresentingViewController. + +2436 +01:42:10,500 --> 01:42:13,030 +Viewbounds.size. +Viewbounds.size. + +2437 +01:42:14,040 --> 01:42:15,300 +'Kay? +明白? + +2438 +01:42:15,300 --> 01:42:18,210 +And this of course we will need to unwrap. +当然我们需要解包 + +2439 +01:42:18,210 --> 01:42:20,090 +But it's okay, +但是这没关系 + +2440 +01:42:20,090 --> 01:42:21,970 +cuz we checked to make sure it's not nil first. +因为我们去检查确保它在开始的时候不为空 + +2441 +01:42:21,980 --> 01:42:23,760 +'Kay? +明白? + +2442 +01:42:23,760 --> 01:42:25,540 +So this is the bounds.size of our presentingViewController. +所以这是我们 presentingViewController 的 bounds.size + +2443 +01:42:25,550 --> 01:42:27,710 +So in the diagnosedHappinessViewContro- +所以在 DiagnosedHappinessViewController 中 + +2444 +01:42:27,720 --> 01:42:30,920 +ller case, it's the whole scene, basically. +它是整个屏幕 + +2445 +01:42:30,920 --> 01:42:34,190 +And we're just gonna see what is a good size that fits. +我们只是想看到什么样是适合的尺寸 + +2446 +01:42:34,190 --> 01:42:36,860 +Now this is only a preferredContentSize. +现在这个只是 preferredContentSize + +2447 +01:42:36,860 --> 01:42:39,420 +So if this size that fits were really huge, for +它适应的尺寸是非常巨大的 + +2448 +01:42:39,430 --> 01:42:43,230 +example, the popover's still going to limit the size to +popover 仍然在限定的尺寸范围中 + +2449 +01:42:43,230 --> 01:42:45,130 +whatever its restrictions are, okay? +限制它自己的大小 + +2450 +01:42:45,130 --> 01:42:47,310 +So we just prefer. +所以我们只是提前设定 + +2451 +01:42:47,320 --> 01:42:49,500 +This is not actual content size, it's just preferred. +这不是实际的内容大小,只是希望它的大小 + +2452 +01:42:49,500 --> 01:42:50,770 +Now, what if we're not in +现在,如果 + +2453 +01:42:50,770 --> 01:42:52,030 +the middle of presenting right here? +presentingViewController 是 nil + +2454 +01:42:52,040 --> 01:42:55,610 +Well, then once again I'm going to let my +好吧,然后再一次我去让我的 + +2455 +01:42:55,610 --> 01:42:58,940 +super class do the work here so whatever it +父类完成这里的工作 + +2456 +01:42:58,940 --> 01:43:01,880 +would normally return I'm going to have it return. +无论正常返回的是什么,我都得让它返回一个值 + +2457 +01:43:01,880 --> 01:43:04,780 +So remember I'm overriding this my super class. +记住,我是在重写 + +2458 +01:43:04,780 --> 01:43:06,130 +So really I'm just getting involved in +所以我只是恰巧 + +2459 +01:43:06,130 --> 01:43:07,480 +this one case where I happen to be in the middle of +在这个案例中,屏幕中展示了我 + +2460 +01:43:07,480 --> 01:43:10,250 +presenting something, then I pretty much know what my +然后我非常想知道我 + +2461 +01:43:10,250 --> 01:43:13,490 +size is based on my text field okay? +基于 textfield 的尺寸是多少,明白? + +2462 +01:43:14,490 --> 01:43:17,690 +So let's run and see how that fixes it. +所以让我们运行并且看下问题是否得到解决 + +2463 +01:43:17,690 --> 01:43:20,560 +All right, so the goal is to get our history, excellent. +好的,所以目标是得到 history,非常棒 + +2464 +01:43:20,560 --> 01:43:23,430 +Now notice also, our history was remembered even +现在可以看到,我们的 history 已经被记住了 + +2465 +01:43:23,430 --> 01:43:26,670 +after we quit our app and run it again because we are using +即使我们退出了的应用又重新运行了一下它,因为我们使用了 + +2466 +01:43:26,670 --> 01:43:30,300 +defaults which these defaults remember things when it quits. +NSUserDefault,退出程序也能存储数据 + +2467 +01:43:30,300 --> 01:43:34,570 +So here we got 0, 150, 100, let's go back over here and +所以这里我们得到了0, 150, 100,让我们重新回到这里并且 + +2468 +01:43:34,570 --> 01:43:35,470 +do nothing. +什么都不做 + +2469 +01:43:35,480 --> 01:43:36,610 +25. +25 + +2470 +01:43:36,610 --> 01:43:37,510 +Looks good. +看起来很棒 + +2471 +01:43:37,510 --> 01:43:40,040 +Let's go back and do Golden Bear. +让我们返回并且点一下 Golden Bear + +2472 +01:43:40,050 --> 01:43:42,780 +Zero, so it's working beautifully there. +0,所以它在这里表现地很不错 + +2473 +01:43:42,780 --> 01:43:46,150 +Okay, again it works no matter what size you use. +好的,无论你的尺寸是多少,它都工作地不错 + +2474 +01:43:46,150 --> 01:43:52,520 +Go on there and it will also work on the iPad as well. +它同样在 iPad 上工作的很好 + +2475 +01:43:52,520 --> 01:43:57,660 +There we go. +启动程序 + +2476 +01:43:57,660 --> 01:43:58,730 +So, there's the history. +点击 history + +2477 +01:43:58,730 --> 01:44:00,530 +Shows it up there. +展示了出来 + +2478 +01:44:00,530 --> 01:44:02,730 +There too. +横屏也一样 + +2479 +01:44:02,730 --> 01:44:05,930 +Okay, so that's it for popovers, but we also managed +好的,popover 就到这里 + +2480 +01:44:05,930 --> 01:44:09,040 +to cover a couple other things there along the way. +demo 过程中也涉及了几点知识 + +2481 +01:44:09,040 --> 01:44:12,200 +Most notably was the polymorphism of +尤其是 ViewController 的 + +2482 +01:44:12,210 --> 01:44:14,010 +View Controllers. +多态性 + +2483 +01:44:14,940 --> 01:44:17,740 +And we were in our Storyboard here, +在 Storyboard 中 + +2484 +01:44:17,740 --> 01:44:20,450 +we ended up actually creating a sub class, +我们创建了一个子类 + +2485 +01:44:20,450 --> 01:44:23,580 +DiagnosedHappinessViewContro- ller here to add some more +去添加更多的功能 + +2486 +01:44:23,580 --> 01:44:25,480 +functionality, okay? +明白? + +2487 +01:44:25,480 --> 01:44:27,620 +And that is not an edge case, +并且这不是在一种边缘情况 + +2488 +01:44:27,620 --> 01:44:28,950 +that's a common thing you wanna do. +这么做很正常 + +2489 +01:44:28,950 --> 01:44:31,650 +You have some reusable HappinessViewController or +你有一些可重复使用的 HappinessViewController 或者 + +2490 +01:44:31,660 --> 01:44:33,620 +something like HappinessViewController. +一些像是 HappinessViewController 的东西 + +2491 +01:44:33,620 --> 01:44:36,660 +You wanna use it, but you need to add something to it and +你想要使用它,但是你需要给它添加一些东西 + +2492 +01:44:36,660 --> 01:44:37,460 +you don't wanna change it. +你不想改变它 + +2493 +01:44:37,460 --> 01:44:38,460 +Well, that's exactly what +这就是 + +2494 +01:44:38,460 --> 01:44:39,690 +object oriented programming is for! +面向对象编程的特点 + +2495 +01:44:39,700 --> 01:44:41,800 +You can create a subclass of it and +你可以为它创建一个子类 + +2496 +01:44:41,800 --> 01:44:48,600 +add the methods that you wanna add to it, to your diagnosed. +添加一些你想要给它添加特定的方法 + +2497 +01:44:48,600 --> 01:44:50,570 +And what's kind of nice too +还不错的是 + +2498 +01:44:50,570 --> 01:44:52,540 +is DiagnosedViewController contains all the stuff that +DiagnosedViewController 中包含了所有 + +2499 +01:44:52,540 --> 01:44:56,110 +has to do with the diagnostic business and nothing else. +有关于诊断的事情,而没有其他别的东西 + +2500 +01:44:56,110 --> 01:44:59,850 +So this is a very nice class well contained, +所以这是一个非常好类 + +2501 +01:44:59,850 --> 01:45:02,950 +only has the diagnostic stuff in it. +只有关于诊断的东西 + +2502 +01:45:02,950 --> 01:45:06,050 +Okay, so that's it, and you don't need this for +这就是今天的内容 + +2503 +01:45:06,050 --> 01:45:09,490 +your homework per se, but there is an extra credit item +你不需要把它当成作业 + +2504 +01:45:09,490 --> 01:45:13,320 +to add a popover so hopefully you'll decide to tackle that. +但是 extra credit 中有关于 popover 的内容,希望你们能够解决 + +2505 +01:45:15,430 --> 01:45:15,460 +>> For more, please visit us at stanford.edu. +想要了解更多,请访问:stanford.edu diff --git a/subtitles/8. View Controller Lifecycle, Autolayout.srt b/subtitles/8. View Controller Lifecycle, Autolayout.srt new file mode 100644 index 0000000..d9ba354 --- /dev/null +++ b/subtitles/8. View Controller Lifecycle, Autolayout.srt @@ -0,0 +1,10689 @@ +1 +00:00:00,001 --> 00:00:04,669 +[MUSIC] +[音乐] + +2 +00:00:04,671 --> 00:00:08,072 +Stanford University. +斯坦福大学 + +3 +00:00:08,074 --> 00:00:11,275 +Okay, well, welcome to Lecture 8 of +好的,欢迎来到2015年冬季学期 + +4 +00:00:11,277 --> 00:00:14,812 +Stanford CS193P winter of 2015. + CS193P 的课程 + +5 +00:00:14,814 --> 00:00:18,348 +Today we have two major topics we're gonna talk about, +今天我们会讲到两个主要的话题 + +6 +00:00:18,350 --> 00:00:21,584 +one is view controller life cycle which is your view +一个是 View Controller 的生命周期 + +7 +00:00:21,586 --> 00:00:23,119 +controller gets born. +也就是 View Controller 从产生 + +8 +00:00:23,121 --> 00:00:25,021 +It lives and does a lot of things and +然后完成了一系列的操作 + +9 +00:00:25,023 --> 00:00:27,856 +then it dies and so you want to be able to find out about +到 View Controller 死亡,你希望能够知道 + +10 +00:00:27,858 --> 00:00:30,392 +all those things that are going on and you can. +这些生命周期中,什么事情正在发生,你能在其中做什么 + +11 +00:00:30,394 --> 00:00:32,627 +I'm gonna have a brief demo about that and +这里我会有一个简单的关于生命周期的 Demo + +12 +00:00:32,629 --> 00:00:34,762 +then we're gonna go into auto layout and +接着我们涉及 Auto Layout 的内容 + +13 +00:00:34,764 --> 00:00:37,331 +I keep promising we're gonna talk about it, so +我保证我们会在这节课中讲到它 + +14 +00:00:37,333 --> 00:00:39,967 +I am gonna finally talk about auto layout. +但是我打算最后再讲 Auto Layout + +15 +00:00:39,969 --> 00:00:42,002 +Of course you all ready know a lot about auto layout and +当然,你已经知道一点点 Auto Layout 的知识了 + +16 +00:00:42,004 --> 00:00:43,987 +I'm gonna review that. +我们在今天的课程中会先回顾它们 + +17 +00:00:43,988 --> 00:00:45,971 +Then we're gonna talk about an important piece of auto +然后,我们会讲一讲 Auto Layout 中一个比较重要的部分 + +18 +00:00:45,974 --> 00:00:50,343 +layout that we haven't talked so far which is size classes, +我们从未涉及到的 Size Classes + +19 +00:00:50,345 --> 00:00:53,078 +and then I'll be doing a humongous couple of +这里,我会做一系列的 Demo + +20 +00:00:53,080 --> 00:00:56,181 +demos on auto lab because, you know, it's the kind of thing +来帮助你理解 Auto Layout,你知道,真正看过的东西 + +21 +00:00:56,183 --> 00:00:59,918 +you're going to have to see it to really understand it, but +才是最容易理解的 + +22 +00:00:59,920 --> 00:01:02,453 +first, let's talk about view controller life cycle. +但是首先,我们先讲一下 View Controller 的生命周期 + +23 +00:01:03,723 --> 00:01:06,090 +When we refer to the view controller life cycle, +当我们谈到 View Controller 的生命周期的时候 + +24 +00:01:06,092 --> 00:01:07,691 +we're just talking about a sequence of +我们讲的是,在这个 View Controller 的生命周期中 + +25 +00:01:07,693 --> 00:01:11,261 +messages that is sent to your view controller as it +一系列发送至它的消息 + +26 +00:01:11,263 --> 00:01:12,929 +progresses through its lifetime. +这些消息伴随着整个的生命周期 + +27 +00:01:14,332 --> 00:01:16,231 +Why do we care about this? +我们可能会问,为什么我要关心这个? + +28 +00:01:16,233 --> 00:01:18,967 +Well because you very commonly wanna override these +那是因为,你们通常会在你们的子类中覆写这些 + +29 +00:01:18,969 --> 00:01:20,935 +messages that are sent to the view controller in +发送给 View Controller 的消息 + +30 +00:01:20,937 --> 00:01:23,871 +your subclass to find out what's going on, because you +来知道,你的应用正在干什么 + +31 +00:01:23,873 --> 00:01:26,140 +might need to do things, make certain decisions or +因为你可能希望做一些决定或者其他的操作 + +32 +00:01:26,142 --> 00:01:29,343 +whatever at certain points in your view controller life +在你的 View Controller 生命周期的某个特定的时刻 + +33 +00:01:29,345 --> 00:01:32,846 +cycle, so let's talk about the cycle and how it goes. +所以,让我们来讲一下 View Controller 的生命周期以及它如何工作的 + +34 +00:01:32,848 --> 00:01:34,881 +It starts off with creation. +生命周期由创建一个 View Controller 开始 + +35 +00:01:34,883 --> 00:01:39,352 +99% of the time, this is from a storyboard, all right. +99%的情况下,它是从 Storyboard 中创建的 + +36 +00:01:39,354 --> 00:01:41,987 +As you know, you create these scenes in the storyboard. +你所知道的,你可以在 Storyboard 中创建这些场景 + +37 +00:01:41,989 --> 00:01:44,856 +Those scenes have a view controller class associated +这些场景会关联一个 View Controller 的类 + +38 +00:01:44,858 --> 00:01:48,493 +with them and you're just, you're segueing to an MVC, +并且,你 segue 到一个 MVC + +39 +00:01:48,495 --> 00:01:52,897 +even if you create an MVC in code, which I don't even talk +甚至是你通过代码来创建一个 MVC 的 + +40 +00:01:52,899 --> 00:01:54,732 +about how to do, maybe we'll talk about it a little later +虽然我目前还没有讲到如何通过代码来创建,不过可能之后会讲到 + +41 +00:01:54,734 --> 00:01:56,433 +in the quarter, but could look up in the documentation, +不过你还是可以通过查找文档来获取这些方法 + +42 +00:01:56,435 --> 00:01:58,218 +it's quite easy. +挺容易的 + +43 +00:01:58,219 --> 00:02:00,002 +Even in that case, you're going to instantiate a view +就在这样的情况下,你将会使用一个标识符(identifier) + +44 +00:02:00,005 --> 00:02:03,006 +controller using identifier in the storyboard, okay, and +在 Storyboard 中去初始化一个 View Controller + +45 +00:02:03,008 --> 00:02:04,707 +that's how you're gonna get the view controller, +那就是你如何得到 View Controller 的 + +46 +00:02:04,709 --> 00:02:07,643 +so creation is all most always from the storyboard, and +所以,大多数情况下,是通过 Storyboard 创建 View Controller 的 + +47 +00:02:07,645 --> 00:02:10,479 +there is an init that gets called, it's kind of a weird +并且,有一个 init 方法被调用,但是是一个挺奇怪的 init 方法 + +48 +00:02:10,481 --> 00:02:12,847 +init, initWithCoder, I'm not gonna talk about it too much, +initWithCoder: ,我不打算花时间讲这个方法 + +49 +00:02:12,849 --> 00:02:15,283 +I mentioned it a little bit in the reading assignment, +我会在阅读作业中涉及一点点 + +50 +00:02:15,285 --> 00:02:16,784 +number one or number two. +好像是作业 No.1 或者 No.2 + +51 +00:02:16,786 --> 00:02:20,654 +I don't remember, so there is an init but we try to stay +我不记得了,所以,这里有一个 init + +52 +00:02:20,656 --> 00:02:23,223 +away from init so if we can, if they're somewhere else, and +但是我们尽可能不去调用 init,有其他的初始化方法 + +53 +00:02:23,225 --> 00:02:25,492 +in the view control life cycle there's a lot of +在 View Controller 的生命周期里,你可以看到一大堆 + +54 +00:02:25,494 --> 00:02:28,995 +somewhere else's to initialize things besides in init, so +除了 init 之外的其他的初始化方法 + +55 +00:02:28,997 --> 00:02:32,698 +I'm not even gonna talk about the init right here. +所以我现在并不打算涉及到 init + +56 +00:02:32,700 --> 00:02:35,100 +Okay, what happens after that initialization though? +好的,初始化之后会发生什么呢? + +57 +00:02:35,102 --> 00:02:36,468 +Well, the first thing is, +第一个发生的事情是 + +58 +00:02:36,470 --> 00:02:40,638 +you get prepared if you're being segued to, all right, +如果你被 segue 到这个 View Controller 的话,那么你会准备好(get prepared) + +59 +00:02:40,640 --> 00:02:44,575 +the next thing is your outlets are gonna get set, 'kay. +另外一个发生的事情是,你的 outlets 都被设置好了,明白了吗? + +60 +00:02:44,577 --> 00:02:47,444 +It's just we're gonna wire up all those at sign IV outlets +就是那些我们与 IBOutlet 链接的东西 + +61 +00:02:47,446 --> 00:02:50,747 +that you have, and then your view controller's gonna +接下来,你的 View Controller 会显示在屏幕上 + +62 +00:02:50,749 --> 00:02:53,316 +appear on screen and then it might disappear and +接着消失在屏幕上 + +63 +00:02:53,318 --> 00:02:56,486 +then might reappear and then disappear, okay, and +之后可能又显示在屏幕上,再次消失 + +64 +00:02:56,488 --> 00:02:59,155 +its geometry might change because of auto rotation or +而且,它的几何位置(geometry)可能因为自动旋转 + +65 +00:02:59,157 --> 00:03:02,991 +something else happens and changes the geometry review, +或者发生一些其他的事情导致了几何位置的改变 + +66 +00:03:02,993 --> 00:03:04,292 +so that's happening. +这就是发生的东西 + +67 +00:03:04,294 --> 00:03:06,494 +And then in obscure cases, +在一些复杂的情况下 + +68 +00:03:06,496 --> 00:03:09,296 +you might have a low memory situation on your device and +你可能会遇到一个设备可用内容低的一个情况 + +69 +00:03:09,298 --> 00:03:13,367 +the system might try to get you involved to resolve that, +系统可能尝试让你解决这个问题 + +70 +00:03:13,369 --> 00:03:15,402 +and we'll talk about that briefly, all right, so +我们会简单地讲讲这个,好的 + +71 +00:03:15,404 --> 00:03:17,104 +that's the cycle. +这就是 View Controller 的生命周期 + +72 +00:03:17,105 --> 00:03:18,805 +So what are these methods that are involved in that cycle? +在生命周期中,会有哪些方法涉及到呢? + +73 +00:03:18,807 --> 00:03:22,408 +Well you know about the preparation that's prepared +你知道的,preparedForSegue 做了准备工作 + +74 +00:03:22,410 --> 00:03:25,044 +for segue and some other MVC that's what prepares you, +一些其他的 MVC 准备你 + +75 +00:03:25,046 --> 00:03:28,047 +and you know about outlet setting, right, just +并且,你知道 outlet 设置 + +76 +00:03:28,049 --> 00:03:30,549 +system automatically sets your outlook from your storyboard. +即系统自动从 Storyboard 中设置了你的 outlet + +77 +00:03:30,551 --> 00:03:32,550 +So the next thing that happens is loading, +接下去发生的事情,就是载入(loading) + +78 +00:03:32,552 --> 00:03:35,720 +as your view gets load, well we call that outlet setting, +你的视图被载入。在这之前设置了 outlet + +79 +00:03:35,722 --> 00:03:39,023 +the loading process, and when it's done loading it sends you +接着进入载入的过程,当完成载入的时候 + +80 +00:03:39,025 --> 00:03:40,924 +this message viewDidLoad. +它会发送一个 viewDidLoad 的消息 + +81 +00:03:40,926 --> 00:03:43,760 +ViewDidLoad is an exceptionally good place to +viewDidLoad 是一个非常好的地方 + +82 +00:03:43,762 --> 00:03:47,297 +put stuff to initialize your view, why is it so good? +去放置你初始化你的视图的代码,为什么? + +83 +00:03:47,299 --> 00:03:51,634 +Because you're prepared by whoever's segueing to you, and +那是因为,你,View Controller,已经由 segue 到你的对象准备好了 + +84 +00:03:51,636 --> 00:03:54,970 +your outlets are all set, 'kay, so you're in +而且你的 outlet 也被设置完成了 + +85 +00:03:54,972 --> 00:03:57,706 +great shape to go do things to initialize your view, +你处于一个初始化你的视图操作的最佳时机 + +86 +00:03:57,708 --> 00:04:01,343 +cuz you are all kinda set up and ready to go. +因为你需要的设置已经都设置完了,你已经准备做接下来的操作了 + +87 +00:04:01,345 --> 00:04:03,644 +Now, when you override viewDidLoad, it's important to +现在,如果你覆写了 viewDidLoad 方法 + +88 +00:04:03,646 --> 00:04:06,147 +call super.viewDidLoad and in fact in +一件很重要的事情就是,别忘了调用 super.viewDidLoad + +89 +00:04:06,149 --> 00:04:09,249 +all these life cycle methods you always wanna call super. +而且在 View Controller 中所有生命周期相关的方法中,你始终希望调用 super 的相应方法 + +90 +00:04:09,251 --> 00:04:10,817 +You can either call it at the beginning or at the end, +你可以在方法的开头或者结尾调用 super.viewDidLoad + +91 +00:04:10,819 --> 00:04:13,586 +kind of up to you, doesn't really matter usually but +这个你自己来决定,通常不会有太大的关系 + +92 +00:04:13,588 --> 00:04:16,289 +you definitely want to let super have a chance to do it, +但是,你希望 super 有机会去做它的事情 + +93 +00:04:16,291 --> 00:04:18,457 +'kay, so don't forget about that. +所以,千万不要忘了 + +94 +00:04:19,560 --> 00:04:23,095 +Now one thing that you often wanna do in vewDidLoad is +通常你在 viewDidLoad 里做的一件事情是 + +95 +00:04:23,097 --> 00:04:24,729 +update your UI, okay? +更新你的用户界面,明白了吗? + +96 +00:04:24,731 --> 00:04:27,765 +Now you're gonna be updating your UI in the property +之前我们说过,一旦你的模型发生了改变 + +97 +00:04:27,767 --> 00:04:31,035 +observers of all your things that change the model, and +你会在模型的属性观察器(property observer)中更新用户界面 + +98 +00:04:31,037 --> 00:04:33,804 +you should continue to do that because your view +你应该继续去做这个操作,因为你的 View Controller + +99 +00:04:33,806 --> 00:04:36,440 +control might be on screen all ready loaded, +已经被载入,也显示在屏幕上了 + +100 +00:04:36,442 --> 00:04:39,576 +someone changes the model, you gotta update the UI. +有些人改变了模型,你必须更新你的用户界面 + +101 +00:04:39,578 --> 00:04:42,178 +But when you're first having your thing created and +但是,当你刚创建了一个 View Controller 的时候 + +102 +00:04:42,180 --> 00:04:44,313 +you want to update your UI, it's kind of, +你同样需要更新你的用户界面 + +103 +00:04:44,315 --> 00:04:47,149 +you know, your property observer's in your model, and +那是因为,你的在模型中的属性观察器 + +104 +00:04:47,151 --> 00:04:50,152 +aren't really updating the UI because your outlets aren't +并不会在 outlet 设置之前去真正更新你的用户界面 + +105 +00:04:50,154 --> 00:04:52,354 +set maybe because you're in the prepare for +因为你在 preparedForSegue 的过程中 + +106 +00:04:52,356 --> 00:04:53,688 +segue phase right? +对吗? + +107 +00:04:53,690 --> 00:04:55,956 +So a lot of times, you get to viewDidLoad and +所以,很多时候,当 View Controller 被调用 viewDidLoad 的时候 + +108 +00:04:55,958 --> 00:04:59,059 +you haven't really been able to update your UI because your +用户界面并没有真正被更新,因为你的 + +109 +00:04:59,061 --> 00:05:00,660 +outlets haven't been set, so +outlet 在这之前还没有被设置好 + +110 +00:05:00,662 --> 00:05:03,430 +viewDidLoad is a great place to then update your UI. +所以,viewDidLoad 是一个更新用户界面的好时候 + +111 +00:05:03,432 --> 00:05:07,033 +So if you factor out updating UI into a separate method like +如果你重构了用户界面的代码并将其分离一些其他的代码 + +112 +00:05:07,035 --> 00:05:09,502 +we did in the demo called update UI, but +比如我们在 Demo 中称之为 updateUI 的方法 + +113 +00:05:09,504 --> 00:05:11,637 +you can call whatever you want, or +但是,你可以调用任何你想要调用的方法 + +114 +00:05:11,639 --> 00:05:15,273 +you can even have a couple different UI updating methods, +或者是,你还可以有一些不同的更新用户界面的方法 + +115 +00:05:15,275 --> 00:05:18,677 +calling those in viewDidLoad is very common, 'kay, +在 viewDidLoad 里调用它们是很常见的方法 + +116 +00:05:18,679 --> 00:05:22,313 +cuz your view is ready to be updated, however, you have to +需要注意的是,虽然你的视图准备被更新 + +117 +00:05:22,315 --> 00:05:26,183 +be careful here because your geometry is not yet set, 'kay? +但是,你的几何位置还没有被设置,好吗? + +118 +00:05:26,185 --> 00:05:27,517 +You only get loaded once, +你只会被载入一次 + +119 +00:05:27,519 --> 00:05:29,753 +when you first come out of the storyboard and +也就是从 Storyboard 中出来 + +120 +00:05:29,755 --> 00:05:31,921 +you get prepared, your outlets gets set, +准备就绪,outlet 设置完毕 + +121 +00:05:31,923 --> 00:05:33,756 +you get viewDidLoad, that's it. +你被调用了 viewDidLoad,仅此一次 + +122 +00:05:33,758 --> 00:05:37,059 +That only happens once in the lifetime of a view controller, +一个 View Controller 的生命周期中只会有一次 + +123 +00:05:37,061 --> 00:05:39,661 +but your geometry, like what your bounds are, +但是你的几何位置,也就是你的边界 + +124 +00:05:39,663 --> 00:05:41,096 +that has not been set yet, +在这个时刻还没有被设置 + +125 +00:05:41,098 --> 00:05:44,332 +that's not gonna be set till later in its lifetime, okay? +在这个 View Controller 生命周期的较晚的时候,它才会被设置,明白了吗? + +126 +00:05:44,334 --> 00:05:47,702 +So do not do, I should have put this in red, do not put, +所以,不要,我应该把这句标记成红色 + +127 +00:05:47,704 --> 00:05:51,005 +do geometry related things in viewDidLoad, 'kay, +“不要在 viewDidLoad 里做与几何位置相关的操作” + +128 +00:05:51,007 --> 00:05:54,374 +you can do almost everything else in viewDidLoad, but +除此之外,你可以做几乎其他的任何操作 + +129 +00:05:54,376 --> 00:05:57,877 +do not do that, 'kay, and we'll talk about where you do +唯独这个不行,你可能会问什么时候才可以做几何位置相关的操作呢? + +130 +00:05:57,879 --> 00:06:01,180 +do those things in a moment here, all right. +我们稍后会讲到 + +131 +00:06:01,182 --> 00:06:04,517 +Next one in the life cycle is viewWillAppear, +下一个在生命周期中被调用的方法是 viewWillAppear + +132 +00:06:04,519 --> 00:06:07,386 +'kay, so that's sent to you right before you're going to +当你的 View Controller 马上要显示在屏幕上的时候 + +133 +00:06:07,388 --> 00:06:08,854 +appear on screen. +它会被调用 + +134 +00:06:08,856 --> 00:06:10,889 +Now, that could be right after viewDidLoad or +这有可能在 viewDidLoad 之后直接被调用 + +135 +00:06:10,891 --> 00:06:12,623 +it could be a long time after viewDidLoad. +或者也有可能在 viewDidLoad 之后,过一会儿才被调用 + +136 +00:06:12,625 --> 00:06:15,192 +It depends on what's going on in your UI, +这个依赖于你用户界面上做的操作 + +137 +00:06:15,194 --> 00:06:17,995 +okay, and viewWillAppear gets an argument, which is +好的,viewWillAppear 会有一个参数 + +138 +00:06:17,997 --> 00:06:20,831 +whether it's an animated appearance or not, 'kay? +这个参数表示这个 View Controller 的出现是否有动画效果的 + +139 +00:06:20,833 --> 00:06:22,966 +Usually you don't care about that. +通常你不需要关心这个参数 + +140 +00:06:22,968 --> 00:06:24,734 +And when would your appearance be animated? +什么时候需要你的 View Controller 的出现带有动画效果呢? + +141 +00:06:24,736 --> 00:06:27,069 +Well you're in a navigation controller and +当你在一个 Navigation Controller 里 + +142 +00:06:27,071 --> 00:06:29,471 +someone presses to segue you on screen, +什么东西触发了 segue 到你的 View Controller 的时候 + +143 +00:06:29,473 --> 00:06:32,207 +you'll slide in, that's the animation, okay? +那么你会通过滑入的方式显示出来,这就是动画效果,明白了吗? + +144 +00:06:33,677 --> 00:06:35,743 +So, viewWillAppear, +好的,viewWillAppear + +145 +00:06:35,745 --> 00:06:38,812 +this could happen all the time, this could happen +这可以在你的 View Controller 的整个生命周期里多次被调用 + +146 +00:06:38,814 --> 00:06:40,981 +repeatedly in the lifetime of your view controller, + +147 +00:06:40,983 --> 00:06:43,416 +cuz your view controller can come on screen or go off. +因为你的 View Controller 能显示在屏幕上,也能从屏幕上消失 + +148 +00:06:43,418 --> 00:06:45,651 +Let's think of an example, split view, +让我们设想一个情况,Split View + +149 +00:06:45,653 --> 00:06:47,586 +the master of a split view. +Split View 的 Master + +150 +00:06:47,588 --> 00:06:50,522 +When you first bring up your iPad user interface, +当你第一次打开 iPad 的用户界面时候 + +151 +00:06:50,524 --> 00:06:52,524 +it's in portrait, you don't see the master, +它是在竖屏模式(portrait)的,你不会看到 Master + +152 +00:06:52,526 --> 00:06:54,659 +you have to kind of slide it out to see the master, +你必须通过滑动来显示 Master + +153 +00:06:54,661 --> 00:06:57,462 +you only see the detail, right, so it's not visible. +这种情况下,你只能看到 Detail,Master 是不可见的 + +154 +00:06:57,464 --> 00:07:00,564 +You rotate to landscape, now the master becomes visible, so +但是,当你旋转你的设备到横屏模式(landscape)的时候,那么 Master 就变的可见了 + +155 +00:07:00,566 --> 00:07:02,066 +you're gonna get viewWillAppear. +这时候 viewWillAppear 会被调用 + +156 +00:07:02,068 --> 00:07:05,902 +You rotate back to portrait, it's off screen. +当你又旋转回竖屏模式的时候,Master 从屏幕上消失了 + +157 +00:07:05,904 --> 00:07:07,904 +You rotate back to landscape, it's gonna appear again, +然后你又旋转到横屏模式,又显示了 + +158 +00:07:07,906 --> 00:07:09,706 +it's gonna send you viewWillAppear again. +viewWillAppear 又会被调用 + +159 +00:07:09,708 --> 00:07:12,475 +So you're gonna get viewWillAppear every time it +所以,每一次 Master 显示在屏幕上的时候 + +160 +00:07:12,477 --> 00:07:14,477 +appears on screen, +viewWillAppear 都会被调用 + +161 +00:07:14,478 --> 00:07:16,478 +'kay, now what would you do when a viewWillAppear? +那么在 viewWillAppear 中,你能够做些什么呢? + +162 +00:07:16,480 --> 00:07:19,014 +A lot of times maybe, if you have to do something very +可能通常的情况下,如果你需要做一些费时间的事情 + +163 +00:07:19,016 --> 00:07:21,282 +expensive, like let's say you have to go out to the network +比如你到网络上去获取什么东西 + +164 +00:07:21,284 --> 00:07:24,118 +to get something, an image or something like that, +一个图片或者其他的 + +165 +00:07:24,120 --> 00:07:27,121 +you might not want to do that in viewDidLoad because maybe +你不想让这些代码在 viewDidLoad 中允许因为 + +166 +00:07:27,123 --> 00:07:30,057 +the user never turns view to landscape and never looks at +用户可能从来不会将屏幕横过来 + +167 +00:07:30,059 --> 00:07:32,426 +your master, maybe you've got an app where the details all +从来不会看你的 Master,用户只关心 Detail 中的内容 + +168 +00:07:32,428 --> 00:07:34,894 +are that matters and people rarely pull out the master. +很少用户会拉出 Master 来看 + +169 +00:07:34,896 --> 00:07:36,646 +Well, you wouldn't wanna do +那么,你不想每一次都调用这些花时间的代码 + +170 +00:07:36,647 --> 00:07:38,397 +that expensive thing until the master actually appeared. +只有当 Master 真正要显示的时候你才希望调用这些代码 + +171 +00:07:38,400 --> 00:07:40,633 +Now, you're gonna wanna do that expensive thing in +而且, 通常你希望能够将这些花时间的代码 + +172 +00:07:40,635 --> 00:07:42,401 +another thread, we'll talk about it on +跑在另外一个线程中,这个我们周三会提到 + +173 +00:07:42,403 --> 00:07:44,236 +Wednesday to keep the main thread active. +如何保持主线程不被阻塞 + +174 +00:07:44,238 --> 00:07:46,438 +And, of course, when that master appeared, if +而且,如果当 Master 显示的时候 + +175 +00:07:46,440 --> 00:07:49,140 +you're waiting for something on the network there's gonna +如果你在等待网络上的数据返回 + +176 +00:07:49,142 --> 00:07:51,642 +be a blank space or something that we'll fill in later, +Master 会是一片空白,或者是一些我们稍后会填充的东西 + +177 +00:07:51,644 --> 00:07:54,078 +maybe you put a spinning wheel, things like that, but +或许你会放置一个 Loading 的滚轮,或者其他的东西 + +178 +00:07:54,080 --> 00:07:56,780 +viewWillAppear since you know you're actually gonna get on +viewWillAppear 已经知道,你要放置在屏幕上的东西可能要花一点点时间 + +179 +00:07:56,782 --> 00:07:59,149 +screen is a place we might kick off something that's +你目前放置的是一个替代物,之后会被替换 + +180 +00:07:59,151 --> 00:08:01,718 +a little bit expensive, also your geometry is set here. +同时你的几何位置也被设置好了 + +181 +00:08:01,720 --> 00:08:04,987 +Okay, by the time you get view will appear your bounds, +所以,当 viewWillAppear 被调用的时候 + +182 +00:08:04,989 --> 00:08:08,424 +your view's bounds, you're a view controller right, so +你视图的边界,还记得你是一个 View Controller 吧? + +183 +00:08:08,426 --> 00:08:11,059 +your view's bound, view.bound is set, so +你视图的边界,view.bound 已经设置好了 + +184 +00:08:11,061 --> 00:08:13,061 +you can do geometry stuff here. +那么你可以在这里做一些几何位置相关的代码 + +185 +00:08:13,063 --> 00:08:16,597 +It's legal and you might want to, 'kay, but +这是完全没有问题的,也正是你希望的 + +186 +00:08:16,599 --> 00:08:19,266 +I'm gonna show you another place you can do that as well +但是,在后面几个 Slide 中,我想给你们展示一个另外的地方 + +187 +00:08:19,268 --> 00:08:21,335 +on the next couple slides. +同样你可以做一些几何位置相关的代码 + +188 +00:08:21,337 --> 00:08:24,804 +There's also a viewDidAppear in addition to viewWillAppear, +除了 viewWillAppear 之外,还有一个 viewDidAppear + +189 +00:08:24,806 --> 00:08:26,072 +'kay, so +好的 + +190 +00:08:26,074 --> 00:08:29,208 +viewDidAppear gets sent to you after you are now on screen. +当你已经显示在屏幕上之后,viewDidAppear 被调用 + +191 +00:08:29,210 --> 00:08:33,912 +You are visible now, 'kay, pretty straightforward, and +此时你是可见的,明白了吗?很明显易懂 + +192 +00:08:33,914 --> 00:08:36,681 +similarly there's viewWillDisappear, so +同样的,与这两个方法相对,有 viewWillDeisappear + +193 +00:08:36,683 --> 00:08:38,416 +you're just about to be taken off screen. +你正要从屏幕上消失的时候被调用 + +194 +00:08:38,418 --> 00:08:41,352 +Again, you're the split view master in landscape, +我们接着上面举的例子,你是横屏模式中 Split View 中的 Master + +195 +00:08:41,354 --> 00:08:43,320 +the person rotates the portrait, you're gonna +如果用户旋转到了竖屏模式,那么 + +196 +00:08:43,322 --> 00:08:46,790 +get viewWillDisappear cuz you're going to disappear, +你的 View Controller 会被调用 viewWillDisappear 方法,因为 Master 视图从屏幕上消失了 + +197 +00:08:46,792 --> 00:08:50,794 +it's just going to show only the detail, 'kay? +随后,屏幕上只会显示 Detail,明白了吗? + +198 +00:08:50,796 --> 00:08:54,864 +Here you might clean up some stuff, you might get rid of +这里你可以做一些清理的操作,你可能会 + +199 +00:08:54,866 --> 00:08:57,867 +some resources that are expensive, like a big image or +清除一些占用资源的对象,类似于一副大图 + +200 +00:08:57,869 --> 00:09:00,135 +something that you can reconstitute fairly quickly, +或者其他你能够快速 + +201 +00:09:00,137 --> 00:09:02,170 +maybe from disk or something. +从磁盘中恢复的东西 + +202 +00:09:02,172 --> 00:09:03,605 +That's the kind of thing you'll do in +这就是你要在 viewWillDisappear 中做的,当然 + +203 +00:09:03,606 --> 00:09:05,039 +viewWillDisappear, and of course, there's a did version +同样的,viewWillDisappear 也有一个 did 版本 + +204 +00:09:05,042 --> 00:09:11,178 +of this too, viewDidDisappear, 'kay, so that will disappear, +viewDidDisappear,明白了吗? + +205 +00:09:11,180 --> 00:09:14,048 +will appear and will disappear in their dids, okay? +willAppear 和 willDisappear 的 did 形态 + +206 +00:09:14,050 --> 00:09:16,317 +Now let's talk about geometry. +接下来,让我们讲一下几何位置 + +207 +00:09:16,318 --> 00:09:18,585 +So when your geometry changes, when your bounds change, +当你几何位置有所变化时,你的边界同样发生了变化 + +208 +00:09:18,587 --> 00:09:21,521 +the system knows that your bounds changed, and +系统知道你的边界改变了,而且 + +209 +00:09:21,523 --> 00:09:24,891 +it knows that you probably have to re-layout your user +他知道,你大概需要重新布局你的用户界面 + +210 +00:09:24,893 --> 00:09:26,158 +interface, okay? + +211 +00:09:26,160 --> 00:09:29,728 +Now 99% of the time, that's gonna happen by magic because +所以,99%的情况下,重新布局是自动完成的 + +212 +00:09:29,730 --> 00:09:32,798 +you've set up your auto layout properly, right, so +因为你已经设置好了 Auto Layout 属性 + +213 +00:09:32,800 --> 00:09:35,467 +you don't even have to do anything, but if for +所以你甚至不需要去做其他的事情 + +214 +00:09:35,469 --> 00:09:37,802 +some reason you wanted to do something, +但是鉴于某些原因,你可能想在这个过程中做什么的话 + +215 +00:09:37,804 --> 00:09:40,271 +you can override one of these two methods, +你可以覆写两个方法中的一个 + +216 +00:09:40,273 --> 00:09:43,574 +viewWillLayoutSubviews and viewDidLayoutSubviews, +viewWillLayoutSubviews 和 viewDidLayoutSubviews + +217 +00:09:43,576 --> 00:09:46,643 +so the system calls viewWillLayoutSubviews anytime +然后系统会在它认为合适的时候去调用 viewWillLayoutSubviews + +218 +00:09:46,645 --> 00:09:48,445 +it wants to, + +219 +00:09:48,446 --> 00:09:50,246 +make sure that your views are properly laid out. +确保你的视图被正确布局 + +220 +00:09:50,248 --> 00:09:54,550 +Now, when it calls, this is not viewsBoundsDidChange, +现在,当它调用的时候,注意这个方法名字不是 viewsBoundsDidChange + +221 +00:09:54,552 --> 00:09:55,818 +that's not the name of this method, +这不是这个方法的名字 + +222 +00:09:55,820 --> 00:09:58,620 +okay, it's a viewWillLayoutSubviews, so +这个方法名字是 viewWillLayoutSubviews + +223 +00:09:58,622 --> 00:10:01,523 +your subviews can get laid out for lots of different reasons, +你的子视图会因为多种原因被重新布局 + +224 +00:10:01,525 --> 00:10:04,325 +maybe one of your subviews changes in a way that causes +可能你视图中的一个发生了改变 + +225 +00:10:04,327 --> 00:10:07,762 +it to change shape and has to be relaid out, et cetera. +比如它的形状发生了改变,整个视图需要重新布局,或者其他类似的情况 + +226 +00:10:07,764 --> 00:10:10,497 +So, viewWillLayoutSubviews is sent to +所以,当你的视图层次或者你的顶层视图的边界发生改变的时候 + +227 +00:10:10,499 --> 00:10:13,400 +you when someone inside your +你会收到 viewWillLayoutSubviews 的消息 + +228 +00:10:13,402 --> 00:10:17,037 +view hierarchy or your top level bounds change in a way + +229 +00:10:17,039 --> 00:10:20,840 +where the system needs you to layout your subviews, okay? +因为系统需要你去重新布局你的子视图,明白了吗? + +230 +00:10:20,842 --> 00:10:23,576 +Now, you can make this happen by calling, just like you +你可以通过通过调用来实现这个 + +231 +00:10:23,578 --> 00:10:26,478 +have set needs display you can say set needs layout. +就像你设置 setNeedsDisplay 那样,setNeedsLayout + +232 +00:10:26,480 --> 00:10:30,715 +You say set needs layout, then the next pass around the event +当你调用了 setNeedsLayout 之后,在下一轮的 Event Loop 中 + +233 +00:10:30,717 --> 00:10:35,286 +loop, the system will re-layout your subviews, 'kay. +系统会重新布局你的子视图,明白了吗? + +234 +00:10:35,288 --> 00:10:38,288 +Now this can be called, quite often this viewWill and +viewWillLayoutSubviews 和 viewDidLayoutSubviews + +235 +00:10:38,290 --> 00:10:42,092 +DidLayoutSubviews because changes are being made all +经常被调用,因为无时无刻都会发生变化 + +236 +00:10:42,094 --> 00:10:44,061 +the time and the system doesn't +系统并不是始终都知道 + +237 +00:10:44,062 --> 00:10:46,029 +always quite know whether that affected your subview, so +是否某个操作影响了你的子视图 + +238 +00:10:46,031 --> 00:10:48,898 +it might ask you to just lay them out again, okay? +所以它可能会让你重新来对子视图布局,明白了吗? + +239 +00:10:48,900 --> 00:10:52,101 +So don't be surprised when you get viewWillLayoutSubviews two +所以,当你的边界改动了一次 + +240 +00:10:52,103 --> 00:10:55,203 +or three times when the bounds only changed once, let's say, +但是你的 viewWillLayoutSubviews 方法被调用了两次或者三次的时候,不要觉得惊讶 + +241 +00:10:55,205 --> 00:10:56,438 +'kay, and you have to, +而且,你需要 + +242 +00:10:56,440 --> 00:10:59,040 +if you're gonna do something in these two methods, +如果你在这两个方法中做了什么的话 + +243 +00:10:59,042 --> 00:11:01,108 +you're gonna have to do the right thing, +你必须做的对 + +244 +00:11:01,110 --> 00:11:03,711 +even if like your bounds don't actually change. +甚至是,你的边界并没有真正改变的情况下 + +245 +00:11:05,114 --> 00:11:07,447 +This whole process of laying out your subviews, +整个布局你子视图的过程 + +246 +00:11:07,449 --> 00:11:10,717 +the idea is to make sure that your subviews +唯一的想法就是,确保你的子视图是 + +247 +00:11:10,719 --> 00:11:13,185 +are properly laid out. +正确被布局的 + +248 +00:11:13,187 --> 00:11:16,655 +Now again, most of that's happening with auto layout, +在一次重申,大多数布局都可以通过 Auto Layout 来做到 + +249 +00:11:16,657 --> 00:11:19,958 +and the auto layout happens between these two methods, so +Auto Layout 在这两个方法之间起作用 + +250 +00:11:19,960 --> 00:11:23,361 +you get view a layout subviews, you do whatever you +首先是 viewWillLayoutSubviews,接着做任何你想做的 + +251 +00:11:23,363 --> 00:11:26,264 +wanna do, then auto layout happens, then you get +然后,Auto Layout 起作用 + +252 +00:11:26,266 --> 00:11:29,200 +viewDidLayoutSubviews, 'kay, so your subviews might have +接下来,viewDidLayoutSubviews,好的 + +253 +00:11:29,202 --> 00:11:33,136 +moved around between the two calls of these, make sense? +你的子视图可能在这两个方法调用之中被移动了,明白了吗? + +254 +00:11:33,138 --> 00:11:34,170 +Any questions about that? +有什么问题吗? + +255 +00:11:34,172 --> 00:11:39,008 +So, yeah, these things might be called quite a lot and +好的,这些方法可能会经常被调用到 + +256 +00:11:39,010 --> 00:11:41,510 +we'll see that in the demo that they might get called, +我们可以在 Demo 中看到,这些方法可能被调用 + +257 +00:11:41,512 --> 00:11:43,462 +and called, and called. +调用、调用 + +258 +00:11:43,463 --> 00:11:45,413 +Autorotation, really you wanna think of +Autorotation,真正要考虑的是 + +259 +00:11:45,416 --> 00:11:49,718 +autorotation primarily as just your bounds changed, so +你的边界的改变 + +260 +00:11:49,720 --> 00:11:52,720 +autorotation is really a non-event. +所以 Autorotation 其实不是一个事件 + +261 +00:11:52,722 --> 00:11:55,856 +As we have seen in all of our apps we have been writing so +目前为止,我们在我们的 App 中编写的代码 + +262 +00:11:55,858 --> 00:11:58,092 +far, we don't even think about autorotation, +我们根本没有考虑过 Autorotation + +263 +00:11:58,094 --> 00:12:00,961 +it just happens our bounds change, auto layout works and +它自动发生,我们的边界改变,Auto Layout 工作 + +264 +00:12:00,963 --> 00:12:03,380 +the world is good. +一切都很正常 + +265 +00:12:03,381 --> 00:12:05,798 +And that's the way you should think of it 99% of the time, +那就是你99%的情况下会考虑的 + +266 +00:12:05,800 --> 00:12:07,833 +but if for some reason, +但是在某些原因之下 + +267 +00:12:07,835 --> 00:12:11,203 +you care about the actual case where rotation is happening, +你需要关心一下,怎么样的旋转正在发生? + +268 +00:12:11,205 --> 00:12:13,905 +in other words, your device got turned and +换言之,你的设备旋转了 + +269 +00:12:13,907 --> 00:12:16,775 +so the bounds got to be wider than tall and when they used +边界是变宽了还是变窄了 + +270 +00:12:16,777 --> 00:12:20,345 +to be taller than wide, then you can participate. +然后你可以参与这个过程,做一些事情 + +271 +00:12:20,347 --> 00:12:23,848 +By the way, first line there says you can go to +顺便一提,这里的第一行说了,你可以 + +272 +00:12:23,850 --> 00:12:25,449 +your project settings and +到你的项目设置(Project Settings)中 + +273 +00:12:25,451 --> 00:12:27,918 +prevent certain autorotation from happening, +取消特定的 Autorotation + +274 +00:12:27,920 --> 00:12:30,787 +and the default by the way is that portrait upside down +默认取消的是,颠倒的竖屏模式 + +275 +00:12:30,789 --> 00:12:31,854 +is prevented. + +276 +00:12:31,856 --> 00:12:33,856 +That's why you noticed your app, +这就是你在我们的 App 中看到的 + +277 +00:12:33,858 --> 00:12:36,425 +you go in the simulator and you rotate it to landscape and +当你在模拟器中,你旋转到了横屏模式 + +278 +00:12:36,427 --> 00:12:38,493 +then you rotate it again to upside down and +然后你再进行一次旋转,到了颠倒的竖屏模式 + +279 +00:12:38,495 --> 00:12:40,128 +it doesn't autorotate, +我们的 App 并没有自动旋转 + +280 +00:12:40,130 --> 00:12:42,063 +that's because in your private setting you said, oh, +这是因为在你的项目设置中,你说 + +281 +00:12:42,065 --> 00:12:45,199 +portrait upside down is not a supported orientation. +“不支持颠倒的竖屏模式” + +282 +00:12:45,201 --> 00:12:46,767 +So when you go to portrait upside down, +所以,当你的 App 处于颠倒的竖屏模式中 + +283 +00:12:46,769 --> 00:12:49,603 +it just does not autorotate, and you can flip those four +Autorotation 将不起作用,当然你可以 + +284 +00:12:49,605 --> 00:12:52,572 +switches for the landscapes and portraits any way you +随意开关竖屏模式和横屏模式的四种模式 + +285 +00:12:52,574 --> 00:12:56,376 +want, okay, it depends on your UI and what makes sense. +这一切都取决于你的用户界面 + +286 +00:12:56,378 --> 00:12:59,145 +Some UIs make no sense in landscape, some only make +一些用户界面不需要横屏模式 + +287 +00:12:59,147 --> 00:13:00,713 +sense in landscape, there might be a game or +一些用户界面只需要横屏模式,比如说游戏 + +288 +00:13:00,715 --> 00:13:04,449 +something that just doesn't make sense in portrait, 'kay? +或者其他不适用于竖屏模式的应用,明白了吗? + +289 +00:13:04,451 --> 00:13:06,384 +So, but if you want to participate in the +所以,如果你想在 Autorotation 中插一手的话 + +290 +00:13:06,386 --> 00:13:09,821 +autorotation, 'kay, like you want to do some animation of +比如你想要定制你自己的动画效果 + +291 +00:13:09,823 --> 00:13:12,656 +your own, because you notice that the rotation is animated, +你注意到了旋转中的动画效果了吗? + +292 +00:13:12,658 --> 00:13:16,026 +right it goes from portrait to landscape, it kinda moves the +对,比如从竖屏模式切换到横屏模式 + +293 +00:13:16,028 --> 00:13:18,495 +views around, it's hard to see cause it's happening so fast, +它移动了视图,但这个效果很难看清,因为速度实在是太快了 + +294 +00:13:18,497 --> 00:13:21,197 +but it is animating it, and you can actually participate +但是,肯定是有动画的,你可以参与其中 + +295 +00:13:21,199 --> 00:13:24,934 +that by this method viewWillTransitionToSize, +通过 viewWillTransitionToSize 这个方法 + +296 +00:13:24,936 --> 00:13:28,904 +which is part of the life cycle. +同样也是 View Controller 生命周期的一部分 + +297 +00:13:28,906 --> 00:13:30,772 +And this transition coordinator you get, +而且你得到的变换坐标系 + +298 +00:13:30,774 --> 00:13:32,340 +now I'm not gonna talk about how to implement this, +现在我不打算说,如何去实现它 + +299 +00:13:32,342 --> 00:13:33,708 +I haven't even talked about animation, +因为我目前还没有谈到动画这部分 + +300 +00:13:33,710 --> 00:13:35,343 +we're not gonna talk about that for a couple of weeks, +所以在最近的几周里,我们都不会讲到它 + +301 +00:13:36,278 --> 00:13:39,479 +but there is a method in that coordinator, for example, +但是在那个 coordinator中有一个方法,比如说 + +302 +00:13:39,481 --> 00:13:43,649 +called animate alongside, and you can specify what kinda +叫做 animate alongside,并且你可以指定什么样的 + +303 +00:13:43,651 --> 00:13:46,452 +animations you want to animate alongside the rotation. +动画你想要 animate alongside回转 + +304 +00:13:46,454 --> 00:13:48,253 +So I'm just telling you this now because it's part of +所以,我现在只是在告诉你这个因为它是 + +305 +00:13:48,255 --> 00:13:50,422 +the view controller life cycle and +视频控制器生活循环系统的一部分 + +306 +00:13:50,424 --> 00:13:53,291 +you should just know in your head that it exists. +你应该在脑海中意识到它的存在 + +307 +00:13:53,293 --> 00:13:55,460 +Okay, it's a little bit of a complicated thing to use, +好吧,它应用起来是有点复杂的东西, + +308 +00:13:55,462 --> 00:13:59,563 +because when you rotate and you change bounds, really it's +因为当你循环并且改变限度的时候,的确是 + +309 +00:13:59,565 --> 00:14:02,433 +container views that are most concerned with that, like +视图容器是与他联系最紧密的 + +310 +00:14:02,435 --> 00:14:05,502 +a split view, it needs to now put both things on screen and +就像是split view,目前它需要将两个东西一起放在屏幕上并且 + +311 +00:14:05,504 --> 00:14:08,838 +put a line and when you switch the other way. +在你以另一种方式打开的时候放入一行 + +312 +00:14:08,840 --> 00:14:12,175 +It's really about container views, a little less than +它是真正关于container view,很少一部分是关于leaf view, + +313 +00:14:12,177 --> 00:14:15,277 +about leaf view controllers, but leaf view controller might +但是 leaf view controller 也许需要了解正在发生什么,好了, + +314 +00:14:15,279 --> 00:14:18,180 +wanna know what's going on, all right, and +然后 + +315 +00:14:18,182 --> 00:14:21,049 +then low memory, you get this didReceiveMemoryWarning. +低内存,你可以用receivememorywarning + +316 +00:14:21,051 --> 00:14:22,684 +Here you wanna throw away anything in +这里,你想要将任何东西扔进 + +317 +00:14:22,686 --> 00:14:25,186 +the heap that's easy to reconstitute. +控制堆中,那很容易重建 + +318 +00:14:26,322 --> 00:14:28,689 +The way you throw things out of the heap, by the way, +你将东西扔进控制堆的方式,顺便讲一句 + +319 +00:14:28,691 --> 00:14:34,094 +is you just set all pointers that you have to them to nil, +你刚刚设定的所有的指示器,你都不得不将它们归零 + +320 +00:14:34,096 --> 00:14:36,329 +okay, if you're not pointing to something, +好了,如果你没有特指某些事, + +321 +00:14:36,331 --> 00:14:38,664 +then it won't stay in the heap, it gets thrown out. +它们将不用存放在控制堆中,它们会被扔掉 + +322 +00:14:38,666 --> 00:14:40,299 +That does not include weak pointers. +那些不包括低水平的指示器 + +323 +00:14:40,301 --> 00:14:41,667 +If you have a weak pointer to something, +如果你有一个低水平的指示器, + +324 +00:14:41,669 --> 00:14:43,435 +it still gets thrown out, 'kay? +它们还是要被扔掉,明白吗 + +325 +00:14:43,437 --> 00:14:46,337 +If the only pointer in the world to an image in the heap +如果世界上只存在一个图像控制器, + +326 +00:14:46,339 --> 00:14:48,205 +is a weak pointer, it's gonna get pitched, and +这个控制器又是低水平的,他将会被调试 + +327 +00:14:48,207 --> 00:14:50,040 +that weak pointer's gonna get set to nil, +然后那个低水平的指示器将会被设定归零 + +328 +00:14:50,042 --> 00:14:52,976 +'kay, as we talked about when we talked about delegation, +就像我们讨论过的代理模型 + +329 +00:14:52,978 --> 00:14:57,580 +'kay, that's the definition of a weak pointer, okay? +那是低水平指示器的定义 + +330 +00:14:57,582 --> 00:15:00,449 +So, in low memory situations, you know, try to clean up. +所以,在低内存的情形下,你知道的,试着去清理掉它 + +331 +00:15:00,451 --> 00:15:01,550 +You'll all most never get this, +你将几乎永远不可能明白这个, + +332 +00:15:01,552 --> 00:15:02,617 +you may never, ever get this. +你可能永远不会明白 + +333 +00:15:02,619 --> 00:15:05,153 +If your app is very highly image intensive, +如果你的app是高清晰度的视频加强器 + +334 +00:15:05,155 --> 00:15:06,621 +maybe it's an image processing app and +可能它是个视频加工app并且 + +335 +00:15:06,623 --> 00:15:09,757 +you've got a lot of images in there, then it's possible, +你已经得到好多设想在里面,然后它是可能的 + +336 +00:15:09,759 --> 00:15:12,192 +I suppose, but it's extremely unlikely, +我推想,但是它是极度没有可能的, + +337 +00:15:12,194 --> 00:15:14,361 +'kay, there's a lot of memory in these devices. +好的,这里有很大的内存在这些装置里 + +338 +00:15:15,964 --> 00:15:19,032 +Okay, now I'm gonna go back to awakeFromNib, which is not +好的,现在我将要回到awakefromnib, + +339 +00:15:19,034 --> 00:15:21,133 +really part of the view controller life cycle, +他不是真正属于view controller life cycle, + +340 +00:15:21,135 --> 00:15:23,018 +but a view controller, +但是属于view controller + +341 +00:15:23,019 --> 00:15:24,902 +just like any other NS object subclass that comes out of +就像是来自storyboard的其他那些NS object 子集 + +342 +00:15:24,905 --> 00:15:27,873 +a storyboard, will get awakeFromNib. +将会得到awkeFromNib + +343 +00:15:27,875 --> 00:15:30,775 +And there are some students, as a class in the past, +并且在那里有一些学生,就像过去的班级一样 + +344 +00:15:30,777 --> 00:15:32,877 +that have kind of abused awakeFromNib and they just +有一种 awakeFromNib的滥用并且他们 + +345 +00:15:32,879 --> 00:15:35,579 +start trying to put everything in their initialization into +开始尝试把所用的东西放进 awakeFromNib的初始化中 + +346 +00:15:35,581 --> 00:15:38,215 +awakeFromNib instead of putting it into viewDidLoad or +来取代把他们放入 viewDidLoad或者 + +347 +00:15:38,217 --> 00:15:41,585 +viewWillAppear, or viewWillLayoutSubviews, +viewWillAppear中,或者viewWillLayoutSubviews + +348 +00:15:41,587 --> 00:15:44,421 +depending on what kind of thing it is. +取决于事情的是什么样的类型 + +349 +00:15:44,423 --> 00:15:47,423 +And I'm just warning you here, don't abuse awakeFromNib, but +我在这里想要警告你们,不要滥用 awakeFromNib方法 + +350 +00:15:47,425 --> 00:15:50,026 +there are some cases where awakeFromNib is necessary. +但是哪有一些方法是 awakeFromNib需要的 + +351 +00:15:50,028 --> 00:15:52,561 +For example, if you want to set yourself as the delegate +比如说,如果你想把总计设置为 delegate + +352 +00:15:52,563 --> 00:15:55,163 +of the split view controller you're in, awayFromNib is +关于你所在的 split view controller中,awakeFromNib是 + +353 +00:15:55,165 --> 00:15:57,632 +a good place to do that, because then it happens really +一个很好地方去设置它,因为它发生的的确很早 + +354 +00:15:57,634 --> 00:16:00,401 +early and you'll start getting those delegate methods from +并且你可以开始得到这些 delegate 方法从 + +355 +00:16:00,403 --> 00:16:02,937 +split view as you go through the rest of your life cycle. +split view当你经过剩下的生命周期的时候 + +356 +00:16:02,939 --> 00:16:05,139 +Okay? +明白? + +357 +00:16:05,140 --> 00:16:07,340 +So there are some times when awakeFromNib is good. +所以 awakeFromNib有时候还是很好用的 + +358 +00:16:07,343 --> 00:16:10,010 +All right, so here's the summary of the life cycle. +好的,在这里做一下关于生命周期的总结 + +359 +00:16:10,012 --> 00:16:11,911 +You get instantiated, usually from the storyboard. +你通常从 storyboard中得到实例化 + +360 +00:16:11,913 --> 00:16:14,180 +You're gonna get awakeFromNib. +你将会得到 awakeFromNib + +361 +00:16:14,182 --> 00:16:16,015 +Segue prep is gonna happen. +Segue 准备发生 + +362 +00:16:16,017 --> 00:16:18,317 +Your outlets are gonna get set by the system. +你的 outlets将会被系统设置 + +363 +00:16:18,319 --> 00:16:20,252 +ViewDidLoad is gonna get called. +viewDidLoad方法将会被调用 + +364 +00:16:20,254 --> 00:16:21,720 +View will appear and disappear. +View将会出现并且消失 + +365 +00:16:21,722 --> 00:16:24,589 +It's gonna happen as your controller goes on and +这会随着你的 controller发生 + +366 +00:16:24,591 --> 00:16:26,708 +off screen. +和关闭屏幕 + +367 +00:16:26,709 --> 00:16:28,826 +And as your view controller's geometry changes or +并且随着你的视图控制器的几何变化 + +368 +00:16:28,828 --> 00:16:31,462 +the subviews change in a way that needs to be re-laid out, +或者 subviews的需要重新加载的方式 + +369 +00:16:31,464 --> 00:16:33,063 +you're gonna get WillLayoutSubviews, +你将会得到 WillLayoutSubviews + +370 +00:16:33,065 --> 00:16:34,931 +then autolayout, then DidLayoutSubviews. +接下来是 autolayout,然后是 DidLayoutSubviews + +371 +00:16:34,933 --> 00:16:37,233 +So that could happen many times. +所以这些可以发生很多次 + +372 +00:16:37,235 --> 00:16:38,401 +And if you get low on memory, +并且如果你的可用内存很小的话 + +373 +00:16:38,403 --> 00:16:40,302 +you could have this memory warning, okay? +你可能会得到内存警报,明白? + +374 +00:16:40,304 --> 00:16:42,537 +So that's the View Controller Lifecycle. +所以这就是 视图控制器的生命周期 + +375 +00:16:42,539 --> 00:16:44,906 +There is actually one other one in here. +这里的确是还有另外的一个 + +376 +00:16:44,908 --> 00:16:48,810 +It'll tell you when your size class changes. +它将会告诉你什么时候你的 size class 发生变化 + +377 +00:16:48,812 --> 00:16:50,845 +But I haven't talked about size class yet, so +但是我目前为止从未探讨过 size + +378 +00:16:50,847 --> 00:16:52,112 +I didn't put that in this list. +所以我没有把它放到这个单子里 + +379 +00:16:52,114 --> 00:16:53,413 +But there's one more, and +但是那里还有一个或者更多 + +380 +00:16:53,415 --> 00:16:57,017 +there will transition to traits or something like that. +那里将会以类似的方式进行转变 + +381 +00:16:57,019 --> 00:17:01,153 +All right, so I'm gonna do a quick demo here, super fast. +好的,所以我准备在这里完成一个快速的demo,非常快速 + +382 +00:17:02,957 --> 00:17:06,991 +Let me get something to drink here, okay? +让我先喝点东西 + +383 +00:17:06,993 --> 00:17:08,826 +So I'm gonna do a quick demo. +所以我准备开始一个快速的 + +384 +00:17:08,828 --> 00:17:11,595 +And all I did is I took Psychologist from last time, +并且所有我做的是从我上次的心理学家那里 + +385 +00:17:11,597 --> 00:17:13,497 +and I just put a bunch of printlns in all +并且我只是把一串 printlns在所有的 + +386 +00:17:13,499 --> 00:17:15,832 +these View Controler Lifecycle methods, okay? +这些 视图控制器生命周期方法中,明白? + +387 +00:17:15,834 --> 00:17:19,069 +So that it would just print out where it is in +所以它将会打印出来在 + +388 +00:17:19,071 --> 00:17:20,937 +Lifecycle all the time. +整个生命周期的过程中 + +389 +00:17:20,939 --> 00:17:22,204 +So, let's go do that. +好的,让我们开始吧 + +390 +00:17:22,206 --> 00:17:22,971 +Let's go run that. +让我们来运行它 + +391 +00:17:24,575 --> 00:17:28,976 +It is here in Developer, Psychologist Lecture 8. +在开发者的这里,Psychologist Lecture 8 + +392 +00:17:28,978 --> 00:17:30,378 +Here we go. +开始吧 + +393 +00:17:30,380 --> 00:17:32,713 +So you can see that in viewWillAppear() I +所以你可以看到噪 viewWillAppear() 方法中 + +394 +00:17:32,715 --> 00:17:35,749 +put a little log for that, disappear, all these. +我为他放置了一些log,disappear,所有的这些 + +395 +00:17:35,751 --> 00:17:38,185 +So I'm just making it basically +所以我只是使他基本的 + +396 +00:17:38,186 --> 00:17:40,620 +logging all the things that are happening, okay. +打印出所有发生的事情,明白? + +397 +00:17:40,622 --> 00:17:42,689 +So lets go, I'm gonna run this on iPad. +让我们继续,我准备在iPad上运行它 + +398 +00:17:44,058 --> 00:17:46,158 +It's a little easier to make things happen here. +在这里做的事是比较容易做到的 + +399 +00:17:48,695 --> 00:17:50,561 +All right, so here's our Psychologist. +好的,这里就是我们的 Psychologist + +400 +00:17:50,563 --> 00:17:52,096 +I haven't changed anything about the app. +我没改变app中的任何东西 + +401 +00:17:52,098 --> 00:17:55,232 +I'm gonna make the console really big so +我准备把 console窗口调大 + +402 +00:17:55,234 --> 00:17:58,135 +that we can see what's going on here. +这样的话我们就可以看到在这里将会发生的事情了 + +403 +00:17:58,137 --> 00:17:59,969 +All right, so notice we came up. +好的,清注意我们来了 + +404 +00:17:59,971 --> 00:18:01,337 +The detail is the only thing, +细节是唯一的东西 + +405 +00:18:01,339 --> 00:18:03,105 +the detail is Happiness View Controller. +细节是 Happiness View Controller. + +406 +00:18:03,107 --> 00:18:04,606 +It's the only thing visible. +这是唯一可见的东西 + +407 +00:18:04,608 --> 00:18:06,341 +So what happened here? +所以这里发生了什么? + +408 +00:18:06,342 --> 00:18:08,075 +The Psychologist got pulled out of the storyboard. +Psychologist 被从 storyboard中拉出来了 + +409 +00:18:08,078 --> 00:18:10,311 +The Happiness got pulled out of the storyboard. +Happiness 被从storyboard中拉出来了 + +410 +00:18:10,313 --> 00:18:12,380 +This zero is which instance of it. +这个实例的值为0 + +411 +00:18:12,382 --> 00:18:15,116 +Cuz we're gonna have multiple instances, eventually. +所以我们准备拥有多个实例 + +412 +00:18:15,118 --> 00:18:16,517 +Then Happiness got awakeFromNib. +这样 Happiness 得到 awakeFromNib + +413 +00:18:16,519 --> 00:18:18,085 +Then Psychologist got awakeFromNib. +Psychologist 也得到 awakeFromNib + +414 +00:18:18,087 --> 00:18:21,154 +The order of awakeFromNib is completely not determinable, +awakeFromNib中的顺序是完全无法确定的 + +415 +00:18:21,156 --> 00:18:22,321 +so you should not depend on it. +所以你不应该依赖于它 + +416 +00:18:23,324 --> 00:18:25,524 +Then the master got viewDidLoad. +记下来 master得到了 viewDidLoad + +417 +00:18:25,526 --> 00:18:27,459 +Even though the master never appears on screen, +即使 master从来没在屏幕上出现过 + +418 +00:18:27,461 --> 00:18:29,461 +it still had its outlet set, and +它仍然有它的 outlet设置 + +419 +00:18:29,463 --> 00:18:31,362 +got viewDidLoad sent to it. +由 viewDidLoad发送给它 + +420 +00:18:31,364 --> 00:18:35,499 +Then interestingly, the master was asked to lay itself out, +接下来很有趣的,master被要求把它自己撤下 + +421 +00:18:35,501 --> 00:18:37,167 +to lay its Subviews out. +把它的 Subviews 撤下 + +422 +00:18:37,169 --> 00:18:38,601 +Okay again, it hasn't appeared. +再试一次,它没有出现 + +423 +00:18:38,603 --> 00:18:40,203 +It hasn't even gotten viewWillAppear, +它甚至都没有得到 + +424 +00:18:40,205 --> 00:18:41,537 +because it's not gonna appear. +因为它没准备出现 + +425 +00:18:43,674 --> 00:18:46,942 +But its Subviews wanna get laid out. +但是它的子视图想要展现出来 + +426 +00:18:46,944 --> 00:18:47,942 +And why is this happen? +为什么会这样呢? + +427 +00:18:47,944 --> 00:18:49,377 +Well, you know, the system might be +好的,你知道的,系统也许 + +428 +00:18:49,379 --> 00:18:52,513 +preparing to animate it onscreen or something. +准备把它绘制在屏幕或者一些东西上 + +429 +00:18:52,515 --> 00:18:53,313 +You just want to make sure. +你只需要确保 + +430 +00:18:53,315 --> 00:18:54,815 +This is not doing any drawing. +这个没有做任何的绘制 + +431 +00:18:54,817 --> 00:18:56,400 +This is just making sure +这个只是确保 + +432 +00:18:56,401 --> 00:18:57,984 +the Subviews are properly laid out. +子视图是被合理的布局出来 + +433 +00:18:57,986 --> 00:19:02,321 +It happens twice here, maybe a before and after animation. +它在这里发生了两次,也许是一个之前和之后的动画 + +434 +00:19:02,323 --> 00:19:03,489 +Who knows what's going on here, +谁知道这里到底发生了什么? + +435 +00:19:03,491 --> 00:19:05,023 +it doesn't really matter. +它根本没有起作用 + +436 +00:19:05,025 --> 00:19:07,859 +The size didn't actually change. +实际上尺寸并没有改变 + +437 +00:19:07,861 --> 00:19:09,260 +Okay, the bound size didn't actually change, so +好的,边界尺寸实际上没有发生变化 + +438 +00:19:09,262 --> 00:19:11,595 +this second one probably did almost nothing here. +所以这两个在这里也许什么都没有做 + +439 +00:19:12,898 --> 00:19:15,832 +Then the detail, Happiness, it gets a videwDidLoad and then +然后 detail,Happiness,它得到了 viewDidLoad并且 + +440 +00:19:15,834 --> 00:19:18,501 +it gets a viewWillAppear, cuz it's gonna appear onscreen. +它也得到了一个 viewWillAppear,所以它将要在屏幕上出现 + +441 +00:19:18,503 --> 00:19:21,204 +The animated is false because it doesn't animate on screen. +动画是关的因为它根本没有以动画的方式展现在屏幕上 + +442 +00:19:21,206 --> 00:19:23,172 +It was the initial thing that shows up in screen, so +它是最初显示在屏幕上的东西 + +443 +00:19:23,174 --> 00:19:24,473 +boom, it just pops up there. +所以从底部,它从这里 pop up出来 + +444 +00:19:25,442 --> 00:19:28,343 +It gets laid out and then it gets viewDidAppear. +它被展示出来并且得到 viewDidAppear方法 + +445 +00:19:28,345 --> 00:19:30,445 +And here it is, okay? +他就在这里,看到了? + +446 +00:19:30,447 --> 00:19:31,779 +Everyone understand that? +每个人都理解了么? + +447 +00:19:31,781 --> 00:19:34,381 +Now I'm going to rotate to landscape, and +现在我准备把屏幕旋转为横向 + +448 +00:19:34,383 --> 00:19:36,049 +that's gonna cause the master to appear. +这将会导致master展示出来 + +449 +00:19:36,051 --> 00:19:37,450 +So watch this. +所以看这里 + +450 +00:19:37,452 --> 00:19:39,803 +So we do rotate, +我们将它转了过来 + +451 +00:19:39,804 --> 00:19:42,155 +all these dash, that's what happened since I rotated here. +所有的这些,发生在我将它旋转的时候 + +452 +00:19:42,157 --> 00:19:45,224 +And you can see Psychologist and Happiness both got +并且你可以看到 Psychologist 和Happiness都得到了 + +453 +00:19:45,226 --> 00:19:48,460 +informed that this transition to size is going to happen. +即将发生旋转尺寸的告知 + +454 +00:19:48,462 --> 00:19:50,045 +So they could have +所以他们可以 + +455 +00:19:50,046 --> 00:19:51,629 +participated in the animation if they want, and you're gonna +以动画的方式进行参与,并且你将会 + +456 +00:19:51,632 --> 00:19:54,199 +see the animation happen in a little bit down the road here. +看到动画发生在路的这里 + +457 +00:19:55,201 --> 00:19:58,069 +The master got another chance to lay its Subviews out in +master得到了另外一次机会去将子视图展示出来 + +458 +00:19:58,071 --> 00:19:59,269 +a little different size. +以一些不同的尺寸 + +459 +00:19:59,271 --> 00:20:02,706 +Because this size, it's only 768 high instead of +因为这个尺寸,它的高度仅仅是768 代替了 + +460 +00:20:02,708 --> 00:20:06,242 +the full 1024, and it's a little wider too. +整个的1024,并且它有一点宽 + +461 +00:20:06,244 --> 00:20:09,078 +So it got laid out, then it got viewWillAppear. +所以它被展示出来,并且得到了 viewWillAppear + +462 +00:20:09,080 --> 00:20:12,715 +So this guy was told it would appear, okay? +所以它被告知可以显示出来了,明白? + +463 +00:20:12,717 --> 00:20:15,517 +And this guy didn't get any viewWillAppear because it's +同时它没有得到任何的 viewWillAppear因为它 + +464 +00:20:15,519 --> 00:20:17,369 +already there. +已经在这里了 + +465 +00:20:17,370 --> 00:20:19,220 +So it's not appearing, it was already there before. +所以它没有显示的过程,因为它在这之前已经在这里了 + +466 +00:20:19,223 --> 00:20:22,291 +So it gets viewWillAppear. +所以它调用了 viewWillAppear + +467 +00:20:22,292 --> 00:20:25,360 +Now the detail gets chance to lay its Subviews out here at +现在 details 得到了机会将它的子视图在这里展示出来 + +468 +00:20:25,362 --> 00:20:27,262 +a new size. +以一个新的尺寸 + +469 +00:20:27,263 --> 00:20:29,163 +Because it used to be the whole screen, +因为它曾经铺满了整个屏幕 + +470 +00:20:29,164 --> 00:20:31,064 +now it's just this part right here, so it got a new layout. +现在它在这里仅仅是一个部分,所以它调用了一个新的 + +471 +00:20:31,067 --> 00:20:33,567 +And then the master was asked to layout its Subviews again. +同时 master被再次请求展示它的 子视图 + +472 +00:20:33,569 --> 00:20:35,635 +So you see how I'm saying this gets called a lot. +所以你可以看到我说的它被调用了很多次 + +473 +00:20:35,637 --> 00:20:37,504 +So you just need to +所以你只需要 + +474 +00:20:37,505 --> 00:20:39,372 +make sure that if you're doing anything in these two methods, +确保你想在这两个方法中想做的事 + +475 +00:20:39,374 --> 00:20:41,674 +that it's okay to be doing it over and over. +它可以被被一遍一遍的做 + +476 +00:20:41,676 --> 00:20:44,343 +Here's where the actually animation happens. +这里是实际动画发生的地方 + +477 +00:20:44,345 --> 00:20:46,945 +And you can see that both the Psychologist and the Happiness +并且你可以看到 Psychologist 和 Happiness + +478 +00:20:46,947 --> 00:20:49,548 +have been invited to animate alongside if they wanted to. +都被要求去展示它们的动画 + +479 +00:20:50,484 --> 00:20:53,718 +Then the master is asked to layout one more time, +然后 master再次被要求展示出来它的布局 + +480 +00:20:53,720 --> 00:20:55,653 +same size. +相同的尺寸 + +481 +00:20:55,654 --> 00:20:57,587 +That's the third time its been asked to do that. +这是它第三次被要求那样做 + +482 +00:20:57,590 --> 00:21:02,092 +And then the master gets viewDataAppear, okay? +然后 master调用了 viewDataAppear,明白? + +483 +00:21:02,094 --> 00:21:04,728 +Now the last thing I'm gonna do is click one of these, +现在我准备做的最后一件事是点击其中的一个 + +484 +00:21:04,730 --> 00:21:07,330 +which is gonna cause a segue which is gonna cause this to +点击的那个将会引发一个 segue并且导致这个 + +485 +00:21:07,332 --> 00:21:08,564 +be replaced. +被替换 + +486 +00:21:08,566 --> 00:21:10,232 +So let's do that. +让我们开始吧 + +487 +00:21:10,233 --> 00:21:11,899 +So we'll try the dancing tree here. +所以我准备把 dancing tree放到这里 + +488 +00:21:11,902 --> 00:21:12,601 +Okay? +明白? + +489 +00:21:12,603 --> 00:21:13,802 +So what happened here? +所以这里发生了什么? + +490 +00:21:13,804 --> 00:21:14,802 +A new Happiness. +一个新的 H + +491 +00:21:14,804 --> 00:21:18,839 +Happiness 1 got instantiated here, okay? +Happiness 1 在这里被实例化了,明白? + +492 +00:21:18,841 --> 00:21:21,508 +We have Happiness 0 up here and Happiness 1. +我们在这里有了 Happiness 0 并且 Happiness 1 + +493 +00:21:21,510 --> 00:21:25,645 +It got prepared with Happiness of a hundred. +它已经被 Happiness准备好了 + +494 +00:21:25,647 --> 00:21:27,180 +Okay? +明白? + +495 +00:21:27,181 --> 00:21:28,714 +Then layout Subviews of the master again. +接下来 master又重新布局了它的子视图 + +496 +00:21:28,716 --> 00:21:33,952 +Then the Happiness 0 got viewWillDisappear. +然后 Happiness 0 调用了viewWillDisappear + +497 +00:21:33,954 --> 00:21:35,387 +Happiness 0, that old Happiness of +Happiness 0,那个原先的 H + +498 +00:21:35,389 --> 00:21:37,105 +course getting pulled out and +课程中的被拽出来了并且 + +499 +00:21:37,106 --> 00:21:38,822 +replaced by the new one, so it got viewWillDisappear. +被一个新的替换掉了,所以它调用了 viewWillDisappear + +500 +00:21:38,825 --> 00:21:41,525 +Then the master got laid out again, and +随后 master再一次展示出 + +501 +00:21:41,527 --> 00:21:44,395 +then viewDidLoad happened on Happiness 1, +然后 Happiness 1调用了 ViewDidLoad方法 + +502 +00:21:44,397 --> 00:21:46,596 +the new happiness that's appearing. +新的 happiness 出现了 + +503 +00:21:46,598 --> 00:21:49,799 +Then it got viewWillAppear cuz it's going to appear. +然后它调用了 viewWillAppear方法所以它出现了 + +504 +00:21:49,801 --> 00:21:51,768 +Then it got a chance to be laid out. +随后它得到了机会被展示出来 + +505 +00:21:51,770 --> 00:21:54,236 +The old Happiness disappeared. +原先的 Happiness 消失了 + +506 +00:21:54,238 --> 00:21:56,972 +The new Happiness appeared and then the old +新的 Happiness出现了并且原先的 + +507 +00:21:56,974 --> 00:21:59,274 +Happiness got deinitialized, thrown out of the heap. +Happiness 被销毁了并且从内存堆中扔掉 + +508 +00:21:59,276 --> 00:22:01,476 +Because like I said, once you segue away from it, +因为就像我说的一样,一旦你从它 segue来开 + +509 +00:22:03,580 --> 00:22:04,312 +boom, it's gone. +boom,它消失了 + +510 +00:22:04,313 --> 00:22:05,045 +Okay? So that's all I +明白?所以那是所有我 + +511 +00:22:05,048 --> 00:22:06,413 +wanted to cover there. +想要掩盖这里 + +512 +00:22:06,415 --> 00:22:08,348 +Everybody cool with that? +大家是不是觉得它相当酷? + +513 +00:22:08,349 --> 00:22:10,282 +Any questions about that View Controller Lifecycle? +有任何关于视图控制器生命周期的问题么? + +514 +00:22:12,387 --> 00:22:14,086 +It's pretty straightforward, but you can already probably +它是非常明确的,但是你也许已经可以 + +515 +00:22:14,088 --> 00:22:15,821 +imagine in your head some things that you were +在你的头脑里想象那些 + +516 +00:22:15,823 --> 00:22:18,790 +doing in your code that's like oh, I wish I had viewDidLoad. +你在你的代码里那么做的样子,哦,我希望我做了 viewDidLoad + +517 +00:22:18,792 --> 00:22:20,158 +That really could have +那真的可以 + +518 +00:22:20,160 --> 00:22:21,893 +initialized some stuff there a little simpler. +使这里的一些学生变得简单 + +519 +00:22:21,895 --> 00:22:24,562 +All right, so let's go back to our slides. +好的,让我们回到我们的 + +520 +00:22:25,865 --> 00:22:29,232 +All right, so you've seen a lot of Autolayout already in +好的,现在你可以看到很多 AutoLayout已经在 + +521 +00:22:29,234 --> 00:22:31,017 +this class, so +这个类中,所以 + +522 +00:22:31,018 --> 00:22:32,801 +I'm gonna review briefly the things you should know. +我准备短暂的去复习一下你应该知道的知识 + +523 +00:22:32,804 --> 00:22:35,204 +One is you know about using the dashed lines. +你知道的一个是关于使用虚线 + +524 +00:22:36,374 --> 00:22:40,175 +Using the blue dashed lines is helping the interface builder. +使用蓝色的虚线用来帮助 interface + +525 +00:22:40,177 --> 00:22:41,810 +By the way, when I refer to interface builder, +顺便说一下,当我涉及到 interface builder的时候 + +526 +00:22:41,812 --> 00:22:44,579 +that means Xcode, the storyboard part of Xcode. +那是指 Xcode,storyboard是Xcode 的一部分 + +527 +00:22:44,581 --> 00:22:46,781 +We call that interface builder for historical reasons. +我们叫它 interface builder是由于一些历史原因 + +528 +00:22:48,184 --> 00:22:50,984 +So, when you're in the storyboard of Xcode, +所以,当你在Xcode的Storyboard中的时候 + +529 +00:22:50,986 --> 00:22:54,388 +the dashed lines are kind of telling Xcode what you want, +虚线是Xcode想要告诉你它要做什么 + +530 +00:22:54,390 --> 00:22:55,889 +what you intend. +你倾向于什么 + +531 +00:22:55,891 --> 00:22:57,824 +As best that you can, okay? +可以达到你最想要的,明白? + +532 +00:22:57,826 --> 00:23:01,227 +Then you know about Ctrl-dragging between views to +然后你知道使用Ctrl键拖拽两个视图来 + +533 +00:23:01,229 --> 00:23:03,095 +create relationships, right? +建立联系,是吧? + +534 +00:23:03,097 --> 00:23:05,864 +Like spacing, and hook this to the left edge, and +就想间距,并且把它吸附在了左边缘 + +535 +00:23:05,866 --> 00:23:06,898 +stuff like that. +就像填塞一样 + +536 +00:23:06,900 --> 00:23:09,467 +You know about those in the lower right corner, +你可以从底部右下角来了解这些 + +537 +00:23:09,469 --> 00:23:12,603 +the "Pin" and "Arranged" popovers down there that let +"Pin" 和 "Arranged" popovers那里可以使 + +538 +00:23:12,605 --> 00:23:15,839 +you do things like set all the things to equal widths, or +你做一些类似于设置所有控件对其宽度的事情 + +539 +00:23:15,841 --> 00:23:17,507 +create spacing between all of them, or +或者为他们建立间距 + +540 +00:23:17,509 --> 00:23:19,776 +line up their left edges, okay? +或者排列他们到左边缘上,明白? + +541 +00:23:19,778 --> 00:23:23,346 +You know about using Reset to Suggested Constraints. +你知道关于使用 Reset 去使用建议的限制 + +542 +00:23:23,348 --> 00:23:24,747 +If you use the blue lines, +如果你使用蓝色的线 + +543 +00:23:24,749 --> 00:23:27,583 +sometimes you'll do Reset to Suggested Constraints, and +有时候你会使用 Reset去使用建议的限制 + +544 +00:23:27,585 --> 00:23:29,584 +it will actually figure out what you want. +并且它会弄清楚你想要的 + +545 +00:23:29,586 --> 00:23:30,819 +I'd say only 50 percent of the time, +我只想说事件还有一半了 + +546 +00:23:30,821 --> 00:23:32,420 +but it's worth a try sometimes. +但是它有事是非常值得尝试的 + +547 +00:23:34,557 --> 00:23:35,722 +The Document Outline, +Document O + +548 +00:23:35,724 --> 00:23:37,724 +you know that on the left in the document outline, +你知道的这些是在 document outline的左侧的 + +549 +00:23:37,726 --> 00:23:39,726 +all your constraints are listed there. +你所有的 constraints 被列在那里 + +550 +00:23:39,728 --> 00:23:41,093 +Okay. And also that's where, +好的,并且那里也是 + +551 +00:23:41,095 --> 00:23:44,029 +if you've got problems, you can click on the little red or +如果你遇到了问题,你可以点击有一点红色的 + +552 +00:23:44,031 --> 00:23:45,797 +yellow button in the upper right-hand corner of +或者黄色的按钮在右上角的角落 + +553 +00:23:45,799 --> 00:23:47,499 +the Document Outline and it'll tell you. +在 Document outline中并且它会告诉你 + +554 +00:23:47,501 --> 00:23:51,836 +It might even suggest some ways to fix things, possibly. +它也许会给你一些建议去修复那些问题 + +555 +00:23:51,838 --> 00:23:53,704 +And certainly will tell you if anything's misplaced. +并且肯定会告诉你如果有什么东西放置错了的话 + +556 +00:23:53,706 --> 00:23:56,807 +And you know from there, you can also fix your misplaced +并且从那里你可以知道,去修复一些你放置错误的 + +557 +00:23:56,809 --> 00:23:59,743 +views by clicking on the little triangles in there. +视图通过点击那里的虚线 + +558 +00:23:59,745 --> 00:24:01,577 +You know about the size inspector. +你知道关于尺寸检查器 + +559 +00:24:01,579 --> 00:24:03,579 +If you inspect a view in your storyboard and +如果你在你的storyboard中检查一个 + +560 +00:24:03,581 --> 00:24:05,080 +you look at the size inspector, +你可以在 size inspector中查看 + +561 +00:24:05,082 --> 00:24:07,282 +you'll see all the constraints listed there. +你可以看到所有的 constraints列在那里 + +562 +00:24:07,284 --> 00:24:10,818 +In there, all the constraints are shown with their details. +在那里,所有的 constraints将其详细信息显示出来 + +563 +00:24:10,820 --> 00:24:13,104 +Okay? +明白? + +564 +00:24:13,105 --> 00:24:15,389 +What the constants are, all that stuff, is listed there. +constraints是什么以及其属性都被列在那里 + +565 +00:24:17,659 --> 00:24:19,859 +And of course you can edit the constraints there. +同样你可以在那里编辑 constraints + +566 +00:24:19,861 --> 00:24:22,929 +You can also, you know that you can click on a constraint. +你同样可以点击一个 constraint + +567 +00:24:22,931 --> 00:24:24,363 +And bring up the attributes inspector. +并且把它带到属性查看器中 + +568 +00:24:24,365 --> 00:24:27,232 +And now you can inspect the constraint directly, okay? +现在你可以直接的查看它的 constraint了,明白? + +569 +00:24:27,234 --> 00:24:29,234 +It will be the thing that's selected so the attributes +它将显示你选中的控件这样属性查看器 + +570 +00:24:29,236 --> 00:24:31,936 +inspector will let you set its attributes, okay? +就可以让你编辑它的属性了,明白? + +571 +00:24:31,938 --> 00:24:34,906 +So you know a lot here about autolayout. +所以你现在知道了很多关于 autolayout的知识了 + +572 +00:24:34,908 --> 00:24:37,041 +And that is basically what autolayout is. +并且那是 autolayout基础的知识 + +573 +00:24:37,043 --> 00:24:38,409 +It's those things. +所有的这些 + +574 +00:24:38,411 --> 00:24:40,877 +Okay, now again, as I've said many times, +好的,再一次,我已经说很多次了 + +575 +00:24:40,879 --> 00:24:43,079 +mastering autolayout requires experience. +管理 autolayout需要经验 + +576 +00:24:43,081 --> 00:24:45,715 +You gotta know how to use all these tools, +你将会知道怎么样使用这些工具 + +577 +00:24:45,717 --> 00:24:47,450 +to greatest effect, okay. +去达到最大的效率 + +578 +00:24:47,452 --> 00:24:49,818 +You gotta familiarize yourself with what things can I +你必须熟悉你自己通过我可以对其控件 + +579 +00:24:49,820 --> 00:24:53,355 +align to things, what things can I pin to here and there, +什么控件我可以将它到处布局 + +580 +00:24:53,357 --> 00:24:56,391 +what things can I set as my constants that make sense. +我可以根据场景来设置我的控件 constraints + +581 +00:24:56,393 --> 00:24:58,192 +You gotta learn all that by doing, okay. +你通过实践来学习所有的这些,明白 + +582 +00:24:58,194 --> 00:25:00,994 +I could spend many days going through every possible one. +我可能话费很多天来熟悉这里的每一件工具 + +583 +00:25:03,532 --> 00:25:05,932 +Autolayout can be done in code. +可以在代码中实现 AutoLayout + +584 +00:25:05,934 --> 00:25:08,568 +There are objects, classes, +那些是对象和类 + +585 +00:25:08,570 --> 00:25:11,737 +in iOS that represent what's going on in autolayout. +在iOS系统中代表着什么可以被autolayout + +586 +00:25:11,739 --> 00:25:14,273 +And in the demo I'm gonna actually show you an example +并且在demo中我会实际向你们展示 + +587 +00:25:14,275 --> 00:25:16,475 +of doing that so you can get an idea of what it looks like. +通过完成一个例子这样你可以什么样的想法 + +588 +00:25:16,477 --> 00:25:17,909 +But we rarely do that. +但是我们很少这样做 + +589 +00:25:17,911 --> 00:25:20,611 +If we can do it in the storyboard, we do it there. +如果我们可以在 storyboard中实现,我们就在那里完成 + +590 +00:25:20,613 --> 00:25:23,114 +We only revert to doing it in code when it's like, +我们只需要将它恢复成代码中的样子 + +591 +00:25:23,116 --> 00:25:26,817 +we just can't express that somehow in the storyboard, +我们只是不知道在 storyboard中它是如何表述的 + +592 +00:25:26,819 --> 00:25:28,418 +which is extremely rare. +这是极其罕见的 + +593 +00:25:28,420 --> 00:25:32,822 +But I'll show you a case where that's true, but all right. +但是我会通过一个例子来向你们展示它真实的样子,但是好吧 + +594 +00:25:32,824 --> 00:25:37,159 +So what about rotation? +关于 + +595 +00:25:37,161 --> 00:25:39,361 +As I said, when you have rotation, +就像我说的,当你准备 + +596 +00:25:39,363 --> 00:25:44,065 +you're just going to rely on your autolayout to do that. +你只是要依靠你的autolayout去完成它 + +597 +00:25:44,067 --> 00:25:48,935 +But occasionally when you rotate, things have changed so +但是当你偶尔的旋转时,事情变得 + +598 +00:25:48,937 --> 00:25:52,339 +drastically in terms of the shape that autolayout just +很大就形状而言,autolayout就 + +599 +00:25:52,341 --> 00:25:53,206 +can't do it. +不能这么做了 + +600 +00:25:53,208 --> 00:25:55,408 +It can't move a view where you want. +它不能像你想要的一样移动视图 + +601 +00:25:55,410 --> 00:25:57,343 +So what's an example of that? +所以有什么这方面的例子呢? + +602 +00:25:57,345 --> 00:25:59,077 +Lets consider our calculator. +让我回忆一下我们的计算器 + +603 +00:25:59,079 --> 00:26:01,813 +Okay lets say we had 20 buttons in our calculator. +好的,我们的计算器有20个按键 + +604 +00:26:01,815 --> 00:26:02,447 +Okay. +好的 + +605 +00:26:02,449 --> 00:26:04,816 +Now in landscape, +现在横屏 + +606 +00:26:04,817 --> 00:26:07,184 +I might want them to be five buttons across and four down. +那么我希望它应该有五列四行 + +607 +00:26:07,186 --> 00:26:08,585 +But when I switch to portrait, +但是当我想转换成竖屏 + +608 +00:26:08,587 --> 00:26:10,454 +now I might want four across and five down. +现在我希望它是四列五行 + +609 +00:26:11,823 --> 00:26:13,373 +Okay, there's no +没有办法 + +610 +00:26:13,374 --> 00:26:14,924 +way you're gonna write autolayout to do that. +使用自动布局去实现这个效果 + +611 +00:26:14,926 --> 00:26:19,128 +Autolayout cannot make such a huge change like doing that. +自动布局不能做如此巨大的变动 + +612 +00:26:19,130 --> 00:26:21,296 +Okay, so how do we deal with that? +所以我们该怎么解决呢? + +613 +00:26:21,298 --> 00:26:23,031 +We still wanna do that, so how do we do it? +我们仍然想要做到这个效果,那我们要怎么做呢? + +614 +00:26:25,902 --> 00:26:28,802 +It's not just in the case of rotation where this is +这也并不是只在旋转情况下 + +615 +00:26:28,804 --> 00:26:30,003 +happening to. +发生 + +616 +00:26:30,005 --> 00:26:32,639 +It also happens, for example, in a split view. +它也同样发生在, 比如说分屏的时候 + +617 +00:26:32,641 --> 00:26:36,576 +When you have the master in the spilt view on the left, +当你左侧屏幕的主干 + +618 +00:26:36,578 --> 00:26:39,612 +it kind of is tall and thin, just like it was on an iPhone. +它高高瘦瘦的, 就像它在 iPhone 一样 + +619 +00:26:39,614 --> 00:26:42,047 +Even though it was on an iPad, it's kind of in a shape, +但是它其实是在 iPad 上,就像在一块形状里面 + +620 +00:26:42,049 --> 00:26:44,850 +a space that's shaped more like an iPhone, right? +一个就像 iPhone 的形状,懂吗? + +621 +00:26:44,852 --> 00:26:47,652 +Lots of vertical space, but not much horizontal space. +有很多垂直空间,但是只有很少的水平空间 + +622 +00:26:47,654 --> 00:26:50,104 +So it's not just rotation where we +也并不是只有在旋转 + +623 +00:26:50,105 --> 00:26:52,555 +care about this size business, the relative size of things. +我们所在意的尺寸,相对大小事物 + +624 +00:26:53,592 --> 00:26:57,694 +So the solution to this is called size classes, and so +因此这解决方式叫作尺寸等级,并且 + +625 +00:26:57,696 --> 00:27:00,697 +your view controller always exists in +的视图控制器一直存在 + +626 +00:27:00,699 --> 00:27:03,399 +a size class environment. +这个尺寸等级的环境里 + +627 +00:27:03,401 --> 00:27:05,100 +For width and height. +对于所有的宽度高度来说 + +628 +00:27:05,102 --> 00:27:08,703 +And currently the size class can either be compact +并且当前的尺寸等级可以是紧凑的 + +629 +00:27:08,705 --> 00:27:09,804 +or regular. +或者是普通的 + +630 +00:27:09,806 --> 00:27:11,839 +Regular just means it's not compact. +普通意味着就不紧凑 + +631 +00:27:11,841 --> 00:27:15,743 +Okay, and so lets try and +好的, 让我们试一下 + +632 +00:27:15,745 --> 00:27:19,613 +understand what when you're in these different situations. +理解当你在这些不同的情景之下的反应 + +633 +00:27:19,615 --> 00:27:24,217 +So for example the iPhone 6+ is an interesting device. +比如 iPhone6+是一个有意思的设备 + +634 +00:27:24,219 --> 00:27:27,920 +In portrait it's width is compact. +在竖屏下它的宽是紧凑的 + +635 +00:27:27,922 --> 00:27:29,321 +It's height is regular. +它的高是普通的 + +636 +00:27:30,390 --> 00:27:32,407 +Okay so that's if you +因此如果你 + +637 +00:27:32,408 --> 00:27:34,425 +had like a full screen view controller on an iPhone 6+. +在 iPhone 6+ 上满屏操作 + +638 +00:27:34,427 --> 00:27:37,795 +When you go to landscape on the 6+ now it's compact in +当你6+横屏时现在高 + +639 +00:27:37,797 --> 00:27:39,530 +height and regular in width. +紧凑, 宽普通 + +640 +00:27:40,966 --> 00:27:42,399 +That make sense? +要怎么做呢? + +641 +00:27:42,401 --> 00:27:44,901 +All right, it makes perfect sense in that one. +当然, 要做一个完美的感受 + +642 +00:27:44,903 --> 00:27:46,669 +But the iPhone is kind of an interesting one, +但是 iPhone 是一个有意思的设备 + +643 +00:27:46,671 --> 00:27:49,171 +other iPhones besides the iPhone 6+, +其他 iPhone 除 iPhone 6+ 之外的 + +644 +00:27:49,173 --> 00:27:53,041 +in portrait it is compact in width and regular in height, +竖屏时宽紧凑高普通 + +645 +00:27:53,043 --> 00:27:55,677 +just like an iPhone 6+, but in landscaped, +就像是 iPhone 6+, 但是在横屏的时候 + +646 +00:27:55,679 --> 00:27:59,147 +it is considered compact in width and compact in height. +它应该被考虑成宽紧凑高也是紧凑 + +647 +00:27:59,149 --> 00:28:02,383 +And that might seem non-intuitive,. +它不是凭直觉的 + +648 +00:28:02,385 --> 00:28:06,653 +But it just turns out that a non iPhone 6+, the width of +但是事实证明非 iPhone 6+,这个宽 + +649 +00:28:06,655 --> 00:28:09,823 +it is just not quite enough to say this is a regular width. +它不充分作为普通宽 + +650 +00:28:09,825 --> 00:28:12,492 +Most UIs just will look better if you +大部分 UI 只是看起来友好如果你 + +651 +00:28:12,494 --> 00:28:14,994 +consider it compact, okay? +只是考虑它的紧凑性,了解吗? + +652 +00:28:14,996 --> 00:28:18,964 +Now the iPad is always regular in both directions. +现在 iPad 一直作为全方向上的普通处理 + +653 +00:28:18,966 --> 00:28:20,632 +Portrait or landscape, it's always so +竖屏或者横屏,它一直都是 + +654 +00:28:20,634 --> 00:28:22,734 +big that it's just regular in both directions. +大并且全方向普通 + +655 +00:28:22,736 --> 00:28:24,635 +There's no compact on the iPad. +iPad 上面没有紧凑 + +656 +00:28:24,637 --> 00:28:26,370 +But again a particular view controller on +但是再次声明一个特别的视图控制器 + +657 +00:28:26,372 --> 00:28:27,904 +an iPad like the master of +在 iPad 上面主要 + +658 +00:28:27,906 --> 00:28:31,074 +a split view side by side that's going to be compact. +分屏并列紧凑的 + +659 +00:28:31,076 --> 00:28:34,844 +Regular height, compact width. +普通的高, 紧凑的宽 + +660 +00:28:34,846 --> 00:28:37,947 +All right, this whole thing is extensible it's not kinda all +当然, 整个事物都是可扩展的, 它没有 + +661 +00:28:37,949 --> 00:28:39,715 +frozen in stone. +固定住 + +662 +00:28:39,717 --> 00:28:41,983 +You if you have a view controller you can find out +你如果你有一个视图控制器你可以发现 + +663 +00:28:41,985 --> 00:28:45,987 +your size class by using this property called trait +你尺寸等级,它是通过使用的属性即特征 + +664 +00:28:45,989 --> 00:28:47,121 +collection. +集合 + +665 +00:28:47,123 --> 00:28:48,489 +And inside traitCollection, +并且在特征集合里 + +666 +00:28:48,491 --> 00:28:50,957 +it's gonna return the horizontal size class and +它将返回水平尺寸等级和 + +667 +00:28:50,959 --> 00:28:52,976 +the vertical size class, +竖直尺寸等级 + +668 +00:28:52,977 --> 00:28:54,994 +and that's just an enum that's either .Compact or +并且这只是枚举的两种。紧凑 + +669 +00:28:54,996 --> 00:28:56,429 +.Regular, okay? +或者普通,了解? + +670 +00:28:56,431 --> 00:29:00,232 +Now, you probably almost never need to do this because you're +现在你很可能几乎从不需要这些因为你将 + +671 +00:29:00,234 --> 00:29:03,669 +gonna edit this in your storyboard, 'kay? +在 storyboard 里编辑,了解吗? + +672 +00:29:03,671 --> 00:29:07,039 +You're going to set up your storyboard to deal with +你将设置你的 storyboard 去处理 + +673 +00:29:07,041 --> 00:29:08,573 +size classes. +尺寸等级 + +674 +00:29:08,575 --> 00:29:10,942 +And then your code, it's just all gonna work. +然后你的代码,它将正常工作 + +675 +00:29:10,944 --> 00:29:12,176 +Okay as long as you got your +直到你的自动布局 + +676 +00:29:12,178 --> 00:29:14,111 +rest of your auto layout going. +不起作用的时候 + +677 +00:29:14,113 --> 00:29:16,130 +So how does that work? +要怎么让它工作? + +678 +00:29:16,131 --> 00:29:18,148 +All right so here's the size classes right horizontal and +当然这里有尺寸等级正确的水平和 + +679 +00:29:18,150 --> 00:29:20,383 +vertical, compact and regular. +垂直,紧凑和普通 + +680 +00:29:20,385 --> 00:29:21,918 +See these four boxes right, +看四个盒子 + +681 +00:29:21,920 --> 00:29:24,086 +that's every possible combination. +这每一个都可能是混合的 + +682 +00:29:24,088 --> 00:29:27,956 +Okay and so for my calculator for example here's what +对于我们的计算器比如这里 + +683 +00:29:27,958 --> 00:29:30,992 +my UI might look like in those situations. +我们的 UI 可能看起来在这些情况下 + +684 +00:29:30,994 --> 00:29:33,995 +Okay you see here that I've gone five across and four +你所看到的这里有五列四行 + +685 +00:29:33,997 --> 00:29:39,467 +down when I have a compact height and regular width. +当它高紧凑宽普通 + +686 +00:29:39,469 --> 00:29:47,507 +But I basically anytime I have a regular width I'm gonna +但是我基本定期有一个普通的宽我将 + +687 +00:29:47,509 --> 00:29:51,711 +go what did I do, every time I actually every time I have. +做我该做的,每一次的确每一次都如此 + +688 +00:29:51,713 --> 00:29:57,449 +A regular height, I go five high. +一个普通的高度,我设置5列 + +689 +00:29:58,619 --> 00:30:01,953 +Okay so lower right is regular height, it's five high. +当然右下角是个普通高,它是五列 + +690 +00:30:01,955 --> 00:30:04,422 +Lower left is regular height is five high. +左下角普通高也是五列 + +691 +00:30:04,424 --> 00:30:06,490 +The top two are compact height, +最上两个是紧凑高 + +692 +00:30:06,492 --> 00:30:10,093 +I've gone to four high five wide. +我将设置四列五行 + +693 +00:30:10,095 --> 00:30:12,028 +Okay. +当然 + +694 +00:30:12,029 --> 00:30:13,962 +So it'd be kinda a pain though if I had to do all four of +它有些问题以至于我只能设置四个 + +695 +00:30:13,965 --> 00:30:16,866 +these for every user interface I built. +这些每一个我建立的用户界面 + +696 +00:30:16,868 --> 00:30:20,703 +So we actually have another size class called any. +因此我们的确有其他的尺寸等级 + +697 +00:30:20,705 --> 00:30:23,872 +And if you throw any into the mix, +并且如果你抛弃这些混乱的 + +698 +00:30:23,874 --> 00:30:27,642 +now I can do this exactly the way I just said which is. +现在我可以确定这个我所说的这个方式 + +699 +00:30:27,644 --> 00:30:31,245 +Any, first of all I'm gonna have an any any, +当然,起先我需要这个 any any + +700 +00:30:31,247 --> 00:30:33,347 +which is the middle, and that's gonna be my base UI. +这个在中间,这些作为我的基本用户界面 + +701 +00:30:34,350 --> 00:30:38,018 +So, if I don't specify any particular size class, it's +因此,如果我指定一些特殊的尺寸等级 + +702 +00:30:38,020 --> 00:30:40,453 +gonna look like that, which is four across and five down. +它就像是这个四列五行 + +703 +00:30:41,556 --> 00:30:44,289 +But in the case where it's vertically compact. +但是在这个垂直紧凑的条件下 + +704 +00:30:45,793 --> 00:30:48,727 +I'm going to go to five across and only four high. +我将它设置为五列可是只有四列 + +705 +00:30:48,729 --> 00:30:50,361 +And I don't care what the width is so +并且我不关心它的宽度 + +706 +00:30:50,363 --> 00:30:51,629 +that's why it's any. +为什么它是 any + +707 +00:30:51,631 --> 00:30:53,664 +So now I only have to do two user interfaces. +现在我只想做好这两个用户界面 + +708 +00:30:53,666 --> 00:30:57,134 +My main user interface, the any any and one other one +我的主要的用户界面,any any 和这个和另外一个 + +709 +00:30:57,136 --> 00:30:59,602 +which is I'm in a compact vertical situation so +在这个紧凑的垂直条件下 + +710 +00:30:59,604 --> 00:31:00,436 +I want to go four high. +我想有四列 + +711 +00:31:01,673 --> 00:31:04,273 +Okay so this makes it a little easier now I only have to do +这有点简单现在我就想 + +712 +00:31:04,275 --> 00:31:06,208 +things and +这个和 + +713 +00:31:06,209 --> 00:31:08,142 +still covers all the same bases as the previous slide. +仍然覆盖的所有的正如之前幻灯片相同的基本框架 + +714 +00:31:08,145 --> 00:31:12,480 +And incredibly, Interface Builder will have a graph that +难以置信的是,界面建立者将有一个图形 + +715 +00:31:12,482 --> 00:31:15,750 +looks almost exactly like this slide that lets you pick +看起来就像幻灯片所说的你所选的 + +716 +00:31:15,752 --> 00:31:18,752 +between these various boxes, and you can design your +这些不同盒子之间的,你可以设计你 + +717 +00:31:18,754 --> 00:31:20,854 +user interface in any of these boxes. +用户界面 + +718 +00:31:21,990 --> 00:31:23,222 +Okay? And it will +好?然后它将 + +719 +00:31:23,224 --> 00:31:24,457 +just magically work. +只是神奇地运作 + +720 +00:31:24,459 --> 00:31:26,892 +So let's take a look at a demo here. +因此让它看起来就像这里的例子 + +721 +00:31:26,894 --> 00:31:28,293 +I actually have a couple of demos. +我的确有一对演示 + +722 +00:31:28,295 --> 00:31:30,628 +The one is called ShowSizeClass, +这个个叫做 ShowSizeClass + +723 +00:31:30,630 --> 00:31:35,099 +it's just an app that I wrote that shows the size +这个应用,我是为了展示尺寸 + +724 +00:31:35,101 --> 00:31:38,369 +class of whatever device you're on at the time. +等级不管你现在处于何种设备之下 + +725 +00:31:38,371 --> 00:31:39,553 +Okay? +可否? + +726 +00:31:39,554 --> 00:31:40,736 +And we're gonna take a look at the code for that. +我们将看一下这个代码 + +727 +00:31:40,739 --> 00:31:43,173 +And then I'm gonna do an app from scratch. +然后我先用 scratch 做这个应用 + +728 +00:31:43,175 --> 00:31:45,208 +Which is called Autolayout. +这个被称为自动布局 + +729 +00:31:45,210 --> 00:31:46,575 +That's the name of my app. +这是应用的名称 + +730 +00:31:46,577 --> 00:31:47,943 +Add it's just gonna have some +添加这个将有一些 + +731 +00:31:47,944 --> 00:31:49,310 +very interesting autolayout things including +非常有趣的自动布局的包括 + +732 +00:31:49,313 --> 00:31:52,080 +the size class problem that we're gonna have to solve. +尺寸等级等这些我们会解决的问题 + +733 +00:31:52,082 --> 00:31:53,615 +Okay so it's kind of kitchen sink of that. +这就像是厨房的污水槽 + +734 +00:31:53,617 --> 00:31:55,516 +All right let's go and +接下来 + +735 +00:31:55,518 --> 00:31:59,520 +look at this app I wrote called ShowSizeClass. +看这个我写的被称为 ShowSizeClass 的应用 + +736 +00:31:59,522 --> 00:32:00,821 +So here's ShowSizeClass, and +在这个 ShowSizeClass 应用里 + +737 +00:32:00,823 --> 00:32:02,956 +I'm just going to run this on some various devices. +我将运行在这些设备上 + +738 +00:32:02,958 --> 00:32:06,459 +Let's run this on an iPhone 6 Plus for example. +例如让我们先运行在 iPhone 6+ 上 + +739 +00:32:07,695 --> 00:32:09,795 +Here's an iPhone 6 Plus. +这是 iPhone 6 + + +740 +00:32:09,797 --> 00:32:10,962 +How do I make this small? +怎么把它变小? + +741 +00:32:10,964 --> 00:32:12,447 +I guess I can't. +我猜我不能 + +742 +00:32:12,448 --> 00:32:13,931 +This is as small as I can make it. +这是我所能做到的最小的 + +743 +00:32:13,933 --> 00:32:17,301 +You see how iPhone 6 Plus in portrait here +你看到 iPhone 6 + 在这里怎样竖屏 + +744 +00:32:17,303 --> 00:32:19,403 +is horizontally compact. +水平紧凑的 + +745 +00:32:19,405 --> 00:32:22,039 +And it's regular vertically. +并且竖直普通的 + +746 +00:32:22,041 --> 00:32:22,872 +That's what the green means. +这是绿颜色的意思 + +747 +00:32:23,975 --> 00:32:26,559 +Okay? +下一步? + +748 +00:32:26,560 --> 00:32:29,144 +If I rotate it, it's regular horizontally and +如果我旋转它,它是水平整齐 + +749 +00:32:29,146 --> 00:32:30,112 +compact vertically. +竖直紧凑的 + +750 +00:32:31,381 --> 00:32:32,280 +Everybody cool with that? +大家是不是觉得它相当酷炫? + +751 +00:32:33,416 --> 00:32:34,248 +All right. Now, +当然,现在 + +752 +00:32:34,249 --> 00:32:35,081 +let's look on the iPhone 6. +让我们再看回 iPhone 6 + +753 +00:32:40,155 --> 00:32:41,954 +All right, iPhone 6 again, +当然,再一次 iPhone 6 + +754 +00:32:41,956 --> 00:32:44,557 +regular vertically, compact width. +垂直普通,水平紧凑 + +755 +00:32:44,559 --> 00:32:47,125 +But if we rotate, it's compact in both directions. +但是如果我们旋转,它将全方向紧凑了 + +756 +00:32:49,162 --> 00:32:53,698 +Okay, let's go to like iPhone 4s or something like that. +下一步,让我们看 iPhone 4s 或者其他设备 + +757 +00:32:59,271 --> 00:33:00,637 +Okay, so here's 4S. +这是 4s + +758 +00:33:00,639 --> 00:33:02,405 +It's also, even though it's kind of short, +也是,虽然它看起来有点短 + +759 +00:33:02,407 --> 00:33:04,640 +it's still considered regular vertically. +它仍然是垂直普通的 + +760 +00:33:04,642 --> 00:33:06,075 +And compact this way, +这个紧凑的方式 + +761 +00:33:06,077 --> 00:33:09,345 +and compact in both directions just like an iPhone 6. +全方向紧凑就像是 iPhone 6 + +762 +00:33:09,347 --> 00:33:11,897 +Okay? +下一步? + +763 +00:33:11,898 --> 00:33:14,448 +And lastly, let's take a quick look at iPad2, or any iPad. +最后,让我们看一下 iPad2,或者其他 iPad + +764 +00:33:14,451 --> 00:33:17,085 +I do iPad too because it fits on this screen. +我选 iPad 是因为它有合适的屏幕 + +765 +00:33:17,087 --> 00:33:18,820 +All the rest of them are too high of resolution again. +其余的又太高了 + +766 +00:33:18,822 --> 00:33:20,154 +All right, look, see. +看这里 + +767 +00:33:20,156 --> 00:33:23,090 +It's regular this way and regular both ways, +这个方式是普通的并且所有方式都是普通的 + +768 +00:33:23,092 --> 00:33:24,658 +this way, okay. +这个方向,当然 + +769 +00:33:24,660 --> 00:33:27,794 +So let's look at the app that I wrote to do that. +因此让我们看我写的这个应用 + +770 +00:33:27,796 --> 00:33:30,963 +I keep going back here to iPhone 6. +我将回到 iPhone 6 + +771 +00:33:34,802 --> 00:33:37,836 +Okay, let's look at the app that I wrote. +让我们看一下这个我写的应用 + +772 +00:33:37,838 --> 00:33:40,172 +Here it is, ShowSizeClass. +这里,ShowSizeClass + +773 +00:33:40,174 --> 00:33:42,040 +It has a storyboard here. +这是一个 storyboard + +774 +00:33:42,042 --> 00:33:43,975 +Here's its storyboard. +这是 storyboard + +775 +00:33:43,976 --> 00:33:45,909 +Let's see if we can find anything in the storyboard. +让我们看看如果我们可以发现 storyboard 的其他东西 + +776 +00:33:45,912 --> 00:33:47,545 +There it is, okay. +这里,好的 + +777 +00:33:47,547 --> 00:33:48,779 +Hm, nteresting. +恩,有趣 + +778 +00:33:48,781 --> 00:33:52,148 +This storyboard, there's no arrows. +这个 storyboard,没有箭头 + +779 +00:33:53,451 --> 00:33:54,750 +There's the dot in the middle, but +这里中间有个小黑点,但是 + +780 +00:33:54,752 --> 00:33:55,751 +where the heck did those arrows? +没有箭头? + +781 +00:33:55,753 --> 00:33:57,219 +Oh, I must draw them in my code. +哦,我必须把他们画到我的代码里 + +782 +00:33:57,221 --> 00:33:58,586 +Let's look at the View control. +让我们看这个视图控制器 + +783 +00:33:58,588 --> 00:34:00,855 +Oh, my View control had no code. +哦,我的视图控制器没有代码 + +784 +00:34:00,857 --> 00:34:02,556 +This app has no code. +这个应用没有代码 + +785 +00:34:02,558 --> 00:34:06,560 +How is it possible that it drew those arrows, okay? +我怎样画出这些箭头呢? + +786 +00:34:06,562 --> 00:34:11,097 +Well, the answer is that those arrows are only drawn for +这些箭头是画来解决 + +787 +00:34:11,099 --> 00:34:13,132 +the SizeClass in question. +这个 SIzeClass 的问题 + +788 +00:34:13,134 --> 00:34:15,401 +So for +因此为了 + +789 +00:34:15,402 --> 00:34:17,669 +example if I have something that is horizontally compact I +例如如果我有一些水平紧凑 + +790 +00:34:17,672 --> 00:34:20,839 +draw those two red arrows and where is that, well +我画这两个红色箭头在这里, + +791 +00:34:20,841 --> 00:34:24,042 +look down at the bottom of the screen here it says any any. +看屏幕下方的 any any 这个区域 + +792 +00:34:24,044 --> 00:34:27,112 +So this is the user interface if you're in any any +这个用户界面如果你在任意 + +793 +00:34:27,114 --> 00:34:29,747 +the default user interface okay. +默认的用户界面 + +794 +00:34:29,749 --> 00:34:33,617 +If I click on this right here I can pick any of +如果我点击右边这里我可以挑出这些 + +795 +00:34:33,619 --> 00:34:36,487 +those nine boxes that I showed on that slide. +九个盒子就我在幻灯片显示的 + +796 +00:34:36,489 --> 00:34:38,789 +So for example look at this box right here. +例如看在这里的这个盒子 + +797 +00:34:38,791 --> 00:34:42,759 +This is any width but a compact height. +这个任意宽度但是紧凑的高 + +798 +00:34:42,761 --> 00:34:45,094 +Now when I click here its actually gonna change my user +现在当我点击这里它的确改变了我们的用户 + +799 +00:34:45,096 --> 00:34:48,030 +interface and show me what the user interface looks like on +界面并且给我们在设备上展示这个用户界面 + +800 +00:34:48,032 --> 00:34:51,266 +a device that is any width but a compact height. +这设备是任意宽但是紧凑的高 + +801 +00:34:52,969 --> 00:34:56,571 +See, these are just two labels I threw out here that do +看,这里有两个标签去作为 + +802 +00:34:56,573 --> 00:35:00,174 +that and same thing let's say over here, any height, +相同事物让我们展示这里,任意高 + +803 +00:35:00,176 --> 00:35:01,041 +compact width. +紧凑的宽 + +804 +00:35:03,145 --> 00:35:06,679 +Or, over here we have regular width, any height. +或者这里普通的宽,任意高 + +805 +00:35:08,282 --> 00:35:10,349 +And over here we have any width, +这里我们用任意宽 + +806 +00:35:10,351 --> 00:35:12,017 +regular height, yeah, there we go. +整齐的高,好,继续 + +807 +00:35:12,019 --> 00:35:13,218 +So that's it. +就这样 + +808 +00:35:13,219 --> 00:35:14,418 +That's my entire user interface. +这是我们整体的用户界面 + +809 +00:35:14,421 --> 00:35:19,456 +I just put the arrows in whichever SizeClass was +我只是在 SizeClass 上放箭头 + +810 +00:35:19,458 --> 00:35:21,792 +appropriate there. +在合适的位置上 + +811 +00:35:22,961 --> 00:35:25,828 +This is really cool to be able to go here and basically edit +这实在是酷能够到达这里,并且有基本编辑 + +812 +00:35:25,830 --> 00:35:28,164 +your user interface in any of these circumstances. +在这些任何状况下在你的用户界面里 + +813 +00:35:28,166 --> 00:35:29,698 +Including specific ones, +在这些特殊的情况下 + +814 +00:35:29,700 --> 00:35:31,500 +like this Compact Width Compact Height. +就像这个紧凑的宽紧凑的高 + +815 +00:35:31,502 --> 00:35:33,535 +That's basically, you're editing your user +这是最基本的,你在编辑的你的用户 + +816 +00:35:33,537 --> 00:35:37,138 +interface for non-iPhone 6 Pluses in Landscape. +界面在横屏非 iPhone 6 plus 上 + +817 +00:35:37,140 --> 00:35:39,840 +Because that's the only one that is both Compact Width and +因为那是只有一个全部紧凑宽 + +818 +00:35:39,842 --> 00:35:41,275 +Compact Height. +和紧凑高 + +819 +00:35:41,277 --> 00:35:42,510 +Okay? +下一步? + +820 +00:35:42,511 --> 00:35:43,744 +So you could actually have a specific one just for +隐藏你们的确可以有一个特殊的在 + +821 +00:35:43,746 --> 00:35:45,478 +that circumstance. +特定状况下 + +822 +00:35:45,480 --> 00:35:46,579 +Okay? But it's nicer to +下一步?但是非常好去使用 + +823 +00:35:46,581 --> 00:35:49,415 +have these Anys, to use these Anys out here so +这些 Any,使用 Any 使 + +824 +00:35:49,417 --> 00:35:51,850 +that they'll work, and we'll see in the demo. +他们运行,我们将在演示中见到的 + +825 +00:35:51,852 --> 00:35:54,353 +And one of the things I challenged, +有一个我们改变的事物 + +826 +00:35:54,355 --> 00:35:56,054 +I didn't really talk about it in the slides there, +我没有在幻灯片里讨论 + +827 +00:35:56,056 --> 00:35:58,756 +but I challenged you to do is, I actually added this as an +但是我期待你去做,我给做出作业3的额外的分数 + +828 +00:35:58,758 --> 00:36:01,258 +extra credit to the homework number three, if you want. +如果你们想的话 + +829 +00:36:01,260 --> 00:36:03,711 +Go back and +回去 + +830 +00:36:03,712 --> 00:36:06,163 +make your calculator user interface look different. +让你们的计数器与众不同 + +831 +00:36:06,165 --> 00:36:07,731 +In different SizeClasses. +在不同的 SizeClasses + +832 +00:36:07,733 --> 00:36:11,034 +Maybe do five buttons by four instead of four by five, +可能是五列四行替代了四列五行 + +833 +00:36:11,036 --> 00:36:12,335 +okay, or something like that. +当然或者其他的 + +834 +00:36:12,337 --> 00:36:15,804 +Or even, some ones have more buttons. +也可以加更多的按键 + +835 +00:36:15,806 --> 00:36:18,807 +If you look at the calculator that Apple ships on +你看 Apple 商城的计算器 + +836 +00:36:18,809 --> 00:36:20,675 +the iPhone, when you go to Landscape, +当你横屏看的时候 + +837 +00:36:20,677 --> 00:36:22,110 +it has a lot more operations. +它有更多的操作 + +838 +00:36:22,112 --> 00:36:23,277 +The buttons are all smaller, but +这些按键更小,但是 + +839 +00:36:23,279 --> 00:36:25,879 +it has a lot of operations that aren't even there. +有更多的操作在那里 + +840 +00:36:25,881 --> 00:36:27,714 +And you can do that with side classes as well. +你可以用 side classes 去实现这些 + +841 +00:36:29,017 --> 00:36:32,785 +Okay, alright so +当然 + +842 +00:36:32,787 --> 00:36:35,054 +now we're gonna write an app here from scratch. +现在我们将用 scratch 写一个应用 + +843 +00:36:36,957 --> 00:36:39,958 +And it is going to look like this. +它将看起来像这个 + +844 +00:36:39,960 --> 00:36:42,160 +Okay here's what it's UIs gonna look like. +这些 UI 看起来像这样的 + +845 +00:36:42,162 --> 00:36:43,661 +It's very, very, this is a demo, okay, +他非常非常,这就是一个演示 + +846 +00:36:43,663 --> 00:36:45,429 +so it's a very simple app. +一个很简单的应用 + +847 +00:36:45,431 --> 00:36:48,165 +It asks for a username and password up here, so +它请求帐号密码 + +848 +00:36:48,167 --> 00:36:52,869 +I have madbum, and password is foo. +我有登录密码 + +849 +00:36:52,871 --> 00:36:56,005 +Now, I can change the security on my password. +我更改这个密码的安全性 + +850 +00:36:56,007 --> 00:37:00,475 +I can have it be secured so I can't see it, okay. +我可以使其可靠,让我看不到它 + +851 +00:37:00,477 --> 00:37:03,445 +But when I log in, it's gonna show me. +但是当我登录,它将会显示 + +852 +00:37:03,447 --> 00:37:06,514 +An icon for the person, +一个面向用户的图标 + +853 +00:37:06,515 --> 00:37:09,582 +the persons name, and what company they work for, okay. +用户的名字他们工作的公司 + +854 +00:37:09,585 --> 00:37:11,485 +Madison Bumgarner in this case. +Madison Bumgarner 也在那 + +855 +00:37:11,487 --> 00:37:15,088 +And if I rotate it's gonna say the same information but +如果我旋转它将显示这些相同的信息但是 + +856 +00:37:15,090 --> 00:37:19,192 +notice that this is not below here, +这个并不在下方 + +857 +00:37:19,194 --> 00:37:22,895 +it's actually moved to be beside it. +它被移除去了 + +858 +00:37:23,931 --> 00:37:25,881 +Okay? +下一步? + +859 +00:37:25,882 --> 00:37:27,832 +So, basically, on Sizeclasses that are regular height, or +因此,基本的,SizeClasses 是普通高或者 + +860 +00:37:27,834 --> 00:37:30,068 +have a lot of room, I put the words at the bottom. +有很多空间,我放很多单词在下面 + +861 +00:37:30,070 --> 00:37:33,604 +I try to use this space to show their picture more. +我尝试用这些空间去显示更多的照片 + +862 +00:37:33,606 --> 00:37:38,475 +And in other SizeClasses, I put it off to the side, okay? +在另外一个 SizeClasses,我把它放到另一边 + +863 +00:37:38,477 --> 00:37:44,914 +And we have other users here, like, Same password. +我们有其他的用户在这里,就像,相同的密码 + +864 +00:37:44,916 --> 00:37:49,151 +Okay it's all got all the different icon or old j apple. +它得到所有不同的图标或者 japple + +865 +00:37:51,088 --> 00:37:52,487 +Okay John Appleseed. +John Appleseed + +866 +00:37:52,489 --> 00:37:55,490 +Okay? In all of these cases +下一步?这些所有的情况下 + +867 +00:37:55,492 --> 00:37:56,223 +it's going to do that. +它将这么做 + +868 +00:37:57,259 --> 00:38:00,127 +Okay so lot going on here to make this work with +很多将在这使其运作通过 + +869 +00:38:00,129 --> 00:38:01,161 +auto layout. +自动布局 + +870 +00:38:01,163 --> 00:38:02,562 +Right you got +你所得到的正确的方式 + +871 +00:38:02,563 --> 00:38:03,962 +this thing automatically changing right here. +这个自动化地在这里改变 + +872 +00:38:03,965 --> 00:38:06,332 +You've got this you've got this image here which you +你将得到这个图片 + +873 +00:38:06,334 --> 00:38:09,001 +want to be the right aspect ration. +这图片是你将在正确方面配给 + +874 +00:38:09,003 --> 00:38:11,403 +You know we got he SizeClass things so +你知道你得到 SizeClass 图片 + +875 +00:38:11,405 --> 00:38:14,172 +we can put the words underneath when it's tall etc. +所以我们可以放这些单词到下面当它很高等 + +876 +00:38:15,641 --> 00:38:16,640 +Okay. +好的 + +877 +00:38:16,642 --> 00:38:18,775 +So that's what we're going to build. +因此我们将建立这个 + +878 +00:38:18,777 --> 00:38:22,612 +Alright, let's go and we're going to start from +好的,让我们开始 + +879 +00:38:22,614 --> 00:38:25,148 +scratch as I like to do usually, so +从 scratch 就像我们通常做的那样 + +880 +00:38:25,150 --> 00:38:27,950 +it's creating a new XCode project, iOS application. +它创建一个新的 xcode 项目,iOS 应用 + +881 +00:38:27,952 --> 00:38:29,618 +I'm going to call it auto layout, okay. +我将称它为自动布局 + +882 +00:38:29,620 --> 00:38:33,355 +I'm going to put it the same place I put all of my +我将放在同一个位置我放在所有 + +883 +00:38:33,357 --> 00:38:34,455 +apps there. +我的应用那里 + +884 +00:38:34,457 --> 00:38:36,424 +Here it is. +就这里 + +885 +00:38:36,425 --> 00:38:38,392 +I'm gonna move this app delegate out of the way. +我将不用这个方式移动这个应用 + +886 +00:38:38,394 --> 00:38:40,027 +And the launch screen out of the way. +不用这个方式登录界面 + +887 +00:38:40,029 --> 00:38:41,928 +For the first time we're actually gonna +第一次我们将 + +888 +00:38:41,930 --> 00:38:44,698 +talk about these image assets here today. +告诉这些图片连接这个地方 + +889 +00:38:44,700 --> 00:38:46,432 +It's a good opportunity to talk about that. +这是一个很好的机会阐述这个 + +890 +00:38:47,702 --> 00:38:48,734 +Okay. And in my controller, +好,在我的控制下 + +891 +00:38:48,736 --> 00:38:49,968 +I'm gonna clear out this code. +我将清理这些代码 + +892 +00:38:49,970 --> 00:38:51,569 +Don't need any of that. +并不需要这么做 + +893 +00:38:51,571 --> 00:38:53,137 +By the way, the things that I cleared out here, +顺便说一下,这个我清理的地方 + +894 +00:38:53,139 --> 00:38:54,739 +you starting to recognize them? +你开始认出他们? + +895 +00:38:54,741 --> 00:38:56,340 +View controller life cycle methods. +视图控制器生命周期方法 + +896 +00:38:57,543 --> 00:38:58,108 +Okay. +好的 + +897 +00:38:59,177 --> 00:39:02,511 +But if I need those, I'll put them back but okay. +但是我需要这些,我将他们放回去 + +898 +00:39:03,714 --> 00:39:05,914 +So, let's go to our storyboard and start building this UI. +让我们到这个 storyboard 并且开始建立这个 UI + +899 +00:39:05,916 --> 00:39:09,984 +Now this is gonna be a lot of clicking things around. +现在这里将有很多点击事物在周围 + +900 +00:39:09,986 --> 00:39:12,019 +I'm gonna make this as big as possible for us here. +我将使这些在这里尽可能大的显示 + +901 +00:39:12,021 --> 00:39:15,589 +That's all right, that there. +好的 + +902 +00:39:16,792 --> 00:39:19,926 +Lot of graphical things happening. +许多绘图事件正在发生 + +903 +00:39:19,928 --> 00:39:20,559 +Let's just do that. +完成了 + +904 +00:39:22,063 --> 00:39:25,030 +Okay, so I'm gonna start with those text fields at +让我们从上面的 TextField 开始 + +905 +00:39:25,032 --> 00:39:26,531 +the top, right? +好吗? + +906 +00:39:26,533 --> 00:39:28,633 +I need a username and password text field. +我需要一个用户名和密码的 TextField + +907 +00:39:28,635 --> 00:39:32,003 +So I'm gonna go down here and grab a text field. +到这里拽一个 TextField + +908 +00:39:32,005 --> 00:39:34,471 +Okay, this is actually gonna be an editable one, so +它是可以编辑的 + +909 +00:39:34,473 --> 00:39:36,973 +I grab this one, text, not label, but text. +所以要 TextField 而不是 Label + +910 +00:39:36,975 --> 00:39:40,377 +And I'm going to put it up in the upper corner to start. +把它放到上面的角落 + +911 +00:39:40,379 --> 00:39:43,112 +Grab another one, put this here. +再拽一个,放到这里 + +912 +00:39:43,114 --> 00:39:45,581 +Okay, now, I'm gonna use some model layout stuff you +现在,我使用一些你们已经了解的 + +913 +00:39:45,583 --> 00:39:46,248 +already know about. +Autolayout 的东西 + +914 +00:39:46,250 --> 00:39:47,582 +I'm gonna use Ctrll drag. +按住 Ctrl 拖动 + +915 +00:39:47,584 --> 00:39:50,919 +Let's stick this one trailing space to that edge. +右边设置为 Trailing Space + +916 +00:39:50,921 --> 00:39:52,854 +Let's stick this one with this trailing space to that end. +这个也一样 + +917 +00:39:52,856 --> 00:39:55,256 +Let's get this one to the top. +上面设置为 Top Space + +918 +00:39:55,258 --> 00:39:56,423 +Let's put a space in +它俩之间 + +919 +00:39:56,425 --> 00:39:58,892 +between the vertical space between them. +设置为 Vertical Space + +920 +00:39:58,894 --> 00:39:59,793 +You know about. +你们已经知道这些了 + +921 +00:39:59,795 --> 00:40:01,394 +Doing all those kind of things. +做一些类似的 Autolayout + +922 +00:40:01,396 --> 00:40:04,397 +Now one thing as I'm working with auto layout I +当我处理 Autolayout 问题时 + +923 +00:40:04,399 --> 00:40:07,799 +often like to click this little button right here. +我会点击这个按钮 + +924 +00:40:08,735 --> 00:40:10,535 +Because this will +因为 + +925 +00:40:10,536 --> 00:40:12,336 +give you a little summary of what's going on. +它会总结出你所出现的问题 + +926 +00:40:13,473 --> 00:40:16,373 +And when all it's complaining about is that frames are gonna +当它只抱怨 Frame 在运行时可能发生变化时 + +927 +00:40:16,375 --> 00:40:19,810 +be moved, a cool thing you can do is go down here +你可以到这里 + +928 +00:40:19,812 --> 00:40:21,411 +to this button. +点击这个按钮 + +929 +00:40:21,413 --> 00:40:24,881 +The same one where we do Reset to Suggested Constraints and +和 Reset to Suggested Constraints 还有 Clear Constraints + +930 +00:40:24,883 --> 00:40:27,717 +Clear Constraints, there's this Update Frame. +在相同位置的,Update Frame + +931 +00:40:27,719 --> 00:40:33,789 +And it will update all frames in your storyboard. +这会更新 storyboard 中所有的框架结构 + +932 +00:40:33,791 --> 00:40:35,990 +Now, it made those smaller because the text in +现在它们变小了 + +933 +00:40:35,992 --> 00:40:38,059 +them is small, but don't worry about that. +因为它们中没有文字 + +934 +00:40:38,061 --> 00:40:39,326 +We're gonna fix that later. +不用担心,后面会修复的 + +935 +00:40:39,328 --> 00:40:41,829 +So I did Undo right there because I wanted them to be +我后退了一步 + +936 +00:40:41,831 --> 00:40:44,698 +a little bigger just as I work. +因为我想让它们在我处理的时候大一点 + +937 +00:40:44,700 --> 00:40:45,832 +Okay? But I'll be going back to +我回时常点击 + +938 +00:40:45,834 --> 00:40:47,400 +look at this often. +看看它们 + +939 +00:40:47,402 --> 00:40:48,734 +And if I see it's just frames, +如果其中只警告关于 frame 的内容 + +940 +00:40:48,736 --> 00:40:50,202 +then I'll be doing Update Frames. +我就会进行 Update Frame 操作 + +941 +00:40:50,204 --> 00:40:51,636 +And if I don't like what it did I +如果我不喜欢它替我做的 + +942 +00:40:51,638 --> 00:40:52,804 +can always undo, keep going. +我可以后退 + +943 +00:40:52,806 --> 00:40:54,405 +All right? +好的 + +944 +00:40:54,407 --> 00:40:58,175 +So let's go and do our things here for +再为 TextField + +945 +00:40:58,177 --> 00:41:02,846 +the user name and password fields. +做一些其他事 + +946 +00:41:02,848 --> 00:41:04,914 +So I'm just going to put some text in these. +在 Label 中输入一些文字 + +947 +00:41:04,916 --> 00:41:05,915 +Password. +Password + +948 +00:41:07,185 --> 00:41:09,351 +User name, so +Username + +949 +00:41:09,353 --> 00:41:12,421 +these ones I kind of want to be on the left. +我想把它放到左边 + +950 +00:41:12,423 --> 00:41:13,588 +Okay, if you remember. +如果你还记得 + +951 +00:41:13,590 --> 00:41:15,590 +So I'm gonna do the same thing here with control drag. +在这里还是使用 Ctrl+Drag + +952 +00:41:15,592 --> 00:41:18,125 +Let's set that leaning space. +左边设置为 Leading Space + +953 +00:41:18,127 --> 00:41:19,993 +Let's set that leaning space. +选择它 + +954 +00:41:19,995 --> 00:41:21,294 +Let's set this thing to the, +把它设置为 + +955 +00:41:21,296 --> 00:41:22,929 +actually I'm not even gonna set this to the top. +实际上我不想把它顶部设置为 Top Space + +956 +00:41:22,931 --> 00:41:24,464 +Now this is an interesting one. +这个设置比较有趣 + +957 +00:41:24,466 --> 00:41:26,766 +So I have these two guys right here. +对于这两个 Label + +958 +00:41:26,768 --> 00:41:30,069 +Really what I want them to do is be lined up with whatever +我想让它们与 TextField + +959 +00:41:30,071 --> 00:41:31,136 +the text is in here. +在同一水平线上 + +960 +00:41:31,138 --> 00:41:33,938 +I wanna line them up by their baselines. +通过设置 baseline + +961 +00:41:33,940 --> 00:41:37,842 +So I'm gonna control drag between the two of them and +Ctrl+Drag 选择它 + +962 +00:41:37,844 --> 00:41:40,310 +go down here and pick Baseline. +选择 Baseline + +963 +00:41:40,312 --> 00:41:43,313 +So this is going to line up their baselines. +这就把它们的 baseline 连在了一起 + +964 +00:41:43,315 --> 00:41:44,314 +Okay? +好的 + +965 +00:41:44,316 --> 00:41:47,016 +Same thing here, drag this one. +对于它也一样 + +966 +00:41:47,018 --> 00:41:48,918 +And line up their baselines there. +把它们的 baseline 连在一起 + +967 +00:41:50,087 --> 00:41:53,155 +Now, another thing I want is that I want them to be kind +另一件我想做的事情是 + +968 +00:41:53,157 --> 00:41:54,989 +of, well, I want these two guys, username and +把这两个 Label + +969 +00:41:54,991 --> 00:41:57,458 +password, to be the same width. +设置成相同宽度 + +970 +00:41:57,460 --> 00:41:59,260 +So, I'm control dragging between them and +它俩之间 Ctrl+Drag + +971 +00:41:59,262 --> 00:42:01,095 +saying Equal Widths. +选择 Equal Widths + +972 +00:42:01,097 --> 00:42:03,364 +You remember in the calculator we +在 Calculator 中 + +973 +00:42:03,365 --> 00:42:05,632 +did the equal widths down here with this thing, okay? +我们用它设置的 Equal Widths + +974 +00:42:05,634 --> 00:42:07,300 +But, you can do it with control drag as well. +但是你也可以通过 Ctrl+Drag 实现 + +975 +00:42:08,436 --> 00:42:10,469 +And then also I want these things attached. +我希望它俩互相依附 + +976 +00:42:10,471 --> 00:42:13,539 +So I want that thing attached to each other so +通过设置它们的 + +977 +00:42:13,541 --> 00:42:15,674 +that its horizontal spacing is set. +Horizontal Spacing + +978 +00:42:15,676 --> 00:42:17,509 +And I want this thing attached to this, +它俩也一样 + +979 +00:42:17,511 --> 00:42:18,476 +its horizontal spacing. +设置 Horizontal Spacing + +980 +00:42:19,412 --> 00:42:22,179 +Now I've done all this stuff even though +我已经做好了所有的工作 + +981 +00:42:22,181 --> 00:42:24,648 +they're really not where I want them right now. +即使它们还不太是我想要的 + +982 +00:42:24,650 --> 00:42:27,650 +So usually you can kinda set things up and +通常你设置好以后 + +983 +00:42:27,652 --> 00:42:30,620 +then just go into the size inspector. +打开 Size Inspector + +984 +00:42:30,622 --> 00:42:32,722 +And inspect all of them and +看看 Autolayout 的数据 + +985 +00:42:32,724 --> 00:42:35,057 +get rid of every magic number you see. +然后去除你看到的每一个魔法数字 + +986 +00:42:36,493 --> 00:42:38,760 +If you get rid of every magic number you see usually it's +如果你把每一个数字都去掉了 + +987 +00:42:38,762 --> 00:42:40,294 +gonna do exactly what you want. +那将会是你需要的 Autolayout 了 + +988 +00:42:40,296 --> 00:42:41,996 +So lets go here, lets start with this one. +从这个开始 + +989 +00:42:41,998 --> 00:42:43,030 +Lets find some magic numbers. +寻找一下魔法数字 + +990 +00:42:43,032 --> 00:42:44,731 +Look at this Leading Space Username. +Leading Space Username + +991 +00:42:44,733 --> 00:42:46,366 +[SOUND] Magic number. +魔法数字! + +992 +00:42:46,368 --> 00:42:48,735 +Okay magic number means number in here, +魔法数字代表这里出现的数字 + +993 +00:42:48,737 --> 00:42:51,103 +anything that's a number get rid of it. +你看到了数字,把它去除就好了 + +994 +00:42:51,105 --> 00:42:52,137 +So 392 I'm gonna get rid of that, +我将要去除 392 + +995 +00:42:52,139 --> 00:42:54,473 +I'm gonna do it by going up here. +去到这里 + +996 +00:42:54,475 --> 00:42:57,075 +Instead of having 392, +我将选择 Standard Value + +997 +00:42:57,076 --> 00:42:59,676 +I'm going to pick Standard Value, okay? +而不是 392 + +998 +00:42:59,679 --> 00:43:00,878 +So now it's gone. +392 消失了 + +999 +00:43:00,880 --> 00:43:02,212 +So you can click on these things and +你可以点击它 + +1000 +00:43:02,214 --> 00:43:04,481 +click Edit to get rid of these. +点击编辑来去掉他们 + +1001 +00:43:04,483 --> 00:43:08,084 +Even 8, which had got by the blue lines, okay? +即使是8,是通过蓝色的线条来得到的,明白? + +1002 +00:43:08,086 --> 00:43:09,452 +I don't like that either. +我同样也不喜欢那个 + +1003 +00:43:09,453 --> 00:43:10,819 +I'm just going to go here and say zero, because +我把它设置为0 + +1004 +00:43:10,822 --> 00:43:13,956 +I want that to be right up against the edge, okay? +我想要挨着那个边界,明白? + +1005 +00:43:13,958 --> 00:43:16,458 +Oops. Sorry. +哦,对不起 + +1006 +00:43:16,460 --> 00:43:19,294 +Same thing, oh, did I do the right thing there? +同样的,我在这里做的对么? + +1007 +00:43:19,296 --> 00:43:22,364 +Leading space, username, yeah, trailing spaces, you're right. +距离顶部的空间,距离底部的空间,是正确的 + +1008 +00:43:22,366 --> 00:43:23,949 +How about this one? +对于它呢? + +1009 +00:43:23,950 --> 00:43:25,533 +Top Space to Top Layout right here, +这里就是顶部布局的顶部空间 + +1010 +00:43:25,535 --> 00:43:26,867 +I'll use the Standard Value for that. +我将对它们使用默认的值 + +1011 +00:43:26,869 --> 00:43:28,135 +Okay? +明白? + +1012 +00:43:28,137 --> 00:43:30,270 +Oops, sorry, keep clicking there. +哦,对不起,继续点击那里 + +1013 +00:43:30,272 --> 00:43:33,340 +And then here, Align Baseline equals three. +然后在这里,距离基线的距离等于3 + +1014 +00:43:33,342 --> 00:43:36,609 +Okay I want these baselines exactly aligned not three off +好的我想要这些基线的实际距离不为3 + +1015 +00:43:36,611 --> 00:43:39,912 +of each other so I'm gonna say zero right here. +所以我准备在这里设置为0 + +1016 +00:43:39,914 --> 00:43:44,249 +So I've gotten rid of all the magic numbers in here. +我已经去掉了这里所有的魔法数字 + +1017 +00:43:44,251 --> 00:43:46,351 +Okay now lets do it for +再来处理一下它 + +1018 +00:43:46,352 --> 00:43:48,452 +this one, okay this one also has a magic number here, +它也有魔法数字 + +1019 +00:43:48,455 --> 00:43:51,622 +lets change that to be Standard Value. +把它设置为 Standard Value + +1020 +00:43:51,624 --> 00:43:53,391 +We got this one, Align Baseline. +设置 Align Baseline + +1021 +00:43:53,393 --> 00:43:54,658 +We want that to be zero. +设置为 0 + +1022 +00:43:55,928 --> 00:43:57,060 +Okay? So we got rid of that. +把它去掉 + +1023 +00:43:57,062 --> 00:43:57,827 +How about this one? +对于它呢 + +1024 +00:43:57,829 --> 00:44:00,396 +Oh, this one's good. +它还可以 + +1025 +00:44:00,398 --> 00:44:01,497 +No magic value. +没有魔法数字 + +1026 +00:44:01,499 --> 00:44:03,165 +And this one, also good. +它也没有 + +1027 +00:44:03,167 --> 00:44:04,165 +Okay? All is good. +所有的都完成了 + +1028 +00:44:04,167 --> 00:44:05,833 +All is well with the world. +每个都没有魔法数字了 + +1029 +00:44:05,835 --> 00:44:07,118 +Okay? +好的 + +1030 +00:44:07,119 --> 00:44:08,402 +But we still have this up here. +但是上面是有警告 + +1031 +00:44:08,404 --> 00:44:10,237 +Frame will be different at run time, so +在运行时,框架结构会不同 + +1032 +00:44:10,239 --> 00:44:12,005 +I'm going to go down here. +去到这里,选择 Update Frame + +1033 +00:44:12,007 --> 00:44:14,874 +And update our frames and this looks good. +这看起来还不错 + +1034 +00:44:14,876 --> 00:44:17,910 +Now, when I look at this I'm like that's really not what I +我再回头看一看 + +1035 +00:44:17,912 --> 00:44:20,946 +want, so I must have made a mistake. +发现有个地方不是我想要的 + +1036 +00:44:20,948 --> 00:44:23,082 +For example, I want this spacing in-between not to +我不想让它俩之间 + +1037 +00:44:23,084 --> 00:44:24,817 +be zero, so +的距离是0 + +1038 +00:44:24,818 --> 00:44:26,551 +I typed zero somewhere where I wanted a standard value. +我想它是 Standard Value + +1039 +00:44:26,553 --> 00:44:29,220 +So, let's go back here and see where that is. +回到这里,看看它是什么 + +1040 +00:44:29,222 --> 00:44:30,588 +Okay? It looks like it's this one +看起来是它 + +1041 +00:44:30,590 --> 00:44:33,157 +you can tell when you mouse over these, it tells you. +当你鼠标放上去的时候,你能看出是哪一个 + +1042 +00:44:33,159 --> 00:44:34,692 +So here let's go back to here and +回到这里 + +1043 +00:44:34,694 --> 00:44:37,894 +instead of zero, let's say Standard Value, okay? +用 Standard Value 代替 0 + +1044 +00:44:37,896 --> 00:44:39,829 +And it moved it there for us. +它为我们做出了修改 + +1045 +00:44:40,999 --> 00:44:42,065 +Sometimes it moves it, +有时它会帮我们移动 + +1046 +00:44:42,066 --> 00:44:43,132 +sometimes you need to do update frames. +有时你需要 Update Frames + +1047 +00:44:43,134 --> 00:44:44,300 +It just kind of depends on +这只取决于 + +1048 +00:44:44,301 --> 00:44:45,467 +the character of the change you're making. +你做出改变的对象 + +1049 +00:44:47,804 --> 00:44:49,103 +Okay? +OK? + +1050 +00:44:49,105 --> 00:44:51,238 +Now, here's a really cool thing. +还有一个很 cool 的事情 + +1051 +00:44:51,240 --> 00:44:53,124 +I want to see what +我想看看在 + +1052 +00:44:53,125 --> 00:44:55,009 +this looks like in portrait and landscape. +垂直和水平模式界面的样子 + +1053 +00:44:55,011 --> 00:44:57,144 +So yeah, I could go up here and hit Run, +我可以运行程序 + +1054 +00:44:57,146 --> 00:45:00,380 +but there is a lot faster way, which is to open up +但是还有更快的方式 + +1055 +00:45:01,883 --> 00:45:05,384 +the assistant editor here and instead of showing your view +打开 Assistant Editor + +1056 +00:45:05,386 --> 00:45:08,253 +controller, go up here and go down to Preview. +选择 Preview + +1057 +00:45:09,589 --> 00:45:11,522 +This will preview your UI. +这会给你预览一下 UI + +1058 +00:45:13,259 --> 00:45:15,726 +Okay? And you can preview it in +你可以以 + +1059 +00:45:16,795 --> 00:45:18,795 +either landscape or portrait. +水平或垂直模式预览 + +1060 +00:45:18,797 --> 00:45:21,564 +You can also preview it on other devices like +你也可以在其他设备上预览 + +1061 +00:45:21,566 --> 00:45:25,000 +maybe an iPhone 6 Plus, okay, which is kind of so +iPhone 6 Plus + +1062 +00:45:25,002 --> 00:45:28,303 +big that we can't barely even see it here. +分辨率太高了,这里可能看不全 + +1063 +00:45:28,305 --> 00:45:30,238 +Barely flip it around, okay? +占的地方太大了 + +1064 +00:45:31,174 --> 00:45:33,341 +Or you can even look at it on an iPad if you wanted. +你也可以放到 iPad 上预览 + +1065 +00:45:34,276 --> 00:45:38,111 +Okay I think four inches works best for +4 英寸的设备 + +1066 +00:45:38,113 --> 00:45:39,846 +this small resolution I have. +比较适合我这个小分辨的 Mac + +1067 +00:45:39,848 --> 00:45:43,549 +But this is really cool, now this can only preview your UI +这很棒,但是只能预览 Ui + +1068 +00:45:43,551 --> 00:45:45,651 +for things that aren't running your code. +但是不能预览到代码对 UI 的改变 + +1069 +00:45:45,653 --> 00:45:47,419 +Okay so if you're gonna do something that you need to +如果你想看到运行代码才能看出的改变 + +1070 +00:45:47,421 --> 00:45:49,587 +run your code then you need to go run it in the app. +运行 App 就可以了 + +1071 +00:45:49,589 --> 00:45:51,256 +But if you just want to +但是你只想看看 + +1072 +00:45:51,257 --> 00:45:52,924 +see how is the auto layout gonna work. +Autolayout 的结果 + +1073 +00:45:52,926 --> 00:45:54,876 +You can do this. +你可以这么做 + +1074 +00:45:54,877 --> 00:45:56,827 +Now another thing that's cool here is what's this gonna look +还有一件很棒的事情是 + +1075 +00:45:56,829 --> 00:45:59,596 +like when you give it off to your localization guys and +当你做本地化工作地时候 + +1076 +00:45:59,598 --> 00:46:03,500 +if this gets translated to German or something like that. +如果这些文字被翻译成了德文 + +1077 +00:46:03,502 --> 00:46:05,602 +You can do that, you can kinda make sure that you +你可以点击它 + +1078 +00:46:05,604 --> 00:46:07,837 +don't have any big problems by going down here, +看看会不会出现什么大得问题 + +1079 +00:46:07,839 --> 00:46:09,772 +see where it says English. +现在上面是 English + +1080 +00:46:09,774 --> 00:46:10,739 +Sort of click on that. +电吉他 + +1081 +00:46:11,942 --> 00:46:14,476 +And we can go to this double length pseudo language. +选择双倍长度的伪语言 + +1082 +00:46:14,478 --> 00:46:17,611 +And all that does is doubles every text. +所有的 text 变成了双倍长度 + +1083 +00:46:19,081 --> 00:46:22,416 +Okay? So even a long translation of +即使 Username + +1084 +00:46:22,418 --> 00:46:25,118 +the word Username would fit there. +被翻译成了很长一串,也能适合这里 + +1085 +00:46:25,120 --> 00:46:27,420 +And my auto layout is working properly. +Autolayout 看起来没什么问题 + +1086 +00:46:27,422 --> 00:46:29,689 +And so my translation is just going to work. +被翻译成其他语言也没问题 + +1087 +00:46:29,691 --> 00:46:31,824 +So Auto Layout is not just used for +它不光可以预览 + +1088 +00:46:31,826 --> 00:46:33,325 +landscape versus portrait or whatever. +横屏和竖屏模式 + +1089 +00:46:33,327 --> 00:46:35,226 +It can be used for translation as well. +它也可以用于检查被翻译后的效果 + +1090 +00:46:35,228 --> 00:46:36,694 +When you're localizing things, +当你做本地化工作的时候 + +1091 +00:46:36,696 --> 00:46:38,896 +you want auto-layout to make things fit. +你需要用 Autolayout 调整 + +1092 +00:46:38,898 --> 00:46:43,266 +Okay? Everyone understand that? +每个人都理解了吗? + +1093 +00:46:43,268 --> 00:46:44,034 +Okay. +OK + +1094 +00:46:44,036 --> 00:46:44,934 +All right, good. +好的 + +1095 +00:46:44,936 --> 00:46:46,602 +So we're making progress here. +我们有些进步了 + +1096 +00:46:46,604 --> 00:46:49,438 +By the way, you probably don't wanna have preview open as +当你做出许多改变的时候 + +1097 +00:46:49,440 --> 00:46:50,605 +you're doing a lot of changes here, +最好不要打开预览模式 + +1098 +00:46:50,607 --> 00:46:53,008 +cuz it's gonna be constantly previewing in real time. +因为它是实时的预览 + +1099 +00:46:53,010 --> 00:46:54,709 +So if you've got a really powerful machine, +如果你的机器性能很强大 + +1100 +00:46:54,711 --> 00:46:56,060 +it could keep up, but +可能会跟上 + +1101 +00:46:56,061 --> 00:46:57,410 +you might be asking it to do a lot of calculations. +但是它会同时进行许多计算 + +1102 +00:46:57,413 --> 00:46:59,947 +So I usually close that while I'm working, and +所以我通常在编辑的时候关闭它 + +1103 +00:46:59,949 --> 00:47:01,548 +then just bring it back whenever I wanna preview. +在希望预览的时候再打开 + +1104 +00:47:02,718 --> 00:47:04,417 +So let's do those two buttons. +让我们来处理这两个按钮 + +1105 +00:47:04,419 --> 00:47:06,452 +Remember, I had the button change security, +我让这个按钮改变安全性 + +1106 +00:47:06,454 --> 00:47:08,020 +which changed this to secure, and +把它变成安全输入 + +1107 +00:47:08,022 --> 00:47:10,255 +then I had the button login, so let's go ahead and do that. +让这个按钮实现登陆,让我们一起实现 + +1108 +00:47:11,258 --> 00:47:13,157 +Another trick I'm going to show you is, and +另一个我想给你们展示的技巧是 + +1109 +00:47:13,159 --> 00:47:16,227 +I'm always scrolling around in here trying to find things. +我总是通过滚动寻找东西 + +1110 +00:47:16,229 --> 00:47:18,195 +You can actually find things real quick by going down to +你也可以在这里输入内容 + +1111 +00:47:18,197 --> 00:47:19,763 +the bottom here and typing like button. +实现快速查找 + +1112 +00:47:19,765 --> 00:47:23,199 +Now it's only going to show you the buttons. +它现在只展现给你 button + +1113 +00:47:23,201 --> 00:47:25,001 +Okay? We got Bar Button and +这里有 Bar Button + +1114 +00:47:25,003 --> 00:47:27,503 +here's regular button, so I'm going to drag that out. +还有普通的 Button,拽一个普通的出来 + +1115 +00:47:27,505 --> 00:47:29,338 +Let's get a couple of those buttons. +多拽几个 + +1116 +00:47:29,340 --> 00:47:33,408 +We'll call this one Change security. +把这个改为 Change Security + +1117 +00:47:34,444 --> 00:47:35,810 +We'll call this one log in. +把这个叫做 Login + +1118 +00:47:37,313 --> 00:47:38,612 +Okay now where do these want to be? +我要把它们放在哪里呢? + +1119 +00:47:38,614 --> 00:47:40,347 +They kind of +我想把它们 + +1120 +00:47:40,348 --> 00:47:42,081 +want to be underneath there something like that. +放到它们下面 + +1121 +00:47:42,084 --> 00:47:45,084 +Definitely I like their baselines lined +当然我想让它俩 + +1122 +00:47:45,086 --> 00:47:46,619 +up right there. +基线对齐 + +1123 +00:47:46,620 --> 00:47:48,153 +So let's go ahead and kind of put those in position. +让我们把它俩放到合适的位置 + +1124 +00:47:48,156 --> 00:47:51,490 +I'm gonna set the vertical spacing between the login and +把这个按钮和它设置为 + +1125 +00:47:51,492 --> 00:47:52,791 +this guy right here and +Vertical Spacing + +1126 +00:47:52,793 --> 00:47:56,461 +then I'm control dragging here to set the baselines the same. +Ctrl+Drag 把它俩的 baseline 设置为对齐 + +1127 +00:47:56,463 --> 00:47:58,947 +Okay? +OK? + +1128 +00:47:58,948 --> 00:48:01,432 +Now, that has actually set the vertical position of both of +现在已经设置好了它俩垂直方向的位置 + +1129 +00:48:01,434 --> 00:48:03,066 +these things, okay. +好的 + +1130 +00:48:03,068 --> 00:48:05,135 +Because the vertical position of these are set and so +因为它俩的垂直位置 + +1131 +00:48:05,137 --> 00:48:07,070 +when I tie this vertical position here and +已经设置完毕了 + +1132 +00:48:07,072 --> 00:48:10,306 +the baseline which is a vertical positioning here but +但是这里有个警告 + +1133 +00:48:10,308 --> 00:48:13,776 +if I go up here it says that the horizontal position of +它俩的水平位置 + +1134 +00:48:13,778 --> 00:48:16,445 +Login and Change Security is ambiguous. +是有歧义的 + +1135 +00:48:16,447 --> 00:48:17,712 +Which makes sense. +这有道理 + +1136 +00:48:17,714 --> 00:48:19,213 +I haven't really specified where these +我还没有指定 + +1137 +00:48:19,215 --> 00:48:19,914 +things are supposed to be. +它俩的水平位置 + +1138 +00:48:19,916 --> 00:48:21,799 +Just because I put them on +我把它俩放到这里 + +1139 +00:48:21,800 --> 00:48:23,683 +the screen doesn't mean that there's an auto layout rule. +不代表已经有了 Autolayout 的约束 + +1140 +00:48:23,686 --> 00:48:25,452 +Now, what do I want it to be? +我想把它俩放到哪? + +1141 +00:48:25,454 --> 00:48:28,621 +Well, I kind of want them to be some reasonable distance +我想让它俩之间有些距离 + +1142 +00:48:28,623 --> 00:48:30,590 +apart so it doesn't look like, you know, +这样看起来 + +1143 +00:48:30,592 --> 00:48:32,058 +this is part of the same thing. +就不像是在一起的一个按钮了 + +1144 +00:48:32,060 --> 00:48:34,593 +That would look like change security log in is one thing. +这样 Change Security Login 看起来就像是一个东西 + +1145 +00:48:34,595 --> 00:48:37,062 +So I want them apart a little bit. +所以我想让它俩之间有点距离 + +1146 +00:48:37,064 --> 00:48:39,664 +But otherwise I want them centered on the screen. +我想让它俩居中在屏幕 + +1147 +00:48:39,666 --> 00:48:41,532 +I want the pair of them centered. +它俩都居中 + +1148 +00:48:41,534 --> 00:48:44,702 +Now, there's no auto layout rule that says that. +但是没有这样的 Autolayout 约束 + +1149 +00:48:44,704 --> 00:48:47,471 +That's too complicated, okay? +这太复杂了 + +1150 +00:48:47,473 --> 00:48:50,841 +But, I can easily do this with a little creativity, and +但是我可以通过一点创意让这个事变得简单 + +1151 +00:48:50,843 --> 00:48:51,941 +when you start doing auto layout, +当你在做 Autolayout 的时候 + +1152 +00:48:51,943 --> 00:48:54,243 +you start realizing, hm, how can I do that? +你会意识到,我要怎么实现这个东西 + +1153 +00:48:54,245 --> 00:48:56,512 +Well, I need to be creative in how I'm gonna approach this. +其实为了实现它,需要一点创意 + +1154 +00:48:56,514 --> 00:48:59,748 +[NOISE] And in this case what I'm gonna do is +在这种情况 + +1155 +00:48:59,750 --> 00:49:04,352 +I'm gonna create two little spacer views on the side here. +我会在这两边放两个占空间的 View + +1156 +00:49:04,354 --> 00:49:06,354 +And I'm gonna set them to be the same width. +把它俩设置为相同宽度 + +1157 +00:49:06,356 --> 00:49:09,357 +Can you see how that's gonna make it so +你能想象到这么做 + +1158 +00:49:09,359 --> 00:49:12,126 +these two kinda get pushed into the middle? +会把两个按钮推到中间吗? + +1159 +00:49:12,128 --> 00:49:14,428 +Right, by the same amount on each side. +只要两边的距离相同 + +1160 +00:49:14,430 --> 00:49:16,697 +So how would I do that? +我该怎么做 + +1161 +00:49:16,698 --> 00:49:18,965 +So I'm gonna do that by just grabbing some views, +我可以拽进来几个 View + +1162 +00:49:18,967 --> 00:49:20,750 +just generic views, +普通的 View 就可以 + +1163 +00:49:20,751 --> 00:49:22,534 +okay, this just a generic view like the one you do to +这就是普通的 View + +1164 +00:49:22,537 --> 00:49:24,337 +do your graph view or the face view or whatever. +就像之前画图和 FaceView 的 View 一样 + +1165 +00:49:24,339 --> 00:49:27,506 +When I'm working on it here, I'm going to give it +我要给它俩改变一下颜色 + +1166 +00:49:27,508 --> 00:49:31,876 +some background color so I can see the thing, okay, +这样我就能看到它俩 + +1167 +00:49:31,878 --> 00:49:36,013 +now when I'm actually ready to go I will turn that back off. +一切设置完毕后,再把颜色改回来 + +1168 +00:49:36,982 --> 00:49:40,317 +And I'm just going to put them in here somewhere, copy and +复制粘贴一个 + +1169 +00:49:40,319 --> 00:49:43,086 +paste another one, put it over here somewhere, and +放到这里 + +1170 +00:49:43,088 --> 00:49:46,756 +then I'm just gonna wire these up to how I want them, +给它俩做些约束 + +1171 +00:49:46,758 --> 00:49:49,158 +so I want this to kind of be on that edge, +我想把它放在这边 + +1172 +00:49:49,160 --> 00:49:50,859 +I want this thing to be on that edge, +把它放到这边 + +1173 +00:49:51,995 --> 00:49:55,063 +I want these two things to kind of be linked. +我想让它俩有所关联 + +1174 +00:49:55,065 --> 00:49:56,581 +Okay. + +1175 +00:49:56,582 --> 00:49:58,098 +Let's say I'll link their horizontal spacing. +设置 Horizontal Spacing + +1176 +00:49:58,101 --> 00:49:59,066 +Now here, I'm going to +现在 + +1177 +00:49:59,068 --> 00:50:00,768 +set multiple things between these two. +我要给它俩设置多个约束 + +1178 +00:50:00,770 --> 00:50:02,836 +I'm gonna set the horizontal spacing and +设置 Horizontal Spacing 还有... + +1179 +00:50:02,838 --> 00:50:04,904 +then notice I'm holding down shift. +注意这里,我按住了 shift + +1180 +00:50:04,906 --> 00:50:06,639 +I'm also gonna set the top and +选中 Top 还有 Bottom + +1181 +00:50:06,641 --> 00:50:09,608 +bottom of this view to match the top and bottom. +让它俩对齐 + +1182 +00:50:09,610 --> 00:50:11,577 +Now, there's no base lines because this is not text. +它没有文字,所以没有基线 + +1183 +00:50:11,579 --> 00:50:12,678 +This is just a generic view. +它只是普通的 View + +1184 +00:50:12,680 --> 00:50:14,512 +So I'm gonna move mine up the top and bottom. +所以我选 Top 和 Bottom + +1185 +00:50:14,514 --> 00:50:16,781 +So I can do Shift+click to do that. +我可以按住 shift 然后这样做 + +1186 +00:50:17,850 --> 00:50:19,583 +Okay. And then same thing over here, +对于它也是一样 + +1187 +00:50:19,585 --> 00:50:21,752 +I'm gonna do the same thing with these two guys. +对它俩做一样的事情 + +1188 +00:50:21,754 --> 00:50:26,923 +I'm gonna set the top whoops, sorry, control drag. +抱歉,Ctrl+Drag + +1189 +00:50:26,925 --> 00:50:30,492 +I'm gonna set the top and bottom horizontal spacing. +选中 Top, Bottom, Horizontal Spacing + +1190 +00:50:32,496 --> 00:50:34,112 +Okay. + +1191 +00:50:34,113 --> 00:50:35,729 +Then I said I wanted to make this one and +然后,我想把它俩 + +1192 +00:50:35,732 --> 00:50:38,733 +this one be equal widths. +设置成相同的宽度 + +1193 +00:50:38,735 --> 00:50:41,369 +So I can just do that with control drag as well, so +我可以 Ctrl+Drag + +1194 +00:50:41,371 --> 00:50:42,603 +I've set that up. +设置完毕 + +1195 +00:50:42,605 --> 00:50:45,505 +I want this to be stuck to this edge, trailing space, +我想让它挨着边缘,Training Space + +1196 +00:50:45,507 --> 00:50:48,975 +I want this to be stuck to this edge, leading space, and +设置 Leading Spacing + +1197 +00:50:48,977 --> 00:50:52,478 +I want these two guys to have some horizontal spacing, +设置它俩 Horizontal Spacing + +1198 +00:50:52,480 --> 00:50:54,213 +I'm not quite sure how much I want yet, but +我不知道我想让它俩间距多少 + +1199 +00:50:54,215 --> 00:50:56,448 +I want some sort of horizontal spacing. +但是我想让它们之间有些间距 + +1200 +00:50:56,450 --> 00:50:59,885 +Now, I've done this, and look, the yellow thing went away. +完成了,黄色的警告消失了 + +1201 +00:50:59,887 --> 00:51:03,254 +It says, okay, I know exactly where to put these things. +这个意思是Xcode已经知道这几个组件的确切位置了。 + +1202 +00:51:03,256 --> 00:51:06,090 +But this is really not where I want these put, okay? +但是这个不是我想要的确切位置。 + +1203 +00:51:06,092 --> 00:51:09,260 +Because I actually want this spacer right up against this, +因为我希望这个贴着这个, + +1204 +00:51:09,262 --> 00:51:11,161 +and I want this spacer right up against this. +这个贴着这个。 + + +1205 +00:51:11,163 --> 00:51:13,663 +So I'm gonna go through that same process again of +所以我要再做一次同样的事情来消除那些 + +1206 +00:51:13,665 --> 00:51:15,699 +getting rid of the magic number. +魔法数。 + +1207 +00:51:15,701 --> 00:51:17,100 +So let's start with this guy. +从这个开始。 + +1208 +00:51:18,136 --> 00:51:20,969 +And get rid of his magic numbers in the size inspector, +在尺寸检查器里消除掉它的魔法数。 + +1209 +00:51:20,971 --> 00:51:22,771 +so it's got this trailing space here, +来到尾部间距这里, + +1210 +00:51:22,773 --> 00:51:23,838 +let's get rid of that. +消除掉它。 + +1211 +00:51:23,840 --> 00:51:26,407 +We want that to be a standard value. +我们希望它是标准值。 + +1212 +00:51:26,409 --> 00:51:29,777 +Okay we got this one, we align the bottoms we want those to +到这里,它们应该底部是对齐的, + +1213 +00:51:29,779 --> 00:51:32,046 +be exactly aligned, so we'll do zero. +所以这个应该是0. + +1214 +00:51:32,048 --> 00:51:34,348 +Same thing with top we want that exactly aligned, so +顶部应该也是对齐的, + +1215 +00:51:34,350 --> 00:51:37,283 +I got rid of all of the magic numbers for this. +这样魔法数就全没了。 + +1216 +00:51:37,285 --> 00:51:38,518 +How about this guy? +继续这个。 + +1217 +00:51:38,520 --> 00:51:39,518 +Same thing. +还是一样的 + +1218 +00:51:39,520 --> 00:51:42,487 +Okay? We want this to be standard value. +这我希望是标准值。 + +1220 +00:51:42,489 --> 00:51:45,657 +Usually I always put it to standard value +通常来说我都会选标准值, + +1221 +00:51:45,659 --> 00:51:47,925 +unless standard value is not an option. +但是当标准值不能选时, + +1222 +00:51:47,927 --> 00:51:49,794 +Then I usually pick zero. +我一般就选0. + +1223 +00:51:49,796 --> 00:51:50,761 +Okay? If standard value is +如果标准值不可用, + +1224 +00:51:50,763 --> 00:51:52,495 +not an option I'll just make it zero. +我就把它设成0. + +1225 +00:51:54,699 --> 00:51:56,565 +Then here, a line top. +这里,顶部对齐, + +1226 +00:51:56,567 --> 00:51:58,033 +Let's see. Standard value, nope. +选标准值,不行。 + +1227 +00:51:58,035 --> 00:51:58,700 +Let's make it zero. +那就是0吧。 + +1228 +00:52:01,905 --> 00:52:02,970 +Okay? + +1229 +00:52:02,972 --> 00:52:04,338 +So, no magic numbers there. +魔法数没了。 + +1230 +00:52:04,340 --> 00:52:05,139 +How about this guy? +继续下一个。 + +1231 +00:52:05,141 --> 00:52:06,473 +Does he have magic numbers? +这个有魔法数吗? + +1232 +00:52:06,475 --> 00:52:07,907 +Yeah, he has this 87. +有一个87. + +1233 +00:52:07,909 --> 00:52:09,909 +That's this difference between these two. +这个跟前边的就不同了。 + +1234 +00:52:11,345 --> 00:52:12,377 +That's okay. +这个是可以的。 + +1235 +00:52:12,379 --> 00:52:13,845 +This has a magic number here. +这里还有一个魔法数。 + +1236 +00:52:13,847 --> 00:52:15,179 +This. +这个 + +1237 +00:52:15,181 --> 00:52:16,847 +Hello. + +1238 +00:52:16,849 --> 00:52:21,151 +Standard value. +标准值。 + +1239 +00:52:21,153 --> 00:52:22,569 +Okay. So now, + +1240 +00:52:22,570 --> 00:52:23,986 +the only magic number we have is this 87, +好了,所以现在唯一的魔法数就是这个87了。 + +1241 +00:52:23,989 --> 00:52:25,855 +which is this distance here. +是这两个之间的距离。 + +1242 +00:52:25,857 --> 00:52:28,557 +Now, what's really cool about this is you can +这里一个非常酷的东西是, + +1243 +00:52:28,559 --> 00:52:30,826 +double click on this. +你可以双击这里。 + +1244 +00:52:30,828 --> 00:52:32,427 +And inspect it right in space. +就可以看到它们的间距。 + +1245 +00:52:32,429 --> 00:52:34,462 +So here I'm gonna make it be let's say 50. +我要把它设成50. + +1246 +00:52:34,464 --> 00:52:37,298 +So this is a magic number right here, because there's +这是一个魔法数,因为 + +1247 +00:52:37,300 --> 00:52:40,034 +really no standard spacing cuz I'm kinda doing somewhat of +这里并没有一个标准的间距,我们正在做的并不是 + +1248 +00:52:40,036 --> 00:52:41,902 +a non standard thing here. +一个标准化的东西。 + +1249 +00:52:41,904 --> 00:52:44,371 +Any time you do a non standard thing, +每当你要做一个非标准化的东西的时候, + +1250 +00:52:44,373 --> 00:52:47,941 +really ask yourself do I really want to be doing this? +都要问一下自己是不是确定。 + +1251 +00:52:47,943 --> 00:52:50,143 +Okay cuz I'm kinda going against the grain by doing +要确定自己做的是不是确实需要 + +1252 +00:52:50,145 --> 00:52:54,513 +something against, you know, what standard values are. +与标准值不同。 + +1253 +00:52:54,515 --> 00:52:57,516 +In this case I'm gonna go ahead and do it, but I should +在这里,我确实需要怎么做,但是 + +1254 +00:52:57,518 --> 00:53:00,452 +probably be asking myself if I really wanna do that. +也应该问一下自己是否确定。 + +1255 +00:53:00,454 --> 00:53:01,886 +And it might be a little confusing to users. +因为这有可能会让使用者迷惑。 + +1256 +00:53:01,888 --> 00:53:03,020 +So let's go ahead and +现在咱们继续, + +1257 +00:53:04,190 --> 00:53:05,989 +look at this thing in the preview again. +在预览里再看一下。 + +1258 +00:53:05,991 --> 00:53:07,757 +So here it is, looks good, see, +看上去没什么问题,看。 + +1259 +00:53:07,759 --> 00:53:09,559 +it made those two things the same width, +这两个辅助的视图宽度是一样的, + +1260 +00:53:09,561 --> 00:53:10,993 +put these things in the center. +把它们两个置于中间。 + +1261 +00:53:10,995 --> 00:53:14,830 +Same thing here, put those in the center, excellent. +横过来,也是一样的,在中间,非常好。 + +1262 +00:53:14,832 --> 00:53:15,430 +Okay? + +1263 +00:53:15,432 --> 00:53:16,764 +So, that's good. +非常好。 + +1264 +00:53:16,766 --> 00:53:18,866 +Now, I've got it where I want it. +我觉得已经达到目的了。 + +1265 +00:53:18,868 --> 00:53:21,485 +So I can go back and +现在我需要回去 + +1266 +00:53:21,486 --> 00:53:24,103 +turn these things back to being non gray, okay? +把这两个辅助视图的灰色去掉, + +1267 +00:53:24,106 --> 00:53:24,971 +Go back to the default. +回到默认状态就好。 + +1268 +00:53:29,444 --> 00:53:30,042 +Okay? + +1269 +00:53:31,278 --> 00:53:33,412 +See how I built that UI? +看到我是怎么构建这个UI的了吗? + +1270 +00:53:33,413 --> 00:53:35,547 +So those spacers, don't forget you can put spacers in. +不要忘了你可以用辅助视图, + +1271 +00:53:35,549 --> 00:53:37,181 +They're perfectly legal to throw in there. +把它们扔在那是完全没有问题的。 + +1272 +00:53:37,183 --> 00:53:37,748 +Question? +有问题么? + +1273 +00:53:42,287 --> 00:53:43,586 +>> So what's the canvas option? +画布选项是什么? + +1274 +00:53:43,588 --> 00:53:45,555 +[INAUDIBLE] you choose the canvas value? +[不清楚]选画布值是什么意思? + +1275 +00:53:45,557 --> 00:53:47,923 +>> Okay. Yeah. When you have something selected. +我明白了,如果你选了一个组件。 + +1276 +00:53:47,925 --> 00:53:49,458 +Okay? + +1277 +00:53:49,459 --> 00:53:50,992 +And you go over here and it says Edit, and +点到这里, + +1278 +00:53:50,995 --> 00:53:53,128 +you can change to the Canvas Value, +你可以选择画布值, + +1279 +00:53:53,130 --> 00:53:55,530 +that says whatever is actually here right now. +意思就是在你看到的实际效果, + +1280 +00:53:55,532 --> 00:53:59,734 +In other words, to what I moved it to, basically. +换句话说,就是我把它挪到的位置。 + +1281 +00:53:59,736 --> 00:54:02,336 +And when you first Ctrl+drag, +就是你第一次Ctrl+拖拽时 + +1282 +00:54:02,338 --> 00:54:03,937 +that's the value it's gonna have, okay? +的实际值。 + +1283 +00:54:03,939 --> 00:54:07,007 +Good question there. +非常好的问题。 + +1284 +00:54:07,009 --> 00:54:08,108 +Okay. + +1285 +00:54:08,109 --> 00:54:09,208 +Now let's start writing some code, okay? +现在我们开始写代码。 + +1286 +00:54:09,210 --> 00:54:11,077 +Cuz I want this change security button to +我希望摁change security这个摁钮可以 + +1287 +00:54:11,079 --> 00:54:12,978 +change this to say secured password. +可以让这里显示为secured password。 + +1288 +00:54:12,980 --> 00:54:14,513 +And I want this to +同时我也希望 + +1289 +00:54:14,514 --> 00:54:16,047 +actually be a secured password in that case, 'kay? +输入的密码变成星号。 + +1290 +00:54:17,050 --> 00:54:18,383 +So what is that code gonna look like? +代码应该是什么样的呢。 + +1291 +00:54:18,385 --> 00:54:20,284 +Let's go here to automatic. +这里我们选自动。 + +1292 +00:54:20,286 --> 00:54:22,653 +Here's our view controller here. +这里就是我们的视图控制器。 + +1293 +00:54:22,655 --> 00:54:25,055 +I'm gonna need some outlets to connect to these things. +这里我需要outlet连接一下组件。 + +1294 +00:54:25,057 --> 00:54:26,890 +So I'm gonna Ctrl+drag some stuff here. +在这里ctrl+拖拽。 + +1295 +00:54:26,892 --> 00:54:29,225 +Let's control + drag that. +先拖这个, + +1296 +00:54:29,227 --> 00:54:31,360 +That is our login field. +这是我们的登陆框。 + +1297 +00:54:31,362 --> 00:54:34,263 +Let's control + drag this. +再拖这个, + +1298 +00:54:34,265 --> 00:54:37,065 +That is our password field. +这是密码框。 + +1299 +00:54:37,067 --> 00:54:40,835 +And let's control + drag over to this. +再拖这个, + +1300 +00:54:40,837 --> 00:54:45,539 +That is our password label, okay. +这是密码标签。 + +1301 +00:54:45,541 --> 00:54:46,840 +So we got that. +搞定。 + +1302 +00:54:46,842 --> 00:54:47,407 +Now. + +1303 +00:54:49,678 --> 00:54:54,613 +Lets say I'm going to do my viewDidLoad() here, okay, and +下边我要实现viewDidLoad()方法,我需要 + +1304 +00:54:54,615 --> 00:54:57,483 +when my view is loaded I'm going to update my UI,、 +在我的视图载入的时候更新我的UI。 + +1305 +00:54:57,485 --> 00:54:59,368 +well first of all, +啊,首先, + +1306 +00:54:59,369 --> 00:55:01,252 +of course, I'm going to do super.viewDidLoad(). +我当然需要写 super.viewDidLoad()。 + +1307 +00:55:01,255 --> 00:55:02,387 +Then I'm gonna update my UI. +然后我要更新我的UI。 + +1308 +00:55:02,389 --> 00:55:05,490 +Gonna make this wider so +把这个弄宽一点, + +1309 +00:55:05,492 --> 00:55:07,858 +this is not jumping out on you so much. +不至于经常换行。 + +1310 +00:55:07,860 --> 00:55:11,595 +I'm not gonna have a private func here to update my UI. +我这里要实现一个私有方法来更新我的UI。 + +1311 +00:55:11,597 --> 00:55:12,963 +And all I'm gonna do in my UI so +目前我要对UI做的事儿是, + +1312 +00:55:12,965 --> 00:55:16,032 +far is, I'm gonna have that password field. +我需要把密码框的 + +1313 +00:55:17,402 --> 00:55:21,203 +I'm gonna set its secure text entry to true. +文字加密输入设为真, + +1314 +00:55:21,205 --> 00:55:23,805 +Or actually, I'm gonna set it to secure. +事实上我要设成 secure 。 + +1315 +00:55:23,807 --> 00:55:26,608 +And I'm gonna have a var for that. +因为我要有一个变量。 + +1316 +00:55:26,610 --> 00:55:29,110 +So let's have a var here called secure. +这里写一个叫 secure 的变量。 + +1317 +00:55:30,046 --> 00:55:31,945 +It's gonna be boolean. +是布尔类型。 + +1318 +00:55:31,947 --> 00:55:33,580 +Actually don't even need to say that. +实际上不需要定义类型, + +1319 +00:55:33,582 --> 00:55:36,049 +Let's say it's false. +给它设为 false 。 + +1320 +00:55:36,050 --> 00:55:38,517 +It starts out false and I'm gonna do a did set here and +它初始值时false,我要加一个didSet,这样的话,每次它的 + +1321 +00:55:38,520 --> 00:55:40,787 +update my UI every time it changes. +值变化的时候就会更新UI。 + +1322 +00:55:40,789 --> 00:55:42,922 +And I'm gonna allow this to be public so +我要把它设为公共的,这样 + +1323 +00:55:42,924 --> 00:55:46,425 +people can set this boolean secure. +别人就可以设置它的布尔值。 + +1324 +00:55:46,427 --> 00:55:49,361 +And what's the problem here? +啊,这出什么问题了? + +1325 +00:55:49,363 --> 00:55:53,231 +Oh computer property must have that there's something +哦,计算属性必须。。。好像是哪 + +1326 +00:55:53,233 --> 00:55:54,231 +wrong there. +错了。 + +1327 +00:55:54,233 --> 00:55:55,499 +Well but that okay. +好了。 + +1328 +00:55:55,501 --> 00:56:00,403 +So, I'm going to let people set this secure thing externally, and +这里我允许其他人从外部设置这个值, + +1330 +00:56:00,405 --> 00:56:04,640 +then that's going to change this to say secure password, +然后可以改变这个标签里的文本为 secure password, + +1331 +00:56:04,642 --> 00:56:08,276 +and it's going to start securing it here. +这里也会变成星号。 + +1332 +00:56:08,278 --> 00:56:10,245 +So, we're going to do secure text entry. +现在我们看这个文本加密输入, + +1333 +00:56:10,247 --> 00:56:13,781 +This is just a property in UI text field that you can set, +这只是一个你可以设置的UITextField的属性, + +1334 +00:56:13,783 --> 00:56:15,550 +that just makes it so +效果就是 + +1335 +00:56:15,551 --> 00:56:17,318 +that when you type, you get the little dots instead of +当是输入的时候,你会看到星号,而不是 + +1336 +00:56:17,320 --> 00:56:19,086 +seeing what the person is typing. +明文。 + +1337 +00:56:19,088 --> 00:56:20,620 +And then I'm also going to, +下边要做的是, + +1338 +00:56:20,622 --> 00:56:25,625 +in the password label, I'm going to set its text. +密码标签,我要设置它的文本, + +1339 +00:56:25,627 --> 00:56:29,795 +If it's secure, I'm going to set it to be secured password. +如果密码是加密的,我需要让它显示 secured password。 + +1340 +00:56:29,797 --> 00:56:31,880 +And if it's not secure, +如果不是, + +1341 +00:56:31,881 --> 00:56:33,964 +I'm going to set it to just be password. +它就显示 password 就好了。 + +1342 +00:56:35,001 --> 00:56:36,000 +Okay. So + +1343 +00:56:36,001 --> 00:56:37,000 +that's this label right here. +就是这个标签。 + +1344 +00:56:37,003 --> 00:56:39,737 +I'm going to change that label depending on whether +我要根据密码是否为加密输入来改变 + +1345 +00:56:39,739 --> 00:56:40,537 +it's secure or not. +它的文本。 + +1346 +00:56:40,539 --> 00:56:43,006 +Does that make sense? +明白了吗? + +1347 +00:56:44,209 --> 00:56:45,975 +All right. So let's go ahead and +好,我们继续, + +1348 +00:56:45,977 --> 00:56:48,110 +run because now we need to run, +来运行一下, + +1349 +00:56:48,112 --> 00:56:51,846 +because we're going to be executing our code here. +看看刚才写的代码是不是可以执行。 + +1350 +00:56:53,216 --> 00:56:55,449 +Let's hope that when we click that button, +我希望当我摁这个摁钮的时候, + +1351 +00:56:55,451 --> 00:56:56,784 +our autolayout makes it so +我们的自动布局 + +1352 +00:56:56,786 --> 00:56:59,286 +that everything kind of shifts over and +会做出相应的位移改变。 + +1353 +00:56:59,288 --> 00:57:02,555 +it doesn't because we need to have a target action. +并没有,因为我们还需要一个target action。 + +1354 +00:57:03,891 --> 00:57:06,592 +Let's do target action here, we want an action method. +弄一个target action,这里需要一个方法。 + +1355 +00:57:06,594 --> 00:57:09,527 +We'll call this toggleSecurity. +我们叫它toggleSecurity。 + +1356 +00:57:10,930 --> 00:57:12,496 +Don't need an argument there,、 +不需要参数。 + +1357 +00:57:12,498 --> 00:57:14,999 +connect, here's toggleSecurity. +点connect,这就是toggleSecurity。 + +1358 +00:57:15,001 --> 00:57:18,435 +And this is secure equals not secure. +这里写 secure = !secure + +1359 +00:57:18,437 --> 00:57:21,271 +Okay, we're just gonna toggle the security on that +当我们摁这个摁钮的时候, + +1360 +00:57:21,273 --> 00:57:22,372 +when this button is pressed. +我们需要改变这个布尔值 + +1361 +00:57:22,374 --> 00:57:25,508 +[SOUND]. + +1362 +00:57:25,510 --> 00:57:27,042 +Okay. So, change security. +好,点这个摁钮。 + +1363 +00:57:27,044 --> 00:57:28,110 +Looks good. And see how it +很好,注意到 + +1364 +00:57:28,112 --> 00:57:29,644 +moved these things? +组件是如何移动的了吗? + +1365 +00:57:29,646 --> 00:57:32,146 +We had equal widths set on these, so +两个输入框是等宽的, + +1366 +00:57:32,148 --> 00:57:33,681 +when I changed security it makes these +当我摁这个摁钮的时候, + +1367 +00:57:33,683 --> 00:57:35,482 +be equal widths which moves everything else out of +两个等宽的输入框就会相应的调整尺寸, + +1368 +00:57:35,484 --> 00:57:38,518 +the way as necessary and it works either way. +横屏也没有问题。 + +1369 +00:57:40,355 --> 00:57:41,620 +Okay? Everybody cool with that? +大家都能明白吗? + +1370 +00:57:42,923 --> 00:57:45,256 +Alright, so next let's do login right here. +下边我们做登陆功能。 + +1371 +00:57:47,861 --> 00:57:49,360 +Okay, so the login is real easy. +登陆非常简单。 + +1372 +00:57:49,362 --> 00:57:53,997 +I'm just going to go over here and Ctrl+drag for +我只需要ctrl+拖拽一个 target action。 + +1373 +00:57:53,999 --> 00:57:54,864 +target action. + +1374 +00:57:55,867 --> 00:57:57,566 +We'll call this login. +给这个方法起名叫 login 。 + +1375 +00:57:57,568 --> 00:57:58,500 +It's an action. +这是一个动作。 + +1376 +00:58:00,204 --> 00:58:01,269 +Oops, sorry got that wrong. +不好意思选错了。 + +1377 +00:58:01,271 --> 00:58:02,537 +Let's us go over here. +从这开始拖, + +1378 +00:58:02,539 --> 00:58:06,907 +Ctrl+drag, an action, called login. +一个动作,起名login。 + +1379 +00:58:06,909 --> 00:58:08,575 +We don't need the sender. +不需要sender。 + +1380 +00:58:10,078 --> 00:58:10,877 +Connect. +连接。 + +1381 +00:58:10,879 --> 00:58:12,011 +Now how am I going to do login? +我要怎么实现登陆呢? + +1382 +00:58:12,013 --> 00:58:16,381 +Well, I actually have a simple user class which I +我要把一个简单的user类拖进 + +1383 +00:58:16,383 --> 00:58:17,248 +am going to drag into here. +项目里来。 + +1384 +00:58:17,250 --> 00:58:18,750 +Here it is right here. +在这。 + +1385 +00:58:18,752 --> 00:58:22,253 +User.swift, okay. +User.swift + +1386 +00:58:22,255 --> 00:58:24,955 +So I'm going drag that into, oops. +要把它拖进来,啊哦。。 + +1387 +00:58:24,957 --> 00:58:26,356 +Lets go here. +往这边挪一下。 + +1388 +00:58:26,358 --> 00:58:27,590 +Easiest way to do this. +最简单的办法, + +1389 +00:58:28,593 --> 00:58:30,693 +All right, so I'm just gonna drag User.swift in here. +把User.swift拖进来。 + +1390 +00:58:30,695 --> 00:58:34,363 +I'm gonna copy it. +需要拷贝它。 + +1391 +00:58:34,365 --> 00:58:35,163 +There we go. +好了。 + +1392 +00:58:37,100 --> 00:58:40,167 +Okay, what does the User.swift look like? +User.swift 长什么样呢? + +1393 +00:58:40,169 --> 00:58:42,319 +Looks like this. +这样的。 + +1394 +00:58:42,320 --> 00:58:44,470 +It's a model class it doesn't has nothing to do with UI. +这是一个model类,跟UI毫无关系。 + +1395 +00:58:44,473 --> 00:58:46,006 +It's just model class. +仅仅是一个model类。 + +1396 +00:58:46,008 --> 00:58:48,575 +And it just has name, company, login and password. +只有姓名,公司,用户名和密码。 + +1397 +00:58:48,577 --> 00:58:50,243 +And it has a function, +这有一个方法, + +1398 +00:58:50,245 --> 00:58:52,912 +just a class function here that you can use to log-in. +一个用来登陆的类方法。 + +1399 +00:58:52,914 --> 00:58:55,948 +And it has a little database of users like +这有一个小的用户的数据库,比如 + +1400 +00:58:55,950 --> 00:58:56,715 +Madison Bumgarner. +Madison Bumgarner。 + +1401 +00:58:57,718 --> 00:59:00,818 +Okay. So that's all that's in there. +这就是全部了。 + +1402 +00:59:01,987 --> 00:59:04,921 +Let's go use that now, in our controller. +接下来我们要在视图控制器里用它。 + +1403 +00:59:04,923 --> 00:59:07,073 +So when I log in, +当我点登陆的时候 + +1404 +00:59:07,074 --> 00:59:09,224 +I'm just going to set my set a loggedInUser so I need some +我就需要设置我的 loggedInUser, + +1405 +00:59:09,227 --> 00:59:13,462 +var which is a logged in user, that's basically my model. +所以我要写一个loggedInUser变量,就是我的model。 + +1406 +00:59:13,464 --> 00:59:17,833 +LoggedInUser, it's going to be a user. +loggedInUser,user类型。 + +1407 +00:59:17,835 --> 00:59:20,335 +And I'm going to do the didSet. +加一个didSet。 + +1408 +00:59:20,337 --> 00:59:22,970 +Actually it's going to be user optional. +应该是一个可选变量, + +1409 +00:59:22,972 --> 00:59:26,040 +And I'm going to do my didSet here, and also updateUI. +现在我要写我的didSet,也是 updateUI 。 + +1410 +00:59:26,042 --> 00:59:28,942 +So if anyone changes my logged in user externally, +如果有人从外部改变了我的 loggedInUser, + +1411 +00:59:28,944 --> 00:59:32,879 +I'll let this be public, then I can update my UI. +这个变量是公共的,然后我可以更新我的UI。 + +1412 +00:59:32,881 --> 00:59:35,715 +And finally, say loggedInUser equals User.login. +最后,我要写 loggedInUser = User.login。 + +1413 +00:59:35,717 --> 00:59:38,284 +And now I need to give it the login, +现在我要给login参数。 + +1414 +00:59:38,286 --> 00:59:39,852 +that's this field right here. +就是输入框里的文本。 + +1415 +00:59:39,854 --> 00:59:43,555 +So I'm going to say loginField.text. +所以这里写 loginField.text 。 + +1416 +00:59:44,591 --> 00:59:46,557 +But this could be an optional. +这个应该是可选的。 + +1417 +00:59:46,559 --> 00:59:47,858 +Okay? + +1418 +00:59:47,860 --> 00:59:50,494 +And the user takes a string. +这是一个字符串参数。 + +1419 +00:59:50,496 --> 00:59:53,263 +So, I'm gonna say, okay, well, if it's nil, if +所以我这里写,如果它为空, + +1420 +00:59:53,265 --> 00:59:56,466 +the log-in fill is nil, then just pass blank empty string. +如果输入框的文本为空,我就传入一个空字符串。 + +1421 +00:59:56,468 --> 00:59:57,534 +Okay? + +1422 +00:59:57,535 --> 00:59:58,601 +That's obviously not gonna log into anything, +很明显这样就不会登陆, + +1423 +00:59:58,603 --> 01:00:00,102 +but that's okay. +但是是允许的。 + +1424 +01:00:00,104 --> 01:00:03,205 +And then, same thing here; passwordField.text. +这里也是一样的,passwordField.text 。 + +1425 +01:00:04,408 --> 01:00:08,076 +And we'll have empty string there as well, kay? +也需要可选一个空字符串。 + +1426 +01:00:08,078 --> 01:00:09,977 +So, that's how we're gonna log in, and +这就是我们如何实现登陆的, + +1427 +01:00:09,979 --> 01:00:11,512 +we'll have a loggedInUser. +通过 loggedInUser 变量。 + +1428 +01:00:11,514 --> 01:00:13,714 +Once we have our updateUI here that's, +还需要在 updateUI 里加入, + +1429 +01:00:13,716 --> 01:00:16,383 +actually we'll do that a little later. +这个等一会再做。 + +1430 +01:00:16,385 --> 01:00:17,116 +Okay. + +1431 +01:00:17,118 --> 01:00:19,819 +So, that's it, okay? +就先这样。 + +1432 +01:00:19,821 --> 01:00:22,554 +So, now we got logged in, we got this whole part of our +现在我们有了登陆功能,就有了全部的 + +1433 +01:00:22,556 --> 01:00:24,990 +user interface working right here. +用户界面。 + +1434 +01:00:24,992 --> 01:00:26,424 +Now about the bottom part. +下边要做底部的部分。 + +1435 +01:00:26,426 --> 01:00:28,026 +The bottom we had an image and +底部应该有一个图片, + +1436 +01:00:28,028 --> 01:00:29,260 +we had the name of the person and +一个人名和他所在 + +1437 +01:00:29,262 --> 01:00:30,627 +the company they worked for. +的公司。 + +1438 +01:00:30,629 --> 01:00:31,828 +So let's do the image first. +我们先搞图片部分。 + +1439 +01:00:31,830 --> 01:00:35,598 +I'm just going to go over here and grab an image. +我直接到这里选一个 image。 + + +1440 +01:00:35,600 --> 01:00:36,932 +I'm going to go up here. +到这里。 + +1441 +01:00:36,934 --> 01:00:40,936 +I'm going to type image, and this is a class, +输入image,这个是一个跟 UILabel 很 + +1442 +01:00:40,938 --> 01:00:44,039 +kind of like a UI label for images, called image view. +类似的类,叫做 image view。 + +1443 +01:00:44,041 --> 01:00:46,941 +I'm going to put this in the corner down here. +把它放在左下角。 + +1444 +01:00:46,943 --> 01:00:49,844 +And we Ctrl+dragged, leading space, +ctrl+拖拽,左间距, + +1445 +01:00:49,846 --> 01:00:52,346 +Ctrl+drag, bottom space. +ctrl+拖拽,底部间距, + +1446 +01:00:52,348 --> 01:00:55,683 +Now, you'd think, oh, I just set this here, it's ready to +这时你会觉得,我已经固定了它的位置, + +1447 +01:00:55,685 --> 01:00:58,518 +go, but when I click this little thing it says, oh, +但是当我点这个黄三角的时候, + +1448 +01:00:58,520 --> 01:01:01,888 +the size and vertical position are ambiguous for imageView. +它说这个imageView的尺寸和垂直距离不确定。 + +1449 +01:01:01,890 --> 01:01:03,856 +And that's because we don't have an image in here so +因为我们还没往里面放一个图片, + +1450 +01:01:03,858 --> 01:01:05,925 +it doesn't know what size it is. +所以不知道尺寸应该有多大。 + +1451 +01:01:05,927 --> 01:01:09,061 +Okay, so let's put an image in here and +那我们就放一个图片进去, + +1452 +01:01:09,063 --> 01:01:12,497 +I got some images we can use right here. +这有一些准备好的图片。 + +1453 +01:01:12,499 --> 01:01:18,102 +Okay, so I'm going to bring this image Stanford into my project. +这里我准备把这张斯坦福的图片拖进我们的项目。 + +1455 +01:01:18,104 --> 01:01:20,404 +This is the first time we have done this and +这是我们第一次这么做, + +1456 +01:01:20,406 --> 01:01:23,106 +this is what this image.xcassests is for. +image.xcassests是管理你app + +1457 +01:01:23,108 --> 01:01:24,941 +This manages all your images in your app. +里所有图片的东西。 + +1458 +01:01:24,943 --> 01:01:27,143 +Here's my app icon, I have not set it to anything so +这是我app的图标,我还没有图标所以 + +1459 +01:01:27,145 --> 01:01:28,912 +those are all blank. +这里是空的。 + +1460 +01:01:28,913 --> 01:01:30,680 +I'm going to to drag this Stanford image in here and +把斯坦福的图片拖到这里来, + +1461 +01:01:30,682 --> 01:01:32,114 +it creates it. +新建了一个图片。 + +1462 +01:01:32,116 --> 01:01:35,083 +Now, notice this says 1x, so that means on +注意这有一个1x,意思是这个图片 + +1463 +01:01:35,085 --> 01:01:38,720 +low resolution devices this is the image it's gonna use. +是用于低分辨率的设备的。 + +1464 +01:01:38,722 --> 01:01:40,171 +And I could actually have +实际上我可以在 + +1465 +01:01:40,172 --> 01:01:41,621 +a different image on a higher resolution device. +高分辨率设备上有一个完全不同的图片。 + +1466 +01:01:41,624 --> 01:01:44,225 +Like maybe on a high resolution device I could do +比如在高分辨率设备上,我可以 + +1467 +01:01:44,227 --> 01:01:46,160 +this one with the Stanford tree. +用这个斯坦福树的图片。 + +1468 +01:01:46,162 --> 01:01:47,845 +I have more resolution, so +分辨率高了, + +1469 +01:01:47,846 --> 01:01:49,529 +I can draw this little tree a little better. +所以我可以给图片多加一棵树。 + +1470 +01:01:49,531 --> 01:01:52,999 +Okay, and on a really high res device like maybe iPhone 6 +在像iPhone 6 plus这样分辨率极高的 + +1471 +01:01:53,001 --> 01:01:56,469 +plus I could put even higher resolution image in there. +设备上我们可以用分辨率更高的图片。 + +1472 +01:01:56,471 --> 01:01:57,737 +So you can manage that. +所以我们可以很好的管理图片。 + +1473 +01:01:57,739 --> 01:01:59,938 +You can also manage other things about the images. +你还可以通过其他的方式管理图片, + +1474 +01:01:59,940 --> 01:02:01,907 +I'm not really gonna go into this, but +这里我不准备细讲,你可以通过 + +1475 +01:02:01,909 --> 01:02:04,142 +you can manage them by size class. +size classes管理它们。 + +1476 +01:02:04,144 --> 01:02:06,177 +Okay, this image appears on compact or +可以让图片在compact或者 + +1477 +01:02:06,179 --> 01:02:07,578 +regular or whatever. +regular下显示。 + +1478 +01:02:07,580 --> 01:02:11,015 +It also has vector graphics in addition to bitmaps. +还可以选择矢量图或者位图。 + +1479 +01:02:11,017 --> 01:02:12,716 +It's a really powerful system for +确实是一个非常强大的管理你app里 + +1480 +01:02:12,718 --> 01:02:14,751 +managing all of your image assets here. +所有图片的系统。 + +1481 +01:02:15,787 --> 01:02:16,952 +Now around here I'm gonna go ahead and +下边我要继续拖一些其他 + +1482 +01:02:16,954 --> 01:02:20,255 +drag some of these other images I have in here as well. +的图片进来。 + +1483 +01:02:21,758 --> 01:02:24,625 +Cuz we'll need those later. +之后会用到。 + +1484 +01:02:24,627 --> 01:02:26,894 +Okay, here's all my images I have down here. +好了,这就是我要用到的全部图片。 + +1485 +01:02:27,963 --> 01:02:29,930 +Okay, so I have an image. +我有了图片, + +1486 +01:02:29,931 --> 01:02:31,898 +So how do I set the image of this little thing in +那么我如何把图片放到我的 + +1487 +01:02:31,900 --> 01:02:34,017 +my storyboard? +storyboard里来呢? + +1488 +01:02:34,018 --> 01:02:36,135 +Well, I just inspect this image view and go here. +我只需要选中这个imageview, 选择检视器。 + +1489 +01:02:36,138 --> 01:02:38,671 +And all the images I just loaded are gonna be here. +我刚才拖进来的图片全在这了。 + +1490 +01:02:38,673 --> 01:02:41,407 +So I'm gonna pick Stanford, okay? +这里我选斯坦福。 + +1491 +01:02:41,409 --> 01:02:44,610 +So, now that I've given an image, look No problems. +我给了它一张图片,看这里,没问题了。 + +1492 +01:02:44,612 --> 01:02:46,445 +It just says the frame is wrong. +它只是说frame是错的。 + +1493 +01:02:46,447 --> 01:02:48,747 +So no problem, let's fix the frame. +这个没问题,我们只需要修复一下frame就好了。 + +1494 +01:02:48,749 --> 01:02:49,313 +Oops. +额。。 + +1495 +01:02:51,317 --> 01:02:52,783 +There. Update frames. +这里,update frames。 + +1496 +01:02:52,785 --> 01:02:55,052 +Oh, ew, that's no good. +额。这什么情况。 + +1497 +01:02:55,054 --> 01:02:56,687 +Okay. + +1498 +01:02:56,688 --> 01:02:58,321 +So we have a big image there, smashes on top of the other +图片好大,盖住了其他东西。 + +1499 +01:02:58,323 --> 01:03:00,289 +thing, so how are we gonna fix that? +我们怎么修复这个问题? + +1500 +01:03:00,291 --> 01:03:02,725 +Well, a simple way to do that would be just to +一个简单的办法就是 + +1501 +01:03:02,727 --> 01:03:06,995 +Ctrl+drag between these two and set the vertical spacing. +按住 Ctrl 拖动,设置他们的垂直间距 + +1502 +01:03:06,997 --> 01:03:07,729 +Okay? And then I +看到了吗? + +1503 +01:03:07,731 --> 01:03:09,397 +can even double click this and +我也可以双击它 + +1504 +01:03:09,399 --> 01:03:14,001 +make this vertical spacing be a standard value. +把垂直间距设置成一个标准值 + +1505 +01:03:14,003 --> 01:03:15,335 +Okay? Now, let's go ahead and +懂了吗? + +1506 +01:03:15,337 --> 01:03:17,070 +update frames. +现在我们来 Update Frames(更新框架) + +1507 +01:03:17,072 --> 01:03:18,971 +And it doesn't smash into the ones on top. +它并没有挤压到上面的元素 + +1508 +01:03:20,975 --> 01:03:21,740 +Okay? +OK? + +1509 +01:03:21,742 --> 01:03:23,441 +Simple solution there. +很简单的解决方案 + +1510 +01:03:23,443 --> 01:03:25,243 +But we still have this right here. +但是我们仍然有一个警告 + +1511 +01:03:25,245 --> 01:03:27,978 +Eight views are vertically ambiguous. +8个 view 在垂直方向会产生歧义 + +1512 +01:03:27,980 --> 01:03:29,213 +Oh my gosh! +我的天! + +1513 +01:03:29,215 --> 01:03:30,180 +What did I do? +我都做什么了? + +1514 +01:03:30,182 --> 01:03:31,314 +It looks perfect to me. +这看起来很完美啊 + +1515 +01:03:31,316 --> 01:03:32,982 +Why is it saying that? +它为什么会有这个警告呢? + +1516 +01:03:32,984 --> 01:03:35,751 +Well, when you get this kinda thing, it's time to go back to +如果有类似这种警告 + +1517 +01:03:35,753 --> 01:03:37,953 +our old friend, the document outline here, okay. +就应该到 Document Outline 去检查一下 + +1518 +01:03:37,955 --> 01:03:40,889 +Let's make some more space. +把程序最大化 + +1519 +01:03:40,891 --> 01:03:42,657 +In the document outline, +在 Document Outline 中 + +1520 +01:03:42,659 --> 01:03:45,126 +we can click on this thing in the corner here. +我们可以点击角落里的这个按钮 + +1521 +01:03:45,128 --> 01:03:46,494 +And look at all these problems we have. +可以看到出现的所有问题 + +1522 +01:03:46,496 --> 01:03:49,063 +Okay, you can see that it's all these vertical things +它们都是关于垂直布局的问题 + +1523 +01:03:49,065 --> 01:03:51,999 +here, understandably, and look what it keeps suggesting. +我们来具体看看它的建议 + +1524 +01:03:52,001 --> 01:03:52,999 +Oh, set the vertical +哦 + +1525 +01:03:53,001 --> 01:03:54,701 +compression resistance priority. +设置 Compression Resistance Priority + +1526 +01:03:54,703 --> 01:03:56,135 +Set the vertical hugging. +设置 Vertical Hugging + +1527 +01:03:56,137 --> 01:03:58,470 +What the heck is compression resistance priority and +Compression Resistance Priority 和 Vertical Hugging + +1528 +01:03:58,472 --> 01:03:59,338 +vertical hugging? +是什么? + +1529 +01:03:59,340 --> 01:04:01,673 +What the heck is that? +它们到底是什么? + +1530 +01:04:01,675 --> 01:04:03,675 +Okay? +OK? + +1531 +01:04:03,676 --> 01:04:05,676 +That has to do with this user interface is going to +它们可以使得 UI + +1532 +01:04:05,679 --> 01:04:08,779 +be expanding and compressing vertically. +在垂直方向扩张或者压缩 + +1533 +01:04:08,781 --> 01:04:11,515 +And when it does, who gets the extra space? +当扩张时,谁能获取额外空间? + +1534 +01:04:11,517 --> 01:04:16,152 +And when it compresses down, who allows themselves to +当压缩时,谁允许它们被压缩 + +1535 +01:04:16,154 --> 01:04:18,988 +be compressed, and who can't compress? +谁又不能压缩? + +1536 +01:04:18,990 --> 01:04:20,256 +Okay? +OK? + +1537 +01:04:20,257 --> 01:04:21,523 +That's what this hugging and +这就是 Hugging + +1538 +01:04:21,526 --> 01:04:23,926 +compression resistance is about. +和 Compression Resistance 的作用 + +1539 +01:04:23,928 --> 01:04:28,697 +So, here we've got, these guys are all lined up. +这些元素都已经设置好了 + +1540 +01:04:28,699 --> 01:04:30,898 +This, okay, these two guys, and +这两个元素和这个按钮 + +1541 +01:04:30,900 --> 01:04:33,334 +this button, they can not be compressed. +它们不能被压缩 + +1542 +01:04:33,336 --> 01:04:34,368 +If they get compressed, +如果它们被压缩了 + +1543 +01:04:34,370 --> 01:04:36,436 +their text is gonna get squished down. +它们上面的文字就会被挤压 + +1544 +01:04:36,438 --> 01:04:38,405 +So, we do not want them compressed. +所以我们不希望这些元素被压缩 + +1545 +01:04:38,407 --> 01:04:40,573 +But this guy, he could be compressed. +但是这个元素,它可以被压缩 + +1546 +01:04:40,575 --> 01:04:42,442 +Because it's an image, +因为它是一张图片 + +1547 +01:04:42,443 --> 01:04:44,310 +it can just redraw itself at a shorter height. +它可以以一个较短的高度重绘自己 + +1548 +01:04:44,312 --> 01:04:48,313 +So, I need to set the resistance to being compressed +所以我需要把阻力设置成可以被压缩 + +1549 +01:04:48,315 --> 01:04:50,548 +for this guy to be lower. +对于这个图片,设置地低一些 + +1550 +01:04:50,550 --> 01:04:52,917 +You've got to lower resistance to being compressed. +把可以被压缩的指数设置地低一些 + +1551 +01:04:52,919 --> 01:04:54,218 +So how do I do that? +我该怎么做呢? + +1552 +01:04:54,220 --> 01:04:55,753 +You do that in the Size Inspector. +你可以去到 Size INspector + +1553 +01:04:55,755 --> 01:04:58,655 +If you select something, you'll see down here at +如果你选中了某个元素 + +1554 +01:04:58,657 --> 01:05:00,857 +the bottom, Content Hugging Priority and +可以看到底部有 Content Hugging Priority + +1555 +01:05:00,859 --> 01:05:03,693 +Content Compression Resistance Priority. +和 Content Compression Resistance Priority + +1556 +01:05:03,695 --> 01:05:05,061 +Okay? Now, these are priorities. +这些就是 Priority + +1557 +01:05:05,063 --> 01:05:06,695 +These are just arbitrary numbers. +它们都用数字代表 + +1558 +01:05:06,697 --> 01:05:10,065 +Right now, this one is 750 in the vertical. +这个元素在垂直方向的 Priority 是 750 + +1559 +01:05:10,067 --> 01:05:12,167 +This one is also 750. +这个也是 750 + +1560 +01:05:12,169 --> 01:05:13,935 +This one is 750. +这个是 750 + +1561 +01:05:13,937 --> 01:05:15,436 +This one is 750. +这个是 750 + +1562 +01:05:15,438 --> 01:05:18,205 +They all have the same priority to be compressed. +它们的压缩系数都是一样的 + +1563 +01:05:18,207 --> 01:05:20,707 +That's why it's complaining, okay? +这就是为什么 Xcode 会有这些警告 + +1564 +01:05:20,709 --> 01:05:23,176 +Cuz it doesn't know which one to compress, +因为它不知道该压缩哪一个 + +1565 +01:05:23,178 --> 01:05:24,911 +cuz they're all the same. +因为它们的数值都是相同的 + +1566 +01:05:24,912 --> 01:05:26,645 +So we can just go back to this one and say, okay well, +现在我们选择这个 ImageView + +1567 +01:05:26,648 --> 01:05:29,882 +we're gonna lower this guy's compression resistance to 700. +我要把它的压缩系数降到 700 + +1568 +01:05:29,884 --> 01:05:32,551 +Oh, all my problems went away. +所有问题都不见了 + +1569 +01:05:33,720 --> 01:05:34,986 +Okay? Now I +看到了吗? + +1570 +01:05:34,987 --> 01:05:36,253 +have no yellow thing up here. +这里已经没有黄色的警告了 + +1571 +01:05:36,256 --> 01:05:37,488 +This resolved everything. +这一个修改解决了所有问题 + +1572 +01:05:37,490 --> 01:05:39,023 +I had eight things that were ambiguous. +曾经有8个有歧义的东西 + +1573 +01:05:39,025 --> 01:05:40,290 +Now they're all fine. +现在都没有问题了 + +1574 +01:05:40,292 --> 01:05:42,158 +Why? Because, when we compress now, +为什么呢?因为压缩的时候 + +1575 +01:05:42,160 --> 01:05:44,794 +we're gonna know that this is the guy who gets compressed, +系统已经知道该压缩哪个元素了 + +1576 +01:05:46,931 --> 01:05:47,880 +and these guys don't. +其它元素就不需要被压缩了 + +1577 +01:05:47,881 --> 01:05:48,830 +Okay? So that's what the compression +这就是有关于压缩的事情 + +1578 +01:05:48,833 --> 01:05:51,800 +thing, and we'll see hugging in in a second, and com, and +稍后我们会讲到 Hugging + +1579 +01:05:51,802 --> 01:05:54,469 +more compression a little later, okay? +和更多与 Compression 相关的 + +1580 +01:05:54,471 --> 01:05:55,403 +So that's what these are about. +这就是相关的东西 + +1581 +01:05:55,405 --> 01:05:56,237 +A lot of people are, like, +许多人会说 + +1582 +01:05:56,238 --> 01:05:57,070 +well, I don't understand these. +我不理解这些东西 + +1583 +01:05:57,073 --> 01:05:57,938 +But it's quite simple. +但是这些概念真的很简单 + +1584 +01:05:57,940 --> 01:05:59,606 +It's just how much is this view, +它只是一个与其它 view 对比的值 + +1585 +01:05:59,608 --> 01:06:02,809 +compared to other views, resisting being compressed? +数值越大代表越不希望被压缩 + +1586 +01:06:02,811 --> 01:06:04,577 +And hugging priority is, +Hugging Priority 是 + +1587 +01:06:04,579 --> 01:06:06,712 +how much does it want to be its size? +它有多希望变得更小 + +1588 +01:06:06,714 --> 01:06:09,014 +How much does it want to be small, in other words? +换句话说,你到底想不想变小 + +1589 +01:06:09,016 --> 01:06:12,484 +So, like this guy always, that button always wants to +好比这个按钮 + +1590 +01:06:12,486 --> 01:06:15,520 +be only big enough to hold the login. +它总是希望能装下 Login 这几个字符 + +1591 +01:06:15,522 --> 01:06:18,923 +It does not want to be really tall or really wide. +它不希望变得更高或更宽 + +1592 +01:06:18,925 --> 01:06:19,990 +It wants to hug. +它希望 Hug + +1593 +01:06:19,992 --> 01:06:22,226 +So, it has a high hugging priority. +所以它的 Hugging Priority 会很高 + +1594 +01:06:22,228 --> 01:06:25,762 +Other things, they might not care if they get bigger. +其他的元素,它们不在乎是否变得更大 + +1595 +01:06:25,764 --> 01:06:26,713 +Okay? +懂了吗? + +1596 +01:06:26,714 --> 01:06:27,663 +Like this thing right here, +就像它 + +1597 +01:06:27,665 --> 01:06:29,765 +it really wants to hug vertically. +它总是希望在垂直方向 Hug + +1598 +01:06:29,767 --> 01:06:32,067 +It doesn't mind if it gets stretched out horizontally. +它不在乎自己是否在横向被拉抻 + +1599 +01:06:33,203 --> 01:06:33,768 +All right? +懂了吗? + +1600 +01:06:34,971 --> 01:06:35,669 +Okay. +好的 + +1601 +01:06:35,671 --> 01:06:37,070 +So, that's that. +就是这样 + +1602 +01:06:37,072 --> 01:06:41,474 +Now, let's go to, what are we going to do next here? +下一步应该做什么呢? + +1603 +01:06:41,476 --> 01:06:44,243 +Let's add a couple more fields. +我们再添加几个 Text Field + +1604 +01:06:44,245 --> 01:06:47,012 +That name, remember we had the name and the company? +还记得 name 和 company 吗? + +1605 +01:06:47,014 --> 01:06:49,181 +Let's go add those and see what happens here. +把这些添加上去,看看会发生什么 + +1606 +01:06:50,450 --> 01:06:52,784 +So those are going to be text fields. +它们都是 Text Field + +1607 +01:06:52,786 --> 01:06:54,752 +So they're labels rather, they're right here at the top. +它们是 Label,在顶部这里 + +1608 +01:06:54,754 --> 01:06:56,387 +So I'm just going to put these out here, +所以我们要把它们放在这里 + +1609 +01:06:56,389 --> 01:06:57,654 +grab a couple of these. +拽几个 Label + +1610 +01:06:57,656 --> 01:06:59,756 +We'll make this one be name. +把这个改成 Name + +1611 +01:06:59,758 --> 01:07:02,492 +We'll make this one be the company. +把这个改成 Company + +1612 +01:07:02,494 --> 01:07:05,161 +All right, now where do I want these to be located? +我应该把它们放到哪里呢? + +1613 +01:07:05,163 --> 01:07:08,530 +Well, I kind of want this to be right here. +我想把它放到这里 + +1614 +01:07:08,532 --> 01:07:11,099 +I really want it to be kind of like right here. +就是放在这里 + +1615 +01:07:11,101 --> 01:07:13,068 +Okay, not perfectly in the middle because I +不是放在最中间 + +1616 +01:07:13,070 --> 01:07:14,502 +am gonna put company right here. +因为我想把 Company 放在这里 + +1617 +01:07:14,504 --> 01:07:17,371 +So now it would be kind of offset down. +稍稍往下面偏移一点 + +1618 +01:07:17,373 --> 01:07:19,640 +But I guess I can say all right, +我觉得这还可以 + +1619 +01:07:19,642 --> 01:07:21,174 +I'll make these two things. +我可以处理好这两个 + +1620 +01:07:21,176 --> 01:07:23,476 +I'll have their horizontal spacing and +我会让它们 Horizontal Spacing + +1621 +01:07:23,478 --> 01:07:25,445 +their Center Y's matched up. +并且把 Center Y 匹配起来 + +1622 +01:07:25,447 --> 01:07:26,579 +The centers vertically. +垂直部分的中央 + +1623 +01:07:27,915 --> 01:07:31,049 +It's kinda not exactly what I want, but it's close. +这可能有点不是我想要的,但是已经非常接近了 + +1624 +01:07:31,051 --> 01:07:34,819 +And then this guy, I will have his vertical spacing, and +对于这个 Label,我要让它 Vertical Spacing + +1625 +01:07:34,821 --> 01:07:38,089 +his left edge lined up with the name. +并且 Left Edge 和 Name 连接起来 + +1626 +01:07:38,091 --> 01:07:38,957 +Right? +对吧? + +1627 +01:07:38,958 --> 01:07:39,824 +That's pretty much what I want. +这大体上是我想要的 + +1628 +01:07:39,826 --> 01:07:41,358 +So that's not bad, but +还不错 + +1629 +01:07:41,360 --> 01:07:43,860 +really I don't want this lined up with the middle here. +但是我不想让它和中间排成一行 + +1630 +01:07:43,862 --> 01:07:46,730 +I want the bottom of this lined up with the middle. +我想让它的底部和中间排成一行 + +1631 +01:07:46,732 --> 01:07:48,064 +So how can I do that? +我怎么才能做到呢? + +1632 +01:07:48,066 --> 01:07:49,432 +Okay, pay attention now. +现在集中注意力 + +1633 +01:07:49,434 --> 01:07:51,066 +It's very important to understand, because now +理解这部分很重要 + +1634 +01:07:51,068 --> 01:07:53,568 +we're gonna start looking at how these constraints work. +因为我们要开始看看这些 Constraint 是怎么工作的 + +1635 +01:07:53,570 --> 01:07:55,470 +So I'm gonna click on this constraint, +我先点击这个 Constraint + +1636 +01:07:55,472 --> 01:07:58,773 +which causes me to inspect it here in the Inspector. +在 Inspector 中,我就可以对其进行检查 + +1637 +01:07:58,775 --> 01:07:59,941 +Okay? This is +OK? + +1638 +01:07:59,942 --> 01:08:01,108 +what a constraint looks like. +这就是一个 Constraint + +1639 +01:08:01,110 --> 01:08:04,111 +Notice the constraint has two items, a first item and +注意看这里的 Constraint 有两个 item + +1640 +01:08:04,113 --> 01:08:04,978 +a second item. +First Item 和 Second Item + +1641 +01:08:04,980 --> 01:08:10,917 +And, for each item, it says something about that item, +对于每一个 Item,都有一些关于 Item 的信息 + +1642 +01:08:10,919 --> 01:08:15,654 +like its center, or its bottom, or its top. +例如它的中间,底部或者顶部 + +1643 +01:08:15,656 --> 01:08:17,456 +Okay? If it had text, +如果上面有文字 + +1644 +01:08:17,458 --> 01:08:19,124 +it could be base lines. +Baseline 也可以选择 + +1645 +01:08:19,126 --> 01:08:20,792 +All right? +懂了吗? + +1646 +01:08:20,793 --> 01:08:22,459 +So, each of them has something like that. +每一个都有类似的东西 + +1647 +01:08:22,462 --> 01:08:23,994 +And then, it has a relationship between them, +然后,它还有一个两个 Item 之间的关系 + +1648 +01:08:23,996 --> 01:08:25,929 +which could be equal, less than or +这个关系可是相等,小于或等于 + +1649 +01:08:25,931 --> 01:08:28,298 +equal, or greater than or equal. +大于或等于 + +1650 +01:08:28,300 --> 01:08:31,901 +So right now I have the center of this Stanford thing +现在,我使得 Standford 图标的中间和 + +1651 +01:08:31,903 --> 01:08:34,270 +equal to the center of the name thing. +Name 的中间相等 + +1652 +01:08:34,272 --> 01:08:38,007 +But it's perfectly fine for me to say I want the center of +对于我来说 + +1653 +01:08:38,009 --> 01:08:41,843 +the Stanford thing to match the bottom of the name thing. +把这个图标的中间和 Name 的底部对齐也是可以的 + +1654 +01:08:41,845 --> 01:08:43,945 +Okay? +OK? + +1655 +01:08:43,947 --> 01:08:45,947 +Understand that? +懂了吗? + +1656 +01:08:45,949 --> 01:08:48,249 +And then, down here you have this constant. +在这里,有一个 Constant + +1657 +01:08:48,251 --> 01:08:49,200 +Okay? +OK? + +1658 +01:08:49,201 --> 01:08:50,150 +The constants, there's two constants. +这里有两个常数 + +1659 +01:08:50,152 --> 01:08:52,319 +One is a multiplier, and one is a constant. +一个是 Multiplier 一个是 Constant + +1660 +01:08:52,321 --> 01:08:54,488 +Okay? +OK? + +1661 +01:08:54,489 --> 01:08:56,656 +So the constant is always added onto the end, +Constant 总是加在最后 + +1662 +01:08:56,658 --> 01:08:59,459 +and the multiplier is going to multiply the things that +Multiplier 的作用是 + +1663 +01:08:59,461 --> 01:09:01,127 +are being compared. +把比较的地方相乘 + +1664 +01:09:01,129 --> 01:09:04,430 +So it really doesn't make sense too much to multiply. +其实相乘没什么意义 + +1665 +01:09:04,432 --> 01:09:06,465 +But it kind of does. +但是也有点意义 + +1666 +01:09:06,466 --> 01:09:08,499 +Watch if I do four to one ratio. +我在这里填入 4:1 + +1667 +01:09:08,502 --> 01:09:10,869 +It's putting this bottom of this +它把它底部的设置成了 + +1668 +01:09:12,005 --> 01:09:16,073 +the ratio of four to one of the size of here. +这里大小的四倍 + +1669 +01:09:16,075 --> 01:09:16,807 +Okay? And +OK? + +1670 +01:09:16,809 --> 01:09:20,276 +this can also be like, 0.5. +这里也可以填 0.5 + +1671 +01:09:20,278 --> 01:09:21,861 +Okay. +好的 + +1672 +01:09:21,862 --> 01:09:23,445 +Which is really tiny, so tiny that it's one. +0.5 有点小 + +1673 +01:09:23,448 --> 01:09:24,246 +Let's say two. +试试2 + +1674 +01:09:25,249 --> 01:09:26,781 +All right? So these can be numbers, or +这里可以填数字 + +1675 +01:09:26,783 --> 01:09:29,000 +they can be ratios. +也可以填比率 + +1676 +01:09:29,001 --> 01:09:31,218 +And then the constant is an amount added to it, like 50. +Constant 是增加的数量,例如50 + +1677 +01:09:31,221 --> 01:09:33,954 +Okay, so I've just added fixed 50 pixels. +在这里添加了50个像素 + +1678 +01:09:33,956 --> 01:09:36,473 +So it's just always added. +它总是在原有的基础上添加 + +1679 +01:09:36,474 --> 01:09:38,991 +So constant is always added, multiplier is multiplied. +Constant 总是添加,Multiplier 就是相乘 + +1680 +01:09:38,994 --> 01:09:42,495 +All constraints are this way, every single one. +每一个 Constraint 都是这样的 + +1681 +01:09:42,497 --> 01:09:43,596 +Okay? And, +OK? + +1682 +01:09:43,598 --> 01:09:46,132 +some make sense with center or top bottom. +有一些对于 Center Top Bottom 有意义 + +1683 +01:09:46,134 --> 01:09:48,667 +Some of them make sense with width and height. +而有一些是 Width 和 Height 有意义 + +1684 +01:09:48,669 --> 01:09:50,402 +And when we do one in code, +当我们在代码里实现 Constraint 的时候 + +1685 +01:09:50,403 --> 01:09:52,136 +you're gonna see we're gonna do width and height. +你会看到,我们会处理 Width 和 Height + +1686 +01:09:52,139 --> 01:09:55,473 +You know, but they're still in the same form. +但是它们的形式都是相同的 + +1687 +01:09:55,475 --> 01:09:57,142 +They always have the same form. +他们总是有相同的形式 + +1688 +01:09:57,143 --> 01:09:58,810 +That's why there's only one constructor for +这就是为什么在代码中 + +1689 +01:09:58,812 --> 01:10:00,678 +these layout constraint in the code. +这个 Layout Constraint 只有一个 Constructor(构造器) + +1690 +01:10:00,680 --> 01:10:02,980 +Okay, and it just takes all of these things. +它把所有这些当做参数 + +1691 +01:10:02,982 --> 01:10:06,149 +The constant, the multiplier the first item. +Constant,Multiplier,First Item + +1692 +01:10:06,151 --> 01:10:07,250 +Which thing on the first item? +哪个元素是 First Item + +1693 +01:10:07,252 --> 01:10:08,117 +The relationship. +Relationship + +1694 +01:10:08,119 --> 01:10:10,086 +And the second item, the second, and +Second Item + +1695 +01:10:10,088 --> 01:10:12,287 +the thing on that, okay? +和 Second Item 上面的元素 + +1696 +01:10:12,289 --> 01:10:13,388 +So we're gonna see that. +我们以后会看到的 + +1697 +01:10:13,390 --> 01:10:15,256 +So, lets see if this worked. +看看我们所做的有没有效果 + +1698 +01:10:15,258 --> 01:10:18,326 +Just for fun let's go ahead and go back to our code, and +回到代码里 + +1699 +01:10:18,328 --> 01:10:19,794 +why are these things up. +把这些东西连接起来 + +1700 +01:10:21,797 --> 01:10:24,097 +Okay, so Ctrl+Drag. +按住 Ctrl 拖动鼠标 + +1701 +01:10:24,099 --> 01:10:26,466 +That's alright, from the name. +从 Name + +1702 +01:10:26,468 --> 01:10:29,569 +oops, Undo, okay. +搞错了 + +1703 +01:10:29,571 --> 01:10:31,437 +Ctrl+Drag from the name. +从 Name + +1704 +01:10:31,439 --> 01:10:34,239 +That is our Name Label and we'll go and +起名为 nameLabel + +1705 +01:10:34,241 --> 01:10:36,875 +Ctrl+Drag from the company here. +同样方法 + +1706 +01:10:36,877 --> 01:10:39,611 +That is our Company Label. +把 Company 设置好 + +1707 +01:10:39,613 --> 01:10:40,311 +All right. +好的 + +1708 +01:10:40,313 --> 01:10:41,812 +And in our Update UI, +在 UpdateUI 里面 + +1709 +01:10:41,814 --> 01:10:45,349 +sorry about the width here, let's do this. +这有点挡住了,把它收回去点 + +1710 +01:10:45,351 --> 01:10:49,786 +In our Update UI here, we are going to update those. +在 UpdateUI 里面,我们来更新这两个 Label + +1711 +01:10:49,788 --> 01:10:54,824 +So we'll just say that our Name Label that text, +把 nameLabel 的 text + +1712 +01:10:54,826 --> 01:10:58,360 +equals our logged in user. +设置为 loggedInUser? + +1713 +01:10:58,362 --> 01:11:00,062 +And if our logged in user is nil, +如果 loggedInUser 是 nil + +1714 +01:11:00,064 --> 01:11:02,530 +then we'll just set the text to be nil as well. +把 text 设置为 nil 就可以了 + +1715 +01:11:02,532 --> 01:11:04,799 +So I'm using optional chaining there. +所以在这里我使用了可选链 + +1716 +01:11:04,801 --> 01:11:06,901 +But that's the name of the person. +这就是登陆者的名字 + +1717 +01:11:06,903 --> 01:11:10,871 +And then, our company label's text equals the logged in +然后,Company Label 的 text + +1718 +01:11:10,873 --> 01:11:12,205 +user's company. +等于 loggedInUser?.company + +1719 +01:11:13,708 --> 01:11:14,774 +Okay? Let's also set +OK? + +1720 +01:11:14,776 --> 01:11:16,308 +that image view right there. +在这里也把 imageView 给设置好 + +1721 +01:11:16,310 --> 01:11:16,875 +Okay? +OK? + +1722 +01:11:18,779 --> 01:11:20,545 +So we'll Ctrl+Drag from the image view +按住 Ctrl 拖动 imageView + +1723 +01:11:20,547 --> 01:11:22,113 +that's just like any other thing. +就像之前做的一样 + +1724 +01:11:22,115 --> 01:11:24,715 +I can Ctrl+Drag this thing over, so let's do that. +我可以拖动它 + +1725 +01:11:24,717 --> 01:11:27,217 +I'm gonna call it the Image View. +把它起名为 imageView + +1726 +01:11:27,219 --> 01:11:29,970 +Okay. And +OK. + +1727 +01:11:29,971 --> 01:11:32,722 +we'll set that as well in our Update UI. +我们也要在 UpdateUI 里更新它 + +1728 +01:11:32,724 --> 01:11:38,227 +Here by saying imageview.image equals the logged in +把这里的 imageView.image 设置为 + +1729 +01:11:38,229 --> 01:11:40,595 +user's image. +登陆用户的 image + +1730 +01:11:40,597 --> 01:11:41,863 +Unfortunately, this is not gonna work. +但是,这不会起作用 + +1731 +01:11:41,865 --> 01:11:44,132 +And why is this not gonna work? +它为什么不起作用呢? + +1732 +01:11:44,134 --> 01:11:47,001 +Because Image is not defined in User. +因为 User 中没有定义 image + +1733 +01:11:47,003 --> 01:11:48,168 +If we go look at User. +如果我们查看一下 User 类 + +1734 +01:11:52,407 --> 01:11:56,442 +Okay, user can't have an image because it's a model. +User 不能拥有 image,因为它是 model + +1735 +01:11:56,444 --> 01:11:57,810 +It doesn't have any UI kit. +它没有导入 UIKit + +1736 +01:11:57,812 --> 01:11:58,777 +There's no UI. +这里没有 UI + +1737 +01:11:58,779 --> 01:12:00,178 +And UI image is a UI thing. +UIImage 是一个 UI 元素 + +1738 +01:12:00,180 --> 01:12:01,012 +Okay. +OK. + +1739 +01:12:01,014 --> 01:12:02,646 +So we can't even model. +所以 model 里不能有它 + +1740 +01:12:02,648 --> 01:12:05,683 +But that doesn't stop us from having an image +但是这也不能组织我们拥有 image 这个 property + +1741 +01:12:05,685 --> 01:12:11,855 +property MUser, because we can use extensions. +因为我们可以使用 extension + +1742 +01:12:11,857 --> 01:12:13,840 +Okay. +OK + +1743 +01:12:13,841 --> 01:12:15,824 +So here I'm gonna make an extension to User. +所以这里,我给 User 添加一个 extension + +1744 +01:12:16,761 --> 01:12:19,128 +Okay, it's gonna be a var called image. +一个叫 image 的变量 + +1745 +01:12:19,130 --> 01:12:23,565 +It's gonna be a UIImage, UIImage, but I'm adding this +类型是 UIImage + +1746 +01:12:23,567 --> 01:12:27,135 +in my controller so that's fine because, it's extending +我把它放到 controller 里 + +1747 +01:12:27,137 --> 01:12:29,337 +my model but it's not actually touching my model. +它扩展了我的 model,但是没有接触我的 model + +1748 +01:12:29,339 --> 01:12:32,106 +My model is still purely fine. +model 还是没问题的 + +1749 +01:12:32,108 --> 01:12:36,343 +And to do this, I'm just gonna return basically a UIImage, +为了实现功能,在这里返回一个 UIImage + +1750 +01:12:36,345 --> 01:12:39,479 +that is named the user's login. +name 是 User 中的 login + +1751 +01:12:39,481 --> 01:12:42,515 +Now notice, I can refer to login here because this +看到了吗,我可以获取到 login + +1752 +01:12:42,517 --> 01:12:43,215 +is user. +因为我们在 User 类中 + +1753 +01:12:43,217 --> 01:12:44,683 +This is on user, so +这是对 User 的扩展 + +1754 +01:12:44,685 --> 01:12:49,220 +login is a user thing, so I can refer to that, 'kay. +所以我可以获取到 + +1755 +01:12:49,222 --> 01:12:52,656 +But this is saying no, because this might return nil. +但是这有一个错误,因为它也许会返回 nil + +1756 +01:12:52,658 --> 01:12:54,324 +So I'm gonna say. +我会说 + +1757 +01:12:54,326 --> 01:12:56,426 +If I can get let the image equal that,. +如果我能获取到 image + +1758 +01:13:01,399 --> 01:13:03,833 +Then, I will return it. +我就返回它 + +1759 +01:13:05,202 --> 01:13:12,107 +Otherwise, I will return a UI image of some unknown user. +否则我就返回一个未知用户的 UIImage + +1760 +01:13:12,109 --> 01:13:13,574 +I have. A thing there I +在这里 + +1761 +01:13:13,576 --> 01:13:15,042 +put in there called, unknown user. +我输入 unknown_user + +1762 +01:13:15,044 --> 01:13:17,978 +That's just an image that I put there. +这是一张图片的名字 + +1763 +01:13:20,449 --> 01:13:23,316 +And this, I'm gonna make this optional so +我把它变成 optional + +1764 +01:13:23,318 --> 01:13:25,851 +the whole thing can return optional. +所以内部就可以返回 optional + +1765 +01:13:25,853 --> 01:13:27,353 +Okay? +OK? + +1766 +01:13:27,355 --> 01:13:30,355 +So now, this is implemented. +现在,这个已经实现完毕了 + +1767 +01:13:30,357 --> 01:13:31,957 +This might return nill but +这个也许会返回 nil + +1768 +01:13:31,958 --> 01:13:33,558 +that's okay, because this is allowed to be nill. +但是这也没问题,因为这个允许是 nil 的 + +1769 +01:13:33,560 --> 01:13:34,492 +And all is well. +万事俱备 + +1770 +01:13:34,494 --> 01:13:35,977 +So let's go take a look, +我们运行程序来看一下 + +1771 +01:13:35,978 --> 01:13:37,461 +now we should have our full UI functioning here. +所有 UI 的功能都已经实现了 + +1772 +01:13:38,564 --> 01:13:39,896 +Let's go on our iPhone here. +用 iPhone 运行一下 + +1773 +01:13:39,898 --> 01:13:47,437 +Oh, I know, right here, +哦,我知道了 + +1774 +01:13:47,439 --> 01:13:53,208 +okay, run, okay, here it is, so let's log in as madbum. +运行一下,我们用 madbum 登陆 + +1775 +01:13:54,611 --> 01:13:56,077 +And log in, and there we go. +登陆完毕 + +1776 +01:13:56,079 --> 01:13:57,612 +Oh, that looks terrible. +这看起来太糟糕了 + +1777 +01:13:59,082 --> 01:14:00,447 +What's going on here? +到底发生了什么? + +1778 +01:14:00,449 --> 01:14:04,718 +Look at how it stretched this thing out, okay? +这个东西被拉抻开了 + +1779 +01:14:04,720 --> 01:14:06,886 +I want this hugging. +我希望它是 Hug 的 + +1780 +01:14:06,888 --> 01:14:07,586 +I don't like this. +我不希望这样 + +1781 +01:14:07,588 --> 01:14:09,221 +This is not hugging, okay? +它没有 Hug + +1782 +01:14:09,223 --> 01:14:10,655 +But there's another problem too, +这里也有个问题 + +1783 +01:14:10,657 --> 01:14:12,374 +we'll look at this in a second. +我们稍后再看 + +1784 +01:14:12,375 --> 01:14:14,092 +But let's look at it this way, though. +我们旋转一下屏幕 + +1785 +01:14:14,094 --> 01:14:15,426 +Same thing, it's no good. +同样地,效果很不好 + +1786 +01:14:16,429 --> 01:14:17,795 +Okay? So, we're getting close. +不过已经很接近了 + +1787 +01:14:17,797 --> 01:14:19,697 +Why is this happening? +为什么会这样呢? + +1788 +01:14:19,698 --> 01:14:21,598 +Well, the reason that this is happening is because we have +发生这件事的原因是 + +1789 +01:14:21,600 --> 01:14:24,834 +all these things attached to each other, and, so +我们把这些 view 都相互依附在一起 + +1790 +01:14:24,836 --> 01:14:27,103 +we can fix this in two ways, actually. +其实我们可以通过两种方式修复 + +1791 +01:14:27,105 --> 01:14:32,408 +One way is I can go here, and change this guy, +一种是,去到这里,改变它 + +1792 +01:14:32,410 --> 01:14:35,310 +who's hugging priority can just be less so +把它的 Hugging Priority 调低 + +1793 +01:14:35,312 --> 01:14:37,712 +that these guys will be more likely to hug. +所以其他这些就更可能 Hug + +1794 +01:14:37,714 --> 01:14:38,697 +Okay. +OK. + +1795 +01:14:38,698 --> 01:14:39,681 +Down on their text. +在它们的 text 下面 + +1796 +01:14:39,683 --> 01:14:43,084 +So I'm gonna set this guy's vertical hugging priority +所以我要设置它的 Vertical Hugging Priority + +1797 +01:14:43,086 --> 01:14:44,184 +down to let's say 200. +把它调到 200 + +1798 +01:14:44,186 --> 01:14:47,087 +The rest of these are at say, 250. +剩下的这些还是 250 + +1799 +01:14:47,089 --> 01:14:49,122 +Okay, these are all at 250. +它们都是 250 + +1800 +01:14:49,124 --> 01:14:51,024 +I'm gonna set mine down to 200. +我把它调低到 200 + +1801 +01:14:51,026 --> 01:14:51,824 +Okay. +好的。 + +1802 +01:14:52,793 --> 01:14:56,361 +So we run, let's log in as mad mom again. +我们再次以madbum登陆。 + +1803 +01:14:59,833 --> 01:15:02,367 +There we go, okay, so it didn't squish this, +走起,很好,这个没被压扁了, + +1804 +01:15:02,369 --> 01:15:04,802 +although wow, now it's stretched this thing way up. +但是,下面的图片被拉伸了。 + +1805 +01:15:04,804 --> 01:15:07,204 +I don't really like that either. +我不希望这样。 + +1806 +01:15:07,206 --> 01:15:07,904 +Okay? +明白吗? + +1807 +01:15:07,906 --> 01:15:09,406 +So why is that happening? +那这是为什么呢? + +1808 +01:15:09,408 --> 01:15:12,675 +Well that's happening because of this constraint right here. +这是因为这个约束。 + +1809 +01:15:12,677 --> 01:15:14,677 +This constraint says, +这个约束说, + +1810 +01:15:14,678 --> 01:15:16,678 +that the distance from the top of the image to the bottom of +从图片顶部到登陆按钮底部的距离 + +1811 +01:15:16,681 --> 01:15:18,914 +here has to equal. +必须相等于。 + +1812 +01:15:18,916 --> 01:15:20,215 +The standard value equal. +标准值。 + +1813 +01:15:20,217 --> 01:15:22,267 +I don't want equal. +但我不想等于一个确定的值。 + +1814 +01:15:22,268 --> 01:15:24,318 +I'm gonna say, if it's greater than or equal, that's fine. +我只需要,大于或等于就可以了。 + +1815 +01:15:25,722 --> 01:15:27,288 +Okay? So this is where you +明白吗?这种情况下 + +1816 +01:15:27,289 --> 01:15:28,855 +would use a greater than or equals, because this spacing, +就可以用到大于或等于选项,因为这个距离, + +1817 +01:15:28,858 --> 01:15:31,091 +I just want to make sure it doesn't smash into it. +我只需要确保图片不和按钮重叠就行。 + +1818 +01:15:31,093 --> 01:15:32,625 +But if it's smaller, that's okay. +所以图片小一点也是没问题的。 + +1819 +01:15:32,627 --> 01:15:33,993 +I don't mind that. +我并不在意。 + +1820 +01:15:35,963 --> 01:15:36,962 +All right. So now, let's try madbum. +好的,我们再次登陆。 + +1821 +01:15:36,964 --> 01:15:37,529 +Madbum. +输入madbum + +1822 +01:15:41,501 --> 01:15:43,534 +Okay, perfect, so now it's doing that, and +很好,完美解决,看这里,而且 + +1823 +01:15:43,536 --> 01:15:46,536 +over here, oops, over this way, working fine. +在横屏模式下,同样没问题。 + +1824 +01:15:47,839 --> 01:15:48,971 +Okay? +看到没? + +1825 +01:15:48,973 --> 01:15:50,957 +So we're getting good, +事情很顺利, + +1826 +01:15:50,958 --> 01:15:52,942 +there's only really two things left that are problems in +整个程序就只剩下 + +1827 +01:15:52,944 --> 01:15:55,027 +this whole thing, +两个问题了, + +1828 +01:15:55,028 --> 01:15:57,111 +one is this guy getting smashed off, gotta fix that. +一个是这两个文本的内容没有显示完整,我们来修复它。 + +1829 +01:15:57,114 --> 01:15:58,447 +And we fix that. +来解决这个问题。 + +1830 +01:15:58,449 --> 01:15:59,614 +You already know how to fix that. +你应该知道如何解决这个问题了 + +1831 +01:15:59,616 --> 01:16:01,549 +I'm just gonna take this, and make it so +只需要选中它,然后 + +1832 +01:16:01,551 --> 01:16:04,452 +that this thing hooks to this edge. +和父视图的边界关联起来。 + +1833 +01:16:04,454 --> 01:16:08,088 +And same thing with this thing hooking to this guy's edge. +这个标签也是一样。 + +1834 +01:16:08,090 --> 01:16:11,224 +And again, I don't want them to be anything but +同样,我需要把他们的值设置为 + +1835 +01:16:11,226 --> 01:16:12,392 +a standard value here. +标准值。 + +1836 +01:16:12,394 --> 01:16:14,193 +So I'm gonna have this one be zero. +选这个或者0. + +1837 +01:16:16,397 --> 01:16:17,963 +And same thing with this one right here. +这个也是一样。 + +1838 +01:16:17,965 --> 01:16:19,264 +I don't like this. +我不想要这个。 + +1839 +01:16:20,633 --> 01:16:21,565 +Nonstandard values. +非标准值。 + +1840 +01:16:21,567 --> 01:16:23,767 +In fact, I've got a couple of them +事实上,前面还有很多 + +1841 +01:16:23,768 --> 01:16:25,968 +left over from previous things here, so let's fix these. +这样的问题需要修复。 + +1842 +01:16:25,971 --> 01:16:29,506 +Standard Values. +标准值。 + +1843 +01:16:29,508 --> 01:16:30,506 +Okay? +明白吗? + +1844 +01:16:30,508 --> 01:16:31,574 +All right. +好的。 + +1845 +01:16:31,576 --> 01:16:32,641 +Everything look good there? +现在看起来都正常了。 + +1846 +01:16:32,643 --> 01:16:33,408 +No magic numbers? +没有 magic numbers吧? + +1847 +01:16:33,410 --> 01:16:34,275 +Oh, here's the magic number. +oh, 这里还有一个。 + +1848 +01:16:34,277 --> 01:16:35,009 +Let's get rid of that. +改掉它。 + +1849 +01:16:37,180 --> 01:16:37,745 +Standard Value. +标准值。 + +1850 +01:16:39,148 --> 01:16:41,548 +That it, okay, got all those. +好的,全部修改了。 + +1851 +01:16:41,550 --> 01:16:43,216 +Everything looks fine, it moved. +看起来很不错。 + +1852 +01:16:43,218 --> 01:16:45,317 +So now, we should be all fixed and ready to go. +现在,应该都修改正确了,可以测试了。 + +1853 +01:16:45,319 --> 01:16:50,022 +Alright, madbum again. +好的,再次登录。 + +1854 +01:16:50,024 --> 01:16:52,791 +Secure this time, don't want you to know madbum's password. +换成安全状态,不想让你看到密码。 + +1855 +01:16:53,993 --> 01:16:56,761 +Okay, looking good, oh, still didn't quite work. +好的,看起来很好,但是,好像还是有问题。 + +1856 +01:16:56,763 --> 01:17:00,697 +We got the name but why did this thing. +姓名标签很正常,但是下面这个。 + +1857 +01:17:00,699 --> 01:17:01,798 +Not do that. +不对。 + +1858 +01:17:01,800 --> 01:17:02,865 +What's going on there? +这是怎么回事? + +1859 +01:17:02,867 --> 01:17:04,266 +Same circle Giants got put up. +同样的问题有发生了。 + +1860 +01:17:04,268 --> 01:17:08,270 +The reason there is this guy's hogging priority is too +原因是这个标签的hugging 优先级别太 + +1861 +01:17:08,272 --> 01:17:10,638 +low, okay. +低了。 + +1862 +01:17:10,640 --> 01:17:12,373 +I'm sorry, his compression resistance, I mean, +很抱歉,是compression resistance值才对, + +1863 +01:17:12,375 --> 01:17:14,075 +is too low. +太低了。 + +1864 +01:17:14,076 --> 01:17:15,776 +He's allowing himself to be compressed. +它允许自己被挤压。 + +1865 +01:17:15,778 --> 01:17:17,111 +Okay. +好的。 + +1866 +01:17:17,112 --> 01:17:18,445 +So here, we need to have the horizontal compression +这里,我们需要提高它的水平 + +1867 +01:17:18,447 --> 01:17:20,247 +resistance of this guy be higher. +resistance值。 + +1868 +01:17:20,249 --> 01:17:21,381 +So I'm gonna set it to 800. +就设置为800. + +1869 +01:17:21,383 --> 01:17:22,882 +Doesn't really matter what we set, +具体设置成多大并不是很重要, + +1870 +01:17:22,884 --> 01:17:24,216 +as long as it's higher than. +只要大于 + +1871 +01:17:24,218 --> 01:17:27,119 +The other things, like this one, which is 750, so +其他视图的值,比如这个,它是750, + +1872 +01:17:27,121 --> 01:17:31,990 +let's set this guy's also, oops, it's compression to 800. +把这个也设置为800. + +1873 +01:17:31,992 --> 01:17:35,926 +Okay, so that prevents them from being compressed down so +这样一来,就可以避免他们被挤压 + +1874 +01:17:35,928 --> 01:17:37,528 +that their text won't show. + 而无法完整显示文本了。 + +1875 +01:17:37,530 --> 01:17:40,130 +Okay. +好的。 + +1876 +01:17:40,132 --> 01:17:46,235 +Oh, well, that's not so good. +oh,情况不妙。 + +1877 +01:17:46,237 --> 01:17:49,138 +Okay, so we fixed one problem, we introduces another one. +看,我们解决了一个问题,又来了另一个。 + +1878 +01:17:49,140 --> 01:17:50,807 +So we certainly- +所以实际上 + +1879 +01:17:50,808 --> 01:17:52,475 +There are two problems with this, +这里有两个问题, + +1880 +01:17:52,476 --> 01:17:54,143 +actually, number one, this is not the right aspect ratio. +首先,图片的宽高比例不对。 + +1881 +01:17:54,145 --> 01:17:55,610 +This is not what the Giants logo looks like, +Giants logo可不是这样的, + +1882 +01:17:55,612 --> 01:17:57,245 +you can barely even tell it's the Giants. +你甚至都认不出来。 + +1883 +01:17:57,247 --> 01:18:00,481 +And number two is, it's way too small, okay? +问题二,太小了,不是吗? + +1884 +01:18:00,483 --> 01:18:03,784 +Look at all this empty space I've got up here, okay, so +看上面的空白空间。 + +1885 +01:18:03,786 --> 01:18:05,085 +we've got two things to fix here. +所以还有两个问题解决后 + +1886 +01:18:05,087 --> 01:18:06,787 +And then we're done. +就完成了。 + +1887 +01:18:06,789 --> 01:18:09,889 +One is make this aspect ratio be enforced, and +一个是修正图片的宽高比问题, + +1888 +01:18:09,891 --> 01:18:13,026 +another one is put this in the right space. +另一个是将它放到正确的位置。 + +1889 +01:18:13,028 --> 01:18:16,595 +In this size class which is I got a lot of vertical space. +在这个size class 我们有充足的垂直空间。 + +1890 +01:18:16,597 --> 01:18:20,198 +So, lets go ahead and fix the aspect ratio one first. +我们先修复图宽高比的问题。 + +1891 +01:18:20,200 --> 01:18:22,867 +You know that one. +你可能会想。 + +1892 +01:18:22,869 --> 01:18:25,236 +We'd like to be able to just go here and +我们可以到这里 + +1893 +01:18:25,238 --> 01:18:27,805 +add some kind of constraint, but we can't actually do that. +加一些约束就好了,但事实上,不可以。 + +1894 +01:18:27,807 --> 01:18:30,708 +And that's because if you remember, when we look +因为,不知道你是否记得 + +1895 +01:18:30,710 --> 01:18:35,845 +at a constraint, its constant and multiplier are constants. +一个约束的的constant和multiplier值是常量。 + +1896 +01:18:35,847 --> 01:18:38,348 +And every time we get a new image, +每次图片更新的时候, + +1897 +01:18:38,350 --> 01:18:40,216 +it has a different aspect ratio. +它的宽高比不同。 + +1898 +01:18:41,318 --> 01:18:42,718 +Okay? +明白吗? + +1899 +01:18:42,719 --> 01:18:44,119 +So, unless we wanted to force everyone's image to +除非我们限制每个图片 + +1900 +01:18:44,121 --> 01:18:46,788 +be the same aspect ratio, we need code to +的宽高比相同,不然的话,我们需要 + +1901 +01:18:46,790 --> 01:18:49,791 +do this because we have to calculate that aspect ratio. +在代码中来计算这个宽高比才行。 + +1902 +01:18:49,793 --> 01:18:50,858 +So, this is what that looks like. +所以,仔细看好了。 + +1903 +01:18:50,860 --> 01:18:53,027 +I'm gonna go through this pretty fast because +我会以非常快的速度演示因为 + +1904 +01:18:53,029 --> 01:18:56,730 +we're over time already, so you can watch it here. +时间不多了,看这里。 + +1905 +01:18:56,732 --> 01:18:58,765 +So, I'm gonna do this like this. +我会这样做。 + +1906 +01:18:58,767 --> 01:19:00,400 +I'm gonna create a new var, +新建一个变量, + +1907 +01:19:00,402 --> 01:19:04,503 +which is an aspectRatioConstraint(), and +命名为aspectRatioConstraint + +1908 +01:19:04,505 --> 01:19:07,706 +it's going to be of type NSLayoutConstraint. +类型为NSLayoutConstraint + +1909 +01:19:07,708 --> 01:19:10,575 +This is the type of those constraints. +这是所有约束的类型。 + +1910 +01:19:10,577 --> 01:19:13,845 +All those constraints in there it is of this type, okay. +所有的约束都是这个类型,是的。 + +1911 +01:19:13,847 --> 01:19:17,448 +Now, I'm gonna create another var called image, UIImage. +现在创建另一个变量,叫做image + +1912 +01:19:18,717 --> 01:19:21,851 +And it can be optional, it's fine. +可以为空,所以设置为optional类型。 + +1913 +01:19:21,853 --> 01:19:24,253 +And it's just gonna be a computed property, +这将使一个computed property, + +1914 +01:19:24,255 --> 01:19:28,424 +where I'm gonna get and set my image views properties. +我会在其中设置和获取我的image view视图。 + +1915 +01:19:28,426 --> 01:19:31,126 +So I'm really just gonna return imageView.image, +我只需要返回 imageView.image, + +1916 +01:19:31,128 --> 01:19:32,327 +I'm gonna set her. +设置她。 + +1917 +01:19:32,329 --> 01:19:33,594 +I'm just going to set it. +设置好就可以了。 + +1918 +01:19:33,596 --> 01:19:35,896 +Let's go to wide here. +这边加宽一点。 + +1919 +01:19:35,898 --> 01:19:37,965 +Wide mode. +更宽一点。 + +1920 +01:19:41,203 --> 01:19:42,435 +Okay, in the center, +好的,在setter方法里面, + +1921 +01:19:42,437 --> 01:19:45,238 +I'm just gonna set it imageView.image = image. +我只需要设置imageView.image = image. + +1922 +01:19:45,240 --> 01:19:47,873 +Now, why am I creating this little computer property? +那么,我为什么创建这个computed property? + +1923 +01:19:47,875 --> 01:19:51,443 +Because every time I set my imageView's image I +因为每当我设置imageView的image的时候 + +1924 +01:19:51,445 --> 01:19:55,547 +want to update this aspect ration constraint, okay. +我需要更新图片的宽高比例约束,明白? + +1925 +01:19:55,549 --> 01:19:58,082 +So, if I can let this constrained view, +所以,如果imageView不为空 + +1926 +01:19:58,084 --> 01:20:00,785 +this is the view I'm trying to constrain, +就是我想添加约束的视图, + +1927 +01:20:00,787 --> 01:20:02,353 +which is the image view. +也就是imageView。 + +1928 +01:20:02,355 --> 01:20:04,054 +If I can let it equal something. +如果我可以let出来。 + +1929 +01:20:04,056 --> 01:20:07,590 +In other words it's not nill, okay? +换句话说就是不为nil,明白吗? + +1930 +01:20:07,592 --> 01:20:12,161 +And if I can let the new image equal new value, +然后如果newValue不为空, + +1931 +01:20:12,163 --> 01:20:14,563 +because this is, we're setting an image here, so +就是我们设置的新图片, + +1932 +01:20:14,565 --> 01:20:18,800 +if I'm able to set an image in this constraint, screen view. +我们就可以为他添加约束了。 + +1933 +01:20:18,802 --> 01:20:20,168 +Then I'm gonna create this +这样我只需要让 + +1934 +01:20:20,170 --> 01:20:22,436 +aspectRatioConstraint equal to something. +aspectRatioConstraint等于某个值就可以了。 + +1935 +01:20:22,438 --> 01:20:24,605 +If I can't set the new image, then I'm gonna +如果image为空, + +1936 +01:20:24,607 --> 01:20:29,409 +set the aspectRatioContraint equal to nil, 'kay. +我会讲aspectRatioConstraint设置为nil,明白吗? + +1937 +01:20:29,411 --> 01:20:31,644 +So someone set my image to nil. +如果别人将图片设置为nil。 + +1938 +01:20:31,646 --> 01:20:32,945 +I can't have a constraint. +我就无法添加约束了。 + +1939 +01:20:32,947 --> 01:20:35,647 +The aspect ration of nil image is nothing, so I don't, +空图片并没有宽高比,所以不必, + +1940 +01:20:35,649 --> 01:20:37,849 +can't even have a constraint there. +设置约束。 + +1941 +01:20:37,851 --> 01:20:39,684 +So how do I create this constraint in the case I +当我们获取到图片的时候 + +1942 +01:20:39,686 --> 01:20:41,419 +do have an image for imageView? +怎样创建这个约束呢? + +1943 +01:20:41,421 --> 01:20:43,220 +I just do it with a constructor, +只需要调用构造器即可, + +1944 +01:20:43,222 --> 01:20:45,556 +NSLayoutConstraint, okay? +NSLayoutConstraint(),明白吗? + +1945 +01:20:45,558 --> 01:20:47,024 +Here's what NSLayoutConstraint's +NSLayoutConstraint()构造器 + +1946 +01:20:47,026 --> 01:20:48,058 +constructor looks like. +就是这样子的。 + +1947 +01:20:48,060 --> 01:20:49,592 +It's got all these things here, +它需要很多参数, + +1948 +01:20:49,594 --> 01:20:52,061 +let's go through them one at a time, and +我们一个一个来, + +1949 +01:20:52,063 --> 01:20:54,863 +it looks just like that inspector I showed you. +就像inspector一样。 + +1950 +01:20:54,865 --> 01:20:59,067 +So one is the thing we're trying to constrain. +首先是你需要添加约束的视图。 + +1951 +01:20:59,069 --> 01:21:03,404 +Which is our image view, what attribute of that, it's width, +也就是imageView,被约束的属性是width, + +1952 +01:21:04,440 --> 01:21:08,742 +how do we want to relate it to our constants and multipliers? +和constants和multipliers的关系是怎样的呢? + +1953 +01:21:08,744 --> 01:21:10,343 +Well, we're going to do aspect ratio, so +我们想做宽高比约束,所以 + +1954 +01:21:10,345 --> 01:21:12,979 +we want the width multiplied times the height. +我们需要width=height*x + +1955 +01:21:12,981 --> 01:21:17,616 +So the width is going to equal the height times the aspect +所以我们让 宽 等于 高 乘以 宽高比 + +1956 +01:21:17,618 --> 01:21:19,551 +ratio, so this is going to be equal. +所以我们选择等号。 + +1957 +01:21:20,587 --> 01:21:22,053 +And what are we relating it to? +然后相对于哪个视图呢? + +1958 +01:21:22,055 --> 01:21:24,121 +We could relate it to another thing, but +我们可以选择其他视图,但是 + +1959 +01:21:24,123 --> 01:21:27,057 +this is the imageviews own aspect ratio, so it's relating +这里是imageView自己的宽高比,所以相对于 + +1960 +01:21:27,059 --> 01:21:31,661 +it to itself, okay, and what attribute is it relating to? +它自己,好,那相对于哪个属性呢? + +1961 +01:21:31,663 --> 01:21:35,365 +It's height, and what is the multiplier going to be? +是height,那么乘以哪个数呢? + +1962 +01:21:35,367 --> 01:21:39,168 +It's going to be that new image aspect ratio. +乘以图片的aspectRatio属性。 + +1963 +01:21:40,404 --> 01:21:42,504 +Okay? And then this constant gets +明白吗?然后是增加的常量 + +1964 +01:21:42,506 --> 01:21:43,438 +added in. +数值。 + +1965 +01:21:43,440 --> 01:21:44,805 +We don't want to add anything else in. +我们不需要增加多余的值。 + +1966 +01:21:44,807 --> 01:21:46,073 +We just want to multiply. +我们只需要乘以宽高比就可以了。 + +1967 +01:21:46,075 --> 01:21:49,643 +So here I'm making this image view's width equal to it's +所以我们让宽等于高乘以 + +1968 +01:21:49,645 --> 01:21:51,411 +height times this multiplier. +乘以宽高比即可。 + +1969 +01:21:52,814 --> 01:21:54,030 +Make sense? +明白吗? + +1970 +01:21:54,031 --> 01:21:55,247 +That's the constraint I'm putting on it. +这是我天津的约束。 + +1971 +01:21:55,249 --> 01:21:56,281 +That's how constraints work. +约束就是这样工作的。 + +1972 +01:21:56,283 --> 01:21:57,366 +That's all it is. +就是这些。 + +1973 +01:21:57,367 --> 01:21:58,450 +Now a couple of things are not good here. +现在还有一些问题。 + +1974 +01:21:58,452 --> 01:22:02,087 +One is there is no such method aspect ratio on UI image. +一个是,UIImage没有aspectRatio方法。 + +1975 +01:22:02,089 --> 01:22:04,622 +So I'm gonna go down here and do an extension for that too. +所以我们到下面添加一个extension。 + +1976 +01:22:05,558 --> 01:22:10,727 +UIImage var aspectRatio. +添加一个aspectRatio熟悉。 + +1977 +01:22:10,729 --> 01:22:12,195 +It's gonna be a CGFloat. +CGFloat类型。 + +1978 +01:22:13,198 --> 01:22:16,565 +I'm just going to return if my size.height is not zero, +如果不为0就直接返回, + +1979 +01:22:16,567 --> 01:22:20,069 +because I don't wanna have to divide by zero. +因为我不想除数为0. + +1980 +01:22:20,071 --> 01:22:23,005 +Then I'm going to return size.width divided by +然后返回宽除以高, + +1981 +01:22:23,007 --> 01:22:26,675 +size.height, otherwise I guess I'll just return zero. +如果为0救直接返回。 + +1982 +01:22:26,677 --> 01:22:30,378 +Okay, so I just added this var to UI image, +好的,为UIImage添加了这个属性, + +1983 +01:22:30,380 --> 01:22:32,463 +because I wanted it and +因为我需要它而且 + +1984 +01:22:32,464 --> 01:22:34,547 +it makes my code read really nicely right here, okay? +这让代码非常可读又美观,不是吗? + +1985 +01:22:34,550 --> 01:22:36,850 +Perfectly reasonable. +非常完美。 + +1986 +01:22:36,851 --> 01:22:39,151 +And the only other thing is, when I set this aspect ratio +最后一个问题是,当我设置这个宽高比约束时 + +1987 +01:22:39,154 --> 01:22:42,589 +constraint I'm creating it, but now I need to enforce it. +我需要将它添加到图片上并使之生效。 + +1988 +01:22:42,591 --> 01:22:45,058 +So how do you enforce a constraint? +那么怎样使一个约束生效呢? + +1989 +01:22:45,060 --> 01:22:47,226 +If you have one in your hand, how do you force it? +如果你现在有一个约束,怎样使他生效? + +1990 +01:22:47,228 --> 01:22:48,594 +And it's very simple, +非常简单, + +1991 +01:22:48,596 --> 01:22:51,697 +you just add it as a constraint to the view. +你只需要将它添加到视图就可以了。 + +1992 +01:22:51,699 --> 01:22:53,031 +So I'm in my view controller here, so +我现在在控制器中, + +1993 +01:22:53,033 --> 01:22:57,335 +I'm going to add this constraint to my view. +我将在这里为视图添加约束。 + +1994 +01:22:57,337 --> 01:23:00,971 +So in didSet, any time this aspect ratio gets set up here, +在didSet方法中,每次设置aspetRatio的时候, + +1995 +01:23:00,973 --> 01:23:02,138 +this is where I set it. +我就在这里设置它。 + +1996 +01:23:02,140 --> 01:23:03,106 +Either to nil or this. +要么为空或不为空。 + +1997 +01:23:04,242 --> 01:23:07,976 +Then if I can let this new +如果这个约束 + +1998 +01:23:07,978 --> 01:23:11,813 +constraint equal the aspect ratio of constraint. +我可以let出来。 + +1999 +01:23:11,815 --> 01:23:13,581 +In other words, if its not nil. +换句话说,如果不为空。 + +2000 +01:23:13,583 --> 01:23:16,884 +Then I'm gonna tell my view please add this constraint. +我就让视图添加这个约束。 + +2001 +01:23:20,122 --> 01:23:23,490 +Now I also, by the way, when it set I want to +同样,随便的,在willSet中 + +2002 +01:23:23,492 --> 01:23:26,793 +remove any old constraint cause I might already have +我们需要移除掉 + +2003 +01:23:26,795 --> 01:23:29,328 +put a constraint from the previous image I was showing. +已经存在的约束。 + +2004 +01:23:29,330 --> 01:23:33,099 +So I'm gonna say if let the existing constraint +所以如果aspectRatioConstant + +2005 +01:23:33,101 --> 01:23:34,867 +equal the aspect ratio constraint and +不为空而且 + +2006 +01:23:34,869 --> 01:23:38,636 +this is my will set so this hasn't been set yet. +由于这是willSet方法,所以这时aspectRatioConstrain还没有设置 + +2007 +01:23:39,606 --> 01:23:41,538 +Then I'm gonna say remove the constraint. +我只需要移除已存在的约束即可。 + +2008 +01:23:44,343 --> 01:23:46,710 +Make sense? So that's it. +明白吗?就是这样。 + +2009 +01:23:46,712 --> 01:23:49,278 +Okay, and that's all we need to do. +这是我们所有需要做的。 + +2010 +01:23:49,280 --> 01:23:51,180 +So let's go ahead and run here. +让我们来测试一下。 + +2011 +01:23:51,182 --> 01:23:53,615 +So I'm going to go back to this view here, +更换一下视图模式, + +2012 +01:23:53,617 --> 01:23:55,884 +and select Storyboard here. +选择storyboard。 + +2013 +01:23:55,886 --> 01:23:57,719 +All right, so we're going to run this. +开始运行。 + +2014 +01:23:57,721 --> 01:23:59,454 +I haven't changed the storyboard since last we +我们至始至终都没有更改过storyboard, + +2015 +01:23:59,456 --> 01:24:02,756 +talked, but now when we go madbomb here. +我们直接运行看看。 + +2016 +01:24:04,360 --> 01:24:07,660 +This thing, it didn't work. +好像没有成功。 + +2017 +01:24:07,662 --> 01:24:09,696 +So why does this not work? +这是为什么呢? + +2018 +01:24:09,698 --> 01:24:12,465 +because, sorry about this, forgot something. +因为,很抱歉,忘了设置些东西。 + +2019 +01:24:12,467 --> 01:24:17,102 +When I set my image, I'm not calling my new image property. +当我设置imageView视图的时候,我没有调用这个新image属性。 + +2020 +01:24:17,104 --> 01:24:20,838 +I put all that nice code here inside this image +我把实现都写在了image属性的 + +2021 +01:24:20,840 --> 01:24:23,174 +property, right? +的监听方法中,记得吗? + +2022 +01:24:23,176 --> 01:24:24,274 +Right here. +就是这里。 + +2023 +01:24:24,276 --> 01:24:25,909 +But I didn't call it. +但是,我忘了使用它。 + +2024 +01:24:25,911 --> 01:24:28,144 +So here I'm actually calling that, so sorry about that. +所以,现在我们改成image,很抱歉。 + +2025 +01:24:28,146 --> 01:24:32,314 +Why did I [INAUDIBLE] there, imageView.image equals +这里好像写错了,imageView.image应该等于 + +2026 +01:24:32,316 --> 01:24:35,384 +newValue, sorry about that, newValue. +newValue,很抱歉。 + +2027 +01:24:35,386 --> 01:24:39,554 +Let's go back here, all right. +再运行一次看看。 + +2028 +01:24:39,556 --> 01:24:43,457 +See, when I rush, then I make mistakes like that. +你看,当我写的太匆忙,就会出些错误。 + +2029 +01:24:43,459 --> 01:24:44,258 +Okay, all right! +好的! + +2030 +01:24:44,260 --> 01:24:44,825 +Whoo. +Whoo。 + +2031 +01:24:45,927 --> 01:24:48,361 +I think that's the Giants logo down there. +这下面应该就是Giants logo了。 + +2032 +01:24:48,363 --> 01:24:50,329 +At least it's the right aspect ratio. +至少宽高比是正确的。 + +2033 +01:24:50,331 --> 01:24:52,498 +But clearly, it's terrible to have that thing there +但是很显然,把它放在这里很糟糕 + +2034 +01:24:52,500 --> 01:24:54,533 +because it's too tiny and we got all this space. +因为太小了,而上面却有这么大空间空着。 + +2035 +01:24:54,535 --> 01:24:57,035 +So last thing we're going to do is +所以,最后一步操作需要 + +2036 +01:24:57,036 --> 01:24:59,536 +use the size classes to put this thing up here, okay? +使用size class把logo放到上面来,明白吗? + +2037 +01:24:59,539 --> 01:25:00,738 +How do we do that? +那要怎样做呢? + +2038 +01:25:00,740 --> 01:25:03,774 +We go back to our storyboard right here. +我们回到storyboard。 + +2039 +01:25:03,776 --> 01:25:04,875 +And right now, we've been doing all our +现在为止,我们都是用的 + +2040 +01:25:04,877 --> 01:25:07,210 +work in this any any. +any any来布局。 + +2041 +01:25:07,212 --> 01:25:10,613 +Okay, and what we want to do is when we're regular height, +我们只需要,在regular高度的时候, + +2042 +01:25:10,615 --> 01:25:13,182 +we're gonna put the name and the company underneath. +将name和company标签放在底部。 + +2043 +01:25:13,184 --> 01:25:17,419 +So I'm gonna go here to where it says any width, +所以我需要到这里改成any 宽度, + +2044 +01:25:17,421 --> 01:25:18,904 +regular height. +regular高度。 + +2045 +01:25:18,905 --> 01:25:20,388 +You see where it says along the top, any width, +你看到了吗?可以在上面改成any宽度, + +2046 +01:25:20,390 --> 01:25:21,089 +regular height. +regular高度。 + +2047 +01:25:21,091 --> 01:25:21,989 +See that? +看到了吗? + +2048 +01:25:21,991 --> 01:25:23,657 +I'm gonna click there. +我点击这里。 + +2049 +01:25:23,659 --> 01:25:25,025 +Now I'm editing. +开始编辑。 + +2050 +01:25:25,026 --> 01:25:26,392 +You see the bar at the bottom is bright blue. +你看底部有一个蓝色的条目。 + +2051 +01:25:26,395 --> 01:25:28,462 +That's to remind you, +这是用来提醒你, + +2052 +01:25:28,463 --> 01:25:30,530 +oh hey, you are editing a specific size class here. +嘿,你现在是在一个特定的size class下编辑。 + +2053 +01:25:30,532 --> 01:25:33,299 +But we're editing any width, regular height. +因为我们现在在any 宽度和register高度下编辑。 + +2054 +01:25:33,301 --> 01:25:36,469 +And so here, this should be in red if I +如果我现在移动他们, + +2055 +01:25:36,471 --> 01:25:39,838 +was doing a slide, this would be in red, which is +约束会变成红色,也就是说 + +2056 +01:25:39,840 --> 01:25:42,607 +when you go to another size class, and you're going to be +当你在一个的新size class下编辑的时候,如果你打算 + +2057 +01:25:42,609 --> 01:25:45,510 +moving things around, remove the constraints on +移动视图,先去除你要移动的视图上的约束 + +2058 +01:25:45,512 --> 01:25:49,147 +the things you're going to be moving before you move them. +再进行移动, + +2059 +01:25:49,149 --> 01:25:50,799 +Because once you start moving them, +因为一旦你开始移动视图, + +2060 +01:25:50,800 --> 01:25:52,450 +it's going to be hard to remember, what did that go to. +你就很难记住这些约束了。 + +2061 +01:25:52,452 --> 01:25:54,651 +So here I am selecting these all and +所以我选中这几个视图然后 + +2062 +01:25:54,653 --> 01:25:58,488 +I am going to go over here and remove the constraint, +到这里移除约束, + +2063 +01:25:58,490 --> 01:26:00,757 +clear the constraints, only from the selected views, +选择清除约束,只清除选中视图的约束, + +2064 +01:26:00,759 --> 01:26:01,991 +these three things I have selected. +也就是我选中的这三个视图。 + +2065 +01:26:01,993 --> 01:26:03,826 +So we're going to clear those constraints, +我们会清除他们所有的约束, + +2066 +01:26:03,828 --> 01:26:05,494 +now they have no constraints, +现在他们身上没有约束了, + +2067 +01:26:05,496 --> 01:26:07,496 +now I am just going to move them around to where I want. +我可以随便移动了。 + +2068 +01:26:07,498 --> 01:26:09,130 +So I want that one there, +我把这个放这里, + +2069 +01:26:09,132 --> 01:26:11,399 +I want these down here at the bottom. +这个放在底部。 + +2070 +01:26:11,401 --> 01:26:12,366 +Put that in the corner. +放在角落。 + +2071 +01:26:12,368 --> 01:26:13,701 +I'll put that on top of there. +然后把这个放在上面。 + +2072 +01:26:13,703 --> 01:26:15,769 +We'll put this down here like that. +放下一点。 + +2073 +01:26:15,771 --> 01:26:17,604 +Now we'll put the new constraints, so +现在我们加新的约束,这样 + +2074 +01:26:17,606 --> 01:26:20,206 +now all new constraints that I'm making are only for +所有新加的约束 + +2075 +01:26:20,208 --> 01:26:22,008 +this size class. +只对当前size class有效。 + +2076 +01:26:22,010 --> 01:26:23,542 +Okay? Not for any-any anymore. +明白吗?不再对any-any有效。 + +2077 +01:26:23,544 --> 01:26:25,544 +I'm kind of forked off here. +就像叉掉了一样。 + +2078 +01:26:25,546 --> 01:26:27,946 +So let's put some new constraints on here. +现在我会加新的约束。 + +2079 +01:26:27,948 --> 01:26:29,547 +This one is leaving space. +这个leading space。 + +2080 +01:26:29,549 --> 01:26:31,449 +This one is leading space. +这个leading space。 + +2081 +01:26:31,451 --> 01:26:34,018 +This one is bottom space. +这个bottom space。 + +2082 +01:26:34,020 --> 01:26:35,819 +We want these separated. +这两个需要分开。 + +2083 +01:26:35,821 --> 01:26:36,653 +Vertical space. +vertical space。 + +2084 +01:26:36,655 --> 01:26:38,888 +We want these two separated. +我们需要这两个也分开。 + +2085 +01:26:38,890 --> 01:26:41,657 +We want this one over here leading space. +这个也添加leading space。 + +2086 +01:26:41,659 --> 01:26:45,160 +We want this to go all the way across, and +这一个横向延伸到边缘,然后 + +2087 +01:26:45,162 --> 01:26:47,029 +then go trailing space. +加上trailing space。 + +2088 +01:26:47,031 --> 01:26:51,199 +You also want this one to go all the way across, and +这样也占满宽度,然后 + +2089 +01:26:51,201 --> 01:26:52,166 +trailing space. +trailing space。 + +2090 +01:26:53,269 --> 01:26:54,101 +Okay. +好的。 + +2091 +01:26:54,103 --> 01:26:55,769 +Again, we would probably go here. +同样,我们需要到这里。 + +2092 +01:26:55,771 --> 01:26:57,403 +Let's see what we've got here. +好像有警告。 + +2093 +01:26:57,405 --> 01:26:58,738 +Frames are different, that's good. +Frames不同,这很简单。 + +2094 +01:26:58,740 --> 01:27:01,039 +Let's go ahead and update our frames. +更新frame就可以了。 + +2095 +01:27:02,476 --> 01:27:03,675 +Okay, looks good. +好的,看起来不错。 + +2096 +01:27:03,677 --> 01:27:05,677 +All looks good. +都很好。 + +2097 +01:27:05,678 --> 01:27:07,678 +Again, we would probably get rid of these magic numbers +再次强调,我们肯能需要去除所有magic numbers + +2098 +01:27:07,680 --> 01:27:08,245 +like this. +像这个。 + +2099 +01:27:08,247 --> 01:27:09,046 +We don't like that. +我们不需要它。 + +2100 +01:27:09,048 --> 01:27:09,879 +We get rid of that. +去掉。 + +2101 +01:27:09,881 --> 01:27:11,280 +We did this one. +这个改了。 + +2102 +01:27:11,282 --> 01:27:12,581 +We don't like that. +也不需要这个。 + +2103 +01:27:12,583 --> 01:27:14,917 +We go select on this guy. +选择这个视图。 + +2104 +01:27:14,919 --> 01:27:19,287 +We've got this here, that. +这个也需要更改。 + +2105 +01:27:19,289 --> 01:27:20,421 +Same thing this one. +这个也是。 + +2106 +01:27:20,423 --> 01:27:21,589 +Okay, he got none, so we're good. +好的,修改完毕。 + +2107 +01:27:21,591 --> 01:27:22,489 +We're good to go. +可以测试了。 + +2108 +01:27:22,491 --> 01:27:25,225 +So now we've created this size class. +现在我们创建了这个size class。 + +2109 +01:27:25,227 --> 01:27:28,828 +One has different arrangement of views and +它有着不同的布局和 + +2110 +01:27:28,830 --> 01:27:29,995 +different constraints. +不同的约束。 + +2111 +01:27:29,997 --> 01:27:30,963 +So now when we run. +我们运行看看。 + +2112 +01:27:33,133 --> 01:27:33,832 +We'll see here. +马上就看到效果了。 + +2113 +01:27:34,868 --> 01:27:35,733 +Hit mad bum again. +登陆。 + +2114 +01:27:37,570 --> 01:27:38,602 +There it is. +就是这样。 + +2115 +01:27:38,603 --> 01:27:39,635 +It's using this space much more +现在更充分地利用了 + +2116 +01:27:39,638 --> 01:27:42,739 +effectively keeping this in it's normal aspect ratio, but +垂直方向上的空间,同时保证宽高比正确,并且 + +2117 +01:27:42,741 --> 01:27:44,874 +in this way it goes back to the old way. +在横屏模式下以原来的方式布局。 + +2118 +01:27:44,876 --> 01:27:47,843 +The any, any way, right? +也就是any any 记得吗? + +2119 +01:27:47,845 --> 01:27:50,312 +Okay, and this is true if we go to someone else. +好的,我们用另一个账户登陆试试。 + +2120 +01:27:50,314 --> 01:27:51,880 +Hennessy. +Hennessy。 + +2121 +01:27:51,882 --> 01:27:55,250 +There, okay, see how that keeps the same aspect ratio +看,宽高比正常 + +2122 +01:27:55,252 --> 01:27:56,884 +and uses that space? +而且充分利用水平空间。 + +2123 +01:27:56,886 --> 01:27:58,953 +Really uses the space nicely here, no. +真的充分利用了空间,不。 + +2124 +01:27:58,955 --> 01:28:00,421 +>> [LAUGH] +laugh + +2125 +01:28:00,423 --> 01:28:02,756 +>> Now why did that happen, okay? +这是为什么呢? + +2126 +01:28:02,758 --> 01:28:05,692 +Because when I cleared the constraints here, +因为当我清除约束的时候, + +2127 +01:28:05,694 --> 01:28:10,296 +okay, to make this new space, I also cleared this little +增加控件的同时,我也清除了 + +2128 +01:28:10,298 --> 01:28:13,665 +constraint that went up here, this vertical spacing. +上面这个约束,垂直距离约束。 + +2129 +01:28:13,667 --> 01:28:15,550 +Right? +明白吗? + +2130 +01:28:15,551 --> 01:28:17,434 +This vertical spacing here wants to be the greater than +垂直距离需要大于 + +2131 +01:28:17,437 --> 01:28:20,171 +or equal to, and standard value. +或等于标准值。 + +2132 +01:28:20,173 --> 01:28:21,505 +Okay? So sometimes when you +明白吗?有时候当你 + +2133 +01:28:21,507 --> 01:28:24,174 +go to another size class, you delete the constraints, +切换到新的size class,你删除约束, + +2134 +01:28:24,176 --> 01:28:26,076 +you move things around, oh, you still have +然后移动视图,你仍然需要 + +2135 +01:28:26,078 --> 01:28:29,446 +to basically debug the new one just as much as the old one. +做一些调试来保证之前的约束有效。 + +2136 +01:28:29,448 --> 01:28:31,548 +So here now, +好,再运行看看。 + +2137 +01:28:31,549 --> 01:28:33,649 +let's go see if our illustrious leader's log in. +登陆看是否显示正确。 + +2138 +01:28:35,419 --> 01:28:36,385 +It's good and it is. +很好,显示正常。 + +2139 +01:28:38,155 --> 01:28:38,720 +Okay? +看到了吗? + +2140 +01:28:39,889 --> 01:28:40,938 +All right. +好的。 + +2141 +01:28:40,939 --> 01:28:41,988 +Sorry to take so long. +很抱歉拖堂这么久。 + +2142 +01:28:41,991 --> 01:28:43,757 +Thank you. +非常感谢。 + +2143 +01:28:43,758 --> 01:28:45,524 +I'll be here if you have any questions, +如果有问题可以提问, + +2144 +01:28:45,527 --> 01:28:46,926 +otherwise I'll see you on Wednesday. +没有的话我们星期三见。 + +2145 +01:28:47,962 --> 01:28:47,993 +>> For more, please visit us at Stanford.edu. +更多内容,请访问Stanford.edu. diff --git a/subtitles/9. Scroll View and Multithreading.srt b/subtitles/9. Scroll View and Multithreading.srt new file mode 100644 index 0000000..2dd3640 --- /dev/null +++ b/subtitles/9. Scroll View and Multithreading.srt @@ -0,0 +1,8744 @@ +1 +00:00:00,001 --> 00:00:04,536 +[MUSIC] +[音乐] + +2 +00:00:04,538 --> 00:00:07,839 +>> Stanford University. +斯坦福大学 + +3 +00:00:07,841 --> 00:00:11,875 +Welcome to Stanford CS193P, Winter of 2015. +欢迎来到2015年冬季的 CS193P 课程 + +4 +00:00:11,877 --> 00:00:15,979 +This is Lecture 9, I believe. +这是第9课 + +5 +00:00:15,981 --> 00:00:20,450 +And today, we are going to turn on our clicker here and +我先把遥控器打开 + +6 +00:00:20,452 --> 00:00:21,684 +then we are going to. +然后我将展示给你们 + +7 +00:00:21,686 --> 00:00:25,454 +I'm going to show you a brief, very brief demo, +一个非常简短的 demo + +8 +00:00:25,456 --> 00:00:30,692 +in addition to the Autolayout Demo that we did last time. +我们上次写的 Autolayout demo + +9 +00:00:30,694 --> 00:00:33,361 +I challenged you in that one to add buttons to +向 Calculator 中添加一些 button + +10 +00:00:33,363 --> 00:00:35,429 +your calculator, then I didn't show you how to do that. +但是我没有告诉你们该怎么实现 + +11 +00:00:35,431 --> 00:00:37,164 +So I'm gonna show you how to do that. +所以我会告诉你们怎么做 + +12 +00:00:37,166 --> 00:00:38,732 +How, in a different size class, +对于不同的 Size Class + +13 +00:00:38,734 --> 00:00:42,535 +you could add some views that aren't in another size class. +你可以添加不一样的 view + +14 +00:00:42,537 --> 00:00:44,804 +Then we're gonna talk about two big topics today. +接下来我们会探讨两个话题 + +15 +00:00:44,806 --> 00:00:46,372 +One of them is ScrollView, okay. +一个是 ScrollView (滚动视图) + +16 +00:00:46,374 --> 00:00:50,009 +And the second one is Multithreading. +另一个是 Multithreading(多线程) + +17 +00:00:50,011 --> 00:00:52,144 +And, kind of as a preamble to do multithreading, +在讲 Multithreading 之前 + +18 +00:00:52,146 --> 00:00:54,212 +I'm going to talk a little bit about closures. +我会提及一些 closure 的知识 + +19 +00:00:54,214 --> 00:00:57,448 +Now, you should all have read your reading assignment, so +你们应该都完成了阅读任务 + +20 +00:00:57,450 --> 00:00:58,683 +you all know about closures. +所以你们都应该了解一些 closure 的知识 + +21 +00:00:58,685 --> 00:01:02,119 +But, I just wanna emphasize something about them. +我就是想强调一下这方面的知识 + +22 +00:01:02,121 --> 00:01:03,687 +That will start to be more important as we +当我们在多线程里使用 closure 的时候 + +23 +00:01:03,689 --> 00:01:06,656 +start using closures more for things like multithreading. +这就变得更重要了 + +24 +00:01:06,658 --> 00:01:10,593 +So, let's make a quick little detour here. +让我们快速进行以下的内容 + +25 +00:01:10,595 --> 00:01:14,096 +I'm just gonna open up Autolayout here. +我先打开 Autolayout 项目 + +26 +00:01:14,098 --> 00:01:15,631 +So here's autolayout. +这就是 Autolayout + +27 +00:01:15,633 --> 00:01:18,633 +And what I wanna be able to do is add another +我想做的事情是 + +28 +00:01:19,836 --> 00:01:23,704 +view only in one of my size classes. +只在其中一个 Size Class 添加一个 view + +29 +00:01:23,706 --> 00:01:25,739 +So here's my Any, Any size class. +这是 Any Any Size Class + +30 +00:01:25,741 --> 00:01:29,242 +And let's say I go back to my Any Width, +回到之前我们进行到的 + +31 +00:01:29,244 --> 00:01:31,010 +Regular Height that we were working on. +Any Width Regular Height Size Class + +32 +00:01:31,012 --> 00:01:35,180 +And let's say, when we're in this particular arrangement, +在这种特殊的布局下 + +33 +00:01:35,182 --> 00:01:36,999 +we wanna have, +我想要 + +34 +00:01:37,000 --> 00:01:38,817 +you know, an extra button up here or something. +在这里添加一个按钮之类的东西 + +35 +00:01:38,819 --> 00:01:41,786 +And all we need to do that is to drag out whatever +我们需要做的 + +36 +00:01:41,788 --> 00:01:44,522 +the extra UI you want is, like this Button. +就是把你需要的 UI 元素拽进来 + +37 +00:01:44,524 --> 00:01:48,158 +And if you inspect the button with the Inspector, +在它们的 Inspector 页面 + +38 +00:01:48,160 --> 00:01:49,393 +Attributes Inspector. +Attributes Inspector + +39 +00:01:49,395 --> 00:01:52,762 +Down at the very bottom, you'll see, right here, +在最底下,在这里 + +40 +00:01:52,764 --> 00:01:55,898 +that there is some switches that control where this +这里有控制这个按钮 + +41 +00:01:55,900 --> 00:01:57,199 +button appears. +应该在哪里出现的选项 + +42 +00:01:57,201 --> 00:01:59,968 +Now, since I dragged this button into this size class, +我是在当前 Size Class 拖拽进来的 + +43 +00:01:59,970 --> 00:02:02,404 +it assumes I only wanted it in this size class. +所以它假定我只想让这个按钮出现在这个 Size Class 里 + +44 +00:02:02,406 --> 00:02:05,273 +You see where it says Installed, right here? +看到这个 Installed 被选中了吗 + +45 +00:02:05,275 --> 00:02:07,508 +I could put it in all size classes by clicking this. +我可以通过点击这个地方,把它放入所有的 Size Class 中 + +46 +00:02:07,510 --> 00:02:09,477 +That means it'll be in all size classes. +这表示所有的 Size Class + +47 +00:02:09,479 --> 00:02:12,780 +Or I could take it out of this size class only, +或者通过点击它 + +48 +00:02:12,782 --> 00:02:15,782 +by unclicking this, okay? +我也可以不让它在这个 Size Class 出现 + +49 +00:02:15,784 --> 00:02:18,118 +And you can add more things. +你也可以把它添加到更多的 Size Class 中去 + +50 +00:02:18,120 --> 00:02:19,652 +I could say in Compact Width, +Compact Width Compact Height + +51 +00:02:19,654 --> 00:02:22,554 +Compact Height, I want this button to be there or not. +我是否希望按钮出现在那里 + +52 +00:02:23,991 --> 00:02:25,390 +Okay? +OK? + +53 +00:02:25,392 --> 00:02:28,259 +And that's true for constraints, as well. +这对于约束也是适用的 + +54 +00:02:28,261 --> 00:02:29,427 +If you have a certain constraint. +如果对于某个约束 + +55 +00:02:29,429 --> 00:02:31,195 +Like we've got constraints down here, +像这里的这个 + +56 +00:02:31,197 --> 00:02:35,298 +like this one right here, that are only in this size class. +只在当前 Size Class 里 + +57 +00:02:35,300 --> 00:02:38,134 +Because these things are only down here in this size class. +因为它们只出现在当前 Size Class 里 + +58 +00:02:38,136 --> 00:02:39,369 +So you can see that's switched. +你可以看到,这是可以转换的 + +59 +00:02:39,371 --> 00:02:43,739 +So, whether something is even there and +不管对于 UI 元素还是约束 + +60 +00:02:43,741 --> 00:02:46,208 +also the constraints, you can control right here. +你都可以在这里控制 + +61 +00:02:46,210 --> 00:02:49,277 +And someone asked me, oh, I did all this work in here, for +有人可能会问 + +62 +00:02:49,279 --> 00:02:51,312 +all this size class, but I changed my mind. +我在这个 Size Class 做完了所有工作,但是我改变主意了 + +63 +00:02:51,314 --> 00:02:53,314 +I don't want it to be different in that size class. +我不想在这个 Size Class 不一样 + +64 +00:02:53,316 --> 00:02:55,683 +How would I go back and undo all this? +我怎么样才能返回呢? + +65 +00:02:55,685 --> 00:02:57,468 +Well, the way you would do +完成这件事的方法就是 + +66 +00:02:57,469 --> 00:02:59,252 +that is bring up your document outline. +打开 Document Outline + +67 +00:02:59,254 --> 00:03:00,820 +And you can select all your constraints. +你可以选中所有的约束 + +68 +00:03:00,822 --> 00:03:03,489 +You can actually shift > click to select. +也可以按住 shift 进行多选操作 + +69 +00:03:03,491 --> 00:03:05,558 +I could select all my constraints. +我可以选择所有的约束 + +70 +00:03:05,560 --> 00:03:07,960 +And you can see over here, in the Inspector, +你可以在 Inspector 里看到 + +71 +00:03:07,962 --> 00:03:10,195 +it's going to show me that, you know, some of. +它会展示给你这些的信息 + +72 +00:03:10,197 --> 00:03:12,731 +It's got a dash here instead of a check. +这里是破折号而不是对勾 + +73 +00:03:12,733 --> 00:03:14,499 +So, kind of some of them are there. +类似的东西 + +74 +00:03:14,501 --> 00:03:17,735 +And if just go here and say, boom, and remove that. +如果我点击这里移除它 + +75 +00:03:17,737 --> 00:03:23,273 +Now, all my constraints are only in my base class. +所有的约束现在只存在于 Any Any Size Class 中 + +76 +00:03:23,275 --> 00:03:25,041 +There's no constraints that are just in this one. +在当前 Size Class 里没有约束了 + +77 +00:03:25,043 --> 00:03:26,909 +And, in fact, if you look down here. +如果你看这里 + +78 +00:03:26,911 --> 00:03:29,512 +Look, all these constraints are all gone. +所有的约束都消失了 + +79 +00:03:29,514 --> 00:03:31,680 +So, in fact, if I go here and Update Frames. +如果我点击 Update Frames + +80 +00:03:31,682 --> 00:03:33,315 +Boom, it goes back to the way it was. +它们就回到了本来的位置 + +81 +00:03:34,317 --> 00:03:34,882 +You see? +看到了吗 + +82 +00:03:36,352 --> 00:03:38,318 +Everyone understand that? +每个人都明白了吧? + +83 +00:03:38,320 --> 00:03:41,755 +So, Constraints and the Views can be turned on and off +Constrains 和 View 可以在 Attributes Inspector + +84 +00:03:41,757 --> 00:03:46,059 +by just inspecting them in the Attributes Inspector, okay? +被调整显示的 Size Class + +85 +00:03:46,061 --> 00:03:47,593 +That's all I wanted to show you there. +这就是我想要展示给你们的 + +86 +00:03:48,963 --> 00:03:50,529 +All right, back to the slides. +好的,回到 slides + +87 +00:03:51,965 --> 00:03:54,098 +All right, so let's. +好的 + +88 +00:03:55,101 --> 00:03:59,369 +Talk about ScrollView. +接着我们来讨论 ScrollView + +89 +00:03:59,371 --> 00:04:02,739 +All right so, you can see this iPhone right here. +你可以看到这里有一个 iPhone + +90 +00:04:02,741 --> 00:04:04,858 +This is like, +它像 iPhone 1 + +91 +00:04:04,859 --> 00:04:06,976 +I don't know, iPhone 1 or something-looking thing. +或者其他的版本 + +92 +00:04:06,978 --> 00:04:10,079 +But, I keep it around because it's a really cool example of +我把它放到这里 + +93 +00:04:10,081 --> 00:04:11,380 +the power of ScrollView. +是想给你们展现一下 ScrollView 的强大 + +94 +00:04:11,382 --> 00:04:12,914 +And what you can do with ScrollView. +你可以对 ScrollView 做些什么 + +95 +00:04:12,916 --> 00:04:15,316 +Especially with ScrollViews inside ScrollViews. +尤其是 ScrollView 内部还有 ScrollView + +96 +00:04:15,318 --> 00:04:19,286 +So, watch this little movie here go as we scroll around, +一起来看看这个短片 + +97 +00:04:19,288 --> 00:04:21,555 +up and down. +到处滑动 + +98 +00:04:21,556 --> 00:04:23,823 +Okay, so that's just normal side-to-side scrolling. +侧面的滑动 + +99 +00:04:23,826 --> 00:04:26,660 +But there's up and down within the side to side. +在侧面滑动里面还可以上下滑动 + +100 +00:04:26,662 --> 00:04:28,629 +When I get to one, I can go up and down. +我可以上下滑动 + +101 +00:04:28,630 --> 00:04:30,597 +And then this app, at the bottom, I can scroll side to +对于这个应用,在底部 + +102 +00:04:30,599 --> 00:04:33,499 +side at the bottom and also up and down. +我可以向两边和上下滑动 + +103 +00:04:33,501 --> 00:04:35,234 +So, you see how the scrolling can kind of +所以 + +104 +00:04:35,236 --> 00:04:36,502 +go both directions. +滑动可以向两个方向进行 + +105 +00:04:36,504 --> 00:04:38,470 +Depending on what you've scrolled into view. +取决于你要滑动什么 + +106 +00:04:38,472 --> 00:04:43,007 +So, ScrollView is very smart about knowing which +ScrollView 很清楚 + +107 +00:04:43,009 --> 00:04:44,542 +way you're scrolling. +你正向哪个方向滑动 + +108 +00:04:44,544 --> 00:04:47,444 +And having, you know, opposing ScrollViews and +ScrollView 能够 + +109 +00:04:47,446 --> 00:04:49,780 +stuff work properly, okay. +正确地工作 + +110 +00:04:49,782 --> 00:04:52,649 +Now, we're not gonna be able to have time, in the brief +我不会占用简短的时间 + +111 +00:04:52,651 --> 00:04:55,318 +time we have here, to discuss how to make all that work. +讨论怎么让它工作 + +112 +00:04:55,320 --> 00:04:57,019 +But I just want you to know the power is there. +我只想让你知道它的能力 + +113 +00:04:57,021 --> 00:04:59,521 +So, someday, if you wanna build an app that has some UI +如果有一天你做的 App 有这些东西 + +114 +00:04:59,523 --> 00:05:02,190 +like that, you know where to go, which is ScrollView. +你应该知道,看 ScrollView 的内容 + +115 +00:05:02,192 --> 00:05:04,392 +So, we're gonna talk about the basics of ScrollView. +所以我们来看看 ScrollView 的一些基础 + +116 +00:05:04,394 --> 00:05:06,961 +Kind of how to get a ScrollView to work. +怎样让 ScrollView 工作 + +117 +00:05:06,963 --> 00:05:10,497 +First, let's talk about how we add subviews to +首先,怎样在 UIView 中 + +118 +00:05:10,499 --> 00:05:11,598 +a normal UIView. +添加 SubView + +119 +00:05:11,600 --> 00:05:13,133 +So, I got a normal UIView here. +这里有个普通的 UIView + +120 +00:05:13,135 --> 00:05:16,703 +This white view in my iPhone here. +iPhone 中白色的 view + +121 +00:05:16,705 --> 00:05:19,305 +And I wanna add a subview to it. +我想给它添加 SubView + +122 +00:05:19,307 --> 00:05:22,941 +And so, you know, from Lecture 5, I think, that I just create +在 lecture 5 大概,我创建了 + +123 +00:05:22,943 --> 00:05:26,812 +the frame which positions it and then I say add subview. +frame 然后 addSubView + +124 +00:05:26,814 --> 00:05:28,413 +Okay, so I've got this view called Logo. +把这个 view 起名为 Logo + +125 +00:05:28,415 --> 00:05:30,248 +And it's just a UIView. +它是一个 UIView + +126 +00:05:30,250 --> 00:05:32,850 +An image view, probably. +也许是个 imageView + +127 +00:05:32,852 --> 00:05:35,652 +And, so I just add subview and, boom, it appears. +我只是 addSubView,它就出现了 + +128 +00:05:35,654 --> 00:05:36,319 +Simple as that. +就是这么简单 + +129 +00:05:36,321 --> 00:05:37,554 +It's really easy. +很简单 + +130 +00:05:37,556 --> 00:05:41,457 +So, what is the analogy to doing this +ScrollView 类似的处理方法 + +131 +00:05:41,459 --> 00:05:42,591 +for ScrollView, okay? +是什么? + +132 +00:05:43,961 --> 00:05:45,060 +Let's go look at that. +让我们一起看看 + +133 +00:05:45,062 --> 00:05:48,463 +So, in a ScrollView, if you wanna add a subview. +在 ScrollView 中,如果你想添加 SubView + +134 +00:05:48,465 --> 00:05:51,899 +The most important thing you have to do is talk about +需要做的最重要的事情就是 + +135 +00:05:51,901 --> 00:05:55,636 +how big the area you wanna scroll over is. +你需要滑动的区域有多大 + +136 +00:05:55,638 --> 00:05:59,839 +So, you set this property in ScrollView called contentSize. +在 ScrollView 设置叫做 contentSize 的属性 + +137 +00:05:59,841 --> 00:06:02,675 +So, here I'm gonna set my contentSize to 3000 +这里我把它设置为 3000 宽 + +138 +00:06:02,677 --> 00:06:05,378 +wide and 2000 high. +2000 高 + +139 +00:06:05,379 --> 00:06:08,080 +So, I'm gonna scroll over this huge space, okay? +所以我会在这个巨大的区域滑动 + +140 +00:06:08,082 --> 00:06:10,015 +Once you set the contentSize, +一旦你设置了 contentSize + +141 +00:06:10,017 --> 00:06:13,751 +now you can add subviews just like you do a normal view. +你就可以像一个普通的 view 一样向它添加 SubView 了 + +142 +00:06:13,753 --> 00:06:15,886 +So, here I got logo frame. +这里我获取了 logo 的 frame + +143 +00:06:15,888 --> 00:06:20,957 +I'm gonna set the frame to way over on the left there and +我把它放到右上角 + +144 +00:06:20,959 --> 00:06:23,760 +I am going to add its subview. +添加 SubView + +145 +00:06:23,762 --> 00:06:26,362 +So I'm adding that subview to the ScrollView. +向这个 ScrollView 当中 + +146 +00:06:26,364 --> 00:06:28,831 +But instead of it appearing onscreen there, +为了让它显示在屏幕上 + +147 +00:06:28,833 --> 00:06:31,467 +it's just kind of placed in this content area. +你只需要把它放置到 content 区域就可以了 + +148 +00:06:32,503 --> 00:06:33,802 +And so, I could add another one. +我也可以添加另外一个 + +149 +00:06:33,804 --> 00:06:37,805 +Here's a huge image, aerial view of Stanford. +这是一个 Stanford 的鸟瞰图 + +150 +00:06:37,807 --> 00:06:39,873 +And so, I'm gonna set its frame and +设置它的 frame + +151 +00:06:39,875 --> 00:06:42,042 +add it as a subview, okay. +给它添加为 SubView + +152 +00:06:42,044 --> 00:06:43,743 +So this is the fundamental, +这是最基本的 + +153 +00:06:43,745 --> 00:06:45,011 +this is all there is to ScrollView. +ScrollView 的内容 + +154 +00:06:45,013 --> 00:06:46,545 +It's really simple, actually. +实际上非常简单 + +155 +00:06:46,547 --> 00:06:48,080 +It confuses people for some reason, but +在某些方面,人们对于这个很困惑 + +156 +00:06:48,082 --> 00:06:49,214 +it's really just this simple. +不过它就是这么简单 + +157 +00:06:49,216 --> 00:06:50,648 +You set the contentSize, +设置好 contentSize + +158 +00:06:50,650 --> 00:06:52,717 +then you add subviews to the ScrollView. +给它添加 SubView + +159 +00:06:52,719 --> 00:06:55,786 +Now, the ScrollView is just going to +ScrollView 就会在那个 content 区域 + +160 +00:06:55,788 --> 00:06:58,322 +be a window on that content area. +变成一个 窗口 + +161 +00:06:58,324 --> 00:07:01,024 +You see, it's just gonna scroll around, +你可以到处拖动 + +162 +00:07:01,026 --> 00:07:02,525 +looking in that content area. +在 content 区域中 + +163 +00:07:02,527 --> 00:07:05,228 +And it'll see all the subviews as it +在这个过程中 + +164 +00:07:05,230 --> 00:07:07,363 +moves around in there, okay? +可以看到添加的 SubView + +165 +00:07:07,365 --> 00:07:08,664 +So, that's it. +就是这样 + +166 +00:07:08,666 --> 00:07:10,900 +That's all there is to it. +就这些 + +167 +00:07:10,901 --> 00:07:13,135 +ScrollView is actually incredibly easy to use. +ScrollView 很容易使用 + +168 +00:07:13,137 --> 00:07:15,637 +Now, you can reposition the views, anytime you want, +你可以在任何时候重置 view 的位置 + +169 +00:07:15,639 --> 00:07:17,638 +just like you could if they were subviews. +如果有 SubView + +170 +00:07:17,640 --> 00:07:20,341 +You can just change their frame and they'll move around. +你可以改变它们的 frame,它们就会到处移动 + +171 +00:07:20,343 --> 00:07:22,976 +Or change the logo's frame, move it around. +改变 logo 的 frame,移动它 + +172 +00:07:22,978 --> 00:07:24,678 +I can also change the contentSize. +我也可以改变 contentSize + +173 +00:07:24,680 --> 00:07:27,147 +[NOISE] And now it zooms down. +现在它向下移动 + +174 +00:07:27,149 --> 00:07:28,781 +I can set the contentSize to be +我可以把 contentSize 设置为 + +175 +00:07:28,783 --> 00:07:30,683 +the size of the biggest subview. +最大 SubView 的尺寸 + +176 +00:07:30,685 --> 00:07:32,585 +And now, again, +同样地 + +177 +00:07:32,586 --> 00:07:34,486 +when I scroll around, it's just zooming around, okay. +当我滑动的时候它也在移动 + +178 +00:07:35,522 --> 00:07:37,088 +So it's very common in the ScrollView, +这在 ScrollView 中很常见 + +179 +00:07:37,090 --> 00:07:39,724 +obviously, to set its contentSize to be the size of +把 contentSize 设置为 + +180 +00:07:39,726 --> 00:07:41,726 +the biggest subview. +最大 SubView 的尺寸 + +181 +00:07:41,728 --> 00:07:43,327 +So that it exactly contains it. +刚好能容纳下它 + +182 +00:07:44,630 --> 00:07:48,331 +Okay, now, as this thing moves around, you might wanna know, +当它到处移动的时候 + +183 +00:07:48,333 --> 00:07:49,965 +where is it, okay? +你想知道现在的位置 + +184 +00:07:49,967 --> 00:07:54,836 +What we are currently looking at in my content area? +我们在看 content 区域的什么东西 + +185 +00:07:54,838 --> 00:07:56,971 +And you do that with the property in +你可以通过 ScrollView 的 + +186 +00:07:56,973 --> 00:07:59,273 +ScrollView called contentOffset. +叫 contenteOffset 的属性获取 + +187 +00:07:59,275 --> 00:08:00,892 +And it's simple. +很简单 + +188 +00:08:00,893 --> 00:08:02,510 +It's just an x-y offset from the upper left,. +它是一个对于左上角顶点的 x-y 偏移 + +189 +00:08:02,512 --> 00:08:04,278 +Of the upper left of the, +ScrollView bounds + +190 +00:08:04,280 --> 00:08:06,947 +you know, bounds of the scroll view. +的左上角 + +191 +00:08:06,949 --> 00:08:10,516 +Okay, now what about the actual rectangle +正在显示的 + +192 +00:08:10,518 --> 00:08:12,284 +that's showing? +真正的矩形区域 + +193 +00:08:12,286 --> 00:08:14,270 +What is that? +是什么 + +194 +00:08:14,271 --> 00:08:16,255 +That is actually the scroll view's bounds. +它实际上 ScrollView 的 bounds + +195 +00:08:16,257 --> 00:08:18,323 +Okay, it's very important to understand that that is +理解这一点很重要 + +196 +00:08:18,325 --> 00:08:20,859 +just the scroll view bound, that yellow rectangle I'm +我正在给你展示的黄色矩形 + +197 +00:08:20,861 --> 00:08:23,761 +showing you there, that's the scroll view's bounds. +是 ScrollView 的 bound + +198 +00:08:23,763 --> 00:08:26,030 +But if you want to know what that rectangle is +如果你想知道在 content 中 + +199 +00:08:26,032 --> 00:08:29,566 +in the content, like, in that aerial view, +这个矩形的坐标,在 aerial view 中 + +200 +00:08:29,568 --> 00:08:31,601 +what is that rectangle, then you have to convert it. +你可以转换坐标 + +201 +00:08:31,603 --> 00:08:34,237 +You have to convert the scrollView's bounds using +使用 convertRect 方法 + +202 +00:08:34,239 --> 00:08:37,774 +convertRect, [COUGH] which is UIView method. +是个 UIView 的方法 + +203 +00:08:37,776 --> 00:08:39,775 +You have to convert it to that, +你可以把它转换为 + +204 +00:08:39,777 --> 00:08:42,978 +to whatever view you wanna convert it +你想要转换的任何 View 的坐标 + +205 +00:08:42,980 --> 00:08:45,480 +to like the aerial view whatever that aerial view is. +无论是哪个 aerial view + +206 +00:08:45,482 --> 00:08:47,549 +Does that make sense? +能听懂吗? + +207 +00:08:47,551 --> 00:08:49,650 +So that rectangle is the scroll view's bounds. +这个矩形是 ScrollView 的 bounds + +208 +00:08:51,053 --> 00:08:51,618 +Okay? +OK? + +209 +00:08:53,055 --> 00:08:53,619 +Questions? +有问题吗? + +210 +00:08:54,789 --> 00:08:56,255 +All right. That's easy. +这很简单 + +211 +00:08:56,257 --> 00:08:57,673 +So that's it. +就是这样 + +212 +00:08:57,674 --> 00:08:59,090 +That's pretty much it to setting up a scroll view and +这基本上就是 + +213 +00:08:59,093 --> 00:09:00,759 +knowing where the thing is scrolling. +设置 ScrollView 的一些步骤 + +214 +00:09:00,761 --> 00:09:02,460 +Couldn't be simpler actually. +不能再简单了 + +215 +00:09:02,462 --> 00:09:04,161 +How do you create a scroll view? +如何创建一个 ScrollView + +216 +00:09:04,163 --> 00:09:05,996 +There's actually numerous ways to do it. +实际上有好几种方法可以实现 + +217 +00:09:05,998 --> 00:09:07,764 +You can drag one into your storyboard. +你可以拽一个到 StoryBoard 中 + +218 +00:09:07,766 --> 00:09:09,750 +That's what I'm gonna do in the demo. +我在 demo 中也会这么做 + +219 +00:09:09,751 --> 00:09:11,735 +You can actually select a UI view in your storyboard and +你也可以在 storyboard 中选中一个 UIView + +220 +00:09:11,737 --> 00:09:14,303 +go up to the menu up there, +在餐单中 + +221 +00:09:14,305 --> 00:09:17,139 +and say embed in scroll view, just like we did embed in +embed in scroll view + +222 +00:09:17,141 --> 00:09:19,308 +navigation controller in a previous thing. +就像我们在之前 Embed in Navigation Controller 一样 + +223 +00:09:19,310 --> 00:09:21,510 +You can of course create Scroll Views in code. +你可以使用代码创建 ScrollView + +224 +00:09:21,512 --> 00:09:22,644 +They're just views, so +它是 view + +225 +00:09:22,646 --> 00:09:24,746 +you can write a UIScrollView frame whatever. +你可以创建一个 UIScrollView frame 之类的 + +226 +00:09:24,748 --> 00:09:26,047 +And boom, you've created a Scroll View. +这样你就创建了一个 ScrollView + +227 +00:09:26,049 --> 00:09:28,816 +So, they're just normal views. +它们只是普通的 view + +228 +00:09:28,818 --> 00:09:30,684 +And then the code if you wanted to +如果你想通过代码添加 + +229 +00:09:30,686 --> 00:09:33,720 +add those subviews in code would look exactly kind of +SubView,那么这些代码 + +230 +00:09:33,722 --> 00:09:35,922 +like what was on the previous slides. +和之前 slides 的会看起来完全一样 + +231 +00:09:35,924 --> 00:09:38,190 +Which is we might create an image view here, +也许创建了一个 imageView + +232 +00:09:38,192 --> 00:09:40,959 +the green is just creating UI image view, +绿色的部分创建了一个 UIImageView + +233 +00:09:40,961 --> 00:09:43,462 +and then I'm just calling addSubview. +然后我调用了 addSubView + +234 +00:09:43,464 --> 00:09:45,630 +But if you just do this, these three lines of code, +如果你只写这三行代码,它不会有效 + +235 +00:09:45,632 --> 00:09:48,199 +it won't work because you have to set the content size. +因为你还没有设置好 contentSize + +236 +00:09:48,201 --> 00:09:49,934 +If you don't set the content size, +如果你没有设置 contenSize + +237 +00:09:49,936 --> 00:09:52,403 +it starts out zero, until you bring your Scroll View up, +它以0开始 + +238 +00:09:52,405 --> 00:09:53,837 +and they'll be nothing there. +它上面就会什么都没有 + +239 +00:09:53,839 --> 00:09:56,773 +Because you won't have that big white area to scroll +因为你不会有那个 + +240 +00:09:56,775 --> 00:09:57,440 +around in. +巨大的白色区域来滑动 + +241 +00:09:57,442 --> 00:09:58,507 +Okay? +ok + +242 +00:09:58,509 --> 00:10:00,075 +So no matter what Sub Views you add, +不管你添加了什么 SubView + +243 +00:10:00,077 --> 00:10:02,177 +if you don't have that big white area defined, +如果你没有设置 contentSize + +244 +00:10:02,179 --> 00:10:04,279 +then Scroll View will not be showing anything. +ScrollView 就不会显示任何东西 + +245 +00:10:04,281 --> 00:10:05,646 +Okay, so it's as simple as that. +就是这么简单 + +246 +00:10:05,648 --> 00:10:08,983 +This is a review of what I showed you graphically. +这是对之前的总结 + +247 +00:10:08,985 --> 00:10:10,217 +Now you can scroll around. +现在你可以到处滑动 + +248 +00:10:10,219 --> 00:10:12,486 +The user scrolls around by just using their finger. +用户通过手指滑动 + +249 +00:10:12,488 --> 00:10:13,920 +Right? They pan around. +使用 pan 手势 + +250 +00:10:13,922 --> 00:10:16,723 +But you can scroll programmatically too by saying +你也可以通过代码滑动 + +251 +00:10:16,725 --> 00:10:20,026 +scrollRectToVisible and this will take a rectangle in the +调用 scrollRectToVisible + +252 +00:10:20,028 --> 00:10:23,462 +content areas view coordinate system, that content size. +content 区域的坐标系统 + +253 +00:10:23,464 --> 00:10:27,666 +And it'll scroll the Scroll View to be showing that. +然后使得 ScrollView 滑动到那里展示这个内容 + +254 +00:10:27,668 --> 00:10:30,034 +And animated is whether it slides over. +animated 参数是是否滑动过去 + +255 +00:10:30,036 --> 00:10:32,136 +If you don't say animated, it's just gonna jump there. +如果为 false,它会直接跳到那里 + +256 +00:10:32,138 --> 00:10:34,538 +Which is kind of abrupt to the user, if it's on screen. +这会有些唐突 + +257 +00:10:35,874 --> 00:10:37,441 +And there's tons of other things you can do +你也可以做好多别的事情 + +258 +00:10:37,442 --> 00:10:39,009 +with a Scroll View that I'm not gonna really talk about. +我不会讲太多 + +259 +00:10:39,011 --> 00:10:41,444 +But you can lock the scrolling direction, so +你可以锁定滑动的区域 + +260 +00:10:41,446 --> 00:10:44,847 +it'll only scroll up and down, or only scroll left and right. +它只能向左右滑动或上下滑动 + +261 +00:10:44,849 --> 00:10:48,316 +It'll flash the scroll indicators if the content size +如果 contentSize 修改了,scroll indicators 会闪一下 + +262 +00:10:48,318 --> 00:10:49,217 +has changed. +如果它改变了 + +263 +00:10:49,219 --> 00:10:50,918 +You can control that. +你可以控制它 + +264 +00:10:50,920 --> 00:10:53,054 +There's a whole bunch of stuff you can look at +你可以在文档中 + +265 +00:10:53,056 --> 00:10:54,722 +UIScrollView in the documentation. +看到大量的关于 ScrollView 的东西 + +266 +00:10:54,724 --> 00:10:55,822 +Okay? +Ok? + +267 +00:10:55,824 --> 00:10:59,726 +I'm going to have one thing important about +我会介绍 ScrollView 中 + +268 +00:10:59,728 --> 00:11:01,727 +scrollview which is zooming. +很重要的一个东西,就是 zooming + +269 +00:11:01,729 --> 00:11:03,713 +Cuz so +到目前为止 + +270 +00:11:03,714 --> 00:11:05,698 +far I just showed you kind of moving around and of course in +我给你们展示了怎样到处滑动 + +271 +00:11:05,700 --> 00:11:10,468 +scroll you can also zoom in on the content area, okay? +当然 ScrollView 也可以 zoom in + +272 +00:11:10,470 --> 00:11:15,906 +Zooming in requires you to do a few things though. +zoom in 需要你做一些工作 + +273 +00:11:15,908 --> 00:11:17,975 +One thing is you have to set the minimum and +其中一件事是 + +274 +00:11:17,977 --> 00:11:19,943 +maximum zoom scale. +设置 zoom scale 的最大值和最小值 + +275 +00:11:19,945 --> 00:11:23,146 +So the zoom scale is just how much you'll zoom in. +zoom scale 是你 zoom in 的程度 + +276 +00:11:23,148 --> 00:11:25,748 +So, if you have a zoom scale of 2.0, +如果设置为2.0 + +277 +00:11:25,750 --> 00:11:29,785 +then that means that you'll only zoom to twice the scale. +这表明你只能 zoom 为原来的两倍大小 + +278 +00:11:29,787 --> 00:11:33,022 +And if you're 2.5, it'll zoom down to half of whatever +2.5 表示 2.5 倍 + +279 +00:11:33,024 --> 00:11:34,923 +the normal size is of the thing you're looking at is. +normal size 是你正在观察的尺寸 + +280 +00:11:34,925 --> 00:11:36,091 +So you have to set these. +所以你需要设置这些 + +281 +00:11:36,093 --> 00:11:39,060 +If you don't set these they'll be default to 1, and +如果你没有设置这些,那默认是1 + +282 +00:11:39,062 --> 00:11:42,196 +it won't work because the scaling will go from 1 to 1. +因为 scale 只能从1到1,所以不会起作用 + +283 +00:11:42,198 --> 00:11:43,581 +Okay? And so +OK? + +284 +00:11:43,582 --> 00:11:44,965 +that means not scaling at all. +这表示根本不 scale + +285 +00:11:44,967 --> 00:11:46,800 +The other thing you have to do is use a delegate. +另一件需要做的事时使用 delegate + +286 +00:11:46,802 --> 00:11:48,735 +So here's the second time I've showed you a delegate. +这是我第二次给你们展示使用 delegate + +287 +00:11:48,737 --> 00:11:50,770 +Now I had you do all that work with a calculator to +在 calculator 中 + +288 +00:11:50,772 --> 00:11:52,371 +do the delegate so that you'd be +我使用了 delegate + +289 +00:11:52,373 --> 00:11:54,907 +ready to do things in iOS that use delegates. +第一次使用 delegate + +290 +00:11:54,909 --> 00:11:55,674 +And here's one. +这是第二次 + +291 +00:11:55,676 --> 00:11:57,475 +'Kay. You've set yourself as +你把自己设置为 ScrollView 的 delegate + +292 +00:11:57,477 --> 00:12:00,111 +the ScrollView's delegate, and you implement this method. +然后你实现它的方法 + +293 +00:12:00,113 --> 00:12:01,412 +You have to implement this method if +你需要实现这个方法 + +294 +00:12:01,414 --> 00:12:04,648 +you want zooming called viewForZoomingInScrollView. +viewForZoomingInScrollView + +295 +00:12:04,650 --> 00:12:09,119 +So the scroll view when it's zooming, it only zooms in, +当 ScrollView 在 zooming 的时候,它只 zoom in + +296 +00:12:09,121 --> 00:12:11,954 +in the coordinate systems of one of its views. +在它 view 中得坐标系统中 + +297 +00:12:11,956 --> 00:12:14,156 +So usually it's kind of the background view. +通常来说它是背景的 view + +298 +00:12:14,158 --> 00:12:15,391 +Like in that aerial example, +就像 aerial 的例子 + +299 +00:12:15,393 --> 00:12:18,160 +it would be the aerial view that we would zoom in, okay. +我们 zoom in 的是 aerial view + +300 +00:12:18,162 --> 00:12:20,095 +But we're zooming the whole contents, so +但是我们 zoom 的是整个 content + +301 +00:12:20,097 --> 00:12:21,346 +everything gets zoomed, +全部都会缩放, + +302 +00:12:21,347 --> 00:12:22,596 +but that's gonna be the view that you're zooming in. +但是你需要在一个视图里进行缩放。 + +303 +00:12:22,599 --> 00:12:24,932 +So you have to tell it which view that is. +你需要告诉系统这是哪个视图。 + +304 +00:12:24,934 --> 00:12:26,066 +It's usually pretty obvious. +通常来说这是显而易见的。 + +305 +00:12:26,068 --> 00:12:28,085 +Often times in ScrollView, +通常来说 + +306 +00:12:28,086 --> 00:12:30,103 +you're only scrolling on one view anyway but +你只会在一个视图上滚动,但是 + +307 +00:12:30,105 --> 00:12:32,405 +you still have to implement this, okay. +你依然需要实现这个方法。 + +308 +00:12:33,541 --> 00:12:35,775 +You can zoom programatically once you've set those two +正确的完成这两步后,你就可以使用代码 + +309 +00:12:35,777 --> 00:12:37,076 +things up properly. +来进行缩放了。 + +310 +00:12:37,078 --> 00:12:40,112 +Then you can set the zoom scale, how zoomed in you are. +你可以设置缩放比例。 + +311 +00:12:40,114 --> 00:12:41,713 +It looks kind of like this. +就像这样, + +312 +00:12:41,715 --> 00:12:43,114 +So, here I've got a picture. +这里有一张图片。 + +313 +00:12:43,116 --> 00:12:45,483 +Let's say my zoomScale is 1.2. +我的缩放比例是1.2. + +314 +00:12:45,485 --> 00:12:46,784 +I go to zoomScale 1. +现在改成1 + +315 +00:12:46,786 --> 00:12:50,987 +I zoom out, zoom back to 1.2 zoomed in. +然后再放大,现在是1.2. + +316 +00:12:50,989 --> 00:12:53,089 +Okay? And same thing with zoom rect. +缩放矩形也是一样的。 + +317 +00:12:53,091 --> 00:12:55,658 +So if I had a little rectangle like that yellow area and +如果我有一个黄色区域这样的小矩形。 + +318 +00:12:55,660 --> 00:12:58,861 +I said zoom to that rect, it would zoom to make that +然后我要缩放到这个矩形,图片就会缩放 + +319 +00:12:58,863 --> 00:13:01,630 +rect fill the edges as much as it could. +到尽可能适应这个矩形。 + +320 +00:13:01,632 --> 00:13:03,798 +Or if I have a rect that was really big, and +或者我有一个很大的矩形, + +321 +00:13:03,800 --> 00:13:07,335 +I said zoom it would zoom it down to fit. +图片就会缩小去适应它。 + +322 +00:13:07,337 --> 00:13:08,702 +Okay? + +323 +00:13:08,704 --> 00:13:13,440 +So, zoomToRect means make this rect kind of either go big or +所以zoomToRect方法就是提供一个矩形,然后背景放大或 + +324 +00:13:13,442 --> 00:13:14,774 +go small to fit. +缩小去适应它。 + +325 +00:13:14,776 --> 00:13:16,776 +Okay? + +326 +00:13:16,778 --> 00:13:18,143 +All right? +好的。 + +327 +00:13:18,145 --> 00:13:19,978 +There are tons of other delegate methods in +滚动视图有非常多的代理 + +328 +00:13:19,980 --> 00:13:21,730 +scroll view. +方法。 + +329 +00:13:21,731 --> 00:13:23,481 +One thing, when you start using scroll view, +这里有一个问题,当你开始使用滚动视图的时候, + +330 +00:13:23,483 --> 00:13:25,183 +you're going to ask me is, +你可能会问我, + +331 +00:13:25,185 --> 00:13:28,085 +hey, scroll view has 12 delegate methods. +滚动视图有12个代理方法。 + +332 +00:13:28,087 --> 00:13:30,854 +And when I say I implement the UIScrollView delegate +当我要实现滚动视图的代理协议时 + +333 +00:13:30,856 --> 00:13:33,790 +protocol, how come the compiler doesn't complain and +为什么编译器没有抱怨说我必须实现 + +334 +00:13:33,792 --> 00:13:36,659 +say that it will implement those 12 methods because I +这12个代理方法?我认为如果我说要实现 + +335 +00:13:36,661 --> 00:13:38,995 +thought if I said I implemented a protocol, +一个协议,我就要实现协议规定的 + +336 +00:13:38,997 --> 00:13:41,630 +I have to implement all those protocols, okay? +所有方法。 + +337 +00:13:43,300 --> 00:13:45,633 +The reason that that happens, that you don't get +编译器没有警告的原因是 + +338 +00:13:45,635 --> 00:13:48,636 +a warning there is because there is actually, for +因为一些历史原因, + +339 +00:13:48,638 --> 00:13:51,605 +historical reasons, a different kind of protocol, +还有一种其他类型的协议, + +340 +00:13:51,607 --> 00:13:54,641 +which is an Objective-C style protocol. +也就是 Objective-C 的协议。 + +341 +00:13:54,643 --> 00:13:56,276 +Objective C was the old language that iOS +Objective-C 是一种老语言,iOS就是用它写成的。 + +342 +00:13:56,278 --> 00:13:59,279 +was written in and in the Objective C style protocols +在 Objective-C 的协议里, + +343 +00:13:59,281 --> 00:14:02,248 +some methods in the protocol were allowed to be optional. +一些方法可以是可选的。 + +344 +00:14:02,250 --> 00:14:03,716 +Now that's not true in Swift, +Swift不可以这样, + +345 +00:14:03,718 --> 00:14:06,819 +but that's true in Objective C. +但是 Objective-C 可以。 + +346 +00:14:06,821 --> 00:14:11,156 +So all these old delegate protocols like +所以像滚动视图代理协议这种老的 + +347 +00:14:11,158 --> 00:14:13,658 +scroll view that have optional methods in them, +协议,里边都是有可选方法的。 + +348 +00:14:13,660 --> 00:14:16,160 +Swift knows how to bridge them. +Swift 知道如何桥接他们。 + +349 +00:14:16,162 --> 00:14:19,363 +You can actually create your own Objective C compatible +事实上你也可以自己写一个 有可选方法的 Objective-C 风格的 + +350 +00:14:19,365 --> 00:14:22,799 +protocol with optional methods by saying @objc in front of +协议,只需要在协议声明之前加上 + +351 +00:14:22,801 --> 00:14:24,534 +your protocol declaration. +@objc 。 + +352 +00:14:24,536 --> 00:14:27,403 +So where you would say protocol face view delegate or +比如你可以写一个 FaceViewDelegate 或者 + +353 +00:14:27,405 --> 00:14:29,271 +face view data source you would say +FaceViewDataSource,在声明的时候 + +354 +00:14:29,273 --> 00:14:32,007 +@objc space protocol, whatever delegate, and +写@objc 空格 protocol, + +355 +00:14:32,009 --> 00:14:34,109 +then you could put optional in there. +然后你就可以定义可选方法了。 + +356 +00:14:34,111 --> 00:14:35,744 +And you can read, +你可以在 + +357 +00:14:35,745 --> 00:14:37,378 +this is all covered in the reading assignments, so +阅读材料里读到这些内容,希望 + +358 +00:14:37,381 --> 00:14:39,547 +hopefully you've got that. +你们已经都看过了。 + +359 +00:14:39,549 --> 00:14:42,116 +But that's the magic that makes it so that when you say +正是因为有这个魔法,所以在你 + +360 +00:14:42,118 --> 00:14:44,918 +you implement the UIScrollView delegate protocol and +需要实现滚动视图代理协议的时候,你不需要 + +361 +00:14:44,920 --> 00:14:48,088 +you don't yet implement all the 12 methods in there. +实现它里边全部的12个方法。 + +362 +00:14:48,090 --> 00:14:49,656 +In fact you only need to implement the ones you +你只需要实现你想实现的方法, + +363 +00:14:49,658 --> 00:14:53,325 +want like view for zooming and scroll view. +比如缩放什么的。 + +364 +00:14:53,327 --> 00:14:54,793 +That's why that works. +这就是为什么不会报错。 + +365 +00:14:54,795 --> 00:14:55,994 +So anyway there are a bunch of +当然还有很多 + +366 +00:14:55,996 --> 00:14:57,395 +other delegate methods in there. +别的代理方法。 + +367 +00:14:57,397 --> 00:15:00,665 +For example scrollViewDidEndZooming. +比如 scrollViewDidEndZooming 。 + +368 +00:15:00,667 --> 00:15:03,467 +So that will be sent to you when the user pinches and +这个方法会在用户用手指缩放完毕离开屏幕的时候 + +369 +00:15:03,469 --> 00:15:05,302 +then they lift their finger up. +被调用。 + +370 +00:15:05,304 --> 00:15:06,603 +'Kay? And it'll say oh, +它会知道 + +371 +00:15:06,605 --> 00:15:08,371 +the user has finished zooming and +用户现在已经结束缩放,而且也能知道 + +372 +00:15:08,373 --> 00:15:10,673 +this is the scale they left it at. +现在的缩放比例。 + +373 +00:15:10,675 --> 00:15:13,142 +And you, at that point, might want to redraw your view to +在这个时间点,你可能需要重绘你的视图让它看上去 + +374 +00:15:14,278 --> 00:15:16,511 +be less grainy, or something like that. +不那么模糊,或者类似的事儿。 + +375 +00:15:16,513 --> 00:15:18,747 +If you do redraw your view at the new scale, +如果你确实要在新的缩放比例重绘视图, + +376 +00:15:18,749 --> 00:15:21,616 +you want to make sure you reset the transform. +那么你需要确保你重置了 transform 。 + +377 +00:15:21,618 --> 00:15:22,850 +Okay. This property on +这是一个视图的属性, + +378 +00:15:22,852 --> 00:15:25,953 +view called transform is an Affine transform. +它是一种仿射变换。 + +379 +00:15:25,955 --> 00:15:28,789 +Really that's all scroll view is modifying. +当你在滚动视图上滑动手指或者 + +380 +00:15:28,791 --> 00:15:29,989 +When you pan around and +所缩放操作的时候, + +381 +00:15:29,991 --> 00:15:32,759 +zoom in, it's just modifying the property transform. +实际上就是在改动这个属性。 + +382 +00:15:32,761 --> 00:15:35,261 +So, you can go look at the documentation for transform in +你们可以去看视图里 transform的文档去 + +383 +00:15:35,263 --> 00:15:37,196 +view to understand what's going on there. +深入了解一下。 + +384 +00:15:37,198 --> 00:15:40,699 +Yeah, it makes scroll view really easy in that it +这使得滚动视图的操作很好理解,因为都是 + +385 +00:15:40,701 --> 00:15:42,233 +just is modifying this transform. +在改变这个属性。 + +386 +00:15:43,370 --> 00:15:44,235 +All right, so that's scroll view. +好,这就是滚动视图。 + +387 +00:15:44,237 --> 00:15:45,636 +So, I have a demo of scroll view. +下边有一个滚动视图的演示。 + +388 +00:15:45,638 --> 00:15:46,937 +We're going to learn some other +在做这个演示的时候,我们还会学 + +389 +00:15:46,939 --> 00:15:49,039 +things along the way while we're doing that. +一些其他的东西。 + +390 +00:15:49,041 --> 00:15:52,408 +Okay, let's do that. +开始 + +391 +00:15:52,410 --> 00:15:53,476 +Let's go over here. +这里 + +392 +00:15:53,478 --> 00:15:54,977 +We're gonna start from scratch again. +我们从头开始做。 + +393 +00:15:54,979 --> 00:15:57,446 +So I'm gonna create a new Xcode project. +建一个新的Xcode项目。 + +394 +00:15:57,448 --> 00:15:58,914 +'Kay. It's gonna be Single View. +单视图应用。 + +395 +00:15:58,915 --> 00:16:00,381 +Those of you who like to follow along are not gonna be +想跟着做的人今天可能 + +396 +00:16:00,384 --> 00:16:01,015 +able to today. +不行了。 + +397 +00:16:01,017 --> 00:16:02,183 +Sorry. +不好意思。 + +398 +00:16:02,185 --> 00:16:05,452 +Because I'm going to be dragging in a file with some +因为我要直接拖一个有很多URL的文件 + +399 +00:16:05,454 --> 00:16:07,855 +URLs in it. +进来。 + +400 +00:16:07,856 --> 00:16:10,257 +I'm going to call this thing Cassini. +给项目起名叫cassini。 + +401 +00:16:10,259 --> 00:16:12,826 +That's going to be the name of my app. +这个就是我的应用的名字。 + +402 +00:16:12,828 --> 00:16:14,794 +And I'm gonna put it where I always put everything. +还放在原来的地方。 + +403 +00:16:15,763 --> 00:16:18,831 +All right, I'm not going to be doing anything with the app +跟原来一样,我们不需要改动AppDelegate这个 + +404 +00:16:18,833 --> 00:16:19,898 +delegate as usual. +文件。 + +405 +00:16:19,900 --> 00:16:21,599 +I'm not going to be doing image assets. +这次也不改动图片库。 + +406 +00:16:21,601 --> 00:16:24,035 +I'm not going to do the launch screen. +不改动启动屏幕。 + +407 +00:16:24,037 --> 00:16:27,138 +So, here I just have a simple storyboard. +只需要这个简单的 storyboard。 + +408 +00:16:27,140 --> 00:16:28,472 +I'm gonna also get rid of +这些关于视图控制器 + +409 +00:16:28,474 --> 00:16:30,574 +all this ViewController life cycle here. +生命周期的方法也没用。 + +410 +00:16:30,576 --> 00:16:31,174 +I don't need that. +这次不需要。 + +411 +00:16:32,410 --> 00:16:33,809 +Get rid of that. +删掉。 + +412 +00:16:33,811 --> 00:16:37,112 +And so here, simple storyboard only has this one +现在这个简单的storyboard只有一个叫 + +413 +00:16:37,114 --> 00:16:40,382 +view controller here called ViewController. +ViewController的视图控制器。 + +414 +00:16:40,384 --> 00:16:41,683 +And I'm not even gonna pay any attention to +而且我也不需要关注这个 + +415 +00:16:41,685 --> 00:16:43,168 +this view controller. +视图控制器。 + +416 +00:16:43,169 --> 00:16:44,652 +Actually, I'm gonna create a new view controller. +我要建一个新的视图控制器。 + +417 +00:16:44,654 --> 00:16:47,722 +I'm gonna drag it out here and this new view controller, +从这拖一个出来,这个新的视图控制器 + +418 +00:16:47,724 --> 00:16:51,958 +its only job in life it's going to display an image. +唯一的任务就是显示一个图片。 + +419 +00:16:51,960 --> 00:16:56,662 +So I'm going give it the URL of an image, a JPEG file or +我可能会传递给它一个图片的URL,JPEG文件或者别的 + +420 +00:16:56,664 --> 00:16:59,765 +whatever, and it's going to display it. +什么东西,反正就是显示图片。 + +421 +00:16:59,767 --> 00:17:01,734 +That's going to be its job in life. +这就是它全部的工作。 + +422 +00:17:01,736 --> 00:17:03,669 +So I need a new view controller for that. +我需要一个新的视图控制器文件。 + +423 +00:17:03,671 --> 00:17:06,504 +So I'm going to call this new view controller. +我要给它起名叫。。。。 + +424 +00:17:06,506 --> 00:17:07,822 +All right? I'm going here, +点这, + +425 +00:17:07,823 --> 00:17:09,139 +Cocoa Touch Class, it's a view controller. +Cocoa Touch 类,视图控制器。 + +426 +00:17:09,142 --> 00:17:11,842 +I'm gonna call it ImageViewController. +起名叫 ImageViewController 。 + +427 +00:17:11,844 --> 00:17:14,278 +Cuz that's what it does, it displays an image. +因为这就是它要干的活,显示一张图片。 + +428 +00:17:14,280 --> 00:17:16,180 +Okay? Very, very simple. +非常简单。 + +429 +00:17:16,181 --> 00:17:18,081 +I'm gonna put it where all the rest of my stuff goes, there. +把它跟我其他的东西放到一起,这。 + +430 +00:17:19,017 --> 00:17:20,183 +All right? So here we go again. +好了,又要来一次, + +431 +00:17:20,185 --> 00:17:21,484 +Again, I'm gonna get rid of my +把所有的视图控制器生命周期 + +432 +00:17:21,486 --> 00:17:22,985 +view controller life cycle there. +相关的方法删掉。 + +433 +00:17:22,987 --> 00:17:25,787 +We're gonna actually add some of those back, +实际上一会儿可能会加一些方法回来, + +434 +00:17:25,789 --> 00:17:28,857 +cuz part of the reason I'm doing this demo, also, +这也是我们做这个演示的一部分, + +435 +00:17:28,859 --> 00:17:30,925 +is to show you a little bit where and +会给你们演示一些视图控制器生命 + +436 +00:17:30,927 --> 00:17:34,128 +why, how we would use a view controller life cycle. +周期的内容。 + +437 +00:17:34,130 --> 00:17:37,097 +So, my ImageViewController, one other thing, +还有一个事, + +438 +00:17:37,099 --> 00:17:40,667 +let me make sure in our storyboard here, we got this thing, +我得确认一下在storyboard里, + +439 +00:17:40,669 --> 00:17:43,436 +I'm gonna make sure I change the identity of it +我要把这个视图控制器的类改成 + +440 +00:17:43,438 --> 00:17:45,371 +to be an ImageViewController. +ImageViewController + +441 +00:17:45,373 --> 00:17:47,506 +So this is an ImageViewController. +现在是 ImageViewController 了。 + +442 +00:17:47,508 --> 00:17:51,710 +This is an easy thing to forget, but do that. +这个事情非常容易忘。 + +443 +00:17:51,712 --> 00:17:54,479 +Okay, so what do I need in my ImageViewController. +在我的 ImageViewController 里, + +444 +00:17:54,481 --> 00:17:57,048 +Well, I need a UIImageView. +我需要一个 UIImageView 。 + +445 +00:17:57,050 --> 00:17:59,550 +We saw that in the Auto Layout demo. +我们在自动布局的演示里见过了。 + +446 +00:17:59,552 --> 00:18:02,286 +It's a just a view, kind of like a UI label for images. +它就是一种视图,一种显示图片的标签。 + +447 +00:18:02,288 --> 00:18:03,787 +Obviously if I'm going to have ImageViewController, +显然如果我要做一个显示图片的视图控制器, + +448 +00:18:03,789 --> 00:18:05,656 +I'm going to need one of those. +我肯定需要一个这个东西。 + +449 +00:18:05,657 --> 00:18:07,524 +Now, I could just drag it out into my story board, but +我可以从storyboard里拖一个进去,但是 + +450 +00:18:07,526 --> 00:18:10,560 +I want to use this demo as an example to show you +我希望通过这个演示给你们看一下如何通过代码 + +451 +00:18:10,562 --> 00:18:14,096 +how you create a view in code, create and use a view in code. +来新建一个视图并使用它。 + +452 +00:18:14,098 --> 00:18:17,700 +So instead, I'm just gonna have a private var here. +这里我建一个私有变量。 + +453 +00:18:17,702 --> 00:18:19,534 +I'm gonna call it imageView. +我叫它 imageView 。 + +454 +00:18:19,536 --> 00:18:21,736 +And it's going to be a UIImageView. +类型是 UIImageView。 + +455 +00:18:21,738 --> 00:18:24,105 +In fact, I'm just gonna create it right here. +我要在这直接新建。 + +456 +00:18:24,107 --> 00:18:25,089 +Okay. + +457 +00:18:25,090 --> 00:18:26,072 +So I have this image view. +现在我又了这个图片视图。 + +458 +00:18:26,075 --> 00:18:27,574 +I'm just calling it there. +我在这直接新建了。 + +459 +00:18:27,576 --> 00:18:29,242 +Notice, I'm not using the frame. +注意我没用frame新建。 + +460 +00:18:29,244 --> 00:18:30,443 +So it's going to create this image view. +所以我这个新的图片视图 + +461 +00:18:30,445 --> 00:18:32,812 +It's going to be zero, zero, by zero, zero. +的frame就是 + +462 +00:18:32,814 --> 00:18:34,380 +It's going to be, it's framed. +(0,0,0,0) + +463 +00:18:34,382 --> 00:18:37,383 +It's going to be, now it's not in any super view anyways, so +现在它不属于任何视图, + +464 +00:18:37,385 --> 00:18:39,184 +it really doesn't matter what its frame is yet. +所以它的frame 是啥也不重要。 + +465 +00:18:39,186 --> 00:18:40,418 +Okay. It's obviously going to +当然,在我们让它显示 + +466 +00:18:40,420 --> 00:18:42,920 +matter a lot once we start putting images in there. +图片的时候就很重要了。 + +467 +00:18:42,922 --> 00:18:46,157 +I'm also going to create a little private var +这里我还要写一个叫 image 的 + +468 +00:18:46,159 --> 00:18:48,058 +here called image. +私有变量。 + +469 +00:18:48,060 --> 00:18:50,127 +And this is going to be a computed var. +这是一个计算属性。 + +470 +00:18:50,129 --> 00:18:51,695 +I did this in Auto Layout as well. +在自动布局演示里我做过。 + +471 +00:18:51,697 --> 00:18:54,063 +It's going to be a UIImage. +它是UIImage类型的。 + +472 +00:18:54,065 --> 00:18:57,099 +And all I'm going to to here in the getter, +在 getter 方法里, + +473 +00:18:57,101 --> 00:19:00,536 +I'm just going to return the imageView's image. +我让它返回 imageView.image 。 + +474 +00:19:00,538 --> 00:19:02,438 +And in the setter, +在 setter 方法里, + +475 +00:19:02,439 --> 00:19:04,339 +I'm basically just going to set the imageView's image to +我直接就写 imageView.image = newValue. + +476 +00:19:04,341 --> 00:19:05,507 +the new value. + +477 +00:19:05,509 --> 00:19:07,041 +Now, why do I do this? +为什么要这么做? + +478 +00:19:07,043 --> 00:19:09,310 +'Kay, I'm doing this for +我这么做的原因 + +479 +00:19:09,311 --> 00:19:11,578 +the exact same reason that I was doing it in the other one, +跟我之前做的完全一样, + +480 +00:19:11,581 --> 00:19:14,848 +which is that when the image is set in my imageView, +我希望我的 imageView 的图片设定好以后, + +481 +00:19:14,850 --> 00:19:17,117 +I want to be able to do things, I want to intervene. +我可以对它做事,我可以干预它。 + +482 +00:19:17,119 --> 00:19:19,719 +So I basically I want to kind of be able to do +所以我想要做一些 + +483 +00:19:19,721 --> 00:19:22,955 +the did set kind of thing to make that work. +类似于didSet的事情。 + +484 +00:19:24,692 --> 00:19:28,126 +So, what's my warning here, UIImage. +啊,这个警告是什么,UIImage 。 + +485 +00:19:28,128 --> 00:19:31,830 +Okay, so here we go. +好了。 + +486 +00:19:31,832 --> 00:19:34,766 +So in other words right here, when this is set, +换句话说,当这个设置的时候, + +487 +00:19:34,768 --> 00:19:36,167 +when this image gets set. +当这个图片设置的时候。 + +488 +00:19:36,169 --> 00:19:38,769 +Setting this image just is going to set the image in +设置这个图片就是设置了imageView的图片, + +489 +00:19:38,771 --> 00:19:40,570 +the imageView, that's all it does. +这是这句代码的意思。 + +490 +00:19:40,572 --> 00:19:42,072 +But I can put other code that I +下边我还想加更多的 + +491 +00:19:42,074 --> 00:19:43,539 +want down here because I'm going to +代码,因为我希望在我的图片变更的时候 + +492 +00:19:43,541 --> 00:19:45,975 +need to do some things every time my image changes. +可以做更多的事情。 + +493 +00:19:45,977 --> 00:19:48,577 +I don't care about getting but every time my +我不关心 getter,但是每次图片设置了 + +494 +00:19:48,579 --> 00:19:51,880 +image gets set in my imageView I need to do some stuff. +的时候我希望imageView可以做一些事情。 + +495 +00:19:51,882 --> 00:19:52,447 +Let me see. +那么 + +496 +00:19:52,449 --> 00:19:55,249 +Well, let's talk about what some of those things might be. +让我们看看可以做什么。 + +497 +00:19:55,251 --> 00:19:57,301 +For example, +比如, + +498 +00:19:57,302 --> 00:19:59,352 +when I set it I probably want to do imageView.sizeToFit. +当我设置图片的时候,我希望做 imageView.sizeToFit 。 + +499 +00:20:00,823 --> 00:20:02,622 +Okay. So when you change the image +当我们改变图片视图里的图片时, + +500 +00:20:02,624 --> 00:20:05,625 +that's in image view, this is kind of like saying label.text +这个就好像是 label.text 等于什么什么。 + +501 +00:20:05,627 --> 00:20:08,661 +equals something, right, I'm changing the imageView that, +事实上我是在修改图片视图, + +502 +00:20:08,663 --> 00:20:10,729 +the image that the imageView's showing. +修改它的显示的图片。 + +503 +00:20:10,731 --> 00:20:13,699 +When you change it, it does not change the bounds or +但是当我们改这个的时候,不会改变图片视图的bounds + +504 +00:20:13,701 --> 00:20:15,400 +the frames of the image view. +或者frame。 + +505 +00:20:15,402 --> 00:20:18,069 +So, sizeToFit causes it to. +sizeToFit 可以。 + +506 +00:20:18,071 --> 00:20:21,872 +So ImageView looks at the image, sees how big it is and +图片视图会观察图片,看它有多大,然后根据这个来拓展自己的 + +507 +00:20:21,874 --> 00:20:23,707 +expands its frame to fit. +frame去适应它。 + + +508 +00:20:23,709 --> 00:20:26,676 +So that's clearly something I'm going to do every time I +这个很显然在我每次变更图片的时候希望 + +509 +00:20:26,678 --> 00:20:28,044 +change the image I want to do that. +做到的。 + +510 +00:20:28,046 --> 00:20:31,013 +So now you can see why I have this nice little convenience. +所以现在你知道我为啥要这么做了。 + +511 +00:20:31,015 --> 00:20:32,915 +You can kind of think this is similar to +你可以把它想成setImage + +512 +00:20:32,917 --> 00:20:35,450 +having a function called setImage. +方法。 + +513 +00:20:35,452 --> 00:20:37,619 +But it's just nicer to do it as a property cuz then I +但是把它当作属性这样处理更好,我同时有了 getter 和 setter, + +514 +00:20:37,621 --> 00:20:41,089 +get set and get and my code looks really nice. +而且代码更漂亮。 + +515 +00:20:41,091 --> 00:20:43,691 +'Kay, so there's that. +这个完事了。 + +516 +00:20:43,693 --> 00:20:47,828 +I'm also going to do viewDidLoad, okay? +下边我要实现一下 viewDidLoad 。 + +517 +00:20:47,830 --> 00:20:50,597 +So viewDidLoad, we know that we of course need to call +首先,我们当然需要调用super, + +518 +00:20:50,599 --> 00:20:53,099 +super, and what I'm gonna do in viewDidLoad? +我要在 viewDidLoad 里做什么呢? + +519 +00:20:53,101 --> 00:20:56,135 +Well, I'm just gonna add my imageView to +我需要把图片视图加入到 + +520 +00:20:56,137 --> 00:20:58,637 +the view hierarchy. +视图的继承树里。 + +521 +00:20:58,639 --> 00:21:00,506 +Okay, I'm going to plop it right here. +我要把它放在这。 + +522 +00:21:00,508 --> 00:21:02,507 +Again my storyboard, got this thing, +在我的storyboard里,要把这个视图 + +523 +00:21:02,509 --> 00:21:04,042 +got my view as a top level view. +作为顶级视图。 + +524 +00:21:04,044 --> 00:21:05,743 +I'm just going to add my view in here. +我现在要把图片视图加进来。 + +525 +00:21:05,745 --> 00:21:07,878 +Now, I'm not doing a scroll view yet, okay. +到目前,我还没开始做滚动视图。 + +526 +00:21:07,880 --> 00:21:09,513 +I'm going to do it without a scroll view, so +我现在要通过不使用滚动视图来实现,然后看看 + +527 +00:21:09,515 --> 00:21:12,549 +we can see what that looks like. +是什么样的。 + +528 +00:21:12,550 --> 00:21:15,584 +So I'm just gonna say view, addSubView, my ImageView. +我这里写 view.addSubView(ImageView) + +529 +00:21:17,055 --> 00:21:19,021 +Okay, and we know that this is fine to do because +这样做没有问题因为我们知道 + +530 +00:21:19,023 --> 00:21:23,291 +viewDidLoad happens after pretty late in the process. +viewDidLoad 会在很晚才回被调用。 + +531 +00:21:23,293 --> 00:21:26,127 +Now, I'm not doing anything here that's geometry based. +现在我做的事儿跟尺寸什么的没有关系。 + +532 +00:21:26,129 --> 00:21:29,263 +I don't set any frames or anything like that, so this is +我没有设置frame或者别的什么,我就仅仅 + +533 +00:21:29,265 --> 00:21:31,866 +just putting the ImageView in there with whatever frame it +把图片视图加了进来,并不管它的frame是多大, + +534 +00:21:31,868 --> 00:21:36,269 +has, either from the last sizeToFit that it got or +不论它从 sizeToFit得到的尺寸还是仍然是0, + +535 +00:21:36,271 --> 00:21:38,238 +it's still zero, zero because it's never been set. +0是因为它还没设置 frame 。 + +536 +00:21:39,274 --> 00:21:40,356 +Okay. + +537 +00:21:40,357 --> 00:21:41,439 +So I'm just adding it as a subview there. +我仅仅是加了一个子视图而已。 + +538 +00:21:42,810 --> 00:21:45,977 +Now, let's talk about what the model is in this +现在我们还看一下这个视图控制器的 + +539 +00:21:45,979 --> 00:21:46,578 +view controller. +model是什么。 + +540 +00:21:46,580 --> 00:21:48,363 +What is it's model? +它的model。 + +541 +00:21:48,364 --> 00:21:50,147 +Look for the model right at the top here. +咱们把model加在最上边。 + +542 +00:21:50,150 --> 00:21:54,218 +It's model is going to be into public. +model应该是公有的。 + +543 +00:21:54,220 --> 00:21:56,086 +It's going to be a public resettable model, +应该是公有并且可以重置的, + +544 +00:21:56,088 --> 00:21:58,555 +which is an image URL. +它是图片的URL。 + +545 +00:21:58,557 --> 00:22:02,091 +And it's just going to be an NSURL, so an NSURL is a class +类型是 NSURL,NSURL是用来存储 NSURL 的类, + +546 +00:22:02,093 --> 00:22:07,363 +that holds a URL, like http:// some Stanford.edu something +比如类似 http://Stanford.edu 的东西。 + +547 +00:22:07,365 --> 00:22:09,931 +and that's going to be the model, and every time we +这就是我们的model,每次设置它的时候,我们就会得到 + +548 +00:22:09,933 --> 00:22:13,068 +set the model it's going to get to that image and +它相应的图片然后把 + +549 +00:22:13,070 --> 00:22:16,204 +put it in the view, okay? +图片放到视图里。 + +550 +00:22:16,206 --> 00:22:18,205 +Everyone understand our nice model here. +大家都明白这个很棒的model了吧。 + +551 +00:22:18,207 --> 00:22:20,291 +It's a very, +这是一个非常 + +552 +00:22:20,292 --> 00:22:22,376 +this is a very well designed MVC it has a very clear model. +设计的非常好的MVC,有一个非常清晰的model。 + +553 +00:22:22,378 --> 00:22:25,045 +It's clear what it does in its view. +model对于视图的作用也非常清晰。 + +554 +00:22:25,047 --> 00:22:27,881 +So one thing that whenever our model is set, +只要我们的model设置了, + +555 +00:22:27,883 --> 00:22:31,184 +though, we want to make sure that we update our UI. +我们就希望UI可以确保被更新。 + +556 +00:22:31,186 --> 00:22:34,954 +So when our, if we set a new image URL I'm immediately +如果我们设置了一个新的图片URL,我就会把现有的 + +557 +00:22:34,956 --> 00:22:38,657 +going to set whatever existing image we have to nil. +图片设置为空。 + +558 +00:22:38,659 --> 00:22:39,791 +Because we're changing it, +因为我们要变更图片, + +559 +00:22:39,793 --> 00:22:43,327 +and then I'm going to call a function fetchImage. +然后我要调用一个fetchImage方法。 + +560 +00:22:47,800 --> 00:22:49,783 +Okay? And + +561 +00:22:49,784 --> 00:22:51,767 +fetchImage is just going to fetch the image that's in +这个方法会根据URL提取图片, + +562 +00:22:51,770 --> 00:22:55,672 +the URL, and load it up into my image view. +并把图片载入到图片视图里。 + +563 +00:22:55,674 --> 00:23:01,877 +So, I need this private function fetchImage, okay? +所以我们需有一个私有方法 fetchImage 。 + +564 +00:23:01,879 --> 00:23:04,546 +So let's talk about how we get an image from a URL. +下面我们看看如何从一个URL里提取图片。 + +565 +00:23:04,548 --> 00:23:07,349 +If someone give me a URL, how do I get the JPEG image or +如果有人给了我一个URL,我如何才能得到JPEG图片或者 + +566 +00:23:07,351 --> 00:23:09,451 +whatever that goes along to it? +里面的其他内容? + +567 +00:23:09,453 --> 00:23:11,152 +And it turned out to be quite simple. +非常简单。 + +568 +00:23:11,154 --> 00:23:16,056 +First, I'm gonna make sure that my image URL is not nil. +首先,我要确保这个图片的URL不为空。 + +569 +00:23:16,058 --> 00:23:18,892 +If someone asks me to load up nil, +如果有人要求我载入一个空的URL, + +570 +00:23:18,894 --> 00:23:20,160 +I'm not gonna do anything. +我就什么都不做。 + +571 +00:23:20,162 --> 00:23:23,362 +So I'm just gonna basically ignore that. +忽略掉它。 + +572 +00:23:24,465 --> 00:23:27,032 +So if it's not nil, so my URL is not nil, I'm gonna go and +如果不为空,我的URL不为空,我就要到 + +573 +00:23:27,034 --> 00:23:30,435 +go out to the Internet, or if it was a local file, +网上或者本地,因为它也有可能是一个本地 + +574 +00:23:30,437 --> 00:23:33,504 +it would be the local file, and get the image data. +文件,去拿到图片的数据。 + +575 +00:23:33,506 --> 00:23:35,806 +So I'm gonna say imageData equals, and +这里写 imageData 等于 + +576 +00:23:35,808 --> 00:23:37,608 +I can do that with the class NSData. +这里我要用 NSData 类, + +577 +00:23:37,610 --> 00:23:41,111 +And you'll remember NSData from a long-ago lecture, +也许你会记得 NSData 在很久以前的一堂课上讲到过, + +578 +00:23:41,113 --> 00:23:43,079 +maybe lecture three or four. +第三课或者第四课吧。 + +579 +00:23:43,081 --> 00:23:45,481 +NSData is just a bag of bits. +NSData 就是一个装比特的包裹。 + +580 +00:23:45,483 --> 00:23:47,783 +Right? So I'm gonna reach out on the +所以我现在要到网上 + +581 +00:23:47,785 --> 00:23:51,887 +Internet and grab the bag of bits, which is this JPEG file. +把这个包裹抓下来,这个包里就是一个JPEG文件。 + +582 +00:23:51,889 --> 00:23:55,123 +And I do that by using contentsOfURL initializer +这里用 contentOfUrl 这个初始化器 + +583 +00:23:55,125 --> 00:23:57,325 +here, and I just give it the URL. +然后把URL传递给它。 + +584 +00:23:57,327 --> 00:23:59,860 +So I can go out and get that. +然后我就在网上得到数据了。 + +585 +00:23:59,862 --> 00:24:01,895 +Now this could return nil. +但是这个是有可能返回空值的。 + +586 +00:24:01,897 --> 00:24:04,398 +What if I just gave it some bogus URL, 'kay? +如果我传递了一个假的URL呢? + +587 +00:24:04,400 --> 00:24:05,699 +There's no file there. +里边没有文件。 + +588 +00:24:05,701 --> 00:24:08,401 +So let's check and make sure this is nil. +我们需要检查它是否为空。 + +589 +00:24:08,403 --> 00:24:13,939 +So I'm gonna say if the imageData does not equal nil. +这里写 if imageData != nil + +590 +00:24:13,941 --> 00:24:16,675 +Why do I keep getting the caps lock there? +我怎么一直开着大写? + +591 +00:24:16,677 --> 00:24:18,576 +I'm not really sure what I'm doing there. +实在不知道我在干嘛。 + +592 +00:24:18,578 --> 00:24:20,511 +ImageData does not equal nil, +ImageData 不等于空, + +593 +00:24:20,513 --> 00:24:23,714 +then I can do something about it, else, I can't. +然后我就可以对它做些什么了,如果为空,就不能。 + +594 +00:24:24,683 --> 00:24:29,185 +So I could do if let, by the way, here, but +我可以写成 if let,但是我这么写 + +595 +00:24:29,187 --> 00:24:30,286 +I'm doing it this way for a reason. +是有原因的。 + +596 +00:24:30,288 --> 00:24:32,621 +You'll see a little bit later. +一会儿你就知道了。 + +597 +00:24:32,623 --> 00:24:34,756 +So if the imageData's not nil, what am I gonna do? +如果imageData不为空,我要做什么呢? + +598 +00:24:34,758 --> 00:24:37,492 +Well, I need to turn that imageData, that bag of bits, +我要把imageData,装着比特的包裹, + +599 +00:24:37,494 --> 00:24:39,160 +into a UIImage. +转化成一个UIImage对象。 + +600 +00:24:39,162 --> 00:24:42,896 +UIImage is the class in iOS that represents an image. +UIImage是iOS里展示图片的类。 + +601 +00:24:42,898 --> 00:24:44,131 +So that's really easy to do. +非常容易实现。 + +602 +00:24:44,133 --> 00:24:45,565 +I'm just gonna say, +我只需要写, + +603 +00:24:45,567 --> 00:24:48,835 +in fact, I'm just gonna assign it to my image. +我要把它赋予image变量里。 + +604 +00:24:48,837 --> 00:24:50,836 +I'm sorry, we don't need self there. +啊,对不起,这里不需要写self。 + +605 +00:24:50,838 --> 00:24:54,973 +I would say image equals UIImage with the data +写 UIImage(data: ) + +606 +00:24:54,975 --> 00:24:57,241 +being that imageData. +参数是刚才的imageData。 + +607 +00:24:59,379 --> 00:25:01,846 +Okay? + +608 +00:25:01,847 --> 00:25:04,314 +Now, otherwise, I'm just gonna say my image equals nil, 'kay? +要不然,我的image就为空。 + +609 +00:25:04,316 --> 00:25:09,252 +And, remember, this image equals something like this is +记住我们给image赋值的时候,这里的代码 + +610 +00:25:09,254 --> 00:25:12,288 +just calling this right down here to +就会被执行。 + +611 +00:25:12,290 --> 00:25:16,625 +set the image in our imageView or whatever, okay? +给我们的图片视图设置一个图片。 + +612 +00:25:16,627 --> 00:25:19,327 +And then, of course, this needs to be unwrapped. +当然,data需要解包。 + +613 +00:25:19,329 --> 00:25:21,196 +But we know we can unwrap it because I +我们知道这个肯定可以解包,因为我之前 + +614 +00:25:21,198 --> 00:25:22,363 +checked to make sure it's not nil. +检查过以确保它不为空。 + +615 +00:25:23,733 --> 00:25:29,403 +Okay, now, this line of code is a very bad line of code for +现在我们回头来看,这行代码是非常有问题的 + +616 +00:25:29,405 --> 00:25:32,472 +us because it might go out over the network. +因为它会访问网络。 + +617 +00:25:33,808 --> 00:25:35,240 +Okay? I could be on cellular. +我可能在用蜂窝网络。 + +618 +00:25:35,242 --> 00:25:39,644 +This might take ten seconds, or a minute, or it might just +这个操作可能需要10秒,甚至一分钟,也有可能 + +619 +00:25:39,646 --> 00:25:44,448 +fail because I have no network connectivity right now, okay? +因为没有网络连接而直接失败。 + +620 +00:25:44,450 --> 00:25:47,651 +So this is not a line of code we wanna be executing in +我们不希望在我们的程序里有这样 + +621 +00:25:47,653 --> 00:25:50,020 +our program, but +的代码。 + +622 +00:25:50,021 --> 00:25:52,388 +we don't know what to do about it right now and I'm gonna +但是我们现在还不知道怎么做,在这次课的后边我会讲到 + +623 +00:25:52,391 --> 00:25:55,759 +show you later in the lecture what we can do about it. +应该怎么做。 + +624 +00:25:55,761 --> 00:25:58,394 +So, for now, we just got this kind of bummer line of +现在我们先把这行会让我们程序变得很慢 + +625 +00:25:58,396 --> 00:26:00,629 +code here that's gonna be really slow. +的烂代码放在这。 + +626 +00:26:00,631 --> 00:26:02,531 +Our app is gonna be really slow. +我们的程序会因为它变的很慢 + +627 +00:26:02,533 --> 00:26:04,833 +Although the network at Stanford here is so、 +尽管斯坦福大学的网很快所以你可能 + +628 +00:26:04,835 --> 00:26:07,702 +fast that it probably won't even seem that slow, but +感觉不到慢,但是 + +629 +00:26:07,704 --> 00:26:10,738 +it will be slow cuz I'm gonna grab some pretty huge images. +如果我要下载一些很大的图片,它就会慢下来。 + +630 +00:26:11,974 --> 00:26:16,076 +All right, there's one other thing I wanna show here in +下面我可能会给你们看一些关于 + + +631 +00:26:16,078 --> 00:26:20,346 +terms of view controller life cycle, though, which is, +viewcontroller生命周期的东西。如果 + +632 +00:26:20,348 --> 00:26:23,315 +if someone sets my imageURL, okay, and +有人设置了图片的URL。但是 + +633 +00:26:23,317 --> 00:26:26,552 +I'm not on screen, do I really want to go and +我们的app不在这个界面上,我是不是需要开始用客户的 + +634 +00:26:26,554 --> 00:26:30,155 +start using up their cellular data plan, okay? +蜂窝网络开始下载呢? + +635 +00:26:30,157 --> 00:26:32,357 +Probably not, 'kay? +不应该这样,对吧? + +636 +00:26:32,359 --> 00:26:35,693 +You gotta remember that people don't have Stanford WiFi +人们不可能在哪都能连到 + +637 +00:26:35,695 --> 00:26:37,094 +internet everywhere. +斯坦福的wifi。 + +638 +00:26:37,096 --> 00:26:40,731 +Some people are using cellular, and it costs money. +很多人在用蜂窝网络,是花钱的。 + +639 +00:26:40,733 --> 00:26:43,800 +So I am not going to actually fetch this +所以如果我不在这个界面上的时候,我不希望 + +640 +00:26:43,802 --> 00:26:46,769 +image unless I'm currently on screen. +图片开始下载。 + +641 +00:26:48,239 --> 00:26:50,272 +So how do I tell if I'm currently on screen? +那我怎么知道是不是在这个界面呢? + +642 +00:26:50,274 --> 00:26:53,475 +Actually I can do that with view.window does not +我可以这么做,view.window != nil + +643 +00:26:53,477 --> 00:26:55,943 +equal nil, 'kay? + +644 +00:26:55,945 --> 00:26:59,180 +So remember view is our top level view in our +view这个属性是我们viewcontroller最顶层的 + +645 +00:26:59,182 --> 00:27:03,217 +controller's view ,and .window is the UI window it's in, +视图,它的window属性如果为空,就说明 + +646 +00:27:03,219 --> 00:27:08,254 +which will be nil if it's not currently on screen, 'kay? +我们现在不在当前的界面上。 + +647 +00:27:08,256 --> 00:27:09,856 +But there's a little bit of a problem here, +但是这里有个小问题, + +648 +00:27:09,858 --> 00:27:14,326 +which is what if I'm offscreen and someone sets my imageURL, +如果我不在这个界面,有人设置了图片的URL。 + +649 +00:27:14,328 --> 00:27:16,795 +I don't fetch the image, and then I come on screen? +图片不会开始下载,但是如果我之后回来了呢? + +650 +00:27:16,797 --> 00:27:18,329 +Aah! + +651 +00:27:18,331 --> 00:27:20,631 +Then I gotta fetch the image, 'kay? +那么我就应该开始下载,对吧? + +652 +00:27:20,633 --> 00:27:22,366 +So where does that happen? +那在哪实现这个部分呢? + +653 +00:27:22,368 --> 00:27:25,002 +Anyone wanna hazard a guess where I would put that code? +有人想猜一下我应该把代码放在哪吗? + +654 +00:27:27,272 --> 00:27:28,971 +Nobody? +没有人? + +655 +00:27:28,973 --> 00:27:31,207 +ViewWillAppear, exactly, very good. +ViewWillAppear,没错,非常好。 + +656 +00:27:31,209 --> 00:27:33,142 +So in viewWillAppear down here, +在 ViewWillAppear 里, + +657 +00:27:33,144 --> 00:27:35,644 +I'm gonna say super.viewWillAppear. +先要调用 super.ViewWillAppear。 + +658 +00:27:36,880 --> 00:27:41,549 +And then I'm just gonna say, if my image is nil, +然后这里我要写,如果我的图片为空, + +659 +00:27:41,551 --> 00:27:44,551 +then fetch the image, 'kay? +那么就开始下载图片。 + +660 +00:27:44,553 --> 00:27:46,253 +Now it could be that my image is nil because I +有可能我的图片为空是因为我尝试下载 + +661 +00:27:46,255 --> 00:27:47,687 +tried to fetch it and it failed, but +但是失败了,这里就会再试一次,然后 + +662 +00:27:47,689 --> 00:27:50,423 +it's just gonna try again and fail, that's okay. +可能又失败了,不过这样没问题。 + +663 +00:27:50,425 --> 00:27:53,726 +But, obviously, my image is not nil, +但是显然如果我的图片不为空, + +664 +00:27:53,728 --> 00:27:55,361 +then I don't wanna fetch it again. +我就不会再下载一次了。 + +665 +00:27:55,363 --> 00:27:58,597 +That would be wasting their cellular data even more, okay? +这样会浪费用户的蜂窝网络。 + +666 +00:27:58,599 --> 00:28:00,899 +So here's a classic example of where we +所以这里是实用 ViewWillAppear 的一个 + +667 +00:28:00,901 --> 00:28:02,000 +would use viewWillAppear, +经典例子。 + +668 +00:28:02,002 --> 00:28:04,735 +because we know it's worth it to go get that data, +因为我们知道我们马上要看到界面,所以在这个点开始从 + +669 +00:28:04,737 --> 00:28:09,639 +because we know we're going to appear onscreen, 'kay? +网络上获取数据是必要的。 + +670 +00:28:09,641 --> 00:28:10,907 +Everybody understand that, +大家都懂了吗? + +671 +00:28:11,943 --> 00:28:15,277 +view controller lifecycle coming to life for you? +对viewcontroller的生命周期了解了吗? + +672 +00:28:15,279 --> 00:28:16,528 +Okay? + +673 +00:28:16,529 --> 00:28:17,778 +So that's good. So let's go ahead and run. +很好,我们继续。 + +674 +00:28:17,781 --> 00:28:19,948 +So you, actually, let's go ahead and +现在我们要放一个 + +675 +00:28:19,950 --> 00:28:21,549 +put a default image in here. +默认的图片。 + +676 +00:28:21,551 --> 00:28:23,384 +I actually have some URLs. +实际上我已经有一些URL了。 + +677 +00:28:23,386 --> 00:28:28,755 +I'm just gonna drag this DemoURL.swift in here. +我要把 DemoURL.swift 这个文件拖进来。 + +678 +00:28:28,757 --> 00:28:32,392 +And all this DemoURL.swift does is it just defines +这个文件只是有一些我们今天这个演示 + +679 +00:28:32,394 --> 00:28:36,395 +a bunch of URLs that we're gonna use in our demo today. +用到的URL。 + +680 +00:28:36,397 --> 00:28:39,064 +So one of them is Stanford, right here. +其中一个是斯坦福的。 + +681 +00:28:39,066 --> 00:28:41,066 +So I'm going to load that up. +我要把它加载进来。 + +682 +00:28:41,068 --> 00:28:48,539 +So in my viewDidLoad, I'm gonna say, if my image is nil, +在viewDidLoad里,我要写,如果我的图片为空。 + +683 +00:28:48,541 --> 00:28:55,846 +then my imageURL equals my DemoURL.Stanford, 'kay? +那么我图片的URL就等于 DemoURL.Stanford 。 + +684 +00:28:55,848 --> 00:28:57,398 +So I'm just gonna, +我在 + +685 +00:28:57,399 --> 00:28:58,949 +in viewDidLoad, I'm gonna set my imageURL. +viewDidLoad 里设置了我的URL。 + +686 +00:28:58,951 --> 00:29:01,317 +Now, it's not gonna actually load this until it +在视图要出现的时候,图片才会真正 + +687 +00:29:01,319 --> 00:29:02,051 +will appear. +开始加载。 + +688 +00:29:02,053 --> 00:29:03,319 +That's okay. + +689 +00:29:03,321 --> 00:29:06,789 +But I'm just setting it right here, 'kay? +在这设置。 + +690 +00:29:06,791 --> 00:29:08,523 +And I'm not, this is really for testing anyway. +不过这个只是为了测试。 + +691 +00:29:08,525 --> 00:29:11,292 +I probably don't even need to do that just cuz we're gonna +我们一会儿在正式开始之前, + +692 +00:29:11,294 --> 00:29:14,462 +remove this code once we start really not testing and +会删了这行代码。 + +693 +00:29:14,464 --> 00:29:16,964 +actually working. + +694 +00:29:16,965 --> 00:29:19,465 +So let's go ahead and run this and see what we got. +这里我们运行一下看会发生什么。 + +695 +00:29:19,468 --> 00:29:20,734 +Oh, so it's not gonna work. +哦,什么都没有。 + +696 +00:29:20,736 --> 00:29:22,802 +Okay, so this comes up, it's blank. +是空白的。 + +697 +00:29:22,804 --> 00:29:23,970 +Why is this blank? +为什么是空白的呢? + +698 +00:29:23,972 --> 00:29:25,871 +Well, let's look at our storyboard. +让我们看一下 storyboard 。 + +699 +00:29:25,873 --> 00:29:27,973 +Here's the entry point to our storyboard. +这里是 storyboard 的入口。 + +700 +00:29:27,975 --> 00:29:29,608 +It's this blank view controller. +它指向一个空的 view controller。 + +701 +00:29:29,610 --> 00:29:30,809 +Anyway, we don't want that. +我们不希望这样。 + +702 +00:29:30,810 --> 00:29:32,009 +Let's move them over here and have it +把它挪到这,让它从 + +703 +00:29:32,012 --> 00:29:35,847 +come into our view controller image view controller here. +我们的图片视图控制器进入。 + +704 +00:29:35,849 --> 00:29:37,782 +Oh yeah, there we go, we got Stanford. +Oh yeah,我们看到了斯坦福的图片。 + +705 +00:29:37,784 --> 00:29:41,852 +That's very nice, but can't scroll around, 'kay? +非常漂亮,但是不能滚动。 + +706 +00:29:41,854 --> 00:29:43,186 +Oops. + +707 +00:29:43,188 --> 00:29:47,023 +I can't zoom, can't turn the pinch, nothing. +不能缩放,不能用手指缩放。 + +708 +00:29:47,025 --> 00:29:48,724 +Okay, so I can't see it, 'kay? +什么都不能做。 + +709 +00:29:48,726 --> 00:29:50,258 +Can't see anything. + +710 +00:29:50,260 --> 00:29:53,294 +So that's, obviously, we need a scroll view, all right? +显然,我们还需要一个滚动视图。 + +711 +00:29:53,296 --> 00:29:55,163 +So, let's go ahead and +我们继续 + +712 +00:29:55,165 --> 00:29:59,566 +first of all, actually, what should we do first here? +首先,我们应该先做什么呢? + +713 +00:29:59,568 --> 00:30:02,936 +Let's do, let's enhance our user interface a little bit +我们需要增强一下我们的用户界面 + +714 +00:30:02,938 --> 00:30:04,871 +more so we can pick other images. +让我们可以选择更多的图片。 + +715 +00:30:04,873 --> 00:30:07,540 +I don't wanna just have this Stanford image, I wanna have +我不希望只能看见斯坦福图片,我希望能看见 + +716 +00:30:07,542 --> 00:30:09,809 +some different images that we can look around in. +一些不同的图片。 + +717 +00:30:09,811 --> 00:30:11,744 +So I'm gonna go over here and +我们到这里拖一个 + +718 +00:30:11,746 --> 00:30:14,212 +drag out a split view controller. +split view controller + +719 +00:30:15,448 --> 00:30:17,014 +Where's that split view? +在哪呢? + +720 +00:30:17,016 --> 00:30:18,683 +Right here. +在这。 + +721 +00:30:18,684 --> 00:30:20,351 +So let's drag out this splitViewController. +让我们拽一个 splitViewController 出来。 + +722 +00:30:20,353 --> 00:30:22,652 +And, as usual, with the split view controller, I'm going to, +跟以前一样,在这个 splitViewController,我要。。。 + +723 +00:30:22,654 --> 00:30:26,256 +when I zoom out a little here, we can look at it. +我先缩小一点就能看见了。 + +724 +00:30:26,258 --> 00:30:28,824 +I'm gonna delete a lot of the stuff that came with it here. +我得删掉这些没用的东西。 + +725 +00:30:29,760 --> 00:30:30,692 +Keep that one. +留着这个, + +726 +00:30:30,694 --> 00:30:32,127 +We'll delete that. +删掉这个。 + +727 +00:30:32,129 --> 00:30:33,828 +I'm gonna have, +我需要 + +728 +00:30:33,830 --> 00:30:39,600 +my image view controller is going to be the detail, 'kay? +让我们的图片视图控制器作为细节视图。 + +729 +00:30:39,602 --> 00:30:41,118 +So I made the detail. +细节视图。 + +730 +00:30:41,119 --> 00:30:42,635 +I'm gonna make my entry point here be my +我要把入口挪到 + +731 +00:30:42,638 --> 00:30:45,138 +split view controller. +splitViewController + +732 +00:30:45,140 --> 00:30:49,575 +And I'm gonna have my master be this little one that was in +把之前的那个view controller作为主视图。 + +733 +00:30:49,577 --> 00:30:51,443 +here before. + +734 +00:30:51,445 --> 00:30:54,646 +By the way, I just Ctrl+drag there and set this little view +我Ctrl + 拖拽到这个view controller,这是 + +735 +00:30:54,648 --> 00:30:56,681 +controller that was there when we first started our app, +我们第一次启动app的时候看见的。 + +736 +00:30:56,683 --> 00:30:58,483 +this blank view controller. +这个空的 view controller。 + +737 +00:30:58,485 --> 00:31:00,151 +I can set it as the root view controller of +我把它设置成导航控制器的根视图控制器, + +738 +00:31:00,153 --> 00:31:02,519 +the navigation controller with Ctrl+drag and +Ctrl + 拖拽到这,选择 + +739 +00:31:02,521 --> 00:31:03,920 +pick root view controller here. +根视图控制器 + +740 +00:31:05,057 --> 00:31:08,458 +In your, in the demo and in your thing, we, you probably +在你们自己做的时候,你们应该选 + +741 +00:31:08,460 --> 00:31:12,061 +did this in Editor > Embed In > Navigation Controller, but +Editor > Embed In > Navigation Controller + +742 +00:31:12,063 --> 00:31:14,730 +you can also do it with Ctrl+drag, 'kay? +你也可以用 Ctrl + 拖拽. + +743 +00:31:14,732 --> 00:31:17,165 +So now I have a nice UI here. +这里我们有一个非常漂亮的UI。 + +744 +00:31:19,803 --> 00:31:22,536 +Comes up, shows my nice image view right there. +运行一下,漂亮的图片视图。 + +745 +00:31:22,538 --> 00:31:24,204 +If I go back, here's my master. +点返回,这里是我的主视图。 + +746 +00:31:24,206 --> 00:31:27,240 +So now, in this master, I'm gonna put some buttons so +现在,在这个主视图里我要加入一些摁钮,这样我们就可以 + +747 +00:31:27,242 --> 00:31:29,943 +we can pick different images to look at instead of +选择其他的图片,就不用一直看着 + +748 +00:31:29,945 --> 00:31:32,078 +just looking at that Stanford thing. +斯坦福了。 + +749 +00:31:32,080 --> 00:31:33,746 +So let's do that, really easy. +开始,非常容易。 + +750 +00:31:33,748 --> 00:31:35,814 +I'm just gonna grab some buttons here. +拖一些摁钮过来。 + +751 +00:31:35,816 --> 00:31:37,349 +Let's do this. + +752 +00:31:37,351 --> 00:31:41,219 +Let's make the buttons really big, +我们把摁钮弄的大一些。 + +753 +00:31:41,221 --> 00:31:44,488 +maybe like 48 point, okay? +48差不多。 + +754 +00:31:44,490 --> 00:31:47,458 +This button bigger. +这个更大。 + +755 +00:31:47,460 --> 00:31:51,027 +And let's make three of them. +弄3个摁钮。 + +756 +00:31:51,029 --> 00:31:52,796 +'Kay? + +757 +00:31:52,797 --> 00:31:54,564 +One of them is gonna be a picture of +一个代表Cassini卫星的 + +758 +00:31:54,566 --> 00:31:56,666 +the Cassini satellite. +图片。 + +759 +00:31:56,668 --> 00:31:58,734 +Okay, that was sent out as Saturn. +通过土星运载火箭发射的。 + +760 +00:31:58,736 --> 00:32:01,803 +Another one is gonna be a picture of Earth. +另外一个是地球的图片。 + +761 +00:32:01,805 --> 00:32:03,338 +Another one is gonna be Saturn. +最后一个是土星。 + +762 +00:32:03,340 --> 00:32:05,206 +Okay? + +763 +00:32:05,208 --> 00:32:08,842 +So let's do a little bit of our favorite thing here, +现在我们做一些好玩的事儿, + +764 +00:32:08,844 --> 00:32:10,510 +which is auto layouts. +自动布局。 + +765 +00:32:10,512 --> 00:32:12,645 +So put that one right in the middle. +把这个放中间。 + +766 +00:32:12,647 --> 00:32:15,982 +Put that one right underneath. +这个放它下面。 + +767 +00:32:15,984 --> 00:32:19,885 +This one right on top, 'kay? +这个在最上面。 + +768 +00:32:19,887 --> 00:32:22,654 +I'm gonna try and reset to suggested constraints and +现在我要重置建议的约束看看 + +769 +00:32:22,656 --> 00:32:24,122 +see how that works. +会发生什么。 + +770 +00:32:24,124 --> 00:32:25,657 +That didn't work very good, let's undo. +看上去不怎么样,回退。 + +771 +00:32:25,659 --> 00:32:28,326 +I think that's because, +我觉得这是因为, + +772 +00:32:28,328 --> 00:32:34,031 +let me make this thing be its normal size, that's why. +我们先把它弄小一点,我觉得这个就是原因。 + +773 +00:32:34,033 --> 00:32:34,798 +There we go. +走你。 + +774 +00:32:34,800 --> 00:32:35,999 +'Kay? + +775 +00:32:36,001 --> 00:32:37,233 +Put these back. +放回运来的位置, + +776 +00:32:37,235 --> 00:32:40,936 +Hopefully, this will, there we go, +希望这次能行, + +777 +00:32:40,938 --> 00:32:45,273 +Reset to Suggested Constraints. +重置建议的约束。 + +778 +00:32:45,275 --> 00:32:46,241 +Oh, still didn't work. +哦,还是不行。 + +779 +00:32:46,242 --> 00:32:47,208 +Okay, well, we'll fix them up, manually. +好吧,我们来手动修复一下吧。 + +780 +00:32:47,210 --> 00:32:49,477 +So this guy, right here. +这个,在这, + +781 +00:32:49,479 --> 00:32:52,346 +oh, that's so bad, it's not even close. +哦,糟糕,完全不对 + +782 +00:32:52,348 --> 00:32:54,648 +Okay. So + +783 +00:32:54,649 --> 00:32:56,949 +I'm just going to do this all manually here, +所以我们完全手动吧。 + +784 +00:32:56,952 --> 00:33:00,687 +going to uh-huh, sorry, wrong thing there. +啊,对不起,弄错了, + +785 +00:33:00,689 --> 00:33:05,358 +Okay, Ctrl+drag, let's make it center vertically. +Ctrl + 拖拽,垂直居中。 + +786 +00:33:05,360 --> 00:33:09,395 +Let's Ctrl+drag and center horizontally as well. +水平居中。 + +787 +00:33:09,397 --> 00:33:12,364 +Let's make this be vertical spacing. +这个的垂直距离。 + +788 +00:33:12,366 --> 00:33:16,968 +We'll make this one be vertical spacing we'll have +和它的垂直距离,这里让它们有一样的 + +789 +00:33:16,970 --> 00:33:20,738 +these things share their center x, center x. +x中心。 + +790 +00:33:20,740 --> 00:33:22,906 +I think we're good to go there. +我觉得这样可以了, + +791 +00:33:22,908 --> 00:33:25,375 +Yep, frames. +对,frame的警告。 + +792 +00:33:25,376 --> 00:33:27,843 +So, let's update our frames, less time. +更新一下frame。 + +793 +00:33:27,846 --> 00:33:30,130 +Okay, there we go. +好了,这下对了。 + +794 +00:33:30,131 --> 00:33:32,415 +All right, so we've got some nice auto layout there, and so +现在也有了很棒的自动布局, + +795 +00:33:32,417 --> 00:33:35,718 +now all we need to do is to segue when these are pressed. +现在我们需要做的就是设置segue,通过点击响应。 + +796 +00:33:35,720 --> 00:33:38,821 +We're gonna segue to our Image View Controller down here. +segue到下边的图片视图控制器。 + +797 +00:33:38,823 --> 00:33:42,157 +So let's set that up and just Ctrl+drag. +Ctrl + 拖拽连起来。 + +798 +00:33:42,159 --> 00:33:45,126 +nope, Ctrl+drag, all right. +不对,Ctrl + 拖拽,对了。 + +799 +00:33:45,128 --> 00:33:46,527 +So I'm gonna show detail because in +选择show detail因为 + +800 +00:33:46,529 --> 00:33:49,397 +the split view I want it to show up on the detail side and +在split view我希望它显示在细节视图上,在iphone上 + +801 +00:33:49,399 --> 00:33:51,532 +on iPhone it's gonna push,. +就是push。 + +802 +00:33:51,534 --> 00:33:54,668 +So there's that one, let's go ahead and set its segue. +我们继续,设置它 + +803 +00:33:54,670 --> 00:33:58,871 +So this one I'll just call it Earth, 'kay, this one, +就叫它 Earth 吧 + +804 +00:33:58,873 --> 00:34:04,677 +down here, show detail we'll call this one Cassini, and +再弄一个show detail,我叫它 Cassini + +805 +00:34:07,314 --> 00:34:12,283 +with this one, show detail, we'll call that one Saturn.、 +最后一个,叫Saturn + +806 +00:34:15,455 --> 00:34:18,622 +Okay, so there we go, we've got a nice story board here, +ok了,我们现在有了个漂亮的 storyboard。 + +807 +00:34:18,624 --> 00:34:21,525 +we've got these segues all set up in here all +我们设置好了全部的segue,现在要做的是 + +808 +00:34:21,527 --> 00:34:23,927 +we need to do is prepare for these segues. +准备他们。 + +809 +00:34:23,929 --> 00:34:25,628 +This View Controller right here, okay, +打开view controller。 + +810 +00:34:25,630 --> 00:34:28,965 +I'm going to select on this and go here to see its code. +我点这就能看见它的代码。 + +811 +00:34:28,967 --> 00:34:31,767 +So here's the code for that View Controller. +这就是view controller的代码。 + +812 +00:34:31,769 --> 00:34:34,236 +It's just this blank one that got created when we +这就是我们建立app的时候那个空白 + +813 +00:34:34,238 --> 00:34:35,003 +created our app. +的文件。 + +814 +00:34:36,139 --> 00:34:38,206 +Okay, and all I need in this ViewController is +我要在这实现 prepareForSegue 。 + +815 +00:34:38,208 --> 00:34:41,075 +prepareForSegue, nothing more, so I'm gonna prepareForSegue. +仅此而已,实现 prepareForSegue 。 + +816 +00:34:41,077 --> 00:34:44,244 +Actually I'm going to make +我得把它弄的宽 + +817 +00:34:44,246 --> 00:34:46,713 +this quite a bit wider here with these huge fonts. +一点,字体太大了。 + +818 +00:34:47,683 --> 00:34:50,817 +And in here I'm going to see if it's a segue to +现在我要检查它是不是要segue到我的 + +819 +00:34:50,819 --> 00:34:53,336 +an image ViewController. +图片视图控制器。 + +820 +00:34:53,337 --> 00:34:55,854 +So I'm gonna say if I can let image view controller equal my +这里写if let ivc = + +821 +00:34:55,857 --> 00:34:58,691 +segue's destinationViewController as +segue.destinationViewController as + +822 +00:34:58,693 --> 00:35:00,592 +an ImageViewController. +ImageViewController + +823 +00:35:00,594 --> 00:35:01,760 +Okay, so we know we're segueing into +现在我们可以确定是segue到 + +824 +00:35:01,762 --> 00:35:03,812 +an image view controller. +图片视图控制器。 + +825 +00:35:03,813 --> 00:35:05,863 +Then if I can let the identifier equal +然后if let identifier 等于 + +826 +00:35:05,865 --> 00:35:10,100 +the segue's identifier, so the identifier's not null, +segue.identifier,这样确保identifier不为空, + +827 +00:35:10,102 --> 00:35:11,868 +then I'm gonna switch on the identifier. +然后对 identifier 作 switch. + +828 +00:35:11,870 --> 00:35:13,937 +This code should all look very familiar to you, +你们应该很熟悉这个了。 + +829 +00:35:13,939 --> 00:35:17,473 +and then in case of Earth, 'kay, +然后,如果是 Earth。 + +830 +00:35:17,475 --> 00:35:20,976 +we are going to have to set the image URL, 'kay? +我们就要设置图片的URL。 + +831 +00:35:20,978 --> 00:35:23,512 +So ivc is an image view controller, +ivc就是我们的图片视图控制器。 + +832 +00:35:23,514 --> 00:35:26,648 +its public settable model is the imageURL. +它的公有的可设置的model就是 imageURL。 + +833 +00:35:26,650 --> 00:35:30,952 +So I'm gonna set that to DemoURL.NASA.Earth. +我把它设置成 DemoURL.NASA.Earth 。 + +834 +00:35:30,954 --> 00:35:33,921 +'Kay, I have a nice one ready to go there. +这个做好了。 + +835 +00:35:33,923 --> 00:35:38,191 +I'm also gonna set the title of that to Earth, +我还要把它的标题设置成 Earth , + +836 +00:35:38,193 --> 00:35:42,028 +'kay, and then same thing here for Saturn. +下边是Saturn,一样的。 + +837 +00:35:43,264 --> 00:35:45,698 +It's image view controllers, +这个是图片视图控制器。 + +838 +00:35:45,700 --> 00:35:49,301 +imageURL equals the DemoURL.NASA.Saturn. +imageURL 等于 DemoURL.NASA.Saturn 。 + +839 +00:35:49,303 --> 00:35:54,939 +ivc.title equals Saturn, and same thing for Cassini. +ivc.title 是 Saturn,下面是Cassini 。 + +840 +00:36:07,353 --> 00:36:07,951 +Let's see. + +841 +00:36:14,393 --> 00:36:17,927 +'Kay, and otherwise we will just break, and +最后如果都不是,就break。什么也 + +842 +00:36:17,929 --> 00:36:19,528 +do nothing, okay? +不做。 + +843 +00:36:20,764 --> 00:36:22,297 +Everybody understand this code? +这些代码大家都能看懂吧? + +844 +00:36:22,299 --> 00:36:24,399 +Hopefully it's completely familiar to you. +希望你们已经非常熟悉了。 + +845 +00:36:24,401 --> 00:36:26,267 +Nothing special there at all. +没什么特别的。 + +846 +00:36:26,269 --> 00:36:29,470 +Okay, so I think that should work. +我觉得应该没问题了。 + +847 +00:36:29,472 --> 00:36:30,470 +Let's try it. +试试看。 + +848 +00:36:30,472 --> 00:36:34,607 +Hopefully it didn't clean anything. +希望没弄坏什么东西。 + +849 +00:36:34,609 --> 00:36:36,842 +All right, so we go back, we've got these things. +我们点返回,看到这些摁钮。 + +850 +00:36:36,844 --> 00:36:37,876 +Let's go ahead, oh, +继续, + +851 +00:36:37,878 --> 00:36:39,745 +my auto layout doesn't look very good there. +啊,自动布局貌似不怎么好。 + +852 +00:36:39,747 --> 00:36:43,148 +Probably messed that up, but anyway, close enough. +可能是弄乱了,不过也差不多了。 + +853 +00:36:43,150 --> 00:36:45,917 +Let's go Earth, oh, it didn't work, okay? +点 Earth, 啊,不行。 + +854 +00:36:45,919 --> 00:36:48,986 +That's because we have back here, +这是因为,我们回到这, + +855 +00:36:48,988 --> 00:36:54,591 +here in our image controller, we have this test code here. +因为在我们的图片视图控制器,有一些测试代码。 + +856 +00:36:54,593 --> 00:36:56,726 +Let's get rid of that, right there. +把测试代码删掉。 + +857 +00:36:56,728 --> 00:36:58,628 +Try again. +再试一下。 + +858 +00:36:58,630 --> 00:37:00,796 +Right back now, let's look at Earth, and +试试 Earth + +859 +00:37:00,798 --> 00:37:03,766 +look how slow this this, you see what I'm talking about? +非常慢,看到没? + +860 +00:37:03,768 --> 00:37:04,933 +Like, hello, +hi + +861 +00:37:04,935 --> 00:37:08,770 +can't do anything, can't click on any buttons. +啥也干不了,也点不了别的摁钮。 + +862 +00:37:08,772 --> 00:37:11,706 +Finally, we get this and this does not look like +最后我们看到了图片,貌似不是地球, + +863 +00:37:11,708 --> 00:37:14,775 +the Earth to me, looks like a bunch of dim photos. +像是一些很暗的照片。 + +864 +00:37:14,777 --> 00:37:17,711 +I don't know what that is how about Cassini? +不知道这是些什么,那Cassini呢? + +865 +00:37:17,713 --> 00:37:21,882 +oh, we got the outer space part of Cassini right, but +啊,我们看到了外太空的部分, + +866 +00:37:21,884 --> 00:37:26,419 +that's all we can see because we need the scroll view now. +但是也只有这些了,我们需要滚动视图。 + +867 +00:37:26,421 --> 00:37:27,787 +We absolutely have to have the scroll view. +必须要用滚动视图了, + +868 +00:37:27,789 --> 00:37:30,155 +These are big images so we can not see anything without it. +如果没有,这些很大的图片,我们什么也看不见。 + +869 +00:37:30,157 --> 00:37:32,891 +So let's go back and put our scroll view in here. +咱们回来,加上滚动视图。 + +870 +00:37:34,994 --> 00:37:37,028 +All right, so how are we gonna put the scroll view in here? +怎么加入滚动视图呢? + +871 +00:37:37,030 --> 00:37:39,830 +Well, I'm actually gonna put the scroll view in +我要用 storyboard 来加入 + +872 +00:37:39,832 --> 00:37:41,698 +using the storyboard. +滚动视图。 + +873 +00:37:41,700 --> 00:37:43,400 +So, I'm gonna drag a scroll view in. +拖一个滚动视图进来。 + +874 +00:37:43,402 --> 00:37:44,701 +That's kinda a simple way to do it. +应该是比较简单的方法了。 + +875 +00:37:44,703 --> 00:37:47,069 +So, let's bounce out here so +缩小一点, + +876 +00:37:47,071 --> 00:37:49,238 +now we're back to our Image View Controller. +来到图片视图控制器。 + +877 +00:37:50,307 --> 00:37:52,207 +All right, this is our Image View Controller, and +在这,我要拖 + +878 +00:37:52,209 --> 00:37:54,042 +I'm just going to drag out a scroll view. +一个滚动视图进来。 + +879 +00:37:54,044 --> 00:37:55,176 +I'm gonna search for +在这里搜索, + +880 +00:37:55,178 --> 00:37:58,845 +it, scroll, there it is, drag it out here. +scroll,啊,在这,拖进来。 + +881 +00:37:59,881 --> 00:38:03,182 +I'm gonna place it so that it's right on the edges with +这样放,沿着蓝线,这样 + +882 +00:38:03,184 --> 00:38:04,917 +the blue lines right there. +就跟边缘对齐了。 + +883 +00:38:04,919 --> 00:38:08,487 +I'm definitely gonna do Reset to Suggested Constraints. +肯定也是需要重置建议的约束。 + +884 +00:38:08,489 --> 00:38:11,256 +I'm gonna make sure that works, which it did, +检查一下是不是成功,行了。 + +885 +00:38:11,258 --> 00:38:13,224 +'kay, no magic numbers. +没有魔法数字。 + +886 +00:38:13,226 --> 00:38:16,194 +Everything looks nice right there, and now I +看上去没问题了, + +887 +00:38:16,196 --> 00:38:20,964 +just need to put my image view inside this scroll view right. +现在我需要把我的图片视图放到滚动视图里。 + +888 +00:38:20,966 --> 00:38:24,101 +So I got this scroll view here all I wanna do is put +我要做的就是这个,把图片视图放到滚动视图 + +889 +00:38:24,103 --> 00:38:25,468 +the image view inside of it. +的里边。 + +890 +00:38:25,470 --> 00:38:28,004 +So how am I gonna put that imageView inside of it. +我要怎么做呢? + +891 +00:38:28,006 --> 00:38:30,773 +That's very, very, very simple I'm just going to +非常非常简单。我只需要给滚动视图一个 + +892 +00:38:30,775 --> 00:38:32,941 +create an outlet to this thing. +outlet。 + +893 +00:38:32,943 --> 00:38:34,509 +Let's put the outlet right here. +把outlet放在这。 + +894 +00:38:34,511 --> 00:38:39,347 +Okay, I'm going to call the outlet scroll view, and +起名叫scrollView, + +895 +00:38:39,349 --> 00:38:42,183 +as soon as that outlet is set +设置好了。 + +896 +00:38:42,185 --> 00:38:47,121 +in it's did Set I'm going to simply say to. +在didSet里我们要做, + +897 +00:38:50,693 --> 00:38:52,392 +The scroll, well actually, we, you know, +实际上我们已经加上了 + +898 +00:38:52,394 --> 00:38:53,559 +we already added the scroll view. +滚动视图。 + +899 +00:38:53,561 --> 00:38:54,994 +Let me make this a little easier on you. +我们做的简单一点。 + +900 +00:38:54,996 --> 00:38:58,263 +See right down here where we add the image view to +看到这里图片视图已经加到 + +901 +00:38:58,265 --> 00:39:01,049 +our view? +我们的视图? + +902 +00:39:01,050 --> 00:39:03,834 +Instead, I'm just gonna add it to the scroll view, 'kay? +相反,我只是把它添加到滚动视图中 + +903 +00:39:03,837 --> 00:39:06,437 +So you can build your view hierarchy in view did load. +这样你可以在 viewDidLoad 中建立视图层次关系 + +904 +00:39:06,439 --> 00:39:08,172 +It's actually a pretty good place to build it, +这里实际上是个很好的地方来创建它 + +905 +00:39:08,174 --> 00:39:10,908 +cuz all your outlets are set, so we know this is set, and so +因为你的所有 outlets 都设置好了,我们知道这个已经设置好了 + +906 +00:39:10,910 --> 00:39:13,410 +we can build our view hierarchy here, 'kay? +我们可以在这里建立我们的视图层次 + +907 +00:39:13,412 --> 00:39:16,446 +So I just added the subview to there but I do actually need +我刚才已在那里添加了子视图,但实际上我 + +908 +00:39:16,448 --> 00:39:17,513 +this didset here. +需要在这里调用 didset + +909 +00:39:17,515 --> 00:39:19,348 +I need again to make this wider so +我需要再次把这个变宽 + +910 +00:39:19,350 --> 00:39:23,985 +you can see it because when I set my scroll view what's +这样你们可以看到,因为当我设置我的滚动视图时, + +911 +00:39:23,987 --> 00:39:26,087 +the most important thing to make a scroll view work? +让一个滚动视图工作最重要的事情是什么? + +912 +00:39:28,257 --> 00:39:29,523 +The content size, right. +contentSize,对吧 + +913 +00:39:29,525 --> 00:39:31,024 +So when my scroll view gets set, +因此当我的滚动视图被设置了 + +914 +00:39:31,026 --> 00:39:32,392 +I need to set the content size, so +我需要设置 contentSize + +915 +00:39:32,394 --> 00:39:35,962 +I'm gonna say scrollView.contentSize, and +所以我要设置 scrollView.contentSize + +916 +00:39:35,964 --> 00:39:37,697 +what size do I want it to be? +我需要设置怎样的大小? + +917 +00:39:37,698 --> 00:39:39,431 +Well I want the content size to be exactly the same size as +好吧,我需要 contentSize 和 imageView + +918 +00:39:39,434 --> 00:39:40,899 +the image view, so +的大小一致 + +919 +00:39:40,901 --> 00:39:45,403 +I'm just gonna say imageView.frame.size. +我要设 imageView.frame.size + +920 +00:39:45,405 --> 00:39:49,674 +'Kay, now that's not, oops, equals. +这不是,等于 + +921 +00:39:49,676 --> 00:39:52,643 +That's not the only place I need to do this, though, 'kay? +这里不是我需要做这个操作的唯一地方 + +922 +00:39:52,645 --> 00:39:53,944 +Any time my image changes, +任何时候我的图片改变了 + +923 +00:39:53,946 --> 00:39:55,779 +obviously my image view might change, +显然我的图片视图也可能改变 + +924 +00:39:55,781 --> 00:39:58,214 +I need to change the content size of my scroll view. +我需要改变滚动视图的内容大小 + +925 +00:39:58,216 --> 00:39:59,482 +So also here. +这里也需要 + +926 +00:39:59,484 --> 00:40:04,686 +Inside the setter for image I need to set my scrollView's +在 setter 里面,我需要设置滚动视图的 + +927 +00:40:04,688 --> 00:40:10,291 +content size equal to the imageView's frame size. +contentSize 等于图片视图的大小 + +928 +00:40:10,293 --> 00:40:12,526 +Here I'm going to do something kind of interesting, +这里我要做些有趣的事情 + +929 +00:40:12,528 --> 00:40:15,662 +which I actually did in auto layout demo after the fact +这是在我发布代码之后在自动布局 + +930 +00:40:15,664 --> 00:40:17,097 +when I posted the code, but +例子中做的 + +931 +00:40:17,099 --> 00:40:18,832 +I'm going to put a question mark right here. +但我要在这里放个问号 + +932 +00:40:19,801 --> 00:40:22,802 +And the reason I'm gonna do that, it allows me to set my +我这样做的原因,我可以在内部设置 + +933 +00:40:22,804 --> 00:40:29,007 +image internally, even if my outlets have not been set yet. +图片,即使我的 outlets 还没被设置。 + +934 +00:40:29,009 --> 00:40:34,512 +I know that these outlets are implicitly wrapped optionals, +我知道这些 outlets 都是可选的 + +935 +00:40:34,514 --> 00:40:35,913 +and of course that means that you can access them, +当然这意味着你可以访问它们 + +936 +00:40:35,915 --> 00:40:39,249 +but the reality is you need to protect against the cases +但事实是你在这些变量可为 + +937 +00:40:39,251 --> 00:40:41,051 +where those things might me nil. +nil 的情况下做些保护措施 + +938 +00:40:41,053 --> 00:40:42,452 +Like setting your image, +比如设置你的图片 + +939 +00:40:42,454 --> 00:40:45,288 +somehow, before that was your set. +某种方式,在你设置前 + +940 +00:40:45,290 --> 00:40:47,256 +So, now I don't need to do it here, +现在这里我不需要了 + +941 +00:40:47,258 --> 00:40:48,457 +because I'm in viewDidLoad. +因为我在 viewDidLoad + +942 +00:40:48,459 --> 00:40:51,026 +And I don't need to do it here because, of course, +我不需要在这里做这些,当然 + +943 +00:40:51,028 --> 00:40:52,494 +it just got set. +它已经被设置了 + +944 +00:40:52,496 --> 00:40:54,262 +But here, I'm going to do it just to be safe. +但这里,为了安全我需要做这个 + +945 +00:40:54,264 --> 00:40:59,066 +Everyone understand that? +每个人都理解了吗? + +946 +00:40:59,068 --> 00:40:59,933 +Okay. + +947 +00:40:59,935 --> 00:41:01,001 +So, let's see. +让我们看看 + +948 +00:41:01,003 --> 00:41:01,567 +It should work. +它应该可以工作 + +949 +00:41:03,971 --> 00:41:06,271 +All right here we go, let's go try Cassini. +我们从这里,让我试试 Cassini + +950 +00:41:06,273 --> 00:41:08,907 +Slow, okay. +很慢 + +951 +00:41:08,909 --> 00:41:10,942 +Oh yeah, look, oh stars. +看看,星星 + +952 +00:41:10,944 --> 00:41:15,680 +Oh, what's that? +这是什么? + +953 +00:41:15,682 --> 00:41:18,716 +Oh, look at that. +看这个 + +954 +00:41:18,718 --> 00:41:19,883 +Oh, sorry. +抱歉 + +955 +00:41:19,885 --> 00:41:21,051 +There it is. +在这里 + +956 +00:41:21,053 --> 00:41:24,620 +Oh, oh,. + +957 +00:41:24,622 --> 00:41:26,856 +It's a spacecraft of some sort. +这是某种太空船 + +958 +00:41:26,858 --> 00:41:28,390 +Hard to tell, kay? +很难说清楚 + +959 +00:41:28,392 --> 00:41:30,659 +We don't really get to see a lot of it, but +我实际上没看到它的大部分 + +960 +00:41:30,661 --> 00:41:31,860 +[INAUDIBLE] Cassini. +Cassini + +961 +00:41:31,862 --> 00:41:34,228 +Okay, well obviously we need zooming, kay? +显然我们需要缩放 + +962 +00:41:34,230 --> 00:41:36,630 +Because I can't see really what's going on here. +因为我不能看清楚这里所发生的 + +963 +00:41:36,632 --> 00:41:39,199 +All right, so let's go back and add zooming. +让我回去,然后添加 zooming + +964 +00:41:39,201 --> 00:41:40,701 +Again, very straightforward. +非常简单 + +965 +00:41:40,702 --> 00:41:42,202 +Remember, there's only two things you really need to do. +记住,实际上你只需要做两件事情 + +966 +00:41:42,204 --> 00:41:43,903 +You gotta set that min max, and +你要设置 min 和 max + +967 +00:41:43,905 --> 00:41:45,872 +you gotta implement that delegate method. +然后你要实现代理方法 + +968 +00:41:45,874 --> 00:41:48,040 +Great place to set delegate methods, of course, +这里是实现代理方法的好地方,当然 + +969 +00:41:48,042 --> 00:41:50,009 +is in the setter of outlets. +在 outlets 的 setter 中 + +970 +00:41:50,011 --> 00:41:51,877 +If you wanna set the delegate of an outlet, so +如果你想设置一个 outlet 的代理 + +971 +00:41:51,879 --> 00:41:55,480 +I'm gonna set the scrollView's delegate to be myself. +我将设置滚动视图的代理为我自己 + +972 +00:41:55,482 --> 00:41:57,582 +Of course I'm gonna have to say that I implemented. +当然我必须实现(代理) + +973 +00:41:57,584 --> 00:41:58,916 +That's the problem here. +这是问题所在 + +974 +00:41:58,918 --> 00:41:59,750 +Okay. + +975 +00:41:59,752 --> 00:42:02,286 +We'll do that in a second. +我们一会就做这个 + +976 +00:42:02,287 --> 00:42:04,821 +While I'm here I'm going to set the minimum zoom scale +这里,我将设置 minimumZoomScale + +977 +00:42:04,823 --> 00:42:05,455 +to 0.03. +为 0.03 + +978 +00:42:05,457 --> 00:42:07,574 +This is a very, +这是张非常 + +979 +00:42:07,575 --> 00:42:09,692 +very large image that we'll be able to look at here. +非常大的图片,我们可以在这里看到 + +980 +00:42:09,694 --> 00:42:12,061 +And the maximum zoom scale to 1.0 and +然后 maximumZoomScale 为 1.0 + +981 +00:42:12,063 --> 00:42:15,297 +maybe these don't wanna be magic numbers. +可能它们不想为神奇的数字 + +982 +00:42:15,299 --> 00:42:17,632 +Maybe these want to based on the actual size of +可能它们想要根据图片视图的 + +983 +00:42:17,634 --> 00:42:18,599 +the imageView. +实际大小 + +984 +00:42:18,601 --> 00:42:20,757 +Okay? + +985 +00:42:20,758 --> 00:42:22,914 +So you might want to make it so +所以你可能想要让它 + +986 +00:42:22,915 --> 00:42:25,071 +that you can perfectly zoom out to fit the scrollView or +完全缩小以适合滚动视图或 + +987 +00:42:25,074 --> 00:42:26,156 +something like that. +其他类似的视图 + +988 +00:42:26,157 --> 00:42:27,239 +But I'm just picking numbers here to +但我挑这些数字只是为了 + +989 +00:42:27,242 --> 00:42:28,541 +make this code simpler. +让代码简单 + +990 +00:42:28,543 --> 00:42:30,943 +So let's go fix the fact about the delegate here. +让我们修改下这里的代理 + +991 +00:42:30,945 --> 00:42:33,779 +So I'm just going to go up here and say, +我要到这上面来,我要设置 + +992 +00:42:33,780 --> 00:42:36,614 +oh yes, ImageViewController is a UIScrollView delegate. +ImageViewController 为滚动视图的代理 + +993 +00:42:36,617 --> 00:42:38,116 +And, as soon as I say that, +一旦我设置了 + +994 +00:42:38,118 --> 00:42:39,884 +this warning went away down here, but +这下面的警告就没了 + +995 +00:42:39,886 --> 00:42:41,686 +I didn't get a new one that said, oh, +我没有另一个新的(警告) + +996 +00:42:41,688 --> 00:42:43,120 +you don't implement this. +你没有实现这个 + +997 +00:42:43,122 --> 00:42:45,022 +And again, cuz this is the old objective C +因为这是老式的 objective C + +998 +00:42:45,024 --> 00:42:47,457 +style protocol where there's optional methods. +风格的协议,这是可选方法 + +999 +00:42:49,027 --> 00:42:50,226 +So, I'm going to implement one of +我要实现它们中的一个 + +1000 +00:42:50,228 --> 00:42:52,761 +them though which is view for zooming in scrollView. +即 viewForZoomingInScrollView + +1001 +00:42:52,763 --> 00:42:55,330 +Okay, as soon as I typed viewFor, +只要我输入 viewFor + +1002 +00:42:55,332 --> 00:42:57,032 +it knew what I was talking about. +它知道我想输入什么 + +1003 +00:42:57,034 --> 00:42:59,434 +And I'm just going to return my imageView because that is +我只要回到图片视图,因为 + +1004 +00:42:59,436 --> 00:43:02,770 +the view that's inside the scrollView's content area that +它在滚动视图的内容区域中 + +1005 +00:43:02,772 --> 00:43:03,437 +I want to zoom on. +就是我想放大的 + +1006 +00:43:03,439 --> 00:43:05,105 +And that's it. +这就是了 + +1007 +00:43:06,174 --> 00:43:08,307 +That's all we need to do, so let's go run. +这就是所有我们需要做的,让我们运行下 + +1008 +00:43:10,211 --> 00:43:11,410 +Now we should be able to go and +现在我们应该能够 + +1009 +00:43:11,412 --> 00:43:14,346 +take a look at Cassini in all of its grandeur. +看到 Cassini 的全部华丽壮美 + +1010 +00:43:14,348 --> 00:43:17,348 +I'm just going to hold down Option so that I can pinch. +我要按住 Option 键,这样我可以捏(图片) + +1011 +00:43:17,350 --> 00:43:18,549 +And I'm just pinching in here. +我在这里捏 + +1012 +00:43:19,985 --> 00:43:21,685 +Oh there it is. And let's go ahead and +这就是,让我们继续 + +1013 +00:43:21,687 --> 00:43:23,286 +rotate the other way. +旋转到其他方式 + +1014 +00:43:23,288 --> 00:43:26,122 +There we go. +我们看到了 + +1015 +00:43:26,123 --> 00:43:28,957 +So we can see it and zoom out a little bit. +因此我们可以看到它缩小了一点点 + +1016 +00:43:28,960 --> 00:43:31,193 +We can still scroll in addition to zooming. +我们依然可以在缩放的时候滚动 + +1017 +00:43:32,129 --> 00:43:33,361 +Okay? And let's go look at +让我们看看 + +1018 +00:43:33,363 --> 00:43:35,430 +this Earth thing so +这个 Earth 图片 + +1019 +00:43:35,431 --> 00:43:37,498 +we can figure out what the heck is going on with that. +现在我们总算清楚它在干什么了 + +1020 +00:43:41,203 --> 00:43:41,968 +So slow. +这么慢 + +1021 +00:43:41,970 --> 00:43:43,169 +Okay, so here it is. +这就是了 + +1022 +00:43:43,171 --> 00:43:44,971 +Oh, now we can move around and look at things. +让我们移动开,看看 + +1023 +00:43:44,973 --> 00:43:46,172 +Let's zoom in on this a little. +让我们在这里缩小一点 + +1024 +00:43:46,174 --> 00:43:49,841 +[INAUDIBLE] oh, whoa, it's the Earth. +它是地球 + +1025 +00:43:49,843 --> 00:43:51,543 +Woo, okay. + +1026 +00:43:51,545 --> 00:43:54,812 +So, yes and as we can imagine, guess what this one is. +既然我们可以想象,猜猜这个是什么 + +1027 +00:43:56,916 --> 00:43:58,616 +Pictures of people. +很多人的照片 + +1028 +00:43:58,617 --> 00:44:00,317 +So this is actually made up of composites of images of +所以这个实际上是人们向 Cassini 挥手的 + +1029 +00:44:00,319 --> 00:44:01,918 +people waving at Cassini. +照片拼图 + +1030 +00:44:01,920 --> 00:44:05,988 +Kay they're taking pictures of themselves waving, see? +他们在挥手的时候拍的照片 + +1031 +00:44:05,990 --> 00:44:07,523 +Hello Cassini. +你好,Cassini + +1032 +00:44:07,525 --> 00:44:09,524 +So that's what this composite is made of and +这就是这张拼图的内容 + +1033 +00:44:09,526 --> 00:44:11,559 +then I'll push in that Saturn out of there. +我要推动土星离开那里 + +1034 +00:44:11,561 --> 00:44:12,627 +'Kay so. + +1035 +00:44:12,629 --> 00:44:14,795 +NASA, pretty cool. +NASA,相当酷 + +1036 +00:44:14,797 --> 00:44:15,929 +All right. + +1037 +00:44:15,931 --> 00:44:17,147 +Okay, so that's good. +这很好 + +1038 +00:44:17,148 --> 00:44:18,364 +So that's all I'm gonna show for now. +这是我现在想演示的所有内容了 + +1039 +00:44:18,367 --> 00:44:20,700 +We'll get back and work on the fact that our app is really, +我们一会将返回,然后解决我们 app 相当相当慢的 + +1040 +00:44:20,702 --> 00:44:21,768 +really slow in a minute. +问题 + +1041 +00:44:22,737 --> 00:44:25,537 +Gotta show you some stuff first though. +先给你们看些材料 + +1042 +00:44:25,539 --> 00:44:26,672 +'Kay, any questions about that? +关于这个有问题吗 + +1043 +00:44:26,674 --> 00:44:29,474 +ScrollView's really easy to use, but you just +滚动视图很容易掌握,但你们 + +1044 +00:44:29,476 --> 00:44:32,276 +gotta know these particular things like the delegate and +要知道这些特别的东西,比如代理和 + +1045 +00:44:32,278 --> 00:44:35,479 +that min max zoom scale and that content size. +minmaxZoomScale 以及 contentSize + +1046 +00:44:35,481 --> 00:44:36,680 +As long as you do those things, +只要你们做了这些事情 + +1047 +00:44:36,682 --> 00:44:38,081 +it'll work really great. +它就能工作的相当好了 + +1048 +00:44:39,084 --> 00:44:40,583 +All right, so a little aside here. +先把这些放一边 + +1049 +00:44:40,585 --> 00:44:42,285 +Just a two minute aside. +只是放一两分钟 + +1050 +00:44:42,286 --> 00:44:43,986 +I'm gonna rip through these slides about closures, but +我要讲讲这些幻灯片上的闭包 + +1051 +00:44:43,988 --> 00:44:45,721 +there's an important aspect about closure that +这是关于闭包非常重要的方面 + +1052 +00:44:45,723 --> 00:44:46,388 +you need to know. +你们需要知道 + +1053 +00:44:46,390 --> 00:44:48,090 +Kay? + +1054 +00:44:48,091 --> 00:44:49,791 +Closures, when you have a closure in your code, +闭包,但你们的代码中有闭包时 + +1055 +00:44:49,793 --> 00:44:53,695 +it captures any variables that are used inside +它会捕获闭包中使用的任何外部变量 + +1056 +00:44:53,697 --> 00:44:57,431 +the closure from the outer scope, where the thing is, +这个是 + +1057 +00:44:57,433 --> 00:44:59,199 +which is a really cool feature. +是非常酷的特点 + +1058 +00:44:59,201 --> 00:45:01,335 +That's what makes it a closure really, okay. +这实际上也让它成为了一个闭包 + +1059 +00:45:01,337 --> 00:45:03,570 +Is that it captures them, okay. +闭包是这样捕获它们 + +1060 +00:45:03,572 --> 00:45:05,805 +You can make incredibly elegant code out of +你可以使用闭包写出难以置信的 + +1061 +00:45:05,807 --> 00:45:06,605 +this, okay. +优雅代码 + +1062 +00:45:06,607 --> 00:45:08,607 +Now here's where I'm going to +现在我要向你们演示 + +1063 +00:45:08,608 --> 00:45:10,608 +show you something about the calculator that if you +计算器的一些东西,如果你们 + +1064 +00:45:10,611 --> 00:45:12,644 +didn't do this in your assignment, that's good. +在你们的作业没做这个,没关系 + +1065 +00:45:12,646 --> 00:45:14,079 +Because in your assignment I wanted you to +因为在你们的作业中,我希望你们 + +1066 +00:45:14,081 --> 00:45:15,613 +use delegation, okay. +使用代理 + +1067 +00:45:15,615 --> 00:45:20,384 +However, sometimes closures can be a substitute or +然而,有时候闭包可以作为一种替代或者 + +1068 +00:45:20,386 --> 00:45:23,653 +a better tool to use than delegation. +是个比代理更好的工具 + +1069 +00:45:23,655 --> 00:45:25,155 +Lets look at this code right here. +看这里的代码 + +1070 +00:45:25,157 --> 00:45:26,823 +Lets say I have a class called grapher. +我有一个类叫做 grapher + +1071 +00:45:26,825 --> 00:45:29,258 +I'm not going to say what kind of thing it could be +我不打算讲这是什么样的东西 + +1072 +00:45:29,260 --> 00:45:31,660 +because some of you haven't turned in your homework yet, +因为你们中有些还没把作业交上来 + +1073 +00:45:31,662 --> 00:45:34,329 +but lets say I had a grapher, okay. +但我有一个 grapher + +1074 +00:45:34,331 --> 00:45:37,298 +And it doesn't have a delegate method or anything it just has +它没有代理方法或其他方法,它只有 + +1075 +00:45:37,300 --> 00:45:42,036 +a var called yForX whose type is a function. +一个变量叫做 yForX,它的类型是函数 + +1076 +00:45:42,038 --> 00:45:44,605 +A function that takes an x and returns a double. +这个函数有个参数 x,并返回 double + +1077 +00:45:44,607 --> 00:45:45,872 +Okay? + +1078 +00:45:45,874 --> 00:45:47,140 +Now that's an optional function. +这是个可选函数 + +1079 +00:45:47,142 --> 00:45:49,742 +That's fine, doesn't have to be set in this grapher. +这很好,在 grapher 中不一定需要设置这个函数 + +1080 +00:45:49,744 --> 00:45:51,677 +And then what if I just said, +然后如果我 + +1081 +00:45:51,678 --> 00:45:53,611 +well I'm going to let the grapher equal a new grapher. +让 grapher 等于一个新的 grapher 会怎样? + +1082 +00:45:53,614 --> 00:45:56,882 +I'm going to let variable graphing brain be +我将让变量 graphingBrain 等于 + +1083 +00:45:56,884 --> 00:45:59,251 +a calculator brain instance I just created. +我刚刚创建的 CalculatorBrain 实例 + +1084 +00:45:59,253 --> 00:46:01,886 +Then I'm gonna set the program of the graphingBrain I +然后我设置我刚刚创建的 graphingBrain + +1085 +00:46:01,888 --> 00:46:04,889 +just created to some other program that I wanna graph. +的程序为另一个我想要做图表的程序 + +1086 +00:46:04,891 --> 00:46:08,792 +Then I'm just gonna say yForX equals a closure and +然后我只要让 yForX 等于一个闭包 + +1087 +00:46:08,794 --> 00:46:10,527 +inside the closure it just says, +然后在闭包内部,只要 + +1088 +00:46:10,529 --> 00:46:13,963 +set the variable value to the argument to the closure and +将变量的值传递给闭包的参数 + +1089 +00:46:13,965 --> 00:46:16,032 +then return the graphingBrain at evaluate. +然后返回 graphingBrain.evaluate() + +1090 +00:46:19,637 --> 00:46:22,237 +So do you see how by using this, +通过这个你们就知道怎么使用闭包 + +1091 +00:46:22,239 --> 00:46:25,173 +first of all we have grapher is completely generic. +首先,我们有一个完全普遍的 grapher + +1092 +00:46:25,175 --> 00:46:27,442 +Knows nothing about a calculator brain. +对于 CalculatorBrain 一无所知 + +1093 +00:46:27,444 --> 00:46:29,310 +And yet we have this five line, +然后我有这五行 + +1094 +00:46:29,312 --> 00:46:32,613 +six lines of code to implement our graphing and +六行代码来实现我们的制图 + +1095 +00:46:32,615 --> 00:46:37,484 +it's all incredibly easy to kind of parse what's going on. +这一切都非常容易解析发生了什么 + +1096 +00:46:37,486 --> 00:46:40,053 +Now this works because the closure, +这个能起作用是因为闭包 + +1097 +00:46:40,055 --> 00:46:41,421 +that little thing in the curly braces, +即在大括号里的小东西 + +1098 +00:46:41,423 --> 00:46:45,257 +captured the little graphing brain that I created. +捕获了我创建的小 graphingBrain + +1099 +00:46:45,259 --> 00:46:47,793 +Okay, so that every time disclosure is called, +因此每次闭包被调用 + +1100 +00:46:47,795 --> 00:46:51,396 +every time, you know, grapher one to yForX. +每次,你们知道的,grapher 一个给 yForX + +1101 +00:46:51,398 --> 00:46:53,832 +It keeps reusing this graphing brain over and over and over. +它一直保持重复使用这个 graphingBrain + +1102 +00:46:53,834 --> 00:46:55,133 +Which is exactly what I want because this +这正是我想要的,因为这个 + +1103 +00:46:55,135 --> 00:46:57,068 +graphing brain's got the right program in it. +graphingBrain 在它里面获得了正确的程序 + +1104 +00:46:57,070 --> 00:46:58,869 +It just keeps calling it over and over. +它只是保持不断调用它 + +1105 +00:46:58,871 --> 00:47:00,570 +It doesn't create a new one every time, it just keeps +它并不是每次都创建一个新的,它只是 + +1106 +00:47:00,572 --> 00:47:03,039 +reusing it because it captured it from the outer scope. +重复使用它(graphingBrain),因为它从外部范围捕获了它 + +1107 +00:47:04,409 --> 00:47:05,975 +Everyone understand what I mean by capture? +每个人都理解我所说的捕获了吗? + +1108 +00:47:07,345 --> 00:47:09,678 +Now, this is really cool and really elegant, +这相当酷,相当优雅 + +1109 +00:47:09,680 --> 00:47:11,946 +it looks really awesome, it is awesome, but +看起来棒极了,太棒了,但 + +1110 +00:47:11,948 --> 00:47:13,214 +there are some dangers. +有些危险 + +1111 +00:47:13,216 --> 00:47:14,415 +Okay? + +1112 +00:47:14,417 --> 00:47:16,767 +Capture danger. +捕获危险 + +1113 +00:47:16,768 --> 00:47:19,118 +The problem is, if a closure captures a pointer to +问题是,如果一个闭包捕获了一个指向某个东西的 + +1114 +00:47:19,121 --> 00:47:23,056 +something and that something has a pointer back to +指针,而这个东西有个指针指回 + +1115 +00:47:23,058 --> 00:47:26,225 +the closure, now you have a loop. +闭包,这样你们就有了一个环 + +1116 +00:47:26,227 --> 00:47:28,094 +A memory cycle that's going to keep them both in +一个内存周期,这将导致它们永远被 + +1117 +00:47:28,096 --> 00:47:29,695 +memory forever. +保留在内存中 + +1118 +00:47:29,697 --> 00:47:31,597 +Okay? Kind of +像 + +1119 +00:47:31,598 --> 00:47:33,498 +like the memory cycle we were talking about before. +我之前讲过的内存周期 + +1120 +00:47:33,499 --> 00:47:35,399 +This is easy to have happen in a closure. +这在闭包内很容易发生 + +1121 +00:47:35,402 --> 00:47:36,901 +This is what it looks like, so +它就像这样 + +1122 +00:47:36,903 --> 00:47:39,137 +here's another example here of closures. +这里是另一个闭包的例子 + +1123 +00:47:39,139 --> 00:47:40,871 +I've got this class called Foo. +我们称这个类为 Foo + +1124 +00:47:40,873 --> 00:47:44,508 +It's got one property which is a function called action. +它有一个叫做 action 的函数属性 + +1125 +00:47:44,510 --> 00:47:47,678 +It's got another function called show, +它有另一个函数叫做 show + +1126 +00:47:47,680 --> 00:47:51,448 +which takes an integer and shows it, prints it. +这个函数接收一个整型输入,然后输出它 + +1127 +00:47:51,450 --> 00:47:54,784 +And then it's got a method called setupMyAction, and +然后它有个方法叫做 setupMyAction + +1128 +00:47:54,786 --> 00:47:57,319 +setupMyAction has a local variable, x, +setupMyAction 有个本地变量,x + +1129 +00:47:57,321 --> 00:47:58,654 +which is an integer. +x 是个整型 + +1130 +00:47:58,656 --> 00:48:02,157 +That it assigns that action. +它分配了那个 action + +1131 +00:48:02,159 --> 00:48:03,608 +[COUGH]. + +1132 +00:48:03,609 --> 00:48:05,058 +Function, property to a closure. +函数,一个闭包属性 + +1133 +00:48:05,061 --> 00:48:08,462 +Inside that closure it uses the x. +它在闭包里面使用了 x + +1134 +00:48:08,464 --> 00:48:10,464 +That's cool, it captures x. +这很酷,它捕获了 x + +1135 +00:48:10,466 --> 00:48:12,065 +This will actually work. +这将能工作 + +1136 +00:48:12,067 --> 00:48:13,800 +This will print 1, 2, 3, 4, 5, 6, 7, 8, 9, 10. +这将输出 1,2,3,4,5,6,7,8,9,10 + +1137 +00:48:13,802 --> 00:48:15,435 +You can see the doMyAction10times at +你可以看到下面的 doMyAction10times + +1138 +00:48:15,437 --> 00:48:17,137 +the bottom. +函数 + +1139 +00:48:17,138 --> 00:48:18,838 +If you set up my action it will do it because the x +如果你调用 setupMyAction(),它可行,因为 + +1140 +00:48:18,840 --> 00:48:20,839 +gets captured by the closure and +x 已被闭包捕获,然后 + +1141 +00:48:20,841 --> 00:48:23,041 +every time the closure get executed. +每次闭包都被执行 + +1142 +00:48:23,043 --> 00:48:25,276 +[COUGH]. It increments that x and +它递增 x + +1143 +00:48:25,278 --> 00:48:26,744 +counts to 10. +然后累计到 10 + +1144 +00:48:26,746 --> 00:48:29,947 +It's also cool because it's capturing self. +捕获本身也很酷 + +1145 +00:48:29,949 --> 00:48:32,549 +Because I'm using myself to show the number, +因为我使用我自己来显示这个数字 + +1146 +00:48:32,551 --> 00:48:34,217 +by calling self.show. +通过调用 self.show + +1147 +00:48:34,219 --> 00:48:36,419 +But here's where the danger comes in. +但这也是危险的来源 + +1148 +00:48:36,421 --> 00:48:38,555 +Okay? + +1149 +00:48:38,556 --> 00:48:40,690 +Because self has a pointer to the closure and +因为 self 有个指针指向闭包,然后 + +1150 +00:48:40,692 --> 00:48:43,859 +the closure inside has a pointer back to self. +闭包内部有个指针指回 self + +1151 +00:48:43,861 --> 00:48:46,729 +Now, when you write a closure you'll notice that any +当你们写一个闭包时,你将注意到任何 + +1152 +00:48:46,731 --> 00:48:49,931 +time you call methods it makes you put self, +时候你调用方法,它都要你输入 self + +1153 +00:48:49,933 --> 00:48:51,833 +makes you say self dot. +让你输入 self. + +1154 +00:48:51,835 --> 00:48:53,501 +That's because it wants you to be clear. +这是因为它要让你清楚知道 + +1155 +00:48:53,503 --> 00:48:56,904 +You are capturing self when you call show. +在你调用 show 时,你正在捕获你自己 + +1156 +00:48:56,906 --> 00:48:58,105 +Okay? + +1157 +00:48:58,107 --> 00:49:01,174 +Now, this is a problem, this class +这是一个问题,这个 Foo + +1158 +00:49:01,176 --> 00:49:04,043 +Foo and this closure are pointed to each other, they +类,和这个闭包互相指向对方,它们 + +1159 +00:49:04,045 --> 00:49:06,779 +will stay in memory forever, they can never be released. +将永远保存在内存中,它们永远不会被释放 + +1160 +00:49:06,781 --> 00:49:08,914 +How do we fix that problem? +我们如何修复这个问题 + +1161 +00:49:08,916 --> 00:49:10,282 +Well, we can actually say, +实际上我们可以 + +1162 +00:49:10,284 --> 00:49:15,553 +when we make a closure, do not capture this variable in here. +当我们创建一个闭包时,别在这里捕获这个变量 + +1163 +00:49:15,555 --> 00:49:17,088 +Okay? + +1164 +00:49:17,089 --> 00:49:18,622 +You do that by saying, [COUGH] unowned, +你通过使用 unowned 来实现 + +1165 +00:49:18,624 --> 00:49:22,359 +whatever the variables you don't want to be captured. +不管变量是什么,你都不想捕获 + +1166 +00:49:22,361 --> 00:49:24,094 +Okay? You just put it right at +你必须把它放在 + +1167 +00:49:24,095 --> 00:49:25,828 +the beginning of the closure, before the in. +闭包的最开始,在 in 之前 + +1168 +00:49:25,831 --> 00:49:27,097 +Okay? If you have arguments, +如果你有参数 + +1169 +00:49:27,099 --> 00:49:29,031 +you put it right before the, in, there. +你把它放在 in 前面,这里 + +1170 +00:49:30,935 --> 00:49:31,900 +That will make it work. +这样它就能工作 + +1171 +00:49:31,902 --> 00:49:34,369 +You can also say weak self. +你也可以使用 weak self + +1172 +00:49:34,371 --> 00:49:36,254 +Which is a little different. +这个有点不同 + +1173 +00:49:36,255 --> 00:49:38,138 +That will make the self be a weak pointer in there. +这将使得 self 为一个弱指针 + +1174 +00:49:38,141 --> 00:49:40,875 +We learned about weak pointers in the lecture when we +在我们讲代理时我们学习了 + +1175 +00:49:40,877 --> 00:49:42,876 +talked about delegation. +弱指针 + +1176 +00:49:42,878 --> 00:49:43,944 +So weak would work, too. +所以 weak 也可行 + +1177 +00:49:43,946 --> 00:49:46,280 +It wouldn't do it. +它不能够 + +1178 +00:49:46,281 --> 00:49:48,615 +The difference between unowned is that pointer doesn't have +无主引用和弱引用的区别是,指针若不是一个 + +1179 +00:49:48,617 --> 00:49:51,184 +to be an optional that can be set to nil. +可选型,那么它可以被设置为 nil + +1180 +00:49:51,186 --> 00:49:52,786 +It can just be anything. +它可以是任何东西 + +1181 +00:49:52,787 --> 00:49:54,387 +You just guarantee that self will never become nil. +你只要保证 self 永远不会变成 nil + +1182 +00:49:54,389 --> 00:49:56,388 +So, for the lifetime of this closure, +因此,在这个闭包的生命周期 + +1183 +00:49:56,390 --> 00:49:58,824 +self can never become nil. +self 永远不会变成 nil + +1184 +00:49:58,826 --> 00:50:00,042 +Okay? + +1185 +00:50:00,043 --> 00:50:01,259 +Now, self can be released from the heap, +现在,self 能够在堆中被释放 + +1186 +00:50:01,261 --> 00:50:03,061 +which will release the closure now, from the heap. +这将从堆中释放闭包 + +1187 +00:50:03,063 --> 00:50:04,095 +That's great, but +非常棒,但 + +1188 +00:50:04,097 --> 00:50:06,463 +that closure can never be executed while self, +在 self,即 Fool 为 nil 时,闭包将 + +1189 +00:50:06,465 --> 00:50:07,831 +this Foo thing, is nil. +永不被执行 + +1190 +00:50:07,833 --> 00:50:09,499 +Which is fine, because it's only used inside Foo, +很好,因为他只在 Foo 内部使用 + +1191 +00:50:09,501 --> 00:50:10,600 +[COUGH] That would never happen. +这永远不会发生 + +1192 +00:50:11,536 --> 00:50:12,167 +Okay? + +1193 +00:50:12,169 --> 00:50:13,619 +Unowned self. +无主 self + +1194 +00:50:13,620 --> 00:50:15,070 +This is all covered in the documentation that you +这全都可以在文档中查阅,你们 + +1195 +00:50:15,072 --> 00:50:17,038 +were supposed to have read, but, you might have +应该读过了,但,你们可能 + +1196 +00:50:17,040 --> 00:50:19,307 +not really understood this, or glossed over it, so I'm +没真正理解它,或忽略了它,因此我 + +1197 +00:50:19,309 --> 00:50:22,276 +just revisiting it to tell you that [COUGH] It's important. +只是重新审视它,告诉你们这很重要 + +1198 +00:50:22,278 --> 00:50:23,243 +Okay. Because we're going to +因为我们将在这门课程中 + +1199 +00:50:23,245 --> 00:50:24,845 +start using closures more and +越来越多地使用闭包 + +1200 +00:50:24,847 --> 00:50:28,981 +more in this class and you will be capturing values and +你们将捕获变量 + +1201 +00:50:28,983 --> 00:50:31,350 +some of them will point back to the closure. +有些会指回闭包 + +1202 +00:50:31,352 --> 00:50:32,551 +Okay? + + +1203 +00:50:32,553 --> 00:50:36,088 +[COUGH] Okay, that's it. +就是这样 + +1204 +00:50:36,090 --> 00:50:37,822 +Next is multithreading. +下一个是multithreading + +1205 +00:50:37,824 --> 00:50:38,690 +Okay. Yes, question. +是的,有问题 + +1206 +00:50:38,692 --> 00:50:40,358 +Is there an example, could you give +例如,能不能举一个 + +1207 +00:50:40,360 --> 00:50:42,893 +an example other than self where it would point back? +除了它自己可指回的例子? + +1208 +00:50:42,895 --> 00:50:46,596 +I think about that swift reference document has a whole +我想Swift参考文档里面有一个大的 + +1209 +00:50:46,598 --> 00:50:50,333 +big, long example, so I would just refer you to that. +完整的例子,所以我觉得你应该回去看那个 + +1210 +00:50:50,335 --> 00:50:51,501 +Any other questions about that? +还有其他关于那个的问题吗 + +1211 +00:50:51,503 --> 00:50:53,002 +[COUGH] Okay. +Okay + +1212 +00:50:53,004 --> 00:50:57,305 +Multithreading, how many people in here have done some +Multithreading,这里有多少人 + +1213 +00:50:57,307 --> 00:50:59,541 +programming in a multithreaded environment before? +之前在多线程环境下编过程的? + +1214 +00:51:02,779 --> 00:51:05,413 +More than half, that's more than usual, so that's good. +超过一半,比一般情况多,很好 + +1215 +00:51:05,415 --> 00:51:07,381 +All right, then this will all be pretty easy for +好的,这对你们来说 + +1216 +00:51:07,383 --> 00:51:08,682 +you to understand. +非常好理解 + +1217 +00:51:08,683 --> 00:51:09,982 +Those of you who haven't, it will be a struggle. +这对没有过多线程编程经历的同学可能稍微有些难 + +1218 +00:51:09,985 --> 00:51:12,318 +The first time you do it, I'm sure all of you can attest, +你们第一次做这个,你们可以作证 + +1219 +00:51:12,320 --> 00:51:16,355 +it's a little bit harder to understand what's going on. +你们理解这个可能会有些困难 + +1220 +00:51:16,357 --> 00:51:17,990 +It's actually fairly simple. +这实际上相当简单 + +1221 +00:51:17,992 --> 00:51:22,227 +What's going on here is, in iOS there are multiple queues. +这里发生的是,在iOS里有多重队列 + +1222 +00:51:22,229 --> 00:51:23,761 +A queue meaning like a queue at +一个队列表示像是一个在 + +1223 +00:51:23,763 --> 00:51:26,497 +the movie where people lined up to go see a movie. +电影院人们排着队去看一部电影 + +1224 +00:51:26,499 --> 00:51:29,233 +A queue in a computer science sense is just a list of things +一个队列在计算机科学里就像是一个 + +1225 +00:51:29,235 --> 00:51:32,469 +where things go into the front of the queue, go into the back +东西可以进入队列前面或者后面 + +1226 +00:51:32,471 --> 00:51:35,071 +of the queue rather and they get pulled off the front. +或者被拉到队列最前面 + +1227 +00:51:35,073 --> 00:51:40,176 +It's a queue of functions, basically closures usually. +这就是一个函数队列,基础的闭包 + +1228 +00:51:40,178 --> 00:51:41,544 +Okay. +Okay + +1229 +00:51:41,545 --> 00:51:42,911 +That are sitting there waiting to run. +就坐在那等着运行 + +1230 +00:51:42,913 --> 00:51:47,749 +Each of these queues has it's own threads to run +每一个队列都有一个自己的线程去运行这些队列 + +1231 +00:51:47,751 --> 00:51:50,151 +these queues, to process the things on the queues. +去处理队列里的东西 + +1232 +00:51:51,120 --> 00:51:53,854 +That makes this a multithreaded environment. +这就造就多线程环境 + +1233 +00:51:53,856 --> 00:51:55,322 +Now, there's a very, +这里有个非常非常重要的 + +1234 +00:51:55,324 --> 00:51:58,158 +very important queue called the main queue. +队列叫做主队列 + +1235 +00:51:58,160 --> 00:52:01,227 +This main queue is a serial queue, meaning it +主队列是个串行队列 + +1236 +00:52:01,229 --> 00:52:04,597 +pulls these functions off the queue one at a time. +这说明主队列一次从队列里拉出一个函数 + +1237 +00:52:04,599 --> 00:52:06,865 +It never runs [COUGH] Two of them at the same time. +它从来不会同一时间一次运行两个函数 + +1238 +00:52:06,867 --> 00:52:08,734 +Okay. They're serial, one at a time. +是连续的,一次一个 + +1239 +00:52:08,736 --> 00:52:13,071 +And all UI activity has to happen on the main queue. +所有的UI活动都必须发生在主队列 + +1240 +00:52:13,073 --> 00:52:16,841 +So if you ever wanted to have a function or closure, +所以当你想要一个函数或是闭包 + +1241 +00:52:16,843 --> 00:52:20,344 +that is executing some code, that did anything with the UI, +这就会执行某些代码,这就会做任何关于UI的事 + +1242 +00:52:20,346 --> 00:52:21,812 +you have to put it on the main queue. +你必须把他放在主队列 + +1243 +00:52:21,814 --> 00:52:24,681 +It can only execute on the main queue. +这只能在主队列里执行 + +1244 +00:52:24,683 --> 00:52:30,519 +This is how basically the UI is protected +这就是UI是如何被从被混入多线程的环境中 + +1245 +00:52:30,521 --> 00:52:33,422 +from getting messed up in the multithreaded environment. +被根本上保护的 + +1246 +00:52:33,424 --> 00:52:34,823 +It has this main queue. +它获得了主队列 + +1247 +00:52:34,825 --> 00:52:35,857 +Okay? So the main queue, +所以主队列 + +1248 +00:52:35,859 --> 00:52:37,225 +very, very important. +非常非常重要 + +1249 +00:52:37,227 --> 00:52:38,726 +The main queue never wants to +主队列绝对不想 + +1250 +00:52:38,728 --> 00:52:44,031 +be doing anything that might block NS data contents of URL. +做任何可能阻塞包含URL的NSData的 + +1251 +00:52:44,033 --> 00:52:46,066 +That should never be in the main queue. +所以这绝对不要出现在主队列里 + +1252 +00:52:46,068 --> 00:52:48,868 +So we're going to have to get that off the main queue. +所以我们要把那个从主队列中拿出来 + +1253 +00:52:48,870 --> 00:52:50,436 +All the code that you write normally in +所以你通常写在你的 + +1254 +00:52:50,438 --> 00:52:53,272 +your MVC that's all happening on the main queue. +MVC里的代码都发生在主队列里 + +1255 +00:52:53,274 --> 00:52:55,841 +View did load, view will appear, all that stuff, +View did load, view will appear,所以东西 + +1256 +00:52:55,843 --> 00:52:57,609 +all happening on the main queue automatically for you, +所有都为你自动的在主队列里发生了 + +1257 +00:52:57,611 --> 00:52:59,544 +you don't have to do anything special. +不用特地去做什么 + +1258 +00:52:59,546 --> 00:53:01,996 +Okay? +Okay? + +1259 +00:53:01,997 --> 00:53:04,447 +But, there are other queues that iOS will create for you +但是iOS还会在你需要的时候为你创建其他队列 + +1260 +00:53:04,450 --> 00:53:06,750 +as you need, and we're going to show you how those work. +我会给你们展示这些是如何做到的 + +1261 +00:53:07,953 --> 00:53:10,153 +First of all, how do execute a function or +首先,如何在另外一个队列里 + +1262 +00:53:10,155 --> 00:53:11,821 +a closure on another queue? +执行一个函数或是闭包? + +1263 +00:53:11,823 --> 00:53:14,790 +Well, you do that with this function [COUGH] Called, +你用这个函数来做到 + +1264 +00:53:14,792 --> 00:53:15,958 +dispatch_async. +叫做dispatch_async + +1265 +00:53:15,960 --> 00:53:17,510 +Okay? +Okay? + +1266 +00:53:17,511 --> 00:53:19,061 +So you say dispatch_async, the argument, +所以就有dispatch_async 参数 + +1267 +00:53:19,063 --> 00:53:21,529 +there's two arguments, a queue and a closure. +这有两个参数,一个队列一个闭包 + +1268 +00:53:22,465 --> 00:53:24,265 +The first argument is the queue. +第一个参数是队列 + +1269 +00:53:24,267 --> 00:53:26,533 +I'm using the trailing closure syntax here to +我在这用了尾随闭包语法 + +1270 +00:53:26,535 --> 00:53:28,869 +put the closure outside the parentheses there but +来把闭包放到了括号外面 + +1271 +00:53:28,871 --> 00:53:31,171 +you just specify what queue you want to +但你只要指明你想用哪个队列 + +1272 +00:53:31,173 --> 00:53:33,706 +execute the closure on and then you pass it to closure. +来执行闭包,然后你再传递闭包 + +1273 +00:53:34,876 --> 00:53:36,442 +Okay? And the closure takes no +Okay?闭包没有参数 + +1274 +00:53:36,444 --> 00:53:39,711 +arguments, returns no arguments and that's it. +不返回参数,就是这样 + +1275 +00:53:39,713 --> 00:53:40,612 +That's how you do it. +这就是你的做法 + +1276 +00:53:40,614 --> 00:53:42,080 +Couldn't be easier. +不能再简单 + +1277 +00:53:42,081 --> 00:53:43,547 +dispatch_async on the queue you want. +dispatch_async就在你想要的队列上了 + +1278 +00:53:43,550 --> 00:53:46,217 +So how do you get the queue that you want? +那么你怎么获得你想要的队列呢? + +1279 +00:53:46,219 --> 00:53:48,886 +Well, you get the main queue using this function +你可以通过这个函数获取主队列: + +1280 +00:53:48,888 --> 00:53:52,089 +dispatch_get_main_queue and that returns the main queue. +dispatch_get_main_queue,然后就能返回主队列 + +1281 +00:53:52,091 --> 00:53:54,257 +There's also an object-oriented way to do it, +也有个面向对象的方式去做到 + +1282 +00:53:54,259 --> 00:53:56,125 +NSOperationQueue.mainQueue. +NSOperationQueue.mainQueue. + +1283 +00:53:57,595 --> 00:53:58,794 +You got this queue and +你获得这个队列 + +1284 +00:53:58,796 --> 00:54:01,730 +here's an example of putting something on the main +这有个把一些东西放进 + +1285 +00:54:01,732 --> 00:54:04,733 +queue dispatch_async, [COUGH] notTheMainQueue, +主队列的例子dispatch_async (notTheMainQueue) + +1286 +00:54:04,735 --> 00:54:07,602 +something, and then inside there [COUGH] You could +在这个里面 + +1287 +00:54:07,604 --> 00:54:10,538 +say dispatch_async_main_queue. +你可以说dispatch_async_main_queue + +1288 +00:54:10,540 --> 00:54:13,173 +This is how you do multithreading programming. +这就是你如何做到多线程编程 + +1289 +00:54:13,175 --> 00:54:15,175 +Those lines of code right there. +这些代码在这 + +1290 +00:54:15,177 --> 00:54:19,278 +I want to do something that doesn't block the UI, so +我想做一些不阻塞UI的事 + +1291 +00:54:19,280 --> 00:54:21,313 +I dispatch it to notTheMainQueue, +我就把他发送进notTheMainQueue + +1292 +00:54:21,315 --> 00:54:23,249 +some other queue, +一些其他的队列 + +1293 +00:54:23,250 --> 00:54:25,184 +[COUGH] I'll talk about how to get those queues in a second. +我一会会说道如何获取那些队列 + +1294 +00:54:25,186 --> 00:54:28,887 +Then I do it, go do something like NSdata contents of URL, +然后我做一些像是包含URL的NSData + +1295 +00:54:28,889 --> 00:54:30,621 +blocks, whatever. +blocks之类的 + +1296 +00:54:30,623 --> 00:54:33,758 +When it's done, I need to talk back to the main queue to +当这做完的时候,我要再说回主队列 + +1297 +00:54:33,760 --> 00:54:37,094 +update my UI with the image I got or something like that. +用图片或者类似的东西来更新我的UI + +1298 +00:54:37,096 --> 00:54:37,928 +The way I do that is [COUGH] +我做这些的方法是 + +1299 +00:54:37,930 --> 00:54:40,263 +I dispatch back to the main queue. +我发送回主队列 + +1300 +00:54:40,265 --> 00:54:42,531 +So you nest these calls to the dispatch. +所以你把那些调用都发送回去 + +1301 +00:54:43,801 --> 00:54:45,884 +Okay? +Okay? + +1302 +00:54:45,885 --> 00:54:47,968 +You're basically running code on another queue and when +你只是把代码运行在另外一个队列里 + +1303 +00:54:47,971 --> 00:54:51,006 +it wants to dock back to the main queue it just posts or +当他想对接进主队列的时候他只是 + +1304 +00:54:51,008 --> 00:54:53,741 +puts some code back on the main queue. +发送或者放了些代码回到主队列 + +1305 +00:54:53,743 --> 00:54:55,443 +Now, the main queue might be busy. +现在,主队列可能正在处理一些事情 + +1306 +00:54:55,445 --> 00:54:57,711 +But when it's done it's a serial queue but +但当这做完的时候,这是个串行队列 + +1307 +00:54:57,713 --> 00:55:02,082 +eventually it will get to this block and it will run it. +但最后还是会获取这个block并继续运行 + +1308 +00:55:02,084 --> 00:55:03,549 +Okay? +Okay? + +1309 +00:55:03,551 --> 00:55:04,684 +Everybody understand that? +所有人都懂了吗 + +1310 +00:55:04,686 --> 00:55:06,051 +That's it. +就是这样 + +1311 +00:55:06,053 --> 00:55:08,153 +It's so simple really, actually when you see it, +这真的很简单,事实上当年看的时候 + +1312 +00:55:08,155 --> 00:55:09,387 +it's almost too simple. +这真的好简单 + +1313 +00:55:09,389 --> 00:55:11,522 +The code, when you write it, it's so simple you +你在写这些代码的时候,因为太简单了 + +1314 +00:55:11,524 --> 00:55:14,325 +can get confused and forget that you're in a multithreaded +你甚至会忘记你是在多线程环境里 + +1315 +00:55:14,327 --> 00:55:16,860 +environment, but this is really, those lines of +但这真的是多线程 + +1316 +00:55:16,862 --> 00:55:18,862 +code you're seeing right there at the bottom, that is +你看到的底下的这些代码 + +1317 +00:55:18,864 --> 00:55:25,335 +the fundamental multithreaded programming syntax in iOS. +这就是iOS中最基础大多线程编程语句 + +1318 +00:55:25,337 --> 00:55:27,103 +How do you get these other queues, +怎么获得其他队列, + +1319 +00:55:27,105 --> 00:55:30,305 +you don't want to run on the main queue. +你不想在主队列中运行的 + +1320 +00:55:30,307 --> 00:55:32,574 +You get a queue from the system by asking for +你通过向系统申请一个恰当档次的service + +1321 +00:55:32,576 --> 00:55:34,809 +a certain quality of service. +来获取队列 + +1322 +00:55:34,811 --> 00:55:36,110 +And the four qualities of service, +有四个档次的service + +1323 +00:55:36,112 --> 00:55:37,511 +there's user interactive, +这是user interactive + +1324 +00:55:37,513 --> 00:55:39,646 +which is I'm going to do something off the main queue, +表示我将要在主队列外做一些事情 + +1325 +00:55:39,648 --> 00:55:41,715 +but the user really wants this done fast, and +但用户想非常快的处理它 + +1326 +00:55:41,717 --> 00:55:43,016 +it's not going to take very long. +不能耽误太久 + +1327 +00:55:43,018 --> 00:55:44,150 +So do it right now. +所以现在就做 + +1328 +00:55:44,152 --> 00:55:45,818 +Okay? So it's a high +Okay?所以这是个 + +1329 +00:55:45,819 --> 00:55:47,485 +priority queue for things that go really fast. +高优先级的队列来让事情处理的很快 + +1330 +00:55:47,488 --> 00:55:50,522 +Then there's USER_INITIATED which is the user just +下一个是USER_INITIATED,是一个 + +1331 +00:55:50,524 --> 00:55:53,692 +asked for this, but I know it's going to take a long time +用户请求这个,但我知道这要很长时间 + +1332 +00:55:53,694 --> 00:55:55,694 +fetching an image off the network, +去从网络抓取图片 + +1333 +00:55:55,696 --> 00:55:59,364 +we would USER_INITIATED, but it's still pretty important. +我就会用USER_INITIATED,但这也很重要 + +1334 +00:55:59,366 --> 00:56:02,166 +Then there's utility, which is I'm just doing something. +下一个是utility,是我只是做一些事情 + +1335 +00:56:02,168 --> 00:56:03,734 +The user didn't just ask me to do this. +用户没有让我去做 + +1336 +00:56:03,736 --> 00:56:05,035 +But it's just something I +但我只是 + +1337 +00:56:05,037 --> 00:56:08,505 +need to do in the background processing things or whatever. +需要做一些后台进程之类的事 + +1338 +00:56:08,507 --> 00:56:11,908 +But it is something that matters right now to the user. +但这是一些现在就关系到用户的事 + +1339 +00:56:11,910 --> 00:56:14,176 +So it would be nice if it returned somewhat soon, but +如果现在就能返回一些东西那就最好了 + +1340 +00:56:14,178 --> 00:56:16,211 +it's not like got to have it. +但不会去主动获取这个 + +1341 +00:56:16,213 --> 00:56:18,513 +And then there's background which is like things that +下一个是background + +1342 +00:56:18,515 --> 00:56:20,482 +are not concerned with what the user is doing right now. +像是一个不关心用户现在在做什么的事 + +1343 +00:56:20,484 --> 00:56:23,584 +Like oh I'm pre-fetching some data, updating some database, +比如我正在预抓取一些数据,更新数据库 + +1344 +00:56:23,586 --> 00:56:26,320 +cleaning up a database, doing stuff in the background. +清楚数据库,在后台做一些事 + +1345 +00:56:26,322 --> 00:56:28,255 +It really has nothing to do with the user doing now, +这真的跟用户现在做的事没关系 + +1346 +00:56:28,257 --> 00:56:29,956 +you understand what I mean? +你理解我的意思吗 + +1347 +00:56:29,958 --> 00:56:30,990 +Just background task. +只是后台任务 + +1348 +00:56:31,960 --> 00:56:34,827 +So you create a quality of service, +所以你建立一种级别的service + +1349 +00:56:34,829 --> 00:56:37,129 +you do that with this really odd int. +你用一个奇怪的int去做 + +1350 +00:56:37,131 --> 00:56:38,797 +One of these constants above there, +上面的其中一个常数 + +1351 +00:56:38,799 --> 00:56:41,800 +.value, close parentheses, okay. +.value,闭括弧 + +1352 +00:56:41,802 --> 00:56:44,035 +For historical reasons, they have them put a nice, +因为历史原因,他们在swift里有个很好看 + +1353 +00:56:44,037 --> 00:56:45,870 +new UI in there Swift, which is interesting. +的新UI,很有趣 + +1354 +00:56:45,872 --> 00:56:47,271 +But anyway, you do that. +不管怎样,你就是做了这个 + +1355 +00:56:47,273 --> 00:56:49,089 +And then you just say, +然后 + +1356 +00:56:49,090 --> 00:56:50,906 +queue equals dispatch_get_global_queue with +queue equals dispatch_get_global_queue with + +1357 +00:56:50,909 --> 00:56:53,076 +that quality of service, comma 0. +that quality of service, comma 0. + +1358 +00:56:53,078 --> 00:56:56,412 +That comma 0 is reserved for future use, okay? +那个0留着以后会用到 + +1359 +00:56:56,414 --> 00:56:57,146 +And that's it. +就是这样 + +1360 +00:56:57,148 --> 00:56:58,547 +Now you have another queue. +现在你有了另外一个队列 + +1361 +00:56:58,549 --> 00:57:00,916 +You can now dispatch async to it, and +你现在可以dispatch async给它 + +1362 +00:57:00,918 --> 00:57:02,517 +be running code off the main queue. +并且在主队列外运行代码 + +1363 +00:57:04,354 --> 00:57:04,919 +Simple as that. +就是这么简单 + +1364 +00:57:05,988 --> 00:57:07,788 +You can create your own serial queues too. +你可以建立自己的串行队列 + +1365 +00:57:07,790 --> 00:57:09,222 +I'm not going to talk about that really, but +我不准备讲那个 + +1366 +00:57:09,224 --> 00:57:11,524 +you might have something where these queues that I'm +但你可能会在我上面提到的 + +1367 +00:57:11,526 --> 00:57:13,109 +talking about at the top, +几种service中 + +1368 +00:57:13,110 --> 00:57:14,693 +these quality service based ones, are concurrent. +同时用到 + +1369 +00:57:14,696 --> 00:57:17,896 +So actually a single queue, like the user interactive +所以一个单独的队列,像是user interactive队列 + +1370 +00:57:17,898 --> 00:57:20,032 +queue, could actually have multiple threads running, +可以真的多线程运行 + +1371 +00:57:20,034 --> 00:57:21,066 +working on it at the same time. +同时在上面工作 + +1372 +00:57:21,068 --> 00:57:22,533 +If you have a multi-core processor they can +如果你有个多核处理器 + +1373 +00:57:22,535 --> 00:57:25,936 +even actually be working on them. +它可以真的在上面工作 + +1374 +00:57:25,938 --> 00:57:27,871 +But mostly it's time sharing, +但大多数情况是分时的 + +1375 +00:57:27,873 --> 00:57:30,540 +time slicing between the various threads. +时间分给了数个线程 + +1376 +00:57:30,542 --> 00:57:32,142 +But, anyway, you can do a serial 1. +但是你可以做一个serial 1 + +1377 +00:57:32,144 --> 00:57:34,410 +And you would do that only if you wanted to do something off +只有当你想在主队列外 + +1378 +00:57:34,412 --> 00:57:38,014 +the main thread that something depends on the next things, +做一些事的时候,这些事根据下面的事区分 + +1379 +00:57:38,016 --> 00:57:39,065 +depends on the next things. +根据下面的事区分 + +1380 +00:57:39,066 --> 00:57:40,115 +So you want to want to do them serially or +所以你想连续的去做 + +1381 +00:57:40,117 --> 00:57:41,283 +you want to throttle. +或者你想可控速度的去做 + +1382 +00:57:41,285 --> 00:57:43,251 +Like you're fetching a bunch of images, but +比如你想要抓去一些图片 + +1383 +00:57:43,253 --> 00:57:45,119 +you don't want to bombard, you know, +但你又不想让他们占了全部网速 + +1384 +00:57:45,121 --> 00:57:47,922 +Flicker or whoever you're requesting the images from +Flicker或者任何你想用上百个问题 + +1385 +00:57:47,924 --> 00:57:49,056 +with hundreds of questions. +来请求图片的网站 + +1386 +00:57:49,058 --> 00:57:50,624 +You're just going to do them one at a time. +你只想一次做一个 + +1387 +00:57:50,626 --> 00:57:52,058 +And they're going to appear in the UI one at a time. +任何他们就会一次在UI上显示一个 + +1388 +00:57:52,060 --> 00:57:54,427 +So you can do your own +所以你用dispatch_queue_create + +1389 +00:57:54,428 --> 00:57:56,795 +serial queues with dispatch_queue_create. +自己做一个串行队列了 + +1390 +00:57:56,798 --> 00:57:57,363 +Okay? +Okay? + +1391 +00:57:59,099 --> 00:58:01,099 +You can also use the multi-threading stuff to +你以后也可以 + +1392 +00:58:01,101 --> 00:58:02,834 +do something in the future. +用多线程去做一些事 + +1393 +00:58:02,836 --> 00:58:03,567 +Okay? You do that with +你通过 + +1394 +00:58:03,569 --> 00:58:04,968 +this dispatch after. +稍后发送这个做到 + +1395 +00:58:04,970 --> 00:58:07,404 +It's kind of odd again. +这又有点奇怪了 + +1396 +00:58:07,406 --> 00:58:11,174 +The arguments are kind of weird, you do this Int 64 +参数有些奇怪,Int 64 + +1397 +00:58:11,176 --> 00:58:15,111 +delay in seconds times double insect per min insect per +delayInSeconds*Double... + +1398 +00:58:15,113 --> 00:58:18,914 +milliseconds dispatch time now delay, blah blah. +...(念语句) + +1399 +00:58:18,916 --> 00:58:23,118 +You create this basically time dispatched_time t +你只是最基本的 + +1400 +00:58:23,120 --> 00:58:26,421 +that is in the future and then you just say +用dispatched_time创建了队列 + +1401 +00:58:26,423 --> 00:58:31,058 +dispatch after that amount of time on to the main queue. +在之后的一段时间会发送到主队列 + +1402 +00:58:31,060 --> 00:58:32,793 +So you're almost always doing dispatch after on +所以你差不多经常要 + +1403 +00:58:32,795 --> 00:58:34,578 +the main queue. +稍后发送到主队列 + +1404 +00:58:34,579 --> 00:58:36,362 +It's rare that you'd be on another queue +你在别的队列做这个真的很罕见 + +1405 +00:58:36,365 --> 00:58:39,065 +because those other queues are kind of +因为另外一个队列 + +1406 +00:58:39,067 --> 00:58:41,768 +concurrent running queues and such. +事同时发生在运行队列的 + +1407 +00:58:41,770 --> 00:58:45,571 +Anyway it's more likely, I want to put up an alert in +这更像如果用户十秒钟什么都不做 + +1408 +00:58:45,573 --> 00:58:49,274 +ten seconds if the user hasn't done something, or +我就显示一个警告 + +1409 +00:58:49,276 --> 00:58:50,942 +something like that. +或者类似的 + +1410 +00:58:50,944 --> 00:58:53,544 +Which is kind of a weird UI, but anyway. +是一种奇怪的UI + +1411 +00:58:53,546 --> 00:58:55,913 +You never want to block the main queue saying oh wait, +你绝对不要想阻塞主队列,说:嘿,等下 + +1412 +00:58:55,915 --> 00:58:58,349 +20 seconds and then it will be able to do this. +20秒,然后就可以做这个了 + +1413 +00:58:58,351 --> 00:59:00,350 +But you want to be able to notify it. +但是为了提示这个 + +1414 +00:59:00,352 --> 00:59:02,085 +And there's tons and +并且有很多 + +1415 +00:59:02,086 --> 00:59:03,819 +tons of stuff that I'm not even going to talk about, but +很多的东西我还没讲到 + +1416 +00:59:03,822 --> 00:59:06,155 +you can do readers and writers. +你可以做readers 和 writers + +1417 +00:59:06,157 --> 00:59:07,757 +You can protect critical sections of +你可以保护你代码的 + +1418 +00:59:07,759 --> 00:59:08,891 +your code doing this. +关键部分去做这个 + +1419 +00:59:08,893 --> 00:59:10,592 +You can do synchronous dispatch. +你可以做synchronous dispatch + +1420 +00:59:10,594 --> 00:59:12,494 +Okay, instead of asynchronously firing these +代替异步去执行 + +1421 +00:59:12,496 --> 00:59:13,795 +things off to put on the queues. +这个队列 + +1422 +00:59:13,797 --> 00:59:15,763 +You can wait for them to execute. +你可以等待他们去执行 + +1423 +00:59:15,765 --> 00:59:17,014 +All that stuff. +所以的东西 + +1424 +00:59:17,015 --> 00:59:18,264 +You won't need any of that for this class probably. +你可能不需要他们中的任何一项 + +1425 +00:59:18,267 --> 00:59:20,667 +The things I showed you, that's the basics of it. +我给你们看的,是最基础的 + +1426 +00:59:20,669 --> 00:59:21,935 +That's probably all you're going to need. +这可能就是你们需要的全部 + +1427 +00:59:22,937 --> 00:59:25,921 +'Kay? +Okay? + +1428 +00:59:25,922 --> 00:59:28,906 +There are APIs in iOS that are multi-threaded. +这在iOS中的API是multi-threaded + +1429 +00:59:28,909 --> 00:59:30,275 +So, you've got to be careful. +所以你要小心 + +1430 +00:59:30,277 --> 00:59:31,676 +If you're doing something, and +如果你做了什么 + +1431 +00:59:31,678 --> 00:59:33,644 +it seems like this might be multi-threaded, +可能会是多线程的 + +1432 +00:59:33,646 --> 00:59:35,146 +this seems like it might take a little while, +这就表示可能要一会功夫 + +1433 +00:59:35,148 --> 00:59:36,513 +like it's gonna access the network or +可能要获取网络 + +1434 +00:59:36,515 --> 00:59:38,181 +something like that. +一类的事情 + +1435 +00:59:38,183 --> 00:59:39,916 +Then you want to read the documentation and +任何你就要读文档 + +1436 +00:59:39,918 --> 00:59:42,485 +see, are you giving it a block, for +看是否让他阻塞了 + +1437 +00:59:42,487 --> 00:59:45,087 +example, that's going to be executed off the main thread? +比如,是不是要执行完主现场了? + +1438 +00:59:45,089 --> 00:59:47,990 +Because in that block, if you want to do something with +因为在这个阻塞里,如果你想要做一些UI的事 + +1439 +00:59:47,992 --> 00:59:50,192 +the UI you have to post back to the main thread. +你需要发送会主线程 + +1440 +00:59:51,361 --> 00:59:52,060 +Okay? So here's what +Okay?所以这就是 + +1441 +00:59:52,062 --> 00:59:54,762 +that looks like for example. +例子看起来的样子 + +1442 +00:59:54,763 --> 00:59:57,463 +Here is an API, this is the NSURL session API. +这有个API,这个NSURL session API + +1443 +00:59:58,567 --> 01:00:00,967 +The thing in yellow is all that really matters. +黄字非常重要 + +1444 +01:00:00,969 --> 01:00:04,337 +It lets you download a file from a URL. +它让你从一个URL中下载一个文件 + +1445 +01:00:04,339 --> 01:00:05,905 +And it does it asynchronously. +而且是异步的去做 + +1446 +01:00:05,907 --> 01:00:08,907 +And you give it a block, which is the completion handler. +你用completion handler给它一个block + +1447 +01:00:08,909 --> 01:00:11,176 +So when it's done, it invokes your block, +当它做完了,它会唤醒你的block + +1448 +01:00:11,178 --> 01:00:12,844 +and it's got some arguments there. +并且这会获取一些参数 + +1449 +01:00:12,846 --> 01:00:16,114 +It moves the file to a local URL that you can open. +这会移动文件到一个你可以打开的本地URL + +1450 +01:00:16,116 --> 01:00:19,316 +You get HTTP response, you can get an error, et cetera. +你获取HTTP应答,你看你会得到一个error或者别的什么 + +1451 +01:00:21,053 --> 01:00:24,054 +So, you want to do something in there to update the UI, +所以,你想要在这做一些事来更新UI + +1452 +01:00:24,056 --> 01:00:26,422 +cause you got the file back, and can you? +因为你取回了文件,那么你可以吗? + +1453 +01:00:26,424 --> 01:00:29,425 +No, you can't, because that's not on the main queue, +不,你不可以,因为那个不在主队列里 + +1454 +01:00:29,427 --> 01:00:32,728 +however you can put dispatch async in there. +但你可以放一个dispatch async在这 + +1455 +01:00:32,730 --> 01:00:33,995 +Okay, so this is exactly the same code, +所以是完全一样的代码 + +1456 +01:00:33,997 --> 01:00:35,530 +I just add dispatch async in there. +我只是在这加了dispatch async + +1457 +01:00:38,601 --> 01:00:39,834 +All right? +All right? + +1458 +01:00:39,836 --> 01:00:41,201 +So that's example where you dispatch a. +这就是你在哪放dispatch async的例子 + +1459 +01:00:41,203 --> 01:00:43,537 +That is the exactly the same thing as I showed you on that +这就是我刚才在第一张课件给你们看的东西 + +1460 +01:00:43,539 --> 01:00:46,006 +very first slide, it's just that it's wrapped inside an +只是包含了一个iOS API + +1461 +01:00:46,008 --> 01:00:48,508 +iOS API instead of just your own dispatch to another queue. +而不是发送到另外一个队列 + +1462 +01:00:48,510 --> 01:00:50,443 +Okay. +Okay. + +1463 +01:00:50,445 --> 01:00:52,111 +All right so. +所以 + +1464 +01:00:52,113 --> 01:00:56,048 +Again, a demo's worth of vowels and words. +一个值得仔细说的例子 + +1465 +01:00:56,050 --> 01:00:59,617 +So let's go look what it looks to make an Imaginarium there. +所以来看看看如何做一个Imaginarium + +1466 +01:01:00,687 --> 01:01:03,287 +Or Christini I guess I called it this time. +这次我猜我叫他Christini + +1467 +01:01:03,289 --> 01:01:06,456 +Let's make this thing be multi-threaded. +来把它变成多线程 + +1468 +01:01:06,458 --> 01:01:09,592 +So we know that it's really bad UI, it blocks every +我们知道这是个糟糕大UI,每次我们请求大图片 + +1469 +01:01:09,594 --> 01:01:13,196 +time we ask for these big images, it's completely stuck. +都会阻塞,真的很不好 + +1470 +01:01:13,198 --> 01:01:16,766 +So where we fetch the image right here, +所以我们在哪获取图片呢? + +1471 +01:01:16,768 --> 01:01:20,535 +we need to be doing that on a different thread. +我们要在另外一个线程里做 + +1472 +01:01:20,537 --> 01:01:21,236 +All right? So how are we +All right? + +1473 +01:01:21,238 --> 01:01:22,270 +going to do that? +所以我准备做这个 + +1474 +01:01:22,272 --> 01:01:24,038 +We'll we're going to do exactly what I +我们就是要做 + +1475 +01:01:24,040 --> 01:01:25,456 +did in the slides there. +之前课件里讲的 + +1476 +01:01:25,457 --> 01:01:26,873 +Which is I'm going to create one of these quality of +我要在这建立一个之前说的 + +1477 +01:01:26,876 --> 01:01:28,342 +service things here, okay. +service中的一个 + +1478 +01:01:28,344 --> 01:01:29,275 +First of all, I don't need to do +首先,我如果image URL为空 + +1479 +01:01:29,277 --> 01:01:32,445 +anything if my image URL is nil. +我什么都不要做 + +1480 +01:01:32,447 --> 01:01:33,679 +So if it's not nil though, +如果不是 + +1481 +01:01:33,681 --> 01:01:35,614 +then I'm going to let my quality of service equal, +如何就让qos等于 + +1482 +01:01:35,616 --> 01:01:42,887 +let's go ahead and do this so you can see lots of code here. +继续,你可以看到很多代码 + +1483 +01:01:42,889 --> 01:01:44,606 +All right, +All right + +1484 +01:01:44,607 --> 01:01:46,324 +I'm gonna select this quality of service to this weird thing +我要选这些service中的一个 + +1485 +01:01:46,326 --> 01:01:49,760 +int and the quality of service I want is going to be this +有些奇怪的service + +1486 +01:01:49,762 --> 01:01:54,331 +user initiated because the user has asked for something. +我想要这个user initiated,用户请求一些东西 + +1487 +01:01:54,333 --> 01:01:56,232 +It's not gonna be quick, +这不会很快 + +1488 +01:01:56,234 --> 01:01:58,935 +but I want it to be done as soon as it can. +当要经快的完成 + +1489 +01:01:58,937 --> 01:02:01,170 +Because the user's waiting for it basically. +因为用户在等着 + +1490 +01:02:01,172 --> 01:02:03,505 +So that's gonna be my quality of service there. +这就是我要的service + +1491 +01:02:03,507 --> 01:02:06,675 +And then I'm just going to say dispatch, async. +然后就是dispatch async + +1492 +01:02:06,677 --> 01:02:08,943 +The queue I want is a global queue, so +我要的是一个global queue + +1493 +01:02:08,945 --> 01:02:12,113 +I'm going to say get global queue. +获取一个global queue + +1494 +01:02:12,115 --> 01:02:15,783 +I'm gonna actually use a different one of these, +我要用一个完全不一样的 + +1495 +01:02:15,785 --> 01:02:16,483 +hold on. +等等 + +1496 +01:02:16,485 --> 01:02:18,351 +Identifier global queue. +Identifier global queue + +1497 +01:02:18,353 --> 01:02:20,153 +And use this one, +用这个 + +1498 +01:02:20,155 --> 01:02:23,289 +which is the one that takes the quality of service there. +一个要选service的 + +1499 +01:02:23,291 --> 01:02:24,556 +So quality of service. +quality of service + +1500 +01:02:26,527 --> 01:02:29,461 +Not caps, Q O S, there we go. +qos,好了 + +1501 +01:02:29,463 --> 01:02:32,764 +The flags are always zero there, and here's my block. +这里的 flags 参数总是 0,这里是 block + +1502 +01:02:32,766 --> 01:02:34,616 +All right? +看到了吗? + +1503 +01:02:34,617 --> 01:02:36,467 +So let's double-click to do that. +让我们双击这个 block + +1504 +01:02:36,469 --> 01:02:38,802 +I'm going to put that outside, you know, +把它放到括号的外部 + +1505 +01:02:38,804 --> 01:02:42,673 +the trailing closure syntax here I'm going to use. +我将会使用的是尾随闭包语法 + +1506 +01:02:42,675 --> 01:02:46,042 +Now inside here, now I can do the things that slow. +在这个 block 内部,我可以处理一些较慢的工作 + +1507 +01:02:46,044 --> 01:02:49,712 +So, let's put all of this inside here, to start. +把下面的这些都放进来 + +1508 +01:02:49,714 --> 01:02:51,047 +Even though we know that's not going to be good. +即使这可能不太正确 + +1509 +01:02:51,049 --> 01:02:52,014 +All right? +好 + +1510 +01:02:52,016 --> 01:02:54,616 +So, I dispatched async in here. +在这里 dispatch_async + +1511 +01:02:54,618 --> 01:02:57,786 +Notice that it's already complaining that you gotta put +注意 Xcode 已经发现了错误 + +1512 +01:02:57,788 --> 01:02:59,120 +self in here. +你需要在这里加上 self + +1513 +01:02:59,122 --> 01:03:01,489 +That's because I put this inside of a closure. +这是因为我把它放入一个闭包内部 + +1514 +01:03:01,491 --> 01:03:04,191 +And it's capturing self because I'm accessing my +因为我尝试获取 imageBar + +1515 +01:03:04,193 --> 01:03:05,959 +image bar here. +所以它捕获到了 self + +1516 +01:03:05,961 --> 01:03:07,060 +All right, so I can fix that one. +我把它改正过来 + +1517 +01:03:07,062 --> 01:03:09,696 +Let's go ahead and do that here as well. +这个也一样 + +1518 +01:03:09,698 --> 01:03:11,897 +Extra parenthesis. +多余的括号 + +1519 +01:03:11,899 --> 01:03:13,065 +Okay, so that's good. +这看起来还不错 + +1520 +01:03:13,067 --> 01:03:14,232 +Now, this is fine, +很好 + +1521 +01:03:14,234 --> 01:03:16,835 +this is that thing that's going to be slow. +这种很慢的工作 + +1522 +01:03:16,837 --> 01:03:19,037 +It's happening on another thread right now, +我们已经把它放到另一个线程处理了 + +1523 +01:03:19,039 --> 01:03:20,571 +that's great. +这很棒 + +1524 +01:03:20,573 --> 01:03:23,340 +But this is not great because here, this is going to +但是也有些问题 + +1525 +01:03:23,342 --> 01:03:26,410 +cause UI stuff to happen all over the place, right? +这里会涉及 UI 的元素 + +1526 +01:03:26,412 --> 01:03:27,744 +Look at all this UI stuff it's going to do. +看到了吗?这里的 UI 元素 + +1527 +01:03:27,746 --> 01:03:31,581 +So I cannot do this on this thread. +我不能在这个线程处理它们 + +1528 +01:03:31,583 --> 01:03:39,622 +So I just have to dispatch it back to the main thread. +所以我需要把它们放回到主线程运行 + +1529 +01:03:42,693 --> 01:03:45,594 +The main two actually, and +实际上是主线程的队列 + +1530 +01:03:45,596 --> 01:03:51,899 +again I'm going to use the trailing closure syntax there. +在这里我还会使用尾随闭包的语法 + +1531 +01:03:51,901 --> 01:03:55,769 +That's exactly why they designed it that way. +这就是为什么他们会这样设计线程 + +1532 +01:03:55,771 --> 01:03:57,187 +All right, so +好 + +1533 +01:03:57,188 --> 01:03:58,604 +now I'm dispatching back to the main queue. +我已经把它们放回了主队列 + +1534 +01:03:58,607 --> 01:04:00,507 +That's good and all is well. +一切都很好 + +1535 +01:04:00,509 --> 01:04:01,808 +And that's it. +就是这样 + +1536 +01:04:01,810 --> 01:04:03,442 +That's all it took. +这些就是需要进行的工作 + +1537 +01:04:03,444 --> 01:04:07,179 +So you can see the multi-threaded, it's like, +在一系列工作之后,你可以到多线程是什么样了 + +1538 +01:04:07,181 --> 01:04:11,916 +after you've made it, except for this weird end thing. +除了这些奇怪的 Int 操作 + +1539 +01:04:11,918 --> 01:04:14,719 +It made about the minimal amount of codes you could +它可以让你进行有可能 + +1540 +01:04:17,957 --> 01:04:18,789 +possibly be. +最少量的编程工作 + +1541 +01:04:18,791 --> 01:04:20,857 +All right, this is not quite right, +不过还是有点问题 + +1542 +01:04:20,859 --> 01:04:22,809 +we're not quite done here, but +这里还是没有完成 + +1543 +01:04:22,810 --> 01:04:24,760 +let's go see if this has fixed our problem at least. +让我们一起看看,这是否至少已经修复了之前的问题 + +1544 +01:04:24,763 --> 01:04:26,496 +So here we are, so I'm going to go Earth. +选择 Earth + +1545 +01:04:26,498 --> 01:04:28,297 +Now look, I can go back. +看到没?我可以返回了 + +1546 +01:04:28,299 --> 01:04:30,299 +My UI is completely active. +UI 是时刻相应的 + +1547 +01:04:30,301 --> 01:04:32,467 +I can do anything I want, +我可以做任何想做的工作 + +1548 +01:04:32,469 --> 01:04:35,737 +even though it's still loading that thing in the background. +即使程序仍在后台载入图片 + +1549 +01:04:35,739 --> 01:04:38,806 +And eventually, once it's kind of sucked it all down, +一旦最终完成了载入 + +1550 +01:04:38,808 --> 01:04:40,941 +it shows it to me, and I can zoom in on it. +它就会展示给我,我可以缩放它 + +1551 +01:04:40,943 --> 01:04:42,642 +Here we go. +就是这样 + +1552 +01:04:44,946 --> 01:04:49,615 +Okay, so that's exactly what we want. +这就是我们想要的效果 + +1553 +01:04:49,617 --> 01:04:53,252 +And it took virtually no code on our part. +事实上我们没写多少代码 + +1554 +01:04:53,254 --> 01:04:54,886 +However, it's not quite right. +然而,还是有点问题 + +1555 +01:04:56,223 --> 01:04:59,023 +And if you have experienced multi-threading, you're gonna +如果你曾经了解过多线程 + +1556 +01:04:59,025 --> 01:05:00,691 +immediately understand what I'm talking about here. +你会立刻明白我接下来将要叙述的内容 + +1557 +01:05:01,694 --> 01:05:05,328 +This is kind of lulls you into thinking, +这有点哄骗你的意思 + +1558 +01:05:05,330 --> 01:05:08,465 +oh I got this right okay ready to go next problem. +这我已经做好了,我可以处理下一个问题了 + +1559 +01:05:08,467 --> 01:05:13,269 +But what happens if this image data takes a long time to +但是如果花费很长时间下载图片数据的时候 + +1560 +01:05:13,271 --> 01:05:17,239 +come back and in the mean time the user asks for +用户请求了一张新的图片 + +1561 +01:05:17,241 --> 01:05:17,906 +a different image. +会出现什么问题? + +1562 +01:05:21,411 --> 01:05:24,712 +Well, we argue, I can't do that of course because we +这里可能会有些争论 + +1563 +01:05:24,714 --> 01:05:27,448 +segue to and from so we are always creating new nvc but +这不会发生的,因为每次 segue 的时候都创建了一个新的 MVC + +1564 +01:05:27,450 --> 01:05:29,182 +imagine a new nvc that stayed on screen. +但是想象一个出现在屏幕上的新 MVC + +1565 +01:05:29,184 --> 01:05:30,784 +And there was a way to click a button and +有一个按钮 + +1566 +01:05:30,786 --> 01:05:32,318 +it would load a new image. +点击它就会载入一张新的图片 + +1567 +01:05:32,320 --> 01:05:37,956 +Well, this thing might come back after the next request +在下次请求之后,这种情况就可能发生了 + +1568 +01:05:37,958 --> 01:05:41,226 +and show the user the old image they wanted instead of +程序就会展现给用户上一次请求的图片 + +1569 +01:05:41,228 --> 01:05:42,260 +the new one they'd asked for. +而不是他们希望的新图片 + +1570 +01:05:42,262 --> 01:05:43,861 +Do you see the problem? +能想清楚这个问题吗? + +1571 +01:05:43,863 --> 01:05:45,296 +So, this is where modern +这里的多线程问题就 + +1572 +01:05:45,297 --> 01:05:46,730 +threading gets a little hard on your brain. +比较难以理解 + +1573 +01:05:46,733 --> 01:05:47,965 +It's like, oh, what? +就好像,什么? + +1574 +01:05:47,967 --> 01:05:49,399 +These things are happening in a different order +这些发生的顺序都不一样 + +1575 +01:05:49,401 --> 01:05:50,900 +because they're happening in different threads, +因为它们发生在不同的线程中 + +1576 +01:05:50,902 --> 01:05:53,136 +different threads of execution here. +不同的线程在执行 + +1577 +01:05:53,138 --> 01:05:54,270 +So how do we fix that? +我们怎么能修复这个问题呢? + +1578 +01:05:54,272 --> 01:05:56,405 +It's actually fairly simple to fix. +实际上非常简单 + +1579 +01:05:56,407 --> 01:05:59,841 +When this image data comes back, okay, +当这个图片数据请求完成以后 + +1580 +01:05:59,843 --> 01:06:03,545 +we're just gonna check and see if the URL that caused it +我们验证一下引发图片请求的 URL + +1581 +01:06:03,547 --> 01:06:07,315 +to be fetched is the one we currently want. +是不是我们当前想要的 + +1582 +01:06:07,317 --> 01:06:12,252 +So I'm just going to go here and say, if the url, which is +这里我会这样,if url + +1583 +01:06:12,254 --> 01:06:18,291 +this url right here, which was captured by this, okay? +也就是这里的 url + +1584 +01:06:18,293 --> 01:06:23,963 +So if this url up here equals self.imageURL, in other words, +验证一下上面的 url 是否等于 self.imageURL + +1585 +01:06:23,965 --> 01:06:26,565 +the url that my user currently wants,. +换句话说,是不是用户当前想要的 + +1586 +01:06:27,801 --> 01:06:29,200 +Then I'm going to do this. +是的话,就这样做 + +1587 +01:06:30,203 --> 01:06:31,368 +Otherwise I'm going to +否则 + +1588 +01:06:31,370 --> 01:06:32,869 +completely ignore this response. +我会完全忽视这次回应 + +1589 +01:06:34,139 --> 01:06:37,373 +Okay, this JPG file came back but the user has moved on. +JPG 文件下载完成,但是用户已经不需要了 + +1590 +01:06:37,375 --> 01:06:39,542 +They don't even care about this. +用户已经不在乎下载好的图片了 + +1591 +01:06:39,544 --> 01:06:42,044 +So you see what I'm talking about, where you've got to +这里我叙述的关于多线程内容 + +1592 +01:06:42,046 --> 01:06:43,645 +think a little bit with this multithreader. +你们应该多思考一些 + +1593 +01:06:43,647 --> 01:06:44,779 +You can't just throw the code in there and +你不能写完代码往这一放 + +1594 +01:06:44,781 --> 01:06:45,880 +go, oh yeah, it works. +哦,它起作用了,就不管了 + +1595 +01:06:45,882 --> 01:06:47,982 +You have to think about things might be happening, +你应该思考一些可能将要发生的事情 + +1596 +01:06:47,984 --> 01:06:51,051 +taking a long time, cuz they're happening separately. +思考地久一点,因为它们不是同一时刻发生的 + +1597 +01:06:53,555 --> 01:06:55,538 +So that's good. +还不错 + +1598 +01:06:55,539 --> 01:06:57,522 +There's really nothing to show there because our UI doesn't +这里没什么好展示的 + +1599 +01:06:57,525 --> 01:06:59,925 +really allow us to specify a different image. +因为 UI 不许我们列举一个不同的图片 + +1600 +01:06:59,927 --> 01:07:02,061 +When we click back and forth in our UI, +当我们在 UI 中后退或者前进 + +1601 +01:07:02,063 --> 01:07:05,697 +we're creating a new MVC every time because we're segue. +会创建新的 MVC,因为我们是通过 segue 连接的 + +1602 +01:07:05,699 --> 01:07:09,401 +So the new MVC is obviously got its own environment. +所以新的 MVC 有它自己的环境 + +1603 +01:07:09,403 --> 01:07:11,869 +So the last thing I want to show you is our UI is not +最后一点我想要展示给你们的是 + +1604 +01:07:11,871 --> 01:07:16,206 +very good because it has a lot of blank white screen in it. +UI 看起来不太好,因为屏幕上有太多空白的地方 + +1605 +01:07:16,208 --> 01:07:18,475 +Okay, right here, blank white screen, it's like oh, +在这里,空白的屏幕 + +1606 +01:07:18,477 --> 01:07:19,676 +blank white screen, what's going on? +用户会说,空白的屏幕?发生了社么? + +1607 +01:07:19,678 --> 01:07:22,011 +Mm, I don't know, what's happening here? +我不知道这里发生了什么 + +1608 +01:07:22,013 --> 01:07:23,062 +I don't know. +我不知道 + +1609 +01:07:23,063 --> 01:07:24,112 +You see what I mean, it's like +你们应该懂我什么意思 + +1610 +01:07:24,115 --> 01:07:26,548 +I can't even tell what's really going on in my UI. +我不能分辨 UI 到底发生了什么 + +1611 +01:07:26,550 --> 01:07:28,016 +It'd be nice if when I clicked here I +如果我点击这里 + +1612 +01:07:28,018 --> 01:07:31,486 +got like a spinning wheel that would say I'm working on it. +出现一个旋转的圆圈,告诉我正在处理,就会好很多 + +1613 +01:07:31,488 --> 01:07:33,521 +I'm trying to get that thing, okay. +我正在获取图片 + +1614 +01:07:33,523 --> 01:07:35,222 +So we want a nice little spinning wheel in here. +所以在这里我们需要一个旋转的圆圈 + +1615 +01:07:35,224 --> 01:07:37,458 +So how do we do the spinning wheel? +我们怎样实现呢? + +1616 +01:07:37,460 --> 01:07:39,726 +Spinning wheel, very easy to do. +很容易实现 + +1617 +01:07:39,728 --> 01:07:42,896 +We're going to go to our story board right here. +选择 storyboard + +1618 +01:07:42,898 --> 01:07:45,765 +Screen realty management is a challenge on +在这么小的屏幕上展示这么多内容 + +1619 +01:07:45,767 --> 01:07:47,566 +this small screen. +很有挑战 + +1620 +01:07:47,568 --> 01:07:50,903 +And I'm just going to drag out a little spinning wheel +我直接向 UI 中 + +1621 +01:07:50,905 --> 01:07:52,138 +into my UI. +拖入一个旋转的圆圈 + +1622 +01:07:52,139 --> 01:07:53,372 +And this is a great chance for me to +向你们展示一下 Document Outline 如何使用 + +1623 +01:07:53,373 --> 01:07:54,606 +show you a little bit of how to use the document outline. +这里是个很好的机会 + +1624 +01:07:54,608 --> 01:07:57,008 +And you'll see why. +你们会知道原因的 + +1625 +01:07:57,010 --> 01:08:00,611 +So here the spinning wheel is called the activity indicator. +旋转的圆圈在这里被称为 Activity Indicator View + +1626 +01:08:00,613 --> 01:08:03,047 +So I'm going to type activity, there it is. +在这里输入 activity + +1627 +01:08:03,049 --> 01:08:07,284 +Little spinning wheel, drag it out, and going to put it here. +从这里拖出这个小圆圈,放到这里 + +1628 +01:08:07,286 --> 01:08:10,987 +Now when I drag that out, it kind of looks like okay good, +放置完毕后,UI 看起来还不错 + +1629 +01:08:10,989 --> 01:08:14,557 +works, got a spinning wheel on there, I'm ready to go. +这里有了一个小圆圈,已经可以开始接下来的工作了 + +1630 +01:08:14,559 --> 01:08:16,392 +But actually, +但是实际上 + +1631 +01:08:16,393 --> 01:08:18,226 +something very bad happened when I dragged that out. +拖拽完毕后,发生了很不好的事情 + +1632 +01:08:18,229 --> 01:08:21,096 +And if I look in the document line, I'll see what it is. +在 Document Outline 你就会发现 + +1633 +01:08:21,098 --> 01:08:25,066 +Which is that this spinning wheel +这个小圆圈被添加成了 + +1634 +01:08:25,068 --> 01:08:28,869 +was added as a SubView of the ScrollView. +ScrollView 的 SubView(子视图) + +1635 +01:08:30,072 --> 01:08:33,040 +Because I dragged it out on top of the ScrollView, so +因为我把它放到了 ScrollView 的上面 + +1636 +01:08:33,042 --> 01:08:34,374 +it added it as a SubView so +所以它被添加成了 SubView + +1637 +01:08:34,376 --> 01:08:36,943 +that mean it's going to be in that content area. +这就表示它会出现在 ScrollView 的区域 + +1638 +01:08:36,945 --> 01:08:39,578 +We don't want that, we want this thing to be floating on +我们不希望这样,我们希望它 + +1639 +01:08:39,580 --> 01:08:42,881 +top of the scroll view. +漂浮在 ScrollView 的顶部 + +1640 +01:08:42,883 --> 01:08:45,050 +It's very hard to fix it in here. +在这里很难修复这个问题 + +1641 +01:08:45,052 --> 01:08:46,618 +Cuz it's like where do you drag it? +你能把它拽到哪里去? + +1642 +01:08:46,620 --> 01:08:48,519 +The scroll view's everywhere. +这里到处都是 ScrollView + +1643 +01:08:48,521 --> 01:08:49,854 +You can't get it. +你不能获取到它 + +1644 +01:08:49,856 --> 01:08:52,656 +So this is what the document outline is great for. +然而这就是 Document Outline 擅长的地方了 + +1645 +01:08:52,658 --> 01:08:53,957 +Watch this. +仔细看 + +1646 +01:08:53,958 --> 01:08:55,257 +I'll take this right out of the scroll view. +我把它拽出 ScrollView + +1647 +01:08:55,260 --> 01:08:56,793 +Boom, it's out. +它已经出去了 + +1648 +01:08:56,795 --> 01:08:58,561 +Now this puts it behind the scroll view, +现在它被放到了 ScrollView 的下面 + +1649 +01:08:58,563 --> 01:09:00,262 +because I told you the subview's list, +因为我告诉过你们这个 SubView 列表 + +1650 +01:09:00,264 --> 01:09:01,330 +the top things are in the back. +列表最上面的元素是在 UI 最底层的 + +1651 +01:09:01,332 --> 01:09:03,265 +So I'll just put the scroll view on top. +所以我把 ScrollView 放到列表最上面 + +1652 +01:09:03,267 --> 01:09:05,266 +So now I have the scroll view in the back, +现在 ScrollView 已经在 UI 最下面了 + +1653 +01:09:05,268 --> 01:09:06,067 +indicator in the front. +小圆圈在前面了 + +1654 +01:09:07,370 --> 01:09:08,469 +Okay? +OK? + +1655 +01:09:08,471 --> 01:09:10,237 +What about constraints? +约束怎么解决? + +1656 +01:09:10,239 --> 01:09:11,971 +Oh, the constraints here are hard to put too, +这里的约束也很难设置 + +1657 +01:09:11,973 --> 01:09:13,306 +because every time you kind of drag, +因为每一次你拖拽的时候 + +1658 +01:09:13,308 --> 01:09:14,807 +it keeps dragging it to the scroll view. +它总被拽到 ScrollView 里 + +1659 +01:09:14,809 --> 01:09:17,142 +Well, I can do constraints in here as well. +我也可以在这里处理约束问题 + +1660 +01:09:17,144 --> 01:09:20,245 +Let's drag the indicator view up to +把小圆圈拽到 + +1661 +01:09:20,247 --> 01:09:22,047 +the view above the scroll view. +ScrollView 上面的 view + +1662 +01:09:22,049 --> 01:09:24,015 +Right, our NVC's view. +MVC 的 view + +1663 +01:09:24,017 --> 01:09:27,451 +And I'm just going to say I want this to be centered +我希望它在这个 view 的 + +1664 +01:09:27,453 --> 01:09:30,087 +horizontally and vertically in that view. +垂直中央和水平中央 + +1665 +01:09:31,356 --> 01:09:33,890 +Boom, I've set the constraints now for +目前我已经通过 Document Outline + +1666 +01:09:33,892 --> 01:09:35,524 +that totally using the document outline. +设置好了它的约束 + +1667 +01:09:37,695 --> 01:09:39,194 +Now lets do one other thing with the indicator. +再对这个小圆圈做一些其他事情 + +1668 +01:09:39,196 --> 01:09:41,563 +I'm going to inspect it over here and +在这里对其属性进行检查 + +1669 +01:09:41,565 --> 01:09:44,866 +you can see the indicator has some different styles. +这个小圆圈有不同的风格 + +1670 +01:09:44,868 --> 01:09:45,800 +We like grey because we +我们喜欢灰色的 + +1671 +01:09:45,802 --> 01:09:47,534 +have a white background so that's good. +因为是白颜色的背景 + +1672 +01:09:47,536 --> 01:09:49,536 +But it also has a couple buttons here and +这里也有几个选项 + +1673 +01:09:49,538 --> 01:09:51,971 +this is a good one to click, hides when stopped. +hides when stopped 这项不错,可以选中 + +1674 +01:09:52,941 --> 01:09:54,474 +That makes it so +这会使得这个小圆圈 + +1675 +01:09:54,475 --> 01:09:56,008 +when the spinner stops spinning it hides itself. +在停止旋转的时候,会把自己给隐藏 + +1676 +01:09:57,311 --> 01:09:59,011 +So it's only showing while it's spinning, +它只会在旋转的时候才会显示 + +1677 +01:09:59,013 --> 01:10:00,545 +which is kind of a nice feature. +这是一个很好地特性 + +1678 +01:10:00,547 --> 01:10:01,979 +You can cause it to show and +你可以让它显示或隐藏 + +1679 +01:10:01,981 --> 01:10:04,348 +hide yourself, but it's nice to have it hide itself. +但是让它自己隐藏还是很不错的 + +1680 +01:10:04,350 --> 01:10:08,885 +All right, so we have this nice little spinner here, so +我们已经有了这个不错的小圆圈 + +1681 +01:10:08,887 --> 01:10:10,754 +let's go ahead and hook it up into our UI. +把它和我们的代码联系起来 + +1682 +01:10:10,756 --> 01:10:14,257 +And I'm just gonna Ctrl+Drag, even control dragging from +按住 Ctrl 拖动 + +1683 +01:10:14,259 --> 01:10:17,093 +this can be a bit of a pain, because it's very small and +可能从这里拖动比较困难 + +1684 +01:10:17,095 --> 01:10:18,660 +you got all these constraints in the way. +因为它很小,周围还有约束 + +1685 +01:10:18,662 --> 01:10:21,296 +So you can actually Ctrl+Drag from over here. +你可以从这里 Ctrl+Drag + +1686 +01:10:21,298 --> 01:10:25,299 +All right so I'll Ctrl+Drag, I'll put it right here. +把它放到这里 + +1687 +01:10:25,301 --> 01:10:26,667 +I'm gonna call it spinner. +起名为 spinner + +1688 +01:10:26,669 --> 01:10:29,370 +I like to call my activity indicators spinners but +我喜欢把 Activity Indicator 称为 spinner + +1689 +01:10:29,372 --> 01:10:32,072 +you could call it activity indicator too. +但是你也可以不像我这么叫 + +1690 +01:10:32,074 --> 01:10:35,075 +So here's my spinner and +这就是 spinner + +1691 +01:10:35,077 --> 01:10:36,509 +what do I need to do with this spinner? +我应该怎么处理它呢? + +1692 +01:10:36,511 --> 01:10:38,528 +Well, I just need to +我只需要 + +1693 +01:10:38,529 --> 01:10:40,546 +start it spinning when I make a request, and then I +在请求的时候让它开始旋转 + +1694 +01:10:40,548 --> 01:10:44,583 +need to stop it from spinning when the request is fulfilled. +当请求已经完成的时候让它停止 + +1695 +01:10:44,585 --> 01:10:45,751 +Okay? +OK? + +1696 +01:10:45,752 --> 01:10:46,918 +So I'm going to do that. +我会这么做 + +1697 +01:10:46,920 --> 01:10:49,821 +And I want to get lots of room here. +我需要一些空间 + +1698 +01:10:49,823 --> 01:10:53,224 +So I've got my spinner, well, where do I make a request? +我在哪里做的请求的? + +1699 +01:10:53,226 --> 01:10:55,426 +Let's see, it's right here. +在这里 + +1700 +01:10:55,428 --> 01:10:58,429 +Right. This is where I dispatch +这里就是我投递请求的地方 + +1701 +01:10:58,430 --> 01:11:01,431 +request so I'm just gonna say spinner, start animating. +在这里,spinner.startAnimating + +1702 +01:11:01,433 --> 01:11:02,765 +But I'm gonna make that even better, +我会处理地更好 + +1703 +01:11:02,767 --> 01:11:04,033 +I'm gonna say question mark, +在这里加一个问号 + +1704 +01:11:04,035 --> 01:11:07,236 +in case we're fetching an image before our +以防在 Outline 设置好之前 + +1705 +01:11:07,238 --> 01:11:08,604 +outlets are loaded. +发出了获取图片的请求 + +1706 +01:11:08,605 --> 01:11:09,971 +For some reason, we don't currently do that cause we +我们通常不会这样做 + +1707 +01:11:09,973 --> 01:11:11,673 +only do it in view will appear. +只会在 viewWillAppear 里这样处理 + +1708 +01:11:11,675 --> 01:11:13,808 +But you know some day someone might write that code. +但是可能某人某天就会写出那样的代码 + +1709 +01:11:14,911 --> 01:11:18,112 +And then I could stop the spinner like down in here but +我可以在下面这里让 spinner 停止旋转 + +1710 +01:11:18,114 --> 01:11:20,881 +actually a great place to stop the spinner is as soon +实际上让 spinner 停止旋转的很好的地方 + +1711 +01:11:20,883 --> 01:11:22,749 +as an image is set. +是在 image 被设置好了的时候 + +1712 +01:11:22,751 --> 01:11:25,351 +Anytime an image gets set I don't want to be spinning, +每一次 image 被设置好了以后,我不希望 spinner 旋转 + +1713 +01:11:25,353 --> 01:11:27,553 +by definition. +显然 + +1714 +01:11:27,555 --> 01:11:29,989 +Right? +好的 + +1715 +01:11:29,990 --> 01:11:32,424 +So I'm just going to say spinner.stop animating. +spinner.stopAnimating + +1716 +01:11:32,426 --> 01:11:32,991 +Okay? +OK? + +1717 +01:11:32,993 --> 01:11:35,126 +And that's it. +就是这样 + +1718 +01:11:35,128 --> 01:11:36,394 +That's all it takes to the do the spinner. +处理 spinner 就需要这些工作 + +1719 +01:11:36,396 --> 01:11:38,328 +So let's go take a look at the spinner spinning. +让我们看看 spinner 旋转的样子 + +1720 +01:11:38,330 --> 01:11:43,400 +All right so the spinner didn't spin at +一开始 spinner 并没有旋转 + +1721 +01:11:43,402 --> 01:11:45,335 +start because I haven't made any requests. +因为我还没有发出任何请求 + +1722 +01:11:45,337 --> 01:11:48,270 +But here if I make a request there's the spinner spinning, +但是如果我做出请求,spinner 就开始旋转了 + +1723 +01:11:48,272 --> 01:11:50,339 +and yeah you can make the spinner larger if you want but +你也可以让 spinner 大一些 + +1724 +01:11:50,341 --> 01:11:52,207 +it's spinning, it's spinning cuz we're still working on +它一直在旋转,因为它正在处理请求 + +1725 +01:11:52,209 --> 01:11:54,776 +it and once the thing appears now my spinner's gone. +一旦我需要的东西出现了,spinner 就消失了 + +1726 +01:11:54,778 --> 01:11:56,944 +It's kinda hard to tell in the dark spots but here in +在暗的区域很难看出来 + +1727 +01:11:56,946 --> 01:12:01,048 +the light spots you can see that our spinner is gone. +但是在亮的地方你可以看到它消失了 + +1728 +01:12:01,050 --> 01:12:03,383 +'Kay same thing we come back, click on this one, +我们回过头再做一次,点击它 + +1729 +01:12:03,385 --> 01:12:05,952 +spinner comes back, right? +spinner 又出现了 + +1730 +01:12:05,954 --> 01:12:07,320 +And I can't scroll it. +我不能滚动它 + +1731 +01:12:07,322 --> 01:12:09,955 +There's no scrolling or anything like that. +这里还没有 ScrollView + +1732 +01:12:09,957 --> 01:12:11,957 +And then once our thing appears right here, +一旦图片出现 + +1733 +01:12:13,727 --> 01:12:14,392 +our spinner is gone. +spinner 就消失了 + +1734 +01:12:19,631 --> 01:12:20,514 +Okay? +OK? + +1735 +01:12:20,515 --> 01:12:21,398 +So that's it for today. +这就是今天的内容了 + +1736 +01:12:21,400 --> 01:12:22,265 +Questions? +有问题吗? + +1737 +01:12:22,267 --> 01:12:25,601 +What about the self referencing and. +self 引用的问题 + +1738 +01:12:25,603 --> 01:12:27,836 +Yeah so let's look at the self referencing thing. +让我们来看看 self 引用的问题 + +1739 +01:12:27,838 --> 01:12:28,804 +Did we have a problem with +闭包内部 + +1740 +01:12:28,806 --> 01:12:30,839 +self referencing inside this closure. +有 self 引用的问题吗? + +1741 +01:12:30,841 --> 01:12:32,974 +That we did right here, and the answer is no, +答案是,没有问题 + +1742 +01:12:32,976 --> 01:12:36,210 +because nowhere inside this closure do we refer to +因为我们没有让闭包内部的任何一个地方 + +1743 +01:12:36,212 --> 01:12:38,579 +anything that points to this closure. +指向这个闭包 + +1744 +01:12:38,581 --> 01:12:41,615 +Cause this closure just got dispatched a synced, +因为这个闭包刚刚 dispatch_async + +1745 +01:12:41,617 --> 01:12:43,650 +right it got put on some queue somewhere, but +被放入了某个队列之中 + +1746 +01:12:43,652 --> 01:12:45,385 +we don't point to it anymore. +但是我们不再指向它了 + +1747 +01:12:45,387 --> 01:12:46,886 +The queue points to it basically, +实际上是那个队列指向它 + +1748 +01:12:46,888 --> 01:12:50,022 +the queue owns this closure, we self don't. +那个队列拥有它,而我们没有 + +1749 +01:12:50,024 --> 01:12:53,291 +So we're okay, we don't have to do any unknown. +所以我们不需要处理,加上 unknown + +1750 +01:12:53,293 --> 01:12:55,093 +But you'll start seeing the unknown thing when we +但是在学习 animation(动画)的时候 + +1751 +01:12:55,095 --> 01:12:56,427 +start doing animation. +你就会开始看到 unknown 了 + +1752 +01:12:56,429 --> 01:12:59,864 +When we start having actions in the animation that +当我们开始学习动画 + +1753 +01:12:59,866 --> 01:13:03,734 +are calling methods inside of our class to do animation, so +在 action 中调用类中的方法的时候 + +1754 +01:13:03,736 --> 01:13:08,471 +you'll see that there. +我们会看到的 + +1755 +01:13:08,473 --> 01:13:09,271 +Okay? That's it, thank you. +懂了吗?就是这样,谢谢 + +1756 +01:13:10,675 --> 01:13:10,706 +For more, please visit us at Stanford.edu. +想了解更多信息,请登录 Stanford.edu \ No newline at end of file diff --git a/tools/trim.rb b/tools/trim.rb new file mode 100644 index 0000000..6277ae6 --- /dev/null +++ b/tools/trim.rb @@ -0,0 +1,55 @@ +#!/usr/bin/env ruby + +module State + LINE_NUMBER = 1 + TIME = 2 + SUB = 3 + SPACE = 4 +end + +input_file = ARGV[0] +output_file = ARGV[1] ? ARGV[1] : ARGV[0] + +if input_file && output_file + + trimmed = [] + + File.read(input_file).each_line do |line| + trimmed << line.strip + end + + result = "" + + last_state = nil + + trimmed.each do |line| + + case line + when /^\d+$/ + result += "\n" + line + + last_state = State::LINE_NUMBER + when /^\d+:\d+:\d+,\d+\s-->\s\d+:\d+:\d+,\d+$/ + result += "\n" + line + + last_state = State::TIME + when /^$/ + result += "\n" + line + + last_state = State::SPACE + else + if last_state != State::SUB + result += "\n" + line + else + result += " " + line + end + last_state = State::SUB + end + + end + + File.open(output_file, 'w') do |file| + file.write(result) + end + +end