关于 Swift
Swift 是一种非常好的编写软件的方式,无论是手机,台式机,服务器,还是其他运行代码的设备。它是一种安全,快速和互动的编程语言,将现代编程语言的精华和苹果工程师文化的智慧,以及来自开源社区的多样化贡献结合了起来。编译器对性能进行了优化,编程语言对开发进行了优化,两者互不干扰,鱼与熊掌兼得。
Swift 对于初学者来说也很友好。它是一门满足工业标准的编程语言,但又有着脚本语言般的表达力和可玩性。它支持代码预览(playgrounds),这个革命性的特性可以允许程序员在不编译和运行应用程序的前提下运行 Swift 代码并实时查看结果。
Swift 通过采用现代编程模式来避免大量常见编程错误:
- 变量始终在使用前初始化。
- 检查数组索引超出范围的错误。
- 检查整数是否溢出。
- 可选值确保明确处理
nil
值。 - 内存被自动管理。
- 错误处理允许从意外故障控制恢复。
Swift 代码被编译和优化,以充分利用现代硬件。语法和标准库是基于指导原则设计的,编写代码的明显方式也应该是最好的。安全性和速度的结合使得 Swift 成为从 “Hello,world!” 到整个操作系统的绝佳选择。
关于语法细节可参考:https://swift.bootcss.com/
语法笔记
2.1 说明
Swift 包含了 C 和 Objective-C 上所有基础数据类型,Int
表示整型值; Double
和 Float
表示浮点型值; Bool
是布尔型值;String
是文本型数据。 Swift 还提供了三个基本的集合类型,Array
、Set
和 Dictionary
。
就像 C 语言一样,Swift 使用变量来进行存储并通过变量名来关联值。在 Swift 中,广泛的使用着值不可变的变量,它们就是常量,而且比 C 语言的常量更强大。在 Swift 中,如果你要处理的值不需要改变,那使用常量可以让你的代码更加安全并且更清晰地表达你的意图。
除了我们熟悉的类型,Swift 还增加了 Objective-C 中没有的高阶数据类型比如元组(Tuple)。元组可以让你创建或者传递一组数据,比如作为函数的返回值时,你可以用一个元组可以返回多个值。
Swift 还增加了可选(Optional)类型,用于处理值缺失的情况。可选表示 “那儿有一个值,并且它等于 x ” 或者 “那儿没有值” 。可选有点像在 Objective-C 中使用 nil
,但是它可以用在任何类型上,不仅仅是类。可选类型比 Objective-C 中的 nil
指针更加安全也更具表现力,它是 Swift 许多强大特性的重要组成部分。
Swift 是一门 类型安全 的语言,这意味着 Swift 可以让你清楚地知道值的类型。如果你的代码需要一个 String
,类型安全会阻止你不小心传入一个 Int
。同样的,如果你的代码需要一个 String
,类型安全会阻止你意外传入一个可选的 String
。类型安全可以帮助你在开发阶段尽早发现并修正错误。
2.2 基础类型
1)变量与常量
声明常量和变量
常量和变量必须在使用前声明,用 let
来声明常量,用 var
来声明变量。下面的例子展示了如何用常量和变量来记录用户尝试登录的次数:
1 | let maximumNumberOfLoginAttempts = 10 |
这两行代码可以被理解为:
“声明一个名字是 maximumNumberOfLoginAttempts
的新常量,并给它一个值 10
。然后,声明一个名字是 currentLoginAttempt
的变量并将它的值初始化为 0
。”
类型注解
当你声明常量或者变量的时候可以加上 类型注解(type annotation) ,说明常量或者变量中要存储的值的类型。如果要添加类型注解,需要在常量或者变量名后面加上一个冒号和空格,然后加上类型名称。
这个例子给 welcomeMessage
变量添加了类型注解,表示这个变量可以存储 String
类型的值:
1 | var welcomeMessage: String |
声明中的冒号代表着 “是…类型” ,所以这行代码可以被理解为:
“声明一个类型为 String
,名字为 welcomeMessage
的变量。”
“类型为 String
”的意思是“可以存储任意 String
类型的值。”
welcomeMessage
变量现在可以被设置成任意字符串:
1 | welcomeMessage = "Hello" |
常量和变量名可以包含几乎所有的字符,包括 Unicode 字符:
1 | let π = 3.14159 |
值得注意的是:
a)在实际项目开发中,应该优先使用 let
类型,如需修改时再改为 var
。
b)let
指的是地址不可修改,但对象内容是可修改的(常量不可修改)。
2)元组(tuples)
把多个值组合成一个复合值。元组内的值可以是任意类型,并不要求是相同类型。
下面这个例子中,(404, "Not Found")
是一个描述 HTTP 状态码(HTTP status code) 的元组。HTTP 状态码是当你请求网页的时候 web 服务器返回的一个特殊值。如果你请求的网页不存在就会返回一个 404 Not Found
状态码。
1 | let http404Error = (404, "Not Found") |
(404, "Not Found")
元组把一个 Int
值和一个 String
值组合起来表示 HTTP 状态码的两个部分:一个数字和一个人类可读的描述。这个元组可以被描述为“一个类型为 (Int, String)
的元组”。
你可以把任意顺序的类型组合成一个元组,这个元组可以包含所有类型。只要你想,你可以创建一个类型为 (Int, Int, Int)
或者 (String, Bool)
或者其他任何你想要的组合的元组。
你可以将一个元组的内容分解(decompose)成单独的常量和变量,然后你就可以正常使用它们了:
1 | let (statusCode, statusMessage) = http404Error |
如果你只需要一部分元组值,分解的时候可以把要忽略的部分用下划线(_
)标记:
1 | let (justTheStatusCode, _) = http404Error |
此外,你还可以通过下标来访问元组中的单个元素,下标从零开始:
1 | print("The status code is \(http404Error.0)") |
你可以在定义元组的时候给单个元素命名:
1 | let http200Status = (statusCode: 200, description: "OK") |
给元组中的元素命名后,你可以通过名字来获取这些元素的值:
1 | print("The status code is \(http200Status.statusCode)") |
作为函数返回值时,元组非常有用。一个用来获取网页的函数可能会返回一个 (Int, String)
元组来描述是否获取成功。和只能返回一个类型的值比较起来,一个包含两个不同类型值的元组可以让函数的返回信息更有用。请参考 函数参数与返回值。
3)可选类型
可选类型用于处理可能缺失的情况。例如:
1 | var surveyAnswer: String? = "123" |
使用 if
或者 while
进行值判断。例如:
1 | // 强制解包 |
4)值类型与引用类型
值类型在赋值或传递时会进行拷贝。引用类型增加引用计数,不进行拷贝。
5)其他
5.1) 类型别名:
Swift 中不使用 typedef
,而是使用 typealias
。
1 | typealias AudioSample = UInt16 |
5.2) 分号:
Swift 中不需要使用分号,但同一行的两个语句可以使用分号分隔。
2.3 运算符
1)空合运算符
空合运算符(a ?? b
)将对可选类型 a
进行空判断,如果 a
包含一个值就进行解包,否则就返回一个默认值 b
。表达式 a
必须是 Optional 类型。默认值 b
的类型必须要和 a
存储值的类型保持一致。
空合运算符是对以下代码的简短表达方法:
1 | a != nil ? a! : b |
上述代码使用了三元运算符。当可选类型 a
的值不为空时,进行强制解包(a!
),访问 a
中的值;反之返回默认值 b
。无疑空合运算符(??
)提供了一种更为优雅的方式去封装条件判断和解包两种行为,显得简洁以及更具可读性。
2)区间运算符
Swift 提供了多种区间运算符,例如闭区间运算符 a...b
和半开区间运算符 a..<b
。
2.4 字符与字符串
Swift 的 String
和 Character
类型兼容 Unicode,允许使用任何字符。例如:
1 | for character in "Dog!🐶" { |
String 是值类型。
2.5 控制流
1)if
语句
if
的条件必须是布尔表达式。例如:
1 | let individualScores = [75, 43, 103, 87, 12] |
2)switch
语句
switch
支持任意类型的数据和多种比较操作。例如:
1 | let vegetable = "red pepper" |
感谢您的提醒,我将在原来的结构基础上添加这部分内容关于函数的说明:
2.6 函数
1)函数的定义
Swift 中函数的定义格式如下:
1 | func funcName(parameters) -> returnType { |
例如,定义一个问候函数:
1 | func greet(person: String) -> String { |
这里的函数格式类似于 JavaScript,但是增加了返回值类型的定义。
2)参数列表
a)参数标签和参数名称
每个函数参数都有一个参数标签(argument label)和一个参数名称(parameter name)。参数标签在调用函数时使用,参数名称在函数的实现中使用。默认情况下,参数名称作为其参数标签。
1 | func someFunction(parameterName: Int) { |
b)省略参数标签
如果不希望为某个参数添加标签,可以使用下划线(_)来代替明确的参数标签。
1 | func someFunction(_ firstParameterName: Int, secondParameterName: Int) { |
c)默认参数
类似于 C++,Swift 函数也可以有默认参数值。
1 | func someFunction(parameterWithoutDefault: Int, parameterWithDefault: Int = 12) { |
d)可变参数
函数可以接受不确定数量的参数,通过在参数类型后面添加 ...
来定义。
1 | func arithmeticMean(_ numbers: Double...) -> Double { |
e)输入输出参数
使用 inout
关键字定义输入输出参数,允许函数修改参数的值。
1 | func swapTwoInts(_ a: inout Int, _ b: inout Int) { |
3)函数类型
函数类型类似于函数指针,由函数的参数类型和返回类型组成。
1 | func addTwoInts(_ a: Int, _ b: Int) -> Int { |
函数类型可以作为参数类型、返回值类型等。
2.7 闭包
Swift 中的闭包类似于 OC 的 Block 和 C++ 的 lambda 表达式。闭包的一般形式为:
1 | { (parameters) -> return type in |
闭包可以用于排序等操作。例如:
1 | let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"] |
闭包是引用类型。
2.8 枚举、结构体、类
1)枚举
Swift 中的枚举更加灵活,不必为每个成员提供值。枚
举成员可以有关联值。例如:
1 | enum CompassPoint { |
2)结构体与类
结构体是值类型,类是引用类型。结构体和类有很多相似之处。例如:
1 | struct SomeStructure { |
2.9 类的构造与析构
类的构造和析构与 C++ 类似,但语法上有所不同。例如:
1 | class Color { |
2.10 属性监听器
属性监听器可以在属性即将改变或已经改变时执行代码。例如:
1 | class SomeClass { |
2.11 类的继承
Swift 支持类的继承。子类可以重写父类的方法、属性和下标。例如:
1 | class Bicycle: Vehicle { |
2.12 扩展
扩展可以给现有的类、结构体、枚举或协议添加新功能。例如:
1 | extension SomeType { |
2.13 协议
协议定义了一组方法、属性或其他要求,用于满足特定任务或功能。例如:
1 | protocol SomeProtocol { |
2.14 泛型
Swift 的泛型允许你写出灵活、可重用的函数和类型。它可以避免重复的代码,用一种清晰的方式来表达代码的意图。