Reputation: 573
The following code archivedTimes() builds successfully in swift4. And it runs fine on a device with ios10.3 installed.
typealias Time = CMTime
typealias Times = [Time]
static let times: Times = Array<Int64>.init(1...9).map({ CMTime.init(value: $0, timescale: 100) })
static func archivedTimes() -> Data {
return archived(times: times)
}
static func archived(times: Times) -> Data {
let values = times.map({ NSValue.init(time: $0) })
return NSKeyedArchiver.archivedData(withRootObject: values) // ERROR here
// -- ideally would instead be:
// return NSKeyedArchiver.archivedData(withRootObject: times)
// -- but probably not compatible with ios 9.3
}
However, while running it on a device with ios9.3 installed, it crashes saying:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSKeyedArchiver encodeValueOfObjCType:at:]: this archiver cannot encode structs'
My guess is that it may have something to do with some conflict between the new Codable protocol and the old NSCoder protocol. But I don't know what!
Note that the issue has nothing to do with the array. As archiving a simple CMTime also leads to such error. However, I posted it like this, because archiving the array of CMTime is ultimately my objective.
Upvotes: 0
Views: 261
Reputation: 573
I believe Codable
protocol is only available in ios10, therefore on ios9, CMTime
does not implement Codable
.
So for ios9, I went with a wrapper class for a CMTime
, which implements the NSCoding
protocol.
This can be done by importing AVFoundation
which declares both the extension to NSValue
and to NSCoder
so as to encode CMTime
.
So then I went with an array of WrappedTime.init($0)
, instead of an array of NSValue.init(time: $0)
.
class WrappedTime: NSObject, NSCoding {
enum EncodeKey: String {
case time = "time"
}
let time: CMTime
// ...
func encode(with aCoder: NSCoder) {
aCoder.encode(time, forKey: EncodeKey.time.rawValue)
}
required init?(coder aDecoder: NSCoder) {
time = aDecoder.decodeTime(forKey: EncodeKey.time.rawValue)
}
init(_ time: Time) {
self.time = time
}
}
Upvotes: 0