1.let关键字
用let修饰的变量会是一个不可变的常量, 也就是说不可以对它进行修改, 但如果用let修饰的常量是一个类, 那么我们可以对其所在的属性进行修改, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13
| class PersonInfo { let name = "xiaoming" var age = 18 var height = 170 var weight = 65 } let personInfo = PersonInfo() personInfo.age += 1 print("person age is \(personInfo.age).")
|
这里边的name就是不可变的, 如果非要去改变, Xcode会建议你把let修改成var.
PS: 如果这个时候, 再声明一个person常量去引用personInfo, 那么person的所指向的内存块是和personInfo相同的.
2.var关键字
用var关键字声明的变量将会是一个可变的变量, 在这里, 我们并不会用var去引用一个类, 也没有必要, 继续拿上面的例子来说:
1 2 3 4 5 6 7 8 9 10 11 12
| class PersonInfo { let name = "xiaoming" var age = 18 var height = 170 var weight = 65 } let personInfo = PersonInfo() personInfo.age += 1 print("person age is \(personInfo.age).")
|
这里面的age就是属于var类型, 在初始化之后, 我们仍然可以给它进行修改.
PS: 如果这个时候, 我们用var修饰personMode变量去引用personInfo, 那么personMode和personInfo所指向的内存块并不同, personMode会将personInfo完整的拷贝一份, 然后放在另外一块内存块去管理.
3.class关键字
在Swift当中, 我们是使用Class关键字去声明一个类, 比如:
1 2 3
| class PersonInfo { // class body }
|
4.struct关键字
在Swift中, 如果我们需要声明一个结构体, 我们就需要使用到struct关键字, 比如:
1 2 3
| struct PersonInfo { // struct body }
|
5.enum关键字
而我们需要声明枚举的时候, 我们就使用enum关键字, 比如:
1 2 3 4 5 6
| enum PersonMode { case zhangsan case lisi case wangwu(String) case luoliu(String, Double, Int) }
|
在Swift当中的enum和Objective-C并不一样, Swift的enum不会被隐式赋值为0, 1, 里面的zhangsan就是这个枚举分支的完整值, 并且在Swift中, 我们可以给enum case声明各种类型, 比如里面的case luoliu一样.
当然, 我们也可以给枚举值默认声明一个值, 但在枚举名之前, 要声明是什么类型, 比如:
1 2 3 4 5 6 7
| enum Numbers: Int { case One = 1, Two, Three, Four } let number = Numbers.One.rawValue print(number)
|
6.override关键字
在Swift中, 如果我们要重写某个方法, 或者某个属性的话, 我们需要在重写的变量前增加一个override关键字, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class Car { var speed: Int { return 200 } func carSpeed() { print("Car max speed is \(speed)km 1 hours.") } } class NewCar: Car { override var speed: Int { return 150 } override func carSpeed() { print("Car max speed is \(speed)km 1 hours.") } }
|
7.final关键字
上面我们介绍了override重写属性或者方法的关键字, 当然有重写, 肯定会有防止重写的关键字, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| class Car { var speed: Int { return 200 } final var carType: String { return "SUV" } func carSpeed() { print("Car max speed is \(speed)km 1 hours.") } } class NewCar: Car { override var speed: Int { return 150 } override func carSpeed() { print("Car max speed is \(speed)km 1 hours.") } override var carType: String { return "MPV" } }
|
8.subscript关键字
所谓的下标, 其实就可以快捷方式的设置或者获取对应的属性, 而不需要调用对应的方法去获取或者存储, 比如:
1 2 3 4 5 6 7 8 9 10 11 12
| struct Animal { let catType: String subscript(animalName: String) -> String { return "catType is \(animalName)." } } let tiger = Animal(catType: "Tiger") print(tiger)
|
9.mutating关键字
作用:写在func前面,以便于让func可以修改struct和protocol的extension中的成员的值。 如果func前面不加mutating,struct和protocol的extension中的成员的值便被保护起来,不能修改.
mutating这个关键字指的是可变, 只能用在struct和enum当中,为的就是可以方便我们在特定环境下, 需要在struct中修改对应的属性值, 比如:
1 2 3 4 5 6 7 8 9 10 11 12
| struct Animal { let catType: String subscript(animalName: String) -> String { return "catType is \(animalName)." } } let tiger = Animal(catType: "Tiger") print(tiger)
|
10.static
用static修饰的变量或者方法, 就会变成静态变量和静态方法, 并且保证在对应的作用域当中只有一份, 同时也不需要依赖实例化, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Animals { static var catName: String! func catTypeName() { _ = "Tiger" } } Animals.catName = "Tiger" print(Animals.catName)
|
static关键字和class关键字的区别
在方法的func关键字之前加上关键字static或者class都可以用于指定类方法.
不同的是用class关键字指定的类方法可以被子类重写, 如下:
override class func work() {
print(“Teacher: University Teacher”)
}
但是用static关键字指定的类方法是不能被子类重写的, 根据报错信息: Class method overrides a ‘final’ class method.
我们可以知道被static指定的类方法包含final关键字的特性–防止被重写.
11.lazy关键字
就是swift中的懒加载
被lazy关键修饰的变量, 只有在第一次被调用的时候才会去计算它初始化值的属性, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| class SuvCar { var BydSuv = "S7" } class MpvCar { lazy var suvCar = SuvCar() var mpvCars = [String]() } let mpvCar = MpvCar() mpvCar.mpvCars.append("CarOne") mpvCar.mpvCars.append("CarTwo") print("I have \(mpvCar.mpvCars.count) MPV.") print("I have a SUV Car, is \(mpvCar.suvCar.BydSuv)")
|
在这里需要注意两点:
1.用lazy修饰的变量必须是用var声明的, 因为属性的初始值可能在实例构造完成之后才会得到。而常量属性在构造过程完成之前必须要有初始值,因此无法声明成延迟属性。
2.如果被lazy修饰的变量没有在初始化时就被多个线程调用, 那就没有办法保证它只被初始化一次了.
12.init关键字
在Swift 中也有对应的构造器, 来看看:
1 2 3 4 5 6 7
| class Player { var coinsInPurse: Int init(coins: Int) { coinsInPurse = 1000 } }
|
这样子coinsInPurse的值就为1000了.
还有一种用法, 就是在init后面加个”?”号, 表明该构造器可以允许失败
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| struct Animal { let species: String init?(species: String) { if species.isEmpty { return nil } self.species = species } } let someCreature = Animal(species: "Giraffe") if let giraffe = someCreature { print("An animal was initialized with a species of \(giraffe.species)") } let anonymousCreature = Animal(species: "") if anonymousCreature == nil { print("The anonymous creature could not be initialized") }
|
13.convenient关键字
该关键字是用来修饰init的, 经过convenient修饰的init方法, 表明该init方式是比较次要, 辅助型的, 比如:
1 2 3 4 5 6 7 8 9
| class Food { var name: String init(name: String) { self.name = name } convenience init() { self.init(name: "[Unnamed]") } }
|
14.required关键字
required也是用来修饰init方法的, 用required修饰说明该构造方法是必须实现的, 比如:
1 2 3 4 5
| class SomeClass { required init() { } }
|
PS: 如果一个子类继承了父类required修饰的init方法, 就必须得去实现该init方法, 但子类可以觉得它之后继承于它的子类可以实现该方法.
15.deinit关键字
在Swift中, 有一个类似dealloc方法, 就是deinit, 但有一些区别, dealloc方法是在引用计数为0的时候, 也就是被释放的时候才会调用, 而deinit是在实例不再引用时自动调用, 并且不用手动去管理引用计数, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
| class Bank { static var coinsInBank = 10_000 static func vendCoins(var numberOfConisToVend: Int) -> Int { numberOfConisToVend = min(numberOfConisToVend, coinsInBank) coinsInBank -= numberOfConisToVend return numberOfConisToVend } static func receiveCoins(coins: Int) { coinsInBank += coins } } class Player { var coinsInPurse: Int init(coins: Int) { coinsInPurse = Bank.vendCoins(coins) } func winCoins(coins: Int) { coinsInPurse += Bank.vendCoins(coins) } deinit { Bank.receiveCoins(coinsInPurse) print("Player is nil.") } } var playerOne: Player? = Player(coins: 100) print("A new player has joined the game with \(playerOne!.coinsInPurse) coins.") print("There are now \(Bank.coinsInBank) coins left in the bank.") playerOne?.winCoins(2_000) print("PlayerOne wn 2000 coins & now has \(playerOne!.coinsInPurse) coins.") print("The bank now only has \(Bank.coinsInBank) coins left.") playerOne = nil
|
16.is关键字
在Swift中, is关键字是用来判断类型所使用的, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| let number = ["xiaoming", 18] for item in number { if item is Int { print("item is Int type.") } else if item is String { print("item is String type") } } // 输出的结果为: // item is String type. // item is Int type.
|
我们可以遍历一个[NSObject]类型的数组, 判断里面各元素的类型
17.throw,do-catch关键字
在Swift 2.0之前, Swift是没有自带的错误信息处理方法, 在2.0更新之后就有了错误信息的处理方法, 让我们来看看.
在这里我们会使用到一个新的语句do-catch, 这个语句和Switch-case有些类似, 但唯独有一点不太一样的就是, 在do-catch语句中需要使用到try关键字, 而Switch-case则不需要, 好了, 下面让我们来看看.
首先我们需要定义一个ErrorType的枚举
1 2 3 4 5
| enum getError: ErrorType { case ErrorOne case ErrorTwo case ErrorThree }
|
然后我们来写一个方法, 用来获取错误类型
1 2 3 4
| func doDangerousStuff() throws { throw getError.ErrorOne }
|
最后我们使用do-catch语句来获取对应的错误类型
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| do { try doDangerousStuff() } catch getError.ErrorOne { print(getError.ErrorOne) } catch getError.ErrorTwo { print(getError.ErrorTwo) } catch getError.ErrorThree { print(getError.ErrorThree) } //输出结果为: ErrorOne
|
18.extension关键字
extension的作用是在不改变原来的类型或者协议基础下增加新的属性或者方法, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| class Person { var name = "xiaoming" } extension Person { var age: Int { return 20 } } let person = Person() print("person name is \(person.name), age is \(person.age).")
|
19.protocol关键字
protocol关键字在Swift中也是属于协议的意思, 所谓的协议就是约束对象, 比如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| protocol Person { var name: String { get } var age: String { get } } class Xiaoming: Person { var name: String { return "xiaoming" } var age: String { return "20" } } class Laozhang: Person { var name: String var age: String init(name: String, age: String) { self.name = name self.age = age } }
|
20.public关键字
public: 指的是可以访问在一个模块内的任何实体, 也可以通过导入该模块来访问, 也就是我们经常在Objective-C中经常需要导入的.h文件中的方法, 该关键字可以用来修饰变量, 方法, 类, 枚举, 结构体等等之类, 比如:
1 2 3 4 5 6 7 8 9 10 11
| public struct Person { } public enum CompassPoint { } public class SomePublecClass {} public var somePublecVariable = 0
|
21.internal关键字
internal: 指的是可以访问同一模块源文件中得任何实体, 但不能从模块的外部去访问该源文件中得实体, 同样, internal也可以修饰变量, 方法, 类, 枚举, 结构体等等之类等, 比如:
1 2 3 4 5 6 7 8 9 10 11
| internal struct Person { } internal enum CompassPoint { } internal class SomePublecClass {} internal var somePublecVariable = 0
|
22.private关键字
private: 指的是限制实体时能在源文件内部使用, 外部不能访问, private也同样可以用来修饰变量, 方法, 类, 枚举, 结构体等等之类, 比如:
1 2 3 4 5 6 7 8 9 10 11
| private struct Person { } private enum CompassPoint { } private class SomePublecClass {} private var somePublecVariable = 0
|