SwiftData @Model: Optional to-many relationship is never nil at runtime

Hi all,

I’m trying to understand SwiftData’s runtime semantics around optional to-many relationships, especially in the context of CloudKit-backed models.

I ran into behavior that surprised me, and I’d like to confirm whether this is intended design or a potential issue / undocumented behavior.

Minimal example

import SwiftUI
import SwiftData

@Model
class Node {
    var children: [Node]? = nil
    var parent: Node? = nil

    init(children: [Node]? = nil, parent: Node? = nil) {
        self.children = children
        self.parent = parent
        print(self.children == nil)
    }
}

struct ContentView: View {
    var body: some View {
        Button("Create") {
            _ = Node(children: nil)
        }
    }
}

Observed behavior

  • If @Model is not used, children == nil prints true as expected.
  • If @Model is used, children == nil prints false.

Inspecting the macro expansion, it appears SwiftData initializes relationship storage using backing data placeholders and normalizes to-many relationships into empty collections at runtime, even when declared as optional.

CloudKit context From the SwiftData + CloudKit documentation:

“The iCloud servers don’t guarantee atomic processing of relationship changes, so CloudKit requires all relationships to be optional.”

Because of this, modeling relationships as optional is required when syncing with CloudKit, even for to-many relationships. This is why I’m hesitant to simply switch the model to a non-optional [Node] = [], even though that would match the observed runtime behavior.

Questions

  1. Is it intentional that optional to-many relationships in SwiftData are never nil at runtime, and instead materialize as empty collections?
  2. If so, is Optional<[Model]> effectively treated as [Model] for runtime access, despite being required for CloudKit compatibility?
  3. Is the defaultValue: nil in the generated Schema.PropertyMetadata intended only for schema/migration purposes rather than representing a possible runtime state?
  4. Is there a recommended modeling pattern for CloudKit-backed SwiftData models where relationships must be optional, but runtime semantics behave as non-optional?

I’m mainly looking to ensure I’m aligning with SwiftData’s intended design and not relying on behavior that could change or break with CloudKit sync.

Thanks in advance for any clarification!

SwiftData &#64;Model: Optional to-many relationship is never nil at runtime
 
 
Q