From 033f44edfc3cb9c62180ce79a3be9ff0f1df0495 Mon Sep 17 00:00:00 2001 From: ApolloZhu Date: Thu, 13 Apr 2017 11:38:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=AC=AC=E4=B8=80=E9=9B=86?= =?UTF-8?q?=E7=BF=BB=E8=AF=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...duction to iOS 10, Xcode 8 and Swift 3.srt | 545 +++++++++++++++++- 1 file changed, 535 insertions(+), 10 deletions(-) diff --git a/subtitles/1. Introduction to iOS 10, Xcode 8 and Swift 3.srt b/subtitles/1. Introduction to iOS 10, Xcode 8 and Swift 3.srt index 675f080..7f2bca6 100644 --- a/subtitles/1. Introduction to iOS 10, Xcode 8 and Swift 3.srt +++ b/subtitles/1. Introduction to iOS 10, Xcode 8 and Swift 3.srt @@ -5501,2099 +5501,2624 @@ we'll go up here and change the color to be white. Okay? 1101 00:55:14,248 --> 00:55:17,583 So that's a pretty decent looking display +现在看起来就像样多了 1102 00:55:17,651 --> 00:55:21,419 right there, for now anyway. Now, if we have these +再挪上去点,先这样吧。如果我们 1103 00:55:21,488 --> 00:55:24,322 buttons being pressed, we need to talk to this display, and +按下按钮,就应该告诉这个显示屏 1104 00:55:24,391 --> 00:55:25,390 tell it what the digits are. +按下了哪个按钮 1105 00:55:25,459 --> 00:55:27,292 So how are we gonna do that? Well again, +怎么做呢? 1106 00:55:27,361 --> 00:55:30,161 we need to make a connection between that display and +我们需要把显示屏连接到代码里 1107 00:55:30,230 --> 00:55:32,564 our code. But this is not the same kind of connection. +但用的和之前是不同的一种连接 1108 00:55:32,633 --> 00:55:34,966 Because we don't touch on that label, and +因为我们不会按下显示屏 1109 00:55:35,035 --> 00:55:38,970 it calls a method, We need to have an instance variable, or +然后让它调用一个方法。我们需要一个实例变量 1110 00:55:39,039 --> 00:55:41,806 property, that points to that thing, so we can talk to it +也就是指向这个显示屏的属性,然后我们就能 1111 00:55:41,875 --> 00:55:44,609 whenever we want, cuz we gotta put these digits on it. +随时在代码中向这个显示屏添加数字了 1112 00:55:44,678 --> 00:55:48,180 Okay? So we're still going to use the same mechanism to +连接的方法还是和之前一样 1113 00:55:48,248 --> 00:55:50,782 make a connection, which is control. And we're going to +按下 Control 键 1114 00:55:50,851 --> 00:55:54,519 drag in here. Okay? And this time we're going to use +然后拖到代码这边来,不过 Connection 选择 1115 00:55:54,588 --> 00:55:58,223 outlet. Outlet means a property that points to this. +Outlet,创建一个指向它的属性 1116 00:55:58,292 --> 00:56:01,526 And I'm going to call this display. It's our display. +名字就叫做 display,这是我们的显示屏 1117 00:56:01,594 --> 00:56:05,030 It got the type right here. This weak and strong, don't +这里的类型已经自动选好了,下面的 Weak 和 Strong 1118 00:56:05,099 --> 00:56:07,065 worry about that. I'm going to talk about that next week. +暂时不需要管,下周才会讲到 1119 00:56:07,133 --> 00:56:11,436 Okay. So don't worry. So, here is +所以不用担心 1120 00:56:11,504 --> 00:56:15,841 our first instance variable in our class. Woo hoo! Okay? +哇哦!第一个类的实例变量 1121 00:56:15,910 --> 00:56:19,678 This right here, is again just some stuff that Xcode +当然,@IBOutlet 是 Xcode 的标记 1122 00:56:19,747 --> 00:56:25,150 throws in there, so you get this, right? This, +让它显示这个小圆点 1123 00:56:25,219 --> 00:56:28,320 I told you ignore, okay? So +你们不需要在意这个 1124 00:56:28,388 --> 00:56:31,222 this is the declaration of our property and +这部分是属性的定义 1125 00:56:31,291 --> 00:56:36,194 of course it's a var and that could be let. If you want +当然,是个变量,其实用 let 也行 1126 00:56:36,263 --> 00:56:38,330 an instance variable that is set at the beginning and +如果你的实例变量始终是初始值 1127 00:56:38,399 --> 00:56:40,833 never changes, you can use let. It's pretty rare, but +一直没变过就可以用 let,不过很少见 1128 00:56:40,901 --> 00:56:45,070 you can do it, okay usually they're var. Display, +你可以这么做,不过一般都是 var 1129 00:56:45,139 --> 00:56:49,841 -that's the name. ": UILabel" is the type, +that's the name. ": UILabel!" is the type, +变量叫 display,: UILabel! 说的是它的类型 1130 00:56:49,910 --> 00:56:53,144 okay? So as you might guess, this has something to do with +好吧?你应该会想到可选类型 1131 00:56:53,213 --> 00:56:57,749 optionals, okay? This is kinda confusing to +一开始就要马上理解是不可能的 1132 00:56:57,818 --> 00:57:00,585 start off the bat, but that exclamation point, +虽然这个感叹号 1133 00:57:00,654 --> 00:57:04,623 which normally means unwrap an optional. Obviously we can't +一般是用来强制解包的,但显然这里 1134 00:57:04,691 --> 00:57:07,459 unwrap here, we're declaring this thing here. +我们不是在解包,我们是在定义变量 1135 00:57:07,527 --> 00:57:10,262 This is pretty much exactly the same as a question mark. +这个的意思和问号是差不多的 1136 00:57:10,331 --> 00:57:12,063 In fact, I'm gonna change it to a question mark for +实际上,现在我要把它改成问号 1137 00:57:12,132 --> 00:57:14,565 now, and later I'll change it back to an exclamation point, +之后再改回来 1138 00:57:14,634 --> 00:57:17,869 and you'll see the difference. But, the type of this display +然后你就能看出区别了。但无论如何 1139 00:57:17,938 --> 00:57:21,873 is optional UI label. Now, why is this an optional UI label? +display 都是可选的 UILabel。为什么呢? 1140 00:57:21,942 --> 00:57:24,342 -Why isn't this just a UI label? +Why isn't this just a UILabel? +为什么就不能只是 UILabel 呢? 1141 00:57:24,411 --> 00:57:27,913 Why does it have to be optional? Because when this UI +为什么要是可选呢?因为当用户界面 1142 00:57:27,982 --> 00:57:31,883 first comes up, iOS needs a few nanoseconds to hook +刚显示的时候,系统需要一点时间 1143 00:57:31,952 --> 00:57:35,387 that up for you. So when this UI first comes up, +关连控件和代码。所以刚加载的时候 1144 00:57:35,456 --> 00:57:39,191 it's not set to an optional not set case and then UI hooks +它是缺省值的。关连完之后 1145 00:57:39,259 --> 00:57:42,093 it up for you, and now it's set forever after that. And +之后就是有值的了 1146 00:57:42,162 --> 00:57:45,397 that's important that it's set forever, and we'll see it has +之后一直都是有值的。 1147 00:57:45,465 --> 00:57:47,966 to do with that exclamation point I just got rid of. But +这就是我刚才去掉的那个感叹号的作用 1148 00:57:48,035 --> 00:57:50,768 for now understand that display is just an optional +现在只要理解这是可选类型就行了 1149 00:57:50,837 --> 00:57:53,405 we'll have to unwrap it every time we use it, okay so +每次使用的时候都要解包 1150 00:57:53,473 --> 00:57:57,342 as simple as that. All right, so now instead of printing +仅此而已。现在我们 1151 00:57:57,411 --> 00:57:59,545 the digits on the screen let's go ahead and +不打印数字到控制台了 1152 00:57:59,613 --> 00:58:01,846 put these digits into the display, +我们把数字加到显示屏上 1153 00:58:01,915 --> 00:58:04,416 and really every time a digit is pressed we wanna append it +每次按下某个数字 1154 00:58:04,485 --> 00:58:07,352 onto the end of the display like if there's 56 in there we +就把它加到显示屏最后。比如现在是 56 1155 00:58:07,420 --> 00:58:12,758 wanna append 2- it's 562 and 8 it's 5268, right? So we're +我们要加个 2,就是 562;再加个 8,就是 5268 1156 00:58:12,826 --> 00:58:16,127 just gonna keep appending. So we need to get the text so +我们就一直往后面加。所以我们就要获取当前 1157 00:58:16,196 --> 00:58:18,663 it's currently in the display and add the digit to it. +display 显示的文字,然后把数字加到后面 1158 00:58:18,732 --> 00:58:20,899 So I'm gonna add another little local variable. +所以我们还需要一个局部变量 1159 00:58:20,968 --> 00:58:26,205 -It's a constant also called textcurrentlyInDisplay and +It's a constant also called textCurrentlyInDisplay and +一个叫做 textCurrentlyInDisplay 的常量 1160 00:58:26,273 --> 00:58:29,541 I'm gonna get that by sending a message to the display, +得到它的值,是通过发送消息到 display 1161 00:58:29,610 --> 00:58:31,143 which I have to unwrap, +当然要先解包 1162 00:58:32,646 --> 00:58:34,612 and now I can send your message. And +然后再发送消息 1163 00:58:34,681 --> 00:58:38,183 here's all the messages that label responds too, +然后这些就是标签所有会响应的消息了 1164 00:58:38,252 --> 00:58:41,452 again, hundreds, okay? So I'm gonna do the same trick, I'm +也是有一大堆,好吧。还是用老方法 1165 00:58:41,521 --> 00:58:45,457 gonna type text because I want the text out of there Look at +我输入 text,文字就是我想要的 1166 00:58:45,526 --> 00:58:48,459 the very first one, the text displayed by the label. +看看这第一个,标签显示的文字 1167 00:58:48,528 --> 00:58:52,197 It's an optional string. Excellent, I'll take it, okay. +可选类型的字符串。很好,就决定是你了 1168 00:58:52,266 --> 00:58:54,399 So, now I've got the text but it's optional. So, +我得到了显示的文字,但是是可选的 1169 00:58:54,467 --> 00:58:59,470 I need to unwrap it, okay? So now textCurrentlyInDisplay. +我需要解包 textCurrentlyInDisplay 1170 00:58:59,539 --> 00:59:02,541 If I option click on it you'll see it's a string. So, +如果我按 Option 键再点击它,类型就只是字符串了 1171 00:59:02,609 --> 00:59:05,610 now I can just say, set the display, unwrap, +我现在就只需要把 display 解包 1172 00:59:05,679 --> 00:59:08,814 text equal to the text that's currently in the display +赋值 text 为 display 现在的文字 1173 00:59:08,882 --> 00:59:12,684 plus the digit. Now, notice when I set an optional, text +加上数字。注意当我赋值给一个可选类型时 1174 00:59:12,753 --> 00:59:16,421 is an optional, right? When I set it equal to something- by +text 是可选的,是吧?我赋值给它的时候 1175 00:59:16,489 --> 00:59:20,558 the way this optional is get and set unlike currentTitle, +顺便说一句,text 是可读写的 1176 00:59:20,627 --> 00:59:24,929 which was get only- so I can set the your label's text here +不像只读的 currentTitle。所以我们能够更改标签的文字 1177 00:59:24,998 --> 00:59:27,999 and get it. When I set this optional right here, +也能得到它。当我赋值给可选类型的时候 1178 00:59:28,068 --> 00:59:31,403 I don't have to unwrap it first, okay? +我并不需要先解包 1179 00:59:31,471 --> 00:59:32,904 So you don't have to unwrap an optional to set it, +所以赋值给可选类型的时候不需要解包 1180 00:59:32,973 --> 00:59:35,807 you just set it. And optionals know okay, +你直接赋值就可以了。因为可选类型已经知道了 1181 00:59:35,875 --> 00:59:39,043 this must be the associated value of an optional string, +这个值也一定是可选字符串类型的 1182 00:59:39,112 --> 00:59:42,047 so I will set it, okay? So that's it, +所以我可以直接赋值给它,这样就可以了 1183 00:59:42,116 --> 00:59:51,489 let's see if that works. Okay, +让我们看看有没有用 1184 00:59:51,558 --> 00:59:55,560 so we got our UI, looks good, got a display in there, mm-hm. +我们的界面显示出来了,显示屏也在上面 1185 00:59:55,629 --> 01:00:01,132 Let's try 8, well 6, well, it's kinda working. +让我们按 8,6。好吧,虽然没什么大问题 1186 01:00:01,201 --> 01:00:02,601 It's definitely doing the appending thing, +因为我们按的数字确实添加在了后面 1187 01:00:02,670 --> 01:00:04,303 but that 0 at the beginning, +不过一开始的那个 0 1188 01:00:04,371 --> 01:00:08,406 that's wrong. That zero is not part of what I was typing. +那是不对的,那并不是我输入的一部分 1189 01:00:08,475 --> 01:00:10,175 That zero just happened to be there at startup. +那个 0 是我一开始默认显示的 1190 01:00:10,243 --> 01:00:13,078 So, it shouldn't be put in in the front there and +所以它并不应该一直显示在前面 1191 01:00:13,146 --> 01:00:14,413 the problem here is really simple. +这个问题很容易解决 1192 01:00:14,481 --> 01:00:17,548 It's just that we haven't taught our calculator to know +只不过是我们还没有教会计算器 1193 01:00:17,617 --> 01:00:19,117 when the user is entering, +哪个部分才是用户输入的 1194 01:00:19,185 --> 01:00:20,652 in the middle of entering a number, +什么时候用户正在输入 1195 01:00:20,721 --> 01:00:22,488 versus when it just started up. +什么时候它刚开始运行 1196 01:00:22,556 --> 01:00:25,123 Or maybe, the result of an operation just appeared +或者显示屏刚显示运算的结果 1197 01:00:25,192 --> 01:00:27,625 there. Obviously when we type we wouldn't want that to +当然我们输入的时候 1198 01:00:27,694 --> 01:00:30,361 -have more, thanks to it. So, we need to teach our +happen, thanks to it. So, we need to teach our +并不希望 0 出现在前面。所以我们 1199 01:00:30,430 --> 01:00:32,931 calculator brain here to know the difference between whether +要让计算器有不同的状态 1200 01:00:32,999 --> 01:00:34,466 the user is in the middle of typing or not. +知道用户是否在输入的过程中 1201 01:00:34,535 --> 01:00:37,302 And we're gonna do that, by creating another property +实现的方法是定于另一个属性 1202 01:00:37,371 --> 01:00:43,141 called userIsInTheMiddleOfTyping. +叫做 userIsInTheMiddleOfTyping 1203 01:00:43,210 --> 01:00:47,546 Which is gonna be a Bool. Now, I typed a long name here. Kind +一个 Bool 类型的属性。这名字挺长的 1204 01:00:47,614 --> 01:00:51,183 of for effect. We probably could have called this typing. +我这是为了舞台效果。多半我们可以就叫它 typing 就行了 1205 01:00:53,119 --> 01:00:57,288 You know, there's trade off between clarity and brevity. +清晰和简洁不可兼得 1206 01:00:57,357 --> 01:01:00,458 Okay, brevity is valued, but clarity is even more +当然简洁很重要,不过表达明确更重要 1207 01:01:00,527 --> 01:01:05,597 important. So, maybe isTyping would have been enough. +也许 isTyping 就够了的 1208 01:01:05,665 --> 01:01:08,967 But I would err slightly on the side of clarity. So I'm +但我还是更偏向于表达清晰 1209 01:01:09,036 --> 01:01:10,936 using this long one. The other thing, the reason I typed this +所以我会用这个很长的名字。另一个原因是 1210 01:01:11,005 --> 01:01:13,304 long is to show you that I'm never gonna have to type this +告诉你我从来不需要再完整地敲这么长的名字 1211 01:01:13,373 --> 01:01:16,375 again, because Xcode is always gonna escape complete this for +因为 Xcode 会帮我自动补全 1212 01:01:16,443 --> 01:01:19,711 me, as you'll see when I start using it. Now when I added +当我用到的时候就你们就知道了 1213 01:01:19,779 --> 01:01:22,915 this beautiful var, this Bool. Okay, a Bool, by the way, +当我添加这个美丽的布尔型变量之后 1214 01:01:22,983 --> 01:01:24,315 is just something that can be true or false, +也就是只能为 true 和 false 的变量之后 1215 01:01:24,384 --> 01:01:28,353 of course. I got an error. Look at that error up there. +出现了错误。看看这里的这个错误 1216 01:01:28,422 --> 01:01:31,857 This little thing here- it's on a line that had nothing to +这里的这个小标记,出现在了这一行 1217 01:01:31,926 --> 01:01:34,760 do with what I just did. What? That's not fair. +和我刚才干的那行毫无关系的地方。这就奇怪了 1218 01:01:34,829 --> 01:01:37,562 What is this? It says Class 'View Controller' +它说什么?它说 Class 'ViewController' has no initializers 1219 01:01:37,631 --> 01:01:40,999 has no initializers. Okay well, what the heck is that? +ViewController 类没有构造器。这是什么意思? 1220 01:01:41,068 --> 01:01:42,634 That has nothing to do with the var either? +这和我们刚定义的变量也没关系啊 1221 01:01:42,703 --> 01:01:45,637 Well, here's the deal here. In Swift, +好吧,事情是这样的 1222 01:01:45,705 --> 01:01:50,475 all properties have to be initialized. Every single one. +Swift 要求所有的属性都要初始化。每个都要 1223 01:01:50,543 --> 01:01:54,246 No exceptions. Now there's two ways +一个都不能少。可以使用两种方法 1224 01:01:54,315 --> 01:01:57,516 to initialize your properties in a class or struct. +来初始化类和结构体里的属性 1225 01:01:57,585 --> 01:01:59,717 One is with an initializer. +一是使用构造器 1226 01:01:59,786 --> 01:02:03,055 An initializer is a special method, it's called init, +构造器是一个特殊的方法,叫做 init 1227 01:02:03,123 --> 01:02:06,525 I-N-I-T. You can have any number of arguments that your +I-N-I-T。可以接受任意数量的参数 1228 01:02:06,593 --> 01:02:09,895 class requires but, in its implementation it has to +只要是这个类需要的;但一定要保证 1229 01:02:09,963 --> 01:02:14,599 initialize all uninitialized properties. Okay? Now, +初始化所有没有初始化的属性 1230 01:02:14,668 --> 01:02:16,234 we're not gonna talk about initializers today. +我们今天不会讲构造器 1231 01:02:16,303 --> 01:02:18,270 I'll talk about it a little bit next Wednesday, +我们下周三会讲一点 1232 01:02:18,339 --> 01:02:21,373 actually. So, we're not gonna use an initializer. Because +所以我们今天不会用构造器 1233 01:02:21,442 --> 01:02:23,976 there's a second way to initialize, which is to just +因为我们还有第二种方法来初始化 1234 01:02:24,044 --> 01:02:27,445 give it a value. Okay, is false, right? The user's +直接赋值就可以了。我们这里设置为 false 1235 01:02:27,514 --> 01:02:30,449 obviously not in the middle of typing at the beginning, so +因为一开始的时候用户肯定没有在输入 1236 01:02:30,518 --> 01:02:34,052 is false. And that got rid of the error. +所以是 false。错误就解决了 1237 01:02:34,120 --> 01:02:39,324 Okay? In fact, we don't need this either. Do you see why? +其实,我们也不需要声名类型,知道为什么吗? 1238 01:02:39,393 --> 01:02:43,094 Because false, can only be a Bool, So +因为 false 是 Bool 类型的 1239 01:02:43,163 --> 01:02:48,566 Swift can infer that this must be a Bool. And again, +Swift 能够自动推导类型,知道这个一定是布尔型的 1240 01:02:48,635 --> 01:02:51,836 we do not want these things in here, if we can help it. Now, +所以如果可能的话,我们习惯不声明类型 1241 01:02:51,905 --> 01:02:55,473 what about this guy? That's not initialized. How come he's +那这个 display 呢?它也没有初始化啊 1242 01:02:55,542 --> 01:02:58,076 not complaining, okay? How come he's not getting that? +为什么没有报错呢?这不公平 1243 01:02:58,145 --> 01:03:01,880 Must be initializers business going on. Well, because he's +使用了构造器么?其实原因是因为它是 1244 01:03:01,949 --> 01:03:05,283 an optional. And optionals are special when it comes +可选类型的。可选类型很特别 1245 01:03:05,352 --> 01:03:08,820 to initialization. They all get this automatic treatment. +初始化的时候会被自动 1246 01:03:08,889 --> 01:03:13,659 Equals nil. nil means not set optional. Okay. +初始化为 nil。nil 表示缺省值 1247 01:03:13,727 --> 01:03:16,027 That's the only thing nil means in Swift. It means +nil 在 Swift 里的意思就是缺省值 1248 01:03:16,096 --> 01:03:20,031 an optional that's not set. So optional will automatically +表示可选类型没有被赋值。所以在定义 1249 01:03:20,100 --> 01:03:23,001 get this treatment at all times when you declare them. +可选类型时都会自动被初始化为 nil 1250 01:03:23,069 --> 01:03:24,836 And it makes sense right, if you have an optional +这是很有道理的。你有一个可选类型 1251 01:03:24,905 --> 01:03:27,138 it's gonna start out not set until you set it. +一开始是没有值的,直到你赋值给它 1252 01:03:27,207 --> 01:03:30,943 Now you could set this equal to some UILabel of some sort, +当然你也可以初始化为某个 UILabel 实例 1253 01:03:31,011 --> 01:03:33,812 and have it be set from the start, that's possible too. +一开始就有值是可能的 1254 01:03:33,881 --> 01:03:40,351 But if you don't say anything it gets not set. Alright, so +但如果没有的话,那就是缺省值 1255 01:03:40,420 --> 01:03:43,588 we've got that. Now we can use this userIsInTheMiddleOfTyping +好,大家都明白了。我们现在就可以用 userIsInTheMiddleOfTyping 了 1256 01:03:43,657 --> 01:03:45,023 thing. We'll say if the user is +如果用户正在输入的中途 1257 01:03:45,092 --> 01:03:46,992 in the middle of typing then we can do, +if userIsInTheMiddleOfTyping 1258 01:03:47,061 --> 01:03:51,863 this business that we just did here, okay? +然后我们再进行下面的这些操作 1259 01:03:51,931 --> 01:03:54,733 What if it's not in the middle of typing? Then we're just +那如果并没有开始输入呢?那我们 1260 01:03:54,802 --> 01:03:58,236 gonna set the display's text equal to the digit, cuz we're +赋值显示屏的文字为当前按下的数字 1261 01:03:58,305 --> 01:04:03,275 starting a new number then. In this case of course, +我们从头开始输入一个数字。这种情况下 1262 01:04:03,343 --> 01:04:08,580 the user is now in the middle of typing Okay, +用户就在输入的过程中了,为 true 1263 01:04:08,649 --> 01:04:11,783 everybody got that? So that's just how we're going to make +大家都还跟的上吧?这就是我们确保 1264 01:04:11,852 --> 01:04:13,651 sure we do the right thing. So let's go ahead and run, +计算器正常显示的方法。让我们运行 1265 01:04:13,720 --> 01:04:16,555 see if that whole 0, leading 0 problem is fixed. +看看开头显示 0 的问题是否解决了 1266 01:04:16,624 --> 01:04:18,423 Should be, because when we start off, +应该是的,因为一开始的时候 1267 01:04:18,492 --> 01:04:20,192 we're not in the middle of typing. So +用户并不是在输入的过程中 1268 01:04:20,261 --> 01:04:22,460 when we start typing a new number, boom, +当我们输入第一个数字 1269 01:04:22,529 --> 01:04:25,497 we get a new number. But if we're in the middle of typing, +就替换为了我们这个数字。但如果我们在输入的过程中 1270 01:04:25,566 --> 01:04:31,135 we keep getting the appending deal. All right, +我们会向后面添加数字 1271 01:04:31,204 --> 01:04:32,671 we are just rocking and rolling here. +我们这一步算是完成了 1272 01:04:32,740 --> 01:04:36,442 Next, let's put some operation buttons in this baby. +下一步,我要放一些运算符在这里 1273 01:04:36,510 --> 01:04:39,411 We can type in numbers, now let's start operating. +我们已经能输入数字了,下一步就是运算 1274 01:04:39,479 --> 01:04:42,147 I'm gonna do that by doing a very bad thing, +接下来我要干一件非常不好的事 1275 01:04:42,215 --> 01:04:46,317 which is I'm going to copy and paste the 7 button. +那就是复制粘贴这个数字 7 按钮 1276 01:04:46,386 --> 01:04:48,687 You're gonna see why that's bad in a moment. And +马上你们马上就知道这为什么是不好的做法 1277 01:04:48,756 --> 01:04:52,824 I'm gonna do a very simple operation, pi, okay? +我就加一个非常简单的运算符派吧,π,Option+P 1278 01:04:52,893 --> 01:04:55,293 So pi is just an operation that's gonna put pi in my +派就是在显示屏中显示派的数值 1279 01:04:55,362 --> 01:04:59,598 display, that's all it's gonna do. So I'm gonna control drag +这就是它的功能。我还是按住 Control 然后拖到代码里 1280 01:04:59,666 --> 01:05:03,368 to wire it up to a method. It's an action, not an outlet. +让它关连一个方法。选的是 Action,不是 Outlet 1281 01:05:03,437 --> 01:05:05,871 It's an action, just like touchDigit was. +就像是 touchDigit 一样的方法 1282 01:05:05,940 --> 01:05:07,372 I'm gonna call it performOperation, +方法叫做 perfomOperation 1283 01:05:07,440 --> 01:05:09,474 cuz that's what it does, it performs an operation. +这就是它的功能,进行某个运算 1284 01:05:09,543 --> 01:05:12,177 I'm gonna make sure I switch this to button like you +我会像作业里要求你们的那样 1285 01:05:12,246 --> 01:05:14,947 guys all are in your homework assignments. And +把这个改成 UIButton 1286 01:05:15,015 --> 01:05:17,615 then I'm going to connect. So now I have this new method +然后点 Connect。新的函数就定义好了 1287 01:05:17,684 --> 01:05:21,820 right here, and it is hooked up to pi, so that's good. +和这个派按钮连起来的 1288 01:05:21,889 --> 01:05:22,821 And what do I want to do in here? +要实现什么功能呢? 1289 01:05:22,890 --> 01:05:25,791 Well, I could do the same thing of asking the button +我可以像之前一样 1290 01:05:25,859 --> 01:05:30,329 which operation it is. How about let mathematicalSymbol, +问这个按钮你是什么运算。要不然用 let mathematicalSymbol 1291 01:05:30,397 --> 01:05:34,199 because that's what these things are in these operation +因为这些按钮的标题就是数学运算符 1292 01:05:34,268 --> 01:05:38,036 buttons, equal the sender.currentTitle!, okay? +把 sender.currentTitle! 赋值给这个常量 1293 01:05:38,105 --> 01:05:40,572 Great, now I've got the pi, but I wanted to show you, +好,我现在得到派了,不过我像给你们看看 1294 01:05:40,641 --> 01:05:43,242 I promised I'd show you how to do this unwrapping without +就像我之前说的那样,教你们如何解包 1295 01:05:43,310 --> 01:05:46,344 crashing, so let's do it here. Let's decide that if we do +又不用导致崩溃。我就用这个来演示。让我们来判断 1296 01:05:46,413 --> 01:05:49,915 have a blank button, a button whose title is not set, let's +这是否是个空白的按钮,这个按钮是否有标题 1297 01:05:49,983 --> 01:05:53,085 say we won't crash. Instead, we'll just do nothing. +如果是的话我们什么都不做就行了,不崩溃 1298 01:05:53,154 --> 01:05:54,319 We won't do any operations. +我们什么运算都不进行 1299 01:05:54,388 --> 01:05:55,921 Like you didn't even click a button, okay? +就像用户就没按这个按钮一样 1300 01:05:55,990 --> 01:05:59,190 So, again, optionals are so important. You can see, +再次强调,可选类型是很重要的 1301 01:05:59,259 --> 01:06:03,629 look how minuscule the syntax is for these things, right? +看看这些不起眼的语法 1302 01:06:03,697 --> 01:06:06,197 Question mark. Exclamation point. You barely have to type +问号,感叹号。使用可选类型并不需要 1303 01:06:06,266 --> 01:06:08,867 to use an optional. Well, it's the same thing if you want to +额外太多的代码。我们想要在解包 1304 01:06:08,936 --> 01:06:10,969 test the optional before unwrapping. +可选类型前,判断其是否为空 1305 01:06:11,038 --> 01:06:13,004 Instead of putting the exclamation point at the end, +我们不用感叹号 1306 01:06:13,073 --> 01:06:18,510 you put two characters at the beginning. if. So +我们只要在前面加两个字母,if 1307 01:06:18,578 --> 01:06:22,881 read this. If I can let mathematical symbol equal +连起来读,如果我能让数学运算符等于 1308 01:06:22,950 --> 01:06:26,385 the sender's currentTitle, then. So, +调用函数按钮当前的标题,那么怎样 1309 01:06:26,453 --> 01:06:29,054 if I can unwrap this optional, get its associated value, +也就是如果我能够解包这个可选类型,获得它的关联值 1310 01:06:29,123 --> 01:06:30,255 then I'll do something, and +那么我就干这些 1311 01:06:30,324 --> 01:06:32,291 then you can just put whatever code you want in here, +然后你就可以在这里面 1312 01:06:32,359 --> 01:06:33,558 and inside here, +使用这个解包的可选类型了 1313 01:06:33,627 --> 01:06:37,161 mathematicalSymbol will be a string, the associated value. +mathematicalSymbol 就是关联值,那个普通的字符串 1314 01:06:37,230 --> 01:06:40,598 The unwrapped optional, right? Outside of these curly braces, +已经解包的可选类型。大括号以外 1315 01:06:40,667 --> 01:06:43,067 mathematicalSymbol is not even defined, so it doesn't matter. +mathematicalSymbol 是未定义的,所以不用担心 1316 01:06:43,136 --> 01:06:45,437 It's not even defined. So +它是未定义的 1317 01:06:45,506 --> 01:06:48,740 inside this mathematicalSymbol, I could +在这个大括号里面 1318 01:06:48,808 --> 01:06:53,878 say if mathematicalSymbol equals, pi, then do something. +我可以判断,如果数学符号是派,我就这样 1319 01:06:53,947 --> 01:06:57,215 Else if the mathematical symbol equals something else, +否则如果是这个,否则如果是这样一直判断下去 1320 01:06:57,284 --> 01:06:59,952 okay? But, if then else, if then else, if then else, that +if...else if...else if... 1321 01:07:00,020 --> 01:07:02,621 would be really bad code. So I'm going to use a different +这样的代码看起来糟糕极了。所以我要换一种 1322 01:07:02,690 --> 01:07:05,156 one here. A different little expression. +另外一种表达式 1323 01:07:05,225 --> 01:07:08,160 I'm going to use switch. So a lot of languages have switch. +我要使用的是 switch 语句,许多语言都有 switch 1324 01:07:08,228 --> 01:07:10,562 So I'm going to switch on the mathematical symbol. +我会尝试匹配这个数学符号 1325 01:07:10,631 --> 01:07:14,532 Not all languages can switch on a string. Some can, but +并不是所有的语言都能匹配字符串的,有些能 1326 01:07:14,601 --> 01:07:17,936 you can in Swift. And I can just say, in the case that +比如 Swift 语言就可以。我能直接用 case "π" 1327 01:07:18,005 --> 01:07:21,573 it is pi, then I'm going to do something. Now, +如果是派的话,我就这样做 1328 01:07:21,642 --> 01:07:23,274 unfortunately I'm getting an error here. +然而 Xcode 报错了 1329 01:07:23,343 --> 01:07:25,143 So, what am I gonna do? Let's just put in what I'm gonna do. +那我想干什么?我们还是先把这部分加进去吧 1330 01:07:25,212 --> 01:07:29,948 I just want the display. Woops, the displays, text to +我们就让显示屏的文字 1331 01:07:30,017 --> 01:07:34,152 equal pi. Okay. This is pretty bad to type it in as a string, +赋值为派,3.1415926。这样直接输入挺不规范的 1332 01:07:34,221 --> 01:07:35,520 we'll get back to that in a second. +我们等会儿来解决这个问题 1333 01:07:35,589 --> 01:07:37,856 But that's basically what I wanted to do, right? +但这就是我要做的 1334 01:07:37,925 --> 01:07:40,925 Is set the display to be pi. Now I'm getting an error. +让显示屏显示派。但还是报错 1335 01:07:40,994 --> 01:07:43,629 What is the error? It says switch has to be exhaustive. +什么原因?它说 Switch must be exhaustive 1336 01:07:43,697 --> 01:07:46,631 And that's true. When you have a switch, you have to have +是这样的,用 switch 语句的时候,一定要 1337 01:07:46,700 --> 01:07:50,402 every possible case. So unless we want to spend the next few +能包含所有的情况。我们也许可以花上 1338 01:07:50,471 --> 01:07:54,172 lectures I guess going like this, case a-a-a, and +接着的几节课的时间,输入比如 case "aaa" 1339 01:07:54,241 --> 01:07:58,510 typing any possible string, okay, this is no good. So +输入所有可能出现的字符串。这当然是不可能的 1340 01:07:58,578 --> 01:08:03,015 luckily though, there is a default case. So +幸运的是,我们可以用 default 1341 01:08:03,083 --> 01:08:05,417 default just means all other cases. +也就是其它的所有情况 1342 01:08:05,486 --> 01:08:06,651 And here I'm just gonna break out of the switch. +我就 break,跳出这个 switch 语句 1343 01:08:06,720 --> 01:08:10,755 I'm gonna use this command break. Now notice that my +就用 break 关键字。注意到我这里 1344 01:08:10,824 --> 01:08:13,257 indentation's gotten a little messed up here. This should +代码的对齐有点乱了,这里 1345 01:08:13,326 --> 01:08:16,661 really be the same indentation as this. A really cool feature +和这里应该是对齐的。Xcode 有个很棒的功能 1346 01:08:16,730 --> 01:08:20,298 is select any text you want, even the whole file, and +那就是你能选中任意的代码,甚至整个文件 1347 01:08:20,367 --> 01:08:24,402 -do Ctrl I for indent ,and it will re-indent everything for +do Ctrl I for indent, and it will re-indent everything for +然后按 Control+I 自动对齐。Xcode 就会帮你对齐 1348 01:08:24,471 --> 01:08:27,072 you. And I recommend you do that on all your source files +我建议你们对你所有作业里的每个代码文件 1349 01:08:27,141 --> 01:08:29,274 when you turn in your homework. Just select all, +都 Command+A 全选,然后自动对齐 1350 01:08:29,342 --> 01:08:34,079 indent. So we got this pi here. Let's see if this works. +我们已经添加了派的相关逻辑,来看看能不能用 1351 01:08:43,857 --> 01:08:45,424 Got the numbers are still working. +按钮还是没问题 1352 01:08:45,493 --> 01:08:49,995 And pi. Okay. That's weird. +再试试派。这就怪了 1353 01:08:50,063 --> 01:08:53,899 I got that pi that I typed in right here. Okay, but +显示了我这里输入的派的值 1354 01:08:53,968 --> 01:08:57,069 what, how come I got this pi symbol added on there? +但为什么后面还有一个派的符号呢 1355 01:08:57,137 --> 01:09:02,140 That seems weird. Let's try a new number. So, no, okay. +这真奇怪。我们再试个数字。这下糟了 1356 01:09:02,209 --> 01:09:05,376 When I type more numbers, it adds it on to the end. So +我按了数字之后,还是加在显示屏的后面 1357 01:09:05,445 --> 01:09:06,945 even if that pi symbol wasn't in there, +即使那个派的符号不在那里 1358 01:09:07,014 --> 01:09:08,847 I'd be able to change the value of pi, +我也能更改派的值 1359 01:09:08,916 --> 01:09:12,885 evidently by adding more digits to it. That's no good. +随便给它加个几位数,这可不行 1360 01:09:12,953 --> 01:09:15,954 And look at this. When I type more it puts an ellipsis, +再看看这个,我再多加几位小数 1361 01:09:16,022 --> 01:09:19,024 and it stops taking numbers. Okay, this is a mess. +它就不显示了,这可真是一团糟 1362 01:09:19,093 --> 01:09:21,226 We got three big problems here. That pi. +我们有三个大问题。一,那个派 1363 01:09:21,294 --> 01:09:23,095 The fact that I can add on things to the end of it, +二,能向派后面加小数位 1364 01:09:23,164 --> 01:09:24,730 and the fact that I get these ellipses. +三,会出现省略号 1365 01:09:24,798 --> 01:09:25,730 So how are we going to fix those? +怎么解决呢? 1366 01:09:25,799 --> 01:09:28,967 Let's go fix all three of those real quick. Okay. So, +我们抓紧时间一起解决吧 1367 01:09:29,036 --> 01:09:31,670 first the pi coming on the end. Well look, +先是这个结尾出现派的问题 1368 01:09:31,739 --> 01:09:34,239 where do I ever set the display sets? I set it here. +我在哪里更改过显示屏的内容?这里 1369 01:09:34,308 --> 01:09:36,708 Well, so clearly the pi's not coming from this. +但派的符号肯定不是从这里来的 1370 01:09:36,777 --> 01:09:40,712 I set it here. This only sets it to one digit so +这里也改过,但是这里只会是显示一个数字 1371 01:09:40,781 --> 01:09:43,015 that can't be it, cuz I've got multiple. +肯定不是这里,因为我这里不只是一位数 1372 01:09:43,083 --> 01:09:49,087 This is the only other place I set it. Maybe +那只剩下这里了 1373 01:09:49,156 --> 01:09:54,392 this is the problem. Do you see the pi button right there? +也许就是它了。看到派按钮了吗? 1374 01:09:54,461 --> 01:09:58,964 It's hooked up to this method. And to this method. So +它也和这个函数关连上了,也关连了这个函数 1375 01:09:59,033 --> 01:10:03,201 it's doing both. It's doing this and putting this on here, +所以两个函数的内容都在执行。先是执行这个部分,显示了派的数值 1376 01:10:03,270 --> 01:10:05,971 and then it's calling this, and doing this. And +然后又调用了这个方法,把派加到了后面 1377 01:10:06,040 --> 01:10:10,575 the digit is the pi, okay? So, that's bad. Now, how are we +这里的数字,其实是派符号。这就是问题 1378 01:10:10,644 --> 01:10:15,080 going to fix that? Question? >> How did you set +怎么解决?同学,什么问题?>> 你是怎么设置 1379 01:10:15,149 --> 01:10:15,681 the order range? >> Yeah, +顺序的? 1380 01:10:15,749 --> 01:10:16,915 the question is how did it decide the order? +>> 我重复下,问题是调用方法的顺序是怎么决定的 1381 01:10:16,984 --> 01:10:18,983 And the answer is the order is undefined. +答案是不确定的 1382 01:10:19,052 --> 01:10:21,019 In my experience, it's usually alphabetical, but +据我的经验,通常是按字母顺序 1383 01:10:21,087 --> 01:10:23,989 it's undefined. So you would never wanna depend on that. +但并没有一个统一的标准。所以你最好不要依靠调用的顺序 1384 01:10:24,058 --> 01:10:26,191 But yeah, perform comes before touchDigit. +这里 performOperation 是在 touchDigit 之前 1385 01:10:26,260 --> 01:10:29,461 I don't know. But you're almost never gonna have two +我也不知道。一般来说不会像这样 1386 01:10:29,529 --> 01:10:31,563 things hooked up like this. This is obviously an error. +和两个方法都关连起来。我们这里肯定是有问题的 1387 01:10:31,631 --> 01:10:35,000 This is causing a problem. So let's fix it. How do we do +导致程序出了问题,所以我们需要解决这个问题。 1388 01:10:35,068 --> 01:10:37,502 that? There's another way to know what's connected other +怎么办?其实还有另一种查看关连的方法 1389 01:10:37,571 --> 01:10:40,772 than using the little circles, which is just to right click +除了用这个小圆点之外,还能直接右键点击 1390 01:10:40,841 --> 01:10:43,976 on something in the UI. So I right clicked on pi, and I got +界面里的控件。比如我右键点击派 1391 01:10:44,044 --> 01:10:47,345 this big window that shows me all the connections to pi. +就出现这个很大的窗口,列出了所有和它的关连 1392 01:10:47,414 --> 01:10:49,614 This would be all the instance variables, all the methods, +也就是关连着的实例变量和方法 1393 01:10:49,683 --> 01:10:52,817 etc. And we can see that for the event Touch Up Inside, +这里也列出了所有 Touch Up Inside 1394 01:10:52,886 --> 01:10:56,521 which means a touch of the finger went up inside +也就是手指抬起的时候 1395 01:10:56,590 --> 01:11:00,692 the bounds of the button. It's sending both these messages, +如果在按钮内部,就发出消息 1396 01:11:00,760 --> 01:11:02,727 touchDigit and perfomOperation, and +给 touchDigit 和 performOperation 1397 01:11:02,796 --> 01:11:05,763 we clearly did not want touchDigit for pi. +我们显然不希望派按钮调用 touchDigit 1398 01:11:05,832 --> 01:11:09,635 Why did I get it? Because I copied and pasted that 7. +但我为什么会有这个关连呢?是因为我是复制粘贴的数字 7 1399 01:11:09,703 --> 01:11:12,404 Remember I said that was a bad idea? Yeah, that's why. So +还记得我说那是个坏主意吗?这就是原因 1400 01:11:12,473 --> 01:11:16,508 let's disconnect it by just clicking this little x, okay, +我们点这个小叉,取消关连 1401 01:11:16,577 --> 01:11:22,181 boom. Now this only is sent by this, and not by this. +现在就只会发消息给 performOperation,不会给 touchDigit 了 1402 01:11:22,249 --> 01:11:24,649 So that fixed that. What about the fact that +第一个问题就解决了。那我能够 1403 01:11:24,718 --> 01:11:28,387 I could type extra numbers on the end of pie? Well, that's +给派再加个几位的问题呢? 1404 01:11:28,455 --> 01:11:31,089 a pretty simple neither. When am I allowed to type other +这也很容易解决。我什么时候可以向显示屏 1405 01:11:31,158 --> 01:11:34,258 numbers in? When the user's in the middle of typing a number. +加数字?当用户正在输入的时候 1406 01:11:34,327 --> 01:11:35,960 Well as soon as I hit pi, +用户按下派之后 1407 01:11:36,029 --> 01:11:39,364 is the user in the middle of typing a number? No, they +还在输入的过程中吗?没有 1408 01:11:39,433 --> 01:11:41,933 just typed pi. So they're not in the middle of typing pi. +他们已经输入完派了,他们并不是在输入派的过程中 1409 01:11:42,002 --> 01:11:43,402 And in fact, they're typing a number. +他们没有还在输入一个数字 1410 01:11:43,471 --> 01:11:45,904 And in fact any time we perform any operation, +其实我们在进行任何运算的时候 1411 01:11:45,973 --> 01:11:49,007 the user is in the middle of typing a number is false. +就可以让 userIsInTheMiddleOfTyping = false 1412 01:11:49,076 --> 01:11:51,476 They are clearly not in the middle of typing anymore. +因为用户显然已经还在输入的过程中了 1413 01:11:51,545 --> 01:11:53,745 Whatever's gonna be display is gonna be the result of that +显示的内容只会是运算的结果 1414 01:11:53,813 --> 01:11:57,849 operation. Okay, so that fixes that. How bout the little +好,解决了第二个问题。那省略号呢 1415 01:11:57,918 --> 01:12:00,385 ellipses, and the numbers getting cut off. Well here's +那些被截断的数字呢 1416 01:12:00,453 --> 01:12:03,956 a kind of a cute fix to that. In label, there is a cool +我们解决的方法挺机智的。标签里有个很酷的功能 1417 01:12:04,024 --> 01:12:06,024 feature called autoshrink, you see it right there? +叫做 Autoshrink,自动缩小,看到了吗 1418 01:12:06,093 --> 01:12:08,460 So I just selected label, brought up this inspector. +选中一个标签,调出检查器 1419 01:12:08,528 --> 01:12:11,730 There's autoshrink, and you can have it shrink down, for +找到这里的 Autoshrink。你可以选择缩小到 1420 01:12:11,798 --> 01:12:14,632 example to a minimum font size, let's say 9 font. +比如说某个字号,像是 9 号 1421 01:12:14,701 --> 01:12:16,468 And now, when we get too many numbers, +我们现在数字多起来之后 1422 01:12:16,536 --> 01:12:19,571 it'll shrink down instead of doing ellipses, right there. +它就会自动缩小,而不是显示省略号了 1423 01:12:19,639 --> 01:12:21,940 Now, this probably isn't the best solution to this. +但这并不一定是最好的解决方案 1424 01:12:22,009 --> 01:12:24,576 A better solution would be, have our calculator only show +更好的方法是,让计算器只显示 1425 01:12:24,644 --> 01:12:27,112 a certain number of digits after the decimal point. +一定长度的数字,或是只到小数点后几位 1426 01:12:27,181 --> 01:12:28,780 Probably would be really better. And +这样也许会更好 1427 01:12:28,849 --> 01:12:30,782 that's extra credit for you in your homework, okay? +这会作为你们作业里的加分项 1428 01:12:30,851 --> 01:12:33,685 So good luck with that. Right, so we got this. +祝你们好运吧。我们稍作修改 1429 01:12:33,754 --> 01:12:35,454 We fixed all these problems, let's take a look. +解决了所有的问题,来实际看看吧 1430 01:12:43,964 --> 01:12:48,533 All right, so got our numbers here. Pi, alright no pi and +数字键还是正常的。派,太好了,没有结尾的符号了 1431 01:12:48,602 --> 01:12:52,537 it didn't add them on to the end and +再按数字键也不是加在派后面了 1432 01:12:52,606 --> 01:12:54,673 what if we had a lot of numbers in here. +再看看如果有很多数字呢 1433 01:12:55,810 --> 01:12:57,642 Yeah, look at that, it's autoshrinking. +很好,看看啊,字号在自动缩小 1434 01:12:57,711 --> 01:12:59,144 Okay, we're not losing any numbers. +没有出现数字消失的情况 1435 01:12:59,213 --> 01:13:00,812 Yeah, probably not the best solution but +虽然这不是最好的解决方案 1436 01:13:00,881 --> 01:13:05,083 I get to show you autoshrink. Okay, what's next? +我就是想展示一下自动缩小。下一步 1437 01:13:05,151 --> 01:13:09,254 We're gonna attack this little problem right here. Okay? +解决这个问题 1438 01:13:09,323 --> 01:13:12,757 This is really ugly, really what I want this to be is this +这实在是太丑陋了,我想让它改成这样 1439 01:13:12,826 --> 01:13:17,061 really cool feature in Swift, Double.pi, which is the double +Swift 里很优秀的特性,Double.pi 1440 01:13:17,130 --> 01:13:20,798 precision floating point value of pi. Of course, I can't say +派在双精度下的浮点值。当然我不能直接就这样写 1441 01:13:20,867 --> 01:13:23,735 this because- Cannot assign value of type 'Double' to +Cannot assign value of type 'Double' to type 'String?' 1442 01:13:23,804 --> 01:13:26,638 an optional string because the only way you can assign +不能把双精度类型的值赋给可选字符串 1443 01:13:26,707 --> 01:13:30,008 anything to an optional string besides nil would be something +因为可选字符串的值不是 nil 的话 1444 01:13:30,077 --> 01:13:33,278 that's a string. So we can set that associated value. Now, +就只能是字符串。所以我们要设置的就是那个关联值 1445 01:13:33,347 --> 01:13:36,047 does anyone know, from what I've shown you today, +有谁知道,我今天讲过的哪个内容 1446 01:13:36,116 --> 01:13:42,821 -how we could convert this to a sting? No brave soul? +how we could convert this to a string? No brave soul? +能够把这个转换成字符串?没有人自告奋勇? 1447 01:13:42,890 --> 01:13:46,258 Back, exactly. Backslash, open parentheses, +没错,就是反斜线,左括号 1448 01:13:46,326 --> 01:13:48,861 close parenthesis, that little trick, right? +右括号,就是这个窍门 1449 01:13:48,929 --> 01:13:52,230 You can just put Double.pi in here. +然后把 Double.pi 放进来 1450 01:13:52,299 --> 01:13:55,033 Doubles can be converted to strings, bingo. +双精度小数可以转换成一个字符串 1451 01:13:55,102 --> 01:13:59,737 Now, this is kinda ugly, okay? This really doesn't look good +但这看起来也不是很好 1452 01:13:59,806 --> 01:14:03,609 because this is more meant to embed things in other strings. +因为这个适用于把其它东西插入到字符串里 1453 01:14:03,677 --> 01:14:06,644 It's not really the way to make something a string. +而不是把它转换成字符串的方法 1454 01:14:06,713 --> 01:14:08,814 The way to really make a new string is to create +新建一个字符串的方法 1455 01:14:08,882 --> 01:14:11,816 a new string. And so, here you're seeing what the syntax +是构造一个字符串。你这里看到的 1456 01:14:11,885 --> 01:14:16,288 is to create a new object, a new struct or a new class, +就是构造一个新对象的方法,一个新的结构体或类的方法 1457 01:14:16,356 --> 01:14:19,625 okay? The name of the class, and then parentheses. +类的名字,然后是一对括号 1458 01:14:19,693 --> 01:14:23,494 Now, inside these parentheses, can be anything the class +在括号里面是任何 1459 01:14:23,563 --> 01:14:27,565 can take to create one of itself, right? Anything that +可以用来构造对象的参数 1460 01:14:27,634 --> 01:14:30,401 class can take. And remember I mentioned those initializers? +任何支持的参数。还记得我提到的构造器吗 1461 01:14:30,470 --> 01:14:33,138 These are the arguments to the initializer. And initializers, +这些就是构造器的参数 1462 01:14:33,206 --> 01:14:34,706 you've got multiple initializers. +你可以有许多不同的构造器 1463 01:14:34,775 --> 01:14:36,875 String has a whole bunch of initializers. +字符串类有不少的构造器 1464 01:14:36,944 --> 01:14:39,444 One of the initializers that a string has, +其中一个 1465 01:14:39,513 --> 01:14:44,749 takes a double. So this would be the right way to +能接受一个双精度小数。所以这才是 1466 01:14:44,818 --> 01:14:46,484 convert from a double to a string and +把双精度小数转换为字符串的方法 1467 01:14:46,553 --> 01:14:48,820 it looks a lot better in the code as well, right. +代码也看起来好多了 1468 01:14:48,889 --> 01:14:52,524 It's more obvious what we're doing, okay? +我们的意图也更明显了 1469 01:14:52,592 --> 01:14:55,527 All right let's add another operation here, +我们再来添加另一个运算 1470 01:14:55,596 --> 01:14:59,030 -I'm gonna make this one be square root. So underneath +I'm gonna make this one be square root. So I'm gonna need +平方根。我需要这个符号 1471 01:14:59,099 --> 01:15:01,967 the square root symbol, from the edit menu, emoji and +从菜单里的 Edit > Emoji & Symbols 1472 01:15:02,035 --> 01:15:06,338 symbols, you can actually search. We could pick a smiley +然后搜索。虽然我们可以就用这个笑脸符号 1473 01:15:06,407 --> 01:15:10,275 face but let's go square root. Square root, here it is, so +但我们还是把平方根找出来。square root,出来了 1474 01:15:10,344 --> 01:15:14,846 we're gonna use this square root symbol in code there. And +我们就使用这个平方根符号 1475 01:15:14,914 --> 01:15:16,748 let's go ahead and copy it so we can use it in the code. +然后 Command+C 复制到剪贴板,等会在代码里用 1476 01:15:16,817 --> 01:15:18,050 All right, so we have this, +这就是我们的平方根按钮 1477 01:15:18,118 --> 01:15:21,753 it's nicely hooked up just to this and not to this. +与且仅与 performOperation 关连 1478 01:15:21,821 --> 01:15:25,724 So that's good. We just need to say case of square root. +我们 switch 再加一个情况,如果是平方根,case "√" 1479 01:15:25,793 --> 01:15:29,160 What do we wanna do? We wanna set the display's text +我们就把显示的文字 1480 01:15:29,229 --> 01:15:32,964 equal to the square root of something. Okay, well what do +赋值为某个数的平方根 1481 01:15:33,033 --> 01:15:35,600 we want this to be the square root of? Well we want it to be +我们希望这是什么的平方根? 1482 01:15:35,669 --> 01:15:39,370 the square root of whatever's in this display already. So, +应该是目前显示屏内容的平方根 1483 01:15:39,439 --> 01:15:45,710 display!.text, okay, will that work? No, because this +能直接把 display!.text 作为参数吗 1484 01:15:45,779 --> 01:15:49,047 is a string and we can't take the square root of a string. +不行,因为那是个字符串,怎么计算一个字符串的平方根啊 1485 01:15:49,116 --> 01:15:53,818 And not only that, the square root returns a double, okay? +还有一个问题,sqrt 的返回值是双精度型的 1486 01:15:53,887 --> 01:15:56,855 And we can't put a double into a string, so we at least have +我们不能把它赋值给一个字符串 1487 01:15:56,924 --> 01:16:00,892 to do this again, put a string around it. Okay? But +所以我们至少需要用 String 的构造器 1488 01:16:00,961 --> 01:16:04,662 this is still a string. So I'm gonna get this out of here and +但这个部分还是字符串。先把这个部分单独出来 1489 01:16:04,731 --> 01:16:06,131 make a little local variable so +存到一个局部变量 operand 1490 01:16:06,200 --> 01:16:10,569 we can work on this, okay? So, we need this operand, +只关注这个部分。我们需要这个运算数 1491 01:16:10,638 --> 01:16:15,574 which is currently a string, to be a double. So +operand 由现在的字符串变为小数 1492 01:16:15,642 --> 01:16:21,079 can we do this, double? You think we can do that? +我们能把它转换为双精度小数吗? 1493 01:16:21,148 --> 01:16:24,083 In the same way that we went this way? Can we go this way? +能像我们转字符串那样吗?能反过来吗? 1494 01:16:25,219 --> 01:16:29,922 -The answer is yes. Or yes! One of those. +The answer is yes. Or yes? One of those. +答案是可以,更准确地说,大部分时候可以 1495 01:16:29,990 --> 01:16:34,326 The answer is yes because, what if that string is hello? +因为,如果那个字符串是 hello 1496 01:16:34,395 --> 01:16:39,164 What do you convert hello to? It can't be converted. +你要怎么把 hello 转成小数?这是做不到的 1497 01:16:39,233 --> 01:16:43,936 So this initializer for double that takes a string, +所以这个双精度的构造器,参数是字符串 1498 01:16:44,004 --> 01:16:48,340 it returns an optional double. Do you see why? Cuz if you +返回值是一个可选的双精度。可以理解吧 1499 01:16:48,408 --> 01:16:50,709 give it a string that it can't convert to a double, +给它个字符串,如果没法转换 1500 01:16:50,778 --> 01:16:53,511 it returns not set. Couldn't do it, basically. +返回就会缺省值。也就是表示无法转换 1501 01:16:53,580 --> 01:16:57,516 So if we look at operand right here, it's an optional double, +所以我们可以看到这个 operand,是 Double? 类型的 1502 01:16:57,585 --> 01:16:59,618 okay? Whereas when we did this string up here, +和上面字符串的构造器是不一样的 1503 01:16:59,687 --> 01:17:01,619 string didn't need to return optional string, +构造的并不会是可选字符串 1504 01:17:01,688 --> 01:17:04,323 because it can always convert a double to a string, always. +因为一定能用字符串表示小数 1505 01:17:04,391 --> 01:17:06,224 But you can't always convert a string to a double, +但不总是能把字符串转换成小数的 1506 01:17:06,293 --> 01:17:08,427 it has to look like a double. Okay? +至少要长得像才行 1507 01:17:08,495 --> 01:17:10,395 So, we're gonna do that and I'm gonna go ahead and +我们就用这个构造器 1508 01:17:10,464 --> 01:17:13,231 force unwrap it here with the exclamation point, assuming +直接用感叹号强制解包 1509 01:17:13,300 --> 01:17:16,068 that I never have anything in my display that can't be +假设显示的内容 1510 01:17:16,136 --> 01:17:19,804 converted to a double. Maybe that's a bad assumption but +总是能转换的。虽然这个假设很大胆 1511 01:17:19,873 --> 01:17:23,007 I'm gonna assume that for now. I'm also gonna Ctrl+I again, +但现在先这样吧。还是顺便用 Control+I 1512 01:17:23,076 --> 01:17:26,511 to get my indenting right. Okay, does this make sense? +把代码对齐。都还能理解吧? 1513 01:17:26,580 --> 01:17:29,280 So now all is well. Operand is a double. +这样就完成了,operand 是 Double 型的 1514 01:17:29,349 --> 01:17:31,015 So I can take the square root of a double. +我就能直接求它的平方根了 1515 01:17:31,084 --> 01:17:33,285 I'm gonna convert it to a string and go to here. +再转成字符串显示出来 1516 01:17:33,353 --> 01:17:36,121 All right, wow, that's a lot of mess. Okay, +有够混乱的 1517 01:17:36,190 --> 01:17:39,123 that's really messy code, I'm gonna have to fix that, but +我有必要整理一下这堆混乱的代码 1518 01:17:39,192 --> 01:17:41,960 conceptually you understand hopefully what's going on +但希望你们能理解这里发生了什么 1519 01:17:42,028 --> 01:17:47,833 there. So let's do this, let's try 81 square root. Square +让我们来试试,81,平方根 1520 01:17:47,901 --> 01:17:51,069 root again. Square root again. How about pi square root? +再平方根,再平方根。派的平方根 1521 01:17:51,138 --> 01:17:55,106 78 square root? All right, this is working perfectly. +78 的平方根。一切正常 1522 01:17:55,175 --> 01:17:59,511 But, our code is really a mess here. Can you imagine, +只不过代码有些乱。你想象一下 1523 01:17:59,580 --> 01:18:02,113 if we have to do another case and another case. +如果我们还有另外好几种情况 1524 01:18:02,182 --> 01:18:04,416 And we're always doing this double this, string that, +我们就需要不断地转换成 Double 再转回 String 1525 01:18:04,485 --> 01:18:07,285 back and forth, exclamation points everywhere. Okay, +每个地方都强制解包 1526 01:18:07,354 --> 01:18:09,254 there's too many dang exclamation points in here for +有太多不安全的感叹号 1527 01:18:09,323 --> 01:18:11,123 the first thing. And the second of all, +这是第一个问题。第二个问题是 1528 01:18:11,191 --> 01:18:12,524 I'm tired of all the strings and doubles. So +转换过来转换过去太麻烦了 1529 01:18:12,592 --> 01:18:15,227 I'm gonna fix all that. Let's start with the exclamation +两个问题都要解决。从感叹号开始 1530 01:18:15,295 --> 01:18:19,230 point thing. Look at every time I use the display. +仔细观察,我每次用 display 的时候 1531 01:18:19,299 --> 01:18:20,732 I use it all over my code. +可以看出我到处都在用 1532 01:18:20,800 --> 01:18:23,268 And every time I have to put an exclamation point, +每次用都有感叹号 1533 01:18:23,337 --> 01:18:27,372 every single time. Even though I know that display, +每次都强制解包,即使我知道 1534 01:18:27,441 --> 01:18:32,243 once it's set up by iOS in the beginning, it never is not in +只要 iOS 系统完成初始化之后 1535 01:18:32,312 --> 01:18:34,780 the not set state, it's always set. So +display 总是存在的,不会出现缺省值的情况 1536 01:18:34,848 --> 01:18:38,850 let's go back up here to this question mark. +我们回到这个问号 1537 01:18:38,919 --> 01:18:42,821 This is what exclamation point in a declaration +这就是在定义的时候使用感叹号的原因 1538 01:18:42,889 --> 01:18:46,258 of an optional means. It means yes, this is an optional, +对于定义可选类型而言,这个感叹号 1539 01:18:46,326 --> 01:18:50,795 just like a question mark. But, everywhere you use this, +和问号是差不多的。只不过每次使用的时候 1540 01:18:50,864 --> 01:18:53,831 I'm going to automatically unwrap it. Now, +会自动强制解包 1541 01:18:53,900 --> 01:18:56,969 it's still unwrapping it, so even if I go down here and +因为会自动解包,所以我们把下面代码里 1542 01:18:57,037 --> 01:18:58,570 I take away this exclamation point, +所有 display 后面的感叹号都去掉 1543 01:18:58,639 --> 01:19:01,539 it works because of this automatic unwrapping. +还是能够正常运行的,因为都自动解包了 1544 01:19:01,608 --> 01:19:05,810 But if this were not set, it would still crash. Okay? +但即使如此,如果 display 缺省值的话,还是会崩溃的 1545 01:19:05,879 --> 01:19:09,481 Because essentially, implicitly unwrapping. +因为这实际上会隐式解包这个 display 1546 01:19:09,550 --> 01:19:14,119 That's why this is called an implicitly unwrapped optional. +这就是所谓的 implicitly unwrapped optional 1547 01:19:14,188 --> 01:19:17,856 Got that phrase? Implicitly unwrapped optional. But +隐式解析可选类型 1548 01:19:17,924 --> 01:19:20,792 it does mean, that we can go around to all of our +这意味着我们可以把所有的 1549 01:19:20,861 --> 01:19:23,795 display question marks, and change them to display. +display! 替换成 display 1550 01:19:23,864 --> 01:19:27,132 And that makes our code look quite a bit nicer. Okay? +这样代码看起来就好些了 1551 01:19:27,200 --> 01:19:31,170 Now we're still having to unwrap text. Sorry about that. +但我们还是要强制解包 text 的,没有办法 1552 01:19:31,238 --> 01:19:33,404 Bottom line is we have to do that. +下面的这行需要保留感叹号 1553 01:19:33,473 --> 01:19:36,909 -That's not an implicitly unwrapped option on that text. +That's not an implicitly unwrapped optional, that text. +text 并不是一个隐式解包的可选类型 1554 01:19:36,977 --> 01:19:39,678 Okay, what about all this double and string thing? +那这些来回转换的呢? 1555 01:19:39,746 --> 01:19:41,913 The way I'm gonna fix that is imagine I had a var. +解决方法是如果我能有个变量 1556 01:19:41,982 --> 01:19:44,216 We'll call it displayValue. +叫 displayValue,显示的数值 1557 01:19:44,284 --> 01:19:49,454 And it was a double. Okay, show me this var. +是 Double 类型的变量 1558 01:19:49,522 --> 01:19:54,425 -Imagine if this var, all it tracked, what's in here, but +Imagine if this var, always tracked, what's in here, but +如果它能够和显示屏的数值保持同步 1559 01:19:54,494 --> 01:19:57,462 as a double? Cuz what's in there, we can only get it as +并以小数存储该多好。现在我们获取显示的值只能是字符串 1560 01:19:57,531 --> 01:19:59,764 a string, we can only set it as a string. But +也只能设置为一个字符串 1561 01:19:59,833 --> 01:20:02,634 wouldn't it be cool if I had a var that just was always what +我能不能有这样一个神奇的变量 1562 01:20:02,703 --> 01:20:05,404 was in there but as a double? Because I need it as a double +值总是显示屏里的小数?因为我每次使用的时候 1563 01:20:05,472 --> 01:20:08,440 all the dang time, and I need to set it as a double too, +我总是需要小数,每次设置的时候也是小数 1564 01:20:08,508 --> 01:20:11,509 okay? So how can I do that? Well, turns out Swift +那要怎么做呢?Swift 里 1565 01:20:11,578 --> 01:20:16,582 has a really cool feature called computed properties. +有个很厉害的特性叫做,computed property,计算型属性 1566 01:20:16,650 --> 01:20:19,752 And all I need to do is put code after the property, and +只需要把代码放到变量后面的那对大括号里 1567 01:20:19,820 --> 01:20:22,587 you can compute the value. Instead of storing +就能实时计算变量的值了,而不是依靠存储的值 1568 01:20:22,656 --> 01:20:25,290 it, right. The user is in the middle of typing a value that +userIsInTheMiddleOfTyping 这个变量的值 1569 01:20:25,359 --> 01:20:27,826 storage somewhere. This one we're gonna compute. And +是存储在某个地方的,displayValue 则是我们计算的 1570 01:20:27,894 --> 01:20:33,098 you can compute both a get case, right? And, +我们既能计算,get,获取的值 1571 01:20:33,167 --> 01:20:39,838 oops, sorry. And a set case. So you can have some code that +也能计算,set,赋于的值。所以你可以有代码 1572 01:20:39,906 --> 01:20:42,841 deals with getting the value and with setting the value. +负责计算获取的值,也可以有代码处理赋值的情况 1573 01:20:42,910 --> 01:20:44,843 So we're not gonna ever store displayValue anywhere. +我们的 displayValue 并不会被存储起来 1574 01:20:44,912 --> 01:20:45,777 We're gonna get it and set it. +我们会处理访问和赋值的计算 1575 01:20:45,846 --> 01:20:48,046 And where are we gonna get it and set it from? +计算的数据源又是哪里呢? 1576 01:20:48,114 --> 01:20:51,983 From the text on the label. Right? So what does the get +是标签显示的文字。那该怎么写 getter? 1577 01:20:52,052 --> 01:20:55,020 look like? Well, we're just gonna return a double of +我们就 return,返回用小数表示的 1578 01:20:55,089 --> 01:20:59,024 the display's text, you don't have to unwrap display, but +显示屏的文字。不用解包 display 1579 01:20:59,093 --> 01:21:02,127 I do have to unwrap text. And I'm gonna force unwrap that. +但是要解包 text。然后强制解包这个整体 1580 01:21:02,196 --> 01:21:06,331 Again, I'm assuming there's always a string that +我还是假设显示的内容 1581 01:21:06,400 --> 01:21:07,799 can be interpreted as a double in there. +一定能被解析为一个双精度小数 1582 01:21:07,867 --> 01:21:09,935 Maybe I wanna change that assumption down the road, but +也许之后我会改主意 1583 01:21:10,004 --> 01:21:12,070 for now I'll do that. How about the set case? +但现在我还是这么做假设。那被赋值的时候怎么办呢? 1584 01:21:12,139 --> 01:21:16,075 In this set case, I'm gonna display, set the display's +在被赋值的时候,我让 display 的 text 1585 01:21:16,143 --> 01:21:19,010 text equal to a string that is the value that +赋值为一个字符串 1586 01:21:19,079 --> 01:21:22,213 people are trying to set the display value to. +字符串是我们想要显示屏接下来显示的值 1587 01:21:22,282 --> 01:21:25,917 So somewhere in the code, we write displayValue equals +也就是比如写 displayValue = 5 1588 01:21:25,986 --> 01:21:29,988 five. And here we have to put a five, +我们就把 5 1589 01:21:30,057 --> 01:21:34,659 a string five into the text of the display up here. +转换成字符串显示到显示屏 1590 01:21:34,728 --> 01:21:38,364 So what do we put inside this little string here. Well, for +那这个字符串构造器的参数写什么? 1591 01:21:38,432 --> 01:21:42,401 this set case, okay, of a computed property, +计算属性的 set 里 1592 01:21:42,469 --> 01:21:46,638 there's a special variable called newValue, and newValue +有个特殊的变量叫做 newValue 1593 01:21:46,707 --> 01:21:50,175 is always of the same type as what you're setting, and it is +newValue 和这个变量是同一个类型的 1594 01:21:50,243 --> 01:21:53,145 the value on the right hand side of an equals if someone +它就是那个在赋值语句右边的 1595 01:21:53,214 --> 01:21:58,683 says that this var equals something, okay? Awesome. +你让变量等于的那个值 1596 01:21:58,752 --> 01:22:00,319 Now that we have this displayValue and +现在这个 displayValue 1597 01:22:00,387 --> 01:22:02,954 it's always tracking that, we can use it down here. +会和显示屏保持同步,也能够在下面使用了 1598 01:22:03,023 --> 01:22:08,026 Look at this code, displayValue equals pi. +改成这样,displayValue = Double.pi,显示的值为派 1599 01:22:08,095 --> 01:22:12,964 Done, get rid of all this mess. displayValue equals +看看啊,这些就都不用了。显示的值等于它自己的平方根 1600 01:22:13,033 --> 01:22:17,669 the square root of the displayValue. All of a sudden, +displayValue = sqrt(displayValue)。一瞬间 1601 01:22:17,738 --> 01:22:21,540 the code down here has become essential, right? +就能抓住重点了 1602 01:22:21,608 --> 01:22:25,410 This is about the minimum you could possibly type to say +这几乎是你能用的最短的代码 1603 01:22:25,479 --> 01:22:30,782 that you wanted pi into the display. Right? And so, when I +来让显示屏显示派 1604 01:22:30,851 --> 01:22:34,419 do this display value equals, this code gets executed. +当我用 displayValue = 的时候,运行的是 set 里这段代码 1605 01:22:34,488 --> 01:22:38,891 When I get the display value here, this code gets executed. +我在这里访问 displayValue 的时候,运行的是 get 里这段代码 1606 01:22:38,959 --> 01:22:40,525 These are called computed properties. You're +这就是计算型变量 1607 01:22:40,594 --> 01:22:41,926 going to see them all over the place. +它们无处不在 1608 01:22:41,995 --> 01:22:46,231 You've already seen one. It's right here, currentTitle +你已经在这里看到过一个了,就是这个 currentTitle 1609 01:22:46,300 --> 01:22:49,434 is a computed property. It's computed by the button class. +它就是个由按钮类计算的计算属性 1610 01:22:49,503 --> 01:22:52,003 It figures out what the current title is on there and +它计算出现在按钮上的标题 1611 01:22:52,072 --> 01:22:55,273 returns it. So there's this is implemented with some +然后返回给你。具体的实现 1612 01:22:55,342 --> 01:22:56,675 code that says return whatever. +就会是 return 什么什么一类的 1613 01:22:56,743 --> 01:22:59,444 How do I know that? Because it's read-only. The only way +我怎么知道的?因为这是只读的,而只有计算属性能实现 1614 01:22:59,513 --> 01:23:03,448 to make a read-only var is using a computed property. +完全只读的。(可以更改 setter 的访问级别来实现伪只读) 1615 01:23:03,517 --> 01:23:06,251 All right, let's make sure we didn't break anything with our +让我们来确认一下有没有导致新 bug 1616 01:23:06,320 --> 01:23:14,393 code clean up there. All right, 89 looking good, +毕竟整理了代码。试试 89 1617 01:23:14,461 --> 01:23:18,463 square root, 81, square root, square root, square root. +平方根。81 的平方根,的平方根,的平方根 1618 01:23:18,532 --> 01:23:21,366 Pi 78 square root. Okay, +派,78,平方根。好 1619 01:23:21,434 --> 01:23:25,537 it's working. Okay, so that's a lot of stuff to digest, +没问题。我知道要消化的内容很多 1620 01:23:25,606 --> 01:23:29,107 I know. Let it all sink in. On Wednesday at the start, +你们花时间理解记忆。星期三一开始 1621 01:23:29,176 --> 01:23:31,610 I'm gonna talk to you about MVC, this design paradigm, and +要讲 MVC,那个设计模式 1622 01:23:31,679 --> 01:23:35,380 then we're gonna add MVC to this and +再运用 MVC 1623 01:23:35,448 --> 01:23:37,983 we're also gonna make sure that UI works on all devices. +最后确保 UI 适用于各种设备 1624 01:23:39,119 --> 01:23:40,752 Okay, see you then. >> For +好,下课 1625 01:23:40,821 --> 01:23:50,228 more, please visit us at stanford.edu. +>> 更多课程详见 stanford.edu