Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

macOS: Realm Environment Injection Crashes Preview #8613

Open
Jaycyn opened this issue Jun 4, 2024 · 6 comments
Open

macOS: Realm Environment Injection Crashes Preview #8613

Jaycyn opened this issue Jun 4, 2024 · 6 comments

Comments

@Jaycyn
Copy link

Jaycyn commented Jun 4, 2024

How frequently does the bug occur?

Always

Description

Injecting a realm into a view as an environment value crashes preview.

Stacktrace & log output

From Preview

== PREVIEW UPDATE ERROR:

    CrashReportError: Fatal Error in SwiftUI.swift
    
    Realm SwiftUI macOS crashed due to fatalError in SwiftUI.swift at line 1422.
    
    'try!' expression unexpectedly raised an error: Error Domain=io.realm Code=10 "Migration is required due to the following errors:
    
    Process: Realm SwiftUI macOS[1249]
    Date/Time: 2024-06-04 22:12:28 +0000
    Log File: <none>

Can you reproduce the bug?

Always

Reproduction Steps

This is the entire project. Note the .environment injection in #Preview causes crash. With that commented out, preview works correctly.

That piece of code is taken from the documentation here Create a Realm with Data for Previews

import RealmSwift
import SwiftUI

struct ContentView: View {
    var body: some View {
        VStack {
            Image(systemName: "globe")
                .imageScale(.large)
                .foregroundStyle(.tint)
            Text("Hello, world!")
        }
        .padding()
    }
}

#Preview {
    return ContentView()
        .environment(\.realm, ItemGroup.previewRealm)  // <----- Causes crash
}

class Item: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var itemName = ""
    @Persisted var isFavorite = false
    @Persisted var ownerId = ""
}

extension Item {
    static let item1 = Item(value: ["itemName": "fluffy coasters", "isFavorite": false, "ownerId": "previewRealm"])
    static let item2 = Item(value: ["itemName": "sudden cinder block", "isFavorite": true, "ownerId": "previewRealm"])
    static let item3 = Item(value: ["itemName": "classy mouse pad", "isFavorite": false, "ownerId": "previewRealm"])
}



class ItemGroup: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var groupName = ""
    @Persisted var items = RealmSwift.List<Item>()
    @Persisted var ownerId = ""
}

extension ItemGroup {
    static let itemGroup = ItemGroup(value: ["ownerId": "previewRealm"])

    static var previewRealm: Realm {
        var realm: Realm
        let identifier = "previewRealm"
        let config = Realm.Configuration(inMemoryIdentifier: identifier)
        do {
            realm = try Realm(configuration: config)
            let realmObjects = realm.objects(ItemGroup.self)
            if realmObjects.count == 1 {
                return realm
            } else {
                try realm.write {
                    realm.add(itemGroup)
                    itemGroup.items.append(objectsIn: [Item.item1, Item.item2, Item.item3])
                }
                return realm
            }
        } catch let error {
            fatalError("Can't bootstrap item data: \(error.localizedDescription)")
        }
    }
}

Version

10.50.1

What Atlas Services are you using?

Local Database only

Are you using encryption?

No

Platform OS and version(s)

macOS 14.2.1

Build environment

Xcode version: 15.4
Realm Database: 14.6.2
Dependency manager and version: SPM

Copy link

sync-by-unito bot commented Jun 4, 2024

➤ PM Bot commented:

Jira ticket: RCOCOA-2380

@nirinchev
Copy link
Member

Hey, can you share the full repro project - it appears like someone else is opening a Realm with the same identifier but a different schema, so the schema validation logic kicks in, but it's not obvious from the shared code what could be culprit.

@Jaycyn
Copy link
Author

Jaycyn commented Jun 7, 2024

Thanks @nirinchev. The entire project is the above code - it's local only so there would not be someone else opening the realm and there are no other apps accessing that projects directory or supporting files directory.

I do have a followup question that may lead to the solution.

Keep in mind that the project itself works, it's only the preview that's crashing

#Preview {
    return ContentView()
        .environment(\.realm, ItemGroup.previewRealm)  // <----- Causes crash
}

When a new, fresh project is first run, Realm creates the default.realm file with the objects schema. If the app is then quit, and the schema is changed in the project but the project is NOT run, the only 'code' that's doing anything is the XCode code that drives the preview with the injected .environment

The preview should only be getting it's data from the ItemGroup.previewRealm so even if the objects schema were to change, if the preview is refreshed, it would still pull data only from the realm defined in the previewRealm, right?

So what would trigger a migration if the app itself is not being run?

@nirinchev
Copy link
Member

I can't seem to repro this with the code provided. I can see a preview with a globe and "Hello world" below it and even if I update it to read some data from the Realm file, it still works just fine. Is it possible you have another instance of Xcode/your app opening an in-memory realm with the same identifier somewhere?

@Jaycyn
Copy link
Author

Jaycyn commented Jun 8, 2024

@nirinchev Yes, I have the same result. However, do this: Add a property to the Item object but DO NOT RUN the project. Let the preview refresh and it will error out.

Here's the Item object (per the original report above)

class Item: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var itemName = ""
    @Persisted var isFavorite = false
    @Persisted var ownerId = ""
}

and then add a property - do NOT run the project

class Item: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var itemName = ""
    @Persisted var isFavorite = false
    @Persisted var ownerId = ""
    @Persisted var test = ""  // added property
}

and preview crashes.

@Jaycyn
Copy link
Author

Jaycyn commented Jun 9, 2024

@nirinchev I am still getting the same error as in the original post - and I am narrowing the issue and think it can be duplicated.

One thing I noted is that on a 100% clean project, using the above code, without running the project, the #Preview generates the Realm files on disk. This apparently means that during development, changing an object schema, even if the added properties are not used anywhere, will crash preview without actually running any code.

  1. Create a new macOS app, SwiftUI

  2. Add Realm via SPM (per the documentation)

  3. copy and paste the code in the Content View. Do NOT run the project

  4. Preview will not work at this point. Go to the Project Target settings and delete App Sandbox and Hardened Runtime

  5. Upon going back to the ContentView, Preview will refesh and show the globe with Hello, World. If you then look at ~/Library/Application Support/your project name, you will see the Realm files have been created - even though the app has not been run

  6. In the ContentView file, go to the Item object model and add a property @Persisted var test = "" so it looks like this

class Item: Object, ObjectKeyIdentifiable {
    @Persisted(primaryKey: true) var _id: ObjectId
    @Persisted var itemName = ""
    @Persisted var isFavorite = false
    @Persisted var ownerId = ""
    @Persisted var test = ""  //add this
}
  1. At that point, preview will crash with a Fatal Error

Realm_Preview_Crash_PreviewReplacement_ContentView_1/ContentView.swift:71: Fatal error: Can't bootstrap item data: Migration is required due to the following errors:
- Property 'Item.test' has been added.
]

Then, delete the realm files that were generated:

  1. delete the folder at ~/Library/Application Support/your project name

  2. refresh preview, and it still crashes, even though the Realm files were deleted.

I thought perhaps adding a Migration (per the documentation) would help but without running the project, that migration doesn't run either.

Deleting the realm folder and cleaning the build folder doesn't help.

I did the above steps 4 times with the same result - My thinking is the preview should not be accessing any files on disk as an in memory realm is being injected. It's not clear (to me) what's causing the issue or how to handle changing an object model during development and have preview work.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants