Swift学习笔记

Getting Started

1
2
3
4
5
import Cocoa

var str = "Hello, playground"

str += "!"

用let定义常量
用var定义变量
swift支持类型推断,定义的时候可以不写具体的类型,但是要付给初始值。

print()用来输出数据到console, print()是函数(function)

Types, Constants, and Variables

需要改改变的值定义成变量,不需要改变的值定义成常量。

1
2
3
let numberOfStoplights: Int = 4
var population: Int
population = 5422

“ \ ()” 用来在一个string中插入常量或者变量的值

Conditionals

x = a ? b : c
如果a是true,x = b,否则x = c
if可以嵌套

Numbers

OS X中,Int是64 bit长的,使用Int时要注意不要越界

声明Int型的实例(instance)

1
let numberOfPages: Int10

Switch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import Cocoa

var statusCode: Int = 404
var errorString: string
switch statusCode {
case 400:
errorString = "Bad request"

case 401:
errorString = "Unauthorized"

case 403:
errorString = "Forbidden"

case 404:
errorString = "Not found"

default:
errorString = "None"

}

swift中的switch不需要break,如果某一个case条件match,就执行对应的代码,然后开始执行switch之后的代码

ranges

valueX…valueY

where

where提供了在switch中附加判断条件的能力

1
2
case let unknownCode where (unknownCode >= 200 && unknownCode < 300) || unknownCode > 505:
errorString = "\(unknownCode) is not a known error code."

tuple

一组逻辑相关的值构成一个元组
(statusCode, errorString)
如果元组中使用了下划线,表示这个值可以是任意值
(404, _ )

Loops

for-in

1
2
3
4
5
6
7
8
import Cocoa

var myFirstInt: Int = 0

for i in 1...5 {
++myFirstInt
print(myFirstInt)
}

for case

1
2
3
for case let i in 1...100 where i % 3 == 0 {
print(i)
}

把1…100中所有能被3整除的数字打印出来

1
2
3
4
5
for i in 1...100 {
if i % 3 == 0 {
print(i)
}
}

这两段代码是等价的,但是第一种可读性更好,代码也更简洁

for Loops

1
2
3
4
for var i = 1; i < 6; ++i {
++myFirstInt
print(myFirstInt)
}

while Loops

1
2
3
4
5
6
var i = 1
while i < 6 {
++myFirstInt
print(myFirstInt)
++i
}

break 跳出循环,执行循环后面的代码
continue 结束本次循环,继续下次循环

Strings

Unicode swift的String和Character类型是建立在Unicode码之上的

Optionals

Optional是swift引入的全新概念,简单来说就是表示某个instance可能为空,如果一个常量或者变量被定义成了optional类型,就表示它可能有值,也可能为空。

swift为了安全而引入了optional,如果一个instance可能有值,也可能是nil,那么它必须被定义为optional类型,反过来说,如果一个instance没有被定义成optional,那么它一定不为空。

强制解包optioanl unwrapping

1
2
3
4
5
6
var errorCodeString: String?

if errorCodeString != nil {
let theError = errorCodeString!
print(theError)
}

optional Binding

1
2
3
4
5
6
7
8
import Cocoa

var errorCodeString: String?
errorCodeString = "404"

if let theError = errorCodeString {
print(theError)
}

Arrays

Arrays are an ordered collection of values. Each position in an array is identified by an index, and any value can appear multiple times in an array.

Accessing and Modifying Arrays

向数组添加值

1
2
3
4
import Cocoa

var bucketList = ["Climb Mt. Everest"]
bucketList.append("Fly hot air balloon to Fiji")

从数组删掉值

1
2
3
import Cocoa

bucketList.removeAtIndex(2)

计算数组中元素个数

1
bucketList.count

取数组中的一部分数值

1
bucketList[0...3]

在数组中插入值

1
bucketList.insert("Toboggan across Alaska", atIndex: 2)

Dictionaries

字典,内部数据无顺序,都是key-value对
swift的字典要求所有的key不是是hashable的。
swift中String, Int, Float, Double, Bool都是hashable的。

Creating a Dictionary

1
2
3
import Cocoa

var movieRatings = ["Donnie Darko": 4, "Chungking Express": 5, "Dark City": 4]

Accessing and Modifying a Dictionary

字典中key-value对的个数:movieRatings.count
从字典中获取值:movieRatings[“Donnie Darko”]
无论何时,你提供给字典一个key,它返回的都是一个optional类型的值, 可能是和这个key匹配的value,也可能是nil
update 字典中的数据:movieRatings.updateValue(5, forKey: “Donnie Darko”)

Adding and Removing Values

向字典中添加一个key-value对: movieRatings[“The Cabinet for Dr. Caligari” = 5]
从字典中删除一个key-value对: movieRatings.removeValueForKey(“Dark City”)

Looping

1
2
3
for (key, value) in movieRatings {
print("The movie \(key) was rated \(value).")
}

单独循环

1
2
3
for movie in movieRatings.keys {
print("User has rated \(movie).")
}

Translating a Dictionary to an Array

1
let watchedMovies = Array(movieRatings.keys)

Sets

What Is a Set

A Set is an unordered collection of distinct instances.
set中的值必须是唯一的。

Getting a Set

1
var groceryBag = Set<String>()

向Set中添加元素

1
groceryBag.insert("Apples")

在set中循环

1
2
3
for food in groceryBag {
print(food)
}

