How to produce a nil of a generic type

Question

I would like to declare a generic class which holds/obtains a variable of type Any?, but casts this variable to a given type, when requested. Something like this

class A<T> {
    var o: NSObject!
    var k: String!
    var v: T {
        get { return o.value(forKeyPath: k) as! T }
        set { o.setValue(newValue, forKeyPath: k) }
    }
}

I would like to this to work so that when o.value(forKeyPath: k) is nil and T can hold a nil (it is ExpressibleByNilLiteral), v returns nil (of type T). As it is, it crashes because of the as!. Is it possible to do this?

An attempted crack at this looks like this (suggested by How to make a computed property of a generic class depend on the class constraints)

class A<T> {
    var o: NSObject!
    var k: String!
    var v: T {
        get { 
            let x = o.value(forKeyPath: k)
            if let E = T.self as? ExpressibleByNilLiteral.Type {
                if let x = x { return x as! T }
                let n: T = <nil of type T> <---- not sure what to put here
                return n
            } else {
                return x as! T 
            }
        }
        set { o.setValue(newValue, forKeyPath: k) }
    }
}

but I am not sure how to make it work.


Show source
| generics   | swift   2017-01-05 19:01 1 Answers

Answers to How to produce a nil of a generic type ( 1 )

  1. 2017-01-06 02:01

    Not sure why, but this actually works

    func cast<T>(_ v: Any?)->T {
        if let E = T.self as? ExpressibleByNilLiteral.Type {
            if let v = v {
                return v as! T
            } else {
                return E.init(nilLiteral: ()) as! T
            }
        } else {
            return v as! T
        }
    }
    

    I thought I already tried this and it did not work... Anyway, now we can substitute all as! calls with cast when we do not want to crash on nil, if the type we are casting to can take it, e.g. in the getter of my question.

Leave a reply to - How to produce a nil of a generic type

◀ Go back