如何跨视图传递 CoreData 对象
Posted
技术标签:
【中文标题】如何跨视图传递 CoreData 对象【英文标题】:How to pass CoreData Object across views 【发布时间】: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 对象的ObservedObject
、EnvironmentObject
或StateObject
。
【参考方案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: )) 另外,由于预览要求我包含一个用户对象,我猜我也必须在预览中生成一个示例对象?以上是关于如何跨视图传递 CoreData 对象的主要内容,如果未能解决你的问题,请参考以下文章
在没有 managedObjectContext 的视图之间传递 CoreData 对象