Swift 可选(Optionals)类型
Swift 的可选(Optional)类型,用于处理值缺失的情况。可选表示"那儿有一个值,并且它等于 x "或者"那儿没有值"。
Swfit语言定义后缀?作为命名类型Optional的简写,换句话说,以下两种声明是相等的:
var optionalInteger: Int?
var optionalInteger: Optional<Int>
在这两种情况下,变量 optionalInteger 都是可选整数类型。注意,在类型和 ?之间没有空格。
Optional 是一个含有两种情况的枚举,None 和 Some(T),用来表示可能有或可能没有值。任何类型都可以明确声明为(或者隐式转换)可选类型。当声明一个可选类型的时候,要确保用括号给 ? 操作符一个合适的范围。例如,声明可选整数数组,应该写成 (Int[])? 写成 Int[]? 会报错。
当你声明一个可选变量或者可选属性的时候没有提供初始值,它的值会默认为 nil。
可选项遵照 LogicValue 协议,因此可以出现在布尔环境中。在这种情况下,如果可选类型T?包含类型为T的任何值(也就是说它的值是 Optional.Some(T) ),这个可选类型等于 true,反之为 false。
如果一个可选类型的实例包含一个值,你可以用后缀操作符 !来访问这个值,如下所示:
optionalInteger = 42
optionalInteger! // 42
使用操作符!去获取值为nil的可选变量会有运行时错误。
你可以用可选链接和可选绑定选择性执行可选表达式上的操作。如果值为nil,任何操作都不会执行,也不会有运行报错。
让我们来详细看下以下实例来了解 Swift 中可选类型的应用:
import Cocoa
var myString:String? = nil
if myString != nil {
print(myString)
}else{
print("字符串为 nil")
}
以上程序执行结果为:
字符串为 nil
可选类型类似于Objective-C中指针的nil值,但是nil只对类(class)有用,而可选类型对所有的类型都可用,并且更安全。
强制解析
当你确定可选类型确实包含值之后,你可以在可选的名字后面加一个感叹号(!)来获取值。这个感叹号表示"我知道这个可选有值,请使用它。"这被称为可选值的强制解析(forced unwrapping)。
注意:
使用!
来获取一个不存在的可选值会导致运行时错误。使用!
来强制解析值之前,一定要确定可选包含一个非nil
的值。
强制解析可选值,使用感叹号(!):
import Cocoa
var myString:String?
myString = "Hello, Swift!"
if myString != nil {
// 强制解析
print( myString! )
}else{
print("myString 值为 nil")
}
自动解析
你可以在声明可选变量时使用感叹号(!)替换问号(?)。这样可选变量在使用时就不需要再加一个感叹号(!)来获取值,它会自动解析。
import Cocoa
var myString:String!
myString = "Hello, Swift!"
if myString != nil {
print(myString)
}else{
print("myString 值为 nil")
}
可选绑定
使用可选绑定(optional binding)来判断可选类型是否包含值,如果包含就把值赋给一个临时常量或者变量。可选绑定可以用在if和while语句中来对可选类型的值进行判断并把值赋给一个常量或者变量。
像下面这样在if语句中写一个可选绑定:
if let constantName = someOptional {
statements
}
类型标注
当你声明常量或者变量的时候可以加上类型标注(type annotation),说明常量或者变量中要存储的值的类型。如果要添加类型标注,需要在常量或者变量名后面加上一个冒号和空格,然后加上类型名称。
var constantName:<data type> = <optional initial value>
事例:
let constB:Float = 3.14159
常量命名
Swift 是一个区分大小写的语言,所以字母大写与小写是不一样的。
常量名也可以使用简单的 Unicode 字符,如下实例:
let 你好 = "你好世界"
print(你好)
以上程序执行结果为:
你好世界
常量输出
变量和常量可以使用 print(swift 2 将 print 替换了 println) 函数来输出。
在字符串中可以使用括号与反斜线来插入常量,如下实例:
let name = "菜鸟教程"
let site = "http://www.runoob.com"
print("\(name)的官网地址为:\(site)")
以上程序执行结果为:
菜鸟教程的官网地址为:http://www.runoob.com
整型字面量
整型字面量可以是一个十进制,二进制,八进制或十六进制常量。 二进制前缀为 0b,八进制前缀为 0o,十六进制前缀为 0x,十进制没有前缀:
let binaryInteger = 0b10001 // 17 - 二进制表示
let octalInteger = 0o21 // 17 - 八进制表示
let hexadecimalInteger = 0x11 // 17 - 十六进制表示
浮点型字面量
浮点型字面量有整数部分,小数点,小数部分及指数部分。
除非特别指定,浮点型字面量的默认推导类型为 Swift 标准库类型中的 Double,表示64位浮点数。
浮点型字面量默认用十进制表示(无前缀),也可以用十六进制表示(加前缀 0x)。
十进制浮点型字面量由十进制数字串后跟小数部分或指数部分(或两者皆有)组成。十进制小数部分由小数点 . 后跟十进制数字串组成。指数部分由大写或小写字母 e 为前缀后跟十进制数字串组成,这串数字表示 e 之前的数量乘以 10 的几次方。例如:1.25e2 表示 1.25 ⨉ 10^2,也就是 125.0;同样,1.25e-2 表示 1.25 ⨉ 10^-2,也就是 0.0125。
十六进制浮点型字面量由前缀 0x 后跟可选的十六进制小数部分以及十六进制指数部分组成。十六进制小数部分由小数点后跟十六进制数字串组成。指数部分由大写或小写字母 p 为前缀后跟十进制数字串组成,这串数字表示 p 之前的数量乘以 2 的几次方。例如:0xFp2 表示 15 ⨉ 2^2,也就是 60;同样,0xFp-2 表示 15 ⨉ 2^-2,也就是 3.75。
负的浮点型字面量由一元运算符减号 - 和浮点型字面量组成,例如 -42.5。
符串型字面量
字符串型字面量由被包在双引号中的一串字符组成,形式如下:
"characters"
字符串型字面量中不能包含未转义的双引号 (")、未转义的反斜线(\)、回车符或换行符。
转义字符 | 含义 |
---|---|
\0 | 空字符 |
\\ | 反斜线 \ |
\b | 退格(BS) ,将当前位置移到前一列 |
\f | 换页(FF),将当前位置移到下页开头 |
\n | 换行符 |
\r | 回车符 |
\t | 水平制表符 |
\v | 垂直制表符 |
\' | 单引号 |
\" | 双引号 |
\000 | 1到3位八进制数所代表的任意字符 |
\xhh... | 1到2位十六进制所代表的任意字符 |
布尔型字面量
布尔型字面量的默认类型是 Bool。
布尔值字面量有三个值,它们是 Swift 的保留关键字:
-
true 表示真。
-
false 表示假。
-
nil 表示没有值。
位运算符
位运算符用来对二进制位进行操作,~,&,|,^分别为取反,按位与与,按位与或,按位与异或运算,如下表实例:
p | q | p & q | p | q | p ^ q |
---|---|---|---|---|
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
1 | 0 | 0 | 1 | 1 |
进行位运算:
运算符 | 描述 | 图解 | 实例 |
---|---|---|---|
& | 按位与。按位与运算符对两个数进行操作,然后返回一个新的数,这个数的每个位都需要两个输入数的同一位都为1时才为1。 | (A & B) 结果为 12, 二进制为 0000 1100 | |
| | 按位或。按位或运算符|比较两个数,然后返回一个新的数,这个数的每一位设置1的条件是两个输入数的同一位都不为0(即任意一个为1,或都为1)。 | (A | B) 结果为 61, 二进制为 0011 1101 | |
^ | 按位异或. 按位异或运算符^比较两个数,然后返回一个数,这个数的每个位设为1的条件是两个输入数的同一位不同,如果相同就设为0。 | (A ^ B) 结果为 49, 二进制为 0011 0001 | |
~ | 按位取反运算符~对一个操作数的每一位都取反。 | (~A ) 结果为 -61, 二进制为 1100 0011 in 2's complement form. | |
<< | 按位左移。左移操作符(<<)将操作数的所有位向左移动指定的位数。 | 下图展示了11111111 << 1(11111111 左移一位)的结果。蓝色数字表示被移动位,灰色表示被丢弃位,空位用橙色的0填充。 | A << 2 结果为 240, 二进制为 1111 0000 |
>> | 按位右移。右移操作符(>>)将操作数的所有位向右移动指定的位数。 | 下图展示了11111111 >> 1(11111111 右移一位)的结果。蓝色数字表示被移动位,灰色表示被丢弃位,空位用橙色的0填充。 | A >> 2 结果为 15, 二进制为 0000 1111 |
Swift 提供了两个区间的运算符。
运算符 | 描述 | 实例 |
---|---|---|
闭区间运算符 | 闭区间运算符(a...b)定义一个包含从a到b(包括a和b)的所有值的区间,b必须大于等于a。 闭区间运算符在迭代一个区间的所有值时是非常有用的,如在for-in循环中: | 1...5 区间值为 1, 2, 3, 4 和 5 |
半开区间运算符 | 半开区间(a..<b)定义一个从a到b但不包括b的区间。 之所以称为半开区间,是因为该区间包含第一个值而不包括最后的值。 | 1..< 5 区间值为 1, 2, 3, 和 4 |
运算符优先级
在一个表达式中可能包含多个有不同运算符连接起来的、具有不同数据类型的数据对象;由于表达式有多种运算,不同的运算顺序可能得出不同结果甚至出现错误运算错误,因为当表达式中含多种运算时,必须按一定顺序进行结合,才能保证运算的合理性和结果的正确性、唯一性。
优先级从上到下依次递减,最上面具有最高的优先级,逗号操作符具有最低的优先级。
相同优先级中,按结合顺序计算。大多数运算是从左至右计算,只有三个优先级是从右至左结合的,它们是单目运算符、条件运算符、赋值运算符。
基本的优先级需要记住:
- 指针最优,单目运算优于双目运算。如正负号。
- 先乘除(模),后加减。
- 先算术运算,后移位运算,最后位运算。请特别注意:1 << 3 + 2 & 7 等价于 (1 << (3 + 2))&7
- 逻辑运算最后计算
Swift 运算符优先级 (从高到低):
运算符 | 实例 |
---|---|
位运算符 | >> &<< &>> >> |
乘法运算符 | &* % & * / |
加法运算符 | | &+ &- + - ^ |
区间运算符 | ..< ... |
类型转换运算符 | is as |
nil 的聚合运算 | ?? |
比较运算符 | != > < >= <= === == |
逻辑与运算符 | && |
逻辑或运算符 | || |
波浪箭头 | ~> |
三元运算符 | ?: |
箭头函数 | ( ) |
赋值运算符 | |= %= /= &<<= &>>= &= *= >>= <<= ^= += -= |
合并空值运算符:??
- 合并空值运算符 a ?? b 如果可选项 a 有值则展开,如果没有值,是 nil,则返回默认值 b。
- 表达式 a 必须是一个可选类型,表达式 b 必须与 a 的存储类型相同
- 合并空值运算符,实际上是三元运算符作用到 Optional 上的缩写 a != nil ? a! : b
- 如果 a 的值是非空,b的值将不会被考虑,也就是合并空值运算符是短路的。
var fff : [String]?
let k=["test"] as? [String] ?? ["str1", "str2", "str3"]
print(k)
let ff=fff as? [String] ?? ["str1", "str2", "str3"]
print(ff)
结果:
["test"]
["str1", "str2", "str3"]
循环类型
Swift 语言提供了以下几种循环类型。点击链接查看每个类型的详细描述:
循环类型 | 描述 |
---|---|
for-in | 遍历一个集合里面的所有元素,例如由数字表示的区间、数组中的元素、字符串中的字符。 |
for 循环 | 该循环方式在 Swift 3 中已经弃用。 用来重复执行一系列语句直到达成特定条件达成,一般通过在每次循环完成后增加计数器的值来实现。 |
while 循环 | 运行一系列语句,如果条件为true,会重复运行,直到条件变为false。 |
repeat...while 循环 | 类似 while 语句区别在于判断循环条件之前,先执行一次循环的代码块。 |
循环控制语句
循环控制语句改变你代码的执行顺序,通过它你可以实现代码的跳转。Swift 以下几种循环控制语句:
控制语句 | 描述 |
---|---|
continue 语句 | 告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。 |
break 语句 | 中断当前循环。 |
fallthrough 语句 | 如果在一个case执行完后,继续执行下面的case,需要使用fallthrough(贯穿)关键字。 |
创建字符串
你可以通过使用字符串字面量或 String 类的实例来创建一个字符串:
// 使用字符串字面量
var stringA = "Hello, World!"
// String 实例化
var stringB = String("Hello, World!")
空字符串
你可以使用空的字符串字面量赋值给变量或初始化一个String类的实例来初始值一个空的字符串。 我们可以使用字符串属性 isEmpty 来判断字符串是否为空:
// 使用字符串字面量创建空字符串
var stringA = ""
if stringA.isEmpty {
print( "stringA 是空的" )
} else {
print( "stringA 不是空的" )
}
// 实例化 String 类来创建空字符串
let stringB = String()
字符串常量
你可以将一个字符串赋值给一个变量或常量,变量是可修改的,常量是不可修改的。
// stringA 可被修改
var stringA = "菜鸟教程:"
stringA += "http://www.runoob.com"
print( stringA )
输出结果:
菜鸟教程:http://www.runoob.com
字符串中插入值
字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式。 您插入的字符串字面量的每一项都在以反斜线为前缀的圆括号中:
var varA = 20
let constA = 100
var varC:Float = 20.0
var stringA = "\(varA) 乘于 \(constA) 等于 \(varC * 100)"
print( stringA )
以上程序执行输出结果为:
20 乘于 100 等于 2000.0
字符串连接
字符串可以通过 + 号来连接,实例如下:
let constA = "菜鸟教程:"
let constB = "http://www.runoob.com"
var stringA = constA + constB
print( stringA )
以上程序执行输出结果为:
菜鸟教程:http://www.runoob.com
字符串长度
字符串长度使用 String.count 属性来计算,实例如下:
Swift 3 版本使用的是 String.characters.count
import Cocoa
var varA = "www.runoob.com"
print( "\(varA), 长度为 \(varA.count)" )
以上程序执行输出结果为:
www.runoob.com, 长度为 14
字符串比较
你可以使用 == 来比较两个字符串是否相等:
var varA = "Hello, Swift!"
var varB = "Hello, World!"
if varA == varB {
print( "\(varA) 与 \(varB) 是相等的" )
} else {
print( "\(varA) 与 \(varB) 是不相等的" )
}
以上程序执行输出结果为:
Hello, Swift! 与 Hello, World! 是不相等的
Unicode 字符串
Unicode 是一个国际标准,用于文本的编码,Swift 的 String 类型是基于 Unicode建立的。你可以循环迭代出字符串中 UTF-8 与 UTF-16 的编码,实例如下:
import Cocoa
var unicodeString = "菜鸟教程"
print("UTF-8 编码: ")
for code in unicodeString.utf8 {
print("\(code) ")
}
print("\n")
print("UTF-16 编码: ")
for code in unicodeString.utf16 {
print("\(code) ")
}
以上程序执行输出结果为:
UTF-8 编码:
232
143
156
233
184
159
230
149
153
231
168
139
UTF-16 编码:
33756
40479
25945
31243
字符串函数及运算符
Swift 支持以下几种字符串函数及运算符:
序号 | 函数/运算符 & 描述 |
---|---|
1 | isEmpty 判断字符串是否为空,返回布尔值 |
2 | hasPrefix(prefix: String) 检查字符串是否拥有特定前缀 |
3 | hasSuffix(suffix: String) 检查字符串是否拥有特定后缀。 |
4 | Int(String) 转换字符串数字为整型。 实例: let myString: String = "256" let myInt: Int? = Int(myString) |
5 | String.count Swift 3 版本使用的是 String.characters.count 计算字符串的长度 |
6 | utf8 您可以通过遍历 String 的 utf8 属性来访问它的 UTF-8 编码 |
7 | utf16 您可以通过遍历 String 的 utf8 属性来访问它的 utf16 编码 |
8 | unicodeScalars 您可以通过遍历String值的unicodeScalars属性来访问它的 Unicode 标量编码. |
9 | + 连接两个字符串,并返回一个新的字符串 |
10 | += 连接操作符两边的字符串并将新字符串赋值给左边的操作符变量 |
11 | == 判断两个字符串是否相等 |
12 | < 比较两个字符串,对两个字符串的字母逐一比较。 |
13 | != 比较两个字符串是否不相等。 |
字符串分割数组 -- 基于空格
let fullName = "First Last" let fullNameArr = fullName.characters.split{$0 == " "}.map(String.init) // or simply: // let fullNameArr = fullName.characters.split{" "}.map(String.init) //现在的方法 var fullNameArr = fullName.split(separator: " ") fullNameArr[0] // First fullNameArr[1] // Last
字符串的遍历 Swift 5:
let str = "菜鸟教程runoob.com" print("---- 正序遍历 ----") var i = 0 for ch in str { print("\(i): \(ch)") i += 1 } print("---- 逆序遍历 ----") var j = str.count for ch in str.reversed() { j -= 1 print("\(j): \(ch)") } print("---- 基于索引的正序遍历 ----") for i in 0..<str.count { let ch: Character = str[str.index(str.startIndex, offsetBy: i)] print("\(i): \(ch)") } print("---- 基于索引的逆序遍历 ----") //for i in stride(from: str.count - 1, to: -1, by: -1) { for i in stride(from: str.count - 1, through: 0, by: -1) { let ch: Character = str[str.index(str.startIndex, offsetBy: i)] print("\(i): \(ch)") } print("---- 基于EnumeratedSequence的遍历 ----") for (i, ch) in str.enumerated() { print("\(i): \(ch)") }
字符串连接字符
以下实例演示了使用 String 的 append() 方法来实现字符串连接字符:
import Cocoa var varA:String = "Hello " let varB:Character = "G" varA2.append(" \(varB) " ) print("varC = \(varA)")
以上程序执行输出结果为:
varC = Hello G
修改数组
你可以使用 append() 方法或者赋值运算符 += 在数组末尾添加元素,如下所示,我们初始化一个数组,并向其添加元素:
import Cocoa
var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
var someVar = someInts[0]
print( "第一个元素的值 \(someVar)" )
print( "第二个元素的值 \(someInts[1])" )
print( "第三个元素的值 \(someInts[2])" )
以上程序执行输出结果为:
第一个元素的值 20
第二个元素的值 30
第三个元素的值 40
我们也可以通过索引修改数组元素的值:
import Cocoa
var someInts = [Int]()
someInts.append(20)
someInts.append(30)
someInts += [40]
// 修改最后一个元素
someInts[2] = 50
如果我们同时需要每个数据项的值和索引值,可以使用 String 的 enumerate() 方法来进行数组遍历。实例如下:
import Cocoa
var someStrs = [String]()
someStrs.append("Apple")
someStrs.append("Amazon")
someStrs.append("Runoob")
someStrs += ["Google"]
for (index, item) in someStrs.enumerated() {
print("在 index = \(index) 位置上的值为 \(item)")
}
合并数组
我们可以使用加法操作符(+)来合并两种已存在的相同类型数组。新数组的数据类型会从两个数组的数据类型中推断出来:
count 属性
我们可以使用 count 属性来计算数组元素个数:
isEmpty 属性
我们可以通过只读属性 isEmpty 来判断数组是否为空,返回布尔值:
创建数组的方法不推荐使用文章中记载的方法。
推荐:
var names: [String] = []
var lookup: [String: Int] = [:]
不推荐:
var names = [String]()
var lookup = [String: Int]()
创建字典
我们可以使用以下语法来创建一个特定类型的空字典:
var someDict = [KeyType: ValueType]()
以下是创建一个空字典,键的类型为 Int,值的类型为 String 的简单语法:
var someDict = [Int: String]()
以下为创建一个字典的实例:
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
访问字典
我们可以根据字典的索引来访问数组的元素,语法如下:
var someVar = someDict[key]
修改字典
我们可以使用 updateValue(forKey:) 增加或更新字典的内容。如果 key 不存在,则添加值,如果存在则修改 key 对应的值。updateValue(_:forKey:)方法返回Optional值。实例如下:
import Cocoa var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"] var oldVal = someDict.updateValue("One 新的值", forKey: 1) var someVar = someDict[1] print( "key = 1 旧的值 \(oldVal)" ) print( "key = 1 的值为 \(someVar)" ) print( "key = 2 的值为 \(someDict[2])" ) print( "key = 3 的值为 \(someDict[3])" )
以上程序执行输出结果为:
key = 1 旧的值 Optional("One") key = 1 的值为 Optional("One 新的值") key = 2 的值为 Optional("Two") key = 3 的值为 Optional("Three")
移除 Key-Value 对
我们可以使用 removeValueForKey() 方法来移除字典 key-value 对。如果 key 存在该方法返回移除的值,如果不存在返回 nil 。实例如下:
import Cocoa
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
var removedValue = someDict.removeValue(forKey: 2)
print( "key = 1 的值为 \(someDict[1])" )
print( "key = 2 的值为 \(someDict[2])" )
print( "key = 3 的值为 \(someDict[3])" )
以上程序执行输出结果为:
key = 1 的值为 Optional("One")
key = 2 的值为 nil
key = 3 的值为 Optional("Three")
你也可以通过指定键的值为 nil 来移除 key-value(键-值)对。实例如下:
someDict[2] = nil
print( "key = 2 的值为 \(someDict[2])" )
key = 2 的值为 nil
遍历字典
我们可以使用 for-in 循环来遍历某个字典中的键值对。实例如下:
import Cocoa
var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"]
for (key, value) in someDict {
print("字典 key \(key) - 字典 value \(value)")
}
字典转换为数组
你可以提取字典的键值(key-value)对,并转换为独立的数组。实例如下:
import Cocoa var someDict:[Int:String] = [1:"One", 2:"Two", 3:"Three"] let dictKeys = [Int](someDict.keys) let dictValues = [String](someDict.values)
print("输出字典的键(key)") for (key) in dictKeys { print("\(key)") } print("输出字典的值(value)") for (value) in dictValues { print("\(value)") }
以上程序执行输出结果为:
输出字典的键(key) 2 3 1 输出字典的值(value) Two Three One
count 属性
我们可以使用只读的 count 属性来计算字典有多少个键值对:
isEmpty 属性
Y我们可以通过只读属性 isEmpty 来判断字典是否为空,返回布尔值:
函数定义
Swift 定义函数使用关键字 func。
定义函数的时候,可以指定一个或多个输入参数和一个返回值类型。
每个函数都有一个函数名来描述它的功能。通过函数名以及对应类型的参数值来调用这个函数。函数的参数传递的顺序必须与参数列表相同。
函数的实参传递的顺序必须与形参列表相同,-> 后定义函数的返回值类型。
语法
func funcname(形参) -> returntype
{
Statement1
Statement2
……
Statement N
return parameters
}
实例
以下我们定义了一个函数名为 runoob 的函数,形参的数据类型为 String,返回值也为 String:
import Cocoa
func runoob(site: String) -> String {
return (site)
}
print(runoob(site: "www.runoob.com"))
以上程序执行输出结果为:
www.runoob.com
函数参数
函数可以接受一个或者多个参数,这些参数被包含在函数的括号之中,以逗号分隔。
以下实例向函数 runoob 传递站点名 name 和站点地址 site:
import Cocoa
func runoob(name: String, site: String) -> String {
return name + site
}
print(runoob(name: "菜鸟教程:", site: "www.runoob.com"))
print(runoob(name: "Google:", site: "www.google.com"))
以上程序执行输出结果为:
菜鸟教程:www.runoob.com
Google:www.google.com
不带参数函数
我们可以创建不带参数的函数。
语法:
func funcname() -> datatype {
return datatype
}
元组作为函数返回值
函数返回值类型可以是字符串,整型,浮点型等。
元组与数组类似,不同的是,元组中的元素可以是任意类型,使用的是圆括号。
你可以用元组(tuple)类型让多个值作为一个复合值从函数中返回。
下面的这个例子中,定义了一个名为minMax(_:)的函数,作用是在一个Int数组中找出最小值与最大值。
import Cocoa
func minMax(array: [Int]) -> (min: Int, max: Int) {
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
let bounds = minMax(array: [8, -6, 2, 109, 3, 71])
print("最小值为 \(bounds.min) ,最大值为 \(bounds.max)")
minMax(_:)函数返回一个包含两个Int值的元组,这些值被标记为min和max,以便查询函数的返回值时可以通过名字访问它们。
以上程序执行输出结果为:
最小值为 -6 ,最大值为 109
如果你不确定返回的元组一定不为nil,那么你可以返回一个可选的元组类型。
你可以通过在元组类型的右括号后放置一个问号来定义一个可选元组,例如(Int, Int)?或(String, Int, Bool)?
注意
可选元组类型如(Int, Int)?
与元组包含可选类型如(Int?, Int?)
是不同的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。
前面的minMax(_:)
函数返回了一个包含两个Int
值的元组。但是函数不会对传入的数组执行任何安全检查,如果array
参数是一个空数组,如上定义的minMax(_:)
在试图访问array[0]
时会触发一个运行时错误。
为了安全地处理这个"空数组"问题,将minMax(_:)
函数改写为使用可选元组返回类型,并且当数组为空时返回nil
:
import Cocoa
func minMax(array: [Int]) -> (min: Int, max: Int)? {
if array.isEmpty { return nil }
var currentMin = array[0]
var currentMax = array[0]
for value in array[1..<array.count] {
if value < currentMin {
currentMin = value
} else if value > currentMax {
currentMax = value
}
}
return (currentMin, currentMax)
}
if let bounds = minMax(array: [8, -6, 2, 109, 3, 71]) {
print("最小值为 \(bounds.min),最大值为 \(bounds.max)")
}
以上程序执行输出结果为:
最小值为 -6,最大值为 109
没有返回值函数
下面是 runoob(_:) 函数的另一个版本,这个函数接收菜鸟教程官网网址参数,没有指定返回值类型,并直接输出 String 值,而不是返回它:
import Cocoa
func runoob(site: String) {
print("菜鸟教程官网:\(site)")
}
runoob(site: "http://www.runoob.com")
以上程序执行输出结果为:
菜鸟教程官网:http://www.runoob.com
函数参数名称
函数参数都有一个外部参数名和一个局部参数名。
局部参数名
局部参数名在函数的实现内部使用。
func sample(number: Int) {
println(number)
}
以上实例中 number 为局部参数名,只能在函数体内使用。
外部参数名
你可以在局部参数名前指定外部参数名,中间以空格分隔,外部参数名用于在函数调用时传递给函数的参数。
如下你可以定义以下两个函数参数名并调用它:
import Cocoa func pow(firstArg a: Int, secondArg b: Int) -> Int { var res = a for _ in 1..<b { res = res * a } print(res) return res } pow(firstArg:5, secondArg:3)
以上程序执行输出结果为:
125