首页 > 解决方案 > 导航时触发 FetchRequest

问题描述

我有一个获取请求,当它的视图被导航离开时会触发。即使没有条目,它也会在列表视图中生成一堆空白单元格。我不确定是什么导致了它,我需要它消失。我认为这可能与导航链接有关,但是当我尝试使用工作表时,我的图像选择器不会触发,因为从工作表导航实际上不起作用。这是我的看法

import SwiftUI

struct LovedOnesView: View {
 @Environment(\.managedObjectContext) var lovedOnes
@FetchRequest(entity: Recipient.entity(), sortDescriptors: []) var lovedOne:FetchedResults<Recipient>
@State var stockImage = UIImage(imageLiteralResourceName: "WrittenPic")
@State var shouldNav: Bool = false

var body: some View {
    VStack {
        Button(action: {
            self.shouldNav.toggle()
        }) {
            Text("Add")
        }
       List {
        ForEach(lovedOne) { lovedOne in
            HStack {


                Person(name: lovedOne.name ?? "")

            }

           }
       }
        NavigationLink(destination: CreateLovedOnes().environment(\.managedObjectContext, self.lovedOnes), isActive: $shouldNav) {
            Text("")
        }

        }.navigationBarTitle(Text("Love Ones"))
}
}

struct LovedOnesView_Previews: PreviewProvider {
static var previews: some View {
    LovedOnesView()
}
}

extension Recipient: Identifiable {
}

struct Person: View {
var name: String = ""
var body: some View {
    HStack{
        Text(name)
    }
}


}

第二个视图如下所示:

import FirebaseAuth
import FirebaseDatabase
import FirebaseStorage

struct CreateLovedOnes: View {
     @Environment(\.managedObjectContext) var lovedOne
    @Environment(\.presentationMode) var presentationMode
    @State private var showSheet: Bool = false
    @State private var showImagePicker: Bool = false
    @State private var sourceType: UIImagePickerController.SourceType = .camera
    @State private var image: UIImage?
    @State var name: String = ""
    @State var relation: String = ""
    @State var birthday: Date = Date()
    @State var phoneNumber: String = ""
    @State var email: String = ""
    @State var admin: String = ""
    @State  var adminEmail: String = ""
    @State var shouldNavigate: Bool = false
    @State private var didSave: Bool = false
    @State var hideMarriage: Bool = true
    @State var marriageDate: Date = Date()
    @State var pickedIndex = 0
    @State var showingAlert: Bool = false
    var relations = Relations().relationArray
    var disableForm: Bool {
        name.isEmpty || phoneNumber.isEmpty || email.isEmpty || admin.isEmpty || admin.isEmpty || image == nil
    }
    var body: some View {
        let receiver = Recipient(context: self.lovedOne)
        return VStack {
            Form {
                HStack {
                    Text("Loved One's Name").padding(.trailing)
                    TextField("John Smith", text: $name)
                }
                VStack{
                    Picker(selection: $pickedIndex, label: Text("Relation")) {
                        ForEach(0 ..< relations.count) {
                            Text(self.relations[$0]).tag($0)
                        }
                    }


            }


                DatePicker("Loved One's Birthday", selection: $birthday, displayedComponents: .date)




                    if relations[pickedIndex] == "Husband" || relations[pickedIndex] == "Wife" {
                        DatePicker("Marraige Date", selection: $marriageDate, displayedComponents: .date)

                }



                HStack {
                    Text("Loved One's Number").padding(.trailing)
                    TextField("1-916-123-4567", text: $phoneNumber)
                }
                HStack {
                    Text("Loved One's Email").padding(.trailing)
                    TextField("this@email.com", text: $email)
                }
                HStack {
                    Text("Name of Admin").padding(.trailing)
                    TextField("John Johnson", text: $admin)
                }
                HStack {
                    Text("Admid Email").padding(.trailing)
                    TextField("admin@email.com", text: $adminEmail)
                }
                HStack {
                    Text("Choose an image")
                    Spacer()
                    Image(uiImage: image ?? UIImage(named:"WrittenPic")!).resizable().scaledToFit().frame(width: 50, height: 50)
                }.onTapGesture {
                    self.showSheet.toggle()
                }.actionSheet(isPresented: $showSheet) {
                    ActionSheet(title: Text("Select Photo"), message: Text("Choose"), buttons: [.default(Text("Photo Library")){
                        self.showImagePicker = true
                        self.sourceType = .photoLibrary
                        },
                                                                                    .default(Text("Camera")){
                                                               self.showImagePicker = true
                                                                                        self.sourceType = .camera
                        }, .cancel()])
                }
            }.sheet(isPresented: $showImagePicker) {
                ImagePicker(image: self.$image, isShown: self.$showImagePicker, sourceType: self.sourceType)
            }

            VStack {

                        NavigationLink(destination: MainView().navigationBarBackButtonHidden(true),isActive: self.$shouldNavigate) {
                           Text("")

                        }

                        Button(action: {
                            receiver.id = UUID()
                            receiver.name = self.name
                            receiver.email = self.email
                            receiver.phoneNumber = self.phoneNumber
                            receiver.age = self.birthday
                            guard let image = self.image else {
                                return
                            }
                            guard let imageData = image.jpegData(compressionQuality: 0.01) else {
                                return
                            }
                            let relationTo = self.relations[self.pickedIndex]
                            receiver.avatar = imageData
                            receiver.relation = relationTo

                            if relationTo == "Husband" || relationTo == "Wife" {
                                receiver.married = true
                                receiver.mariageDate = self.marriageDate
                            }
                            else {
                                receiver.married = false
                            }

                            receiver.adminName = self.admin
                            receiver.adminEmail = self.adminEmail


                         do {
                             try self.lovedOne.save()
                             self.didSave.toggle()
                             if self.didSave {
                                 print("I saved")

                             }
                         } catch {
                             print("Could not save \(error)")
                         }

                            if self.didSave {
                                self.saveToFirebase(recipientName: self.name, avatar: image, birthday: self.birthday, email: self.email, relation: self.relation, isMarried: self.hideMarriage , marriageDate: self.marriageDate, adminName: self.admin, adminEmail: self.adminEmail, lovedOneNumber: self.phoneNumber)
                            }


                        }) {
                         Text("Save Loved One")
                        }.disabled(disableForm)
                         .frame(minWidth: 0, maxWidth: 300, minHeight: 0, maxHeight: 50)
                         .font(.largeTitle).foregroundColor(.white).background(LinearGradient(gradient: Gradient(colors: [Color.themeColor, Color.white]), startPoint: /*@START_MENU_TOKEN@*/.leading/*@END_MENU_TOKEN@*/, endPoint: /*@START_MENU_TOKEN@*/.trailing/*@END_MENU_TOKEN@*/)).opacity(disableForm ? 0 : 1)
            }.alert(isPresented: $showingAlert) {
                Alert(title: Text("Same Name Error"), message: Text("You've already added this person please change the name"), dismissButton: .default(Text("Got it!")))


            }

        }.navigationBarTitle("Loved One Creation")


    }

