【问题标题】:lost data in the coreDatacoreData 中的数据丢失
【发布时间】:2018-07-22 13:24:10
【问题描述】:

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

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

【问题讨论】:

    标签: swift core-data swift4


    【解决方案1】:

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

    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 实体/如果不存在,则创建一个新实体。

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

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

    【讨论】:

      【解决方案2】:

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

      话虽如此,我认为您需要重新考虑您的设计,在同一个实体中具有重复(或更多)字段看起来像是一个难以维护的尴尬设计。更好的解决方案是只有一个组属性、一个主题属性等,并用一个包含 pairId 的属性来补充它。

      还有,为什么实体名称是Users,好像没有持有什么样的用户id?

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-03-20
        • 1970-01-01
        • 1970-01-01
        • 2020-12-24
        • 2021-04-24
        • 1970-01-01
        • 2020-10-21
        • 2014-03-22
        相关资源
        最近更新 更多