《Swift by Tutorials》学习笔记,第一章

原本已经决定把JavaScript系统学习一遍,却因为各种原因转投到了iOS门下,也导致了我将近两个月的时间没有写博客了。今天开始要把博客重新捡起来了,在现阶段博客的主要内容还是自己的一些学习笔记,因为刚开始学习,没有太多能分享的东西,等到之后如果小有所成,再来写一点类似教程类的博客。

现阶段如果要学iOS都是直接从Swift开始上手了,这门语言是苹果公司现在主推的语言,鉴于苹果公司一贯的激进作风,Swift应该会慢慢取代OC语言成为开发iOS应用的主打语言。Swift语言的语法还是比较简明的,如果有别的程序语言的基础,要上手是非常容易的。

起步

新版的Xcode提供了一个新工具,Playground,这个工具是用来学习Swift语法的利器。Playground的功能可以相当于Python中的解释器来使用,当你在左边输入一条语句,Playground会自动进行编译和运行,然后在右边的面板中输出语句的结果。

有了如此好用的工具,就可以愉快地开始学习Swift了。

变量、常量和字符串

新建一个Playground,然后将原来的内容删除,输入如下代码:

var greeting: String = "Hello"
println(greeting)

就可以立即在右边的面板中看到输出了Hello。这个面板用来快速查看结果很方便,但是如果想要查看完成的控制台输出,可以在菜单View/Assistant Editor/Show Assistant Editor中打开

上面的代码中定义了一个变量greeting,我们可以改变它的值:

var greeting: Stringn = "Hello"
greeting = "Bonjour"
println(greeting)

在Swift当中,还有更方便的方法来声明一个变量:

var greeting = "Hello" 

在上面的语句当中,没有指定变量greeting的类型,但是编译器会根据赋值的内容来自动推断出要声明的变量的类型,这称为 类型推断

看到这样的语句,很容易让人误以为Swift是弱类型的语言,事实上,Swift是实实在在的强类型语言。像下面的代码在编译期间会报 type 'String' does not conform to protocol 'IntegerLiteralConvertible' 的错误:

var greeting = "Hello"
greeting = 42
println(greeting)

可以直接使用+号对字符串进行拼接:

var greeting = "Hello"
greeting = greeting + " World"
println(greeting)

Swift当中的字符串默认是可变的,即我们可以改变字符串的值。

上面的代码中声明的都是变量,如果要声明常量,可以使用let关键字。如果将上面的代码改为

let greeting = "Hello"
...

则会导致编译错误,因为在常量初始化完成之后,就不能再改变它们的值了。

苹果官方建议应尽量使用常量,使用常量可以使代码健壮,同时使编译器对代码进行优化。所以在Swift当中,基本上的使用let会比使用var多。

Swift为字符串提供了少量的操作方法,好在Swift的字符串可以与NSString进行无缝地切换使用:

import Foundation

var greeting = "hello".stringByAppendingString(" world")
println(greeting)

并且Swift当中的字符串是值类型,也即在对字符串进行赋值的时候,传递的是值,而不是地址,这与许多语言都是不一样的。

...
var alternateGreeting = greeting
alternateGreeting += " and beyond!"
println(alternateGreeting)
println(greeting)

在上面的代码中,因为拷贝的是字符串的值,所以在对alternateGreeting进行修改的时候,不会影响到原本的greeting

分号

在Swift当中,只要当多条语句写在同一行的时候才需要使用分号来分隔,其它情况下都不需要加分号

数值类型与转换

现在来看看Swift当中的数值类型:

var radius = 4
let pi = 3.14159

上面的代码声明了一个Int型的变量raidus和一个Double型的常量pi。同样的,我们不需要指定类型,编译器会自己推断出所需要的类型。默认没有指定类型的情况下,编译器对整型和符点型都是使用IntDouble

虽然Swift情况有各种不同范围的整数类型,比如Int8(8 位有符号整型)和UInt16(16位无符号整型),同时还有Float类型的符点类型。但是官方建议在没有特殊要求的情况下尽量使用IntDouble

在定义整型数据的时候,还可以使用千位分隔符,用来增加可读性:

let million = 1_000_000

我们可以使用各种基本的运算符对变量进行操作,但是由于Swift是强类型语言,同时它不允许自动的隐式转换,所以在进行运算的时候可能会碰到坑:

var area = raidus * radius * pi

上面这句会在编译期报错。因为整数与符点数是不同的类型,所以我们不能直接进行运算,而需要这么做:

var area = Double(radius) * Double(radius) * pi

将整型转化成符点型然后再进行计算。要注意我们并不是进行了强制类型转换,而是使用了Double的构造函数重新构造了一个Double型的数,然后再进行运算的。

Swift也会对数值的范围进行检测,如果数值的运算超出了数值范围,编译器也会报错。这些都是Swift提供的安全特性。

布尔类型

布尔类型只有两个值,即truefalse。与OC不同,Swift不会将非零值视为true,也不会将零视为false,它只接受truefalse两个值。

元组

元组可以用将一些简单的值组成成一种类型。与结构体和类不同,在使用元组的时候,不需要声明一种新的类型,而可以直接使用。

// 声明一个元组,并获取它的值
var address = (742, "Evergreen Terrace")
println(address.0)
pritnln(address.1)

如果我们访问了超出范围的元组索引,也会在编译期造成错误。

可以使用索引来对元组的值进行修改:

// 修改元组的值
address.0 = 744

上面的元组声明中,我们使用了类型推断,我们也可以显式地指定类型,同时还可以对元组进行解包:

// 声明(Int, String)类型的元组
var address: (Int, String) = (742, "Evergreen Terrace")

// 对元组进行解包
let (house, street) = address
println(house)
println(street)

我们还可以对元组的元素进行命名,然后通过名称访问元素:

var address = (number: 742, street: "Evergreen Terrace")
println(address.number)
println(address.street)

字符串插值

有时,需要在字符串当中插入数值类型的值,这时可以使用字符串插值:

var address = (742, "Evergreen Terrace")
let (house, street) = address
let str = "I live at \(house), \(street)"
println(str)

控制流

For 循环

在Swift当中,支持普通的for循环,同时也支持增强型的for-in循环。

let greeting = "Swift by Tutorials"

for i in 1...5 {
    println("\(i) - \(greeting)")

上面的代码中,1...5是一个Range类型的值,三个点代表的是范围包括最后一个数,如果不想包含最后一个数,则可以使用1..<5

While 循环

Swift也同时支持whiledo-while循环。

var i = 0
while i < 5 {
    println("\(i) - \(greeting)")
    i++

If 语句

Swift支持ifif/elseif/else-if/else类型的控制语句。

let greeting = "Swift by Turtorials"

for i in 1...5 {
    if i == 5 {
        println(greeting.uppercaseString)
    } else {
        println(greeting)
    }

需要注意的是,在Swift当中,就算执行体只有一条语句,也必须加上花括号。

Swift 语句

Swift中的switch语句可谓强大。它不仅能够匹配数值类型,还能匹配其它的类型,但是要匹配的类型,与case中的类型必须要一致,不然会造成错误。

var direction = "up"

switch direction {
case "down":
    println("Going down!")
case "up":
    println("Going up!")
default:
    println("Going Nowhere")

这段代码将会输出Going up,可以看出在Swift当中,每个case后面是不需要显式加上break的。同时,case中的情况,必须要穷举完要判断的类型的所有情况,否则编译器将会报错。

除了上面这种标准的用法,Swift当中的switch还有很多其它的灵活的用法。如:

switch direction {
case "down", "up":
    println("Going Somewhere!")
default:
    println("Going Nowhere")
}

只要directiondown或者up其中之一,则第一个case就能匹配成功。

还能使用范围值来进行匹配:

var score = 570

switch score {
case 1..<10:
    println("novice")
case 10..<100:
    println("proficient")
case 100..<100:
    println("rock-star")
default:
    println("awesome")
}

switch还有很多其它强大的功能,在后面的章节会讨论。

总结

这章主要讨论了swift中的一些基础数值类型与控制流,除了一些特殊的地方,其它语法都与主流的语言大同小异的。只要有其它语言的背景,上手swift的速度是很快的。