从数组构建set

1
var groceryBag: Set = ["Apples", "Oranges", "Pineapple"]

set中是否存在:groceryBag.contains(“Bananas”)
set取并集:let commonGroceryBag = groceryBag.union(friendsGroceryBag)
set取交集:let itemsToReturn = commonGroceryBag.intersect(roommatesGroceryBag)
两个set是否有交集:let disjoint = yourSecondBag.isDisjointWith(roommatesSecondBag)

###Functions

A function is a named set of code that is used to accomplish some specific task.

定义一个function

1
2
3
4
5
6
import Cocoa

func printGreeting() {
print("Hello, playground.")
}
printGreeting()

function 的参数

1
2
3
4
5
func printPersonalGreeting(name: String) {
print("Hello \(name), welcome to your playground.")
}

printPersonalGreeting("Matt")

printPersonalGreeting调用时,不需要使用第一个参数的名字。

By default, if you call a function with more than one parameter, the first parameter name is not used, but all others are.

外部参数名:

1
2
3
4
func divisionDescription(forNumerator num: Double, andDenominator den: Double) {
print("\(num) divided by \(den) equals \(num / den)")
}
divisionDescription(forNumerator: 9.0, andDenominator: 3.0)

外部参数用于函数调用,内部参数用于实现函数的功能。

Variadic parameters

可变参数,参数的个数不是固定的,一个function只能含有一个variadic parameters 而且必须是最后一个参数

1
2
3
4
5
6
func printPersonalGreeting(names: String...) {
for name in names {
print("Hello \(name), welcome to the playground")
}
}
printPersonalGreeting("Alex", "Chris", "Drew", "Pat")

Default parameter values

Swift 的参数可以有默认值,默认值应该放在函数参数列表的最后,如果一个参数有默认值,那么在调用行数的时候可以不提供这个参数的值。

1
2
3
4
func divisionDescription(forNumerator num: Double, andDenominator den: Double, withPunctuation punctuation: String = ".") {
print("\(num) divided by \(den) equals \(num/den)\(punctuation)")
}
divisionDescription(forNumerator: 9.0, andDenominator: 3.0)

In-out parameters

有时候需要改变传入函数的参数的值,这时候需要定义In-out参数,但是它不能有默认值,另外可变参数不能定义为In-out参数。

1
2
3
4
5
6
7
var error = "The request failed:"
func appendErrorCode(code: Int, inout toErrorString errorSting: String) {
if code == 400 {
errorSting += " bad request."
}
}
appendErrorCode(400, toErrorString: &error)

Nested Functions and Scope

Swift支持function的嵌套定义,可以在一个function中再定义一个function,内部的function在外面是不可访问的。

1
2
3
4
5
6
7
func areaOfTriangle(withBase base: Double, andHeight height: Double) -> Double {
let numerator = base * height
func divide() -> Double {
return numerator / 2
}
return divide()
}

Exiting Early from a Function

A guard statement is used to exit early from a function if some condition is not met, hence the name guard.

1
2
3
4
5
6
7
8
func greetByMiddleName(name: (first: String, middle: String?, last: String)) {
guard let middleName = name.middle else {
print("Hey there!")
return
}
print("Hey \(middleName)")
}
greetByMiddleName(("Matt", "Danger", "Mathias"))

如果middle中有值,则执行guard之后的print,如果middle中没有值,则执行guard中的语句并提早从function中return。

Closures

Closures are discrete bundles of functionality that can be used in your application to accomplish specific tasks.

You can think of a function as a named closure.

Closures Syntax

给数组排序

1
2
3
4
5
6
7
8
import Cocoa

var volunteerCounts = [1, 3, 40, 32, 2, 53, 77, 13]

func sortAscending(i: Int, j: Int) -> Bool {
return i < j
}
let volunteersSorted = volunteerCounts.sort(sortAscending)

sortAscending提供了针对数组中元素的比较规则,sortAscending就是一个closure.

Closure Expression Syntax

{(parameters) -> return type in
//Code
}

1
2
3
4
let volunteersSorted = volunteerCounts.sort({
(i: Int, j: Int) -> Bool in
return i < j
})

Closures 能够使用swift的类型推断,所以参数的类型可以省略

1
let volunteersSorted = volunteerCounts.sort({i, j in i < j})

这个Closure只有一个表达式,因此可以删掉return关键字,如果closure的表达式多于一个,那么必须使用return关键字。

Swift provides shorthand argument names that you can refer to inline closure expressions. These shorthand argument names behave similarly to the explicitly declared arguments you have been using: they have the same types and values. The complier’s type inference capabilities help it know the number and types of arguments your closure takes, which means it is not necessary to name them.

1
let volunteersSorted = volunteersCount.sort({$0 < $1})

编译器知道sort需要一个closure类型的参数,这个closure的参数类型和数组里面的元素类型是一样的,closure有两个参数,他们的值的比较结果决定了排序顺序,因此可以用$0代表第一个参数,$1代表第二个参数。

If a closure is passed to a function’s final argument, it can be written inline, outside of and after the function’s parentheses.
如果closure是一个function的最后一个参数,那么它能写在function的括号以外。

1
2
3
4
5
import Cocoa

var volunteersCounts = [1, 3, 40, 32, 2, 53, 77, 13]

let volunteersSorted = volunteersCounts.sort {$0 < $1}

It is always more important to make sure that your code is readable and maintainable.