Strange behaviour of Field.Stored behaving as optional #373

Closed
opened 2025-12-29 15:30:21 +01:00 by adam · 2 comments
Owner

Originally created by @ptrkstr on GitHub (Sep 4, 2021).

The documentation shows the following example of Field.Stored

@Field.Stored("title")
var title: String = "Mr."

@Field.Stored("nickname")
var nickname: String?

From that, my understanding is if you give a default value or an initial value (via dynamicInitialValue), then the field is non-optional.

So if I have the following model:

class Person: CoreStoreObject {
    @Field.Stored("name")
    var name: String = ""
}

Then I should be able to do the following:

    @ListState(
        From<Person>().orderBy(.ascending(\.$name)),
        in: CoreStoreDefaults.dataStack
    )
    private var people
    
    var body: some View {
        List {
            ForEach(objectIn: people) { person in
                Text(person.name)
            }
        }
    }

However Xcode complains that "Value of optional type 'String?' must be unwrapped to a value of type 'String'" for name in person.name.

The very strange thing is that Xcode's code complete shows it as non-optional.
image

I'm using Xcode 12.5.1 (12E507)

Is this intended behaviour?
I've attached the project.

BugCoreStore.zip

Originally created by @ptrkstr on GitHub (Sep 4, 2021). The documentation shows the following example of Field.Stored ```swift @Field.Stored("title") var title: String = "Mr." @Field.Stored("nickname") var nickname: String? ``` From that, my understanding is if you give a default value or an initial value (via dynamicInitialValue), then the field is non-optional. So if I have the following model: ```swift class Person: CoreStoreObject { @Field.Stored("name") var name: String = "" } ``` Then I should be able to do the following: ```swift @ListState( From<Person>().orderBy(.ascending(\.$name)), in: CoreStoreDefaults.dataStack ) private var people var body: some View { List { ForEach(objectIn: people) { person in Text(person.name) } } } ``` However Xcode complains that **"Value of optional type 'String?' must be unwrapped to a value of type 'String'"** for `name` in `person.name`. The very strange thing is that Xcode's code complete shows it as non-optional. <img width="958" alt="image" src="https://user-images.githubusercontent.com/11362913/132094009-728dc8c1-bfaa-477d-9dcf-7e60e55678c8.png"> I'm using Xcode 12.5.1 (12E507) Is this intended behaviour? I've attached the project. [BugCoreStore.zip](https://github.com/JohnEstropia/CoreStore/files/7109724/BugCoreStore.zip)
adam closed this issue 2025-12-29 15:30:22 +01:00
Author
Owner

@JohnEstropia commented on GitHub (Sep 4, 2021):

@patrickbdev ListStates always return ObjectPublisher instances, and thus there are two things you'd need to note here:

  1. To access the properties, use the propertyWrapper syntax: person.$name
  2. For ObjectPublishers, the value of the properties are always an optional of the actual value, because this instance may have been deleted on the thread that it is being accessed on. Think of ObjectPublishers as living ObservableObjects: you cannot just read their values or else your SwiftUI Views will not get automatically updated.

Now this is where @ObjectStates come in. Your inner View that needs to read the properties need to use that ObjectPublisher and observe on it through @ObjectState. The @ObjectState returns an ObjectSnapshot which will now let you access .$name as a non-optional.

You can see this all in action in the Demo app, particularly the Modern.ColorsDemo.SwiftUI.ListView.swift and Modern.ColorsDemo.SwiftUI.ItemView.swift files.

@JohnEstropia commented on GitHub (Sep 4, 2021): @patrickbdev `ListState`s always return `ObjectPublisher` instances, and thus there are two things you'd need to note here: 1. To access the properties, use the propertyWrapper syntax: `person.$name` 2. For `ObjectPublisher`s, the value of the properties are *always* an optional of the actual value, because this instance may have been deleted on the thread that it is being accessed on. Think of `ObjectPublisher`s as living `ObservableObject`s: you cannot just read their values or else your SwiftUI `View`s will not get automatically updated. Now this is where `@ObjectState`s come in. Your inner `View` that needs to read the properties need to use that `ObjectPublisher` and observe on it through `@ObjectState`. The `@ObjectState` returns an `ObjectSnapshot` which will now let you access `.$name` as a non-optional. You can see this all in action in the Demo app, particularly the `Modern.ColorsDemo.SwiftUI.ListView.swift` and `Modern.ColorsDemo.SwiftUI.ItemView.swift` files.
Author
Owner

@ptrkstr commented on GitHub (Sep 5, 2021):

Thank you for the prompt response @JohnEstropia, that does make sense and answers the question. I'm very impressed with this project, you've gained yourself another sponsor 😇

@ptrkstr commented on GitHub (Sep 5, 2021): Thank you for the prompt response @JohnEstropia, that does make sense and answers the question. I'm very impressed with this project, you've gained yourself another sponsor 😇
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/CoreStore#373