β

Swift3 指导手册:基础篇

SwiftGG 25 阅读

作者:Jameson Quave, 原文链接 ,原文日期:2016-08-29
译者: 与狼同行 ;校对: walkingway ;定稿: CMB

在 Swift 3 指导手册中,我们将聚焦如何帮助初学者从一个完完全全的新手到基本掌握 Swift 。这里会使用 Swift 3 来教学。我们编写这个指导的初衷是因为市面上的很多指导手册都已过时了,因此它就不适合仅仅以“ Swift3 有哪些新功能”来行文。我们找了几位有多门语言的编程经验的人士,来教你 Swift 语言的独特性以及如何用好它。

变量和常量

任何 Swift 中的变量要么不变的,要么是可变的。这句话可不要和 Int Float 这些变量类型混淆。变量和常量仅仅是一种视角来描绘持有的值是可修改的(即可变性),亦或是不能修改的(即不可变性)。
要定义一个常量,使用 let 关键字。

举例来说:

let name = "Jameson"
name = "Bob"
error: cannot assign to value: 'name' is a 'let' constant
name = "Bob"
~~~~ ^

要解决它,我们可以使用 var 关键字,来定义一个可以修改的变量:

let age: Int = 5

相似的,你可以声明一个字符串类型:

let age = 5
let name = "Jameson"

age 和 name 的类型仍然是 Int 和 String ,但是这次我们跳过了类型声明,因为很显然,5 是 Int 类型,而 “Jameson” 是一个字符串。

记住, let 关键字仅仅使值变得不可变。如果我们预测这个 age 的值是可变的,而 name 不是可变的,那么我们应该这么写:

var age = 5
let name = "Jameson"
age = 25
print(age)
25

使用字符串

print 打印命令或者 String 的字符串总是很方便。例如,我想要打印一个包含变量 age 和变量 name 的语句,可以在两个 String 变量之间用 + 操作符。

let sentence = "\(name) is \(age)"
print(sentence)
Robb is 15

现在也可以看到同样的效果,但是它更容易阅读和组合。

也许你注意到了, age 现在是一个 String 类型因为它现在是 “15” 而不是 15,没有了引号。这是因为如果一个字符串和一个整型组合, Int 类型将不会自动转型为 String 类型,这在组合前是非常重要的一步。

这样的话,以下代码会产生错误。

let age = 15
let name = "Robb"

let stringAge = String(age)

let sentence = name + " is " + stringAge
print(sentence)
Robb is 15

我们创建了一个新的变量叫做 stringAge 。然后使用了类型转换,因为字符串插值操作会单独的分析每一个表达式,同样获取到圆括号内的内容。

var favoriteColor: String?

在对可选类型的声明中如果不进行赋值,那么它就是 nil 的。你可以使用 print 函数来对它进行打印来证实这个观点。

var favoriteColor: String?
favoriteColor = "Blue"
print(favoriteColor)
Optional("Blue")

我们发现结果不是 "Blue" ,而是 Optional("Blue") 。那是因为实际值仍然包裹在可选类型之中。
你可以认为可选类型就像一个生日礼物,像礼物盒外面那层精美的包装纸,拆开他们之后,也许里面什么都没有。这对某些过生日的人真是个残忍的礼物,不过这确实真的会发生。也许礼物盒中确实会有真的礼物,可也得拆开并且实际去看才知道,现在它只是一个没有被拆开,躺在我们手中的一个盒子。

如果我们想知道里面是什么,需要马上拆开礼物,对可选类型来说也是一样,当传递和使用它们时,实际我们只是在和一个也许有值的容器在打交道。就像礼物一样,可选类型在被使用之前必须被解包。

Swift 中声明一个可选类型可以不赋值,编译也会通过。但是如果我们声明这些变量时不加上可选类型的符号,那么就会报错。

var favoriteColor: String
error: variables must have an initial value

解包

我们现在知道可选类型是什么了,它们可以使变量可以为空,也知道与其说它们是值不如说是一个容器。因此,在项目中要访问可选类型中的内容时,我们该怎么做?

第一,最普遍的方式是使用可选类型绑定,在可选绑定中,你可以在一个 if 语句中把可选类型的值赋给一个新的值。如果可选类型包含一个值,那个新的变量就会被成功设置,并且跟随 if 语句的代码闭包也会成功执行。
来看例子,这里将声明两个可选类型,一个叫做 favoriteAnimal ,它被设置值为 Fox ,而另外一个是 favoriteSong 我们并没有对它进行赋值。

if let unwrappedFavoriteAnimal = favoriteAnimal {
print("Favorite animal is: " + unwrappedFavoriteAnimal)
}
Favorite animal is: Fox

当没有被设置值时,仅仅会触发 else 语句,或者如果连 else 语句都没有,那么什么都不会触发。

var favoriteAnimal: String?
var favoriteSong: String?

favoriteAnimal = "Fox"
favoriteSong = "Shake it Off"

