MangoByte MangoByte
 ·  Essay

SwiftData Enums in Xcode Previews: Technical Findings

Notes and tips on how get these two work nicely together when using Enum with associated values.

The issue

SwiftData models containing enums with associated values cause intermittent crashes during delete operations in Xcode previews

Affected Configuration

  • SwiftData models with enum properties that have associated values
  • Delete operations in Xcode previews
  • All iOS versions (17.0+)

Example Code That Crashes

enum Priority: Codable {
      case low
      case medium
      case high(dueDate: Date)
      case urgent(dueDate: Date, reason: String)
  }

  @Model
  class TodoItem {
      var id = UUID()
      var title: String
      var priority: Priority  // ❌ Causes intermittent crashes on delete
      var isCompleted = false
  }

Technical Details

Crash Signature

libswiftCore.dylib: swift::swift_dynamicCastFailure
SwiftData: Dynamic cast failure during delete operation

Crash Characteristics

  • Intermittent: May work initially, fails unpredictably
  • Preview-specific: Only occurs in Xcode previews, not runtime
  • Delete-specific: Only triggered by delete operations
  • Type-casting related: SwiftData’s internal dynamic cast fails

Working Solution

Approach: Decompose Enum Storage

@Model
  class TodoItem {
      var id = UUID()
      var title: String

      // Store enum components separately
      private var priorityType: String = "medium"
      private var priorityDueDate: Date?
      private var priorityReason: String?

      // Reconstruct enum via computed property
      var priority: Priority {
          get {
              switch priorityType {
              case "low": return .low
              case "medium": return .medium
              case "high":
                  return .high(dueDate: priorityDueDate ?? Date())
              case "urgent":
                  return .urgent(
                      dueDate: priorityDueDate ?? Date(),
                      reason: priorityReason ?? ""
                  )
              default: return .medium
              }
          }
          set {
              switch newValue {
              case .low:
                  priorityType = "low"
                  priorityDueDate = nil
                  priorityReason = nil
              case .medium:
                  priorityType = "medium"
                  priorityDueDate = nil
                  priorityReason = nil
              case .high(let date):
                  priorityType = "high"
                  priorityDueDate = date
                  priorityReason = nil
              case .urgent(let date, let reason):
                  priorityType = "urgent"
                  priorityDueDate = date
                  priorityReason = reason
              }
          }
      }
  }

Preview Configuration (iOS 18.0+) Using PreviewModifier

@MainActor
  struct TodoPreviewModifier: PreviewModifier {
      static func makeSharedContext() throws -> ModelContainer {
          let config = ModelConfiguration(isStoredInMemoryOnly: true)
          let container = try ModelContainer(for: TodoItem.self, configurations: config)
          container.mainContext.autosaveEnabled = false
          return container
      }

      func body(content: Content, context: ModelContainer) -> some View {
          content.modelContainer(context)
      }
  }

  #Preview(traits: .modifier(TodoPreviewModifier())) {
      TodoListView()
  }

  Basic Preview Setup

  #Preview {
      let config = ModelConfiguration(isStoredInMemoryOnly: true)
      let container = try! ModelContainer(for: TodoItem.self, configurations: config)
      container.mainContext.autosaveEnabled = false

      return TodoListView()
          .modelContainer(container)
  }

Key Findings

1. Enum Storage: SwiftData cannot reliably handle enums with associated values during delete operations

2. Decomposition Works: Storing enum data as separate properties avoids the crash

3. API Preservation: Computed properties maintain the same public interface

4. Preview-Specific: Issue only occurs in Xcode previews, not in production

5. Intermittent Nature: Crash may not occur immediately, making it hard to detect

Recommendations

When to Use This Pattern

  • SwiftData models with enums containing associated values
  • When delete operations are required
  • For reliable Xcode previews

Benefits

  • Eliminates preview crashes
  • Enables property-based queries
  • Maintains existing API
  • Future-proof solution

Additional Advantages

  • Can query on individual enum components
  • Simpler migration if schema changes
  • More explicit storage format
All notes and essays
© 2026 MangoByte. Built simple, on purpose.