問題はweakDelegates
が強い参照と型WeakDelegateContainerのその要素への参照であることであるが、強い参照です。
あなたの状況は、クラスNSHashTableが存在する理由です。 weakObjects()
を使用して初期化します。これはARC弱参照のセットを提供します。それぞれの参照は、参照オブジェクトが存在しなくなったときには削除され、削除されます(WeakDelegateContainerタイプは必要ありません)。
あなたのセットがANYOBJECTを保持しているとして入力する必要がありますが、あなたは簡単にあなたが供給しSomeDelegate準拠のオブジェクトを取得していることを保証するために媒介することができる:
let list = NSHashTable<AnyObject>.weakObjects()
func addToList(_ obj:SomeDelegate) {
list.add(obj)
}
func retrieveFromList(_ obj:SomeDelegate) -> SomeDelegate? {
if let result = list.member(obj) as? SomeDelegate {
return result
}
return nil
}
func retrieveAllFromList() -> [SomeDelegate] {
return list.allObjects as! [SomeDelegate]
}
retrieveAllFromList()
リストはまだ存在してオブジェクトのみ機能。存在していたオブジェクトは、NSHashTableのnil
に変更され、allObjects
には含まれていません。それは私が "余分な簿記なし"という意味です。 NSHashTableはすでに簿記を行っています。
func test() {
let c = SomeClass() // adopter of SomeDelegate
self.addToList(c)
if let cc = self.retrieveFromList(c) {
cc.someFunction()
}
print(self.retrieveAllFromList()) // one SomeClass object
delay(1) {
print(self.retrieveAllFromList()) // empty
}
}
また、あなたがNSPointerArrayを使用することができます。ここでは
はそれをテストするコードです。その要素は、スウィフトに使うには少し冗長になり得る、ポインタ・ツー・空ですが、あなただけ(https://stackoverflow.com/a/33310021/341994にクレジット)一度あなたのアクセサ関数を記述する必要があります。ここでは
let parr = NSPointerArray.weakObjects()
func addToArray(_ obj:SomeDelegate) {
let ptr = Unmanaged<AnyObject>.passUnretained(obj).toOpaque()
self.parr.addPointer(ptr)
}
func fetchFromArray(at ix:Int) -> SomeDelegate? {
if let ptr = self.parr.pointer(at:ix) {
let obj = Unmanaged<AnyObject>.fromOpaque(ptr).takeUnretainedValue()
if let del = obj as? SomeDelegate {
return del
}
}
return nil
}
はそれをテストするためのコードです:
let c = SomeClass()
self.addToArray(c)
for ix in 0..<self.parr.count {
if let del = self.fetchFromArray(at:ix) {
del.someFunction() // called
}
}
delay(1) {
print(self.parr.count) // 1
for ix in 0..<self.parr.count {
if let del = self.fetchFromArray(at:ix) {
del.someFunction() // not called
}
}
}
興味深いことに、私たち工assが存在の外に出た後、私たちの配列のcount
は1のままである - しかし、someFunction
を呼び出すために、それを循環し、someFunction
への呼び出しはありません。これは、配列内のSomeClassポインタがnil
に置き換えられたためです。 NSHashTableとは異なり、配列は自動的に要素nil
のパージされません。彼らは、私たちのアクセサコードがエラーに対して守られているので、何の害もしませんが、あなたは、配列を圧縮したい場合は、ここでは(https://stackoverflow.com/a/40274426/341994)それを行うためのトリックです:その質問の
self.parr.addPointer(nil)
self.parr.compact()
答えが準拠するクラスを参照しますAnyObjectへ。私はAnyObjectに従わないプロトコルオブジェクトの配列を持っています。 – Leontien
プロトコルは自分自身に準拠することができないので、リンクされた答えをバットからすぐに使うことはできません( 'AnyObject'制約を' SomeDelegate'に置き換えると思うかもしれません)にリンクする。しかし、あなたは[次のQ&A](http://stackoverflow.com/questions/32807948/using-as-a-concrete-type-conforming-to-protocol-anyobject-is-not-supported)を見ることができます。 'class'制約付きプロトコルインスタンスを弱参照で保持できるカスタムコンテナを実装しています。 – dfri
dfriのリンクが助けになりました。私は一般的な解決策が必要ないので、Kyle Redfearnの答えを使用しました。私はこの質問の答えに私の解決策を置くので、他人のために見つけるのが簡単になります。 – Leontien