专注收集记录技术开发学习笔记、技术难点、解决方案
网站信息搜索 >> 请输入关键词:
您当前的位置: 首页 > Swift

Swift 入门参照

发布时间:2011-06-30 07:23:31 文章来源:www.iduyao.cn 采编人员:星星草
Swift 入门参考

Swift 是苹果推出的一门新语言,它的语法仍然是在 C 语言基础上的延伸,溶入了面向对象语言和脚本语言的特征,还有一点 Objective-C 的影子。 

 

基本类型

 

Swift 是强数据类型的,也是类型安全的,常量和变量都有着明确的类型。大多数情况下,编译器可根据赋值推导出类型,从而帮助省略代码书写,使得代码比较简洁。Swift 中的类型包括基本类型(Int, Double等),还包括类、结构和枚举。类型在 Swift 中称作 Type。

 

定义常量与变量使用 let 和 var 关键字。let 用于定义常量,var 则定义变量,形式为:

var v : Type = ..  // 定义一个变量

let c : Type = ..  // 定义一个常量

以字典为例,Swift 使用 let 和 var 来定义可修改字典和不可修改字典,这与 Objective-C 中以 NSDictionary 和 NSMutableDictionary 分开实现是不同的。

 

Swift 的基本类型包括 Int, Float, Double, Bool, String 等。

整型类型其实包含了 Int8, Int16, Int32, Int64 四种类型,在没有明确位宽要求的情况下,使用 Int 即可,编译器会根据机器位宽自动选择。对于整型数值的类型推导,Swift 优先选择 Int 型。

浮点类型包括了32位的 Float 和64位的 Double 两种类型,同样,在没有明确位宽要求的情况下,推荐使用 Double。对于浮点数值的类型推导,Swift 优先选择 Double 型。如果表达式中有整型和浮点型,则推导类型为 Double型。

布尔型 Bool,只能取 true 和 false,Swift 的类型安全不允许像 C 语言那样将整型转为布尔型。

字符串类型 String 是一组 Character 的有序集合,包括了若干 Unicode 字符。

 

运算符

 

Swift 的运算符完全涵盖了 C 的运算符,包括:基本运算,一元运算,复合运算,男较运算,关系运算,移位运算符,位域运算等等。

 

Swift 在运算符上还做了一些扩展。最大的变化是增加了范围运算符 ..< 和 ...

..< 是半开区间范围,表示 [start, end),如 1 ..< 3 表示 1, 2。

... 是闭区间范围,表示 [start, end],如 1 ... 3 表示 1, 2, 3。

范围运算常用于循环语句和 switch 语句。

 

Swift 扩展了求模运算符 %,可以对浮点做模运算,如 8 % 2.5 = 0.5。

赋值运算符的语义发生了变化,不再像 C 语言那样返回数值,也即 (a = b) != c 这样的语法不再支持。

 

Optional

 

Optional 类型由 Type? 定义,它的引入是为了处理有值/无值问题。一个 Optional 变量要么无值(缺失某类型的值),要么有某种值。无值即 unset,或称为 nil。

Swift 的 Optional 类型可以支持任意类型,包括类、结构和枚举类型。Objective-C 的 nil 只能用于 class 这种引用类型,表达的是空指针的含义,含义上与 Swift 也有不同。

可以给 Optional 变量赋 nil,但不能给非 Optional 变量赋 nil。定义Optional 变量但不设初值的,默认被设为nil。

 

判断一个 Optional 变量是否有值,可以用 if 等条件判断语句,如确定有值,则可在变量后加!来提取类型值,这称作强制取值(forced unwrapping),例如:

if someOptional != nil {

  println(“\(someOptional!)”)

}

如果对一个无值的 Optional 变量取值,程序将崩溃。

 

上述语句还可以可以写作:

if let arg = someOptional {

  println(“\(arg)”)

}

这种用法称作 Optional binding。若语句内需要修改 arg,也可以使用 var 关键字。

 

如果已知某个 Optional 变量有值,可以不必执行检查而直接取值,这类变量在定义时,类型后面添加!标识,使用时表现为普通变量而非 Optional 变量。

let possibleValue : String? = “have value”

let assumedValue : String! = “implicitly unwrapped optional”

在使用 assumedValue 时,无需再加!取值,这种方式称作隐式取值。对于这类变量,仍然可以用 if 等条件判断其是否有值。

可以理解为,隐式 Optional 其实仍是 Optional 类型,只是引用时自动加上了取值操作。

 

Swift 提供了 nil 合并运算符,形式为:( a ?? b )

若 Optional 变量 a 有值,则取 a 的值,否则返回非Optional变量 b 作为默认值。

 

数组、字典与集合

 

数组、字典和集合是 Swift 提供的集合类型。

 

数组是一组相同元素类型的有序值集合,类型以 Array 表示。数组的定义使用Array<Type>或者使用更简单的[Type]语法定义,比如创建空数组:Array<Int>() 或者 [Int]()。

