Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-9300] Swift 4 Decodable does not suport Core Data update features #51771

Open
swift-ci opened this issue Nov 19, 2018 · 1 comment
Open
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. Codable Area → standard library: `Codable` and co. standard library Area: Standard library umbrella

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-9300
Radar None
Original Reporter ankitthakur85 (JIRA User)
Type Bug

Attachment: Download

Additional Detail from JIRA
Votes 0
Component/s Standard Library
Labels Bug, Codable
Assignee None
Priority Medium

md5: 5562d7e9d1c7a83e347c89f119735f3f

Issue Description:

In Decodable protocol there is only one api

/// Creates a new instance by decoding from the given decoder.
public init(from decoder: Decoder) throws

Above method is already convenience init but still if we call

`self = existingUser` then it says. self is immutable.

If we could have

onload

or

oncomplete

protocol methods also, then

we could fetch the existing managed object from core data and update with self.

required convenience init(from decoder: Decoder) throws {
        // since we are decoding json to managedobject, so using background managedobject context
        guard let backgrounManagedObjectContext = CodingUserInfoKey.backgrounManagedObjectContext,
            let parentLoginKey = CodingUserInfoKey.parentLogin,
            let userTypeKey = CodingUserInfoKey.userType,
            let managedObjectContext = decoder.userInfo[backgrounManagedObjectContext] as? NSManagedObjectContext,
            let parentLogin:String = decoder.userInfo[parentLoginKey] as? String,
            let userType:Int64 = decoder.userInfo[userTypeKey] as? Int64,
        let entity = NSEntityDescription.entity(forEntityName: "User", in: managedObjectContext) else {
                fatalError("Failed to decode User")
        }
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        var existingUser:User?
        do {
            let fetchRequest:NSFetchRequest = User.fetchRequest()
            let predicate = NSPredicate(format: "login CONTAINS[cd] %@ and parentLogin CONTAINS[cd] %@ and userType == %d", try container.decodeIfPresent(String.self, forKey: .login) ?? "", parentLogin, userType)
            fetchRequest.predicate = predicate
            
            let fetchResults = try managedObjectContext.fetch(fetchRequest)
            
            if (fetchResults.count > 0){
                existingUser = fetchResults.first
            }
            
        } catch let error {
            print(error)
        }
        // This is possible
        self.init(entity: entity, insertInto: managedObjectContext)
       // But we cannot do, self is immutable
       self = existingUser
}

So, currently we are inserting the values from core data to self object and then use the decoder container

if existingUser != nil {
            self.avatarURL = existingUser?.avatarURL
            self.bio = existingUser?.bio
            self.blog = existingUser?.blog
            self.company = existingUser?.company
            self.createdAt = existingUser?.createdAt
            self.email = existingUser?.email
            self.followers = existingUser?.followers ?? 0
            self.followersURL = existingUser?.followersURL
            self.following = existingUser?.following ?? 0
            self.followingURL = existingUser?.followingURL
            self.location = existingUser?.location
            self.login = existingUser?.login
            self.name = existingUser?.name
            self.publicGists = existingUser?.publicGists ?? 0
            self.publicRepos = existingUser?.publicRepos ?? 0
            self.gistsURL = existingUser?.gistsURL
            self.updatedAt = existingUser?.updatedAt
            self.url = existingUser?.url
            self.parentLogin = existingUser?.parentLogin
            self.userType = existingUser?.userType ?? 1
            
            managedObjectContext.delete(existingUser!)
        }
        
        self.avatarURL = try container.decodeIfPresent(String.self, forKey: .avatarURL)
        self.bio = try container.decodeIfPresent(String.self, forKey: .bio)
        self.blog = try container.decodeIfPresent(String.self, forKey: .blog)
        self.company = try container.decodeIfPresent(String.self, forKey: .company)
        self.createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt)
        self.email = try container.decodeIfPresent(String.self, forKey: .email)
        self.followers = try container.decodeIfPresent(Int64.self, forKey: .followers) ?? 0
        self.followersURL = try container.decodeIfPresent(String.self, forKey: .followersURL)
        self.following = try container.decodeIfPresent(Int64.self, forKey: .following) ?? 0
        self.followingURL = try container.decodeIfPresent(String.self, forKey: .followingURL)
        self.location = try container.decodeIfPresent(String.self, forKey: .location)
        self.login = try container.decodeIfPresent(String.self, forKey: .login)
        self.name = try container.decodeIfPresent(String.self, forKey: .name)
        self.publicGists = try container.decodeIfPresent(Int64.self, forKey: .publicGists) ?? 0
        self.publicRepos = try container.decodeIfPresent(Int64.self, forKey: .publicRepos) ?? 0
        self.gistsURL = try container.decodeIfPresent(String.self, forKey: .gistsURL)
        self.updatedAt = try container.decodeIfPresent(Date.self, forKey: .updatedAt)
        self.url = try container.decodeIfPresent(String.self, forKey: .url)
        self.parentLogin = parentLogin
        self.userType = userType

Attaching all the core data files for review.User+CoderDecoder.swift

@belkadan
Copy link
Contributor

cc @itaiferber

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior. Codable Area → standard library: `Codable` and co. standard library Area: Standard library umbrella
Projects
None yet
Development

No branches or pull requests

2 participants