
Chinese: 
本字幕由志愿者义务贡献，采用许可协议
知识共享 署名-非商业性使用-相同方式共享 3.0 美国
Stanford University. Welcome to Stanford CS193P,
斯坦福大学。>> 欢迎参加 2017 年冬季学期
this is Developing Applications for iOS,
斯坦福 CS193P 课程，iOS 应用程序开发
winter of 2017. This is the only lecture in this quarter
这是本季度唯一一节我不打算
where I'm not going to do a demo, so this is all slides,
做示例程序的课，这次全是幻灯片
and that's because I'm pretty much going to try and
那是因为我很想
get you fully up to speed on Swift. Everything that I'm
让你们完全掌握 Swift。我今天讲到的内容
going to talk about today is covered either in your reading
包括在你们的今天截止的阅读任务一
assignment one, which was due today, so hopefully you're
所以希望你们已经完成了这项作业
done with that, or it's in reading assignment two,
或者是在阅读任务二中
which is going out today and is due next Wednesday. So,
也就是今天的作业，下周三截止
why am I even covering this? Because I know that reading
所以为什么我竟然会包括这个呢？因为我知道
through that reading assignment can be a big slog
那个阅读任务的信息量太大，全部读完
through a lot of information, and I want you to understand
并不是一件令人愉悦的事情
the things in there that are really important. As I go
并且我希望你们能理解这些非常重要
through the slides today, if you see something and
今天我播放幻灯片的时候，如果你看到一些东西

English: 
[MUSIC]                         
Stanford University.            
Welcome to Stanford CS193P,     
this is Developing              
Applications for iOS,           
winter of 2017. This is the     
only lecture in this quarter    
where I'm not going to do       
a demo, so this is all slides,  
and that's because I'm          
pretty much going to try and    
get you fully up to speed on    
Swift. Everything that I'm      
going to talk about today is    
covered either in your reading  
assignment one, which was due   
today, so hopefully you're      
done with that, or it's in      
reading assignment two,         
which is going out today and    
is due next Wednesday. So,      
why am I even covering this?    
Because I know that reading     
through that reading            
assignment can be a big slog    
through a lot of information,   
and I want you to understand    
the things in there that        
are really important. As I go   
through the slides today,       
if you see something and        

Chinese: 
I explain it and you're like, my gosh I didn't get that,
或我对它的解释让你感觉 “我天完全搞不懂”
just make a note about whatever the topic is that I'm
先把我讲的内容记下来
talking about and then you can go back and
等回去之后你可以再次
read about it again in your reading assignment to try and
试着通过阅读任务的相关内容理解
understand it. If you still don't understand it,
如果你依然搞不懂
you can of course ask on the class forums.
你当然可以在课堂论坛上提问
You can think of this as kind of the highlights of the first
你可以把这当成给最开始的
two reading assignments. Some of these are also highlights
两个阅读任务勾重点
of the first two lectures I did in the demos,
最开始两节课的示例程序中的重点
so there's a little bit of that in there too.
也会包含一些
But, this is really kind of the important stuff in Swift,
但是，我现在教你们的
that I can teach you at this point.
真的是 Swift 中很重要的内容
There's more important stuff in Swift to come, okay,
Swift 中还有更重要的东西要讲
but I'll teaching it kinda as we go in the next two weeks.
但我大概将会在接下来的两周里讲解
Okay, so lot of Swift topics,
好了，这么多 Swift 的话题
let's start with the first one, probably everybody's
让我们从第一个开始，大概所有人
favorite topic when they first learn Swift,
刚开始学习 Swift 时最喜欢的话题
which is optional. Optional is interesting in Swift,
就是 Optional。Swift 中的 Optional 很有意思
because not a lot of other languages have optional, so
因为其他有 Optional 的语言并不多，所以
I'm sure, in fact I've heard, that some of you are like,
我很确定，实际上我已经听说了，就是你们中有些人感觉
"Hmm, I'm not sure I really understand that optional
“额，我不确定我真的理解了 Optional 是个啥东西”

English: 
I explain it and you're like,   
my gosh I didn't get that,      
just make a note about          
whatever the topic is that I'm  
talking about and               
then you can go back and        
read about it again in your     
reading assignment to try and   
understand it. If you           
still don't understand it,      
you can of course ask           
on the class forums.            
You can think of this as kind   
of the highlights of the fist   
two reading assignments. Some   
of these are also highlights    
of the first two lectures       
I did in the demos,             
so there's a little bit         
of that in there to.            
But, this is really kind of     
the important stuff in Swift,   
that I can teach                
you at this point.              
There's more important stuff    
in Swift to come, okay,         
but I'll teaching it kinda as   
we go in the next two weeks.    
Okay, so lot of Swift topics,   
let's start with the first      
one, probably everybody's       
favorite topic when             
they first learn Swift,         
which is optional. Optional     
is interesting in Swift,        
because not a lot of other      
languages have optional, so     
I'm sure, in fact I've heard,   
that some of you are like,      
"Hmm, I'm not sure I really     
understand that optional        

Chinese: 
thing". And that's probably okay, but by the end of next
这没关系，但是在下周结束之前
week you should feel very confident with Optionals,
你应该会感到对 Optional 很有把握了
because you're gonna see that they are absolutely everywhere
因为你将会看到它们实际上会出现在 iOS 中的任何地方
in iOS. Now, I mentioned this in the lecture but
我在课上提到这个
I wanted to show it to you from a code,
但是我想用一段代码向你展示它
kind of a code point of view, which is that optional
从代码的角度来看
is nothing more than an enum, it is fact just an enum,
Optional 实际上就是个枚举
this is the enum that is an optional. It's a generic type,
这是 Optional 作为泛型枚举的定义
kind of like array, how with array when you say the type,
有点像 Array，泛型数组的定义
you say the type of the thing you're putting in the array.
需要声明元素的类型
You should all be familiar to that, with that from Java for
你们对此应该都不陌生，就像 Java 一样
example, same thing in Swift.
在 Swift 中也是一样的
So, with optional it is the same way,
同理，对于 Optional
you put this type, the type that's associated, there,
尖括号里的类型 T
or not that's associated, but
不是作为实际关联值的类型
the type of the generic type that we're talking about.
而是我们正在谈论的泛型
that "T" in an optional,
Optional 中的那个 T
is just the type that's going to be the associated value.
相当于关联值的占位符
When you look at this enum Optional,
这个枚举 Optional
it only has two cases: "none" which is "not set," and
它只有两种情况：.none，未赋值
"some" which is "set". When it's in the some case, look:
和 .some，已赋值。当它为 .some 时
"(T)". You know what that is from the calculator demo,
注意这个 (T)。从计算器示例程序中你们知道

English: 
thing". And that's probably     
okay, but by the end of next    
week you should feel very       
confident with Optionals,       
because you're gonna see that   
they are absolutely everywhere  
in iOS. Now, I mentioned        
this in the lecture but         
I wanted to show it             
to you from a code,             
kind of a code point of view,   
which is that optional          
is nothing more than an enum,   
it is fact just an enum,        
this is the enum that is an     
optional. It's a generic type,  
kind of like array, how with    
array when you say the type,    
you say the type of the thing   
you're putting in the array.    
You should all be familiar to   
that, with that from Java for   
example, same thing in Swift.   
So, with optional               
it is the same way,             
you put this type and the type  
that's associated there, or     
not that's associated, but      
the type of the generic type    
that we're talking about,       
that "T" in an optional,        
is just the type that's going   
to be the associated value.     
When you look at                
this enum Optional,             
it only has two cases: "none"   
which is "not set," and         
"some" which is "set". When     
it's in the some case, look:    
"(T)", you know what that is    
from the calculator demo,       

English: 
that's an associated value,     
just like when we had           
operation in calculator it had  
associated values, like unary   
operation had an associative    
value of a function, and        
constant had an associated      
value of the constant's value.  
Same thing here, with           
optional, in the "some" case,   
the "set" case, it just has     
an associated value, and        
it's whatever type              
the option was, so              
if this is an optional string,  
then it would be a string.      
Now what makes optional like,   
" I don't really get optional,  
what is it?", it's because of   
all those question marks and    
exclamation points. But,        
all those question marks and    
exclamation points,             
are just sugar,                 
syntactic sugar, to make your   
code look a little simpler and  
straight forward, because it's  
so common to use them. So,      
I'm going to map this           
enum to that sugar.             
Let's take a look, here's       
the first one: If I say let x:  
String?=nil, that's             
exactly the same as             

Chinese: 
that's an associated value, just like when we had
那是个关联值
operation in calculator it had associated values, like unary
就像计算器中的运算
operation had an associative value of a function, and
比如一元运算符有一个函数作为关联值
constant had an associated value of the constant's value.
常量有一个关联的常量值
Same thing here, with optional, in the "some" case,
Optional 的 .some 是一样的
the "set" case, it just has an associated value, and
已赋值的情况下，它也有一个关联值
it's whatever type the optional was, so
关联值的类型决定于可选值的类型
if this is an optional string, then it would be a string.
如果这是个可选字符串，那么关联值将会是一个字符串
Now what makes optional like, " I don't really get optional,
其实让你感到“我理解不了 Optional
what is it?", it's because of all those question marks and
Optional 到底是个啥？”的原因
exclamation points. But, all those question marks and
完全在于问号和感叹号
exclamation points, are just sugar,
但是，所有这些问号和感叹号都只是语法糖
syntactic sugar, to make your code look a little simpler and
目的是让代码看起来更简单和直观
straight forward, because it's so common to use them. So,
特别是当它们经常被使用
I'm going to map this enum to that sugar.
我把语法糖改用原本枚举的方法写出来
Let's take a look, here's the first one: If I say let x:
让我们来看看，这是第一个：如果我写
String?=nil, that's exactly the same as
let x: String? = nil，那和写

English: 
saying let x =                  
Optional.none,          
just like by saying array,      
I'd say                         
Array that would mean   
I want an array of String,      
here when I say Optional        
, that means I want     
an Optional String. And         
I'm picking the none case, and  
in just the same way, if I      
say let x = Optional=   
hello, I'm just saying x        
= Optional.some         
with associated value hello.    
Everyone got that? That's all   
that's happening there with     
the question mark thing.        
And then here is the unwrap.    
When we do that exclamation     
point all we're doing is doing  
the switch to get things out    
of an optional, so we're        
switching on the optional,      
and it's in the "Some" case,    
then we're going to grab that   
associated value just like we   
did in the calculator, and      
we say "let function" or "let   
value" to grab the associated   
value, we're saying             
"let value" here and            
it's grabbing that value        
that's associated with it.      

Chinese: 
saying let x = Optional.none,
let x = Optional.none 是完全一样的
just like by saying array, I'd say
就像数组一样
Array that would mean I want an array of String,
Array 意思是我想要一个字符串数组
here when I say Optional , that means I want
在这里当我说 Optional 时，意思是我想要
an Optional String. And I'm picking the none case, and
一个可选字符串，并且我选择了 .none
in just the same way, if I say let x = Optional=
用同样的方式，如果我写 let x: String? = "hello"
hello, I'm just saying x = Optional.some
相当于我写 let x = Optional.some("hello")
with associated value hello. Everyone got that? That's all
所有人都懂了吧？
that's happening there with the question mark thing.
这就是关于问号的全部了
And then here is the unwrap. When we do that exclamation
然后这里是解包。当我们写感叹号时
point all we're doing is doing the switch to get things out
我们只是在写一个 switch 来把 Optional 里的
of an optional, so we're switching on the optional,
内容拿出来，所以我们判断 Optional
and it's in the "Some" case, then we're going to grab that
它处于 .some 情况下，那我们就抓取那个
associated value just like we did in the calculator, and
关联值，就像我们在计算器中做的那样
we say "let function" or "let value" to grab the associated
我们用 let function 或者 let value 去抓取关联值
value, we're saying "let value" here and
在这里我们用 let value
it's grabbing that value that's associated with it.
它抓取与它相关联的那个值

Chinese: 
If it's in case none, where it's not set,
如果它处于 .none 情况下，也就是未赋值时
then it raises an exception and crashes your program,
它会抛出一个异常使你的程序崩溃
we haven't talked about how to do that, it's quite easy, but
我们还没有谈到如何做，这很简单
that's what happens here,
但这就是这里发生的事情
that's all exclamation point is, it's basically a switch.
感叹号的本质就是一个 switch
And then finally, If we do the "if let",
最后，如果我们执行 if let
"if let" is also just a switch, but
if let 也只是个 switch
in the none case of an if let, we don't raise an exception,
但是在 .none 时不会抛出异常
we just break, break out of the switch, do nothing. Okay,
只会跳出这个 switch，什么都不做
does that help you a little bit understand what optional
希望这对帮助你理解什么是 Optional 有点帮助
is? Optional is a type, it's an enum, it's just like any
Optional 是一个类型，它是个枚举，它跟其他任何类型
other type, it just has this interesting behavior, and
都一样，它只是有这些有趣的行为
it's got all the question marks and
所有的问号和感叹号
exclamation points to make all the code look a little
都是为了让代码看起来更简单一点
simpler. Now, there's even other stuff about optionals
现在有一些 Optional 的其他的
that are interesting. Optionals can be chained.
有意思的事情。Optional 可以被链接
Now what does this mean? Well, this is best shown by example.
啥意思呢？额，这最好通过一个例子来展示
So, let's say I have a Optional UILabel like my
假设我有一个类似于我的计算器中的 display
display in the calculator and it's got the text, that's also
的 Optional UILabel。而且它有 text 文本

English: 
If it's in case none,           
where it's not set,             
then it raises an exception     
and crashes your program,       
we haven't talked about how to  
do that, it's quite easy, but   
that's what happens here,       
that's all exclamation point    
is, it's basically a switch.    
And then finally,               
If we do the "if let",          
"if let" is also                
just a switch, but              
in the none case of an if let,  
we don't raise an exception,    
we just break, break out of     
the switch, do nothing. Okay,   
does that help you a little     
bit understand what optional    
is? Optional is a type, it's    
an enum, it's just like any     
other type, it just has this    
interesting behavior, and       
it's got all                    
the question marks and          
exclamation points to make      
all the code look a little      
simpler. Now, there's even      
other stuff about optionals     
that are interesting.           
Optionals can be chained.       
Now what does this mean? Well,  
this is best shown by example.  
So, let's say I have            
a Optional UILabel like my      
display in the calculator and   
it's got the text, that's also  

English: 
an optional, Optional String,   
we all know that. And           
let's say we want to get the    
hashValue which is just a var   
on string, which hashes the     
string, gives you some integer  
for it, I want to get that      
hashValue of what's in          
the display. So then I would    
probably do some code that      
looks like this, this is        
probably similar code to what   
we have in our calculator       
where I've got my display,      
that's my IBOutlet probably     
that display UILabel?, and      
I'm going go do "if let" here,  
because I don't want to crash   
so I don't want to do           
exclamation points,             
I'm going to do "if let",       
so I'm going to say "if let     
some temporary value equals     
to the display" (now temp1 is   
the UILabel), and then I say,   
"if let temp2 = temp1.text",    
I'm sending text                
to the UILabel and              
now I'm getting back a String,  
not an Optional String, but     
a String, because I did "if     
let", then I can finally say,   
then "let x = temp2",           
which is the String,            
the hashValue. Okay, this is a  
lot of code to have to type to  

Chinese: 
an optional, Optional String, we all know that. And
那也是一个 Optional，可选字符串
let's say we want to get the hashValue which is just a var
我们想得到 hashValue，也就是一个字符串的变量
on string, which hashes the string, gives you some integer
它哈希这个字符串，给你一个代表它的整数
for it, I want to get that hashValue of what's in
我想得到 display 中的字符串的 hashValue
the display. So then I would probably do some code that
所以我大概会写一些类似于
looks like this, this is probably similar code to what
这样的代码，这很可能和我们在计算器中
we have in our calculator where I've got my display,
得到我的 display 的代码很像
that's my IBOutlet probably that display UILabel?, and
那大概是我的 @IBOutlet display: UILabel?
I'm going go do "if let" here, because I don't want to crash
这里我打算用 if let，因为我不想让程序崩溃
so I don't want to do exclamation points,
所以我不想用感叹号
I'm going to do "if let", so I'm going to say "if let
我想用 if let，所以我打算写如果让
some temporary value equals to the display" (now temp1 is
一个临时变量 temp1 等于 display（现在 temp1 是
the UILabel), and then I say, "if let temp2 = temp1.text",
是 UILabel），然后我写 if let temp2 = temp1.text
I'm sending text to the UILabel and
我正在将文本发送给 UILabel
now I'm getting back a String, not an Optional String, but
现在我得到了一个字符串，不是可选字符串，而是
a String, because I did "if let", then I can finally say,
字符串，因为我用了 if let，最后我写道
then "let x = temp2", which is the String,
let x = temp2.hashValue，来获得字符串的哈希值
the hashValue. Okay, this is a lot of code to have to type to
我们写这么多代码只是为了

Chinese: 
just get that dang hashValue, out of that UILabel's text.
获得一个 UILabel 文本那该死的哈希值
With optional chaining, this same code looks like this,
用 Optional Chaining，可选链接
the first line of those two lines.
同样的代码能用第一行表示
"If let x = display?.text?.hashValue,
if let x = display?.text?.hashValue
then do something with x". In that case of course, x will
然后用 x 做一些事情。当然在这种情况下，x 不是
be a non-optional, because I'm doing if let on it.
一个 Optional，因为我用了 if let
If I take the "if" off, and just do "let x =" all that,
如果我将 if 删掉，只写 let x = 的话
then x will be an optional Int. Now, how is this working?
那么 x 将会是个 Optional Int。那么这是什么原理呢？
What's happening is that every time that you have one of
每当你在 Optional
those question marks after an Optional, it's saying,
后面加问号的时候
if this is in the set case, then grab it and keep on
如果它处于已赋值的状态，那么抓取它然后继续
going, send the next thing. If it's in the nil case, then
向后执行，发送下一个东西。如果它处于空的状态
just return nil for this whole expression, this entire line,
整个表达式将返回空，整个一行
boom, it's just gonna return nil. If I'm if letting it,
它仅仅是返回空。如果我用 if let
then obviously the code won't get executed.
那么很显然代码将不会被执行
You can do as many of these as you want in a row, and
在一行中你想写多少写多少，并且
we do this all the time, this optional chaining is going to
我们成天都在做这种事，你的代码中将会
be all over your code, and it makes perfect sense because
大量使用可选链接。并且它很容易理解

English: 
just get that dang hashValue,   
out of that UILabel's text.     
With optional chaining, this    
same code looks like this,      
the first line of               
those two lines.                
"If let x =                     
display?.text?.hashValue,       
then do something with x".      
In that case of course, x will  
be a non-optional, because      
I'm doing if let on it.         
If I take the "if" off, and     
just do "let x =" all that,     
then x will be an optional      
Int. Now, how is this working?  
What's happening is that every  
time that you have one of       
those question marks after      
an Optional, it's saying,       
if this is in the set case,     
then grab it and keep on        
going, send the next thing.     
If it's in the nil case, then   
just return nil for this whole  
expression, this entire line,   
boom, it's just gonna return    
nil. If I'm if letting it,      
then obviously the code         
won't get executed.             
You can do as many of these     
as you want in a row, and       
we do this all the time, this   
optional chaining is going to   
be all over your code, and      
it makes perfect sense because  

English: 
again, we're using this         
question mark and exclamation   
point. Here we happen to use    
the question mark when we're    
accessing it versus when we're  
declaring it. That's what it    
means to use a question mark    
when you're accessing it,       
it means go get it,             
and if it's not set,            
then just return nil from       
this whole expression,          
it will just bail out           
of the whole thing,             
It will never even execute      
hash value because we'll never  
get down to that end of it, if  
any of these things are nil.    
Another cool optional things    
we can do is optional           
defaulting. So what if we had   
wanted to put a string in our   
UI label like in our display,   
but we know that if that        
string is nil, we don't want    
to put nil in there because     
what'll happen to our label     
if we put nil in as the text?   
It'll collapse down, right,     
probably most of you saw that.  
You have to put                 
something in there,             
at least a space. So let's      
say that I want to do that,     
I want to put space in there    
if it's nil. This is the code   
that it would look like here:   
I'd have my string, I would     
say if the string is not nil,   
then put it in the display,     

Chinese: 
again, we're using this question mark and exclamation
因为问号和感叹号
point. Here we happen to use the question mark when we're
我们在访问它时会用
accessing it versus when we're declaring it. That's what it
声明的时候也会用
means to use a question mark when you're accessing it,
这就是访问它时使用问号的含义
it means go get it, and if it's not set,
它的意思是有关联值就去获取
then just return nil from this whole expression,
未赋值那么整个表达式返回空
it will just bail out of the whole thing,
它会保护整个过程
It will never even execute hash value because we'll never
如果当中任何一个为空，它甚至不会执行 hashValue
get down to that end of it, if any of these things are nil.
因为我们不会执行到底
Another cool optional things we can do is optional
我们能用 Optional 做的另一件很酷的事是
defaulting. So what if we had wanted to put a string in our
可选默认值。我们想将一个字符串放到类似于 display
UI label like in our display, but we know that if that
的 UILabel 里面，但如果我们知道那个
string is nil, we don't want to put nil in there because
字符串是空的，我们不想将它放进去
what'll happen to our label if we put nil in as the text?
如果我们将空当成文本放到 label 里面将会发生什么？
It'll collapse down, right, probably most of you saw that.
它将会崩溃，对吧，可能你们中大部分人都已经见识过了
You have to put something in there,
你必须在这里放一些东西
at least a space. So let's say that I want to do that,
至少是个空格。所以让我们来实现这个功能
I want to put space in there if it's nil. This is the code
如果为空的话我想在那儿放一个空格。代码
that it would look like here: I'd have my string, I would
看起来差不多是这样的：我有个字符串
say if the string is not nil, then put it in the display,
如果字符串不是空的，那么将它放到字符串里

Chinese: 
otherwise, if it is nil, put space in there. This looks
其他情况下，如果它为空，在这放个空格
a lot cleaner with optional defaulting, which looks like
用可选默认值的话代码会显得很简洁
this, display.text = s ?? " ". That means if s is nil, use
就像这样，display.text = s ?? " "。意思是如果 s 为空
this other thing. It's like the default in case s is nil.
就用另一个东西，也就是 s 为空时的默认值
We will use this all the time as well. Everybody got that?
我们也将会一直使用这个东西。所有人都懂了吧？
Just optional defaulting. Alright, so I bring those out
就是给可选提供默认值。好了，我提到的
of the optional world just to highlight them,
只是 Optional 的世界中想再次强调的
because there's a lot in the reading that you're doing
因为你已经阅读过很多关于 Optional 的东西了
about optional, but these are kind of the highlights.
但是这些还是需要强调的
There are a couple more things actually I'll show you later,
实际上之后还有一些我想展示给你们的东西
but basically that's it for optionals. Alright, tuples.
但这基本上就是可选的全部内容了
So I had you skip tuples in reading assignment one, but
下一个，元组。虽然在阅读任务一中跳过了
you'll be reading about them in reading assignment two.
但你们将会在任务二中读到它们
What is a tuple?
元组是什么？
A tuple is super simple, it's just a grouping of values,
元组非常简单，它只是一组值
and you can use it anywhere you're using a type. What does
你在任何使用类型地方，都可以用元组
a tuple look like? It looks like this. This var here,
元组长啥样呢？它长这个样。这里的变量
this constant, actually x, I'm setting its type to be a tuple
这个常量，就是 x，我将它的类型设置成一个元组

English: 
otherwise, if it is nil,        
put space in there. This looks  
a lot cleaner with optional     
defaulting, which looks like    
this, display.text = s That     
means if s is nil, use          
this other thing. It's like     
the default in case s is nil.   
We will use this all the time   
as well. Everybody got that?    
Just optional defaulting.       
Alright, so I bring those out   
of the optional world           
just to highlight them,         
because there's a lot in        
the reading that you're doing   
about optional, but these       
are kind of the highlights.     
There are a couple more things  
actually I'll show you later,   
but basically that's it for     
optionals. Alright, tuples.     
So I had you skip tuples in     
reading assignment one, but     
you'll be reading about them    
in reading assignment two.      
What is a tuple?                
A tuple is super simple, it's   
just a grouping of values,      
and you can use it anywhere     
you're using a type. What does  
a tuple look like? It looks     
like this. This var here,       
this constant, actually x, I'm  
setting its type to be a tuple  

Chinese: 
with a string and int and a double, that's its type. A tuple
由 String，Int 和 Double 组成，那就是它的类型
can have any number of things in there, but realistically,
一个元组内可以包含任意多的类型，但是实际上
we probably only have three or four, sometime only two, but
我们大概只会有3或4个，有时候只有俩
it can have any number. I can set x equal to parentheses,
但它可以有无穷多个。我可以使 x 等于一个圆括号
those three, any value of those three types. So here,
这三个，这三个类型的任何值。在这里
I've set it to hello, 5, and 0.85.
我将它设置为 "hello"，5 和 0.85
Now I can get the values out into individual variables by
我可以将值拿出来赋给独立的变量
saying let parentheses three different variable names equal x.
通过 let (三个不同的变量名) = x
And now it will pull out the three different values
现在它将会把这三个不同的值
into the three separate variables, word, number, and
赋给三个分开的变量，word，number 和
value. So it's kind of mirror image there,
value。它在这像一个镜像图片
you can kinda go either, either direction,
你可以向正向或反向的方向走
putting things in or out. We actually, believe it or not,
把东西放进来或拿出去。信不信由你，我们实际上
don't do it that way most of the time,
大多数时候并不这样用
because it is also possible to name the elements of a tuple.
因为命名元组中的元素也是可以的
So here, I define x, same thing, string int double, but
这里我定义的 x 也是 (String, Int, Double)
look, I've named each of them,
但看这儿，我已经命名了它们

English: 
with a string and int and       
a w, that's its type. A tuple   
can have any number of things   
in there, but realistically,    
we probably only have three or  
four, sometime only two, but    
it can have any number. I can   
set x equal to parentheses,     
those three, any value of       
those three types. So here,     
I've set it to hello,           
5, and 0.85.                    
Now I can get the values out    
into individual variables by    
saying let parentheses three    
different variable names equal  
x. And now it will pull out     
the three different values      
into the three separate         
variables, word, number, and    
value. So it's kind of          
mirror image there,             
you can kinda go either,        
either direction,               
putting things in or out. We    
actually, believe it or not,    
don't do it that way            
most of the time,               
because it is also possible to  
name the elements of a tuple.   
So here, I define x, same       
thing, string int double, but   
look, I've named each of them,  

