GO FURTHER, FASTER: Try the Swift Career Accelerator today! >>

Bug with SwiftUI ColorPicker and SwiftData

Forums > SwiftUI

So I think this is a bug and not be being dumb. In order to try and get to a MVP which demonstrates the problem I've stripped my code right back to the basics.

I have a swift data model which stores a colour, since swiftData doesn't store colour I am storing the colour as the four elements and using a calulcated property to persist it. My model looks like this:

  @Model
    class PersistantStateManagerStorage {

        init() {

        }

        var defaultColour: Color {
            get {
                print("getting colour ")
                print("it is \(self._$backingData) \(dfblue)");

                return Color(red: dfred, green: dfgreen, blue: dfblue, opacity: dfopacity) }
            set {
                if let components = newValue.cgColor?.components {
                    dfred = components[0]
                    dfgreen = components[1]
                    dfblue = components[2]
                    dfopacity = components[3]
                }
            }
        }

        // color components for this location (colour can't be stored as a colour which is dumb
        var dfred: Double = 1.0
        var dfblue: Double = 1.0
        var dfgreen: Double = 1.0
        var dfopacity: Double = 1.0

    }

I then have a view with a colour picker and a rectangle, and I create a singleton object of my model when the view appears:


@MainActor
struct ContentView: View {
    @Environment(\.modelContext) private var modelContext

    @Query private var persistantStores:[PersistantStateManagerStorage]

    var body: some View {

        HStack {

            ForEach(persistantStores) {
                s in

                VStack {
                    ColorPicker("Default Colour", selection: Bindable(s).defaultColour, supportsOpacity: false)

                }.frame(maxWidth: 250)

                ZStack {
                    Rectangle().fill(s.defaultColour).position(x:100, y:100).frame(width: 200, height: 200).focusable()
                }.background(){
                    Color.black.ignoresSafeArea()

                }.frame(width: 500, height: 500)

            }
        }.onAppear(){

            if self.persistantStores.count  == 0
            {
                print ("make")
                let store = PersistantStateManagerStorage()
                modelContext.insert(store)
                try? modelContext.save()

            }
        }

    }

}

I know the logic of this is a little weird, but it's purely to be the simplest way of demonstrating the problem.

Now, for the weirdness.. You run this and make a new document, if you don't click on the rectangle and simply close the document then all is fine. However if you select the rectangle (note that it is focussable) and then close the file (saving or deleting) then the app will crash with the error:

SwiftData/BackingData.swift:124: Fatal error: Unable to get value - no backing Managed Object

However, if I add a state variable for colour to the view, and change the colour picker to not bind directly to my model oject - such as

 ColorPicker("Default Colour", selection: $col, supportsOpacity: false).onChange(of: col){

                        s.defaultColour = col
                    }.onAppear()
                    {
                        col = s.defaultColour

                    }

Then all seems happy

Any ideas or is this indeed a bug?

   

Hmm. I actually think I have a fundamental misunderstanding of bindings in swiftUI/swiftData

I am seeing the same issue if I bind a double value to a slider. I am not clear if I am doing something with how I am creating the binding from the object that I get from the @Query array - I am generally very confused..

   

Hacking with Swift is sponsored by Essential Developer.

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until February 9th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.