Swift是一门新的iOS系统的开发语言,其更轻量级,类似脚本语言,支持ARC以及Playground。Playground文件可以在修改代码时,立即看到结果。
Swift相比于OC有很多优势,例如,type-safe, 会做类型检查,避免类型转换异常;引入Optional类型,不用每次都用if语句判断一个值是否为nil;引入Tuples,可以在函数中一次返回多个不同类型的值。
下面是Swift的语法介绍。
Format
无需导入输入输出或者字符串库:
1 | print("Hello, world!") |
如果想不自动换行:
1 | print("nimei", terminator:"") |
Comments
1 | // This is a comment. |
注意,”/*”可以嵌套。
Semicolons
一般不需要加”;”号,除非多行写成一行:
1 | let cat = "🐱"; print(cat) |
Simple Values
用let定义常量,而var定义变量。不用定义类型:
1 | var myVariable = 42 |
如果需要显式定义,可以这样写:
1 | let explicitDouble: Double = 70 |
没有隐式的类型转换,如果需要类型转换,需要显示定义:
1 | let widthLabel = "The width is " + String(94) |
如果是在字符串中,可以用“\“+”()”来转换:
1 | let apples = 3 |
用”[]”来创建Array和Dictionary:
1 | var shoppingList = ["catfish", "water", "tulips", "blue paint"] |
定义一个空的需要用初始化函数:
1 | let emptyArray = [String]() |
如果是已经知道类型的变量,可以直接这样写:
1 | shoppingList = [] |
用”?”定义Optional类型,Optional类型可以有值,也可以为nil。用”??”可以给Optional类型赋值一个默认值:
1 | let nickName: String? = nil |
Control Flow
if语句:必须是跟着Boolean类型,不能是数字,不会隐式跟0比较:
1 | var score = 51 |
if-let语句:必须是跟着Optional类型,如果Optional类型有值,则直接赋值,进入if语句,如果没有,则进入else语句:
1 | var optionalString: String? = "Hello" |
switch:支持任意格式的数据和表达式,不止整形和等式.同时,可以用let进行局部赋值。
1 | let vegetable = "red pepper" |
for-in:
1 | let individualScores = [75, 43, 103, 87, 12] |
while:
1 | var n = 2 |
for:可以用”..<”来局部遍历索引。
1 | var total = 0 |
Functions and Closures
func:
用“->”来定义返回值:
1 | func greet(person: String, day: String) -> String { |
参数前可以设置别名,或者用“_”表示别名为空:
1 | func greet(_ person: String, on day: String) -> String { |
参数可以定义成不定数的:
1 | func sumOf(numbers: Int...) -> Int { |
返回值可以用名称或者数字做索引:
1 | func calculateStatistics(scores: [Int]) -> (min: Int, max: Int, sum: Int) { |
Func可以嵌套:
1 | func returnFifteen() -> Int { |
Func可以作为参数和返回值:
1 | func hasAnyMatches(list: [Int], condition: (Int) -> Bool) -> Bool { |
Closure
Closure用“{}”包含,并用in分割参数返回值和具体实现:
1 | { |
如果Closure的类型已经确定,可以更精简地写:
1 | let mappedNumbers = numbers.map({ number in 3 * number }) |
除了用名字,也可以用数字索引来表示参数:
1 | let sortedNumbers = numbers.sorted { $0 > $1 } |
Objects and Classes
Classes:
定义:
1 | class NamedShape { |
注意,Class的每个属性值都需要赋值,可以在定义时,也可以在构造函数中。
继承和重写:
1 | class Square: NamedShape { |
Get/Set:(可以用newValue指代参数值)
1 | var perimeter: Double { |
WillSet/DidSet:(在Set执行前后会被调用)
1 | var square: Square { |
Objects:
对于是Optional类型的对象,可以用“?”来进行判断,如果值为nil,则结果直接为nil,否则为具体值。但是赋值式左边的类型是Optional类型。
1 | let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square") |
Enumerations and Structures
Enumerations:
Enum的Raw Values的类型,可以是Int, Float以及String。Int类型的默认从0开始,也可以强制设置为其他。
1 | enum Rank: Int { |
Raw Values类型也可以不设置:
1 | enum Suit { |
可以直接用init?(rawValue:)来创造一个实例:
1 | if let convertedRank = Rank(rawValue: 3) { |
还可以添加参数:
1 | enum ServerResponse { |
Structs
Structs跟Classes的区别在于:Structs都是值传递,Classes都是引用传递。
1 | struct Card { |
Protocols and Extensions
Protocols
1 | protocol ExampleProtocol { |
Classed,Enumerations, Structs都可以适配Protocols:
1 | class SimpleClass: ExampleProtocol { |
注意:mutating关键字在Structs中使用,用于标识会修改Structs元素,而Classes不用,Classes的方法本来就可以修改Classes。
Protocols可以当类型使用:
1 | let protocolValue: ExampleProtocol = a |
Extensions
Extensions用于给一个已有的类型添加功能,可以结合Extensions和Protocol一起使用:
1 | extension Int: ExampleProtocol { |
Error Handling
Error定义:
1 | enum PrinterError: Error { |
用throw来抛出异常,throws关键字来标识Func:
1 | func send(job: Int, toPrinter printerName: String) throws -> String { |
用do-catch来捕获异常,在do中用try来标识可能抛出异常的地方:
1 | do { |
多catch:
1 | do { |
用try?来转换结果为Optional,如果有异常,则结果为nil,否则则为实际值:
1 | let printerSuccess = try? send(job: 1884, toPrinter: "Mergenthaler") |
用defer来定义在Func中其他代码都执行结束后,执行的代码(类似finally):
1 | var fridgeIsOpen = false |
Generics
用“
1 | func makeArray<Item>(repeating item: Item, numberOfTimes: Int) -> [Item] { |
Classed,Enumerations, Structs都定义Generics类型:
1 | enum OptionalValue<Wrapped> { |
用where关键字在Func后,来列出要求,例如,要求类型必须适配Protocol,要求两种类型必须相同,要求一个Class必须有一个指定的父类:
1 | func anyCommonElements<T: Sequence, U: Sequence>(_ lhs: T, _ rhs: U) -> Bool |