结构体
struct User{
var age:Int
var name:String
var hobby:String
init(age:Int,name:String,hobby:String){
self.age = age
self.name = name
self.hobby = hobby
}
//定义下标
subscript(index:Int) -> String{
get{
switch index{
case 0:
return name
case 1:
return hobby
default:
return "\(index)"
}
}
set(newValue){
switch index{
case 0:
name = newValue
case 1:
hobby = newValue
default:
print(newValue)
}
}
}
}
类
class User{
var age:Int
var name:String
init(age:Int,name:String){
self.age = age
self.name = name
}
deinit{
}
}
类和结构体的相同点
- 都可以定义存储属性
- 都可以定义下标
下标使用subscript修饰,在subscript的实现部分,类似计算属性,需要实现getter方法和可选的setter方法,getter方法用于通过下标取值,setter方法用于通过下标设置值
- 都可以定义方法
- 都定义初始化器
- 都可以使用extension来拓展功能
- 都可以遵循协议来提供某种功能
类和结构体不同点
- 类有继承的特性,而结构体没有
- 类有析构函数用来释放其分配的资源
- 类型转换使能够在运行时检查和解释类实例的类型
- 引用计数允许对一个类实例有多个引用
对象的创建过程
swift对象本质为HeapObject 占用16字节
HeapObject构造函数中有两个参数
1:metadata是HeapMetadata 类型的指针,占8字节
2:通过查找 refCounts 得到它是InlineRefCounts类型,占用8字节
对象内存分配流程
__allocating_init -> swift_allocObject_ -> swift_slowAlloc -> malloc
类和结构体的初始化过程
指定初始化器 便捷初始化器
需要注意一点是:当前类的编译器默认不会自动提供成员初始化器,但是对于结构体来说 编译器会提供默认的初始化方法
struct User{
var age:Int
var name:String
}
class User{
var age:Int
var name:String
init(age:Int,name:String){
self.age = age
self.name = name
}
}
安全检查
1: 指定初始化器必须保证在向上委托给父类初始化器之前,其所在类引入的 所有属性初始化完成
2: 指定初始化器必须先向上委托父类初始化器,然后才能 为继承的属性设置新值,如果不这样做,指定初始化器 赋予的新值将被父类中的初始化器所覆盖
3:便捷初始化器必须先委托同类中的其他初始化器,然后在为任意属性赋新值,如果没这么做,便捷初始化器赋予的新值将被自己类中其他指定初始化器所覆盖
4:初始化器在第一阶段初始化完成之前,不能调用任何 实例方法,不能读取任何实例属性的值,也不能引用self 作为值
class Student:User{
var salary:Int
init(age:Int,name:String,salary:Int){
//对应上面1
self.salary = salary
super.init(age:age,name:name)
//对应上面2
self.name = "学生:" + name
}
convenience init(name:String){
self.init(age:10,name:name,salary:100)
//对应上面3
self.name = name + "学生"
}
}
iOS 内存分布
栈区(stack): 局部变量和函数运行过程中的上下文
Heap: 存储所有对象
Global: 存储全局变量;常量;代码区
LLDB命令 exp var 输出var这个变量的值 exp var = 10 (将var值变成10) frame info 获取当前断点地址、代码行数以及函数的相关参数 rame variable:展示当前作用域下的参数和局部变量