一、可选型
为什么会有可选型?当一个变量被希望表示为某一个指定的类型值,同时也被希望在某种情况下表示为空。那么就需要一个可选型。Optional
可选型的语法是在Swift的基本类型后面添加 ? 符号,如 Int? String? 可选型如果取值为空,那么表示为 nil
如果想定义一个可选型的变量,那么需要显示的声明为可选型。可选型变量打印时显示Optional
可选型变量需要进行解包(unwrap)才能与其他的变量进行运算。
解包:
1. 强制解包,使用 ! 关键字,强制解包是具有风险的,当可选型变量的值为nil时,会报致命错误fatal error
2. 在条件判断语句中进行解包,定义一个新的变量并且将可选型变量赋值给它。如 if let op1 = op1{ } if var op1 = op1{}
但是这样定义的新变量仅仅只在if语句块中有效。其他地方无效并没有这个变量。
1 var errorCode: Int? = 404;
2 var errorMsg: String? = "not found";
3 if var errorCode = errorCode,
4 var errorMsg = errorMsg{
5 print(errorMsg);
6 }
swift3.0版本中,if语句里的条件判断语句不能使用where关键字,而是使用逗号 , 来将多个条件进行分割,同时使用, 逗号保证了所有的条件之间是一种逻辑与 & 的关系
3. optional chaining
使用语法 ? 来尝试解包,可以省略掉大段的 if 语句代码
1 var str: String? = "Swift Optional";
2 str?.uppercased()
1 var msg1 = errorMsg==nil ?"NO Error":errorMsg;
2 var msg2 = errorMsg ?? "No Error";
??也可以用来对可选型变量进行解包 Nil-Coalesce
** 可选型是一个重要的类型
很多方法都会返回可选型类型的结果,如 Int的构造函数, StringObj.range(of: str)
返回Range<String.Index>?
*** 隐式可选型
语法 var str: String! = nil;
var str: String! = "Hello, Swift";
在类的定义中运用广泛,以后讨论。
二、数组
数组的类型声明有两种形式:
[Int]方括号里面存放的是数组中数据的类型
Array<Int> 泛型的写法,这种写法和C#中的泛型是一样的,<>中存放的就是数组中数据的类型
所以由此可见,swift中的数组里的每一个成员的数据类型必须一致,并且数组的语法格式和大多数语言一样,都是使用[ ]一对中括号将数据包裹起来。
1 var numbers1:[Int] = [1,2,3,4,5];
2 var numbers2:Array<Int> = [10,11,12,13,14];
3 var letters1:[String] = ["a", "b", "c", "d", "e" ];
4 var letters2:Array<Character> =["x", "y", "z"];
定义空数组: []直接定义空数组,但是必须要求显示声明数组类型; 使用数组的构造函数进行空数组的声明,此时可以不用显示声明数据类型。
1 var empty1: [Int] = [];
2 var empty2: Array<String> = [];
3 var empty3: [Float] = [Float]();
4 var empty4: [(Int,Int)] = [(Int,Int)]();
5 var empty5: [(Int,Int?)] = Array<(Int,Int?)>();
6 var empty6: [(Int,Int?)?] = Array<(Int,Int?)?>();
数组的一种初始化构造函数:通过给定的长度和一个数据来创建一个具有给定长度的重复值的数组,此时可以不用显示声明数组类型。
1 var arr1 = Array(repeating: "4.5", count: 5);
** 数组的常用成员属性和方法
isEmpty count first last contains() index(of: ) index(after: ) index(before: ) startIndex endIndex max() min()
*** 数组的比较
在Swift语言中,数组是一个有序的数据集合。同时数组的比较是值比较,而不是引用比较。
****** 数组的遍历
1 //第一种遍历,将索引值进行循环
2 var arr = [1,2,3,4,5];
3 for index in 0..<arr.count{
4 index;
5 arr[index];
6 }
7 //第二种遍历,将数组值进行循环
8 for number in arr{
9 number;
10 }
11 //第三种遍历,通过可枚举接口方法获取一个可枚举的结构体
12 for (index, number) in arr.enumerated(){
13 index;
14 number;
15 }
以上都是数组的查(查找),接着我们来学习 增(增加), 删(删除), 改(修改)
* 增
数组方法: += 这里需要注意类型一致,数组只能和数组相加 append insert
1 var cousre = ["JavaScript","NodeJS","Vue"];
2 cousre.append("CSS3");
3 course.append(contentsOf: ["HTML","CSS"]);
1 course.insert("JavaScript", at: 4);
2 course.insert(contentsOf: ["CSS3","NodeJS"], at: 2);
* 删
数组方法: remove removeAll removeLast removeFirst removeSubrange
remove方法需要指定删除项的索引值
removeLast和removeFirst如果传入索引值参数,表示从开头或者从末尾处开始,指定索引处往后或者往前的内容都会被删除。
* 改
修改数组,可以直接使用索引方括号的形式进行修改数据值即可。
***** 二维数组
类型定义 Array<Array<Int>> [ [Int] ] Array<[Int]> [Array<Int>]
二维数组的方法与一维数组是一致的,同样 += 需要注意二维数组只能与二维数组进行相加运算。
NSArray
提到Swift数组,就不能不提到NSArray。 在Swift3.0版本中,不指定类型的数组默认情况下已经都是Array类型了,不同于2.0版本还在使用NSArray默认类型。
那么如果需要使用NSArray,就必须显示声明NSArray类型,或者 as NSArray语法。
NSArray不同于Array的区别在于NSArray可以将不同类型的数据放到一个数组中。
在Swift3.0版本中,要么使用显示声明为NSArray,要么使用显示声明为NSObject,要么不声明而是将数组中的每一个值as NSObject转换为NSObject类型
三、Dictionary字典
字典是一组键值对的无序集合,所以字典的比较也是值比较,但是注意是无序的。同时字典的键名是具有唯一性的。
字典的类型声明 Dictionary<String, String> [String : String]
空字典的声明 [:] Dictionary<String, String>() [String: String]()
dic.keys dic.values 都是LazyMapCollection<Dictionary<String,String>,String>
dic.count dic.isEmpty
1 var edic1:[String:String] = [:];
2 var edic2:Dictionary<String,String> = [:];
3 var edic3 = [String:String]();
4 var edic4 = Dictionary<String,String>();
1 Array(dic.keys);
2 Array(dic.values);
3 //字典的遍历
4 //键名的遍历
5 for key in dic.keys{
6 print(key);
7 }
8 //键值的遍历
9 for value in dic.values{
10 print(value);
11 }
12 //键值对的遍历
13 for (key,value) in dic{
14 print(key);
15 print(value);
16 }
字典的增删改查方法: 使用键名的方式来增加,修改或删除某个值 updateValue(value, forKey: key); removeAll(); removeValue(forKey: key);
四、集合Set
集合Set的类型声明: Set<Int>
1 var set : Set<Int> = [1,2,6,4,3,5,8];
2 var empty1 = Set<Int>();
3 var empty2: Set<String> = [];
4 var empty3: Set<Int> = Set();
属性与方法: count isEmpty first contains() removeAll() remove() removeFirst()
***** for in语句可以遍历 Range, Characters, Array, Dictionary, Set.
可以发现,凡是符合一个序列特性的类型值都是可以使用for in语句进行循环遍历,String类型就不符合序列Sequence所以不能使用for in.
五、函数
函数的定义语法,以func关键字开头, 返回值使用 -> 形式表示。如果函数没有返回值,可以不写 -> ,也可以写成 -> () 或者 -> Void
1 //函数定义语法
2 //func funcName(arg1: type, arg2 : type, ...) -> type {
3 // return .....;
4 //}
5
6 func sayHelloTo(name: String?) -> String{
7 return "Say Hello to " + (name?.uppercased() ?? "Guest" );
8 }
9
10 sayHelloTo(name : "Jordan mike");
函数的返回值是元组类型时,可以返回多个返回值
1 func findMaxAndMin(numbers: Array<Int>)->(max: Int, min: Int)?{
2 guard numbers.count > 0 else {
3 return nil;
4 }
5 var minNumber = numbers[0];
6 var maxNumber = numbers[0];
7 for number in numbers{
8 maxNumber = number > maxNumber ? number : maxNumber;
9 minNumber = number < minNumber ? number : minNumber;
10 }
11 return (maxNumber, minNumber);
12 }
swift语言中的 外部参数名,内部参数名,调用时省略参数名
默认情况下,内部和外部参数名是一致的。
如果需要指定外部参数名,可以在参数名前面再添加一个参数名。这样前面的是外部参数名,后面的是内部参数名。
如果需要省略调用函数时的外部参数名,需要将外部参数名定义为下划线 _
1 func speakTo(name: String, words: String)->String{
2 return name + "Speak some words: " + words;
3 }
4
5 speakTo(name: "tom", words: "I love you");
6
7 func speak(to name: String, letters words: String)->String{
8 return name + "Speak some words: " + words;
9 }
10
11 speak(to: "nike", letters: "I love football");
12
13 func say(_ name: String, _ words: String)->String{
14 return name + "Speak some words: " + words;
15 }
16
17 say("andi", "I love you! ");
定义函数时,可以给函数中的参数定义默认值,这样在调用函数时可以省掉该参数,从而采用默认值进行函数调用。
定义函数时,可以给函数定义可变参数,语法是在参数类型后面加上 ... 但是在一个函数中最多只能有一个可变参数。与其他语言不同的是,swift语言并没有强制要求可变参数的位置必须是最后一个参数。
在Swift3.0版本中,函数参数前面关键字只能使用默认的let 以及 inout引用类型参数,默认情况下函数的形参都是值传入方式,同时在函数内部是不允许对该参数进行重新赋值计算的。在swift2.0版本中定义了var 关键字,但是在3.0版本中却将这个语法取消了。兼容方式是在函数内部重新定义一个同名的var变量。 如果你希望函数调用时使用引用传递的方式,那么需要在该形参冒号后面,也就是参数类型前面添加关键字 inout ,同时在函数调用时使用&语法。 可以通过swap函数进行理解。
函数类型也是一种变量类型,可以用来实现所谓的委托。参考Array的sort, sorted, map, filter, reduce等方法。这里需要注意的是swift2.0版本中的sort与sortInPlace在新版中已经被修改了。
****函数闭包 closure
1 //Trailing closure
2 var arr = [1,11,22,12,32,31,18];
3 arr.sort(by: {(a:Int, b:Int)->Bool in return a<b;});
4 arr.sort(by: {a,b in return a<b;});
5 arr.sort(by: {a,b in a<b;});
6 arr.sort(by: {$0<$1;});
7 arr.sort(by: <);
***** 闭包和函数都是引用类型,而基本类型数组集合字典都是值类型