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

swift-ci opened this issue Nov 19, 2018 · 1 comment

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

swift-ci opened this issue Nov 19, 2018 · 1 comment


Copy link

@swift-ci swift-ci commented Nov 19, 2018

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




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 {
        // 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
   = existingUser?.bio
   = existingUser?.blog
   = existingUser?.company
            self.createdAt = existingUser?.createdAt
   = 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
   = 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
        self.avatarURL = try container.decodeIfPresent(String.self, forKey: .avatarURL) = try container.decodeIfPresent(String.self, forKey: .bio) = try container.decodeIfPresent(String.self, forKey: .blog) = try container.decodeIfPresent(String.self, forKey: .company)
        self.createdAt = try container.decodeIfPresent(Date.self, forKey: .createdAt) = 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) = 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

Copy link

@belkadan belkadan commented Nov 26, 2018

@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
None yet

No branches or pull requests

2 participants