类与结构体区别
类是引用类型。是对当前存储具体 实例内存地址的引用。
结构体是值类型,存储的就是具体的实例
引用类型和值类型最大的区别就是存储的位置不同:一般情况,值类型存储的在栈上,引用类型存储在堆上, 堆区比栈区效率低一些,尽量使用结构体
栈区(stack): 局部变量和函数运行过程中的上下文
Heap: 存储所有对象
Global: 存储全局变量;常量;代码区
栈区先进后出方式存储,堆区:在堆区查找一块和存储对象同样大小的空间并放入其中,释放时需要查找存储对象的内存地址。堆区比栈区多一些查找步骤,堆区比栈区效率低一些
内存优化,堆区储存改为栈区储存
示例1:
enum Color { case blue, green, gray }
enum Orientation { case left, right }
enum Tail { case none, tail, bubble }
var cache = [String : UIImage]()
func makeBalloon(_ balloon: String) -> UIImage {
if let image = cache[balloon] {
return image
}
}
makeBalloon('color:\(Color.blue)Orientation:\(orientation.left)tail:\(Tail.none)')
cache一个Key类型是String的字典,String类型是堆区储存
将Key类型改为enum, enum是栈区储存
enum Color { case blue, green, gray }
enum Orientation { case left, right }
enum Tail { case none, tail, bubble }
var cache = [Balloon : UIImage]()
func makeBalloon(_ balloon: Balloon) -> UIImage? {
if let image = cache[balloon] {
return image
}
return nil
}
struct Balloon: Hashable {
var color: Color
var orientation: Orientation
var tail: Tail
}
makeBalloon(Balloon(color: Color.blue, orientation: Orientation.left, tail: Tail.bubble))
示例2: 实例model
struct Attachment {
let fileURL: URL
let uuid: String
let mineType: String
}
String类型是堆区储存,修改成值类型
struct Attachment {
let fileURL: URL
let uuid: UUID
let mineType: String
}
enum MineType: String {
case jpeg = "image/jpeg"
}
类和结构体的内存结构
p 和 po 的区别在于使用 po 只会输出对应的值,而 p 则会返回值的类型以及命令结果
的引用名。
x/8g: 读取内存中的值(8g: 8字节格式输出)
frame varibale -L xxx 查看类和结构体的内存结构
struct/class LGTeacher {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
}
Swift 对象内存分配
class LGTeacher {
var age: Int
var name: String
init(age: Int, name: String) {
self.age = age
self.name = name
}
}
类调试
1.切换成汇编调试 Debug->Debug workflow->Always show Disassembly
2.在super.viewDidLoad() 断点
LGTeacher.__allocating_init(age: Swift.Int, name: Swift.String)调用
3.__allocating_init断点
__allocating_init -----> swift_allocObject -----> _swift_allocObject_ ----->
swift_slowAlloc -----> Malloc
Swift 对象的内存结构:
struct HeapObject{
var metadata: UnsafeRawPointer
var refcounted1: UInt32
var refcounted2: UInt32
}
struct Metadata{
var kind: Int
var superClass: Any.Type
var cacheData: (Int, Int)
var data: Int
var classFlags: Int32
var instanceAddressPoint: UInt32
var instanceSize: UInt32
var instanceAlignmentMask: UInt16
var reserved: UInt16
var classSize: UInt32
var classAddressPoint: UInt32
var typeDescriptor: UnsafeMutableRawPointer
var iVarDestroyer: UnsafeRawPointer
}
替换LGTeacher示例对象的内存结构为 自定义的结构
let t = LGTeacher(age: 18, name: "Tom")
let objcRawPtr = Unmanaged.passUnretained(t as AnyObject).toOpaque()
let objcPtr = objcRawPtr.bindMemory(to: HeapObject.self
, capacity:1)
print(objcPtr.pointee)
let metadata = objcPtr.pointee.metadata.bindMemory(to: Metadata.self, capacity: MemoryLayout<Metadata>.stride).pointee
print(metadata)
Swift 对象的内存结构 HeapObject (OC objc_object) ,有两个属性: 一个是Metadata ,一个是 RefCount