保存到 CoreData 似乎有效,但它不是 Swift

Posted

技术标签:

【中文标题】保存到 CoreData 似乎有效,但它不是 Swift【英文标题】:Saving to CoreData seems to be working but it doesn't Swift 【发布时间】:2019-11-13 08:57:50 【问题描述】:

将我的用户保存到 CoreData 似乎正在保存,因为 do catch 保存块不会引发任何错误,我实际上确实在其中得到了成功打印,但是在加载保存的用户时找不到。 我注意到它是因为当我启动应用程序时,登录时它每次都会从 firebase 下载用户。 基本上整个逻辑是:

登录调用 User.findUser() 这将在 CoreData 中查找用户 如果找到它只会加载用户详细信息并继续,否则将调用 Firebase.downloadUserDetails() 在 Firebase 中查找用户(在这种情况下,这意味着这是用户第一次在设备上启动应用程序)。如果找到,它将下载用户的详细信息并调用User.saveUserDetails(),这会将用户保存到 CoreData。所以在下次登录时应该可以找到它。好吧,如果我在此之后重新运行该应用程序,User.findUser() 仍然找不到任何用户并重新开始整个过程​​。

我之前没有意识到这一点,因为User.saveUserDetails() 在保存时不会打印任何错误,但我在 CoreData 中添加了对任何User 记录的检查,它始终显示为 0

你能看到发生了什么吗?如何检查我是否在 AppDelegate 中正确设置了 CoreData?

这是保存功能:

static func saveUserDetails(completed: @escaping(Bool) -> (),userId: String, fcmToken: String, email: String, fullName: String, familyName: String, givenName: String, profileImage: UIImage, address: String, city: String, zipCode: String, region: String, country: String, phoneNumber: String) 

        let context = AppDelegate.viewContext
        //check if user is already in database
        let request: NSFetchRequest<User> = User.fetchRequest()

        // check for any existing records in CoreData
        print("check for any existing records in CoreData")
        do 
            let fetchPre = try context.fetch(request)
            print("saveUserDetails: Users saved in CoreData are: \(fetchPre.count)")

            for user in fetchPre 
                print("User id is : \(String(describing: user.userId))")
                print("User name is : \(String(describing: user.fullName))")
            
         catch  
            print(" Error fetching user during saving : \(error)")
        


        request.predicate = NSPredicate(format: "userId == %@", userId)
        //        request.fetchLimit = 1
        do 
            let fetch = try context.fetch(request)
            print("saveUserDetails: fetch is \(fetch.count)")
            for value in fetch 
                print(" User/saveUserDetails:   checking for existing user")
                if userId == value.userId 
                    print("   user is already saved ")
                    // save changes in database
//                    value.setValue(userId, forKey: "userId")
                    value.setValue(fcmToken, forKey: "fcmToken")
                    value.setValue(fullName, forKey: "fullName")
                    value.setValue(familyName, forKey: "familyName")
                    value.setValue(givenName, forKey: "givenName")
                    value.setValue(address, forKey: "address")
                    value.setValue(city, forKey: "city")
                    value.setValue(region, forKey: "region")
                    value.setValue(zipCode, forKey: "zipCode")
                    value.setValue(country, forKey: "country")
                    value.setValue(phoneNumber, forKey: "phoneNumber")
                    value.setValue(email, forKey: "email")
                    //                    return
                 else 
                    print(" User/saveUserDetails: user is new")
                    //create user in database
                    let user = User(context: context)
                    user.userId = userId
                    user.fcmToken = fcmToken
                    user.fullName = fullName
                    user.familyName = familyName
                    user.givenName = givenName
                    user.address = address
                    user.zipCode = zipCode
                    user.city = city
                    user.region = region
                    user.country = country
                    user.phoneNumber = phoneNumber
                    user.profilePicture = UIImageJPEGRepresentation(profileImage, 1.0)! as NSData

                

                do 
                    // save changes in database
                    try context.save()
                    print("  User/saveUserDetails: user is saved")
                    completed(true)
                 catch  
                    print("Error saving user details : \(error)")
                
            
         catch  
            print(" Error fetching user during saving : \(error)")

        

    

【问题讨论】:

很多代码和一个非常模糊的问题。您是否尝试对此进行调试以更好地了解正在发生的事情? @JoakimDanielson 我重新格式化了问题并修改了示例代码,它实际上有点太长了..现在saveUserDetails()function 执行检查以查找任何User 记录,甚至在保存时再次它没有找到任何。我真的不明白为什么..没有抛出错误,所以看起来实际上是在保存.. 【参考方案1】:

你的代码中有一个逻辑错误,现在你这样做

let fetch = try context.fetch(request)
for value in fetch 
    if userId == value.userId 
    ...
     else 
    ...

由于您的请求有一个谓词“userId == %@”,userId,因此只有在找到具有给定 id 的用户时才会进入 for 循环,这意味着永远不会出现 else 部分执行并且没有创建新用户。 一世 因此,我建议不要使用for 循环,而是

if let user = fetch.first  //I assume the predicate means we get one or zero users back
    //Handle user update
 else 
    //Handle new user

【讨论】:

绝对!!非常感谢您指出这一点。我迷失在功能中,看不到它。现在完美运行。

以上是关于保存到 CoreData 似乎有效,但它不是 Swift的主要内容,如果未能解决你的问题,请参考以下文章

在 UITextView 委托方法 textViewDidChange 中将文本保存在 Core Data 中是不是有效?

在 coredata 中更新加载布尔值

iOS - 核心数据 - NSManagedObjectContext - 不确定是不是保存

CoreData 似乎保存了错误的变量

需要有关 CoreData 保存的帮助

在保存到 CoreData 之前检查数据中的 nil