Swift类与结构体

165 阅读3分钟

结构体

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方法用于通过下标设置值

类和结构体不同点

  • 类有继承的特性,而结构体没有
  • 类有析构函数用来释放其分配的资源
  • 类型转换使能够在运行时检查和解释类实例的类型
  • 引用计数允许对一个类实例有多个引用

对象的创建过程

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 内存分布

截屏2021-12-26 21.07.12.png

栈区(stack): 局部变量和函数运行过程中的上下文

Heap: 存储所有对象

Global: 存储全局变量;常量;代码区

LLDB命令 exp var 输出var这个变量的值 exp var = 10 (将var值变成10) frame info 获取当前断点地址、代码行数以及函数的相关参数 rame variable:展示当前作用域下的参数和局部变量