我想在Swift中存储一个弱引用数组。数组本身不应该是弱引用——它的元素应该是。我认为Cocoa NSPointerArray提供了一个非类型安全的版本。
当前回答
在很多情况下,返回一个可取消的选项会更简洁。这允许调用站点决定何时显式地销毁值(以及通过解压缩隐式地销毁值):
public protocol Cancellable {
func cancel()
}
private struct MyValue: Identifiable {
let id: String
// ...
}
private class CancellationHandler: Cancellable {
let handler: () -> ()
init(handler: @escaping () -> ()) { self.handler = handler }
func cancel() { handler() }
deinit { handler() }
}
public class Container {
private var array = [MyType]()
public func add() -> Cancellable {
let value = MyValue(...)
array.append(value)
return CancellationHandler {
array.removeFirst(where: { $0.id == value.id })
}
}
}
let cancellable = container.add()
// Both cancellable.cancel() and the cancellable descoping
// will call the `cancel` function, removing the value from array.
其他回答
创建一个通用包装器,如下:
class Weak<T: AnyObject> {
weak var value : T?
init (value: T) {
self.value = value
}
}
将该类的实例添加到数组中。
class Stuff {}
var weakly : [Weak<Stuff>] = [Weak(value: Stuff()), Weak(value: Stuff())]
定义Weak时,可以使用struct或class。
同样,为了帮助获取数组内容,你可以做一些如下的事情:
extension Array where Element:Weak<AnyObject> {
mutating func reap () {
self = self.filter { nil != $0.value }
}
}
上面使用的AnyObject应该替换为T -但我不认为当前的Swift语言允许这样定义扩展。
可以通过创建包装器对象来保存弱指针来实现这一点。
struct WeakThing<T: AnyObject> {
weak var value: T?
init (value: T) {
self.value = value
}
}
然后在数组中使用这些
var weakThings = WeakThing<Foo>[]()
这不是我的解决方案。我是在苹果开发者论坛上找到它的。
@GoZoner有一个很好的答案,但它崩溃了Swift编译器。
下面是一个弱对象容器的版本,它不会使当前发布的编译器崩溃。
struct WeakContainer<T where T: AnyObject> {
weak var _value : T?
init (value: T) {
_value = value
}
func get() -> T? {
return _value
}
}
然后你可以创建一个这些容器的数组:
let myArray: Array<WeakContainer<MyClass>> = [myObject1, myObject2]
同样的问题还有另一种解决方案……它的重点是存储对对象的弱引用,但也允许存储结构。
[我不确定它有多有用,但它确实花了一段时间来纠正语法]
class WeakWrapper : Equatable {
var valueAny : Any?
weak var value : AnyObject?
init(value: Any) {
if let valueObj = value as? AnyObject {
self.value = valueObj
} else {
self.valueAny = value
}
}
func recall() -> Any? {
if let value = value {
return value
} else if let value = valueAny {
return value
}
return nil
}
}
func ==(lhs: WeakWrapper, rhs: WeakWrapper) -> Bool {
return ObjectIdentifier(lhs) == ObjectIdentifier(rhs)
}
class Stuff {}
var weakArray : [WeakWrapper] = [WeakWrapper(value: Stuff()), WeakWrapper(value: CGRectZero)]
extension Array where Element : WeakWrapper {
mutating func removeObject(object: Element) {
if let index = self.indexOf(object) {
self.removeAtIndex(index)
}
}
mutating func compress() {
for obj in self {
if obj.recall() == nil {
self.removeObject(obj)
}
}
}
}
weakArray[0].recall()
weakArray[1].recall() == nil
weakArray.compress()
weakArray.count
可以围绕Array创建包装器。或者使用这个库https://github.com/NickRybalko/WeakPointerArray let array =弱指针数组<AnyObject>() 它是类型安全的。
推荐文章
- 如何删除默认的导航栏空间在SwiftUI导航视图
- 如何在iOS中使用Swift编程segue
- Swift -整数转换为小时/分钟/秒
- 如何舍入一个双到最近的Int在迅速?
- 扁平化数组的数组在Swift
- Swift:声明一个空字典
- 为什么ARC仍然需要@autoreleasepool ?
- 从数组中随机选择一个元素
- Java:强/软/弱/幻影引用的区别
- 在Swift中如何调用GCD主线程上的参数方法?
- swift语言中的结构与类
- 我如何在Swift连接字符串?
- 我应该如何从字符串中删除所有的前导空格?- - - - - -斯威夫特
- 新的自动引用计数机制是如何工作的?
- Swift:理解// MARK