Vincenzo
Vincenzo

Reputation: 6358

Saving to CoreData seems to be working but it doesn't Swift

Saving my user to CoreData appears to be saving as the do catch saving block doesn't throw any error and I actually do get the success print in it, but then when loading saved user is not found. I noticed it because when I launch the app, at login it downloads the user from firebase every time. Basically the whole logic is:

Login calls User.findUser() this will look for user in CoreData if found it will simply load user details and continue, else will call Firebase.downloadUserDetails() that will look for user in Firebase ( in this case it means that is the first time user launch the app on the device ). If found it will download user's details and call User.saveUserDetails() that will save user to CoreData. So at the next login it should be found. Well if I re run the app after this, User.findUser() still won't find any users and start the whole process again.

I didn't realised it before as the User.saveUserDetails() doesn't print any error while saving, but I added a check for any User record in CoreData and it always shows 0

Can you see what's happening? How do I check if I properly set CoreData in AppDelegate?

This is the saving function:

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

        }

    }

Upvotes: 0

Views: 128

Answers (1)

Joakim Danielson
Joakim Danielson

Reputation: 51861

There is a logical bug in your code, right now you do

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

Since you have a predicate for your request, "userId == %@", userId, the for loop will only be entered if a user is found with the given id which means the else part can never be executed and no new user created. I So instead of a for loop I would suggest something like

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

Upvotes: 1

Related Questions