English: 
I called the string part w,     
I called the int part i, and    
I called the double part v for  
some reason. Now, I still set   
it equal in exactly the same    
way, no difference there. But   
now I don't need to pull it     
out into separate variables.    
I can just say x.w and get the  
w, the first component of it.   
You see that? This is how       
we do tuples, with names.       
I strongly recommend            
you almost always use           
names with tuples. It's just    
a little easier to read,        
clearer to say what your        
intent is as a programmer.      
Because those names             
of the parts of the tuple can   
have good variable names.       
You're gonna see in your        
programming assignment number   
2, I'm gonna have you write a   
function that returns a tuple,  
and it's going to specify the   
names of the parts. Now even    
if you name them, like we       
have x with the named ones,     
you can still do that thing     
where you just say, let (word,  
num, val) equal x, and          
it'll still pull it out into    
individual ones, so naming      
them doesn't stop you from      
pulling them out by individual  
variable, if you want.          

Chinese: 
I called the string part w, I called the int part i, and
我把 String 部分叫做 w，把 Int 部分叫做 i
I called the double part v for some reason. Now, I still set
把 Double 部分叫做 v。现在我仍然用和刚才
it equal in exactly the same way, no difference there. But
一样的方法给它赋值，没什么不同。但是
now I don't need to pull it out into separate variables.
现在我不需要将其拉出到单独的变量中
I can just say x.w and get the w, the first component of it.
我可以只写 x.w 来得到 w，也就是它的第一部分
You see that? This is how we do tuples, with names.
看懂了吧？这就是通过命名来使用元组的方法
I strongly recommend you almost always use
我强烈推荐你在几乎任何情况下都用
names with tuples. It's just a little easier to read,
命名的方法使用元组。它使代码读起来更简单
clearer to say what your intent is as a programmer.
作为一个程序员更清楚地表明你的意图
Because those names
因为元组中
of the parts of the tuple can have good variable names.
每个部分都可以有很好的变量名
You're gonna see in your programming assignment number
你们将会在编程任务二中看到
2, I'm gonna have you write a function that returns a tuple,
我将让你们写一个返回元组的函数
and it's going to specify the names of the parts. Now even
并且元组的部分必须具体命名。现在即便
if you name them, like we have x with the named ones,
你已经命名了他们，就像我们用 x 命名他们
you can still do that thing where you just say, let (word,
你依然可以用 let (word,
num, val) equal x, and it'll still pull it out into
num, val) = x，它依然会将其拉出到
individual ones, so naming them doesn't stop you from
单独的变量中，所以命名他们不会阻止你
pulling them out by individual variable, if you want.
将其拉出到单独的变量中，如果你想这么做的话

Chinese: 
Also, in tuples, you can always put underbar for
还有，在元组中，你无论何时都可以在
any of the names, like here I could say let word_ val or
任何地方放下划线，就像这里我可以写
let word,_, val equal x, and then I would get word and
let (word, _, val) = x，这样我可以得到 word 和
val into individual variables, and I would just ignore that
val 的值，无视掉中间那个
middle one. Underbar in Swift always kinda means ignore
划线在 Swift 中意味着无视它
that, I'm not interested in that particular thing.
我不在乎它的细节
We've already seen this with function parameters when we
我们已经在当我们想无视函数参数
want to ignore the external name of a function parameter.
的外部变量名时见过它了
Alright, so using tuples that return values,
好了，用元组返回数据
like I said, you're gonna see this in the homework.
就像我写的这样，你们将会在作业中看到这个
Nothing special here. It's a type like any other type, so
没啥特别的东西。它跟其他任何一种类型都一样，所以
it can be the return type of a function. So, this is how you
它可以作为函数的返回类型。所以，这就是你们让
can have a function that returns multiple values.
一个函数返回多个值的方法
In some languages, it's very difficult to do this.
在某些语言中，这一点很难做到
You have to create a structure or something to return.
你必须创建一个结构体或其他东西来返回
However, it's very, very, very easy in Swift.
然而，在 Swift 中这非常简单
You literally just do this. And
你真的只需要用元组
when you get the value that comes back from that function,
并且当你函数的返回值时
you just access the elements by name. Notice that when I
你可以用名字来访问元素。注意在代码中的 getSize()

English: 
Also, in tuples, you can        
always put underbar for         
any of the names, like here I   
could say let word_ val or      
let word,_, val equal x, and    
then I would get word and       
val into individual variables,  
and I would just ignore that    
middle one. Underbar in Swift   
always kinda means ignore       
that, I'm not interested        
in that particular thing.       
We've already seen this with    
function parameters when we     
want to ignore the external     
name of a function parameter.   
Alright, so using tuples        
that return values,             
like I said, you're gonna       
see this in the homework.       
Nothing special here. It's      
a type like any other type, so  
it can be the return type of a  
function. So, this is how you   
can have a function that        
returns multiple values.        
In some languages, it's         
very difficult to do this.      
You have to create a structure  
or something to return.         
However, it's very, very,       
very easy in Swift.             
You literally just do this.     
And                             
when you get the value that     
comes back from that function,  
you just access the elements    
by name. Notice that when I     

Chinese: 
returned it in my code there in getSize, I didn't have to
当我返回它时，我不需要
give the names; I could if I wanted to,
把名字带上；如果我想我也可以带上
I could have said return weight:150, height:, but
我可以写 return (weight: 150, height: xxx)
I decided, eh, I'm just gonna return the values. Okay,
但是我决定，额，我只想返回数值
another thing: range, range is an important little
另一个内容：Range。Range 是 Swift 中重要的
struct in Swift: all that it represents is two end points.
结构体：它代表两个端点
So a range is useful for, for example, a selection of text,
所以举个例子， Range 适用于文本的选择
where the selection starts and where the selection ends.
选择开始的地方和选择结束的地方
It's also good for a sub-slice of an array. If you've got
它也很适合分割一个数组。如果你有一个
array of 100 elements, you might want the 15th to
有100个元素的数组，你可能想要其中从第15个到
the 40th one, so you could specify that range, 15 to 40.
第40个这一段，你可以写一个 Range，从15到40
So range is this really simple little struct, which kind of
所以 Range 是个很简单的结构体，看起来
looks like this. I say kind of, because it's a little more
就像这样。我说“像”，因为它比这还更
complicated than this, but it basically looks like this.
复杂一点，但它看起来大概就是这样的
It's a generic type like array because of course, you can
这是个像数组的泛型，因为当然，你可以
have a range of ints. You could have a range of floats.
有一个整数的 Range。你可以有一个浮点数的 Range
You could have a range of strings even. Okay, so
你甚至可以有一个字符串的 Range
that T right there could be float, float, int,
所以那个 T 可以是浮点数，整数，字符串

English: 
returned it in my code there    
in getSize, I didn't have to    
give the names; I               
could if I wanted to,           
I could have said return        
weight:150, height:, but        
I decided, eh, I'm just gonna   
return the values. Okay,        
another thing: range,           
range is an important little    
struct in Swift: all that it    
represents is two end points.   
So a range is useful for, for   
example, a selection of text,   
where the selection starts and  
where the selection ends.       
It's also good for a sub-slice  
of an array. If you've got      
array of 100 elements,          
you might want the 15th to      
the 40th one, so you could      
specify that range, 15 to 40.   
So range is this really simple  
little struct, which kind of    
looks like this. I say kind     
of, because it's a little more  
complicated than this, but      
it basically looks like this.   
It's a generic type like array  
because of course, you can      
have a range of ints. You       
could have a range of floats.   
You could have a range of       
strings even. Okay, so          
that T right there could        
be float, float, int,           

Chinese: 
string. T is restricted a little bit, and I haven't
T 有一些限制，我还没有
really talked about how you restrict a generic type.
真正讲到如何限制一个泛型
But that T is restricted,
但这个 T 被限制了
and it has to be what's called comparable. That's because
它必须是 Comparable，可比较的
range needs to make sure that the start index is less than
那是因为 Range 需要确保起点小于终点
the end index. That's part of what a range is defined to be.
这是 Range 定义的一部分
So that T has to be something that can be compared
所以 T 必须是可以比较的东西
to see if the start index is less than the end index,
查看开始端点是否小于终止端点
minor thing there. So, for example, a range of int
这是个细节。所以，举个例子，整数的 Range
would be great for specifying a range in an array,
很适合具体说明数组中的 Range
cuz an array is indexed by integers, right, starting at 0
因为数组的下标是整数，对吧
and going up to the number of things in the array.
从 0 开始，一直到小于数组长度的整数
Now there are other more powerful, more capable ranges,
还有一些更强大，更好用的 Range
like CountableRange. A CountableRange is
例如 CountableRange，也是个 Range
just like a range, except for that you can count through
但特别之处在于你可以通过
intermediate values between the start and the end.
起始端点和终止端点的中间的值计数
Okay, it's like a range of ints. A CountableRange means
它看起来就像整数的 Range
the begin point and end point and one point each.
CountableRange 包含了起点，终点，以及中间每个点
Now as you stride through that range, it depends on what
遍历 Range 的过程因值的具体类型而不同

English: 
string. T is restricted         
a little bit, and I haven't     
really talked about how you     
restrict a generic type.        
But that T is restricted,       
and it has to be what's called  
comparable. That's because      
range needs to make sure that   
the start index is less than    
the end index. That's part of   
what a range is defined to be.  
So that T has to be something   
that can be compared            
to see if the start index       
is less than the end index,     
minor thing there. So, for      
example, a range of int         
would be great for specifying   
a range in an array,            
cuz an array is indexed by      
integers, right, starting at 0  
and going up to the number      
of things in the array.         
Now there are other more        
powerful, more capable ranges,  
like CountableRange.            
A CountableRange is             
just like a range, except for   
that you can count through      
intermediate values between     
the start and the end.          
Okay, it's like a range of      
ints. A CountableRange means    
the begin point and             
end point and one point each.   
Now as you stride through that  
range, it depends on what       

Chinese: 
the type is. Striding through a range of ints is different
遍历整数 Range 和
then striding through a range of floats, or striding through
遍历浮点数
a range of strings. There's a little difference there, and
或者是字符串的 Range 都不同
we'll talk about that in a minute.
具体不同之处，我很快会讲到
There's a special syntax for
Range 的有个特别的语法
doing range, which is "dot dot less-than" or "dot dot dot".
也就是 ..< 或者 ...
Dot Dot Less-than means that you put the start index and
..< 的用法是你将开始点
the end index on either side of the dot dot less than.
与终止点放到 ..< 的两侧
And that means go from the start index to the end index,
那意味着从开始点到终止点
but don't include the end index, not inclusive of it,
但不包括终止点，不包括它
and the dot dot dot includes both ends. So for
... 同时包括两个端点
example, in an array, let's have an array of four strings,
举个例子，在数组中，有四个字符串
a, b, c, d, and let's say that I want to get the c and
a b c d。假设我想把 c 和
the d out of there, I can say array sub, (just
d 拿出来，我可以写 array[]
like how I can say array sub 5 or array sub 3 is the fourth
就像我可以写 array[5]，或 array[3]（数组中第四个）
index of the array), I can also specify a range and
我也可以写一个 Range 作为下标
get a sub array, a slice of the array, it's called. So
来得到一个子数组，也就是数组中的一部分
I can say 2...3, which means index 2 in the array,
我可以写 2...3，意思是数组中第三个元素

English: 
the type is. Striding through   
a range of ints is different    
then striding through a range   
of floats, or striding through  
a range of strings. There's     
a little difference there, and  
we'll talk about                
that in a minute.               
There's a special syntax for    
doing range, which is "dot dot  
less-than" or "dot dot dot".    
Dot Dot Less-than means that    
you put the start index and     
the end index on either side    
of the dot dot less than.       
And that means go from the      
start index to the end index,   
but don't include the end       
index, not inclusive of it,     
and the dot dot dot             
includes both ends. So for      
example, in an array, let's     
have an array of four strings,  
a, b, c, d, and let's say       
that I want to get the c and    
the d out of there,             
I can say array sub, ( just     
like how I can say array sub 5  
or array sub 3 is the fourth    
index of the array),            
I can also specify a range and  
get a sub array, a slice of     
the array, it's called. So      
I can say 2...3, which          
means index 2 in the array,     

Chinese: 
which is c because a is index 0, b is index 1, c is index 2,
也就是 c，因为 a 是[0]，b是[1]，c是[2]
dot dot dot index 3, which is the d inclusive, cuz it's dot
...3，也就包括了 d，因为 ... 是闭区间
dot dot. And then the less than 1 would be exclusive,
有小于号的那个是不包括的
so that's why the d wouldn't be included in that one. So
所以这就是为什么在这一个 d 不会被包括
see how I'm using a range to get a sub slice of an array,
我使用 Range 来得到数组的一部分的方法
that's kind of cool. By the way,
很酷吧。顺带一提
if you say give me the array from 6...8,
如果你写给我这个数组的 6...8
that's going to crash at run time with an array index out
在运行时将会崩溃，因为数组下标
of bounds because this array only has four elements. So
越界，因为这个数组只有四个元素。所以
just because I'm accessing this subscripting with a range
即便是用 Range 而非数字来访问下标时
instead of with a number, it still has to be in bounds.
它依然需要在边界之内
And then if I say array[4...1],
然后如果我写 array[4...1]
that also will crash at run time, because the range
运行时一样会崩溃，因为 Range
is going to look at that and say I can't create a range
会看着它说我不能创建一个
where the start value is greater than the end value,
开始点大于终止点的 Range
can't be a backwards range, that's why that type like
Range 不能是前后颠倒的。因此必须是可比较的
int has to be comparable, of course you can compare ints.
类似于整数那样的（当然你可以比较整数）
One thing very important to understand: a string,
注意，理解一件事非常重要

English: 
which is c because a is index   
0, b is index 1, c is index 2,  
dot dot dot index 3, which is   
the d inclusive, cuz it's dot   
dot dot. And then the less      
than 1 would be exclusive,      
so that's why the d wouldn't    
be included in that one. So     
see how I'm using a range to    
get a sub slice of an array,    
that's kind of cool.            
By the way,                     
if you say give me              
the array from 6...8,           
that's going to crash at run    
time with an array index out    
of bounds because this array    
only has four elements. So      
just because I'm accessing      
this subscripting with a range  
instead of with a number,       
it still has to be in bounds.   
And then if I say               
array[4...1],                   
that also will crash at run     
time, because the range         
is going to look at that and    
say I can't create a range      
where the start value is        
greater than the end value,     
can't be a backwards range,     
that's why that type like       
int has to be comparable, of    
course you can compare ints.    
One thing very important        
to understand: a string,        

Chinese: 
a subrange of a string is not a range of ints.
获取字符串的子串不是通过整数 Range
You might think it is, right, I've got this string,
你们可能觉得是，我得到了这个字符串
100 characters, you might think strings sub 15 to 40
有 100 个字符，你可能会想 string[15..<40]
would be the 15th character to the 40th. And
就是从第 15 个字符到第 40 个
it's not: a string subrange is a range of string.index,
但并不是：字符串的子串是 String.Index 的 Range
which is a different little data type, and
是个稍微有点不同的数据类型
I'm going to talk all about that in a few slides.
我将会在接下来的幻灯片中讲到它
But I just want to make it really clear,
我只想说明一点
that it is possible to say string subrange start..<end,
写 string[start..<end] 是可以的
but start and end are not ints, they're string.indexes,
但是 start 和 end 不是整数，他们是 String.Index
and we'll see how that works. If the type
我们将会看到它是如何工作的。如果你用 ..<
of the range that you create with dot dot less than or
或者 ... 创建的 Range 的类型
dot dot dot, if that type is an int, (actually,
如果那个类型是整数
if it's strideable by int, they can be strided by int so
也就可以作为整数遍历的
it's not gonna be float, but I'm not really prepared to
那自然不会是浮点数。但我还没准备好
talk to you about strideable), but if the range has
给你们讲 Strideable。总之如果 Range 的
ints on either end, so it's a range from 2 to 7, for
任意一个端点是整数，例如一个从 2 到 7 的 Range

English: 
a subrange of a string          
is not a range of ints.         
You might think it is,          
right, I've got this string,    
100 characters, you might       
think strings sub 15 to 40      
would be the 15th               
character to the 40th. And      
it's not: a string subrange     
is a range of string.index,     
which is a different            
little data type, and           
I'm going to talk all about     
that in a few slides.           
But I just want to              
make it really clear,           
that it is possible to say      
string subrange start..<end,    
but start and end are not       
ints, they're string.indexes,   
and we'll see how that works.   
If the type                     
of the range that you create    
with dot dot less than or       
dot dot dot, if that type       
is an int, (actually,           
if it's strideable by int,      
they can be strided by int so   
it's not gonna be float, but    
I'm not really prepared to      
talk to you about strideable),  
but if the range has            
ints on either end, so          
it's a range from 2 to 7, for   

Chinese: 
example, then it automatically creates that countable range,
它会自动创建为一个 CountableRange
that more capable range.
那个更好用的 Range
That range then becomes what's called a sequence, And
那个 Range 之后会变成一个叫做 Sequence（序列）的东西
sequences can be iterated through or enumerated, and
Sequence 可以被迭代或者罗列
the way you do that is with "for in", so Swift's for
实现方法是用 for in 语句
statement, this is the only one there is. It's called
也就是 Swift 中唯一的 for 语句
"for in" and all it ever means is, I want to go and enumerate
for in 的意思是，我想要遍历这个 Sequence
all the values of a sequence. I'm going to talk about what
中所有的值。我打算讲讲什么东西
things that can be sequenced. Countable range is 1,
可以成为 Sequence。CountableRange 可以
because if an int goes from 0 to 7, and
比如 0 到 7 的整数 CountableRange
it's a countable range, then it can go 0, 1, 2, 3, 4, 5, 6,
自然可以遍历 0 1 2 3 4 5 6 7
7. Arrays are sequences, sequences of their elements.
数组是 Sequence，由它元素构成的序列
So you can "for in" through an array. Dictionaries are also,
所以你可以用 for in 遍历一个数组。字典也可以
and we'll see that a little later. So here's how you do
过一会儿我们就会看到。这相当于 C 语言
a normal C-like for loop, for (i = 0; i < 20; i++).
for (i = 0; i < 20; i++) 这个 for 循环语句
You cannot do that in Swift, that syntax simply doesn't
你在 Swift 中不能这样写，这个语法已经

English: 
example, then it automatically  
creates that countable range,   
that more capable range.        
That range then becomes         
what's called a sequence, And   
sequences can be iterated       
through or enumerated, and      
the way you do that is with     
"for in", so Swift's for        
statement, this is the only     
one there is. It's called       
"for in" and all it ever means  
is, I want to go and enumerate  
all the values of a sequence.   
I'm going to talk about what    
things that can be sequenced.   
Countable range is 1,           
because if an int               
goes from 0 to 7, and           
it's a countable range, then    
it can go 0, 1, 2, 3, 4, 5, 6,  
7. Arrays are sequences,        
sequences of their elements.    
So you can "for in" through an  
array. Dictionaries are also,   
and we'll see that a little     
later. So here's how you do     
a normal C-like for loop,       
for (i = 0; i < 20; i++).       
You cannot do that in Swift,    
that syntax simply doesn't      

Chinese: 
exist. Instead you would say for i in the range 0..<20,
不存在了。作为替代你应该写 for i in 0..<20
because notice I said it's less than 20, not less than or
注意我写的是小于 20，不是小于或
equal to 20, so 0..<20 means go through that. And so
等于 20，所以 0..<20 意思是遍历它
that little block of code is going to be executed once for
这一小块儿代码将被执行
0, 1, 2, 3, 4, all the way up to number 19, so
0 1 2 3 4 直到 19
that's same thing as what you see there.
那和你们在那里看到的一样
Now what about floats? Floats are a little weird.
那浮点数呢？浮点数稍微有点奇怪
What if I wanted to do for (i = 0.5; i <= 15.25; i += 0.3).
我该如何实现 for (i = 0.5; i <= 15.25; i+=0.3)
Whoa, how am I gonna do that? I can't, for
噫，我该咋办呢？我不能写
example, say for i in 0.5...15.25.
for i in 0.5...15.25
How does it know to go by 0.3? And the answer is, it doesn't.
它怎么知道每次加 0.3 呢？答案是，不能
In fact, a range like that, 0.5...15.25 is not a countable
事实上，像 0.5...15.25 这样的只是 Range
range, it's just range. It only knows the start and end,
不是 CountableRange，它只知道起点与终点
it knows nothing about what's in between, so
它对中间一无所知，所以
it cannot be a sequence, it can't be for in over. But
它不能作为一个序列遍历

English: 
exist. Instead you would say    
for i in the range 0..<20,      
because notice I said it's      
less than 20, not less than or  
equal to 20, so 0..<20 means    
go through that. And so         
that little block of code is    
going to be executed once for   
0, 1, 2, 3, 4, all the way      
up to number 19, so             
that's same thing as            
what you see there.             
Now what about floats?          
Floats are a little weird.      
What if I wanted to do for{i    
= 0.5; i <= 15.25; i += 0.}.    
Whoa, how am I gonna do that?   
I can't, for                    
example, say for                
i in 0.5...15.25.               
How does it know to go by 0.3?  
And the answer is, it doesn't.  
In fact, a range like that,     
0.5...15.25 is not a countable  
range, it's just range. It      
only knows the start and end,   
it knows nothing about          
what's in between, so           
it cannot be a sequence,        
it can't be for in over. But    

Chinese: 
luckily, there's this great global function called stride.
幸运的是，有一个叫做 stride 的全局函数
Stride takes a from and a to, or a through,
stride 接受一个 from，和一个 through 或者 to
(depending whether you wanna go through to the end,
取决于你是想遍历到最后
or just to to and not including it), and
还是仅仅是到那儿但不包括它
a by, which is, what it's going to step by.
和一个 by，意思是，每一步加上的数值大小
So here, I say stride from 0.5 through 15.25,
所以在这，我写 stride(from: 0.5, through: 15.25
because I want less than or equal to, by 0.3, and
因为我想小于或等于，by: 0.3)
that's gonna create a new object, it's a CountableRange.
那会创建一个新对象，它是个 CountableRange
Now it's a special CountableRange, it knows
它是一个特别的 CountableRange，它知道
how to count from 0.5 to 15.25 by that 0.3 step. You
如何从 0.5 每隔 0.3 数到 15.25
don't need to worry about how it implements it, Stride just
你不需要关心它是如何实现的，stride 只是
creates you a CountableRange. Actually this will be called
给你创建了个 CountableRange。实际上它被称作
a ClosedCountableRange because it counts through to the end,
ClosedCountableRange，因为它遍历到最后
so it's a dot dot dot kind of range instead of a dot dot
所以它是个 ... 类的 Range，而不是 ..<
less than kind of range. So I have a CountableRange, and
所以我有了 CountableRange，并且
it's a sequence, so I can for in it, so I say for i in.
它是个序列，所以能用 for in 了：for i in
Stride, I'd probably say for f in, or even better than f or
stride，我可能会用 for f in，或者比 f 或 i 更好的名字
i. A lot of times, by the way, on my slides, I'm gonna use
顺带一提，为了放进幻灯片里
variables like i or x or d because I want it to fit on my
我会用类似 i 或 x 的变量名

English: 
luckily, there's this great     
global function called stride.  
Stride takes a from and         
a to, or a through,             
(depending whether you wanna    
go through to the end,          
or just to to and               
not including it), and          
a by, which is,                 
what it's going to step by.     
So here, I say stride           
from 0.5 through 15.25,         
because I want less than or     
equal to, by 0.3, and           
that's gonna create a new       
object, it's a CountableRange.  
Now it's a special              
CountableRange, it knows        
how to count from 0.25 to       
15.25 by that 0.3 step. You     
don't need to worry about how   
it implements it, Stride just   
creates you a CountableRange.   
Actually this will be called    
a ClosedCountableRange because  
it counts through to the end,   
so it's a dot dot dot kind      
of range of a dot dot           
less than kind of range. So     
I have a CountableRange, and    
it's a sequence, so I can for   
in it, so I say for i in.       
Stride, I'd probably say for    
f in, or even better than f or  
i. A lot of times, by the way,  
on my slides, I'm gonna use     
variables like i or x or d      
because I want it to fit on my  

Chinese: 
slide, I don't want it to be wrapping. It's hard for you to
我不想让代码被换行。如果幻灯片上的代码
read the slide if the code's always wrapping around, so
到处都在换行你们读起来会很难受，所以
just because you see me using i and d and f doesn't mean
你们不要因为看到我用 i 和 d 还有 f
that's license to have those kind of terrible names for
就以为可以给你们的变量起这么
your variables. You need to have meaningful names. So
糟糕的名字。你需要起有意义的名字。所以
that's how for in works here,
for in 就是这样用的
because stride is gonna return a CountableRange,
因为 stride 会返回一个 CountableRange
ClosedCountableRange in this case. So
在这种情况下是 CloseCountableRange
that's how you do your standard for loops from C.
这就是实现 C 中的标准 for 循环的方法
Alright, let's talk about the data structures in Swift.
好了，让我们谈谈 Swift 中的数据结构
You've already learned about three of the four of them,
你们已经学了它们四个中的三个了
which are classes, structures, and enums. In our lecture,
分别是类，结构体，枚举。在课上
we already did all three of those things.
这三种东西我们都做过了
We had a class, which is our view controller subclass.
我们做过类，就是我们的 ViewController 的子类
We had a struct, which is our calculator brain.
我们做过结构体，就是我们的 CalculatorBrain
And we had enum, which was our operation.
并且还做过枚举，就是我们的 Operation
The fourth one is protocols, and
第四个是 protocol，协议
I'm not gonna talk about that until next week or
直到下个星期或者下个星期之后
even the week after. Protocols are super, duper important,
我才会讲到它。协议是非常重要的
I don't want to make it sound like they're not important,
我不想让它们听起来似乎它们不重要的样子
But they're new to a lot of you, and so I'm gonna try and
但它对于你们大部分人来说是十分陌生的，所以我觉得

