3

I understand difference between class and struct in Swift. Now I'm wondering what to use for hierarchy model.

To define a class is pretty simple (setting connections on properties set is now irrelevant).

class XYClass {
    var title: String
    var subinstances: [XYClass]
    weak var superinstance: XYClass?
}

But it looks like pretty fine model for struct. Especially if I need to instantiate a lots of these and frequently. But I'm wondering if I can somehow safely point to superinstance or I need to store whole object graph to every instance on every change... Should I use class or struct and if struct, how to define it?

user500
  • 4,519
  • 6
  • 43
  • 56
  • I think this answer provides a good answer. http://stackoverflow.com/questions/24232799/why-choose-struct-over-class – Marius Fanu Mar 27 '15 at 16:57

1 Answers1

2

You are making a linked list. If you were to try to form a linked list of structs of a single type, memory management would not be feasible, and the compiler would stop you dead in your tracks. This won't compile:

struct XYClass {
    var title: String
    var subinstances: [XYClass]
    var superinstance: XYClass?
}

The compiler has spotted the problem. You cannot refer to an instance of a struct as a property of that struct. (The compiler calls this a "recursive value type".)

Thus, for your situation, you must use a class, because only then can you get a weak reference and avoid a retain cycle. Only a reference to a class can be weak (and only if the reference is typed as an Optional).

This will compile, and will give your linked list coherent memory management:

class XYClass {
    var title: String = ""
    var subinstances: [XYClass] = []
    weak var superinstance: XYClass?
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I would like to point out that one should use the prefix declaration modifier `unowned` instead of `weak` under the guaranteed presence of a logical hierarchical parent. – Vatsal Manot Mar 27 '15 at 18:06
  • @VatsalManot I don't think it is guaranteed. There must be a top level (root). It has no superinstance, and we would thus have a very dangerous situation. `weak` is a much better choice, because we can use an Optional and have `nil` automatically if the referent is deallocated. This situation is not at all appropriate for `unowned`. Use `unowned` only if the referent is existentially _prior_ and _guaranteed_. For example, if a class retains a function, the function can refer to the class instance as `unowned` because if it didn't exist there would be no one to retain the function. – matt Mar 27 '15 at 18:09
  • I think that a dummy superinstance should be created for the root instance. As for memory management, `unowned` makes it easier to maintain a list, as the deallocation of one superinstance would trigger a chain collapse of all it's subinstances, eliminating the headache of memory leaks. – Vatsal Manot Mar 27 '15 at 18:23
  • The dummy superinstance would itself have an unowned superinstance, so all you have done is to push the same problem back one level. And there are not going to be any memory leaks with the model I have suggested: instance retains its subinstances but not its superinstance, so there is no possibility of a retain cycle. – matt Mar 27 '15 at 18:27
  • Use subclasses, separating the root and the children instances. The root instance should not have a super-instance. This is a more favorable (and structured) approach as opposed to the cumbersome woes of your average `Optional` addict. – Vatsal Manot Mar 27 '15 at 18:32
  • @VatsalManot Feel free to submit that as a separate answer! – matt Mar 27 '15 at 18:38