数组
///创建数组
//创建某一类型的含有n个初始元素的数组
var array1 = [Int](repeating: 5, count: 3)
//创建某一类型空数组
var array2 = [Int]()
//创建某一类型的任意数量数组
var array3: [Any] = ["1", 2, "3"]
///替换元素
array1[2] = 6
print("array1:\(array1)")
///拼接元素
array2.append(1);
array3.append(4)
print("array2:\(String(describing: array2))\narray3:\(array3)")
///拼接数组
let sumArray = array1+array3
print("sumArray:\(sumArray)")
print("sumArray长度:\(sumArray.count)")
以上示例运行结果:
array1:[5, 5, 6]
array2:[1]
array3:["1", 2, "3", 4]
sumArray:[5, 5, 6, "1", 2, "3", 4]
sumArray长度:7
字典
- 创建及修改
///创建字典
//创建空字典
var dic1 = [String: String]()
//有初始值的字典
var dic2: [Int: Any] = [1:1, 2:"2", 3:"oldValue"]
///修改字典
//通过指定的 key 来修改字典的值
dic1["key1"] = "value1"
dic1["key2"] = "value2"
dic1["key3"] = "value3"
print("dic1:\(dic1)")
//使用 updateValue(forKey:) 增加或更新字典的内容。如果 key 不存在,则添加值,如果存在则修改 key 对应的值, 方法返回Optional值
if let oldValue = dic2.updateValue("3", forKey: 3){
print("dic2 oldValue: \(oldValue)")
}
dic2.updateValue(4, forKey: 4)
print("dic2:\(dic2)")
运行结果
dic1:["key1": "value1", "key3": "value3", "key2": "value2"]
dic2 oldValue: oldValue
dic2:[1: 1, 4: 4, 2: "2", 3: "3"]
- 移除键值对:
///移除 Key-Value 对
//通过制定key
dic1["key1"] = nil
print(dic1)
//使用 removeValueForKey() 方法来移除字典 key-value 对。如果 key 存在该方法返回移除的值,如果不存在返回 nil
if let removedValue = dic1.removeValue(forKey: "key2") {
print("dic1 removedValue:\(removedValue)")
}
print(dic1)
运行结果:
["key3": "value3", "key2": "value2"]
dic1 removedValue:value2
["key3": "value3"]
- 字典遍历
///遍历字典
for (key, value) in dic2 {
print("字典 key \(key) - 字典 value \(value)")
}
//使用enumerate()方法来进行字典遍历,返回的是字典的索引及 (key, value)
for (key, value) in dic2.enumerated() {
print("字典 index: \(key) - 字典 (key, value) : \(value)")
}
运行结果
字典 key 2 - 字典 value 2
字典 key 1 - 字典 value 1
字典 key 4 - 字典 value four
字典 key 3 - 字典 value 3
字典 index: 0 - 字典 (key, value) : (key: 2, value: "2")
字典 index: 1 - 字典 (key, value) : (key: 1, value: 1)
字典 index: 2 - 字典 (key, value) : (key: 4, value: "four")
字典 index: 3 - 字典 (key, value) : (key: 3, value: "3")
- 其它方法
///字典转数组
let keys = [Int](dic2.keys)
print(keys)
let values = dic2.values
print(values)
//打印键值对数量
print(dic2.count)
//打印是否为空键值对
print(dic2.isEmpty)
运行结果
[2, 4, 3, 1]
["2", "four", "3", 1]
4
false
枚举
枚举简单的说也是一种数据类型,只不过是这种数据类型只包含自定义的特定数据,它是一组有共同特性的数据的集合。
Swift 的枚举类似于 Objective C 和 C 的结构,枚举的功能为:
-
它声明在类中,可以通过实例化类来访问它的值。
-
枚举也可以定义构造函数(initializers)来提供一个初始成员值;可以在原始的实现基础上扩展它们的功能。
-
可以遵守协议(protocols)来提供标准的功能。
enum weekDays{
case Monday
case Tuesday
case Wensday
case Thursday
case Friday
case Saterday
case Sunday
}
//或者
enum weekDaysTwo{
case Monday,Tuesday,Wensday,Thursday,Friday,Saterday,Sunday
}
var day = weekDays.Monday
day = .Friday
var day2: weekDays = .Tuesday
switch day {
case .Monday:
print("星期一")
case .Friday:
print("星期五")
default:
print("其它")
}
运行结果:
星期五
枚举中定义的值(如 Sunday,Monday,……和Saturday)是这个枚举的成员值(或成员)。case关键词表示一行新的成员值将被定义。
注意: 和 C 和 Objective-C 不同,Swift 的枚举成员在被创建时不会被赋予一个默认的整型值。在上面的DaysofaWeek例子中,Sunday,Monday,……和Saturday不会隐式地赋值为0,1,……和6。相反,这些枚举成员本身就有完备的值,这些值是已经明确定义好的weekDays类型。
相关值
Student 的枚举类型,它可以是 Name 的一个字符串(String),或者是 Mark 的一个相关值(Int,Int,Int)。
enum Student{
case Name(String)
case Mark(Int,Int,Int)
}
let stu = Student.Name("Jason")
let marks = Student.Mark(70, 80, 90)
switch marks {
case .Name(let stuName):
print(stuName)
case .Mark(let mark1, let mark2, let mark3):
print(mark1,mark2,mark3)
default:
print("")
}
运行结果:
70 80 90
原始值
原始值可以是字符串,字符,或者任何整型值或浮点型值。每个原始值在它的枚举声明中必须是唯一的。
在原始值为整数的枚举时,不需要显式的为每一个成员赋值,Swift会自动为你赋值。
例如,当使用整数作为原始值时,隐式赋值的值依次递增1。
num Month: Int{
case January = 1,February,March,April,May,June,July,Auguset,September,October,November,December
}
let month = Month.January.rawValue
print(month)
运行结果:
1
闭包
闭包(Closures)是自包含的功能代码块,可以在代码中使用或者用来作为参数传值。
Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的 匿名函数比较相似。
全局函数和嵌套函数其实就是特殊的闭包。
闭包的形式有:
全局函数 | 嵌套函数 | 闭包表达式 |
---|---|---|
有名字但不能捕获任何值。 | 有名字,也能捕获封闭函数内的值。 | 无名闭包,使用轻量级语法,可以根据上下文环境捕获值。 |
Swift中的闭包有很多优化的地方:
- 根据上下文推断参数和返回值类型
- 从单行表达式闭包中隐式返回(也就是闭包体只有一行代码,可以省略return)
- 可以使用简化参数名,如$0, $1(从0开始,表示第i个参数…)
- 提供了尾随闭包语法(Trailing closure syntax)
语法
以下定义了一个接收参数并返回指定类型的闭包语法:
{(parameters) -> return type in
statements
}
实例:
1.无参数无返回值,只执行操作:
//()->() 闭包
let prin = {print("这是一个闭包")}
// 这两个都一样
let prin: () -> () = {print("这是一个闭包")}
prin()
2.接受参数并有返回值
// 第一种写法
let divide = {(val1: Int, val2: Int) -> Int in
return val1/val2
}
let result = divide(200,10)
print(result)
//第二种写法
var divideJian: (Int, Int) -> Int = {(val1: Int, val2: Int) -> Int in
return val1/val2
}
let result2 = divideJian(200,20)
print(result2)
//简化1: 类型自动推导 可以根据参数推断 只有一行可以不写return
divideJian = {(val1, val2) in
val1/val2
}
let result3 = divideJian(200,20)
print(result3)
//简化2: $可以取参数列表中的的参数 $0对应第一个,以此类推
divideJian = {$0/$1}
let result4 = divideJian(200,20)
print(result4)
运行结果:
20
10
10
10
3.尾随闭包(闭包作为函数参数)
尾随闭包是一个书写在函数括号之后的闭包表达式,函数支持将其作为最后一个参数调用。
定义函数
func PlusNumbersDescription(num1: Int, num2: Int, description: (Int, Int) -> String) {
let result = description(num1,num2)
print("description返回的内容是:\(result)")
}
不使用尾随闭包进行函数调用
let 定义好的闭包: (Int, Int) -> String = {
print("执行定义好的闭包")
return "\($0) + \($1) = \($0 + $1)"
}
PlusNumbersDescription(num1: 4, num2: 4, description: 定义好的闭包)
使用尾随闭包进行函数调用 (敲回车)
PlusNumbersDescription(num1: 5, num2: 5) { (a, b) -> String in
print("执行尾随闭包1")
return "\(a) + \(b) = \(a + b)"
}
//或者
PlusNumbersDescription(num1: 6, num2: 6) {
print("执行尾随闭包2")
return "\($0) + \($1) = \($0 + $1)"
}
运行结果:
执行定义好的闭包
description返回的内容是:4 + 4 = 8
执行尾随闭包1
description返回的内容是:5 + 5 = 10
执行尾随闭包2
description返回的内容是:6 + 6 = 12
4.捕获值
函数和闭包都是引用类型!
闭包可以在其定义的上下文中捕获常量或变量。
例如:
/*
由于闭包定义和变量counter在同一作用域中,
故闭包可以根据上下文语境捕获并访问变量counter。
对变量counter做的任何改变,对闭包来说都是透明可见的。
*/
var count: Int = 0
let increaseCounter = {() -> Int in
count += 1
return count
}
print(increaseCounter()) //1
print(increaseCounter()) //2
print(increaseCounter()) //3
即使定义这些常量和变量的原域已经不存在,闭包仍然可以在闭包函数体内引用和修改这些值。
例如:
/*
函数和闭包都是引用类型
无论您将函数/闭包赋值给一个常量还是变量,实际上都是将常量/变量的值设置为对应函数/闭包的引用
上面的例子中,increaseCounter指向闭包的引用是一个常量,而并非闭包内容本身。
意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包
*/
func makeIncreasementor(forIncreasement amount: Int) -> () -> Int{
var counter: Int = 0
let increase = {() -> Int in
counter += amount
return counter
}
return increase
}
let counter1 = makeIncreasementor(forIncreasement: 10)
print(counter1()) //10
print(counter1()) //20
print(counter1()) //30
print(counter1()) //40
//将一个闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
let counter3 = counter1
print(counter3()) //50
print(counter1()) //60
print(counter3()) //70
//不同的闭包空间(函数实体内)变量各自独立
let counter2 = makeIncreasementor(forIncreasement: 5)
print(counter2()) //5
print(counter2()) //10
print(counter2()) //15
5.闭包表达式
闭包表达式是一种利用简洁语法构建内联闭包的方式。 闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。
sorted 方法
Swift 标准库提供了名为 sorted(by:) 的方法,会根据您提供的用于排序的闭包函数将已知类型数组中的值进行排序。
排序完成后,sorted(by:) 方法会返回一个与原数组大小相同,包含同类型元素且元素已正确排序的新数组。原数组不会被 sorted(by:) 方法修改。
sorted(by:)方法需要传入两个参数:
- 已知类型的数组
- 闭包函数,该闭包函数需要传入与数组元素类型相同的两个值,并返回一个布尔类型值来表明当排序结束后传入的第一个参数排在第二个参数前面还是后面。如果第一个参数值出现在第二个参数值前面,排序闭包函数需要返回 true,反之返回 false。
实例:
let mixArray = [3,6,1,6,2,10];
let mixArray2 = ["BB", "DDD", "A", "CCCC"];
let sorted1 = mixArray.sorted() //系统默认排序规则对整数数组排序
let sorted2 = mixArray2.sorted() //系统默认排序规则对字符数组排序
print(sorted1)
print(sorted2)
let sortedClosure: (String, String) -> Bool = {$0.count > $1.count} //自定义闭包 定义排序规则
let sorted3 = mixArray2.sorted(by: sortedClosure) //非尾随闭包的方式
let sorted4 = mixArray2.sorted { (a, b) -> Bool in //尾随闭包的方式
a.count<b.count
}
//其它方式
// let sorted4 = names.sorted( by: { $0 > $1 } ) //简化闭包
// let sorted4 = names.sorted(by: >) //运算符函数的方式
print(sorted3)
print(sorted4)
运行结果:
[1, 2, 3, 6, 6, 10]
["A", "BB", "CCCC", "DDD"]
["CCCC", "DDD", "BB", "A"]
["A", "BB", "DDD", "CCCC"]
Swift函数
Swift 函数用来完成特定任务的独立的代码块。
Swift使用一个统一的语法来表示简单的C语言风格的函数到复杂的Objective-C语言风格的方法。
-
函数声明: 告诉编译器函数的名字,返回类型及参数。
-
函数定义: 提供了函数的实体。
Swift 函数包含了参数类型及返回值类型
函数定义
Swift 定义函数使用关键字 func。
定义函数的时候,可以指定一个或多个输入参数和一个返回值类型。
每个函数都有一个函数名来描述它的功能。通过函数名以及对应类型的参数值来调用这个函数。函数的参数传递的顺序必须与参数列表相同。
函数的实参传递的顺序必须与形参列表相同,-> 后定义函数的返回值类型。
语法
func funcname(形参列表) -> returntype
{
Statement1
Statement2
……
Statement N
return parameters
}
元组作为函数返回值
函数返回值类型可以是字符串,整型,浮点型等。
元组与数组类似,不同的是,元组中的元素可以是任意类型,使用的是圆括号。
你可以用元组(tuple)类型让多个值作为一个复合值从函数中返回。
func getMaxAndMinValueFrom(array nums: [Int]) -> (Max: Int, Min: Int)?{
var MinValue: Int = nums[0]
var MaxValue: Int = nums[0]
for value in nums[0..<nums.count] {
if MinValue > value {
MinValue = value
}else if MaxValue < value {
MaxValue = value
}
}
return (MaxValue, MinValue)
}
let numsArray = [1,2,3,4,5,6,7,8]
if let result = getMaxAndMinValueFrom(array: numsArray) {
print("maxValue:\(result.Max), minValue:\(result.Min)")
}
输出结果:
maxValue:8, minValue:1
注意
可选元组类型如(Int, Int)?与元组包含可选类型如(Int?, Int?)是不同的.可选的元组类型,整个元组是可选的,而不只是元组中的每个元素值。
内部参数名及外部参数名
你可以在局部参数名前指定外部参数名,中间以空格分隔,外部参数名用于在函数调用时传递给函数的参数。
func funcName(外部参数名 内部参数名:参数类型) -> 返回值类型{
statements
return parameters
}
注意
如果你提供了外部参数名,那么函数在被调用时,必须使用外部参数名。
调用隐藏参数
外部参数或内部参数前面加_和空格 即_ 外部参数、_ 内部参数,在函数调用时会隐藏外部参数提示
可变参数
可变参数可以接受零个或多个值。函数调用时,你可以用可变参数来指定函数参数
其数量是不确定的。可变参数通过在变量类型名后面加入(…)的方式来定义。
func varaableParameters<T>(array: T...){
for item in array {
print(item)
}
}
func vareableParas(numbers: Int...){
var result = 0;
for item in numbers {
result += item
}
print(result)
}
varaableParameters(array: 3,4,5,6)
varaableParameters(array: "hello","world")
vareableParas(numbers: 5,5,5,5)
输出结果
3
4
5
6
hello
world
20
常量,变量及 I/O 参数
一般默认在函数中定义的参数都是常量参数,也就是这个参数你只可以查询使用,不能改变它的值。
如果想要声明一个变量参数,可以在参数定义前加 inout 关键字,这样就可以改变这个参数的值了。
一般默认的参数传递都是传值调用的,而不是传引用。所以传入的参数在函数内改变,并不影响原来的那个参数。传入的只是这个参数的副本。
当传入的参数作为输入输出参数时,需要在参数名前加 & 符,表示这个值可以被函数修改。
func swapTwoNumbers(_ a: inout Int, _ b: inout Int){
let temporaryA = a
a = b
b = temporaryA
}
var x = 5
var y = 6
swapTwoNumbers(&x, &y)
print("x:\(x) y:\(y)")
func mergeString(_ string: inout String){
string += "拼接了一段字符串。"
}
var string = "待拼接的字符串,"
mergeString(&string)
print(string)
输出结果:
x:6 y:5
待拼接的字符串,拼接了一段字符串。
函数类型及使用
每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成。
在 Swift 中,使用函数类型就像使用其他类型一样。例如,你可以定义一个类型为函数的常量或变量,并将适当的函数赋值给它:
func SumWithTwoNumber( num1: Int, num2: Int){
let result = num1 + num2
print(result)
}
let sumFunc: (Int, Int) -> Void = SumWithTwoNumber(num1:num2:)
sumFunc(10, 20) //输出30
函数类型作为参数类型、函数类型作为返回类型
//函数1
func SumWithTwoNumber(num1: Int, num2: Int){
let result = num1 + num2
print(result)
}
//函数类型
let sumFunc: (Int, Int) -> Void = SumWithTwoNumber(num1:num2:)
//函数2,将函数1作为参数
func DealWithFuncAndParameter(functon: (Int, Int) -> Void, num1: Int, Num2: Int){
functon(num1, Num2)
}
//调用函数2
DealWithFuncAndParameter(functon: sumFunc, num1: 20, Num2: 30)
函数的嵌套使用
函数嵌套指的是函数内定义一个新的函数,外部的函数可以调用函数内定义的函数。
func functionReturnFuncton(_ num1: Int, _ num2: Int) -> (Int) -> Int{
let plus = num1 + num2
func realPlusNumber(num: Int) -> Int{
return plus * num1 * num2 * num
}
return realPlusNumber(num:)
}
let functon1 = functionReturnFuncton(10, 10)
print(functon1(5))
输出结果:
10000
返回数据类型可以是函数也可以是闭包,用闭包实现同样功能
func FuncReturnBiBao(_ num1: Int, _ num2: Int) -> (Int) -> Int{
let plus = num1 + num2
let biBao: (Int) -> Int = {number in
number * plus * num1 * num2
}
return biBao
}
let function2 = FuncReturnBiBao(10, 10)
print(function2(5))
输出结果:
10000