【问题标题】:How to pass CoreData Object across views如何跨视图传递 CoreData 对象
【发布时间】:2021-03-17 19:26:14
【问题描述】:

因此,我正在开发自己的 SwiftUI 项目,试图弄清楚如何将 SwiftUI 与 CoreData 集成以实现数据持久性。我遇到了一些麻烦,我试图弄清楚如何获取我在“注册视图”中创建的用户实体或从“登录视图”中创建的现有用户,以及如何将该用户对象传递到ContentView,这是用户登录后出现的第一个视图。

首先,我不确定是否应该在 ContentView 中使用 @Binding 属性包装器来捕获从“登录视图”或“注册视图”传入的对象,或者是否应该只使用一个常量但没有包装器(我猜@Binding 是这里的方法,但我想对此进行一些澄清)。

其次,我想弄清楚为什么添加 @Binding 包装器会强制预览在输入 selectedUser 属性之前添加逗号?另外,我将如何解决预览错误?

第三,我对应该在何时何地导入 CoreData 感到有些困惑。我什至必须导入它吗?如果是这样,在哪些情况下我必须导入 CoreData?

我知道这是很多菜鸟问题,但我是菜鸟,我一直在寻找答案,无论我在哪里,都会得到不同的答案。非常感激。谢谢!

import SwiftUI

struct ContentView: View {
            
    @Environment(\.managedObjectContext) var moc
    
    @Binding var selectedUser : User //Assign logged in user to this variable...
    
    
    var body: some View {
        
            VStack{
                Spacer()
                VStack(spacing: 50){
                    
                    NavigationLink(destination: SupportView()){
                        awButton(content: "Request Support", backColor: Color(#colorLiteral(red: 0, green: 0.723585546, blue: 0.9907287955, alpha: 1)))
                            .shadow(color: Color.primary.opacity(0.5), radius: 20, x: 0, y: 20)
                            .rotation3DEffect(Angle(degrees:10), axis: (x: 10.0, y: 0, z: 0))
                    }

                    NavigationLink(destination: QuoteView()){
                        awButton(content: "Request Quote", backColor: Color(#colorLiteral(red: 0.9372549057, green: 0.3490196168, blue: 0.1921568662, alpha: 1)))
                            .shadow(color: Color.primary.opacity(0.5), radius: 20, x: 0, y: 20)
                            .rotation3DEffect(Angle(degrees:10), axis: (x: 10.0, y: 0, z: 0))
                    }

                    NavigationLink(destination: TicketView()){
                        awButton(content: "Ticket Status", backColor: Color(#colorLiteral(red: 0.4666666687, green: 0.7647058964, blue: 0.2666666806, alpha: 1)))
                            .shadow(color: Color.primary.opacity(0.5), radius: 20, x: 0, y: 20)
                            .rotation3DEffect(Angle(degrees:10), axis: (x: 10.0, y: 0, z: 0))
                    }
                }
                Spacer()
            }
            .navigationTitle("AccessWeb")
            .navigationBarItems(trailing: HStack{
                Image(systemName: "bell")
                    .font(.system(size: 30))
                Image(systemName:"person.circle")
                    .font(.system(size: 30))
                Text("Tester")
                    .font(.system(size: 20))
            })
       }
}

struct ContentView_Previews: PreviewProvider {

    static var previews: some View {
        
        ContentView(, selectedUser: <#Binding<User?>#>)
    }
}



import SwiftUI
import CoreData

struct SignUpView: View {

@State private var name: String = ""
@State private var company: String = ""
@State private var user: String = ""
@State private var pass: String = ""
@State private var photo: Image?

@State private var showingImagePicker = false
@State private var inputImage: UIImage?

@State private var isSignUpValid: Bool = false
@State private var shoudlShowSignUpAlert: Bool = false
    
@Environment(\.managedObjectContext) var moc

var body: some View {
    
    VStack{

        TextField("Company", text: $company)
            .padding(.leading)
        Divider()
            .padding(.bottom)
        
        TextField("First and Last Name", text: $name)
            .padding(.leading)
        Divider()
            .padding(.bottom, 30)
        
        TextField("Username", text: $user)
            .padding(.leading)
        Divider()
            .padding(.bottom)
        
        SecureField("Password", text: $pass)
            .padding(.leading)
            
        Divider()
            .padding(.bottom, 50)
        
        ZStack{
            Circle()
                .fill(Color.secondary)
                .frame(width: 200, height: 200)
                
            if photo != nil {
                photo?
                    .resizable()
                    .scaledToFit()
                    .clipShape(Circle())
                    .frame(width: 300, height: 300)
            } else {
                Text("Tap to select a photo")
                    .foregroundColor(.white)
                    .font(.headline)
            }
        }
        .onTapGesture {
            self.showingImagePicker = true
        }
        .padding(.bottom, 50)
        
        
        NavigationLink(
            destination: ContentView(),
            isActive: self.$isSignUpValid){
            Text("Sign Up")
                .foregroundColor(.blue)
                .onTapGesture {

                    //Pass the appropriate User data onto the ContentView...
                    
                    //TriggerLogin
                    let isLoginValid = self.user == "Tester" && self.pass == "Test1234"
                    
                    if isLoginValid {
                        self.isSignUpValid = true //trigger NavLink
                        
                        let newUser = User(context: self.moc)
                        newUser.company = company
                        newUser.name = name
                        newUser.username = user
                        newUser.password = pass
                        newUser.photo = coreDataObjectFromImages(image: (inputImage ?? UIImage(systemName:"person.circle"))!)

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

                    } else {
                        self.shoudlShowSignUpAlert = true
                    }


                }
        }
        .frame(width: 300, height: 50)
        .background(Color.green)
        .clipShape(RoundedRectangle(cornerRadius: 20, style: .continuous))
    }
    .sheet(isPresented: $showingImagePicker, onDismiss: loadImage){
        ImagePicker(image: self.$inputImage)
    }
    .navigationTitle("Sign Up")
    .alert(isPresented: $shoudlShowSignUpAlert, content: {
        Alert(title: Text("Fill it out correctly!"))
    })
}

【问题讨论】:

  • 由于您的问题如此广泛,很难回答,但如果您想知道如何传递 CoreData 对象并共享它们,Apple SwiftUI tutorials 是一个很好的资源。 CoreData 对象是一个ObservableObject,所以无论您在哪里看到可以是CoreData 对象的ObservedObjectEnvironmentObjectStateObject

标签: core-data swiftui


【解决方案1】:

对于你的第一个问题:这里不需要使用绑定。你只需在你的 ContentView 中声明一个 User 类型的变量。

CoreData 和 SwiftUI 结合在一起如此强大的原因在于 ManagedObjects 符合 ObservableObjects。所以你可以在你的视图中将它们声明为ObservedObject

import SwiftUI

struct ContentView: View {
            
    @Environment(\.managedObjectContext) var moc
    
    //@Binding var selectedUser : User

    @ObservedObject var selectedUser: User //<< here declare it 

第三个问题:由于 CoreData 是一个框架,就像 iOS 中的其他框架一样,当你使用它的函数、类、结构时,你必须导入它。你可以看看here

【讨论】:

  • 谢谢,这有帮助!知道为什么我在更改为 @ObservedObject 后在 ContentView 的预览中看到逗号吗? (ContentView(, selectedUser: )) 另外,由于预览要求我包含一个用户对象,我猜我也必须在预览中生成一个示例对象?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-11-29
  • 2016-07-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多