Swift dictionary with weak reference keys?
Asked Answered
L

2

21

Let's say I have a some objects representing network connections. Once these connections are disconnected, the associated objects disappear. I don't want to hang on to a connection object which is no longer connected.

I also want to associate some data with these connections using a dictionary. So I might have the code:

class Connection { ... }
class Metadata { ... }

var metadata: [Connection: Metadata] = [:]

But the above code means that the dictionary will keep references to the Connection objects which I don't want. I'd prefer to have the associated entries be removed, ideally automatically, when the Connection objects disappear.

So I tried:

var metadata: [weak Connection: Metadata] = [:]

But this doesn't work. What is a good alternative solution to this?

Layman answered 23/11, 2015 at 0:39 Comment(0)
B
33

You are describing an NSMapTable. It gives you a dictionary-like thing with weak references to its keys and/or values.

Buchalter answered 23/11, 2015 at 0:49 Comment(4)
Just a note to everyone writing Swift on the server: NSMapTable and NSHashTable does not exist on Linux, so you'll need to use an approach like Rob's answer.Alodie
Except that NSMapTable's weak keys are broken: key objects do not get actually released and are being held by internal implementation details.Morez
@Morez I think "broken" is rather inappropriate. There are some good articles about how it works.Buchalter
I'm referring an issue as described here. To my best knowledge it's still as broken as it was 8 years ago.Morez
O
4

You can write a generic type for weak references like they did in How do I declare an array of weak references in Swift? Because you are doing this for the dictionary key, you have to go through some extra work to make it conform to Hashable, but it can be done.

Personally, though, I wouldn't use the connection objects as the key. I use a unique string identifier for the network request be the key (e.g., the taskIdentifier of the NSURLSessionTask).

That resolves the concern of the collection maintaining a strong reference to the request.

Regarding the removing of the item when the task is done, I just make this clean-up part of the task completion logic.

Octopus answered 23/11, 2015 at 6:10 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.