gpt4 book ai didi

swift - 如何使用 swiftui 将文本字段存储到核心数据中

转载 作者:行者123 更新时间:2023-12-01 21:50:11 29 4
gpt4 key购买 nike

当输入 TextField 时,我无法完成使用核心数据存储值,并在进入 View 时再次显示的任务。可能吗?

我需要存储namesurname。为此,我创建了 ProfileData 数据模型,但找不到任何相关信息。关于如何使其正常工作。

请在下面找到代码:

import SwiftUI
import CoreData

struct ProfileView: View {
@State private var name: String = ""
@State private var surname: String = ""
@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(
entity: ProfileData.entity(),
sortDescriptors: [
NSSortDescriptor(keyPath: \ProfileData.name, ascending: true),
NSSortDescriptor(keyPath: \ProfileData.surname, ascending: true),

]
) var profile: FetchedResults<ProfileData>
@EnvironmentObject var profile1: ProfileData

var body: some View {
VStack {
HStack {
VStack {
HStack {
Text("Meno:")
.font(.headline)
.padding()
TextField("", text: $name, onCommit: {
self.profile1.name = self.name
try? self.managedObjectContext.save()})
.onAppear {
self.name = self.profile.name != nil ? "\(self.profile.name!)" : "Zadajte meno" //here I get error Value of type 'FetchedResults<ProfileData>' has no member 'name'
}
.onDisappear {
self.profile1.name = self.name
try? self.managedObjectContext.save()
}
} .padding(.leading, 37)
}
HStack {
Text("Priezvisko:")
.font(.headline)
.padding()
TextField("Zadajte priezvisko", text: $surname)
}
}
}
}
.navigationBarTitle(Text("Profil"))
}
}

这是我的 ProfileData+CoreClassData.swift:

import Foundation
import CoreData

@objc(ProfileData)
public class ProfileData: NSManagedObject {

}

这是我的 ProfileData+CoreDataProperties.swifft

//
// ProfileData+CoreDataProperties.swift
// UcmMap
//
// Created by Jakub Adamec on 06/01/2020.
// Copyright © 2020 Jakub Adamec. All rights reserved.
//
//

import Foundation
import CoreData


extension ProfileData {

@nonobjc public class func fetchRequest() -> NSFetchRequest<ProfileData> {
return NSFetchRequest<ProfileData>(entityName: "ProfileData")
}

@NSManaged public var name: String?
@NSManaged public var surname: String?

}

最佳答案

完整代码如下:

import SwiftUI
import CoreData

@objc(ProfileData)
public class ProfileData: NSManagedObject, Identifiable {
public var id = UUID()
}


extension ProfileData {


@NSManaged public var name: String?
public var wrappedName: String{
get{name ?? "NoName"}
set{name = newValue}
}
@NSManaged public var surname: String?
public var wrappedSurname: String{
get{surname ?? "NoSurname"}
set{surname = newValue}
}
}

struct ProfileView: View {
@State private var name: String = ""
@State private var surname: String = ""
@Environment(\.managedObjectContext) var moc: NSManagedObjectContext // it will need you to add new examples of youre entities and save all changes
@FetchRequest(
entity: ProfileData.entity(),
sortDescriptors: [
NSSortDescriptor(keyPath: \ProfileData.name, ascending: true),
NSSortDescriptor(keyPath: \ProfileData.surname, ascending: true),

]
) var profileList: FetchedResults<ProfileData>
//fetchRequest is a list of all objects off type ProfileData - saved and unsaved

var body: some View {
NavigationView{

List{
ForEach(profileList){profile in
NavigationLink(destination: profileUpdateView(profile: profile)){
Text("\(profile.wrappedName) \(profile.wrappedSurname) ")
}
}
HStack{
Image(systemName: "plus.circle.fill")
.foregroundColor(.green)
.imageScale(.large)
Button("add a new profile"){
let newProfile = ProfileData(context: self.moc)
newProfile.wrappedName = "Name"
newProfile.wrappedSurname = "Surname"
}

}
}

.navigationBarTitle(Text("Profile"))
.navigationBarItems(trailing: Button("save"){
if self.moc.hasChanges{
do{try self.moc.save()}
catch{print("Cant save changes: \(error)")}
}
})

}
}
}
struct profileUpdateView: View {
@ObservedObject var profile: ProfileData
var body: some View{
VStack {
HStack {
Text("Meno:")
.font(.headline)
.padding()
TextField("Zadajte meno", text: $profile.wrappedName)
}
HStack {
Text("Priezvisko:")
.font(.headline)
.padding()
TextField("Zadajte priezvisko", text: $profile.wrappedSurname)
}
}
}
}
struct ProfileView_Previews: PreviewProvider {
static var previews: some View {
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
let newProfile = ProfileData(context: context)
newProfile.wrappedName = "Name"
newProfile.wrappedSurname = "Surname"
return ProfileView().environment(\.managedObjectContext, context)
}
}

注意几件事:

  1. FetchRequest 返回您定义类型的实体列表。可能有一项、多项或可能没有。
  2. 如果您获取某些内容,则需要使用 ForEach 循环来显示结果(大多数情况下)。
  3. 为此,我向您的实体添加了一个 id。它没有连接到 CoreData,每次 FetchRequest 得到新的结果,id 都会改变,但没关系。它的唯一目的是让 ForEach知道,循环的哪一部分与确切的对象相连。为此ForEach 可以更改它并向您显示更新
  4. 不要忘记将数据模型中实体的 codegen 属性更改为 manual/none。为此,请打开 DataModel,选择您的实体并转到数据模型检查器(屏幕右侧)。如果您不这样做,编译器将在编译过程中创建这些文件,并且此类将被定义两次。
  5. 如果你想创建你的类型的新对象——你需要使用 MOC。这是创建 NSManagedObject 类型对象的唯一方法。
  6. 您可以在 TextField 中放置一个 BindableObject。您尝试为此目的使用 @State,但您不需要它。可以修改普通objects 属性就像这样: TextField("Zadajte meno", text: $profile.wrappedName) $ 符号是为了让这个属性包装 @Binding。这意味着,在此内部所做的所有更改View 将立即转换为该对象。
  7. 你不能只放置 @NSManaged 属性,因为它们中的大多数都有可选类型,如 String?。我做了一个计算属性wrappedName 以便在 View 中简单地使用它。
  8. 我在更新 View 中使用了一个@ObservedObject 包装器。它类似于 @State,但用于类。当您希望在此对象更改时立即更新 View 时,您可以使用它。它还有助于创建 Binding。您的类必须满足 ObservableObject 协议(protocol)要求,但 NSManagedObject 已经满足,因此您无需担心。所有 @NSManaged 属性都已经是 @Published
  9. 即使您使用 CoreData,也有一种方法可以使用 Canvas。只需从 AppDelegate 获取上下文,创建任何测试实体。但请记住,保存的更改将添加到您的预览中。
  10. 最后,您需要使用moc.save() 保存所有更改。它会抛出异常,因此您必须在 try-catch 中执行此操作。而它的检查是否真的有未保存的更改的好习惯。

祝您学习 SwiftUI 顺利。没有太多关于使用 SwiftUI 和 CoreData 的信息。尝试在 hackingwithswift 上查看,有很多有用的信息。

关于swift - 如何使用 swiftui 将文本字段存储到核心数据中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59615175/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com