    func saveToFirebase(recipientName: String, avatar: UIImage, birthday: Date, email: String, relation: String, isMarried: Bool, marriageDate: Date, adminName: String, adminEmail: String, lovedOneNumber:String){
        guard let userID = Auth.auth().currentUser?.uid else {
            return
        }

        Database.database().reference().child("users").child(userID).child(recipientName).observeSingleEvent(of: .value) { (snapshot) in
            if snapshot.exists() {
                self.showingAlert = true

            } else {
                self.uploadMedia(avatar: avatar, name: recipientName, userID: userID, completion: { (url) in
                    guard let url = url else {return}
                    let dateFormat = DateFormatter()
                    dateFormat.dateFormat = "MM-dd-yyyy"
                    let dateString = dateFormat.string(from: birthday)
                    let marDateString = dateFormat.string(from: marriageDate)

                    Database.database().reference().child("users").child(userID).child("lovedOnes").child(recipientName).child("info").updateChildValues(["name" : recipientName,"avatar": url,"birthday": dateString,"email": email, "relation": relation,"married": isMarried, "admin": adminName, "adminEmail": adminEmail,"phoneNumber": lovedOneNumber, "marriageDate":marDateString])


                })
            }

         self.presentationMode.wrappedValue.dismiss()

    }

    }
    func uploadMedia(avatar: UIImage, name:String,userID: String,completion: @escaping (_ url: String?) -> Void) {
           let storageRef = Storage.storage().reference().child(userID).child(name).child("avatar")

           let jpegRep = avatar.jpegData(compressionQuality: 0.30)!
           let imagetoLoad = UIImage(data: jpegRep)

           if let uploadData = imagetoLoad?.pngData() {
               storageRef.putData(uploadData, metadata: nil) { (metadata, error) in
                   if error != nil {
                       print("error")
                       completion(nil)
                   } else {
                       storageRef.downloadURL(completion: { (url, error) in
                           if error == nil {
                               completion(url?.absoluteString)
                           }
                       })

                   }
               }
           }

       }
}

struct CreateLovedOnes_Previews: PreviewProvider {
    static var previews: some View {
        CreateLovedOnes()
    }
}

标签: swiftcore-dataswiftui

解决方案


我发现他们有问题。let receiver = Recipient(context: self.lovedOne)应该在保存信息的按钮代码中。这消除了返回 VStack 的需要。我认为我之前使用它的方式由于某种奇怪的原因导致了列表的小夜曲。


推荐阅读