Categories
Foundation iOS Swift

Referencing itself in a struct in Swift

It took a long time, I mean years, but it finally happened. I stumbled on a struct which had a property of the same type.

struct Message {
let id: Int
// This is OK:
let replies: [Message]
// This is not OK
// Value type 'Message' cannot have a stored property that recursively contains it
let parent: Message?
}
view raw Struct.swift hosted with ❤ by GitHub

At first, it is kind of interesting that the replies property compiles fine, although it is a collection of the same type. I guess it is so because array’s storage type is a reference type.

The simplest workaround is to use a closure for capturing the actual value.

struct Message {
let id: Int
let replies: [Message]
private let parentClosure: () -> Message?
var parent: Message? { parentClosure() }
}
view raw Struct2.swift hosted with ❤ by GitHub

Or we could go for using a boxed wrapper type.

struct Message {
let id: Int
let replies: [Message]
private let parentBoxed: Boxed<Message>?
var parent: Message? { parentBoxed?.value}
}
class Boxed<T> {
let value: T
init(value: T) {
self.value = value
}
}
view raw Struct3.swift hosted with ❤ by GitHub

Or if we prefer property wrappers, using that instead.

struct Message {
let id: Int
let replies: [Message]
@Boxed var parent: Message?
}
@propertyWrapper
class Boxed<Value> {
var value: Value
init(wrappedValue: Value) {
value = wrappedValue
}
var wrappedValue: Value {
get { value }
set { value = newValue }
}
}
view raw Struct4.swift hosted with ❤ by GitHub

Then there are also options like changing the struct into class instead, but that is something to consider. Or finally, creating a

All in all, it is fascinating how something simple like this actually has a pretty complex background.

If this was helpful, please let me know on Mastodon@toomasvahter or Twitter @toomasvahter. Feel free to subscribe to RSS feed. Thank you for reading.