English: 
slide, I don't want it to be    
wrapping. It's hard for you to  
read the slide if the code's    
always wrapping around, so      
just because you see me using   
i and d and f doesn't mean      
that's license to have those    
kind of terrible names for      
your variables. You need to     
have meaningful names. So       
that's how for in works here,   
because stride is gonna         
return a CountableRange,        
ClosedCountableRange in         
this case. So                   
that's how you do your          
standard for loops from C.      
Alright, let's talk about       
the data structures in Swift.   
You've already learned about    
three of the four of them,      
which are classes, structures,  
and enums. In our lecture,      
we already did all              
three of those things.          
We had a class, which is our    
view controller subclass.       
We had a struct,                
which is our calculator brain.  
And we had enum,                
which was our operation.        
The fourth one is protocols,    
and                             
I'm not gonna talk about        
that until next week or         
even the week after. Protocols  
are super, duper important,     
I don't want to make it sound   
like they're not important,     
But they're new to a lot of     
you, and so I'm gonna try and   

Chinese: 
ease you in with these ones that are more familiar,
先介绍你们更熟悉的这三个
although different in Swift probably than what you're used
尽管在 Swift 中或多或少有些不同
to, they're still more familiar to you.
但相较而言你还是更熟悉它们的
Let's just review quickly these three structs and what's
这里我们就快速复习一下这三块儿内容以及他们的
the same and different about them. So what's the same?
相同点与不同点。所以相同点是啥呢？
They're declared very,
它们的声明非常
very similar: they have different key word, but
非常相似：它们有不同的关键字，但
they're almost exactly the same.
它们几乎是相同的
The only difference really is a class can specify a super
唯一的不同是类可以指明它的父类
class, otherwise they're declared exactly the same.
除此之外他们的声明完全相同
They can all have properties and functions, So,
它们都可以有属性和函数，因此
they're all very similar in that way. The only thing here
如此看来它们都非常相似。唯一一件事
is that there cannot be any stored properties in an enum.
就是枚举中不能有储存属性
Enum keeps any data it has in associated values, so it can't
枚举把它的数据保存在关联值中，所以它不能
have any stored properties, but it can have computed
有任何储存属性，但是它可以有计算
properties and they certainly all can have functions.
属性并且它们当然都可以有函数
Another thing that's very similar is they can all
还有很相似的一点是除了枚举它们
have initializers except enums. Enums don't need
都能初始化。枚举（注：一般）不需要
an initializer cuz you just say the case you want, but
因为你可以直接说明你想要的情况
structs and classes have initializers. Okay, so
结构体和类一般都有初始化
that's the same. Now what are the differences?
这就是相同点。不同点是啥呢？

English: 
ease you in with these ones     
that are more familiar,         
although different in Swift     
probably than what you're used  
to, they're still               
more familiar to you.           
Let's just review quickly       
these three structs and what's  
the same and different about    
them. So what's the same?       
They're declared very,          
very similar: they have         
different key word, but         
they're almost                  
exactly the same.               
The only difference really is   
a class can specify a super     
class, otherwise they're        
declared exactly the same.      
They can all have properties    
and functions, So,              
they're all very similar in     
that way. The only thing here   
is that there cannot be any     
stored properties in an enum.   
Enum keeps any data it has in   
associated values, so it can't  
have any stored properties,     
but it can have computed        
properties and they certainly   
all can have functions.         
Another thing that's very       
similar is they can all         
have initializers except        
enums. Enums don't need         
an initializer cuz you just     
say the case you want, but      
structs and classes have        
initializers. Okay, so          
that's the same.                
Now what are the differences?   

Chinese: 
Well of course, inheritance is a big difference for classes.
当然了，继承是类的一个很大的不同点
Classes have inheritance. Structs and enums do not. But
类有继承，结构体和枚举没有。但是
the most important difference, which I mentioned last time,
最主要的不同点，是我上次提到的
is that structs and enums are value types, and
就是结构体和枚举是值类型
classes are reference types. So let's go into that and talk
而类是引用类型。让我们深入讲解
about it just a little more. It's so important, I'm gonna
一下这个问题。这很重要，我打算
talk about it again. A value type, what does that mean?
把它再讲一遍。值类型是什么意思？
It means that it's copied when you pass it as an argument
它的意思是当你把它作为参数传送它时它被复制了
It's copied, even if you just assign it to another variable,
甚至如果你仅仅是把它
to a function.
分配给其他变量或是函数都会拷贝
it gets copied. If you assign it to a let, it's immutable,
如果将它分配给一个 let，它是不可改变的
that's very important to understand. If you assigned
理解这一点很重要。如果你分配
a value type to a let, using let x equal that thing,
一个值类型给 let，用 let x = 那个东西
you just made it immutable, no matter how complicated it is.
不管它有多复杂，你已经使它不可改变了
If it's an array or dictionary,
如果它是个数组或字典
you can't add any elements. If it's a calculatorBrain,
你不能增加任何元素。如果它是 CalculatorBrain
it means you can't call any of its mutable functions, So
你将不能调用它的任何可变的函数，所以
you can't do perform operation on it. Now in assignment two,
你不能对它进行操作。在任务二中
I'm gonna have you add a method to the calculator brain
我打算让你们给 CalculatorBrain 增加一个方法

English: 
Well of course, inheritance is  
a big difference for classes.   
Classes have inheritance.       
Structs and enums do not. But   
the most important difference,  
which I mentioned last time,    
is that structs and             
enums are value types, and      
classes are reference types.    
So let's go into that and talk  
about it just a little more.    
It's so important, I'm gonna    
talk about it again. A value    
type, what does that mean?      
It means that it's copied when  
you pass it as an argument      
It's copied, even if you just   
assign it to another variable,  
to a function.                  
it gets copied. If you assign   
it to a let, it's immutable,    
that's very important to        
understand. If you assigned     
a value type to a let,          
using let x equal that thing,   
you just made it immutable, No  
matter how complicated it is.   
If it's an array or             
dictionary,                     
you can't add any elements.     
If it's a calculatorBrain,      
it means you can't call any     
of its mutable functions, So    
you can't do perform operation  
on it. Now in assignment two,   
I'm gonna have you add a        
method to the calculator brain  

English: 
that is gonna let you use       
the calculator brain when it's  
immutable, which is kinda       
cool. You still wouldn't be     
able to perform operation but   
you can be able to something    
very important, immutably. Now  
because of this, this kind of   
copyright-on-write behavior     
of value types, you must,       
of course, mark all the         
functions that are going to     
modify it as mutating. And      
that's how the Swift knows,     
"Oops, I've gotta make a copy   
of this, an actual real copy,   
if someone writes to it". Now   
a reference class is pretty     
different in that it gets       
stored in the heap somewhere    
with a pointer to it, and       
when you pass it around to      
a function or to assign it to   
another variable or something   
like that, you're just passing  
a pointer around to it.         
Now, by the way, when you say,  
let x equal a reference type,   
you can still send it           
messages that will mutate it.   
All you're saying is            
the pointer can't change, but   

Chinese: 
that is gonna let you use the calculator brain when it's
那使你们在当 CalculatorBrain 是不可改变的时候
immutable, which is kinda cool. You still wouldn't be
使用它，这很酷。你依然不能
able to perform operation but you can be able to something
操作它但是你可以做一些重要的
very important, immutably. Now because of this, this kind of
不改变就能完成的事情。因此，为了实现值类型的
copy-on-write behavior of value types, you must,
写入时复制的行为，你必须
of course, mark all the functions that are going to
标记所有改变值的函数为 mutating
modify it as mutating. And that's how the Swift knows,
这是为了 Swift 知道
"Oops, I've gotta make a copy of this, an actual real copy,
“哦，我需要实际拷贝它，得到一个真正的副本
if someone writes to it". Now a reference class is pretty
如果有人往它里面写数据的话。”引用类型是很
different in that it gets stored in the heap somewhere
不同的，它被储存在一个堆中
with a pointer to it, and when you pass it around to
有一个指针指向它，当你把它传送到
a function or to assign it to another variable or something
函数中或将它分配给另一个变量之类的东西时
like that, you're just passing a pointer around to it.
你只是在传送指向它的指针
Now, by the way, when you say, let x equal a reference type,
现在，顺带一提，当你写 let x = 一个引用类型时
you can still send it messages that will mutate it.
你依然可以给它发送使它转变的信息
All you're saying is the pointer can't change, but
虽然指针是不能改变的，但是

Chinese: 
what it points to can always be changed.
指针指向的东西在任何时候都能改变
Now reference types are what you're used to.
引用类型是你们习惯的
Most languages that have object-oriented reference
大部分语言都有面向对象的引用类型
types. Reference types are a little bit Wild West- I
引用类型有点狂野
don't have time to teach you this, I hope you'll get to see
我没时间给你们讲这个，我希望你们
this sometime in your career at Stanford, but
在斯坦福的时光里可以接触它
there is a different way of thinking about programming
还有一种不同的编程思想，它与你们之前
than you're used to: it's called functional programming.
接触到的不同：它叫做函数式编程
How many people have heard the phrase,
有多少人曾经听说过这个词
functional programming? So about half of you. The idea
函数式编程？有一半左右。函数式编程
of functional programming is: you don't want this Wild West
的思想是：你不想要这样的狂野
where you've got these objects with multiple people pointing
你有这些有多人指向它们的对象
at them, any of whom could modify it at any time.
它们中任何一个在任何时间都能修改它
That leaves you open to a lot of difficulty in verifying
这给你核实你的程序的正确性
the correctness of your program.
带来了不小的困难
Whereas if you have a lot of objects that are immutable,
然而如果你有一大堆不可改变的对象
you know they can't change, and their APIs are basically
你知道它们不可能被改变，并且它们的 API 基本上
like mathematical functions where data goes in and
类似于数学函数，数据输入后
predictable data comes out, because there's
可预计的数据输出
not all this side-effecting, data-effecting other objects
因为不会受到其它的数据影响

English: 
what it points to can           
always be changed.              
Now reference types             
are what you're used to.        
Most languages that have        
object-oriented reference       
types. Reference types          
are a little bit Wild West- I   
don't have time to teach you    
this, I hope you'll get to see  
this sometime in your           
career at Stanford, but         
there is a different way of     
thinking about programming      
than you're used to: it's       
called functional programming.  
How many people have            
heard the phrase,               
functional programming?         
So about half of you. The idea  
of functional programming is:   
you don't want this Wild West   
where you've got these objects  
with multiple people pointing   
at them, any of whom could      
modify it at any time.          
That leaves you open to a lot   
of difficulty in verifying      
the correctness                 
of your program.                
Whereas if you have a lot of    
objects that are immutable,     
you know they can't change,     
and their APIs are basically    
like mathematical functions     
where data goes in and          
predictable data comes out,     
because there's                 
not all this side-effecting,    
data-effecting other objects    

Chinese: 
that someone else is pointing to in all this.
也不会存在被多个指针引用的情况
It's this really well-contained little thing.
这是个非常好的东西
Now iOS was not developed with functional programming in mind
iOS 完全不是按函数式编程开发的
at all. But the people who invented Swift,
但是发明 Swift 的这群人
they were thinking about functional programming, So
它们考虑到了函数式编程，所以
you can kind of mix a lot of the elements of
如果你正在开发一款 iOS 应用程序
functional programming into your application,
你可以把函数式编程的元素
if you're building an iOS application. Now that's a new
混合到你的应用程序中
frontier in iOS, because for however long, 20 years,
这属于开发 iOS 的前沿思想，因为过去 20 年
really, or 30 years, really, if you consider all the way
或者是 30 年，如果把给 iOS
back to the invention of the technology that led to iOS,
奠基的技术发明都算上的话
people have been programming with basically
人们为了追求面向对象
reference types only, for their object-orienting.
基本上只用了引用类型
But when you do this programming with structs and
但当你用结构体和枚举，特别是协议
enums, and especially when you throw in protocols, (which I
（就是我给你说的那个可重要的，但是
told you I was gonna tell you that are very important, but
现在不能给你讲的那个东西）
I cannot explain to you yet, and generics),
以及泛型编程时
when you start throwing those things all in there, you can
当你开始完全掌握这些东西时
really do a good job of doing real functional programming.
你就真的可以把函数式编程做的很好了

English: 
that someone else is            
pointing to in all this.        
It's this really                
well-contained little thing.    
Now iOS was not developed with  
functional programming in mind  
at all. But                     
the people who invented Swift,  
they were thinking about        
functional programming, So      
you can kind of mix             
a lot of the elements of        
functional programming          
into your application,          
if you're building an iOS       
application. Now that's a new   
frontier in iOS, because for    
however long, 20 years,         
really, or 30 years, really,    
if you consider all the way     
back to the invention of the    
technology that led to iOS,     
people have been                
programming with basically      
reference types only, for       
their object-orienting.         
But when you do this            
programming with structs and    
enums, and especially when you  
throw in protocols, (which I    
told you I was gonna tell you   
that are very important, but    
I cannot explain to you yet,    
and generics),                  
when you start throwing those   
things all in there, you can    
really do a good job of doing   
real functional programming.    

Chinese: 
All of the Swift foundation is really designed with a lot
Swift 的基础框架中很多是基于
of functional programming in mind. If you ever really wanna
函数式编程思想设计的。如果你想
kind of see a good example of how to apply this immutability
看更多关于如何实现这种不可变性
and generics, and protocols and all that stuff to build
和在泛型、协议这些基础上搭建
an architecture, chase down all the things that
的体系的例子，就去查看
are going on in the foundation library: string and range and
基础库中的实现方法，String、Range
all these things. Remember, that I said things like
等所有内容。记住我说的类似于
the range is a sequence, or this thing is comparable,
记得我说过 CountableRange 是 Sequence
remember how I said things like that? Okay, well,
或者这个是 Comparable 的之类的吗？
how do you express that? You use protocols,
那如何表达这些概念？你可以使用 Protocol（协议）
with these immutable types, that can be immutable and
和那些不可变的类型
use generics. So I can't explain all that,
以及 Generic（泛型）。我并不能在此一一解释
I've already spent too much time on it than I have to even
因为已经花了太多时间在这些概念上，超过我
talk about it in the lecture today, but just so
应该在今天的课程中讲解的内容，但是
you know, there is a huge advantage of programming in
你们知道的，有时换一种编写代码的方式
a different way; it requires a real mindset change.
会带来巨大的好处。这需要观念上的改变
So hopefully, you'll take a class where maybe the whole
希望你们有机会写一个类，里面全部内容
class is functional programming,
都基于函数式编程思想
and really you'll get a feel for it.
这样你们就会对这个概念有一定认识了

English: 
All of the Swift foundation     
is really designed with a lot   
of functional programming in    
mind. If you ever really wanna  
kind of see a good example of   
how to apply this immutability  
and generics, and protocols     
and all that stuff to build     
an architecture,                
chase down all the things that  
are going on in the foundation  
library: string and range and   
all these things. Remember,     
that I said things like         
the range is a sequence, or     
this thing is comparable,       
remember how I said things      
like that? Okay, well,          
how do you express that?        
You use protocols,              
with these immutable types,     
that can be immutable and       
use generics.                   
So I can't explain all that,    
I've already spent too much     
time on it than I have to even  
talk about it in the lecture    
today, but just so              
you know, there is a huge       
advantage of programming in     
a different way; it requires    
a real mindset change.          
So hopefully, you'll take       
a class where maybe the whole   
class is functional             
programming,                    
and really you'll               
get a feel for it.              

Chinese: 
Swift does a good job of supporting for
Swift 在基础层面已经对函数式编程
the fundamentals you need to do that. That's kind
提供了你需要的支持。对于应该怎么选择编程思想
of the long-winded answer to which do you choose. If you're
我已经给出了长篇大论式的解答。如果你
doing more of a functional approach, even if you're doing
正在学习更多关于函数式编程的知识，或者只是
a reference-based approach like what you're used to, try
了解传统的基于引用的思想，都可以尝试
to lean towards immutability, try to ask yourself,
向这种不可变的方式上转变。试着问自己
can this thing work and be immutable? Is there some
这些内容不可变后还能正常运作吗？是否有
functionality in my program that I could share by creating
一些功能可以通过泛型来共享其实现部分
a generic, for example. At least those leanings
这种思想上的转变至少
might help you build the apps that are more testable,
会帮助你构建更具有可测试性的应用
because it's a lot easier to write a test for
这会让测试变得更容易
something that's like a mathematical function where
例如一个数学相关的函数
you know the data out is supposed to be the same for
如果可以确认数据在经过处理后
the data in, than it is for something where there's
和传入时保持相同，会比那些
a lot of data that you have to set everything up. Set this,
需要设置很多输入数据的要容易的多。预先设置这个
set this and this and this, and now call the method,
这个以及这个，然后调用方法
that's a lot more difficult to write test cases for, etc.
为这样的方法编写测试用例会非常困难
So that's value and reference. Let's talk a little bit about
以上说的是值和引用。接下来讲一些
the syntax of methods. I'm gonna go fast on this.
方法的语法。我会加快一些速度
Hopefully, you all understand this.
希望你们可以理解这些内容
All parameter names have external names and internal
所有的参数包含外部参数名和内部参数名

English: 
Swift does a good job           
of supporting for               
the fundamentals you need       
to do that. That's kind         
of the long-winded answer to    
which do you choose. If you're  
doing more of a functional      
approach, even if you're doing  
a reference-based approach      
like what you're used to, try   
to lean towards immutability,   
try to ask yourself,            
can this thing work and         
be immutable? Is there some     
functionality in my program     
that I could share by creating  
a generic, for example.         
At least those leanings         
might help you build the apps   
that are more testable,         
because it's a lot easier       
to write a test for             
something that's like           
a mathematical function where   
you know the data out is        
supposed to be the same for     
the data in, than it is for     
something where there's         
a lot of data that you have to  
set everything up. Set this,    
set this and this and this,     
and now call the method,        
that's a lot more difficult     
to write test cases for, etc.   
So that's value and reference.  
Let's talk a little bit about   
the syntax of methods.          
I'm gonna go fast on this.      
Hopefully, you all              
understand this.                
All parameter names have        
external names and internal     

English: 
names. The internal name is     
used inside the definition, or  
the inside the implementation   
of the function.                
So here I have these two        
functions, foo and bar. Bar     
calls foo. So you can see that  
inside foo's implementation,    
it is using the first and       
the second, whereas bar,        
when bar calls foo,             
it uses external first and      
external second, as the names   
of the items. And you know      
that you can put an under       
bar to make it so there's no    
external name. We only do       
that 99.99% of the time with    
the first item. Why do we do    
it? Because sometimes the name  
of the method, and/or the type  
of that first argument, is      
enough to make it clear what    
that thing is supposed to be,   
so we don't need to             
put an external name.           
It's kinda clear.               
All the other parameters,       
we don't have the advantage of  
having the name of the method   
there. So that's why we         
almost never put underbar for   
the later ones. By the way,     
if you only put one             

Chinese: 
names. The internal name is used inside the definition, or
内部参数名用于函数的声明
the inside the implementation of the function.
或函数内容的实现部分
So here I have these two functions, foo and bar. Bar
有两个函数，foo 和 bar。bar 调用了 foo
calls foo. So you can see that inside foo's implementation,
所以在 foo 的内部
it is using the first and the second, whereas bar,
它用了 first 和 second 作为参数名，但是
when bar calls foo, it uses external first and
bar 调用 foo 时， 使用了 externalFirst 和
external second, as the names of the items. And you know
externalSecond 作为参数名
that you can put an under bar to make it so there's no
你可以在没有外部参数名时
external name. We only do that 99.99% of the time with
用下划线来代替。这种下划线的方式我们99.99%的时候只对
the first item. Why do we do it? Because sometimes the name
第一个参数使用。为什么要这样做？因为有时通过函数名
of the method, and/or the type of that first argument, is
或者第一个参数的类型
enough to make it clear what that thing is supposed to be,
已经可以明确的推断出第一个参数应该是什么
so we don't need to put an external name.
这时我们就没必要写外部参数名了
It's kinda clear. All the other parameters,
这样显得更清晰。对于其他参数
we don't have the advantage of having the name of the method
把参数名省略只留函数名没什么好处
there. So that's why we almost never put underbar for
所以几乎不会在除第一个参数名之外的地方
the later ones. By the way, if you only put one
使用下划线。顺带，如果只写了一个

English: 
parameter name, then that's     
both the external name and      
the internal name, and          
that's not that uncommon,       
you'll do that occasionally.    
All right, so you know all      
that. When it comes to doing    
overriding, subclassing, in     
reference types and classes,    
when you override, you have to  
explicitly let Swift know that  
you know you're doing that.     
And you do that by putting      
the override keyword.           
So if you override a method     
from your superclass you have   
to say override func whatever.  
You can mark a method or        
even a whole class final, and   
that means that it cannot be    
overridden, subclasses will     
not be allowed to override it.  
Most languages have that.       
Now on the topic of methods.    
You've seen, actually you've    
seen both, but mostly seen and  
understood instance methods.    
These are methods,              
or vars, that are being sent    
to an instance of the class     

Chinese: 
parameter name, then that's both the external name and
参数名，那么这个名称既是外部参数名
the internal name, and that's not that uncommon,
也是内部参数名，这种情况并不罕见
you'll do that occasionally. All right, so you know all
可以偶尔使用。好了，这些就是全部
that. When it comes to doing overriding, subclassing, in
接下来是重写和子类
reference types and classes, when you override, you have to
对于引用类型和对象，可以重写
explicitly let Swift know that you know you're doing that.
你必须明确地让 Swift 知道你要重写
And you do that by putting the override keyword.
要用 override 关键字
So if you override a method from your superclass you have
所以，如果你要重写一个父类的方法
to say override func whatever. You can mark a method or
必须使用 override func。可以将一个方法或
even a whole class final, and that means that it cannot be
整个类标记为 final，这意味着它无法
overridden, subclasses will not be allowed to override it.
被重写，子类不允许重写它
Most languages have that. Now on the topic of methods.
大部分语言拥有这类语法。继续方法这个主题
You've seen, actually you've seen both, but mostly seen and
可以看到，实际上两个都在这里，但是通常你们更熟悉
understood instance methods. These are methods,
实例方法。实例方法
or vars, that are being sent to an instance of the class
或实例变量，可以通过给一个类

Chinese: 
struct or enum. In other words, one of them.
结构体或枚举的实例发送消息来访问。也就是给某一个具体对象
Like I create one of them: I create a double of 15.5,
比如我可以创建它们的一个实例：我创建一个值为 15.5 的 Double
I have one, and I can send it messages.
我有了一个实例，就可以给它发送消息
But types, like the type double, the type string,
但是类型，例如 Double，String
the type calculator brain, they can also have methods and
CalculatorBrain，它们也可以拥有方法和
vars. Computed vars, no storage, but computed vars.
变量。计算变量，没有存储空间，是计算得出的变量
All you do to add a method or a var to a type is
要给类型添加方法或变量，只要
you put static in front of the declaration.
将 static 关键字放在声明语句前面即可
So "static func whatever" means this is a function on
static func 意思是这个方法
the type, not on instances of the type, on the type itself.
属于类型。不属于实例，是类型本身的方法
For example, let's think about double here.
还是以 Double 举例
Double actually has quite a few static or type methods and
Double 拥有不少类型方法和
vars. You access them by sending the message to
变量。可以通过发送消息给
Double to the actual word, capital D-O-U-B-L-E. You
Double 来访问。一字不差，D-O-U-B-L-E
don't send it to an instance, you send it to that word. And
不要发送给一个实例，而是发送给那个类型的名称
you've already seen at least one of these, which was pi.
你已经看到过至少一个例子了，比如 π

English: 
struct or enum.                 
In other words, one of them.    
Like I create one of them:      
I create a double of 15.5,      
I have one, and                 
I can send it messages.         
But types, like the type        
double, the type strength,      
the type calculator brain,      
they can also have methods and  
vars. Computed vars,            
no storage, but computed vars.  
All you do to add a method or   
a var to a type is              
you put static in front         
of the declaration.             
So "static func whatever"       
means this is a function on     
the type, not on instances of   
the type, on the type itself.   
For example,                    
let's think about double here.  
Double actually has quite a     
few static or type methods and  
vars. You access them by        
sending the message to          
Double to the actual word,      
capital D-O-U-B-L-E. You        
don't send it to an instance,   
you send it to that word. And   
you've already seen at least    
one of these, which was pi.     

Chinese: 
Remember we said Double.pi and we got the value of pi?
还记得我们通过 Double.pi 取得到了 π 的值吗？
Pi is a var, a computed var, on the class or
π 是一个变量，一个计算变量
struct actually, double, but it also has other methods,
属于 Double 这个结构体。Double 也有一些其他方法
like abs. Abs takes a double value and
例如 abs。abs 接受一个 Double 的值
returns the absolute value of it. That is on the type.
返回这个值的绝对值。这是类型的方法
You say Double.abs, Double.pi. As opposed to, for example,
可以用 Double.abs，Double.pi。但是
if I have a double like x is equal 23.85.
如果我有一个 Double 类型的实例 x，它等于 23.85
So x is now a double. I can't say x Double.pi cause
x 是一个 Double 实例。这时不能通过 x 调用 Double.pi
x is an instance of a double. You see the difference?
因为 x 是 Double 的一个实例。你们是否明白了其中的区别？
We see saying x.pi, trying to send pi
如果我们说 x.pi，尝试把 pi 发送给
to an instance versus sending pi to a type double.
实例，对比发送 pi 给类型 Double 的区别
So what do we use these type methods for?
为什么要用类型方法？
Well, we can't access any instance variables because
我们没法访问任何一个实例变量
we're not sending them to an instance.
因为我们没有给实例发送消息
We mostly use them for utility methods, things like that.
类型方法通常是类中的辅助方法，比如
Constants like pi is a good example. Things that
常量，π 就是一个很好的例子。还有那些
kind of are functions that are associated with this type but
和这个类型本身关联

