Reputation: 6436
I got two classes like this:
class Session {
var name: String
var data: [Double]
var routes: [Route]
init(named name: String, data: [Double] = [], routes: [Route] = []) {
self.name = name
self.data = data
self.routes = routes
}
}
class Route {
var session: Session
var startIndex: Int
var endIndex: Int
// A route stores only references to the real underlying data stored in a Session
var data: [Double] { Array(session.data[startIndex...endIndex]) }
init(session: Session, startIndex: Int, endIndex: Int) {
self.session = session
self.startIndex = startIndex
self.endIndex = endIndex
}
}
Note that a Route object cannot be initialised without a corresponding Session, it always depends on it. The goal is to store in Route only references to the real data stored in the Session object.
First, is there a potential retain cycle in this pattern, and how to break it if there is one?
Second question: I want to make a Session Codable. The problem is as Session relies on Route and Route on Session I can't make one Codable without making the other too and I fall into an endless loop.
I don't necessarily require that Route conforms to codable as a route will always depends on a Session, an exemple JSON would be:
{
"name": "Session Name"
"data": [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
"routes": [
{
"start_index": 3
"end_index": 8
}
...
]
}
From this I would be able to recover a Session from a JSON.
I tried:
nestedContainer
but it requires Route to be Codable.session
and then changing it back to the real session but it feels awkward and not very robust.init
with an additional argument session, but I can't access this initializer after. Maybe I can extend and overload the decode method of JSONDecoder to take this into account?Upvotes: 1
Views: 440
Reputation: 2762
What you've modeled is a circular dependency and can't be represented in JSON. The easiest solution is to change the session
property on route.
weak var session: Session?
This prevents a retain cycle and makes it so that session isn't required in Route.init
. With that change in place you can then loop through all the Route
s at the end of your Session
initializer and assign the session.
The downside to this solution is that you need to write your own initializers, but it sounds like you were experimenting with that anyway.
Upvotes: 3