update new articles
This commit is contained in:
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.1" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.1" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_9">
|
||||
<section class="normal" id="section-gitbook_8">
|
||||
|
||||
<h1 id="-">基础部分</h1>
|
||||
<p>Swift 是 iOS 和 OS X 应用开发的一门新语言。然而,如果你有 C 或者 Objective-C 开发经验的话,你会发现 Swift 的很多内容都是你熟悉的。</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.2" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.2" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_31">
|
||||
<section class="normal" id="section-gitbook_30">
|
||||
|
||||
<h1 id="-">基础运算符</h1>
|
||||
<p>运算符是检查, 改变, 合并值的特殊符号或短语. 例如, 加号 <code>+</code> 把计算两个数的和(如 <code>let i = 1 + 2</code>). 复杂些的运行算包括逻辑与<code>&&</code>(如 <code>if enteredDoorCode && passedRetinaScan</code>), 还有自增运算符 <code>++i</code> 这样让自身加一的便捷运算.</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.3" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.3" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_10">
|
||||
<section class="normal" id="section-gitbook_9">
|
||||
|
||||
<h1 id="-strings-and-characters-">字符串和字符 (Strings and Characters)</h1>
|
||||
<p>本页包含内容:</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.4" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.4" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.5" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.5" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.6" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.6" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_24">
|
||||
<section class="normal" id="section-gitbook_23">
|
||||
|
||||
<h1 id="-functions-">函数(Functions)</h1>
|
||||
<p>本页包含内容:</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.7" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.7" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_25">
|
||||
<section class="normal" id="section-gitbook_24">
|
||||
|
||||
<h1 id="-">闭包</h1>
|
||||
<p>本页内容包含:</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.8" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.8" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_26">
|
||||
<section class="normal" id="section-gitbook_25">
|
||||
|
||||
<h1 id="-">枚举</h1>
|
||||
<p>本页内容包含:</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.9" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.9" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_27">
|
||||
<section class="normal" id="section-gitbook_26">
|
||||
|
||||
<h3 id="-">类和结构体</h3>
|
||||
<p>本页包含内容:</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.10" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.10" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.11" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.11" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,6 +587,209 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_28">
|
||||
|
||||
<h1 id="-methods-">方法(Methods)</h1>
|
||||
<p><strong>方法</strong>是与某些特定类型相关联的功能/函数。类、结构体、枚举都可以定义实例方法;实例方法为指定类型的实例封装了特定的任务与功能。类、结构体、枚举也可以定义类(型)方法(type itself);类型方法与类型自身相关联。类型方法与Objective-C中的类方法(class methods)相似。</p>
|
||||
<p>在Swift中,结构体和枚举能够定义方法;事实上这是Swift与C/Objective-C的主要区别之一。在Objective-C中,类是唯一能定义方法的类型。在Swift中,你能够选择是否定义一个类/结构体/枚举,并且你仍然享有在你创建的类型(类/结构体/枚举)上定义方法的灵活性。</p>
|
||||
<h3 id="-instance-methods-">实例方法(Instance Methods)</h3>
|
||||
<p><strong>实例方法</strong>是某个特定类、结构体或者枚举类型的实例的方法。实例方法支撑实例的功能: 或者提供方法,以访问和修改实例属性;或者提供与实例的目的相关的功能。实例方法的语法与函数完全一致,参考<a href="functions.html" title="函数说明">函数说明</a>。</p>
|
||||
<p>实例方法要写在它所属的类型的前后括号之间。实例方法能够访问他所属类型的所有的其他实例方法和属性。实例方法只能被它所属的类的特定实例调用。实例方法不能被孤立于现存的实例而被调用。</p>
|
||||
<p>下面是定义一个很简单的类<code>Counter</code>的例子(<code>Counter</code>能被用来对一个动作发生的次数进行计数):</p>
|
||||
<pre><code>class Counter {
|
||||
var count = 0
|
||||
func increment() {
|
||||
count++
|
||||
}
|
||||
func incrementBy(amount: Int) {
|
||||
count += amount
|
||||
}
|
||||
func reset() {
|
||||
count = 0
|
||||
}
|
||||
}
|
||||
</code></pre><p><code>Counter</code>类定理了三个实例方法:</p>
|
||||
<ul>
|
||||
<li><code>increment</code>让计数器按一递增;</li>
|
||||
<li><code>incrementBy(amount: Int)</code>让计数器按一个指定的整数值递增;</li>
|
||||
<li><code>reset</code>将计数器重置为0。</li>
|
||||
</ul>
|
||||
<p><code>Counter</code>这个类还声明了一个可变属性<code>count</code>,用它来保持对当前计数器值的追踪。</p>
|
||||
<p>和调用属性一样,用点语法(dot syntax)调用实例方法:</p>
|
||||
<pre><code> let counter = Counter()
|
||||
// the initial counter value is 0
|
||||
counter.increment()
|
||||
// the counter's value is now 1
|
||||
counter.incrementBy(5)
|
||||
// the counter's value is now 6
|
||||
counter.reset()
|
||||
// the counter's value is now 0
|
||||
</code></pre><h3 id="-local-and-external-parameter-names-for-methods-">方法的局部参数名称和外部参数名称(Local and External Parameter Names for Methods)</h3>
|
||||
<p>函数参数有一个局部名称(在函数体内部使用)和一个外部名称(在调用函数时使用),参考<a href="external_parameter_names.html">External Parameter Names</a>。对于方法参数也是这样,因为方法就是函数(只是这个函数与某个类型相关联了)。但是,方法和函数的局部名称和外部名称的默认行为是不一样的。</p>
|
||||
<p>Swift中的方法和Objective-C中的方法极其相似。像在Objective-C中一样,Swift中方法的名称通常用一个介词指向方法的第一个参数,比如:<code>with</code>,<code>for</code>,<code>by</code>等等。前面的<code>Counter</code>类的例子中<code>incrementBy</code>方法就是这样的。介词的使用让方法在被调用时能像一个句子一样被解读。Swift这种方法命名约定很容易落实,因为它是用不同的默认处理方法参数的方式,而不是用函数参数(来实现的)。</p>
|
||||
<p>具体来说,Swift默认仅给方法的第一个参数名称一个局部参数名称;但是默认同时给第二个和后续的参数名称局部参数名称和外部参数名称。
|
||||
这个约定与典型的命名和调用约定相匹配,这与你在写Objective-C的方法时很相似。这个约定还让expressive method调用不需要再检查/限定参数名。</p>
|
||||
<p>看看下面这个<code>Counter</code>的替换版本(它定义了一个更复杂的<code>incrementBy</code>方法):</p>
|
||||
<pre><code>class Counter {
|
||||
var count: Int = 0
|
||||
func incrementBy(amount: Int, numberOfTimes: Int) {
|
||||
count += amount * numberOfTimes
|
||||
}
|
||||
}
|
||||
</code></pre><p><code>incrementBy</code>方法有两个参数: <code>amount</code>和<code>numberOfTimes</code>。默认地,Swift只把<code>amount</code>当作一个局部名称,但是把<code>numberOfTimes</code>即看作本地名称又看作外部名称。下面调用这个方法:</p>
|
||||
<pre><code>let counter = Counter()
|
||||
counter.incrementBy(5, numberOfTimes: 3)
|
||||
// counter value is now 15
|
||||
</code></pre><p>你不必为第一个参数值再定义一个外部变量名:因为从函数名<code>incrementBy</code>已经能很清楚地看出它的目的/作用。但是第二个参数,就要被一个外部参数名称所限定,以便在方法被调用时让他目的/作用明确。</p>
|
||||
<p>这种默认的行为能够有效的检查方法,比如你在参数numberOfTimes前写了个井号( <code>#</code> )时:</p>
|
||||
<pre><code>func incrementBy(amount: Int, #numberOfTimes: Int) {
|
||||
count += amount * numberOfTimes
|
||||
}
|
||||
</code></pre><p>这种默认行为使上面代码意味着:在Swift中定义方法使用了与Objective-C同样的语法风格,并且方法将以自然表达式的方式被调用。</p>
|
||||
<h3 id="-modifying-external-parameter-name-behavior-for-methods-">修改外部参数名称(Modifying External Parameter Name Behavior for Methods)</h3>
|
||||
<p>有时为方法的第一个参数提供一个外部参数名称是非常有用的,尽管这不是默认的行为。你可以自己添加一个明确的外部名称;你也可以用一个hash符号作为第一个参数的前缀,然后用这个局部名字作为外部名字。</p>
|
||||
<p>相反,如果你不想为方法的第二个及后续的参数提供一个外部名称,你可以通过使用下划线(<code>_</code>)作为该参数的显式外部名称来覆盖默认行为。</p>
|
||||
<h3 id="-self-the-self-property-"><code>self</code>属性(The self Property)</h3>
|
||||
<p>类型的每一个实例都有一个隐含属性叫做<code>self</code>,它完全等同于这个实力变量本身。你可以在一个实例的实例方法中使用这个隐含的<code>self</code>属性来引用当前实例。</p>
|
||||
<p>上面例子中的<code>increment</code>方法可以被写成这样:</p>
|
||||
<pre><code>func increment() {
|
||||
self.count++
|
||||
}
|
||||
</code></pre><p>实际上,你不必在你的代码里面经常写<code>self</code>。不论何时,在一个方法中使用一个已知的属性或者方法名称,如果你没有明确的写<code>self</code>,Swift假定你是指当前实例的属性或者方法。这种假定在上面的<code>Counter</code>中已经示范了:<code>Counter</code>中的三个实例方法中都使用的是<code>count</code>(而不是<code>self.count</code>)</p>
|
||||
<p>这条规则的主要例外发生在当实例方法的某个参数名称与实例的某个属性名称相同时。
|
||||
在这种情况下,参数名称享有优先权,并且在引用属性时必须使用一种更恰当(被限定更严格)的方式。
|
||||
你可以使用隐藏的<code>self</code>属性来区分参数名称和属性名称。</p>
|
||||
<p>下面的例子演示了<code>self</code>消除方法参数<code>x</code>和实例属性<code>x</code>之间的歧义:</p>
|
||||
<pre><code>struct Point {
|
||||
var x = 0.0, y = 0.0
|
||||
func isToTheRightOfX(x: Double) -> Bool {
|
||||
return self.x > x
|
||||
}
|
||||
}
|
||||
let somePoint = Point(x: 4.0, y: 5.0)
|
||||
if somePoint.isToTheRightOfX(1.0) {
|
||||
println("This point is to the right of the line where x == 1.0")
|
||||
}
|
||||
// prints "This point is to the right of the line where x == 1.0"
|
||||
</code></pre><p>如果不使用<code>self</code>前缀,Swift就认为两次使用的<code>x</code>都指的是名称为<code>x</code>的函数参数。</p>
|
||||
<h3 id="-modifying-value-types-from-within-instance-methods-">在实例方法中修改值类型(Modifying Value Types from Within Instance Methods)</h3>
|
||||
<p>结构体和枚举是<strong>值类型</strong><a href=""#"">Structures and Enumerations Are Value Types</a>。一般情况下,值类型的属性不能在他的实例方法中被修改。</p>
|
||||
<p>但是,如果你确实需要在某个具体的方法中修改结构体或者枚举的属性,你可以选择<code>变异(mutating)</code>这个方法。方法可以从内部变异它的属性;并且它做的任何改变在方法结束时都会回写到原始结构。方法会给它隐含的<code>self</code>属性赋值一个全新的实例,这个新实例在方法结束后将替换原来的实例。</p>
|
||||
<p>要<code>变异</code>方法, 将关键字<code>mutating</code> 放到方法的<code>func</code>关键字之前就可以了:</p>
|
||||
<pre><code>struct Point {
|
||||
var x = 0.0, y = 0.0
|
||||
mutating func moveByX(deltaX: Double, y deltaY: Double) {
|
||||
x += deltaX
|
||||
y += deltaY
|
||||
}
|
||||
}
|
||||
var somePoint = Point(x: 1.0, y: 1.0)
|
||||
somePoint.moveByX(2.0, y: 3.0)
|
||||
println("The point is now at (\(somePoint.x), \(somePoint.y))")
|
||||
// prints "The point is now at (3.0, 4.0)"
|
||||
</code></pre><p>上面的Point结构体定义了一个变异方法(mutating method)<code>moveByX</code>,<code>moveByX</code>用来移动一个point。<code>moveByX</code>方法在被调用时修改了这个point,而不是返回一个新的point。方法定义是加上那个了<code>mutating</code>关键字,所以方法可以修改值类型的属性了。</p>
|
||||
<p>注意:不能在结构体类型的常量上调用变异方法,因为常量的属性不能被改变,就算你想改变的是常量的可变属性也不行,参考<a href=""#"">Stored Properties of Constant Structure Instances</a></p>
|
||||
<pre><code>let fixedPoint = Point(x: 3.0, y: 3.0)
|
||||
fixedPoint.moveByX(2.0, y: 3.0)
|
||||
// this will report an error
|
||||
</code></pre><h3 id="-self-assigning-to-self-within-a-mutating-method-">在变异方法中给self赋值(Assigning to self Within a Mutating Method)</h3>
|
||||
<p>变异方法能够赋给隐含属性<code>self</code>一个全新的实例。上面<code>Point</code>的例子可以用下面的方式改写:</p>
|
||||
<pre><code>struct Point {
|
||||
var x = 0.0, y = 0.0
|
||||
mutating func moveByX(deltaX: Double, y deltaY: Double) {
|
||||
self = Point(x: x + deltaX, y: y + deltaY)
|
||||
}
|
||||
}
|
||||
</code></pre><p>新版的变异方法<code>moveByX</code>创建了一个新的分支结构(他的x和y的值都被设定为目标值了)。调用这个版本的方法和调用上个版本的最终结果是一样的。</p>
|
||||
<p>枚举的变异方法可以让<code>self</code>从相同的枚举设置为不同的成员。</p>
|
||||
<pre><code>enum TriStateSwitch {
|
||||
case Off, Low, High
|
||||
mutating func next() {
|
||||
switch self {
|
||||
case Off:
|
||||
self = Low
|
||||
case Low:
|
||||
self = High
|
||||
case High:
|
||||
self = Off
|
||||
}
|
||||
}
|
||||
}
|
||||
var ovenLight = TriStateSwitch.Low
|
||||
ovenLight.next()
|
||||
// ovenLight is now equal to .High
|
||||
ovenLight.next()
|
||||
// ovenLight is now equal to .Off
|
||||
</code></pre><p>上面的例子中定义了一个三态开关的枚举。每次调用<code>next</code>方法时,开关在不同的电源状态(<code>Off</code>,<code>Low</code>,<code>High</code>)之前循环切换。</p>
|
||||
<h3 id="-type-methods-">类型方法(Type Methods)</h3>
|
||||
<p>实例方法是被类型的某个实例调用的方法。你也可以定义类列本身调用的方法,这种方法就叫做<strong>类型方法</strong>。声明类的类型方法,在方法的<code>func</code>关键字之前加上关键字<code>class</code>;声明结构体和枚举的类型方法,在方法的<code>func</code>关键字之前加上关键字<code>static</code>。</p>
|
||||
<blockquote>
|
||||
<p>注意:</p>
|
||||
<p>在Objective-C里面,你只能为Objective-C的类定义类型方法(type-level methods)。在Swift中,你可以为所有的类、结构体和枚举定义类型方法:Each type method is explicitly scoped to the type it supports.</p>
|
||||
</blockquote>
|
||||
<p>类型方法和实例方法一样用点语法调用。但是,你是在类型上调用这个方法,而不是在实例上调用。下面是如何在SomeClass类上调用类型方法的例子:</p>
|
||||
<pre><code>class SomeClass {
|
||||
class func someTypeMethod() {
|
||||
// type method implementation goes here
|
||||
}
|
||||
}
|
||||
SomeClass.someTypeMethod()
|
||||
</code></pre><p>在类型方法的方法体(body)中,<code>self</code>指向这个类型本身,而不是类型的某个实例。对于结构体和枚举来说,这意味着你可以用<code>self</code>来消除静态属性和静态方法参数之间的二意性(类似于我们在前面处理实例属性和实例方法参数时做的那样)。</p>
|
||||
<p>一般地,在类型方法里面所使用的任何未限定的方法和属性名称,将会指向其他的类型级别的方法和属性。一个类型方法可以用另一个类型方法的名称调用踏,而无需在方法名称前面加上类型名称的前缀。同样,结构体和枚举的类型方法也能够直接通过静态属性的名称访问静态属性,而不需要类型名称前缀。</p>
|
||||
<p>下面的例子定义了一个名为<code>LevelTracker</code>结构体。它监测玩家的发展情况(游戏的不同层次或阶段)。这是一个单人游戏,但也可以用作多玩家游戏中单个设备上的信息存储。</p>
|
||||
<p>游戏初始时,所有的游戏等级(除了等级1)都被锁定。每次有玩家完成一个等级,这个等级就对这个设备上的所有玩家解锁。<code>LevelTracker</code>结构体用静态属性和方法监测游戏的哪个等级已经被解锁。他还监测每个玩家的当前等级。</p>
|
||||
<pre><code>struct LevelTracker {
|
||||
static var highestUnlockedLevel = 1
|
||||
static func unlockLevel(level: Int) {
|
||||
if level > highestUnlockedLevel { highestUnlockedLevel = level }
|
||||
}
|
||||
static func levelIsUnlocked(level: Int) -> Bool {
|
||||
return level <= highestUnlockedLevel
|
||||
}
|
||||
var currentLevel = 1
|
||||
mutating func advanceToLevel(level: Int) -> Bool {
|
||||
if LevelTracker.levelIsUnlocked(level) {
|
||||
currentLevel = level
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre><p><code>LevelTracker</code>监测玩家的已解锁的最高等级。这个值被存储在静态属性<code>highestUnlockedLevel</code>中。</p>
|
||||
<p><code>LevelTracker</code>还定义了两个类型方法与<code>highestUnlockedLevel</code>配合工作。第一个类型方法是<code>unlockLevel</code>:一旦新等级被解锁,它会更新<code>highestUnlockedLevel</code>的值。第二个类型方法是<code>levelIsUnlocked</code>:如果某个给定的等级已经被解锁,他返回<code>true</code>。(注意:我们没用使用<code>LevelTracker.highestUnlockedLevel</code>,这个类型方法还是能够访问静态属性<code>highestUnlockedLevel</code>)</p>
|
||||
<p>除了静态属性和类型方法,<code>LevelTracker</code>还监测每个玩家的进度。它用实例属性<code>currentLevel</code>来监测玩家当前正在进行的等级。</p>
|
||||
<p>为了便于管理<code>currentLevel</code>属性,<code>LevelTracker</code>定义了实例方法<code>advanceToLevel</code>。这个方法会在更新<code>currentLevel</code>之前检查所请求的新等级是否已经解锁。<code>advanceToLevel</code>方法返回布尔值以指示是否确实能够设置<code>currentLevel</code>了。</p>
|
||||
<p>下面,<code>Player</code>类使用<code>LevelTracker</code>来监测和更新每个玩家的发展进度:</p>
|
||||
<pre><code>class Player {
|
||||
var tracker = LevelTracker()
|
||||
let playerName: String
|
||||
func completedLevel(level: Int) {
|
||||
LevelTracker.unlockLevel(level + 1)
|
||||
tracker.advanceToLevel(level + 1)
|
||||
}
|
||||
init(name: String) {
|
||||
playerName = name
|
||||
}
|
||||
}
|
||||
</code></pre><p><code>Player</code>类创建一个新的<code>LevelTracker</code>实例来检测这个用户的发展进度。他提供了<code>completedLevel</code>方法:一旦玩家完成某个指定等级就调用它。这个方法为所有玩家解锁下一等级,并且将当前玩家的进度更新为下一等级。(我们忽略了<code>advanceToLevel</code>返回的布尔值,因为之前调用<code>LevelTracker.unlockLevel</code>时就知道了这个等级已经被解锁了)</p>
|
||||
<p>你还可以为一个新的玩家创建一个<code>Player</code>的实例,然后看这个玩家完成等级一时发生了什么:</p>
|
||||
<pre><code>var player = Player(name: "Argyrios")
|
||||
player.completedLevel(1)
|
||||
println("highest unlocked level is now \(LevelTracker.highestUnlockedLevel)")
|
||||
// prints "highest unlocked level is now 2"
|
||||
</code></pre><p>如果你创建了第二个玩家,并尝试让他开始一个没有被任何玩家解锁的等级,你试图去设置玩家当前等级时会失败的:</p>
|
||||
<pre><code>player = Player(name: "Beto")
|
||||
if player.tracker.advanceToLevel(6) {
|
||||
println("player is now on level 6")
|
||||
} else {
|
||||
println("level 6 has not yet been unlocked")
|
||||
}
|
||||
// prints "level 6 has not yet been unlocked"
|
||||
</code></pre>
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.12" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.12" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,6 +587,113 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_29">
|
||||
|
||||
<h1 id="-subscripts-">下标 (Subscripts)</h1>
|
||||
<p>下标可以定义在类(Class)、结构体(structures)和枚举(enumerations)这些目标中,可以认为是访问对象、集合或序列的快捷方式。举例来说,用下标访问一个数组(Array)实例中的元素可以这样写 <code>someArray[index]</code> ,访问字典(Dictionary)实例中的元素可以这样写 <code>someDictionary[key]</code>,而不需要再调用实例的某个方法来获得元素的值。</p>
|
||||
<p>对于同一个目标可以定义多个下标,通过索引值类型的不同来进行重载,而且索引值的个数可以是多个。</p>
|
||||
<blockquote>
|
||||
<p>译者:这里下标重载在本小节中原文并没有任何演示</p>
|
||||
</blockquote>
|
||||
<h2 id="-">下标语法</h2>
|
||||
<p>下标允许你通过在实例后面的方括号中传入一个或者多个的索引值来对实例进行访问和赋值。语法类似于实例方法和实例属性的混合。与定义实例方法类似,定义下标使用<code>subscript</code>关键字,显式声明入参(一个或多个)和返回类型。与实例方法不同的是下标可以设定为读写或只读。这种方式又有点像实例属性的getter和setter:</p>
|
||||
<pre><code>subscript(index: Int) -> Int {
|
||||
get {
|
||||
// 返回与入参匹配的Int类型的值
|
||||
}
|
||||
|
||||
set(newValue) {
|
||||
// 执行赋值操作
|
||||
}
|
||||
}
|
||||
</code></pre><p><code>newValue</code>的类型必须和下标定义的返回类型相同。与实例属性相同的是set的入参声明<code>newValue</code>就算不写,在set代码块中依然可以使用<code>newValue</code>这个变量来访问新赋的值。</p>
|
||||
<p>与只读实例属性一样,可以直接将原本应该写在get代码块中的代码写在subscript中即可:</p>
|
||||
<pre><code>subscript(index: Int) -> Int {
|
||||
// 返回与入参匹配的Int类型的值
|
||||
}
|
||||
</code></pre><p>下面代码演示了一个在TimesTable结构体中使用只读下标的用法,该结构体用来展示传入整数的N倍。</p>
|
||||
<pre><code>struct TimesTable {
|
||||
let multiplier: Int
|
||||
subscript(index: Int) -> Int {
|
||||
return multiplier * index
|
||||
}
|
||||
}
|
||||
let threeTimesTable = TimesTable(multiplier: 3)
|
||||
println("3的6倍是\(threeTimesTable[6])")
|
||||
// 输出 "3的6倍是18"
|
||||
</code></pre><p>在上例中,通过TimesTable结构体创建了一个用来表示索引值三倍的实例。数值3作为结构体构造函数入参表示这个值将成为实例成员multiplier的值。</p>
|
||||
<p>你可以通过下标来来得到结果,比如<code>threeTimesTable[6]</code>。这句话访问了threeTimesTable的第六个元素,返回18或者6的3倍。</p>
|
||||
<blockquote>
|
||||
<p><b>提示</b></p>
|
||||
<p>TimesTable例子是基于一个固定的数学公式。它并不适合开放写权限来对threeTimesTable[someIndex]进行赋值操作,这也是为什么下标只定义为只读的原因。</p>
|
||||
</blockquote>
|
||||
<h2 id="-">下标用法</h2>
|
||||
<p>下标根据使用场景不同也具有不同的含义。通常下标是用来访问集合(collection),列表(list)或序列(sequence)中元素的快捷方式。你可以为特定的类或结构体中自由的实现下标来提供合适的功能。</p>
|
||||
<p>例如,Swift的字典(Dictionary)实现了通过下标来对其实例中存放的值进行存取操作。在字典中设值可以通过给字典提供一个符合字典索引类型的索引值的表达式赋一个与字典存放值类型匹配的值来做到:</p>
|
||||
<pre><code>var numberOfLegs = ["spider": 8, "ant": 6, "cat": 4]
|
||||
numberOfLegs["bird"] = 2
|
||||
</code></pre><p>上例定义一个名为numberOfLegs的变量并用一个字典表达式初始化出了包含三对键值的字典实例。numberOfLegs的字典存放值类型推断为<code>Dictionary<String, Int></code>。字典实例创建完成之后通过下标的方式将整型值<code>2</code>赋值到字典实例的索引为<code>bird</code>的位置中。</p>
|
||||
<p>更多关于字典(Dictionary)下标的信息请参考<a href="#">字典的访问与修改</a></p>
|
||||
<blockquote>
|
||||
<p><b>提示</b></p>
|
||||
<p>Swift中Dictionary的下标实现中,在get部分返回值是<code>Int?</code>,也就是说不是每个字典的索引都能得到一个整型值,对于没有设过值的索引的访问返回的结果就是<code>nil</code>;同样想要从字典实例中删除某个索引下的值也只需要给这个索引赋值为<code>nil</code>即可。</p>
|
||||
</blockquote>
|
||||
<h2 id="-">下标选项</h2>
|
||||
<p>下标允许任意数量的入参索引,并且每个入参类型也没有限制。下标的返回值也可以是任何类型。下标可以使用变量参数和可变参数,但使用in-out参数或给参数设置默认值都是不允许的。</p>
|
||||
<p>一个类或结构体可以根据自身需要提供多个下标实现,在定义下标时通过入参个类型进行区分,使用下标时会自动匹配合适的下标实现运行,这就是下标的重载。</p>
|
||||
<p>一个下标入参是最常见的情况,但只要有合适的场景也可以定义多个下标入参。如下例定义了一个Matrix结构体,将呈现一个Double类型的二维数组。Matrix结构体的下标需要两个整型参数:</p>
|
||||
<pre><code>struct Matrix {
|
||||
let rows: Int, columns: Int
|
||||
var grid: Double[]
|
||||
init(rows: Int, columns: Int) {
|
||||
self.rows = rows
|
||||
self.columns = columns
|
||||
grid = Array(count: rows * columns, repeatedValue: 0.0)
|
||||
}
|
||||
func indexIsValidForRow(row: Int, column: Int) -> Bool {
|
||||
return row >= 0 && row < rows && column >= 0 && column < columns
|
||||
}
|
||||
subscript(row: Int, column: Int) -> Double {
|
||||
get {
|
||||
assert(indexIsValidForRow(row, column: column), "Index out of range")
|
||||
return grid[(row * columns) + column]
|
||||
}
|
||||
set {
|
||||
assert(indexIsValidForRow(row, column: column), "Index out of range")
|
||||
grid[(row * columns) + columns] = newValue
|
||||
}
|
||||
}
|
||||
}
|
||||
</code></pre><p>Matrix提供了一个两个入参的构造方法,入参分别是<code>rows</code>和<code>columns</code>,创建了一个足够容纳rows * columns个数的Double类型数组。为了存储,将数组的大小和数组每个元素初始值0.0,都传入数组的构造方法中来创建一个正确大小的新数组。关于数组的构造方法和析构方法请参考<a href="#">Creating and Initializing an Array</a>。</p>
|
||||
<p>你可以通过传入合适的row和column的数量来构造一个新的Matrix实例:</p>
|
||||
<pre><code>var matrix = Matrix(rows: 2, columns: 2)
|
||||
</code></pre><p>上例中创建了一个新的两行两列的Matrix实例。在阅读顺序从左上到右下的Matrix实例中的数组实例grid是矩阵二维数组的扁平化存储:</p>
|
||||
<pre><code>// 示意图
|
||||
grid = [0.0, 0.0, 0.0, 0.0]
|
||||
|
||||
col0 col1
|
||||
row0 [0.0, 0.0,
|
||||
row1 0.0, 0.0]
|
||||
</code></pre><p>将值赋给带有row和column下标的matrix实例表达式可以完成赋值操作,下标入参使用逗号分割</p>
|
||||
<pre><code>matrix[0, 1] = 1.5
|
||||
matrix[1, 0] = 3.2
|
||||
</code></pre><p>上面两句话分别让matrix的右上值为1.5,坐下值为3.2:</p>
|
||||
<pre><code>[0.0, 1.5,
|
||||
3.2, 0.0]
|
||||
</code></pre><p>Matrix下标的getter和setter中同时调用了下标入参的row和column是否有效的判断。为了方便进行断言,Matrix包含了一个名为indexIsValid的成员方法,用来确认入参的row或column值是否会造成数组越界:</p>
|
||||
<pre><code>func indexIsValidForRow(row: Int, column: Int) -> Bool {
|
||||
return row >= 0 && row < rows && column >= 0 && column < columns
|
||||
}
|
||||
</code></pre><p>断言在下标越界时触发:</p>
|
||||
<pre><code>let someValue = matrix[2, 2]
|
||||
// 断言将会触发,因为 [2, 2] 已经超过了matrix的最大长度
|
||||
</code></pre><blockquote>
|
||||
<p>译者:这里有个词Computed Properties 这里统一翻译为实例属性了 微软术语引擎里没有这个词</p>
|
||||
</blockquote>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.13" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.13" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_8">
|
||||
<section class="normal" id="section-gitbook_7">
|
||||
|
||||
<h1 id="-">继承</h1>
|
||||
<p>一个类可以继承另一个类的方法,属性和其它特性。当一个类继承其它类,继承类叫子类,被继承类叫超类(或父类)。在Swift中,继承是区分「类」与其它类型的一个基本特征。</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.14" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.14" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.15" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.15" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_33">
|
||||
<section class="normal" id="section-gitbook_32">
|
||||
|
||||
<h1 id="-">析构过程</h1>
|
||||
<p>在一个类的实例被释放之前,析构函数被立即调用。用关键字deinit来标示析构函数,类似于初始化函数用init来标示。析构函数只适用于类类型。</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.16" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.16" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_34">
|
||||
<section class="normal" id="section-gitbook_33">
|
||||
|
||||
<h1 id="-">自动引用计数</h1>
|
||||
<p>本页包含内容:</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.17" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.17" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_35">
|
||||
<section class="normal" id="section-gitbook_34">
|
||||
|
||||
<h1 id="optional-chaining">Optional Chaining</h1>
|
||||
<p>可选链(Optional Chaining)是一种可以请求和调用属性、方法及子脚本的过程,它的自判断性体现于请求或调用的目标当前可能为空(<code>nil</code>)。如果自判断的目标有值,那么调用就会成功;相反,如果选择的目标为空(<code>nil</code>),则这种调用将返回空(<code>nil</code>)。多次请求或调用可以被链接在一起形成一个链,如果任何一个节点为空(<code>nil</code>)将导致整个链失效。</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.18" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.18" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_36">
|
||||
<section class="normal" id="section-gitbook_35">
|
||||
|
||||
<h1 id="-type-casting-">类型检查(Type Casting)</h1>
|
||||
<p>(ps:为了方便各位检验所以保留了英文,可删。)
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.19" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.19" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_37">
|
||||
<section class="normal" id="section-gitbook_36">
|
||||
|
||||
<h1 id="-">类型嵌套</h1>
|
||||
<p>本页包含内容:</p>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.20" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.20" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_38">
|
||||
<section class="normal" id="section-gitbook_37">
|
||||
|
||||
<h1 id="-extensions-">扩展(Extensions)</h1>
|
||||
<hr>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.21" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.21" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.22" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.22" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_41">
|
||||
<section class="normal" id="section-gitbook_40">
|
||||
|
||||
<h1 id="-">泛型</h1>
|
||||
<hr>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2.23" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2.23" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
|
||||
<div class="book" data-level="2" data-basepath=".." data-revision="1402238318316">
|
||||
<div class="book" data-level="2" data-basepath=".." data-revision="1402267410054">
|
||||
<div class="book-header">
|
||||
<!-- Actions Left -->
|
||||
<a href="#" class="btn pull-left toggle-summary" aria-label="Toggle summary"><i class="fa fa-align-justify"></i></a>
|
||||
@ -587,7 +587,7 @@
|
||||
|
||||
<div class="page-inner">
|
||||
|
||||
<section class="normal" id="section-gitbook_45">
|
||||
<section class="normal" id="section-gitbook_44">
|
||||
|
||||
<h1 id="swift-">Swift 教程</h1>
|
||||
<p>本章介绍了 Swift 的各种特性及其使用方法,是全书的核心部分。</p>
|
||||
|
||||
Reference in New Issue
Block a user