let a : Array<Int> = [1, 2, 3]

由于 Swift 可以进行类型推导,因此上面的语句也可以写为:

let a = [1, 2, 3]

 

数组提供了一些属性,如获取数组元素数量的 count 属性,判断数组是否为空的 isEmpty 属性。

 

数组元素的引用使用下标语法,下标从0开始,支持范围运算符,如a[0] 或者 a[0...1]。下标语法可用作元素赋值,但不可用于添加或插入新元素。

添加元素使用 append 方法。还可通过 += 添加另一个数组,这涉及到了运算符重载的概念(操作符两端须为同一类型,也即需数组类型,而非元素类型)。

其它常用方法还有 insert, removeAtIndex, reverse 等。

 

遍历数组可使用 for-in 语法,或者通过 enumerate 全局函数获取带下标及值的元组:

for (index, value) in enumerate(array) {

  ...

}

 

字典类型以 Dictionary 表示,字典的定义与使用与数组类似:

定义字典:Dictionary<Key, Value>或[Key:Value]

使用下标语法访问。

由于字典里某个键值不一定有对应的值,因此总是返回 Optional 类型。

 

集合类型以 Set 表示,一组相同元素类型的无序值集合,与数组类似。

集合并没有简写语法,定义集合:

var s : Set<Type> = [value1, value2, value3]

 

元组

 

元组是由多个值组成的复合值,其成员可以是不同类型。元组的引入,使一小组相关数据的传递变得十分方便。元组非常适合函数需要返回多个值的情况,而这在其它语言里需要构造新的对象来实现。

 

元组的定义语法为 ( Type1, Type2, Type3 ),如

let aTuple = (1, “Yes”)

默认情况下,元组成员的访问以从0开始的下标方式,如 aTuple.0 取出 1,aTuple.1 取出 ”Yes”。可以为元组定义成员描述,如:

let aTuple = (aNumber:1, aString:”Yes”)

此时可由 aTuple.aNumber, aTuple.aString 访问指定成员。

 

控制流

 

Swift 中的代码控制与 C 基本上相同,有部分书写和语义的变化。

 

if, for, while, do-while, switch 等条件判断语句,条件判断部分不再需要括号。如:

if x == y {

}

花括号是不可省略的,即使只有一条语句,这与 C 不同。

 

for-in 语法,用于遍历容器:

for index in 1 ..< 10 {} // 使用了范围运算符

for var i = 0; i < 3; i++ {} // 这个语法仍然支持

 

Swift 对 switch 语句作了较大改动,case 的条件判断更加强大。

case 条件支持字符串的直接比较,支持范围运算符,支持多个值的匹配,例如:

 

let x = 10

switch x {

  case 1:

    ...

  case 2, 3:  // 匹配多值,以逗号分隔

    ...

  case 10 ... 20: // 范围匹配 

    ...

  default:

    ...

}

 

要注意的是,case 必须涵盖 switch 条件的所有可能性,当不可能涵盖全部范围时,必须提供 default 分支。同时,Swift 不再支持 C 语言的 fall through 行为,当 case 体执行完成后,直接跳出,而无需显式书写 break 语句。若确实需要 fall through 行为,使用 fallthrough 关键字:

 

switch x {

  case 1:

    fallthrough

  default:

}

 

由于 Swift 引入了元组,所以 switch 也支持元组匹配,并且可以使用值绑定(Value Binding)的语法获取元组成员值进行比较,更可使用 where 语句扩展条件判断:

 

let point = (1, 1)

switch point {

  case (0, 0):  // 比较元组

    ...

  case (_, 0):   // 第一个成员可以是任意值

    ...

  case (let x, 1): // 值绑定语法,case 体内可使用 x 的值。

    ...

  case let (x, y) where x == y: // where 语句

    ...

  default:

    ...

}

 

let (x, y) 是 (let x, let y) 的简写法,若对元组所有成员做值绑定时,可将 let 提到外面。同样的,在需要的情况下,也可以使用 var。

 

其它的控制语句还有 continue, break, return 等,这些与 C 的语义相同。

 

枚举

 

Swift 对枚举进行了较大改动,功能也变得更加强大了。

定义一个枚举类型的语法为:

enum SomeEnumeration {

    case North
    case South
    case East
    case West
}

case 定义的是枚举的成员值(也即成员),一条 case 可以定义多个成员,以逗号分隔。与 C 不同的是,枚举成员并没有默认的整数值。

每个枚举成员可以有一个关联值,并且不同成员可以用不同的类型,如:

enum Barcode {
    case UPCA(Int, Int, Int, Int)
    case QRCode(String)
}

关联值在定义枚举变量时提供,比如:

var code = Barcode.UPCA(8, 8059, 51226, 3)
switch code {
    case .UPCA(let a, let b, let c, let d): // 可简写为case let .UPCA(a, b, c, d)
        println(...)
    case .QRCode(let a):
        ...
}