if let unwrappedFavoriteSong = favoriteSong {
if let unwrappedFavoriteAnimal = favoriteAnimal {
print(unwrappedFavoriteSong + " " + unwrappedFavoriteAnimal)
}
}

这看上去非常杂乱,因此 Swift 提供一种简便方式来一次解包多个变量:

let starks: [String] = ["Eddard", "Catelyn", "Robb", "Sansa"]

这里我们定义了一个基本的 Array 类型,它是字符串数组类型 [String]
这个方括号暗示了它是一个存放字符串对象的数组,而不是一个字符串类型。一般来说,Swift 可以通过检测所赋的初值进行类型推断。

let starks = ["Robb", "Sansa", "Arya", "Jon"]
print( starks[0] )
print( starks[2] )
print( starks.first! )
Robb
Arya
Robb

你应该发现数组是以 0 为下标开始的,因此数组中的第一个元素 "Robb" 可以通过 stack[0] 来访问。
另外,可能你会发现使用 first 方法返回的是一个可选值。而下标访问器返回的并不是一个可选值。如果访问数组中没有出现的下标,程序将会在运行时报错。因此在通过下标访问时检查数组的长度:

let ages = ["Robb": 15, "Sansa": 12, "Arya": 10, "Jon": 15]

我们可以访问这些值通过 String 的键

if let aryasAge = ages["Arya"] {
print("Arya is \(aryasAge) years old")
}
Arya is 10 years old

我们也可以把数组存储在字典中,或者把字典存储在数组中,或者把他们混合使用。

let colors: Set<String> = ["Blue", "Red", "Orange", "Blue"]

代码创建了一个字符串的集合。大于和小于符号 "<"">" 暗示 Swift 中的泛型类型,你可能注意到了 "Blue" 在列表中出现了两次,但是如果我们把颜色打印出来,马上就会发现:

["Orange", "Red", "Blue"]

你也许还注意到了顺序也不一致了,因为集合不会维持特定的顺序。

我们无法像访问数组下标一样的方式去访问集合。但是可以用集合中内置的方法来增加或者删除元素,可以通过 contains 方法来查看是否集合中包含了该元素。

["Black", "Orange", "Blue"]
true
false

构造集合对象最常见的方式就是罗列哪些元素应该纳入列表,哪些元素应该被排除。

这里还有许多方法我还没有提到,我建议你去阅读一下苹果的官方文档关于这三种集合类型,这样就会对它们更了解。

元组

元组并不是一种集合,而应该说是用一个标识符来表示多个不同变量。

let fullName = ("Jameson", "Quave")
print(fullName.1)
print(fullName.0)
let (first, last) = ("Jameson", "Quave")
print(first)
let (first, _) = ("Jameson", "Quave")
print(first)
if 10 > 5 {
print("10 is greater than 5.")
}
else {
print("10 is not greater than five.")
}
if (10 > 5) {
...

Swift 也支持 switch 语句,在编译期的时候检查你是否已经覆盖了所有的可能条件,如果你没有覆盖所有的条件,你得加上 defualt:case 来处理一些没有考虑到的情况:

This is Jameson

由于此处 name 的值是 "This is Jameson" 。我们匹配到了第二个条件,然后执行下面这行。

let name = "Jason"
switch(name) {
case "Joe":
print("Name is Joe")
case "Jameson":
print("This is Jameson")
default:
print("I don't know of this person!")
}
let names = ["Robb", "Sansa", "Arya", "Jon"]

for name in names {
print("Name: \(name)")
}
for i in 1...10 {
if i % 3 == 0 {
print(i)
}
}
let byThrees = stride(from: 3, to: 10, by: 3)
for n in byThrees {
print(n)
}
for n in stride(from: 3, to: 10, by: 3) {
print(n)
}
let names = ["Robb", "Sansa", "Arya", "Jon"]
for nameIndex in names.indices {
if(nameIndex < 3) {
print(names[nameIndex])
}
}
let names = ["Robb", "Sansa", "Arya", "Jon"]
for (index, name) in names.enumerated() {
print("\(index): \(name)")
}
: Robb
1: Sansa
2: Arya
3: Jon

在 Swift3 中还有很多方式来遍历对象,但他们通常不是很常用。

也许你已经发现我们的循环中同时给两个变量赋值,index 和 name。它们被用逗号分隔并被括号括起来,表示我们从 enumerated() 返回的两个被命名的变量。

本篇文章快速总结了一下 Swift 3 中手册中比较基础的部分,下一章,我将带领你们在真是项目中去演练我们所学到的知识,做到活学活用。

本文由 SwiftGG 翻译组翻译,已经获得作者翻译授权,最新文章请访问 http://swift.gg

Swift3.0的基础教程
作者:SwiftGG
走心的 Swift 翻译组
原文地址:Swift3 指导手册:基础篇, 感谢原作者分享。

发表评论