let weakPencilBox1 = WeakArray([pencil2B, pencilHB])
CFGetRetainCount(pencil2B as CFTypeRef)
CFGetRetainCount(pencilHB as CFTypeRef)
// 3 3
let firstElement = weakPencilBox1.filter { $0 != nil }.first
firstElement!!.type
// 2B
CFGetRetainCount(pencil2B as CFTypeRef)
CFGetRetainCount(pencilHB as CFTypeRef)
// 4 3 Note: 这里的 4 是因为 firstElement 持有(Retain)了 pencil2B,导致其引用计数增 1
NSPointerArray
let weakPencilBox2 = NSPointerArray.weakObjects()
let pencil2BPoiter = Unmanaged.passUnretained(pencil2B).toOpaque()
let pencilHBPoiter = Unmanaged.passUnretained(pencilHB).toOpaque()
CFGetRetainCount(pencil2B as CFTypeRef)
CFGetRetainCount(pencilHB as CFTypeRef)
// 4 3
weakPencilBox2.addPointer(pencil2BPoiter)
weakPencilBox2.addPointer(pencilHBPoiter)
CFGetRetainCount(pencil2B as CFTypeRef)
CFGetRetainCount(pencilHB as CFTypeRef)
// 4 3
A collection similar to an array, but with a broader range of available memory semantics.
即 NSPointerArray 比普通的 NSArray 多了一层内存语义。可以更方便的控制其中元素的引用关系,但少了 Swift 中着重强调的类型安全,所以更推荐第一种做法。
Extension
其实不只是数组,集合类型的数据结构对其中的元素默认均是强引用。所以为了更加方便地自定义内存管理方式,Objective-C/Swift 中均有普通类型的对应。但在目前的 Swift 中,NSHashTable 和 NSMapTable 均需要指定类型,更加的类型安全(在网上的过时资料中可以看出,之前的 Swift 也没有规定需指定类型),而在 Objective-C 中只要满足 id 类型即可。
Preface
为了方便下述 Demo,这里定义一个 Pencil 类,并会使用
func CFGetRetainCount(_ cf: CoreFoundation.CFTypeRef!) -> CFIndex
方法,即传入一个CFTypeRef
类型的对象即可获取其引用计数。什么是CFTypeRef
?查阅官方文档即可得知typealias CFTypeRef = AnyObject
,所以CFTypeRef
其实就是AnyObject
。而AnyObject
又是所有类隐含遵守的协议。What
在 Swift 中,当创建一个数组时,数组本身对于添加进去的对象元素默认是强引用(Strong),会使得其引用计数自增。
那么今天的问题即是,如何使得数组本身对数组元素进行弱引用?
How
WeakBox
定义好一个可以将所有类型的对象转化为弱引用的类,再通过构建好的新类型,将每个强引用元素转换为弱引用元素。利用 Extension,还可以遵守协议,扩展一些集合方法。
NSPointerArray
即
NSPointerArray
比普通的NSArray
多了一层内存语义。可以更方便的控制其中元素的引用关系,但少了 Swift 中着重强调的类型安全,所以更推荐第一种做法。Extension
其实不只是数组,集合类型的数据结构对其中的元素默认均是强引用。所以为了更加方便地自定义内存管理方式,Objective-C/Swift 中均有普通类型的对应。但在目前的 Swift 中,
NSHashTable
和NSMapTable
均需要指定类型,更加的类型安全(在网上的过时资料中可以看出,之前的 Swift 也没有规定需指定类型),而在 Objective-C 中只要满足id
类型即可。NSHashTable
:NSMapTable
:Reference