变量通过 var 声明,常量通过 let 声明。 Swift 可以推断变量的类型(type reference),所以声明变量可以直接如下:
1 2 3 4 5
var string = “My string”
//也可以先声明类型(必须)或声明与赋值同时:
var string:String = “My string”
苹果官方建议在声明有小数部分的变量时都采用 Double,因其具有更高的精准度。
Swift 中 bool 值是 true 和 false。
“+” 号也可用于 string :
1 2 3
var name1 = "Tim McGraw" var name2 = "Romeo" var both = name1 + " and " + name2 //"Tim McGraw and Romeo"
字符串的对比运算是”case-sensitive”,也就是区分大小写:
1 2 3
var name = “TIM MCGRAW" var name2 = "TiM mCgRaW" name == name2 //result is false
在 string 中插入变量:
1 2 3 4 5
var name = “TimMcGraw” “Your name is \(name)” //可以在括号中运算: var age = 25 “His age is \(age * 2)”
Arrays,Dictionaries,Loops,Switch case
通过类型注释(Type annotaions)可以申明数组内容的类型:
1 2
var songs: [String] = ["Shake it Off", "You Belong with Me", "Back to December", 3] //以上会报错,因为数组内有非 String 类型的”3”在内。
以下代码仅仅是声明了一个将要被分配包含String对象数组的变量:
1 2 3 4 5 6 7 8
var array:[String] //没有真正创建数组对象
var array: [String] = [] //这时才是创建了数组对象
var array = [String] () //效果同上,语法更为简洁。
数组可以直接使用”+”运算符结合:
1 2 3 4 5 6
var songs = ["Shake it Off", "You Belong with Me", "Love Story"] var songs2 = ["Today was a Fairytale", "White Horse", "Fifteen"] var both = songs + songs2
both += [“Everything”] //可以增加并赋值
创建一个 Disctionary:
1 2 3 4 5 6 7
var person = [ "first": "Taylor", "middle": "Alison", "last": "Swift", "month": "December", "website": "taylorswift.com" ]
Swift 中,条件表达式不需要括号:
1 2 3 4 5 6 7
if person == "hater" { action = "hate" } elseif person == "player" { action = "play" } else { action = "cruise" }
在 Swift 2.0中,println() 改为 print()
Swift 的 for 循环语法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// closed range operator for i in1...10{ println("\(i) x 10 is \(i * 10)") } /* 以上结果相当于: println("1 x 10 is \(1 * 10)") println("2 x 10 is \(2 * 10)") println("3 x 10 is \(3 * 10)") println("4 x 10 is \(4 * 10)") println("5 x 10 is \(5 * 10)") println("6 x 10 is \(6 * 10)") println("7 x 10 is \(7 * 10)") println("8 x 10 is \(8 * 10)") println("9 x 10 is \(9 * 10)") println("10 x 10 is \(10 * 10)") */
不需要「循环数」时也可以用下划线代替:
1 2 3
for_in1 ... 5 { str += " fake" }
half open range operator(半开区间运算符):”..<”,例如 ..<5 将会循环四次,count 将会是 1,2,3,4。”..<” 可以方便于遍历数组(数组的 index 从0算起):
1 2 3
for i in0 ..< count(people) { println("\(people[i]) gonna \(actions[i])") }
遍历数组的语法:
1 2 3 4 5 6 7 8 9 10 11 12
...
for song in songs { println("My favorite song is \(song)") } //通过 index 同时遍历俩数组: var people = ["players", "haters", "heart-breakers", "fakers"] var actions = ["play", "hate", "break", "fake"]
for i in0 ... 3 { println("\(people[i]) gonna \(actions[i])") }
获取数组内的对象数量的方法在 Swift 1.2中是 count(array),在 Swift 2.0中是 array.count。
loop 中的 continue 语法 将会终止当前的迭代回到 loop 的开头继续迭代。
switch/case 语法可以简化较多的 if/else if 语法,Swift 要求 switch 条件变量所有可能的情况都得涵盖( cases should exhustive),否则 Xcode 可能无法构建应用,default 可以避免该问题。
可以在 switch/case 中使用 “…”(half open range operator) 将变量可能的范围作为一个 case:
1 2 3 4 5 6 7 8 9 10 11
let studioAlbums = 5 switch studioAlbums { case0...1: println("You're just starting out") case2...3: println("You're a rising star") case4...5: println("You're world famous!") default: println("Have you done something new?") }
Swift 2.0 方法调用和1.2稍有不同,需要写明参数名,目的是提高代码可读性:
1 2 3 4 5 6
funcprintAlbumRelease(name: String, year: Int) { println("\(name) was released in \(year)") } printAlbumRelease("Fearless", year: 2008) printAlbumRelease("Speak Now", year: 2010) printAlbumRelease("Red", year: 2012)
“->”符号为方法声明返回值:
1
funcalbumsIsTaylor(name: String) -> Bool
Optionals
Apple 在 Swift 中为其加入了 Optional,Optional 是一种类型,可以有值,也可以等于 nil(也就是没有值)。在 oc 中,只有指向对象的指针可以为 nil,而在 swift 中基本类型创建后没有初始值,而是为 nil,并且无法使用。
在 Swift 中,类和结构体有点相似,都可以拥有属性和方法,区别在于结构体是值拷贝,这意味着改变拷贝值不会改变原来的值,而类是指针拷贝,拷贝的变量会指向相同的实例,见下例:
1 2 3 4 5 6 7 8 9 10 11 12 13
// Value type example structS{ var data: Int = -1 } var a = S() var b = a // a is copied to b a.data = 42// Changes a, not b println("\(a.data), \(b.data)") // prints "42, -1"
// Reference type example classC{ var data: Int = -1 } var x = C() var y = x // x is copied to y x.data = 42// changes the instance referred to by x (and y) println("\(x.data), \(y.data)") // prints "42, 42"
structPerson{ var clothes: String var shoes: String
funcdescribe() { print("I like wearing \(clothes) with \(shoes)") } }
let taylor = Person(clothes: "T-shirts", shoes: "sneakers") let other = Person(clothes: "short skirts", shoes: "high heels") taylor.describe() //"I like wearing T-shirts with sneakers" other.describe() //"I like wearing short skirts with high heels" //调用方法时,不同的对象使用相应的值
Property observers
Swift 提供了两个观察者方法,willSet 和 didSet,分别会在属性的值将要改变以及改变后触发(常用于用户界面的更新):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
structPerson{ var clothes: String { willSet { updateUI("I'm changing from \(clothes) to \(newValue)") } didSet { updateUI("I just changed from \(oldValue) to \(clothes)") } } }
funcupdateUI(msg: String) { print(msg) }
var taylor = Person(clothes: "T-shirts") taylor.clothes = "short skirts"//值改变,将会调用观察者方法
Computed properties
Computed properties 其实就是自己重写属性的 get/set 方法:
1 2 3 4 5 6 7 8 9 10 11 12
structPerson{ var age: Int
var ageInDogYears: Int { get { return age * 7 } } }
var fan = Person(age: 25) print(fan.ageInDogYears) //输出:25 * 7
overridefuncgetPerformance() -> String { return"The live album \(name) sold lots" } }
总而言之,一个对象可以同时实现自己类的行为和其父类的行为,这称为「多态」。
Converting types with type casting
这种情况时有发生:你有一个明确声明的对象,但你知道它其实是另一种类型(比如上面的继承类StudioAlbum 和 LiveAlbum 被当做 Album 保存在数组中,因为它们继承于 Album 所以是允许的),当需要调用方法时,Swift 可能不知道它的真实类型而无法编译,解决办法是 type casting,即类型转换,可以将一个对象的类型转为另一种类型:
1 2 3
for album in allAlbums { print(album.getPerformance()) } //根据上面代码块的内容
allAlbums 数组拥有三个类型为 Album 的对象,但是其中两个我们知道是 StudioAlbum 和 LiveAlbum,但是 Swift 却不知道,如果你想执行 print(album.studio) 则无法编译,因为只有 StudioAlbum拥有那个属性。
Type casting 有三种形式,但常见的只有两种:as? 和 as!,分别是可选向下转型以及强制向下转型,前者会返回一个转型后的可选值(optional value),若转型失败会返回nil;当你确定可以转型成功时使用后者,如果转型失败可能导致应用崩溃: P.S.「转型」并不是指真的改变实例或它的值,而只是告诉 Swift 把这个对象看做某个类的实例。
1 2 3
for album in allAlbums { let studioAlbum = album as? StudioAlbum }
var taylorSwift = StudioAlbum(name: "Taylor Swift", studio: "The Castles Studios") var fearless = StudioAlbum(name: "Speak Now", studio: "Aimeeland Studio")
var allAlbums: [Album] = [taylorSwift, fearless]
for album in allAlbums { let studioAlbum = album as! StudioAlbum print(studioAlbum.studio) //便利数组时如果数组内有 liveAlbum 类的实例就会 crash,因为使用了强制转型 //所以为了不 crash,只存放 `StudioAlbum` 实例在数组中 }
Swfit 也允许将转型写在数组遍历层,在数组便利初始就将数据转型,如此更有效率:
1 2 3
for album in allAlbums as! [StudioAlbum] { print(album.studio) //相当于省去了 let studioAlbum = album as! StudioAlbum }