I have four obscure questions about the usual process of boxing weak references.
To demonstrate the issues, here's a notification system, Notes
.
You'd use it like this...
class SyncedCell: UITableViewCell, Notes {
override func layoutSubviews() {
...
listen(forNote: "soloCell")
}
func editing() {
say(note: "soloCell")
...
input.becomeFirstResponder()
}
func note() {
print("Hooray, I got a note..")
editingCancel()
}
So, the code for Notes
is below.
For a given key (say "soloCell") you simply keep an array of references to any object which wants to get a message when that key is called.
Naturally, these have to be weak references.
So, when a new object arrives that needs to be memorized in the list...
var b:_Box = _Box()
b.p = self
_notes[k]?.append(b)
(The "listen" function just adds that object to the list of items for that key. The "say" function runs through the list of listening items for that key: for each item - if the item has not gone away in the meantime - it sends a message.)
So! As far as I know, you cannot keep an array of weak references.
You have to box them up, as you see in the kodes below.
Really, is that correct? Using a box is ugly, is there a way to just plain keep a list of weak references? Without having to box?
Relatedly: in the kodes
AnyObject
is the base. Is that best?Notice the protocol is not
: class
. This is disturbing and I'm not sure if it should be.Note that very unfortunately in Swift - as far as I know - you cannot observe a weak reference going to nil. Is this still the case as of 2017? Is there any way at all to achieve this?
Footnote - regarding point 4, "is there any way to achieve this?" The only possibility seems to be to add an associatedPbject to the watched items. (Example of that)[https://stackoverflow.com/a/32607010/294884]
code...
struct _Box {
weak var p: AnyObject?
// note: I prefer to spell out the assigment,
// rather than have a convenience initializer here
}
var _notes:[String:[_Box]] = [:]
protocol Notes {
func note()
}
extension Notes where Self:AnyObject {
func listen(forNote k: String) {
if _notes.index(forKey: k) == nil {
_notes[k] = []
}
var b:_Box = _Box()
b.p = self
_notes[k]?.append(b)
}
func say(note k:String) {
if let _n = _notes[k] {
var k:Int = 0
print("notes.4 saying......")
for b in _n {
let p = b.p
if (p == nil) {
print("\(k) notes.4 there's one that's been removed")
}
else {
print("\(k) notes.4 sending ok...")
(p as! Notes).note()
}
k = k + 1
}
}
__noteCleaner()
}
func __noteCleaner() {
for var (k, _n) in _notes {
let kn = _n.count
for i in (0..<kn).reversed() {
let p = _n[i].p
if (p == nil) {
_n.remove(at: i)
let newk = _n.count
print("notes.4, removed a dud listener for key \(k) new length is \(newk)")
}
}
if (_n.count == 0) {
print("notes.4, removed a seemingly unused key \(k)")
_notes.removeValue(forKey: k)
}
}
}
}