基本数据类型
数值类型
整数
- Swift提供了一个额外的整数类型: Int 它拥有与当前平台的原生字相同的长度 (根据32位和64位的系统转化出对应位数的Int,和NSInteger类似),同样的Swift也提供了UInt类型,来表示平台长度相关的无符号整数。
- 建议在用到整数的地方都使用Int,保证了长度 Int的安全性
浮点数
- Double: 64位浮点数,至少有15位数字的精度 8个字节
- Float: 32位浮点数,至少有6位数字的精度 4个字节
- 在两种类型都可以的情况下,推荐使用Double类型,保证数字范围的安全性
数值范围
这里补充一点在OC中没有Bool类型,OC中的Bool类型是unsigned char类型占用一个字节
再补充一点 iOS 中 NSInteger是一个有符号整数类型,其大小取决于运行平台的架构
- 32位系统
NSInteger 占用4字节(32位),与int的大小相同
- 64位系统
NSInteger 占用8字节(64位),与long的大小相同
NSInteger的定义<Foundation/NSObjcRuntime.h>中
objectivec
#if __LP64__ || TARGET_OS_WIN64
typedef long NSInteger;
#else
typedef int NSInteger;
#endif
Swift中的数值范围
Swift中后面的数字表示了其所占位数的大小,UInt与Int分别表示的是有符号与无符号的Int
类型别名
- 类型别名是一个为已存在类型定义的一个可选择的名字
- 你可以使用关键字typealias定义一个类型的别名
- 当你想通过在一个在上下文中看起来更适合可具有表达性的名字来引用一个已存在的类型时,这时别名就非常有用了
swift
typealias AudioSample = UInt8
let sample: AudioSample = 32
Tuple类型
- 元组把多个值合并成单一的复合型的值
- 元组内的值可以是任何类型,并且可以不必是同一类型
swift
let error = (1, "没有权限")
print(error.0)
print(error.1)
print(error.self)
- 元组中的每一个元素可以指定对应的元素名称
- 如果没有指定名称的元素也可以使用下标的方式来引用
swift
let error = (errorCode:1, errorMessage: "没有权限")
print(error.errorCode)
print(error.errorMessage)
- 用var定义的元组就是可变元组,let定义的就是不可变元组
- 不管是可变还是不可变元组,元组在创建后就不能增加和删除元素
- 可以对可变元组的元素进行修改,但是不能改变其类型
- any类型可以改为任何类型
Tuple可以作为函数的返回值,作为函数返回值的时候可以返回多个值,方便操作函数的返回值
- 使用Tuple为函数返回多个值
- 返回值的Tuple可以在函数的返回类型部分被命名 (作为返回值的时候,可以将返回值的tuple中的参数进行命名)
swift
func writeToFile(content: String) -> (errorCode: Int, errorMessage: String) {
return (1, "没有权限")
}
Optional类型
为什么需要Optional
-
Objective-C 里面的nil是无类型的指针
-
Objective-C 里面的数组、字典、集合等都不允许放nil
-
Objective-C 所有对象变量都可以为nil
-
Objective-C 只能用在对象上,而在其他地方又用其他特殊值(例如NSNotFound)表示值的缺失
-
通过在变量类型后面加上?表示
-
这里有一个值,他等于x
或者
-
这里根本没有值
-
可选类型
- 可以给可选变量赋值一个nil来将之设置为没有值
- 在Objective-C中nil是一个指向不存在对象的指针
- 在Swift中,nil不是指针,他是值缺失的一种特殊类型,任何类型的可选值都可以设置成nil而不仅仅是对象类型
Optional-If语句以及强制展开
- 可选项是没法直接使用的
- 需要用!展开之后才能使用(意思是我知道这个可选值里边有值)
swift
var str: String? = "abc"
if str != nil {
let count = str!.count
print(count)
}
Optional 强制展开
使用!来获取一个不存在的可选值会导致运行错误,在使用!强制展开之前必须确保可选项中包含一个非nil的值
swift
var str: String?
let count = str!.count // 会产生Crash
Optional 绑定
- 可以使用可选项绑定来判断可选项是否包含值,如果包含就把值赋给你个临时变量或者常量
- 可选绑定可以与if 和 while的语句使用来检查可选项内部的值,并赋值给变量或者常量
- 同一个if语句中包含多可选项绑定,用逗号分隔即可,如果任一可选绑定结果是nil或者布尔值为false,那么整个if判断会被看做false
swift
var str: String? = "abc"
if let actualStr = str {
let count = actualStr.count
print(count)
}
Optional 隐式展开
- 有些可选项一旦被设定值之后就会一直拥有值,在这种情况相爱,就可以去掉检查的需求,也不必每次访问的都进行展开
- 通过在声明的类型后边添加一个!(String!)而非问号(?)来书写隐式展开可选项
- 隐式展开可选项主要被用在Swift类的初始化过程中
swift
var str: String! = "abc"
let count = str.count
print(count)
初始化的时候使用
Optional可选链
- 可选项后面加问号
- 如果可选项不为nil,返回一个可选项结果,否则返回nil
swift
var str: String? = "abc"
let count = str?.count
if count != nil {
let index = count! - 1
print(index)
}
- 可选项使用方式 总结
- if 判断 强制展开 !
- 绑定 if let 绑定解开
- 隐式展开 声明的时候使用 ! 在变量初始化环节,或者判断一个变量肯定有值后, 不想后面的步骤再做判断
- 可选链 然后还是1 2 3 三种方式 只不过中间的过程变成了可选链的调用
Optional 实现探究
- Optional 其实是标准库中的一个enum类型
- 用标准库实现语言特性的典型
- Optional.none 就是nil
- Optional.some则是包装了实际的值
swift
var str: Optional<String> = "abc"
if let actualStr = str {
let count = actualStr.count
print(count)
}
!的实现是unsafelyUnwrapped实现的,其为Optional的泛型属性
理论上我们可以直接调用unsafelyUnwrapped获取可选项的值
swift
var str: String? = "abc"
let count = str.unsafelyUnwrapped.count
print(count)
// unsafelyUnwrapped 其实就是 ! 拆包
String类型
- 字面量
- 初始化器语法
- isEmpty 检查是否空串
swift
var emptyString = ""
var anotherEmptyString = String()
if emptryString.isEmpty {
print("Nothing to see here")
}
多行字面量
- 多行字符串字面量是用三个双引号引起来的一系列字符
- 多行字符串字面量把所有行包括在引号内,开始和结束默认不会有换行符
- 当你的代码中在多行字符串字面量里面包含了换行,那个换行符同样会成为字符串里的值,如果你想要使用换行符来让你的代码易读,却不像让换行符成为字符串中的值,那就在那些行的末尾使用反斜杠()
字符串里面的特殊字符
- 转义特殊字符 \0 (空字符) \(反斜杠) \t(水平制表符) \n (换行符) \r(回车符) \"(双引号)以及\'(单引号)
- 任意的Unicode标量,写作\u{n},里面的n是一个1-8位的16进制数字,其值是合法的unicode值
- 可以在多行字符串字面量中包含双引号(")而不需要转义,要在多行字符串中包含文本""",转义至少一个双引号
swift
let text = """
This is a multiline string.
It contains a triple quote: \"""
And it continues here.
"""
print(text)
扩展字符串分隔符 raw string
- 在字符串字面量中放置扩展分隔符来在字符串中包含特殊字符串而不让他们真的生效
- 把字符串放在双引号内并由井号包裹
- 如果字符串里有#则首位需要两个##
- 如果你需要字符串中某个特殊符号的效果,使用匹配你包裹的井号数量的井号并在前面写转义符
其实就是将""中的""不生效前面加#来做区分,同时让转义符不生效 如果想生效的话使用转义字符并匹配对应的#
字符串的可变性
- var指定的可以修改
- let指定的不可修改
- 对比Objective-C (NSString和NSMutableString)
字符串插值
- 字符串插值是一种从混合常量、变量、字面量和表示式的字符串字面量构造新String值的方式
- 每一个你插入到字符串字面量的元素都要被一对圆括号包裹,然后使用反斜杠作为前缀
- 类似于NSString的stringWithFormat方法,但是更加简便更加强大
swift
let multipiler = 3
let message = "\(mulipiler) times 2.5 is \(Double(multiplier) * 2.5)"
- 可以在扩展字符串分隔符中创建一个包含在其他情况下会被当做字符串插值的字符
- 要在使用扩展分隔符的字符串中使用字符串插值,在反斜杠后使用匹配首尾井号数量的井号
String是值类型 其实Swift中基础数据类型都是值类型的
字符串索引
-
每一个String值都有相关的索引类型,String.Index,它相当于每个Character在字符串中的位置
-
startIndex属性来访问String中第一个Character的位置,endIndex属性就是String中最后一个字符后的位置(访问的话需要使用endIndex - 1)
-
endIndex属性并不是字符串下标脚本的合法实际参数
-
如果String为空,则startIndex与endIndex相等
-
使用index(before:) 和 index(after:)方法来访问给定索引的前后
-
要访问给定索引更远的索引,可以使用index(_:offsetBy:)
-
使用indices属性来访问字符串中每个字符的索引
swift
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]
插入
- 插入字符,使用insert(_:at:) 方法
- 插入另一个字符串的内容到特定的索引,使用Insert(contentsOf:at:)方法
删除
- 移除字符 使用remove(at:)方法
- 移除一小段特定范围的字符串,使用removeSubrange(_:)方法
子字符串
- 使用下标或者类似prefix(_:)的方式得到的子字符串是Substring类型
- Substring拥有String的大部分方法
- Substring可以转化为String类型
index(of: ) 查询对应字符在index中的位置 index
- 子字符串重用一部分原字符串的内存
- 修改字符串或者子字符串之前都不需要花费拷贝内存的代价
- String和Substring都遵循StringProtocol协议,也就是说他基本上能很方便地兼容所有接受StringProtocol值的字符串操作函数
字符串的比较
- 字符串和字符串相等性 (== 和 ≠)
- 前缀相等性 hasPrefix(_ :)
- 后缀相等性 hasSuffix(_ :)
swift
var welcome = "hello world"
var welcome1 = "hello"
print(welcome == welcome1)
print(welcome.hasPrefix("hello"))
print(welcome.hasSuffix("world"))