枚举成员也可以有默认值,这在 Swift 里称为原始值(raw values),原始值必须是同一种类型,如:

enum ASCIIControlCharacter : Character {
    case Tab = "\t"
    case LineFeed = "\n"
    case CarriageReturn = "\r"
}

使用整数作为raw values时,其行为与 C 相似,数值会递增。raw values 并不是关联值,两者并不相同。Swift 提供了从根据原始值获取枚举成员的方法:

let possiblePlanet = Planet(rawValue:7)

因为 rawValue 有可能无对应的成员,因此只能返回 Optional 类型。

 

Optional 实质上也一种枚举类型,也即:

enum Optional<T> {
    case None
    case Some<T>
}

取值操作等价于下面代码:

var y = x! 等价于
switch x {
    case Some(let value): y = value
    case None: // raise exception
}

 

函数与闭包

 

Swift 的函数语法不再像 Objective-C 那样独特了,更像是类 C 的写法,一个函数的一般定义形式如下:

func funcname(externalName internalName:Type) -> ReturnType {
    ...
}

func 关键字用于定义一个函数,-> 语法用于指定返回类型。比较怪异的是参数部分,不过如果有 Objective-C 的基础,也很容易理解。

一个参数有内部参数名和外部参数名(可省略)两种,内部参数名是函数体内使用的参数名,如果不填写外部参数名,那定义出的函数和其它语言没什么不同,假如定义了这样一个函数:

func aFunction(s1: String) -> String

其调用语法即:

let aString = aFunc(“a string”)

Objective-C 的命名方式使得参数更容易阅读,Swift 函数外部参数名的使用也是为了沿用这一优点。

假如定义函数形式为:

func aFunction(sourceString src : String, withPostString post : String) -> String

在定义了外部参数名的情况下,函数调用者必须书写外部参数名:

aFunction(sourceString: “a string”, withPostString: “post”)

是不是很像 Objective-C 的写法。如果不需要外部参数名(比如,第一个参数的描述常常不需要外部参数名),那么可以用下划线来表示忽略。当内部名与外部名相同时,可用#name同时生成内外部参数名。

有默认值的入参会自动生成外部入参名,默认值入参必须在入参列表的最后。变参以...表示,一个函数只能有一个,且作为最后一个入参,如存在默认值入参,需置于其后。变参实际上是数组,函数内可用for-in遍历。

函数入参默认是常量,函数内不可修改。参数名前添加 var 可使入参为变量。但是,函数体内的改动只在函数体内有效,若要在函数返回后,修改仍生效,需要使用 inout 关键字声明入参。inout 入参需以 &param 的语法传入。

函数也是一种类型,函数类型由入参和返回值构成,类似其它语言原型的概念。例如 (Int, Int) -> Int。但一般语言不将返回值作为函数定义的一部分。

可以定义函数类型的变量,也可用作其它函数的入参类型,返回值类型。函数类型函数还可以嵌套定义。运算符也是函数。

闭包与 Objective-C 里的 block 对应,与其它语言的 lambda 类似,在本质上就是函数。Swift 对闭包做了一些优化:

  • 从上下文推导参数和返回值类型
  • 单个表达式闭包可隐式返回
  • 简写入参名称
  • Trailing closure语法。如果函数最后一个入参是闭包,可将其写在函数定义外,以方便阅读。

与嵌套函数相比,闭包有时更加有用。

无返回值的函数其实也是有返回值的,只是返回一个空的元组,即()。当无返回值函数用作闭包时,若不写返回值部分,其写法与元组是一样的,要显式地写作 func funcName(parameters) -> ()

闭包表达式是指内联的简单闭包,其一般形式为:

{ (parameters) -> return type in
statements
}

比如调用 sorted 函数:
sorted(array, closure)

以闭包表达式形式写作:

sorted(array, { (s1:String, s2:String) -> Bool in return s1 > s2 })

闭包表达式可使用常量入参,变量入参,inout 入参,变参,元组,不使用默认值入参。大多数情况下,闭包表达式的入参和返回值是可以推导的,可以省略类型,不需要写完整形式。闭包只有一句表达式时,可以省略 return。闭包有默认入参,从$0, $1依次类推。简写参数名:$0, $1, ... 可在闭包里使用。

因为运算符也是函数,因此 sorted 所接受的闭包,可以是一个运算符。

当闭包表达式是函数最后一个入参时,可使用称作 trailing closure 的尾部闭包写法,这个写法只是为了方便阅读,例如:

reversed = sorted(array) { $0 > $1 }

如果仅有闭包表达式一个入参,也可省略函数名后的()。

闭包内保持对变量的引用(闭包定义时的上下文),这称为值捕获(Capturing values)。

 

- 待续 - 

友情提示:
信息收集于互联网,如果您发现错误或造成侵权,请及时通知本站更正或删除,具体联系方式见页面底部联系我们,谢谢。

其他相似内容:

热门推荐: