Swift基本数据类型
声明常量和变量
- 使用关键字let来声明常量
- 使用关键字var来声明变量
- 可以在一行中声明多个变量或常量,用逗号分割
var x=0.0,y=0.0,z=0.0
类型标注
- 在声明一个变量或常量的时候提供类型标注,来明确变量或常量能够储存值的类型
- 添加类型标注,是在变量或常量的名字后加冒号,再加一个空格,最后加类型名称
- 一行中定义多个变量以及类型标注,用逗号分割
变量和常量命名
- 变量和常量的名字几乎可以使用任何字符,甚至包括Unicode字符
- 变量和常量的名字不能包含空白字符、数学符号、箭头、保留的(或者无效的)Unicode码位、连线和制表符。也不能以数字开头。
打印常量和变量
- print(_:separator:terminator:)
- 字符串插值
整数
- Swift提供了8,16,32和64位编码的有符号和无符号整数
- 命名方式:8位UInt8,16位UInt16,32位的有整数的Int32
- min,max访问整数的最小最大值
- Int,32位为32位,64位平台为64
- UInt无符号的
- 建议使用Int
浮点类型
- Double: 64位,至少15位精度
- Float: 32位,至少6位精度
- 推荐用Double
数值范围
Bool
- Bool: true和false
- Swift的类型安全,非Bool值无法替换Bool值
类型别名
typealias AudioSample = UInt8
let sample: AudioSample = 32
Tuple分解
- 元祖的内容分解成单独的常量或变量
- 不需要的数据用下划线(_)代替
例如:
let error = (1,"没有权限");
let (errCode,errMessage) = error;
print(errCode)
print(errMessage)
print(error.0)
print(error.1)
let error = (errorCode:1,errorMessage:"没有权限")
print(error.errorCode)
print(error.errorMessage)
//元祖可以修改
var verror = (errorCode:1,errorMessage:"没有权限")
verror.errorCode = 2;
print(verror)
// 输出结果errorCode=2
// 元祖可以定义类型
var error: (errorCode:Int,errorMessage:Any) = (errorCode:1,errorMessage:"没有权限")
元祖可以作为函数返回值
fun writeFile(content: String) -> (errorCode:Int,errorMessage:String){
return (1,"没有权限")
}
let error = writeFile(conten:"")
print(error)
Optional
- OC中的nil是无类型的指针
- OC中的数组、字典、集合不允许放入nil
- OC所有对象变量都可以为nil
- OC中nil只能用在对象上,而在其他地方用其他特殊值(如NSNotFound),表示值的缺失
- OC中nil是一个指向不存在对象的指针
- SWift中,nil不是指针,它是值缺失的一种类型,任何类型的可选项都可以设置成nil而不仅仅是对象类型
- 可选项无法直接使用
- 使用!强制展开,如果为nil强制展开则报错
- 可选项可以与if和while进行绑定
- 隐式展开主要用在Swift类的初始化中
// 隐式展开
var str: String! = "abc"
let count = str.count
print(count)
Optional-可选链
- 可选项后面加问号
- 如果可选项不为nil,返回一个可选项结果,否则返回nil
let str: String? = "abc"
if let actualStr = str {
let count = actualStr.count
print(count)
}
// 强制展开 如果str为nil则报错
let count = str!.count
// 强制展开
let count = str?.count
if count != nil {
let lastIndex = count! - 1
print(lastIndex)
}
Optional实现探究
- Optional是标准库里的一个enum类型
- 用标准库实现语言特性的典型
- Optional.none就是nil
- Optional.some包装实际值
- 泛型属性 unsafelyUnwrapped
let str: Optional<String> = "abc"
if let actualStr = str {
let count = actualStr.count
print(count)
}
if str != nil {
let count = str.unsafelyUnwrapped.count
print(count)
}
String
- 字面量
- 初始化器语法
- isEmpty检查是否为空串
var emptyString = ""
var anotherEmptyString = String()
if emptyString.isEmpty {
print("Nothing to see here")
}
字面量
- 字符串字面量是被双引号("),包裹鹅固定顺序文本字符
- Swift会为str常量推断类型为String
let str = "some string"
多行字面量
- 是用三个双引号引起来的一系列字符
- 所有行包括在引号内,开始和结束默认没有换行符
- 多行字面量,有换行,末尾使用斜杠()增加可读性
- 要让多行字符串字面量起始或结束于换行,就在第一或最后一行写一个空行
- 多行字符串可以缩进以匹配周围的代码。双引号(""")前的空格会告诉Swift其他行前应该有多少空白是需要忽略的
- 如果在某行的空格超过了结束的双引号("""),那么这些空格会被包含
字符串里的特殊字符
- 转义特殊字符\0(空字符),\(反斜杠),\t(水平制表符),\n(换行符),\r(回车符),"(双引号)以及'(单引号)
- 任意的Unicode标量,写作\u{n},里边的n是一个1-8位的16进制数字,其值是合法Unicode值
- 可以在多行字符串字面量中包含双引号(")而不需转义。要在多行字符串中包含文本""",转义至少一个双引号
扩展字符串分割符(Raw String)
- 在字符串字面量中放置扩展分隔符来在字符串中包含特殊字符而不让他们真的生效
- 把字符串放在双引号(")内并由(#)包裹
- 如果字符串里有"#则首尾需要两个##
- 如果需要字符串中某个特殊符号的效果,使用匹配包裹#号数量的井号并在前面写转义符号\
字符串的可变性
- var指定的可以修改
- let指定的不可修改
- 对比OC(NSString和NSMutableString)
var variableString = "Horse"
variableString += " and carriage"
// variableString is now "Horse and carriage"
let constantString = "HighLander"
constantString += " and another Highlander"
// this reports a compile-time error - a constant string cannot be modified
字符串是值类型
- String值在传递给方法或者函数的时候会被复制过去
- 赋值给常量或者变量的时候也是一样
- Swift编译器优化了字符串使用,只在用到时才拷贝
操作字符
- for-in循环遍历String中的每一个独立的Character
- Character类型
- String值可以通过传入Character数组来构造
字符串拼接
- 使用加运算符(+)创建新字符串
- 使用加赋值符号(+=)在已经存在的String值末尾加一个String值
- 使用String类型的append()方法给String变量的末尾加Character值
字符串插值
- 字符串插值是一种从混合常量、变量、字面量和表达式的字符串自卖你两构造新String值的方法
- 每一个你插入到字符串字面量的元素都要被一堆圆括号包裹,然后使用反斜杠前缀
- 类似于NSString的stringWithFormat 方法,但是更加简便,更强大
let multiplier = 3
let message = "\(multiplier) times 2.5 is \(Double(multiplier)*2.5)"
- 可以在扩展字符串分隔符中创建一个包含在其他情况下会被当作字符串插值的字符
- 扩展分隔符的字符串中使用字符串插值,在反斜杠后使用匹配首尾井号数量的井号
print(#"Write an interpolated string in Swift using \(multiplier)."#)
// "Write an interpolated string in Swift using\\(multiplier)"
print(#"6 times 7 is \#(6*7)."#)
// "6 times 7 is 42.\n"
字符串索引
- 每一个String值都有相关的索引类型,String.index,它相当于每个Character在字符串中的位置
- startIndex属性来访问Strin中第一个Character的位置。endIndex属性就是String中最后一个字符串的位置
- endIndex属性并不是字符串下标脚本的合法设计参数
- 如果String为空,则startIndex与endIndex相等
let greeting = "Guan Tag!"
greeting[greeting.startIndex] // "G"
使用index(befote:)和index(after:)方法来访问给定索引的前后 要访问给定索引更远的索引,可以使用index(_:offsetBy:) 使用indices属性来访问字符串中每个字符的索引
let greeting = "Guten Tag!"
greeting[greeting.startIndex]
greeting[greeting.index(before:greeting.endIndex)]
greeting[greeting.index(before:greeting.startIndex)]
let index = greeting.index(greeting.startIndex,offsetBy:7)
greeting[index] // "a"
插入
- 插入字符,使用insert(_:at)方法
- 插入另一个字符串的内容到特定的索引,使用insert(contentsOf:at:)方法
var welcome = "hello"
welcome.insert("!",at:welcome.endIndex)
welcome.insert(contentsOf:" there",at:welcome.index(before:welcome.endIndex))
// 输出位 ”hello there!“
删除
- 移除字符,使用remove(at:)方法
- 移除一小段特定范围的字符串,使用removeSubrange(_:)方法
welcome.remove(at:welcome.index(before:welcome.endIndex))
print(welcome)
let range = welcome.index(welcome.endIndex,offsetBy:-6)..<welcome.endIndex
welcome.removeSubrange(range)
print(welcome)
子字符串
- 使用下标或者类似prefix(_:)的方法得到的子字符串是Substring类型
- Substring拥有String的大部分方法
- Substring可以转成String类型
let greeting = "Hello,world!"
let index = greeting.index(of:",") ?? greeting.endIndex
let beginning = greeting[..<index]
let newString = String(beginning)
- 子字符串重用一部分原字符串的内存
- 修改字符串或者子字符串之前都不需要花费拷贝内存的代价
- String和Substring都遵循StringProtocol协议,也就是说它基本上能很方便地兼容所有接受StringProtocol值的字符串操作函数
字符串比较
- 字符串和字符相等性(==和!=)
- 前缀相等性hasPrefix(_:)
- 后缀相等性hasSuffix(_:)
var vwelcome = "hello,world"
var welcome1 = "hello"
print(welcome == welcome1) // false
print(welcome.hasPrefix("hello")) // true
print(welcome.hasSuffix("world")) // true