Swift笔记(三)
字符串和字符(String and Character)
Swift的String类型和Foundation的NSString类进行了无缝桥接,所有NSString API都可以调用Swift的String类型的值
字符串字面量(String Literals)
字符串字面量是由双引号(“”)包裹的具有固定顺序的文本字符集
字符串字面量可以包含以下特殊字符:
- 转义字符\0(空字符)、\(反斜线)、\t(水平制表符)、\n(换行符)、\r(回车符)、"(双引号)、'(单引号)
- 单字节 Unicode 标量,写成\xnn,其中nn为两位十六进制数
- 双字节 Unicode 标量,写成\unnnn,其中nnnn为四位十六进制数
- 四字节 Unicode 标量,写成\Unnnnnnnn,其中nnnnnnnn为八位十六进制数
初始化空字符串
1 | var emptyString = "" |
字符串可变性(String Mutability)
可以通过分配一个变量来对字符串进行修改,或者分配一个常量保证其不被修改
字符串是值类型
String类型进行常量、变量赋值操作或在函数\方法中传递,会进行拷贝,是值传递
字符
Swift的String类型表示特定序列的character类型值的集合
1 | for character in "Hello world"} |
可以表明Character类型来创建字符常量或者变量
1 | let a:Character = "1" |
计算字符数量
通过调用全局的countElement函数,并将字符串作为参数传递,可以获取字符串的字符数量
1 | let str = "I have a word" |
连接字符串和字符
使用+相加就可以连接字符串
使用+=可以讲一个字符串加上另一个字符串存到原有的字符串上
字符串插值
字符串插值是一种构建新字符串的方式,可以在其中包含常量、变量、字面量和表达式
1 | \(Double(3) * 2.5) // "7.5" |
比较字符串
Swift 提供了三种方式来比较字符串的值:字符串相等、前缀相等和后缀相等。
字符串相等
1 | let str = "一样样的" |
大写和小写字符串
通过字符串的uppercaseString和lowercaseString属性来方位大写/小写版本的字符串
Unicode
Unicode是一个国际标准,用于文本的编码和表示。
每一个字符都可以被Unicode解释成一个或多个unicode标量。字符的unicode标量是一个唯一的21位数字,例如U+0061表示小写的拉丁字母a
当Unicode字符串被写进文本文件或其他存储结构当中,这些unicode标量将会按照Unicode定义的集中格式之一进行编码,其中包括UTF-8(以8位代码单元进行编码)和UTF-16(以16位代码单元进行编码)
字符串的Unicode表示
Swift提供了几种不同的方法来访问字符串的Unicode
- UTF-8 代码单元集合 (利用字符串的utf8属性进行访问)
- UTF-16 代码单元集合 (利用字符串的utf16属性进行访问)
- 21位的 Unicode 标量值集合 (利用字符串的unicodeScalars属性进行访问)
utfb属性其为UTF8View类型的属性,是无符号8位(UInt)值的集合,同理utf16属性是UTF16View类型的属性
1 | let dogString "Dog!" |
Unicode标量
unocodeScalars属性为UnicodeScalarView类型的属性,是UnicodeScalar的集合,UnicodeScalar是21位的 Unicode 代码点。
1 | for scale in dogString.unicodeScalars { |
集合类型(Collection Types)
数组
数组使用有序列表存储同一类型的多个值,相同的值可以多次出现在一个数组的不同位置中
在Swift中。数据值在被存储进入某个数组之前类型必须明确,方法是通过显示的类型标注或类型推断,Swift的数组是类型安全的,并且它包含的类型必须明确,这点和NSArray和NSMutableArray很不同。
数组的简单语法
数组遵循Array<SomeType>这样的形式,其中SomeType是这个数组中唯一允许存在的数据类型。也可以使用像SomeType[]这样的简单语法。
数组构造语句
形如[value1,value2,value3]
1 | var names:String[] = ["joy","jack"] |
变量被声明为字符串类型的数组
由于Swift的类型推断机制,也可以这样写
1 | var names = ["jay","jack"] |
访问和修改数组
可以通过数组的方法和属性来访问和修改数组,或者下表语法。还可以使用数组的只读属性count来获取数组中的数据数量,使用isEmpty属性可以检测数组是否为空,使用append方法在数组后面添加新的数据项,也可以使用(+=)添加单个数据项或者拥有相同数据类型的数组
也可以通过索引获取数组项
1 | var names = ["joy","jack"] |
调用insert(atIndex:)可以再在指定位置插入数据,removeAtIndex方法可以移除数组中的某一项,removeLast方法可以移除最后一项
数组的遍历
使用for-in循环来遍历所有数组中的数据项
1 | for item in shoppingList{ |
也可以使用全局enumerate函数来进行数组遍历
1 | for (index,value) in enumerate(shoppingList) { |
创建或构造一个数组
1 | var someInts = Int[]() |
字典
字典是一种存储多个相同类型的值的容器,没个值都关联唯一的键,键作为字典中的这个值数据的标识符。字典的数据项没有具体的顺序,需要通过键访问数据。
与Objective-C中的NSDictionary和NSMutableDictionary类可以使用任何类型的对象做键和值不同,Swift在某个特定字典中可以存储的键和值必须提前定义,方法是通过显式标注或者类型推断
Swift的字典可以使用Dictionary<KeyType,ValueType>定义,其中keyType是键的数据类型,ValueType是值的数据类型。keyType的唯一限制是可哈希的,这样可以保证它的唯一性,所有Swift的基本类型(String,Int,Double和Bool)都是可哈希的,未关联的枚举成员也是可哈希的。
字典字面量
[key1:value1,key2:value2,key3:value3]可以创建字典
1 | var airports:Dictionary<String,String> = ["TYO":"Tokyo","DUB":"Dublin"] |
读取和修改字典
使用下标语法或者字典的方法属性可以读取字典,只读属性count来获取字典的数据项的数量
也可以使用下标法添加新的数据项updateValue(forkey:)方法可以设置或更新特定键对应的值,根据键值是否存在判断。该函数会返回包含一个字典值类型的可选值
1 | airports["LHR"] = "London Heathrow" // 添加数据项 |
使用下标法也可以访问对应键的值,如果不存在,返回nil,通过下标法设置某键的值为nil,也可以删除数据项,也可以使用removeValueForKey方法移除
1 | if let removedValue = airports.removeValueForKey("DUB"){ |
字典遍历
使用for-in语法便可遍历,每一个字典的数据项都由(key,value)元组形式返回
1 | for (airportCode,airportName) in airport { |
也可以访问它的keys和values属性检索一个字典的键或者值
1 | for airportCode in airports.keys { |
创建字典
创建空字典
1 | var nameOfIntegers = Dictionary<Int,String>() |
集合的可变性
如果数组或字典设置为变量,那么它的数据项是可变的,设置为常量,那么它的大小是不可变的,数据在首次设定之后便不能改变。不同的是,数组的大小不能改变,但是可以改变它的值。
控制流
For循环
for循环用作按照指定的次数多次执行一系列语句。Swift提供了两种for循环形式:
for-in用来遍历一个区间(range),序列(sequence),集合(collection),系列(progression)里面多有的元素- for条件递增(
for-condition-increment)语句,用来重复执行一系列语句知道达到特定条件,一般通过在每次循环完成后增加计数器的值来实现。
For-In
1 | // index不需要声明 |
如果不需要知道区间每一项的值,可以使用下划线(_)替代变量名忽略对值的访问
1 | for _ in 1...9{ |
For条件递增(for-condition-increment)
1 | for var index = 0; index < 3;++index{ |
下面是一般情况下这种循环方式的格式:
for
initialization;condition;increment{
statements
}
While循环
while循环运行一系列语句直到条件变成false。这类循环适合使用在第一次迭代前迭代次数未知的情况下。Swift 提供两种while循环形式:
- while循环,每次在循环开始时计算条件是否符合;
- do-while循环,每次在循环结束时计算条件是否符合。
一般格式如下:
1 | while condition{ |
条件语句
Swift提供两种类型的条件语句:if语句和switch语句。通常,当条件较为简单且可能的情况很少时,使用if语句。而switch语句更适用于条件较复杂、可能情况较多且需要用到模式匹配(pattern-matching)的情境。
If
if语句最简单的形式就是只包含一个条件,当且仅当该条件为true时,才执行相关代码:
1 | if true { |
Switch
switch语句会尝试把某个值与若干个模式(pattern)进行匹配。根据第一个匹配成功的模式,switch语句会执行对应的代码。
1 | witch some value to consider { |
swift不存在隐藏的贯穿,即不需要break,执行完也会推出,同时swift还支持区间匹配
1 | switch count{ |
元组匹配
1 | var count = (1,3) |
值绑定
case分支的模式允许将匹配的值绑定到一个临时的常量或变量,这些变量或常量在该case分支里就可以被引用————这种行为被称为值绑定
1 | let point = (2,0) |
Where
case分支模式可以使用where语句来判断额外的条件
1 | let point = (1,0) |
控制转移语句(Control Transfer Statements)
控制转移语句改变你代码的执行顺序,通过它你可以实现代码的跳转。Swift有四种控制转移语句。- continue
- break
- fallthrough
- return
Continue
continue语句告诉一个循环体立刻停止本次循环迭代,重新开始下次循环迭代。
Break
break语句会立刻结束整个控制流的执行。
贯穿(Fallthrough)
Swift不存在C语言中switch语句的贯穿行为,要实现需要使用fallthrouth
1 | switch count{ |
带标签的语句(Labeled Statements)
环体和switch代码块两者都可以使用break语句来提前结束整个方法体,通过带标签的语句可以指定想要终止哪个循环或者switch代码块,如果有许多嵌套的循环体,也可以实现continue指定跳转
1 | label name:while condition{ |
1 | loop:while count != 100{ |
函数(Functions)
函数的定义与调用(Defining and Calling Functions)
1 | func sayHello(personName:String) -> String{ |
函数参数与返回值(Function Parameters and Return Values)
- 多个参数
1 | func fun(start: Int,end: Int) -> Int { |
- 无参
1 | func say() -> String{ |
- 无返回值
1 | func sayGoodbye(personName: String){ |
- 多返回值
// 计算一个字符串中元音、辅音和其他字母的个数
1 | func count(str:String) -> (vowels: Int, consonants: Int,others: Int) { |
函数参数名称
在函数定义时定义的参数为局部参数名,只能在函数体中使用
外部函数名
类似于Objective-C的函数命名
1 | func join(string s1:String,toString s2:String) -> String{ |
简写外部参数名
上面的方法需要为参数提供外部参数名和内部参数名,可以通过# 简写,将外部参数名和内部参数名等同起来
1 | func join(# string:String,# toString:String) -> String{ |
默认参数值
为参数提供一个初始值,调用时,缺省可以忽略并使用默认值
1 | func join(str1 String,str2 String = "world") -> String{ |
可变参数
1 | func add (numbers: Double...) -> Double { |
常量参数和变量参数
函数参数默认是常量,在函数体中更改参数值将会导致编译错误,如果参数定义为变量就可以当做参数的副本来使用
1 | // 用来右对齐输入的字符串到一个长的输出字符串中。左侧空余的地方用指定的填充字符填充 |
输入输出参数
一个输入输出参数时,在参数定义前加inout关键字。一个输入输出参数有传入函数的值,这个值被函数修改,然后被传出函数,替换原来的值。当传入的参数作为输入输出参数时,需要在参数前加&符,表示这个值可以被函数修改。
1 | func swap (inout a:Int,inout b:Int){ |
函数类型
每个函数都有种特定的函数类型,由函数的参数类型和返回类型组成。() -> ()表示没用参数,返回Void,在Swift中,Void与空元组是一样的
使用函数类型
使用函数名来给另一个函数赋值
1 | var fun2:(Int,Int) -> Int = fun1 |
使用函数类型
1 | var mathFunction:(Int,Int) -> Int = addTwoInts |
函数类型作为参数类型
1 | func printMathResult(matchFunction:(Int,Int) -> Int,a:Int,b:Int){ |
函数类型作为返回类型
1 | func chooseStepFunction(backwards:Bool) -> (Int) -> Int { |
闭包
闭包之自包含的函数代码块,可以在代码中传递和使用,与Objective-C的blocks相似
闭包可以捕获和存储其所在上下文任意常量和变量的引用。
全局和嵌套函数也是特殊的闭包,闭包采取如下三种形式:
- 全局函数是一个有名字但不会捕获任何值的闭包
- 嵌套函数是一个有名字并可以捕获其封闭函数内值的闭包
- 闭包表达式是一个利用轻量级语法所写的可以捕获其上下文中变量或常量值的匿名闭包
闭包表达式(Closure Expreessions)
闭包表达式是一种利用简洁语法构建内联闭包的方式,闭包表达式提供了一些语法优化,使得撰写闭包变得简单明了。
闭包表达式语法
闭包表带式语法一般形式:
1 | { (parameters) -> returnType in |
Swift标准库提供了sort函数,会根据基于输出类型排序的闭包函数将已知类型数组的值进行排序,返回一个与原数组大小相同的新数组,并排序完成。

