Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expected type Date for key... #101

Closed
pepasflo opened this issue Feb 2, 2017 · 5 comments
Closed

Expected type Date for key... #101

pepasflo opened this issue Feb 2, 2017 · 5 comments

Comments

@pepasflo
Copy link

pepasflo commented Feb 2, 2017

Sometimes I get into a situation where Date parsing doesn't seem to work.

This:

self.createdAt = try json.value(for: "created_at")

Throws this:

Type mismatch. Expected type Date for key: created_at. Got '__NSCFString'

I can work around this by transforming to a string first, then to Date:

let s: String = try json.value(for: "created_at")
self.createdAt = try Date.value(for: s)

My Date support looks like so:

extension Date {
    @nonobjc static let ISO8601SecondFormatter:DateFormatter = {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ";
        formatter.timeZone = TimeZone(abbreviation:"GMT")
        return formatter
    }()
    
    static func fromISO8601String(_ dateString:String) -> Date? {
        if let date = ISO8601SecondFormatter.date(from: dateString) {
            return date
        }
        return .none
    }
}
extension Date : ValueType {
    public static func value(_ object: Any) throws -> Date {
        guard let dateString = object as? String else {
            throw MarshalError.typeMismatch(expected: String.self, actual: type(of: object))
        }
        guard let date = Date.fromISO8601String(dateString) else {
            throw MarshalError.typeMismatch(expected: "ISO8601 date string", actual: dateString)
        }
        return date
    }
}
@bwhiteley
Copy link
Contributor

@pepasflo Is it because your signature is a bit off? Try
static func value(from object: Any) throws -> Value

@pepasflo
Copy link
Author

pepasflo commented Feb 2, 2017

@bwhiteley That was precisely it!

For those following along at home, this causes an exception:

extension Date : ValueType {
    public static func value(_ object: Any) throws -> Date {

while this works correctly:

extension Date : ValueType {
    public static func value(from object: Any) throws -> Date {

(the only difference being _ in place of from).

It is a shame I can't lean on the compiler to spot this difference. It turns out you can make any sort of typo in the function name, or even omit it entirely, and Xcode will compile it without complaining that Date doesn't adhere to ValueType:

extension Date : ValueType {}

Why is it that I can get away with declaring an empty protocol conformance? Is this because one of the other generic implementations of ValueType will satisfy the value(from:) requirement?

@pepasflo
Copy link
Author

pepasflo commented Feb 2, 2017

(marking closed)

@pepasflo pepasflo closed this as completed Feb 2, 2017
@bwhiteley
Copy link
Contributor

@pepasflo It is because ValueType has a protocol extension providing a default implementation.

I've been bit by this a sort of thing few times. It can happen with ObjC protocols that have optional methods, or Swift protocols that have default implementations in a protocol extension. If you have a typo in your func name, it's not conforming to the protocol like you expect but the compiler offers no help. I've wished Swift had a conforming keyword for protocol conformance that behaved like override so the compiler could catch such things.

Since your first message I've been reading swift-evolution discussions about such a thing. It appears there are edge cases that complicate adding such a feature.

@pepasflo
Copy link
Author

pepasflo commented Feb 2, 2017

Thanks so much for taking to time to explain this!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants