coreData中的数据丢失

时间:2018-07-22 13:24:10

标签: swift core-data swift4

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

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中)

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")
}
}    
}

并拍照我现在在CoreData中拥有的

photo

2 个答案:

答案 0 :(得分:0)

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

let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users")
request.returnsObjectsAsFaults = false

不设置谓词,因此它总是返回那里的所有Users实体。下面让您遍历每个实体,这就是为什么存在for循环的原因。

for data in result as! [NSManagedObject] {

这是一个示例,您可以使用谓词仅获取带有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")
    }

    // ...
}

为使谓词正常工作,实体当然必须具有所述属性pairId

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

一种选择是删除旧的(如果存在的话),并始终在保存时创建一个新的。

“如果一个按钮不存在则创建一个新按钮”的另一种选择是为所有四个按钮预先创建,然后在保存时获取实体并在那里进行更新。但是,您还必须检查启动是否已经存在,否则将在每个启动四个上创建。

答案 1 :(得分:0)

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

话虽这么说,但我认为您需要重新考虑您的设计,在同一实体中具有重复的(或更多)字段看起来像一个笨拙的设计,将很难维护。更好的解决方案是只具有一个组属性,一个主题属性等等,并用包含pairId的属性对其进行补充。

还有,为什么实体名称为Users,似乎没有任何类型的用户ID?