English: 
Remember we said Double.pi and  
we got the value of pi?         
Pi is a var, a computed var,    
on the class or                 
struct actually, double, but    
it also has other methods,      
like abs.                       
Abs takes a double value and    
returns the absolute value      
of it. That is on the type.     
You say Double.abs, Double.pi.  
As opposed to, for example,     
if I have a double              
like x is equal 23.85.          
So x is now a double.           
I can't say x Double.pi cause   
x is an instance of a double.   
You see the difference?         
We see saying x.pi,             
trying to send pi               
to an instance versus           
sending pi to a type double.    
So what do we use these         
type methods for?               
Well, we can't access any       
instance variables because      
we're not sending               
them to an instance.            
We mostly use them for utility  
methods, things like that.      
Constants like pi is a good     
example. Things that            
kind of are functions that are  
associated with this type but   

Chinese: 
don't belong to a particular instance or
但不属于任何一个特定的实例
wouldn't really operate on an instance. Now for example,
或者不会真的对一个实例进行操作的方法。例如
you might have an instance method or
可以有一个实例方法
even an instance var called abs, A-B-S, with no arguments,
或一个实例变量叫做 abs，A-B-S，没有参数
That you would send to an instance, and it would take
当你调用它时，它会
the absolute value of the thing you sent it to. But
取这个实例的绝对值
of course the type one has to have an argument because
但是类型方法需要接受一个参数
you're sending it to the type double,
因为你发送消息给 Double 类型
so there's no double involved.
所以并没有 Double
There's no instance of a double involved. Everybody got
没有 Double 实例参与计算
that? Alright: properties. You know all about properties.
所有人都明白了吗？属性，你们都知道什么是属性
We saw computed properties like display value in
我们已经看过了计算属性，比如之前计算器中
our calculator. There's actually some really cool
用来显示的数值。属性有一些非常棒的特性
features on properties. One of the most interesting ones is
其中最有趣的一个是
property observers. What is a property observer?
属性观察器。什么是属性观察器？
A property observer is a little piece of code that
属性观察器是一些代码
will get executed when your property changes.
可以在属性改变的时候自动执行
Anytime your property changes just a little piece of code
任何时候属性改变了，这段代码
can get executed. Now you can actually find out
就会被执行。你能准确地捕捉到
just before your property changes. Or
属性将要改变之前，或者

English: 
don't belong to                 
a particular instance or        
wouldn't really operate on      
an instance. Now for example,   
you might have                  
an instance method or           
even an instance var called     
abs, A-B-S, with no arguments,  
That you would send to          
an instance, and it would take  
the absolute value of           
the thing you sent it to. But   
of course the type one has      
to have an argument because     
you're sending it               
to the type double,             
so there's no double involved.  
There's no instance of a        
double involved. Everybody got  
that? Alright: properties.      
You know all about properties.  
We saw computed properties      
like display value in           
our calculator. There's         
actually some really cool       
features on properties. One of  
the most interesting ones is    
property observers.             
What is a property observer?    
A property observer is          
a little piece of code that     
will get executed when          
your property changes.          
Anytime your property changes   
just a little piece of code     
can get executed.               
Now you can actually find out   
just before your                
property changes. Or            

English: 
you can find out just after     
your property changes.          
Or both. And the way you        
do this, and this works for     
your stored properties, like    
userIs InTheMiddleOfTyping:     
we could put a property         
observer on there, and          
execute some code every time    
we change that. It also works   
for inherited properties,       
so if you inherit something     
from your superclass, you can   
put these properties in and     
notice that it changed. By the  
way, if you have a property     
which is a value type,          
(a struct or                    
something, like an array or     
an dictionary), this property   
observer stuff will happen      
if that thing gets changed,     
if it gets mutated. So if you   
add something to the array,     
boom, the Property Observer     
will kick in and say,           
"that changed". How do          
these Property Observers        
work? They look a lot like      
a computed property. Remember   
that the computed property      
displayValue had get and        
then we had some code,          
And then we had set and         
we had some code?               
This is similar except for      
get and set it's will set,      
or did set.                     

Chinese: 
you can find out just after your property changes.
属性刚刚改变之后
Or both. And the way you do this, and this works for
或者上述两种。这只能应用于
your stored properties, like userIs InTheMiddleOfTyping:
存储属性，比如 userIsInTheMiddleOfTyping
we could put a property observer on there, and
我们可以加一个属性观察器
execute some code every time we change that. It also works
每次它被改变都会执行一段代码。这个功能
for inherited properties, so if you inherit something
也对继承的属性有效，比如继承了某些
from your superclass, you can put these properties in and
父类的属性，可以通过属性观察器
notice that it changed. By the way, if you have a property
观察它们的改变。顺便，如果属性
which is a value type, (a struct or
是值类型，如结构体
something, like an array or an dictionary), this property
数组、字典等，这些属性观察器
observer stuff will happen if that thing gets changed,
会在它们指向的值被改变时
if it gets mutated. So if you add something to the array,
或是包含的内容被改变时触发。比如向数组中添加元素
boom, the Property Observer will kick in and say,
那就炸了，属性观察器会触发并告诉你
"that changed". How do these Property Observers
“有东西改变了”。属性观察器是
work? They look a lot like a computed property. Remember
基于什么原理工作的呢？它们很像计算属性那样。还记得
that the computed property displayValue had get and
displayValue 的 get 方法执行时
then we had some code, And then we had set and
我们在 get 中加入了一些别的代码，set 的时候
we had some code? This is similar except for
也是一样。这基本上是类似的，除了
get and set it's will set, or did set.
这个是 willSet 和 didSet

English: 
By the way, you probably would  
never (I don't even know if     
you can) use this in            
a computed property because     
you've got the set              
clause there so                 
you can just put                
it right in set.                
You don't need to find out      
when it's set because you set   
it. But for stored properties   
and inherited properties,       
that make sense, so             
you have willSet.               
Now, willSet, first of all,     
you put it all in a curly       
brace after the property        
just like if you were doing     
a computed property but, this   
is not a computed property,     
just adding a curly brace       
doesn't make it a computed      
property, you have to put       
get or set in there, but,       
if I put willSet, then,         
inside that code,               
there's a special variable      
just like there in the set      
case of computer property,      
called newValue, and            
that is the value that that     
thing is going to be set to.    
It's not set yet.               
Some property,                  
see some stored property        
up there? It has not yet        
been set to newValue but it's   
going to be. And then didSet,   
that code occurs after some     
property has been set and       
the special variable            
in there is oldValue.           
That's the value it used to     
have before it got set. So      

Chinese: 
By the way, you probably would never (I don't even know if
顺便，你可能永远不会（我也不知道
you can) use this in a computed property because
是不是能这么做）将属性观察器用于计算属性，因为
you've got the set clause there so
既然已经有了 set 语句
you can just put it right in set.
完全可以将代码放在 set 里
You don't need to find out when it's set because you set
根本不需要去监视何时它被改变，因为只有你的 set 方法在改变它
it. But for stored properties and inherited properties,
但是存储属性和继承来的属性不一样
that make sense, so you have willSet.
这时属性观察器有存在价值，所以有了 willSet
Now, willSet, first of all, you put it all in a curly
现在，willSet，首先你要把大括号
brace after the property just like if you were doing
放在属性的后面，像计算属性一样
a computed property but, this is not a computed property,
但是这不是计算属性
just adding a curly brace doesn't make it a computed
加上大括号不会让它变成计算属性
property, you have to put get or set in there, but,
你要里面加上 get 或 set，但是
if I put willSet, then, inside that code,
如果在里面加上了 willSet
there's a special variable just like there in the set
会出现一个特殊的变量，和 set 计算属性时
case of computer property, called newValue, and
的情况类似，叫做 newValue
that is the value that that thing is going to be set to.
这个值将会被赋予给这个属性
It's not set yet. Some property,
但是还没赋予给它。一些属性
see some stored property up there? It has not yet
看到上面那些存储属性了吗？它还没
been set to newValue but it's going to be. And then didSet,
被设置成 newValue，但马上就要设置了
that code occurs after some property has been set and
didSet 中的那些代码在属性被设置之后执行
the special variable in there is oldValue.
在那里特殊变量叫做 oldValue
That's the value it used to have before it got set. So
这个值是它被改变前的值

Chinese: 
you can compare if they've changed, for
你可以对比是否发生了变化
example. So where do we use these things?
这些特性要用在哪里呢？
Probably the number one place that we use them is in our
可能最重要的一个用途是在
Controller in view. Let's say I'm a button and
控制视图中。比如，我是个按钮
my background color changes. I inherit my background color
我的背景色改变了，我的背景色是继承自
from my super class, UI view. Up the chain of super classes.
继承树最上层的父类 UIView 的
Every time the background color changes,
每次背景色改变时
the button wants to redraw itself so
这个按钮都想重绘自己
it will have var background color is a UI color,
所以它有一个背景色属性，类型是 UIColor
open curly brace, didSet open curly brace
添加一个大括号，didSet 再跟一个大括号
draw myself closed curly brace. Question? Okay,
在这里重绘自身。有什么问题？
so the question is, if someone changes some stored property
问题是，如果某人改变了存储属性
there, am I responsible for doing something about that
我是否要负责在
in willSet or didSet? Do I have to actually set it? And
willSet 或 didSet 中做些什么？我是否真的要去设置它？
the answer is no. Okay, that's being set somewhere else.
答案是否。如果被别的什么地方改变了
You're just getting a chance to run some other code that
你只是获得了一个机会去执行其他代码
you wanna run just before and just after it happens.
你希望执行的是 set 前后的事情
But you're not responsible for setting the actual value.
你无需负责 set 这件事本身
That's done for you. That's why you get to
系统已经为你做好了，所以你得到是

English: 
you can compare if              
they've changed, for            
example. So                     
where do we use these things?   
Probably the number one place   
that we use them is in our      
Controller in view.             
Let's say I'm a button and      
my background color changes.    
I inherit my background color   
from my super class, UI view.   
Up the chain of super classes.  
Every time the background       
color changes,                  
the button wants to             
redraw itself so                
it will have var background     
color is a UI color,            
open curly brace,               
didSet open curly brace         
draw myself closed curly        
brace. Question? Okay,          
so the question is, if someone  
changes some stored property    
there, am I responsible for     
doing something about that      
in willSet or didSet? Do I      
have to actually set it? And    
the answer is no. Okay, that's  
being set somewhere else.       
You're just getting a chance    
to run some other code that     
you wanna run just before and   
just after it happens.          
But you're not responsible for  
setting the actual value.       
That's done for you.            
That's why you get to           

English: 
see the old value and the new   
value in the two of them.       
So we'll see this next week     
when we start drawing on        
screen, where we're gonna be    
watching properties change so   
we can cause ourselves to       
redraw. Next, lazy properties.  
Lazy initialization is          
a really powerful tool.         
It's gonna get you out of       
a lot of binds in this class.   
What does it mean?              
A lazy var, a var               
that you say lazy in front of,  
whatever it's set equal to,     
that equals doesn't actually    
happen until someone accesses   
that var. Until someone asks    
for the value of that var,      
it doesn't actually do          
the initialization there.       
It doesn't do that              
equal something.                
So it's lazy. It's waiting.     
Now why do you wanna be lazy?   
Well, one obvious reason        
is like here, lazy var          
brain equals calculator         
brain, what if calculator       
brain was really expensive to   
create. What if it opened       
a network connection because    

Chinese: 
see the old value and the new value in the two of them.
oldValue 和 newValue
So we'll see this next week when we start drawing on
我们下周讲屏幕绘图之后会涉及这些
screen, where we're gonna be watching properties change so
那时我们会去观察属性改变
we can cause ourselves to redraw. Next, lazy properties.
来决定什么时候去调用自身的重绘。接下来，lazy（延时）属性
Lazy initialization is a really powerful tool.
延时初始化是一个强大的工具
It's gonna get you out of a lot of binds in this class.
这可以帮你减少很多的麻烦
What does it mean? A lazy var, a var
具体是什么意思？一个延时变量，是一个变量
that you say lazy in front of, whatever it's set equal to,
在前面加上 lazy 关键字，不管它被赋什么值
that equals doesn't actually happen until someone accesses
都不会真的立刻执行，直到某处访问了这个值
that var. Until someone asks for the value of that var,
直到某处需要这个变量的值之前
it doesn't actually do the initialization there.
它都不会真的初始化
It doesn't do that equal something.
这和常规的赋值不一样
So it's lazy. It's waiting.
所以它是延时的。它会等待
Now why do you wanna be lazy? Well, one obvious reason
为什么需要 lazy 呢？一个明显的原因
is like here, lazy var brain equals calculator
像这样，lazy var brain = CalculatorBrain()
brain, what if calculator brain was really expensive to
如果 CalculatorBrain 的创建非常耗资源
create. What if it opened a network connection because
或者它会打开一个网络连接

Chinese: 
we're going to share the calculation with the internet
我们会把计算结果共享至互联网
or something, you know what I mean,
或者一些其他情况，你应该知道我的意思了
do something that is expensive.
总之就是做一些耗资源的操作
Well, you wouldn't want to do it,
好吧，你肯定不想这样做
unless someone actually tried to access the brain,
除非某处真的需要访问这个 brain
called set up operand on it or something. Then you would
调用设置操作数或者其他什么。这时你才
want to actually do the work to create it.
想要真的创建它
Okay so one reason to be lazy,
这是一个需要 lazy 的理由
it's not that important of a reason it turns out, but
延后高消耗的操作这点
one is to delay expensive operations. But
似乎并没有那么重要
what's another reason to do it? Well, in Swift,
但是另一个原因是，在 Swift 中
all vars have to be initialized. Remember that?
所有的变量都要被初始化，还记得吗？
Remember we added userIsInTheMiddleOfTyping.
我们曾添加了 userIsInTheMiddleOfTyping
And we didn't say, equals false. And we got an error.
我们没有让它等于 false，这时产生了一个错误
It said we had no init, because we hadn't initialized
说缺少构造器，因为我们没有初始化它
that. Not only did they all have to be initialized, but
不仅所有变量都要初始化，而且
they all had to be initialized before you could even send
属性要在可以被发送消息前初始化
a message to that class, even internally. So
即使在类内部也是如此
you can't invoke any of your own methods until you fully
也就是你无法调用任何一个实例方法，直到
initialize yourself. What if one of the things you want to
实例完全初始化了。如果你希望某个属性

English: 
we're going to share the        
calculation with the internet   
or something,                   
you know what I mean,           
do something that               
is expensive.                   
Well, you wouldn't              
want to do it,                  
unless someone actually         
tried to access the brain,      
called set up operand on it or  
something. Then you would       
want to actually do             
the work to create it.          
Okay so one reason to be lazy,  
it's not that important of      
a reason it turns out, but      
one is to delay                 
expensive operations. But       
what's another reason to        
do it? Well, in Swift,          
all vars have to be             
initialized. Remember that?     
Remember we added               
userIsInTheMiddleOfTyping.      
And we didn't say, equals       
false. And we got an error.     
It said we had no init,         
because we hadn't initialized   
that. Not only did they all     
have to be initialized, but     
they all had to be initialized  
before you could even send      
a message to that class,        
even internally. So             
you can't invoke any of your    
own methods until you fully     
initialize yourself. What if    
one of the things you want to   

English: 
initialize needs to call        
a method on yourself? It's      
impossible. Because if you      
need to initialize something    
to be allowed to send messages  
to yourself and you need        
to send a message to yourself   
to initialize something,        
it's a deadlock. You can't do   
it. Okay, well lazy let's you   
do it. Because you can say for  
example, the last one there;    
lazy my property equals some    
method on myself. This is not   
going to be executed until      
someone says my property and    
no one's allowed to access      
my property until I'm fully     
initialized. So                 
by definition there's no way    
that that is gonna try to get   
initialized until I'm already   
fully initialized. And yet      
this lazy thing counts as this  
thing having been initialized.  
So this is the big loophole.    
Lazy var myProperty counts      
as having been initialized      
even though it really hasn't    
yet. Because it's waiting for   
something to actually access    
myProperty. But it counts for   
the purposes of that rule, so   
now someone comes along later   

Chinese: 
initialize needs to call a method on yourself? It's
的初始化过程调用另一个实例方法怎么办？
impossible. Because if you need to initialize something
这是不可能的。比如你需要初始化某个属性
to be allowed to send messages to yourself and you need
才能来给实例发消息
to send a message to yourself to initialize something,
但这个属性的初始化，又要求实例已经完成了构造
it's a deadlock. You can't do it. Okay, well lazy let's you
这就陷入了僵局。原本没法这么做，但是可以通过 lazy 实现
do it. Because you can say for example, the last one there;
比如用这里最后的 myProperty 举例
lazy my property equals some method on myself. This is not
将这个延时属性设置为实例的某个方法的值
going to be executed until someone says my property and
直到某人访问它之前，这段代码都不会运行
no one's allowed to access my property until I'm fully
记住，直到实例初始化完成之前，谁也不能访问这个属性
initialized. So by definition there's no way
所以很明确
that that is gonna try to get initialized until I'm already
在实例完全初始化之前，延迟属性一定没有初始化
fully initialized. And yet this lazy thing counts as this
但这时延时属性会被视作
thing having been initialized. So this is the big loophole.
已经初始化了。这是一个很大的“漏洞”
Lazy var myProperty counts as having been initialized
延时属性被视为已初始化
even though it really hasn't yet. Because it's waiting for
但实际上它没被初始化，因为 myProperty 在等待
something to actually access myProperty. But it counts for
某处实际访问它。所以这个漏洞的存在
the purposes of that rule, so now someone comes along later
是为了遵守那条规则。现在某处实际访问了它

Chinese: 
and accesses it, now we can call this method. So
我们再调用这个方法
do you see how deferring the calling of this method in
你们理解了吗？推迟调用这个方法
order to initialize this gets us around that requirement
使得我们可以摆脱
that everything be initialized?
所有内容都要被初始化的限制
It's really tricky. And then the middle one there,
这真的有点复杂。中间这个
someProperty, that's super tricky. Because you can
someProperty，它更复杂。你可以
actually have a closure, (remember what a closure is,
用一个 closure（闭包），（回忆下什么是闭包
right from calculator brain, it's just a function,
在 CalculatorBrain 中用到过，其实闭包就是函数
in line function), you can actually have a closure
一个内联函数），你可以用一个闭包
to initialize your thing lazily. All you do is you
来延时初始化一个变量。你要做的仅仅是
put the closure, open curly brace, close curly brace.
把闭包写在这里，开始大括号，结束大括号
It obviously has to return something of the type
显然，还要返回符合这个变量类型的结果
of that var. And then just put the little open parenthesis,
然后还要加上一对小括号
close parenthesis at the end. When we open parenthesis and
在闭包的结尾
close parenthesis at the end of the closure,
在闭包的结尾加上小括号
that means execute this closure right now. But
意味着立刻执行这个闭包
it's not gonna execute right now, it's gonna act lazy so
但是实际上它并不会立刻执行，因为它是延时执行的
it's gonna happen later. And that means that that closure
它会稍后才被执行。这意味着
inside could reference self. Because self will be fully
闭包内部可以引用 self。因为当这个闭包执行的时候
initialized by the time this closure gets executed,
self 肯定已经被完全初始化了

English: 
and accesses it, now we         
can call this method. So        
do you see how deferring        
the calling of this method in   
order to initialize this gets   
us around that requirement      
that everything                 
be initialized?                 
It's really tricky.             
And then the middle one there,  
someProperty, that's super      
tricky. Because you can         
actually have a closure,        
(remember what a closure is,    
right from calculator brain,    
it's just a function,           
in line function), you can      
actually have a closure         
to initialize your thing        
lazily. All you do is you       
put the closure, open curly     
brace, close curly brace.       
It obviously has to return      
something of the type           
of that bar. And then just put  
the little open parenthesis,    
close parenthesis at the end.   
When we open parenthesis and    
close parenthesis at            
the end of the closure,         
that means execute this         
closure right now. But          
it's not gonna execute right    
now, it's gonna act lazy so     
it's gonna happen later. And    
that means that that closure    
inside could reference self.    
Because self will be fully      
initialized by the time         
this closure gets executed,     

Chinese: 
since it's lazily executed. So
前提是确保它是延时执行的
lazy will get you out of some of these tricky wickets,
lazy 可以使你摆脱这类棘手的处境
because when you see me talk about initialization,
当你们听我讲到初始化时
you're gonna be like, "I don't want to do that, ever".
你们可能会说“我永远不想那样做”
You're going to try and avoid it, and
你们会尝试避免它
this is a good way to avoid it. So yeah,
这就是一种很好的避免的方式
it still satisfies all those things. Alright, on to Array.
它仍然满足所有规则。好了，下面讲 Array（数组）
Everybody knows what an array is. Everyone knows what
所有人都知道数组是什么，所有人都知道泛型数组是什么
a generic array is. You just, when you declare the array,
你肯定知道，因为当你声明一个数组时
you have to say what type of things are gonna
必须指明它的内容的类型是什么
be in the array. There's a different syntax though,
也有另一种语法
which I didn't introduce when I did dictionary in the demo.
之前的 demo 中，我用了字典，但是没有提到过这个语法
But you can declare an array, those two yellow things
你可以声明一个数组，上面黄色标注的两个声明方法
up there are exactly the same thing. So,
是一样的
open square bracket,
左半方括号
string close square bracket is exactly the same as saying
String，右半方括号
array angle bracket string. It's just kind of a special
这与 Array 加上一对尖括号，括起来 String，是等价的
way to declare an array and it actually seems to be
[String] 这种声明数组的特殊方式更被大众接受
the preferred way. I actually prefer the other way because
但是我比较喜欢用 Array
it's a little clearer to you that are learning that this is
更明确地告诉你们这些学生，这是个数组
an array, because it says the word array and string.
毕竟包含了 Array 和 String 两个单词
But open square bracket, close square bracket,
不过中括号的方式

English: 
since it's lazily executed. So  
lazy will get you out of some   
of these tricky wickets,        
because when you see me         
talk about initialization,      
you're gonna be like, "I        
don't want to do that, ever".   
You're going to try and         
avoid it, and                   
this is a good way to           
avoid it. So yeah,              
it still satisfies all those    
things. Alright, on to Array.   
Everybody knows what an array   
is. Everyone knows what         
a generic array is. You just,   
when you declare the array,     
you have to say what            
type of things are gonna        
be in the array. There's        
a different syntax though,      
which I didn't introduce when   
I did dictionary in the demo.   
But you can declare an array,   
those two yellow things         
up there are exactly            
the same thing. So,             
open square bracket,            
string close square bracket     
is exactly the same as saying   
array angle bracket string.     
It's just kind of a special     
way to declare an array and     
it actually seems to be         
the preferred way. I actually   
prefer the other way because    
it's a little clearer to you    
that are learning that this is  
an array, because it says       
the word array and string.      
But open square bracket,        
close square bracket,           

English: 
we know that's going to         
be index into an array so       
it looks kind of array-ish but  
just get used to it. [String]   
means an array of string.       
It's the declaration of         
the S and the name of that      
type array of string. So if I   
had a string right here like    
this giraffe, cow, doggie, and  
bird. Four animals in here,     
four strings and I said         
animals dot append ostrich,     
well append appends something   
onto the array, now the thing   
you are appending has to        
be the same type obviously      
as the type of everything in    
the array, however the type     
was declared. Notice that       
animals is in inferred.         
By Swift, to be an array of     
string. Because Swift sees      
that you sent it to             
an array of things and          
it looked at all the things     
and they were all strings.      
So it said, the animals must    
be an array of string. Now,     
this line of code               
animals.append("Ostrich").      
That's very bad.                
Can anyone tell me why          
that's not gonna work?          

Chinese: 
we know that's going to be index into an array so
我们知道这是通过索引访问数组元素的方式
it looks kind of array-ish but
它也看起来更有数组的风格
just get used to it. [String] means an array of string.
习惯了就好了。[String] 代表一个包含字符串的数组
That's the name of that type
这是字符串数组这个类型的名称
array of string. So if I had a string right here like
如果我有一些字符串
this giraffe, cow, doggie, and bird. Four animals in here,
比如 Giraffe，Cow，Doggie，Bird 这四种动物
four strings and I said animals dot append ostrich,
四个字符串，然后我调用 animals.append("Ostrich")
well append appends something onto the array, now the thing
append 这个方法会将一些东西加入到数组中
you are appending has to be the same type obviously
你加入的新东西显然也必须
as the type of everything in the array, however the type
和数组中其他元素是同一个类型
was declared. Notice that animals is in inferred.
因为类型已经被声明了。注意这里 animals 的类型已经
By Swift, to be an array of string. Because Swift sees
被 Swift 推断为 Array，因为 Swift
that you sent it to an array of things and
通过检查你在数组中包含的每一个元素
it looked at all the things and they were all strings.
判断出它们全都是字符串
So it said, the animals must be an array of string. Now,
所以它断定，animals 必然是一个 Array
this line of code animals.append("Ostrich").
这行代码 animals.append("Ostrich")
That's very bad.
存在问题
Can anyone tell me why that's not gonna work?
谁能告诉我它为什么有问题？

Chinese: 
Yeah? >> That's exactly right.
>> 答得好，给你颗糖吃
We define this animal's variable with let, so
我们声明 animals 时用的是 let
it's immutable. So when we say append an ostrich onto
它是不可变的，所以我们 append("Ostrich")
an immutable thing, it's going to crash my program.
添加进这个不可变的数组，就会导致程序崩溃
But actually, it won't even crash my program.
其实不会真的导致程序崩溃
It won't even compile.
而是连编译都无法通过
Like, Swift compiler's just gonna say, no way,
Swift 编译器会告诉你，这样做不行
you can't do append of something or other.
你没法 append 或者做其他操作
So that's a good one over there, you got that.
这就是个很好的例子，你们已经掌握了
How about this one? I'll give you a second chance for
那么这个呢？再给你们一次机会
everyone. Why is this one no good? Okay,
下面这个有什么错误？
I'm trying to get animals[4] over there, why? Nobody?
我尝试获取 animals[4]，为什么，谁要回答？
This one's easier. Array index, yes! Array index is
这个问题比较简单。数组的索引，答得好，再发颗糖
out of bounds because arrays are indexed starting at zero.
数组的索引值越界了，数组是从 0 开始索引的
Okay, so giraffe, cow, doggie, bird that's zero, one, two and
所以 Giraffe，Cow，Doggie，Bird 对应 0，1，2，3
three. So if I say, give me array number four, bam,
如果我说，把第四个给我
crashed my program array index out of bounds.
程序就会因为数组索引越界而崩溃
Let's talk about the fact that array is a sequence.
下面讲讲数组作为一个 Sequence（序列）的特性

