BLACK FRIDAY: Save 50% on all my Swift books and bundles! >>

SOLVED: Day 47 Challenge: Codable class?

Forums > 100 Days of SwiftUI

Hi everyone,

I'm trying to implement an "Activity" struct or class that has a "last completed" property. Since struct are not mutable, I am not able to use a struct AFAIK. I wanted to therefore use a class, but the item has to be Codable as well.

But whenever I want to create an instance of this class, I am getting this error:

Missing argument for parameter 'from' in call
Insert 'from: <#Decoder#>, '

My class definition is:

class Activity: Identifiable, Codable {
    var id = UUID()
    var name: String
    var repeatFreq: String
    var description: String
    var lastCompleted: Date?

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

    var getDate: String {
        if let lastDate = lastCompleted {
            let formatter = DateFormatter()
            formatter.dateFormat = "d MMM"
            return formatter.string(from: lastDate)
        } else {
            return "Never"
        }
    }

    func completedToday() {
        self.lastCompleted = Date()
    }

}

Thanks

3      

I just had a peak on the next topic... how to make classes codable. I guess my question here was too early :-)

But please let me know if there is an easy way to achieve what I am trying to do (ie without making Activity a class for example).

3      

You can keep Activity as a struct if you add the mutating keyword to the completedToday function.

And if Activity is a struct then you won't need the init you have there; you can just used the synthesized memberwise initializer that the compiler provides for you.

struct Activity: Identifiable, Codable {
    let id = UUID() //constant instead of variable because this won't change
    var name: String
    var repeatFreq: String
    var description: String
    var lastCompleted: Date?

    static let formatter: DateFormatter = {
        let fmt = DateFormatter()
        fmt.dateFormat = "d MMM"
        return fmt
    }()

    var getDate: String {
        if let lastDate = lastCompleted {
            return Activity.formatter.string(from: lastDate)
        } else {
            return "Never"
        }
    }

    mutating func completedToday() {
        self.lastCompleted = Date()
    }

}

var activity = Activity(name: "Greet", repeatFreq: "every day", description: "hello")
activity.completedToday()
print(activity.lastCompleted!)

Note that I also pulled the DateFormatter out into a static member of the Activity type and used that static member in the getDate computed property. Why? Because creating a DateFormatter is an expensive operation so you should try to minimize the number of times you do that. And since every instance of Activity that you create will use the same date format, they can all share the same DateFormatter and that way it's only created once instead of every time you want to format the date.

3      

Thanks very much, it is exactly what I was looking for and forgot about the mutating keyword. I have set the id to let but Swift is giving my this warning, although everything seems to work:

Immutable property will not be decoded because it is declared with an initial value which cannot be overwritten

How about the other properties? Name, Frequency and Desc will never change once the activity has been added... should they be let instead of var?

Last thing that bothers me is the large space on top of the Form: https://ibb.co/t8xsrKk

Problem solved: I had to remove the NavigationView in my ActivityView

3      

Save 50% in my WWDC sale.

SAVE 50% All our books and bundles are half price for Black Friday, so you can take your Swift knowledge further without spending big! Get the Swift Power Pack to build your iOS career faster, get the Swift Platform Pack to builds apps for macOS, watchOS, and beyond, or get the Swift Plus Pack to learn advanced design patterns, testing skills, and more.

Save 50% on all our books and bundles!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.