1. 程式人生 > >swift class type isa-swizzling

swift class type isa-swizzling

類型 class heap 靜態 sun unsafe ack capacity nat

class 是引用類型,生成的實例分布在 Heap(堆) 內存區域上,在 Stack(棧)只存放著一個指向堆中實例的指針。因為考慮到引用類型的動態性和 ARC 的原因,class 類型實例需要有一塊單獨區域存儲類型信息和引用計數。

在 Swift 中,class 類型的方法派發是通過 V-Table 來實現動態派發的。Swift 會為每一種類類型生成一個 Type 信息並放在靜態內存區域中,而每個類類型實例的 type 指針就指向靜態內存區域中本類型的 Type 信息。當某個類實例調用方法的時候,首先會通過該實例的 type 指針找到該類型的 Type 信息,然後通過信息中的 V-Table 得到方法的地址,並跳轉到相應的方法的實現地址去執行方法。

通過上面的分析,我們知道一個類類型的方法派發是通過頭部的 type 指針來決定的,如果我們將某個類實例的 type 指針指向另一個 type 會不會有什麽好玩的事情發生呢?哈哈 ~ 一起來試試 ~

class Wolf {

var name: String = "wolf"

func soul() {

print("my soul is wolf")

}

func headPointerOfClass() -> UnsafeMutablePointer<Int8> {

let opaquePointer = Unmanaged.passUnretained(self as AnyObject).toOpaque()

let mutableTypedPointer = opaquePointer.bindMemory(to: Int8.self, capacity: MemoryLayout<Wolf>.stride)

return UnsafeMutablePointer<Int8>(mutableTypedPointer)

}

}

class Fox {

var name: String = "fox"

func soul() {

print("my soul is fox")

}

func headPointerOfClass() -> UnsafeMutablePointer<Int8> {

let opaquePointer = Unmanaged.passUnretained(self as AnyObject).toOpaque()

let mutableTypedPointer = opaquePointer.bindMemory(to: Int8.self, capacity: MemoryLayout<Fox>.stride)

return UnsafeMutablePointer<Int8>(mutableTypedPointer)

}

}

let wolf = Wolf()

var wolfPtr = UnsafeMutableRawPointer(wolf.headPointerOfClass())

let fox = Fox()

var foxPtr = UnsafeMutableRawPointer(fox.headPointerOfClass())

foxPtr.advanced(by: 0).bindMemory(to: UnsafeMutablePointer<Wolf.Type>.self, capacity: 1).initialize(to: wolfPtr.advanced(by: 0).assumingMemoryBound(to: UnsafeMutablePointer<Wolf.Type>.self).pointee)

print(type(of: fox)) //Wolf

print(fox.name) //"fox"

fox.soul()

https://mp.weixin.qq.com/s/zIkB9KnAt1YPWGOOwyqY3Q

swift class type isa-swizzling