无法从核心数据加载SwiftUI选择器选择并显示为选择内容

时间:2019-12-09 02:11:30

标签: ios xcode core-data swiftui

我有一个SwiftUI应用,可将数据持久保存在CoreData中。我想要一个捡拾器 用户可以从一个实体中选择一个项目,然后将该信息存储在 另一个实体作为选择器显示。

我有一个名为Patient的实体,用户在其中添加数据。我有一个实体 名为Clinic的列表,它是用户创建的对象的列表。目的是使用 选择器快速添加信息,而无需为每个重复输入项目 患者记录。

Swift中,我通过将UIPicker附加到TextField来做到这一点。很好。我有 在SwiftUI中无法做到等效。我可以创造和填充 选择器数据,我成功将更改保存到“患者”实体,但是我有 在以下情况下,无法将患者诊所数据默认加载到选择器中: 详细视图已加载。

这部分应用等效于主/详细样式。 DetailView是:

struct DetailView: View {

    @Environment(\.managedObjectContext) var managedObjectContext
    @Environment(\.presentationMode) var presentationMode
    @FetchRequest(fetchRequest: Clinic.getAllClinics()) var clinics: FetchedResults<Clinic>
    @State private var selectClinicItem: Int = 0
    var patient: Patient

    @State private var updatedFirstName: String = "No First Name"
    @State private var updatedLastName: String = "No Last Name"
    @State private var updatedClinic: String = "Clinic Not Chosen"
    @State private var chosenClinicUUID: UUID = UUID()

    var body: some View {

        ScrollView {
            Group {//top group
                VStack {
                    MyDataCell(tfData: $updatedFirstName, passedInLabel: "First Name", patient: patient, patientAttribute: patient.firstName ?? "No First")
                }//Top VStack - 8 views
            }//top Group

            Group {//second group
                Form {
                    Picker(selection: self.$chosenClinicUUID, label: Text("Choose Clinic")) {
                        ForEach(clinics) { c in
                            Text("\(c.name ?? "no name")")
                        }
                    }
                    .frame(width:320, height: 30)
                }//Form
                .frame(width:350, height: 200)
                .clipShape(RoundedRectangle(cornerRadius: 12))
                .overlay(RoundedRectangle(cornerRadius: 12)
                .stroke(Color.gray, lineWidth: 2))
                .padding(.leading, 12)
                .padding(.top, 20)
                .padding(.bottom, 20)
            }//second Group

        }//scroll or top level Form

            .modifier(AdaptsToSoftwareKeyboard())
            .navigationBarTitle("View and Edit", displayMode: .inline)
            .navigationBarItems(trailing: Button(action: {

                self.patient.firstName = self.updatedFirstName
                self.patient.lastName = self.updatedLastName
                self.patient.clinicName = self.updatedClinic
                self.patient.clinicID = self.chosenClinicUUID

                let n = self.clinics.filter { $0.id == self.patient.clinicID }

                if n.count > 0 {
                    self.patient.clinicName = n[0].name
                }

                do {
                    try self.managedObjectContext.save()
                } catch {
                    print(error)
                }

                self.updatedFirstName = ""
                self.updatedLastName = ""
                self.updatedClinic = ""

                self.presentationMode.wrappedValue.dismiss()

            }) {
                Text("Save")
            })

    }//body
}

患者类,供参考:

public class Patient : NSManagedObject, Identifiable {
    @NSManaged public var id: UUID
    @NSManaged public var firstName: String?
    @NSManaged public var lastName: String?
    @NSManaged public var clinicName: String?
    @NSManaged public var clinicID: UUID
}

extension Patient {
    static func getAllPatients() -> NSFetchRequest<Patient> {
        let request: NSFetchRequest<Patient> = Patient.fetchRequest() as! NSFetchRequest<Patient>
        let sortDescriptor = NSSortDescriptor(key: "lastName", ascending: true)
        request.sortDescriptors = [sortDescriptor]
        return request
    }
}

诊所课程:

public class Clinic : NSManagedObject, Identifiable {
    @NSManaged public var id: UUID
    @NSManaged public var name: String?
    @NSManaged public var comment: String?
    @NSManaged public var isShown: Bool
}

extension Clinic {
    static func getAllClinics() -> NSFetchRequest<Clinic> {
        let request: NSFetchRequest<Clinic> = Clinic.fetchRequest() as! NSFetchRequest<Clinic>
        let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
        request.sortDescriptors = [sortDescriptor]
        return request
    }
}

enter image description here enter image description here

任何指导将不胜感激。 Xcode版本11.2.1(11B500)

3 个答案:

答案 0 :(得分:1)

这就是我所做的,一个Icon的虚拟实例

sData[2].status

...在我的代码后面,我能够添加关系

{
  "from": 0, 
  "size": 5, 
  "_source": ["sData.status"],
        "query": {
          "bool": {
            "must":[
              {
                "wildcard": {
                  "server": "*ABC2501*"
                }
              },         
              {
                "wildcard": {
                  "sData[2].status": "*Finish*"
                }
              }
            ]
          }
        },
        "sort": [
          { "requestDate": {"order": "desc"}}
        ]
}

您可以的话

  @FetchRequest(
    entity: Icon.entity(),
    sortDescriptors: []
  ) var coreDataIcon: FetchedResults<Icon>

  @State private var oneCoreDataIconIndex: Int = 0

  var body: some View {

    Form {

        Picker("Select Icon", selection: $oneCoreDataIconIndex) {
          ForEach (0..<coreDataIcon.count) {
            Image(systemName: self.coreDataIcon[$0].wrappedIcon)
              .tag($0)
              .font(.title)
          }//ForEach

        }//Picker

      }//Form

...和

oneAccount.icon = self.coreDataIcon[self.oneCoreDataIconIndex]

稍后在您的代码中

    @State private var chosenClinicIndex: Int = 0

这还会显示您选择之前的初始诊所

像我的

enter image description here

答案 1 :(得分:0)

尝试使用Int(与数组结合使用)而不是实际的UUID作为选择变量。检出this

答案 2 :(得分:0)

通过在初始化期间手动设置选定的索引来解决该问题。似乎是一种奇怪的方式。

struct MyView: View {
    ...
    @ObservedObject var model = VideoDetailsModel()
    @State var selectedCategoryIndex : Int = -1

    // Init with initial model
    init(onDismiss: @escaping (VideoDetails?) -> ()) {
        self.onDismiss = onDismiss
    }

    // Init with existing model
    init(model: VideoDetailsViewModel, onDismiss: @escaping (VideoDetails?) -> ()) {
        self.model = model
    
        self.onDismiss = onDismiss
        let selectedIndex = self.model.categories.categories.firstIndex(where: {
            return $0 == self.model.videoModel?.categories[0]
        }) ?? -1
        
        // Force the set state here since initialisation is optional
        _selectedCategoryIndex = .init(initialValue: selectedIndex)
    }
    
    var body: some View {
    ... 
            Picker(selection: $selectedCategoryIndex , label: Text("Category")) {
                ForEach(0..<self.model.categories.categories.count, id: \.self) { index in
                    Text(self.model.categories.categories[index])
                }
            }
    ... 
}