用泛型创建结构数组

用泛型创建结构数组

问题描述:

我正在尝试创建一个使用泛型来设置属性类型的结构.

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

如下所示,它工作正常,但是我希望能够遍历这些结构的集合并检查 expiry 道具,以便在其过期时可以采取措施.

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) }

但是这样做会引发错误

错误:CacheExp.playground:45:11:错误:协议类型为可编码"(又名'可分解和可分解可编码")不符合可解码",因为仅具体类型可以符合协议,让foo:[CacheWrapper] = [a,b,c]

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]

我该如何实现?

CacheWrapper 的通用参数必须是符合 Codable 的具体类型.协议不符合自身.

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

一种解决方案是创建一个协议,该协议要求实现 expiry (必要时还需要 id )

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 }
}

采用可包装

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

并注释

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

然后您可以打印

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