Korg
Korg

Reputation: 11

Using Codable to archiving with Swift

I'm trying to save some data from textFields in an iOS app in swift with codable, but when I define the function for archiving xcode tells me "Generic parameter 'Value' could not be inferred".

I'm learning about archiving, if someone can help me I'll be very greatful.

This is the code that I'm using

class ProfileViewController: UITableViewController {
    var currentProfile: Profile?
    @IBOutlet weak var name: UITextField!
    @IBOutlet weak var surname: UITextField!

    @IBAction func saveProfileButton(_ sender: Any) {
        addCurrentProfile()
        saveProfile()
    }

    func addCurrentProfile(){
        currentProfile?.name = name.text ?? ""
        currentProfile?.surname = surname.text ?? ""
    }

    struct Profile {
        var name: String
        var surname: String

        enum CodingKeys: String, CodingKey {
            case name
            case surname

        }

        init(name:String, surname:String) {
            self.name = name
            self.surname = surname
        }

        func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(name, forKey: .name)
            try container.encode(surname, forKey: .surname)

        }

        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            name = try container.decode(String.self, forKey: .name)
            surname = try container.decode(String.self, forKey: .surname)
        }
    }

    func saveProfile() {
        do {
            let data = try PropertyListEncoder().encode(currentProfile)
            let success = NSKeyedArchiver.archiveRootObject(data, toFile: profile_data.path)
            print(success ? "Successful save" : "Save Failed")
        } catch {
            print("Save Failed")
        }
    }
}

Upvotes: 0

Views: 350

Answers (2)

nikksindia
nikksindia

Reputation: 1177

First thing is to make your struct confirm to Codable protocol like:

struct Profile:Codable {
        var name: String
        var surname: String

        enum CodingKeys: String, CodingKey {
            case name
            case surname

        }

        init(name:String, surname:String) {
            self.name = name
            self.surname = surname
        }

        func encode(to encoder: Encoder) throws {
            var container = encoder.container(keyedBy: CodingKeys.self)
            try container.encode(name, forKey: .name)
            try container.encode(surname, forKey: .surname)

        }

        init(from decoder: Decoder) throws {
            let container = try decoder.container(keyedBy: CodingKeys.self)
            name = try container.decode(String.self, forKey: .name)
            surname = try container.decode(String.self, forKey: .surname)
        }
    }

then, you can achieve the object using PropertyListEncoder as below:

func saveProfile() {
        do {
            let data = try PropertyListEncoder().encode(currentProfile)
            let success = NSKeyedArchiver.archiveRootObject(data, toFile: profile_data.path)
            print(success ? "Successful save" : "Save Failed")
        } catch {
            print("Save Failed")
        }
    }

Upvotes: 1

E.Coms
E.Coms

Reputation: 11539

It seems there are several questions here. The direct answer to your question : "Generic parameter 'Value' could not be inferred". is: you forget to add the protocol:

 struct Profile: Codable {
...}

Upvotes: 0

Related Questions