0

I am trying to create a struct that uses generics to set a property type.

This is working fine as below, however I'd like to be able to iterate over a collection of these structs and check the expiry prop so I can take action if it has expired.

enum ContainerExpiryType {

    case seconds(_ seconds: Int), minutes(_ minutes: Int), hours(_ hours: Int), days(_ days: Int), date(_ date: Date)

    private var calender: Calendar {
        return Calendar.current
    }

    var date: Date? {
        switch self {
        case .seconds(let seconds):
            return calender.date(byAdding: .second, value: seconds, to: Date())
        case .minutes(let minutes):
            return calender.date(byAdding: .minute, value: minutes, to: Date())
        case .hours(let hours):
            return calender.date(byAdding: .hour, value: hours, to: Date())
        case .days(let days):
            return calender.date(byAdding: .day, value: days, to: Date())
        case .date(let date):
            return date
        }
    }
}

struct CacheWrapper<T: Codable>: Codable {
    var id: UUID
    var expiry: Date
    var object: T

    init(object: T, expiry: ContainerExpiryType) {
        self.id = UUID()
        self.expiry = expiry.date ?? Date()
        self.object = object
    }
}

let a = CacheWrapper<String>(object: "foo", expiry: .days(1))
let b = CacheWrapper<String>(object: "bar", expiry: .days(2))
let c = CacheWrapper<Int>(object: 5, expiry: .days(-100))

let foo: [CacheWrapper<Codable>] = [a, b, c]

foo.forEach { print($0.expiry) }

Doing this however throws an error

error: CacheExp.playground:45:11: error: protocol type 'Codable' (aka 'Decodable & Encodable') cannot conform to 'Decodable' because only concrete types can conform to protocols let foo: [CacheWrapper] = [a,b,c]

How can I achieve this?

1 Answer 1

0

The generic argument of CacheWrapper must be a concrete type conforming to Codable. A protocol cannot conform to itself.

A solution is to create a protocol with a requirement to implement expiry (and id if necessary)

protocol Wrappable {
    var id: UUID { get }
    var expiry: Date { get }
}

Adopt Wrappable

struct CacheWrapper<T: Codable>: Codable, Wrappable { ...

and annotate

let foo: [Wrappable] = [a, b, c]

Then you can print

foo.forEach { print($0.expiry) }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.