内容简介: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.
即 NSPointerArray
比普通的 NSArray
多了一层内存语义。可以更方便的控制其中元素的引用关系,但少了 Swift 中着重强调的类型安全,所以更推荐第一种做法。
Extension
其实不只是数组,集合类型的数据结构对其中的元素默认均是强引用。所以为了更加方便地自定义内存管理方式,Objective-C/Swift 中均有普通类型的对应。但在目前的 Swift 中, NSHashTable
和 NSMapTable
均需要指定类型,更加的类型安全(在网上的过时资料中可以看出,之前的 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 中对集合类型元素的弱引用》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:- 读 Zepto 源码之集合元素查找
- 读 Zepto 源码之集合元素查找
- 图解集合 5 :不正确地使用HashMap引发死循环及元素丢失
- CSS 基础:块级元素、行内元素、替换元素、非替换元素
- CSS 技巧篇(六):display设置元素为行内元素时,元素之间存在间隙问题
- 探究行内元素和块级元素
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Persuasive Technology
B.J. Fogg / Morgan Kaufmann / 2002-12 / USD 39.95
Can computers change what you think and do? Can they motivate you to stop smoking, persuade you to buy insurance, or convince you to join the Army? "Yes, they can," says Dr. B.J. Fogg, directo......一起来看看 《Persuasive Technology》 这本书的介绍吧!