Practice - 在 Swift 中对集合类型元素的弱引用

栏目: Swift · 发布时间: 6年前

内容简介:For more, please visit my GitHub repo:为了方便下述 Demo,这里定义一个 Pencil 类,并会使用在 Swift 中,当创建一个数组时,数组本身对于添加进去的对象元素默认是强引用(Strong),会使得其引用计数自增。

For more, please visit my GitHub repo: github.com/kingcos/Per…

Date Notes Swift Xcode
2018-03-15 更新部分表述,并将题目扩展至集合类型 4.0 9.2
2018-03-08 首次提交 4.0 9.2

Preface

为了方便下述 Demo,这里定义一个 Pencil 类,并会使用 func CFGetRetainCount(_ cf: CoreFoundation.CFTypeRef!) -> CFIndex 方法,即传入一个 CFTypeRef 类型的对象即可获取其引用计数。什么是 CFTypeRef ?查阅官方文档即可得知 typealias CFTypeRef = AnyObject ,所以 CFTypeRef 其实就是 AnyObject 。而 AnyObject 又是所有类隐含遵守的协议。

class Pencil {
    var type: String
    var price: Double
    
    init(_ type: String, _ price: Double) {
        self.type = type
        self.price = price
    }
}

CFGetRetainCount(Pencil("2B", 1.0) as CFTypeRef)
// 1

let pencil2B = Pencil("2B", 1.0)
let pencilHB = Pencil("HB", 2.0)

CFGetRetainCount(pencil2B as CFTypeRef)
CFGetRetainCount(pencilHB as CFTypeRef)
// 2 2
复制代码

What

在 Swift 中,当创建一个数组时,数组本身对于添加进去的对象元素默认是强引用(Strong),会使得其引用计数自增。

let pencilBox = [pencil2B, pencilHB]

CFGetRetainCount(pencil2B as CFTypeRef)
CFGetRetainCount(pencilHB as CFTypeRef)
// 3 3
复制代码

那么今天的问题即是,如何使得数组本身对数组元素进行弱引用?

How

WeakBox

final class WeakBox<A: AnyObject> {
    weak var unbox: A?
    init(_ value: A) {
        unbox = value
    }
}

struct WeakArray<Element: AnyObject> {
    private var items: [WeakBox<Element>] = []
    
    init(_ elements: [Element]) {
        items = elements.map { WeakBox($0) }
    }
}

extension WeakArray: Collection {
    var startIndex: Int { return items.startIndex }
    var endIndex: Int { return items.endIndex }
    
    subscript(_ index: Int) -> Element? {
        return items[index].unbox
    }
    
    func index(after idx: Int) -> Int {
        return items.index(after: idx)
    }
}
复制代码

定义好一个可以将所有类型的对象转化为弱引用的类,再通过构建好的新类型,将每个强引用元素转换为弱引用元素。利用 Extension,还可以遵守协议,扩展一些集合方法。

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.

Apple Documentation

NSPointerArray 比普通的 NSArray 多了一层内存语义。可以更方便的控制其中元素的引用关系,但少了 Swift 中着重强调的类型安全,所以更推荐第一种做法。

Extension

其实不只是数组,集合类型的数据结构对其中的元素默认均是强引用。所以为了更加方便地自定义内存管理方式,Objective-C/Swift 中均有普通类型的对应。但在目前的 Swift 中, NSHashTableNSMapTable 均需要指定类型,更加的类型安全(在网上的过时资料中可以看出,之前的 Swift 也没有规定需指定类型),而在 Objective-C 中只要满足 id 类型即可。

  • NSHashTable :
// NSHashTable - NSSet
let weakPencilSet = NSHashTable<Pencil>(options: .weakMemory)

weakPencilSet.add(pencil2B)
weakPencilSet.add(pencilHB)
复制代码
  • NSMapTable :
// NSMapTable - NSDictionary
class Eraser {
    var type: String
    
    init(_ type: String) {
        self.type = type
    }
}

let weakPencilDict = NSMapTable<Eraser, Pencil>(keyOptions: .strongMemory, valueOptions: .weakMemory)
let paintingEraser = Eraser("Painting")

weakPencilDict.setObject(pencil2B, forKey: paintingEraser)
复制代码
  • Objective-C:
NSHashTable *set = [NSHashTable hashTableWithOptions:NSPointerFunctionsWeakMemory];
[set addObject:@"Test"];
[set addObject:@12];
复制代码

也欢迎您关注我的微博@萌面大道V

Reference


以上所述就是小编给大家介绍的《Practice - 在 Swift 中对集合类型元素的弱引用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

游戏编程中的人工智能技术

游戏编程中的人工智能技术

布克兰德 / 吴祖增 / 清华大学出版社 / 2006-5 / 39.0

《游戏编程中的人工智能技术》是人工智能游戏编程的一本指南性读物,介绍在游戏开发中怎样应用遗传算法和人工神经网络来创建电脑游戏中所需要的人工智能。书中包含了许多实用例子,所有例子的完整源码和可执行程序都能在随书附带的光盘上找到。光盘中还有不少其他方面的游戏开发资料和一个赛车游戏演示软件。 《游戏编程中的人工智能技术》适合遗传算法和人工神经网络等人工智能技术的各行业人员,特别是要实际动手做应用开......一起来看看 《游戏编程中的人工智能技术》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码