Swift学习笔记 ①

2,115 阅读14分钟

大家好,我是Mars。更新了Xcode 11 正式版后,对 Swift UI 做了一些简单的尝试,功能很强大,需要更深入的研究。之前在工作中业余时间自学了Swift,尝试重构了我司线上项目。后来因为项目赶进度,对Swift的研究也就搁浅下来。Swift 5 发布以后, ABI更加稳定,苹果今年又推出了 Swift UI ,所以是时候好好研究一下 Swift 这门语言了。后续会通过一系列的文章来分享和总结学习 Swift 的整个过程,希望大家多多支持和关注。 #语法篇

一、基础语法

分号

Swift不要求在每行语句的结尾使用分号; ,当在同一行书写多条语句时,必须用分号隔开:

var str = "Hello, swift"
print(str)
let name = "Mars"; let age = 18;

标识符

标识符就是给变量、常量、方法、函数、枚举、结构体、类、协议等指定的名字。构成标识符的字母均有一定的规范,Swift语言中标识符的命名规则如下:

  • 区分大小写,Mynamemyname是两个不同的标识符;
  • 标识符首字符可以以下划线 _ 或者字母开始,但不能是数字;
  • 标识符中其他字符可以是下划线 _ 、字母或数字。

Swift中的字母采用的是 Unicode 编码。Unicode 叫做统一编码制,它包含了亚洲文字编码,如中文、日文、韩文等字符,甚至是我们在聊天工具中使用的表情符号

let 🐂 = 20
var 🐓 = "Chicken"

