【iOS】Swift语法畅游,语法查询

最好下载官方的Playground Demo对比查看,写的很好。下载地址

如果官方更新地址,导致失效了,那就直接搜The Swift Programming Language,然后A Swift Tour中就能看到地址了。


学习新语法的经典通用语句:

1
print("Hello, world!")

Simple Values

let声明常量。var声明变量。

1
2
3
var myVariable = 42
myVariable = 50
let myConstant = 42

创建的时候不需要显式的指出常量或变量的类型。创建的时候提供一个值让编译器推断它的类型。上例中编译器会推断myVariable 是整型,因为初始值是个整数。

初始值如果没有提供足够的信息,或者没有初始值,那就在变量后用冒号指定类型。

1
2
3
let implicitInteger = 70
let implicitDouble = 70.0
let explicitDouble: Double = 70

swift不会对值进行隐式转换。需要转换类型的时候要显示的指出:

1
2
3
let label = "The width is "
let width = 94
let widthLabel = label + String(width)

widthLabel的值是”The width is 94”。

如果这样写:

1
let widthLabel = label + width

就会报错:error: binary operator ‘+’ cannot be applied to operands of type ‘String’ and ‘Int’

有一个简单的方法在string中包含值。用括号把值包起来,然后在括号前面写一个反斜线(\)

1
2
3
4
let apples = 3
let oranges = 5
let appleSummary = "I have \(apples) apples."
let fruitSummary = "I have \(apples + oranges) pieces of fruit."

对于占用多行的字符串使用三个双引号(“”“),只要匹配关闭引号的缩进,每个引用行的开始处的缩进就会被删除,通过下面例子理解这句话。

1
2
3
4
5
6
7
8
let quotation = """
Even though there's whitespace to the left,
the actual lines aren't indented.
Except for this line.
Double quotes (") can appear without being escaped.

I still have \(apples + oranges) pieces of fruit.
"""

结果是:

1
2
3
4
5
6
Even though there's whitespace to the left,
the actual lines aren't indented.
Except for this line.
Double quotes (") can appear without being escaped.

I still have 8 pieces of fruit.

如果修改关闭引号的缩进:

1
2
3
4
5
6
7
8
let quotation = """
Even though there's whitespace to the left,
the actual lines aren't indented.
Except for this line.
Double quotes (") can appear without being escaped.

I still have \(apples + oranges) pieces of fruit.
"""

结果就变成了

1
2
3
4
5
6
Even though there's whitespace to the left,
the actual lines aren't indented.
Except for this line.
Double quotes (") can appear without being escaped.

I still have 8 pieces of fruit.

创建数组和字典:

1
2
3
4
5
6
7
8
var shoppingList = ["catfish", "water", "tulips", "blue paint"]
shoppingList[1] = "bottle of water"

var occupations = [
"Malcolm": "Captain",
"Kaylee": "Mechanic",
]
occupations["Jayne"] = "Public Relations"

创建空数组或字典

1
2
et emptyArray = [String]()
let emptyDictionary = [String: Float]()

如果类型信息已经被推断出了,就可以用[]写空数组,用[:]写空字典。

1
2
shoppingList = []
occupations = [:]

Control Flow

ifswitch条件语句。for-inwhilerepeat-while循环。

条件的括号是可选的,执行语句的花括号是必须的。

1
2
3
4
5
6
7
8
9
10
let individualScores = [75, 43, 103, 87, 12]
var teamScore = 0
for score in individualScores {
if score > 50 {
teamScore += 3
} else {
teamScore += 1
}
}
print("teamScore is \(teamScore)")

在类型后面加?来标记值是可选的

1
2
3
4
5
6
7
8
9
10
11
var optionalString: String? = "Hello"
print(optionalString == nil)

var optionalName: String? = "John Appleseed"
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
} else {
greeting = "Hello, tell me nmae"
}
print(greeting)

结果是

1
2
false
Hello, John Appleseed

如果把String都设置成nil

1
2
3
4
5
6
7
8
9
10
11
var optionalString: String? = nil
print(optionalString == nil)

var optionalName: String? = nil
var greeting = "Hello!"
if let name = optionalName {
greeting = "Hello, \(name)"
} else {
greeting = "Hello, tell me nmae"
}
print(greeting)

结果是

1
2
true
Hello, tell me nmae

另一种处理可选值的方法是使用??操作符。如果可选值是nil,后面的默认值就会被代替使用:

1
2
3
let nickName: String? = nil
let fullName: String = "John Appleseed"
let informalGreeting = "Hi \(nickName ?? fullName)"

Switch语句非常多类型的比较,不局限于整数相等了

1
2
3
4
5
6
7
8
9
10
11
let vegetable = "red pepper"
switch vegetable {
case "celery":
print("Add some raisins and make ants on a log.")
case "cucumber", "watercress":
print("That would make a good tea sandwich.")
case let x where x.hasSuffix("pepper"):
print("Is it a spicy \(x)?")
default:
print("Everything tastes good in soup.")
}

结果是

1
Is it a spicy red pepper?

default是必须的,如果不写default,就会报错:

1
error: switch must be exhaustive

执行完case语句的内容后,不写break,也不会接着往下执行其他case的内容。所以这里都不需要显式的写break。

可以使用for-in 对字典进行迭代遍历。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
largest = number
}
}
}
print(largest)