English: 
Yeah?                           
>> That's exactly right.        
We define this animal's         
variable with let, so           
it's immutable. So when we      
say append an ostrich onto      
an immutable thing, it's        
going to crash my program.      
But actually, it won't          
even crash my program.          
It won't even compile.          
Like, Swift compiler's          
just gonna say, no way,         
you can't do append of          
something or other.             
So that's a good one            
over there, you got that.       
How about this one? I'll        
give you a second chance for    
everyone.                       
Why is this one no good? Okay,  
I'm trying to get animal[4]     
over there, why? Nobody?        
This one's easier. Array        
index, yes! Array index is      
out of bounds because arrays    
are indexed starting at zero.   
Okay, so giraffe, cow, doggie,  
bird that's zero, one, two and  
three. So if I say, give        
me array number four, bam,      
crashed my program array        
index out of bounds.            
Let's talk about the fact       
that array is a sequence.       

English: 
Array is actually a collection  
and collections are sequences.  
And a sequence means I can do   
for in on it. So if I say for   
animal in animals, my little    
for loop will get executed      
four times, once with animal    
being giraffe, next one with    
animal being cow, next one      
with animal being doggie,       
next one animal being bird.     
Okay, so that's a really cool   
feature. Remember this is the   
only four there is in swift.    
For in, that's the only for     
there is, nothing else.         
So array in a lot of            
classes instructs               
in iOS have some                
interesting methods             
that have arguments that are    
closures. So I teach closures   
to you right at the beginning   
of the of the quarter.          
And why do I do that? Because   
closures are an important       
thing to understand if you      
want to really use iOS API      
well. So let's take at this     
(just so we can learn a little  
bit about how closures          
can make our API great,         

Chinese: 
Array is actually a collection and collections are sequences.
数组实际上是一个 Collection（集合），而集合又是序列
And a sequence means I can do for in on it. So if I say for
一个序列意味着我可以对它进行 for...in 循环
animal in animals, my little for loop will get executed
如果我说 for animal in animals，这个 for 循环就会执行四次
four times, once with animal being giraffe, next one with
第一次 animal 取值为 Giraffe，第二次
animal being cow, next one with animal being doggie,
animal 是 Cow，接下来是 Doggie
next one animal being bird. Okay, so that's a really cool
最后一个是 Bird。这真是一个很棒的功能
feature. Remember this is the only for there is in swift.
记住这是 Swift 中唯一的 for 循环形式
For in, that's the only for there is, nothing else.
for...in 这就是唯一的，没有其他了
So array in a lot of classes and structs
在数组，以及 iOS 众多类和结构体中
in iOS have some interesting methods
有一些有趣的方法
that have arguments that are closures. So I teach closures
它们有闭包类型的参数
to you right at the beginning of the of the quarter.
所以我在这期课程的开头就先讲了闭包
And why do I do that? Because closures are an important
为什么我要先讲它，因为如果你想把 iOS API 用好
thing to understand if you want to really use iOS API
就应该先理解闭包这个重要的概念
well. So let's take at this (just so we can learn a little
我们看看这个（我们从中还可以学到
bit about how closures can make our API great,
如何把我们自己的 API 设计的更好

Chinese: 
especially again if you're doing functional programming,
尤其是你要用函数式编程的话
closures can be really good), but why are closures so great?
闭包可以从中起到很大作用），闭包为什么这么有用？
So let's look at this so, this first function right here
我们看看这些，第一个方法
called filter is an array method.
叫做 filter，是数组的方法
Nothing special about it, it's just func in array.
它没什么特别的，只是一个数组的方法
It has one argument, which is called includeElement.
它有一个参数，叫做 includeElement
And that argument is a function. It's a function that
这个参数是一个函数
takes one argument which is of the same type of the things in
这个函数有一个类型与数组元素类型一致的参数
the arrays, cuz it's a t. So I have an array angle bracket t.
因为这个类型是 T，所以我有一个 Array
It's a generic type so this function is declared in that
这是一个泛型，这个函数是
generic type so the t means the same t, the same type. So
基于这个泛型声明的。所以这个 T 是同一个 T，同一个类型
if I have an array of strings this filter expects this
如果我有一个字符串数组，那么 filter 方法的参数
to be a function that takes a string. As its only argument.
就是一个接受字符串作为唯一参数的函数
And it returns a Bool, so that's the argument.
并且这个函数返回一个布尔值
The argument is a function that takes a string and
所以 filter 的参数是一个函数，接受字符串
returns a Bool or takes a T, whatever that is, and
也就是对应的 T 类型，并返回布尔值
returns a Bool. And then what's the return
那么 filter 方法本身

English: 
especially again if you're      
doing functional programming,   
closures can be really good),   
but why are closures so great?  
So let's look at this so,       
this first function right here  
called filter is                
an array method.                
Nothing special about it,       
it's just funk and array.       
It has one argument, which      
is called includeElement.       
And that argument is a          
function. It's a function that  
takes one argument which is of  
the same type of the things in  
the arrays, cuz it's a t. So I  
have an array angle bracket t.  
It's a generic type so this     
function is declared in that    
generic type so the t means     
the same t, the same type. So   
if I have an array of strings   
this filter expects this        
to be a function that takes a   
string. As its only argument.   
And it returns a Bool,          
so that's the argument.         
The argument is a function      
that takes a string and         
returns a Bool or takes a T,    
whatever that is, and           
returns a Bool.                 
And then what's the return      

English: 
value of this filter thing?     
It's an array of T, so another  
array with the same kind of     
elements. So what does filter   
do? Filter takes every single   
element In the array that       
you're sending it to and it     
runs that little function. And  
if that function returns true,  
it includes it in the array it  
returns. If it returns          
false it doesn't.               
It throws it out. So            
it's a filter: it's filtering   
your array and creating a new   
array with all the things you   
don't want as defined by this   
function that you're            
providing as an argument.       
With all the things you don't   
want thrown out. So for         
example here, I have this       
var that I'm creating,          
bigNumbers, and I'm creating    
an array on the fly 2,          
47,118,5,9, (see?               
I created an array), and look,  
I'm sending it a message right  
away. Yeah, I didn't have to    
put it into another var,        
by the way, I could have but,   
I just want all be on one line  
here. I created this array and  
I'm sending it                  
the message filter and          
look what I'm providing for     
the argument there.             
That include element it has an  
underbar, so, you don't have    

Chinese: 
value of this filter thing? It's an array of T, so another
返回什么东西？返回的是 T 类型元素的数组
array with the same kind of elements. So what does filter
是一个与原数组包含同类型元素的新数组
do? Filter takes every single element In the array that
filter 有什么用？filter 对数组中的每个元素
you're sending it to and it runs that little function. And
执行一次传入的函数
if that function returns true, it includes it in the array it
如果函数返回 true，就把那个元素包含在返回的数组中
returns. If it returns false it doesn't.
如果函数返回 false
It throws it out. So
就把那个元素过滤掉（不放入返回数组）
it's a filter: it's filtering your array and creating a new
filter 就是过滤器：它创建一个新数组来过滤原数组
array with all the things you don't want as defined by this
根据作为参数传入的函数来判断
function that you're providing as an argument.
哪些是你不想要的元素
With all the things you don't want thrown out. So for
把你不想要的元素都过滤掉
example here, I have this var that I'm creating,
例如：我有一个变量
bigNumbers, and I'm creating an array on the fly 2,
叫做 bigNumbers，我紧接着创建了一个数组 [2,47,118,5,9]
47,118,5,9, (see? I created an array), and look,
（看，我创建了一个数组）
I'm sending it a message right away. Yeah, I didn't have to
我紧接着给数组发送了一个消息
put it into another var, by the way, I could have but,
我没必要声明另一个变量，尽管我可以那样做
I just want all be on one line here. I created this array and
但是在这里我更希望只用一行代码。我创建了这个数组
I'm sending it the message filter and
然后给它发送消息 filter
look what I'm providing for the argument there.
仔细看参数这里我写的是什么
That include element it has an underbar, so, you don't have
因为 includeElement 的外部参数名有下划线，所以没必要

English: 
to actually put the include     
element column in there. So,    
what am I putting in there?     
That's a closure. So            
that means, it's a function.    
Now, Swift knows that this is   
a function that                 
returns a bool. So              
I don't have to put the word    
return in there. I can use      
dollar zero to be the one and   
only argument to the function.  
And I'm just going              
to check and                    
see if dollar zero is greater   
than 20, in other words,        
is this a big number. So I get  
back an array which has only    
47 and 118 in it, because I've  
filtered out all the things     
where the value's not greater   
than 20. Imagine writing        
this line of code without       
filter. You're gonna have       
to a four loop. You're gonna    
have to create another array.   
You're gonna have to run        
this little function,           
call this function,             
create a new array and          
add, append thing to do it.     
It's at least four or           
five lines of code. And         
here you get it in one line of  
code, okay? So you see how      
closure there has helped us.    

Chinese: 
to actually put the include element column in there. So,
真的写上 includeElement 这个参数名
what am I putting in there? That's a closure. So
所以我在这里填入的是什么？是一个闭包
that means, it's a function. Now, Swift knows that this is
这意味着，它是个函数。Swift 知道它
a function that returns a bool. So
是个函数，而且会返回布尔值
I don't have to put the word return in there. I can use
所以我没必要在闭包里加上 return
dollar zero to be the one and only argument to the function.
我可以用 $0 代表闭包的第一个也是唯一的一个参数
And I'm just going to check and
我接下来要检查
see if dollar zero is greater than 20, in other words,
$0 是否比 20 大，也就是说
is this a big number. So I get back an array which has only
检查它是不是个“大数字”。然后我取得了一个新数组
47 and 118 in it, because I've filtered out all the things
里面只有 47 和 118，因为我已经把所有
where the value's not greater than 20. Imagine writing
不满足大于 20 这个条件的数都过滤掉了。想象一下
this line of code without filter. You're gonna have
如果不依靠 filter 来实现这行代码
to a for loop. You're gonna have to create another array.
你可能要写个 for 循环，然后创建一个新数组
You're gonna have to run this little function,
然后执行这个小函数
call this function, create a new array and
调用这个函数，创建新数组
add, append thing to do it. It's at least four or
然后把符合条件的加进去
five lines of code. And here you get it in one line of
至少也要四五行代码。用了 filter，只用一行代码就实现了
code, okay? So you see how closure there has helped us.
闭包是如何帮我们实现这个功能的？你们理解了吗

Chinese: 
This is also much more readable cuz you can read this
这也让代码更具可读性
like this: Let the big numbers equal this array, but
可以这样读：让 bigNumbers 等于这个数组
filter for things there are greater than 20.
但是只要其中比 20 大的
That reads nicely, so I'm just clear.
这样读起来太顺了，表达清晰
It's very easy to understand what's going on here.
非常容易让人理解这行代码在做什么
So here's another one. It's called map. What does map do?
另一个方法，叫做 map，它是做什么的？
It takes a closure, or a function. And
它也接受一个闭包，或者说一个函数
it executes that function in order to transform each
它会执行那个函数
of the elements in the array you're sending map to,
将你传入数组的每个元素进行转化
to a new array.
然后输出到一个新数组
Now that transformation could be anything that a function
这种转化可以是任何形式的，只要通过函数能做到
can do. And you can convert it to any new type you want.
甚至可以转化为任何你想要的新类型
Although it's one function, so it
但是它是一个函数
coverts everything to the same type. So you could use it for
它只能把所有东西转化为同一个类型
type conversions like I have here. I've taken 1,
你可以用它来实现类型转化。例如这里
2, 3 and mapped it to the string versions of 1, 2, 3, so
我把数字 1，2，3 映射成字符串形式的 "1"，"2"，"3"
now I have the new array with strings in it. String of 1,
现在我得到了一个新数组，包含字符串的数组 ["1"，"2"，"3"]
string of 2, string of 3. That's a trivial mapping.
这只是个意义不大的映射
But you can imagine much more powerful mappings where you
但你可以想象下功能更加强大的映射
take each element of the array, and
对数组的每个元素

English: 
This is also much more          
readable cuz you can read this  
like this: Let the big          
numbers equal this array, but   
filter for things there         
are greater than 20.            
That reads nicely,              
so I'm just clear.              
It's very easy to understand    
what's going on here.           
So here's another one. It's     
called map. What does map do?   
It takes a closure,             
or a function. And              
it executes that function       
in order to transform each      
of the elements in the array    
you're sending map to,          
to a new array.                 
Now that transformation could   
be anything that a function     
can do. And you can convert     
it to any new type you want.    
Although it's one function,     
so it                           
coverts everything to the same  
type. So you could use it for   
type conversions like I         
have here. I've taken 1,        
2, 3 and mapped it to the       
string versions of 1, 2, 3, so  
now I have the new array with   
strings in it. String of 1,     
string of 2, string of 3.       
That's a trivial mapping.       
But you can imagine much more   
powerful mappings where you     
take each element               
of the array, and               

Chinese: 
call some complicated function on it, and get the result into
调用非常复杂的函数，取得结果
a new array. So by creating a really powerful argument there
放入新数组。这需要创建一个非常强大的函数作为参数
instead of String($0), something more powerful, you
替代 String($0)
can really have one line of code that's really expressive.
你可以创造出意义丰富的单行代码
It can do a lot of things. One thing about this one: notice
可以做很多事情。注意这个地方
that after the word map, there's no parentheses,
map 的后面没有小括号
no open parentheses. Did you notice that?
没有左半小括号，注意到了吗？
You see the difference between filter and map, okay?
你们是否注意到了 filter 和 map 的区别
When I called filter, I said open parentheses,
当我调用 filter 时，我在后面写了个小括号
open curly brace, the function, curly brace, close
然后是大括号，函数，大括号结束，小括号结束
parentheses. Here I just say, { String$0}, no parentheses.
但是 map 这里，我只是用了 { String($0) }，没有小括号
And this is what's called the trailing closure syntax. You
这种语法叫做尾随闭包
are allowed to have closures that are the last argument to
当闭包作为最后一个参数时
a function. The outside of the parentheses of that function,
你可以把闭包放到函数的参数部分的括号的外边
if they're trailing, see they're trailing the call. And
如果是尾随闭包，它们跟在函数调用的尾部
in fact, if there's only one argument and
实际上，如果只有一个参数
it's closure, you don't need the parentheses at all.
并且这个参数是闭包，连小括号都不需要了
And that's what happened there with map.
这种情形就是 map 这行代码这样
I'm just saying map, parentheses get rid of them.
只是说 map，省略了小括号

English: 
call some complicated function  
on it, and get the result into  
a new array. So by creating a   
really powerful argument there  
instead of String($0),          
something more powerful, you    
can really have one line of     
code that's really expressive.  
It can do a lot of things. One  
thing about this one: notice    
that after the word map,        
there's no parentheses,         
no open parentheses.            
Did you notice that?            
You see the difference          
between filter and map, okay?   
When I called filter,           
I said open parentheses,        
open curly brace, the           
function, curly brace, close    
parentheses. Here I just say,   
{ String$0}, no parentheses.    
And this is what's called the   
trailing closure syntax. You    
are allowed to have closures    
that are the last argument to   
a function. The outside of the  
parentheses of that function,   
if they're trailing, see        
they're trailing the call. And  
in fact, if there's             
only one argument and           
it's closure, you don't need    
the parentheses at all.         
And that's what happened        
there with map.                 
I'm just saying map,            
parentheses get rid of them.    

English: 
Just put the closure there,     
trailing. And                   
that also results in            
some pretty cool looking        
code right here, you see that?  
So you can use that anywhere    
that a closure is the last      
argument of function.           
You can take it outside of the  
curly braces. Cuz you already   
got the curly braces, and       
that's why they do it.          
You don't really need the       
parentheses around it as well.  
So put that at the end.         
And put all the rest of the     
arguments, if you had them,     
inside the parentheses right    
before. This last one, I won't  
go into the details, but        
it's a similar kind of thing.   
Reduce: what reduce does is     
it takes an entire array and    
reduces it to a single value.   
So here I'm reducing it by      
adding all the numbers in the   
array up. So my closure is $0   
+ $1, because the argument it   
takes is a function that takes  
two elements. One of them is    
an element from the array and   
the other is the answer so      
far, and                        
then it returns the new answer  
so far. So it just executes     
that function over and          
over and over on the arrays.    
By the way, notice that I       
can say this as sum = [1,       

Chinese: 
Just put the closure there, trailing. And
把闭包跟在后面
that also results in some pretty cool looking
产生了像这行代码一样的很酷的效果
code right here, you see that? So you can use that anywhere
你们理解了吗？你们可以在任何地方
that a closure is the last argument of function.
用这个语法，只要最后一个参数是函数
You can take it outside, just put the curly braces. Cuz you already
你可以把闭包从小括号中提出来，只留下大括号这部分
got the curly braces, and that's why they do it.
因为已经有大括号扩起来了，所以语法允许
You don't really need the parentheses around it as well.
周围的小括号也不需要了
So put that at the end.
把闭包直接放在尾部
And put all the rest of the arguments, if you had them,
如果有其他参数的话
inside the parentheses right before. This last one, I won't
仍然把它们放在小括号内。最后一个
go into the details, but it's a similar kind of thing.
我不会深入讲解，不过这个和前面的 map 是类似的
Reduce: what reduce does is it takes an entire array and
reduce，它的功能是将整个数组
reduces it to a single value. So here I'm reducing it by
变成一个值，这里我把
adding all the numbers in the array up. So my closure is $0
整个数组的数字都加起来，闭包写作 $0 + $1
+ $1, because the argument it takes is a function that takes
因为这个参数是有两个参数的函数
two elements. One of them is an element from the array and
其中一个是数组中的一个元素
the other is the answer so far, and
另一个是目前为止累计的结果
then it returns the new answer so far. So it just executes
然后它返回新的结果
that function over and over and over on the arrays.
所以 reduce 对数组不断地执行这个函数
By the way, notice that I can say this as sum = [1,
注意到了吗，我也可以写成 let sum = [1,2,3].reduce(0, +)

English: 
2, 3].reduce(0, +) which is     
my starting so far value.       
Which I haven't added a name    
on, so it starts at 0 and       
then I can say plus. The        
reason I can say plus right     
there at the bottom line,       
is because plus                 
in Swift is not some kinda      
weird built-in thing,           
it's just a function. It's      
a function that happens to be   
declared in a way that says,    
this is a function, but         
it's two arguments it's         
going either side of it.        
It's called an infix            
operator on a function. So      
since plus is just a function,  
and                             
I'm taking a function           
as an argument,                 
as long as it's a function      
that takes two arguments and    
returns one, which is exactly   
what plus does, it works        
there. We could have done that  
in our calculator brain, too.   
Remember all that closures      
we were doing ($0* $1),         
that could've just been *),     
($0+$1), that could've just     
been +. Cuz + is a function     
that takes two doubles and      
returns a double. Plus also     
know how to plus other types,   

Chinese: 
2, 3].reduce(0, +) which is my starting so far value.
0 代表初始的迭代值
Which I haven't added a name on, so it starts at 0 and
它没有参数名，所以会从零开始
then I can say plus. The reason I can say plus right
然后我可以只写个加号，最下面这行代码
there at the bottom line, is because plus
可以直接写个加号的原因是
in Swift is not some kinda weird built-in thing,
加号在 Swift 中不是什么特殊的内置的符号
it's just a function. It's a function that happens to be
它仅仅是个函数。是这样一个函数
declared in a way that says, this is a function, but
它是这样声明的，这是个函数
it's two arguments it's going either side of it.
它的两个参数就是加号两侧的值
It's called an infix operator on a function. So
这叫做 infix（中缀）操作符函数
since plus is just a function, and
因为 + 是个函数
I'm taking a function as an argument,
我把一个函数作为这里的参数
as long as it's a function that takes two arguments and
因为它是一个接受两个参数
returns one, which is exactly what plus does, it works
返回一个值的函数，就和加法运算是一致的
there. We could have done that in our calculator brain, too.
所以它可以用在这里，也可以用在 CalculatorBrain 中
Remember all that closures we were doing ($0* $1),
还记得那些形如 $0 * $1 的闭包吗
that could've just been *), ($0+$1), that could've just
它可以被简化为 *，$0 + $1 可以被简化为 +
been +. Cuz + is a function that takes two doubles and
因为 + 是一个函数，接受两个 Double 作为参数
returns a double. Plus also know how to plus other types,
返回一个 Double，+ 也懂得怎么操作其他类型

Chinese: 
ints. And it even knows how to plus and into a float,
比如 Int，Float 也可以
for example, etc. You can plus strings together.
你还可以对两个 String 相加
So that was just a little aside just to give you
再说就有点远了，这里只做简单的介绍
an introduction there. You're gonna start seeing a lot of
你还会看到很多方法
methods that take functions as arguments.
它们的参数是有两个参数的函数
So I want you to start to get comfortable with that.
我希望你们逐渐适应这种方式
Okay, dictionary. So we learned a lot about dictionary
好了，下面讲 Dictionary（字典）。在第一讲中
in our first lecture. Dictionary also has this
我们已经学了不少有关字典的知识了
special declaration syntax, which is open square bracket
字典也有这种特殊的声明语法
key type colon value type closed square bracket. So
左半方括号，键类型，冒号，值类型，右半方括号
those two things in yellow are equivalent.
所以两个标注为黄色的部分是等价的
And the one on the bottom seems to be the preferred
目前第二个好像更受欢迎一些
one these days. So you know you can create a dictionary.
你们已经知道了能创建一个字典
By the way, I show you creating dictionaries from
我这里展示的是如何通过常量
kind of constant values here.
来创建一个字典
But you can create a dictionary just by saying,
但是你也可以先创建空字典
let d equal dictionary. Open parenthesis,
比如 let d = [String:Int]()
close parenthesis. And if you say var d
或者是创建可变的字典的变量
equals dictionary, then now you can start appending items
比如 var d = [String:Int]()
onto it because you get an empty dictionary to start. But
可以之后再往里面加东西

English: 
ints. And it even knows how     
to plus and into a float,       
for example, etc.               
You can plus strings together.  
So that was just a little       
aside just to give you          
an introduction there. You're   
gonna start seeing a lot of     
methods that take               
functions as arguments.         
So I want you to start to       
get comfortable with that.      
Okay, dictionary. So we         
learned a lot about dictionary  
in our first lecture.           
Dictionary also has this        
special declaration syntax,     
which is open square bracket    
key type colon value type       
closed square bracket. So       
those two things in             
yellow are equivalent.          
And the one on the bottom       
seems to be the preferred       
one these days. So you know     
you can create a dictionary.    
By the way, I show you          
creating dictionaries from      
kind of constant values here.   
But you can create              
a dictionary just by saying,    
let d equal dictionary.         
Open parenthesis,               
close parenthesis.              
And if you say var d            
equals dictionary, then now     
you can start appending items   
onto it because you get an      
empty dictionary to start. But  

English: 
here I'm starting my            
dictionary with stuff in it.    
That probably should say        
var pac12teamRankings           
because two lines later I say   
pac12teamRankings sub Cal       
equals 12. Note also that       
when I try to get the ranking   
of Ohio State, it returns nil.  
And we know that when we        
use square brackets to get      
something out of                
the dictionary, it returns      
an optional of our value type.  
Our value type here is ints,    
so it's gonna return            
an optional int.                
Alright, enumeration.           
A dictionary is also            
a collection and thus can be    
sequenced. So you can do for    
in on it. Of course,            
a dictionary has keys and       
values. So we need a tuple      
to do our enumeration for       
the tuple key common value      
in the dictionary. And          
then it'll go through and       
key in value will be set.       
It's a perfectly                
straightforward way             

Chinese: 
here I'm starting my dictionary with stuff in it.
这里我初始化字典时就包含了一些内容
That probably should say var pac12teamRankings
这里应该用 var pac12teamRankings 而不是 let
because two lines later I say pac12teamRankings sub Cal
因为隔了两行代码之后
equals 12. Note also that
我用了 pac12teamRankings["Cal"] = 12
when I try to get the ranking of Ohio State, it returns nil.
另外注意我尝试获取键为 "Ohio State" 的值，返回的是 nil
And we know that when we use square brackets to get
我们知道当用方括号
something out of the dictionary, it returns
在字典中查询某个键时
an optional of our value type. Our value type here is ints,
返回的是值类型的可选类型，这里我们的值类型是 Int
so it's gonna return an optional int.
所以返回的是 Int?
Alright, enumeration. A dictionary is also
下面是字典的枚举。字典也是一个 Collection
a collection and thus can be sequenced. So you can do for
因此也是 Sequence，所以可以用 for...in 循环
in on it. Of course, a dictionary has keys and
字典包含键和值
values. So we need a tuple to do our enumeration for
所以我们要用一个元组来枚举
the tuple key common value in the dictionary. And
写作 for (key, value) in dictionary
then it'll go through and key in value will be set.
然后这个循环就开始了，会遍历所有的键值对
It's a perfectly straightforward way
用这种方式对字典进行枚举或迭代

Chinese: 
to enumerate or iterate over a dictionary. Okay,
很完美，而且容易书写
String. So string, you would think, is the simplest class
String，你可能会认为
in all of any language. It's just a string, right?
String 是所有编程语言中最简单的类，它仅仅是个字符串
Well, that turns out not to be so true. When you think of
但是这种想法可能不那么正确
a string that represents every language in the entire world,
想象一下当一个字符串可以表达世界上所有语言的时候
all of a sudden it got real complicated real fast.
它突然间就变得复杂了
Because some languages are ideographic. Some languages go
因为一些语言是表意的
right to left instead of left to right. Some languages have
还有一些语言是从右往左书写的
a lot of diacritic marks and accents in them. Some don't.
一些语言有很多变音符或重音符，而另外一些没有
Most languages don't use the same alphabet as we use.
绝大多数语言和我们用的字母表不一样
So string is super complicated,
所以字符串其实非常复杂
this is a very complicated class. Now string tries
这是一个非常复杂的类
its best and does a pretty good job of simplifying it for
String 尽其所能让我们操作字符串变得容易
your use. But the complexity is still there. Now the most
但是复杂性还是存在的
important complexity about a string is that representing
String 最复杂的是
a string is not always one character equals one
显示的每一个字符

