0

I have several Pickers in a SwiftUI App where the Picker items are stored in Core Data. Each Picker item is only a title: String and a comment: String.

The App has a List and DetailView format, with the Picker in the DetailView. I use an @State var to indicate whether editing is in process. If isEditing is false, a text field shows the stored choice. If isEditing is true, the Picker is shown. This all works well except that setting isEditing to true displays the picker with item 0 from the data backing. The real value is still in Core Data but it looks to the user that the choice has been overwritten.

I created a custom Binding to set the user selections:

var spinner1Binding: Binding<Int> { Binding( get: { self.selectionIndex1 }, set: { self.selectionIndex1 = $0 self.picker1Text = picker1ListVM.picker1Items[self.selectionIndex1].picker1Title patientDetailVM.pubSpinner1 = picker1ListVM.picker1Items[self.selectionIndex1].picker1Title })} 

The view model picker1Items is an array of Picker1Model

struct Picker1Model: Identifiable { let picker1Item: Picker1Item var id: NSManagedObjectID { return picker1Item.objectID } var picker1Title: String { return picker1Item.title ?? "No Picker 1 Title" } var picker1Comment: String { return picker1Item.comment ?? "No Picker 1 Comment" } }//picker 1 model 

This is the code in DetailView. I only added the second text to illustrate that the real value is still the published value:

VStack { Text(appSpinner1Title + ":") .modifier(LabelTextSetup()) //Remove this when problem solved Text(isEditing ? "Current: \(patientDetailVM.pubSpinner1)" : "") .modifier(LabelTextSetup()) } Spacer() if isEditing { Picker(selection: spinner1Binding, label : Text("Picker One Choice")) { ForEach(picker1ListVM.picker1Items.indices, id: \.self) { index in Text(picker1ListVM.picker1Items[index].picker1Title).tag(index) }//for }//picker } else { Text(patientDetailVM.pubSpinner1) .modifier(LabelTextSetup()) } 

When not editing it looks like this:

enter image description here

When editing it looks like this. Obviously, what I want is for the picker to display "Urgently Ortho" in this scenario.

enter image description here

Seems like this should be easy, but I have not been successful.

Any guidance would be appreciated. Xcode 13.2.1 iOS 15

5
  • Does this answer your question? Choosing CoreData Entities from form picker Commented Dec 21, 2021 at 2:42
  • stackoverflow.com/questions/67237434/… Commented Dec 21, 2021 at 2:45
  • Not really. The code to create the picker and save the values to Core Data works as expected. The ONLY issue is that I have not been able to set the initial selection to the value that is indeed in Core Data. See my answer for a solution that works but is not particularly elegant. Commented Dec 22, 2021 at 0:41
  • Your code is impossible to sort with what you provided it is incomplete and it does not connect but you don’t need custom anything to connect a picker to a core data entity to keep it always correct. Just wrap the core data object with ObservedObject and use the value directly. You may need to cast your options to optionals in the tag. See the links for samples. Commented Dec 22, 2021 at 1:28
  • I appreciate the help. Commented Dec 22, 2021 at 4:19

1 Answer 1

1

The problem is that I have been unable to set the selection for the Picker item to show as the current item (from Core Data) when I create the Picker. I thought I should be able to do that in the custom Binding for the Picker, but I could not get anything to work correctly.

My solution is to create a function that gathers the current value stored in Core Data and execute that function whenever the Picker is created. It works, but it seems like there should be a better way.

func setSelection1() { for x in 0..<picker1ListVM.picker1Items.count { if picker1ListVM.picker1Items[x].picker1Title == patientDetailVM.pubSpinner1 { selectionIndex1 = x }//if }//for in }//set selection 

Then also in the view displaying the Picker, call the function in .onAppear:

Picker(selection: spinner1Binding, label : Text("Picker One Choice")) { ForEach(picker1ListVM.picker1Items.indices, id: \.self) { index in Text(picker1ListVM.picker1Items[index].picker1Title).tag(index) }//for }//picker .onAppear { setSelection1() } 

Hope this helps others.

Sign up to request clarification or add additional context in comments.

1 Comment

Nice work around, I have been going round in circles figuring this out.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.