结果是25.

while循环

1
2
3
4
5
6
7
8
9
10
11
var n = 2
while n < 100 {
n *= 2
}
print(n)

var m = 2
repeat {
m *= 2
} while m < 100
print(m)

结果都是128。用Playground中还可以看到右边显示了每个循环的次数都是6次。fun!

for循环

1
2
3
4
5
var total = 0
for i in 0..<4 {
total += i
}
print(total)

..<来产生index的范围。..<表示不包含上限,即不包含4。表示包含上限的范围。

注意不存在..>这样的操作符。。。error: use of unresolved operator '..>'

Functions and Closures

func声明函数。->来分开参数名和函数返回值。即->前面是参数,后面是函数返回值。

1
2
3
4
func greet(person: String, day: String) -> String {
return "Hello \(person), today is \(day)."
}
print(greet(person: "Bob", day: "Tuesday"))

默认情况下,函数使用其参数名称作为参数的标签。 在参数名称之前编写自定义参数标签,或者写_不使用参数标签。

1
2
3
4
func greet(_ person: String, on day: String) -> String {
return "Hello \(person), today is \(day)."
}
greet("John", on: "Wednesday")

使用一个元组来创建复合值,例如,从函数返回多个值。 元组的元素可以通过名称或数字来引用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) {
var min = scores[0]
var max = scores[0]
var sum = 0

for score in scores {
if score > max {
max = score
} else if score < min {
min = score
}
sum += score
}

return (min, max, sum)
}
let statistics = calculateStatistics(scores: [5, 3, 100, 3, 9])
print(statistics.sum)
print(statistics.2)

结果都是120,两个print打印的都是sum

函数嵌套

1
2
3
4
5
6
7
8
9
func returnFifteen() -> Int {
var y = 10
func add() {
y += 5
}
add()
return y
}
print(returnFifteen())

结果是15

这里说函数是first-class type,这个可以看一下网上的讨论 - 地址

函数可以作为另一个函数的返回值

1
2
3
4
5
6
7
8
func makeIncrementer() -> ((Int) -> Int) {
func addOne(number: Int) -> Int {
return 1 + number
}
return addOne
}
var increment = makeIncrementer()
print(increment(7))

结果是8.

函数也可以作为另一个函数的参数

1
2
3
4
5
6
7
8
9
10
11
12
13
func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool {
for item in list {
if condition(item) {
return true
}
}
return false
}
func lessThanTen(number: Int) -> Bool {
return number < 10
}
var numbers = [20, 19, 7, 12]
hasAnyMatches(list: numbers, condition: lessThanTen)

结果是ture