English: 
to enumerate or iterate         
over a dictionary. Okay,        
String. So string, you would    
think, is the simplest class    
in all of any language.         
It's just a string, right?      
Well, that turns out not to     
be so true. When you think of   
a string that represents every  
language in the entire world,   
all of a sudden it got real     
complicated real fast.          
Because some languages are      
ideographic. Some languages go  
right to left instead of left   
to right. Some languages have   
a lot of diacritic marks and    
accents in them. Some don't.    
Most languages don't use        
the same alphabet as we use.    
So string is super              
complicated,                    
this is a very complicated      
class. Now string tries         
its best and does a pretty      
good job of simplifying it for  
your use. But the complexity    
is still there. Now the most    
important complexity about      
a string is that representing   
a string is not always          
one character equals one        

English: 
internal representation unit.   
Now the units, the kind of      
thing that's used to represent  
strings on the inside,          
are Unicodes. I had you skip    
that reading in assignment      
one, I'm putting it in for      
assignment two.                 
It's really not that critical   
that you understand it.         
I think it's very interesting,  
though, so                      
you probably want to read it.   
But the thing about Unicodes    
is it's not one Unicode         
equals one character.           
In fact, if you have like a     
little emoji of a dog barking,  
that might be three Unicode     
characters. It's only one with  
regards to what you perceive    
to be a character. Or           
even more simply, the example   
I have here, the word cafe.     
It's got e accent aigu on       
the end, right, it's a French   
word, e accent aigu.            
That could be four Unicodes,    
because there is a Unicode for  
e accent aigu.                  
Or it could be five. It could   
be the e with another Unicode   
character that says put         
an accent on that previous      
character. So, when you have    
this kind of unknown how many   

Chinese: 
internal representation unit. Now the units, the kind of
并不是都能用一个字节表示的
thing that's used to represent strings on the inside,
String 内部用来表达一个字符串的编码
are Unicodes. I had you skip that reading in assignment
叫做 Unicode。在作业一中，我让你们跳过阅读这部分
one, I'm putting it in for assignment two.
现在我把这部分放在了作业二中
It's really not that critical that you understand it.
理解这部分内容并没有那么重要
I think it's very interesting, though, so
但是我觉得这是个很有趣的东西
you probably want to read it. But the thing about Unicodes
所以你可能愿意去阅读这些
is it's not one Unicode equals one character.
Unicode 的一个特点是，一个 Unicode 不等价于一个字符
In fact, if you have like a little emoji of a dog barking,
比如有一个类似狗叫的表情
that might be three Unicode characters. It's only one with
它很可能是由三个 Unicode 字符表达的
regards to what you perceive to be a character. Or
但看起来，它就是一个字符
even more simply, the example I have here, the word cafe.
来看个更简单的例子，café 这个单词
It's got e accent aigu on the end, right, it's a French
它的结尾有个闭音符，它是一个法语词
word, e accent aigu. That could be four Unicodes,
以 é 结尾。这个词可能是由 4 个 Unicode 构成的
because there is a Unicode for e accent aigu.
有一个单独的 Unicode 代表 é
Or it could be five. It could be the e with another Unicode
也有可能是由 5 个 Unicode 构成的。可能是 e 加上另一个
character that says put an accent on that previous
表达“给前面那个字符加上闭音符”这样含义的 Unicode
character. So, when you have this kind of unknown how many
当你不知道到底有多少字符来表达它的时候

Chinese: 
characters it represents, you need a new abstraction
你需要一个新的抽象概念
to represent what we perceive as humans to be a character.
来表达我们人类认知上的字符
Even that is difficult to truly define, when you think
要针对世界上所有语言，定义出这种抽象概念非常困难
of all the languages in the world. It's easy in English,
只是针对英语的话很简单
though. So that's really how we're gonna interact with
这就是我们使用 String 的方法
strings: to try to think of them in terms of characters.
把它视作一串人类认知上的字符
But a string itself is not actually
但是 String 本身并不是
a collection of characters.
单纯的字符的集合
A string is a more powerful internal structure,
String 是一个内部非常强大的结构体
it's got all the Unicodes in there and all that stuff,
它包含了一串字符中所有的 Unicode 和其他东西
it's not quite that. And that makes for a little bit of
和你想象的不太一样
complication as you're gonna see. Now, you can't; String is
因此在使用 String 的时候还有其他不便之处
indexable which means you can use the open square brackets
虽然 String 可以用类似索引数组的形式
just like you can in array to get one of the characters.
通过方括号取得字符串中的某个字符
The only rub is what I said on the other slide that index
我之前提到过会带来的麻烦是
is not an int. So if you have the word hello,
String 的索引不是一个 Int 类型。你有一个单词 hello
it's not like you can say, hello[1] equals e.
你没法通过类似 hello[1] 的方式来取得字符 e
You can't do it that way because it might,
你没法那样做，因为可能有这种情况
if it was cafe then cafe sub 3.
如果这个单词是 café，然后取 café[3]

English: 
characters it represents,       
you need a new abstraction      
to represent what we perceive   
as humans to be a character.    
Even that is difficult to       
truly define, when you think    
of all the languages in the     
world. It's easy in English,    
though. So that's really how    
we're gonna interact with       
strings: to try to think of     
them in terms of characters.    
But a string itself             
is not actually                 
a collection of characters.     
A string is a more powerful     
internal structure,             
it's got all the Unicodes in    
there and all that stuff,       
it's not quite that. And        
that makes for a little bit of  
complication as you're gonna    
see. Now, you can't string, is  
indexable which means you can   
use the open square brackets    
just like you can in array to   
get one of the characters.      
The only rub is what I said     
on the other slide that index   
is not an int.                  
So if you have the word hello,  
it's not like you can say,      
hello[1] equals e.              
You can't do it that            
way because it might,           
if it was cafe                  
then cafe sub 3.                

Chinese: 
It's not clear. You want a character at that point
String 并不清楚你想要的是第四个字节还是整个字符
so you've got to make sure you get the right index in there
同时你还要确保自己提供的了正确的索引
because that index behind the scenes can be quite
因为这个索引位置的背后，实际上非常复杂
complicated. There's this other struct for it, which is
因此产生了另外一个结构体，叫做 String.Index
called a String.Index. So let's say I had a string,
我有一个字符串
which I'm gonna call s and I'm gonna put hello into there.
命名为 s，然后我把 "hello" 赋值给它
Now, what if I wanted s[0] now, I can't do s[0],
现在，我要取得 s[0]，当然没法写作 s[0]
because we don't index strings by integers but
因为没法通过整数来索引字符串
let's say I want that. How do I get it? Well,
我要那个字符，到底怎么拿到它？
I start by calling this var, again using this var and
首先我操作 s，调用 s.startIndex
string called startIndex, okay? It gives us
它返回给我一个 String.Index 类型的值
a string.index. It's very important, we need to get
下面很关键，我们需要一个变量保存这个 String.Index
a hold of a string.index because the way we're gonna
因为我们接下来要在字符串中
move around in string is by taking index we know and
以这个已知的索引为基准
moving forward or backward by character, by human
以人类认知的字符为单位向前或者向后移动
understandable character. Not by Unicodes, because we
不是以 Unicode 为单位
don't know how many Unicodes there are per character but
因为我们不知道每个字符到底用了几个 Unicode 来表达
by character, we're gonna be moving back and forth.
我们只根据字符来前后移动
So we start with this first one.
所以我们从第一个开始
And so now I can create a variable firstChar which is of
现在我创建一个变量叫做 firstChar
this type Character,
它是 Character 类型的

English: 
It's not clear that you want    
a character at that point, and  
so you've got to make sure you  
get the right index in there    
because that index behind       
the scenes can be quite         
complicated. There's this       
other struct for it, which is   
called a string.index.          
So let's say I had a string,    
which I'm gonna call s and I'm  
gonna put hello into there.     
Now, what if I wanted s[0]      
now, I can't do s[0],           
because we don't index          
strings by integers but         
let's say I want that.          
How do I get it? Well,          
I start by calling this var,    
again using this var and        
string called startIndex,       
okay? It gives us               
a string.index. It's very       
important, we need to get       
a hold of a string.index        
because the way we're gonna     
move around in string is        
by taking index we know and     
moving forward or backward      
by character, by human          
understandable character.       
Not by Unicodes, because we     
don't know how many Unicodes    
there are per character but     
by character, we're gonna       
be moving back and forth.       
So we start with                
this first one.                 
And so now I can create a       
variable firstChar which is of  
this type Character,            

English: 
that human                      
understandable character.       
That's gonna be equal           
s[firstIndex]. So see look,     
I've used square brackets       
to index into a string, but     
I had to use a String.Index     
not an Int. This first index    
I got by asking the string      
"what's your first index"?      
Well this is kinda useless      
because I have to ask           
the string, what's the index    
of your first character and     
then turn around say okay give  
me S of your first character.   
So that's not                   
the interesting thing,          
what if I want the next         
character. If I                 
want the next character, I ask  
the string what's the index of  
the character after your        
first character. And            
it'll give me a new index,      
of its second character and     
now I can get that one. Even    
that is a little bit like,      
my God, you're kidding me,      
this is really how I have to    
do this? What if I wanted       
to go jump ahead though, and    
get the fourth, the fifth       
character, let's say? Well I    
can jump ahead by saying s,     
give me the index of,           
starting at your first index,   
that's four ahead so            
jump four ahead,                
four characters ahead.          
This is all a little            

Chinese: 
that human understandable character.
是人类认知上的字符
That's gonna be equal s[firstIndex]. So see look,
它将被赋值成 s[firstIndex]
I've used square brackets to index into a string, but
看，这里我用了方括号来索引字符串
I had to use a String.Index not an Int. This first index
我必须用 String.Index 而不是 Int 类型
I got by asking the string "what's your first index"?
我得到字符串的第一个索引，还要先问它才行
Well this is kinda useless because I have to ask
这个步骤感觉挺多余的
the string, what's the index of your first character and
我先向字符串索要它的第一个字符的索引之后
then turn around say okay give me S of your first character.
然后又说“好吧，我实际上要的是你的第一个字符”
So that's not the interesting thing,
这种方式一点也不有趣
what if I want the next character. If I
如果我要下一个字符呢?
want the next character, I ask the string what's the index of
如果我要下一个字符，我要对字符串说
the character after your first character. And
“你的第一个字符之后的字符的索引是什么”
it'll give me a new index, of its second character and
它会给我一个新的索引，即它第二个字符的索引
now I can get that one. Even that is a little bit like,
这样我才能拿到第二个字符。这种感觉就像是
my God, you're kidding me,
大地母亲在忽悠着我
this is really how I have to do this? What if I wanted
我真的只能这么做吗?
to go jump ahead though, and get the fourth, the fifth
我想跳过前面的字符，直接取得第四个，第五个怎么办？
character, let's say? Well I can jump ahead by saying s,
我们要这样做：对字符串 s 说
give me the index of, starting at your first index,
“从你的第一个索引开始”
that's four ahead so jump four ahead,
因为要跳到第四个，所以“往前跳四下”
four characters ahead. This is all a little
这样它就前进了四个字符

English: 
tedious and of course this is   
not the actual way that we're   
interacting with strings.       
We're usually looking for       
substrings, okay, or            
subranges of characters or      
we're trying to find            
a character in a string.        
By the way, you can use         
ranges, so I could say          
give me the substring which is  
firstIndex...secondIndex and    
it would give me he.            
A new string which is he, so    
you can use ranges there but    
they have to be string.index    
not ints. So we want            
basically something that        
is a collection of characters.  
A string is not a collection    
of characters so you can't do   
for in, for example, on it.     
You can't even say index(of:).  
Index(of:) is this great        
thing where you can,            
if you have a collection        
of things, you can say give     
me this index of this thing in  
there. You can't even do that   
with a string because it's      
not a collection. Luckily,      
string has a var which will     
give you a collection of its    
characters. And                 
not only is it gonna give       
you a collection of its         
characters that you can for     

Chinese: 
tedious and of course this is not the actual way that we're
这实在够无聊的，当然这不是我们和 String 打交道的常见方式
interacting with strings. We're usually looking for
我们常用的是寻找子串
substrings, okay, or subranges of characters or
或者子串所处的位置
we're trying to find a character in a string.
或者寻找一个字符串中是否存在某个字符
By the way, you can use ranges, so I could say
顺便，在这里你可以用 Range，所以可以说
give me the substring which is firstIndex...secondIndex and
给我 firstIndex...secondIndex 区间的子串
it would give me he. A new string which is he, so
这样它会返回我 "he"。一个新字符串 "he"
you can use ranges there but they have to be string.index
所以这里你可以用 Range，但必须是 String.Index 类型的
not ints. So we want basically something that
而不是 Int 类型的。所以我们更希望的是
is a collection of characters. A string is not a collection
操作一串字符的集合。String 不是字符的集合
of characters so you can't do for in, for example, on it.
所以你没法对它用 for...in 遍历
You can't even say index(of:).
你也没法对它用 index(of:) 方法
index(of:) is this great thing where you can,
index(of:) 对于一个集合而言非常好用
if you have a collection of things, you can say give
你可以说
me this index of this thing in there. You can't even do that
把这个元素的索引找出来
with a string because it's not a collection. Luckily,
但是你没法对 String 这样做，因为它不是 Collection
string has a var which will give you a collection of its
幸运的是，String 有一个变量
characters. And not only is it gonna give
不仅返回给你一个它包含的字符的集合
you a collection of its characters that you can for
你还可以对这个字符集合用

Chinese: 
in over and do index(of:), but the string indexes you get
for...in 循环，或者调用 index(of:)，而且你通过这个集合
from that collection will match what's in the string. So
索引到的字符和字符串中实际包含的字符是匹配的
you can use this collection of characters to find things in
所以你可以用这个字符集合来查找字符
there, get the index of a character, things like
或者取得某个字符的索引，等等
that. And then use the indexes you find there to go back to
然后拿着你找到的索引，对原字符串说
your string and say, okay now give me a substring. So
现在给我一个指定的子串
characters is the name of this var on string. So for example,
String 下的这个变量名字叫做 characters
if I want to iterate over all the characters one by one,
举例来说，如果我要所有的字符，一个挨一个
do a for loop over them I can say, for c:,
用 for 循环遍历它们，我可以这样说
which will be of type character,
for c: Character in s.characters
by the way, in s.characters. I can't say for c: in s, for
我不能说 for c in s
c: in s.characters. And that's just gonna call my for
必须说 for c in s.characters
loop once with each character. Question? Yeah,
这样就能通过 for 循环变量遍历每一个字符了。有什么问题？
great question. So if I do this over cafe,
问得好！如果我对 café 做 for 循环
what am I gonna get? I'm gonna get four characters, okay,
我会得到什么？我会得到四个字符
because that E-accent-agu that they use is considered in our
因为 é 被视作
human perception one character.
一个人类认知中的字符
I'll get four characters. So there is a character.
我会得到四个字符，有一个 Character
Characters are struct, right? And in the character
Character 是结构体，Character 中刚好

English: 
in over and do index(of:), but  
the string indexes you get      
from that collection will       
match what's in the string. So  
you can use this collection of  
characters to find things in    
there, get the index of         
a character, things like        
that. And then use the indexes  
you find there to go back to    
your string and say, okay       
now give me a substring. So     
characters is the name of this  
var on string. So for example,  
if I want to iterate over all   
the characters one by one,      
do a for loop over              
them I can say, for c:,         
which will be of                
type character,                 
by the way, in s.characters.    
I can't say for c: in s, for    
c: in s.characters. And         
that's just gonna call my for   
loop once with each character.  
Question? Yeah,                 
great question.                 
So if I do this over cafe,      
what am I gonna get? I'm gonna  
get four characters, okay,      
because that E-accent-agu that  
they use is considered in our   
human perception                
one character.                  
I'll get four characters.       
So there is a character.        
Characters are struct,          
right and in the character      

Chinese: 
there is a character that represents e-accent-agu.
有一个能代表 é
No matter how it's represented in the string,
不论它在 String 内部是怎么表达的
in the string it might be two characters, it might be one,
也许是两个字符，也许是一个
it doesn't matter. You're gonna get the one character
都没有关系。因为你得到的是一个能代表它的 Character
for it, so that's a really good question. How would I
这个问题问得好
know how many characters there are in a string? Again,
我怎么才能知道到底一个字符串中有多少字符？
from the user perspective. s.characters.count,
人类认知的字符。s.characters.count
not s.length or something, s.characters.count,
不是 s.length 或者其他什么，就是 s.characters.count
the count of the characters in the collection of characters
意思是在这个字符串的字符集合中，元素的数量
for this string. Also, what if I want to find the first space
那么如果我要找字符串中的第一个空格怎么做？
in a string? Got a string with a bunch of words, I wanna find
有个字符串，它包含很多单词
the first space. I would say s.characters.index(of: " ").
我要找第一个空格。我应该用 s.characters.index(of: " ")
And that's giving me a string.index(of: " ") that
这会返回给我空格在字符集合中的索引
collection of characters. I can then use that string in
然后我可以利用这个索引
that index though to go back to my string and do something.
回到原字符串中做些什么事情
Maybe insert something there or
比如插入一些新字符
delete the word that's right after the space or insert
删除空格之后的那个单词
another space. I'll have the index into the string now.
或者插入另外一个空格。总之，我将会得到字符串的索引
String is a value type, so when you do let versus var,
String 是一个值类型，来对比下用 let 或 var 声明时的不同