如果一定要使用关键字作为标识符,可以在关键字前后添加重音符号(`),例如:

let `class` = "asda"

Swift 空格

Swift语言并不像C/C++,Java那样完全忽视空格,Swift对空格的使用有一定的要求,但又不像Python对缩进的要求那么严格。 在Swift中,运算符不能直接跟在变量或常量的后面。例如下面的代码会报错:

let a= 1 + 2
let b = 1+ 2

只有这样写才不会报错:

let a = 1 + 2;  // 编码规范推荐使用这种写法
let b = 3+4 // 这样也可以

打印输出

Swift 使用自带的 print 函数打印输出:

print("Mars") // 输出 Mars

print 函数是一个全局函数,完整的函数签名为:

/// - Parameters:
///   - items:  需要打印的参数
///   - separator: 分隔符,默认使用空格来做分隔符(`" "`).
///   - terminator:  换行 (`"\n"`).
public func print(_ items: Any..., separator: String = " ", terminator: String = "\n")

print 函数需要传入三个参数,参数具体含义已经在代码中注释。其中items参数是Any类型,可以传入任何类型。...代表可变参数,可以传入多个参数。例如:

print("1","2","3","4") //输出1 2 3 4

最后面两个是有默认值的,separator是分隔符,默认是用空格做分隔符,terminator默认是换行\n。当然,传入其他参数来修改默认值,例如:

// 取消分隔符和换行
print("123", separator:"", terminator:"")
print(20)   // 打印结果为 12320
// 替换分隔符
print("1","2","3", separator:"+", terminator:"") //打印结果为 1+2+3

print 函数打印外部变量使用\()

let age = 18
print("age is \(age)") //打印结果为 age is 18

二、常量

swift中,常量一旦设定,在程序运行时就无法改变其值。所以常量只能赋值1次。 常量可以是任何的数据类型如:整型常量,浮点型常量,字符常量或字符串常量。同样也有枚举类型的常量。 ####常量的声明 swift中定义常量用let关键字。

let constA = 42

类型标注

当声明常量或者变量的时候可以加上类型标注(type annotation),用来说明常量或者变量中要存储的值的类型。如果要添加类型标注,需要在常量或者变量名后面加上一个冒号和空格,然后加上类型名称

let constB: Int = 32
let constC: Float = 3.1415
let constD: Int
constD = 21

上面例子中,常量constD在声明时指定了数据类型为Int,所以紧接着将常量constD赋值为 21,这个操作是允许的。但是如果常量在声明时即没有赋值又没有指定类型,就会报错。例如下面的代码就是错误的:

//错误代码示例
let age
age = 10

需要注意的是,常量和变量在初始化之前都不能使用。 其中,常量的值不要求在编译时期确定,但是在使用之前必须赋值1次。例如下面的常量age

func getAge() -> Int {
    return 20
    
}
let age = getAge()
print(age)

常量命名

常量的命名可以由字母,数字和下划线组成。常量需要以字母或下划线开始。 Swift 是一个区分大小写的语言,所以字母大写与小写是不一样的。

三、变量

变量声明

swift中使用 var 关键字声明变量,如下所示:

var varA = 42
print(varA) // 打印输出42

var varB:Float
varB = 3.14159
print("pi is \(varB)")// 打印输出pi is 3.14159

变量命名

变量名可以由字母,数字和下划线组成。 变量名需要以字母或下划线开始。 Swift 是一个区分大小写的语言,所以字母大写与小写是不一样的。 变量名也可以使用简单的 Unicode 字符,如下实例:

四、数据类型

Swift 提供了非常丰富的数据类型,下面用一张表格来简单展示一下Swift 的常见数据类型:

常见数据类型.png

swift跟其他语言不同,仅提供了两大类的数据类型:值类型引用类型。值类型又包括枚举和结构体两种。我们在OC中常用的IntBool等基本数据类型在swift中都属于结构体类型。

Int

Swift 提供了一个特殊的整数类型Int,包括Int8Int16Int32Int64。长度与当前平台的原生字长相同:

  • 在32位平台上,IntInt32长度相同。
  • 在64位平台上,IntInt64长度相同。

Int8Int16Int32Int64 分别表示 8 位, 16 位, 32 位, 和 64 位的有符号整数形式。

除非你需要特定长度的整数,一般来说使用Int就够了。这可以提高代码一致性和可复用性。即使是在32位平台上,Int可以存储的整数范围也可以达到-2,147,483,648 ~ 2,147,483,647,大多数时候这已经足够大了。

UInt

Swift 也提供了一个特殊的无符号类型UInt,包括UInt8UInt16UInt32UInt64。长度与当前平台的原生字长相同:

  • 在32位平台上,UIntUInt32长度相同。
  • 在64位平台上,UIntUInt64长度相同。

UInt8UInt16UInt32UInt64 分别表示 8 位, 16 位, 32 位 和 64 位的无符号整数形式。

注意: 尽量不要使用UInt,除非你真的需要存储一个和当前平台原生字长相同的无符号整数。除了这种情况,最好使用Int,即使你要存储的值已知是非负的。统一使用Int可以提高代码的可复用性,避免不同类型数字之间的转换,并且匹配数字的类型推断。

浮点数:Float、Double

浮点数是有小数部分的数字,比如 3.141590.1 和 -273.15

浮点类型比整数类型表示的范围更大,可以存储比 Int 类型更大或者更小的数字。Swift 提供了两种有符号浮点数类型:

  • Double 表示64位浮点数。精确度很高,至少有15位数字,当你需要存储很大或者很高精度的浮点数时请使用此类型。
  • Float 表示32位浮点数。精度只有6位数字,精度要求不高的话可以使用此类型。

定义Double类型数据很简单,直接赋值一个小数就可以了,定义Float类型数据需要声明类型:

let letDouble = 3.12 // Double类型
let letFloat: Float = 3.31 // Float类型

布尔值:Bool

Swift 有一个基本的布尔(Boolean)类型,叫做 Bool。布尔值指逻辑上的值,因为它们只能是真或者假。Swift 有两个布尔常量,truefalse

五、字面量

字面量,就是指像特定的数字,字符串或者布尔值等,能够直接指出自己的类型并为变量进行赋值的值。比如:

let aNumber = 3         //整型字面量
let aString = "Hello"   //字符串字面量
let aBool = true        //布尔值字面量

整型字面量

整型字面量可以是一个十进制,二进制,八进制或十六进制常量。 二进制前缀为 0b,八进制前缀为 0o,十六进制前缀为 0x,十进制没有前缀:

let decimalInteger = 17           // 17 - 十进制
let binaryInteger = 0b10001       // 17 - 0b开头,二进制
let octalInteger = 0o21           // 17 - 0o开头,八进制
let hexadecimalInteger = 0x11     // 17 - 0x开头,十六进制

浮点型字面量

浮点型字面量有整数部分,小数点,小数部分及指数部分。 除非特别指定,浮点型字面量的默认推导类型为 Swift 标准库类型中的 Double,表示64位浮点数。 浮点型字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 0x)。

let doubleDecimal1 = 125.0 // 十进制,等价于1.25e2 即 1.25 ⨉ 10^2
let doubleDecimal2 = 0.0125 // 十进制,等价于1.25e-2 即 1.25 ⨉ 10^-2
let doubleHexadecimall1= 0xFp2 // 十六进制,0xFp2 表示 15 ⨉ 2^2,也就是十进制的 60.0
let doubleHexadecimall2= 0xFp-2 // 十六进制,0xFp-2 表示 15 ⨉ 2^-2,也就是 3.75

再例如以下都是表示12.1875:

let decimalDouble = 12.1875       //十进制浮点型字面量
let exponentDouble = 1.21875e1    //十进制浮点型字面量
let hexadecimalDouble = 0xC.3p0   //十六进制浮点型字面量

浮点型字面量允许使用下划线 _ 来增强数字的可读性,下划线会被系统忽略,因此不会影响字面量的值。同样地,也可以在数字前加 0,并不会影响字面量的值。例如:

let a = 1_000_000 // 1000000
let b = 000123456 //123456

字符串型字面量

字符串型字面量由被包在双引号中的一串字符组成,形式如下:

let name = "mars"

需要注意的是,字符型(Character)字面量需要声明类型,因为字符型字面量也是使用双引号,所以需要声明类型跟字符串行区别开来:

let char: Character = "a"

类型转换

swift中,整数和浮点数不能直接做运算,需要进行数据类型转换:

let intA = 3
let doubleB = 0.14159
let pi = Double(intA) + doubleB
let intPi = Int(pi)

例子中,intA为整数,doubleB为浮点数,类型不同不能直接相加,需要将intA强转为浮点型,再做运算。相加的结果pi即浮点型。同样也可以直接将pi通过Int关键字强转为Int类型。

当然,数字字面量可以直接相加,因为本身没有明确类型:

let result = 3 + 0.14159

六、元组(Tuple)

元组是swift语言中一种复合类型,可以将多种类型的数据组合在一起。例如:

let http404Error = (404, "Not Found")
print("The status code is \(http404Error.0)") // 打印输出The status code is 404

例子中的常量 http404Error 就是元组类型,此处为(Int, String)类型。我们可以通过下标获取常量 http404Error 具体数据内容:

print(http404Error.0) // 打印输出404
print(http404Error.1) // 打印输出Not Found

当然我们也可以用一个元组来接收已经定义好的元组类型常量 http404Error

let (statusCode, statusMessage) = http404Error
print("The status code is \(statusCode)") // 打印输出The status code is 404

如果只想不想接收其中某部分数据,使用 _ 替代即可:

let (justTheStatusCode, _) = http404Error // 只接收了 http404Error 中Int类型数据

在定义元组类型变量时,也可以给具体值指定标签 标签名+: ,获取时通过点语法即可获取具体值:

let http200Status = (statusCode: 200, description: "success")
print("The status code is \(http200Status.statusCode)") // 打印输出The status code is 200

七、if-else

Swift中,if 后面的条件可以省略小括号,但大括号不可省略。条件只能是Bool类型

let grade = 99
if grade >= 90 {
    print("Grade is A")
}else if grade >= 80 {
    print("Grade is B")
}else if grade >= 70 {
    print("Grade is C")
}else {
    print("Grade is D")
} // 打印输出Grade is A

八、while

Swift中,while 后面的条件可以省略小括号,但大括号不可省略。

var num = 5
while num > 0 {
    print("num is \(num)")
    num -= 1
} // 打印输出num is 5 num is 4 num is 3 num is 2 num is 1

注意这里没有使用num--,是因为在 Swift 3.0 中,就去掉了自增++和自减--运算符。 Swift中还提供了repeat - while语句,相当于C语言中的do - while语句:

var num1 = -1
repeat {
    print("num is \(num1)")
}while num > 0 // 打印输出 num is -1

九、for-in 循环

Swift 中使用for-in 循环用于遍历一个集合里面的所有元素。

var arr = [1, 2, 3, 4, 5]
for index in arr {
    print(index)
} // 打印输出 1 2 3 4 5 

例子中,index默认是常量,也可以声明为变量:

var arr = [1,2,3,4,5]
for var index in arr {
    print(index)
} // 打印输出 1 2 3 4 5 

如果在循环中不需要index,也可以用 _替代:

var arr = [1,2,3,4,5]
for _ in arr {
    print("hello")
} // 打印输出 hello hello hello hello hello

闭区间运算符 ...

闭区间运算符表示取值范围,例如:

a...b //a <= 取值 <= b

上面for-in 循环的例子就可以写成:

for index in 1...5 {
    print(index)
} // 打印输出 1 2 3 4 5 

半开区间运算符 ..<

半开区间运算符表示取值范围,例如:

a..<b //a <= 取值 < b

运用到for-in 循环中:

for index in 1..<5 {
    print(index)
} // 打印输出 1 2 3 4

区间运算符运用在数组上

上面讲述的区间运算符也可以用在数组上,表示下标值范围:

var names = ["tom", "jack", "mars", "thomas"]
for name in names[0...3] {
    print(name)
} // 打印输出tom jack mars thomas

也可以使用单侧区间来指定范围:

// ...2 表示 0 1 2
var names = ["tom", "jack", "mars", "thomas"]
for name in names[...2] {
    print(name)
} // 打印输出tom jack mars

使用半开区间运算符:

// ..<2 表示 0 1
var names = ["tom", "jack", "mars", "thomas"]
for name in names[..<2] {
    print(name)
} // 打印输出tom jack

十、switch

Swift 中 switch 语句,必须要保证能处理所有情况switch 语句中casedefault后面不能写大括号{}。默认可以不用写 break,也不会贯穿到后面的条件:

var number = 1
switch number {
case 1:
    print("number is 1")
case 2:
    print("number is 2")
default:
    print("number is other")
} // 打印输出 number is 1

可以使用fallthrough关键字实现贯穿效果(复合条件):

var number = 1
switch number {
case 1:
    print("number is 1")
    fallthrough
case 2:
    print("number is 2")
default:
    print("number is other")
} // 打印输出 number is 1 number is 2

复合条件

除了使用fallthrough关键字实现复合条件,也可以在条件中写入多个条件并用逗号分隔开。另外,switch也支持字符串 String 和字符 Character 类型:

let stri = "Mars"
switch stri {
case "Mars", "Tom":
    print("He is my friend")
default:
    break
} // 打印输出 He is my friend

switch中的区间匹配

区间运算符同样也可以运用到switch语句中:

let count = 89
switch count {
case 0:
    print("none")
case 1..<10:
    print("a few")
case 10..<100:
    print("a lot")
default:
    print("many")
} // 打印输出 a lot

十一、where

swift中可以使用where关键字来过滤筛选条件:

var numbers = [10, 20, -10, 30, -20]
var sum = 0
for num in numbers where num > 0 {
    sum += num
}
print(sum) // 打印输出60

例子中,where num > 0筛选出数组中的正数,然后进入循环进行相加。

结语

简单学习了一下swift的部分基础语法,今天就到这里,文中如果有不对的地方可以留言指出来。欢迎大家扫码关注微信公众号,一起交流学习。

更多技术知识请扫码关注微信公众号

iOS进阶

iOS进阶.jpg