Swiftに一連の弱い参照を格納したいと思います。配列自体は弱参照であってはなりません-その要素は弱参照であるべきです。 Cocoa NSPointerArray
は、このタイプセーフでないバージョンを提供すると思います。
次のように汎用ラッパーを作成します。
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言語ではそのように定義された拡張が許可されていないと思います。
NSHashTableはweakObjectsHashTableで使用できます。 NSHashTable.weakObjectsHashTable()
Swift 3の場合:NSHashTable.weakObjects()
OS X v10.5以降で使用できます。
IOS 6.0以降で利用可能。
パーティーには少し遅れていますが、試してみてください。配列ではなくセットとして実装しました。
class WeakObject<T: AnyObject>: Equatable, Hashable {
weak var object: T?
init(object: T) {
self.object = object
}
var hashValue: Int {
if let object = self.object { return unsafeAddressOf(object).hashValue }
else { return 0 }
}
}
func == <T> (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
return lhs.object === rhs.object
}
class WeakObjectSet<T: AnyObject> {
var objects: Set<WeakObject<T>>
init() {
self.objects = Set<WeakObject<T>>([])
}
init(objects: [T]) {
self.objects = Set<WeakObject<T>>(objects.map { WeakObject(object: $0) })
}
var allObjects: [T] {
return objects.flatMap { $0.object }
}
func contains(object: T) -> Bool {
return self.objects.contains(WeakObject(object: object))
}
func addObject(object: T) {
self.objects.unionInPlace([WeakObject(object: object)])
}
func addObjects(objects: [T]) {
self.objects.unionInPlace(objects.map { WeakObject(object: $0) })
}
}
var alice: NSString? = "Alice"
var bob: NSString? = "Bob"
var cathline: NSString? = "Cathline"
var persons = WeakObjectSet<NSString>()
persons.addObject(bob!)
print(persons.allObjects) // [Bob]
persons.addObject(bob!)
print(persons.allObjects) // [Bob]
persons.addObjects([alice!, cathline!])
print(persons.allObjects) // [Alice, Cathline, Bob]
alice = nil
print(persons.allObjects) // [Cathline, Bob]
bob = nil
print(persons.allObjects) // [Cathline]
WeakObjectSetはString型ではなくNSString型を取ることに注意してください。なぜなら、文字列型はAnyTypeではないからです。私のSwiftバージョンはApple Swift version 2.2 (swiftlang-703.0.18.1 clang-703.0.29)
です。
コードはGistから取得できます。 https://Gist.github.com/codelynx/30d3c42a833321f17d39
** 2017年11月に追加
コードをSwift 4に更新しました
// Swift 4, Xcode Version 9.1 (9B55)
class WeakObject<T: AnyObject>: Equatable, Hashable {
weak var object: T?
init(object: T) {
self.object = object
}
var hashValue: Int {
if var object = object { return UnsafeMutablePointer<T>(&object).hashValue }
return 0
}
static func == (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
return lhs.object === rhs.object
}
}
class WeakObjectSet<T: AnyObject> {
var objects: Set<WeakObject<T>>
init() {
self.objects = Set<WeakObject<T>>([])
}
init(objects: [T]) {
self.objects = Set<WeakObject<T>>(objects.map { WeakObject(object: $0) })
}
var allObjects: [T] {
return objects.flatMap { $0.object }
}
func contains(_ object: T) -> Bool {
return self.objects.contains(WeakObject(object: object))
}
func addObject(_ object: T) {
self.objects.formUnion([WeakObject(object: object)])
}
func addObjects(_ objects: [T]) {
self.objects.formUnion(objects.map { WeakObject(object: $0) })
}
}
Gokejiが述べたように、使用中のコードに基づいてNSStringが割り当て解除されないことがわかりました。私は頭をかいて、次のようにMyStringクラスを作成しました。
// typealias MyString = NSString
class MyString: CustomStringConvertible {
var string: String
init(string: String) {
self.string = string
}
deinit {
print("relasing: \(string)")
}
var description: String {
return self.string
}
}
次に、NSString
をMyString
に置き換えます。それからそれが機能すると言うのは奇妙です。
var alice: MyString? = MyString(string: "Alice")
var bob: MyString? = MyString(string: "Bob")
var cathline: MyString? = MyString(string: "Cathline")
var persons = WeakObjectSet<MyString>()
persons.addObject(bob!)
print(persons.allObjects) // [Bob]
persons.addObject(bob!)
print(persons.allObjects) // [Bob]
persons.addObjects([alice!, cathline!])
print(persons.allObjects) // [Alice, Cathline, Bob]
alice = nil
print(persons.allObjects) // [Cathline, Bob]
bob = nil
print(persons.allObjects) // [Cathline]
次に、この問題に関連する奇妙なページを見つけました。
弱い参照は割り当て解除されたNSStringを保持します(XC9 + iOS Simのみ)
https://bugs.Swift.org/browse/SR-5511
問題はRESOLVED
であると書かれていますが、これがこの問題にまだ関係しているかどうか疑問に思っています。とにかく、MyStringとNSStringの動作の違いはこのコンテキストを超えていますが、誰かがこの問題を理解してくれたら幸いです。
これは私の解決策ではありません。 Apple開発者フォーラムで見つけました 。
@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]
これを行うには、弱いポインターを保持するラッパーオブジェクトを作成します。
struct WeakThing<T: AnyObject> {
weak var value: T?
init (value: T) {
self.value = value
}
}
そして、配列でこれらを使用して
var weakThings = WeakThing<Foo>[]()
私はジェネリックで弱いコンテナを作成するという同じ考えを持っていました。
その結果、NSHashTable
のラッパーを作成しました。
class WeakSet<ObjectType>: SequenceType {
var count: Int {
return weakStorage.count
}
private let weakStorage = NSHashTable.weakObjectsHashTable()
func addObject(object: ObjectType) {
guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
weakStorage.addObject(object as? AnyObject)
}
func removeObject(object: ObjectType) {
guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
weakStorage.removeObject(object as? AnyObject)
}
func removeAllObjects() {
weakStorage.removeAllObjects()
}
func containsObject(object: ObjectType) -> Bool {
guard object is AnyObject else { fatalError("Object (\(object)) should be subclass of AnyObject") }
return weakStorage.containsObject(object as? AnyObject)
}
func generate() -> AnyGenerator<ObjectType> {
let enumerator = weakStorage.objectEnumerator()
return anyGenerator {
return enumerator.nextObject() as! ObjectType?
}
}
}
使用法:
protocol MyDelegate : AnyObject {
func doWork()
}
class MyClass: AnyObject, MyDelegate {
fun doWork() {
// Do delegated work.
}
}
var delegates = WeakSet<MyDelegate>()
delegates.addObject(MyClass())
for delegate in delegates {
delegate.doWork()
}
WeakSet
は任意のタイプで初期化でき、このタイプがAnyObject
プロトコルに準拠していない場合、詳細な理由でアプリがクラッシュするため、これは最適なソリューションではありません。しかし、今のところこれ以上良い解決策はありません。
元の解決策は、次の方法でWeakSet
を定義することでした。
class WeakSet<ObjectType: AnyObject>: SequenceType {}
ただし、この場合、WeakSet
はプロトコルで初期化できません。
protocol MyDelegate : AnyObject {
func doWork()
}
let weakSet = WeakSet<MyDelegate>()
現在、上記のコードはコンパイルできません(Swift 2.1、Xcode 7.1)。
だからこそ、AnyObject
への準拠をやめ、fatalError()
アサーションでガードを追加しました。
機能的なスタイルのラッパーはどうですか?
class Class1 {}
func captureWeakly<T> (_ target:T) -> (() -> T?) where T: AnyObject {
return { [weak target] in
return target
}
}
let obj1 = Class1()
let obj2 = Class1()
let obj3 = Class1()
let captured1 = captureWeakly(obj1)
let captured2 = captureWeakly(obj2)
let captured3 = captureWeakly(obj3)
返されたクロージャを呼び出して、ターゲットがまだ生きていることを確認します。
let isAlive = captured1() != nil
let theValue = captured1()!
そして、このクロージャーを配列に保存できます。
let array1 = Array<() -> (Class1?)>([captured1, captured2, captured3])
また、クロージャーを呼び出してマッピングすることにより、弱くキャプチャされた値を取得できます。
let values = Array(array1.map({ $0() }))
WeakContainerの既存の例は役立ちますが、ListsやDictionariesなどの既存のSwiftコンテナーで弱参照を使用することは実際には役立ちません。
ContainsなどのListメソッドを使用する場合、WeakContainerはEquatableを実装する必要があります。そこで、WeakContainerを赤道できるようにするコードを追加しました。
辞書でWeakContainerを使用したい場合は、辞書キーとして使用できるようにハッシュ可能にしました。
また、これはWeakObjectに名前を変更し、これがクラスタイプ専用であることを強調し、WeakContainerの例と区別します。
struct WeakObject<TYPE where TYPE:AnyObject> : Equatable, Hashable
{
weak var _value : TYPE?
let _originalHashValue : Int
init (value: TYPE)
{
_value = value
// We keep around the original hash value so that we can return it to represent this
// object even if the value became Nil out from under us because the object went away.
_originalHashValue = ObjectIdentifier(value).hashValue
}
var value : TYPE?
{
return _value
}
var hashValue: Int
{
return _originalHashValue
}
}
func ==<T>(lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool
{
if lhs.value == nil && rhs.value == nil {
return true
}
else if lhs.value == nil || rhs.value == nil {
return false
}
// If the objects are the same, then we are good to go
return lhs.value! === rhs.value!
}
これにより、弱参照のディクショナリを使用するなどのクールなことができます。
private var m_observerDict : Dictionary<WeakObject<AnyObject>,FLObservationBlock> = Dictionary()
func addObserver( observer:AnyObject, block:FLObservationBlock )
{
let weakObserver = WeakObject(value:observer)
m_observerDict[weakObserver] = block
}
func removeObserver( observer:AnyObject )
{
let weakObserver = WeakObject(value:observer)
m_observerDict.removeValueForKey(weakObserver)
}
[吉川和] [1]の回答に基づく
import Foundation
protocol Weakable: class {
associatedtype T: AnyObject = Self
var asWeakValue: WeakObject<T> { get }
}
protocol WeakObjectProtocol {
associatedtype WeakObjectType
var value: WeakObjectType? {get set}
init(object: WeakObjectType)
}
class WeakObject<T: AnyObject>: WeakObjectProtocol {
typealias WeakObjectType = T
weak var value: WeakObjectType?
required init(object: WeakObjectType) {
self.value = object
}
var referenceCount: Int {
return CFGetRetainCount(value)
}
}
extension WeakObject: Equatable {
static func == (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
return lhs.value === rhs.value
}
}
extension WeakObject: CustomStringConvertible {
var description: String {
if let value = value {
let className = String(describing: type(of: value.self))
return "{class: \(className); referenceCount: \(referenceCount)}"
}
return "nil"
}
}
extension Array where Element: AnyObject {
var asWeakArray: Array<WeakObject<Element>> {
var weakArray = [WeakObject<Element>]()
for item in self {
let obj = WeakObject(object: item)
weakArray.append(obj)
}
return weakArray
}
}
extension UIView: Weakable {
var asWeakValue: WeakObject<UIView> { return WeakObject(object: self) }
}
var weakArray = [WeakObject<UIView>]()
weakArray = view.subviews.asWeakArray
weakArray.append(view.asWeakValue)
ソリューションコードを貼り付けることを忘れないでください
import UIKit
class ViewController: UIViewController {
private var weakArray = [WeakObject<UIView>]()
override func viewDidLoad() {
super.viewDidLoad()
addSubviews()
weakArray = view.subviews.asWeakArray
weakArray.append(createRandomRectangleAndAdd(to: view).asWeakValue)
}
private func printArray(title: String) {
print("=============================\n\(title)\ncount: \(weakArray.count)")
weakArray.enumerated().forEach { print("\($0) \(String(describing: $1))") }
}
}
extension ViewController {
private func createRandomRectangleAndAdd(to parentView: UIView) -> UIView {
let view = UIView(frame: CGRect(x: Int.random(in: 0...200),
y: Int.random(in: 60...200),
width: Int.random(in: 0...200),
height: Int.random(in: 0...200)))
let color = UIColor(red: CGFloat.random(in: 0...255)/255,
green: CGFloat.random(in: 0...255)/255,
blue: CGFloat.random(in: 0...255)/255,
alpha: 1)
view.backgroundColor = color
parentView.addSubview(view)
return view
}
private func addSubviews() {
_ = createRandomRectangleAndAdd(to: view)
_ = createRandomRectangleAndAdd(to: view)
addButtons()
}
private func createButton(title: String, frame: CGRect, action: Selector) -> UIButton {
let button = UIButton(frame: frame)
button.setTitle(title, for: .normal)
button.addTarget(self, action: action, for: .touchUpInside)
button.setTitleColor(.blue, for: .normal)
return button
}
private func addButtons() {
view.addSubview(createButton(title: "Add",
frame: CGRect(x: 10, y: 20, width: 40, height: 40),
action: #selector(addView)))
view.addSubview(createButton(title: "Delete",
frame: CGRect(x: 60, y: 20, width: 60, height: 40),
action: #selector(deleteView)))
view.addSubview(createButton(title: "Remove nils",
frame: CGRect(x: 120, y: 20, width: 100, height: 40),
action: #selector(removeNils)))
}
@objc func deleteView() {
view.subviews
.filter { view -> Bool in return !(view is UIButton) }
.first?.removeFromSuperview()
view.layoutIfNeeded()
printArray(title: "First view deleted")
}
@objc func addView() {
weakArray.append(createRandomRectangleAndAdd(to: view).asWeakValue)
printArray(title: "View addded")
}
@objc func removeNils() {
weakArray = weakArray.filter { $0.value != nil }
printArray(title: "Remove all nil elements in weakArray")
}
}
extension UIView: Weakable {
var asWeakValue: WeakObject<UIView> { return WeakObject(object: self) }
}
@GoZonerの優れた回答をHashable
に準拠させる方法は次のとおりです。したがって、Set
、Dictionary
、Array
などのコンテナオブジェクトでインデックスを作成できます。
private class Weak<T: AnyObject>: Hashable {
weak var value : T!
init (value: T) {
self.value = value
}
var hashValue : Int {
// ObjectIdentifier creates a unique hashvalue for objects.
return ObjectIdentifier(self.value).hashValue
}
}
// Need to override so we can conform to Equitable.
private func == <T>(lhs: Weak<T>, rhs: Weak<T>) -> Bool {
return lhs.hashValue == rhs.hashValue
}
同じ問題のさらに別の解決策...この問題の焦点は、オブジェクトへの弱い参照を格納することですが、構造体も格納できるようにすることです。
[どれほど便利かはわかりませんが、構文が正しくなるまで時間がかかりました]
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
NSPointerArray
はすでにこれのほとんどを自動的に処理するため、タイプセーフなラッパーを作成することで問題を解決しました。
class WeakArray<T: AnyObject> {
private let pointers = NSPointerArray.weakObjects()
init (_ elements: T...) {
elements.forEach{self.pointers.addPointer(Unmanaged.passUnretained($0).toOpaque())}
}
func get (_ index: Int) -> T? {
if index < self.pointers.count, let pointer = self.pointers.pointer(at: 0) {
return Unmanaged<T>.fromOpaque(pointer).takeUnretainedValue()
} else {
return nil
}
}
func append (_ element: T) {
self.pointers.addPointer(Unmanaged.passUnretained(element).toOpaque())
}
func forEach (_ callback: (T) -> ()) {
for i in 0..<self.pointers.count {
if let element = self.get(i) {
callback(element)
}
}
}
// implement other functionality as needed
}
使用例:
class Foo {}
var foo: Foo? = Foo()
let array = WeakArray(foo!)
print(array.get(0)) // Optional(Foo)
foo = nil
DispatchQueue.main.async{print(array.get(0))} // nil
前もってより多くの作業を行いますが、残りのコードでの使用はIMOのほうがずっときれいです。配列のようにしたい場合は、添え字を実装したり、SequenceType
などにすることもできます(ただし、私のプロジェクトではappend
とforEach
のみが必要なので、正確なコードを手元に用意してください)。
他の答えはジェネリックの角度をカバーしています。 nil
角度をカバーする簡単なコードを共有すると思います。
アプリに現在存在するすべてのLabel
の静的配列(時々読む)が必要でしたが、以前のnil
の場所は見たくありませんでした。
派手なものはありません、これは私のコードです...
public struct WeakLabel {
public weak var label : Label?
public init(_ label: Label?) {
self.label = label
}
}
public class Label : UILabel {
static var _allLabels = [WeakLabel]()
public static var allLabels:[WeakLabel] {
get {
_allLabels = _allLabels.filter{$0.label != nil}
return _allLabels.filter{$0.label != nil}.map{$0.label!}
}
}
public required init?(coder: NSCoder) {
super.init(coder: coder)
Label._allLabels.append(WeakLabel(self))
}
public override init(frame: CGRect) {
super.init(frame: frame)
Label._allLabels.append(WeakLabel(self))
}
}
Array
の周りにラッパーを作成できます。または、このライブラリを使用します https://github.com/NickRybalko/WeakPointerArraylet array = WeakPointerArray<AnyObject>()
タイプセーフです。
これは@Eonilの仕事に基づいています。クロージャーの弱バインド戦略が大好きだったのですが、変数に関数演算子を使用したくありませんでした。
代わりに、私がしたことは次のとおりです。
class Weak<T> where T: AnyObject {
fileprivate var storedWeakReference: ()->T? = { return nil }
var value: T? {
get {
return storedWeakReference()
}
}
init(_ object: T) {
self.storedWeakReference = storeWeakReference(object)
}
fileprivate func storeWeakReference<T> (_ target:T) -> ()->T? where T: AnyObject {
return { [weak target] in
return target
}
}
}
このようにして、次のようなことができます。
var a: UIViewController? = UIViewController()
let b = Weak(a)
print(a) //prints Optional(<UIViewController: 0xSomeAddress>)
print(b.value) //prints Optional(<UIViewController: 0xSomeAddress>)
a = nil
print(a) //prints nil
print(b.value) //prints nil
これは、弱いオブジェクトのコンテナを保持するタイプセーフコレクションです。また、アクセス時にコンテナ/ラッパーを自動的に削除します。
例:
protocol SomeDelegate: class {
func doSomething()
}
class SomeViewController: UIViewController {
var delegates: WeakCollection<SomeDelegate> = []
func someFunction(delegate: SomeDelegate) {
delegates.append(delegate)
}
func runDelegates() {
delegates.forEach { $0.doSomething() }
}
}
カスタムコレクションhttps://Gist.github.com/djk12587/46d85017fb3fad6946046925f36cefdc
import Foundation
/**
Creates an array of weak reference objects.
- Important:
Because this is an array of weak objects, the objects in the array can be removed at any time.
The collection itself will handle removing nil objects (garbage collection) via the private function cleanUpNilContainers()
*/
class WeakCollection<T>: RangeReplaceableCollection, ExpressibleByArrayLiteral {
typealias Index = Int
typealias Element = T
typealias Iterator = IndexingIterator<[Element]>
private var weakContainers: [WeakReferenceContainer]
required convenience init(arrayLiteral: Element...) {
self.init()
self.weakContainers = WeakCollection.createWeakContainers(from: arrayLiteral)
}
required init() {
weakContainers = []
}
required init<S>(_ elements: S) where S: Sequence, WeakCollection.Element == S.Element {
self.weakContainers = WeakCollection.createWeakContainers(from: elements)
}
static private func createWeakContainers<S>(from weakCollection: S) -> [WeakReferenceContainer] where S: Sequence,
WeakCollection.Element == S.Element {
return weakCollection.compactMap { WeakReferenceContainer(value: $0 as AnyObject) }
}
func append<S>(contentsOf newElements: S) where S: Sequence, WeakCollection.Element == S.Element {
self.weakContainers.append(contentsOf: WeakCollection.createWeakContainers(from: newElements))
}
var startIndex: Index {
return references.startIndex
}
var endIndex: Index {
return references.endIndex
}
func replaceSubrange<C, R>(_ subrange: R, with newElements: C) where
C: Collection, R: RangeExpression, WeakCollection.Element == C.Element, WeakCollection.Index == R.Bound {
weakContainers.replaceSubrange(subrange, with: WeakCollection.createWeakContainers(from: newElements))
}
func index(after i: Int) -> Int {
return references.index(after: i)
}
func makeIterator() -> IndexingIterator<[Element]> {
return references.makeIterator()
}
subscript(index: Int) -> Element {
get {
return references[index]
}
set {
weakContainers[index] = WeakReferenceContainer(value: newValue as AnyObject)
}
}
}
extension WeakCollection {
private class WeakReferenceContainer {
private(set) weak var value: AnyObject?
init(value: AnyObject?) {
self.value = value
}
}
private func cleanUpNilContainers() {
weakContainers = weakContainers.compactMap { $0.value == nil ? nil : $0 }
}
private var references: [Element] {
cleanUpNilContainers()
return weakContainers.compactMap { $0.value as? T }
}
}
この私のソリューション:
-
// MARK: - WeakObjectSet
public class WeakObject<T: AnyObject>: Equatable, Hashable {
// MARK: Public propreties
public weak var object: T?
public var hashValue: Int {
return self.identifier.hashValue
}
// MARK: Private propreties
private let identifier: ObjectIdentifier
// MARK: Initializer
public init(object: T) {
self.identifier = ObjectIdentifier(object)
self.object = object
}
public static func == (lhs: WeakObject<T>, rhs: WeakObject<T>) -> Bool {
return lhs.identifier == rhs.identifier
}
}
// MARK: - WeakObjectSet
public class WeakObjectSet<T: AnyObject> {
// MARK: Public propreties
public var allObjects: [T] {
return allSetObjects.compactMap { $0.object }
}
// MARK: Private propreties
private var objects: Set<WeakObject<T>>
private var allSetObjects: Set<WeakObject<T>> {
get {
objects = self.objects.filter { $0.object != nil }
return objects
}
set {
objects.formUnion(newValue.filter { $0.object != nil })
}
}
// MARK: Initializer
public init() {
self.objects = Set<WeakObject<T>>([])
}
public init(objects: [T]) {
self.objects = Set<WeakObject<T>>(objects.map { WeakObject(object: $0) })
}
// MARK: Public function
public func contains(_ object: T) -> Bool {
return self.allSetObjects.contains(WeakObject(object: object))
}
public func addObject(_ object: T) {
self.allSetObjects.insert(WeakObject(object: object))
}
public func addObjects(_ objects: [T]) {
objects.forEach { self.allSetObjects.insert(WeakObject(object: $0)) }
}
}