English: 
there is a character that       
represents e-accent-agu.        
No matter how it's              
represented in the string,      
in the string it might be two   
characters, it might be one,    
it doesn't matter. You're       
gonna get the one character     
for it, so that's a really      
good question. How would I      
know how many characters        
there are in a string? Again,   
from the user perspective.      
s.characters.count,             
not s.length or something,      
s.characters.count,             
the count of the characters in  
the collection of characters    
for this string. Also, what if  
I want to find the first space  
in a string? Got a string with  
a bunch of words, I wanna find  
the first space. I would say    
s.characters.index(of: " ").    
And that's giving me            
a string.index(of: " ') that    
collection of characters.       
I can then use that string in   
that index though to go back    
to my string and do something.  
Maybe insert                    
something there or              
delete the word that's right    
after the space or insert       
another space. I'll have        
the index into the string now.  
String is a value type, so      
when you do let versus var,     

English: 
if you do let you cannot        
do things like append on to     
the string cuz it's immutable.  
Most strings in Swift           
are immutable, that makes       
it super high performance.      
But if you have a var you can   
do reading plus equals there    
and so I can have hello there.  
It doesn't have any effect on   
hello, the let one because      
that's immutable, right? Okay,  
so I can't do that. And         
I can use the characters to     
manipulate strings in really    
powerful ways. I can, I don't   
have time to talk about all of  
it, this is where you really    
do need to read your reading    
assignment carefully. But for   
example if I want to insert     
the word you into hello there,  
so it says hello you there,     
okay, I would just get the,     
find the first base by doing    
characters.index(of: " "),      
which I showed you on the       
previous slide. Then there's    
a method in string called,      
insert the constant,            
the content of this             
collection of characters        
at this location, this          
string.index. So, when I want   
a collection of characters      
that represents " you", I say,  

Chinese: 
if you do let you cannot do things like append on to
如果你用 let 声明，就没法做类似于 append 之类的操作
the string cuz it's immutable. Most strings in Swift
因为它是不可变的，Swift 中绝大多数字符串都是不可变的
are immutable, that makes it super high performance.
这使得它效率非常高
But if you have a var you can do greeting plus equals there
但是如果你用 var 声明 greeting，可以 greeting += " there"
and so I can have hello there. It doesn't have any effect on
然后得到字符串 "hello there"。这种操作不会改变 hello
hello, the let one because that's immutable, right? Okay,
因为 hello 是 let 声明的，不可变，明白了吗？
so I can't do that. And I can use the characters to
所以我没法对 hello 做类似的操作。我还可以通过 characters
manipulate strings in really powerful ways. I can, I don't
对字符串做出一些更强大的操作
have time to talk about all of it, this is where you really
我没时间讲解所有字符串操作相关的内容
do need to read your reading assignment carefully. But for
剩下的部分需要你们课后认真阅读
example if I want to insert the word you into hello there,
我就讲一个例子，如果我要在 hello 和 there 中间
so it says hello you there, okay, I would just get the,
插入一个单词 you 变成 hello you there
find the first space by doing characters.index(of: " "),
我要先通过 characters.index(of: " ") 找到第一个空格
which I showed you on the previous slide. Then there's
这个用法上一页我已经展示了
a method in string called, insert the constant,
然后 String 有个方法叫做 insert(contentsOf:at:)
the content of this collection of characters
这个方法可以在指定的位置插入复数字符构成的集合
at this location, this string.index. So, when I want
指定的位置是 String.Index 类型
a collection of characters that represents " you", I say,
我要插入代表 " you" 的字符集合

Chinese: 
" you".characters, because it's the .characters, and
所以这个应该写作 " you".characters
it gives me a collection of characters for that string. So
因为 .characters 是 " you" 对应的字符集合
it seems a little weird but It actually turns out to work out
这用法好像有点奇怪，但它确实能达到我要的结果
pretty well. And there's a billion other functions,
Swift 中还有非常多的函数
in Swift, many, many, many,
非常，非常，非常多
I can't talk about them all.
我没法每个都讲
Notice I say if let firstSpace, because that might
注意到这里我用了 if let firstSpace，因为有可能
return nil if it couldn't find it. So I wouldn't do it there,
没找到指定的内容，返回 nil 就不执行大括号内的代码
I wouldn't insert it there. Yeah a bunch of other things
也就不会对原字符串进行插入操作。这里还有一大堆其他方法
checking where strings have prefixes or not.
这个方法可以检查字符串是否包含某个前缀
You can replace subrange, of course you have to find
你可以替换子串，当然替换之前
the range which usually you're gonna have to look at that
你通常要通过访问字符串的字符集合
collection of characters to find the ranges you wanna
来确定要替换的范围
replace things etc. Even cool methods like components
更有趣的一个方法，你可以通过 components(separatedBy:)
separated by string will take a string that has like comma or
对包含逗号或者其他分隔字符的字符串
separated values and grab all of the values and
拆分得到所有子串
put them in an array which is kinda fun. Okay so
然后返回一个包含这些子串的数组
a lot: string has dozens and dozens of methods, you really
讲了这么多，String 还有很多很多方法
need to familiarize yourself. If you don't take the time to
你需要去熟悉它们
familiarize yourself with those thing in strings.
如果你不在这上面花时间的话
Then I guarantee you're going to be writing a program and
我保证有一天你会遇到这种情况，你在写一个程序的时候

English: 
" you".characters, because      
it's the .characters, and       
it gives me a collection of     
characters for that string. So  
it seems a little weird but It  
actually turns out to work out  
pretty well. And there's        
a billion other functions,      
in Swift, many, many, many,     
I can't talk about them all.    
Notice I say if let             
firstSpace, because that might  
return nil if it couldn't find  
it. So I wouldn't do it there,  
I wouldn't insert it there.     
Yeah a bunch of other things    
checking where strings          
have prefixes or not.           
You can replace subrange,       
of course you have to find      
the range which usually you're  
gonna have to look at that      
collection of characters to     
find the ranges you wanna       
replace things etc. Even        
cool methods like components    
separated by string will take   
a string that has like calm or  
separated values and            
grab all of the values and      
put them in an array which      
is kinda fun. Okay so           
a lot: string has dozens and    
dozens of methods, you really   
need to familiarize yourself.   
If you don't take the time to   
familiarize yourself with       
those thing in strings.         
Then I guarantee you're going   
to be writing a program and     

Chinese: 
you're going to want to do some string parsing or
需要对字符串进行解析或其他某种操作
something and you're going to write a whole bunch of
你写了一大段代码来完成这个功能
code to do it and then find out there was one method that
然后发现其实只要一个原生的方法
did exactly what you want in the string.
就能实现你想要的功能
There are things in there take closures and
有些方法会接受闭包
do all kinds of fun stuff so
然后做各种有趣的操作
make sure you pay attention to both to string and
所以你要同时留意 String
to the character view which is a collection of characters.
和 String.CharacterView，也就是字符的集合
All right, other classes. This is kind of quick summary here
好了，接下来讲讲其他类。快速过一遍其他重要的类
of other important classes. One is NSObject, NSObject is
第一个是 NSObject，它是
a class. It is the root of all Objective-C classes. An iOS
所有 Objective-C 类的根类
app written before a couple years ago when Swift came out,
Swift 诞生之前的许多年间
all the classes in there would inherit eventually from
iOS 应用中所有类都要继承自 NSObject
NSObject. So NSObject has a base functionality. You do not
NSObject 具有很多基础性的功能
need to subclass from NSObject to make a swift class.
Swift 中的类不需要继承自 NSObject
However there are some really obscure features still left in
但是，iOS 中残留有很多比较复杂的功能
iOS where to expecting a class that inherit from NSObject.
仍然需要使用继承自 NSObject 的类
If we even get to them, I'll show them to you. They're
等用到的时候，我再展示给你们
pretty rare. But that's just so you know what NSObject is.
这种情况不会太多。你们知道 NSObject 是什么就够了
Doesn't really have meaning to you,
这对你们意义不大

English: 
you're going to want to         
do some string parsing or       
something and you're going      
to write a whole bunch of       
code to do it and then find     
out there was one method that   
did exactly what you            
want in the string.             
There are things in             
there take closures and         
do all kinds of fun stuff so    
make sure you pay attention     
to both to string and           
to the character view which is  
a collection of characters.     
All right, other classes. This  
is kind of quick summary here   
of other important classes.     
One is NSObject, NSObject is    
a class. It is the root of all  
Objective-C classes. An iOS     
app written before a couple     
years ago when Swift came out,  
all the classes in there        
would inherit eventually from   
NSObject. So NSObject has a     
base functionality. You do not  
need to subclass from NSObject  
to make a swift class.          
However there are some really   
obscure features still left in  
IOS where to expecting a class  
that inherit from NSObject.     
If we even get to them,         
I'll show them to you. They're  
pretty rare. But that's just    
so you know what NSObject is.   
Doesn't really have             
meaning to you,                 

English: 
cuz you guys are gonna          
be Swift programmers.           
NSNumber is another class,      
it's a generic number           
holder. This is also inherited  
from Objective-C, you can tell  
by the NS there. Until we       
can hold any kind of number,    
floating point, decimal,        
you can even hold a bool,       
since it considers that a       
number where zero is false and  
one is true. Any nonzero        
is true. And you can also       
do type conversions. Again,     
in swift, we're gonna be using  
the actual concrete number      
classes like double an int and  
we'll use their constructors.   
To do type conversion.          
But just so that you know that  
NSNumber is around. Okay,       
date. Super important class.    
Anytime you are representing    
a date or time, you're gonna    
wanna use this date struct.     
And it has a lot of ancillary   
classes that go with it,        
like calendar, date formatter,  
date components like date       
components will tell you        
the month of a date. And        
of course, what the month       
of is of a date depends on      
the calendar it's in, cuz not   
everyone uses a calendar like   

Chinese: 
cuz you guys are gonna be Swift programmers.
因为你们将要成为的是 Swift 程序员
NSNumber is another class, it's a generic number
其次是 NSNumber，是一个通用的数字容器
holder. This is also inherited from Objective-C, you can tell
NS 前缀表明，它也是从 Objective-C 那边继承来的
by the NS there. Until we can hold any kind of number,
它可以持有任何类型的数字
floating point, decimal, you can even hold a bool,
浮点数，小数，甚至是布尔值
since it considers that a number where zero is false and
因为它会把 0 当作 false
one is true. Any nonzero is true. And you can also
把 1 当作 true，非零的都当作 true
do type conversions. Again, in swift, we're gonna be using
你还可以对它做类型转换。不过，再次强调，在 Swift 中
the actual concrete number classes like double an int and
我们更倾向于使用固定的数字类型，如：Double，Int
we'll use their constructors. To do type conversion.
我们通过这些类型的构造器来做类型转换
But just so that you know that NSNumber is around. Okay,
知道 NSNumber 这些就够了
date. Super important class. Anytime you are representing
Date 是一个非常重要的结构体。任何时候
a date or time, you're gonna wanna use this date struct.
你想表达一个日期或时间，都要用到 Date 这个结构体
And it has a lot of ancillary classes that go with it,
而且还有一系列和它相关的辅助结构体
like calendar, date formatter, date components like date
比如 Calendar，DateFormatter，DateComponents
components will tell you the month of a date. And
DateComponents 可以告诉你某个日期对应的月份
of course, what the month of is of a date depends on
当然，还要知道日期所处的历法，才能确定它对应的月份
the calendar it's in, cuz not everyone uses a calendar like
因为不是所有人都和我们用一样的历法

Chinese: 
we do. All right, there's a lot of calendars
世界上有许多历法
all over the Earth that are different than ours.
和我们使用的历法不同
So anytime you're even contemplating putting a date
因此，当你考虑在界面上展示一个日期的时候
anywhere in your UI you need to be using this class.
都应该用这个结构体
Because if you wanna have your app work in anything but
如果你希望你的应用可以在非英语环境下正常工作
English, you're gonna have to format your date, using
你就必须用 DateFormatter 对日期进行格式化
the DateFormatter, in whatever locale your app is running in.
把日期用当地的习惯表达
So date is super important. You would think date is really
Date 非常重要，可能你之前低估了 Date
easy, but no. Date actually has a lot of complexity to it,
实际上 Date 非常复杂
because of all the different ways we represent dates in
因为世界上有许多种表达日期的方式
the world. Same, similar to strings complexity. And
这点和 String 的复杂性是类似的
then there's data, D-A-T-A, that represents a bag of bits.
然后是 Data，D-A-T-A，代表一串二进制数据
Just a bits, bunch of bits in there. Usually this might be
仅仅是一连串的二进制数据
something like an image, the bits of an image, or
它可能是个图片，图片的二进制数据
something like that. Something you get over the the network.
或者其他类似的东西，比如从网络获取的数据
So data is how we represent those.
这些东西我们都用 Data 来表达
Notice that there is a struct, it's a value type.
注意，它是个结构体，是值类型
It gets passed around copy on right. And
它通过值的复制来传递
you'll start seeing data in UI maybe week five or
你们将会在第五或第六周 UI 部分开始接触到它

English: 
we do. All right,               
there's a lot of calendars      
all over the Earth that         
are different than ours.        
So anytime you're even          
contemplating putting a date    
anywhere in your UI you need    
to be using this class.         
Because if you wanna have       
your app work in anything but   
English, you're gonna have      
to format your date, using      
the DateFormatter, in whatever  
locale your app is running in.  
So date is super important.     
You would think date is really  
easy, but no. Date actually     
has a lot of complexity to it,  
because of all the different    
ways we represent dates in      
the world. Same, similar        
to strings complexity. And      
then there's data, D-A-T-A,     
that represents a bag o' bits.  
Just a bits, bunch of bits in   
there. Usually this might be    
something like an image,        
the bits of an image, or        
something like that. Something  
you get over the the network.   
So data is how we               
represent those.                
Notice that there is a struct,  
it's a value type.              
It gets passed around           
copy on right. And              
you'll start seeing data        
in UI maybe week five or        

English: 
six of this class.              
All right, initialization.      
So initialization is            
very complicated. You're        
gonna have to read the reading  
assignment on it eventually.    
I'm gonna give you the really   
fast highlights of it. init     
method, again, we can have      
them on classes or structs.     
They are used to initialize     
any of the properties that we   
didn't initialize with equals   
or using lazy or they were      
optionals. All those are taken  
care of and if there's one      
left, or more than one left,    
then we need an initializer.    
To initialize it. And they're   
kind of a pain in the neck.     
Because, especially for         
classes. For structs,           
they're not a pain in the       
neck. They are perfectly fine.  
Struct, you just have an init   
with whatever argue you want,   
arguments you want.             
And initialize your variables.  
It's all very simple. But for   
classes, it's a little more     
complicated. Now, whether       
you're a struct or a class,     
you can have multiple init.     
And they can have different     
arguments. As long as you give  
them enough arguments to be     
able to initialize all their    
variables, you're good to go.   

Chinese: 
six of this class. All right, initialization.
接下来是 Initialization（构造）
So initialization is very complicated. You're
构造非常复杂
gonna have to read the reading assignment on it eventually.
你们必须完成有关这部分的课后阅读作业
I'm gonna give you the really fast highlights of it. init
我只会帮你们快速过一遍重点
method, again, we can have them on classes or structs.
类或结构体都可以拥有构造器
They are used to initialize any of the properties that we
用来初始化那些
didn't initialize with equals or using lazy or they were
没有使用等号赋值或延时加载，也不是可选类型的属性
optionals. All those are taken care of and if there's one
如果有至少一个属性符合以上特点
left, or more than one left, then we need an initializer.
我们就必须创建一个构造器
To initialize it. And they're kind of a pain in the neck.
这个规则有时很烦人
Because, especially for classes. For structs,
尤其对类而言
they're not a pain in the neck. They are perfectly fine.
对结构体而言，则没有这种烦恼
Struct, you just have an init with whatever argue you want,
结构体中，你会自动得到一个构造器
arguments you want. And initialize your variables.
接受所有需要初始化的属性为参数，并初始化它们
It's all very simple. But for classes, it's a little more
这很简单吧。但是对类而言，就稍微有点复杂了
complicated. Now, whether you're a struct or a class,
不论是类还是结构体
you can have multiple init. And they can have different
都可以拥有多个构造器
arguments. As long as you give them enough arguments to be
并且可以接受不同的参数。只要确保传给它们的参数
able to initialize all their variables, you're good to go.
足够用来初始化它们的全部变量

English: 
So you can have as              
many inits as you want.         
And a lot of classes have       
multiple inits. Meaning on      
kinda how they are being used,  
how they are being created.     
Think of something              
like string.                    
String has an init              
that takes a double.            
It has a string that takes      
another sting if you want to    
make a copy of the string it    
turns out. It takes an init.    
It has all these things that    
you can compare to string.      
Or not all the things           
you compare string but          
a lot of things you can         
compare to a string.            
It has an initialized that it   
will take that as an argument   
for example. Callers execute    
your init by creating           
one of the thing. They just     
put the name of the type and    
parentheses and the arguments   
you want for that init. So      
they pick which of your         
init that they want and         
they call that one              
with those arguments.           
We've seen many examples of     
this in our lecture, so far.    
You get some inits for free.    
If you're a base class, okay,   
you don't inherit               
from anything else.             
You get a free init with no     
arguments. Congratulations.     
So that means, at least,        
people can create you.          
But, again, if you have any     
vars that aren't initialized,   

Chinese: 
So you can have as many inits as you want.
因此你想创建多少构造器都可以
And a lot of classes have multiple inits. Depending on
也确实有很多类都有不止一个构造器
kinda how they are being used, how they are being created.
创建过程取决于使用方式
Think of something like string.
以 String 为例思考一下
String has an init that takes a double.
String 有一个接受 Double 的构造器
It has a string that takes another string if you want to
它还有接受另一个字符串的构造器
make a copy of the string it turns out. It takes an Int.
如果你要一份原字符串的拷贝就可以用这个构造器
It has all these things that you can convert to string.
它还可以接受 Int，以及所有可以转化为字符串的东西
Or not all the things you convert to string but
或许不是所有
a lot of things you can convert to a string.
但是相当多都是可以的
It has an initializer that it will take that as an argument
String 会有对应的构造器，接受对应类型的参数
for example. Callers execute your init by creating
调用者通过执行你的构造器
one of the thing. They just put the name of the type and
来创造一个对应的实例
parentheses and the arguments you want for that init. So
他们可以通过类型名和小括号，传入你要求的参数来构造
they pick which of your init that they want and
他们会选用合适的构造器
they call that one with those arguments.
调用那个构造器，传入指定的参数
We've seen many examples of this in our lecture, so far.
在这门课程中，我们已经遇到过很多这种例子了
You get some inits for free. If you're a base class, okay,
有一些构造器系统会帮你自动生成。如果你有个基类
you don't inherit from anything else.
它没有继承自任何其他类
You get a free init with no arguments. Congratulations.
你会自动得到一个不含参数的构造器
So that means, at least, people can create you.
恭喜你，这意味着起码别人可以创建这个类的实例
But, again, if you have any vars that aren't initialized,
但是，如果你有些变量没被初始化

English: 
you're gonna have to create     
your inits that initialize      
them. Structs are even better.  
They get an init that has all   
of their vars. Now if a struct  
implements even one of its own  
initializers, it stops getting  
this one, this free one.        
You only get the free one if    
you don't do any other ones.    
So it's like the default one.   
And we saw this in              
the lecture also.               
We got the free one in the      
init function, first operand.   
We never wrote that init        
function, we got it for free.   
It just appeared and            
we were able to call it. , so   
structure nice you get          
the basic free init for         
all your vars. What can you     
do inside of a nit? I'm         
gonna start going fast here,    
okay. So here we go. One,       
you can set any properties      
value even if that property     
already had its value set,      
you can reset something else.   
You can set lets. So            
you're gonna have a let that's  
got less x equal 5. You can     
still reset it in your init.    
Your init is allowed to set     
lets. You can call other init   

Chinese: 
you're gonna have to create your inits that initialize
你就必须创建一个构造器来初始化它们
them. Structs are even better. They get an init that has all
结构体更加方便，它们会自动生成一个包含所有变量的构造器
of their vars. Now if a struct implements even one of its own
如果你添加了任何一个自定义的构造器
initializers, it stops getting this one, this free one.
结构体就会失去自动生成的那个构造器
You only get the free one if you don't do any other ones.
只有当你没有添加任何别的构造器时，它才会自动生成一个
So it's like the default one.
它就像是一个默认构造器
And we saw this in the lecture also.
这种情况我们之前也遇到了
We got the free one in the init function, first operand.
我们自动获得了这个 init(function:firstOperand:) 构造器
We never wrote that init function, we got it for free.
我们从来没写过这个方法，完全是自动获得的
It just appeared and we were able to call it, remember that? so
它自然就存在了，我们也确实可以调用它，想起来了吗？
structure is nice you get the basic free init for
所以结构体很方便，你自动就获得了包含所有变量的构造器
all your vars. What can you do inside of a init? I'm
在构造器中可以做什么呢？
gonna start going fast here, okay. So here we go. One,
这部分我会加快速度
you can set any properties value even if that property
首先，你可以给属性赋值，即使它已经被赋过值了
already had its value set, you can reset something else.
你可以重新给变量赋成别的值
You can set lets. So you're gonna have a let that's
还可以初始化 let 声明的常量。比如有一个属性 let x = 5
got lets x equal 5. You can still reset it in your init.
构造器内仍然可以重设它（误：常量不能重新赋值）
Your init is allowed to set lets. You can call other init
所以构造器内只允许对常量属性赋初值

English: 
methods okay in your own class  
or your own struct. And you do  
that by saying self.init with   
whatever the arguments to that  
init method are so init         
methods can call each other.    
In a class,                     
you can call super.init.        
An initializer from             
your super class.               
Of course you need to get       
your super class initialized.   
Now, when we start talking      
about class though,             
and we start talking about      
calling inits in our super,     
and we start thinking           
about inheritance,              
it gets really complicated. So  
let's start thinking about      
class and break this down.      
Let's start with what are you   
required to do in an init for   
a class? in a struct it's       
easy you're just required to    
initialize all your vars        
that aren't initialized. But    
in a class what are you         
required to do? By the time     
it's done you have to have      
initialized all your vars.      
We know that. There are two     
types of initializers.          
A convenience initializer.      
This is only for classes.       
A convenience initializer and   
what's called                   
a designated initializer.       

Chinese: 
methods okay in your own class or your own struct. And you do
你还可以调用这个类或结构体的其他构造器
that by saying self.init with whatever the arguments to that
通过 self.init() 并且传入指定的参数来调用
init method are so init methods can call each other.
所以构造器是能互相调用的
In a class, you can call super.init.
在一个类的构造器中，你还能调用 super.init()
An initializer from your super class.
一个继承自父类的构造器
Of course you need to get your super class initialized.
这是理所当然的，你必须让父类也得以构造
Now, when we start talking about class though,
既然我们现在已经开始讨论类了
and we start talking about calling inits in our super,
并且提到调用父类的构造器
and we start thinking about inheritance,
我们就需要思考继承这个概念
it gets really complicated. So
这是个很复杂的概念
let's start thinking about class and break this down.
所以我们还是先思考类，不提继承
Let's start with what are you required to do in an init for
我们从这个问题切入：在类的构造器中必须做的是什么？
a class? in a struct it's easy you're just required to
在结构体中很简单
initialize all your vars that aren't initialized. But
我们只要把所有没被初始化的变量初始化就行了
in a class what are you required to do? By the time
但是在一个类中，我们必须做的事情有哪些？
it's done you have to have initialized all your vars.
你必须完成初始化所有变量的任务
We know that. There are two types of initializers.
这点我们已经知道了。存在两种构造器
A convenience initializer.
Convenience Initializer（便利构造器）
This is only for classes. A convenience initializer and
只有类才有便利构造器
what's called a designated initializer.
另一种被称为 Designated Initializer（指定构造器）

Chinese: 
Designated is the default. There's no keyword it's just
不带任何关键词就会被默认为指定构造器
if it's not marked convenience then it's a designated.
如果没被标记为 convenience，它就是指定构造器
Now here's where the rules come in.
现在开始引入规则部分
A designated initializer non convenience must and
一个指定构造器，非便利构造器
can only, call the designated initializer that it is in,
必须调用且只能调用
that is in it's immediate superclass,
它直接继承的父类的指定构造器
it's very important. It has to call a superclass init
这点很关键，它必须调用父类的构造器
and it has to get designated initializer. It cannot call
并且必须是指定构造器
it's convenience initializer in a superclass. Nor
它没法调用父类的便利构造器
can it call two classes up the inherent chain unless the one
也没法调用继承关系中更上层的父类（的任何构造器）
right above inherited the init from the one up above, and
除非它的父类的构造器是继承自更上层父类的
we'll talk about that in a second. You have to initialize
这点我们过会再讲
all of your properties before you call that super init.
你必须初始化自身的所有属性，之后才能调用 super.init
You must have completely
你必须完完全全地
done all the ones that you introduced in your class.
把自己新引入的属性都初始化
Get them initialized before you call super init. And,
之后才能调用 super.init
you have to call the super one before you can reinitialize or
而且你只有在调用了 super.init 之后
change the value of any of its properties, obviously,
才能改变继承自父类的属性
you gotta let your super class have a chance to initialize
显然，你必须等你的父类把它自身构造完成

English: 
Designated is the default.      
There's no keyword it's just    
if it's not marked convenience  
then it's a designated.         
Now here's where                
the rules come in.              
A designated initializer        
non convenience must and        
can only, call the designated   
initializer that it is in,      
that is in it's                 
immediate superclass,           
it's very important. It has     
to call a superclass init       
and it has to get designated    
initializer. It cannot call     
it's convenience initializer    
in a superclass. Nor            
can it call two classes up the  
inherent chain unless the one   
right above inherited the init  
from the one up above, and      
we'll talk about that in a      
second. You have to initialize  
all of your properties before   
you call that super init.       
You must have completely        
done all the ones that you      
introduced in your class.       
Get them initialized before     
you call super init. And,       
you have to call the super one  
before you can reinitialize or  
change the value of any of      
it's Properties, obviously,     
you gotta let your super class  
have a chance to initialize     

English: 
itself before you start         
mucking with its properties.    
Otherwise, when units call      
super, it's probably gonna      
blast whatever you did          
to its properties.              
A convenience init can only,    
must and can only,              
call an initializer in          
its own class, no super.        
Only in your own class,         
convenience initializer only    
in your own class. You can      
call it another convenience or  
you can call it designator,     
but it has to be                
in your own class,              
not in your super class. And    
a convenience init has to call  
whatever init it's gonna call   
in itself before it can         
set any of the property         
values. It's kind of different  
from an init that calls into    
super because that one has      
to do its initialization,       
the designated one,             
before it calls super.          
This, in this case,             
you have to do convenience,     
you have to call your           
other one first.                
And the calling of all other    
inits, whatever you do, any     
inits that you have to call     
has to be done in all cases,    
before you start calling        
methods on yourself or          
accessing properties.           
Not setting the properties,     
but accessing them.             

Chinese: 
itself before you start mucking with its properties.
之后才能改变它的属性
Otherwise, when your inits call super, it's probably gonna
另外，当你初始化完毕自身的属性之后
be last whatever you did to its properties.
调用 super.init 通常就是你要做的最后一件事
A convenience init can only, must and can only,
一个便利构造器，必须且只能
call an initializer in its own class, no super.
调用其自身所在类的构造器，不能调用父类的构造器
Only in your own class,
只能是自身所在类的
convenience initializer only in your own class. You can
便利构造器只能调用自身所在类的构造器
call it another convenience or you can call it designator,
你可以在它内部调用其他便利构造器或者指定构造器
but it has to be in your own class,
但是都必须是你自身所在类的构造器
not in your super class. And
不能是父类的
a convenience init has to call whatever init it's gonna call
一个便利构造器必须先调用任何一个其他构造器
in itself before it can set any of the property
之后才能设置属性
values. It's kind of different from an init that calls into
这和构造器中调用父类构造器的情形相反
super because that one has to do its initialization,
指定构造器必须先初始化自身新引入的属性
the designated one, before it calls super.
然后才能调用父类的构造器
This, in this case, you have to do convenience,
但是到了便利构造器这里
you have to call your other one first.
你必须先调用一个自身的其他构造器
And the calling of all other inits, whatever you do, any
任何其他构造器，无论哪个都行
inits that you have to call has to be done in all cases,
任何情况下，在完成某个构造器的调用之后
before you start calling methods on yourself or
你才能开始调用自身的方法
accessing properties.
或者访问自身的属性
Not setting the properties, but accessing them.
不是设置属性的初始值，而是访问它们

Chinese: 
In other words, you have to be fully initialized before your
换句话说就是，在你的便利构造器开始使用这个类之前
init can start using your class. All right,
你必须先完全构造自身
whew is right: a lot of rules there, and a lot of them
呼，终于讲完了这一大堆规则
are conflicting and all that stuff. Let's make it even more
而且其中一部分还相互冲突，纠缠不清
complicated when we talk about inheriting inits. So,
接下来讲继承构造器，事情会变得更复杂
you wanna get some inits from your super class,
你可能希望从父类继承一些构造器
whoa, not so fast. If you don't implement
不过先别急。如果你没有实现任何一个指定构造器
any designated inits, you only implement convenience inits,
你只实现了一些便利构造器
then you'll inherit all of your super classes designated,
这样的话你就能继承所有父类的指定构造器
but only if you don't implement any of them.
但是前提是你没有实现任何一个指定构造器
And if you implement even one designated init,
哪怕你只实现了一个指定构造器
now you're not gonna inherit all your super classes. If you
你就没法继承父类的任何指定构造器
override all of your super classes designated inits,
如果你重写了父类所有的指定构造器
then you'll inherit all of its con, convenience inits.
你就能继承父类所有的便利构造器
Now why is that? That's because your superclass,
为什么会这样呢？因为你的父类
when it implements these convenience inits,
实现它的便利构造器
it depends on the designated inits being implemented,
要建立在指定构造器已经实现的基础上
so you have to implement them all.
所以你要实现父类全部的指定构造器
Of course, you could inherit them all by implementing
当然，如果你没有实现任何一个指定构造器

English: 
In other words, you have to be  
fully initialized before your   
init can start using            
your class. All right,          
whew is right: a lot of rules   
there, and a lot of them        
are conflicting and all that    
stuff. Let's make it even more  
complicated when we talk        
about inheriting inits. So,     
you wanna get some inits        
from your super class,          
whoa, not so fast.              
If you don't implement          
any designated inits, you only  
implement convenience inits,    
then you'll inherit all of      
your super classes designated,  
but only if you don't           
implement any of them.          
And if you implement            
even one designated init,       
now you're not gonna inherit    
all your super classes. If you  
override all of your super      
classes designated inits,       
then you'll inherit all of      
its con, convenience inits.     
Now why is that? That's         
because your superclass,        
when it implements these        
convenience inits,              
it depends on the designated    
inits being implemented,        
so you have to                  
implement them all.             
Of course, you could inherit    
them all by implementing        

English: 
none of them as well. So, any   
init that you inherit by these  
rules can be used to            
satisfy any of these other,     
other requirements that we're   
talking about on the previous   
stage. You can make an init     
required. You just say          
required init. Required is      
a key word, and that will       
make it so the subclass has     
to implement that init, okay,   
it's required. Failable inits,  
we talked about these with      
double. If you put a question   
mark after your init,           
init question mark, that means  
that this init can fail.        
And that means that this init,  
or when you create this thing,  
will return optional            
version of this class. So       
we thought it was double.       
If we said double parentheses   
string, it would return         
an optional double.             
It was a failable init, and     
that's because you could have   
said double of hello, and       
you would be like " I can't     
turn it into double: fail".     
And the way you fail out of     
a failable init is you just     
return nil. Otherwise,          
you don't return anything out   
of init, it just initializes,   
but the one time you            
return anything is out          
a failed init, you can return   
nil. So, an example here is     

Chinese: 
none of them as well. So, any init that you inherit by these
也一样能继承父类全部的便利构造器
rules can be used to satisfy any of these other,
你通过这些规则继承来的构造器也一样满足
other requirements that we're talking about on the previous
我们上一页讲到的“必须做的事情”
stage. You can make an init required. You just say
你可以通过 required init 把一个构造器变为必要构造器
required init. Required is a key word, and that will
required 是一个关键词
make it so the subclass has to implement that init, okay,
它要求所有子类必须实现这个构造器
it's required. Failable inits, we talked about these with
因为它是“必要的”。可失败构造器，我们以 Double 为例
double. If you put a question mark after your init,
如果你在 init 后面加一个问号
init question mark, that means that this init can fail.
init? 代表它是可失败的
And that means that this init, or when you create this thing,
意味着这个构造器，或者说当你创建这个实例的时候
will return optional version of this class. So
返回的是这个类型的可选类型
we thought it was double.
我们想一下 Double
If we said double parentheses string, it would return
如果我们通过传入一个字符串构造 Double
an optional double. It was a failable init, and
会返回一个 Double? 这就是一个可失败构造器
that's because you could have said double of hello, and
因为你有可能这样写：Double("hello")
you would be like " I can't turn it into double: fail".
你会得到这样的回答“我没法把它转化为 Double，失败了”
And the way you fail out of a failable init is you just
这种失败具体表现就是你得到的返回值是 nil
return nil. Otherwise,
另外
you don't return anything out of init, it just initializes,
通常你不用在构造器里写 return，因为它本身就是构造器
but the one time you return anything is out
但是仅有一种情况你要写 return
a failed init, you can return nil. So, an example here is
那就是可失败构造器失败的时候，你要 return nil

English: 
UIImage. UIImaged named         
looks up that image in          
the xe assets. Remember that    
xe assets thing that I moved    
off to supporting files at the  
beginning of the first demo?    
This looks it up in there, of   
course, it might not find it.   
So we do if let image =         
UIImage(named: "foo"),          
then we do something,           
otherwise we fail,              
that UI image initializer       
failed. Alright, Any and        
AnyObject. There is no more     
init, we're done with init.     
Any and AnyObject: these        
are types, special types.       
These types really are almost   
exclusively used for backwards  
compatibility with Objective C  
because Objective C had a type  
in it called id,                
which was kind of like Any,     
AnyObject actually. So Swift    
needed some compatibility, but  
Swift doesn't really            
use Any very much, so           
we wouldn't, Swift is strongly  
typed. So you wouldn't wanna    
have a type which is like, it   
can be anything. Okay, because  
that's what Any and AnyObject   
are, it's like anything,        

Chinese: 
UIImage. UIImaged named looks up that image in
拿 UIImage 举例，UIImage(named:) 会在
the xcassets. Remember that xcassets thing that I moved
xcassets 文件中寻找指定的图片。还记得 xcassets 文件吗？
off to supporting files at the beginning of the first demo?
就是第一个 demo 中我移动到 Supporting Files 文件夹的那个
This looks it up in there, of course, it might not find it.
这个方法就是在那里寻找图片，当然有可能找不到
So we do if let image = UIImage(named: "foo"),
所以我们要这样写 if let image = UIImage(named: "foo")
then we do something, otherwise we fail,
如果找到了我们会做某些操作
that UIImage initializer failed. Alright, Any and
如果 UIImage 构造失败我们就什么都不做
AnyObject. There is no more init, we're done with init.
下面是 Any 和 AnyObject，不讲构造器了
Any and AnyObject: these are types, special types.
Any 和 AnyObject 都是类型，特殊的类型
These types really are almost exclusively used for backwards
几乎可以这样理解，这些类型的存在仅仅是为了
compatibility with Objective C because Objective C had a type
向下兼容 Objective-C 中叫做 id 的一个类型
in it called id, which was kind of like Any,
它和 Any 类似
AnyObject actually. So Swift needed some compatibility, but
确切地说它更像 AnyObject。Swift 需要兼容这些
Swift doesn't really use Any very much, so
Swift 中用到 Any 的情况并不多
we wouldn't, Swift is strongly typed. So you wouldn't wanna
Swift 是一个强类型语言
have a type which is like, it can be anything. Okay, because
一个能代表任意类型的类型，没有存在的必要
that's what Any and AnyObject are, it's like anything,
Any 和 AnyObject 能代表任何类型

Chinese: 
any type. It's this weird kind of typeless type kinda thing.
它们指代的是类型不明的东西
The only difference between Any and
Any 与 AnyObject 唯一的区别是
AnyObject is AnyObject can only be a class,
AnyObject 只能指代某个类
it has be a reference type. Any can be anything,
必须是引用类型，Any 没有这个限制
reference or a value type, that's the only difference.
引用类型或值类型都可以，这是它们之间唯一的区别
So why do we have these AnyObject things?
为什么要有 AnyObject 和 Any？
Where are they gonna show up? Well,
它们要用在哪里？
there are some methods in iOS where one of the arguments
iOS 中有一些方法确实能接受任何类型的参数
truly could be anything. One example here is when you have
比如：当你有很多 MVC 时
multiple MVCs, which we're gonna learn about next week.
这个我们下周会详细学
The way you go from one to the next, next is called segueing,
从一个跳转到另一个的方式叫做 Segue
you segue from one MVC to the next.
你能从一个 MVC Segue 到下一个
And the thing that causes a segue to happen, okay,
Segue 的发起者
is the argument in this method called prepare for
就是方法 prepare(for:sender:) 中
segue called sender, okay,
叫做 sender 的参数
just like we had sender in the IB action. So
和我们之前用到的 IBAction 中的 sender 是相似的
the sender is the one who's causing this segue to happen,
这个 sender 就是 Segue 的发起者
well, a button could be causing a segue to happen,
一个按钮可以发起 Segue
a line in a table view could be causing it. Some custom
TableView 中的一行也可以
piece of code of yours could be causing this MVC to segue.
一小段自定义的代码也可以
So when you're preparing for it, you've gotta be
所以当你准备 Segue 的时候
able to say which one it was, and that's just Any. So
你要能接受任何类型的 sender，所以这里用 Any

English: 
any type. It's this weird kind  
of typeless type kinda thing.   
The only difference             
between Any and                 
AnyObject is AnyObject          
can only be a class,            
it has be a reference type.     
Any can be anything,            
reference or a value type,      
that's the only difference.     
So why do we have these         
AnyObject things?               
Where are they gonna show up?   
Well,                           
there are some methods in iOS   
where one of the arguments      
truly could be anything. One    
example here is when you have   
multiple MVCs, which we're      
gonna learn about next week.    
The way you go from one to the  
next, next is called segueing,  
you segue from one              
MVC to the next.                
And the thing that causes       
a segue to happen, okay,        
is the argument in this         
method called prepare for       
segue called sender, okay,      
just like we had sender         
in the IB action. So            
the sender is the one who's     
causing this segue to happen,   
well, a button could be         
causing a segue to happen,      
a line in a table view could    
be causing it. Some custom      
piece of code of yours could    
be causing this MVC to segue.   
So when you're preparing for    
it, you've gotta be             
able to say which one it was,   
and that's just Any. So         

English: 
if this were a Swift API,       
they wouldn't have done Any.    
They'd have had a protocol      
where you could be a segue      
sender. And you'd have to       
implement probably some         
functionality that would make   
sense here. But in this case,   
it's Any. It knows optional     
Any too because you can have    
nil, the center could be nil.   
Where else will you see it?     
You could have an array of      
AnyObject or an array of Any.   
That could be an array that     
has doubles and strings and     
things mixed in there. Now you  
might be tempted to use this    
in your assignment number two   
when you see the assignment.    
But you're not allowed to       
because one of the required     
tasks says you can't use Any    
or AnyObject. Also you          
wouldn't be very Swifty.        
In Swift, if we wanted          
to put doubles and              
strings in the same array,      
we use an enum.                 
That's what we did with our     
operations array, and that's    
what we would do in Swift, so   
we wouldn't use AnyObject.      
Another thing you could         
possibly use Any for is for     
a cookie, right, some piece     
of data that you're giving      
out that you don't want people  
to know what class it is.       
And they're just gonna give     
it back to you at some point,   

Chinese: 
if this were a Swift API, they wouldn't have done Any.
不过如果是一个纯 Swift API，通常不会用 Any
They'd have had a protocol where you could be a segue
应该有一个协议类型代表那些能当做 Segue 发起者的东西
sender. And you'd have to implement probably some
而且你还要为这个协议实现一些合适的功能
functionality that would make sense here. But in this case,
使它可以在这里发挥作用。但是现在这里用的是 Any
it's Any. It knows optional Any too because you can have
而且是 Any?，因为这里它可以是 nil
nil, the sender could be nil. Where else will you see it?
sender 可以是 nil。还有哪里能遇到这种用法？
You could have an array of AnyObject or an array of Any.
你可以有一个以 AnyObject 或 Any 为元素的数组
That could be an array that has doubles and strings and
这样的数组能够同时包含 Double 和 String
things mixed in there. Now you might be tempted to use this
当你看到作业二的内容之后
in your assignment number two when you see the assignment.
你可能对这种用法跃跃欲试
But you're not allowed to
但是我不允许你们用
because one of the required tasks says you can't use Any
作业的要求中有一条写明了
or AnyObject. Also you wouldn't be very Swifty.
你不能用 Any 或 AnyObject。这种用法很不 Swifty
In Swift, if we wanted to put doubles and
Swift 中，如果我们要把 Double 和 String
strings in the same array, we use an enum.
放入同一个数组，应该使用 enum（枚举）
That's what we did with our operations array, and that's
就像之前 CalculatorBrain 中存放操作符的数组
what we would do in Swift, so we wouldn't use AnyObject.
这才是我们在 Swift 中实现的方式，不要用 AnyObject
Another thing you could possibly use Any for is for
另外，可能用到 Any 的一种情况是
a cookie, right, some piece of data that you're giving
cookie，指的是：你要发送出去的一串数据
out that you don't want people to know what class it is.
你不希望别人知道它是什么类型
And they're just gonna give it back to you at some point,
他们只需要在某个时候原封不动的返回给你

Chinese: 
and you'll do something with it and
然后你会对它做一些操作
only you know what it is.
只有你知道它是什么
So you know, an opaque type, you could use it for
只有你知道它的隐藏类型，只有你能用它
that. How do we use something of type Any, because we can't
我们要怎么使用 Any 类型的变量呢？
send any messages to it cuz it's not of any type, so
我们没法给 Any 类型的变量发送消息。它不是任何类型
we don't know any methods that it does or whatever. Instead,
我们不知道它有哪些方法，我们对它一无所知
we have convert it, and we convert type Any or, or
所以我们必须对它进行转换，我们要把 Any 或 AnyObject
AnyObject into some class that we know about using as.
用 as 转换为我们已知的类型
As is a key word, and we do as question mark because we don't
as 是一个关键词，我们用 as? 是因为
know for sure that we can convert something,
我们也不确定它是不是能被转换成功
so it's an optional. And we use it with if let.
所以它是可选类型，我们通常和 if let 一起使用
So if I had some variable unknown,
如果我有一个未知类型的变量
which is of type Any, so I don't really know what it is.
它是 Any 类型，我不知道它的真实类型
But I think it might be MyType, I'm not sure.
但是我认为它可能 MyType 类型的，我也不太确定
But I think that might be MyType in there. So I say,
我认为它是 MyType，所以我可以写
if let foo = unknown as? MyType,
if let foo = unknown as? MyType
if let. Then inside there, foo is now going to be unknown,
if let，然后 foo 就是那个未知的东西转换为 MyType 后的结果
but as MyType. So I will be able to
所以我能给 foo 发消息
send foo message whatever MyType, I'll be able to send foo
发送任何 MyType 可以接受的消息

English: 
and you'll do                   
something with it and           
only you know what it is.       
So you know, an opaque type,    
you could use it for            
that. How do we use something   
of type Any, because we can't   
send any messages to it cuz     
it's not of AnyType, so         
we don't know any methods that  
it does or whatever. Instead,   
we have convert it, and         
we convert type Any or, or      
AnyObject into some class       
that we know about using as.    
As is a key word, and we do as  
question mark because we don't  
know for sure that we           
can convert something,          
so it's an optional.            
And we use it with if let.      
So if I had some                
variable unknown,               
which is of type Any, so I      
don't really know what it is.   
But I think it might be         
MyType, I'm not sure.           
But I think that might be       
MyType in there. So I say,      
if let foo =                    
unknown as MyType,              
if let. Then inside there, foo  
is now going to be unknown,     
but as MyType.                  
So I will be able to            
send foo message whatever my    
tape, I'll be able to send foo  

Chinese: 
whatever MyType understands, methods and vars.
任何它的方法或变量
So that's how we use it. We use this "as?", it's called
通过用 as? 这种方法，我们得以使用 Any 类型的变量
casting. This casting, by the way, not just for AnyObject,
这种操作叫 Casting（类型检查）。不仅是 AnyObject 和 Any
we can cast other things. For example, if I had a variable
其他类型我们也可以检查。比如有一个变量 vc
which is, vc which is a type UIViewController,
它的类型是 UIViewController
I could assign it to UI, to CalculatorViewController.
我可以让它指向一个 CalculatorViewController
Because CalculatorViewController is
因为 CalculatorViewController 是
a subclass of UIViewController. So
UIViewController 的子类
it is a UIViewController, so I could assign it to vc. But
所以它也是一个 UIViewController，我可以用 vc 指向它
if I assign it like this, with this typing,
但是这样操作之后
I cannot say vc.displayValue cuz vc.displayValue,
我就没法访问 vc.displayValue 了
displayValue is a var in CalculatorViewController,
因为 displayValue 是 CalculatorViewController 的变量
and vc is of type UIViewController.
但是 vc 是 UIViewController 类型的
Even though it points to a CalculatorViewController,
尽管它实际指向的是 CalculatorViewController
from Swift's perspective, it's typed as vc, and
但是 Swift 现在把他视为 vc 的类型
Swift is strongly typed. So if I wanted to send displayValue,
因为 Swift 是强类型语言，如果我要访问 displayValue
I would have to say, if I can let calcVC = vc
我只能这样写 if let calcVC = vc as? CalculatorViewController
as a CalculatorViewController Now I can send displayValue to
之后我才能访问 calcVC 的 displayValue 属性
calcVC. Cuz it's the type that you actually
因为 vc 明确声明了类型

English: 
whatever MyType understands,    
methods and vars.               
So that's how we use it.        
We use this "as?", it's called  
casting. This casting, by the   
way, not just for AnyObject,    
we can cast other things. For   
example, if I had a variable    
which is, vc which is           
a type UIViewController,        
I could assign it to UI,        
to CalculatorViewController.    
Because                         
CalculatorViewController is     
a subclass of                   
UIViewController. So            
it is a UIViewController, so    
I could assign it to vc. But    
if I assign it like this,       
with this typing,               
I cannot say vc.displayValue    
cuz vc.displayValue,            
displayValue is a var in        
CalculatorViewController,       
and vc is of type               
UIViewController.               
Even though it points to        
a CalculatorViewController,     
from Swift's perspective,       
it's typed as vc, and           
Swift is strongly typed. So if  
I wanted to send displayValue,  
I would have to say,            
if I can let calcVC = vc        
as a CalculatorViewController   
Now I can send displayValue to  
calcVC. Cuz it's the type       
that you actually               

English: 
type it as that matters, not    
what it's pointing to. So you   
have to use as to get it to     
be something that you really    
wanna use. Okay, I'm gonna      
go a little bit over here.      
If you have to go, it's,        
it's fine, just keep it quiet.  
The last thing I'm gonna        
talk about is user defaults.    
User defaults is                
a very lightweight,             
limited database. It's a tiny   
little database that persists   
between launchings of           
your app. It's great for        
things like settings and        
stuff like that.                
Don't put anything big in       
there. The only thing you can   
put in this database is what's  
called a property list.         
A property list just means      
any combination of array,       
dictionary, string,             
date, data, or                  
a number, like int,             
float, double, whatever.        
That's what a property list     
is. It's just conceptual.       
There's no actual type          
property list, unfortunately.   
If this were a Swift API, it    
probably would be such a type.  
It could be a protocol.         
But anyway, there's not.        
This is from Objective-C.       
So since there's no type        
that represents that            
codgepodge of classes,          
this API that I'm gonna show    
user defaults uses Any. And     

Chinese: 
type it as that matters, not what it's pointing to. So you
所以 Swift 不考虑实际指向的类型
have to use as to get it to be something that you really
因此使用前必须先转换为你想要的那个类型
wanna use. Okay, I'm gonna go a little bit over here.
我会稍微拖点堂
If you have to go, it's, it's fine, just keep it quiet.
如果有人要走，可以先走，保持安静
The last thing I'm gonna talk about is user defaults.
最后一个知识点是 UserDefaults
User defaults is a very lightweight,
它是一个轻量级的、受限制的数据库
limited database. It's a tiny little database that persists
它是一个可以在应用多次启动之间
between launchings of your app. It's great for
保存持久化数据的微型数据库，非常适合用来
things like settings and stuff like that.
保存设置信息，或者类似的东西
Don't put anything big in there. The only thing you can
不要保存太大的数据
put in this database is what's called a property list.
你只能保存 Property List（属性列表）形式的数据
A property list just means any combination of array,
属性列表是以下这些类型的混合体：Array
dictionary, string, date, data, or
Dictionary、String、Date、Data
a number, like int, float, double, whatever.
或者 Int，Float，Double 等任意类型的数字
That's what a property list is. It's just conceptual.
这就是属性列表的概念
There's no actual type property list, unfortunately.
并没有一个与之对应的真实类型
If this were a Swift API, it probably would be such a type.
如果这是个 Swift 的 API，它可能是一个确切类型
It could be a protocol. But anyway, there's not.
可能是个协议类型，可惜并不是
This is from Objective-C. So since there's no type
这是一个来自 Objective-C 的东西
that represents that hodgepodge of classes,
所以没有一个类型能代表这个大杂烩
this API that I'm gonna show user defaults uses Any. And
下面我要向你们介绍的 UserDefaults API 中使用了 Any

English: 
this is what it looks like.     
It has this core, set, and      
get. Set Any? Now that          
Any can't really be Any,        
it has to be one of those       
types, string, dictionary,      
array, whatever, it has         
to be be a Property List,       
forKey string. So you just      
put it, anything you want       
in this database                
under a certain key.            
And then you get it back out    
by saying, object for key, and  
it returns you an Any. And      
it's an optional Any because    
it might not be                 
in the database,                
in which it is returned nil.    
So it says any but              
it's not really Any, it's Any   
as long as the property lists,  
which means it's one of         
these ten classes or            
whatever. The way you read and  
write it, you don't create      
a user default by saying let    
x equal user defaults           
with parentheses.               
You say let defaults =          
UserDefaults.standard, so       
that's a type var on            
the user default struct.        
And you get this standard       
UserDefaults and                
then you can send               
it things like set,             
that thing I was telling you,   
set Any. And here,              
I've got three different sets,  
one of them setting of double,  
one setting an array of ints.   
An array of ints is okay        

Chinese: 
this is what it looks like. It has this core, set, and
它们看上去是这样的，它的核心方法 set 和 get
get. Set Any? Now that Any can't really be Any,
set 接受 Any? 类型。注意这里 Any 并不是任何类型都可以
it has to be one of those types, string, dictionary,
它必须是这几种确切类型之一：String、Dictionary、Array 等
array, whatever, it has to be be a Property List,
总之它必须是一个属性列表
forKey string. So you just put it, anything you want
forKey: String 意味着你要设置一个关键字
in this database under a certain key.
什么都可以，数据将会被存储在这个关键字下
And then you get it back out by saying, object for key, and
然后你也可以获取里面的内容，通过 object(forKey:) 方法
it returns you an Any. And it's an optional Any because
它会返回给你一个 Any?，一个可选类型的 Any
it might not be in the database,
因为数据库里可能没有指定关键字的数据
in which it is returned nil. So it says any but
这时就会返回 nil。虽然它返回 Any
it's not really Any, it's Any as long as the property lists,
但是这个 Any 并不是什么都可以，它依然还是个属性列表
which means it's one of these ten classes or
意味着它只能是那十种类型之一
whatever. The way you read and
这就是读取和写入它的方法
write it, you don't create a user default by saying let
你不需要通过 let x = UserDefaults()
x equal user defaults with parentheses.
创建一个 UserDefaults
You say let defaults = UserDefaults.standard, so
你应该通过 let defaults = UserDefaults.standard
that's a type var on the user default struct.
这是一个 UserDefaults 的类型变量
And you get this standard UserDefaults and
你可以取得这个叫做 standard 的 UserDefaults
then you can send it things like set,
然后你可以调用它的 set 方法
that thing I was telling you, set Any. And here,
像刚刚讲过的那样 set 任何属于属性列表的类型
I've got three different sets, one of them setting of double,
这里我展示了三种不同的 set，其一设置了 Double
one setting an array of ints. An array of ints is okay
另一个设置了一个 Int 类型的数组，这是允许的

English: 
because array is part of        
property list. And so is int,   
so that's okay. That's          
a property list. An array       
of ints is a property list, a   
property list. So is a double,  
cuz it's one of those types.    
And I just set them in there.   
And then when I get them out,   
I use that object for key.      
And actually for                
some common types,              
like doubles, arrays and        
dictionaries, there's actually  
a nice little method in there   
to give you that type back.     
That's so you that don't        
get an Any back and             
then have to do as. Because     
you know that objects for       
key returns an Any until        
you give this Any and           
you have to go if this          
thing has a double,             
then I've got it. That would    
be annoying. So instead,        
it just has a method called     
double that does that as for    
you. And if the as fails        
then you, I think either,       
I don't know if it returns a    
double or an optional double,   
but you might get zero back,    
you might get a nil.            
I don't remember exactly.       
But for array in dictionary,    
a couple of interesting         
things to note. Obviously,      
the Anys that are inside        
the array in dictionary,        
those will have to be property  
lists as well, the things that  

Chinese: 
because array is part of property list. And so is int,
因为数组可以是属性列表的一部分，Int 也行
so that's okay. That's a property list. An array
所以 Int 类型的数组是完全可以的，它是一个属性列表
of ints is a property list, a property list. So is a double,
Int 类型的数组是属性列表，一个单独的 Double 也是
cuz it's one of those types. And I just set them in there.
因为它也是属性列表包含的类型之一。这里我 set 过了
And then when I get them out, I use that object for key.
当我要 get 的时候，我要用 object(forKey:) 方法
And actually for some common types,
我要获取的是常见的类型
like doubles, arrays and dictionaries, there's actually
比如 Double，Array 或者 Dictionary
a nice little method in there to give you that type back.
有一些很便利的方法可以帮你直接取回指定的类型
That's so you that don't get an Any back and
这样你就不用先拿到一个 Any，然后在对它进行 as 操作了
then have to do as. Because you know that objects for
因为通过 object(forKey:) 拿到的是 Any
key returns an Any until you get this Any and
你拿到它之后
you have to go if this thing as a double,
还要去判断它能不能 as 成 Double
then I've got it. That would be annoying. So instead,
然后才算真正拿到了它，这种做法太麻烦
it just has a method called double that does that as for
作为替代，叫做 double(forKey:) 的方法帮你做了 as 的工作
you. And if the as fails then you, I think either,
而且如果获取失败了，我想想
I don't know if it returns a double or an optional double,
我也忘了它会返回 Double 还是 Double?
but you might get zero back, you might get a nil.
你可能得到 0，也可能是 nil
I don't remember exactly. But for array and dictionary,
我也记不清了。对于字典或数组
a couple of interesting things to note. Obviously,
它们有些有趣的特点，要特别注意
the Anys that are inside the array and dictionary,
它们作为返回值时，其中包含的元素 Any
those will have to be property lists as well, the things that
一样必须是属性列表

English: 
are returned to you.            
And also know that dictionary,  
this convenience                
method dictionary,              
it's the string is always       
the key in the dictionary.      
If you had a dictionary where   
the keys were say, ints.        
I think that's a valid key,     
yeah, in the dictionary, yeah,  
it is. Then you would not       
use this convenience method.    
You'd have to use object for    
key and then use as to turn it  
back into a dictionary          
with int keys.                  
Saving the database is          
autosave, so you actually       
don't have to save it. If you   
wanna force it to save because  
you're worried that             
the autosave might not happen.  
You're gonna exit your program  
or something, you can use this  
method synchronize. It's        
called synchronize defaults.    
It will synchronize it.         
That's almost it, assertions.   
Sorry, one last quick thing.    
Assertions are just a little    
Swift function that takes a     
closure as the first argument   
and a message as                
the second argument.            
All it does is it executes the  
closure. If that returns true,  
it does not crash your          
program. If it returns false,   

Chinese: 
are returned to you. And also know that dictionary,
对于字典
this convenience method dictionary,
有一个方法是 dictionary(forKey:)
it's the string is always the key in the dictionary.
它的键必须是 String 类型的
If you had a dictionary where the keys were say, ints.
如果你有一个字典，键类型是 Int
I think that's a valid key, yeah, in the dictionary, yeah,
我记得 Int 是一个可以作为键的类型，没错，确实是
it is. Then you would not use this convenience method.
那你就不能用这个方法了
You'd have to use object for key and then use as to turn it
你必须用 object(forKey:) 然后再用 as 把它转换为
back into a dictionary with int keys.
以 Int 为键类型的字典
Saving the database is autosave, so you actually
这个数据库的保存是自动的
don't have to save it. If you wanna force it to save because
你没必要手工去保存它。如果你害怕自动保存会失效
you're worried that the autosave might not happen.
你希望强制保存它
You're gonna exit your program or something, you can use this
比如你可能强退了程序
method synchronize. It's called synchronize defaults.
你可以用这个方法手动同步：defaults.synchronize()
It will synchronize it. That's almost it, assertions.
它会同步数据库。最后是 Assertions（断言）
Sorry, one last quick thing. Assertions are just a little
抱歉，只剩最后一个小知识点了
Swift function that takes a closure as the first argument
断言只是 Swift 中的一个小函数，第一个参数是个闭包
and a message as the second argument.
第二个参数是一个消息字符串
All it does is it executes the closure. If that returns true,
它做的仅仅是执行这个闭包，如果返回为 true
it does not crash your program. If it returns false,
就什么都不做。如果返回为 false

Chinese: 
it crashes your program and prints that message out. So
就会导致你的程序崩溃掉，并且输出这段消息
you could put, you know, some validation call. This line of
所以你可以把它用于验证合法性
code will not even execute in the version of your app that
在你发布到 App Store 的版本中，这行代码不会执行
you ship on the app store. When you build the app for
当你用 Release 模式生成程序的时候
release, the asserts are completely ignored.
断言会被完全忽略掉
It doesn't even actually give the closure, let alone crash.
不会执行这段闭包，更不会崩溃
It just ignores them, so this is a debugging thing only,
仅仅是忽略掉它们。这只是个调试用的东西
okay? That's it! For Friday,
好了，讲完了
we do have Friday session, it's at the normal time. And
这周五我们会上课，老时间
it's gonna be on source code management.
会讲一些源码管理的知识
A really cool way to manage your code even if you're just
一种非常酷的管理源码的方法
one programmer working on a project by yourself. And then
即使你独自做项目，也有必要学习
next week I'm going to talk about doing custom drawing
下周我会讲自定义视图中的绘制
in your own view. Multi-touch, like pinches and swipes, and
还有各种手势，比如 Pinch（捏合）和 Swipe（轻扫）等
things like that. And finally, multiple MVCs so
最后是有关多个 MVC 的知识
we can build a more powerful calculator.
我们可以构建一个更强大的计算器
Your assignment two has gone out. It's already posted.
作业二已经布置完毕，发布出来了
It's essentially enhancing your calculator with a lot of
主要内容是加强你的计算器
the things that I talked about today like tuples and
运用我们今天讲的很多知识
defaulting values and even value types.
比如元组和默认值，还有值类型

English: 
it crashes your program and     
prints that message out. So     
you could put, you know, some   
validation call. This line of   
code will not even execute in   
the version of your app that    
you ship on the app store.      
When you build the app for      
release, the asserts            
are completely ignored.         
It doesn't even actually give   
the closure, let alone crash.   
It just ignores them, so this   
is a debugging thing only,      
okay? That's it! For Friday,    
we do have Friday session,      
it's at the normal time. And    
it's gonna be on source         
code management.                
A really cool way to manage     
your code even if you're just   
one programmer working on a     
project by yourself. And then   
next week I'm going to talk     
about doing custom drawing      
in your own view. Multi-touch,  
like pinches and swipes, and    
things like that.               
And finally, multiple MVCs so   
we can build a more             
powerful calculator.            
Your assignment two has gone    
out. It's already posted.       
It's essentially enhancing      
your calculator with a lot of   
the things that I talked        
about today like tuples and     
defaulting values and           
even value types.               

English: 
All kinds of stuff. So we'll    
have a lot of fun with that.    
>> For more,                    
please visit us                 
at standford.edu                

Chinese: 
All kinds of stuff. So we'll have a lot of fun with that.
运用各种知识去完成它，享受这个有趣的过程吧
>> For more,
>> 更多课程
please visit us at stanford.edu
详见 stanford.edu
