Swift coreData中丢失的数据

Swift coreData中丢失的数据,swift,core-data,swift4,Swift,Core Data,Swift4,我的应用程序将显示教师日程,在第一个控制器中,教师需要选择正确的一对(第一对、第二对、第三对),然后在我的代码中写入必要的数据(如科目名称、房间、组数),如果我在第一对中写入数据并保存,它将显示给我,但如果我在第二对中写入数据并选择保存按钮,第一对中以前的数据丢失,因此我有丢失数据的问题,这是我选择对的控制器的代码: class ChoosePair: UIViewController { enum choosePair: Int{ case FirstPair = 21

我的应用程序将显示教师日程,在第一个控制器中,教师需要选择正确的一对(第一对、第二对、第三对),然后在我的代码中写入必要的数据(如科目名称、房间、组数),如果我在第一对中写入数据并保存,它将显示给我,但如果我在第二对中写入数据并选择保存按钮,第一对中以前的数据丢失,因此我有丢失数据的问题,这是我选择对的控制器的代码:

class ChoosePair: UIViewController {  

enum choosePair: Int{
    case FirstPair = 21
    case SecondPair = 22
    case ThirdPair = 23
    case FourPair = 24

}
   @IBAction func PairButtons(_ sender: UIButton){
            guard let day = choosePair.init(rawValue: sender.tag) else { return }
            switch day {
            case .FirstPair:
                let FirstPair = self
                UserDefaults.standard.set(21, forKey: "pairId")
                performSegue(withIdentifier: "SheduleTeacher", sender: self)
                break
            case .SecondPair:
                let SecondPair = self
                UserDefaults.standard.set(22, forKey: "pairId")
                performSegue(withIdentifier: "SheduleTeacher", sender: SecondPair)
                break
            case .ThirdPair:
                let ThirdPair = self
                UserDefaults.standard.set(23, forKey: "pairId")
                performSegue(withIdentifier: "SheduleTeacher", sender: ThirdPair)
                break
            case .FourPair:
                let  FourPair = self
                UserDefaults.standard.set(24, forKey: "pairId")
                performSegue(withIdentifier: "SheduleTeacher", sender: FourPair)
                break
        }
}
}  
以及第二个控制器的代码(我在其中写入数据并将其保存在CoreData中)

课程安排教师:UIViewController{
var pairId=UserDefaults.standard.integer(forKey:“pairId”)
@IBVAR弱var主题标签:UILabel!
@IBVAR房间标签:UILabel!
@IBVAR弱时间标签:UILabel!
@iblabel:UILabel!
@IBVAR弱组标签:UILabel!
@IBVAR船长标签:UILabel!
@IBOutlet弱var subjectField:UITextField!
@IBOutlet弱var roomField:UITextField!
@ibvar时间域:UITextField!
@IBOutlet弱var emailField:UITextField!
@IBOutlet弱var组字段:UITextField!
@IBVAR captainField:UITextField!
让appDelegate=UIApplication.shared.delegate为!appDelegate
重写func viewDidLoad(){
super.viewDidLoad()
让上下文=appDelegate.persistentContainer.viewContext
let request=NSFetchRequest(entityName:“用户”)
request.returnsObjectsAsFaults=false
做{
let result=try context.fetch(请求)
对于结果中的数据![NSManagedObject]{
subjectField.text=data.value(forKey:“subject\(pairId)”)作为?字符串
roomField.text=data.value(forKey:“room\(pairId)”)作为?字符串
timeField.text=data.value(forKey:“time\(pairId)”)作为?字符串
emailField.text=data.value(forKey:“emailGroup\(pairId)”)作为?字符串
groupField.text=data.value(forKey:“组\(pairId)”)作为?字符串
captainField.text=data.value(forKey:“captain\(pairId)”)作为?字符串
}
}抓住{
打印(“失败”)
}
subjectLabel.layer.borderWidth=1.0
roomLabel.layer.borderWidth=1.0
timeLabel.layer.borderWidth=1.0
emailLabel.layer.borderWidth=1.0
groupLabel.layer.borderWidth=1.0
captainLabel.layer.borderWidth=1.0
}
@iAction func saveButton(\发送方:UIButton){
让上下文=appDelegate.persistentContainer.viewContext
让entity=NSEntityDescription.entity(在:上下文中,名为“用户”)
让newUser=NSManagedObject(实体:实体!,插入到:上下文)
newUser.setValue(self.subjectField!.text,forKey:“subject\(pairId)”)
newUser.setValue(self.roomField!.text,forKey:“room\(pairId)”)
newUser.setValue(self.timeField!.text,forKey:“time\(pairId)”)
newUser.setValue(self.emailField!.text,forKey:“emailGroup\(pairId)”)
newUser.setValue(self.groupField!.text,forKey:“组\(pairId)”)
newUser.setValue(self.captainField!.text,forKey:“captain\(pairId)”)
做{
尝试context.save()
}抓住{
打印(“保存失败”)
}
}    
}
并拍摄我现在在CoreData中的内容

class SheduleTeacher: UIViewController {

var pairId =  UserDefaults.standard.integer(forKey: "pairId")

@IBOutlet weak var subjectLabel: UILabel!
@IBOutlet weak var roomLabel: UILabel!
@IBOutlet weak var timeLabel: UILabel!
@IBOutlet weak var emailLabel: UILabel!
@IBOutlet weak var groupLabel: UILabel!
@IBOutlet weak var captainLabel: UILabel!

@IBOutlet weak var subjectField: UITextField!
@IBOutlet weak var roomField: UITextField!
@IBOutlet weak var timeField: UITextField!
@IBOutlet weak var emailField: UITextField!
@IBOutlet weak var groupField: UITextField!
@IBOutlet weak var captainField: UITextField!

let appDelegate = UIApplication.shared.delegate as! AppDelegate

override func viewDidLoad() {
    super.viewDidLoad()
    let context = appDelegate.persistentContainer.viewContext
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
    request.returnsObjectsAsFaults = false
    do {
        let result = try context.fetch(request)
        for data in result as! [NSManagedObject] {
            subjectField.text = data.value(forKey: "subject\(pairId)") as? String
            roomField.text = data.value(forKey: "room\(pairId)") as? String
            timeField.text = data.value(forKey: "time\(pairId)") as? String
            emailField.text = data.value(forKey: "emailGroup\(pairId)") as? String
            groupField.text = data.value(forKey: "group\(pairId)") as? String
            captainField.text = data.value(forKey: "captain\(pairId)") as? String
        }
    } catch {
        print("Failed")
    }
    subjectLabel.layer.borderWidth = 1.0
    roomLabel.layer.borderWidth = 1.0
    timeLabel.layer.borderWidth = 1.0
    emailLabel.layer.borderWidth = 1.0
    groupLabel.layer.borderWidth = 1.0
    captainLabel.layer.borderWidth = 1.0
}

@IBAction func saveButton(_ sender: UIButton) {
let context = appDelegate.persistentContainer.viewContext
let entity = NSEntityDescription.entity(forEntityName: "Users", in: context)
let newUser = NSManagedObject(entity: entity!, insertInto: context)
newUser.setValue(self.subjectField!.text, forKey: "subject\(pairId)")
newUser.setValue(self.roomField!.text, forKey: "room\(pairId)")
newUser.setValue(self.timeField!.text, forKey: "time\(pairId)")
newUser.setValue(self.emailField!.text, forKey: "emailGroup\(pairId)")
newUser.setValue(self.groupField!.text, forKey: "group\(pairId)")
newUser.setValue(self.captainField!.text, forKey: "captain\(pairId)")
do {
try context.save()
} catch {
print("Failed saving")
}
}    
}

谓词用于将获取限制为仅获取某些实体

let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
request.returnsObjectsAsFaults = false
下面是一个示例,您可以使用谓词仅获取具有
entity.pairId==pairId
的实体

override func viewDidLoad() {
    super.viewDidLoad()
    let context = AppDelegate.shared.persistentContainer.viewContext
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
    request.returnsObjectsAsFaults = false
    request.predicate = NSPredicate(format: "pairId = %@", argumentArray: [pairId])

    do {
        let results = try context.fetch(request)

        guard results.count == 1 else {
            fatalError("Bad count: \(results.count)")
        }

        guard let data = results.first! as? NSManagedObject else {
            fatalError("No NSManagedObject")
        }

        context.performAndWait {
            subjectField.text = data.value(forKey: "subject\(pairId)") as? String
            roomField.text = data.value(forKey: "room\(pairId)") as? String
            timeField.text = data.value(forKey: "time\(pairId)") as? String
            emailField.text = data.value(forKey: "emailGroup\(pairId)") as? String
            groupField.text = data.value(forKey: "group\(pairId)") as? String
            captainField.text = data.value(forKey: "captain\(pairId)") as? String
        }
    } catch {
        print("Failed")
    }

    // ...
}
override func viewDidLoad(){
super.viewDidLoad()
让上下文=AppDelegate.shared.persistentContainer.viewContext
let request=NSFetchRequest(entityName:“用户”)
request.returnsObjectsAsFaults=false
request.predicate=NSPredicate(格式:“pairId=%@”,参数数组:[pairId])
做{
let results=try context.fetch(请求)
guard results.count==1其他{
fatalError(“错误计数:\(results.count)”)
}
guard let data=results.first!as?NSManagedObject else{
fatalError(“无NSManagedObject”)
}
context.performAndWait{
subjectField.text=data.value(forKey:“subject\(pairId)”)作为?字符串
roomField.text=data.value(forKey:“room\(pairId)”)作为?字符串
timeField.text=data.value(forKey:“time\(pairId)”)作为?字符串
emailField.text=data.value(forKey:“emailGroup\(pairId)”)作为?字符串
groupField.text=data.value(forKey:“组\(pairId)”)作为?字符串
captainField.text=data.value(forKey:“captain\(pairId)”)作为?字符串
}
}抓住{
打印(“失败”)
}
// ...
}
当然,实体必须具有所述属性
pairId
,谓词才能工作

您也可以在
save()
方法中执行类似的操作。在那里,您可以更新检索到的
用户
实体/如果实体不存在,则创建一个新实体

另一种方法是删除旧文件(如果存在),并在保存时始终创建新文件


“如果一个按钮不存在,则创建一个新按钮”的另一个替代方法是为所有四个按钮预创建,然后在保存时获取实体并在那里更新它们。但是,您也必须在启动时检查它们是否已经存在,否则您将在每次启动时创建四个。

在您的
saveButton
函数中,您每次都创建一个新的用户实例,这意味着第二对的数据不会与第一对的数据一起写入,而是作为一个单独的记录写入。您需要更新现有对象,即您在
viewDidLoad
中获取的对象。(我非常怀疑任何数据丢失)

尽管如此,我认为您需要重新考虑您的设计,在同一个实体中有重复(或更多)字段看起来是一个难以维护的笨拙设计。更好的解决方案是只拥有一个group属性、一个subject属性等等,并用一个保存pairId的属性对其进行补充

还有,为什么实体名为Users,它似乎不持有任何类型的用户id

override func viewDidLoad() {
    super.viewDidLoad()
    let context = AppDelegate.shared.persistentContainer.viewContext
    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
    request.returnsObjectsAsFaults = false
    request.predicate = NSPredicate(format: "pairId = %@", argumentArray: [pairId])

    do {
        let results = try context.fetch(request)

        guard results.count == 1 else {
            fatalError("Bad count: \(results.count)")
        }

        guard let data = results.first! as? NSManagedObject else {
            fatalError("No NSManagedObject")
        }

        context.performAndWait {
            subjectField.text = data.value(forKey: "subject\(pairId)") as? String
            roomField.text = data.value(forKey: "room\(pairId)") as? String
            timeField.text = data.value(forKey: "time\(pairId)") as? String
            emailField.text = data.value(forKey: "emailGroup\(pairId)") as? String
            groupField.text = data.value(forKey: "group\(pairId)") as? String
            captainField.text = data.value(forKey: "captain\(pairId)") as? String
        }
    } catch {
        print("Failed")
    }

    // ...
}