声明常量和变量
使用关键字 let 来声明常量
使用关键字 var 来声明变量
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0
- 可以在一行中声明多个变量或常量,用逗号分隔
var x = 0.0, y = 0.0, z = 0.0
类型标注
在声明一个变量或常量的时候提供类型标注,来明确变量或常量能够储存值的类型
添加类型标书的方法是在变量或者常量的名字后边加一个冒号,在跟一个空格,最后加上要使用的类型名称
可以再一行中定义多个相关的变量为相同的类型,用逗号分隔,只要在最后的变量名字后加上类型标注
var welcomeMessage : String
welcomeMessage = "hello"
welcomeMessage = 10 // Cannot assgin value of type 'Int' to type 'String'
变量和常量命名
常量和变量的名字几乎可以使用任何字符,甚至包括Unicode字符
常量和变量的名字不能包含空白字符、数学符号、箭头、保留的(或者无效的)、Unicode码位、连线和制表符。也不能艺术字开头,尽管数字几乎可以使用在名字其他的任何地方
let π = 3.1415926
let 你好 = "你好世界"
let = "dogcow"
打印常量和变量
print(_:separator:terminator:)
字符串插值
let π = 3.1415926
let 你好 = "你好世界"
print("欢迎语是\(你好)")
整数
Swift提供了8,16,32和64位编码的有符号和无符号整数
命名方式:例如8位无符号的类型是UInt8,32位有符号整数的类型是Int32
通过min和max属性来访问每个整数类型的最小值和最大值
Swift提供了一个额外的整数类型:Int,它拥有与当前平台的原生字相同的的长度
同时Swift也提供了UInt类型,来表示平台长度相关的无符号整数
建议在用到整数的地方都使用Int
浮点类型
Double:64位浮点数,至少有15位数字的精度
Float:32位浮点数,至少有6位数字的精度
在俩种类型都可以的情况下,推荐使用Double类型
Bool
Bool:true 和 false
Swift的类型安全机制会阻止你用一个非布尔变量的值替换掉 Bool
let i = 1
if i {
printf(i)
}
error: 'Int' is not convertible to 'Bool'
正确为:
if i == 1 {
printf(i)
}
类型别名
类型别名是一个位已存在类型定义的可选择的名字
可以关键字
typealias
定义一个类型的别名想通过在一个上下文看起来更合适的可具表达性的名字来引用一个已存在类型时,这时候别名就非常有用了
typealias AudioSample = UInt8
let sample: AudioSample = 32
Tuple
元祖把多个值和成单一的复合型的值
元祖内的值可以是任何类型,而且可以不必是同一类型
let error = (1, "没有权限")
print(error.0)
print(error.1)
- 元组 元素命名
- 元组中的每一个元素可以指定对应元素名称
- 如果没有指定名称的元素也可以使用下标的方式来引用
let error = (errorCode: 1, errorMessage: "没有权限")
print(error.errorCode)
print(error.errorMessage)
Tuple修改
- 用var定义的元组就是可变元组,let定义的就是不可变元组
- 不管是可变还是不可变元组,元组在创建后就不能增加和删除元素
- 可以对可变元组的元素进行修改,但是不能改变其类型
- any类型可以改为任何类型
var error = (errorCode: 1, errorMessage: "没有权限")
error.errorCode = 2
error.errorMessage = "2"
var error:(Any, String)= (1, "没有权限")
error.0 = 2
error.0 = "abc"
Tuple分解
- 以将一个元组的内容分解成单独的常量或变量
- 如果只需要使用其中的一部分数据,不需要的数据可以用下划线(_)代替
let error = (1, "没有权限")
let (errorCode, errorMessage) = error
print(error.errorCode)
print(error.errorMessage)
let error = (1, "没有权限")
let (_, errorMessage) = error
print(error.errorMessage)
作为函数返回值
使用Tuple作为函数返回多个值
返回值Tuple可以再函数的返回类型部分被命名
func writeToFile(content: String) -> (errorCode: Int, errorMessage: String) {
return(1, "没有权限")
}
为什么需要 Optional
Object—C 里的nil是无类型的指针
Object—C 里面的数组、字典、集合等不允许放入nil
Object—C 所有的对象变量都可以为nil
Object—C 只能用在对象上、而在其他地方又用其他特殊值(例如NSNotFound)表示值的缺失
-
通常在变量类型后面加 ? 表示
- 这里有一个值,他等于 x
或者 - 这里根本没有值
- 这里有一个值,他等于 x
-
你可以通过给可选变量赋值一个nil来将之设为没有值
- 在 Object—C 中nil是一个只想不存在对象的指针
- 在Swift中,nil不是指针,他是值缺失的一种特殊类型,任何类型的可选项都可以设置成nil而不仅仅是对象类型
var str: String = nil // 'nil' cannot initalize specified type 'String'
var str1: String? = nil
Optional-If语句以及强制展开
- 可选项是没法直接使用的
- 需要用 ! 展开之后才能使用(意思是我知道这个可选项里边有值,展开吧)
var str: String? = "abc"
let count = str.cont // 报错
var str: String? = "abc"
if str != nil {
let count = str.cont
print(count)
}
- 使用 ! 来获取一个不存在的可选值会导致运行错误,在使用 ! 强制展开之前必须确保可选项中包含一个非nil的值
var str: String?
let count = str!.count // error:Exe...
Optional - 绑定
可以使用可选绑定来判断可选项是否包含之,如果包含就把值赋值给一个临时的常量或者变量
可选绑定可以与if 和 while 的语句使用来检查可选项内部的值,并赋值给一个变量或常量
同一个if语句包含多可选绑定,用逗号分隔即可。如果任一可选绑定结果是nil或者布尔类型值为fasle,那么整个if判断会被看做false
var str: String? = "abc"
if let actualStr = str {
let count = actualStr.count
print(count)
}
Optional-隐式展开
有些可选项一旦被设定值之后,就会一直拥有值,在这种情况下,就可以去掉检查的需求,也不必每次访问的时候都进行展开
通过在声明的类型后边加一个叹号(String!)而非问好(String?)来书写隐式展开可选项
隐式展开可选项主要被用在Swift类的初始化过程中
var str: String! = "abc"
ley count = str.count
Optional-可选链
可选项后面加问号
如果可选项不为nil,返回一个可选项结果,否则返回nil
var str: String? = "abc"
let count = str?.count
let lastIndex = count - 1 //报错
var str: String? = "abc"
let count = str?.count
if count != nil {
let lastIndex = count - 1
}
Optional-实现探究
- Optional其实是标准库里的一个enum类型
- 用标准库实现语言特性的典型
public enum Optional : ExpressibleByNilLiteral {
case none
case some(Wrapped)
public init(_ some: Wrapped)
}
- Optional.none 就是nil
- Optional.some则包装了实际的值
var str: Optional = "abc"
if let actualStr = str{
let count = actualStr.count
print(count)
}
泛型属性 unsafelyUnwrapped
Optional-展开实现
理论上我们可以直接调用 unsafelyUnwrapped 获取可选项的值
var str: String = "abc"
let count = str.unsafelyUnwrapped.count
print(count)
初始化空串
字面量
初始化器语法
isEmpty 检查是否为空串
var emptyString = ""
var anotherEmptyString = String()
if emptyString.isEmpty {
print("Nothing to see here")
}
字面量
字符串字面量是被双引号(")包括的固定顺序文本字符
Swift会为str常量推断类型为String
let str = "Some string"
多行字面量
多行字符串字面量是用三个双引号引起来的一系列字符
多行字符串字面量把所有的包括在引号内,开始和结束默认不会有换行符
当你的代码在多行字符串字面量里面包含了换行,那个换行符同样会成为字符串里面的值。如果你想要使用换行符来让你的代码易读,去不想让换行符成为字符串的值,那就在那些行的末尾使用反斜杠(\)
let softWrappQuotation = """
the white rabbit put on his spectacles
begin at the begining the kind said gravely, and go on
"""
let softWrappQuotation = """
the white rabbit put on his spectacles \
begin at the begining the kind said gravely, and go on \
"""
多行字面量
要让多行字符串字面量其实和技术于换行,就在第一或最后一行写一个空行
多行字符串可以缩进以匹配周围的代码。双引号(""")前的空格会告诉swift其他行前应该有多少空白是需要忽略的
如果你在某行的空格超过了结束的双引号("""),那么这些空格会被包含
let softWrappQuotation = """
the white rabbit put on his spectacles \
begin at the begining the kind said gravely, and go on \
"""
字符串里面的特殊字符
转义特殊字符 \0(空字符) \(反斜杠) \t(水平制表符) \n(换行符) \r(回车符) "(双引号) 以及 '(单引号)
任意的Unicode标量,写作\u{n},里面的n是一个1-8的16进制数字,其值是合法的Unicode值
可以再多行字符串字面量中包含双引号(")而不需要转义。要在多行字符窜中包含文本""",转义至少一个双引号
扩展字符串分隔符(Raw String)
在字符串字面量中放置扩展分隔符在字符串中包含特殊字符而不让它们真的生效
把字符串放在双引号(")内由井号(#)包裹
如果字符里有"#则收尾需要俩个##
如果你需要字符串中某个特殊符号的效果,使用陪陪你包括的井号数量的井号并在前面写转义符号\
字符串的可变性
var 指定的可以修改
let 指定的不可修改
对比Object-C(NSString 和 NSMutableString)
var variableString = "Horse"
variableString += "and carriage"
let contantString = "Highlander"
contantString += "and another Highlander"
// this reports a compelee-time error - a constant string cannot be modified
字符串是值类型
String 值在传递给方法或者函数的时候被复制过去
赋值给常量或者变量的时候也是一样
Swift 编译器优化了字符串使用的资源,实际上拷贝只会在确实需要的时候才进行
var str: String = "abc"
var str1 = str
print(str == str1)
str += "def"
print(str)
print(str1)
print(str == str1)
操作字符
for-in 循环遍历String中的每一个独立的Character
Character类型
String 值可以通过传入Character数组来构造
for character in "dog!" {
prfint(character)
}
字符串拼接
使用加运算符(+)创建新字符串
使用加复制符号(+=)在已经存在的String值末尾追加一个String
使用String类型的append()方法来可以给一个String变量的末尾追加Character值
字符串插值
字符串插值是一种从混合常量、变量、字面量和表达式的字符串字面量构造新String值的方法
每一个你插入到字符串字面量的元素都要被一堆圆括号包过,然后使用反斜杠前缀
类似NSString的stringWithFormat方法,但是更加简便,更强大
let multilier = 3
let message = "\(multilier) times 2.5 is \(Double(multilier) * 2.5)"
- 可以再扩展字符串分隔符中创建一个包含在其他情况下会被当做字符串插值的字符
- 要在使用扩展分隔符的字符串中使用字符串插值,在反斜杠后使用匹配收尾井号数量的井号
print(#"Write an interpolated string in Swift using\(multipier)."#)
print(#"6 times 7 is \#(6 * 7)."#)
字符串索引
每一个String值都有相关的索引类型,String.Index,它相当于每个Character在字符串中的位置
startIndex属性来访问String中第一个Character的位置,endIndex属性就是String中最后一个字符串额位置
endIndex属性并不是字符串下标脚本的合法实际参数
如果String为空,则startIndex与endIndex相等
let greeting = "Guten Tag"
greeting[greeting.startIndex]
let greeting = "Guten Tag"
greeting[1] // subscript(_:) is unavailable: cannot subsript
- 使用index(before:)和index(after:)方法来访问给定索引的前后
- 要访问给定索引更远的索引,你可以使用index(_:offsetBy:)
- 使用indices属性来访问字符串中每个字符的索引
let greeting = "Guten Tag"
greeting[greeting.startIndex]
greeting[greeting.index(before:greeting.endIndex)]
greeting[greeting.index(after:greeting.startIndex)]
let index = greeting.index(greeting.startIndex, offsetBy:7)
greeting[index]
插入
插入字符,使用inser(_:at:)方法
插入另一个字符串的内容到特定的索引,使用insert(contentOf:at:)方法
var welcome = "hello"
welcome.insert("!", at:welcome.endIndex)
welcome.insert(contentsOf:" there", at: welcome.index(before:welcome.endIndex))
删除
移除字符,使用remove(at:)方法
移除一小段特定范围的字符串,使用removeSubrange(_:)方法
子字符串
使用下标或者类似prefix(_:)的方法得到的字符串是Substring类型
Substring拥有String的大部分方法
Substring可以转成String类型
let greeting = "hello world"
let index = greeting.index(of: ",") ?? greeting.endIndex
let begining = greeting[..
子字符串
子字符串重用一部分原字符串的内存
修改字符串或者子字符串之前都不需要话费拷贝内存的代价
String和Substring都遵循StringProtocol协议,也就是说它基本上很方便地兼容所有接受Stringprotocol值的字符串操作函数
字符粗比较
字符串和字符串相等性(== 和 !=)
前缀相等性hasPrefix(:_)
后缀相等性 hasSuffix(:_)
var welcome = "hello world"
var welcome1 = "hello"
print(welcome == welcome1)
print(welcome.hasPrefix("hello"))
print(welcome.hasSuffix("hello"))